diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -1,34 +1,35 @@ 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 46d46e5f0edf5bf67b778b86a5515685be648ae5 release-2-1-0 f0a8c5985691243ee3c0b5f79be829a68601a527 release-2-1-1 647f106f32b2d3423854e3791467edd3bb523fec release-2-1-2 f6610876ef80299ea6d470d616539ac82a89a7f9 release-2-1-3 5e3e27541e17c42085935e7a8c6181bdf6a09191 release-2-1-4 eea16346ccff6eeb694b64c7bcfb88c7f525f6f3 release-2-1-5 +f0199517f6279a79be29173dfdd727414f45922a release-2-2-0 diff --git a/ACDC/ACDCGen.h b/ACDC/ACDCGen.h --- a/ACDC/ACDCGen.h +++ b/ACDC/ACDCGen.h @@ -1,765 +1,765 @@ // -*- C++ -*- // // ACDCGen.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ACDCGen_H #define ACDCGen_H #include #include "ACDCGenConfig.h" #include "ACDCTraits.h" #include "ACDCGenCell.h" #include "ThePEG/Utilities/Exception.h" namespace ACDCGenerator { /** * ACDCGen is a general class for sampling multi-dimensional * functions. ACDCGen can sample several functions simultaneously, * selecting different functions according to the relative * probabilities determined by their total integrals. The functions * are sampled on a unit hypercube. Function object of any class can * be used as long as the ACDCFncTraits class is specialized * correctly. ACDCFncTraits can also be used to rescale values in the * unit hypercube to any desired range. ACDCGen needs a random number * generator. Again, random number generators of any class can be used * as long as the ACDCRandomTraits class is specialized correctly. * * To give an unweighted samlpe ACDCGen uses a compensating * algorithm. Before the production sampling begins, the functions are * sampled randomly in the hypercube a user-defined number of times to * find an approximate maxumum value. The hypercube is then divided * into cells each of which have an approximate maximum value of the * function, to enable efficient sampling. The maxima are only * approximate though and, if a function value is found above the * maximum in a cell the ACDCGen will go into a compensating mode. The * cell is then first subdivided further and in the following this * cell will be over-sampled to compensate for that fact that it was * under-sampled before. In this way the probability of obtaining a * biased sample is reduced. Also rather functions with large peaks * are then sampled rather efficiently. Functions with narrow peaks * should, however, be avoided since there is no guarantee that the * peack is actually hit. */ template class ACDCGen { public: /** Template argument typedef. */ typedef Rnd RndType; /** Template argument typedef. */ typedef ACDCRandomTraits RndTraits; /** Template argument typedef. */ typedef FncPtr FncPtrType; /** A vector of cells. */ typedef vector CellVector; /** A vector of function objects. */ typedef vector FncVector; /** A vector of integers. */ typedef vector DimVector; /** The size type of the vectors used. */ typedef DimVector::size_type size_type; /** Template argument typedef. */ typedef ACDCFncTraits FncTraits; public: /** * Standard constructor requiring a random generator object to be * used. */ inline ACDCGen(Rnd * r); /** * Default Constructor. */ inline ACDCGen(); /** * Destructor. */ inline ~ACDCGen(); /** * Add a function of a given dimension, \a dim, according to which * points will be generated. Note that each function, \a f, added * like this will have its own tree of cells. The \a maxrat argument * determines the lowest ratio of values allowed between the cell * with lowest and highest value. If negative it is given by 1/nTry(). */ inline bool addFunction(DimType dim, FncPtrType f, double maxrat = -1.0); /** * Remove all added functions and reset the generator; */ inline void clear(); public: /** * Generate a point, choosing between the different functions * specified. The chosen function is returned, while the generated * point is obtained by the function lastPoint(). */ inline FncPtrType generate(); /** * Reject the last generated point. Only used in the evaluation of * the total integral. */ inline void reject(); /** * Return the last generated point. * @return a vector of doubles, each in the interval ]0,1[. */ inline const DVector & lastPoint() const; /** * Return the value of the last chosen function in the last point. */ inline double lastF() const; /** * Return the function chosen for the last generated point. */ inline FncPtrType lastFunction() const; /** * return the index of the function chosen for the last generated * point. */ inline size_type last() const; public: /** @name Functions influencing the efficiency of the generation. */ //@{ /** * Set the minimum cell size considered for this generation. The * default is the machine limit for double precision times a * hundred. */ inline void eps(double newEps); /** * Set the safety margin used to multiply the highest found function * value in a cell when setting its overestimated value. (Default is * 1.1.) */ inline void margin(double newMargin); /** * Set the number of points (with non-zero function value) used to * initialize the tree of cells to use in the generation for each * function. */ inline void nTry(size_type newNTry); /** * Set the maximum number of attempts to generate a phase space * point, or to find non-zero points in the initialization. */ inline void maxTry(long); //@} public: /** @name Information about the current generation. */ //@{ /** * Return the current Monte Carlo estimate of the integral of the * specified function (or all functions if NULL) over the unit volume. */ inline double integral(FncPtrType f = FncPtrType()) const; /** * Return the error on the current Monte Carlo estimate of the * integral of the specified function (or all functions if NULL) * over the unit volume. */ inline double integralErr(FncPtrType f = FncPtrType()) const; /** * The number of accepted points so far. */ inline long n() const; /** * The number of calls to generate() so far. Note that the number of * calls to the specified functions may be larger. It is up to the * user to keep track of those. */ inline long N() const; /** * The ratio of the number of accepted and number of tried points * n()/N(); */ inline double efficiency() const; /** * Return the number of active cells created so far. */ inline int nBins() const; /** * Return the maximum depth of any tree of cells used. */ inline int depth() const; /** * Return the current overestimation of the full integral of all * specified functions over the unit volume. */ inline double maxInt() const; //@} /** @name Access to member variables. */ //@{ /** * The minimum cell size considered for this generation. */ inline double eps() const; /** * The safety margin used to multiply the highest found function * value in a cell when setting its overestimated value. */ inline double margin() const; /** * The number of points used to initialize the tree of cells to use * in the generation. */ inline size_type nTry() const; /** * The maximum number of attempts to generate a phase space point, * or to find non-zero points in the initialization. */ inline long maxTry() const; /** * Returns true if generating random numbers are so cheap that a new * one can be thrown everytime a sub-cell is chosen. Otherwise * random numbers used for this will be reused. */ inline bool cheapRandom() const; /** * The number of functions used. */ inline size_type size() const; /** * Returns true if the generator is currently in a state of * compensating an erroneous overestimation of one of the specified * functions. If so, the integral and the generated points are not * statistically correct. */ inline bool compensating(); /** * Return an estimate of how many points need to be sampled before * the generator finishes compensating. */ inline long compleft() const; /** * Return a vector with information about all cells. */ vector extractCellInfo() const; //@} public: /** @name Functions related to the random number generator. */ //@{ /** * Set to true if generating random numbers are so cheap that a new * one can be thrown everytime a sub-cell is chosen. Otherwise * random numbers used for this will be reused. */ inline void cheapRandom(bool b); /** * Set a new random number generator. */ inline void setRnd(Rnd * r); /** * Double precision number in the interval ]0,1[. */ inline double rnd() const; /** * Double precision number in the interval ]lo,up[. */ inline double rnd(double lo, double up) const; /** * Fill the r vector with doubles r[i] in the interval ]lo[i],up[i][. */ inline void rnd(const DVector & lo, const DVector & up, DVector & r)const; /** * Fill the D first elements in the r vector with doubles in the * interval ]0,1[. */ inline void rnd(DimType D, DVector & r) const; /** * Integer in the interval [0,x[ */ inline long rndInt(long x) const; //@} public: /** * This function is to be used in ThePEG for output to * a persistent stream and will not work properly for normal * ostreams. */ template void output(POStream &) const; /** * This function is to be used in ThePEG for input from a persistent * stream and will not work properly for normal istreams. */ template void input(PIStream &); private: /** * Calculate the overestimated integral for all functions. */ inline double doMaxInt(); /** * Return the vector of functions. */ inline const FncVector & functions() const; /** * Return the i'th function. */ inline FncPtrType function(size_type i) const; /** * Return a vector with the dimensions of all functions. */ inline const DimVector & dimensions() const; /** * Return the dimension of the i'th function. */ inline DimType dimension(size_type i) const; /** * Return the dimension of the function chosen for the last * generated point. */ inline DimType lastDimension() const; /** * Return the roots of all cell trees. */ inline const CellVector & cells() const; /** * Return the root cell for the i'th function. */ inline ACDCGenCell * cell(size_type i) const; /** * Return the root cell for the function chosen for the last * generated point. */ inline ACDCGenCell * lastPrimary() const; /** * Return a vector with the incremental sum of overestimated * integrals for each function. */ inline const DVector & sumMaxInts() const; /** * Return the cell chosen for the last generated point. */ inline ACDCGenCell * lastCell() const; /** * Choose a function according to its overestimated integral and * choose a cell to generate a point in. */ inline void chooseCell(DVector & lo, DVector & up); /** * Start the compensation procedure for the last chosen cell when a * function velue has been found which exceeds the previous * overestimation. */ inline void compensate(const DVector & lo, const DVector & up); private: /** * The random number generator to be used for this Generator. */ RndType * theRnd; /** * The number of accepted points (weight > 0) so far. */ long theNAcc; /** * The number of attempted points so far. */ long theN; /** * The number of attempts per function so far. */ vector theNI; /** * The summed weights per function so far. */ DVector theSumW; /** * The summed squared weights per function so far. */ DVector theSumW2; /** * The smallest possible division allowed. */ double theEps; /** * The factor controlling the loss of efficiency when compensating. */ double theMargin; /** * The number of points to use to find initial average. */ size_type theNTry; /** * The maximum number of attempts to generate a phase space point, * or to find non-zero points in the initialization. */ long theMaxTry; /** * True if generating random numbers are so cheap that a new one can * be thrown everytime a sub-cell is chosen. Otherwise random * numbers used for this will be reused. */ bool useCheapRandom; /** * A vector of functions. */ FncVector theFunctions; /** * The dimensions of the functions in theFunctions. */ DimVector theDimensions; /** * The root of the cell tree for the functions in theFunctions. */ CellVector thePrimaryCells; /** * The accumulated sum of overestimated integrals of the functions * in theFunctions. */ DVector theSumMaxInts; /** * The last index chosen */ size_type theLast; /** * The last cell chosen. */ ACDCGenCell * theLastCell; /** * The last point generated. */ DVector theLastPoint; /** * The function value of the last point. */ double theLastF; /** * A helper struct representing a level of compensation. */ struct Level { /** * The number of attempts after which this level disapprears. */ long lastN; /** * The previous max value in the Cell to compensate. */ double g; /** * The cell which is being compensated. */ ACDCGenCell * cell; /** * The index corresponding to the cell being compensated. */ size_type index; /** * The integration limits for the cell being compensated. */ DVector up; /** * The integration limits for the cell being compensated. */ DVector lo; }; /** * A vector (stack) of levels */ typedef vector LevelVector; /** * The vector (stack) of levels */ LevelVector levels; /** * This is a help struct to perform the divide-and-conquer slicing * of cells before starting the compensation procedure. */ struct Slicer { /** * The constructor takes the number of dimensions of the function * approximated by the current cell, the ACDCGen object * controlling the generation and the lower-left and upper-right * corners of the cell to be sliced. */ Slicer(DimType, ACDCGen &, const DVector &, const DVector &); /** * The constructor used internally when diagonally chopped-off * cells need to be sliced themselves. */ Slicer(DimType Din, const Slicer & s, ACDCGenCell * cellin, const DVector & loin, const DVector & xselin, const DVector & upin, double fselin); /** * Destructor. */ ~Slicer(); /** * Called from both constructors to do the actual work. */ void divideandconquer(); /** * Initialize the procedure, finding the slicing points around the * current point */ void init(); /** * Do the slicing and increase the overestimate of the function in * the resulting cell. If a point with a higher function value has * been found repeat the slicing around that point etc. */ void slice(); /** * After slicing a cell, find the maximum function value found in * the resulting cell. Also set the minimum value found. */ double shiftmaxmin(); /** * Find the slice point of the current cell in the direction given. */ void dohalf(DimType); /** * If split is in more than one dimensions check the overestimate * for the chopped-off cell. */ void checkdiag(ACDCGenCell * cell, DimType d, double lod, double upd); /** * The dimension of the cell to be sliced. */ DimType D; /** * The lower-left corner of the current cell. */ DVector lo; /** * The upper-right corner of the current cell. */ DVector up; /** * The lower-left point found closest to the current * point which gives a function value below the overestimate. */ DVector xcl; /** * The upper-right point found closest to the current point which * gives a function value below the overestimate. */ DVector xcu; /** * The lower-left point furthest away from the * current point which gives a function value abov the * overestimate. */ DVector xhl; /** * The upper-right point furthest away from the * current point which gives a function value abov the * overestimate. */ DVector xhu; /** * The function values found for the xhl point. */ DVector fhl; /** * The function values found for the xhu point. */ DVector fhu; /** * The current point around which we are slicing. */ DVector xsel; /** * The function value in the current point. */ double fsel; /** * The current cell. */ ACDCGenCell * current; /** * The cell which resulted from the first slicing procedure. This * is the first one to get an increased overestimate and is the * one to be compensated. All other cells with increased * overestimates are sub-cells to this one */ ACDCGenCell * first; /** * The lower-left corner of the 'first' cell. */ DVector firstlo; /** * The upper-right corner of the 'first' cell. */ DVector firstup; /** * A pointer to the function to be used. */ FncPtr f; /** * The epsilon() value obtained from the controlling * ACDCGen object. */ double epsilon; /** * The margin() value obtained from the controlling * ACDCGen object. */ double margin; /** * The dimensions to slice in rated by the resulting fractional * volume of the resulting slice. If the dimension is negative it * means that the cell should be slized from below. */ multimap rateslice; /** * The minimu function value found in the current sliced cell (set * by shiftmaxmin()). */ double minf; /** * If true, then the whole original cell should compensated in the * continued generation. */ bool wholecomp; }; public: /** The maximum recursion depth of the compensation so far. */ static size_type maxsize; private: /** * Copy constructor is private and not implemented. */ ACDCGen(const ACDCGen &); /** * Assignment is private and not implemented. */ ACDCGen & operator=(const ACDCGen &) = delete; }; } #include "ACDCGen.icc" #endif diff --git a/ACDC/ACDCGen.icc b/ACDC/ACDCGen.icc --- a/ACDC/ACDCGen.icc +++ b/ACDC/ACDCGen.icc @@ -1,828 +1,828 @@ // -*- C++ -*- // // ACDCGen.icc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // namespace ACDCGenerator { template inline ACDCGen::ACDCGen(Rnd * r) : theRnd(r), theNAcc(0), theN(0), theNI(1, 0), theSumW(1, 0.0), theSumW2(1, 0.0), theEps(100*std::numeric_limits::epsilon()), theMargin(1.1), theNTry(100), theMaxTry(10000), useCheapRandom(false), theFunctions(1), theDimensions(1, 0), thePrimaryCells(1), theSumMaxInts(1, 0.0), theLast(0), theLastCell(0), theLastF(0.0) { maxsize = 0; } template inline ACDCGen::ACDCGen() : theRnd(0), theNAcc(0), theN(0), theNI(1, 0), theSumW(1, 0.0), theSumW2(1, 0.0), theEps(100*std::numeric_limits::epsilon()), theMargin(1.1), theNTry(100), theMaxTry(10000), useCheapRandom(false), theFunctions(1), theDimensions(1, 0), thePrimaryCells(1), theSumMaxInts(1, 0.0), theLast(0), theLastCell(0), theLastF(0.0) { maxsize = 0; } template inline ACDCGen::~ACDCGen() { clear(); } template inline void ACDCGen::setRnd(Rnd * r) { theRnd = r; } template inline void ACDCGen::clear() { theNAcc = 0; theN = 0; theNI = vector(1, 0); theSumW = DVector(1, 0.0); theSumW2 = DVector(1, 0.0); theFunctions = FncVector(1); theDimensions = DimVector(1, 0); for ( int i = 0, N = thePrimaryCells.size(); i < N; ++i ) delete thePrimaryCells[i]; thePrimaryCells = CellVector(1); theSumMaxInts = DVector(1, 0.0); theLast = 0; theLastCell = 0; theLastPoint.clear(); theLastF = 0.0; levels.clear(); } template inline bool ACDCGen:: addFunction(DimType dim, FncPtrType fnc, double maxrat) { if ( maxrat < 0.0 ) maxrat = 1.0/nTry(); typedef multimap PointMap; theLast = theFunctions.size(); theFunctions.push_back(fnc); theNI.push_back(0); theSumW.push_back(0.0); theSumW2.push_back(0.0); theDimensions.push_back(dim); // Generate nTry() points with non-zero function value DVector x(dim); PointMap pmap; long itry = 0; while ( pmap.size() < nTry() ) { if ( ++itry > maxTry() ) { thePrimaryCells.push_back(new ACDCGenCell(0.0)); theSumMaxInts.push_back(theSumMaxInts.back() + cells().back()->doMaxInt()); return false; } rnd(dim, x); double val = FncTraits::value(fnc, x); if ( val > 0.0 ) { pmap.insert(make_pair(val, x)); itry = 0; } } // Create the root cell and set its overestimated function value to // the smallest non-zero value found double minf = pmap.begin()->first; double maxf = (--pmap.end())->first; minf = max(minf, maxrat*maxf); // thePrimaryCells.push_back(new ACDCGenCell(pmap.begin()->first)); thePrimaryCells.push_back(new ACDCGenCell(minf)); theLastF = pmap.begin()->first; pmap.erase(pmap.begin()); theSumMaxInts.push_back(theSumMaxInts.back() + cells().back()->doMaxInt()); // Start the divide-and-conquer procedure using the point with the // highest function value found. theLastF = (--pmap.end())->first; theLastPoint = (--pmap.end())->second; pmap.erase(--pmap.end()); DVector up(dim, 1.0); DVector lo(dim, 0.0); theLastCell = cells().back()->getCell(lo, lastPoint(), up); if ( lastF() > lastCell()->g() ) { compensate(lo, up); levels.clear(); } // For each other generated point check that it's below the // overestimated value of the corresponding cell. If not start the // divide-and-conquer using that point. while ( !pmap.empty() ) { theLastPoint = pmap.begin()->second; theLastF = pmap.begin()->first; pmap.erase(pmap.begin()); DVector up(dim, 1.0); DVector lo(dim, 0.0); theLastCell = cells().back()->getCell(lo, lastPoint(), up); if ( lastF() > lastCell()->g() ) { compensate(lo, up); levels.clear(); } } // cells().back()->smooth(1.0/nTry()); return true; } template inline void ACDCGen::chooseCell(DVector & lo, DVector & up) { if ( compensating() ) { // If we are compensating, we must choose the cell to be compensated. up = levels.back().up; lo = levels.back().lo; theLastCell = levels.back().cell; theLast = levels.back().index; } else { // Otherwise, first choose the function to be used and choose the // corresponding root cell. theLast = upper_bound(sumMaxInts().begin(), sumMaxInts().end(), rnd()*sumMaxInts().back()) - sumMaxInts().begin(); if(theLast>=sumMaxInts().size()) { throw ThePEG::Exception() << "Selected a function outside the allowed range" << " in ACDCGen::chooseCell(). This is usually due" << " to a floating point error (nan or inf) in the" << " calculation of the weight" << ThePEG::Exception::abortnow; } up = DVector(lastDimension(), 1.0); lo = DVector(lastDimension(), 0.0); theLastCell = lastPrimary(); } // Now select randomly a sub-cell of the chosen cell if ( cheapRandom() ) { theLastCell = lastCell()->generate(lo, up, theRnd); } else { DVector rndv(lastDimension()); rnd(lastDimension(), rndv); theLastCell = lastCell()->generate(lo, up, rndv); } } template inline typename ACDCGen::FncPtrType ACDCGen::generate() { long itry = 0; while ( true ) { if ( ++itry > maxTry() ) return FncPtrType(); ++theN; // First choose a function and a cell to generate in. DVector up; DVector lo; chooseCell(lo, up); // Now choose a point in that cell according to a flat distribution. DimType D = lastDimension(); theLastPoint.resize(D); for ( DimType d = 0; d < D; ++d ) theLastPoint[d] = rnd(lo[d], up[d]); // Calculate the function value in this point theLastF = FncTraits::value(lastFunction(), theLastPoint); if ( theLastF <= 0.0 ) continue; // If we are compensating we require the function value to be // above the previous overestimate of the function. if ( compensating() && lastF() < levels.back().g ) theLastF = 0.0; double w = lastF()/lastCell()->g(); if ( w > 1.0 ) { // If the value was above the overestimate then we must start // the compensation procedure and the curren point is disregarded. --theN; compensate(lo, up); continue; } // Accept the point according to the ratio of the true and // overestimated function value. theSumW[last()] += w; theSumW2[last()] += w*w; ++theNI[last()]; if ( w > rnd() ) { ++theNAcc; return lastFunction(); } } } template inline void ACDCGen::reject() { theSumW[last()] -= 1.0; theSumW2[last()] -= 1.0; --theNAcc; } template inline bool ACDCGen::compensating() { while ( levels.size() && levels.back().lastN < N() ) levels.pop_back(); // Leave all levels which has reached there 'expiry date'. return !levels.empty(); } template inline long ACDCGen::compleft() const { if ( levels.empty() ) return 0; long left = 1; for ( int i = 0, Ni = levels.size(); i < Ni; ++i ) left = max(left, levels[i].lastN - N()); return left; } template inline void ACDCGen:: compensate(const DVector & lo, const DVector & up) { //Save the previous overestimated integral and create a new //compensation level. double i0 = maxInt(); Level level; level.g = lastCell()->g(); // Start the divide-and-conquer algorithm slicing up the selected // cell and specify it as the cell to compensate. Slicer slicer(lastDimension(), *this, lo, up); level.cell = slicer.first; level.index = last(); level.up = slicer.firstup; level.lo = slicer.firstlo; // Now calculate the the new overestimated total integral and // calculate the number of attempted points needed to compensate. double rat = (doMaxInt())/i0; level.lastN = long(N()*rat); // If we are already compensating increase also the previous // compensation levels. for ( size_type i = 0; i < levels.size(); ++i ) levels[i].lastN = long(levels[i].lastN*rat); levels.insert(levels.end(), level); maxsize = std::max(maxsize, levels.size()); } template inline void ACDCGen::eps(double newEps) { theEps = newEps; } template inline void ACDCGen::margin(double newMargin) { theMargin = newMargin; } template inline long ACDCGen::N() const { return theN; } template inline long ACDCGen::n() const { return theNAcc; } template inline typename ACDCGen::size_type ACDCGen::nTry() const { return theNTry; } template inline void ACDCGen::nTry(size_type newNTry) { theNTry = newNTry; } template inline long ACDCGen::maxTry() const { return theMaxTry; } template inline void ACDCGen::maxTry(long newMaxTry) { theMaxTry = newMaxTry; } template inline bool ACDCGen::cheapRandom() const { return useCheapRandom; } template inline void ACDCGen::cheapRandom(bool b) { useCheapRandom = b; } template inline double ACDCGen::maxInt() const { return theSumMaxInts.back(); } template inline double ACDCGen::doMaxInt() { for ( size_type i = 1, imax = functions().size(); i < imax; ++i ) theSumMaxInts[i] = sumMaxInts()[i - 1] + cells()[i]->doMaxInt(); return maxInt(); } template inline int ACDCGen::nBins() const { int sum = 0; for ( size_type i = 1; i < functions().size(); ++i ) sum += cell(i)->nBins(); return sum; } template inline int ACDCGen::depth() const { int mx = 0; for ( size_type i = 1; i < functions().size(); ++i ) mx = max(mx, cell(i)->depth()); return mx; } template inline double ACDCGen::efficiency() const { return N() > 0? double(n())/double(N()): 0.0; } template inline double ACDCGen::integral(FncPtrType f) const { if ( N() <= 0 ) return maxInt(); double sumw = 0.0; for ( size_type i = 1; i < functions().size(); ++i ) if ( functions()[i] == f || !f ) sumw += theSumW[i]; return maxInt()*sumw/N(); } template inline double ACDCGen::integralErr(FncPtrType f) const { if ( N() <= 0 ) return maxInt(); double sumw2 = 0.0; double sumw = 0.0; for ( size_type i = 1; i < functions().size(); ++i ) if ( functions()[i] == f || !f ) { sumw2 += theSumW2[i]; sumw += theSumW[i]; } if ( f ) return maxInt()*sqrt(sumw2)/N(); return maxInt()*sqrt(max(0.,sumw2 - sumw*sumw/N()))/N(); } template inline double ACDCGen::eps() const { return theEps; } template inline double ACDCGen::margin() const { return theMargin; } template inline double ACDCGen::rnd() const { return RndTraits::rnd(theRnd); } template inline double ACDCGen::rnd(double lo, double up) const { return RndTraits::rnd(theRnd, lo, up); } template inline void ACDCGen:: rnd(const DVector & lo, const DVector & up, DVector & r) const { RndTraits::rnd(theRnd, lo.begin(), lo.end(), up.begin(), r.begin()); } template inline void ACDCGen:: rnd(DimType D, DVector & r) const { RndTraits::rnd(theRnd, D, r.begin()); } template inline long ACDCGen::rndInt(long x) const { return RndTraits::rndInt(theRnd, x); } template inline const typename ACDCGen::FncVector & ACDCGen::functions() const { return theFunctions; } template inline typename ACDCGen::FncPtrType ACDCGen::function(size_type i) const { return functions()[i]; } template inline typename ACDCGen::FncPtrType ACDCGen::lastFunction() const { return function(last()); } template inline const typename ACDCGen::DimVector & ACDCGen::dimensions() const { return theDimensions; } template inline DimType ACDCGen::dimension(size_type i) const { return dimensions()[i]; } template inline DimType ACDCGen::lastDimension() const { return dimension(last()); } template inline const typename ACDCGen::CellVector & ACDCGen::cells() const { return thePrimaryCells; } template inline ACDCGenCell * ACDCGen::cell(size_type i) const { return cells()[i]; } template inline ACDCGenCell * ACDCGen::lastPrimary() const { return cell(last()); } template inline const DVector & ACDCGen::sumMaxInts() const { return theSumMaxInts; } template inline typename ACDCGen::size_type ACDCGen::last() const { return theLast; } template inline typename ACDCGen::size_type ACDCGen::size() const { return cells().size() - 1; } template inline ACDCGenCell * ACDCGen::lastCell() const { return theLastCell; } template inline const DVector & ACDCGen::lastPoint() const { return theLastPoint; } template inline double ACDCGen::lastF() const { return theLastF; } template typename ACDCGen::size_type ACDCGen::maxsize = 0; template vector ACDCGen::extractCellInfo() const { vector ret; for ( size_type i = 1; i < cells().size(); ++i ) { DVector lo(dimension(i), 0.0); DVector up(dimension(i), 1.0); cell(i)->extract(lo, up, ret); } return ret; } template ACDCGen::Slicer:: Slicer(DimType Din, ACDCGen & gen, const DVector & loin, const DVector & upin) : D(Din), lo(loin), up(upin), xcl(loin), xcu(upin), xhl(loin), xhu(upin), fhl(Din, 0.0), fhu(Din, 0.0), xsel(gen.lastPoint()), fsel(gen.lastF()), current(gen.lastCell()), first(gen.lastCell()), firstlo(loin), firstup(upin),f(gen.lastFunction()), epsilon(gen.eps()), margin(gen.margin()), minf(0.0), wholecomp(false) { divideandconquer(); } template ACDCGen::Slicer::~Slicer() { // Added for debugging purposes. } template void ACDCGen::Slicer::divideandconquer() { // If the current function value was just a little above the // overestimate, just increase the overestimate of this cell and // we're done. if ( fsel < current->g()*margin ) { current->g(current->g()*margin); return; } // First initialize and slice up the current cell and save the // resulting for the compensation procedure. init(); slice(); if ( !wholecomp ) { first = current; firstlo = lo; firstup = up; } // Find the largest function value in the current cell and as long // as it is above the current overestimate, increase the // overestimate and repeat the slicing. while ( shiftmaxmin() > current->g() ) { current->g(minf*margin); if ( current->g() > fsel ) return; init(); slice(); } } template double ACDCGen::Slicer::shiftmaxmin() { // Find the largest diagonal DVector test = xsel; double scale = 0.0; for ( DimType d = 0; d < D; ++d ) if ( fhl[d] > fsel || fhu[d] > fsel ) scale += 1.0; scale = sqrt(scale); for ( DimType d = 0; d < D; ++d ) { if ( fhl[d] > fsel && fhl[d] > fhu[d] ) test[d] = test[d] + (xhl[d] - test[d])/scale; if ( fhu[d] > fsel && fhu[d] > fhl[d] ) test[d] = test[d] + (xhu[d] - test[d])/scale; } // Find the largest value above overestimate DimType dsel = -1; double x = 0; minf = fsel; for ( DimType d = 0; d < D; ++d ) { // Find the point with the function minimum value above the // current overestimate. minf = std::min(minf, fhl[d]); minf = std::min(minf, fhu[d]); // Find points with the maximum function value and shift the // current point to it. if ( fhu[d] > fsel ) { fsel = fhu[d]; dsel = d; x = xhu[d]; } if ( fhl[d] > fsel ) { fsel = fhl[d]; dsel = d; x = xhl[d]; } } // Check also the largest diagonal // double ftest = (*f)(test); // if ( ftest > fsel ) { // xsel = test; // fsel = ftest; // dsel = -1; // } if ( dsel >= 0 ) xsel[dsel] = x; minf = std::max(minf, current->g()); return fsel; } template void ACDCGen::Slicer::dohalf(DimType d) { xcl[d] = lo[d]; // Find the point closest below the current point in the given // dimension with a function value below the current overestimate, // also find the one furthest away from the current point with a // function value above the current overestimate. Use a crude // iterative mid-point selection. while ( true ) { xhl[d] = (xsel[d] + xcl[d])*0.5; std::swap(xsel[d], xhl[d]); fhl[d] = FncTraits::value(f, xsel); std::swap(xsel[d], xhl[d]); if ( fhl[d] > current->g() ) break; if ( xsel[d] - xcl[d] < epsilon ) break; xcl[d] = xhl[d]; } // Check if the current slicing is worth doing... double cut = ( up[d] - xcl[d] )/( up[d] - lo[d] ); if ( cut < 1.0 - current->g()/fsel && cut > 0.0 ) rateslice.insert(std::make_pair(cut, -1-d)); // Find the point closest above the current point in the given // dimension with a function value below the current overestimate, // also find the one furthest away from the current point with a // function value above the current overestimate. Use a crude // iterative mid-point selection. xcu[d] = up[d]; while ( true ) { xhu[d] = (xsel[d] + xcu[d])*0.5; std::swap(xsel[d], xhu[d]); fhu[d] = FncTraits::value(f, xsel); std::swap(xsel[d], xhu[d]); if ( fhu[d] > current->g() ) break; if ( xcu[d] - xsel[d] < epsilon ) break; xcu[d] = xhu[d]; } // Check if the current slicing is worth doing... cut = ( xcu[d] - lo[d] )/( up[d] - lo[d] ); if ( cut < 1.0 - current->g()/fsel && cut > 0.0 ) rateslice.insert(std::make_pair(cut, 1+d)); } template void ACDCGen::Slicer::init() { for ( DimType d = 0; d < D; ++d ) dohalf(d); } template void ACDCGen::Slicer::slice() { while ( !rateslice.empty() ) { // Perform the slicing which reduces the volume of the cell the // most first. DimType d = rateslice.begin()->second; rateslice.erase(rateslice.begin()); if ( d > 0 ) { // Slice from above. d = d - 1; current->splitme(lo[d], xcu[d], up[d], d); checkdiag(current->upper(), d, xcu[d], up[d]); current = current->lower(); up[d] = xcu[d]; } else { // Slice from below.. d = -d - 1; current->splitme(lo[d], xcl[d], up[d], d); checkdiag(current->lower(), d, lo[d], xcl[d]); current = current->upper(); lo[d] = xcl[d]; } dohalf(d); } } template void ACDCGen::Slicer:: checkdiag(ACDCGenCell * cell, DimType dc, double lod, double upd) { return; // Look at the midpoint in the dc direction in which a cell has been // chopped off. if ( upd - lod <= epsilon ) return; DVector newlo = lo; DVector newup = up; newlo[dc] = lod; newup[dc] = upd; DVector newsel = xsel; newsel[dc] = 0.5*(lod + upd); double newfsel = FncTraits::value(f, newsel); double newfh = newfsel; DVector newxsel = newsel; vector dir(D, 0); // For each other direction look at the mid point between the point // chosen above and the borders of the cell. Save the point which // gives the highest function value. for ( DimType d = 0; d < D; ++d ) { if ( d == dc ) continue; double xdum = 0.5*(newlo[d] + newsel[d]); swap(xdum, newsel[d]); double fh1 = FncTraits::value(f, newsel); if ( fh1 > newfsel ) { newfsel = fh1; newxsel = newsel; } if ( fh1 > newfh ) dir[d] = -1; swap(xdum, newsel[d]); xdum = 0.5*(newsel[d] + newup[d]); swap(xdum, newsel[d]); double fh2 = FncTraits::value(f, newsel); if ( fh2 > newfsel ) { newfsel = fh2; newxsel = newsel; } if ( fh2 > newfh && fh2 > fh1 ) dir[d] = 1; swap(xdum, newsel[d]); } // Now check along the diagonal where we found the highest values. for ( DimType d = 0; d < D; ++d ) { if ( dir[d] == 0 ) continue; if ( dir[d] > 0 ) newsel[d] = 0.5*(newsel[d] + newup[d]); else newsel[d] = 0.5*(newlo[d] + newsel[d]); } newfh = FncTraits::value(f, newsel); if ( newfh > newfsel ) { newfsel = newfh; newxsel = newsel; } if ( newfsel < cell->g() ) return; // If this the highest value is above the overestimate, also this // cell needs to be divided up and conquered. wholecomp = true; Slicer dummy(D, *this, cell, newlo, newxsel, newup, newfsel); } template ACDCGen::Slicer:: Slicer(DimType Din, const Slicer & s, ACDCGenCell * cellin, const DVector & loin, const DVector & xselin, const DVector & upin, double fselin) : D(Din), lo(loin), up(upin), xcl(loin), xcu(upin), xhl(loin), xhu(upin), fhl(Din, 0.0), fhu(Din, 0.0), xsel(xselin), fsel(fselin), current(cellin), first(cellin), firstlo(loin), firstup(upin),f(s.f), epsilon(s.epsilon), margin(s.margin), minf(0.0), wholecomp(false) { divideandconquer(); } template template void ACDCGen::output(POStream & os) const { os << theNAcc << theN << theEps << theMargin << theNTry << theMaxTry << useCheapRandom << theLast << theLastPoint << theLastF << theFunctions.size() << levels.size(); for ( int i = 1, N = theFunctions.size(); i < N; ++i ) os << theFunctions[i] << theDimensions [i] << theSumMaxInts[i] << *thePrimaryCells[i] << theNI[i] << theSumW[i] << theSumW2[i]; if ( theLast > 0 ) // first entry in thePrimaryCells always points at 0x0 os << thePrimaryCells[theLast]->getIndex(theLastCell); else os << -1l; for ( int i = 0, N = levels.size(); i < N; ++i ) os << levels[i].lastN << levels[i].g << levels[i].index << levels[i].up << levels[i].lo << thePrimaryCells[levels[i].index]->getIndex(levels[i].cell); } template template void ACDCGen::input(PIStream & is) { clear(); long fsize = 0; long lsize = 0; is >> theNAcc >> theN >> theEps >> theMargin >> theNTry >> theMaxTry >> useCheapRandom >> theLast >> theLastPoint >> theLastF >> fsize >> lsize; while ( --fsize ) { theFunctions.push_back(FncPtrType()); theDimensions.push_back(DimType()); theSumMaxInts.push_back(0.0); theNI.push_back(0); theSumW.push_back(0.0); theSumW2.push_back(0.0); thePrimaryCells.push_back(new ACDCGenCell(0.0)); is >> theFunctions.back() >> theDimensions.back() >> theSumMaxInts.back() >> *thePrimaryCells.back() >> theNI.back() >> theSumW.back() >> theSumW2.back(); } long index = -1; is >> index; if ( index == -1 ) theLastCell = 0x0; else theLastCell = thePrimaryCells[theLast]->getCell(index); while ( lsize-- ) { levels.push_back(Level()); is >> levels.back().lastN >> levels.back().g >> levels.back().index >> levels.back().up >> levels.back().lo >> index; levels.back().cell = thePrimaryCells[levels.back().index]->getCell(index); } } } diff --git a/ACDC/ACDCGenCell.h b/ACDC/ACDCGenCell.h --- a/ACDC/ACDCGenCell.h +++ b/ACDC/ACDCGenCell.h @@ -1,284 +1,284 @@ // -*- C++ -*- // // ACDCGenCell.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ACDCGenCell_H #define ACDCGenCell_H #include "ACDCGenConfig.h" #include "ACDCTraits.h" namespace ACDCGenerator { struct ACDCGenCellInfo; /** ACDCGenCell is the class representing a generation cell in ACDCGen. */ class ACDCGenCell { public: /** * Constructor taking the maximum value as argument. */ inline ACDCGenCell(double newG); /** * Constructor taking the maximum value and the volume as argument. */ inline ACDCGenCell(double newG, double newV); /** * The destuctor will also delete all child cells. */ inline ~ACDCGenCell(); /** * Choose a cell recursively according to their relative * overestimated integrals. * @param lo the lower-left corner of the chosen cell. * @param up the upper-right corner of the chosen cell. * @param rnd the random generator object used to throw dice to * choose sub-cell. * @return a pointer to the chosen cell. */ template inline ACDCGenCell * generate(DVector & lo, DVector & up, RndType * rnd); /** * Choose a cell recursively according to their relative * overestimated integrals. * @param lo the lower-left corner of the chosen cell. * @param up the upper-right corner of the chosen cell. * @param rndv a pre-generated set of random numbers (one for each * dimension) used to choose sub-cell and then rescales that random * number to be reused by the sub-cell. * @return a pointer to the chosen cell. */ inline ACDCGenCell * generate(DVector & lo, DVector & up, DVector & rndv); /** * Find a cell. For a given phase space point, \a x, find the * corresponding cell. Afterwards, the \a up and \a lo vectors will * contain the upper-right and lower-left corners of the chosen * cell. */ inline ACDCGenCell * getCell(DVector & lo, const DVector & x, DVector & up); /** * Smooth out the levels. If one cell has an overestimated integral * which is less than \a frac of the adjacent one, rescale it to * avoid situations where it is never sampled. */ inline void smooth(double frac); /** * Returns true if this cell has been split. */ inline bool isSplit() const; /** * Recalculate (recursively) the overestimated integral for this * cell (and of the sub-cells) and return it. Optionally \a rescale * the overestimated integral. */ inline double doMaxInt(double rescale = 1.0); /** * Return the last calculated the overestimated integral for this * cell. */ inline double maxInt() const; /** * Split this cell into two. The cell is split along the \a newDim * direction, where the lower and upper limit is given by \a lo and * \a up and the point of division is given by \a newDiv. */ inline void splitme(double lo, double newDiv, double up, DimType newDim); /** * Set a new overestimated maximum function value in this cell. */ inline void g(double newG); /** * Return the overestimated maximum function value in this cell. */ inline double g() const; /** * Return the volume of this cell. */ inline double v() const; /** * Return the direction in which it has been split. Return -1 if it * has not been split. */ inline DimType dim() const; /** * Return the point of division in the dim() direction. Return -1.0 * if it has not been split. */ inline double div() const; /** * Return the upper sub-cell. Return null if it has not been split. */ inline ACDCGenCell * upper() const; /** * Return the lower sub-cell. Return null if it has not been split. */ inline ACDCGenCell * lower() const; /** * Return the number of cells in this sub-tree which have not been * split. */ inline int nBins() const; /** * Return the maximum depth of this sub-tree. */ inline int depth() const; /** * Append ACDCGenCellInfo objects describing this subtree to a given * vector. * @param lo the lower-left corner of this cell. * @param up the upper-right corner of this cell. * @param v the vector where the ACDCGenCellInfo objects will be appended. */ inline void extract(DVector & lo, DVector & up, vector & v) const; /** * Get the index of the given cell. */ inline long getIndex(const ACDCGenCell * c) const; /** * Helper function for getIndex(const ACDCGenCell *) with an extra * argument to use as counter. */ inline long getIndex(const ACDCGenCell * c, long & indx) const; /** * Return the cell corresponding to the given index \a i. */ inline ACDCGenCell * getCell(long i); /** * Helper function for getCell(long) with an extra argument to use as * counter. */ inline ACDCGenCell * getCell(long i, long & indx); public: /** * If the cell has not been split this is the overestimated maximum * function value in this cell. Otherwise it is the weighted * average of the sub-cells values. */ double theG; /** * The volume of this cell. */ double theV; /** * Pointers to the upper sub-cell. */ ACDCGenCell * theUpper; /** * Pointers to the lower sub-cell. */ ACDCGenCell * theLower; /** * The point of division in the dim() direction. */ double theDivision; /** * The direction in which it has been split. */ DimType theSplitDimension; private: /** * Default constructor is private and not implemented. */ ACDCGenCell(); /** * Copy constructor is private and not implemented. */ ACDCGenCell(const ACDCGenCell &); /** * Assignment is private and not implemented. */ ACDCGenCell & operator=(const ACDCGenCell &) = delete; }; /** * This is a class describing cells to the outside world to be used * for debugging purposes. They only make sense if extracted with the * ACDCGenCell::extract function. */ struct ACDCGenCellInfo { /** the integer used for indices. */ typedef vector::size_type Index; /** * The overestimated maximum function value of this cell. */ double g; /** * The volume of the corresponding cell. */ double v; /** * The upper-right corner of the corresponding cell. */ DVector up; /** * The lower-left corner of the corresponding cell. */ DVector lo; /** * The index of the upper sub-cells in the vector in which the * corresponding cell was inserted. */ Index iup; /** * The index of the lower sub-cell in the vector in which the * corresponding cell was inserted. */ Index ilo; }; } #include "ACDCGenCell.icc" #endif diff --git a/ACDC/ACDCGenCell.icc b/ACDC/ACDCGenCell.icc --- a/ACDC/ACDCGenCell.icc +++ b/ACDC/ACDCGenCell.icc @@ -1,227 +1,227 @@ // -*- C++ -*- // // ACDCGenCell.icc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // namespace ACDCGenerator { inline ACDCGenCell::ACDCGenCell(double newG) : theG(newG), theV(1.0), theUpper(0), theLower(0), theDivision(-1.0), theSplitDimension(-1) {} inline ACDCGenCell:: ACDCGenCell(double newG, double newV) : theG(newG), theV(newV), theUpper(0), theLower(0), theDivision(-1.0), theSplitDimension(-1) {} inline ACDCGenCell::~ACDCGenCell() { if ( isSplit() ) { delete theUpper; delete theLower; } } template inline ACDCGenCell * ACDCGenCell:: generate(DVector & lo, DVector & up, RndType * rnd) { if ( isSplit() ) { if ( ACDCRandomTraits:: rndBool(rnd, upper()->maxInt(), lower()->maxInt()) ) { lo[dim()] = div(); return upper()->generate(lo, up, rnd); } else { up[dim()] = div(); return lower()->generate(lo, up, rnd); } } return this; } inline ACDCGenCell * ACDCGenCell:: generate(DVector & lo, DVector & up, DVector & rndv) { if ( isSplit() ) { double r = lower()->maxInt()/maxInt(); if ( rndv[dim()] > r ) { lo[dim()] = div(); rndv[dim()] = (rndv[dim()] - r)/(1.0 - r); return upper()->generate(lo, up, rndv); } else { up[dim()] = div(); rndv[dim()] = rndv[dim()]/r; return lower()->generate(lo, up, rndv); } } return this; } inline ACDCGenCell * ACDCGenCell:: getCell(DVector & lo, const DVector & x, DVector & up) { if ( isSplit() ) { if ( x[dim()] > div() ) { lo[dim()] = div(); return upper()->getCell(lo, x, up); } else { up[dim()] = div(); return lower()->getCell(lo, x, up); } } else return this; } inline void ACDCGenCell:: splitme(double lo, double newDiv, double up, DimType newDim) { theSplitDimension = newDim; theDivision = newDiv; double frac = (up - div())/(up - lo); theUpper = new ACDCGenCell(g(), v()*frac); frac = (div() - lo)/(up - lo); theLower = new ACDCGenCell(g(), v()*frac); } inline bool ACDCGenCell::isSplit() const { return upper(); } inline double ACDCGenCell::doMaxInt(double scale) { if ( isSplit() ) theG = (upper()->doMaxInt() + lower()->doMaxInt())/v(); else theG *= scale; return maxInt(); } inline void ACDCGenCell::smooth(double frac) { if ( !isSplit() ) return; upper()->smooth(frac); lower()->smooth(frac); if ( upper()->maxInt() < lower()->maxInt()*frac && upper()->maxInt() > 0.0 ) upper()->doMaxInt(lower()->maxInt()*frac/upper()->maxInt()); else if ( lower()->maxInt() < upper()->maxInt()*frac && lower()->maxInt() > 0.0 ) lower()->doMaxInt(upper()->maxInt()*frac/lower()->maxInt()); doMaxInt(); } inline double ACDCGenCell::maxInt() const { return g()*v(); } inline void ACDCGenCell::g(double newG) { theG = newG; } inline int ACDCGenCell::nBins() const { return isSplit()? upper()->nBins() + lower()->nBins(): 1; } inline int ACDCGenCell::depth() const { return isSplit()? std::max(upper()->depth(), lower()->depth()) + 1: 1; } inline double ACDCGenCell::g() const { return theG; } inline double ACDCGenCell::v() const { return theV; } inline double ACDCGenCell::div() const { return theDivision; } inline DimType ACDCGenCell::dim() const { return theSplitDimension; } inline ACDCGenCell * ACDCGenCell::upper() const { return theUpper; } inline ACDCGenCell * ACDCGenCell::lower() const { return theLower; } inline void ACDCGenCell:: extract(DVector & lo, DVector & up, vector & out) const { // First add this cell which gets index isave. ACDCGenCellInfo::Index isave = out.size(); out.push_back(ACDCGenCellInfo()); out.back().g = g(); out.back().v = v(); out.back().up = up; out.back().lo = lo; out.back().iup = 0; out.back().ilo = 0; if ( isSplit() ) { // If split add the upper cell. out[isave].iup = out.size(); double save = lo[dim()]; lo[dim()] = div(); upper()->extract(lo, up, out); lo[dim()] = save; // Then add the lower cell. out[isave].ilo = out.size(); save = up[dim()]; up[dim()] = div(); lower()->extract(lo, up, out); up[dim()] = save; } } template inline OStream & operator<<(OStream & os, const ACDCGenCell & c) { os << c.dim() << c.div() << c.g() << c.v(); if ( c.dim() < 0 ) return os; return os << *c.upper() << *c.lower(); } template inline IStream & operator>>(IStream & is, ACDCGenCell & c) { is >> c.theSplitDimension >> c.theDivision >> c.theG >> c.theV; if ( c.dim() < 0 ) return is; c.theUpper = new ACDCGenCell(0.0); c.theLower = new ACDCGenCell(0.0); return is >> *c.theUpper >> *c.theLower; } inline long ACDCGenCell::getIndex(const ACDCGenCell * c) const { long indx = -1; return getIndex(c, indx); } inline long ACDCGenCell::getIndex(const ACDCGenCell * c, long & indx) const { ++indx; if ( c == this ) return indx; if ( isSplit() ) { long i = upper()->getIndex(c, indx); if ( i >= 0 ) return i; return lower()->getIndex(c, indx); } return -1; } inline ACDCGenCell * ACDCGenCell::getCell(long i) { long indx = -1; return getCell(i, indx); } inline ACDCGenCell * ACDCGenCell::getCell(long i, long & indx) { ++indx; if ( i == indx ) return this; if ( isSplit() ) { ACDCGenCell * tmp = upper()->getCell(i, indx); if ( tmp ) return tmp; return lower()->getCell(i, indx); } return 0; } } diff --git a/ACDC/ACDCGenConfig.h b/ACDC/ACDCGenConfig.h --- a/ACDC/ACDCGenConfig.h +++ b/ACDC/ACDCGenConfig.h @@ -1,62 +1,62 @@ // -*- C++ -*- // // ACDCGenConfig.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ACDCGenConfig_H #define ACDCGenConfig_H /** @file ACDCGenConfig.h is the main config header file for * ACDCGen. Do not make changes in this file. If you need to modify * anything, edit a copy of the file which can be included instead of * this file using the macro ACDC_ALT_CONFIG. * * ACDCGen uses some classes and functions from the standard * library. These are here imported into the ACDCGenerator * namespace. If alternative classes with the same API are needed * these should be imported with the same name into the namespace in * the ACDC_ALT_CONFIG file. */ #ifndef ACDC_ALT_CONFIG #include #include #include /** The namespace in which all ACDCGen classes are defined. */ namespace ACDCGenerator { using std::vector; using std::multimap; using std::numeric_limits; using std::map; using std::max; using std::min; using std::swap; using std::make_pair; /** The integer type used to represent the dimension of the a * functions to be sampled- */ typedef short DimType; } #else #include ACDC_ALT_CONFIG #endif namespace ACDCGenerator { /** A vector of doubles. */ typedef vector DVector; } #endif diff --git a/ACDC/ACDCTraits.h b/ACDC/ACDCTraits.h --- a/ACDC/ACDCTraits.h +++ b/ACDC/ACDCTraits.h @@ -1,109 +1,109 @@ // -*- C++ -*- // // ACDCTraits.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ACDCTraits_H #define ACDCTraits_H namespace ACDCGenerator { /** * ACDCTraitsType is an empty non-polymorphic base class for all * traits classes in ACDCGenerator. */ struct ACDCTraitsType {}; /** * ACDCFncTraits defines the interface to functions to be sampled by * ACDCGen. It only defines one function which defines how the * functions are called. If the default implementation is not * suitable, ACDCFncTraits may be specialized for a function class * implementing a function with the same signature. */ template struct ACDCFncTraits: public ACDCTraitsType { /** * Call a function to be sampled by ACDCGen. * @return (*f)(x). */ static inline double value(const FncPtr & f, const DVector & x) { return (*f)(x); } }; /** * ACDCRandomTraits defines the interface to random number generator * objects to be used by ACDCGen. If this default implementation is * not suitable, ACDCRandomTraits may be specialized for any class as * long as functions with the same signature are present. */ template struct ACDCRandomTraits: public ACDCTraitsType { /** * Return a flat random number in the interval ]0,1[. */ static inline double rnd(Rnd * r) { return r->flat(); } /** * Return a flat random number in the interval ]\a xl,\a xu[. */ static inline double rnd(Rnd * r, double xl, double xu) { return xl + (xu - xl)*rnd(r); } /** * Generate a set of random numbers. * @param r the random generator. * @param l an input iterator giving the lower limit of the interval * of the first requested random number. * @param lend an input iterator marking the end of the range of * requested random numbers. * @param u an input iterator giving the upper limit of the interval * of the first requested random number. * @param res the ouput iterator used to output the random numbers. */ template static inline void rnd(Rnd * r, InputIterator l, InputIterator lend, InputIterator u, OutputIterator res) { for ( ; l != lend; ++l ) *res++ = *l + (*u++ - *l)*rnd(r); } /** * Generate \a D random numbers. The numbers are put into the * OutputIterator \a res. */ template static inline void rnd(Rnd * r, int D, OutputIterator res) { for ( int d = 0; d < D; ++d ) *res++ = rnd(r); } /** * Return true with probability \a x. */ static inline bool rndBool(Rnd * r, double x) { return rnd(r) < x; } /** * Return true with probability \a x(\a x + \a y). */ static inline bool rndBool(Rnd * r, double x, double y) { return rndBool(r, x/(x + y)); } /** * Return a random integer in the interval [0,\a x[. */ static inline long rndInt(Rnd * r, long x) { return long(rnd(r, 0.0, double(x))); } }; } #endif diff --git a/ACDC/DRand48Traits.h b/ACDC/DRand48Traits.h --- a/ACDC/DRand48Traits.h +++ b/ACDC/DRand48Traits.h @@ -1,90 +1,90 @@ // -*- C++ -*- // // DRand48Traits.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef DRand48Traits_H #define DRand48Traits_H #include #include "ACDCTraits.h" namespace ACDCGenerator { /** @cond TRAITSPECIALIZATIONS */ /** Dummy struct to represent the standard drand48() random number generator. */ struct DRAND48 {}; /** * Specialization of ACDCRandomTraits for using the standard drand48() * random number generator. */ template <> struct ACDCRandomTraits: public ACDCTraitsType { /** * Return a flat random number in the interval ]0,1[. */ static inline double rnd(DRAND48 * r) { return drand48(); } /** * Return a flat random number in the interval ]\a xl,\a xu[. */ static inline double rnd(DRAND48 * r, double xl, double xu) { return xl + (xu - xl)*rnd(r); } /** * Generate a set of random numbers. * @param r the random generator. * @param l an input iterator giving the lower limit of the interval * of the first requested random number. * @param lend an input iterator marking the end of the range of * requested random numbers. * @param u an input iterator giving the upper limit of the interval * of the first requested random number. * @param res the ouput iterator used to output the random numbers. */ template static inline void rnd(DRAND48 * r, InputIterator l, InputIterator lend, InputIterator u, OutputIterator res) { for ( ; l != lend; ++l ) *res++ = *l + (*u++ - *l)*rnd(r); } /** * Generate \a D random numbers. The numbers are put into the * OutputIterator \a res. */ template static inline void rnd(DRAND48 * r, int D, OutputIterator res) { for ( int d = 0; d < D; ++d ) *res++ = rnd(r); } /** * Return true with probability \a x. */ static inline bool rndBool(DRAND48 * r, double x) { return rnd(r) < x; } /** * Return true with probability \a x(\a x + \a y). */ static inline bool rndBool(DRAND48 * r, double x, double y) { return rndBool(r, x/(x + y)); } /** * Return a random integer in the interval [0,\a x[. */ static inline long rndInt(DRAND48 * r, long x) { return long(rnd(r, 0.0, double(x))); } }; /** @endcond */ } #endif diff --git a/Analysis/FactoryBase.cc b/Analysis/FactoryBase.cc --- a/Analysis/FactoryBase.cc +++ b/Analysis/FactoryBase.cc @@ -1,195 +1,195 @@ // -*- C++ -*- // // FactoryBase.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the FactoryBase class. // #include "FactoryBase.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Config/algorithm.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "AIDA_helper.h" using namespace ThePEG; FactoryBase::FactoryBase() : theFilename(""), theSuffix("aida"), theStoreType("xml"), theAnalysisFactory(0), theTree(0), theHistogramFactory(0), theDataSetFactory(0) {} FactoryBase::FactoryBase(const FactoryBase & x) : Interfaced(x), theFilename(x.theFilename), theSuffix(x.theSuffix), theStoreType(x.theStoreType), theAnalysisFactory(0), theTree(0), theHistogramFactory(0), theDataSetFactory(0) {} FactoryBase::~FactoryBase() {} FactoryBase::DataFiller::~DataFiller() { int N = v.size()/(3*dset->dimension()); for ( int i = 0; i < N; ++i ) { AIDA::IDataPoint * p = dset->addPoint(); for ( int j = 0; j < p->dimension(); ++j ) { p->coordinate(j)->setValue(v.front()); v.pop_front(); p->coordinate(j)->setErrorPlus(v.front()); v.pop_front(); p->coordinate(j)->setErrorMinus(v.front()); v.pop_front(); } } } void FactoryBase::clear() { if ( theTree ) delete theTree; if ( theAnalysisFactory ) delete theAnalysisFactory; theHistogramFactory = 0; theDataSetFactory = 0; theTree = 0; theAnalysisFactory = 0; } void FactoryBase::dofinish() { Interfaced::dofinish(); for_each(clients, mem_fn(&InterfacedBase::finish)); tree().commit(); clear(); } void FactoryBase::doinitrun() { Interfaced::doinitrun(); string file = filename(); if ( file == "" ) file = generator()->filename(); else if ( file[0] != '/' ) file = generator()->path() + "/" + file; file += "." + suffix(); theTree = analysisFactory().createTreeFactory()->create (file, storeType(), false, true); theTree->setOverwrite(false); theHistogramFactory = analysisFactory().createHistogramFactory(tree()); theDataSetFactory = analysisFactory().createDataPointSetFactory(tree()); } void FactoryBase::persistentOutput(PersistentOStream & os) const { os << theFilename << theSuffix << theStoreType; } void FactoryBase::persistentInput(PersistentIStream & is, int) { clear(); is >> theFilename >> theSuffix >> theStoreType; } AbstractClassDescription FactoryBase::initFactoryBase; // Definition of the static class description member. void FactoryBase::Init() { static ClassDocumentation documentation ("There is no documentation for the FactoryBase class"); static Parameter interfaceFilename ("Filename", "Together with Suffix, the name of the file " "where the resulting histograms will be stored. If empty, the run-name " "provided by the current EventGenerator will be used instead.", &FactoryBase::theFilename, "", true, false); static Parameter interfaceSuffix ("Suffix", "Together with Filename, the name of the file " "where the resulting histograms will be stored.", &FactoryBase::theSuffix, "aida", true, false); static Parameter interfaceStoreType ("StoreType", "The format in which the histograms are stored in the output file. " "The allowed values depend on the actual AIDA implementation used.", &FactoryBase::theStoreType, "xml", true, false); } AIDA::ITree & FactoryBase::tree() const { return *theTree; } AIDA::IHistogramFactory & FactoryBase::histogramFactory() const { return *theHistogramFactory; } AIDA::IDataPointSetFactory & FactoryBase::dataSetFactory() const { return *theDataSetFactory; } void FactoryBase::mkdir(const string & path) { tree().mkdir(path); } void FactoryBase::mkdirs(const string & path) { tree().mkdirs(path); } void FactoryBase::cd(const string & path) { tree().cd(path); } FactoryBase::tH1DPtr FactoryBase::createHistogram1D(const string & path, int nb, double lo, double up) { return histogramFactory().createHistogram1D(path, nb, lo, up); } FactoryBase::tH1DPtr FactoryBase::createHistogram1D(const string & path, const string & title, int nb, double lo, double up) { return histogramFactory().createHistogram1D(path, title, nb, lo, up); } FactoryBase::tH1DPtr FactoryBase::createHistogram1D(const string & path, const string & title, const std::vector & edges) { return histogramFactory().createHistogram1D(path, title, edges); } FactoryBase::tH2DPtr FactoryBase::createHistogram2D(const string & path, int nbx, double xlo, double xup, int nby, double ylo, double yup) { return histogramFactory().createHistogram2D(path, nbx, xlo, xup, nby, ylo, yup); } FactoryBase::tH2DPtr FactoryBase::createHistogram2D(const string & path, const string & title, int nbx, double xlo, double xup, int nby, double ylo, double yup) { return histogramFactory().createHistogram2D(path, title, nbx, xlo, xup, nby, ylo, yup); } FactoryBase::tH2DPtr FactoryBase::createHistogram2D(const string & path, const string & title, const std::vector & xedges, const std::vector & yedges) { return histogramFactory().createHistogram2D(path, title, xedges, yedges); } FactoryBase::DataFiller FactoryBase::createDataSet(const string & path, const string & title, int dim) { return DataFiller(dataSetFactory().create(path, title, dim)); } void FactoryBase::registerClient(tIPtr client) { initrun(); clients.insert(client); } diff --git a/Analysis/FactoryBase.h b/Analysis/FactoryBase.h --- a/Analysis/FactoryBase.h +++ b/Analysis/FactoryBase.h @@ -1,551 +1,551 @@ // -*- C++ -*- // // FactoryBase.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_FactoryBase_H #define THEPEG_FactoryBase_H // // This is the declaration of the FactoryBase class. // #include "ThePEG/Interface/Interfaced.h" #include "FactoryBase.fh" namespace AIDA { class IHistogram1D; class IHistogram2D; class IDataPointSet; class IAnalysisFactory; class ITree; class IHistogramFactory; class IDataPointSetFactory; } namespace ThePEG { /** * Here is the documentation of the FactoryBase class. This * abstract class is used to wrap the interface to a particular * AIDA-compliant histogram package to be used in * AnalysisHandlers in ThePEG. Concrete subclasses must * implement the doinitrun() function to create an object of a class * inheriting from AIDA::IAnalysisFactory and assign it with the * analysisFactory(AIDA::IAnalysisFactory*) function before calling * doinitrun() for the FactoryBase base class. * * A FactoryBase object should be assigned to the EventGenerator * object controlling a run, and AnalysisHandlers should * access it via the Generator with the generator() function. * * @see \ref FactoryBaseInterfaces "The interfaces" * defined for FactoryBase. */ class FactoryBase: public Interfaced { public: /** * Convenient typedef for pointer to AIDA::IHistogram1D. */ typedef AIDA::IHistogram1D * tH1DPtr; /** * Convenient typedef for pointer to const AIDA::IHistogram1D. */ typedef const AIDA::IHistogram1D * tcH1DPtr; /** * Convenient typedef for pointer to AIDA::IHistogram2D. */ typedef AIDA::IHistogram2D * tH2DPtr; /** * Convenient typedef for pointer to const AIDA::IHistogram2D. */ typedef const AIDA::IHistogram2D * tcH2DPtr; /** * Convenient typedef for pointer to AIDA::IHistogram1D. */ typedef AIDA::IDataPointSet * tDSetPtr; /** * Convenient typedef for pointer to const AIDA::IHistogram1D. */ typedef const AIDA::IDataPointSet * tcDSetPtr; public: /** * DataFiller is a helper class to facilitate adding data to a * DataPointSet. For a D-dimensional DataPointSet N*3*D numbers should * be added with the standard << operator ordered as x-value, * x-upper-error, x-lower-error, y-value, y-upper-error, etc.. Only * when the DataFIller object is detleted will the points be added. */ class DataFiller { public: /** * The standard constructor needs a IDataPointSet as argument. */ DataFiller(AIDA::IDataPointSet * dps) : dset(dps) {} /** * Copy constructor. */ DataFiller(const DataFiller & df) : dset(df.dset) {} /** * Destructor. Will commit the pints filled to the underlying * IDataPointSet. */ ~DataFiller(); /** * Add a number to measurement currently being read. */ DataFiller & operator<<(double x) { v.push_back(x); return *this; } /** * Automatic conversion to the underlying IDataPointSet. */ operator AIDA::IDataPointSet * () { return dset; } private: /** * The underlying IDataPointSet. */ AIDA::IDataPointSet * dset; /** * The collected numbers to be committed to the IDataPointSet. */ deque v; }; public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ FactoryBase(); /** * The copy constructor. */ FactoryBase(const FactoryBase &); /** * The destructor. */ virtual ~FactoryBase(); //@} public: /** @name Simple access functions. */ //@{ /** * Together with suffix(), the name of the file where the resulting * histograms will be stored. If empty, generator()->filename() will * be used instead. */ const string & filename() const { return theFilename; } /** * Together with filename(), the name of the file where the * resulting histograms will be stored. */ const string & suffix() const { return theSuffix; } /** * The format in which the histograms are stored in the output file. */ const string & storeType() const { return theStoreType; } //@} /** @name Manipulate histograms */ //@{ /** * Rescale the given \a histogram so that the integral over the bins * will give the correct integrated cross section for the observable * in the given \a unit. */ virtual void normalizeToXSec(tH1DPtr histogram, CrossSection unit = picobarn) const = 0; /** * Rescale the given \a histogram so that the integral over the bins * will give the correct integrated cross section for the observable * in the given \a unit. */ virtual void normalizeToXSec(tH2DPtr histogram, CrossSection unit = picobarn) const = 0; /** * Rescale the given \a histogram so that the integral over the bins * gives the fraction of the total cross section generated which is * contained in the bins. */ virtual void normalizeToXSecFraction(tH1DPtr histogram) const = 0; /** * Rescale the given \a histogram so that the integral over the bins * gives the fraction of the total cross section generated which is * contained in the bins. */ virtual void normalizeToXSecFraction(tH2DPtr histogram) const = 0; /** * Rescale the given \a histogram so that the integral over the bins * gives one. */ virtual void normalizeToUnity(tH1DPtr histogram) const = 0; /** * Rescale the given \a histogram so that the integral over the bins * gives one. */ virtual void normalizeToUnity(tH2DPtr histogram) const = 0; //@} /** @name Access the underlying AIDA objects. */ //@{ /** * Access the underlying AIDA::IAnalysisFactory object. */ AIDA::IAnalysisFactory & analysisFactory() const { return *theAnalysisFactory; } /** * Access the underlying AIDA::ITree object. */ AIDA::ITree & tree() const; /** * A pointer to the underlying AIDA::IHistogramFactory object. */ AIDA::IHistogramFactory & histogramFactory() const; /** * A pointer to the underlying AIDA::IDataPointSetFactory object. */ AIDA::IDataPointSetFactory & dataSetFactory() const; /** * Create a new directory in the underlying AIDA tree. */ void mkdir(const string & path); /** * Create a new directory in the underlying AIDA tree. */ void mkdirs(const string & path); /** * Set the default working directory for the underlying AIDA tree. */ void cd(const string & path); /** * Create and return a AIDA::IHistogram1D object in the underlying * AIDA histogram factory. Note that the histogram factory is * responsible for deleting this histogram. * @param path the full path of where the histogram should be placed * in the underlying AIDA tree (on the form * "/dir/subdir/histogramname"). Not that the directory part of the * path typically must already exist in the tree. The directories * can be created with mkdir(string) or mkdirs(string). * The title of the histogram will be set to the name part of the path. * @param nb the number of bins in the histogram. * @param lo the lower edge of the histogram. * @param up the upper edge of the histogram. * @return a pointer to the created AIDA::IHistogram1D object. */ tH1DPtr createHistogram1D(const string & path, int nb, double lo, double up); /** * Create and return a AIDA::IHistogram1D object in the underlying * AIDA histogram factory. Note that the histogram factory is * responsible for deleting this histogram. * @param path the full path of where the histogram should be placed * in the underlying AIDA tree (on the form * "/dir/subdir/histogramname"). Not that the directory part of the * path typically must already exist in the tree. The directories * can be created with mkdir(string) or mkdirs(string). * @param title the title of the histogram. * @param nb the number of bins in the histogram. * @param lo the lower edge of the histogram. * @param up the upper edge of the histogram. * @return a pointer to the created AIDA::IHistogram1D object. */ tH1DPtr createHistogram1D(const string & path, const string & title, int nb, double lo, double up); /** * Create and return a AIDA::IHistogram1D object in the underlying * AIDA histogram factory. Note that the histogram factory is * responsible for deleting this histogram. * @param path the full path of where the histogram should be placed * in the underlying AIDA tree (on the form * "/dir/subdir/histogramname"). Not that the directory part of the * path typically must already exist in the tree. The directories * can be created with mkdir(string) or mkdirs(string). * @param title the title of the histogram. * @param edges A vector of bin edges specifying th bins. * @return a pointer to the created AIDA::IHistogram1D object. */ tH1DPtr createHistogram1D(const string & path, const string & title, const std::vector & edges); /** * Create and return a AIDA::IHistogram2D object in the underlying * AIDA histogram factory. Note that the histogram factory is * responsible for deleting this histogram. * @param path the full path of where the histogram should be placed * in the underlying AIDA tree (on the form * "/dir/subdir/histogramname"). Not that the directory part of the * path typically must already exist in the tree. The directories * can be created with mkdir(string) or mkdirs(string). * The title of the histogram will be set to the name part of the path. * @param nbx the number of x-bins in the histogram. * @param xlo the lower x-edge of the histogram. * @param xup the upper x-edge of the histogram. * @param nbx the number of y-bins in the histogram. * @param xlo the lower y-edge of the histogram. * @param xup the upper y-edge of the histogram. * @return a pointer to the created AIDA::IHistogram1D object. */ tH2DPtr createHistogram2D(const string & path, int nbx, double xlo, double xup, int nby, double ylo, double yup); /** * Create and return a AIDA::IHistogram2D object in the underlying * AIDA histogram factory. Note that the histogram factory is * responsible for deleting this histogram. * @param path the full path of where the histogram should be placed * in the underlying AIDA tree (on the form * "/dir/subdir/histogramname"). Not that the directory part of the * path typically must already exist in the tree. The directories * can be created with mkdir(string) or mkdirs(string). * @param title the title of the histogram. * @param nbx the number of x-bins in the histogram. * @param xlo the lower x-edge of the histogram. * @param xup the upper x-edge of the histogram. * @param nby the number of y-bins in the histogram. * @param ylo the lower y-edge of the histogram. * @param yup the upper y-edge of the histogram. * @return a pointer to the created AIDA::IHistogram1D object. */ tH2DPtr createHistogram2D(const string & path, const string & title, int nbx, double xlo, double xup, int nby, double ylo, double yup); /** * Create and return a AIDA::IHistogram2D object in the underlying * AIDA histogram factory. Note that the histogram factory is * responsible for deleting this histogram. * @param path the full path of where the histogram should be placed * in the underlying AIDA tree (on the form * "/dir/subdir/histogramname"). Not that the directory part of the * path typically must already exist in the tree. The directories * can be created with mkdir(string) or mkdirs(string). * @param title the title of the histogram. * @param xedges A vector of bin edges specifying the x-bins. * @param yedges A vector of bin edges specifying the y-bins. * @return a pointer to the created AIDA::IHistogram1D object. */ tH2DPtr createHistogram2D(const string & path, const string & title, const std::vector & xedges, const std::vector & yedges); /** * Create a IDataPointSet with the given \a path and \a title and * containing points with the given number of dimensions, \a * dim. The returned object is a DataFiller which can be used to * facilitate the addition of data points to the set or be converted * to a pointer to the created IDataPointSet. */ DataFiller createDataSet(const string & path, const string & title, int dim); /** * Used by a \a client object to indicate that he has required * histograms from this factory. It is guaranteed that the clients * finish() function is called before the underlying AIDA::ITree is * committed and the AIDA::IHistogramFactory is deleted together * with all histograms. */ void registerClient(tIPtr client); //@} protected: /** * Set the underlying AIDA::IAnalysisFactory object. Note that this * surrenders the controll of the factory to the FactoryBase * object which will delete it in the finish() function. Typically * this function should be called by a concrete subclass in the * doinitrun() function before the doinitrun() function of this * class is called. */ void analysisFactory(AIDA::IAnalysisFactory * x) { theAnalysisFactory = x; } /** * Delete all associated AIDA objects. Note that the tree is not * explicitly committed. */ void clear(); public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object. 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(); //@} private: /** * Together with theSuffix, the name of the file where the resulting * histograms will be stored. If empty, generator()->filename() will * be used instead. */ string theFilename; /** * Together with theFilename, the name of the file where the * resulting histograms will be stored. */ string theSuffix; /** * The format in which the histograms are stored in the output file. */ string theStoreType; /** * A pointer to the underlying AIDA::IAnalysisFactory object. */ AIDA::IAnalysisFactory * theAnalysisFactory; /** * A pointer to the underlying AIDA::ITree object. */ AIDA::ITree * theTree; /** * A pointer to the underlying AIDA::IHistogramFactory object. */ AIDA::IHistogramFactory * theHistogramFactory; /** * A pointer to the underlying AIDA::IDataPointSetFactory object. */ AIDA::IDataPointSetFactory * theDataSetFactory; /** * A set of client objects which have required histograms from this * factory. */ set clients; private: /** * The static object used to initialize the description of this class. * Indicates that this is an abstract class with persistent data. */ static AbstractClassDescription initFactoryBase; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FactoryBase & operator=(const FactoryBase &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of FactoryBase. */ template <> struct BaseClassTrait { /** Typedef of the first base class of FactoryBase. */ typedef Interfaced NthBase; }; /** This template specialization informs ThePEG about the name of * the FactoryBase 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::FactoryBase"; } }; /** @endcond */ } #endif /* THEPEG_FactoryBase_H */ diff --git a/Analysis/GraphvizPlot.cc b/Analysis/GraphvizPlot.cc --- a/Analysis/GraphvizPlot.cc +++ b/Analysis/GraphvizPlot.cc @@ -1,92 +1,92 @@ // -*- C++ -*- // // Graphviz.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the Graphviz class. // #include "GraphvizPlot.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/EventRecord/Event.h" #include "ThePEG/EventRecord/StandardSelectors.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG; void GraphvizPlot::dofinish() { AnalysisHandler::dofinish(); if (! _quiet ) cout << "\nGraphvizPlot: plots can be generated like this:\n" << "GraphvizPlot: 'dot -Tsvg " << generator()->filename() << '-' << name() << '-' << _eventNumber << ".dot > plot.svg'\n"; } void GraphvizPlot::analyze(tEventPtr event, long, int, int) { if (event->number() != _eventNumber) return; // prepare dot file ostringstream fname; fname << generator()->filename() << '-' << name() << '-' << event->number() << ".dot"; ofstream hepmcdotfile(fname.str().c_str()); printGraphviz(hepmcdotfile, event); hepmcdotfile.close(); } void GraphvizPlot::persistentOutput(PersistentOStream & os) const { os << _eventNumber << _quiet; } void GraphvizPlot::persistentInput(PersistentIStream & is, int) { is >> _eventNumber >> _quiet; } ClassDescription GraphvizPlot::initGraphvizPlot; // Definition of the static class description member. void GraphvizPlot::Init() { static ClassDocumentation documentation ("There is no documentation for the GraphvizPlot class"); static Parameter interfaceEventNumber ("EventNumber", "The number of the event that should be drawn.", &GraphvizPlot::_eventNumber, 1, 1, 1, false, false, Interface::lowerlim); interfaceEventNumber.setHasDefault(false); static Switch interfaceQuiet ("Quiet", "Prevent GraphvizPlot from outputing instructions for how to generate " "the actual graph.", &GraphvizPlot::_quiet, false, true, false); static SwitchOption interfaceQuietVerbose (interfaceQuiet, "Verbose", "Allow output.", false); static SwitchOption interfaceQuietQuiet (interfaceQuiet, "Quiet", "Prevent output.", true); interfaceQuiet.setHasDefault(false); } diff --git a/Analysis/GraphvizPlot.h b/Analysis/GraphvizPlot.h --- a/Analysis/GraphvizPlot.h +++ b/Analysis/GraphvizPlot.h @@ -1,184 +1,184 @@ // -*- C++ -*- // // Graphviz.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_GraphvizPlot_H #define THEPEG_GraphvizPlot_H // // This is the declaration of the GraphvizPlot class. // #include "ThePEG/Repository/CurrentGenerator.h" #include "ThePEG/Handlers/AnalysisHandler.h" namespace ThePEG { /** \ingroup Analysis * The GraphvizPlot class generates * an output of the tree structure of the event which can be viewed using dot. * * @see \ref GraphvizPlotInterfaces "The interfaces" * defined for GraphvizPlot. */ class GraphvizPlot: public AnalysisHandler { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ GraphvizPlot() : _eventNumber(1), _quiet(false) {} //@} public: /** @name Virtual functions required by the AnalysisHandler class. */ //@{ /** * Analyze a given Event. Note that a fully generated event * may be presented several times, if it has been manipulated in * between. The default version of this function will call transform * to make a lorentz transformation of the whole event, then extract * all final state particles and call analyze(tPVector) of this * analysis object and those of all associated analysis objects. The * default version will not, however, do anything on events which * have not been fully generated, or have been manipulated in any * way. * @param event pointer to the Event to be analyzed. * @param ieve the event number. * @param loop the number of times this event has been presented. * If negative the event is now fully generated. * @param state a number different from zero if the event has been * manipulated in some way since it was last presented. */ virtual void analyze(tEventPtr event, long ieve, int loop, int state); //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const {return new_ptr(*this);} /** 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 {return new_ptr(*this);} //@} protected: /** @name Standard Interfaced functions. */ //@{ /** * Finalize this object. Called in the run phase just after a * run has ended. Used eg. to write out statistics. */ virtual void dofinish(); //@} /** * Helper function to obtain the name of a particle. */ string particleName(tcPPtr) const; private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initGraphvizPlot; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ GraphvizPlot & operator=(const GraphvizPlot &) = delete; private: /** * Event number that should be drawn */ long _eventNumber; /** * Tell the object not to write out messages to the standard output. */ bool _quiet; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of GraphvizPlot. */ template <> struct BaseClassTrait { /** Typedef of the first base class of GraphvizPlot. */ typedef AnalysisHandler NthBase; }; /** This template specialization informs ThePEG about the name of * the GraphvizPlot 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::GraphvizPlot"; } /** Return the name(s) of the shared library (or libraries) be loaded to get * access to the GraphvizPlot class and any other class on which it depends * (except the base class). */ static string library() { return "GraphvizPlot.so"; } }; /** @endcond */ } #endif /* THEPEG_GraphvizPlot_H */ diff --git a/Analysis/HIHepMCFile.cc b/Analysis/HIHepMCFile.cc --- a/Analysis/HIHepMCFile.cc +++ b/Analysis/HIHepMCFile.cc @@ -1,319 +1,319 @@ // -*- C++ -*- // // HIHepMCFile.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the HIHepMCFile class. // #include "HIHepMCFile.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/EventRecord/Event.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Vectors/HepMCConverter.h" using namespace ThePEG; HIHepMCFile::HIHepMCFile() : _eventNumber(1), _format(1), _filename(), #ifdef HAVE_HEPMC_ROOTIO _ttreename(),_tbranchname(), #endif _unitchoice(), _geneventPrecision(16) {} // Cannot copy streams. // Let doinitrun() take care of their initialization. HIHepMCFile::HIHepMCFile(const HIHepMCFile & x) : AnalysisHandler(x), _eventNumber(x._eventNumber), _format(x._format), _filename(x._filename), #ifdef HAVE_HEPMC_ROOTIO _ttreename(x._ttreename),_tbranchname(x._tbranchname), #endif _hepmcio(), _hepmcdump(), _unitchoice(x._unitchoice), _geneventPrecision(x._geneventPrecision) {} IBPtr HIHepMCFile::clone() const { return new_ptr(*this); } IBPtr HIHepMCFile::fullclone() const { return new_ptr(*this); } void HIHepMCFile::doinitrun() { AnalysisHandler::doinitrun(); switch ( _format ) { #ifdef HAVE_HEPMC3 default: { if ( _filename.empty() ) _filename = generator()->filename() + ".hepmc"; HepMC::WriterAsciiHepMC2 * tmpio = new HepMC::WriterAsciiHepMC2(_filename.c_str()); tmpio->set_precision(_geneventPrecision); _hepmcio = tmpio; } break; case 6: { if ( _filename.empty() ) _filename = generator()->filename() + ".hepmc"; HepMC::WriterAscii * tmpio = new HepMC::WriterAscii(_filename.c_str()); tmpio->set_precision(_geneventPrecision); _hepmcio = tmpio; } break; case 7: { if ( _filename.empty() ) _filename = generator()->filename() + ".hepevt"; HepMC::WriterHEPEVT * tmpio = new HepMC::WriterHEPEVT(_filename.c_str()); _hepmcio = tmpio; } break; #ifdef HAVE_HEPMC_ROOTIO case 8: { if ( _filename.empty() ) _filename = generator()->filename() + ".root"; HepMC::WriterRoot * tmpio = new HepMC::WriterRoot(_filename.c_str()); _hepmcio = tmpio; } break; case 9: { if ( _filename.empty() ) _filename = generator()->filename() + ".root"; HepMC::WriterRootTree * tmpio = new HepMC::WriterRootTree(_filename.c_str()); _hepmcio = tmpio; } break; #endif #else default: { HepMC::IO_GenEvent * tmpio = new HepMC::IO_GenEvent(_filename.c_str(), ios::out); tmpio->precision(_geneventPrecision); _hepmcio = tmpio; } break; case 2: _hepmcio = new HepMC::IO_AsciiParticles(_filename.c_str(), ios::out); break; case 5: _hepmcio = 0; _hepmcdump.open(_filename.c_str()); break; #endif } } void HIHepMCFile::dofinish() { #ifdef HAVE_HEPMC3 _hepmcio->close(); delete _hepmcio; #else if (_hepmcio) { delete _hepmcio; _hepmcio = 0; } else _hepmcdump.close(); #endif AnalysisHandler::dofinish(); cout << "\nHIHepMCFile: generated HepMC output.\n"; } void HIHepMCFile::analyze(tEventPtr event, long, int, int) { if (event->number() > _eventNumber) return; Energy eUnit; Length lUnit; switch (_unitchoice) { default: eUnit = GeV; lUnit = millimeter; break; case 1: eUnit = MeV; lUnit = millimeter; break; case 2: eUnit = GeV; lUnit = centimeter; break; case 3: eUnit = MeV; lUnit = centimeter; break; } #ifdef HAVE_HEPMC3 if (!_hepmcio->run_info()) { _hepmcio->set_run_info(std::make_shared()); std::vector w_names; w_names.push_back("Default"); for ( map::const_iterator w = event->optionalWeights().begin(); w != event->optionalWeights().end(); ++w ) { w_names.push_back(w->first); } _hepmcio->run_info()->set_weight_names(w_names); } #endif HepMC::GenEvent * hepmc = HepMCConverter::convert(*event, false, eUnit, lUnit); #ifdef HAVE_HEPMC3 std::shared_ptr heavyion=std::make_shared(); heavyion->set(1,1,1,1,1,1); #else HepMC::HeavyIon heavyion(1,1,1,1,1,1); #endif const LorentzPoint v1 = event->incoming().first->vertex(); const LorentzPoint v2 = event->incoming().second->vertex(); double bpar = (v1 - v2).perp()/femtometer; #ifdef HAVE_HEPMC3 heavyion->event_plane_angle=atan2((v1 - v2).y(),(v1 - v2).x()); heavyion->impact_parameter=float(bpar); #else heavyion.HepMC::HeavyIon::set_event_plane_angle(atan2((v1 - v2).y(),(v1 - v2).x())); heavyion.HepMC::HeavyIon::set_impact_parameter(float(bpar)); #endif #ifdef HAVE_HEPMC3 // Clear and blatant abuse of the Pdf info container!! HepMC::GenPdfInfoPtr pdfinfo=std::make_shared(); pdfinfo->set(1,1,event->optionalWeight("averageKappa"),event->optionalWeight("junctions"),event->optionalWeight("lambdaSum"),1,1); #else HepMC::PdfInfo pdfinfo(1,1,event->optionalWeight("averageKappa"),event->optionalWeight("junctions"),event->optionalWeight("lambdaSum"),1,1); #endif #ifdef HAVE_HEPMC3 hepmc->set_heavy_ion(heavyion); hepmc->set_pdf_info(pdfinfo); #else hepmc->set_heavy_ion(heavyion); hepmc->set_pdf_info(pdfinfo); #endif #ifdef HAVE_HEPMC3 if (!_hepmcio->run_info()) { _hepmcio->set_run_info(std::make_shared()); std::vector w_names; w_names.push_back("Default"); for ( map::const_iterator w = event->optionalWeights().begin(); w != event->optionalWeights().end(); ++w ) { w_names.push_back(w->first); } _hepmcio->run_info()->set_weight_names(w_names); } hepmc->set_run_info(_hepmcio->run_info()); if (_hepmcio) _hepmcio->write_event(*hepmc); #else if (_hepmcio) _hepmcio->write_event(hepmc); else hepmc->print(_hepmcdump); #endif delete hepmc; } void HIHepMCFile::persistentOutput(PersistentOStream & os) const { os << _eventNumber << _format << _filename << _unitchoice << _geneventPrecision; } void HIHepMCFile::persistentInput(PersistentIStream & is, int) { is >> _eventNumber >> _format >> _filename >> _unitchoice >> _geneventPrecision; } ClassDescription HIHepMCFile::initHIHepMCFile; // Definition of the static class description member. void HIHepMCFile::Init() { static ClassDocumentation documentation ("This analysis handler will output the event record in HepMC format."); static Parameter interfacePrintEvent ("PrintEvent", "The number of events that should be printed.", &HIHepMCFile::_eventNumber, 1, 0, 0, false, false, Interface::lowerlim); static Switch interfaceFormat ("Format", #ifdef HAVE_HEPMC3 #ifdef HAVE_HEPMC_ROOTIO "Output format (1 = GenEvent, 6 = GenEventHepMC3, 7 = HEPEVT, 8 = GenEvent in ROOT, 9 = GenEvent in ROOT TTree )", #else "Output format (1 = GenEvent, 6 = GenEventHepMC3, 7 = HEPEVT", #endif #else "Output format (1 = GenEvent, 2 = AsciiParticles, 5 = HepMC dump", #endif &HIHepMCFile::_format, 1, false, false); static SwitchOption interfaceFormatGenEvent (interfaceFormat, "GenEvent", "IO_GenEvent format", 1); static SwitchOption interfaceFormatAsciiParticles (interfaceFormat, "AsciiParticles", "Deprecated (IO_AsciiParticles format)", 2); static SwitchOption interfaceFormatDump (interfaceFormat, "Dump", "Event dump (human readable)", 5); static Parameter interfaceFilename ("Filename", "Name of the output file", &HIHepMCFile::_filename, ""); #ifdef HAVE_HEPMC_ROOTIO static Parameter interfaceTTreename ("TTreename", "Name of the TTree in output file", &HIHepMCFile::_ttreename, "hepmc3_tree"); static Parameter interfaceTBranchname ("TBranchname", "Name of the branch in output file", &HIHepMCFile::_tbranchname, "hepmc3_tree"); #endif static Parameter interfacePrecision ("Precision", "Choice of output precision for the GenEvent format " " (as number of digits).", &HIHepMCFile::_geneventPrecision, 16, 6, 16, false, false, Interface::limited); static Switch interfaceUnits ("Units", "Unit choice for energy and length", &HIHepMCFile::_unitchoice, 0, false, false); static SwitchOption interfaceUnitsGeV_mm (interfaceUnits, "GeV_mm", "Use GeV and mm as units.", 0); static SwitchOption interfaceUnitsMeV_mm (interfaceUnits, "MeV_mm", "Use MeV and mm as units.", 1); static SwitchOption interfaceUnitsGeV_cm (interfaceUnits, "GeV_cm", "Use GeV and cm as units.", 2); static SwitchOption interfaceUnitsMeV_cm (interfaceUnits, "MeV_cm", "Use MeV and cm as units.", 3); } diff --git a/Analysis/HIHepMCFile.h b/Analysis/HIHepMCFile.h --- a/Analysis/HIHepMCFile.h +++ b/Analysis/HIHepMCFile.h @@ -1,232 +1,232 @@ // -*- C++ -*- // // HIHepMCFile.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_HIHepMCFile_H #define THEPEG_HIHepMCFile_H // // This is the declaration of the HIHepMCFile class. // #include #include #include #include "ThePEG/Handlers/AnalysisHandler.h" #include "ThePEG/Repository/CurrentGenerator.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Config/HepMCHelper.h" namespace ThePEG { /** \ingroup Analysis * The HIHepMCFile class outputs ThePEG events in HepMC format with additional Heavy Ion information. * * @see \ref HIHepMCFileInterfaces "The interfaces" * defined for HIHepMCFile. */ class HIHepMCFile: public AnalysisHandler { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ HIHepMCFile(); /** * The copy constructor. */ HIHepMCFile(const HIHepMCFile &); //@} public: /** @name Virtual functions required by the AnalysisHandler class. */ //@{ /** * Analyze a given Event. Note that a fully generated event * may be presented several times, if it has been manipulated in * between. The default version of this function will call transform * to make a lorentz transformation of the whole event, then extract * all final state particles and call analyze(tPVector) of this * analysis object and those of all associated analysis objects. The * default version will not, however, do anything on events which * have not been fully generated, or have been manipulated in any * way. * @param event pointer to the Event to be analyzed. * @param ieve the event number. * @param loop the number of times this event has been presented. * If negative the event is now fully generated. * @param state a number different from zero if the event has been * manipulated in some way since it was last presented. */ virtual void analyze(tEventPtr event, long ieve, int loop, int state); //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} protected: /** @name Standard Interfaced functions. */ //@{ /** * 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(); //@} private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initHIHepMCFile; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ HIHepMCFile & operator=(const HIHepMCFile &) = delete; private: /** * Last event that should be written out as HepMC format */ long _eventNumber; /** * The HepMC format */ int _format; /** * The HepMC filename */ string _filename; #ifdef HAVE_HEPMC_ROOTIO /** * The name of TTRee in ROOT file */ string _ttreename; /** * The name of branch in ROOT file */ string _tbranchname; #endif /** * The HepMC I/O handler */ #ifdef HAVE_HEPMC3 HepMC::Writer *_hepmcio; #else HepMC::IO_BaseClass *_hepmcio; #endif /** * The HepMC dump file */ ofstream _hepmcdump; /** * Selector for the choice of units */ int _unitchoice; /** * Choice of output precision in GenEvent format */ unsigned int _geneventPrecision; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of HIHepMCFile. */ template <> struct BaseClassTrait { /** Typedef of the first base class of HIHepMCFile. */ typedef AnalysisHandler NthBase; }; /** This template specialization informs ThePEG about the name of * the HIHepMCFile 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::HIHepMCFile"; } /** Return the name(s) of the shared library (or libraries) be loaded to get * access to the HIHepMCFile class and any other class on which it depends * (except the base class). */ static string library() { return "HepMCAnalysis.so"; } }; /** @endcond */ } #endif /* THEPEG_HIHepMCFile_H */ diff --git a/Analysis/HepMC3File.cc b/Analysis/HepMC3File.cc --- a/Analysis/HepMC3File.cc +++ b/Analysis/HepMC3File.cc @@ -1,144 +1,144 @@ // -*- C++ -*- // // HepMC3File.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the HepMC3File class. // #include "HepMC3File.h" #include #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/EventRecord/Event.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Config/HepMCHelper.h" #include "HepMC/IO/IO_GenEvent.h" using namespace ThePEG; HepMC3File::HepMC3File() : _eventNumber(1), _filename(), _unitchoice(), _geneventPrecision(16) {} // Cannot copy streams. // Let doinitrun() take care of their initialization. HepMC3File::HepMC3File(const HepMC3File & x) : AnalysisHandler(x), _eventNumber(x._eventNumber), _filename(x._filename), _hepmcio(), _unitchoice(x._unitchoice), _geneventPrecision(x._geneventPrecision) {} IBPtr HepMC3File::clone() const { return new_ptr(*this); } IBPtr HepMC3File::fullclone() const { return new_ptr(*this); } void HepMC3File::doinitrun() { AnalysisHandler::doinitrun(); // set default filename unless user-specified name exists if ( _filename.empty() ) _filename = generator()->filename() + ".hepmc"; HepMC::IO_GenEvent * tmpio = new HepMC::IO_GenEvent(_filename.c_str(), ios::out); tmpio->set_precision(_geneventPrecision); _hepmcio = tmpio; } void HepMC3File::dofinish() { if (_hepmcio) { delete _hepmcio; _hepmcio = 0; } AnalysisHandler::dofinish(); cout << "\nHepMC3File: generated HepMC output.\n"; } void HepMC3File::analyze(tEventPtr event, long, int, int) { if (event->number() > _eventNumber) return; HepMC::GenEvent * hepmc = HepMCConverter::convert(*event, false, GeV, millimeter); if (_hepmcio) _hepmcio->write_event(*hepmc); delete hepmc; } void HepMC3File::persistentOutput(PersistentOStream & os) const { os << _eventNumber << _filename << _unitchoice << _geneventPrecision; } void HepMC3File::persistentInput(PersistentIStream & is, int) { is >> _eventNumber >> _filename >> _unitchoice >> _geneventPrecision; } ClassDescription HepMC3File::initHepMC3File; // Definition of the static class description member. void HepMC3File::Init() { static ClassDocumentation documentation ("This analysis handler will output the event record in HepMC format."); static Parameter interfacePrintEvent ("PrintEvent", "The number of events that should be printed.", &HepMC3File::_eventNumber, 1, 0, 0, false, false, Interface::lowerlim); static Parameter interfaceFilename ("Filename", "Name of the output file", &HepMC3File::_filename, ""); static Parameter interfacePrecision ("Precision", "Choice of output precision for the GenEvent format " " (as number of digits).", &HepMC3File::_geneventPrecision, 16, 6, 16, false, false, Interface::limited); static Switch interfaceUnits ("Units", "Unit choice for energy and length", &HepMC3File::_unitchoice, 0, false, false); static SwitchOption interfaceUnitsGeV_mm (interfaceUnits, "GeV_mm", "Use GeV and mm as units.", 0); static SwitchOption interfaceUnitsMeV_mm (interfaceUnits, "MeV_mm", "Use MeV and mm as units.", 1); static SwitchOption interfaceUnitsGeV_cm (interfaceUnits, "GeV_cm", "Use GeV and cm as units.", 2); static SwitchOption interfaceUnitsMeV_cm (interfaceUnits, "MeV_cm", "Use MeV and cm as units.", 3); } diff --git a/Analysis/HepMC3File.h b/Analysis/HepMC3File.h --- a/Analysis/HepMC3File.h +++ b/Analysis/HepMC3File.h @@ -1,205 +1,205 @@ // -*- C++ -*- // // HepMC3File.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_HepMC3File_H #define THEPEG_HepMC3File_H // // This is the declaration of the HepMC3File class. // #include #include #include "ThePEG/Handlers/AnalysisHandler.h" #include "ThePEG/Repository/CurrentGenerator.h" #include "ThePEG/Repository/EventGenerator.h" #include "HepMC/IO/IO_Base.h" namespace ThePEG { /** \ingroup Analysis * The HepMC3File class outputs ThePEG events in HepMC format. * * @see \ref HepMC3FileInterfaces "The interfaces" * defined for HepMC3File. */ class HepMC3File: public AnalysisHandler { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ HepMC3File(); /** * The copy constructor. */ HepMC3File(const HepMC3File &); //@} public: /** @name Virtual functions required by the AnalysisHandler class. */ //@{ /** * Analyze a given Event. Note that a fully generated event * may be presented several times, if it has been manipulated in * between. The default version of this function will call transform * to make a lorentz transformation of the whole event, then extract * all final state particles and call analyze(tPVector) of this * analysis object and those of all associated analysis objects. The * default version will not, however, do anything on events which * have not been fully generated, or have been manipulated in any * way. * @param event pointer to the Event to be analyzed. * @param ieve the event number. * @param loop the number of times this event has been presented. * If negative the event is now fully generated. * @param state a number different from zero if the event has been * manipulated in some way since it was last presented. */ virtual void analyze(tEventPtr event, long ieve, int loop, int state); //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} protected: /** @name Standard Interfaced functions. */ //@{ /** * 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(); //@} private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initHepMC3File; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ HepMC3File & operator=(const HepMC3File &) = delete; private: /** * Last event that should be written out as HepMC format */ long _eventNumber; /** * The HepMC filename */ string _filename; /** * The HepMC I/O handler */ HepMC::IO_Base *_hepmcio; /** * Selector for the choice of units */ int _unitchoice; /** * Choice of output precision in GenEvent format */ unsigned int _geneventPrecision; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of HepMC3File. */ template <> struct BaseClassTrait { /** Typedef of the first base class of HepMC3File. */ typedef AnalysisHandler NthBase; }; /** This template specialization informs ThePEG about the name of * the HepMC3File 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::HepMCFile"; } /** Return the name(s) of the shared library (or libraries) be loaded to get * access to the HepMC3File class and any other class on which it depends * (except the base class). */ static string library() { return "HepMCAnalysis.so"; } }; /** @endcond */ } #endif /* THEPEG_HepMC3File_H */ diff --git a/Analysis/HepMCFile.cc b/Analysis/HepMCFile.cc --- a/Analysis/HepMCFile.cc +++ b/Analysis/HepMCFile.cc @@ -1,340 +1,340 @@ // -*- C++ -*- // // HepMCFile.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the HepMCFile class. // #include "HepMCFile.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/EventRecord/Event.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Vectors/HepMCConverter.h" using namespace ThePEG; HepMCFile::HepMCFile() : _eventNumber(1), _format(1), _filename(), #ifdef HAVE_HEPMC_ROOTIO _ttreename(),_tbranchname(), #endif _unitchoice(), _geneventPrecision(16), _addHI(0) {} // Cannot copy streams. // Let doinitrun() take care of their initialization. HepMCFile::HepMCFile(const HepMCFile & x) : AnalysisHandler(x), _eventNumber(x._eventNumber), _format(x._format), _filename(x._filename), #ifdef HAVE_HEPMC_ROOTIO _ttreename(x._ttreename),_tbranchname(x._tbranchname), #endif _hepmcio(), _hepmcdump(), _unitchoice(x._unitchoice), _geneventPrecision(x._geneventPrecision) {} IBPtr HepMCFile::clone() const { return new_ptr(*this); } IBPtr HepMCFile::fullclone() const { return new_ptr(*this); } void HepMCFile::doinitrun() { AnalysisHandler::doinitrun(); if ( _filename.empty() ) _filename = generator()->filename() + ".hepmc"; switch ( _format ) { #ifdef HAVE_HEPMC3 default: { HepMC::WriterAsciiHepMC2 * tmpio = new HepMC::WriterAsciiHepMC2(_filename.c_str()); tmpio->set_precision(_geneventPrecision); _hepmcio = tmpio; } break; case 6: { if ( _filename.empty() ) _filename = generator()->filename() + ".hepmc"; HepMC::WriterAscii * tmpio = new HepMC::WriterAscii(_filename.c_str(),NULL); tmpio->set_precision(_geneventPrecision); _hepmcio = tmpio; } break; case 7: { if ( _filename.empty() ) _filename = generator()->filename() + ".hepevt"; HepMC::WriterHEPEVT * tmpio = new HepMC::WriterHEPEVT(_filename.c_str()); _hepmcio = tmpio; } break; #ifdef HAVE_HEPMC_ROOTIO case 8: { if ( _filename.empty() ) _filename = generator()->filename() + ".root"; HepMC::WriterRoot * tmpio = new HepMC::WriterRoot(_filename.c_str()); _hepmcio = tmpio; } break; case 9: { if ( _filename.empty() ) _filename = generator()->filename() + ".root"; HepMC::WriterRootTree * tmpio = new HepMC::WriterRootTree(_filename.c_str()); _hepmcio = tmpio; } break; #endif #else default: { HepMC::IO_GenEvent * tmpio = new HepMC::IO_GenEvent(_filename.c_str(), ios::out); tmpio->precision(_geneventPrecision); _hepmcio = tmpio; } break; case 2: _hepmcio = new HepMC::IO_AsciiParticles(_filename.c_str(), ios::out); break; case 5: _hepmcio = 0; _hepmcdump.open(_filename.c_str()); break; #endif } } void HepMCFile::dofinish() { #ifdef HAVE_HEPMC3 _hepmcio->close(); delete _hepmcio; #else if (_hepmcio) { delete _hepmcio; _hepmcio = 0; } else _hepmcdump.close(); #endif AnalysisHandler::dofinish(); cout << "\nHepMCFile: generated HepMC output.\n"; } void HepMCFile::analyze(tEventPtr event, long, int, int) { if (event->number() > _eventNumber) return; Energy eUnit; Length lUnit; switch (_unitchoice) { default: eUnit = GeV; lUnit = millimeter; break; case 1: eUnit = MeV; lUnit = millimeter; break; case 2: eUnit = GeV; lUnit = centimeter; break; case 3: eUnit = MeV; lUnit = centimeter; break; } #ifdef HAVE_HEPMC3 _hepmcio->set_run_info(std::make_shared()); std::vector w_names; w_names.push_back("Default"); for ( map::const_iterator w = event->optionalWeights().begin(); w != event->optionalWeights().end(); ++w ) { w_names.push_back(w->first); } _hepmcio->run_info()->set_weight_names(w_names); #endif HepMC::GenEvent * hepmc = HepMCConverter::convert(*event, false, eUnit, lUnit); const LorentzPoint v1 = event->incoming().first->vertex(); const LorentzPoint v2 = event->incoming().second->vertex(); if ( _addHI > 0 || ( _addHI == 0 && v1.perp() >= ZERO && v2.perp() >= ZERO ) ) { double bpar = (v1 - v2).perp()/femtometer; #ifdef HAVE_HEPMC3 std::shared_ptr heavyion=std::make_shared(); heavyion->set(1,1,1,1,1,1); heavyion->event_plane_angle=atan2((v1 - v2).y(),(v1 - v2).x()); heavyion->impact_parameter=float(bpar); hepmc->set_heavy_ion(heavyion); #else HepMC::HeavyIon heavyion(1,1,1,1,1,1); heavyion.HepMC::HeavyIon::set_event_plane_angle(atan2((v1 - v2).y(),(v1 - v2).x())); heavyion.HepMC::HeavyIon::set_impact_parameter(float(bpar)); #endif hepmc->set_heavy_ion(heavyion); } #ifdef HAVE_HEPMC3 hepmc->set_run_info( _hepmcio->run_info()); _hepmcio->write_event(*hepmc); #else if (_hepmcio) _hepmcio->write_event(hepmc); else hepmc->print(_hepmcdump); #endif delete hepmc; } void HepMCFile::persistentOutput(PersistentOStream & os) const { os << _eventNumber << _format << _filename << _unitchoice << _geneventPrecision << _addHI; } void HepMCFile::persistentInput(PersistentIStream & is, int) { is >> _eventNumber >> _format >> _filename >> _unitchoice >> _geneventPrecision >> _addHI; } ClassDescription HepMCFile::initHepMCFile; // Definition of the static class description member. void HepMCFile::Init() { static ClassDocumentation documentation ("This analysis handler will output the event record in HepMC format."); static Parameter interfacePrintEvent ("PrintEvent", "The number of events that should be printed.", &HepMCFile::_eventNumber, 1, 0, 0, false, false, Interface::lowerlim); static Switch interfaceFormat ("Format", #ifdef HAVE_HEPMC3 #ifdef HAVE_HEPMC_ROOTIO "Output format (1 = GenEvent, 6 = GenEventHepMC3, 7 = HEPEVT, 8 = GenEvent in ROOT, 9 = GenEvent in ROOT TTree )", #else "Output format (1 = GenEvent, 6 = GenEventHepMC3, 7 = HEPEVT", #endif #else "Output format (1 = GenEvent, 2 = AsciiParticles, 5 = HepMC dump", #endif &HepMCFile::_format, 1, false, false); static SwitchOption interfaceFormatGenEvent (interfaceFormat, "GenEvent", "IO_GenEvent format", 1); static SwitchOption interfaceFormatAsciiParticles (interfaceFormat, "AsciiParticles", "Deprecated (IO_AsciiParticles format)", 2); static SwitchOption interfaceFormatDump (interfaceFormat, "Dump", "Event dump (human readable)", 5); #ifdef HAVE_HEPMC3 static SwitchOption interfaceFormatGenEventHepMC3 (interfaceFormat, "GenEventHepMC3", "GenEvent in HepMC3", 6); static SwitchOption interfaceFormatHEPEVT (interfaceFormat, "HEPEVT", "HEPEVT", 7); #ifdef HAVE_HEPMC_ROOTIO static SwitchOption interfaceFormatGenEventROOT (interfaceFormat, "GenEventROOT", "GenEvent in ROOT", 8); static SwitchOption interfaceFormatGenEventROOTTree (interfaceFormat, "GenEventROOTTree", "GenEvent in ROOT TTree", 9); #endif #endif static Parameter interfaceFilename ("Filename", "Name of the output file", &HepMCFile::_filename, ""); #ifdef HAVE_HEPMC_ROOTIO static Parameter interfaceTTreename ("TTreename", "Name of the TTree in output file", &HepMCFile::_ttreename, "hepmc3_tree"); static Parameter interfaceTBranchname ("TBranchname", "Name of the branch in output file", &HepMCFile::_tbranchname, "hepmc3_tree"); #endif static Parameter interfacePrecision ("Precision", "Choice of output precision for the GenEvent format " " (as number of digits).", &HepMCFile::_geneventPrecision, 16, 6, 16, false, false, Interface::limited); static Switch interfaceUnits ("Units", "Unit choice for energy and length", &HepMCFile::_unitchoice, 0, false, false); static SwitchOption interfaceUnitsGeV_mm (interfaceUnits, "GeV_mm", "Use GeV and mm as units.", 0); static SwitchOption interfaceUnitsMeV_mm (interfaceUnits, "MeV_mm", "Use MeV and mm as units.", 1); static SwitchOption interfaceUnitsGeV_cm (interfaceUnits, "GeV_cm", "Use GeV and cm as units.", 2); static SwitchOption interfaceUnitsMeV_cm (interfaceUnits, "MeV_cm", "Use MeV and cm as units.", 3); static Switch interfaceAddHI ("AddHI", "Options for adding heavy ion info to GenEvent.", &HepMCFile::_addHI, 0, false, false); static SwitchOption interfaceAddHIMaybe (interfaceAddHI, "Maybe", "Add Heavy Ion info if both incoming particles impact parameter is not exactly zero.", 0); static SwitchOption interfaceAddHINever (interfaceAddHI, "Never", "Never add Heavy Ion info.", -1); static SwitchOption interfaceAddHIAlways (interfaceAddHI, "Always", "Always add Heavy Ion info.", 1); } diff --git a/Analysis/HepMCFile.h b/Analysis/HepMCFile.h --- a/Analysis/HepMCFile.h +++ b/Analysis/HepMCFile.h @@ -1,236 +1,236 @@ // -*- C++ -*- // // HepMCFile.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_HepMCFile_H #define THEPEG_HepMCFile_H // // This is the declaration of the HepMCFile class. // #include #include #include #include "ThePEG/Handlers/AnalysisHandler.h" #include "ThePEG/Repository/CurrentGenerator.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Config/HepMCHelper.h" namespace ThePEG { /** \ingroup Analysis * The HepMCFile class outputs ThePEG events in HepMC format. * * @see \ref HepMCFileInterfaces "The interfaces" * defined for HepMCFile. */ class HepMCFile: public AnalysisHandler { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ HepMCFile(); /** * The copy constructor. */ HepMCFile(const HepMCFile &); //@} public: /** @name Virtual functions required by the AnalysisHandler class. */ //@{ /** * Analyze a given Event. Note that a fully generated event * may be presented several times, if it has been manipulated in * between. The default version of this function will call transform * to make a lorentz transformation of the whole event, then extract * all final state particles and call analyze(tPVector) of this * analysis object and those of all associated analysis objects. The * default version will not, however, do anything on events which * have not been fully generated, or have been manipulated in any * way. * @param event pointer to the Event to be analyzed. * @param ieve the event number. * @param loop the number of times this event has been presented. * If negative the event is now fully generated. * @param state a number different from zero if the event has been * manipulated in some way since it was last presented. */ virtual void analyze(tEventPtr event, long ieve, int loop, int state); //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} protected: /** @name Standard Interfaced functions. */ //@{ /** * 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(); //@} private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initHepMCFile; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ HepMCFile & operator=(const HepMCFile &) = delete; private: /** * Last event that should be written out as HepMC format */ long _eventNumber; /** * The HepMC format */ int _format; /** * The HepMC filename */ string _filename; #ifdef HAVE_HEPMC_ROOTIO /** * The name of TTRee in ROOT file */ string _ttreename; /** * The name of branch in ROOT file */ string _tbranchname; #endif /** * The HepMC I/O handler */ #ifdef HAVE_HEPMC3 HepMC::Writer *_hepmcio; #else HepMC::IO_BaseClass *_hepmcio; #endif /** * The HepMC dump file */ ofstream _hepmcdump; /** * Selector for the choice of units */ int _unitchoice; /** * Choice of output precision in GenEvent format */ unsigned int _geneventPrecision; /** * Choice of adding Heavy Ion information. */ int _addHI; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of HepMCFile. */ template <> struct BaseClassTrait { /** Typedef of the first base class of HepMCFile. */ typedef AnalysisHandler NthBase; }; /** This template specialization informs ThePEG about the name of * the HepMCFile 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::HepMCFile"; } /** Return the name(s) of the shared library (or libraries) be loaded to get * access to the HepMCFile class and any other class on which it depends * (except the base class). */ static string library() { return "HepMCAnalysis.so"; } }; /** @endcond */ } #endif /* THEPEG_HepMCFile_H */ diff --git a/Analysis/LWH/AIAnalysisFactory.h b/Analysis/LWH/AIAnalysisFactory.h --- a/Analysis/LWH/AIAnalysisFactory.h +++ b/Analysis/LWH/AIAnalysisFactory.h @@ -1,55 +1,55 @@ // -*- C++ -*- // // AIAnalysisFactory.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef LWH_AIAnalysisFactory_H #define LWH_AIAnalysisFactory_H #include /** @cond DONT_DOCUMENT_STRIPPED_DOWN_AIDA_INTERFACES */ namespace AIDA { class IDataPointSetFactory; class IFitFactory; class IFunctionFactory; class IPlotterFactory; class ITupleFactory; class ITreeFactory; class ITree; class IHistogramFactory; class IAnalysisFactory { public: virtual ~IAnalysisFactory() {} virtual ITreeFactory * createTreeFactory() = 0; virtual IHistogramFactory * createHistogramFactory(ITree & tree) = 0; virtual IDataPointSetFactory * createDataPointSetFactory(ITree &) = 0; virtual ITupleFactory * createTupleFactory(ITree &) = 0; virtual IFunctionFactory * createFunctionFactory(ITree &) = 0; virtual IFitFactory * createFitFactory() = 0; virtual IPlotterFactory * createPlotterFactory(int = 0, char * * = 0, const std::string & = "", const std::string & = "") = 0; }; } /** @endcond */ #endif /* LWH_AIAnalysisFactory_H */ diff --git a/Analysis/LWH/AIAxis.h b/Analysis/LWH/AIAxis.h --- a/Analysis/LWH/AIAxis.h +++ b/Analysis/LWH/AIAxis.h @@ -1,45 +1,45 @@ // -*- C++ -*- // // AIAxis.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef LWH_AIAxis_H #define LWH_AIAxis_H /** @cond DONT_DOCUMENT_STRIPPED_DOWN_AIDA_INTERFACES */ namespace AIDA { class IAxis { public: virtual ~IAxis() {} virtual bool isFixedBinning() const = 0; virtual double lowerEdge() const = 0; virtual double upperEdge() const = 0; virtual int bins() const = 0; virtual double binLowerEdge(int index) const = 0; virtual double binUpperEdge(int index) const = 0; virtual double binWidth(int) const = 0; virtual int coordToIndex(double coord) const = 0; enum { UNDERFLOW_BIN = -2, OVERFLOW_BIN = -1 }; }; } /** @endcond */ #endif /* LWH_AIAxis_H */ diff --git a/Analysis/LWH/AIDataPoint.h b/Analysis/LWH/AIDataPoint.h --- a/Analysis/LWH/AIDataPoint.h +++ b/Analysis/LWH/AIDataPoint.h @@ -1,45 +1,45 @@ // -*- C++ -*- // // AIDataPoint.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef LWH_AIDataPoint_H #define LWH_AIDataPoint_H /** @cond DONT_DOCUMENT_STRIPPED_DOWN_AIDA_INTERFACES */ namespace AIDA { class IMeasurement; /** * Basic user-level interface class for holding and managing * a single set of "measurements". * * @author The AIDA team (http://aida.freehep.org/) * */ class IDataPoint { public: virtual ~IDataPoint() {} virtual int dimension() const = 0; virtual IMeasurement * coordinate(int coord) = 0; virtual const IMeasurement * coordinate(int coord) const = 0; }; } /** @endcond */ #endif /* LWH_AIDataPoint_H */ diff --git a/Analysis/LWH/AIDataPointSet.h b/Analysis/LWH/AIDataPointSet.h --- a/Analysis/LWH/AIDataPointSet.h +++ b/Analysis/LWH/AIDataPointSet.h @@ -1,63 +1,63 @@ // -*- C++ -*- // // AIDataPointSet.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef LWH_AIDataPointSet_H #define LWH_AIDataPointSet_H /** @cond DONT_DOCUMENT_STRIPPED_DOWN_AIDA_INTERFACES */ namespace AIDA { class IAnnotation; class IDataPoint; /** * Basic user-level interface class for holding and managing * a single set of "data points". * * @author The AIDA team (http://aida.freehep.org/) * */ class IDataPointSet { public: virtual ~IDataPointSet() { /* nop */; } virtual IAnnotation & annotation() = 0; virtual const IAnnotation & annotation() const = 0; virtual std::string title() const = 0; virtual bool setTitle(const std::string & title) = 0; virtual int dimension() const = 0; virtual void clear() = 0; virtual int size() const = 0; virtual IDataPoint * point(int index) = 0; virtual bool setCoordinate(int coord, const std::vector & val, const std::vector & err) = 0; virtual bool setCoordinate(int coord, const std::vector & val, const std::vector & errp, const std::vector & errm) = 0; virtual const IDataPoint * point(int index) const = 0; virtual IDataPoint * addPoint() = 0; virtual bool addPoint(const IDataPoint & point) = 0; virtual bool removePoint(int index) = 0; virtual double lowerExtent(int coord) const = 0; virtual double upperExtent(int coord) const = 0; virtual bool scale(double scaleFactor) = 0; virtual bool scaleValues(double scaleFactor) = 0; virtual bool scaleErrors(double scaleFactor) = 0; virtual void * cast(const std::string & className) const = 0; }; } /** @endcond */ #endif /* LWH_AIDataPointSet_H */ diff --git a/Analysis/LWH/AIDataPointSetFactory.h b/Analysis/LWH/AIDataPointSetFactory.h --- a/Analysis/LWH/AIDataPointSetFactory.h +++ b/Analysis/LWH/AIDataPointSetFactory.h @@ -1,111 +1,111 @@ // -*- C++ -*- // // AIDataPointSetFactory.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef LWH_AIDataPointSetFactory_H #define LWH_AIDataPointSetFactory_H /** @cond DONT_DOCUMENT_STRIPPED_DOWN_AIDA_INTERFACES */ namespace AIDA { class IDataPointSet; class IHistogram1D; class IDataPointSetFactory { public: virtual ~IDataPointSetFactory() { /* nop */; } virtual IDataPointSet * create(const std::string &, const std::string &, int ) = 0; virtual IDataPointSet * create(const std::string &, int) = 0; virtual IDataPointSet * createY(const std::string &, const std::string &, const std::vector &, const std::vector &) = 0; virtual IDataPointSet * createY(const std::string &, const std::string &, const std::vector &, const std::vector &, const std::vector &) = 0; virtual IDataPointSet * createY(const std::string &, const std::vector &, const std::vector &) = 0; virtual IDataPointSet * createY(const std::string &, const std::vector &, const std::vector &, const std::vector &) = 0; virtual IDataPointSet * createX(const std::string &, const std::string &, const std::vector &, const std::vector &) = 0; virtual IDataPointSet * createX(const std::string &, const std::string &, const std::vector &, const std::vector &, const std::vector &) = 0; virtual IDataPointSet * createX(const std::string &, const std::vector &, const std::vector &) = 0; virtual IDataPointSet * createX(const std::string &, const std::vector &, const std::vector &, const std::vector &) = 0; virtual IDataPointSet * createXY(const std::string &, const std::string &, const std::vector &, const std::vector &, const std::vector &, const std::vector &, const std::vector &, const std::vector &) = 0; virtual IDataPointSet * createXY(const std::string &, const std::string &, const std::vector &, const std::vector &, const std::vector &, const std::vector &) = 0; virtual IDataPointSet * createXY(const std::string &, const std::vector &, const std::vector &, const std::vector &, const std::vector &, const std::vector &, const std::vector &) = 0; virtual IDataPointSet * createXY(const std::string &, const std::vector &, const std::vector &, const std::vector &, const std::vector &) = 0; virtual IDataPointSet * createXYZ(const std::string &, const std::string &, const std::vector &, const std::vector &, const std::vector &, const std::vector &, const std::vector &, const std::vector &, const std::vector &, const std::vector &, const std::vector &) = 0; virtual IDataPointSet * createXYZ(const std::string &, const std::string &, const std::vector &, const std::vector &, const std::vector &, const std::vector &, const std::vector &, const std::vector &) = 0; virtual IDataPointSet * createXYZ(const std::string &, const std::vector &, const std::vector &, const std::vector &, const std::vector &, const std::vector &, const std::vector &, const std::vector &, const std::vector &, const std::vector &) = 0; virtual IDataPointSet * createXYZ(const std::string &, const std::vector &, const std::vector &, const std::vector &, const std::vector &, const std::vector &, const std::vector &) = 0; virtual IDataPointSet * createCopy(const std::string &, const IDataPointSet &) = 0; virtual bool destroy(IDataPointSet *) = 0; virtual IDataPointSet * create(const std::string &, const IHistogram1D &, const std::string & = "") = 0; }; } /** @endcond */ #endif /* LWH_AIDataPointSetFactory_H */ diff --git a/Analysis/LWH/AIHistogram1D.h b/Analysis/LWH/AIHistogram1D.h --- a/Analysis/LWH/AIHistogram1D.h +++ b/Analysis/LWH/AIHistogram1D.h @@ -1,81 +1,81 @@ // -*- C++ -*- // // AIHistogram1D.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef LWH_AIHistorgram1D_H #define LWH_AIHistorgram1D_H /** @cond DONT_DOCUMENT_STRIPPED_DOWN_AIDA_INTERFACES */ namespace AIDA { class IAnnotation; class IBaseHistogram { public: virtual ~IBaseHistogram() {} virtual std::string title() const = 0; virtual bool setTitle(const std::string & title) = 0; virtual int dimension() const = 0; virtual bool reset() = 0; virtual int entries() const = 0; }; class IHistogram : virtual public IBaseHistogram { public: virtual ~IHistogram() {} virtual int allEntries() const = 0; virtual int extraEntries() const = 0; virtual double equivalentBinEntries() const = 0; virtual double sumBinHeights() const = 0; virtual double sumAllBinHeights() const = 0; virtual double sumExtraBinHeights() const = 0; virtual double minBinHeight() const = 0; virtual double maxBinHeight() const = 0; }; class IAxis; class IHistogram1D: virtual public IHistogram { public: virtual ~IHistogram1D() {} virtual bool fill(double x, double weight = 1.) = 0; virtual double binMean(int index) const = 0; virtual int binEntries(int index) const = 0; virtual double binHeight(int index) const = 0; virtual double binError(int index) const = 0; virtual double mean() const = 0; virtual double rms() const = 0; virtual const IAxis & axis() const = 0; virtual int coordToIndex(double coord) const = 0; virtual bool add(const IHistogram1D & hist) = 0; virtual bool scale(double scaleFactor) = 0; }; } /** @endcond */ #endif /* LWH_AIHistorgram1D_H */ diff --git a/Analysis/LWH/AIHistogram2D.h b/Analysis/LWH/AIHistogram2D.h --- a/Analysis/LWH/AIHistogram2D.h +++ b/Analysis/LWH/AIHistogram2D.h @@ -1,202 +1,202 @@ // -*- C++ -*- // // AIHistogram2D.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef LWH_AIHistogram2D_H #define LWH_AIHistogram2D_H /** @cond DONT_DOCUMENT_STRIPPED_DOWN_AIDA_INTERFACES */ #include "AIHistogram1D.h" namespace AIDA { class IAxis; class IHistogram2D : virtual public IHistogram { public: virtual ~IHistogram2D() { /* nop */; } /** * Fill the IHistogram2D with a couple of values and the * corresponding weight. * @param x The x value to be filled in. * @param y The y value to be filled in. * @param weight The corresponding weight (by default 1). * @return false If the weight is <0 or >1 (?). * */ virtual bool fill(double x, double y, double weight = 1.) = 0; /** * The weighted mean along the x axis of a given bin. * @param indexX The x bin number (0...N-1) or OVERFLOW or UNDERFLOW. * @param indexY The y bin number (0...N-1) or OVERFLOW or UNDERFLOW. * @return The mean of the corresponding bin along the x axis. * */ virtual double binMeanX(int indexX, int indexY) const = 0; /** * The weighted mean along the y axis of a given bin. * @param indexX The x bin number (0...N-1) or OVERFLOW or UNDERFLOW. * @param indexY The y bin number (0...N-1) or OVERFLOW or UNDERFLOW. * @return The mean of the corresponding bin along the y axis. * */ virtual double binMeanY(int indexX, int indexY) const = 0; /** * Number of entries in the corresponding bin (ie the number of times fill was called for this bin). * @param indexX The x bin number (0...N-1) or OVERFLOW or UNDERFLOW. * @param indexY The y bin number (0...N-1) or OVERFLOW or UNDERFLOW. * @return The number of entries in the corresponding bin. * */ virtual int binEntries(int indexX, int indexY) const = 0; /** * Sum of all the entries of the bins along a given x bin. * This is equivalent to projectionX().binEntries(index). * @param index The x bin number (0...N-1) or OVERFLOW or UNDERFLOW. * @return The number of entries in the corresponding set of bins. * */ virtual int binEntriesX(int index) const = 0; /** * Sum of all the entries of the bins along a given y bin. * This is equivalent to projectionY().binEntries(index). * @param index The y bin number (0...N-1) or OVERFLOW or UNDERFLOW. * @return The number of entries in the corresponding set of bins. * */ virtual int binEntriesY(int index) const = 0; /** * Total height of a give bin (ie the sum of the weights in this bin). * @param indexX The x bin number (0...N-1) or OVERFLOW or UNDERFLOW. * @param indexY The y bin number (0...N-1) or OVERFLOW or UNDERFLOW. * @return The height of the corresponding bin. * */ virtual double binHeight(int indexX, int indexY) const = 0; /** * Sum of all the heights of the bins along a given x bin. * This is equivalent to projectionX().binHeight(index). * @param index The x bin number (0...N-1) or OVERFLOW or UNDERFLOW. * @return The sum of the heights in the corresponding set of bins. * */ virtual double binHeightX(int index) const = 0; /** * Sum of all the heights of the bins along a given y bin. * This is equivalent to projectionY().binHeight(index). * @param index The y bin number (0...N-1) or OVERFLOW or UNDERFLOW. * @return The sum of the heights in the corresponding set of bins. * */ virtual double binHeightY(int index) const = 0; /** * The error of a given bin. * @param indexX The x bin number (0...N-1) or OVERFLOW or UNDERFLOW. * @param indexY The y bin number (0...N-1) or OVERFLOW or UNDERFLOW. * @return The error on the corresponding bin. * */ virtual double binError(int indexX, int indexY) const = 0; /** * The mean of the IHistogram2D along the x axis. * @return The mean of the IHistogram2D along the x axis. * */ virtual double meanX() const = 0; /** * The mean of the IHistogram2D along the y axis. * @return The mean of the IHistogram2D along the y axis. * */ virtual double meanY() const = 0; /** * The RMS of the IHistogram2D along the x axis. * @return The RMS if the IHistogram2D along the x axis. * */ virtual double rmsX() const = 0; /** * The RMS of the IHistogram2D along the y axis. * @return The RMS if the IHistogram2D along the y axis. * */ virtual double rmsY() const = 0; /** * Get the x axis of the IHistogram2D. * @return The x coordinate IAxis. * */ virtual const IAxis & xAxis() const = 0; /** * Get the y axis of the IHistogram2D. * @return The y coordinate IAxis. * */ virtual const IAxis & yAxis() const = 0; /** * Get the bin number corresponding to a given coordinate along the x axis. * This is a convenience method, equivalent to xAxis().coordToIndex(coord). * @see IAxis#coordToIndex(double) * @param coord The coordinalte along the x axis. * @return The corresponding bin number. * */ virtual int coordToIndexX(double coord) const = 0; /** * Get the bin number corresponding to a given coordinate along the y axis. * This is a convenience method, equivalent to yAxis().coordToIndex(coord). * @see IAxis#coordToIndex(double) * @param coord The coordinalte along the y axis. * @return The corresponding bin number. * */ virtual int coordToIndexY(double coord) const = 0; /** * Add to this IHistogram2D the contents of another IHistogram2D. * @param hist The IHistogram2D to be added to this IHistogram2D. * @return false If the IHistogram2Ds binnings are incompatible. * */ virtual bool add(const IHistogram2D & hist) = 0; virtual bool scale(double scaleFactor) = 0; }; // class } // namespace AIDA /** @endcond */ #endif /* LWH_AIHistogram2D_H */ diff --git a/Analysis/LWH/AIHistogramFactory.h b/Analysis/LWH/AIHistogramFactory.h --- a/Analysis/LWH/AIHistogramFactory.h +++ b/Analysis/LWH/AIHistogramFactory.h @@ -1,112 +1,112 @@ // -*- C++ -*- // // AIHistogramFactory.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef LWH_AIHistogramFactory_H #define LWH_AIHistogramFactory_H /** @cond DONT_DOCUMENT_STRIPPED_DOWN_AIDA_INTERFACES */ namespace AIDA { class ICloud1D; class ICloud2D; class ICloud3D; class IBaseHistogram; class IHistogram1D; class IHistogram2D; class IHistogram3D; class IProfile1D; class IProfile2D; class IHistogramFactory { public: virtual ~IHistogramFactory() {} virtual bool destroy(IBaseHistogram * hist) = 0; virtual IHistogram1D * createHistogram1D(const std::string &, const std::string &, int, double, double, const std::string & = "") = 0; virtual IHistogram1D * createHistogram1D(const std::string &, int, double, double) = 0; virtual IHistogram1D * createHistogram1D(const std::string &, const std::string & , const std::vector &, const std::string & = "") = 0; virtual IHistogram1D * createCopy(const std::string &, const IHistogram1D &) = 0; virtual IHistogram1D * add(const std::string &, const IHistogram1D &, const IHistogram1D &) = 0; virtual IHistogram1D * subtract(const std::string &, const IHistogram1D &, const IHistogram1D &) = 0; virtual IHistogram1D * multiply(const std::string &, const IHistogram1D &, const IHistogram1D &) = 0; virtual IHistogram1D * divide(const std::string &, const IHistogram1D &, const IHistogram1D &) = 0; virtual IHistogram2D * createHistogram2D(const std::string & path, const std::string & title, int nx, double xlo, double xup, int ny, double ylo, double yup, const std::string & = "") = 0; virtual IHistogram2D * createHistogram2D(const std::string & pathAndTitle, int nx, double xlo, double xup, int ny, double ylo, double yup) = 0; virtual IHistogram2D * createHistogram2D(const std::string & path, const std::string & title, const std::vector & xedges, const std::vector & yedges, const std::string & = "") = 0; virtual IHistogram2D * createCopy(const std::string & path, const IHistogram2D & hist) = 0; virtual IHistogram2D * add(const std::string &, const IHistogram2D &, const IHistogram2D &) = 0; virtual IHistogram2D * subtract(const std::string &, const IHistogram2D &, const IHistogram2D &) = 0; virtual IHistogram2D * multiply(const std::string &, const IHistogram2D &, const IHistogram2D &) = 0; virtual IHistogram2D * divide(const std::string &, const IHistogram2D &, const IHistogram2D &) = 0; virtual IHistogram1D * projectionX(const std::string &, const IHistogram2D &) = 0; virtual IHistogram1D * projectionY(const std::string &, const IHistogram2D &) = 0; virtual IHistogram1D * sliceX(const std::string &, const IHistogram2D &, int) = 0; virtual IHistogram1D * sliceY(const std::string &, const IHistogram2D &, int) = 0; virtual IHistogram1D * sliceX(const std::string &, const IHistogram2D &, int, int) = 0; virtual IHistogram1D * sliceY(const std::string &, const IHistogram2D &, int, int) = 0; }; } /** @endcond */ #endif /* LWH_AIHistogramFactory_H */ diff --git a/Analysis/LWH/AIManagedObject.h b/Analysis/LWH/AIManagedObject.h --- a/Analysis/LWH/AIManagedObject.h +++ b/Analysis/LWH/AIManagedObject.h @@ -1,41 +1,41 @@ // -*- C++ -*- // // AIManagedObject.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef LWH_AIManagedObject_H #define LWH_AIManagedObject_H #include /** @cond DONT_DOCUMENT_STRIPPED_DOWN_AIDA_INTERFACES */ namespace AIDA { class ITree; class IManagedObject { public: virtual ~IManagedObject() {} virtual std::string name() const = 0; virtual void * cast(const std::string & className) const = 0; }; } /** @endcond */ #endif /* LWH_AIManagedObject_H */ diff --git a/Analysis/LWH/AIMeasurement.h b/Analysis/LWH/AIMeasurement.h --- a/Analysis/LWH/AIMeasurement.h +++ b/Analysis/LWH/AIMeasurement.h @@ -1,38 +1,38 @@ // -*- C++ -*- // // AIMeasurement.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef LWH_AIMeasurement_H #define LWH_AIMeasurement_H /** @cond DONT_DOCUMENT_STRIPPED_DOWN_AIDA_INTERFACES */ namespace AIDA { class IMeasurement { public: virtual ~IMeasurement() {} virtual double value() const = 0; virtual double errorPlus() const = 0; virtual double errorMinus() const = 0; virtual bool setValue(double value) = 0; virtual bool setErrorPlus(double errorPlus) = 0; virtual bool setErrorMinus(double errorMinus) = 0; }; } /** @endcond */ #endif /* LWH_AIMeasurement_H */ diff --git a/Analysis/LWH/AITree.h b/Analysis/LWH/AITree.h --- a/Analysis/LWH/AITree.h +++ b/Analysis/LWH/AITree.h @@ -1,51 +1,51 @@ // -*- C++ -*- // // AITree.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef LWH_AITree_H #define LWH_AITree_H /** @cond DONT_DOCUMENT_STRIPPED_DOWN_AIDA_INTERFACES */ namespace AIDA { class IManagedObject; class ITree { public: virtual ~ITree() {} virtual std::string storeName() const = 0; virtual IManagedObject * find(const std::string & name) = 0; virtual std::string pwd() const = 0; virtual bool commit() = 0; virtual bool close() = 0; virtual bool mkdir(const std::string &) = 0; virtual bool mkdirs(const std::string &) = 0; virtual bool cd(const std::string &) = 0; virtual bool rmdir(const std::string & str) = 0; virtual bool rm(const std::string & str) = 0; virtual std::string findPath(const IManagedObject & o) const = 0; virtual bool mv(const std::string & oldo, const std::string & newo) = 0; virtual void setOverwrite(bool o = true) = 0; virtual bool cp(const std::string &, const std::string &, bool = false) = 0; }; } /** @endcond */ #endif /* LWH_AITree_H */ diff --git a/Analysis/LWH/AITreeFactory.h b/Analysis/LWH/AITreeFactory.h --- a/Analysis/LWH/AITreeFactory.h +++ b/Analysis/LWH/AITreeFactory.h @@ -1,42 +1,42 @@ // -*- C++ -*- // // AITreeFactory.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef LWH_AITreeFactory_H #define LWH_AITreeFactory_H #include /** @cond DONT_DOCUMENT_STRIPPED_DOWN_AIDA_INTERFACES */ namespace AIDA { class ITree; class ITreeFactory { public: virtual ~ITreeFactory() {} virtual ITree * create(const std::string &, const std::string & = "", bool = false, bool = false, const std::string & = "") = 0; }; } /** @endcond */ #endif /* LWH_AITreeFactory_H */ diff --git a/Analysis/LWH/AnalysisFactory.h b/Analysis/LWH/AnalysisFactory.h --- a/Analysis/LWH/AnalysisFactory.h +++ b/Analysis/LWH/AnalysisFactory.h @@ -1,147 +1,147 @@ // -*- C++ -*- // // AnalysisFactory.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef LWH_AnalysisFactory_H #define LWH_AnalysisFactory_H // // This is the declaration of the AnalysisFactory class. // #include "AIAnalysisFactory.h" #include "TreeFactory.h" #include "HistogramFactory.h" #include "DataPointSetFactory.h" #include /** * The LWH namespace contains a Light-Weight Histogram package which * implements the most rudimentary histogramming facilities according * to the AIDA interface * specifications. Currently the only thing that is supported is * simple, equally binned, one dimensional histograms and data * points. It is mainly intended to be used in applications where one * needs to fill simple histograms and output them. With LWH it is * then possible to do this without the overhead of a full AIDA * implementation, but still having the option to use a full * implementation later on with minimal changes. Note also that since * LWH consists only of header files, the installation is trivial - * just put the header files where they can be found by your compiler. */ namespace LWH { using namespace AIDA; /** * The "master" factory from which other factories are obtained. * Typically accessed by: *
IAnalysisFactory* af = AIDA_createAnalysisFactory();
*/ class AnalysisFactory: public IAnalysisFactory { public: /// Destructor. virtual ~AnalysisFactory() { clear(); } /** * Create an ITreeFactory. * @return The ITreeFactory. */ ITreeFactory * createTreeFactory() { return new TreeFactory; } /** * Create an HistogramFactory. * @param tree The ITree which created histograms will be associated to. * @return The IHistogramFactory. * */ IHistogramFactory * createHistogramFactory(ITree & tree) { Tree & tr = dynamic_cast(tree); HistogramFactory * hf = new HistogramFactory(tr); histfacs.insert(hf); return hf; } /** * Not implemented in LWH. * @return null pointer always. * */ IDataPointSetFactory * createDataPointSetFactory(ITree & tree) { Tree & tr = dynamic_cast(tree); DataPointSetFactory * df = new DataPointSetFactory(tr); datafacs.insert(df); return df; } /** * Not implemented in LWH. * @return null pointer always. */ ITupleFactory * createTupleFactory(ITree &) { return 0; } /** * Not implemented in LWH. * @return null pointer always. */ IFunctionFactory * createFunctionFactory(ITree &) { return 0; } /** * Not implemented in LWH. * @return null pointer always. */ IPlotterFactory * createPlotterFactory(int = 0, char * * = 0, const std::string & = "", const std::string & = "") { return 0; } /** * Not implemented in LWH. * @return null pointer always. */ IFitFactory * createFitFactory() { return 0; } private: /** Delete all produced factories. */ void clear() { for ( std::set::iterator it = histfacs.begin(); it != histfacs.end(); ++it ) delete *it; for ( std::set::iterator it = datafacs.begin(); it != datafacs.end(); ++it ) delete *it; for ( std::set::iterator it = treefacs.begin(); it != treefacs.end(); ++it ) delete *it; histfacs.clear(); datafacs.clear(); treefacs.clear(); } /** The histogram factories. */ std::set histfacs; /** The dataset factories. */ std::set datafacs; /** The tree factories. */ std::set treefacs; }; } #endif /* LWH_AnalysisFactory_H */ diff --git a/Analysis/LWH/Axis.h b/Analysis/LWH/Axis.h --- a/Analysis/LWH/Axis.h +++ b/Analysis/LWH/Axis.h @@ -1,153 +1,153 @@ // -*- C++ -*- // // Axis.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef LWH_Axis_H #define LWH_Axis_H // // This is the declaration of the Axis class representing // #include #include #include #include "AIAxis.h" namespace LWH { using namespace AIDA; /** * An Axis represents a binned histogram axis. A 1D Histogram would have * one Axis representing the X axis, while a 2D Histogram would have two * axes representing the X and Y Axis. */ class Axis: public IAxis { public: /** * Standard constructor. */ Axis(int n, double lo, double up) : lower(lo), upper(up), nbins(n) {} /** * Copy constructor. */ Axis(const Axis & a) : IAxis(a), lower(a.lower), upper(a.upper), nbins(a.nbins) {} /// Destructor. virtual ~Axis() { } /** * Check if the IAxis has fixed binning, i.e. if all the bins have * the same width. @return true if the binning is * fixed, false otherwise. * */ bool isFixedBinning() const {return true; } /** * Get the lower edge of the IAxis. * @return The IAxis's lower edge. * */ double lowerEdge() const { return lower; } /** * Get the upper edge of the IAxis. * @return The IAxis's upper edge. * */ double upperEdge() const { return upper; } /** * The number of bins (excluding underflow and overflow) on the IAxis. * @return The IAxis's number of bins. * */ int bins() const { return nbins; } /** * Get the lower edge of the specified bin. * @param index The bin number: 0 to bins()-1 for the in-range bins * or OVERFLOW or UNDERFLOW. * @return The lower edge of the corresponding bin; for the * underflow bin this is Double.NEGATIVE_INFINITY. * */ double binLowerEdge(int index) const { return index < 0? -std::numeric_limits::max(): lower + double(std::min(index, nbins))*binWidth(0); } /** * Get the upper edge of the specified bin. * @param index The bin number: 0 to bins()-1 for the in-range bins * or OVERFLOW or UNDERFLOW. * @return The upper edge of the corresponding bin; for the overflow * bin this is Double.POSITIVE_INFINITY. * */ double binUpperEdge(int index) const { return index >= nbins? std::numeric_limits::max(): lower + double(std::max(index, -1) + 1)*binWidth(0); } /** * Get the width of the specified bin. * The argument gives the bin number: 0 to bins()-1) for the in-range bins * or OVERFLOW or UNDERFLOW. * @return The width of the corresponding bin. * */ double binWidth(int) const { return (upper - lower)/double(nbins); } /** * Convert a coordinate on the axis to a bin number. If the * coordinate is less than the lowerEdge UNDERFLOW is returned; if * the coordinate is greater or equal to the upperEdge OVERFLOW is * returned. * @param coord The coordinate to be converted. * @return The corresponding bin number. * */ int coordToIndex(double coord) const { if ( coord >= upper ) return OVERFLOW_BIN; else if ( coord < lower ) return UNDERFLOW_BIN; else return int((coord - lower)/binWidth(0)); } /** * Return the midpoint of the specified bin. No checking is * performed to ensure the argument is a valid bin. */ double binMidPoint(int index) const { return lower + (double(index) + 0.5)*binWidth(0); } private: /** The lower edge. */ double lower; /** The upper edge. */ double upper; /** The number of bins. */ int nbins; }; } #endif /* LWH_Axis_H */ diff --git a/Analysis/LWH/DataPoint.h b/Analysis/LWH/DataPoint.h --- a/Analysis/LWH/DataPoint.h +++ b/Analysis/LWH/DataPoint.h @@ -1,106 +1,106 @@ // -*- C++ -*- // // DataPoint.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef LWH_DataPoint_H #define LWH_DataPoint_H // // This is the declaration of the DataPoint class representing // #include #include #include #include "AIDataPoint.h" #include "Measurement.h" namespace LWH { using namespace AIDA; /** * An DataPoint represents a binned histogram axis. A 1D Histogram would have * one DataPoint representing the X axis, while a 2D Histogram would have two * axes representing the X and Y DataPoint. */ class DataPoint: public IDataPoint { public: /** * Construct a data point with a given number of dimensions. */ DataPoint(int dim = 2) : m(dim) {} /** * Copy constructor. */ DataPoint(const DataPoint & d) : IDataPoint(d), m(d.m) {} /** * Copy from any IDataPoint. */ DataPoint(const IDataPoint & id) : m(id.dimension()) { for ( int i = 0, N = m.size(); i < N; ++i ) m[i] = Measurement(id.coordinate(i)->value(), id.coordinate(i)->errorPlus(), id.coordinate(i)->errorMinus()); } /** * Default assignment operator (to avoid compiler warnings). */ DataPoint & operator=(const DataPoint &) = default; /** * Destructor. */ virtual ~DataPoint() {} /** * Get the dimension of the IDataPoint, i.e. the number * of coordinates the point has. * @return The dimension. */ int dimension() const { return m.size(); } /** * Get the IMeasurement for a given coordinate. * @param coord The coordinate. * @return The corresponding IMeasurement. */ IMeasurement * coordinate(int coord) { return &(m[coord]); } /** * Get the IMeasurement for a given coordinate. * @param coord The coordinate. * @return The corresponding IMeasurement. */ const IMeasurement * coordinate(int coord) const { return &(m[coord]); } private: /** * The included measurements. */ std::vector m; }; } #endif /* LWH_DataPoint_H */ diff --git a/Analysis/LWH/DataPointSet.h b/Analysis/LWH/DataPointSet.h --- a/Analysis/LWH/DataPointSet.h +++ b/Analysis/LWH/DataPointSet.h @@ -1,370 +1,370 @@ // -*- C++ -*- // // DataPointSet.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef LWH_DataPointSet_H #define LWH_DataPointSet_H // // This is the declaration of the DataPointSet class representing // #include #include #include #include #include "AIDataPointSet.h" #include "ManagedObject.h" #include "DataPoint.h" namespace LWH { using namespace AIDA; /** * An DataPointSet represents a binned histogram axis. A 1D Histogram would have * one DataPointSet representing the X axis, while a 2D Histogram would have two * axes representing the X and Y DataPointSet. */ class DataPointSet: public IDataPointSet, public ManagedObject { public: /** * Standard constructor takes the dimension, \a D, of the data * points as argument. */ DataPointSet(int D): dim(D) {} /** * Destructor. */ virtual ~DataPointSet() {} /** * Not implemented in LWH. will throw an exception. */ IAnnotation & annotation() { throw std::runtime_error("LWH cannot handle annotations"); } /** * Not implemented in LWH. will throw an exception. */ const IAnnotation & annotation() const { throw std::runtime_error("LWH cannot handle annotations"); } /** * Get the data set's title. * @return The data set's title. */ std::string title() const { return theTitle; } /** * Get the data set's title. * @return The data set's title. */ std::string name() const { return theTitle; } /** * Set the data set's title. * @param title The title. * @return false If title cannot be changed. */ bool setTitle(const std::string & title) { theTitle = title; return true; } /** * Get the dimension of the IDataPoints that can be stored in the set. * @return The dimension of the IDataPoints storable in the set. * */ int dimension() const { return dim; } /** * Remove all the IDataPoints in the set. * After this the IDataPointSet is as just created. */ void clear() { dset.clear(); } /** * Get the current size of the IDataPointSet, i.e. the number * of IDataPoints contained in the set. * @return The size of the IDataPointSet. */ int size() const { return dset.size(); } /** * Get the IDataPoint at a give index in the set. * @param index The IDataPoint index. * @return The corresponding IDataPoint. */ IDataPoint * point(int index) { return &(dset[index]); } /** * Set the values and errors of a given coordinate all at once. If * this method is called on an empty IDataPointSet, a number of * points equal to the size of the arrays provided is created; if * the IDataPointSet is not empty the dimension of the array must * match with the size of the IDataPointSet. * @param coord The coordinate's index * @param val The array of the values for the given coordinate * @param err The array with the symmetric errors. * @return false if an illegal coordinate is provided or if there is * a mismatch between the size of the array and the size of the * IDataPointSet. */ bool setCoordinate(int coord, const std::vector & val, const std::vector & err) { return setCoordinate(coord, val, err, err); } /** * Set the values and errors of a given coordinate all at once. If * this method is called on an empty IDataPointSet, a number of * points equal to the size of the arrays provided is created; if * the IDataPointSet is not empty the dimension of the array must * match with the size of the IDataPointSet. * @param coord The coordinate's index * @param val The array of the values for the given coordinate * @param errp The array with the plus errors. * @param errm The array with the minus errors. * @return false if an illegal coordinate is provided or if there is * a mismatch between the size of the array and the size of the * IDataPointSet. * */ bool setCoordinate(int coord, const std::vector & val, const std::vector & errp, const std::vector & errm) { if ( coord < 0 || coord >= dimension() ) return false; if ( val.size() != dset.size() || errp.size() != dset.size() || errm.size() != dset.size() ) return false; for ( int i = 0, N = val.size(); i < N; ++i ) { dset[i].coordinate(coord)->setValue(val[i]); dset[i].coordinate(coord)->setErrorPlus(errp[i]); dset[i].coordinate(coord)->setErrorMinus(errm[i]); } return true; } /** * Return the data point at the given index. * @return 0 if index is out of range. */ const IDataPoint * point(int index) const { if ( index < 0 || unsigned(index) >= dset.size() ) return 0; return &(dset[index]); } /** * Add a new empty IDataPoint at the end of the set. * @return The newly added point. */ IDataPoint * addPoint() { dset.push_back(DataPoint(dimension())); return &(dset.back()); } /** * Add a copy of an IDataPoint at the end of the set. * @param point The IDataPoint to be added. * @return false If the point has the wrong dimension or * if the point cannot be added. */ bool addPoint(const IDataPoint & point) { if ( dimension() && dimension() != point.dimension() ) return false; dset.push_back(DataPoint(point)); return true; } /** * Remove the IDataPoint at a given index. * @param index The index of the IDataPoint to be removed. * @return false If the index is < 0 or >= size(). */ bool removePoint(int index) { if ( index < 0 || unsigned(index) >= dset.size() ) return false; dset.erase(dset.begin() + index); return true; } /** * Get the lower value for a give axis. * @param coord The coordinate of the axis. * @return The lower edge of the corresponding axis. * If coord < 0 or coord >= dimension(), or if the * set is empty NaN is returned. */ double lowerExtent(int coord) const { if ( dset.empty() ) return std::numeric_limits::quiet_NaN(); if ( coord < 0 || coord >= dimension() ) return std::numeric_limits::quiet_NaN(); double low = dset[0].coordinate(coord)->value(); for ( int i = 1, N = dset.size(); i < N; ++i ) low = std::min(low, dset[i].coordinate(coord)->value()); return low; } /** * Get the upper value for a give axis. * @param coord The coordinate of the axis. * @return The upper edge of the corresponding axis. * If coord < 0 or coord >= dimension(), or if the set * is empty NaN is returned. */ double upperExtent(int coord) const { if ( dset.empty() ) return std::numeric_limits::quiet_NaN(); if ( coord < 0 || coord >= dimension() ) return std::numeric_limits::quiet_NaN(); double upp = dset[0].coordinate(coord)->value(); for ( int i = 1, N = dset.size(); i < N; ++i ) upp = std::max(upp, dset[i].coordinate(coord)->value()); return upp; } /** * Scales the values and the errors of all the measurements * of each point by a given factor. * @param scale The scale factor. * @return false If an illegal scaleFactor is provided. */ bool scale(double scale) { for ( int i = 0, N = dset.size(); i < N; ++i ) for ( int j = 0, M = dset[i].dimension(); j < M; ++j ) { IMeasurement * m = dset[i].coordinate(j); m->setValue(m->value()*scale); m->setErrorPlus(m->errorPlus()*scale); m->setErrorMinus(m->errorPlus()*scale); } return true; } /** * Scales the values of all the measurements * of each point by a given factor. * @param scale The scale factor. * @return false If an illegal scaleFactor is provided. */ bool scaleValues(double scale) { for ( int i = 0, N = dset.size(); i < N; ++i ) for ( int j = 0, M = dset[i].dimension(); j < M; ++j ) { IMeasurement * m = dset[i].coordinate(j); m->setValue(m->value()*scale); } return true; } /** * Scales the errors of all the measurements * of each point by a given factor. * @param scale The scale factor. * @return false If an illegal scaleFactor is provided. */ bool scaleErrors(double scale) { for ( int i = 0, N = dset.size(); i < N; ++i ) for ( int j = 0, M = dset[i].dimension(); j < M; ++j ) { IMeasurement * m = dset[i].coordinate(j); m->setErrorPlus(m->errorPlus()*scale); m->setErrorMinus(m->errorPlus()*scale); } return true; } /** * Not implemented in LWH. * @return null pointer always. */ void * cast(const std::string &) const { return 0; } /** * Write out the data set in the AIDA xml format. */ bool writeXML(std::ostream & os, std::string path, std::string name) { os << " \n"; for ( int d = 0; d < dimension(); ++d ) os << " \n"; for ( int i = 0, N = size(); i < N; ++i ) { os << " \n"; for ( int j = 0, M = dimension(); j < M; ++j ) os << " coordinate(j)->value() << "\" errorPlus=\"" << point(i)->coordinate(j)->errorPlus() << "\" errorMinus=\"" << point(i)->coordinate(j)->errorMinus() << "\"/>\n"; os << " \n"; } os << " " << std::endl; return true; } /** * Write out the data set in a flat text file suitable for * eg. gnuplot to read. The coloums are layed out as 'x1 x2 ... xn * dx1+ dx2+ ... dxn+ dx1- dx2- ... dxn-'. */ bool writeFLAT(std::ostream & os, std::string path, std::string name) { os << "# " << path << "/" << name << " " << size() << " \"" << title() << " \" dimension " << dimension() << std::endl; for ( int i = 0, N = size(); i < N; ++i ) { for ( int j = 0, M = dimension(); j < M; ++j ) os << point(i)->coordinate(j)->value() << " "; for ( int j = 0, M = dimension(); j < M; ++j ) os << point(i)->coordinate(j)->errorPlus() << " "; for ( int j = 0, M = dimension(); j < M; ++j ) os << point(i)->coordinate(j)->errorMinus() << " "; os << std::endl; } os << std::endl; return true; } private: /** The title */ std::string theTitle; /** * The included data points. */ std::vector dset; /** * The dimension of the points in this set. */ unsigned int dim; }; } #endif /* LWH_DataPointSet_H */ diff --git a/Analysis/LWH/DataPointSetFactory.h b/Analysis/LWH/DataPointSetFactory.h --- a/Analysis/LWH/DataPointSetFactory.h +++ b/Analysis/LWH/DataPointSetFactory.h @@ -1,707 +1,707 @@ // -*- C++ -*- // // DataPointSetFactory.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef LWH_DataPointSetFactory_H #define LWH_DataPointSetFactory_H // // This is the declaration of the DataPointSetFactory class. // #include "AIDataPointSetFactory.h" #include "DataPointSet.h" #include "Histogram1D.h" #include "Tree.h" #include #include namespace LWH { using namespace AIDA; /** * Basic user-level interface for creating a factory * of IDataPointSet. The created objects are assumed to be * managed by the tree which is associated to the factory. */ class DataPointSetFactory: public IDataPointSetFactory { public: /** * Standard constructor. */ DataPointSetFactory(Tree & t) : tree(&t) {} /** * Destructor. */ virtual ~DataPointSetFactory() {} /** * Create an empty IDataPointSet. * @param path The path of the IDataPointSet. The path can either * be a relative or full path. * ("/folder1/folder2/dataName" and "../folder/dataName" * are valid paths). All the directories in the path * must exist. The characther `/` cannot be used in * names; it is only used to delimit directories within * paths. * @param title The title of the IDataPointSet. * @param dim The dimension of the IDataPoints that can be stored * in the set. * @return The newly created IDataPointSet. */ virtual IDataPointSet * create(const std::string & path, const std::string & title, int dim) { DataPointSet * dset = new DataPointSet(dim); dset->setTitle(title); if ( !tree->insert(path, dset) ) { delete dset; dset = 0; throw std::runtime_error("LWH could not create DataPointSet '" + title + "'." ); } return dset; } /** * Create an empty IDataPointSet. * @param pathAndTitle The path of the IDataPointSet. The path can either be * a relative or full path. The last part of the path is * used as the title. ("/folder1/folder2/dataTitle" and * "../folder/dataTitle" are valid paths). * All the directories in the path must exist. The * characther `/` cannot be used in names; it is only * used to delimit directories within paths. * @param dim The dimension of the IDataPoints that can be stored * in the set. * @return The newly created IDataPointSet. */ virtual IDataPointSet * create(const std::string & pathAndTitle, int dim) { std::string title = pathAndTitle.substr(pathAndTitle.rfind('/') + 1); return create(pathAndTitle, title, dim); } /** * Create a two dimensional IDataPointSet providing the data along y (the x * value is the index of the y value in the array). * @param path The path of the IDataPointSet. The path can either be a * relative or full path. ("/folder1/folder2/dataTitle" and * "../folder/dataTitle" are valid paths). All the directories * in the path must exist. The characther `/` cannot be used * in names; it is only used to delimit directories within paths. * @param title The title of the IDataPointSet. * @param y The array of the y values * @param ey The array with the symmetric errors on y * @return The created IDataPointSet. */ virtual IDataPointSet * createY(const std::string & path, const std::string & title, const std::vector & y, const std::vector & ey) { return createY(path, title, y, ey, ey); } /** * Create a two dimensional IDataPointSet providing the data along y (the x * value is the index of the y value in the array). * @param path The path of the IDataPointSet. The path can either be a * relative or full path. ("/folder1/folder2/dataTitle" and * "../folder/dataTitle" are valid paths). All the directories * in the path must exist. The characther `/` cannot be used * in names; it is only used to delimit directories within paths. * @param title The title of the IDataPointSet. * @param y The array of the y values * @param eyp The array with the plus errors on y * @param eym The array with the minus errors on y * @return The created IDataPointSet. */ virtual IDataPointSet * createY(const std::string & path, const std::string & title, const std::vector & y, const std::vector & eyp, const std::vector & eym) { IDataPointSet * dset = create(path, title, 2); std::vector x, ex; for ( int i = 0, N = y.size(); i < N; ++i ) { dset->addPoint(DataPoint(2)); x.push_back(i); ex.push_back(0); } if ( !dset->setCoordinate(0, x, ex, ex) || !dset->setCoordinate(1, y, eyp, eym) ) throw std::runtime_error("LWH could add points to DataPointSet '" + title + "'." ); return dset; } /** * Create a two dimensional IDataPointSet providing the data along y (the x value is the index of the y value in the array). * @param pathAndTitle The path of the IDataPointSet. The path can either be * a relative or full path. The last part of the path is * used as the title. ("/folder1/folder2/dataTitle" and * "../folder/dataTitle" are valid paths). All the * directories in the path must exist. The characther * `/` cannot be used in names; it is only used to * delimit directories within paths. * @param y The array of the y values * @param ey The array with the symmetric errors on y * @return The created IDataPointSet. * */ virtual IDataPointSet * createY(const std::string & pathAndTitle, const std::vector & y, const std::vector & ey) { std::string title = pathAndTitle.substr(pathAndTitle.rfind('/') + 1); return createY(pathAndTitle, title, y, ey); } /** * Create a two dimensional IDataPointSet providing the data along y (the x * value is the index of the y value in the array). * @param pathAndTitle The path of the IDataPointSet. The path can either be * a relative or full path. The last part of the path is * used as the title. ("/folder1/folder2/dataTitle" and * "../folder/dataTitle" are valid paths). All the * directories in the path must exist. The characther * `/` cannot be used in names; it is only used to * delimit directories within paths. * @param y The array of the y values * @param eyp The array with the plus errors on y * @param eym The array with the minus errors on y * @return The created IDataPointSet. */ virtual IDataPointSet * createY(const std::string & pathAndTitle, const std::vector & y, const std::vector & eyp, const std::vector & eym) { std::string title = pathAndTitle.substr(pathAndTitle.rfind('/') + 1); return createY(pathAndTitle, title, y, eyp, eym); } /** * Create a two dimensional IDataPointSet providing the data along x (the y * value is the index of the x value in the array). * @param path The path of the IDataPointSet. The path can either be a * relative or full path. ("/folder1/folder2/dataTitle" and * "../folder/dataTitle" are valid paths). All the directories * in the path must exist. The characther `/` cannot be used * in names; it is only used to delimit directories within paths. * @param title The title of the IDataPointSet. * @param x The array of the x values * @param ex The array with the symmetric errors on x * @return The created IDataPointSet. */ virtual IDataPointSet * createX(const std::string & path, const std::string & title, const std::vector & x, const std::vector & ex) { return createX(path, title, x, ex, ex); } /** * Create a two dimensional IDataPointSet providing the data along x (the y * value is the index of the x value in the array). * @param path The path of the IDataPointSet. The path can either be a * relative or full path. ("/folder1/folder2/dataTitle" and * "../folder/dataTitle" are valid paths). All the directories * in the path must exist. The characther `/` cannot be used * in names; it is only used to delimit directories within paths. * @param title The title of the IDataPointSet. * @param x The array of the x values * @param exp The array with the plus errors on x * @param exm The array with the minus errors on x * @return The created IDataPointSet. */ virtual IDataPointSet * createX(const std::string & path, const std::string & title, const std::vector & x, const std::vector & exp, const std::vector & exm) { IDataPointSet * dset = create(path, title, 2); std::vector y, ey; for ( int i = 0, N = x.size(); i < N; ++i ) { dset->addPoint(DataPoint(2)); y.push_back(i); ey.push_back(0); } if ( !dset->setCoordinate(0, x, exp, exm) || !dset->setCoordinate(1, y, ey, ey) ) throw std::runtime_error("LWH could add points to DataPointSet '" + title + "'." ); return dset; } /** * Create a two dimensional IDataPointSet providing the data along x (the y * value is the index of the x value in the array). * @param pathAndTitle The path of the IDataPointSet. The path can either be * a relative or full path. The last part of the path is * used as the title. ("/folder1/folder2/dataTitle" and * "../folder/dataTitle" are valid paths). All the * directories in the path must exist. The characther * `/` cannot be used in names; it is only used to * delimit directories within paths. * @param x The array of the x values * @param ex The array with the symmetric errors on x * @return The created IDataPointSet. */ virtual IDataPointSet * createX(const std::string & pathAndTitle, const std::vector & x, const std::vector & ex) { std::string title = pathAndTitle.substr(pathAndTitle.rfind('/') + 1); return createX(pathAndTitle, title, x, ex, ex); } /** * Create a two dimensional IDataPointSet providing the data along x (the y * value is the index of the x value in the array). * @param pathAndTitle The path of the IDataPointSet. The path can either be * a relative or full path. The last part of the path is * used as the title. ("/folder1/folder2/dataTitle" and * "../folder/dataTitle" are valid paths). All the * directories in the path must exist. The characther * `/` cannot be used in names; it is only used to * delimit directories within paths. * @param x The array of the x values * @param exp The array with the plus errors on x * @param exm The array with the minus errors on x * @return The created IDataPointSet. */ virtual IDataPointSet * createX(const std::string & pathAndTitle, const std::vector & x, const std::vector & exp, const std::vector & exm) { std::string title = pathAndTitle.substr(pathAndTitle.rfind('/') + 1); return createX(pathAndTitle, title, x, exp, exm); } /** * Create a two dimensional IDataPointSet providing the data. * @param path The path of the IDataPointSet. The path can either be a * relative or full path. ("/folder1/folder2/dataTitle" and * "../folder/dataTitle" are valid paths). All the directories * in the path must exist. The characther `/` cannot be used * in names; it is only used to delimit directories within paths. * @param title The title of the IDataPointSet. * @param x The array of the x values * @param y The array of the y values * @param exp The array with the plus errors on x * @param eyp The array with the plus errors on y * @param exm The array with the minus errors on x * @param eym The array with the minus errors on y * @return The created IDataPointSet. */ virtual IDataPointSet * createXY(const std::string & path, const std::string & title, const std::vector & x, const std::vector & y, const std::vector & exp, const std::vector & eyp, const std::vector & exm, const std::vector & eym) { IDataPointSet * dset = create(path, title, 2); for ( int i = 0, N = y.size(); i < N; ++i ) dset->addPoint(DataPoint(2)); if ( !dset->setCoordinate(0, x, exp, exm) || !dset->setCoordinate(1, y, eyp, eym) ) throw std::runtime_error("LWH could add points to DataPointSet '" + title + "'." ); return dset; } /** * Create a two dimensional IDataPointSet providing the data. * @param path The path of the IDataPointSet. The path can either be a * relative or full path. ("/folder1/folder2/dataTitle" and * "../folder/dataTitle" are valid paths). All the directories * in the path must exist. The characther `/` cannot be used * in names; it is only used to delimit directories within paths. * @param title The title of the IDataPointSet. * @param x The array of the x values * @param y The array of the y values * @param ex The array with the symmetric errors on x * @param ey The array with the symmetric errors on y * @return The created IDataPointSet. */ virtual IDataPointSet * createXY(const std::string & path, const std::string & title, const std::vector & x, const std::vector & y, const std::vector & ex, const std::vector & ey) { return createXY(path, title, x, y, ex, ey, ex, ey); } /** * Create a two dimensional IDataPointSet providing the data. * @param pathAndTitle The path of the IDataPointSet. The path can either be * a relative or full path. The last part of the path is * used as the title. ("/folder1/folder2/dataTitle" and * "../folder/dataTitle" are valid paths). All the * directories in the path must exist. The characther * `/` cannot be used in names; it is only used to * delimit directories within paths. * @param x The array of the x values * @param y The array of the y values * @param exp The array with the plus errors on x * @param eyp The array with the plus errors on y * @param exm The array with the minus errors on x * @param eym The array with the minus errors on y * @return The created IDataPointSet. */ virtual IDataPointSet * createXY(const std::string & pathAndTitle, const std::vector & x, const std::vector & y, const std::vector & exp, const std::vector & eyp, const std::vector & exm, const std::vector & eym) { std::string title = pathAndTitle.substr(pathAndTitle.rfind('/') + 1); return createXY(pathAndTitle, title, x, y, exp, eyp, exm, eym); } /** * Create a two dimensional IDataPointSet providing the data. * @param pathAndTitle The path of the IDataPointSet. The path can either be * a relative or full path. The last part of the path is * used as the title. ("/folder1/folder2/dataTitle" and * "../folder/dataTitle" are valid paths). All the * directories in the path must exist. The characther * `/` cannot be used in names; it is only used to * delimit directories within paths. * @param x The array of the x values * @param y The array of the y values * @param ex The array with the symmetric errors on x * @param ey The array with the symmetric errors on y * @return The created IDataPointSet. */ virtual IDataPointSet * createXY(const std::string & pathAndTitle, const std::vector & x, const std::vector & y, const std::vector & ex, const std::vector & ey) { std::string title = pathAndTitle.substr(pathAndTitle.rfind('/') + 1); return createXY(pathAndTitle, title, x, y, ex, ey, ex, ey); } /** * Create a three dimensional IDataPointSet providing the data. * @param path The path of the IDataPointSet. The path can either be a * relative or full path. ("/folder1/folder2/dataTitle" and * "../folder/dataTitle" are valid paths). All the directories * in the path must exist. The characther `/` cannot be used * in names; it is only used to delimit directories within paths. * @param title The title of the IDataPointSet. * @param x The array of the x values * @param y The array of the y values * @param z The array of the z values * @param exp The array with the plus errors on x * @param eyp The array with the plus errors on y * @param ezp The array with the plus errors on z * @param exm The array with the minus errors on x * @param eym The array with the minus errors on y * @param ezm The array with the minus errors on z * @return The created IDataPointSet. */ virtual IDataPointSet * createXYZ(const std::string & path, const std::string & title, const std::vector & x, const std::vector & y, const std::vector & z, const std::vector & exp, const std::vector & eyp, const std::vector & ezp, const std::vector & exm, const std::vector & eym, const std::vector & ezm) { IDataPointSet * dset = create(path, title, 3); for ( int i = 0, N = y.size(); i < N; ++i ) dset->addPoint(DataPoint(3)); if ( !dset->setCoordinate(0, x, exp, exm) || !dset->setCoordinate(1, y, eyp, eym) || !dset->setCoordinate(2, z, ezp, ezm) ) throw std::runtime_error("LWH could add points to DataPointSet '" + title + "'." ); return dset; } /** * Create a three dimensional IDataPointSet providing the data. * @param path The path of the IDataPointSet. The path can either be a * relative or full path. ("/folder1/folder2/dataTitle" and * "../folder/dataTitle" are valid paths). All the directories * in the path must exist. The characther `/` cannot be used * in names; it is only used to delimit directories within paths. * @param title The title of the IDataPointSet. * @param x The array of the x values * @param y The array of the y values * @param z The array of the z values * @param ex The array with the symmetric errors on x * @param ey The array with the symmetric errors on y * @param ez The array with the symmetric errors on z * @return The created IDataPointSet. */ virtual IDataPointSet * createXYZ(const std::string & path, const std::string & title, const std::vector & x, const std::vector & y, const std::vector & z, const std::vector & ex, const std::vector & ey, const std::vector & ez) { return createXYZ(path, title, x, y, z, ex, ey, ez, ex, ey, ez); } /** * Create a two dimensional IDataPointSet providing the data. * @param pathAndTitle The path of the IDataPointSet. The path can either be * a relative or full path. The last part of the path is * used as the title. ("/folder1/folder2/dataTitle" and * "../folder/dataTitle" are valid paths). All the * directories in the path must exist. The characther * `/` cannot be used in names; it is only used to * delimit directories within paths. * @param x The array of the x values * @param y The array of the y values * @param z The array of the z values * @param exp The array with the plus errors on x * @param eyp The array with the plus errors on y * @param ezp The array with the plus errors on z * @param exm The array with the minus errors on x * @param eym The array with the minus errors on y * @param ezm The array with the minus errors on z * @return The created IDataPointSet. */ virtual IDataPointSet * createXYZ(const std::string & pathAndTitle, const std::vector & x, const std::vector & y, const std::vector & z, const std::vector & exp, const std::vector & eyp, const std::vector & ezp, const std::vector & exm, const std::vector & eym, const std::vector & ezm) { std::string title = pathAndTitle.substr(pathAndTitle.rfind('/') + 1); return createXYZ(pathAndTitle, title, x, y, z, exp, eyp, ezp, exm, eym, ezm); } /** * Create a two dimensional IDataPointSet providing the data. * @param pathAndTitle The path of the IDataPointSet. The path can either be * a relative or full path. The last part of the path is * used as the title. ("/folder1/folder2/dataTitle" and * "../folder/dataTitle" are valid paths). All the * directories in the path must exist. The characther * `/` cannot be used in names; it is only used to * delimit directories within paths. * @param x The array of the x values * @param y The array of the y values * @param z The array of the z values * @param ex The array with the symmetric errors on x * @param ey The array with the symmetric errors on y * @param ez The array with the symmetric errors on z * @return The created IDataPointSet. */ virtual IDataPointSet * createXYZ(const std::string & pathAndTitle, const std::vector & x, const std::vector & y, const std::vector & z, const std::vector & ex, const std::vector & ey, const std::vector & ez) { std::string title = pathAndTitle.substr(pathAndTitle.rfind('/') + 1); return createXYZ(pathAndTitle, title, x, y, z, ex, ey, ez, ex, ey, ez); } /** * Make a copy of a given IDataPointSet. * @param path The path of the IDataPointSet. The path can either be a * relative or full path. ("/folder1/folder2/dataTitle" and * "../folder/dataTitle" are valid paths). All the directories * in the path must exist. The characther `/` cannot be used * in names; it is only used to delimit directories within paths. * @param dataPointSet The IDataPointSet to be copied. * @return The copy of the given IDataPointSet. */ virtual IDataPointSet * createCopy(const std::string & path, const IDataPointSet & dataPointSet) { IDataPointSet * dset = create(path, dataPointSet.title(), dataPointSet.dimension()); for ( int i = 0, N = dataPointSet.size(); i < N; ++i ) dset->addPoint(*dataPointSet.point(i)); return dset; } /** * Destroy a given IDataPointSet. * @param dataPointSet The IDataPointSet to be destroyed. * @return false If dataPointSet cannot be destroyed. */ virtual bool destroy(IDataPointSet * dataPointSet) { IManagedObject * mo = dynamic_cast(dataPointSet); if ( !mo ) return false; return tree->rm(tree->findPath(*mo)); } /** * Create an IDataPointSet from an IHistogram1D. * @param path The path of the IDataPointSet. The path can either * be a relative or full path. * ("/folder1/folder2/dataName" and "../folder/dataName" * are valid paths). All the directories in the path * must exist. The characther `/` cannot be used in * names; it is only used to delimit directories within * paths. * @param hist The IHistogram1D from which the data is taken. * @return The newly created IDataPointSet. */ virtual IDataPointSet * create(const std::string & path, const IHistogram1D & hist, const std::string & = "") { IDataPointSet * dset = create(path, hist.title(), 2); std::vector x, y, ex, ey; for ( int i = 2, N = hist.axis().bins() + 2; i < N; ++i ) { dset->addPoint(DataPoint(2)); x.push_back(hist.binMean(i - 2)); ex.push_back(hist.axis().binWidth(i - 2)); y.push_back(hist.binHeight(i - 2)); ey.push_back(hist.binError(i - 2)); } if ( !dset->setCoordinate(0, x, ex, ex) || !dset->setCoordinate(1, y, ey, ey) ) throw std::runtime_error("LWH could add points to DataPointSet '" + hist.title() + "'." ); return dset; } /** * Create an IDataPointSet from an IHistogram2D. * @param path The path of the IDataPointSet. The path can either * be a relative or full path. * ("/folder1/folder2/dataName" and "../folder/dataName" * are valid paths). All the directories in the path * must exist. The characther `/` cannot be used in * names; it is only used to delimit directories within * paths. * @param hist The IHistogram2D from which the data is taken. * @param options Options, currently not specified * @return The newly created IDataPointSet. */ virtual IDataPointSet * create(const std::string & path, const IHistogram2D & hist, const std::string & = "") { IDataPointSet * dset = create(path, hist.title(), 3); std::vector x, y, z, ex, ey, ez; for ( int ix = 2, Nx = hist.xAxis().bins() + 2; ix < Nx; ++ix ) for ( int iy = 2, Ny = hist.yAxis().bins() + 2; iy < Ny; ++iy ) { dset->addPoint(DataPoint(3)); //x.push_back(hist.binMean(i - 2)); // < "Dynamic" version // Shouldn't IAxis have a binCentre(size_t binId) method? // (According to Java AIDA v3.3.0 API) x.push_back((hist.xAxis().binLowerEdge(ix - 2) + hist.xAxis().binUpperEdge(ix - 2))/2.0); ex.push_back(hist.xAxis().binWidth(ix - 2)/2.0); y.push_back((hist.yAxis().binLowerEdge(iy - 2) + hist.yAxis().binUpperEdge(iy - 2))/2.0); ey.push_back(hist.yAxis().binWidth(iy - 2)/2.0); const double binwidth = hist.xAxis().binWidth(ix - 2)* hist.yAxis().binWidth(iy - 2); z.push_back(hist.binHeight(ix - 2, iy - 2)/binwidth); ez.push_back(hist.binError(ix - 2, iy - 2)/binwidth); } if ( !dset->setCoordinate(0, x, ex, ex) || !dset->setCoordinate(1, y, ey, ey) || !dset->setCoordinate(2, z, ez, ez) ) throw std::runtime_error("LWH could not add points to DataPointSet '" + hist.title() + "'." ); return dset; } /** * LWH cannot handle a IHistogram3D. */ virtual IDataPointSet * create(const std::string &, const IHistogram3D &, const std::string & = "") { return error("IHistogram3D"); } /** * LWH cannot handle a ICloud1. */ virtual IDataPointSet * create(const std::string &, const ICloud1D &, const std::string & = "") { return error("ICloud1D"); } /** * LWH cannot handle a ICloud2D. */ virtual IDataPointSet * create(const std::string &, const ICloud2D &, const std::string & = "") { return error("ICloud2D"); } /** * LWH cannot handle a ICloud3D. */ virtual IDataPointSet * create(const std::string &, const ICloud3D &, const std::string & = "") { return error("ICloud3D"); } /** * LWH cannot handle a IProfile1D. */ virtual IDataPointSet * create(const std::string &, const IProfile1D &, const std::string & = "") { return error("IProfile1D"); } /** * LWH cannot handle a IProfile2D. */ virtual IDataPointSet * create(const std::string &, const IProfile2D &, const std::string & = "") { return error("IProfile2D"); } /** * LWH cannot handle the addition of data points. */ virtual IDataPointSet * add(const std::string &, const IDataPointSet &, const IDataPointSet &) { return error("addition of data points"); } /** * LWH cannot handle the subtraction of data points. */ virtual IDataPointSet * subtract(const std::string &, const IDataPointSet &, const IDataPointSet &) { return error("subtraction of data points"); } /** * LWH cannot handle the multiplication of data points. */ virtual IDataPointSet * multiply(const std::string &, const IDataPointSet &, const IDataPointSet &) { return error("multiplication of data points"); } /** * LWH cannot handle the division of data points. */ virtual IDataPointSet * divide(const std::string &, const IDataPointSet &, const IDataPointSet &) { return error("division of data points"); } /** * LWH cannot handle the weighted mean of data points. */ virtual IDataPointSet * weightedMean(const std::string &, const IDataPointSet &, const IDataPointSet &) { return error("weighted means of data points"); } private: /** Throw a suitable error. */ template static T * error(std::string feature) { throw std::runtime_error("LWH cannot handle " + feature + "."); } /** The tree where the actual data sets are stored. */ Tree * tree; }; } #endif diff --git a/Analysis/LWH/Histogram1D.h b/Analysis/LWH/Histogram1D.h --- a/Analysis/LWH/Histogram1D.h +++ b/Analysis/LWH/Histogram1D.h @@ -1,520 +1,520 @@ // -*- C++ -*- // // Histogram1D.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef LWH_Histogram1D_H #define LWH_Histogram1D_H // // This is the declaration of the Histogram1D class. // #include "AIHistogram1D.h" #include "ManagedObject.h" #include "Axis.h" #include "VariAxis.h" #include #include namespace LWH { using namespace AIDA; /** * User level interface to 1D Histogram. */ class Histogram1D: public IHistogram1D, public ManagedObject { public: /** HistFactory is a friend. */ friend class HistogramFactory; public: /** * Standard constructor. */ Histogram1D(int n, double lo, double up) : fax(new Axis(n, lo, up)), vax(0), sum(n + 2), sumw(n + 2), sumw2(n + 2), sumxw(n + 2), sumx2w(n + 2) { ax = fax; } /** * Standard constructor for variable bin width. */ Histogram1D(const std::vector & edges) : fax(0), vax(new VariAxis(edges)), sum(edges.size() + 1), sumw(edges.size() + 1), sumw2(edges.size() + 1), sumxw(edges.size() + 1), sumx2w(edges.size() + 1) { ax = vax; } /** * Copy constructor. */ Histogram1D(const Histogram1D & h) : IBaseHistogram(h), IHistogram(h), IHistogram1D(h), ManagedObject(h), fax(0), vax(0), sum(h.sum), sumw(h.sumw), sumw2(h.sumw2), sumxw(h.sumxw), sumx2w(h.sumx2w) { const VariAxis * hvax = dynamic_cast(h.ax); if ( vax ) ax = vax = new VariAxis(*hvax); else ax = fax = new Axis(dynamic_cast(*h.ax)); } /// Destructor. virtual ~Histogram1D() { delete ax; } /** * Get the Histogram's title. * @return The Histogram's title. */ std::string title() const { return theTitle; } /** * Get the Histogram's title. * @return The Histogram's title. */ std::string name() const { return theTitle; } /** * Set the histogram title. * @param title The title. * @return false If title cannot be changed. */ bool setTitle(const std::string & title) { theTitle = title; return true; } /** * Not implemented in LWH. will throw an exception. */ IAnnotation & annotation() { throw std::runtime_error("LWH cannot handle annotations"); } /** * Not implemented in LWH. will throw an exception. */ const IAnnotation & annotation() const { throw std::runtime_error("LWH cannot handle annotations"); } /** * Get the Histogram's dimension. * @return The Histogram's dimension. */ int dimension() const { return 1; } /** * Reset the Histogram; as if just created. * @return false If something goes wrong. */ bool reset() { sum = std::vector(ax->bins() + 2); sumw = std::vector(ax->bins() + 2); sumxw = std::vector(ax->bins() + 2); sumx2w = std::vector(ax->bins() + 2); sumw2 = std::vector(ax->bins() + 2); return true; } /** * Get the number of in-range entries in the Histogram. * @return The number of in-range entries. * */ int entries() const { int si = 0; for ( int i = 2; i < ax->bins() + 2; ++i ) si += sum[i]; return si; } /** * Sum of the entries in all the IHistogram's bins, * i.e in-range bins, UNDERFLOW and OVERFLOW. * This is equivalent to the number of times the * method fill was invoked. * @return The sum of all the entries. */ int allEntries() const { return entries() + extraEntries(); } /** * Number of entries in the UNDERFLOW and OVERFLOW bins. * @return The number of entries outside the range of the IHistogram. */ int extraEntries() const { return sum[0] + sum[1]; } /** * Number of equivalent entries, * i.e. SUM[ weight ] ^ 2 / SUM[ weight^2 ] * @return The number of equivalent entries. */ double equivalentBinEntries() const { double sw = 0.0; double sw2 = 0.0; for ( int i = 2; i < ax->bins() + 2; ++i ) { sw += sumw[i]; sw2 += sumw2[i]; } return sw2/(sw*sw); } /** * Sum of in-range bin heights in the IHistogram, * UNDERFLOW and OVERFLOW bins are excluded. * @return The sum of the in-range bins heights. * */ double sumBinHeights() const { double sw = 0.0; for ( int i = 2; i < ax->bins() + 2; ++i ) sw += sumw[i]; return sw; } /** * Sum of the heights of all the IHistogram's bins, * i.e in-range bins, UNDERFLOW and OVERFLOW. * @return The sum of all the bins heights. */ double sumAllBinHeights() const { return sumBinHeights() + sumExtraBinHeights(); } /** * Sum of heights in the UNDERFLOW and OVERFLOW bins. * @return The sum of the heights of the out-of-range bins. */ double sumExtraBinHeights() const { return sumw[0] + sumw[1]; } /** * Minimum height of the in-range bins, * i.e. not considering the UNDERFLOW and OVERFLOW bins. * @return The minimum height among the in-range bins. */ double minBinHeight() const { double minw = sumw[2]; for ( int i = 3; i < ax->bins() + 2; ++i ) minw = std::min(minw, sumw[i]); return minw; } /** * Maximum height of the in-range bins, * i.e. not considering the UNDERFLOW and OVERFLOW bins. * @return The maximum height among the in-range bins. */ double maxBinHeight() const{ double maxw = sumw[2]; for ( int i = 3; i < ax->bins() + 2; ++i ) maxw = std::max(maxw, sumw[i]); return maxw; } /** * Fill the IHistogram1D with a value and the * corresponding weight. * @param x The value to be filled in. * @param weight The corresponding weight (by default 1). * @return false If the weight is <0 or >1 (?). */ bool fill(double x, double weight = 1.) { int i = ax->coordToIndex(x) + 2; ++sum[i]; sumw[i] += weight; sumxw[i] += x*weight; sumx2w[i] += x*x*weight; sumw2[i] += weight*weight; return weight >= 0 && weight <= 1; } /** * The weighted mean of a bin. * @param index The bin number (0...N-1) or OVERFLOW or UNDERFLOW. * @return The mean of the corresponding bin. */ double binMean(int index) const { int i = index + 2; return sumw[i] != 0.0? sumxw[i]/sumw[i]: ( vax? vax->binMidPoint(index): fax->binMidPoint(index) ); }; /** * The weighted RMS of a bin. * @param index The bin number (0...N-1) or OVERFLOW or UNDERFLOW. * @return The RMS of the corresponding bin. */ double binRms(int index) const { int i = index + 2; return sumw[i] == 0.0 || sum[i] < 2? ax->binWidth(index): std::sqrt(std::max(sumw[i]*sumx2w[i] - sumxw[i]*sumxw[i], 0.0))/sumw[i]; }; /** * Number of entries in the corresponding bin (ie the number of * times fill was called for this bin). * @param index The bin number (0...N-1) or OVERFLOW or UNDERFLOW. * @return The number of entries in the corresponding bin. */ int binEntries(int index) const { return sum[index + 2]; } /** * Total height of the corresponding bin (ie the sum of the weights * in this bin). * @param index The bin number (0...N-1) or OVERFLOW or UNDERFLOW. * @return The height of the corresponding bin. */ double binHeight(int index) const { return sumw[index + 2]; } /** * The error of a given bin. * @param index The bin number (0...N-1) or OVERFLOW or UNDERFLOW. * @return The error on the corresponding bin. * */ double binError(int index) const { return std::sqrt(sumw2[index + 2]); } /** * The mean of the whole IHistogram1D. * @return The mean of the IHistogram1D. */ double mean() const { double s = 0.0; double sx = 0.0; for ( int i = 2; i < ax->bins() + 2; ++i ) { s += sumw[i]; sx += sumxw[i]; } return s != 0.0? sx/s: 0.0; } /** * The RMS of the whole IHistogram1D. * @return The RMS if the IHistogram1D. */ double rms() const { double s = 0.0; double sx = 0.0; double sx2 = 0.0; for ( int i = 2; i < ax->bins() + 2; ++i ) { s += sumw[i]; sx += sumxw[i]; sx2 += sumx2w[i]; } return s != 0.0? std::sqrt(std::max(s*sx2 - sx*sx, 0.0))/s: ax->upperEdge() - ax->lowerEdge(); } /** * Get the x axis of the IHistogram1D. * @return The x coordinate IAxis. */ const IAxis & axis() const { return *ax; } /** * Get the bin number corresponding to a given coordinate along the * x axis. This is a convenience method, equivalent to * axis().coordToIndex(coord). * @param coord The coordinalte along the x axis. * @return The corresponding bin number. */ int coordToIndex(double coord) const { return ax->coordToIndex(coord); } /** * Add to this Histogram1D the contents of another IHistogram1D. * @param h The Histogram1D to be added to this IHistogram1D. * @return false If the IHistogram1Ds binnings are incompatible. */ bool add(const Histogram1D & h) { if ( ax->upperEdge() != h.ax->upperEdge() || ax->lowerEdge() != h.ax->lowerEdge() || ax->bins() != h.ax->bins() ) return false; for ( int i = 0; i < ax->bins() + 2; ++i ) { sum[i] += h.sum[i]; sumw[i] += h.sumw[i]; sumxw[i] += h.sumxw[i]; sumx2w[i] += h.sumx2w[i]; sumw2[i] += h.sumw2[i]; } return true; } /** * Add to this IHistogram1D the contents of another IHistogram1D. * @param hist The IHistogram1D to be added to this IHistogram1D. * @return false If the IHistogram1Ds binnings are incompatible. */ bool add(const IHistogram1D & hist) { return add(dynamic_cast(hist)); } /** * Scale the contents of this histogram with the given factor. * @param s the scaling factor to use. */ bool scale(double s) { for ( int i = 0; i < ax->bins() + 2; ++i ) { sumw[i] *= s; sumxw[i] *= s; sumx2w[i] *= s; sumw2[i] *= s*s; } return true; } /** * Scale the given histogram so that the integral over all bins * (including overflow) gives \a intg. This function also corrects * for the bin-widths, which means that it should only be run once * for each histogram. Further rescaling must be done with the * scale(double) function. */ void normalize(double intg) { double oldintg = sumAllBinHeights(); if ( oldintg == 0.0 ) return; for ( int i = 0; i < ax->bins() + 2; ++i ) { double fac = intg/oldintg; if ( i >= 2 ) fac /= (ax->binUpperEdge(i - 2) - ax->binLowerEdge(i - 2)); sumw[i] *= fac; sumxw[i] *= fac; sumx2w[i] *= fac; sumw2[i] *= fac*fac; } } /** * Return the integral over the histogram bins assuming it has been * normalize()d. */ double integral() const { double intg = sumw[0] + sumw[1]; for ( int i = 2; i < ax->bins() + 2; ++i ) intg += sumw[i]*(ax->binUpperEdge(i - 2) - ax->binLowerEdge(i - 2)); return intg; } /** * Not implemented in LWH. * @return null pointer always. */ void * cast(const std::string &) const { return 0; } /** * Write out the histogram in the AIDA xml format. */ bool writeXML(std::ostream & os, std::string path, std::string name) { os << " \n upperEdge() << "\" numberOfBins=\"" << ax->bins() << "\" min=\"" << ax->lowerEdge() << "\" direction=\"x\""; if ( vax ) { os << ">\n"; for ( int i = 0, N = ax->bins() - 1; i < N; ++i ) os << " binUpperEdge(i) << "\"/>\n"; os << " \n"; } else { os << "/>\n"; } os << " \n \n \n \n"; for ( int i = 0; i < ax->bins() + 2; ++i ) if ( sum[i] ) { os << " \n"; } os << " \n " << std::endl; return true; } /** * Write out the histogram in a flat text file suitable for * eg. gnuplot to read. The coloums are layed out as 'x w w2 n'. */ bool writeFLAT(std::ostream & os, std::string path, std::string name) { os << "# " << path << "/" << name << " " << ax->lowerEdge() << " " << ax->bins() << " " << ax->upperEdge() << " \"" << title() << " \"" << std::endl; for ( int i = 2; i < ax->bins() + 2; ++i ) os << 0.5*(ax->binLowerEdge(i - 2) + ax->binUpperEdge(i - 2)) << " " << sumw[i] << " " << sqrt(sumw2[i]) << " " << sum[i] << std::endl; os << std::endl; return true; } private: /** The title */ std::string theTitle; /** The axis. */ IAxis * ax; /** Pointer (possibly null) to a axis with fixed bin width. */ Axis * fax; /** Pointer (possibly null) to a axis with fixed bin width. */ VariAxis * vax; /** The counts. */ std::vector sum; /** The weights. */ std::vector sumw; /** The squared weights. */ std::vector sumw2; /** The weighted x-values. */ std::vector sumxw; /** The weighted x-square-values. */ std::vector sumx2w; }; } #endif /* LWH_Histogram1D_H */ diff --git a/Analysis/LWH/HistogramFactory.h b/Analysis/LWH/HistogramFactory.h --- a/Analysis/LWH/HistogramFactory.h +++ b/Analysis/LWH/HistogramFactory.h @@ -1,1036 +1,1036 @@ // -*- C++ -*- // // HistogramFactory.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef LWH_HistogramFactory_H #define LWH_HistogramFactory_H // // This is the declaration of the HistogramFactory class. // #include "AIHistogramFactory.h" #include "Histogram1D.h" #include "Histogram2D.h" #include "Tree.h" #include #include namespace LWH { using namespace AIDA; /** * User level interface for factory classes of Histograms (binned, * unbinned, and profile). The created objects are assumed to be * managed by the tree which is associated to the factory. So far only * one-dimensional histograms are implemented in LWH. */ class HistogramFactory: public IHistogramFactory { public: /** * Standard constructor. */ HistogramFactory(Tree & t) : tree(&t) {} /** * Destructor. */ virtual ~HistogramFactory() {} /** * Destroy an IBaseHistogram object. * @param hist The IBaseHistogram to be destroyed. * @return false If the histogram cannot be destroyed. */ bool destroy(IBaseHistogram * hist) { IManagedObject * mo = dynamic_cast(hist); if ( !mo ) return false; return tree->rm(tree->findPath(*mo)); } /** * LWH cannot create a ICloud1D, an unbinned 1-dimensional histogram. */ ICloud1D * createCloud1D(const std::string &, const std::string &, int = -1, const std::string & = "") { return error("ICloud1D"); } /** * LWH cannot create a ICloud1D, an unbinned 1-dimensional histogram. */ ICloud1D * createCloud1D(const std::string &) { return error("ICloud1D"); } /** * LWH cannot create a copy of an ICloud1D. */ ICloud1D * createCopy(const std::string &, const ICloud1D &) { return error("ICloud1D"); } /** * LWH cannot create a ICloud2D, an unbinned 2-dimensional histogram. */ ICloud2D * createCloud2D(const std::string &, const std::string &, int = -1, const std::string & = "") { return error("ICloud2D"); } /** * LWH cannot create a ICloud2D, an unbinned 2-dimensional histogram. */ ICloud2D * createCloud2D(const std::string &) { return error("ICloud2D"); } /** * LWH cannot create a copy of an ICloud2D. */ ICloud2D * createCopy(const std::string &, const ICloud2D &) { return error("ICloud2D"); } /** * LWH cannot create a ICloud3D, an unbinned 3-dimensional histogram. */ ICloud3D * createCloud3D(const std::string &, const std::string &, int = -1, const std::string & = "") { return error("ICloud3D"); } /** * LWH cannot create a ICloud3D, an unbinned 3-dimensional histogram. */ ICloud3D * createCloud3D(const std::string &) { return error("ICloud3D"); } /** * LWH cannot create a copy of an ICloud3D. */ ICloud3D * createCopy(const std::string &, const ICloud3D &) { return error("ICloud3D"); } /** * Create a IHistogram1D. * @param path The path of the created IHistogram. The path must be a * full path. ("/folder1/folder2/dataName" is a valid path). * The characther `/` cannot be used in names; it is only * used to delimit directories within paths. * @param title The title of the IHistogram1D. * @param nBins The number of bins of the x axis. * @param lowerEdge The lower edge of the x axis. * @param upperEdge The upper edge of the x axis. * @return The newly created IHistogram1D ot the null pointer * if something went wrong, such as a non existing * directrory in the path or that an object with the * given path already existed. * @throws std::runtime_error if histogram could not be created. */ IHistogram1D * createHistogram1D(const std::string & path, const std::string & title, int nBins, double lowerEdge, double upperEdge, const std::string & = "") { Histogram1D * hist = new Histogram1D(nBins, lowerEdge, upperEdge); hist->setTitle(title); if ( !tree->insert(path, hist) ) { delete hist; hist = 0; throw std::runtime_error("LWH could not create histogram '" + title + "'." ); } return hist; } /** * Create a IHistogram1D. * @param pathAndTitle The path of the created IHistogram. The path must be a * full path. ("/folder1/folder2/dataName" is a valid * path). The characther `/` cannot be used in names; it * is only used to delimit directories within paths. * @param nBins The number of bins of the x axis. * @param lowerEdge The lower edge of the x axis. * @param upperEdge The upper edge of the x axis. * @return The newly created IHistogram1D. * @throws std::runtime_error if histogram could not be created. */ IHistogram1D * createHistogram1D(const std::string & pathAndTitle, int nBins, double lowerEdge, double upperEdge) { std::string title = pathAndTitle.substr(pathAndTitle.rfind('/') + 1); return createHistogram1D(pathAndTitle, title, nBins, lowerEdge, upperEdge); } /** * Create a IHistogram1D. * @param path The path of the created IHistogram. The path can either * be a relative or full path. * ("/folder1/folder2/dataName" and "../folder/dataName" * are valid paths). All the directories in the path must * exist. The characther `/` cannot be used in names; * it is only used to delimit directories within paths. * @param title The title of the IHistogram1D. * @param binEdges The array of the bin edges for the x axis. */ IHistogram1D * createHistogram1D(const std::string & path, const std::string & title, const std::vector & binEdges, const std::string & = "") { Histogram1D * hist = new Histogram1D(binEdges); hist->setTitle(title); if ( !tree->insert(path, hist) ) { delete hist; hist = 0; throw std::runtime_error("LWH could not create histogram '" + title + "'." ); } return hist; } /** * Create a copy of an IHistogram1D. * @param path The path of the created IHistogram. The path must be a * full path. ("/folder1/folder2/dataName" is a valid * path). The characther `/` cannot be used in names; it * is only used to delimit directories within paths. * @param hist The IHistogram1D to be copied. * @return The copy of the IHistogram1D. * @throws std::runtime_error if histogram could not be created. */ IHistogram1D * createCopy(const std::string & path, const IHistogram1D & hist) { Histogram1D * h = new Histogram1D(dynamic_cast(hist)); h->setTitle(path.substr(path.rfind('/') + 1)); if ( !tree->insert(path, h) ) { delete h; h = 0; throw std::runtime_error("LWH could not create a copy of histogram '" + hist.title() + "'." ); } return h; } /** * Create a IHistogram2D. */ IHistogram2D * createHistogram2D(const std::string & path, const std::string & title, int nx, double xlo, double xup, int ny, double ylo, double yup, const std::string & = "") { Histogram2D * hist = new Histogram2D(nx, xlo, xup, ny, ylo, yup); hist->setTitle(title); if ( !tree->insert(path, hist) ) { delete hist; hist = 0; throw std::runtime_error("LWH could not create histogram '" + title + "'." ); } return hist; } /** * Create a IHistogram2D. */ IHistogram2D * createHistogram2D(const std::string & pathAndTitle, int nx, double xlo, double xup, int ny, double ylo, double yup) { std::string title = pathAndTitle.substr(pathAndTitle.rfind('/') + 1); return createHistogram2D(pathAndTitle, title, nx, xlo, xup, ny, ylo, yup); } /** * Create a IHistogram2D. */ IHistogram2D * createHistogram2D(const std::string & path, const std::string & title, const std::vector & xedges, const std::vector & yedges, const std::string & = "") { Histogram2D * hist = new Histogram2D(xedges, yedges); hist->setTitle(title); if ( !tree->insert(path, hist) ) { delete hist; hist = 0; throw std::runtime_error("LWH could not create histogram '" + title + "'." ); } return hist; } /** *Create a copy of an IHistogram2D. */ IHistogram2D * createCopy(const std::string & path, const IHistogram2D & hist) { Histogram2D * h = new Histogram2D(dynamic_cast(hist)); h->setTitle(path.substr(path.rfind('/') + 1)); if ( !tree->insert(path, h) ) { delete h; h = 0; throw std::runtime_error("LWH could not create a copy of histogram '" + hist.title() + "'." ); } return h; } /** * LWH cannot create a IHistogram3D. */ IHistogram3D * createHistogram3D(const std::string &, const std::string &, int, double, double, int, double, double, int, double, double, const std::string & = "") { return error("IHistogram3D"); } /** * LWH cannot create a IHistogram3D. */ IHistogram3D * createHistogram3D(const std::string &, int, double, double, int, double, double, int, double, double) { return error("IHistogram3D"); } /** * LWH cannot create a IHistogram3D. */ IHistogram3D * createHistogram3D(const std::string &, const std::string &, const std::vector &, const std::vector &, const std::vector &, const std::string & = "") { return error("IHistogram3D"); } /** * LWH cannot create a copy of an IHistogram3D. */ IHistogram3D * createCopy(const std::string &, const IHistogram3D &) { return error("IHistogram3D"); } /** * LWH cannot create a IProfile1D. */ IProfile1D * createProfile1D(const std::string &, const std::string &, int, double, double, const std::string & = "") { return error("IProfile1D"); } /** * LWH cannot create a IProfile1D. */ IProfile1D * createProfile1D(const std::string &, const std::string &, int, double, double, double, double, const std::string & = "") { return error("IProfile1D"); } /** * LWH cannot create a IProfile1D. */ IProfile1D * createProfile1D(const std::string &, const std::string &, const std::vector &, const std::string & = "") { return error("IProfile1D"); } /** * LWH cannot create a IProfile1D. */ IProfile1D * createProfile1D(const std::string &, const std::string &, const std::vector &, double, double, const std::string & = "") { return error("IProfile1D"); } /** * LWH cannot create a IProfile1D. */ IProfile1D * createProfile1D(const std::string &, int, double, double) { return error("IProfile1D"); } /** * LWH cannot create a IProfile1D. */ IProfile1D * createProfile1D(const std::string &, int, double, double, double, double) { return error("IProfile1D"); } /** * LWH cannot create a copy of an IProfile1D. */ IProfile1D * createCopy(const std::string &, const IProfile1D &) { return error("IProfile1D"); } /** * LWH cannot create a IProfile2D. */ IProfile2D * createProfile2D(const std::string &, const std::string &, int, double, double, int, double, double, const std::string & = "") { return error("IProfile2D"); } /** * LWH cannot create a IProfile2D. */ IProfile2D * createProfile2D(const std::string &, const std::string &, int, double, double, int, double, double, double, double, const std::string & = "") { return error("IProfile2D"); } /** * LWH cannot create a IProfile2D. */ IProfile2D * createProfile2D(const std::string &, const std::string &, const std::vector &, const std::vector &, const std::string & = "") { return error("IProfile2D"); } /** * LWH cannot create a IProfile2D. */ IProfile2D * createProfile2D(const std::string &, const std::string &, const std::vector &, const std::vector &, double, double, const std::string & = "") { return error("IProfile2D"); } /** * LWH cannot create a IProfile2D. */ IProfile2D * createProfile2D(const std::string &, int, double, double, int, double, double) { return error("IProfile2D"); } /** * LWH cannot create a IProfile2D. */ IProfile2D * createProfile2D(const std::string &, int, double, double, int, double, double, double, double) { return error("IProfile2D"); } /** * LWH cannot create a copy of an IProfile2D. */ IProfile2D * createCopy(const std::string &, const IProfile2D &) { return error("IProfile2D"); } /** * Create a Histogram1D by adding two Histogram1D. * @param path The path of the created IHistogram. The path must be a * full path. ("/folder1/folder2/dataName" is a valid * path). The characther `/` cannot be used in names; it * is only used to delimit directories within paths. * @param hist1 The first member of the addition. * @param hist2 The second member of the addition. * @return The sum of the two IHistogram1D. * @throws std::runtime_error if histogram could not be created. */ Histogram1D * add(const std::string & path, const Histogram1D & hist1, const Histogram1D & hist2) { if ( !checkBins(hist1, hist2) ) return 0; Histogram1D * h = new Histogram1D(hist1); h->setTitle(path.substr(path.rfind('/') + 1)); h->add(hist2); if ( !tree->insert(path, h) ) return 0; return h; } /** * Create an IHistogram1D by adding two IHistogram1D. * @param path The path of the created IHistogram. The path must be a * full path. ("/folder1/folder2/dataName" is a valid * path). The characther `/` cannot be used in names; it * is only used to delimit directories within paths. * @param hist1 The first member of the addition. * @param hist2 The second member of the addition. * @return The sum of the two IHistogram1D. * @throws std::runtime_error if histogram could not be created. */ IHistogram1D * add(const std::string & path, const IHistogram1D & hist1, const IHistogram1D & hist2) { return add(path, dynamic_cast(hist1), dynamic_cast(hist2)); } /** * Create a Histogram1D by subtracting two Histogram1D. * @param path The path of the created IHistogram. The path must be a * full path. ("/folder1/folder2/dataName" is a valid * path). The characther `/` cannot be used in names; it * is only used to delimit directories within paths. * @param h1 The first member of the subtraction. * @param h2 The second member of the subtraction. * @return The difference of the two IHistogram1D. * @throws std::runtime_error if histogram could not be created. */ Histogram1D * subtract(const std::string & path, const Histogram1D & h1, const Histogram1D & h2) { if ( !checkBins(h1, h2) ) return 0; Histogram1D * h = new Histogram1D(h1); h->setTitle(path.substr(path.rfind('/') + 1)); for ( int i = 0; i < h->ax->bins() + 2; ++i ) { h->sum[i] += h2.sum[i]; h->sumw[i] -= h2.sumw[i]; h->sumw2[i] += h2.sumw2[i]; } if ( !tree->insert(path, h) ) return 0; return h; } /** * Create an IHistogram1D by subtracting two IHistogram1D. * @param path The path of the created IHistogram. The path must be a * full path. ("/folder1/folder2/dataName" is a valid * path). The characther `/` cannot be used in names; it * is only used to delimit directories within paths. * @param hist1 The first member of the subtraction. * @param hist2 The second member of the subtraction. * @return The difference of the two IHistogram1D. * @throws std::runtime_error if histogram could not be created. */ IHistogram1D * subtract(const std::string & path, const IHistogram1D & hist1, const IHistogram1D & hist2) { return subtract(path, dynamic_cast(hist1), dynamic_cast(hist2)); } /** * Create a Histogram1D by multiplying two Histogram1D. * @param path The path of the created IHistogram. The path must be a * full path. ("/folder1/folder2/dataName" is a valid * path). The characther `/` cannot be used in names; it * is only used to delimit directories within paths. * @param h1 The first member of the multiplication. * @param h2 The second member of the multiplication. * @return The product of the two IHistogram1D. * @throws std::runtime_error if histogram could not be created. */ Histogram1D * multiply(const std::string & path, const Histogram1D & h1, const Histogram1D & h2) { if ( !checkBins(h1, h2) ) return 0; Histogram1D * h = new Histogram1D(h1); h->setTitle(path.substr(path.rfind('/') + 1)); for ( int i = 0; i < h->ax->bins() + 2; ++i ) { h->sumw[i] *= h2.sumw[i]; h->sumw2[i] += h1.sumw[i]*h1.sumw[i]*h2.sumw2[i] + h2.sumw[i]*h2.sumw[i]*h1.sumw2[i]; } if ( !tree->insert(path, h) ) return 0; return h; } /** * Create an IHistogram1D by multiplying two IHistogram1D. * @param path The path of the created IHistogram. The path must be a * full path. ("/folder1/folder2/dataName" is a valid * path). The characther `/` cannot be used in names; it * is only used to delimit directories within paths. * @param hist1 The first member of the multiplication. * @param hist2 The second member of the multiplication. * @return The product of the two IHistogram1D. * @throws std::runtime_error if histogram could not be created. */ IHistogram1D * multiply(const std::string & path, const IHistogram1D & hist1, const IHistogram1D & hist2) { return multiply(path, dynamic_cast(hist1), dynamic_cast(hist2)); } /** * Create n Histogram1D by dividing two Histogram1D. * @param path The path of the created IHistogram. The path must be a * full path. ("/folder1/folder2/dataName" is a valid * path). The characther `/` cannot be used in names; it * is only used to delimit directories within paths. * @param h1 The first member of the division. * @param h2 The second member of the division. * @return The ration of the two IHistogram1D. * @throws std::runtime_error if histogram could not be created. */ Histogram1D * divide(const std::string & path, const Histogram1D & h1, const Histogram1D & h2) { if ( !checkBins(h1, h2) ) return 0; Histogram1D * h = new Histogram1D(h1); h->setTitle(path.substr(path.rfind('/') + 1)); for ( int i = 0; i < h->ax->bins() + 2; ++i ) { if ( h2.sum[i] == 0 || h2.sumw[i] == 0.0 ) { h->sum[i] = 0; h->sumw[i] = h->sumw2[i] = 0.0; continue; } h->sumw[i] /= h2.sumw[i]; h->sumw2[i] = h1.sumw2[i]/(h2.sumw[i]*h2.sumw[i]) + h1.sumw[i]*h1.sumw[i]*h2.sumw2[i]/ (h2.sumw[i]*h2.sumw[i]*h2.sumw[i]*h2.sumw[i]); } if ( !tree->insert(path, h) ) return 0; return h; } /** * Create an IHistogram1D by dividing two IHistogram1D. * @param path The path of the created IHistogram. The path must be a * full path. ("/folder1/folder2/dataName" is a valid * path). The characther `/` cannot be used in names; it * is only used to delimit directories within paths. * @param hist1 The first member of the division. * @param hist2 The second member of the division. * @return The ration of the two IHistogram1D. * @throws std::runtime_error if histogram could not be created. */ IHistogram1D * divide(const std::string & path, const IHistogram1D & hist1, const IHistogram1D & hist2) { return divide(path, dynamic_cast(hist1), dynamic_cast(hist2)); } inline bool _neq(double a, double b, double eps = 1e-5) const { using std::abs; if ( a == 0 && b == 0 ) return false; if ( abs(a-b) < eps*(abs(a) + abs(b)) ) return false; return true; } /** * Check if two histograms have the same bins. */ bool checkBins(const Histogram1D & h1, const Histogram1D & h2) const { if ( _neq(h1.ax->upperEdge(), h2.ax->upperEdge()) || _neq(h1.ax->lowerEdge(), h2.ax->lowerEdge()) || _neq(h1.ax->bins(), h2.ax->bins()) ) return false; if ( h1.fax && h2.fax ) return true; for ( int i = 0; i < h1.ax->bins(); ++i ) { if ( _neq(h1.ax->binUpperEdge(i), h2.ax->binUpperEdge(i)) || _neq(h1.ax->binLowerEdge(i), h2.ax->binLowerEdge(i)) ) return false; } return true; } /** * Check if two histograms have the same bins. */ bool checkBins(const Histogram2D & h1, const Histogram2D & h2) const { if (_neq( h1.xax->upperEdge(), h2.xax->upperEdge()) || _neq( h1.xax->lowerEdge(), h2.xax->lowerEdge()) || h1.xax->bins() != h2.xax->bins() ) return false; if (_neq( h1.yax->upperEdge(), h2.yax->upperEdge()) || _neq( h1.yax->lowerEdge(), h2.yax->lowerEdge()) || h1.yax->bins() != h2.yax->bins() ) return false; if ( h1.xfax && h2.xfax && h1.yfax && h2.yfax ) return true; for ( int i = 0; i < h1.xax->bins(); ++i ) { if ( _neq(h1.xax->binUpperEdge(i), h2.xax->binUpperEdge(i)) || _neq(h1.xax->binLowerEdge(i), h2.xax->binLowerEdge(i)) ) return false; } for ( int i = 0; i < h1.yax->bins(); ++i ) { if ( _neq(h1.yax->binUpperEdge(i), h2.yax->binUpperEdge(i)) || _neq(h1.yax->binLowerEdge(i), h2.yax->binLowerEdge(i)) ) return false; } return true; } /** * LWH cannot create an IHistogram2D by adding two IHistogram2D. */ IHistogram2D * add(const std::string & path, const IHistogram2D & hist1, const IHistogram2D & hist2) { return add(path, dynamic_cast(hist1), dynamic_cast(hist2)); } /** * LWH cannot create an IHistogram2D by adding two IHistogram2D. */ Histogram2D * add(const std::string & path, const Histogram2D & h1, const Histogram2D & h2) { if ( !checkBins(h1, h2) ) return 0; Histogram2D * h = new Histogram2D(h1); h->setTitle(path.substr(path.rfind('/') + 1)); h->add(h2); if ( !tree->insert(path, h) ) { delete h; return 0; } return h; } /** * LWH cannot create an IHistogram2D by subtracting two IHistogram2D. */ Histogram2D * subtract(const std::string & path, const Histogram2D & h1, const Histogram2D & h2) { if ( !checkBins(h1, h2) ) { //std::cout << "!!!!!!!" << std::endl; return 0; } Histogram2D * h = new Histogram2D(h1); h->setTitle(path.substr(path.rfind('/') + 1)); for ( int ix = 0; ix < h->xax->bins() + 2; ++ix ) for ( int iy = 0; iy < h->yax->bins() + 2; ++iy ) { h->sum[ix][iy] += h2.sum[ix][iy]; h->sumw[ix][iy] -= h2.sumw[ix][iy]; h->sumw2[ix][iy] += h2.sumw2[ix][iy]; h->sumxw[ix][iy] -= h2.sumxw[ix][iy]; h->sumx2w[ix][iy] -= h2.sumx2w[ix][iy]; h->sumyw[ix][iy] -= h2.sumyw[ix][iy]; h->sumy2w[ix][iy] -= h2.sumy2w[ix][iy]; } if ( !tree->insert(path, h) ) { //std::cout << "&&&&&&&" << std::endl; delete h; return 0; } return h; } /** * LWH cannot create an IHistogram2D by subtracting two IHistogram2D. */ IHistogram2D * subtract(const std::string & path, const IHistogram2D & h1, const IHistogram2D & h2) { return subtract(path, dynamic_cast(h1), dynamic_cast(h2)); } /** * LWH cannot create an IHistogram2D by multiplying two IHistogram2D. */ IHistogram2D * multiply(const std::string & path, const IHistogram2D & h1, const IHistogram2D & h2) { return multiply(path, dynamic_cast(h1), dynamic_cast(h2)); } /** * LWH cannot create an IHistogram2D by multiplying two IHistogram2D. */ Histogram2D * multiply(const std::string & path, const Histogram2D & h1, const Histogram2D & h2) { if ( !checkBins(h1, h2) ) return 0; Histogram2D * h = new Histogram2D(h1); h->setTitle(path.substr(path.rfind('/') + 1)); for ( int ix = 0; ix < h->xax->bins() + 2; ++ix ) for ( int iy = 0; iy < h->yax->bins() + 2; ++iy ) { h->sum[ix][iy] *= h2.sum[ix][iy]; h->sumw[ix][iy] *= h2.sumw[ix][iy]; h->sumw2[ix][iy] += h1.sumw[ix][iy]*h1.sumw[ix][iy]*h2.sumw2[ix][iy] + h2.sumw[ix][iy]*h2.sumw[ix][iy]*h1.sumw2[ix][iy]; } if ( !tree->insert(path, h) ) { delete h; return 0; } return h; } /** * LWH cannot create an IHistogram2D by dividing two IHistogram2D. */ Histogram2D * divide(const std::string & path, const Histogram2D & h1, const Histogram2D & h2) { if ( !checkBins(h1,h2) ) return 0; Histogram2D * h = new Histogram2D(h1); h->setTitle(path.substr(path.rfind('/') + 1)); for ( int ix = 0; ix < h->xax->bins() + 2; ++ix ) for ( int iy = 0; iy < h->yax->bins() + 2; ++iy ) { if ( h2.sum[ix][iy] == 0 || h2.sumw[ix][iy] == 0.0 ) { h->sum[ix][iy] = 0; h->sumw[ix][iy] = h->sumw2[ix][iy] = 0.0; continue; } h->sumw[ix][iy] /= h2.sumw[ix][iy]; h->sumw2[ix][iy] = h1.sumw2[ix][iy]/(h2.sumw[ix][iy]*h2.sumw[ix][iy]) + h1.sumw[ix][iy]*h1.sumw[ix][iy]*h2.sumw2[ix][iy]/ (h2.sumw[ix][iy]*h2.sumw[ix][iy]*h2.sumw[ix][iy]*h2.sumw[ix][iy]); } if ( !tree->insert(path, h) ) { delete h; return 0; } return h; } /** * LWH cannot create an IHistogram2D by dividing two IHistogram2D. */ IHistogram2D * divide(const std::string & path, const IHistogram2D & h1, const IHistogram2D & h2) { return divide(path, dynamic_cast(h1), dynamic_cast(h2)); } /** * LWH cannot create an IHistogram3D by adding two IHistogram3D. */ IHistogram3D * add(const std::string &, const IHistogram3D &, const IHistogram3D &) { return error("3D histograms"); } /** * LWH cannot create an IHistogram3D by subtracting two IHistogram3D. */ IHistogram3D * subtract(const std::string &, const IHistogram3D &, const IHistogram3D &) { return error("3D histograms"); } /** * LWH cannot create an IHistogram3D by multiplying two IHistogram3D. */ IHistogram3D * multiply(const std::string &, const IHistogram3D &, const IHistogram3D &) { return error("3D histograms"); } /** * LWH cannot create an IHistogram3D by dividing two IHistogram3D. */ IHistogram3D * divide(const std::string &, const IHistogram3D &, const IHistogram3D &) { return error("3D histograms"); } /** * LWH cannot create an IHistogram1D by projecting an IHistogram2D * along its x axis. */ IHistogram1D * projectionX(const std::string & path, const IHistogram2D & h) { return projectionX(path, dynamic_cast(h)); } /** * LWH cannot create an IHistogram1D by projecting an IHistogram2D * along its x axis. */ Histogram1D * projectionX(const std::string & path, const Histogram2D & h) { return sliceX(path, h, 0, h.yax->bins() - 1); } /** * LWH cannot create an IHistogram1D by projecting an IHistogram2D * along its y axis. */ IHistogram1D * projectionY(const std::string & path, const IHistogram2D & h) { return projectionY(path, dynamic_cast(h)); } /** * LWH cannot create an IHistogram1D by projecting an IHistogram2D * along its y axis. */ Histogram1D * projectionY(const std::string & path, const Histogram2D & h) { return sliceY(path, h, 0, h.xax->bins() - 1); } /** * LWH cannot create an IHistogram1D by slicing an IHistogram2D * parallel to the y axis at a given bin. */ IHistogram1D * sliceX(const std::string & path, const IHistogram2D & h, int i) { return sliceX(path, dynamic_cast(h), i, i); } /** * LWH cannot create an IHistogram1D by slicing an IHistogram2D * parallel to the y axis at a given bin. */ Histogram1D * sliceX(const std::string & path, const Histogram2D & h, int i) { return sliceX(path, h, i, i); } /** * LWH cannot create an IHistogram1D by slicing an IHistogram2D * parallel to the x axis at a given bin. */ IHistogram1D * sliceY(const std::string & path, const IHistogram2D & h, int i) { return sliceY(path, dynamic_cast(h), i, i); } /** * LWH cannot create an IHistogram1D by slicing an IHistogram2D * parallel to the x axis at a given bin. */ Histogram1D * sliceY(const std::string & path, const Histogram2D & h, int i) { return sliceY(path, h, i, i); } /** * LWH cannot create an IHistogram1D by slicing an IHistogram2D * parallel to the y axis between two bins (inclusive). */ IHistogram1D * sliceX(const std::string & path, const IHistogram2D & h, int il, int iu) { return sliceX(path, dynamic_cast(h), il, iu); } /** * LWH cannot create an IHistogram1D by slicing an IHistogram2D * parallel to the y axis between two bins (inclusive). */ Histogram1D * sliceX(const std::string & path, const Histogram2D & h2, int il, int iu) { Histogram1D * h1; if ( h2.xfax ) h1 = new Histogram1D(h2.xfax->bins(), h2.xfax->lowerEdge(), h2.xfax->upperEdge()); else { std::vector edges(h2.xax->bins() + 1); edges.push_back(h2.xax->lowerEdge()); for ( int i = 0; i < h2.xax->bins(); ++i ) edges.push_back(h2.xax->binLowerEdge(i)); h1 = new Histogram1D(edges); } for ( int ix = 0; ix < h2.xax->bins() + 2; ++ix ) for ( int iy = il + 2; iy <= iu + 2; ++iy ) { h1->sum[ix] += h2.sum[ix][iy]; h1->sumw[ix] += h2.sumw[ix][iy]; h1->sumw2[ix] += h2.sumw2[ix][iy]; h1->sumxw[ix] += h2.sumxw[ix][iy]; h1->sumx2w[ix] += h2.sumx2w[ix][iy]; } if ( !tree->insert(path, h1) ) { delete h1; return 0; } return h1; } /** * LWH cannot create an IHistogram1D by slicing an IHistogram2D * parallel to the x axis between two bins (inclusive). */ IHistogram1D * sliceY(const std::string & path, const IHistogram2D & h, int il, int iu) { return sliceY(path, dynamic_cast(h), il, iu); } Histogram1D * sliceY(const std::string & path, const Histogram2D & h2, int il, int iu) { Histogram1D * h1; if ( h2.yfax ) h1 = new Histogram1D(h2.yfax->bins(), h2.yfax->lowerEdge(), h2.yfax->upperEdge()); else { std::vector edges(h2.yax->bins() + 1); edges.push_back(h2.yax->lowerEdge()); for ( int i = 0; i < h2.yax->bins(); ++i ) edges.push_back(h2.yax->binLowerEdge(i)); h1 = new Histogram1D(edges); } for ( int iy = 0; iy < h2.yax->bins() + 2; ++iy ) for ( int ix = il + 2; ix <= iu + 2; ++ix ) { h1->sum[iy] += h2.sum[ix][iy]; h1->sumw[iy] += h2.sumw[ix][iy]; h1->sumw2[iy] += h2.sumw2[ix][iy]; h1->sumxw[iy] += h2.sumyw[ix][iy]; h1->sumx2w[iy] += h2.sumy2w[ix][iy]; } if ( !tree->insert(path, h1) ) { delete h1; return 0; } return h1; } /** * LWH cannot create an IHistogram2D by projecting an IHistogram3D * on the x-y plane. */ IHistogram2D * projectionXY(const std::string &, const IHistogram3D &) { return error("2D histograms"); } /** * LWH cannot create an IHistogram2D by projecting an IHistogram3D * on the x-z plane. */ IHistogram2D * projectionXZ(const std::string &, const IHistogram3D &) { return error("2D histograms"); } /** * LWH cannot create an IHistogram2D by projecting an IHistogram3D * on the y-z plane. */ IHistogram2D * projectionYZ(const std::string &, const IHistogram3D &) { return error("2D histograms"); } /** * LWH cannot create an IHistogram2D by slicing an IHistogram3D * perpendicular to the Z axis, between "index1" and "index2" * (inclusive). */ IHistogram2D * sliceXY(const std::string &, const IHistogram3D &, int, int) { return error("2D histograms"); } /** * LWH cannot create an IHistogram2D by slicing an IHistogram3D * perpendicular to the Y axis, between "index1" and "index2" * (inclusive). */ IHistogram2D * sliceXZ(const std::string &, const IHistogram3D &, int, int) { return error("2D histograms"); } /** * LWH cannot create an IHistogram2D by slicing an IHistogram3D * perpendicular to the X axis, between "index1" and "index2" * (inclusive). */ IHistogram2D * sliceYZ(const std::string &, const IHistogram3D &, int, int) { return error("2D histograms"); } private: /** Throw a suitable error. */ template static T * error(std::string feature) { throw std::runtime_error("LWH cannot handle " + feature + "."); } /** The tree where the actual histograms are stored. */ Tree * tree; }; } #endif /* LWH_HistogramFactory_H */ diff --git a/Analysis/LWH/ManagedObject.h b/Analysis/LWH/ManagedObject.h --- a/Analysis/LWH/ManagedObject.h +++ b/Analysis/LWH/ManagedObject.h @@ -1,48 +1,48 @@ // -*- C++ -*- // // ManagedObject.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef LWH_ManagedObject_H #define LWH_ManagedObject_H // // This is the declaration of the ManagedObject class. // #include "AIManagedObject.h" #include namespace LWH { using namespace AIDA; /** * The creator of trees. */ class ManagedObject: public IManagedObject { public: /// Destructor. virtual ~ManagedObject() {} /** * Write out the object to the given stream in XML format. */ virtual bool writeXML(std::ostream & os, std::string path, std::string name) = 0; /** * Write out the object to the given stream in simple table format. */ virtual bool writeFLAT(std::ostream & os, std::string path, std::string name) = 0; }; } #endif /* LWH_ManagedObject_H */ diff --git a/Analysis/LWH/Measurement.h b/Analysis/LWH/Measurement.h --- a/Analysis/LWH/Measurement.h +++ b/Analysis/LWH/Measurement.h @@ -1,131 +1,131 @@ // -*- C++ -*- // // Measurement.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef LWH_Measurement_H #define LWH_Measurement_H // // This is the declaration of the Measurement class representing // #include #include #include #include "AIMeasurement.h" namespace LWH { using namespace AIDA; /** * Basic user-level interface class for holding a single "measurement" * with positive and negative errors (to allow for asymmetric errors). * "IMeasurement" = "value" + "errorPlus" - "errorMinus" */ class Measurement: public IMeasurement { public: /** * Standard constructor. */ Measurement(double v = 0.0, double ep = 0.0, double em = 0.0) : val(v), errp(ep), errm(em) {} /** * Copy constructor. */ Measurement(const Measurement & m) :IMeasurement(m), val(m.val), errp(m.errp), errm(m.errm) {} /** * Default assignment operator (to avoid compiler warnings). */ Measurement & operator=(const Measurement &) = default; /** * Destructor. */ virtual ~Measurement() { /* nop */; } /** * Get the value of the Measurement. * @return The value of the Measurement. */ double value() const { return val; } /** * Get the plus error of the IMeasurement. * @return The plus error. */ double errorPlus() const { return errp; } /** * Get the minus error of the IMeasurement. * @return The minus error. */ double errorMinus() const { return errm; } /** * Set the value of the IMeasurement. * @param v The new value of the IMeasurement. * @return false If the value cannot be set. */ bool setValue(double v) { val = v; return true; } /** * Set the plus error of the IMeasurement. * @param ep The new plus error of the IMeasurement. * @return false If the error cannot be set or it is negative. */ bool setErrorPlus(double ep) { errp = ep; return ep < 0.0; } /** * Set the minus error of the IMeasurement. * @param em The new minus error of the IMeasurement. * @return false If the error cannot be set or it is negative. */ bool setErrorMinus(double em) { errm = em; return em < 0.0; } private: /** * The value. */ double val; /** * The plus error. */ double errp; /** * The minus error. */ double errm; }; } #endif /* LWH_Measurement_H */ diff --git a/Analysis/LWH/Tree.h b/Analysis/LWH/Tree.h --- a/Analysis/LWH/Tree.h +++ b/Analysis/LWH/Tree.h @@ -1,434 +1,434 @@ // -*- C++ -*- // // Tree.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef LWH_Tree_H #define LWH_Tree_H // // This is the declaration of the Tree class. // #include "AITree.h" #include "ManagedObject.h" #include #include #include #include #include #include namespace LWH { using namespace AIDA; /** * The Tree class is a simple implementation of the AIDA::ITree * interface. */ class Tree: public ITree { public: /** The AnalysisFactory is a friend. */ friend class AnalysisFactory; /** A path is a vector of directory names. */ typedef std::vector Path; /** A set of paths */ typedef std::set PathSet; /** Map of paths to objects. */ typedef std::map ObjMap; public: /** * The standard constructor. */ Tree(std::string storename, bool xml = true) : name(storename), flat(!xml), cwd("/"), overwrite(true) { dirs.insert(Path()); } /** * The default constructor. */ Tree(): name(""), flat(false), cwd("/") { dirs.insert(Path()); } /** * The copy constructor. */ Tree(const Tree & dt) : ITree(dt), name(dt.name), flat(dt.flat), dirs(dt.dirs), objs(dt.objs), cwd(dt.cwd), overwrite(true) {} /// Destructor. virtual ~Tree() { for ( ObjMap::iterator it = objs.begin(); it != objs.end(); ++it ) delete it->second; } /** * Get the name of the store. * @return The store's name. */ std::string storeName() const { return name; } /** * Get the IManagedObject at a given path in the ITree. The path can either be * absolute or relative to the current working directory. * @param path The path. * @return The corresponding IManagedObject. */ IManagedObject * find(const std::string & path) { ObjMap::const_iterator it = objs.find(path); return it == objs.end()? (IManagedObject *)0: it->second; } /** * LWH cannot get a mounted ITree at a given path in the current ITree. * @return 0 always. */ ITree * findTree(const std::string &) { return 0; } /** * Change to a given directory. * @param dir The absolute or relative path of the directory we are * changing to. * @return false If the path does not exist. */ bool cd(const std::string & dir) { PathSet::iterator it = dirs.find(purgepath(str2pth(fullpath(sts(dir))))); if ( it == dirs.end() ) return false; cwd = pth2str(*it); return true; } /** * Insert the ManagedObject \a o in the tree with the path \a str. */ bool insert(std::string str, IManagedObject * o) { Path path = purgepath(str2pth(fullpath(str))); if ( dirs.find(path) == dirs.end() ) { std::string fullname = pth2str(path); path.pop_back(); if ( dirs.find(path) != dirs.end() ) { ObjMap::iterator old = objs.find(fullname); if ( old == objs.end() || overwrite ) { if ( old != objs.end() ) { delete old->second; objs.erase(old); } objs[fullname] = o; return true; } } } return false; } /** * Get the path of the current working directory. * @return The path of the current working directory. */ std::string pwd() const { return cwd; } /** * Not implemented in LWH. * @return false always. * */ bool ls(const std::string & = ".", bool = false, std::ostream & = std::cout) const { return false; } /** * Not implemented in LWH. */ std::vector listObjectNames(const std::string & = ".", bool = false) const { return std::vector(); } /** * Not implemented in LWH. */ std::vector listObjectTypes(const std::string & = ".", bool = false) const { return std::vector(); } /** * Create a new directory. Given a path only the last directory * in it is created if all the intermediate subdirectories already exist. * @param dir The absolute or relative path of the new directory. * @return false If a subdirectory within the path does * not exist or it is not a directory. Also if the directory already exists. */ bool mkdir(const std::string & dir) { Path p = purgepath(str2pth(fullpath(sts(dir)))); Path base = p; base.pop_back(); if ( dirs.find(base) == dirs.end() ) return false; dirs.insert(p); return true; } /** * Create a directory recursively. Given a path the last directory * and all the intermediate non-existing subdirectories are created. * @param dir The absolute or relative path of the new directory. * @return false If an intermediate subdirectory * is not a directory, or if the directory already exists. */ bool mkdirs(const std::string & dir) { return mkdirs(purgepath(str2pth(fullpath(sts(dir))))); } /** * Create a directory recursively. Given a Path the last directory * and all the intermediate non-existing subdirectories are created. * @param p The full Path of the new directory. * @return false If an intermediate subdirectory * is not a directory, or if the directory already exists. */ bool mkdirs(Path p) { if ( dirs.find(p) != dirs.end() ) return true; dirs.insert(p); p.pop_back(); return mkdirs(p); } /** * Remove a directory and all the contents underneeth. * @param dir The absolute or relative path of the directory to be removed. * @return false If path does not exist or if it is not * a directory or if the directory is not empty. */ bool rmdir(const std::string & dir) { Path path = purgepath(str2pth(fullpath(sts(dir)))); if ( dirs.find(path) == dirs.end() ) return false; for ( ObjMap::const_iterator it = objs.begin(); it != objs.end(); ++it ) if ( it->first.substr(0, dir.length()) == dir ) return false; dirs.erase(path); return true; } /** * Remove and delete an IManagedObject by specifying its path. * @param path The absolute or relative path of the IManagedObject to be * removed. * @return false If path does not exist. */ bool rm(const std::string & path) { ObjMap::iterator it = objs.find(fullpath(path)); if ( it == objs.end() ) return false; delete it->second; objs.erase(it); return true; } /** * Get the full path of an IManagedObject. * @param o The IManagedObject whose path is to be returned. * @return The object's absolute path. * If the object does not exist, an empty string is returned. */ std::string findPath(const IManagedObject & o) const { for ( ObjMap::const_iterator it = objs.begin(); it != objs.end(); ++it ) if ( it->second == &o ) return it->first; return ""; } /** * Move an IManagedObject or a directory from one directory to another. * @param oldp The path of the IManagedObject [not direcoty] to be moved. * @param newp The path of the diretory in which the object has to be * moved to. * @return false If either path does not exist. */ bool mv(const std::string & oldp, const std::string & newp) { Path newpath = purgepath(str2pth(fullpath(sts(newp)))); std::string foldp = fullpath(oldp); Path oldpath = purgepath(str2pth(foldp)); ObjMap::iterator it = objs.find(foldp); if ( it == objs.end() ) return false; if ( dirs.find(newpath) != dirs.end() ) return false; newpath.push_back(oldpath.back()); if ( !insert(pth2str(newpath), it->second) ) return false; objs.erase(foldp); return true; } /** * Print all histograms to the current filename. * @return false if something went wrong. */ bool commit() { std::ofstream of(name.c_str()); if ( !of ) return false; if ( !flat ) of << "\n\n" << "\n" << "" << std::endl; for ( ObjMap::const_iterator it = objs.begin(); it != objs.end(); ++it ) { ManagedObject * o = dynamic_cast(it->second); if ( !o ) continue; std::string path = it->first.substr(0, it->first.rfind('/')); std::string name = it->first.substr(it->first.rfind('/') + 1); if ( flat ) o->writeFLAT(of, path, name); else o->writeXML(of, path, name); } if ( !flat ) of << "" << std::endl; return of.good(); } /** * Not implemented in LWH. */ void setOverwrite(bool o = true) { overwrite = o; } /** * Not implemented in LWH. * @return false always. */ bool cp(const std::string &, const std::string &, bool = false) { return false; } /** * Not implemented in LWH. * @return false always. */ bool symlink(const std::string &, const std::string &) { return false; } /** * Not implemented in LWH. * @return false always. */ bool mount(const std::string &, ITree &, const std::string &) { return false; } /** * Not implemented in LWH. * @return false always. */ bool unmount(const std::string &) { return false; } /** * Calls commit(). */ bool close() { return commit(); } /** * Not implemented in LWH. * @return null pointer always. */ void * cast(const std::string &) const { return 0; } protected: /** Strip trailing slash. */ std::string sts(std::string s) const { if ( s[s.length() - 1] == '/' ) s = s.substr(0, s.length() - 1); if ( s[s.length() - 1] == '/' ) return ""; return s; } /** Strip trailing name */ std::string stn(std::string s) const { std::string::size_type slash = s.rfind('/'); return s.substr(0, slash); } /** Get proper full path from possibly relative path. */ std::string fullpath(std::string d) const { if ( d[0] != '/' ) d = cwd + "/" + d; return pth2str(purgepath(str2pth(d))); } /** Convert a string containing a path to a Path object. */ Path str2pth(std::string s) const { Path pth; std::string::size_type i = s.find_first_not_of("/"); while ( i != std::string::npos ) { s = s.substr(i); i = s.find_first_of("/"); pth.push_back(s.substr(0, i)); if ( i == std::string::npos ) return pth; s = s.substr(i); i = s.find_first_not_of("/"); } return pth; } /** Convert a Path object to a corresponding string. */ std::string pth2str(const Path & pth) const { std::string str; for ( int i = 0, N = pth.size(); i < N; ++i ) str += "/" + pth[i]; return str; } /** Remove '..' and '.' components of the given Path object. */ Path purgepath(const Path & pth) const { Path p; for ( int i = 0, N = pth.size(); i < N; ++i ) { if ( pth[i] == ".." ) p.pop_back(); else if ( pth[i] != "." ) p.push_back(pth[i]); } return p; } private: /** The filename to print histograms to. */ std::string name; /** If true write histograms in FLAT format, otherwise in XML. */ bool flat; /** The set of defined directories. */ PathSet dirs; /** The set of defined objects. */ ObjMap objs; /** The current working directory. */ std::string cwd; /** Overwrite strategy. */ bool overwrite; }; } #endif /* LWH_Tree_H */ diff --git a/Analysis/LWH/TreeFactory.h b/Analysis/LWH/TreeFactory.h --- a/Analysis/LWH/TreeFactory.h +++ b/Analysis/LWH/TreeFactory.h @@ -1,95 +1,95 @@ // -*- C++ -*- // // TreeFactory.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef LWH_TreeFactory_H #define LWH_TreeFactory_H // // This is the declaration of the TreeFactory class. // #include "AITreeFactory.h" #include #include #include "Tree.h" namespace LWH { using namespace AIDA; /** * The creator of trees. */ class TreeFactory: public ITreeFactory { public: /// Destructor. virtual ~TreeFactory() { clear(); } /** * Creates a new tree that is not associated with a store. */ ITree * create() { Tree * tree = new Tree; trees.insert(tree); return tree; } /** * Creates a new Tree and associates it with a store. * The store is assumed to be write-only. * The store will be created. * @param storeName The name of the store, if empty (""), the tree is * created in memory and therefore will not be associated * with a file. */ Tree * createTree(const std::string & storeName) { return new Tree(storeName); } /** * Creates a new Tree and associates it with a store. * The store is assumed to be write-only. * The store will be created. * @param storeName The name of the store, if empty (""), the tree is * created in memory and therefore will not be associated * with a file. * @param storeType must be "xml". * @param readOnly must be false since we cannot read in trees. * @param createNew must be true indicating that the file will be created */ ITree * create(const std::string & storeName, const std::string & storeType = "", bool readOnly = false, bool createNew = false, const std::string & = "") { if ( storeType != "xml" && storeType != "" && storeType != "flat" ) throw std::runtime_error("Can only store trees in xml or flat format."); if ( readOnly || !createNew ) throw std::runtime_error("Cannot read in trees."); return new Tree(storeName, storeType != "flat"); } private: /** Delete all trees. */ void clear() { for ( std::set::iterator it = trees.begin(); it != trees.end(); ++it ) delete *it; trees.clear(); } /** The created trees. */ std::set trees; }; } #endif /* LWH_TreeFactory_H */ diff --git a/Analysis/LWH/VariAxis.h b/Analysis/LWH/VariAxis.h --- a/Analysis/LWH/VariAxis.h +++ b/Analysis/LWH/VariAxis.h @@ -1,183 +1,183 @@ // -*- C++ -*- // // VariAxis.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef LWH_VariAxis_H #define LWH_VariAxis_H // // This is the declaration of the VariAxis class representing // #include #include #include #include #include "AIAxis.h" namespace LWH { using namespace AIDA; /** * An VariAxis represents a binned histogram axis. A 1D Histogram would have * one VariAxis representing the X axis, while a 2D Histogram would have two * axes representing the X and Y VariAxis. */ class VariAxis: public IAxis { public: /** * Standard constructor. */ VariAxis(const std::vector & edges) { for ( int i = 0, N = edges.size(); i < N; ++i ) binco[edges[i]] = 0; std::map::iterator it = binco.begin(); for ( int i = 0, N = edges.size(); i < N; ++i ) (it++)->second = i; } /** * Copy constructor. */ VariAxis(const VariAxis & a) : IAxis(a), binco(a.binco) {} /// Destructor. virtual ~VariAxis() { } /** * Check if the IAxis has fixed binning, i.e. if all the bins have * the same width. @return true if the binning is * fixed, false otherwise. * */ bool isFixedBinning() const {return false; } /** * Get the lower edge of the IAxis. * @return The IAxis's lower edge. * */ double lowerEdge() const { if ( binco.size() ) return binco.begin()->first; return 0; } /** * Get the upper edge of the IAxis. * @return The IAxis's upper edge. * */ double upperEdge() const { if ( !binco.size() ) return 0; std::map::const_iterator last = binco.end(); return (--last)->first; } /** * The number of bins (excluding underflow and overflow) on the IAxis. * @return The IAxis's number of bins. * */ int bins() const { return binco.size() - 1; } /** * Get the lower edge of the specified bin. * @param index The bin number: 0 to bins()-1 for the in-range bins * or OVERFLOW or UNDERFLOW. * @return The lower edge of the corresponding bin; for the * underflow bin this is Double.NEGATIVE_INFINITY. * */ std::pair binEdges(int index) const { std::pair edges(0.0, 0.0); if ( !binco.size() ) return edges; std::map::const_iterator lo = binco.end(); std::map::const_iterator up = binco.begin(); if ( index >= 0 ) while ( index-- >= 0 && up != binco.end() ) lo = up++; edges.first = ( lo == binco.end() )? -std::numeric_limits::max(): lo->first; edges.second = ( up == binco.end() )? std::numeric_limits::max(): up->first; return edges; } /** * Get the lower edge of the specified bin. * @param index The bin number: 0 to bins()-1 for the in-range bins * or OVERFLOW or UNDERFLOW. * @return The lower edge of the corresponding bin; for the * underflow bin this is Double.NEGATIVE_INFINITY. * */ double binLowerEdge(int index) const { return binEdges(index).first; } /** * Get the upper edge of the specified bin. * @param index The bin number: 0 to bins()-1 for the in-range bins * or OVERFLOW or UNDERFLOW. * @return The upper edge of the corresponding bin; for the overflow * bin this is Double.POSITIVE_INFINITY. * */ double binUpperEdge(int index) const { return binEdges(index).second; } /** * Get the width of the specified bin. * @param index The bin number: 0 to bins()-1) for the in-range bins * or OVERFLOW or UNDERFLOW. * @return The width of the corresponding bin. * */ double binWidth(int index) const { std::pair edges = binEdges(index); return edges.second - edges.first; } /** * Convert a coordinate on the axis to a bin number. If the * coordinate is less than the lowerEdge UNDERFLOW is returned; if * the coordinate is greater or equal to the upperEdge OVERFLOW is * returned. * @param coord The coordinate to be converted. * @return The corresponding bin number. * */ int coordToIndex(double coord) const { std::map::const_iterator up = binco.upper_bound(coord); if ( up == binco.begin() ) return UNDERFLOW_BIN; else if ( up == binco.end() ) return OVERFLOW_BIN; else return up->second - 1; } /** * Return the midpoint of the specified bin. No checking is * performed to ensure the argument is a valid bin. */ double binMidPoint(int index) const { std::pair edges = binEdges(index); return (edges.second + edges.first)/2.0; } private: /** * A map relating the lower edge of a bin to the corresponding bin * number. */ std::map binco; }; } #endif /* LWH_VariAxis_H */ diff --git a/Analysis/LWHFactory.cc b/Analysis/LWHFactory.cc --- a/Analysis/LWHFactory.cc +++ b/Analysis/LWHFactory.cc @@ -1,86 +1,86 @@ // -*- C++ -*- // // LWHFactory.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the LWHFactory class. // #include "LWHFactory.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Repository/EventGenerator.h" #ifndef LWH #define LWH ThePEGLWH #endif #include "AnalysisFactory.h" using namespace ThePEG; void LWHFactory::doinitrun() { analysisFactory(new LWH::AnalysisFactory); FactoryBase::doinitrun(); } void LWHFactory::normalizeToXSec(tH1DPtr histogram, CrossSection unit) const { LWH::Histogram1D * h = dynamic_cast(histogram); if ( h ) h->normalize(h->sumAllBinHeights()*generator()->integratedXSec()/ (generator()->sumWeights()*unit)); } void LWHFactory::normalizeToXSecFraction(tH1DPtr histogram) const { LWH::Histogram1D * h = dynamic_cast(histogram); if ( h ) h->normalize(h->sumAllBinHeights()/generator()->sumWeights()); } void LWHFactory::normalizeToUnity(tH1DPtr histogram) const { LWH::Histogram1D * h = dynamic_cast(histogram); if ( h ) h->normalize(1.0); } void LWHFactory::normalizeToXSec(tH2DPtr histogram, CrossSection unit) const { LWH::Histogram2D * h = dynamic_cast(histogram); if ( h ) h->normalize(h->sumAllBinHeights()*generator()->integratedXSec()/ (generator()->sumWeights()*unit)); } void LWHFactory::normalizeToXSecFraction(tH2DPtr histogram) const { LWH::Histogram2D * h = dynamic_cast(histogram); if ( h ) h->normalize(h->sumAllBinHeights()/generator()->sumWeights()); } void LWHFactory::normalizeToUnity(tH2DPtr histogram) const { LWH::Histogram2D * h = dynamic_cast(histogram); if ( h ) h->normalize(1.0); } void LWHFactory::persistentOutput(PersistentOStream &) const {} void LWHFactory::persistentInput(PersistentIStream &, int) {} ClassDescription LWHFactory::initLWHFactory; // Definition of the static class description member. void LWHFactory::Init() { static ClassDocumentation documentation ("This class represents the Light-Weight Histogram package which " "implements the most rudimentary histogramming facilities according " "to the AIDA interface " "specifications. Currently the only thing that is supported is " "simple, equally binned, one dimensional histograms. If you are " "using AnalysisHandlers which accesses other features in the AIDA " "interface you may end up with an ungraceful crash."); } diff --git a/Analysis/LWHFactory.h b/Analysis/LWHFactory.h --- a/Analysis/LWHFactory.h +++ b/Analysis/LWHFactory.h @@ -1,192 +1,192 @@ // -*- C++ -*- // // LWHFactory.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_LWHFactory_H #define THEPEG_LWHFactory_H // // This is the declaration of the LWHFactory class. // #include "ThePEG/Analysis/FactoryBase.h" namespace ThePEG { /** * Here is the documentation of the LWHFactory class. It inherits from * the abstract FactoryBase class and implements the Light-Weight * Histogram package, LWH. This implements the most rudimentary * histogramming facilities according to the AIDA interface * specifications. Currently the only thing that is supported is * simple, equally binned, one dimensional histograms. It is mainly * intended to be used in applications where one needs to fill simple * histograms and output them. With LWH it is then possible to do this * without the overhead of a full AIDA implementation, but still * having the option to use a full implementation later on with * minimal changes. * * @see \ref LWHFactoryInterfaces "The interfaces" * defined for LWHFactory. */ class LWHFactory: public FactoryBase { public: /** @name Manipulate histograms */ //@{ /** * Rescale the given \a histogram so that the integral over the bins * will give the correct integrated cross section for the observable * in the given \a unit. */ virtual void normalizeToXSec(tH1DPtr histogram, CrossSection unit = picobarn) const; /** * Rescale the given \a histogram so that the integral over the bins * gives the fraction of the total cross section generated which is * contained in the bins. */ virtual void normalizeToXSecFraction(tH1DPtr histogram) const; /** * Rescale the given \a histogram so that the integral over the bins * gives one. */ virtual void normalizeToUnity(tH1DPtr histogram) const; /** * Rescale the given \a histogram so that the integral over the bins * will give the correct integrated cross section for the observable * in the given \a unit. */ virtual void normalizeToXSec(tH2DPtr histogram, CrossSection unit = picobarn) const; /** * Rescale the given \a histogram so that the integral over the bins * gives the fraction of the total cross section generated which is * contained in the bins. */ virtual void normalizeToXSecFraction(tH2DPtr histogram) const; /** * Rescale the given \a histogram so that the integral over the bins * gives one. */ virtual void normalizeToUnity(tH2DPtr histogram) const; //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const { return new_ptr(*this); } /** 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 { return new_ptr(*this); } //@} protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); //@} private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initLWHFactory; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ LWHFactory & operator=(const LWHFactory &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of LWHFactory. */ template <> struct BaseClassTrait { /** Typedef of the first base class of LWHFactory. */ typedef FactoryBase NthBase; }; /** This template specialization informs ThePEG about the name of * the LWHFactory 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::LWHFactory"; } /** Return the name of the shared library be loaded to get access to * the LWHFactory class and every other class it uses * (except the base class). */ static string library() { return "LWHFactory.so"; } }; /** @endcond */ } #endif /* THEPEG_LWHFactory_H */ diff --git a/Config/Complex.h b/Config/Complex.h --- a/Config/Complex.h +++ b/Config/Complex.h @@ -1,28 +1,28 @@ // -*- C++ -*- // // Complex.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_Complex_H #define ThePEG_Complex_H // // This is file wraps the standard complex header and makes some // convenient typedefs in the ThePEG namespace. // #include namespace ThePEG { using std::complex; /// ThePEG code should use Complex for all complex scalars using Complex = std::complex; } #endif /* ThePEG_Complex_H */ diff --git a/Config/Constants.h b/Config/Constants.h --- a/Config/Constants.h +++ b/Config/Constants.h @@ -1,86 +1,86 @@ // -*- C++ -*- // // Constants.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_Constants_H #define ThePEG_Constants_H // This file defines a number of useful constants, placed in the // namespace ThePEG::Constants. #include "Unitsystem.h" #include #include namespace ThePEG { /** * The Constants namespace containing some useful physical constants * with suitable units. */ namespace Constants { using namespace ThePEG::Units; /** A really large length. */ constexpr Length MaxLength = 1.0e23_mm; /** A really large energy. */ constexpr Energy MaxEnergy = 1.0e6_GeV; /** A really large squared energy. */ constexpr Energy2 MaxEnergy2 = MaxEnergy * MaxEnergy; /** The largest possible double. */ constexpr double MaxDouble = DBL_MAX; /** A really large double. */ constexpr double HugeDouble = DBL_MAX * 1.0e-4; /** The largest possible float. */ constexpr double MaxFloat = FLT_MAX; /** A really large floa.t */ constexpr double HugeFloat = FLT_MAX * 0.01; /** A really large rapidity */ constexpr double MaxRapidity = 100.0; /** Good old \f$\pi\f$. */ constexpr double pi = M_PI; /** Good old \f$2\pi\f$. */ constexpr double twopi = 2.0 * pi; /** A really large integer */ constexpr long MaxInt = 1000000000L; /** The smallest non-zero double. */ constexpr double epsilon = DBL_EPSILON; /** The Euler gamma */ constexpr double EulerGamma = 0.5772156649015329; /** \f$\zeta(2)\f$. */ constexpr double zeta2 = pi*pi/6.; /** \f$\zeta(3)\f$. */ constexpr double zeta3 = 1.2020569031595943; /** \f$\zeta(4)\f$. */ constexpr double zeta4 = 0.4*zeta2*zeta2; /** \f$\zeta(5)\f$. */ constexpr double zeta5 = 1.0369277551433699; /** \f$\zeta(6)\f$. */ constexpr double zeta6 = 4.*zeta2*zeta4/7.; } } #endif /* ThePEG_Constants_H */ diff --git a/Config/Containers.h b/Config/Containers.h --- a/Config/Containers.h +++ b/Config/Containers.h @@ -1,368 +1,368 @@ // -*- C++ -*- // // Containers.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_Containers_H #define ThePEG_Containers_H /** \file * This file defines a number of containers. Some are just typedefs of * std containers, while others are wrappers around * std containers introduced in the hope of reducing the * amount of debugging and code duplication. * * Do not make changes in this file. If you need to modify any of the * standard containers used 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 "ThePEG/Utilities/UnitIO.h" namespace ThePEG { /** A set of pointers to ParticleData objects. */ ThePEG_DECLARE_SET(PDPtr,ParticleDataSet); /** A vector of pointers to ParticleData objects. */ typedef vector PDVector; /** A vector of pointers to const ParticleData objects. */ typedef vector cPDVector; /** A vector of transient pointers to ParticleData objects. */ typedef vector tPDVector; /** A vector of transient pointers to const ParticleData objects. */ typedef vector tcPDVector; /** A set of pointers to MatcherBase objects. */ ThePEG_DECLARE_SET(PMPtr,MatcherSet); /** A set of pointers to DecayMode objects */ ThePEG_DECLARE_SET(DMPtr,DecayModeSet); /** A set of pointers to InterfacedBase objects */ ThePEG_DECLARE_SET(IBPtr,ObjectSet); /** A set of pointers to InterfacedBase objects */ ThePEG_DECLARE_SET(IBPtr,DependencySet); /** A map relating integers to ParticleData objects */ ThePEG_DECLARE_MAP(long,PDPtr,ParticleMap); /** A map relating character strings to InterfacedBase objects */ ThePEG_DECLARE_MAP(string,IBPtr,ObjectMap); /** A map relating InterfacedBase objects to corresponding * DependencySet containers */ ThePEG_DECLARE_MAP(IBPtr,DependencySet,DependencyMap); /** A vector of pointers to InterfacedBase objects. */ typedef vector IVector; /** A vector of pointers to const InterfacedBase objects. */ typedef vector CIVector; /** A vector of pointers to Particle objects. */ typedef vector ParticleVector; /** A vector of pointers to Particle objects. */ typedef vector PVector; /** A vector of pointers to const Particle objects. */ typedef vector cPVector; /** A vector of transient pointers to Particle objects. */ typedef vector tPVector; /** A vector of transient pointers to const Particle objects. */ typedef vector tcPVector; /** A list of pointers to Particle objects. */ typedef list ParticleList; /** A list of pointers to Particle objects. */ typedef list PList; /** A list of pointers to const Particle objects. */ typedef list cPList; /** A list of transient pointers to Particle objects. */ typedef list tPList; /** A list of transient pointers to const Particle objects. */ typedef list tcPList; /** A map relating character strings to bare pointers to InterfaceBase objects */ ThePEG_DECLARE_MAP(string,const InterfaceBase *,InterfaceMap); /** A rebinder for InterfacedBase objects. */ typedef Rebinder TranslationMap; /** A map relating character strings to EventGenerator objects */ ThePEG_DECLARE_MAP(string,EGPtr,GeneratorMap); /** A vector of pointers to AnalysisHandler objects. */ typedef vector AnalysisVector; /** A pair of pointers to ParticleData objects. */ typedef pair PDPair; /** A pair of pointers to const ParticleData objects. */ typedef pair cPDPair; /** A pair of transient pointers to ParticleData objects. */ typedef pair tPDPair; /** A pair of transient pointers to const ParticleData objects. */ typedef pair tcPDPair; /** A pair of pointers to Particle objects. */ typedef pair PPair; /** A pair of pointers to const Particle objects. */ typedef pair cPPair; /** A pair of transient pointers to const Particle objects. */ typedef pair tPPair; /** A pair of transient pointers to const Particle objects. */ typedef pair tcPPair; /** An Interval in scale. */ typedef Interval SInterval; /** A vector of intervals of scales. */ typedef vector SIntervalVector; /** A vector of pairs of transient pointers to PartonBins. */ typedef vector tPartonPairVec; /** A pair of transient pointers to ColourLine objects. */ typedef pair tColinePair; /** A set of pointers to DecayMode objects. */ ThePEG_DECLARE_SET(tDMPtr,DecaySet); /** A set oc character strings. */ ThePEG_DECLARE_SET(string,StringSet); /** A vector of energies. */ typedef vector EnergyVector; /** A vector of pointers to EventInfoBase objects. */ typedef vector EIVector; /** A vector of doubles. */ typedef vector DVector; /** A pair of doubles. */ typedef pair DPair; /** @name Global shift operators to simplify adding and removing * objects to containers. */ //@{ /** * Overload the left shift operator for vector to push_back objects to * a vector. * @param tv the vector being filled by push_back. * @param u the object being pushed back. * @return a referens to the vector. */ template vector & operator<<(vector & tv, const U & u) { tv.push_back(u); return tv; } /** * Overload the right shift operator for vector to pop objects from * a vector. * @param tv the vector being popped by pop_back. * @param u the object at the back of the vector before popping. * @return a referens to the vector. */ template vector & operator>>(vector & tv, U & u) { u = tv.back(); tv.pop_back(); return tv; } /** * Overload the left shift operator for stack to push objects to * a vector. * @param ts the stack being filled by push. * @param u the object being pushed. * @return a referens to the stack. */ template stack & operator<<(stack & ts, const U & u) { ts.push(u); return ts; } /** * Overload the right shift operator for stack to pop objects from * a stack. * @param ts the stack being popped. * @param u the object at the top of the stack before popping. * @return a referens to the stack. */ template stack & operator>>(stack & ts, U & u) { u = ts.top(); ts.pop(); return ts; } /** * Overload the left shift operator for deque to push_back objects to * a deque. * @param td the deque being filled by push_back. * @param u the object being pushed back. * @return a referens to the deque. */ template deque & operator<<(deque & td, const U & u) { td.push_back(u); return td; } /** * Overload the right shift operator for vector to pop objects from * a deque. * @param td the deque being popped by pop_front. * @param u the object at the front of the deque before popping. * @return a referens to the deque. */ template deque & operator>>(deque & td, U & u) { u = td.front(); td.pop_front(); return td; } /** * Overload the left shift operator for std::set to insert objects in * a set. * @param ts the set being filled by insert. * @param u the object being inserted. * @return a referens to the set. */ template set & operator<<(set & ts, const U & u) { ts.insert(u); return ts; } //@} /** @name Functions for I/O of containers of objects with unit. */ //@{ /** * Ouput a vector of objects with the specified unit. * @param os the stream used for output. * @param v the vector to be output. * @param u the unit to be used. */ template void ounitstream(OStream & os, const vector & v, UT & u) { os << v.size(); for ( typename vector::const_iterator i = v.begin(); i != v.end(); ++i ) os << ounit(*i, u); } /** * Input a vector of objects with the specified unit. * @param is the stream used for input. * @param v the vector to be input. * @param u the unit to be used. */ template void iunitstream(IStream & is, vector & v, UT & u) { typename vector::size_type l; is >> l; v.resize(l); for ( typename vector::iterator i = v.begin(); i != v.end(); ++i ) is >> iunit(*i, u); } /** * Ouput a set of objects with the specified unit. * @param os the stream used for output. * @param s the set to be output. * @param u the unit to be used. */ template void ounitstream(OStream & os, const set & s, UT & u) { os << s.size(); for ( typename set::const_iterator i = s.begin(); i != s.end(); ++i ) os << ounit(*i, u); } /** * Input a set of objects with the specified unit. * @param is the stream used for input. * @param s the set to be input. * @param u the unit to be used. */ template void iunitstream(IStream & is, set & s, UT & u) { s.clear(); typename set::size_type l; is >> l; T t; while ( l-- ) { is >> iunit(t, u); s.insert(t); } } /** * Ouput a map of keys and objects where the objects are output with * the specified unit. * @param os the stream used for output. * @param m the map to be output. * @param u the unit to be used for the mapped objects. */ template void ounitstream(OStream & os, const map & m, UT & u) { os << m.size(); for ( typename map::const_iterator i = m.begin(); i != m.end(); ++i ) os << i->first << ounit(i->second, u); } /** * Input a map of keys and objects where the objects are input with * the specified unit. * @param is the stream used for input. * @param m the map to be input. * @param u the unit to be used for the mapped objects. */ template void iunitstream(IStream & is, map & m, UT & u) { m.clear(); typename map::size_type l; is >> l; T t; K k; while ( l-- ) { is >> k >> iunit(t, u); m[k] = t; } } //@} } #endif /* ThePEG_Containers_H */ diff --git a/Config/HepMCHelper.h b/Config/HepMCHelper.h --- a/Config/HepMCHelper.h +++ b/Config/HepMCHelper.h @@ -1,180 +1,180 @@ // -*- C++ -*- // // HepMCHelper_HepMC.h is a part of ThePEG - A multi-purpose Monte Carlo event generator -// Copyright (C) 2002-2017 The Herwig Collaboration +// Copyright (C) 2002-2019 The Herwig Collaboration // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is a helper header to implement HepMC conversions // #include "ThePEG/Vectors/HepMCTraits.h" #ifdef HAVE_HEPMC3 #include "HepMC3/GenEvent.h" #include "HepMC3/GenVertex.h" #include "HepMC3/GenParticle.h" #include "HepMC3/Version.h" #include "HepMC3/WriterAscii.h" #include "HepMC3/WriterHEPEVT.h" #include "HepMC3/WriterAsciiHepMC2.h" #ifdef HAVE_HEPMC3_WRITERROOT_H #include "HepMC3/WriterRoot.h" #endif #ifdef HAVE_HEPMC3_WRITERROOTTREE_H #include "HepMC3/WriterRootTree.h" #endif namespace HepMC3 { using PdfInfo=GenPdfInfo; using Polarization=std::pair; } namespace HepMC=HepMC3; #else #include "HepMC/GenEvent.h" #include "HepMC/GenVertex.h" #include "HepMC/GenParticle.h" #include "HepMC/Version.h" #include "HepMC/IO_BaseClass.h" #include "HepMC/IO_GenEvent.h" #include "HepMC/IO_AsciiParticles.h" namespace HepMC { #undef GenParticlePtr #undef GenVertexPtr typedef GenParticle * GenParticlePtr; typedef GenVertex * GenVertexPtr; } #endif namespace ThePEG { /** * Struct for HepMC conversion */ #ifndef HAVE_HEPMC3 template<> struct HepMCTraits : public HepMCTraitsBase { #else // This is version 3! template<> struct HepMCTraits : public HepMCTraitsBase { /** 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(HepMC::Units::GEV, HepMC::Units::MM); e->set_event_number(evno); e->set_event_number(evno); //std::vector wnames; std::vector wvalues; //wnames.push_back("Default"); wvalues.push_back(weight); for ( map::const_iterator w = optionalWeights.begin(); w != optionalWeights.end(); ++w ) { //wnames.push_back(w->first); wvalues.push_back(w->second); } //e->run_info()->set_weight_names(wnames); e->weights()=wvalues; return e; } /** Create a new vertex. */ static VertexPtrT newVertex() { return std::make_shared(VertexT()); } /** 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.add_attribute("event_scale",std::make_shared(sqrt(scale)/unit)); e.add_attribute("mpi",std::make_shared(-1));//Please fix it later, once ThePEG authors respond e.add_attribute("signal_process_id",std::make_shared(0));//Please fix it later, once ThePEG authors respond e.add_attribute("alphaQCD",std::make_shared(aS)); e.add_attribute("alphaQED",std::make_shared(aEM)); } /** 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.add_attribute("flow"+std::to_string(indx),std::make_shared(coline)); } /** Add an incoming particle, \a p, to the vertex, \a v. */ static void addIncoming(VertexT & v, ParticlePtrT p) { v.add_particle_in(p); } /** Add an outgoing particle, \a p, to the vertex, \a v. */ static void addOutgoing(VertexT & v, ParticlePtrT p) { v.add_particle_out(p); } /** Set the primary vertex, \a v, for the event \a e. */ static void setSignalProcessVertex(EventT & e, VertexPtrT v) { e.add_vertex(v); e.add_attribute("signal_process_vertex", std::make_shared(v->id())); } /** Set a vertex, \a v, for the event \a e. */ static void addVertex(EventT & e, VertexPtrT v) { e.add_vertex(v); } /** Set the beam particles for the event.*/ static void setBeamParticles(EventT & e, ParticlePtrT p1, ParticlePtrT p2) { // e.set_beam_particles(p1,p2); p1->set_status(4); p2->set_status(4); e.set_beam_particles(p1, p2); } /** 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 ParticlePtrT 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). HepMC::FourVector p_scalar(p.x()/unit, p.y()/unit, p.z()/unit, p.e()/unit); ParticlePtrT genp = std::make_shared(ParticleT(p_scalar, id, status)); genp->set_generated_mass(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.add_attribute("theta",std::make_shared(the)); genp.add_attribute("phi",std::make_shared(phi)); } /** 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) { HepMC::FourVector v_scaled(p.x()/unit, p.y()/unit, p.z()/unit, p.e()/unit); v.set_position(v_scaled); } #endif }; } diff --git a/Config/PhysicalQty.h b/Config/PhysicalQty.h --- a/Config/PhysicalQty.h +++ b/Config/PhysicalQty.h @@ -1,321 +1,321 @@ // -*- C++ -*- // // PhysicalQty.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2006-2017 David Grellscheid, Leif Lonnblad +// Copyright (C) 2006-2019 David Grellscheid, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Physical_Qty_H #define Physical_Qty_H #include "TemplateTools.h" #include #include #include /** @file * * The PhysicalQty class allows compile-time checking of dimensional * correctness. Mathematical operations that are inconsistent are * flagged as type errors. * * Do not use the classes directly in ThePEG, use the wrappers defined * in Units.h or Phys_Qty.h instead. */ namespace ThePEG { /// Helper class to construct zero unitful quantities. struct ZeroUnit { /** Automatic conversion to double. */ constexpr operator double() const { return 0.0; } }; /// ZERO can be used as zero for any unitful quantity. constexpr ZeroUnit ZERO = ZeroUnit(); /** * This template class allows the compiler to check calculations with * physical quantities for dimensional correctness. A quantity can be * composed of arbitrary fractional powers of length L, energy E and * charge Q. Commonly used quantities should be typedef'ed (see Units.h). * * Some member functions can break dimensional consistency if the user * is not careful; these are marked explicitly. * * Do not use this class directly in ThePEG, use the pre-defined quantities * from Units.h or the wrapper in Phys_Qty.h instead. */ // only specialization is with std::ratio below template class Qty; template struct qty_equal { static constexpr bool value = false; }; template struct qty_equal, Qty> { static constexpr bool value = std::ratio_equal::value && std::ratio_equal::value && std::ratio_equal::value; }; template struct is_qty { static constexpr bool value = qty_equal::value; }; template using enable_if_same_qty = typename std::enable_if::value, ResultT>::type; template class Qty, std::ratio, std::ratio> { private: /// Constructor from raw values. Breaks consistency. constexpr Qty(double val) : rawValue_(val) {} public: /// The name of the class for persistent IO static std::string className() { std::ostringstream os; os << "Qty<" << L << ',' << E << ',' << Q << ',' << DL << ',' << DE << ',' << DQ << '>'; return os.str(); } /// General power type template using Power = Qty::type, typename std::ratio::type, typename std::ratio::type>; /// Our type using Type = Power<1,1>; /// The squared type. using Squared = Power<2,1>; /// The inverse type. using Inverse = Power<-1,1>; /// The sqrt type. using Sqrt = Power<1,2>; /// Basic unit of this quantity. static constexpr Type baseunit() { return Type(1.0); } /// Default constructor to 0. constexpr Qty() : rawValue_(0.0) {} /// Default constructor to 0. constexpr Qty(ZeroUnit) : rawValue_(0.0) {} /// Constructor from a compatible quantity template constexpr Qty(const U & q, double factor = 1.0, enable_if_same_qty * = nullptr) : rawValue_(q.rawValue() * factor) {} /// Access to the raw value. Breaks consistency. constexpr double rawValue() const { return rawValue_; } /// Assignment multiplication by dimensionless number. Type & operator*=(double x) { rawValue_ *= x; return *this; } /// Assignment division by dimensionless number. Type & operator/=(double x) { rawValue_ /= x; return *this; } /// Assignment addition with compatible quantity. Type & operator+=(const Type & x) { rawValue_ += x.rawValue(); return *this; } /// Assignment subtraction with compatible quantity. Type & operator-=(const Type & x) { rawValue_ -= x.rawValue(); return *this; } private: /// The raw value in units of Qty::baseunit(). double rawValue_; }; /// Specialization of Qty for <0,0,0> with conversions to double. template<> class Qty,std::ratio<0>,std::ratio<0>> { public: /// Our type using Type = Qty,std::ratio<0>,std::ratio<0>>; /// General power type template using Power = Type; /// The squared type. using Squared = Type; /// The inverse type. using Inverse = Type; /// The sqrt type. using Sqrt = Type; /// Basic unit of this quantity. static constexpr Type baseunit() { return 1.0; } /// Default constructor to 0. constexpr Qty(ZeroUnit) : rawValue_(0.0) {} /// Default constructor from a double. constexpr Qty(double x = 0.0, double factor=1.0) : rawValue_(x * factor) {} /// Constructor from a compatible quantity template constexpr Qty(const U & q, double factor=1.0, enable_if_same_qty * = nullptr) : rawValue_(q.rawValue() * factor) {} /// Access to the raw value. constexpr double rawValue() const { return rawValue_; } /// Cast to double. constexpr operator double() const { return rawValue_; } /// Assignment multiplication by dimensionless number. Type & operator*=(double x) { rawValue_ *= x; return *this; } /// Assignment division by dimensionless number. Type & operator/=(double x) { rawValue_ /= x; return *this; } /// Assignment addition with compatible quantity. Type & operator+=(const Type & x) { rawValue_ += x.rawValue(); return *this; } /// Assignment subtraction with compatible quantity. Type & operator-=(const Type & x) { rawValue_ -= x.rawValue(); return *this; } /// Assignment addition with double. Type & operator+=(double x) { rawValue_ += x; return *this; } /// Assignment subtraction with double. Type & operator-=(double x) { rawValue_ -= x; return *this; } private: /// The raw value. double rawValue_; }; using QtyDouble = Qty,std::ratio<0>,std::ratio<0>>; /// @name Result types for binary operations. //@{ /** * BinaryOpTraits should be specialized with typdefs called MulT and * DivT which gives the type resulting when multiplying and dividing * the template argument types respectively. */ template struct BinaryOpTraits; /** @cond TRAITSPECIALIZATIONS */ template struct BinaryOpTraits, Qty> { /** The type resulting from multiplication of the template type with itself. */ typedef Qty, std::ratio_add, std::ratio_add> MulT; /** The type resulting from division of one template type with another. */ typedef Qty, std::ratio_subtract, std::ratio_subtract> DivT; }; /** * Multiplication template */ template struct BinaryOpTraits> { /** The type resulting from multiplication of the template type */ typedef Qty MulT; /** The type resulting from division of the template type */ typedef typename BinaryOpTraits>::DivT DivT; }; /** * Multiplication template */ template struct BinaryOpTraits, double> { /** The type resulting from multiplication of the template type */ typedef Qty MulT; /** The type resulting from division of the template type */ typedef Qty DivT; }; //@} /// @name Type traits for alternative code generation. //@{ /** Type traits for alternative code generation*/ template struct TypeTraits> { /** Enum for dimensions*/ enum { hasDimension = true }; /// Type switch set to dimensioned type. typedef DimensionT DimType; /// Base unit static constexpr Qty baseunit() { return Qty::baseunit(); } }; /** Type traits for alternative code generation*/ template <> struct TypeTraits { /** Enum for dimensions*/ enum { hasDimension = false }; /// Type switch set to standard type. typedef StandardT DimType; /// Base unit static constexpr QtyDouble baseunit() { return 1.0; } }; //@} /** @endcond */ } #endif diff --git a/Config/PhysicalQtyComplex.h b/Config/PhysicalQtyComplex.h --- a/Config/PhysicalQtyComplex.h +++ b/Config/PhysicalQtyComplex.h @@ -1,290 +1,290 @@ // -*- C++ -*- // // PhysicalQtyComplex.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2006-2017 David Grellscheid, Leif Lonnblad +// Copyright (C) 2006-2019 David Grellscheid, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Physical_Qty_Complex_H #define Physical_Qty_Complex_H #include "PhysicalQty.h" #include "PhysicalQtyOps.h" #include /** @file PhysicalQtyComplex.h * Overloads for operations on complex physical quantities. */ namespace std { /** * Template specialization for std::complex > * with conversions to complex */ template<> class complex { public: /// Default constructor constexpr complex(double r=0.0, double i=0.0) : rawValue_(r,i) {} /// Constructor from complex constexpr complex(complex C) : rawValue_(C) {} /** * The internal representation of the dimensionful quantity. * Using this will break dimension-consistency. */ constexpr complex rawValue() const { return rawValue_; } /// Real part constexpr double real() const { return rawValue_.real(); } /// Imaginary part constexpr double imag() const { return rawValue_.imag(); } /// Cast to complex constexpr operator complex() const { return rawValue_; } /// Addition-assignment complex & operator+=(const complex x) { rawValue_ += x.rawValue(); return *this; } /// Subtraction-assignment complex & operator-=(const complex x) { rawValue_ -= x.rawValue(); return *this; } private: /// Internal value of the dimensioned quantity complex rawValue_; }; } // ========================================= namespace ThePEG { /// @name Overloads for mathematical operations //@{ // complex qty = complex qty * complex qty template inline constexpr auto operator*(std::complex> q1, std::complex> q2) -> std::complex { return {q1.real()*q2.real() - q1.imag()*q2.imag(), q1.real()*q2.imag() + q1.imag()*q2.real()}; } // complex qty = complex qty * complex qty template inline constexpr std::complex::Squared> operator*(std::complex> q1, std::complex> q2) { return {q1.real()*q2.real() - q1.imag()*q2.imag(), q1.real()*q2.imag() + q1.imag()*q2.real()}; } // complex qty = complex double - complex qty inline constexpr std::complex operator-(std::complex q1, std::complex q2) { return {q1.real()-q2.real(), q1.imag()-q2.imag()}; } // complex qty = complex double + complex qty inline constexpr std::complex operator+(std::complex q1, std::complex q2) { return {q1.real()+q2.real(), q1.imag()+q2.imag()}; } // complex qty = complex double * complex qty template inline constexpr std::complex> operator*(std::complex q1, std::complex> q2) { return {q1.real()*q2.real() - q1.imag()*q2.imag(), q1.real()*q2.imag() + q1.imag()*q2.real()}; } // complex qty = complex double / complex qty template inline std::complex::Inverse> operator/(std::complex q1, std::complex> q2) { auto tmp = q1*conj(q2); auto norm = (q2*conj(q2)).real(); return {tmp.real()/norm, tmp.imag()/norm}; } // complex qty = complex double / qty template inline constexpr std::complex::Inverse> operator/(std::complex q1, Qty q2) { return {q1.real()/q2, q1.imag()/q2}; } // complex qty = complex qty / complex double template inline std::complex> operator/(std::complex> q1, std::complex q2) { auto tmp = q1*conj(q2); auto norm = (q2*conj(q2)).real(); return {tmp.real()/norm, tmp.imag()/norm}; } // complex qty = qty / complex double template inline std::complex> operator/(Qty q1, std::complex q2) { auto tmp = q1*conj(q2); auto norm = (q2*conj(q2)).real(); return {tmp.real()/norm, tmp.imag()/norm}; } // complex double = complex qty / complex qty template inline std::complex operator/(std::complex> q1, std::complex> q2) { auto tmp = q1*conj(q2); auto norm = (q2*conj(q2)).real(); return {tmp.real()/norm, tmp.imag()/norm}; } // complex double = qty / complex qty template inline std::complex operator/(Qty q1, std::complex> q2) { auto tmp = q1*conj(q2); auto norm = (q2*conj(q2)).real(); return {tmp.real()/norm, tmp.imag()/norm}; } // complex double = complex qty / qty template inline constexpr std::complex operator/(std::complex> q1, Qty q2) { return {q1.real()/q2, q1.imag()/q2}; } // complex qty = complex qty / complex qty template inline auto operator/(std::complex> q1, std::complex> q2) -> std::complex { auto tmp = q1*conj(q2); auto norm = (q2*conj(q2)).real(); return {tmp.real()/norm, tmp.imag()/norm}; } // complex qty = qty / complex qty template inline auto operator/(Qty q1, std::complex> q2) -> std::complex { auto tmp = q1*conj(q2); auto norm = (q2*conj(q2)).real(); return {tmp.real()/norm, tmp.imag()/norm}; } // complex qty = complex qty / qty template inline constexpr auto operator/(std::complex> q1, Qty q2) -> std::complex { return {q1.real()/q2, q1.imag()/q2}; } // complex qty = complex qty * complex double template inline constexpr std::complex> operator*(std::complex> q1, std::complex q2) { return q2 * q1; } // complex qty = qty * complex qty template inline constexpr auto operator*(Qty q1, std::complex> q2) -> std::complex { return {q1*q2.real(), q1*q2.imag()}; } // complex qty = qty * complex qty template inline constexpr std::complex::Squared> operator*(Qty q1, std::complex> q2) { return {q1*q2.real(), q1*q2.imag()}; } // complex qty = qty * complex double template inline constexpr std::complex> operator*(Qty q1, std::complex q2) { return {q1*q2.real(), q1*q2.imag()}; } // complex qty = complex double * qty template inline constexpr std::complex> operator*(std::complex q1, Qty q2) { return q2 * q1; } // complex qty = complex qty * qty template inline constexpr auto operator*(std::complex> q1, Qty q2) -> decltype(q2*q1) { return q2 * q1; } // complex qty = complex qty * qty template inline constexpr std::complex::Squared> operator*(std::complex> q1, Qty q2) { return q2 * q1; } // complex qty *= double template inline constexpr std::complex> & operator*=(std::complex> & q1, double q2) { return (q1 = q1 * q2); } // complex qty /= double template inline constexpr std::complex> & operator/=(std::complex> & q1, double q2) { return (q1 = q1 / q2); } //@} } #endif diff --git a/Config/PhysicalQtyOps.h b/Config/PhysicalQtyOps.h --- a/Config/PhysicalQtyOps.h +++ b/Config/PhysicalQtyOps.h @@ -1,226 +1,226 @@ // -*- C++ -*- // // PhysicalQtyOps.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2006-2017 David Grellscheid, Leif Lonnblad +// Copyright (C) 2006-2019 David Grellscheid, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Physical_Qty_Ops_H #define Physical_Qty_Ops_H #include "PhysicalQty.h" #include /** @file PhysicalQtyOps.h * Overloads for mathematical operations on physical quantities. */ namespace ThePEG { /// @name Overloads for mathematical operations on physical quantities. //@{ // qty = qty * qty template inline constexpr typename BinaryOpTraits::MulT operator*(T q1, U q2) { typedef typename BinaryOpTraits::MulT RetT; return RetT{RetT::baseunit(), q1.rawValue()*q2.rawValue()}; } // qty = qty / qty template inline constexpr typename BinaryOpTraits::DivT operator/(T q1, U q2) { typedef typename BinaryOpTraits::DivT RetT; return RetT{RetT::baseunit(), q1.rawValue()/q2.rawValue()}; } // qty = qty + qty template inline enable_if_same_qty operator+(T q1, U q2) { q1 += q2; return q1; } // qty = qty - qty template inline enable_if_same_qty operator-(T q1, U q2) { q1 -= q2; return q1; } // qty == qty template inline constexpr enable_if_same_qty operator==(T q1, U q2) { return q1.rawValue()==q2.rawValue(); } // qty != qty template inline constexpr enable_if_same_qty operator!=(T q1, U q2) { return q1.rawValue()!=q2.rawValue(); } // qty < qty template inline constexpr enable_if_same_qty operator<(T q1, U q2) { return q1.rawValue() inline constexpr enable_if_same_qty operator<=(T q1, U q2) { return q1.rawValue()<=q2.rawValue(); } // qty > qty template inline constexpr enable_if_same_qty operator>(T q1, U q2) { return q1.rawValue()>q2.rawValue(); } // qty >= qty template inline constexpr enable_if_same_qty operator>=(T q1, U q2) { return q1.rawValue()>=q2.rawValue(); } // comparisons with ZERO template inline constexpr enable_if_same_qty operator==(T q1, ZeroUnit) { return q1.rawValue() == 0.0; } template inline constexpr enable_if_same_qty operator!=(T q1, ZeroUnit) { return q1.rawValue() != 0.0; } template inline constexpr enable_if_same_qty operator<(T q1, ZeroUnit) { return q1.rawValue() < 0.0; } template inline constexpr enable_if_same_qty operator>(T q1, ZeroUnit) { return q1.rawValue() > 0.0; } template inline constexpr enable_if_same_qty operator<=(T q1, ZeroUnit) { return q1.rawValue() <= 0.0; } template inline constexpr enable_if_same_qty operator>=(T q1, ZeroUnit) { return q1.rawValue() >= 0.0; } // qty = qty * double template inline constexpr enable_if_same_qty operator*(T q,double x) { return T{q,x}; } // qty = double * qty template inline constexpr enable_if_same_qty operator*(double x,T q) { return T{q,x}; } // qty = qty / double template inline constexpr enable_if_same_qty operator/(T q,double x) { return T{q, 1./x}; } // qty = double / qty template inline constexpr enable_if_same_qty operator/(double x, T q) { typedef typename T::Inverse RetT; return RetT{RetT::baseunit(), x/q.rawValue()}; } // qty = -qty template inline constexpr enable_if_same_qty operator-(T q) { typedef T RetT; return RetT{q, -1.0}; } // qty = sqrt(qty) // std::sqrt is not constexpr template inline enable_if_same_qty sqrt(T q) { typedef typename T::Sqrt RetT; return RetT{RetT::baseunit(), std::sqrt(q.rawValue())}; } // double = atan2(y,x) template inline constexpr enable_if_same_qty atan2(T y, U x) { return std::atan2(y.rawValue(), x.rawValue()); } // qty = abs(qty) template inline constexpr enable_if_same_qty abs(T q) { return T{T::baseunit(), std::abs(q.rawValue())}; } // qty = pow(qty) template inline constexpr enable_if_same_qty, T> pow(T q) { typedef typename T::template Power RetT; return RetT{RetT::baseunit(), std::pow(q.rawValue(),double(Num)/double(Den))}; } // max for T,U types template inline T max(const T & t, const U & u) { const T & utmp = u; return std::max(t, utmp); } // ZeroUnit in front should take U type template inline U max(const ZeroUnit & t, const U & u) { const U & ttmp = t; return std::max(ttmp, u); } // min for T,U types template inline T min(const T & t, const U & u) { const T & utmp = u; return std::min(t, utmp); } // ZeroUnit in front should take U type template inline U min(const ZeroUnit & t, const U & u) { const U & ttmp = t; return std::min(ttmp, u); } //@} } #endif diff --git a/Config/Pointers.h b/Config/Pointers.h --- a/Config/Pointers.h +++ b/Config/Pointers.h @@ -1,108 +1,108 @@ // -*- C++ -*- // // Pointers.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_Pointers_H #define ThePEG_Pointers_H /** \file * This file declares typedefs of commonly used pointers in * ThePEG. The standard way of declaring the typedefs is by using the * ThePEG_DECLARE_CLASS_POINTERS macro which in turn used the Ptr * traits class to define normal pointers, normal const pointers, * transient pointers and transient const pointers for a given * class. For the standard classes, the following typedefs should be * introduced for a class abbreviated with T: * TPtr for a normal (smart) pointer, cTPtr * for a normal const pointer, tTPtr for a transient * pointer and tcTPtr for transient const pointer. * * Do not make changes in this file. If you need to modify any of the * standard pointer declarations used 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 "ThePEG/Config/ThePEG.h" namespace ThePEG { /** This macro helps us to declare pointers and stuff to standard classes. */ #define ThePEG_DECLARE_TEMPLATE_POINTERS(full, abbrev) \ /** Alias for a reference counted pointer to full. */ \ typedef typename ThePEG::Ptr::pointer abbrev; \ /** Alias for a reference counted pointer to a const full. */ \ typedef typename ThePEG::Ptr::const_pointer c ## abbrev; \ /** Alias for a transient pointer to full. */ \ typedef typename ThePEG::Ptr::transient_pointer t ## abbrev; \ /** Alias for a transient pointer to a const full. */ \ typedef typename ThePEG::Ptr::transient_const_pointer tc ## abbrev /** This macro helps us to declare pointers and stuff to standard classes. */ #define ThePEG_DECLARE_POINTERS(full, abbrev) \ /** Alias for a reference counted pointer to full. */ \ typedef ThePEG::Ptr::pointer abbrev; \ /** Alias for a reference counted pointer to a const full. */ \ typedef ThePEG::Ptr::const_pointer c ## abbrev; \ /** Alias for a transient pointer to full. */ \ typedef ThePEG::Ptr::transient_pointer t ## abbrev; \ /** Alias for a transient pointer to a const full. */ \ typedef ThePEG::Ptr::transient_const_pointer tc ## abbrev /** This macro helps us to declare pointers and stuff to standard classes. */ #define ThePEG_DECLARE_CLASS_POINTERS(full, abbrev) \ class full; \ ThePEG_DECLARE_POINTERS(full, abbrev) ThePEG_DECLARE_CLASS_POINTERS(InterfacedBase,IBPtr); ThePEG_DECLARE_CLASS_POINTERS(Interfaced,IPtr); ThePEG_DECLARE_CLASS_POINTERS(ParticleData,PDPtr); ThePEG_DECLARE_CLASS_POINTERS(MatcherBase,PMPtr); ThePEG_DECLARE_CLASS_POINTERS(DecayMode,DMPtr); ThePEG_DECLARE_CLASS_POINTERS(Particle,PPtr); ThePEG_DECLARE_CLASS_POINTERS(EventGenerator,EGPtr); ThePEG_DECLARE_CLASS_POINTERS(EventHandler,EHPtr); ThePEG_DECLARE_CLASS_POINTERS(StepHandler,StepHdlPtr); ThePEG_DECLARE_CLASS_POINTERS(Hint,HintPtr); ThePEG_DECLARE_CLASS_POINTERS(HadronizationHandler,HadrHdlPtr); ThePEG_DECLARE_CLASS_POINTERS(CascadeHandler,CascHdlPtr); ThePEG_DECLARE_CLASS_POINTERS(MultipleInteractionHandler,MIHdlPtr); ThePEG_DECLARE_CLASS_POINTERS(DecayHandler,DecayHdlPtr); ThePEG_DECLARE_CLASS_POINTERS(PileupHandler,PileHdlPtr); ThePEG_DECLARE_CLASS_POINTERS(LuminosityFunction,LumiFnPtr); ThePEG_DECLARE_CLASS_POINTERS(PartonExtractor,PExtrPtr); ThePEG_DECLARE_CLASS_POINTERS(RandomGenerator,RanGenPtr); ThePEG_DECLARE_CLASS_POINTERS(AnalysisHandler,AnaPtr); ThePEG_DECLARE_CLASS_POINTERS(EventManipulator, EvtManipPtr); ThePEG_DECLARE_CLASS_POINTERS(Decayer,DecayerPtr); ThePEG_DECLARE_CLASS_POINTERS(Event,EventPtr); ThePEG_DECLARE_CLASS_POINTERS(Collision,CollPtr); ThePEG_DECLARE_CLASS_POINTERS(Step,StepPtr); ThePEG_DECLARE_CLASS_POINTERS(SubProcess,SubProPtr); ThePEG_DECLARE_CLASS_POINTERS(Strategy,StrategyPtr); ThePEG_DECLARE_CLASS_POINTERS(XComb,XCombPtr); ThePEG_DECLARE_CLASS_POINTERS(RemnantHandler,RemHPtr); ThePEG_DECLARE_CLASS_POINTERS(PDFBase,PDFPtr); ThePEG_DECLARE_CLASS_POINTERS(StandardModelBase,SMPtr); ThePEG_DECLARE_CLASS_POINTERS(ColourBase,CBPtr); ThePEG_DECLARE_CLASS_POINTERS(SpinInfo,SpinPtr); ThePEG_DECLARE_CLASS_POINTERS(EventInfoBase,EIPtr); ThePEG_DECLARE_CLASS_POINTERS(ReweightBase,ReweightPtr); ThePEG_DECLARE_CLASS_POINTERS(ColourLine,ColinePtr); ThePEG_DECLARE_POINTERS(Base,BPtr); // ThePEG_DECLARE_CLASS_POINTERS(,); } // #include "Pointers.icc" #ifndef ThePEG_TEMPLATES_IN_CC_FILE // #include "Pointers.tcc" #endif #endif /* ThePEG_Pointers_H */ diff --git a/Config/TemplateTools.h b/Config/TemplateTools.h --- a/Config/TemplateTools.h +++ b/Config/TemplateTools.h @@ -1,67 +1,67 @@ // -*- C++ -*- // // TemplateTools.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2006-2017 David Grellscheid, Leif Lonnblad +// Copyright (C) 2006-2019 David Grellscheid, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef Template_Tools_H #define Template_Tools_H #include /** * @file TemplateTools.h * Useful template machinery. Based on Alexandrescu, "Modern C++ Design". */ namespace ThePEG { /// Conversion between integers and types. template struct Int2Type { enum { value = v }; }; /// Dummy type for ambiguous function signatures. struct DummyType {}; /** @endcond */ /// Selection mechanism for type-dependent implementations. enum ImplSelector { Dimensioned, Standard, Enumerated }; /// Typedef for dimensioned types. typedef Int2Type DimensionT; /// Typedef for non-dimensioned types. typedef Int2Type StandardT; /// Typedef for non-dimensioned types. typedef Int2Type EnumT; /// Type traits for built-in types template struct TypeTraits { /// Boolean flag. Is true for physical quantities. enum { hasDimension = false }; /// Implementation selector typedef StandardT DimType; /// Base unit for arithmetic types // construction with extra U type is necessary to make // enable_if work before concepts are supported properly template static constexpr typename std::enable_if< (std::is_arithmetic::value && std::is_same::value), U>::type baseunit() { return static_cast(1); } }; } #endif diff --git a/Config/ThePEG.cc b/Config/ThePEG.cc --- a/Config/ThePEG.cc +++ b/Config/ThePEG.cc @@ -1,24 +1,24 @@ // -*- C++ -*- // // ThePEG.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // This file contains the implementations of the declarations in // ThePEG.h. #include "ThePEG/Config/ThePEG.h" using namespace ThePEG; void Base::debug() const { debugme(); } void Base::debugme() const { cerr << "(#ref: " << referenceCount() << ")"; } diff --git a/Config/ThePEG.h b/Config/ThePEG.h --- a/Config/ThePEG.h +++ b/Config/ThePEG.h @@ -1,148 +1,148 @@ // -*- C++ -*- // // ThePEG.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_H #define ThePEG_H /** \file ThePEG.h * This is the main config header file for ThePEG. Do not make * changes in this file. If you need to modify anything, edit a copy * of the file which can be included instead of this file using the * macro ThePEG_ALTERNATE_CONFIG. */ #ifndef ThePEG_ALTERNATE_CONFIG #include "ThePEG/Pointer/Ptr.h" #include "ThePEG/Pointer/PtrTraits.h" #include "ThePEG/Pointer/RCPtr.h" #include "ThePEG/Utilities/Rebinder.fh" #include "ThePEG/Utilities/Interval.fh" #include "ThePEG/Utilities/ClassDescription.fh" #include "ThePEG/Interface/InterfaceBase.fh" #include "ThePEG/Persistency/PersistentOStream.fh" #include "ThePEG/Persistency/PersistentIStream.fh" #include "TemplateTools.h" #include "Complex.h" #include "Unitsystem.h" #include "Constants.h" #include "std.h" /** * This is the main namespace within which all identifiers in ThePEG * are declared. External packages based on ThePEG should not * introduce identifiers in the ThePEG namespace, but in a separate * namespace which need not be nested within the ThePEG namespace. */ namespace ThePEG { // Introduce some identifiers in the ThePEG namespace/ using namespace ThePEG::Pointer; using ThePEG::Pointer::Ptr; using namespace ThePEG::Units; /** * Define the base class from which all (polymorphic) classes in * ThePEG are derived. */ struct Base: public ReferenceCounted { /** The virtual destructor */ virtual ~Base() {} /** * 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() {} /** * Print out debugging information for this object on std::cerr. To * be called from within a debugger. Simply calls the virtual * debugme() function. */ void debug() const; /** * Print out debugging information for this object on std::cerr. To * be called from within a debugger via the debug() function. */ virtual void debugme() const; }; /** * Define the base class from which all persistent classes in * ThePEG are derived. */ typedef Base PersistentBase; /** * TraitsType is an empty, non-polymorphic, base class. It is used as * a base class of all traits classes in ThePEG in order to group them * together in the documentation. It currently serves no other * purpose. */ struct TraitsType {}; /** * A standard exception class to be used for vetoing a whole event. */ struct Veto { /** the default constructor. */ Veto(); }; /** * A standard exception class to be used to temporarily stop the * generation of an event. */ struct Stop {}; /** * The square function should really have been included in the * standard C++ library. */ template inline constexpr auto sqr(const T& x) -> decltype(x*x) { return x*x; } // Debugging in ThePEG may be swithced off completely by this // compilation swithc, eliminating possible overhead in error // checking. #ifndef ThePEG_NO_DEBUG /** Macro for accessing debug functions to enable compile-time disabling. */ #define ThePEG_DEBUG_LEVEL Debug::level /** Macro for accessing debug functions to enable compile-time disabling. */ #define ThePEG_DEBUG_ITEM(item) Debug::debugItem(item) #else /** Macro for accessing debug functions to enable compile-time disabling. */ #define ThePEG_DEBUG_LEVEL 0 /** Macro for accessing debug functions to enable compile-time disabling. */ #define ThePEG_DEBUG_ITEM(item) false #endif } #include "Pointers.h" #include "Containers.h" #else #include ThePEG_ALTERNATIVE_CONFIG #endif #endif /* ThePEG_H */ diff --git a/Config/Unitsystem.h b/Config/Unitsystem.h --- a/Config/Unitsystem.h +++ b/Config/Unitsystem.h @@ -1,275 +1,275 @@ // -*- C++ -*- // // Unitsystem.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad, David Grellscheid +// Copyright (C) 1999-2019 Leif Lonnblad, David Grellscheid // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_Units_H #define ThePEG_Units_H #include "ThePEG/Vectors/Lorentz5Vector.fh" #include "ThePEG/Vectors/LorentzVector.fh" #include "ThePEG/Vectors/ThreeVector.fh" #include "ThePEG/Vectors/Transverse.fh" #include "PhysicalQty.h" #include "PhysicalQtyOps.h" #include "PhysicalQtyComplex.h" namespace ThePEG { /** * The Units namespace contains the declaration of a number of classes * for variables with dimension. Currently they are all typedefs of * double, but in the future the SIUnits package will be used. * * The file Utilities/UnitIO.h defines helper-classes and helper * functions to read and write variables with dimensions. As an * example, to read and write an energy variable e in * units of GeV, use: os << ounit(e, GeV) and is >> * iunit(e, GeV) */ namespace Units { /// adapter for the old style of naming quantities template using Qty = ThePEG::Qty, std::ratio, std::ratio>; /** Energy. */ typedef Qty<0,1,0> Energy; /** Mass has the same unit as Energy <=> c == 1. */ typedef Energy Mass; /** Length. */ typedef Qty<1,0,0> Length; /** Time has the same unit as Length. <=> c == 1. */ typedef Length Time; /** Inverse Length. */ typedef Qty<-1,0,0> InvLength; /** Velocities are dimensionless fractions of c. */ typedef double Velocity; /** Charge. */ typedef Qty<0,0,1> Charge; /** Angular momentum. */ typedef Qty<1,1,0> AngularMomentum; /** Tension. */ typedef Qty<-1,1,0> Tension; /** Area will be assumed to be Length\f$^2\f$. */ typedef Qty<2,0,0> Area; /** Inverse Area. */ typedef Qty<-2,0,0> InvArea; /** Cross section is an area. */ typedef Area CrossSection; /** * @name Higher powers of energy. * Even higher powers can be created with similar typedefs. */ //@{ typedef Qty<0, 2, 0> Energy2; typedef Qty<0, 3, 0> Energy3; typedef Qty<0, 4, 0> Energy4; typedef Qty<0, 5, 0> Energy5; typedef Qty<0, 6, 0> Energy6; typedef Qty<0, 7, 0> Energy7; typedef Qty<0, 8, 0> Energy8; typedef Qty<0, 9, 0> Energy9; typedef Qty<0,10, 0> Energy10; typedef Qty<0,11, 0> Energy11; typedef Qty<0,12, 0> Energy12; typedef Qty<0, 1,0, 1,2,1> SqrtEnergy; typedef Qty<0,-1,0, 1,2,1> InvSqrtEnergy; typedef Qty<0, -1, 0> InvEnergy; typedef Qty<0, -2, 0> InvEnergy2; typedef Qty<0, -3, 0> InvEnergy3; typedef Qty<0, -4, 0> InvEnergy4; typedef Qty<0, -5, 0> InvEnergy5; typedef Qty<0, -6, 0> InvEnergy6; typedef Qty<0, -7, 0> InvEnergy7; typedef Qty<0, -8, 0> InvEnergy8; typedef Qty<0, -9, 0> InvEnergy9; typedef Qty<0,-10, 0> InvEnergy10; typedef Qty<0,-11, 0> InvEnergy11; typedef Qty<0,-12, 0> InvEnergy12; //@} /** CrossSection*Energy2. */ typedef Qty<2,2,0> Energy2XSec; /** CrossSection/Energy2. */ typedef Qty<2,-2,0> DiffXSec; /** CrossSection/Energy4. */ typedef Qty<2,-4,0> Diff2XSec; /** CrossSection/Energy6 */ typedef Qty<2,-6,0> Diff3XSec; /** Scale is the same as a squared energy. */ typedef Energy2 Scale; /** A point in three-dimensional euclidean space. */ typedef ThreeVector Point; /** A distance in three-dimensional euclidean space. */ typedef ThreeVector Distance; /** A direction in three-dimensional euclidean space. */ typedef ThreeVector Axis; /** A momentum in three-dimensional euclidean space. */ typedef ThreeVector Momentum3; /** A three-dimensional boost vector. */ typedef ThreeVector Boost; /** A distance in four-dimensional space-time. */ typedef LorentzVector LorentzDistance; /** A distance in four-dimensional space-time with an explicit * invariant time component. */ typedef Lorentz5Vector Lorentz5Distance; /** A point in four-dimensional space-time. */ typedef LorentzVector LorentzPoint; /** A momentum in four-dimensional space-time. */ typedef LorentzVector LorentzMomentum; /** A momentum in four-dimensional space-time with an explicit * invariant mass component. */ typedef Lorentz5Vector Lorentz5Momentum; /** Transverse components of a momentum. */ typedef Transverse TransverseMomentum; /// @name Pre-defined basic units. //@{ constexpr Length operator "" _mm( long double x ) { return Length{Length::baseunit(), static_cast(x)}; } constexpr Length operator "" _mm( unsigned long long x ) { return Length{Length::baseunit(), static_cast(x)}; } constexpr Length meter = 1.0e+3_mm; constexpr Length millimeter = 1_mm; constexpr Length mm = 1_mm; constexpr Length centimeter = 10_mm; constexpr Length micrometer = 1.0e-3_mm; constexpr Length nanometer = 1.0e-6_mm; constexpr Length picometer = 1.0e-9_mm; constexpr Length femtometer = 1.0e-12_mm; constexpr Energy operator "" _MeV( long double x ) { return Energy{Energy::baseunit(), static_cast(x)}; } constexpr Energy operator "" _MeV( unsigned long long x ) { return Energy{Energy::baseunit(), static_cast(x)}; } constexpr Energy operator "" _GeV( long double x ) { return Energy{1000_MeV, static_cast(x)}; } constexpr Energy operator "" _GeV( unsigned long long x ) { return Energy{1000_MeV, static_cast(x)}; } constexpr Energy operator "" _TeV( long double x ) { return Energy{1000_GeV, static_cast(x)}; } constexpr Energy operator "" _TeV( unsigned long long x ) { return Energy{1000_GeV, static_cast(x)}; } constexpr Energy keV = 1.0e-3_MeV; constexpr Energy MeV = 1_MeV; constexpr Energy GeV = 1_GeV; constexpr Energy TeV = 1_TeV; constexpr Energy2 operator "" _MeV2( long double x ) { return Energy2{Energy2::baseunit(), static_cast(x)}; } constexpr Energy2 operator "" _MeV2( unsigned long long x ) { return Energy2{Energy2::baseunit(), static_cast(x)}; } constexpr Energy2 operator "" _GeV2( long double x ) { return Energy2{1.0e+6_MeV2, static_cast(x)}; } constexpr Energy2 operator "" _GeV2( unsigned long long x ) { return Energy2{1.0e+6_MeV2, static_cast(x)}; } constexpr Energy2 MeV2 = 1_MeV2; constexpr Energy2 GeV2 = 1_GeV2; constexpr InvEnergy InvGeV = 1/GeV; constexpr Area operator "" _pb( long double x ) { return Area{1.0e-34 * Area::baseunit(), static_cast(x)}; } constexpr Area operator "" _pb( unsigned long long x ) { return Area{1.0e-34 * Area::baseunit(), static_cast(x)}; } constexpr Area femtobarn = 1.0e-03_pb; constexpr Area picobarn = 1_pb; constexpr Area nanobarn = 1.0e+03_pb; constexpr Area microbarn = 1.0e+06_pb; constexpr Area millibarn = 1.0e+09_pb; constexpr Area barn = 1.0e+12_pb; constexpr Charge eplus = Charge::baseunit(); //@} /// Planck's constant times c (PDG 2006 value 197.326968(17) MeV fm) constexpr Qty<1,1,0> hbarc = 197.326968e-15 * MeV * meter; /// Planck's constant (PDG 2006 value 197.326968(17) MeV fm) constexpr Qty<1,1,0> hbar_Planck = hbarc / 1.0; // c is one } /** * Use symbols from this namespace to make forced breaks of unit * consistency explicit. */ namespace UnitRemoval { /// @name Helper units to make breaks of unit consistency explicit. //@{ constexpr Units::Energy E = Units::Energy::baseunit(); constexpr Units::Energy2 E2 = E*E; constexpr Units::Energy3 E3 = E*E2; constexpr Units::Energy4 E4 = E2*E2; constexpr Units::InvEnergy InvE = 1.0/E; constexpr Units::InvEnergy2 InvE2 = 1.0/E2; constexpr Units::InvEnergy3 InvE3 = 1.0/E3; constexpr Units::InvEnergy4 InvE4 = 1.0/E4; constexpr Units::SqrtEnergy SqrtE = Units::SqrtEnergy::baseunit(); constexpr Units::InvSqrtEnergy InvSqrtE = Units::InvSqrtEnergy::baseunit(); //@} } } #endif /* ThePEG_Units_H */ diff --git a/Config/algorithm.h b/Config/algorithm.h --- a/Config/algorithm.h +++ b/Config/algorithm.h @@ -1,150 +1,150 @@ // -*- C++ -*- // // algorithm.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_algorithm_H #define ThePEG_algorithm_H /** \file * This file implements a number of interfaces to std:: * algorithms, modified to take a whole container as argument rather * than a range of iterators, Also defines IteratorRange to * encapsulate a range of iterators and corresponding algorithms. */ #include "ThePEG/Config/ThePEG.h" #include namespace ThePEG { /** * A pair of iterators to be used in specialized algorithms instead * of the standard first, last construction. */ template struct IteratorRange: public std::pair { /** The underlying representation. */ typedef std::pair BaseType; /** Default constructor. */ IteratorRange() {} /** Copy constructor */ IteratorRange(const IteratorRange & ir): BaseType(ir) {} /** Constructor taking the underlying pair representation as argument. */ IteratorRange(const BaseType & ir): BaseType(ir) {} }; /** Return an IteratorRange corresponding to the whole container. */ template inline IteratorRange range(Container & c) { return std::make_pair(c.begin(), c.end()); } /** Return an IteratorRange of const iterators corresponding to the * whole container. */ template inline IteratorRange range(const Container & c) { return std::make_pair(c.begin(), c.end()); } /** Return an IteratorRange of reverse iterators corresponding to the * whole container. */ template inline IteratorRange rrange(Container & c) { return std::make_pair(c.rbegin(), c.rend()); } /** Return an IteratorRange of reverse const iterators corresponding * to the whole container. */ template inline IteratorRange rrange(const Container & c) { return std::make_pair(c.rbegin(), c.rend()); } /** The std::for_each function taking an IteratorRange as argument. */ template inline FNC for_each(IteratorRange r, FNC f) { return std::for_each(r.first, r.second, f); } /** The std::find function taking an IteratorRange as argument. */ template inline Iterator find(IteratorRange r, const T & t) { return std::find(r.first, r.second, t); } /** The std::find_if function taking an IteratorRange as argument. */ template inline Iterator find_if(IteratorRange r, Pred p) { return std::find_if(r.first, r.second, p); } /** The std::replace function taking an IteratorRange as argument. */ template inline void replace(IteratorRange r, const T & oval, const T & nval) { return std::replace(r.first, r.second, oval, nval); } /** The std::for_each function taking a whole container as argument. */ template inline FNC for_each(Cont & c, FNC f) { return std::for_each(c.begin(), c.end(), f); } /** The std::for_each function taking a whole const container as argument. */ template inline FNC for_each(const Cont & c, FNC f) { return std::for_each(c.begin(), c.end(), f); } /** The std::find function taking a whole container as argument. */ template inline typename Cont::iterator find(Cont & c, const Type & t) { return find(range(c), t); } /** The std::find function taking a whole const container as argument. */ template inline typename Cont::const_iterator find(const Cont & c, const Type & t) { return find(range(c), t); } /** The std::find_if function taking a whole container as argument. */ template inline typename Cont::iterator find_if(Cont & c, const Pred & p) { return find_if(range(c), p); } /** The std::find_if function taking a whole const container as argument. */ template inline typename Cont::const_iterator find_if(const Cont & c, const Pred & p) { return find_if(range(c), p); } /** The std::replace function taking a whole container as argument. */ template inline void replace(Cont & c, const T & oval, const T & nval) { return replace(range(c), oval, nval); } } // #include "algorithm.icc" #ifndef ThePEG_TEMPLATES_IN_CC_FILE // #include "algorithm.tcc" #endif #endif /* ThePEG_algorithm_H */ diff --git a/Config/std.h b/Config/std.h --- a/Config/std.h +++ b/Config/std.h @@ -1,188 +1,188 @@ // -*- C++ -*- // // std.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_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 #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::array; 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_fn; 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/Cuts.cc b/Cuts/Cuts.cc --- a/Cuts/Cuts.cc +++ b/Cuts/Cuts.cc @@ -1,663 +1,663 @@ // -*- C++ -*- // // Cuts.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the Cuts class. // #include "Cuts.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/EventRecord/SubProcess.h" #include "ThePEG/EventRecord/Collision.h" #include "ThePEG/EventRecord/TmpTransform.h" #include "ThePEG/Utilities/UtilityBase.h" #include "ThePEG/Utilities/HoldFlag.h" #include "ThePEG/Utilities/Debug.h" #include "ThePEG/Repository/CurrentGenerator.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Config/algorithm.h" using namespace ThePEG; Cuts::Cuts(Energy MhatMin) : theSMax(ZERO), theY(0), theCurrentSHat(-1.0*GeV2), theCurrentYHat(0), theMHatMin(MhatMin), theMHatMax(Constants::MaxEnergy), theYHatMin(-Constants::MaxRapidity), theYHatMax(Constants::MaxRapidity), theX1Min(0.0), theX1Max(1.0), theX2Min(0.0), theX2Max(1.0), theScaleMin(ZERO), theScaleMax(Constants::MaxEnergy2), theSubMirror(false), theCutWeight(1.0), theLastCutWeight(1.0) {} Cuts::~Cuts() {} IBPtr Cuts::clone() const { return new_ptr(*this); } IBPtr Cuts::fullclone() const { return new_ptr(*this); } void Cuts::doinitrun() { Interfaced::doinitrun(); if ( Debug::level ) { describe(); for_each(theOneCuts, mem_fn(&OneCutBase::describe)); for_each(theTwoCuts, mem_fn(&TwoCutBase::describe)); for_each(theMultiCuts, mem_fn(&MultiCutBase::describe)); } } void Cuts::describe() const { CurrentGenerator::log() << fullName() << ":\n" << "MHat = " << theMHatMin/GeV << " .. " << theMHatMax/GeV << " GeV\n" << "Scale = " << theScaleMin/GeV2 << " .. " << theScaleMax/GeV2 << " GeV2\n" << "YHat = " << theYHatMin << " .. " << theYHatMax << '\n' << "X1 = " << theX1Min << " .. " << theX1Max << '\n' << "X2 = " << theX2Min << " .. " << theX2Max << "\n\n"; if ( theJetFinder ) theJetFinder->describe(); } void Cuts::initialize(Energy2 smax, double Y) { theSMax = smax; theMHatMax = min(theMHatMax, sqrt(smax)); theY = Y; theSubMirror = false; } void Cuts::initEvent() { theCurrentSHat = -1.0*GeV2; theCurrentYHat = 0.0; theSubMirror = false; } bool Cuts::initSubProcess(Energy2 shat, double yhat, bool mirror) const { theCutWeight = 1.0; theLastCutWeight = 1.0; theSubMirror = mirror; theCurrentSHat = shat; theCurrentYHat = yhat; if ( shat <= sHatMin() || shat > sHatMax()*(1.0 + 1000.0*Constants::epsilon) ) { theCutWeight = 0.0; return false; } if ( yhat <= yHatMin() || yhat >= yHatMax() ) { theCutWeight = 0.0; return false; } double x1 = min(1.0, sqrt(shat/SMax())*exp(yhat)); if ( x1 <= x1Min() || x1 > x1Max() ) { theCutWeight = 0.0; return false; } double x2 = min(1.0, sqrt(shat/SMax())*exp(-yhat)); if ( x2 <= x2Min() || x2 > x2Max() ) { theCutWeight = 0.0; return false; } return true; } bool Cuts::passCuts(const tcPDVector & ptype, const vector & p, tcPDPtr t1, tcPDPtr t2) const { if ( subMirror() ) { vector pmir = p; for ( int i = 0, N = pmir.size(); i < N; ++i ) pmir[i].setZ(-pmir[i].z()); swap(t1,t2); HoldFlag<> nomir(theSubMirror, false); return passCuts(ptype, pmir, t1, t2); } bool pass = true; theCutWeight = 1.0; theLastCutWeight = 1.0; if ( jetFinder() ) { if ( ptype.size() > jetFinder()->minOutgoing() ) { vector jets; tcPDVector jettype; if ( !jetFinder()->restrictConsitutents() ) { jets = p; jettype = ptype; } else { tcPDVector::const_iterator pd = ptype.begin(); vector::const_iterator pm = p.begin(); for ( ; pd != ptype.end(); ++pd, ++pm ) { if ( pm->rapidity() > jetFinder()->constituentRapidityRange().first && pm->rapidity() < jetFinder()->constituentRapidityRange().second ) { jets.push_back(*pm); jettype.push_back(*pd); } } } if ( jetFinder()->cluster(jettype,jets,this,t1,t2) ){ return passCuts(jettype,jets,t1,t2); } } } for ( int i = 0, N = p.size(); i < N; ++i ) for ( int j = 0, M = theOneCuts.size(); j < M; ++j ) { pass &= theOneCuts[j]->passCuts(this, ptype[i], p[i]); theCutWeight *= theLastCutWeight; theLastCutWeight = 1.0; if ( !pass ) { theCutWeight = 0.0; return false; } } for ( int i1 = 0, N1 = p.size() - 1; i1 < N1; ++i1 ) for ( int i2 = i1 + 1, N2 = p.size(); i2 < N2; ++i2 ) for ( int j = 0, M = theTwoCuts.size(); j < M; ++j ) { pass &= theTwoCuts[j]->passCuts(this, ptype[i1], ptype[i2], p[i1], p[i2]); theCutWeight *= theLastCutWeight; theLastCutWeight = 1.0; if ( !pass ) { theCutWeight = 0.0; return false; } } for ( int j = 0, M = theMultiCuts.size(); j < M; ++j ) { pass &= theMultiCuts[j]->passCuts(this, ptype, p); theCutWeight *= theLastCutWeight; theLastCutWeight = 1.0; if ( !pass ) { theCutWeight = 0.0; return false; } } if ( t1 ) { LorentzMomentum p1(ZERO, ZERO, 0.5*sqrt(currentSHat()), 0.5*sqrt(currentSHat())); for ( int i = 0, N = p.size(); i < N; ++i ) for ( int j = 0, M = theTwoCuts.size(); j < M; ++j ) { pass &= theTwoCuts[j]->passCuts(this, t1, ptype[i], p1, p[i], true, false); theCutWeight *= theLastCutWeight; theLastCutWeight = 1.0; if ( !pass ) { theCutWeight = 0.0; return false; } } } if ( t2 ) { LorentzMomentum p2(ZERO, ZERO, -0.5*sqrt(currentSHat()), 0.5*sqrt(currentSHat())); for ( int i = 0, N = p.size(); i < N; ++i ) for ( int j = 0, M = theTwoCuts.size(); j < M; ++j ) { pass &= theTwoCuts[j]->passCuts(this, ptype[i], t2, p[i], p2, false, true); theCutWeight *= theLastCutWeight; theLastCutWeight = 1.0; if ( !pass ) { theCutWeight = 0.0; return false; } } } return pass; } bool Cuts::passCuts(const tcPVector & p, tcPDPtr t1, tcPDPtr t2) const { tcPDVector ptype(p.size()); vector mom(p.size()); for ( int i = 0, N = p.size(); i < N; ++i ) { ptype[i] = p[i]->dataPtr(); mom[i] = p[i]->momentum(); } return passCuts(ptype, mom, t1, t2); } bool Cuts::passCuts(const SubProcess & sub) const { if ( !passCuts(tcPVector(sub.outgoing().begin(), sub.outgoing().end()), sub.incoming().first->dataPtr(), sub.incoming().second->dataPtr()) ) return false; return true; } bool Cuts::passCuts(const Collision & coll) const { tSubProPtr sub = coll.primarySubProcess(); LorentzMomentum phat = sub->incoming().first->momentum() + sub->incoming().second->momentum(); if ( !initSubProcess(phat.m2(), phat.rapidity()) ) return false; TmpTransform tmp(sub, Utilities::getBoostToCM(sub->incoming())); if ( !passCuts(*sub) ) return false; return true; } Energy2 Cuts::minS(const tcPDVector & pv) const { Energy2 mins = ZERO; for ( int i = 0, N = theMultiCuts.size(); i < N; ++i ) mins = max(mins, theMultiCuts[i]->minS(pv)); return mins; } Energy2 Cuts::maxS(const tcPDVector & pv) const { Energy2 maxs = SMax(); for ( int i = 0, N = theMultiCuts.size(); i < N; ++i ) maxs = min(maxs, theMultiCuts[i]->maxS(pv)); return maxs; } Energy2 Cuts::minSij(tcPDPtr pi, tcPDPtr pj) const { Energy2 mins = ZERO; for ( int i = 0, N = theTwoCuts.size(); i < N; ++i ) mins = max(mins, theTwoCuts[i]->minSij(pi, pj)); if ( mins > ZERO ) return mins; mins = sqr(pi->massMin() + pj->massMin()); mins = max(mins, sqr(minKTClus(pi, pj))/4.0); mins = max(mins, minDurham(pi, pj)*currentSHat()/2.0); mins = max(mins, minKT(pi)*minKT(pj)*minDeltaR(pi, pj)/4.0); return mins; } Energy2 Cuts::minTij(tcPDPtr pi, tcPDPtr po) const { Energy2 mint = ZERO; for ( int i = 0, N = theTwoCuts.size(); i < N; ++i ) mint = max(mint, theTwoCuts[i]->minTij(pi, po)); if ( mint > ZERO ) return mint; mint = max(mint, sqr(minKT(po))); return mint; } double Cuts::minDeltaR(tcPDPtr pi, tcPDPtr pj) const { double mindr = 0.0; for ( int i = 0, N = theTwoCuts.size(); i < N; ++i ) mindr = max(mindr, theTwoCuts[i]->minDeltaR(pi, pj)); return mindr; } Energy Cuts::minKTClus(tcPDPtr pi, tcPDPtr pj) const { Energy minkt = ZERO; for ( int i = 0, N = theTwoCuts.size(); i < N; ++i ) minkt = max(minkt, theTwoCuts[i]->minKTClus(pi, pj)); return minkt; } double Cuts::minDurham(tcPDPtr pi, tcPDPtr pj) const { double y = 0.0; for ( int i = 0, N = theTwoCuts.size(); i < N; ++i ) y = max(y, theTwoCuts[i]->minDurham(pi, pj)); return y; } Energy Cuts::minKT(tcPDPtr p) const { Energy minkt = ZERO; for ( int i = 0, N = theOneCuts.size(); i < N; ++i ) minkt = max(minkt, theOneCuts[i]->minKT(p)); if ( minkt > ZERO ) return minkt; minkt = minKTClus(p, tcPDPtr()); return minkt; } double Cuts::minEta(tcPDPtr p) const { double mineta = -Constants::MaxRapidity; for ( int i = 0, N = theOneCuts.size(); i < N; ++i ) mineta = max(mineta, theOneCuts[i]->minEta(p)); return mineta; } double Cuts::maxEta(tcPDPtr p) const { double maxeta = Constants::MaxRapidity; for ( int i = 0, N = theOneCuts.size(); i < N; ++i ) maxeta = min(maxeta, theOneCuts[i]->maxEta(p)); return maxeta; } double Cuts::minYStar(tcPDPtr p) const { if ( currentSHat() < ZERO ) return -Constants::MaxRapidity; if ( subMirror() ) { HoldFlag<> nomir(theSubMirror, false); return -maxYStar(p); } double etamin = minEta(p); double ytot = Y() + currentYHat(); if ( etamin > 0.0 ) { Energy minkt = minKT(p); Energy maxm = p->massMax(); return asinh(minkt*sinh(etamin)/sqrt(sqr(minkt) + sqr(maxm))) - ytot; } else { return etamin - ytot; } } double Cuts::maxYStar(tcPDPtr p) const { if ( currentSHat() < ZERO ) return Constants::MaxRapidity; if ( subMirror() ) { HoldFlag<> nomir(theSubMirror, false); return -minYStar(p); } double etamax = maxEta(p); double ytot = Y() + currentYHat(); if ( etamax > 0.0 ) { return etamax - ytot; } else { Energy minkt = minKT(p); Energy maxm = p->massMax(); return asinh(minkt*sinh(etamax)/sqrt(sqr(minkt) + sqr(maxm))) - ytot; } } double Cuts::minRapidityMax(tcPDPtr p) const { double minRapidityMax = -Constants::MaxRapidity; for ( int i = 0, N = theOneCuts.size(); i < N; ++i ) minRapidityMax = max(minRapidityMax, theOneCuts[i]->minRapidityMax(p)); return minRapidityMax; } double Cuts::maxRapidityMin(tcPDPtr p) const { double maxRapidityMin = Constants::MaxRapidity; for ( int i = 0, N = theOneCuts.size(); i < N; ++i ) maxRapidityMin = min(maxRapidityMin, theOneCuts[i]->maxRapidityMin(p)); return maxRapidityMin; } void Cuts::persistentOutput(PersistentOStream & os) const { os << ounit(theSMax, GeV2) << theY << ounit(theCurrentSHat, GeV2) << theCurrentYHat << ounit(theMHatMin, GeV) << ounit(theMHatMax, GeV) << theYHatMin << theYHatMax << theX1Min << theX1Max << theX2Min << theX2Max << ounit(theScaleMin, GeV2) << ounit(theScaleMax, GeV2) << theOneCuts << theTwoCuts << theMultiCuts << theJetFinder << theSubMirror << theCutWeight << theLastCutWeight << theFuzzyTheta; } void Cuts::persistentInput(PersistentIStream & is, int) { is >> iunit(theSMax, GeV2) >> theY >> iunit(theCurrentSHat, GeV2) >> theCurrentYHat >> iunit(theMHatMin, GeV) >> iunit(theMHatMax, GeV) >> theYHatMin >> theYHatMax >> theX1Min >> theX1Max >> theX2Min >> theX2Max >> iunit(theScaleMin, GeV2) >> iunit(theScaleMax, GeV2) >> theOneCuts >> theTwoCuts >> theMultiCuts >> theJetFinder >> theSubMirror >> theCutWeight >> theLastCutWeight >> theFuzzyTheta; } ClassDescription Cuts::initCuts; // Definition of the static class description member. Energy Cuts::maxMHatMin() const { return theMHatMax; } Energy Cuts::minMHatMax() const { return theMHatMin; } Energy2 Cuts::maxScaleMin() const { return theScaleMax; } Energy2 Cuts::minScaleMax() const { return theScaleMin; } double Cuts::maxYHatMin() const { return theYHatMax; } double Cuts::minYHatMax() const { return theYHatMin; } double Cuts::maxX1Min() const { return theX1Max; } double Cuts::minX1Max() const { return theX1Min; } double Cuts::maxX2Min() const { return theX2Max; } double Cuts::minX2Max() const { return theX2Min; } void Cuts::Init() { typedef double (ThePEG::Cuts::*IGFN)() const; typedef void (ThePEG::Cuts::*ISFN)(double); static ClassDocumentation documentation ("Cuts is a class for implementing kinematical cuts in ThePEG. The " "class itself only implements cuts on the total momentum of the hard " "sub-process, implemented as minimum and maximum values of \\f$x_1\\f$ " "and \\f$x_2\\f$ (or \\f$\\hat{s}\\f$ and \\f$\\hat{y}\\f$. Further cuts " "can be implemented either by inheriting from this base class, in which " "the virtual cut() function should be overridden, or by assigning " "objects of class OneCutBase, TwoCutBase and MultiCutBase defining " "cuts on single particles, pairs of particles and groups of " "particles respectively."); static Parameter interfaceMHatMin ("MHatMin", "The minimum allowed value of \\f$\\sqrt{\\hat{s}}\\f$.", &Cuts::theMHatMin, GeV, 2.0*GeV, ZERO, Constants::MaxEnergy, true, false, Interface::limited, 0, 0, 0, &Cuts::maxMHatMin, 0); interfaceMHatMin.setHasDefault(false); static Parameter interfaceMHatMax ("MHatMax", "The maximum allowed value of \\f$\\sqrt{\\hat{s}}\\f$.", &Cuts::theMHatMax, GeV, 100.0*GeV, ZERO, ZERO, true, false, Interface::lowerlim, 0, 0, &Cuts::minMHatMax, 0, 0); interfaceMHatMax.setHasDefault(false); static Parameter interfaceScaleMin ("ScaleMin", "The minimum allowed value of the scale to be used in PDFs and " "coupling constants.", &Cuts::theScaleMin, GeV2, ZERO, ZERO, Constants::MaxEnergy2, true, false, Interface::limited, 0, 0, 0, &Cuts::maxScaleMin, 0); interfaceScaleMin.setHasDefault(false); static Parameter interfaceScaleMax ("ScaleMax", "The maximum allowed value of the scale to be used in PDFs and " "coupling constants.", &Cuts::theScaleMax, GeV2, 10000.0*GeV2, ZERO, ZERO, true, false, Interface::lowerlim, 0, 0, &Cuts::minScaleMax, 0, 0); interfaceScaleMax.setHasDefault(false); static Parameter interfaceYHatMin ("YHatMin", "The minimum value of the rapidity of the hard sub-process " "(wrt. the rest system of the colliding particles).", &Cuts::theYHatMin, -10.0, 0.0, Constants::MaxRapidity, true, false, Interface::upperlim, (ISFN)0, (IGFN)0, (IGFN)0, &Cuts::maxYHatMin, (IGFN)0); interfaceYHatMin.setHasDefault(false); static Parameter interfaceYHatMax ("YHatMax", "The maximum value of the rapidity of the hard sub-process " "(wrt. the rest system of the colliding particles).", &Cuts::theYHatMax, 10.0, -Constants::MaxRapidity, 0.0, true, false, Interface::lowerlim, (ISFN)0, (IGFN)0, &Cuts::minYHatMax, (IGFN)0, (IGFN)0); interfaceYHatMax.setHasDefault(false); static Parameter interfaceX1Min ("X1Min", "The minimum value of the positive light-cone fraction of the hard " "sub-process.", &Cuts::theX1Min, 0.0, 0.0, 1.0, true, false, Interface::limited, (ISFN)0, (IGFN)0, (IGFN)0, &Cuts::maxX1Min, (IGFN)0); interfaceX1Min.setHasDefault(false); static Parameter interfaceX1Max ("X1Max", "The maximum value of the positive light-cone fraction of the hard " "sub-process.", &Cuts::theX1Max, 0.0, 0.0, 1.0, true, false, Interface::limited, (ISFN)0, (IGFN)0, &Cuts::minX1Max, (IGFN)0, (IGFN)0); interfaceX1Max.setHasDefault(false); static Parameter interfaceX2Min ("X2Min", "The minimum value of the negative light-cone fraction of the hard " "sub-process.", &Cuts::theX2Min, 0.0, 0.0, 1.0, true, false, Interface::limited, (ISFN)0, (IGFN)0, (IGFN)0, &Cuts::maxX2Min, (IGFN)0); interfaceX2Min.setHasDefault(false); static Parameter interfaceX2Max ("X2Max", "The maximum value of the negative light-cone fraction of the hard " "sub-process.", &Cuts::theX2Max, 0.0, 0.0, 1.0, true, false, Interface::limited, (ISFN)0, (IGFN)0, &Cuts::minX2Max, (IGFN)0, (IGFN)0); interfaceX2Max.setHasDefault(false); static RefVector interfaceOneCuts ("OneCuts", "The objects defining cuts on single outgoing partons from the " "hard sub-process.", &Cuts::theOneCuts, -1, true, false, true, false, false); static RefVector interfaceTwoCuts ("TwoCuts", "The objects defining cuts on pairs of particles in the " "hard sub-process.", &Cuts::theTwoCuts, -1, true, false, true, false, false); static RefVector interfaceMultiCuts ("MultiCuts", "The objects defining cuts on sets of outgoing particles from the " "hard sub-process.", &Cuts::theMultiCuts, -1, true, false, true, false, false); static Reference interfaceJetFinder ("JetFinder", "Set a JetFinder object used to define cuts on the" "level of reconstructed jets as needed for higher order corrections.", &Cuts::theJetFinder, false, false, true, true, false); static Reference interfaceFuzzy ("Fuzzy", "The fuzziness to be applied to cuts (may not be supported by all cut objects).", &Cuts::theFuzzyTheta, false, false, true, true, false); interfaceX1Min.rank(10); interfaceX1Max.rank(9); interfaceX2Min.rank(8); interfaceX2Max.rank(7); interfaceMHatMin.rank(6); interfaceMHatMax.rank(5); interfaceYHatMin.rank(4); interfaceYHatMax.rank(3); interfaceOneCuts.rank(2); interfaceTwoCuts.rank(1); } double Cuts::yHatMin() const { return theX1Min > 0.0 && theX2Max > 0.0? max(theYHatMin, 0.5*log(theX1Min/theX2Max)): theYHatMin; } double Cuts::yHatMax() const { return theX1Max > 0.0 && theX2Min > 0.0? min(theYHatMax, 0.5*log(theX1Max/theX2Min)): theYHatMax; } bool Cuts::yHat(double y) const { return y > yHatMin() && y < yHatMax(); } double Cuts::x1Min() const { return max(theX1Min, (theMHatMin/sqrt(SMax()))*exp(theYHatMin)); } double Cuts::x1Max() const { return min(theX1Max, (theMHatMax/sqrt(SMax()))*exp(theYHatMax)); } bool Cuts::x1(double x) const { return x > x1Min() && x <= x1Max(); } double Cuts::x2Min() const { return max(theX2Min, (theMHatMin/sqrt(SMax()))/exp(theYHatMax)); } double Cuts::x2Max() const { return min(theX2Max, (theMHatMax/sqrt(SMax()))/exp(theYHatMin)); } bool Cuts::x2(double x) const { return x > x2Min() && x <= x2Max(); } template vector::transient_const_pointer> Cuts::oneCutObjects() const { typedef typename Ptr::transient_const_pointer tcPtr; vector ret; for ( int i = 0, N = theOneCuts.size(); i < N; ++i ) if ( dynamic_ptr_cast(theOneCuts[i]) ) ret.push_back(dynamic_ptr_cast(theOneCuts[i])); return ret; } template vector::transient_const_pointer> Cuts::twoCutObjects() const { typedef typename Ptr::transient_const_pointer tcPtr; vector ret; for ( int i = 0, N = theTwoCuts.size(); i < N; ++i ) if ( dynamic_ptr_cast(theTwoCuts[i]) ) ret.push_back(dynamic_ptr_cast(theTwoCuts[i])); return ret; } template vector::transient_const_pointer> Cuts::multiCutObjects() const { typedef typename Ptr::transient_const_pointer tcPtr; vector ret; for ( int i = 0, N = theMultiCuts.size(); i < N; ++i ) if ( dynamic_ptr_cast(theMultiCuts[i]) ) ret.push_back(dynamic_ptr_cast(theMultiCuts[i])); return ret; } diff --git a/Cuts/Cuts.h b/Cuts/Cuts.h --- a/Cuts/Cuts.h +++ b/Cuts/Cuts.h @@ -1,838 +1,838 @@ // -*- C++ -*- // // Cuts.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_Cuts_H #define THEPEG_Cuts_H // // This is the declaration of the Cuts class. // #include "ThePEG/Interface/Interfaced.h" #include "Cuts.fh" #include "OneCutBase.h" #include "TwoCutBase.h" #include "MultiCutBase.h" #include "JetFinder.h" #include "FuzzyTheta.h" namespace ThePEG { /** * Cuts is a class for implementing kinematical cuts in ThePEG. The * class itself only implements cuts on the total momentum of the hard * sub-process, implemented as minimum and maximum values of \f$x_1\f$ * and \f$x_2\f$ (or \f$\hat{s}=x_1x_2S_{tot}\f$ and * \f$\hat{y}=\log(x_1/x_2)/2\f$. Further cuts can be implemented * either by inheriting from this base class, in which the virtual * cut() function should be overridden, or by assigning objects of * class OneCutBase, TwoCutBase and MultiCutBase defining cuts on * single particles, pairs of particles and groups of particles in the * hard sub-process respectively. * * The Cuts object must be initialized specifying the overall * laboratory frame, giving the total squared invariant mass, \f$S\f$, * and the rapidity, \f$Y\f$, of the colliding particles in this * frame. The colliding particles are thus assumed to be directed * along the \f$z\f$-axis. * * For each event, the Cuts object must also be initialized giving the * squared invarint mass, \f$\hat{s}\f$, and the total rapidity, * \f$\hat{y}\f$, of the hard sub-process in the center-of-mass frame * of the colliding particles. Note that this means that the * transformation between the lab frame and the rest frame of the hard * sub-process is assumed to be a simple boost along the z-axis. * * @see \ref CutsInterfaces "The interfaces" * defined for Cuts. */ class Cuts: public Interfaced { public: /** * A vector of OneCutBase pointers. */ typedef vector OneCutVector; /** * A vector of TwoCutBase pointers. */ typedef vector TwoCutVector; /** * A vector of MultiCutBase pointers. */ typedef vector MultiCutVector; public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ Cuts(Energy MhatMin=2*GeV); /** * The destructor. */ virtual ~Cuts(); //@} public: /** @name Initialization functions. */ //@{ /** * Initialize this object specifying the maximum total invariant * mass squared, \a smax, and the total rapidity, \a Y, of the * colliding particles (for the maximum invariant mass). A sub-class * overriding this function must make sure the base-class function * is called. This function should be called once in the beginning * of a run. */ virtual void initialize(Energy2 smax, double Y); /** * Initialize this object for a new event. A sub-class overriding * this function must make sure the base-class function is called. * This function is called before the generation of a new * sub-process, before the incoming partons have been generated. */ virtual void initEvent(); /** * Set information about the invariant mass squared, \a shat, and * rapidity, \a yhat, of the hard sub-process. The rapidity should * be given wrt. the center of mass of the colliding particles. A * sub-class overriding this function must make sure the base-class * function is called. This function is called before the generation * of a new sub-process, after the incoming partons have been * generated. If \a mirror is true any questions regarding cuts on * the sub-process in the functions minYStar(tcPDPtr), * maxYStar(tcPDPtr p), passCuts(const tcPDVector &, const * vector &, tcPDPtr, tcPDPtr) and passCuts(const * tcPVector &, tcPDPtr t1, tcPDPtr) will assume that the z-axis is * reversed in the sub-process rest frame. Returns false if the * given values were outside of the cuts. */ virtual bool initSubProcess(Energy2 shat, double yhat, bool mirror = false) const; //@} /** @name Check functions to see if a state has passed the cuts or not. */ //@{ /** * Check if the outgoing particles, with the given types and * momenta, from a sub-process passes the cuts. The particles must * be given in the rest frame of tha hard sub-process, and the * initSubProcess must have been called before. Also the types of * the incoming partons, \a t1 and \a t2, may be given if availible. */ virtual bool passCuts(const tcPDVector & ptype, const vector & p, tcPDPtr t1 = tcPDPtr(), tcPDPtr t2 = tcPDPtr()) const; /** * Check if the outgoing particles from a sub-process passes the * cuts. The particles must be given in the rest frame of tha hard * sub-process, and the initSubProcess must have been called * before. Also the types of the incoming partons, \a t1 and \a t2, * may be given if availible. */ bool passCuts(const tcPVector & p, tcPDPtr t1 = tcPDPtr(), tcPDPtr t2 = tcPDPtr()) const; /** * Check if the incoming and outgoing particles in the given * sub-process passes the cuts. The sub-process must be given in its * rest frame, and the initSubProcess must have been called before. */ bool passCuts(const SubProcess & sub) const; /** * Check if the given collision passes the cuts. The collision must * be given in its rest frame. */ bool passCuts(const Collision & coll) const; //@} /** @name Access to cuts of the underlying cut objects. */ //@{ /** * Return the minimum allowed squared invariant mass of two outgoing * partons of type \a pi and \a pj. This function first determines * the minimum from the corresponding function from in TwoCutBase * objects. If no minimum was found, one is derived from * minKTClus(), minDurham(), minKT() and minDeltaR(), if possible. */ Energy2 minSij(tcPDPtr pi, tcPDPtr pj) const; /** * Return the minimum allowed value of the negative of the squared * invariant mass of an incoming parton of type \a pi and an * outgoing parton of type \a po. This function first determines the * minimum from the corresponding function from in TwoCutBase * objects. If no minimum was found, one is derived from minKT(), if * possible. */ Energy2 minTij(tcPDPtr pi, tcPDPtr po) const; /** * Return the minimum allowed value of \f$\Delta * R_{ij}=\sqrt{\Delta\eta_{ij}^2+\Delta\phi_{ij}^2}\f$ of two * outgoing partons of type \a pi and \a pj. Simply returns the * maximum of the results from calling the corresponding function in * the TwoCutBase objects. */ double minDeltaR(tcPDPtr pi, tcPDPtr pj) const; /** * Return the minimum allowed value of the longitudinally invariant * \f$k_\perp\f$-algorithms distance measure. This is defined as * \f$\min(p_{\perp i}, p_{\perp * j})\sqrt{\Delta\eta_{ij}^2+\Delta\phi_{ij}^2}\f$ for two outgoing * partons, or simply \f$p_{\perp i}\f$ or \f$p_{\perp j}\f$ for a * single outgoing parton. Returns 0 if both partons are incoming. A * null pointer indicates an incoming parton, hence the type of the * incoming parton is irrelevant. Simply returns the maximum of the * results from calling the corresponding function in the TwoCutBase * objects. */ Energy minKTClus(tcPDPtr pi, tcPDPtr pj) const; /** * Return the minimum allowed value of the Durham * \f$k_\perp\f$-algorithms distance measure. This is defined as * \f$2\min(E_j^2, E_j^2)(1-\cos\theta_{ij})/\hat{s}\f$ for two * outgoing partons. Simply returns the maximum of the results from * calling the corresponding function in the TwoCutBase objects. */ double minDurham(tcPDPtr pi, tcPDPtr pj) const; /** * Return the minimum allowed value of the transverse momentum of an * outgoing parton. This function first determines the minimum from * the corresponding function from in OneCutBase objects. If no * minimum was found, one is derived from minKTClus(), if possible. */ Energy minKT(tcPDPtr p) const; /** * Return the minimum allowed pseudo-rapidity of an outgoing parton * of the given type. The pseudo-rapidity is measured in the lab * system. Simply returns the maximum of the results from calling * the corresponding function in the OneCutBase objects. */ double minEta(tcPDPtr p) const; /** * Return the maximum allowed pseudo-rapidity of an outgoing parton * of the given type. The pseudo-rapidity is measured in the lab * system. Simply returns the minimum of the results from calling * the corresponding function in the OneCutBase objects. */ double maxEta(tcPDPtr p) const; /** * Return the minimum allowed rapidity of an outgoing parton * of the given type. The rapidity is measured in the lab * system. Simply returns the maximum of the results from calling * the corresponding function in the OneCutBase objects. */ double minRapidityMax(tcPDPtr p) const; /** * Return the maximum allowed rapidity of an outgoing parton * of the given type. The rapidity is measured in the lab * system. Simply returns the minimum of the results from calling * the corresponding function in the OneCutBase objects. */ double maxRapidityMin(tcPDPtr p) const; /** * Return the minimum allowed rapidity of an outgoing parton of the * given type in the center-of-mass system of the hard sub-process. * Only available after initSubProcess() has been called. */ double minYStar(tcPDPtr p) const; /** * Return the minimum allowed rapidity of an outgoing parton of the * given type in the center-of-mass system of the hard sub-process. * Only available after initSubProcess() has been called. */ double maxYStar(tcPDPtr p) const; /** * Return the minimum allowed value of the squared invariant mass of * a set of outgoing partons of the given types. Typically used to * cut off the tails of the mass of a resonance for * efficiency. Simply returns the maximum of the results from * calling the corresponding function in the MultiCutBase objects. */ Energy2 minS(const tcPDVector & pv) const; /** * Return the maximum allowed value of the squared invariant mass of * a set of outgoing partons of the given types. Typically used to * cut off the tails of the mass of a resonance for * efficiency. Simply returns the minimum of the results from * calling the corresponding function in the MultiCutBase objects. */ Energy2 maxS(const tcPDVector & pv) const; //@} /** @name Direct access to underlying cut objects. */ //@{ /** * Return a vector of pointers to objects of the given class (with * base class OneCutBase). */ template vector::transient_const_pointer> oneCutObjects() const; /** * Return a vector of pointers to objects of the given class (with * base class TwoCutBase). */ template vector::transient_const_pointer> twoCutObjects() const; /** * Return a vector of pointers to objects of the given class (with * base class MultiCutBase). */ template vector::transient_const_pointer> multiCutObjects() const; /** * Return the objects defining cuts on single outgoing partons from the * hard sub-process. */ const OneCutVector& oneCuts() const { return theOneCuts; } /** * Return the objects defining cuts on pairs of particles in the hard * sub-process. */ const TwoCutVector& twoCuts() const { return theTwoCuts; } /** * Return the objects defining cuts on sets of outgoing particles from the * hard sub-process. */ const MultiCutVector& multiCuts() const { return theMultiCuts; } /** * Return the jet finder */ Ptr::tptr jetFinder() const { return theJetFinder; } /** * Add a OneCutBase object. */ void add(tOneCutPtr c) { theOneCuts.push_back(c); } /** * Add a TwoCutBase object. */ void add(tTwoCutPtr c) { theTwoCuts.push_back(c); } /** * Add a MultiCutBase object. */ void add(tMultiCutPtr c) { theMultiCuts.push_back(c); } //@} public: /** @name Simple access functions. */ //@{ /** * The maximum allowed total invariant mass squared allowed for * events to be considered. */ Energy2 SMax() const { return theSMax; } /** * The total rapidity of the colliding particles corresponding to * the maximum invariant mass squared, SMax(). */ double Y() const { return theY; } /** * The invariant mass squared of the hard sub-process of the event * being considered. */ Energy2 currentSHat() const { return theCurrentSHat; } /** * The total rapidity of hard sub-process (wrt. the rest system of * the colliding particles so that currentYHat() + Y() gives the * true rapidity) of the event being considered. */ double currentYHat() const { return theCurrentYHat; } //@} /** @name Functions to inquire about specific cuts. */ //@{ /** * The minimum allowed value of \f$\hat{s}\f$. */ Energy2 sHatMin() const { return max(sqr(theMHatMin), theX1Min*theX2Min*SMax()); } /** * The maximum allowed value of \f$\hat{s}\f$. */ Energy2 sHatMax() const { return min(sqr(theMHatMax), theX1Max*theX2Max*SMax()); } /** * Check if the given \f$\hat{s}\f$ is within the cuts. */ bool sHat(Energy2 sh) const { return sh > sHatMin() && sh <= sHatMax()*(1.0 + 1000.0*Constants::epsilon); } /** * The minimum allowed value of \f$\sqrt{\hat{s}}\f$. */ Energy mHatMin() const { return max(theMHatMin, sqrt(theX1Min*theX2Min*SMax())); } /** * The maximum allowed value of \f$\sqrt{\hat{s}}\f$. */ Energy mHatMax() const { return min(theMHatMax, sqrt(theX1Max*theX2Max*SMax())); } /** * The minimum value of the rapidity of the hard sub-process * (wrt. the rest system of the colliding particles). */ double yHatMin() const; /** * The maximum value of the rapidity of the hard sub-process * (wrt. the rest system of the colliding particles). */ double yHatMax() const; /** * Check if the given \f$\hat{y}\f$ is within the cuts. */ bool yHat(double y) const; /** * The minimum value of the positive light-cone fraction of the hard * sub-process. */ double x1Min() const; /** * The maximum value of the positive light-cone fraction of the hard * sub-process. */ double x1Max() const; /** * Check if the given \f$x_1\f$ is within the cuts. */ bool x1(double x) const; /** * The minimum value of the negative light-cone fraction of the hard * sub-process. */ double x2Min() const; /** * The maximum value of the negative light-cone fraction of the hard * sub-process. */ double x2Max() const; /** * Check if the given \f$x_2\f$ is within the cuts. */ bool x2(double x) const; /** * The minimum allowed value of the scale to be used in PDF's and * coupling constants. */ Energy2 scaleMin() const { return theScaleMin; } /** * The maximum allowed value of the scale to be used in PDF's and * coupling constants. */ Energy2 scaleMax() const { return theScaleMax; } /** * Check if the given scale is within the cuts. */ bool scale(Energy2 Q2) const { return Q2 > scaleMin() && Q2 < scaleMax(); } /** * Set true if a matrix element is should be using this cut and is * mirrored along the z-axis . */ bool subMirror() const { return theSubMirror; } /** * Return the overall cut weight */ double cutWeight() const { return theCutWeight; } /** * Set the cut weight as appropriate from the call to the last n-cut * object. */ void lastCutWeight(double w) const { theLastCutWeight = w; } /** * Return the fuzziness object */ Ptr::tcptr fuzzy() const { return theFuzzyTheta; } /** * Check for value inside the given bounds and update the weight */ template bool isInside(const Value& v, const Value& lower, const Value& upper, double& weight) const { if ( !fuzzy() ) { if ( v >= lower && v <= upper ) return true; weight = 0.0; return false; } return fuzzy()->isInside(v,lower,upper,weight); } /** * Check for value inside the given bounds and update the weight */ template bool isLessThan(const Value& v, const Value& upper, double& weight) const { if ( !fuzzy() ) { if ( v <= upper ) return true; weight = 0.0; return false; } return fuzzy()->isLessThan(v,upper,weight); } /** * Check for value inside the given bounds and update the weight */ template bool isLargerThan(const Value& v, const Value& lower, double& weight) const { if ( !fuzzy() ) { if ( v >= lower ) return true; weight = 0.0; return false; } return fuzzy()->isLargerThan(v,lower,weight); } //@} public: /** * Describe the currently active cuts in the log file. */ virtual void describe() const; protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * Helper function used by the interface. */ Energy maxMHatMin() const; /** * Helper function used by the interface. */ Energy minMHatMax() const; /** * Helper function used by the interface. */ double maxYHatMin() const; /** * Helper function used by the interface. */ double minYHatMax() const; /** * Helper function used by the interface. */ double maxX1Min() const; /** * Helper function used by the interface. */ double minX1Max() const; /** * Helper function used by the interface. */ double maxX2Min() const; /** * Helper function used by the interface. */ double minX2Max() const; /** * Helper function used by the interface. */ Energy2 maxScaleMin() const; /** * Helper function used by the interface. */ Energy2 minScaleMax() const; private: /** * The maximum allowed total invariant mass squared allowed for * events to be considered. */ Energy2 theSMax; /** * The total rapidity of the colliding particles corresponding to * the maximum invariant mass squared, SMax(). */ double theY; /** * The invariant mass squared of the hard sub-process of the event * being considered. */ mutable Energy2 theCurrentSHat; /** * The total rapidity of hard sub-process (wrt. the rest system of * the colliding particles so that currentYHat() + Y() gives the * true rapidity) of the event being considered. */ mutable double theCurrentYHat; /** * The minimum allowed value of \f$\sqrt{\hat{s}}\f$. */ Energy theMHatMin; /** * The maximum allowed value of \f$\sqrt{\hat{s}}\f$. */ Energy theMHatMax; /** * The minimum value of the rapidity of the hard sub-process * (wrt. the rest system of the colliding particles). */ double theYHatMin; /** * The maximum value of the rapidity of the hard sub-process * (wrt. the rest system of the colliding particles). */ double theYHatMax; /** * The minimum value of the positive light-cone fraction of the hard * sub-process. */ double theX1Min; /** * The maximum value of the positive light-cone fraction of the hard * sub-process. */ double theX1Max; /** * The minimum value of the negative light-cone fraction of the hard * sub-process. */ double theX2Min; /** * The maximum value of the negative light-cone fraction of the hard * sub-process. */ double theX2Max; /** * The minimum allowed value of the scale to be used in PDF's and * coupling constants. */ Energy2 theScaleMin; /** * The maximum allowed value of the scale to be used in PDF's and * coupling constants. */ Energy2 theScaleMax; /** * The objects defining cuts on single outgoing partons from the * hard sub-process. */ OneCutVector theOneCuts; /** * The objects defining cuts on pairs of particles in the hard * sub-process. */ TwoCutVector theTwoCuts; /** * The objects defining cuts on sets of outgoing particles from the * hard sub-process. */ MultiCutVector theMultiCuts; /** * An optional jet finder used to define cuts on the level of * reconstructed jets. */ Ptr::ptr theJetFinder; /** * Set to true if a matrix element is should be using this cut and is * mirrored along the z-axis . */ mutable bool theSubMirror; /** * The overall cut weight */ mutable double theCutWeight; /** * The cut weight as appropriate from the call to the last n-cut * object. */ mutable double theLastCutWeight; /** * The fuzziness object */ Ptr::ptr theFuzzyTheta; private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initCuts; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ Cuts & operator=(const Cuts &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of Cuts. */ template <> struct BaseClassTrait { /** Typedef of the first base class of Cuts. */ typedef Interfaced NthBase; }; /** This template specialization informs ThePEG about the name of * the Cuts 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::Cuts"; } }; /** @endcond */ } #endif /* THEPEG_Cuts_H */ diff --git a/Cuts/DeltaMeasureCuts.cc b/Cuts/DeltaMeasureCuts.cc --- a/Cuts/DeltaMeasureCuts.cc +++ b/Cuts/DeltaMeasureCuts.cc @@ -1,122 +1,122 @@ // -*- C++ -*- // // DeltaMeasureCuts.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the DeltaMeasureCuts class. // #include "DeltaMeasureCuts.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/Cuts/Cuts.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Repository/CurrentGenerator.h" #include "ThePEG/PDT/MatcherBase.h" using namespace ThePEG; void DeltaMeasureCuts::describe() const { CurrentGenerator::log() << fullName() << ":\n" << "MinDeltaR = " << theMinDeltaR << " \n" << "MinDeltaEta = " << theMinDeltaEta << " \n\n"; } IBPtr DeltaMeasureCuts::clone() const { return new_ptr(*this); } IBPtr DeltaMeasureCuts::fullclone() const { return new_ptr(*this); } Energy DeltaMeasureCuts::minDeltaMeasureCuts(tcPDPtr, tcPDPtr) const { return ZERO; } Energy2 DeltaMeasureCuts::minSij(tcPDPtr, tcPDPtr) const { return ZERO; } Energy2 DeltaMeasureCuts::minTij(tcPDPtr, tcPDPtr) const { return ZERO; } Energy DeltaMeasureCuts::minKTClus(tcPDPtr, tcPDPtr) const { return ZERO; } double DeltaMeasureCuts::minDeltaR(tcPDPtr, tcPDPtr) const { return theMinDeltaR; } double DeltaMeasureCuts::minDurham(tcPDPtr, tcPDPtr) const { return 0.0; } bool DeltaMeasureCuts::passCuts(tcCutsPtr, tcPDPtr pitype, tcPDPtr pjtype, LorentzMomentum pi, LorentzMomentum pj, bool inci, bool incj) const { if ( theMatcher && !theMatcher->matches(*pitype) ) return true; if ( theMatcher && !theMatcher->matches(*pjtype) ) return true; if ( inci || incj ) return true; else { double deta2 = sqr(pi.eta() - pj.eta()); if (abs(pi.eta() - pj.eta()) <= theMinDeltaEta) return false; double dphi = abs(pi.phi() - pj.phi()); if ( dphi > Constants::pi ) dphi = 2.0*Constants::pi - dphi; double dr = sqrt(deta2 + sqr(dphi)); if ( dr <= theMinDeltaR ) return false; } return true; } void DeltaMeasureCuts::persistentOutput(PersistentOStream & os) const { os << theMinDeltaEta << theMinDeltaR << theMatcher; } void DeltaMeasureCuts::persistentInput(PersistentIStream & is, int) { is >> theMinDeltaEta >> theMinDeltaR >> theMatcher; } ClassDescription DeltaMeasureCuts::initDeltaMeasureCuts; // Definition of the static class description member. void DeltaMeasureCuts::Init() { static ClassDocumentation documentation ("This clas implements the cuts relevant for the " "\\f$\\Delta R\\f$-measure in the longitudinally invariant " "kt-algorithm. By default the cut is only applied to coloured " "particles, but optionally it may be applied to all particle types."); static Parameter interfaceMinDeltaR ("MinDeltaR", "The minimum allowed legoplot distance ", &DeltaMeasureCuts::theMinDeltaR, 0.7, 0.0, 10.0, false, false, Interface::limited); static Parameter interfaceMinDeltaEta ("MinDeltaEta", "The minimum allowed rapidity separation ", &DeltaMeasureCuts::theMinDeltaEta, 0.0, 0.0, 10.0, false, false, Interface::limited); static Reference interfaceMatcher ("Matcher", "If non-null only particles matching this object will be affected " "by the cut.", &DeltaMeasureCuts::theMatcher, true, false, true, true, false); } diff --git a/Cuts/DeltaMeasureCuts.h b/Cuts/DeltaMeasureCuts.h --- a/Cuts/DeltaMeasureCuts.h +++ b/Cuts/DeltaMeasureCuts.h @@ -1,215 +1,215 @@ // -*- C++ -*- // // DeltaMeasureCuts.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_DeltaMeasureCuts_H #define THEPEG_DeltaMeasureCuts_H // // This is the declaration of the DeltaMeasureCuts class. // #include "ThePEG/Cuts/TwoCutBase.h" #include "ThePEG/PDT/MatcherBase.h" namespace ThePEG { /** * This class implements a cuts on legoplot and rapidity separation * * @see \ref DeltaMeasureCutsInterfaces "The interfaces" * defined for DeltaMeasureCuts. */ class DeltaMeasureCuts: public TwoCutBase { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ DeltaMeasureCuts() : theMinDeltaR(0.0), theMinDeltaEta(0.0) {} //@} public: /** @name Overridden virtual functions defined in the base class. */ //@{ /** * Return the minimum allowed value of the longitudinally invariant * \f$k_\perp\f$-algorithms distance measure. This is defined as * \f$\min(p_{\perp i}, p_{\perp * j})\sqrt{\Delta\eta_{ij}^2+\Delta\phi_{ij}^2}\f$ for two outgoing * partons, or simply \f$p_{\perp i}\f$ or \f$p_{\perp j}\f$ for a * single outgoing parton. Returns 0 if both partons are incoming. A * null pointer indicates an incoming parton, hence the type of the * incoming parton is irrelevant. */ virtual Energy minDeltaMeasureCuts(tcPDPtr pi, tcPDPtr pj) const; /** * Return the minimum allowed value of the longitudinally invariant * \f$k_\perp\f$-algorithms distance measure. Returns ZERO. */ virtual Energy minKTClus(tcPDPtr pi, tcPDPtr pj) const; /** * Return the minimum allowed squared invariant mass of two outgoing * partons of type \a pi and \a pj. Returns zero. */ virtual Energy2 minSij(tcPDPtr pi, tcPDPtr pj) const; /** * Return the minimum allowed value of the negative of the squared * invariant mass of an incoming parton of type \a pi and an * outgoing parton of type \a po. Returns zero. */ virtual Energy2 minTij(tcPDPtr pi, tcPDPtr po) const; /** * Return the minimum allowed value of \f$\Delta * R_{ij}=\sqrt{\Delta\eta_{ij}^2+\Delta\phi_{ij}^2}\f$ of two * outgoing partons of type \a pi and \a pj. Returns zero. */ virtual double minDeltaR(tcPDPtr pi, tcPDPtr pj) const; /** * Return the minimum allowed value of the Durham * \f$k_\perp\f$-algorithms distance measure. This is defined as * \f$2\min(E_j^2, E_j^2)(1-\cos\theta_{ij})/\hat{s}\f$ for two * outgoing partons. Returns zero. */ virtual double minDurham(tcPDPtr pi, tcPDPtr pj) const; /** * Return true if a pair of particles with type \a pitype and \a * pjtype and momenta \a pi and \a pj respectively passes the * cuts. \a inci and \a inj indicates if the corresponding particles * are incoming. */ virtual bool passCuts(tcCutsPtr parent, tcPDPtr pitype, tcPDPtr pjtype, LorentzMomentum pi, LorentzMomentum pj, bool inci = false, bool incj = false) const; //@} /** * Describe the currently active cuts in the log file. */ virtual void describe() const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * The minimum allowed legoplot separation */ double theMinDeltaR; /** * The minimum allowed rapidity separation */ double theMinDeltaEta; /** * If non-null only particles matching this object will be affected * by this cut. */ PMPtr theMatcher; private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initDeltaMeasureCuts; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ DeltaMeasureCuts & operator=(const DeltaMeasureCuts &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of DeltaMeasureCuts. */ template <> struct BaseClassTrait { /** Typedef of the first base class of DeltaMeasureCuts. */ typedef TwoCutBase NthBase; }; /** This template specialization informs ThePEG about the name of * the DeltaMeasureCuts 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::DeltaMeasureCuts"; } /** Return the name of the shared library be loaded to get * access to the DeltaMeasureCuts class and every other class it uses * (except the base class). */ static string library() { return "DeltaMeasureCuts.so"; } }; /** @endcond */ } #endif /* THEPEG_DeltaMeasureCuts_H */ diff --git a/Cuts/FastJetFinder.cc b/Cuts/FastJetFinder.cc --- a/Cuts/FastJetFinder.cc +++ b/Cuts/FastJetFinder.cc @@ -1,297 +1,297 @@ // -*- C++ -*- // // FastJetFinder.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad -// Copyright (C) 2009-2017 Simon Platzer +// Copyright (C) 1999-2019 Leif Lonnblad +// Copyright (C) 2009-2019 Simon Platzer // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the FastJetFinder class. // #include "FastJetFinder.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Repository/CurrentGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Cuts/Cuts.h" #include "fastjet/ClusterSequence.hh" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG; FastJetFinder::FastJetFinder() : theDCut(ZERO), theConeRadius(0.7), theVariant(kt), theMode(inclusive), theRecombination(recoE) {} FastJetFinder::~FastJetFinder() {} void FastJetFinder::doinit() { fastjet::ClusterSequence::set_fastjet_banner_stream(0); } void FastJetFinder::doinitrun() { fastjet::ClusterSequence::set_fastjet_banner_stream(& CurrentGenerator::log()); // Force banner to be printed right now; suppresses later output. fastjet::ClusterSequence::print_banner(); } IBPtr FastJetFinder::clone() const { return new_ptr(*this); } IBPtr FastJetFinder::fullclone() const { return new_ptr(*this); } void FastJetFinder::describe() const { generator()->log() << "'" << name() << "' clustering jets from constituents matched by '" << unresolvedMatcher()->name() << "'\n" << "into " << (theMode == inclusive ? "inclusive" : "exclusive") << " jets recombining with the " << (theRecombination == recoPt ? "pt" : "E") << " scheme\n"; generator()->log() << "The measure used is "; switch(theVariant) { case 1: generator()->log() << "kt"; break; case 2: generator()->log() << "CA"; break; case 3: generator()->log() << "antiKt"; break; case 4: generator()->log() << "sphericalKt"; break; case 5: generator()->log() << "sphericalCA"; break; case 6: generator()->log() << "sphericalAntiKt"; break; default: assert(false); } generator()->log() << "\n"; generator()->log() << "The cone radius is R = " << theConeRadius << "\n"; if ( theMode == exclusive ) { generator()->log() << "The exclusive resolution scale in GeV is D = " << sqrt(theDCut/GeV2) << "\n"; } generator()->log() << flush; } bool FastJetFinder::cluster(tcPDVector & ptype, vector & p, tcCutsPtr, tcPDPtr, tcPDPtr) const { if ( ptype.size() <= minOutgoing() ){ return false; } tcPDVector::iterator di = ptype.begin(); vector::iterator pi = p.begin(); size_t index = 0; vector recombinables; tcPDVector ptypeBuffer; vector pBuffer; for ( ; di != ptype.end(); ++di, ++pi, index++ ) { if ( !unresolvedMatcher()->check(**di) ) { ptypeBuffer.push_back(*di); pBuffer.push_back(*pi); continue; } recombinables.push_back(fastjet::PseudoJet( (*pi).x()/GeV,(*pi).y()/GeV,(*pi).z()/GeV, (*pi).t()/GeV )); recombinables.back().set_user_index(index); } fastjet::Strategy strategy = fastjet::Best; fastjet::RecombinationScheme recomb_scheme; if ( theRecombination == recoE ) recomb_scheme = fastjet::E_scheme; else if ( theRecombination == recoPt) recomb_scheme = fastjet::pt_scheme; else assert(false); fastjet::JetAlgorithm jet_algorithm = fastjet::kt_algorithm; if ( theVariant == CA ) { jet_algorithm = fastjet::cambridge_algorithm; } else if ( theVariant == antiKt ) { jet_algorithm = fastjet::antikt_algorithm; } else if ( theVariant > 3 ) { jet_algorithm = fastjet::ee_genkt_algorithm; } fastjet::JetDefinition jet_def; if ( theVariant < 4 ) { jet_def = fastjet::JetDefinition(jet_algorithm, theConeRadius, recomb_scheme, strategy); } else { int power = 1; if ( theVariant == sphericalCA ) { power = 0; } if ( theVariant == sphericalAntiKt ) { power = -1; } jet_def = fastjet::JetDefinition(jet_algorithm, theConeRadius, power, recomb_scheme, strategy); } fastjet::ClusterSequence clust_seq(recombinables, jet_def); double dcut = 0.0; if ( theVariant != antiKt && theVariant != sphericalAntiKt ) { dcut = theDCut/GeV2; } else { dcut = theDCut != ZERO ? GeV2/theDCut : ZERO; } vector recoJets; if ( theMode == inclusive ) recoJets = clust_seq.inclusive_jets(); else if ( theMode == exclusive ) recoJets = clust_seq.exclusive_jets(dcut); if ( recoJets.size() + pBuffer.size() == p.size() ){ return false; } else { tcPDVector ptypeNew; vector pNew; for (vector::const_iterator iter = recoJets.begin(); iter != recoJets.end(); iter++){ ptypeNew.push_back(ptype[iter->constituents().begin()->user_index()]); pNew.push_back(LorentzMomentum(iter->px()*GeV, iter->py()*GeV, iter->pz()*GeV, iter->E()*GeV)); } di = ptypeBuffer.begin(); pi = pBuffer.begin(); for (; di != ptypeBuffer.end(); di++, pi++){ ptypeNew.push_back(*di); pNew.push_back(*pi); } ptype = ptypeNew; p = pNew; return true; } } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void FastJetFinder::persistentOutput(PersistentOStream & os) const { os << ounit(theDCut,GeV2) << theConeRadius << theVariant << theMode << theRecombination; } void FastJetFinder::persistentInput(PersistentIStream & is, int) { is >> iunit(theDCut,GeV2) >> theConeRadius >> theVariant >> theMode >> theRecombination; } // *** Attention *** The following static variable is needed for the type // description system in ThePEG. Please check that the template arguments // are correct (the class and its base class), and that the constructor // arguments are correct (the class name and the name of the dynamically // loadable library where the class implementation can be found). DescribeClass describeFastJetFinder("ThePEG::FastJetFinder", "FastJetFinder.so"); void FastJetFinder::Init() { static ClassDocumentation documentation ("FastJetFinder implements the class of longitudinally invariant kt " "jet clustering algorithms, as relevant for cuts on the real " "emission contribution to a NLO calculation. Recombination is " "exclusively performed using the pt scheme."); static Parameter interfaceDCut ("DCut", "The distance cut, when acting exclusively. " "The inverse is taken for the anti-kt algorithm, " "while for the Cambridge/Aachen variant dCut/GeV2 is used.", &FastJetFinder::theDCut, GeV2, 0.0*GeV2, 0.0*GeV2, 0*GeV2, false, false, Interface::lowerlim); static Parameter interfaceConeRadius ("ConeRadius", "The cone radius R used in inclusive mode.", &FastJetFinder::theConeRadius, 0.7, 0.0, 10.0, false, false, Interface::limited); static Switch interfaceVariant ("Variant", "The variant to use.", &FastJetFinder::theVariant, kt, false, false); static SwitchOption interfaceVariantKt (interfaceVariant, "Kt", "Kt algorithm.", kt); static SwitchOption interfaceVariantCA (interfaceVariant, "CA", "Cambridge/Aachen algorithm.", CA); static SwitchOption interfaceVariantAntiKt (interfaceVariant, "AntiKt", "Anti kt algorithm.", antiKt); static SwitchOption interfaceVariantSphericalKt (interfaceVariant, "SphericalKt", "Spherical kt algorithm.", sphericalKt); static SwitchOption interfaceVariantSphericalCA (interfaceVariant, "SphericalCA", "Spherical Cambridge/Aachen algorithm.", sphericalCA); static SwitchOption interfaceVariantSphericalAntiKt (interfaceVariant, "SphericalAntiKt", "Spherical anti kt algorithm.", sphericalAntiKt); static Switch interfaceMode ("Mode", "The mode to use.", &FastJetFinder::theMode, inclusive, false, false); static SwitchOption interfaceModeInclusive (interfaceMode, "Inclusive", "Find inclusive jets.", inclusive); static SwitchOption interfaceModeExclusive (interfaceMode, "Exclusive", "Find exclusive jets.", exclusive); static Switch interfaceRecombination ("RecombinationScheme", "The recombination scheme to use.", &FastJetFinder::theRecombination, recoE, false, false); static SwitchOption interfaceRecombinationPt (interfaceRecombination, "Pt", "Add transverse momenta", recoPt); static SwitchOption interfaceRecombinationE (interfaceRecombination, "E", "Add the four-momenta", recoE); } diff --git a/Cuts/FastJetFinder.h b/Cuts/FastJetFinder.h --- a/Cuts/FastJetFinder.h +++ b/Cuts/FastJetFinder.h @@ -1,187 +1,187 @@ // -*- C++ -*- // // FastJetFinder.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad -// Copyright (C) 2009-2017 Simon Platzer +// Copyright (C) 1999-2019 Leif Lonnblad +// Copyright (C) 2009-2019 Simon Platzer // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_FastJetFinder_H #define THEPEG_FastJetFinder_H // // This is the declaration of the FastJetFinder class. // #include "ThePEG/Cuts/JetFinder.h" namespace ThePEG { /** * FastJetFinder implements the class of longitudinally invariant kt * jet clustering algorithms. * * @see \ref FastJetFinderInterfaces "The interfaces" * defined for FastJetFinder. */ class FastJetFinder: public JetFinder { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ FastJetFinder(); /** * The destructor. */ virtual ~FastJetFinder(); //@} public: /** * Perform jet clustering on the given outgoing particles. * Optionally, information on the incoming particles is provided. * Return true, if a clustering has been performed. */ virtual bool cluster(tcPDVector & ptype, vector & p, tcCutsPtr parent, tcPDPtr t1 = tcPDPtr(), tcPDPtr t2 = tcPDPtr()) const; /** * Describe this jet fined. */ virtual void describe() const; public: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object. Called in the read phase. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); //@} /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The resolution cut. */ Energy2 theDCut; /** * The `cone radius' R. */ double theConeRadius; /** * The possible variants. */ enum variants { kt = 1, CA = 2, antiKt = 3, sphericalKt = 4, sphericalCA = 5, sphericalAntiKt = 6 }; /** * The variant. */ int theVariant; /** * The possible modes. */ enum modes { inclusive = 1, exclusive = 2 }; /** * The mode. */ int theMode; /** * The possible recombination schemes. */ enum recombinations { recoPt = 1, recoE = 2 }; /** * The recombination scheme */ int theRecombination; private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FastJetFinder & operator=(const FastJetFinder &) = delete; }; } #endif /* THEPEG_FastJetFinder_H */ diff --git a/Cuts/FuzzyTheta.cc b/Cuts/FuzzyTheta.cc --- a/Cuts/FuzzyTheta.cc +++ b/Cuts/FuzzyTheta.cc @@ -1,82 +1,82 @@ // -*- C++ -*- // // FuzzyTheta.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad -// Copyright (C) 2009-2017 Simon Platzer +// Copyright (C) 1999-2019 Leif Lonnblad +// Copyright (C) 2009-2019 Simon Platzer // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the FuzzyTheta class. // #include "FuzzyTheta.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG; FuzzyTheta::FuzzyTheta() : theEnergyWidth(1*GeV), theRapidityWidth(0.1), theAngularWidth(0.1) {} FuzzyTheta::~FuzzyTheta() {} IBPtr FuzzyTheta::clone() const { return new_ptr(*this); } IBPtr FuzzyTheta::fullclone() const { return new_ptr(*this); } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void FuzzyTheta::persistentOutput(PersistentOStream & os) const { os << ounit(theEnergyWidth,GeV) << theRapidityWidth << theAngularWidth; } void FuzzyTheta::persistentInput(PersistentIStream & is, int) { is >> iunit(theEnergyWidth,GeV) >> theRapidityWidth >> theAngularWidth; } ClassDescription FuzzyTheta::initFuzzyTheta; void FuzzyTheta::Init() { static ClassDocumentation documentation ("FuzzyTheta implements fuzzy cut prescriptions."); static Parameter interfaceEnergyWidth ("EnergyWidth", "The width of smeared energy- and momentum-type cuts.", &FuzzyTheta::theEnergyWidth, GeV, 1.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Parameter interfaceRapidityWidth ("RapidityWidth", "The width of smeared rapidity-type cuts.", &FuzzyTheta::theRapidityWidth, 0.1, 0.0, 0, false, false, Interface::lowerlim); static Parameter interfaceAngularWidth ("AngularWidth", "The width of smeared angular-type cuts.", &FuzzyTheta::theAngularWidth, 0.1, 0.0, Constants::pi, false, false, Interface::limited); } diff --git a/Cuts/FuzzyTheta.h b/Cuts/FuzzyTheta.h --- a/Cuts/FuzzyTheta.h +++ b/Cuts/FuzzyTheta.h @@ -1,342 +1,342 @@ // -*- C++ -*- // // FuzzyTheta.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad -// Copyright (C) 2009-2017 Simon Platzer +// Copyright (C) 1999-2019 Leif Lonnblad +// Copyright (C) 2009-2019 Simon Platzer // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_FuzzyTheta_H #define ThePEG_FuzzyTheta_H // // This is the declaration of the FuzzyTheta class. // #include "ThePEG/Interface/Interfaced.h" #include "ThePEG/Repository/EventGenerator.h" #include namespace ThePEG { namespace CutTypes { /** * Identify an energy-type cut */ struct Energy {}; /** * Identify a momentum-type cut */ struct Momentum {}; /** * Identify a rapidity-type cut */ struct Rapidity {}; /** * Identify an azimuth-type cut */ struct Azimuth {}; /** * Identify an polar-angle-type cut */ struct Polar {}; } /** * FuzzyTheta implements fuzzy cut prescriptions * * @see \ref FuzzyThetaInterfaces "The interfaces" * defined for FuzzyTheta. */ class FuzzyTheta: public Interfaced { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ FuzzyTheta(); /** * The destructor. */ virtual ~FuzzyTheta(); //@} public: /** * Return the (compact) support of the delta approximation * considered, given its center value. This default version assumes * a box approximation. All values are assumed to be in units of the * width considered. */ virtual pair support(double x) const { return make_pair(x-0.5,x+0.5); } /** * Return the overlap integral of the delta approximation with the * given box and center. This default version assumes * a box approximation. All values are assumed to be in units of the * width considered. */ virtual double overlap(double x, const pair& box) const { if ( x - 0.5 >= box.first && x + 0.5 <= box.second ) return 1.; if ( x - 0.5 > box.second || x + 0.5 < box.first ) return 0.; return min(box.second,x+0.5) - max(box.first,x-0.5); } /** * Return the overlap, optionally considering absolute lower and * upper bounds. */ double overlap(double x, pair box, const pair& support) const { box.first = max(box.first,support.first); box.second = min(box.second,support.second); assert(x >= support.first && x <= support.second); assert(support.second - support.first >= 1.); if ( x - 0.5 < support.first ) x = support.first + 0.5; if ( x + 0.5 > support.second ) x = support.second - 0.5; return overlap(x,box); } /** * Return the bounds for an energy-type cut */ pair bounds(const CutTypes::Energy&) const { return make_pair(0.,generator()->maximumCMEnergy()/theEnergyWidth); } /** * Return the width for an energy-type cut */ Energy width(const CutTypes::Energy&) const { return theEnergyWidth; } /** * Return the bounds for a momentum-type cut */ pair bounds(const CutTypes::Momentum&) const { return make_pair(0.,0.5*generator()->maximumCMEnergy()/theEnergyWidth); } /** * Return the width for a momentum-type cut */ Energy width(const CutTypes::Momentum&) const { return theEnergyWidth; } /** * Return the bounds for a rapidity-type cut */ pair bounds(const CutTypes::Rapidity&) const { return make_pair(-Constants::MaxRapidity/theRapidityWidth, Constants::MaxRapidity/theRapidityWidth); } /** * Return the width for a rapidity-type cut */ double width(const CutTypes::Rapidity&) const { return theRapidityWidth; } /** * Return the bounds for a azimuth-type cut */ pair bounds(const CutTypes::Azimuth&) const { return make_pair(0.0,2.*Constants::pi/theAngularWidth); } /** * Return the width for a azimuth-type cut */ double width(const CutTypes::Azimuth&) const { return theAngularWidth; } /** * Return the bounds for a polar-angle-type cut */ pair bounds(const CutTypes::Polar&) const { return make_pair(0.0,Constants::pi/theAngularWidth); } /** * Return the width for a polar-type cut */ double width(const CutTypes::Polar&) const { return theAngularWidth; } /** * Check for value inside the given bounds and update the weight */ template bool isInside(const Value& v, const Value& lower, const Value& upper, double& weight) const { CutType type; Value w = width(type); weight *= overlap(v/w,pair(lower/w,upper/w),bounds(type)); if ( weight == 0.0 ) return false; return true; } /** * Check for value inside the given bounds and update the weight */ template bool isLessThan(const Value& v, const Value& upper, double& weight) const { CutType type; Value w = width(type); pair b = bounds(type); weight *= overlap(v/w,pair(b.first,upper/w),b); if ( weight == 0.0 ) return false; return true; } /** * Check for value inside the given bounds and update the weight */ template bool isLargerThan(const Value& v, const Value& lower, double& weight) const { CutType type; Value w = width(type); pair b = bounds(type); weight *= overlap(v/w,pair(lower/w,b.first),b); if ( weight == 0.0 ) return false; return true; } public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The width to be considered for momenta */ Energy theEnergyWidth; /** * The width to be considered for rapidity quantities */ double theRapidityWidth; /** * The width to be considered for angular quantities */ double theAngularWidth; private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initFuzzyTheta; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FuzzyTheta & operator=(const FuzzyTheta &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of FuzzyTheta. */ template <> struct BaseClassTrait { /** Typedef of the first base class of FuzzyTheta. */ typedef Interfaced NthBase; }; /** This template specialization informs ThePEG about the name of * the FuzzyTheta 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::FuzzyTheta"; } }; /** @endcond */ } #endif /* ThePEG_FuzzyTheta_H */ diff --git a/Cuts/JetCuts.cc b/Cuts/JetCuts.cc --- a/Cuts/JetCuts.cc +++ b/Cuts/JetCuts.cc @@ -1,232 +1,232 @@ // -*- C++ -*- // // JetCuts.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad -// Copyright (C) 2009-2017 Simon Platzer +// Copyright (C) 1999-2019 Leif Lonnblad +// Copyright (C) 2009-2019 Simon Platzer // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the JetCuts class. // #include "JetCuts.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Repository/CurrentGenerator.h" using namespace ThePEG; JetCuts::JetCuts() : theOrdering(orderPt) {} JetCuts::~JetCuts() {} void JetCuts::describe() const { CurrentGenerator::log() << name() << " cutting on jets ordered in " << (ordering() == orderPt ? "pt " : "y ") << " with regions:\n"; for ( vector::ptr>::const_iterator r = jetRegions().begin(); r != jetRegions().end(); ++r ) (**r).describe(); if ( !jetPairRegions().empty() ) { CurrentGenerator::log() << "and jet pair cuts:\n"; for ( vector::ptr>::const_iterator r = jetPairRegions().begin(); r != jetPairRegions().end(); ++r ) (**r).describe(); for ( vector::ptr>::const_iterator r = multiJetRegions().begin(); r != multiJetRegions().end(); ++r ) (**r).describe(); } if ( !jetVetoRegions().empty() ) { CurrentGenerator::log() << "vetoing jets inside:\n"; for ( vector::ptr>::const_iterator r = jetVetoRegions().begin(); r != jetVetoRegions().end(); ++r ) (**r).describe(); } CurrentGenerator::log() << "\n"; } IBPtr JetCuts::clone() const { return new_ptr(*this); } IBPtr JetCuts::fullclone() const { return new_ptr(*this); } void JetCuts::persistentOutput(PersistentOStream & os) const { os << theUnresolvedMatcher << theJetRegions << theJetVetoRegions << theJetPairRegions << theMultiJetRegions << theOrdering; } void JetCuts::persistentInput(PersistentIStream & is, int) { is >> theUnresolvedMatcher >> theJetRegions >> theJetVetoRegions >> theJetPairRegions >> theMultiJetRegions >> theOrdering; } struct PtLarger { inline bool operator()(const LorentzMomentum& a, const LorentzMomentum& b) const { return a.perp() > b.perp(); } }; struct YLess { inline bool operator()(const LorentzMomentum& a, const LorentzMomentum& b) const { return a.rapidity() < b.rapidity(); } }; bool JetCuts::passCuts(tcCutsPtr parent, const tcPDVector & ptype, const vector & p) const { vector jets; tcPDVector::const_iterator ptypeit = ptype.begin(); vector::const_iterator pit = p.begin(); for ( ; ptypeit != ptype.end(); ++ptypeit, ++pit ) if ( unresolvedMatcher()->check(**ptypeit) ) jets.push_back(*pit); if ( ordering() == orderPt ) { sort(jets.begin(),jets.end(),PtLarger()); } else if ( ordering() == orderY ) { sort(jets.begin(),jets.end(),YLess()); } else assert(false); for ( vector::ptr>::const_iterator r = jetRegions().begin(); r != jetRegions().end(); ++r ) (**r).reset(); set matchedJets; for ( size_t k = 0; k < jets.size(); ++k ) { for ( vector::ptr>::const_iterator r = jetRegions().begin(); r != jetRegions().end(); ++r ) { if ( (**r).matches(parent,k+1,jets[k]) ) { matchedJets.insert(k+1); break; } } } double cutWeight = 1.0; bool pass = true; for ( vector::ptr>::const_iterator r = jetRegions().begin(); r != jetRegions().end(); ++r ) { pass &= (**r).didMatch(); cutWeight *= (**r).cutWeight(); if ( !pass ) { parent->lastCutWeight(0.0); return false; } } for ( vector::ptr>::const_iterator r = jetPairRegions().begin(); r != jetPairRegions().end(); ++r ) { pass &= (**r).matches(parent); cutWeight *= (**r).cutWeight(); if ( !pass ) { parent->lastCutWeight(0.0); return false; } } for ( vector::ptr>::const_iterator r = multiJetRegions().begin(); r != multiJetRegions().end(); ++r ) { pass &= (**r).matches(); cutWeight *= (**r).cutWeight(); if ( !pass ) { parent->lastCutWeight(0.0); return false; } } if ( !jetVetoRegions().empty() ) { for ( size_t k = 0; k < jets.size(); ++k ) { if ( matchedJets.find(k+1) != matchedJets.end() ) continue; for ( vector::ptr>::const_iterator r = jetVetoRegions().begin(); r != jetVetoRegions().end(); ++r ) { pass &= !(**r).matches(parent,k+1,jets[k]); cutWeight *= 1. - (**r).cutWeight(); if ( !pass ) { parent->lastCutWeight(0.0); return false; } } } } parent->lastCutWeight(cutWeight); return pass; } ClassDescription JetCuts::initJetCuts; // Definition of the static class description member. void JetCuts::Init() { static ClassDocumentation documentation ("JetCuts combines various JetRegion and JetPairRegion objects into a " "cut object."); static Reference interfaceUnresolvedMatcher ("UnresolvedMatcher", "A matcher identifying unresolved partons", &JetCuts::theUnresolvedMatcher, false, false, true, false, false); static RefVector interfaceJetRegions ("JetRegions", "The jet regions to be used.", &JetCuts::theJetRegions, -1, false, false, true, false, false); static RefVector interfaceJetVetoRegions ("JetVetoRegions", "The jet veto regions to be used.", &JetCuts::theJetVetoRegions, -1, false, false, true, false, false); static RefVector interfaceJetPairRegions ("JetPairRegions", "The jet pair regions to be used.", &JetCuts::theJetPairRegions, -1, false, false, true, false, false); static RefVector interfaceMultiJetRegions ("MultiJetRegions", "The multi jet regions to be used.", &JetCuts::theMultiJetRegions, -1, false, false, true, false, false); static Switch interfaceOrdering ("Ordering", "The ordering to apply on jets.", &JetCuts::theOrdering, orderPt, false, false); static SwitchOption interfaceOrderingOrderPt (interfaceOrdering, "OrderPt", "Order in decreasing transverse momentum.", orderPt); static SwitchOption interfaceOrderingOrderY (interfaceOrdering, "OrderY", "Order in rapidity.", orderY); } diff --git a/Cuts/JetCuts.h b/Cuts/JetCuts.h --- a/Cuts/JetCuts.h +++ b/Cuts/JetCuts.h @@ -1,232 +1,232 @@ // -*- C++ -*- // // JetCuts.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad -// Copyright (C) 2009-2017 Simon Platzer +// Copyright (C) 1999-2019 Leif Lonnblad +// Copyright (C) 2009-2019 Simon Platzer // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_JetCuts_H #define THEPEG_JetCuts_H // // This is the declaration of the JetCuts class. // #include "ThePEG/Cuts/MultiCutBase.h" #include "ThePEG/PDT/MatcherBase.h" #include "ThePEG/Cuts/JetRegion.h" #include "ThePEG/Cuts/JetPairRegion.h" #include "ThePEG/Cuts/MultiJetRegion.h" namespace ThePEG { /** * JetCuts combines various JetRegion and JetPairRegion objects into a * cut object. * * @see JetRegion * @see JetPairRegion * * @see \ref JetCutsInterfaces "The interfaces" * defined for JetCuts. */ class JetCuts: public MultiCutBase { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ JetCuts(); /** * The destructor. */ virtual ~JetCuts(); //@} public: /** @name Overridden virtual functions defined in the base class. */ //@{ /** * Return true if a set of outgoing particles with typea \a ptype * and corresponding momenta \a p passes the cuts. */ virtual bool passCuts(tcCutsPtr parent, const tcPDVector & ptype, const vector & p) const; //@} /** * Describe the currently active cuts in the log file. */ virtual void describe() const; public: /** * Return the matcher for unresolved partons. */ Ptr::tptr unresolvedMatcher() const { return theUnresolvedMatcher; } /** * Return the jet regions to match. */ const vector::ptr>& jetRegions() const { return theJetRegions; } /** * Return the jet veto regions to check. */ const vector::ptr>& jetVetoRegions() const { return theJetVetoRegions; } /** * Return the jet pair regions to match. */ const vector::ptr>& jetPairRegions() const { return theJetPairRegions; } /** * Return the multi jet regions to match. */ const vector::ptr>& multiJetRegions() const { return theMultiJetRegions; } /** * Enumerate the ordering to apply on jets */ enum Orderings { orderPt = 1, orderY = 2 }; /** * Return the ordering */ int ordering() const { return theOrdering; } public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * A matcher for unresolved partons. */ Ptr::ptr theUnresolvedMatcher; /** * The jet regions to match. */ vector::ptr> theJetRegions; /** * The jet veto regions to check */ vector::ptr> theJetVetoRegions; /** * The jet pair regions to match. */ vector::ptr> theJetPairRegions; /** * The multi jet regions to match. */ vector::ptr> theMultiJetRegions; /** * Types of the ordering to apply on jets */ int theOrdering; private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initJetCuts; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ JetCuts & operator=(const JetCuts &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of JetCuts. */ template <> struct BaseClassTrait { /** Typedef of the first base class of JetCuts. */ typedef MultiCutBase NthBase; }; /** This template specialization informs ThePEG about the name of * the JetCuts 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::JetCuts"; } /** Return the name of the shared library be loaded to get * access to the JetCuts class and every other class it uses * (except the base class). */ static string library() { return "JetCuts.so"; } }; /** @endcond */ } #endif /* THEPEG_JetCuts_H */ diff --git a/Cuts/JetFinder.cc b/Cuts/JetFinder.cc --- a/Cuts/JetFinder.cc +++ b/Cuts/JetFinder.cc @@ -1,113 +1,113 @@ // -*- C++ -*- // // JetFinder.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad -// Copyright (C) 2009-2017 Simon Platzer +// Copyright (C) 1999-2019 Leif Lonnblad +// Copyright (C) 2009-2019 Simon Platzer // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the JetFinder class. // #include "JetFinder.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Command.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG; JetFinder::JetFinder() : theMinOutgoing(1), theRestrictConstituents(false), theConstituentRapidityRange(Constants::MaxRapidity,Constants::MaxRapidity) {} JetFinder::~JetFinder() {} string JetFinder::doYRange(string in) { istringstream ins(in); double first, second; ins >> first >> second; if ( first > second ) swap(first,second); theConstituentRapidityRange = make_pair(first,second); return ""; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void JetFinder::persistentOutput(PersistentOStream & os) const { os << theUnresolvedMatcher << theMinOutgoing << theRestrictConstituents << theConstituentRapidityRange; } void JetFinder::persistentInput(PersistentIStream & is, int) { is >> theUnresolvedMatcher >> theMinOutgoing >> theRestrictConstituents >> theConstituentRapidityRange; } // *** Attention *** The following static variable is needed for the type // description system in ThePEG. Please check that the template arguments // are correct (the class and its base class), and that the constructor // arguments are correct (the class name and the name of the dynamically // loadable library where the class implementation can be found). DescribeAbstractClass describeJetFinder("ThePEG::JetFinder", ""); void JetFinder::Init() { static ClassDocumentation documentation ("JetFinder defines an interface to jet finders to be used when cuts " "should actually be defined on the level of reconstructed jets such " "as typically encountered in higher order corrections."); static Reference interfaceUnresolvedMatcher ("UnresolvedMatcher", "A matcher identifying unresolved partons", &JetFinder::theUnresolvedMatcher, false, false, true, false, false); static Parameter interfaceMinOutgoing ("MinOutgoing", "The minimum number of outgoing partons to be clustered.", &JetFinder::theMinOutgoing, 1, 1, 0, false, false, Interface::lowerlim); static Switch interfaceRestrictConstituents ("RestrictConstituents", "Restrict the constituents for clustering.", &JetFinder::theRestrictConstituents, false, false, false); static SwitchOption interfaceRestrictConstituentsYes (interfaceRestrictConstituents, "Yes", "", true); static SwitchOption interfaceRestrictConstituentsNo (interfaceRestrictConstituents, "No", "", false); static Command interfaceYRange ("ConstituentRapidityRange", "Restrict clustering to a rapidity range.", &JetFinder::doYRange, false); } diff --git a/Cuts/JetFinder.h b/Cuts/JetFinder.h --- a/Cuts/JetFinder.h +++ b/Cuts/JetFinder.h @@ -1,175 +1,175 @@ // -*- C++ -*- // // JetFinder.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad -// Copyright (C) 2009-2017 Simon Platzer +// Copyright (C) 1999-2019 Leif Lonnblad +// Copyright (C) 2009-2019 Simon Platzer // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_JetFinder_H #define THEPEG_JetFinder_H // // This is the declaration of the JetFinder class. // #include "ThePEG/Interface/Interfaced.h" #include "ThePEG/PDT/MatcherBase.h" #include "Cuts.fh" namespace ThePEG { /** * JetFinder defines an interface to jet finders to be used when cuts * should actually be defined on the level of reconstructed jets such * as typically encountered in higher order corrections. * * @see \ref JetFinderInterfaces "The interfaces" * defined for JetFinder. */ class JetFinder: public Interfaced { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ JetFinder(); /** * The destructor. */ virtual ~JetFinder(); //@} public: /** * Perform jet clustering on the given outgoing particles. * Optionally, information on the incoming particles is provided. * Return true, if a clustering has been performed. */ virtual bool cluster(tcPDVector & ptype, vector & p, tcCutsPtr parent, tcPDPtr t1 = tcPDPtr(), tcPDPtr t2 = tcPDPtr()) const = 0; /** * Return the matcher for unresolved partons. */ Ptr::tptr unresolvedMatcher() const { return theUnresolvedMatcher; } /** * Set the minimum number of outgoing partons on which clustering * should be performed. */ void minOutgoing(unsigned int n) { theMinOutgoing = n; } /** * Return the minimum number of outgoing partons on which clustering * should be performed. */ unsigned int minOutgoing() const { return theMinOutgoing; } /** * Return true, if jets should only be constructed from matching * objects inside a given rapidity interval. */ bool restrictConsitutents() const { return theRestrictConstituents; } /** * Jets should only be constructed from matching * objects inside a given rapidity interval. */ void restrictConsitutents(bool on) { theRestrictConstituents = on; } /** * Return the rapidity interval within objects should be considered * for clustering, if appropriate */ const pair& constituentRapidityRange() const { return theConstituentRapidityRange; } /** * Set the rapidity interval within objects should be considered * for clustering, if appropriate */ void constituentRapidityRange(const pair& r) { theConstituentRapidityRange = r; } /** * Describe this jet finder */ virtual void describe() const = 0; 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(); // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * Command to insert a rapidity range */ string doYRange(string); /** * A matcher for unresolved partons. */ Ptr::ptr theUnresolvedMatcher; /** * The minimum number of outgoing partons on which clustering * should be performed. */ unsigned int theMinOutgoing; /** * True, if jets should only be constructed from matching * objects inside a given rapidity interval. */ bool theRestrictConstituents; /** * The rapidity interval within objects should be considered * for clustering, if appropriate */ pair theConstituentRapidityRange; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ JetFinder & operator=(const JetFinder &) = delete; }; } #endif /* THEPEG_JetFinder_H */ diff --git a/Cuts/JetPairRegion.cc b/Cuts/JetPairRegion.cc --- a/Cuts/JetPairRegion.cc +++ b/Cuts/JetPairRegion.cc @@ -1,209 +1,209 @@ // -*- C++ -*- // // JetPairRegion.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad -// Copyright (C) 2009-2017 Simon Platzer +// Copyright (C) 1999-2019 Leif Lonnblad +// Copyright (C) 2009-2019 Simon Platzer // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the JetPairRegion class. // #include "JetPairRegion.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Repository/CurrentGenerator.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG; JetPairRegion::JetPairRegion() : theMassMin(0.*GeV), theMassMax(Constants::MaxEnergy), theDeltaRMin(0.0), theDeltaRMax(Constants::MaxRapidity), theDeltaYMin(0.0), theDeltaYMax(Constants::MaxRapidity), theOppositeHemispheres(false), theCutWeight(1.0) {} JetPairRegion::~JetPairRegion() {} IBPtr JetPairRegion::clone() const { return new_ptr(*this); } IBPtr JetPairRegion::fullclone() const { return new_ptr(*this); } void JetPairRegion::describe() const { CurrentGenerator::log() << "JetPairRegion '" << name() << "' matching " << " JetRegions '" << firstRegion()->name() << "' and '" << secondRegion()->name() << "' with\n"; CurrentGenerator::log() << "m = " << massMin()/GeV << " .. " << massMax()/GeV << " GeV\n" << "dR = " << deltaRMin() << " .. " << deltaRMax() << "\n" << "dy = " << deltaYMin() << " .. " << deltaYMax() << "\n"; } bool JetPairRegion::matches(tcCutsPtr parent) { if ( !firstRegion()->didMatch() || !secondRegion()->didMatch() ) { theCutWeight = 0.0; return false; } theCutWeight = 1.0; const LorentzMomentum& pi = firstRegion()->lastMomentum(); const LorentzMomentum& pj = secondRegion()->lastMomentum(); Energy m = (pi+pj).m(); if ( !(firstRegion()->lessThanEnergy(massMin(),m,theCutWeight) && firstRegion()->lessThanEnergy(m,massMax(),theCutWeight)) ) return false; double dy = abs(pi.rapidity() - pj.rapidity()); if ( !(firstRegion()->lessThanRapidity(deltaYMin(),dy,theCutWeight) && firstRegion()->lessThanRapidity(dy,deltaYMax(),theCutWeight)) ) return false; double dphi = abs(pi.phi() - pj.phi()); if ( dphi > Constants::pi ) dphi = 2.0*Constants::pi - dphi; double dR = sqrt(sqr(dy)+sqr(dphi)); if ( !(firstRegion()->lessThanRapidity(deltaRMin(),dR,theCutWeight) && firstRegion()->lessThanRapidity(dR,deltaRMax(),theCutWeight)) ) return false; double py = (pi.rapidity() + parent->currentYHat()) * (pj.rapidity() + parent->currentYHat()); if ( theOppositeHemispheres && !firstRegion()->lessThanRapidity(py,0.0,theCutWeight) ) return false; return true; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void JetPairRegion::persistentOutput(PersistentOStream & os) const { os << theFirstRegion << theSecondRegion << ounit(theMassMin,GeV) << ounit(theMassMax,GeV) << theDeltaRMin << theDeltaRMax << theDeltaYMin << theDeltaYMax << theOppositeHemispheres << theCutWeight; } void JetPairRegion::persistentInput(PersistentIStream & is, int) { is >> theFirstRegion >> theSecondRegion >> iunit(theMassMin,GeV) >> iunit(theMassMax,GeV) >> theDeltaRMin >> theDeltaRMax >> theDeltaYMin >> theDeltaYMax >> theOppositeHemispheres >> theCutWeight; } // *** Attention *** The following static variable is needed for the type // description system in ThePEG. Please check that the template arguments // are correct (the class and its base class), and that the constructor // arguments are correct (the class name and the name of the dynamically // loadable library where the class implementation can be found). DescribeClass describeThePEGJetPairRegion("ThePEG::JetPairRegion", "JetCuts.so"); void JetPairRegion::Init() { static ClassDocumentation documentation ("JetPairRegion implements constraints on jets matching two jet regions."); static Reference interfaceFirstRegion ("FirstRegion", "The first region to act on.", &JetPairRegion::theFirstRegion, false, false, true, false, false); static Reference interfaceSecondRegion ("SecondRegion", "The second region to act on.", &JetPairRegion::theSecondRegion, false, false, true, false, false); static Parameter interfaceMassMin ("MassMin", "The minimum jet-jet invariant mass.", &JetPairRegion::theMassMin, GeV, 0.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Parameter interfaceMassMax ("MassMax", "The maximum jet-jet invariant mass.", &JetPairRegion::theMassMax, GeV, Constants::MaxEnergy, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Parameter interfaceDeltaRMin ("DeltaRMin", "The minimum jet-jet lego-plot separation.", &JetPairRegion::theDeltaRMin, 0.0, 0.0, 0, false, false, Interface::lowerlim); static Parameter interfaceDeltaRMax ("DeltaRMax", "The maximum jet-jet lego-plot separation.", &JetPairRegion::theDeltaRMax, Constants::MaxRapidity, 0, 0, false, false, Interface::lowerlim); static Parameter interfaceDeltaYMin ("DeltaYMin", "The minimum jet-jet rapidity separation.", &JetPairRegion::theDeltaYMin, 0.0, 0.0, 0, false, false, Interface::lowerlim); static Parameter interfaceDeltaYMax ("DeltaYMax", "The maximum jet-jet rapidity separation.", &JetPairRegion::theDeltaYMax, Constants::MaxRapidity, 0, 0, false, false, Interface::lowerlim); static Switch interfaceOppositeHemispheres ("OppositeHemispheres", "Should the jets go into opposite detector hemispheres?", &JetPairRegion::theOppositeHemispheres, false, true, false); static SwitchOption interfaceOppositeHemispheresTrue (interfaceOppositeHemispheres, "True", "Require jets to be in different hemispheres", true); static SwitchOption interfaceOppositeHemispheresFalse (interfaceOppositeHemispheres, "False", "Do not require jets to be in different hemispheres", false); static SwitchOption interfaceOppositeHemispheresYes (interfaceOppositeHemispheres, "Yes", "Require jets to be in different hemispheres", true); static SwitchOption interfaceOppositeHemispheresNo (interfaceOppositeHemispheres, "No", "Do not require jets to be in different hemispheres", false); } diff --git a/Cuts/JetPairRegion.h b/Cuts/JetPairRegion.h --- a/Cuts/JetPairRegion.h +++ b/Cuts/JetPairRegion.h @@ -1,215 +1,215 @@ // -*- C++ -*- // // JetPairRegion.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad -// Copyright (C) 2009-2017 Simon Platzer +// Copyright (C) 1999-2019 Leif Lonnblad +// Copyright (C) 2009-2019 Simon Platzer // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_JetPairRegion_H #define ThePEG_JetPairRegion_H // // This is the declaration of the JetPairRegion class. // #include "ThePEG/Cuts/JetRegion.h" namespace ThePEG { /** * JetPairRegion implements constraints on jets matching two jet regions. * * @see JetRegion * @see JetCuts * * @see \ref JetPairRegionInterfaces "The interfaces" * defined for JetPairRegion. */ class JetPairRegion: public HandlerBase { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ JetPairRegion(); /** * The destructor. */ virtual ~JetPairRegion(); //@} public: /** * Return the first jet region to act on. */ Ptr::tptr firstRegion() const { return theFirstRegion; } /** * Return the second jet region to act on. */ Ptr::tptr secondRegion() const { return theSecondRegion; } /** * Return the minimum jet-jet invariant mass. */ Energy massMin() const { return theMassMin; } /** * Return the maximum jet-jet invariant mass. */ Energy massMax() const { return theMassMax; } /** * Return the minimum jet-jet lego-plot separation. */ double deltaRMin() const { return theDeltaRMin; } /** * Return the maximum jet-jet lego-plot separation. */ double deltaRMax() const { return theDeltaRMax; } /** * Return the minimum jet-jet rapidity separation. */ double deltaYMin() const { return theDeltaYMin; } /** * Return the maximum jet-jet rapidity separation. */ double deltaYMax() const { return theDeltaYMax; } /** * Return the cut weight encountered from the last call to matches() */ double cutWeight() const { return theCutWeight; } public: /** * Describe the currently active cuts in the log file. */ virtual void describe() const; /** * Return true, if the requirements on the jet regions are fullfilled. */ virtual bool matches(tcCutsPtr parent); public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The first jet region to act on. */ Ptr::ptr theFirstRegion; /** * The second jet region to act on. */ Ptr::ptr theSecondRegion; /** * The minimum jet-jet invariant mass. */ Energy theMassMin; /** * The maximum jet-jet invariant mass. */ Energy theMassMax; /** * The minimum jet-jet lego-plot separation. */ double theDeltaRMin; /** * The maximum jet-jet lego-plot separation. */ double theDeltaRMax; /** * The minimum jet-jet rapidity separation. */ double theDeltaYMin; /** * The maximum jet-jet rapidity separation. */ double theDeltaYMax; /** * Should the jets go into opposite detector hemispheres? */ bool theOppositeHemispheres; /** * The cut weight encountered from the last call to matches() */ double theCutWeight; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ JetPairRegion & operator=(const JetPairRegion &) = delete; }; } #endif /* ThePEG_JetPairRegion_H */ diff --git a/Cuts/JetRegion.cc b/Cuts/JetRegion.cc --- a/Cuts/JetRegion.cc +++ b/Cuts/JetRegion.cc @@ -1,267 +1,267 @@ // -*- C++ -*- // // JetRegion.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad -// Copyright (C) 2009-2017 Simon Platzer +// Copyright (C) 1999-2019 Leif Lonnblad +// Copyright (C) 2009-2019 Simon Platzer // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the JetRegion class. // #include "JetRegion.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Command.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/ParVector.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Utilities/StringUtils.h" #include "ThePEG/Repository/CurrentGenerator.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG; JetRegion::JetRegion() : thePtMin(0.*GeV), thePtMax(Constants::MaxEnergy), theDidMatch(false), theLastNumber(0), theFuzzy(false), theCutWeight(1.0), theEnergyCutWidth(1.0*GeV), theRapidityCutWidth(0.1) {} JetRegion::~JetRegion() {} IBPtr JetRegion::clone() const { return new_ptr(*this); } IBPtr JetRegion::fullclone() const { return new_ptr(*this); } string JetRegion::doYRange(string in) { istringstream ins(StringUtils::stripws(in)); theYRanges.clear(); while ( !ins.eof() ) { double first, second; ins >> first; if ( ins.eof() ) throw Exception() << "need an even number n of values to define n/2 rapidity intervals" << Exception::abortnow; ins >> second; if ( first > second ) swap(first,second); theYRanges.push_back(make_pair(first,second)); } return ""; } void JetRegion::describe() const { CurrentGenerator::log() << "JetRegion '" << name() << "' matching "; if ( accepts().empty() ) CurrentGenerator::log() << "any jets "; else { CurrentGenerator::log() << "jets "; for ( vector::const_iterator k = accepts().begin(); k != accepts().end(); ++k ) { CurrentGenerator::log() << "#" << *k; if ( k != --accepts().end() ) CurrentGenerator::log() << ", "; else CurrentGenerator::log() << " "; } } CurrentGenerator::log() << " within:\n"; CurrentGenerator::log() << "pt = " << ptMin()/GeV << " .. " << ptMax()/GeV << " GeV\n"; for ( vector >::const_iterator r = yRanges().begin(); r != yRanges().end(); ++r ) { CurrentGenerator::log() << "y = " << r->first << " .. " << r->second << "\n"; } } double step(double r) { if ( r < -0.5 ) return 0.0; if ( r > 0.5 ) return 1.0; return r+0.5; } bool JetRegion::lessThanEnergy(Energy a, Energy b, double& weight) const { if ( !fuzzy() ) { if ( a < b ) { weight = 1.0; return true; } weight = 0.0; return false; } double w = step((b-a)/theEnergyCutWidth); if ( w == 0.0 ) { weight = 0.0; return false; } weight *= w; return true; } bool JetRegion::lessThanRapidity(double a, double b, double& weight) const { if ( !fuzzy() ) { if ( a < b ) { weight = 1.0; return true; } weight = 0.0; return false; } double w = step((b-a)/theRapidityCutWidth); if ( w == 0.0 ) { weight = 0.0; return false; } weight *= w; return true; } bool JetRegion::matches(tcCutsPtr parent, int n, const LorentzMomentum& p, double yHat) { // one jet region can only contain one jet if ( didMatch() ) return false; if ( !accepts().empty() && find(accepts().begin(),accepts().end(),n) == accepts().end() ) return false; theCutWeight = 1.0; if ( !(lessThanEnergy(ptMin(),p.perp(),theCutWeight) && lessThanEnergy(p.perp(),ptMax(),theCutWeight)) ) { theCutWeight = 0.0; theDidMatch = false; return false; } double currentY = parent ? parent->currentYHat() : yHat; bool inRange = false || yRanges().empty(); for ( vector >::const_iterator r = yRanges().begin(); r != yRanges().end(); ++r ) { double rangeWeight = 1.0; if ( lessThanRapidity(r->first,p.rapidity() + currentY,rangeWeight) && lessThanRapidity(p.rapidity() + currentY,r->second,rangeWeight) ) { theCutWeight *= rangeWeight; inRange = true; break; } } if ( !inRange ) { theCutWeight = 0.0; theDidMatch = false; return false; } theDidMatch = true; theLastNumber = n; theLastMomentum = p; return true; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void JetRegion::persistentOutput(PersistentOStream & os) const { os << ounit(thePtMin,GeV) << ounit(thePtMax,GeV) << theYRanges << theAccepts << theFuzzy << theCutWeight << ounit(theEnergyCutWidth,GeV) << theRapidityCutWidth; } void JetRegion::persistentInput(PersistentIStream & is, int) { is >> iunit(thePtMin,GeV) >> iunit(thePtMax,GeV) >> theYRanges >> theAccepts >> theFuzzy >> theCutWeight >> iunit(theEnergyCutWidth,GeV) >> theRapidityCutWidth; } // *** Attention *** The following static variable is needed for the type // description system in ThePEG. Please check that the template arguments // are correct (the class and its base class), and that the constructor // arguments are correct (the class name and the name of the dynamically // loadable library where the class implementation can be found). DescribeClass describeThePEGJetRegion("ThePEG::JetRegion", "JetCuts.so"); void JetRegion::Init() { static ClassDocumentation documentation ("JetRegion implements the requirement of finding a jet inside a " "given range of transverse momenta, and (pseudo-)rapidity."); static Parameter interfacePtMin ("PtMin", "The minimum pt required.", &JetRegion::thePtMin, GeV, 0.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Parameter interfacePtMax ("PtMax", "The maximum pt allowed.", &JetRegion::thePtMax, GeV, Constants::MaxEnergy, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Command interfaceYRange ("YRange", "Insert a rapidity range.", &JetRegion::doYRange, false); static ParVector interfaceAccepts ("Accepts", "The jet numbers accepted. If empty, any jets are accepted.", &JetRegion::theAccepts, -1, 1, 1, 10, false, false, Interface::upperlim); static Switch interfaceFuzzy ("Fuzzy", "Make this jet region a fuzzy cut", &JetRegion::theFuzzy, false, false, false); static SwitchOption interfaceFuzzyYes (interfaceFuzzy, "Yes", "", true); static SwitchOption interfaceFuzzyNo (interfaceFuzzy, "No", "", false); static Parameter interfaceEnergyCutWidth ("EnergyCutWidth", "The pt cut smearing.", &JetRegion::theEnergyCutWidth, GeV, 1.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Parameter interfaceRapidityCutWidth ("RapidityCutWidth", "The rapidity cut smearing.", &JetRegion::theRapidityCutWidth, 0.1, 0.0, 0, false, false, Interface::lowerlim); } diff --git a/Cuts/JetRegion.h b/Cuts/JetRegion.h --- a/Cuts/JetRegion.h +++ b/Cuts/JetRegion.h @@ -1,248 +1,248 @@ // -*- C++ -*- // // JetRegion.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad -// Copyright (C) 2009-2017 Simon Platzer +// Copyright (C) 1999-2019 Leif Lonnblad +// Copyright (C) 2009-2019 Simon Platzer // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_JetRegion_H #define ThePEG_JetRegion_H // // This is the declaration of the JetRegion class. // #include "ThePEG/Handlers/HandlerBase.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Cuts/Cuts.h" namespace ThePEG { /** * JetRegion implements the requirement of finding a jet inside a * given range of transverse momenta, and (pseudo-)rapidity. * * @see JetPairRegion * @see JetCuts * * @see \ref JetRegionInterfaces "The interfaces" * defined for JetRegion. */ class JetRegion: public HandlerBase { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ JetRegion(); /** * The destructor. */ virtual ~JetRegion(); //@} public: /** * Return the minimum pt. */ Energy ptMin() const { return thePtMin; } /** * Return the maximum pt. */ Energy ptMax() const { return thePtMax; } /** * Return the rapidity ranges. */ const vector >& yRanges() const { return theYRanges; } /** * Return the jets accepted by this region (with respect to the * ordering imposed by the JetCuts object). If empty, any jet will * be accepted. */ const vector& accepts() const { return theAccepts; } /** * Return true, if this jet region is fuzzy */ bool fuzzy() const { return theFuzzy; } /** * Return the cut weight encountered from the last call to matches() */ double cutWeight() const { return theCutWeight; } /** * Perform a (potentially) fuzzy check on energy-type quantities */ bool lessThanEnergy(Energy a, Energy b, double& weight) const; /** * Perform a (potentially) fuzzy check on angular-type quantities */ bool lessThanRapidity(double a, double b, double& weight) const; public: /** * Describe the currently active cuts in the log file. */ virtual void describe() const; /** * Return true, if the given jet matches this region. */ virtual bool matches(tcCutsPtr parent, int n, const LorentzMomentum& p, double yHat = 0.0); /** * Return true, if this region matched a jet in the last call to matches(). */ bool didMatch() { return theDidMatch; } /** * Reset this region to act on a new event. */ virtual void reset() { theDidMatch = false; } /** * Return the number of the last jet matching this region. */ int lastNumber() const { return theLastNumber; } /** * Return the momentum of the last jet matching this region. */ const LorentzMomentum& lastMomentum() const { return theLastMomentum; } public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * Command to insert a rapidity range */ string doYRange(string); /** * The minimum pt. */ Energy thePtMin; /** * The maximum pt. */ Energy thePtMax; /** * The rapidity ranges. */ vector > theYRanges; /** * The jets accepted by this region (with respect to the ordering * imposed by the JetCuts object). If empty, any jet will be * accepted. */ vector theAccepts; /** * True, if this region matched a jet in the last call to matches(). */ bool theDidMatch; /** * The number of the last jet matching this region. */ int theLastNumber; /** * Return the momentum of the last jet matching this region. */ LorentzMomentum theLastMomentum; /** * True if this region is fuzzy */ bool theFuzzy; /** * The cut weight encountered from the last call to matches() */ double theCutWeight; /** * The smearing width for the pt or mass cuts, if fuzzy */ Energy theEnergyCutWidth; /** * The smearing width for the rapidity cut, if fuzzy */ double theRapidityCutWidth; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ JetRegion & operator=(const JetRegion &) = delete; }; } #endif /* ThePEG_JetRegion_H */ diff --git a/Cuts/KTClus.cc b/Cuts/KTClus.cc --- a/Cuts/KTClus.cc +++ b/Cuts/KTClus.cc @@ -1,138 +1,138 @@ // -*- C++ -*- // // KTClus.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the KTClus class. // #include "KTClus.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/Cuts/Cuts.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Repository/CurrentGenerator.h" using namespace ThePEG; void KTClus::describe() const { CurrentGenerator::log() << fullName() << ":\n" << "Cut = " << theCut/GeV << " GeV\n\n"; } IBPtr KTClus::clone() const { return new_ptr(*this); } IBPtr KTClus::fullclone() const { return new_ptr(*this); } Energy KTClus::minKTClus(tcPDPtr pi, tcPDPtr pj) const { if ( onlyJets && ( ( pi && !pi->coloured() ) || ( pj && !pj->coloured() ) ) ) return ZERO; if ( !pi && !pj ) return ZERO; return theCut; } Energy2 KTClus::minSij(tcPDPtr, tcPDPtr) const { return ZERO; } Energy2 KTClus::minTij(tcPDPtr, tcPDPtr) const { return ZERO; } double KTClus::minDeltaR(tcPDPtr, tcPDPtr) const { return 0.0; } double KTClus::minDurham(tcPDPtr, tcPDPtr) const { return 0.0; } bool KTClus::passCuts(tcCutsPtr, tcPDPtr pitype, tcPDPtr pjtype, LorentzMomentum pi, LorentzMomentum pj, bool inci, bool incj) const { if ( onlyJets && ( ( !inci && pitype && !pitype->coloured() ) || ( !incj && pjtype && !pjtype->coloured() ) ) ) return true; if ( inci && incj ) return true; else if ( inci ) { if ( pj.perp() <= theCut ) return false; } else if ( incj ) { if ( pi.perp() <= theCut ) return false; } else { double deta2 = sqr(pi.eta() - pj.eta()); double dphi = abs(pi.phi() - pj.phi()); if ( dphi > Constants::pi ) dphi = 2.0*Constants::pi - dphi; double dr = sqrt(deta2 + sqr(dphi)); if ( min(pi.perp(), pj.perp())*dr <= theCut ) return false; } return true; } void KTClus::persistentOutput(PersistentOStream & os) const { os << ounit(theCut, GeV) << onlyJets; } void KTClus::persistentInput(PersistentIStream & is, int) { is >> iunit(theCut, GeV) >> onlyJets; } ClassDescription KTClus::initKTClus; // Definition of the static class description member. void KTClus::Init() { static ClassDocumentation documentation ("This clas implements the cuts relevant for the " "\\f$\\Delta R\\f$-measure in the longitudinally invariant " "kt-algorithm. By default the cut is only applied to coloured " "particles, but optionally it may be applied to all particle types."); static Parameter interfaceCut ("Cut", "The minimum allowed value of the longitudinally invariant " "\\f$k_\\perp\\f$-algorithms distance measure. This is defined as " "\\f$\\min(p_{\\perp i}, p_{\\perp j})" "\\sqrt{\\Delta\\eta_{ij}^2+\\Delta\\phi_{ij}^2}\\f$ for two outgoing " "partons, or simply \\f$p_{\\perp i}\\f$ or \\f$p_{\\perp j}\\f$ for a " "single outgoing parton.", &KTClus::theCut, GeV, 10.0*GeV, ZERO, ZERO, true, false, Interface::lowerlim); interfaceCut.setHasDefault(false); static Switch interfaceOnlyJets ("OnlyJets", "If true, only apply the cut to pairs of coloured particles.", &KTClus::onlyJets, true, true, false); static SwitchOption interfaceOnlyJetsOnlyJets (interfaceOnlyJets, "OnlyJets", "The cut is only applied to pairs of coloured particles.", true); static SwitchOption interfaceOnlyJetsAll (interfaceOnlyJets, "All", "The cut is applied to all particle types.", false); interfaceOnlyJets.setHasDefault(false); interfaceCut.rank(10); interfaceOnlyJets.rank(9); } diff --git a/Cuts/KTClus.h b/Cuts/KTClus.h --- a/Cuts/KTClus.h +++ b/Cuts/KTClus.h @@ -1,205 +1,205 @@ // -*- C++ -*- // // KTClus.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_KTClus_H #define THEPEG_KTClus_H // // This is the declaration of the KTClus class. // #include "ThePEG/Cuts/TwoCutBase.h" namespace ThePEG { /** * This clas implements the cuts relevant for the \f$\Delta * R\f$-measure in the longitudinally invariant kt-algorithm. By * default the cut is only applied to coloured particles, but * optionally it may be applied to all particle types. * * @see \ref KTClusInterfaces "The interfaces" * defined for KTClus. */ class KTClus: public TwoCutBase { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ KTClus() : theCut(10.0*GeV), onlyJets(true) {} //@} public: /** @name Overridden virtual functions defined in the base class. */ //@{ /** * Return the minimum allowed value of the longitudinally invariant * \f$k_\perp\f$-algorithms distance measure. This is defined as * \f$\min(p_{\perp i}, p_{\perp * j})\sqrt{\Delta\eta_{ij}^2+\Delta\phi_{ij}^2}\f$ for two outgoing * partons, or simply \f$p_{\perp i}\f$ or \f$p_{\perp j}\f$ for a * single outgoing parton. Returns 0 if both partons are incoming. A * null pointer indicates an incoming parton, hence the type of the * incoming parton is irrelevant. */ virtual Energy minKTClus(tcPDPtr pi, tcPDPtr pj) const; /** * Return the minimum allowed squared invariant mass of two outgoing * partons of type \a pi and \a pj. Returns zero. */ virtual Energy2 minSij(tcPDPtr pi, tcPDPtr pj) const; /** * Return the minimum allowed value of the negative of the squared * invariant mass of an incoming parton of type \a pi and an * outgoing parton of type \a po. Returns zero. */ virtual Energy2 minTij(tcPDPtr pi, tcPDPtr po) const; /** * Return the minimum allowed value of \f$\Delta * R_{ij}=\sqrt{\Delta\eta_{ij}^2+\Delta\phi_{ij}^2}\f$ of two * outgoing partons of type \a pi and \a pj. Returns zero. */ virtual double minDeltaR(tcPDPtr pi, tcPDPtr pj) const; /** * Return the minimum allowed value of the Durham * \f$k_\perp\f$-algorithms distance measure. This is defined as * \f$2\min(E_j^2, E_j^2)(1-\cos\theta_{ij})/\hat{s}\f$ for two * outgoing partons. Returns zero. */ virtual double minDurham(tcPDPtr pi, tcPDPtr pj) const; /** * Return true if a pair of particles with type \a pitype and \a * pjtype and momenta \a pi and \a pj respectively passes the * cuts. \a inci and \a inj indicates if the corresponding particles * are incoming. */ virtual bool passCuts(tcCutsPtr parent, tcPDPtr pitype, tcPDPtr pjtype, LorentzMomentum pi, LorentzMomentum pj, bool inci = false, bool incj = false) const; //@} /** * Describe the currently active cuts in the log file. */ virtual void describe() const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * The minimum allowed value of the longitudinally invariant * \f$k_\perp\f$-algorithms distance measure. */ Energy theCut; /** * If true, only apply the cut to pairs of coloured particles. */ bool onlyJets; private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initKTClus; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ KTClus & operator=(const KTClus &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of KTClus. */ template <> struct BaseClassTrait { /** Typedef of the first base class of KTClus. */ typedef TwoCutBase NthBase; }; /** This template specialization informs ThePEG about the name of * the KTClus 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::KTClus"; } /** Return the name of the shared library be loaded to get * access to the KTClus class and every other class it uses * (except the base class). */ static string library() { return "KTClus.so"; } }; /** @endcond */ } #endif /* THEPEG_KTClus_H */ diff --git a/Cuts/MultiCutBase.cc b/Cuts/MultiCutBase.cc --- a/Cuts/MultiCutBase.cc +++ b/Cuts/MultiCutBase.cc @@ -1,79 +1,79 @@ // -*- C++ -*- // // MultiCutBase.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MultiCutBase class. // #include "MultiCutBase.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/CurrentGenerator.h" using namespace ThePEG; void MultiCutBase::describe() const { CurrentGenerator::log() << fullName() << " has no description.\n\n"; } Energy2 MultiCutBase::minS(const tcPDVector &) const { return ZERO; } Energy2 MultiCutBase::maxS(const tcPDVector &) const { return Constants::MaxEnergy2; } bool MultiCutBase::passCuts(tcCutsPtr, const tcPDVector & ptype, const vector & p) const { long NN = (1 << ptype.size()); // NN is the number of different combinations that can be made. for ( long ii = 1; ii < NN; ++ii ) { long mask = ii; tcPDVector pt; LorentzMomentum sum; int i = -1; while ( mask ) { ++i; int sel = mask%2; mask /= 2; if ( !sel ) continue; pt.push_back(ptype[i]); sum += p[i]; } if ( pt.size() < 2 ) continue; if ( sum.m2() < minS(pt) ) return false; if ( sum.m2() >= maxS(pt) ) return false; } return true; } bool MultiCutBase::passCuts(tcCutsPtr parent, const tcPVector & p) const { tcPDVector ptype(p.size()); vector mom(p.size()); for ( int i = 0, N = p.size(); i < N; ++i ) { ptype[i] = p[i]->dataPtr(); mom[i] = p[i]->momentum(); } return passCuts(parent, ptype, mom); } AbstractNoPIOClassDescription MultiCutBase::initMultiCutBase; // Definition of the static class description member. void MultiCutBase::Init() { static ClassDocumentation documentation ("This class corresponds to a kinematical cut to be made on a set of " "outgoing particles from a hard sub-process."); } diff --git a/Cuts/MultiCutBase.h b/Cuts/MultiCutBase.h --- a/Cuts/MultiCutBase.h +++ b/Cuts/MultiCutBase.h @@ -1,127 +1,127 @@ // -*- C++ -*- // // MultiCutBase.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_MultiCutBase_H #define THEPEG_MultiCutBase_H // // This is the declaration of the MultiCutBase class. // #include "ThePEG/Interface/Interfaced.h" #include "MultiCutBase.fh" #include "Cuts.fh" namespace ThePEG { /** * This class corresponds to a kinematical cut to be made on a set of * outgoing particles from a hard sub-process. * * There are three virtual functions to be overridden by concrete * sub-classes. minS() and maxS() should return the minimum and * maximum invariant mass of of a set of particle types. In addition * the passCut() function should return true if a set of particle * with a given types and given momenta will pass the cuts. * * @see \ref MultiCutBaseInterfaces "The interfaces" * defined for MultiCutBase. */ class MultiCutBase: public Interfaced { public: /** @name Virtual functions to be overridden by sub-classes. */ //@{ /** * Return the minimum allowed value of the squared invariant mass of * a set of outgoing partons of the given types. Typically used to * cut off the tails of the mass of a resonance for efficiency. */ virtual Energy2 minS(const tcPDVector & pv) const; /** * Return the maximum allowed value of the squared invariant mass of * a set of outgoing partons of the given types. Typically used to * cut off the tails of the mass of a resonance for efficiency. */ virtual Energy2 maxS(const tcPDVector & pv) const; /** * Return true if a set of outgoing particles with typea \a ptype * and corresponding momenta \a p passes the cuts. */ virtual bool passCuts(tcCutsPtr parent, const tcPDVector & ptype, const vector & p) const; /** * Return true if the given vector of particles passes the cuts. */ bool passCuts(tcCutsPtr parent, const tcPVector & p) const; //@} /** * Describe the currently active cuts in the log file. */ virtual void describe() const; public: /** * 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(); private: /** * The static object used to initialize the description of this class. * Indicates that this is an abstract class without persistent data. */ static AbstractNoPIOClassDescription initMultiCutBase; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MultiCutBase & operator=(const MultiCutBase &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of MultiCutBase. */ template <> struct BaseClassTrait { /** Typedef of the first base class of MultiCutBase. */ typedef Interfaced NthBase; }; /** This template specialization informs ThePEG about the name of * the MultiCutBase 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::MultiCutBase"; } }; /** @endcond */ } #endif /* THEPEG_MultiCutBase_H */ diff --git a/Cuts/MultiJetRegion.cc b/Cuts/MultiJetRegion.cc --- a/Cuts/MultiJetRegion.cc +++ b/Cuts/MultiJetRegion.cc @@ -1,190 +1,190 @@ // -*- C++ -*- // // MultiJetRegion.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad -// Copyright (C) 2009-2017 Simon Platzer +// Copyright (C) 1999-2019 Leif Lonnblad +// Copyright (C) 2009-2019 Simon Platzer // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MultiJetRegion class. // #include "MultiJetRegion.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Repository/CurrentGenerator.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG; MultiJetRegion::MultiJetRegion() : theMassMin(0.*GeV), theMassMax(Constants::MaxEnergy), theDeltaRMin(0.0), theDeltaRMax(Constants::MaxRapidity), theDeltaYMin(0.0), theDeltaYMax(Constants::MaxRapidity), theCutWeight(1.0) {} MultiJetRegion::~MultiJetRegion() {} IBPtr MultiJetRegion::clone() const { return new_ptr(*this); } IBPtr MultiJetRegion::fullclone() const { return new_ptr(*this); } void MultiJetRegion::describe() const { CurrentGenerator::log() << "MultiJetRegion '" << name() << "' matching JetRegions:\n"; for ( vector::ptr>::const_iterator r = regions().begin(); r != regions().end(); ++r ) { CurrentGenerator::log() << "'" << (**r).name() << "'\n"; } CurrentGenerator::log() << "with\n"; CurrentGenerator::log() << "m = " << massMin()/GeV << " .. " << massMax()/GeV << " GeV\n" << "dR = " << deltaRMin() << " .. " << deltaRMax() << "\n" << "dy = " << deltaYMin() << " .. " << deltaYMax() << "\n"; } bool MultiJetRegion::matches() { int n = regions().size(); for ( int i = 0; i < n; ++i ) for ( int j = i+1; j < n; ++j ) if ( !matches(i,j) ) return false; return true; } bool MultiJetRegion::matches(int i, int j) { if ( !regions()[i]->didMatch() || !regions()[j]->didMatch() ) { theCutWeight = 0.0; return false; } theCutWeight = 1.0; const LorentzMomentum& pi = regions()[i]->lastMomentum(); const LorentzMomentum& pj = regions()[j]->lastMomentum(); Energy m = (pi+pj).m(); if ( !(regions()[i]->lessThanEnergy(massMin(),m,theCutWeight) && regions()[i]->lessThanEnergy(m,massMax(),theCutWeight)) ) return false; double dy = abs(pi.rapidity() - pj.rapidity()); if ( !(regions()[i]->lessThanRapidity(deltaYMin(),dy,theCutWeight) && regions()[i]->lessThanRapidity(dy,deltaYMax(),theCutWeight)) ) return false; double dphi = abs(pi.phi() - pj.phi()); if ( dphi > Constants::pi ) dphi = 2.0*Constants::pi - dphi; double dR = sqrt(sqr(dy)+sqr(dphi)); if ( !(regions()[i]->lessThanRapidity(deltaRMin(),dR,theCutWeight) && regions()[i]->lessThanRapidity(dR,deltaRMax(),theCutWeight)) ) return false; return true; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void MultiJetRegion::persistentOutput(PersistentOStream & os) const { os << theRegions << ounit(theMassMin,GeV) << ounit(theMassMax,GeV) << theDeltaRMin << theDeltaRMax << theDeltaYMin << theDeltaYMax << theCutWeight; } void MultiJetRegion::persistentInput(PersistentIStream & is, int) { is >> theRegions >> iunit(theMassMin,GeV) >> iunit(theMassMax,GeV) >> theDeltaRMin >> theDeltaRMax >> theDeltaYMin >> theDeltaYMax >> theCutWeight; } // *** Attention *** The following static variable is needed for the type // description system in ThePEG. Please check that the template arguments // are correct (the class and its base class), and that the constructor // arguments are correct (the class name and the name of the dynamically // loadable library where the class implementation can be found). DescribeClass describeThePEGMultiJetRegion("ThePEG::MultiJetRegion", "JetCuts.so"); void MultiJetRegion::Init() { static ClassDocumentation documentation ("MultiJetRegion implements pairwise constraints on jets matching several jet regions."); static RefVector interfaceRegions ("Regions", "The jet regions to act on.", &MultiJetRegion::theRegions, -1, false, false, true, false, false); static Parameter interfaceMassMin ("MassMin", "The minimum jet-jet invariant mass.", &MultiJetRegion::theMassMin, GeV, 0.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Parameter interfaceMassMax ("MassMax", "The maximum jet-jet invariant mass.", &MultiJetRegion::theMassMax, GeV, Constants::MaxEnergy, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Parameter interfaceDeltaRMin ("DeltaRMin", "The minimum jet-jet lego-plot separation.", &MultiJetRegion::theDeltaRMin, 0.0, 0.0, 0, false, false, Interface::lowerlim); static Parameter interfaceDeltaRMax ("DeltaRMax", "The maximum jet-jet lego-plot separation.", &MultiJetRegion::theDeltaRMax, Constants::MaxRapidity, 0, 0, false, false, Interface::lowerlim); static Parameter interfaceDeltaYMin ("DeltaYMin", "The minimum jet-jet rapidity separation.", &MultiJetRegion::theDeltaYMin, 0.0, 0.0, 0, false, false, Interface::lowerlim); static Parameter interfaceDeltaYMax ("DeltaYMax", "The maximum jet-jet rapidity separation.", &MultiJetRegion::theDeltaYMax, Constants::MaxRapidity, 0, 0, false, false, Interface::lowerlim); } diff --git a/Cuts/MultiJetRegion.h b/Cuts/MultiJetRegion.h --- a/Cuts/MultiJetRegion.h +++ b/Cuts/MultiJetRegion.h @@ -1,205 +1,205 @@ // -*- C++ -*- // // MultiJetRegion.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad -// Copyright (C) 2009-2017 Simon Platzer +// Copyright (C) 1999-2019 Leif Lonnblad +// Copyright (C) 2009-2019 Simon Platzer // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_MultiJetRegion_H #define ThePEG_MultiJetRegion_H // // This is the declaration of the MultiJetRegion class. // #include "ThePEG/Cuts/JetRegion.h" namespace ThePEG { /** * MultiJetRegion implements pairwise constraints on jets matching several jet regions. * * @see JetRegion * @see JetCuts * * @see \ref MultiJetRegionInterfaces "The interfaces" * defined for MultiJetRegion. */ class MultiJetRegion: public HandlerBase { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ MultiJetRegion(); /** * The destructor. */ virtual ~MultiJetRegion(); //@} public: /** * Return the jet regions to act on. */ const vector::ptr>& regions() const { return theRegions; } /** * Return the minimum jet-jet invariant mass. */ Energy massMin() const { return theMassMin; } /** * Return the maximum jet-jet invariant mass. */ Energy massMax() const { return theMassMax; } /** * Return the minimum jet-jet lego-plot separation. */ double deltaRMin() const { return theDeltaRMin; } /** * Return the maximum jet-jet lego-plot separation. */ double deltaRMax() const { return theDeltaRMax; } /** * Return the minimum jet-jet rapidity separation. */ double deltaYMin() const { return theDeltaYMin; } /** * Return the maximum jet-jet rapidity separation. */ double deltaYMax() const { return theDeltaYMax; } /** * Return the cut weight encountered from the last call to matches() */ double cutWeight() const { return theCutWeight; } public: /** * Describe the currently active cuts in the log file. */ virtual void describe() const; /** * Return true, if the requirements on the jet regions are fullfilled. */ virtual bool matches(); /** * Return true, if the requirements on two jet regions are fullfilled. */ virtual bool matches(int i, int j); public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The jet regions to act on. */ vector::ptr> theRegions; /** * The minimum jet-jet invariant mass. */ Energy theMassMin; /** * The maximum jet-jet invariant mass. */ Energy theMassMax; /** * The minimum jet-jet lego-plot separation. */ double theDeltaRMin; /** * The maximum jet-jet lego-plot separation. */ double theDeltaRMax; /** * The minimum jet-jet rapidity separation. */ double theDeltaYMin; /** * The maximum jet-jet rapidity separation. */ double theDeltaYMax; /** * The cut weight encountered from the last call to matches() */ double theCutWeight; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MultiJetRegion & operator=(const MultiJetRegion &) = delete; }; } #endif /* ThePEG_MultiJetRegion_H */ diff --git a/Cuts/NJetsCut.cc b/Cuts/NJetsCut.cc --- a/Cuts/NJetsCut.cc +++ b/Cuts/NJetsCut.cc @@ -1,105 +1,105 @@ // -*- C++ -*- // // NJetsCut.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad -// Copyright (C) 2009-2017 Simon Platzer +// Copyright (C) 1999-2019 Leif Lonnblad +// Copyright (C) 2009-2019 Simon Platzer // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the NJetsCut class. // #include "NJetsCut.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Repository/CurrentGenerator.h" using namespace ThePEG; NJetsCut::NJetsCut() : nJetsMin(0), nJetsMax(-1) {} NJetsCut::~NJetsCut() {} void NJetsCut::describe() const { CurrentGenerator::log() << fullName() << ": requires "; if ( nJetsMin > 0 ) CurrentGenerator::log() << "at least " << nJetsMin; if ( nJetsMax > 0 ) CurrentGenerator::log() << " and at most " << nJetsMax; CurrentGenerator::log() << " jets.\n"; } IBPtr NJetsCut::clone() const { return new_ptr(*this); } IBPtr NJetsCut::fullclone() const { return new_ptr(*this); } void NJetsCut::persistentOutput(PersistentOStream & os) const { os << unresolvedMatcher << nJetsMin << nJetsMax; } void NJetsCut::persistentInput(PersistentIStream & is, int) { is >> unresolvedMatcher >> nJetsMin >> nJetsMax; } bool NJetsCut::passCuts(tcCutsPtr, const tcPDVector & ptype, const vector & p) const { tcPDVector::const_iterator ptit = ptype.begin(); vector::const_iterator pit = p.begin(); int njets = 0; for ( ; ptit != ptype.end(); ++ptit, ++pit ) if ( unresolvedMatcher->check(**ptit) ) { ++njets; } if ( nJetsMax > 0 ) return njets >= nJetsMin && njets <= nJetsMax; return njets >= nJetsMin; } ClassDescription NJetsCut::initNJetsCut; // Definition of the static class description member. void NJetsCut::Init() { static ClassDocumentation documentation ("NJetsCut is a simple cut on jet multiplicity."); static Reference interfaceUnresolvedMatcher ("UnresolvedMatcher", "A matcher identifying unresolved partons", &NJetsCut::unresolvedMatcher, false, false, true, false, false); static Parameter interfaceNJetsMin ("NJetsMin", "The minimum number of jets required.", &NJetsCut::nJetsMin, 0, 0, 0, false, false, Interface::lowerlim); static Parameter interfaceNJetsMax ("NJetsMax", "The maximum number of jets allowed. If -1 no limit is imposed.", &NJetsCut::nJetsMax, -1, -1, 0, false, false, Interface::lowerlim); } diff --git a/Cuts/NJetsCut.h b/Cuts/NJetsCut.h --- a/Cuts/NJetsCut.h +++ b/Cuts/NJetsCut.h @@ -1,170 +1,170 @@ // -*- C++ -*- // // NJetsCut.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad -// Copyright (C) 2009-2017 Simon Platzer +// Copyright (C) 1999-2019 Leif Lonnblad +// Copyright (C) 2009-2019 Simon Platzer // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_NJetsCut_H #define THEPEG_NJetsCut_H // // This is the declaration of the NJetsCut class. // #include "ThePEG/Cuts/MultiCutBase.h" #include "ThePEG/PDT/MatcherBase.h" namespace ThePEG { /** * NJetsCut is a simple cut on jet multiplicity. * * @see \ref NJetsCutInterfaces "The interfaces" * defined for NJetsCut. */ class NJetsCut: public MultiCutBase { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ NJetsCut(); /** * The destructor. */ virtual ~NJetsCut(); //@} public: /** @name Overridden virtual functions defined in the base class. */ //@{ /** * Return true if a set of outgoing particles with typea \a ptype * and corresponding momenta \a p passes the cuts. */ virtual bool passCuts(tcCutsPtr parent, const tcPDVector & ptype, const vector & p) const; //@} /** * Describe the currently active cuts in the log file. */ virtual void describe() const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * A matcher for unresolved partons. */ Ptr::ptr unresolvedMatcher; /** * The minimum number of jets. */ int nJetsMin; /** * The maximum number of jets. */ int nJetsMax; private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initNJetsCut; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ NJetsCut & operator=(const NJetsCut &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of NJetsCut. */ template <> struct BaseClassTrait { /** Typedef of the first base class of NJetsCut. */ typedef MultiCutBase NthBase; }; /** This template specialization informs ThePEG about the name of * the NJetsCut 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::NJetsCut"; } /** Return the name of the shared library be loaded to get * access to the NJetsCut class and every other class it uses * (except the base class). */ static string library() { return "JetCuts.so"; } }; /** @endcond */ } #endif /* THEPEG_NJetsCut_H */ diff --git a/Cuts/OneCutBase.cc b/Cuts/OneCutBase.cc --- a/Cuts/OneCutBase.cc +++ b/Cuts/OneCutBase.cc @@ -1,86 +1,86 @@ // -*- C++ -*- // // OneCutBase.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the OneCutBase class. // #include "OneCutBase.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/Cuts/Cuts.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Repository/CurrentGenerator.h" using namespace ThePEG; OneCutBase::~OneCutBase() {} void OneCutBase::describe() const { CurrentGenerator::log() << fullName() << " has no description.\n\n"; } Energy OneCutBase::minMaxKT(tcPDPtr p) const { return minKT(p); } double OneCutBase::minMaxEta(tcPDPtr p) const { return minEta(p); } double OneCutBase::maxMinEta(tcPDPtr p) const { return maxEta(p); } bool OneCutBase::passCuts(tcCutsPtr parent, tcPDPtr ptype, LorentzMomentum p) const { if ( p.perp() <= minKT(ptype) ) return false; double y = p.rapidity() + parent->Y() + parent->currentYHat(); if ( p.mt()*sinh(y) <= p.perp()*sinh(minEta(ptype)) ) return false; if ( p.mt()*sinh(y) >= p.perp()*sinh(maxEta(ptype)) ) return false; return true; } bool OneCutBase::passCuts(tcCutsPtr parent, tcPPtr p) const { return passCuts(parent, p->dataPtr(), p->momentum()); } Energy OneCutBase::minKT(tcPDPtr) const { return ZERO; } double OneCutBase::minEta(tcPDPtr) const { return -Constants::MaxRapidity; } double OneCutBase::maxEta(tcPDPtr) const { return Constants::MaxRapidity; } double OneCutBase::minRapidityMax(tcPDPtr) const { return -Constants::MaxRapidity; } double OneCutBase::maxRapidityMin(tcPDPtr) const { return Constants::MaxRapidity; } AbstractNoPIOClassDescription OneCutBase::initOneCutBase; // Definition of the static class description member. void OneCutBase::Init() { static ClassDocumentation documentation ("This class corresponds to a kinematical cut to be made on a single " "outgoing parton from a hard sub-process."); } diff --git a/Cuts/OneCutBase.h b/Cuts/OneCutBase.h --- a/Cuts/OneCutBase.h +++ b/Cuts/OneCutBase.h @@ -1,193 +1,193 @@ // -*- C++ -*- // // OneCutBase.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_OneCutBase_H #define THEPEG_OneCutBase_H // // This is the declaration of the OneCutBase class. // #include "ThePEG/Interface/Interfaced.h" #include "OneCutBase.fh" #include "Cuts.fh" namespace ThePEG { /** * This class corresponds to a kinematical cut to be made on a single * outgoing parton from a hard sub-process. * * There are four main virtual functions which must be overridden by * concrete sub-classes. minKT() should return the minimum allowed * transverse momentum of a given type, while minEta() and maxEta() * should return the minimum and maximum allowed pseudo-rapidity for a * particle of a given type as measured in the lab-system. Note that * when applied in the rest frame of a hard sub-process, the * transformation from the lab frame is assumed to be a simple boost * along the z-axis. In addition the passCut() function should return * true if a particle with a given type and given momentum will pass * the cuts. * * @see \ref OneCutBaseInterfaces "The interfaces" * defined for OneCutBase. */ class OneCutBase: public Interfaced { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ OneCutBase() {} /** * The destructor. */ virtual ~OneCutBase(); //@} public: /** @name Virtual functions to be overridden by sub-classes. */ //@{ /** * Return the minimum allowed value of the transverse momentum of an * outgoing parton. */ virtual Energy minKT(tcPDPtr p) const = 0; /** * Return the minimum allowed pseudo-rapidity of an outgoing parton * of the given type. The pseudo-rapidity is measured in the lab * system. */ virtual double minEta(tcPDPtr p) const = 0; /** * Return the maximum allowed pseudo-rapidity of an outgoing parton * of the given type. The pseudo-rapidity is measured in the lab * system. */ virtual double maxEta(tcPDPtr p) const = 0; /** * Return the minimum allowed rapidity of an outgoing parton * of the given type. The rapidity is measured in the lab * system. */ virtual double minRapidityMax(tcPDPtr p) const; /** * Return the maximum allowed rapidity of an outgoing parton * of the given type. The rapidity is measured in the lab * system. */ virtual double maxRapidityMin(tcPDPtr p) const; /** * Return the minimum allowed value of the transverse momentum of * the outgoing parton with the lagrest transverse momentum. This * version simply returns minKt(). */ virtual Energy minMaxKT(tcPDPtr p) const; /** * Return the minimum allowed pseudo-rapidity of the outgoing parton * of the given type with the maximum pseudo-rapidity. The * pseudo-rapidity is measured in the lab system. This version * simply returns minEta(). */ virtual double minMaxEta(tcPDPtr p) const; /** * Return the maximum allowed pseudo-rapidity of the outgoing parton * of the given type with the minimum pseudo-rapidity.. The * pseudo-rapidity is measured in the lab system. This version * simply returns maxEta(). */ virtual double maxMinEta(tcPDPtr p) const; /** * Return true if a particle with type \a ptype and momentum \a p * passes the cuts. The \a parent contains information about the * kinematics of the hard sub-process. */ virtual bool passCuts(tcCutsPtr parent, tcPDPtr ptype, LorentzMomentum p) const; /** * Return true if the given particle passes the cuts. The \a parent * contains information about the kinematics of the hard * sub-process. */ bool passCuts(tcCutsPtr parent, tcPPtr p) const; //@} /** * Describe the currently active cuts in the log file. */ virtual void describe() const; public: /** * 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(); private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static AbstractNoPIOClassDescription initOneCutBase; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ OneCutBase & operator=(const OneCutBase &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of OneCutBase. */ template <> struct BaseClassTrait { /** Typedef of the first base class of OneCutBase. */ typedef Interfaced NthBase; }; /** This template specialization informs ThePEG about the name of * the OneCutBase 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::OneCutBase"; } }; /** @endcond */ } #endif /* THEPEG_OneCutBase_H */ diff --git a/Cuts/OneJetCut.cc b/Cuts/OneJetCut.cc --- a/Cuts/OneJetCut.cc +++ b/Cuts/OneJetCut.cc @@ -1,108 +1,108 @@ // -*- C++ -*- // // OneJetCut.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad -// Copyright (C) 2009-2017 Simon Platzer +// Copyright (C) 1999-2019 Leif Lonnblad +// Copyright (C) 2009-2019 Simon Platzer // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the OneJetCut class. // #include "OneJetCut.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Repository/CurrentGenerator.h" using namespace ThePEG; OneJetCut::OneJetCut() : ptMin(20.*GeV), yMin(-5), yMax(5) {} OneJetCut::~OneJetCut() {} void OneJetCut::describe() const { CurrentGenerator::log() << fullName() << " requesting one jet with:\n" << "pt(jet)/GeV > " << ptMin/GeV << " y(jet) > " << yMin << " y(jet) < " << yMax << "\n"; } IBPtr OneJetCut::clone() const { return new_ptr(*this); } IBPtr OneJetCut::fullclone() const { return new_ptr(*this); } void OneJetCut::persistentOutput(PersistentOStream & os) const { os << unresolvedMatcher << ounit(ptMin,GeV) << yMin << yMax; } void OneJetCut::persistentInput(PersistentIStream & is, int) { is >> unresolvedMatcher >> iunit(ptMin,GeV) >> yMin >> yMax; } bool OneJetCut::passCuts(tcCutsPtr, const tcPDVector & ptype, const vector & p) const { tcPDVector::const_iterator ptit = ptype.begin(); vector::const_iterator pit = p.begin(); for ( ; ptit != ptype.end(); ++ptit, ++pit ) if ( unresolvedMatcher->check(**ptit) ) { double y = pit->rapidity(); if ( pit->perp() > ptMin && y > yMin && y < yMax ) { return true; } } return false; } ClassDescription OneJetCut::initOneJetCut; // Definition of the static class description member. void OneJetCut::Init() { static ClassDocumentation documentation ("OneJetsCut is a simple one-jet inclusive cut, requiring at least " "one jet above a certain pt in a given rapidity interval."); static Reference interfaceUnresolvedMatcher ("UnresolvedMatcher", "A matcher identifying unresolved partons", &OneJetCut::unresolvedMatcher, false, false, true, false, false); static Parameter interfacePTMin ("PTMin", "Set the minimum pt required for the jet.", &OneJetCut::ptMin, GeV, 20.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); static Parameter interfaceYMin ("YMin", "Set the minimum rapidity required for the jet.", &OneJetCut::yMin, -5, 0, 0, false, false, Interface::nolimits); static Parameter interfaceYMax ("YMax", "Set the maximum rapidity required for the jet.", &OneJetCut::yMax, 5, 0, 0, false, false, Interface::nolimits); } diff --git a/Cuts/OneJetCut.h b/Cuts/OneJetCut.h --- a/Cuts/OneJetCut.h +++ b/Cuts/OneJetCut.h @@ -1,176 +1,176 @@ // -*- C++ -*- // // OneJetCut.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad -// Copyright (C) 2009-2017 Simon Platzer +// Copyright (C) 1999-2019 Leif Lonnblad +// Copyright (C) 2009-2019 Simon Platzer // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_OneJetCut_H #define THEPEG_OneJetCut_H // // This is the declaration of the OneJetCut class. // #include "ThePEG/Cuts/MultiCutBase.h" #include "ThePEG/PDT/MatcherBase.h" namespace ThePEG { /** * OneJetsCut is a simple one-jet inclusive cut, requiring at least * one jet above a certain pt in a given rapidity interval. * * @see \ref OneJetCutInterfaces "The interfaces" * defined for OneJetCut. */ class OneJetCut: public MultiCutBase { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ OneJetCut(); /** * The destructor. */ virtual ~OneJetCut(); //@} public: /** @name Overridden virtual functions defined in the base class. */ //@{ /** * Return true if a set of outgoing particles with typea \a ptype * and corresponding momenta \a p passes the cuts. */ virtual bool passCuts(tcCutsPtr parent, const tcPDVector & ptype, const vector & p) const; //@} /** * Describe the currently active cuts in the log file. */ virtual void describe() const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * A matcher for unresolved partons. */ Ptr::ptr unresolvedMatcher; /** * The minimum pt */ Energy ptMin; /** * The minimum rapidity */ double yMin; /** * The maximum rapidity */ double yMax; private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initOneJetCut; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ OneJetCut & operator=(const OneJetCut &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of OneJetCut. */ template <> struct BaseClassTrait { /** Typedef of the first base class of OneJetCut. */ typedef MultiCutBase NthBase; }; /** This template specialization informs ThePEG about the name of * the OneJetCut 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::OneJetCut"; } /** Return the name of the shared library be loaded to get * access to the OneJetCut class and every other class it uses * (except the base class). */ static string library() { return "JetCuts.so"; } }; /** @endcond */ } #endif /* THEPEG_OneJetCut_H */ diff --git a/Cuts/SimpleDISCut.cc b/Cuts/SimpleDISCut.cc --- a/Cuts/SimpleDISCut.cc +++ b/Cuts/SimpleDISCut.cc @@ -1,224 +1,224 @@ // -*- C++ -*- // // SimpleDISCut.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the SimpleDISCut class. // #include "SimpleDISCut.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/Cuts/Cuts.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Repository/CurrentGenerator.h" using namespace ThePEG; void SimpleDISCut::describe() const { CurrentGenerator::log() << fullName() << ":\n" << "Q2 = " << theMinQ2/GeV2 << " .. " << theMaxQ2/GeV2 << " GeV2\n" << "y = " << theMiny << " .. " << theMaxy << " \n" << "W2 = " << theMinW2/GeV2 << " .. " << theMaxW2/GeV2 << " GeV2\n\n"; } IBPtr SimpleDISCut::clone() const { return new_ptr(*this); } IBPtr SimpleDISCut::fullclone() const { return new_ptr(*this); } bool SimpleDISCut::check(long idi, long ido) const { if ( abs(idi) <= 10 || abs(idi) > 16 ) return false; if ( idi*ido <= 0 ) return false; if ( chargedCurrent ) { if ( abs(idi)%2 ) return abs(idi) == abs(ido) - 1; else return abs(idi) == abs(ido) + 1; } else { return ( idi == ido ); } } Energy2 SimpleDISCut::minTij(tcPDPtr pi, tcPDPtr po) const { if ( !check(pi->id(), po->id()) ) return ZERO; return theMinQ2; } bool SimpleDISCut::passCuts(tcCutsPtr cuts, tcPDPtr pitype, tcPDPtr pjtype, LorentzMomentum pi, LorentzMomentum pj, bool inci, bool incj) const { if ( inci ) { if ( incj ) return true; if ( !check(pitype->id(), pjtype->id()) ) return true; Energy2 Q2 = -(pi - pj).m2(); double x = min(1.0, sqrt(cuts->currentSHat()/cuts->SMax())* exp(-cuts->currentYHat())); Energy2 W2 = (1.0 - x)*Q2/x; double y = Q2/cuts->SMax()/x; return y > theMiny && y < theMaxy && Q2 > theMinQ2 && Q2 < theMaxQ2 && W2 > theMinW2 && W2 < theMaxW2; } else if ( incj ) { if ( !check(pjtype->id(), pitype->id()) ) return true; Energy2 Q2 = -(pj - pi).m2(); double x = min(1.0, sqrt(cuts->currentSHat()/cuts->SMax())* exp(cuts->currentYHat())); Energy2 W2 = (1.0 - x)*Q2/x; double y = Q2/cuts->SMax()/x; return y > theMiny && y < theMaxy && Q2 > theMinQ2 && Q2 < theMaxQ2 && W2 > theMinW2 && W2 < theMaxW2; } return true; } Energy2 SimpleDISCut::minSij(tcPDPtr, tcPDPtr) const { return ZERO; } double SimpleDISCut::minDeltaR(tcPDPtr, tcPDPtr) const { return 0.0; } Energy SimpleDISCut::minKTClus(tcPDPtr, tcPDPtr) const { return ZERO; } double SimpleDISCut::minDurham(tcPDPtr, tcPDPtr) const { return 0.0; } void SimpleDISCut::persistentOutput(PersistentOStream & os) const { os << ounit(theMinQ2, GeV2) << ounit(theMaxQ2, GeV2) << theMiny << theMaxy << ounit(theMinW2, GeV2) << ounit(theMaxW2, GeV2) << chargedCurrent; } void SimpleDISCut::persistentInput(PersistentIStream & is, int) { is >> iunit(theMinQ2, GeV2) >> iunit(theMaxQ2, GeV2) >> theMiny >> theMaxy >> iunit(theMinW2, GeV2) >> iunit(theMaxW2, GeV2) >> chargedCurrent; } ClassDescription SimpleDISCut::initSimpleDISCut; // Definition of the static class description member. double SimpleDISCut::maxMiny() const { return theMaxy; } double SimpleDISCut::minMaxy() const { return theMiny; } Energy2 SimpleDISCut::maxMinQ2() const { return theMaxQ2; } Energy2 SimpleDISCut::minMaxQ2() const { return theMinQ2; } Energy2 SimpleDISCut::maxMinW2() const { return theMaxW2; } Energy2 SimpleDISCut::minMaxW2() const { return theMinW2; } void SimpleDISCut::Init() { typedef double (ThePEG::SimpleDISCut::*IGFN)() const; typedef void (ThePEG::SimpleDISCut::*ISFN)(double); static ClassDocumentation documentation ("SimpleDISCut inherits from TwoCutBase and omplements a simple " "\\f$Q^2\\f$ cut on the a scattered lepton, either neutral or charged " "current."); static Parameter interfaceMinQ2 ("MinQ2", "The minimum \\f$Q^2\\f$.", &SimpleDISCut::theMinQ2, GeV2, 1.0*GeV2, ZERO, Constants::MaxEnergy2, true, false, Interface::limited, 0, 0, 0, &SimpleDISCut::maxMinQ2, 0); static Parameter interfaceMaxQ2 ("MaxQ2", "The maximum \\f$Q^2\\f$. Note that this is only applied as a post-cut " "and will not affect the initial phase space cuts in the generation.", &SimpleDISCut::theMaxQ2, GeV2, 100.0*GeV2, ZERO, ZERO, true, false, Interface::lowerlim, 0, 0, &SimpleDISCut::minMaxQ2, 0, 0); static Parameter interfaceMiny ("Miny", "The minimum \\f$y\\f$.", &SimpleDISCut::theMiny, 0.0, 0.0, 1.0, true, false, Interface::limited, (ISFN)0, (IGFN)0, (IGFN)0, &SimpleDISCut::maxMiny, (IGFN)0); static Parameter interfaceMaxy ("Maxy", "The maximum \\f$y\\f$. Note that this is only applied as a post-cut " "and will not affect the initial phase space cuts in the generation.", &SimpleDISCut::theMaxy, 0.0, 0.0, 1.0, true, false, Interface::lowerlim, (ISFN)0, (IGFN)0, &SimpleDISCut::minMaxy, (IGFN)0, (IGFN)0); static Parameter interfaceMinW2 ("MinW2", "The minimum \\f$W^2\\f$. Note that this is only applied as a post-cut " "and will not affect the initial phase space cuts in the generation.", &SimpleDISCut::theMinW2, GeV2, 100.0*GeV2, ZERO, Constants::MaxEnergy2, true, false, Interface::limited, 0, 0, 0, &SimpleDISCut::maxMinW2, 0); static Parameter interfaceMaxW2 ("MaxW2", "The maximum \\f$W^2\\f$. Note that this is only applied as a post-cut " "and will not affect the initial phase space cuts in the generation.", &SimpleDISCut::theMaxW2, GeV2, 1000000.0*GeV2, ZERO, ZERO, true, false, Interface::lowerlim, 0, 0, &SimpleDISCut::minMaxW2, 0, 0); static Switch interfaceCurrent ("Current", "Determines whether this cut should be applied to charged or neutral " "current events.", &SimpleDISCut::chargedCurrent, false, true, false); static SwitchOption interfaceCurrentCharged (interfaceCurrent, "Charged", "The cut is only applied to charged current events.", true); static SwitchOption interfaceCurrentNeutral (interfaceCurrent, "Neutral", "The cut is only applied to neutral current events.", false); interfaceMiny.rank(12); interfaceMaxy.rank(11); interfaceMinQ2.rank(10); interfaceMaxQ2.rank(9); interfaceCurrent.rank(8); interfaceMiny.setHasDefault(false); interfaceMaxy.setHasDefault(false); interfaceMinQ2.setHasDefault(false); interfaceMaxQ2.setHasDefault(false); interfaceMinW2.setHasDefault(false); interfaceMaxW2.setHasDefault(false); interfaceCurrent.setHasDefault(false); } diff --git a/Cuts/SimpleDISCut.h b/Cuts/SimpleDISCut.h --- a/Cuts/SimpleDISCut.h +++ b/Cuts/SimpleDISCut.h @@ -1,271 +1,271 @@ // -*- C++ -*- // // SimpleDISCut.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_SimpleDISCut_H #define THEPEG_SimpleDISCut_H // // This is the declaration of the SimpleDISCut class. // #include "ThePEG/Cuts/TwoCutBase.h" namespace ThePEG { /** * SimpleDISCut inherits from TwoCutBase and omplements a simple * \f$Q^2\f$ cut on the a scattered lepton, either neutral or charged * current. * * @see \ref SimpleDISCutInterfaces "The interfaces" * defined for SimpleDISCut. */ class SimpleDISCut: public TwoCutBase { public: /** * The default constructor. */ SimpleDISCut() : theMinQ2(1.0*GeV2), theMaxQ2(100.0*GeV2),theMiny(0.0), theMaxy(1.0), theMinW2(100.0*GeV2), theMaxW2(1000000.0*GeV2), chargedCurrent(false) {} public: /** @name Overridden virtual functions defined in the base class. */ //@{ /** * Return the minimum allowed squared invariant mass of two outgoing * partons of type \a pi and \a pj. Returns zero. */ virtual Energy2 minSij(tcPDPtr pi, tcPDPtr pj) const; /** * Return the minimum allowed value of the negative of the squared * invariant mass of an incoming parton of type \a pi and an * outgoing parton of type \a po. Return the minimum \f$Q^2\f$ if * the incoming and outgoing particles are matching leptons. */ virtual Energy2 minTij(tcPDPtr pi, tcPDPtr po) const; /** * Return the minimum allowed value of \f$\Delta * R_{ij}=\sqrt{\Delta\eta_{ij}^2+\Delta\phi_{ij}^2}\f$ of two * outgoing partons of type \a pi and \a pj. Returns zero. */ virtual double minDeltaR(tcPDPtr pi, tcPDPtr pj) const; /** * Return the minimum allowed value of the longitudinally invariant * \f$k_\perp\f$-algorithms distance measure. This is defined as * \f$\min(p_{\perp i}, p_{\perp * j})\sqrt{\Delta\eta_{ij}^2+\Delta\phi_{ij}^2}\f$ for two outgoing * partons, or simply \f$p_{\perp i}\f$ or \f$p_{\perp j}\f$ for a * single outgoing parton. Returns 0 if both partons are incoming. A * null pointer indicates an incoming parton, hence the type of the * incoming parton is irrelevant. Returns zero. */ virtual Energy minKTClus(tcPDPtr pi, tcPDPtr pj) const; /** * Return the minimum allowed value of the Durham * \f$k_\perp\f$-algorithms distance measure. This is defined as * \f$2\min(E_j^2, E_j^2)(1-\cos\theta_{ij})/\hat{s}\f$ for two * outgoing partons. Returns zero. */ virtual double minDurham(tcPDPtr pi, tcPDPtr pj) const; /** * Return true if a pair of particles with type \a pitype and \a * pjtype and momenta \a pi and \a pj respectively passes the * cuts. \a inci and \a inj indicates if the corresponding particles * are incoming. */ virtual bool passCuts(tcCutsPtr parent, tcPDPtr pitype, tcPDPtr pjtype, LorentzMomentum pi, LorentzMomentum pj, bool inci = false, bool incj = false) const; //@} /** * Describe the currently active cuts in the log file. */ virtual void describe() const; protected: /** * Check that the types of the incoming and outgoing particle types * matches a DIS event. */ bool check(long idi, long ido) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * Helper function used by the interface. */ double maxMiny() const; /** * Helper function used by the interface. */ double minMaxy() const; /** * Helper function used by the interface. */ Energy2 maxMinQ2() const; /** * Helper function used by the interface. */ Energy2 minMaxQ2() const; /** * Helper function used by the interface. */ Energy2 maxMinW2() const; /** * Helper function used by the interface. */ Energy2 minMaxW2() const; private: /** * The minimum \f$Q^2\f$. */ Energy2 theMinQ2; /** * The maximum \f$Q^2\f$. This is only applied as a post-cut. */ Energy2 theMaxQ2; /** * The minimum \f$y\f$. */ double theMiny; /** * The maximum \f$y\f$. This is only applied as a post-cut. */ double theMaxy; /** * The minimum \f$W^2\f$. This is only applied as a post-cut. */ Energy2 theMinW2; /** * The maximum \f$W^2\f$. This is only applied as a post-cut. */ Energy2 theMaxW2; /** * If true the cut is applied to charged current events, otherwise * it is applied to neutral current events. */ bool chargedCurrent; private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initSimpleDISCut; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ SimpleDISCut & operator=(const SimpleDISCut &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of SimpleDISCut. */ template <> struct BaseClassTrait { /** Typedef of the first base class of SimpleDISCut. */ typedef TwoCutBase NthBase; }; /** This template specialization informs ThePEG about the name of * the SimpleDISCut 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::SimpleDISCut"; } /** Return the name of the shared library be loaded to get * access to the SimpleDISCut class and every other class it uses * (except the base class). */ static string library() { return "SimpleDISCut.so"; } }; /** @endcond */ } #endif /* THEPEG_SimpleDISCut_H */ diff --git a/Cuts/SimpleKTCut.cc b/Cuts/SimpleKTCut.cc --- a/Cuts/SimpleKTCut.cc +++ b/Cuts/SimpleKTCut.cc @@ -1,170 +1,170 @@ // -*- C++ -*- // // SimpleKTCut.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the SimpleKTCut class. // #include "SimpleKTCut.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/PDT/MatcherBase.h" #include "ThePEG/Cuts/Cuts.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Repository/CurrentGenerator.h" using namespace ThePEG; SimpleKTCut::~SimpleKTCut() {} void SimpleKTCut::describe() const { CurrentGenerator::log() << fullName() << ":\n" << "KT = " << theMinKT/GeV << " .. " << theMaxKT/GeV << " GeV\n" << "Eta = " << theMinEta << " .. " << theMaxEta << "\n\n"; } IBPtr SimpleKTCut::clone() const { return new_ptr(*this); } IBPtr SimpleKTCut::fullclone() const { return new_ptr(*this); } Energy SimpleKTCut::minKT(tcPDPtr p) const { if ( theMatcher && !theMatcher->matches(*p) ) return ZERO; return theMinKT; } double SimpleKTCut::minEta(tcPDPtr p) const { if ( theMatcher && !theMatcher->matches(*p) ) return -Constants::MaxRapidity; return theMinEta; } double SimpleKTCut::maxEta(tcPDPtr p) const { if ( theMatcher && !theMatcher->matches(*p) ) return Constants::MaxRapidity; return theMaxEta; } bool SimpleKTCut::passCuts(tcCutsPtr parent, tcPDPtr ptype, LorentzMomentum p) const { if ( theMatcher && !theMatcher->matches(*ptype) ) return true; if ( p.perp() < theMinKT ) return false; if ( p.perp() > theMaxKT ) return false; double y = abs(p.t()) <= abs(p.z()) ? (p .z() > ZERO ? 1e10 : -1e10) : p.rapidity(); y += parent->Y() + parent->currentYHat(); if ( p.mt()*sinh(y) <= p.perp()*sinh(theMinEta) ) return false; if ( p.mt()*sinh(y) >= p.perp()*sinh(theMaxEta) ) return false; return true; } void SimpleKTCut::persistentOutput(PersistentOStream & os) const { os << ounit(theMinKT, GeV) << ounit(theMaxKT, GeV) << theMinEta << theMaxEta << theMatcher; } void SimpleKTCut::persistentInput(PersistentIStream & is, int) { is >> iunit(theMinKT, GeV) >> iunit(theMaxKT, GeV) >> theMinEta >> theMaxEta >> theMatcher; } ClassDescription SimpleKTCut::initSimpleKTCut; // Definition of the static class description member. Energy SimpleKTCut::maxKTMin() const { return theMaxKT; } Energy SimpleKTCut::minKTMax() const { return theMinKT; } double SimpleKTCut::maxEtaMin() const { return theMaxEta; } double SimpleKTCut::minEtaMax() const { return theMinEta; } void SimpleKTCut::Init() { typedef double (ThePEG::SimpleKTCut::*IGFN)() const; typedef void (ThePEG::SimpleKTCut::*ISFN)(double); typedef Energy (ThePEG::SimpleKTCut::*IGFNK)() const; typedef void (ThePEG::SimpleKTCut::*ISFNK)(Energy); static ClassDocumentation documentation ("This is a very simple concrete sub-class of OneCutbase simply " "requiring a minimum transverse momentum of any outgoing particle. " "It is also possible to require a minimum and maximum pseudorapidity. " "Optionally the restrictions only apply to particles matching a " "specific matcher object."); static Parameter interfaceMinKT ("MinKT", "The minimum allowed value of the transverse momentum of an outgoing " "parton.", &SimpleKTCut::theMinKT, GeV, 10.0*GeV, ZERO, Constants::MaxEnergy, true, false, Interface::limited, (ISFNK)0, (IGFNK)0, (IGFNK)0, &SimpleKTCut::maxKTMin, (IGFNK)0); static Parameter interfaceMaxKT ("MaxKT", "The maximum allowed value of the transverse momentum of an outgoing " "parton. Note that this cut does not increase the efficiency of the phase " "space generation, but is only applied as a post-cut.", &SimpleKTCut::theMaxKT, GeV, Constants::MaxEnergy, ZERO, ZERO, true, false, Interface::lowerlim, (ISFNK)0, (IGFNK)0, &SimpleKTCut::minKTMax, (IGFNK)0, (IGFNK)0); static Parameter interfaceMinEta ("MinEta", "The minimum allowed pseudo-rapidity of an outgoing parton. " "The pseudo-rapidity is measured in the lab system.", &SimpleKTCut::theMinEta, -Constants::MaxRapidity, 0, Constants::MaxRapidity, true, false, Interface::upperlim, (ISFN)0, (IGFN)0, (IGFN)0, &SimpleKTCut::maxEtaMin, (IGFN)0); static Parameter interfaceMaxEta ("MaxEta", "The maximum allowed pseudo-rapidity of an outgoing parton. " "The pseudo-rapidity is measured in the lab system.", &SimpleKTCut::theMaxEta, Constants::MaxRapidity, -Constants::MaxRapidity, 0, true, false, Interface::lowerlim, (ISFN)0, (IGFN)0, &SimpleKTCut::minEtaMax, (IGFN)0, (IGFN)0); static Reference interfaceMatcher ("Matcher", "If non-null only particles matching this object will be affected " "by the cut.", &SimpleKTCut::theMatcher, true, false, true, true, false); interfaceMinKT.rank(10); interfaceMaxKT.rank(6); interfaceMinEta.rank(9); interfaceMaxEta.rank(8); interfaceMatcher.rank(7); interfaceMinKT.setHasDefault(false); interfaceMaxKT.setHasDefault(false); interfaceMinEta.setHasDefault(false); interfaceMaxEta.setHasDefault(false); } diff --git a/Cuts/SimpleKTCut.h b/Cuts/SimpleKTCut.h --- a/Cuts/SimpleKTCut.h +++ b/Cuts/SimpleKTCut.h @@ -1,233 +1,233 @@ // -*- C++ -*- // // SimpleKTCut.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_SimpleKTCut_H #define THEPEG_SimpleKTCut_H // // This is the declaration of the SimpleKTCut class. // #include "ThePEG/Cuts/OneCutBase.h" namespace ThePEG { /** * This is a very simple concrete sub-class of OneCutbase simply * requiring a minimum transverse momentum of any outgoing * particle. It is also possible to require a minimum and maximum * pseudorapidity. Optionally the restrictions only apply to particles * matching a specific matcher object. * * @see \ref SimpleKTCutInterfaces "The interfaces" * defined for SimpleKTCut. */ class SimpleKTCut: public OneCutBase { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ SimpleKTCut(Energy minKT=10*GeV) : theMinKT(minKT), theMaxKT(Constants::MaxEnergy), theMinEta(-Constants::MaxRapidity), theMaxEta(Constants::MaxRapidity) {} /** * The destructor. */ virtual ~SimpleKTCut(); //@} public: /** @name Overwritten virtual functions defined in the base class. */ //@{ /** * Return the minimum allowed value of the transverse momentum of an * outgoing parton. */ virtual Energy minKT(tcPDPtr p) const; /** * Return the minimum allowed pseudo-rapidity of an outgoing parton * of the given type. The pseudo-rapidity is measured in the lab * system. */ virtual double minEta(tcPDPtr p) const; /** * Return the maximum allowed pseudo-rapidity of an outgoing parton * of the given type. The pseudo-rapidity is measured in the lab * system. */ virtual double maxEta(tcPDPtr p) const; /** * Return true if a particle with type \a ptype and momentum \a p * passes the cuts. The \a parent contains information about the * kinematics of the hard sub-process. */ virtual bool passCuts(tcCutsPtr parent, tcPDPtr ptype, LorentzMomentum p) const; //@} /** * Describe the currently active cuts in the log file. */ virtual void describe() const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * Helper function used by the interface. */ Energy maxKTMin() const; /** * Helper function used by the interface. */ Energy minKTMax() const; /** * Helper function used by the interface. */ double maxEtaMin() const; /** * Helper function used by the interface. */ double minEtaMax() const; private: /** * The minimum allowed value of the transverse momentum of an * outgoing parton. */ Energy theMinKT; /** * The maximum allowed value of the transverse momentum of an * outgoing parton. */ Energy theMaxKT; /** * The minimum allowed pseudo-rapidity of an outgoing parton. The * pseudo-rapidity is measured in the lab system. */ double theMinEta; /** * The maximum allowed pseudo-rapidity of an outgoing parton. The * pseudo-rapidity is measured in the lab system. */ double theMaxEta; /** * If non-null only particles matching this object will be affected * by this cut. */ PMPtr theMatcher; private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initSimpleKTCut; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ SimpleKTCut & operator=(const SimpleKTCut &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of SimpleKTCut. */ template <> struct BaseClassTrait { /** Typedef of the first base class of SimpleKTCut. */ typedef OneCutBase NthBase; }; /** This template specialization informs ThePEG about the name of * the SimpleKTCut 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::SimpleKTCut"; } /** Return the name of the shared library be loaded to get * access to the SimpleKTCut class and every other class it uses * (except the base class). */ static string library() { return "SimpleKTCut.so"; } }; /** @endcond */ } #endif /* THEPEG_SimpleKTCut_H */ diff --git a/Cuts/TwoCutBase.cc b/Cuts/TwoCutBase.cc --- a/Cuts/TwoCutBase.cc +++ b/Cuts/TwoCutBase.cc @@ -1,71 +1,71 @@ // -*- C++ -*- // // TwoCutBase.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the TwoCutBase class. // #include "TwoCutBase.h" #include "Cuts.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/CurrentGenerator.h" using namespace ThePEG; TwoCutBase::~TwoCutBase() {} void TwoCutBase::describe() const { CurrentGenerator::log() << fullName() << " has no description.\n\n"; } bool TwoCutBase::passCuts(tcCutsPtr parent, tcPDPtr pitype, tcPDPtr pjtype, LorentzMomentum pi, LorentzMomentum pj, bool inci, bool incj) const { if ( inci && incj ) return true; else if ( inci ) { if ( -(pj - pi).m2() <= minTij(pitype, pjtype) ) return false; if ( pj.perp() <= minKTClus(tcPDPtr(), pjtype) ) return false; } else if ( incj ) { if ( -(pi - pj).m2() <= minTij(pjtype, pitype) ) return false; if ( pi.perp() <= minKTClus(tcPDPtr(), pitype) ) return false; } else { if ( (pi + pj).m2() <= minSij(pitype, pjtype) ) return false; double deta2 = sqr(pi.eta() - pj.eta()); double dphi = abs(pi.phi() - pj.phi()); if ( dphi > Constants::pi ) dphi = 2.0*Constants::pi - dphi; double dr = sqrt(deta2 + sqr(dphi)); if ( dr < minDeltaR(pitype, pjtype) ) return false; if ( min(pi.perp(), pj.perp())*dr <= minKTClus(pitype, pjtype) ) return false; if ( 2.0*sqr(min(pi.e(), pj.e()))*(1.0 - cos(pi.angle(pj))) < parent->currentSHat()*minDurham(pitype, pjtype) ) return false; } return true; } bool TwoCutBase::passCuts(tcCutsPtr parent, tcPPtr pi, tcPPtr pj, bool inci, bool incj) const { return passCuts(parent, pi->dataPtr(), pj->dataPtr(), pi->momentum(), pj->momentum(), inci, incj); } AbstractNoPIOClassDescription TwoCutBase::initTwoCutBase; // Definition of the static class description member. void TwoCutBase::Init() { static ClassDocumentation documentation ("This class corresponds to a kinematical cut to be made on a pair of " "particles in a hard sub-process."); } diff --git a/Cuts/TwoCutBase.h b/Cuts/TwoCutBase.h --- a/Cuts/TwoCutBase.h +++ b/Cuts/TwoCutBase.h @@ -1,175 +1,175 @@ // -*- C++ -*- // // TwoCutBase.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_TwoCutBase_H #define THEPEG_TwoCutBase_H // // This is the declaration of the TwoCutBase class. // #include "ThePEG/Interface/Interfaced.h" #include "TwoCutBase.fh" #include "Cuts.fh" namespace ThePEG { /** * This class corresponds to a kinematical cut to be made on a pair of * particles in a hard sub-process. * * There are six main virtual functions to be overridden by concrete * sub-classes. minsSij(), minTij(), minDeltaR(), minKTClus() and * minDurham() returns the minimum allowed values of pre defined * kinematical variable. In addition the passCut() function should * return true if a pair of particle with a given types and given * momenta will pass the cuts. * * @see \ref TwoCutBaseInterfaces "The interfaces" defined for * TwoCutBase. */ class TwoCutBase: public Interfaced { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ TwoCutBase() {} /** * The destructor. */ virtual ~TwoCutBase(); //@} public: /** @name Virtual functions to be overridden by sub-classes. */ //@{ /** * Return the minimum allowed squared invariant mass of two outgoing * partons of type \a pi and \a pj. */ virtual Energy2 minSij(tcPDPtr pi, tcPDPtr pj) const = 0; /** * Return the minimum allowed value of the negative of the squared * invariant mass of an incoming parton of type \a pi and an * outgoing parton of type \a po. */ virtual Energy2 minTij(tcPDPtr pi, tcPDPtr po) const = 0; /** * Return the minimum allowed value of \f$\Delta * R_{ij}=\sqrt{\Delta\eta_{ij}^2+\Delta\phi_{ij}^2}\f$ of two * outgoing partons of type \a pi and \a pj. */ virtual double minDeltaR(tcPDPtr pi, tcPDPtr pj) const = 0; /** * Return the minimum allowed value of the longitudinally invariant * \f$k_\perp\f$-algorithms distance measure. This is defined as * \f$\min(p_{\perp i}, p_{\perp * j})\sqrt{\Delta\eta_{ij}^2+\Delta\phi_{ij}^2}\f$ for two outgoing * partons, or simply \f$p_{\perp i}\f$ or \f$p_{\perp j}\f$ for a * single outgoing parton. Returns 0 if both partons are incoming. A * null pointer indicates an incoming parton, hence the type of the * incoming parton is irrelevant. */ virtual Energy minKTClus(tcPDPtr pi, tcPDPtr pj) const = 0; /** * Return the minimum allowed value of the Durham * \f$k_\perp\f$-algorithms distance measure. This is defined as * \f$2\min(E_j^2, E_j^2)(1-\cos\theta_{ij})/\hat{s}\f$ for two * outgoing partons. */ virtual double minDurham(tcPDPtr pi, tcPDPtr pj) const = 0; /** * Return true if a pair of particles with type \a pitype and \a * pjtype and momenta \a pi and \a pj respectively passes the * cuts. \a inci and \a inj indicates if the corresponding particles * are incoming. */ virtual bool passCuts(tcCutsPtr parent, tcPDPtr pitype, tcPDPtr pjtype, LorentzMomentum pi, LorentzMomentum pj, bool inci = false, bool incj = false) const; /** * Return true if the given pair of particles passes the cuts. \a * inci and \a inj indicates if the corresponding particles are * incoming. */ bool passCuts(tcCutsPtr parent, tcPPtr pi, tcPPtr pj, bool inci = false, bool incj = false) const; //@} /** * Describe the currently active cuts in the log file. */ virtual void describe() const; public: /** * 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(); private: /** * The static object used to initialize the description of this class. * Indicates that this is an abstract class with persistent data. */ static AbstractNoPIOClassDescription initTwoCutBase; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ TwoCutBase & operator=(const TwoCutBase &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of TwoCutBase. */ template <> struct BaseClassTrait { /** Typedef of the first base class of TwoCutBase. */ typedef Interfaced NthBase; }; /** This template specialization informs ThePEG about the name of * the TwoCutBase 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::TwoCutBase"; } }; /** @endcond */ } #endif /* THEPEG_TwoCutBase_H */ diff --git a/Cuts/V2LeptonsCut.cc b/Cuts/V2LeptonsCut.cc --- a/Cuts/V2LeptonsCut.cc +++ b/Cuts/V2LeptonsCut.cc @@ -1,227 +1,227 @@ // -*- C++ -*- // // V2LeptonsCut.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the V2LeptonsCut class. // #include "V2LeptonsCut.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Repository/CurrentGenerator.h" using namespace ThePEG; V2LeptonsCut::~V2LeptonsCut() {} void V2LeptonsCut::describe() const { CurrentGenerator::log() << fullName() << ":\n" << "M = " << theMinM/GeV << " .. " << theMaxM/GeV << " GeV\n\n"; } IBPtr V2LeptonsCut::clone() const { return new_ptr(*this); } IBPtr V2LeptonsCut::fullclone() const { return new_ptr(*this); } Energy2 V2LeptonsCut::minS(const tcPDVector & pv) const { if ( pv.size() != 2 ) return ZERO; if ( !checkTypes(pv[0]->id(), pv[1]->id()) ) return ZERO; return sqr(theMinM); } Energy2 V2LeptonsCut::maxS(const tcPDVector & pv) const { if ( pv.size() != 2 ) return Constants::MaxEnergy2; if ( !checkTypes(pv[0]->id(), pv[1]->id()) ) return Constants::MaxEnergy2; return sqr(theMaxM); } bool V2LeptonsCut::passCuts(tcCutsPtr, const tcPDVector & ptype, const vector & p) const { for ( int i = 0, N = ptype.size() - 1; i < N; ++i ) for ( int j = i + 1, M = ptype.size(); j < M; ++j ) { if ( !checkTypes(ptype[i]->id(), ptype[j]->id()) ) continue; Energy2 s = (p[i] + p[j]).m2(); if ( s <= sqr(theMinM) || s >= sqr(theMaxM) ) return false; } return true; } int V2LeptonsCut::family(long id) const { switch ( abs(id) ) { case ParticleID::eminus: case ParticleID::nu_e: return electron; case ParticleID::muminus: case ParticleID::nu_mu: return muon; case ParticleID::tauminus: case ParticleID::nu_tau: return tau; } return 0; } bool V2LeptonsCut::checkTypes(long id1, long id2) const { // Must be particle anti-particle pair; if ( id1*id2 >= 0 ) return false; // Check that we have leptons, the families are the same and matches // the chosen ones. int fam1 = family(id1); if ( !fam1 ) return false; int fam2 = family(id2); if ( fam2 != fam1 || !(theFamilies&fam1) ) return false; // Check charge combination. int ccomb; if ( (id1%2) && (id2%2) ) ccomb = posneg; else if ( id1%2 ) { if ( id1 > 0 ) ccomb = negneu; else ccomb = posneu; } else if ( id2%2 ) { if ( id2 > 0 ) ccomb = negneu; else ccomb = posneu; } else ccomb = neuneu; return (theCComb&ccomb); } void V2LeptonsCut::persistentOutput(PersistentOStream & os) const { os << ounit(theMinM, GeV) << ounit(theMaxM, GeV) << theFamilies << theCComb; } void V2LeptonsCut::persistentInput(PersistentIStream & is, int) { is >> iunit(theMinM, GeV) >> iunit(theMaxM, GeV) >> theFamilies >> theCComb; } Energy V2LeptonsCut::maxMinM() const { return theMaxM; } Energy V2LeptonsCut::minMaxM() const { return theMinM; } ClassDescription V2LeptonsCut::initV2LeptonsCut; // Definition of the static class description member. void V2LeptonsCut::Init() { static ClassDocumentation documentation ("This class inherits from MultiCutBase and describes cuts on the " "invariant mass of two final state leptons corresponding to the decay " "of a vector boson. It can be used when generating matrix elements to " "avoid the long tails of the resonance."); static Parameter interfaceMinM ("MinM", "The minimum allowed invariant mass of the matched lepton pair.", &V2LeptonsCut::theMinM, GeV, 70.0*GeV, ZERO, Constants::MaxEnergy, true, false, Interface::limited, 0, 0, 0, &V2LeptonsCut::maxMinM, 0); static Parameter interfaceMaxM ("MaxM", "The maximum allowed invariant mass of the matched lepton pair.", &V2LeptonsCut::theMaxM, GeV, 90.0*GeV, ZERO, ZERO, true, false, Interface::lowerlim, 0, 0, &V2LeptonsCut::minMaxM, 0, 0); static Switch interfaceFamilies ("Families", "The different lepton families for which this cut should apply.", &V2LeptonsCut::theFamilies, electron|muon, true, false); static SwitchOption interfaceFamiliesElectron (interfaceFamilies, "Electron", "Only apply cut to electrons and electron neutrinos.", electron); static SwitchOption interfaceFamiliesMuon (interfaceFamilies, "Muon", "Only apply cut to muons and muon neutrinos.", muon); static SwitchOption interfaceFamiliesTau (interfaceFamilies, "Tau", "Only apply cut to taus and tau neutrinos.", tau); static SwitchOption interfaceFamiliesElectronMuon (interfaceFamilies, "ElectronMuon", "Only apply cut to electron and muon leptons.", electron|muon); static SwitchOption interfaceFamiliesAll (interfaceFamilies, "All", "Apply cut to all lepton families.", electron|muon|tau); static Switch interfaceCComb ("CComb", "The charge combination of the lepton pair on which to cut.", &V2LeptonsCut::theCComb, posneu|negneu, true, false); static SwitchOption interfaceCCombAll (interfaceCComb, "All", "Cut on all relevant charge combinations.", posneg|negneu|posneu|neuneu); static SwitchOption interfaceCCombWplus (interfaceCComb, "Wplus", "Cut on positive lepton neutrin pairs.", posneu); static SwitchOption interfaceCCombWminus (interfaceCComb, "Wminus", "Cut on negative lepton anti-neutrin pairs.", negneu); static SwitchOption interfaceCCombW (interfaceCComb, "W", "Cut on charged lepton neutrino pairs.", posneu|negneu); static SwitchOption interfaceCCombGamma (interfaceCComb, "Gamma", "Cut on charged lepton anti-lepton pairs.", posneg); static SwitchOption interfaceCCombZ (interfaceCComb, "Z", "Cut on lepton anti-lepton pairs.", neuneu|posneg); static SwitchOption interfaceCCombZneutrinos (interfaceCComb, "Zneutrinos", "Cut on neutrino anti-neutrino pairs.", neuneu); interfaceMinM.rank(10); interfaceMaxM.rank(9); interfaceMinM.setHasDefault(false); interfaceMaxM.setHasDefault(false); interfaceCComb.setHasDefault(false); interfaceFamilies.setHasDefault(false); } diff --git a/Cuts/V2LeptonsCut.h b/Cuts/V2LeptonsCut.h --- a/Cuts/V2LeptonsCut.h +++ b/Cuts/V2LeptonsCut.h @@ -1,234 +1,234 @@ // -*- C++ -*- // // V2LeptonsCut.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_V2LeptonsCut_H #define THEPEG_V2LeptonsCut_H // // This is the declaration of the V2LeptonsCut class. // #include "ThePEG/Cuts/MultiCutBase.h" namespace ThePEG { /** * This class inherits from MultiCutBase and describes cuts on the * invariant mass of two final state leptons corresponding to the * decay of a vector boson. It can be used when generating matrix * elements to avoid the long tails of the resonance. * * @see \ref V2LeptonsCutInterfaces "The interfaces" * defined for V2LeptonsCut. */ class V2LeptonsCut: public MultiCutBase { /** * Enumeration of the different families. */ enum Family { electron = 1, /**< Lepton Family. */ muon = 2, /**< Muon Family. */ tau = 4 /**< Tau Family. */ }; /** * Enumeration of charge combinations. */ enum CComb { posneg = 1, /**< charged lepton anti-lepton pair. */ negneu = 2, /**< negative lepton anti-neutrino pair. */ posneu = 4, /**< positive lepton anti-neutrino pair. */ neuneu = 8 /**< neutrino anti-neutrino pair. */ }; public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ V2LeptonsCut() : theMinM(70.0*GeV), theMaxM(90.0*GeV), theFamilies(electron|muon), theCComb(negneu|posneu) {} /** * The destructor. */ virtual ~V2LeptonsCut(); //@} public: /** @name Overridden virtual functions defined in the base class. */ //@{ /** * Return the minimum allowed value of the squared invariant mass of * a set of outgoing partons of the given types. Typically used to * cut off the tails of the mass of a resonance for efficiency. */ virtual Energy2 minS(const tcPDVector & pv) const; /** * Return the maximum allowed value of the squared invariant mass of * a set of outgoing partons of the given types. Typically used to * cut off the tails of the mass of a resonance for efficiency. */ virtual Energy2 maxS(const tcPDVector & pv) const; /** * Return true if a set of outgoing particles with typea \a ptype * and corresponding momenta \a p passes the cuts. */ virtual bool passCuts(tcCutsPtr parent, const tcPDVector & ptype, const vector & p) const; //@} /** * Describe the currently active cuts in the log file. */ virtual void describe() const; protected: /** * Check if the PDG id numbers matches this cut. */ bool checkTypes(long id1, long id2) const; /** * Check the family of the given PDG id number. */ int family(long id) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * Helper function used by the interface. */ Energy maxMinM() const; /** * Helper function used by the interface. */ Energy minMaxM() const; private: /** * The minimum invariant mass. */ Energy theMinM; /** * The maximum invariant mass. */ Energy theMaxM; /** * Integer corresponding to the lepton families to match. */ int theFamilies; /** * Integer corresponding to the charge combination to match. */ int theCComb; private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initV2LeptonsCut; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ V2LeptonsCut & operator=(const V2LeptonsCut &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of V2LeptonsCut. */ template <> struct BaseClassTrait { /** Typedef of the first base class of V2LeptonsCut. */ typedef MultiCutBase NthBase; }; /** This template specialization informs ThePEG about the name of * the V2LeptonsCut 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::V2LeptonsCut"; } /** Return the name of the shared library be loaded to get * access to the V2LeptonsCut class and every other class it uses * (except the base class). */ static string library() { return "V2LeptonsCut.so"; } }; /** @endcond */ } #endif /* THEPEG_V2LeptonsCut_H */ diff --git a/EventRecord/Collision.cc b/EventRecord/Collision.cc --- a/EventRecord/Collision.cc +++ b/EventRecord/Collision.cc @@ -1,213 +1,213 @@ // -*- C++ -*- // // Collision.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined member functions of // the 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 #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 ( 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 ( 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/Collision.h b/EventRecord/Collision.h --- a/EventRecord/Collision.h +++ b/EventRecord/Collision.h @@ -1,416 +1,416 @@ // -*- C++ -*- // // Collision.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_Collision_H #define ThePEG_Collision_H // This is the decalaration of the Collision class. It #include "EventConfig.h" #include "Particle.h" #include "StandardSelectors.h" #include "ThePEG/Vectors/LorentzVector.h" #include "ThePEG/Vectors/LorentzRotation.h" namespace ThePEG { /** * This is the decalaration of the Collision class. It contains all * Particles produced in the generation of a collision * between two particles in an Event. The particles are divided into * Steps corresponding to the particles present after a * given step in the event generation. The collision also carries * information about the SubProcesses in the collision. * * @see Event * @see Step * @see SubProcess * @see Particle */ class Collision: public EventRecordBase { public: /** * EventHandler is a friend of most Event classes. */ friend class EventHandler; /** Most of the Event classes are friends with each other. */ friend class Event; /** Most of the Event classes are friends with each other. */ friend class Step; public: /** * The standard constructor takes a pair of incoming particles as * argument. Optionally can be given a pointer to the Event which * this Collision belongs, and a pointer to the EventHandler * which produced this collision. * @param newIncoming a pair of incoming particles. * @param newEvent the Event to which this Collision belongs. * @param newHandler the handler object in charge of the generation * of this Collision. */ Collision(const PPair & newIncoming, tEventPtr newEvent = tEventPtr(), tcEventBasePtr newHandler = tcEventBasePtr()) : theIncoming(newIncoming), theEvent(newEvent), theHandler(newHandler) { addParticle(incoming().first); addParticle(incoming().second); } /** * The destructor */ ~Collision(); public: /** * Create a new step in this collision, which is a copy of * the last step (if any) and return a pointer to it. * @param newHandler the handler object in charge of generating the * new step. */ tStepPtr newStep(tcEventBasePtr newHandler = tcEventBasePtr()); /** * Add a new Step to this Collision. */ void addStep(tStepPtr s); /** * Return a pointer to the EventHandler which produced this * Collision. May be the null pointer. */ tcEventBasePtr handler() const { return theHandler; } /** * Return a pointer to the Event to which this Collision * belongs. May be the null pointer. */ tEventPtr event() const { return theEvent; } /** @name Functions for accessing particles etc. */ //@{ /** * Extract particles from this Collision which satisfies the * requirements given by an object of the SelectorBase class. * @param r an output iterator specifying where the extracted * (pointers to) particles will be appended. * @param s SelectorBase object defining which particles should be * extracted. */ template void select(OutputIterator r, const SelectorBase & s) const; /** * Extract all final state particles in this Collision. * @param r an output iterator specifying where the extracted * (pointers to) particles will be appended. */ template void selectFinalState(OutputIterator r) const { select(r, SelectFinalState()); } /** * Extract all final state particles in this Collision. * @return a vector of pointers to the extracted particles. */ tPVector getFinalState() const { tPVector ret; selectFinalState(back_inserter(ret)); return ret; } /** * Return a pointer to the primary SubProcess in this Collision. May * be the null pointer. */ tSubProPtr primarySubProcess() const { return subProcesses().empty()? SubProPtr(): subProcesses().front(); } /** * Return the possibly empty list of sub processes in this Collision. */ const SubProcessVector & subProcesses() const { return theSubProcesses; } /** * Return a const pointer to the last step in this Collission. */ tcStepPtr finalStep() const { return steps().empty()? tcStepPtr(): tcStepPtr(steps().back()); } /** * Return a pointer to the last step in this Collission. */ tStepPtr finalStep() { return steps().empty()? StepPtr(): steps().back(); } /** * Return the vector of steps in this Collision. */ const StepVector & steps() const { return theSteps; } /** * Return a pointer to a given Step in this Collision. */ tcStepPtr step(unsigned int i) const { return i < steps().size()? tcStepPtr(theSteps[i]): tcStepPtr(); } /** * Return a reference to the pair of colliding particles in this * Collision. */ const PPair & incoming() const { return theIncoming; } /** * Return the set of remnants in this collision. Remnants are * defined as the daughters of the incoming particles which are not * incoming particles to any SubProcess or children thereof which * are present in the final state. */ tParticleSet getRemnants() const; /** * Return true if the given particle is a remnant of the colliding * particles. Calls the getRemnants method, so to check several * particles it is better to call getRemnants directly and check if * the particles are members of the resulting set by hand. */ bool isRemnant(tPPtr p) const { return member(getRemnants(), p); } //@} /** * Return the vertex position of this Collision. */ const LorentzPoint & vertex() const { return theVertex; } /** * Set the vertex position of this Collision. */ void vertex(const LorentzPoint & p) { theVertex = p; } /** * Transform all particles in this Collision. */ void transform(const LorentzRotation &); /** * Return the total invariant mass squared of the final-state * particles in this Collision. */ Energy2 m2() const { return ( incoming().first->momentum() + incoming().second->momentum() ).m2(); } /** @name Functions for removing entires from a Collision. */ //@{ /** * Remove (recursively) the decay products from a given Particle and * add the particle to the list of final state particles. */ void removeDecay(tPPtr); /** * Remove (recursively) the given Particle from the Collision. If * this was the last daughter of the mother Particle, the latter is * added to the list of final state particles. */ void removeParticle(tPPtr); /** * Remove all steps which have no new particles introduced in them. */ void cleanSteps(); /** * Remove the last Step in this Collision. */ void popStep(); //@} public: /** * Standard function for writing to a persistent stream. */ void persistentOutput(PersistentOStream &) const; /** * Standard functions for reading from a persistent stream. */ void persistentInput(PersistentIStream &, int); /** * Standard Init function. @see Base::Init(). */ static void Init(); protected: /** @name Internal functions for adding and removing entires. */ //@{ /** * Add a new SubProcess to this Collision. */ void addSubProcess(tSubProPtr p); /** * Remove a SubProcess from this Collision. */ void removeSubProcess(tSubProPtr p); /** * Add a range of particles to this Collision. */ template void addParticles(Iterator first, Iterator last); /** * Add a particle to this Collision. */ void addParticle(tPPtr p); /** * Remove a given Particle entry. */ void removeEntry(tPPtr p); //@} /** * Return a reference to the list of all particles in this Collision. */ const ParticleSet & all() const { return allParticles; } /** * Clone this Collision. This also makes clones of all steps, sub * processes and particles in this Collision. */ CollPtr clone() const; /** * Rebind to cloned objects. When a Collision is cloned, a shallow * copy is done first, then all Particles etc, are * cloned, and finally this method is used to see to that the * pointers in the cloned Collision points to the cloned * Particles etc. */ void rebind(const EventTranslationMap & trans); private: /** * The pair of colliding particles. */ PPair theIncoming; /** * A vector of all steps in this Collision. */ StepVector theSteps; /** * A vector of all sub-processes in this Collision. The front * element points to the primary sub-process. */ SubProcessVector theSubProcesses; /** * A set of all particles in this Collision. */ ParticleSet allParticles; /** * A pointer to the Event to which this Collision belongs. */ tEventPtr theEvent; /** * A pointer to the EventHandler which performed the generation * of this Collision. */ tcEventBasePtr theHandler; /** * The vertex position of this Collision */ LorentzPoint theVertex; private: /** * Describe concrete class with persistent data. */ static ClassDescription initCollision; /** * Private default constructor must only be used by the * PersistentIStream class via the ClassTraits class . */ Collision() {} /** * The ClassTraits class must be a friend to be able to * use the private default constructor. */ friend struct ClassTraits; /** * The assignment operator is private and not implemented. */ Collision & operator=(const Collision &) = delete; /** Output to a standard ostream. */ friend ostream & operator<<(ostream & os, const Collision & c); }; /** Output a Collision to a standard ostream. */ ostream & operator<<(ostream &, const Collision &); /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base class of Collision. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of Collision. */ typedef EventRecordBase NthBase; }; /** This template specialization informs ThePEG about the name of * the Collision class and how to create it. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "ThePEG::Collision"; } /** Create a Collision object. */ static TPtr create() { return TPtr::Create(Collision()); } }; /** @endcond */ } #ifndef ThePEG_TEMPLATES_IN_CC_FILE #include "Collision.tcc" #endif #endif /* ThePEG_Collision_H */ diff --git a/EventRecord/Collision.tcc b/EventRecord/Collision.tcc --- a/EventRecord/Collision.tcc +++ b/EventRecord/Collision.tcc @@ -1,45 +1,45 @@ // -*- C++ -*- // // Collision.tcc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the templated member functions of // the Collision class. // #include "Step.h" #include "Event.h" namespace ThePEG { template void Collision::select(OutputIterator r, const SelectorBase & s) const { if ( s.allSteps() ) { if ( incoming().first && s.intermediate() && s.check(*incoming().first) ) *r++ = incoming().first; if ( incoming().first && s.intermediate() && s.check(*incoming().second) ) *r++ = incoming().second; for ( StepVector::const_iterator it = theSteps.begin(); it != theSteps.end(); ++it ) (**it).select(r, s); } else { if ( incoming().first && s.intermediate() && s.check(*incoming().first) && steps().size() < 2 ) *r++ = incoming().first; if (incoming().first && s.intermediate() && s.check(*incoming().second) && steps().size() < 2 ) *r++ = incoming().second; finalStep()->select(r, s); } } template void Collision::addParticles(Iterator first, Iterator last) { allParticles.insert(first, last); if ( event() ) event()->addParticles(first, last); } } diff --git a/EventRecord/ColourBase.cc b/EventRecord/ColourBase.cc --- a/EventRecord/ColourBase.cc +++ b/EventRecord/ColourBase.cc @@ -1,56 +1,56 @@ // -*- C++ -*- // // ColourBase.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the ColourBase class. // #include "ColourBase.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Utilities/Rebinder.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG; EIPtr ColourBase::clone() const { return new_ptr(*this); } bool ColourBase::hasColourLine(tcColinePtr line, bool anti) const { return ( anti? ( antiColourLine() == line ): ( colourLine() == line ) ); } vector ColourBase::antiColourLines() const { return antiColourLine()? vector(1, antiColourLine()): vector(); } vector ColourBase::colourLines() const { return colourLine()? vector(1, colourLine()): vector(); } void ColourBase::rebind(const EventTranslationMap & trans) { theAntiColourLine = trans.translate(theAntiColourLine); theColourLine = trans.translate(theColourLine); } void ColourBase::persistentOutput(PersistentOStream & os) const { os << theAntiColourLine << theColourLine; } void ColourBase::persistentInput(PersistentIStream & is, int) { is >> theAntiColourLine >> theColourLine; } ClassDescription ColourBase::initColourBase; void ColourBase::Init() {} diff --git a/EventRecord/ColourBase.h b/EventRecord/ColourBase.h --- a/EventRecord/ColourBase.h +++ b/EventRecord/ColourBase.h @@ -1,173 +1,173 @@ // -*- C++ -*- // // ColourBase.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_ColourBase_H #define ThePEG_ColourBase_H // This is the declaration of the ColourBase class. #include "ThePEG/EventRecord/EventInfoBase.h" #include "ThePEG/EventRecord/ColourLine.h" namespace ThePEG { /** * ColourBase is the base class to be used to supply a * Particle with information about its colour * state. This base class supplies information about the * ColourLines to which the particle is * connected. This should be sufficient for most uses. If any other * info is required for a particle, it may be supplied by an object of * a sub-class of ColourBase, the additional information * would then have to be extracted by dynamically casting to the * sub-class. * * @see Particle * @see ColourLine */ class ColourBase: public EventInfoBase { public: /** ColourLine is a good friend. */ friend class ColourLine; public: /** * Return the anti-colour line to which this particle is connected. */ tColinePtr antiColourLine() const { return theAntiColourLine; } /** * Return the colour line to which this particle is connected. */ tColinePtr colourLine() const { return theColourLine; } /** * Return the anti-colour lines to which this particle is * connected. (Always only one colour line for this base class.) */ virtual vector antiColourLines() const; /** * Return the colour lines to which this particle is * connected. (Always only one colour line for this base class.) */ virtual vector colourLines() const; /** * Return true if the particle is connected to the given (\a anti-) * colour \a line. */ virtual bool hasColourLine(tcColinePtr line, bool anti = false) const; /** * Return true if the particle is connected to the given anti-colour * \a line. */ bool hasAntiColourLine(tcColinePtr line) const { return hasColourLine(line, true); } protected: /** * Set the anti-colour \a line to which this particle is connected. */ virtual void antiColourLine(tColinePtr line) { theAntiColourLine = line; } /** * Set the (\a anti-) colour line to which this particle is connected. */ virtual void colourLine(tColinePtr l, bool anti = false) { if ( anti ) antiColourLine(l); else theColourLine = l; } /** * Remove the anti-colour \a line to which this particle is connected. */ virtual void removeAntiColourLine(tcColinePtr line) { if ( antiColourLine() == line ) theAntiColourLine = tColinePtr(); } /** * Remove the (\a anti-) colour line to which this particle is connected. */ virtual void removeColourLine(tcColinePtr line, bool anti = false) { if ( anti ) removeAntiColourLine(line); else if ( colourLine() == line ) theColourLine = tColinePtr(); } public: /** * Rebind to cloned objects. When a ColourBase is cloned, a shallow * copy is done first, then all ColourLines etc, are * cloned, and finally this method is used to see to that the * pointers in the cloned ColourBase points to the cloned * ColourLines etc. */ virtual void rebind(const EventTranslationMap & trans); /** * Standard function for writing to a persistent stream. */ void persistentOutput(PersistentOStream &) const; /** * Standard functions for reading from a persistent stream. */ void persistentInput(PersistentIStream &, int); /** * Standard Init function. @see Base::Init(). */ static void Init(); /** * Standard clone method. */ virtual EIPtr clone() const; private: /** * The anti-colour line to which this particle is connected. */ ColinePtr theAntiColourLine; /** * The colour line to which this particle is connected. */ ColinePtr theColourLine; private: /** * Describe concrete class with persistent data. */ static ClassDescription initColourBase; /** * Private and non-existent assignment operator. */ ColourBase & operator=(const ColourBase &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ ThePEG_DECLARE_CLASS_TRAITS(ColourBase,EventInfoBase); /** @endcond */ } #endif /* ThePEG_ColourBase_H */ diff --git a/EventRecord/ColourLine.cc b/EventRecord/ColourLine.cc --- a/EventRecord/ColourLine.cc +++ b/EventRecord/ColourLine.cc @@ -1,159 +1,159 @@ // -*- C++ -*- // // ColourLine.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the ColourLine class. // #include "ColourLine.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/EventRecord/Event.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Config/algorithm.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG; tColinePtr ColourLine::create(tPPtr col, tPPtr anti) { if ( col->colourLine() || anti->antiColourLine() ) return tColinePtr(); ColinePtr l = new_ptr(ColourLine()); l->addColoured(col); l->addAntiColoured(anti); return l; } tColinePtr ColourLine::create(tPPtr col, bool anti) { if ( col->colourLine(anti) ) return tColinePtr(); ColinePtr l = new_ptr(ColourLine()); l->addColoured(col, anti); return l; } tColinePtr ColourLine::create(tColinePtr son1, tColinePtr son2, tColinePtr sin1, tColinePtr sin2) { if ( !son1 || !son2 || !sin1 || !sin2 ) return tColinePtr(); ColinePtr l = new_ptr(ColourLine()); l->theSourceNeighbours = make_pair(son1, son2); son1->theSourceNeighbours = make_pair(son2, l); son2->theSourceNeighbours = make_pair(l, son1); l->theSinkNeighbours = make_pair(sin1, sin2); sin1->theSinkNeighbours = make_pair(sin2, l); sin2->theSinkNeighbours = make_pair(l, sin1); son1->orphanedConnectors.push_back(l); return l; } ColourLine::~ColourLine() {} tPPtr ColourLine::startParticle() const { if ( sourceNeighbours().first ) return tPPtr(); for ( tPVector::const_reverse_iterator it = antiColoured().rbegin(); it != antiColoured().rend(); ++it ) if ( !(**it).outgoingAntiColour() ) return *it; return tPPtr(); } tPPtr ColourLine::endParticle() const { if ( sinkNeighbours().first ) return tPPtr(); for ( tPVector::const_reverse_iterator it = coloured().rbegin(); it != coloured().rend(); ++it ) if ( !(**it).outgoingColour() ) return *it; return tPPtr(); } void ColourLine::addAntiColouredIndexed(tPPtr p, int index) { theAntiColoured.push_back(p); Ptr::pointer colour = dynamic_ptr_cast::pointer> (p->colourInfo()); colour->antiColourLine(this, index); } void ColourLine::addColouredIndexed(tPPtr p, int index, bool anti) { if ( anti ) addAntiColouredIndexed(p, index); else { theColoured.push_back(p); Ptr::pointer colour = dynamic_ptr_cast::pointer> (p->colourInfo()); colour->colourLine(this, index); } } void ColourLine::addAntiColoured(tPPtr p) { theAntiColoured.push_back(p); p->colourInfo()->antiColourLine(this); } void ColourLine::addColoured(tPPtr p, bool anti) { if ( anti ) addAntiColoured(p); else { theColoured.push_back(p); p->colourInfo()->colourLine(this); } } void ColourLine::removeAntiColoured(tPPtr p) { tPVector::iterator cp=find(range(theAntiColoured), p); if(cp!=theAntiColoured.end()) theAntiColoured.erase(cp); p->colourInfo()->removeAntiColourLine(this); } void ColourLine::removeColoured(tPPtr p, bool anti) { if ( anti ) removeAntiColoured(p); else { tPVector::iterator cp=find(range(theColoured), p); if(cp!=theColoured.end()) theColoured.erase(cp); p->colourInfo()->removeColourLine(this); } } bool ColourLine::join(ColinePtr line) { if ( !startParticle() || startParticle() != line->endParticle() ) return false; while ( line->coloured().size() ) { tPPtr p = line->coloured()[0]; line->removeColoured(p); theColoured.insert(theColoured.begin(), p); p->colourInfo()->colourLine(this); } while ( line->antiColoured().size() ) { tPPtr p = line->antiColoured()[0]; line->removeAntiColoured(p); theAntiColoured.push_back(p); p->colourInfo()->antiColourLine(this); } return true; } void ColourLine::write(ostream & os, tcEventPtr event, bool anti) const { os << ( anti? '-': '+' ); int index = event->colourLineIndex(this); if ( sourceNeighbours().first && sourceNeighbours().second ) os << '(' << event->colourLineIndex(sourceNeighbours().first) << '*' << event->colourLineIndex(sourceNeighbours().second) << ')'; os << index; if ( sinkNeighbours().first && sinkNeighbours().second ) os << '(' << event->colourLineIndex(sinkNeighbours().first) << '.' << event->colourLineIndex(sinkNeighbours().second) << ')'; } void ColourLine::persistentOutput(PersistentOStream & os) const { os << theColoured << theAntiColoured << theSourceNeighbours << theSinkNeighbours << orphanedConnectors; } void ColourLine::persistentInput(PersistentIStream & is, int) { is >> theColoured >> theAntiColoured >> theSourceNeighbours >> theSinkNeighbours >> orphanedConnectors; } ClassDescription ColourLine::initColourLine; // Definition of the static class description member. diff --git a/EventRecord/ColourLine.h b/EventRecord/ColourLine.h --- a/EventRecord/ColourLine.h +++ b/EventRecord/ColourLine.h @@ -1,315 +1,315 @@ // -*- C++ -*- // // ColourLine.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_ColourLine_H #define ThePEG_ColourLine_H // This is the declaration of the ColourLine class. #include "EventConfig.h" #include "ThePEG/Utilities/ClassDescription.h" #include "ThePEG/EventRecord/ColourSinglet.h" namespace ThePEG { /** * The ColourLine class represents colour lines connecting * Particles. A ColourLine keeps track on * the particles connected to it. To connect a particle to a colour * line the addColoured() and * addAntiColoured() functions should be used - these * will automatically set up the Particle correctly. There is no * method in a Particle to directly set its colour lines. * * If a colour line stems from a colour source or ends in a colour * sink, it is possible to obtain the neighbouring colour lines. This * is also the way junction strings and sinks and sources are * implemented. * * @see Particle * @see ColourBase */ class ColourLine: public EventRecordBase { public: /** @name Creation functions. */ //@{ /** * Create a colour line. Set a pair of colour - anticolour particles * in a newly created colour line. */ static tColinePtr create(tPPtr col, tPPtr anti); /** * Create a colour line. Set a particle for which the created object * is a (anti-)colour line . * @param p the particle to be connected. * @param anti if true, the created object is the anti-colour line * of \a p. */ static tColinePtr create(tPPtr p, bool anti = false); /** * Create a colour line. Set a particle for which the created object * is a anti-colour line . * @param p the particle to be connected. */ static tColinePtr createAnti(tPPtr p) { return create(p, true); } /** * Create a coloue line which is a connector between two junctions, * a source junction with neigboring colour lines \a son1 and \a * son2 and a sink junction with neigboring colour lines \a sin1 and * \a sin2. */ static tColinePtr create(tColinePtr son1, tColinePtr son2, tColinePtr sin1, tColinePtr sin2); //@} /** * Destructor. */ virtual ~ColourLine(); public: /** @name Access particles connected to the colour line. */ //@{ /** * Return the vectors of particles connected to this line with their * colours. */ const tPVector & coloured() const { return theColoured; } /** * Return the vectors of particles connected to this line with their * anti-colours. */ const tPVector & antiColoured() const { return theAntiColoured; } /** * Return the first particle on this colour line. Returns null if * this line stems from a colour source. If the particle is * outgoing, its anti colour is connected, otherwise its colour is * connected. */ tPPtr startParticle() const; /** * Return the last particle on this colour line. Returns null if * this line ends in a colour sink. If the particle is outgoing, its * colour is connected, otherwise its anti colour is connected. */ tPPtr endParticle() const; //@} /** @name Add and remove particles in a colour line. */ //@{ /** * Add a particle having this as a anti-colour line. */ void addAntiColoured(tPPtr); /** * Add a particle having this as a (anti-)colour line. * @param p the particle to be connected. * @param anti if true, this is the anti-colour line of \a p. */ void addColoured(tPPtr p, bool anti = false); /** * Add a particle having this as a anti-colour line at a given index. */ void addAntiColouredIndexed(tPPtr p, int index); /** * Add a particle having this as a (anti-)colour line at a given index. * @param p the particle to be connected. * @param anti if true, this is the anti-colour line of \a p. */ void addColouredIndexed(tPPtr p, int index, bool anti=false); /** * Remove a particle having this as an anti-colour line. */ void removeAntiColoured(tPPtr); /** * Remove a particle having this as a (anti-)colour line. * @param p the particle to be removed. * @param anti if true, this is the anti-colour line of \a p. */ void removeColoured(tPPtr p, bool anti = false); //@} /** @name Functions for junction strings. */ //@{ /** * If this colour line ends in a colour sink, these two colour lines * ends in the same. */ tColinePair sinkNeighbours() const { return theSinkNeighbours; } /** * If this colour line stems from a colour source (sink), these two colour * lines stems from (ends in) the same. * @param anti if true return sinkNeighbours(). */ tColinePair sourceNeighbours(bool anti = false) const { return anti? theSinkNeighbours: theSourceNeighbours; } /** * Add two colour lines as neighbours to this line. Afterwards all * three will end in the same sink. Also the neighbors are set up * correspondingly. */ void setSinkNeighbours(tColinePtr l1, tColinePtr l2) { theSinkNeighbours.second = l1->theSinkNeighbours.second = l2; l2->theSinkNeighbours.second = theSinkNeighbours.first = l1; l1->theSinkNeighbours.first = l2->theSinkNeighbours.first = this; } /** * Add two colour lines as neighbours to this line. Afterwards all * three will stem from the same source. Also the neighbors are set * up correspondingly. */ void setSourceNeighbours(tColinePtr l1, tColinePtr l2) { theSourceNeighbours.second = l1->theSourceNeighbours.second = l2; l2->theSourceNeighbours.second = theSourceNeighbours.first = l1; l1->theSourceNeighbours.first = l2->theSourceNeighbours.first = this; } //@} /** * Join with the given ColourLine. The colour of the given \a line * is joined so that it will flow into this line, ie. the * anti-coloured particle in the end of the \a line will become * connected to the coloured particle in the of this line. After * the joining the given \a line will not be connected to * anything. */ bool join(ColinePtr line); /** * Return the first (anti-)coloured parton among the given range of * particles which is on this colour line. */ template typename std::iterator_traits::value_type getColouredParticle(Iterator first, Iterator last, bool anti = false) const { typedef typename std::iterator_traits::value_type ParticlePointer; for ( ; first != last; ++first ) if ( (**first).coloured() && (**first).hasColourLine(this, anti) ) return *first; return ParticlePointer(); } /** * Write out information about this colour line to the stream. */ void write(ostream & os, tcEventPtr event, bool anti) const; public: /** * Standard function for writing to a persistent stream. */ void persistentOutput(PersistentOStream &) const; /** * Standard function for reading from a persistent stream. */ void persistentInput(PersistentIStream &, int); private: /** * The particles connecting to this colour line, following the * incoming colour flow. */ tPVector theColoured; /** * The particles connecting to this colour line, following the * outgoing colour flow. */ tPVector theAntiColoured; /** * If this colour line stems from a colour source, these two colour * lines stems from the same. */ tColinePair theSourceNeighbours; /** * If this colour line ends in a colour sink, these two colour lines * ends in the same. */ tColinePair theSinkNeighbours; /** * Colour lines which are connectors between two junctions do not * have a particle which owns it, instead it is owned by one of the * source neighbours. */ vector orphanedConnectors; private: /** * Describe a concrete class with persistent data. */ static ClassDescription initColourLine; /** * Private and non-existent assignment operator. */ ColourLine & operator=(const ColourLine &) = delete; }; } namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** * The following template specialization informs ThePEG about the * base class of ColourLine. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of ColourLine. */ typedef EventRecordBase 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::ColourLine"; } /** Return the name of the shared library to be loaded to get * access to this class. */ static string library() { return "ColourLine.so"; } }; /** @endcond */ } #endif /* ThePEG_ColourLine_H */ diff --git a/EventRecord/ColourSinglet.cc b/EventRecord/ColourSinglet.cc --- a/EventRecord/ColourSinglet.cc +++ b/EventRecord/ColourSinglet.cc @@ -1,284 +1,284 @@ // -*- C++ -*- // // ColourSinglet.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the ColourSinglet class. // #include "ColourSinglet.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Utilities/UtilityBase.h" #include "ThePEG/Repository/UseRandom.h" using namespace ThePEG; LorentzMomentum ColourSinglet::momentum() const { return Utilities::sumMomentum(partons().begin(), partons().end()); } tcPDVector ColourSinglet::getTripletData() const { tcPDVector ret; for ( int i = 0, N = partons().size(); i < N; ++i ) if ( parton(i)->data().iColour() != PDT::Colour8 ) ret.push_back(parton(i)->dataPtr()); return ret; } vector ColourSinglet::getSinglets(tcParticleSet & left) { vector ret; while ( !left.empty() ) { tcPPtr p = *left.begin(); // First just remove colour singlets. if ( !p->coloured() || !p->hasColourInfo() ) { left.erase(left.begin()); continue; } // Find a connected coulour line. tcColinePtr cl = p->colourLine(); if ( !cl ) cl = p->antiColourLine(); // Get the Colour singlet corresponding to this line. ret.push_back(ColourSinglet(cl, left)); } return ret; } ColourSinglet::ColourSinglet(tcColinePtr cl, tcParticleSet & left) { // Follow colour line forward and add coloured partons to the first // string piece. addPiece(); if ( !fill(1, true, cl, left) ) // If needed also follow colourline backward and add // anti-coloured partons. fill(1, false, cl, left); for ( Index i = 1, N = nPieces(); i <= N; ++i ) partons().insert(partons().end(), piece(i).begin(), piece(i).end()); } bool ColourSinglet:: fill(Index s0, bool forward, tcColinePtr cl, tcParticleSet & left) { tcColinePtr first = cl; tcPPtr p; while ( (p = cl->getColouredParticle(left.begin(), left.end(), !forward)) ) { left.erase(p); if ( forward ) piece(s0).push_back(p); else piece(s0).push_front(p); if ( p->hasColourLine(first, forward) ) return true; if ( !( cl = p->colourLine(forward) ) ) return false; } // If we get here we have ended up in a colour source or sink. tColinePair fork = cl->sourceNeighbours(forward); if ( !fork.first || !fork.second ) throw ColourSingletException() << "Inconsistent Colour flow." << Exception::eventerror; Junction j = addJunction(s0, forward); fill(j.first, !forward, fork.first, left); fill(j.second, !forward, fork.second, left); return false; } ColourSinglet::Junction ColourSinglet::addJunction(Index s0, bool forward) { // Add two new string pieces. Index s1 = addPiece(); Index s2 = addPiece(); // Connect the new pieces with the original. junction(s0, forward).first = s1; junction(s0, forward).second = s2; junction(s1, forward).first = s0; junction(s1, forward).second = s2; junction(s2, forward).first = s0; junction(s2, forward).second = s1; // Return the indices of the new pieces. return junction(s0, forward); } ColourSinglet ColourSinglet::splitInternal(Index sp) { if ( !sp ) { // If no piece is specified, first find all internal string pieces. vector internals; for ( Index i = 1, N = nPieces(); i <= N; ++i ) if ( sink(i).first && sink(i).second && source(i).first && source(i).second ) internals.push_back(i); // If no internal lines are found, return empty singlet. if ( internals.empty() ) return ColourSinglet(); // Otherwise pick randomly between the internal lines. sp = UseRandom::irnd(internals.size()); } vector assign(piece(sp).size()); for ( int i = 0, N = piece(sp).size(); i < N; ++i ) assign[i] = UseRandom::rndbool(); return splitInternal(sp, source(sp).first, UseRandom::rndbool()? sink(sp).first: sink(sp).second, assign); } ColourSinglet ColourSinglet:: splitDiDiQuark(tcPPair qq1, tcPPair qq2, const vector & assign) { ColourSinglet ret; // Add teo new string pieces. Junction j = addJunction(1, true); sink(1) = sink(j.first) = sink(j.second) = source(1) = source(j.first) = source(j.second) = Junction(); // Add the second quarks to one piece each piece(j.first).push_back(qq2.first); piece(j.second).push_back(qq2.second); // Add intermediate colour octets to either of the new pieces. for ( unsigned i = piece(1).size() - 2; i > 0; --i ) ((i < assign.size()? assign[i]: UseRandom::rndbool() )? piece(j.first): piece(j.second)).push_back(piece(1)[i]); // Add the first quarks to one piece each piece(j.first).push_back(qq1.first); piece(j.second).push_back(qq1.second); // Create two new singlets and let this be one of them and return // the other. ColourSinglet csa(*this, j.first); ColourSinglet csb(*this, j.second); ret.swap(csa); swap(csb); return ret; } ColourSinglet ColourSinglet:: splitDiQuarkJunction(Index sp, tcPPtr diq, tcPPair qq, const vector & assign) { ColourSinglet ret; Junction j; if ( source(sp).first && source(sp).second ) { // This is a diquark, so we remove the source junction and add // string piece sp to the source neighbours according to assign // and end with one of the quarks. j = source(sp); source(j.first) = source(j.second) = Junction(); for ( unsigned i = 0, N = piece(sp).size(); i < N; ++i ) { if ( diq == piece(sp)[i] ) { piece(j.first).push_back(qq.first); piece(j.second).push_back(qq.second); } ((i < assign.size()? assign[i]: UseRandom::rndbool() )? piece(j.first): piece(j.second)).push_back(piece(sp)[i]); } } else if ( sink(sp).first && sink(sp).second ) { // This is a anti-diquark, so we remove the source junction and add // string piece sp to the source neighbours according to assign // and end with one of the anti quarks. j = sink(sp); sink(j.first) = sink(j.second) = Junction(); // 'i' can't be unsigned here. would get infinite loop! for ( int i = piece(sp).size() - 1; i >= 0; --i ) { if ( diq == piece(sp)[i] ) { piece(j.first).push_front(qq.first); piece(j.second).push_front(qq.second); } ((static_cast(i) < assign.size()? assign[i]: UseRandom::rndbool() )? piece(j.first): piece(j.second)).push_front(piece(sp)[i]); } } else return ret; // Create two new singlets and let this be one of them and return // the other. ColourSinglet csa(*this, j.first); ColourSinglet csb(*this, j.second); ret.swap(csa); swap(csb); return ret; } ColourSinglet ColourSinglet:: splitInternal(Index sp, Index sa, Index sc, const vector & assign) { ColourSinglet ret; // If the selected string piece was not internal, return nothing. if ( !sink(sp).first || !sink(sp).second || !source(sp).first || !source(sp).second ) return ret; // If the selected adjacent pieces are not connected, return // nothing. Index sb = 0; if ( sa == source(sp).first ) sb = source(sp).second; else if ( sa == source(sp).second ) sb = source(sp).first; else return ret; Index sd = 0; if ( sc == sink(sp).first ) sd = sink(sp).second; else if ( sc == sink(sp).second ) sd = sink(sp).first; else return ret; // Copy the partons from the split string piece randomly to the // pieces to be joined. for ( unsigned i = 0, N = piece(sp).size(); i < N; ++i ) { if ( (i < assign.size()? assign[i]: UseRandom::rndbool() ) ) piece(sa).push_back(piece(sp)[i]); else piece(sb).push_back(piece(sp)[i]); } // Join the to string pieces piece(sa).insert(piece(sa).end(), piece(sc).begin(), piece(sc).end()); piece(sb).insert(piece(sb).end(), piece(sd).begin(), piece(sd).end()); source(sa) = source(sc); source(sb) = source(sd); // Create new colour singlets ColourSinglet csa(*this, sa); ColourSinglet csb(*this, sb); ret.swap(csa); swap(csb); return ret; } ColourSinglet::ColourSinglet(const ColourSinglet & cs, Index si) { addPiece(); fill(1, true, cs, si); fill(1, false, cs, si); for ( Index i = 1, N = nPieces(); i <= N; ++i ) partons().insert(partons().end(), piece(i).begin(), piece(i).end()); } void ColourSinglet:: fill(Index i0, bool forward, const ColourSinglet & cs, Index i1) { // first copy the string piece from cs. piece(i0) = cs.piece(i1); // If the piece in cs had a (forward) junction, add copy also the // connected string pieces if ( cs.junction(i1, forward).first || cs.junction(i1, forward).second ) { Junction j = addJunction(i0, forward); fill(j.first, !forward, cs, cs.junction(i1, forward).first); fill(j.second, !forward, cs, cs.junction(i1, forward).second); } return; } diff --git a/EventRecord/ColourSinglet.h b/EventRecord/ColourSinglet.h --- a/EventRecord/ColourSinglet.h +++ b/EventRecord/ColourSinglet.h @@ -1,296 +1,296 @@ // -*- C++ -*- // // ColourSinglet.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_ColourSinglet_H #define ThePEG_ColourSinglet_H #include "ThePEG/EventRecord/EventConfig.h" namespace ThePEG { /** * A ColourSinglet object represents a set of * colour-connected partons in a total colour-singlet state. The * simplest form is a single string represented by a vector of partons * starting from a colour-triplet parton followed by a number of * colour-octet partons and ending in a anti-triplet. A closed string * is represented by a vector of colour-octet partons. If junctions * are present, there will be a vector of string pieces containing the * associated partons, with associated information about the string * pieces connected via sinks or sources. * * @see ColourLine * @see Particle * */ class ColourSinglet { public: /** A piece of string. */ typedef deque StringPiece; /** An integer type used as index in a string pieece. */ typedef StringPiece::size_type Index; /** Representaion of a junction. */ typedef pair Junction; public: /** * Default constructor. */ ColourSinglet() {} /** * Constructor taking an initial colour line and a set of partons to * select from. */ ColourSinglet(tcColinePtr cl, tcParticleSet & left); protected: /** * Internal constructor. When splitting an internal line, create a * new colour singlet starting from the string piece \a si in the * singlet \a cs. */ ColourSinglet(const ColourSinglet & cs, Index si); public: /** * Access the vector of partons. */ tcPVector & partons() { return thePartons; } /** * Access the vector of partons. */ const tcPVector & partons() const { return thePartons; } /** * Access a parton giving an index. */ tcPPtr parton(tcPVector::size_type i) const { return thePartons[i]; } /** * Return the total momentum for the partons in the colour singlet. */ LorentzMomentum momentum() const; /** * Return the number of string pieces. */ Index nPieces() const { return thePieces.size(); } /** * Return the partons belonging to string piece with index i (note * that the indices starts with 1). */ StringPiece & piece(Index i) { return thePieces[i - 1]; } /** * Return the partons belonging to string piece with index i (note * that the indices starts with 1). */ const StringPiece & piece(Index i) const { return thePieces[i - 1]; } /** * Return the sink (or source if \a forward is false) neighbors of * a string piece with index i (note that the indices starts with 1). */ Junction & junction(Index i, bool forward) { return forward ? sink(i) : source(i); } /** * Return the sink (or source if \a forward is false) neighbors of * a string piece with index i (note that the indices starts with 1). */ const Junction & junction(Index i, bool forward) const { return forward ? sink(i) : source(i); } /** * Return the sink or source neighbors of a string piece with index * i (note that the indices starts with 1). */ Junction & sink(Index i) { return theSinks[i - 1]; } /** * Return the sink or source neighbors of a string piece with index * i (note that the indices starts with 1). */ const Junction & sink(Index i) const { return theSinks[i - 1]; } /** * Return the sink or source neighbors of a string piece with index * i (note that the indices starts with 1). */ Junction & source(Index i) { return theSources[i - 1]; } /** * Return the sink or source neighbors of a string piece with index * i (note that the indices starts with 1). */ const Junction & source(Index i) const { return theSources[i - 1]; } /** * Extract colour-singlet strings/clusters of partons from the given * set. The set will be empty afterwards if all went well - even * colour-singlet particles will be removed. */ static vector getSinglets(tcParticleSet & left); /** * Extract colour-singlet strings/clusters of partons from the given * range of particles. */ template static vector getSinglets(Iterator first, Iterator last) { tcParticleSet pset(first, last); return getSinglets(pset); } /** * Return a vector with data objects corresponding to all triplet * partons in this singlet. */ tcPDVector getTripletData() const; /** * Split a junction string. Split an internal string piece \a sp * (one that starts from a source and ends in a sink). Randomly pair * together the connectin string pieces and randomly assign possible * colour octet partons to the two joined string pieces. The singlet * will then split into two - one is returned and this will contain * the other. If no argument is given, a random internal line will * be picked. */ ColourSinglet splitInternal(Index sp = 0); /** * Split a junction string. Split an internal string piece \a sp * (one that starts from a source and ends in a sink). The source * neighbour \a sa will be joined with the sink neighbour \a * sc. Possible colour octet partons in the split string piece will * be assigned to the joined \a sa-\a sc string piece if the * corresponing \a assign element is true. The singlet will then * split into two - one is returned and this will contain the other. */ ColourSinglet splitInternal(Index sp, Index sa, Index sc, const vector & assing); /** * Split a junction string. If a sting piece \a sp is connected to a * junction and ends in a diquark diq, split the diquark into two * quarks, remove the junction, adding the other partons to the * first neighbouring string piece if the corresponding \a assign * element is true. The singlet will then split into two - one is * returned and this will contain the other. Note that the * parent-children relationship and colour flows of the diquark and * the two quarks is not handled by this function. */ ColourSinglet splitDiQuarkJunction(Index sp, tcPPtr diq, tcPPair qq, const vector & assign = vector()); /** * Split a di-quark string. If this singlet is a simple string with * (anti-)diquarks in both ends, split the diquarks into the given * quark pairs and create two new string pieces the betwen the quark * and anit-quarks, adding the remaining partons to the first piece * if the corresponding \a assign element is true. The singlet will * then split into two - one is returned and this will contain the * other. Note that the parent-children relationship and colour * flows of the diquark and the two quarks is not handled by this * function. */ ColourSinglet splitDiDiQuark(tcPPair qq1, tcPPair qq2, const vector & assign = vector()); /** * Swap this colour singlet for the argument. */ void swap(ColourSinglet & x) { thePartons.swap(x.thePartons); thePieces.swap(x.thePieces); theSources.swap(x.theSources); theSinks.swap(x.theSinks); } private: /** * Fill a string piece. Follow a colour line \a forward in colour * removing partons from the \a left set and adding them to the * string piece \a s0 as we go along. If a line ends in a colour * sink/source, follow the other two colour lines in turn with the * value of \a forward reversed. */ bool fill(Index s0, bool forward, tcColinePtr first, tcParticleSet & left); /** * Fill a string piece. When creating a new singlet from an old one * which has been split, add the string piece \a i1. If it ends in a * sink or a source add the neighbors recursively. */ void fill(Index i0, bool forward, const ColourSinglet & cs, Index i1); /** * Add a new string piece and return its index. */ Index addPiece() { thePieces.push_back(StringPiece()); theSinks.push_back(Junction()); theSources.push_back(Junction()); return nPieces(); } /** * Add a junction which is a source (or sink if \a forward) to the * string piece \a s0. Return the indices of the two connected * string pieces. */ Junction addJunction(Index s0, bool forward); public: /** @cond EXCEPTIONCLASSES */ /** An exception class to indicate that something went wrong with a * ColourSinglet. */ class ColourSingletException: public Exception {}; /** @endcond */ private: /** * The vector of all partons. */ tcPVector thePartons; /** * The different string pieces. */ vector thePieces; /** * The source neighbours of the string pieces. */ vector theSources; /** * The sink neighbours of the string pieces. */ vector theSinks; }; } #endif /* ThePEG_ColourSinglet_H */ diff --git a/EventRecord/Event.cc b/EventRecord/Event.cc --- a/EventRecord/Event.cc +++ b/EventRecord/Event.cc @@ -1,361 +1,361 @@ // -*- C++ -*- // // Event.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined member functions of // the 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 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 ( 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 ( 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; os << "Weight: " << e.weight(); if ( ! e.optionalWeights().empty() ) { os << " [ "; for ( auto w : e.optionalWeights() ) os << w.first << ':' << w.second << ' '; os << " ]"; } 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/Event.h b/EventRecord/Event.h --- a/EventRecord/Event.h +++ b/EventRecord/Event.h @@ -1,474 +1,474 @@ // -*- C++ -*- // // Event.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_Event_H #define ThePEG_Event_H // This is the decalaration of the Event class. #include "Particle.h" #include "StandardSelectors.h" #include "SubProcess.h" #include "ThePEG/Utilities/Named.h" namespace ThePEG { /** * The Event class contains all Particles produced in the generation * of an event. The particles are divided into Collisions * corresponding to the actiual collisions between incoming particles * in a bunch crossing. * * Event inherits from the Named which holds the name of an event. * * @see Collision * @see Step * @see SubProcess * @see Particle * @see SelectorBase * @see Named * */ class Event : public EventRecordBase, public Named { public: /** * EventHandler is a friend of most Event classes. */ friend class EventHandler; /** Most of the Event classes are friends with each other. */ friend class Collision; /** Map colour lines to indices. */ typedef map ColourLineMap; public: /** * The standard constructor for an Event takes as arguments a pair * of colliding particles (corresponding to the primary collision in * case of multiple collisions in an event). Optionally a pointer to * the EventHandler which performed the generation, an event name * and event number can be given. * @param newIncoming a pair of incoming particles to the prinary Collision. * @param newHandler the handler object in charge of the generation * of this Event. * @param newName the name of this event. * @param newNumber the number of this event. * @param weight the weight of this event */ Event(const PPair & newIncoming, tcEventBasePtr newHandler = tcEventBasePtr(), string newName = "", long newNumber = -1, double weight = 1.0); /** * The copy constructor. */ Event(const Event&); /** * The destructor. */ ~Event(); /** * Returns a full clone of this Event. All collisions, * Particles etc. in this Event are cloned. */ EventPtr clone() const; public: /** * Return a pointer to the EventHandler which produced this * Event. May be the null pointer. */ tcEventBasePtr handler() const { return theHandler; } /** @name Functions for accessing particles etc. */ //@{ /** * Extract particles from this event which satisfies the * requirements given by an object of the SelectorBase class. * @param r an output iterator specifying where the extracted * (pointers to) particles will be appended. * @param s SelectorBase object defining which particles should be * extracted. */ template void select(OutputIterator r, const SelectorBase & s) const; /** * Extract all final state particles in this Event. * @param r an output iterator specifying where the extracted * (pointers to) particles will be appended. */ template void selectFinalState(OutputIterator r) const { select(r, SelectFinalState()); } /** * Extract all final state particles in this Event. * @param c a container where the extracted (pointers to) particles * will be appended. */ template void getFinalState(Container & c) const { selectFinalState(inserter(c)); } /** * Extract all final state particles in this Event. * @return a vector of pointers to the extracted particles. */ tPVector getFinalState() const { tPVector ret; selectFinalState(back_inserter(ret)); return ret; } /** * Return a pointer to the primary Collision in this Event. May * be the null pointer. */ tCollPtr primaryCollision() const { return collisions().empty() ? tCollPtr() : tCollPtr(collisions()[0]); } /** * Return a possibly empty list of collisions in this Event. */ const CollisionVector & collisions() const { return theCollisions; } /** * Return a pointer to the primary SubProcess in the prinmary * Collision in this Event. May be the null pointer. */ tSubProPtr primarySubProcess() const; /** * Return a reference to the pair of colliding particles in the * primary Collision of this Event. */ const PPair & incoming() const { return theIncoming; } //@} /** * Create a new Collision in this event and return a pointer to it. */ tCollPtr newCollision(); /** * Create a new Step in the current Collision, which is a copy of * the last Step (if any) and return a pointer to it. If no * collision exists, one will be added. */ tStepPtr newStep(); /** * Transform all particles in this Event. */ void transform(const LorentzRotation &); /** * Return the number assigned to this Event. The name is accessed * with the name() method of the Named base class. */ long number() const { return theNumber; } /** * Return the index of the given colour line. */ int colourLineIndex(tcColinePtr) const; /** @name Functions for removing entires from an Event. */ //@{ /** * Remove (recursively) the decay products from a given Particle and * add the particle to the list of final state particles. */ void removeDecay(tPPtr); /** * Remove the given Particle from the Collision. If this was the * last daughter of the mother Particle, the latter is added to the * list of final state particles. */ void removeParticle(tPPtr); /** * Remove all steps which have no new particles introduced in them. */ void cleanSteps(); //@} /** * Return the weight associated with this event. */ double weight() const { return theWeight; } /** * Return an optional named weight associated to this event. Returns * 0, if no weight identified by this name is present. */ double optionalWeight(const string& name) const; /** * Return the optional named weights associated to this event. */ const map& optionalWeights() const { return theOptionalWeights; } /** * Print this Event in Graphviz format on the standard output. */ void printGraphviz() const; /** * Set the weight associated with this event. */ void weight(double w) { theWeight = w; } /** * Set an optional named weight associated to this event. */ void optionalWeight(const string& name, double value); /** * Access the optional named weights associated to this event. */ map& optionalWeights() { return theOptionalWeights; } /** * Set event info. */ void setInfo(tcEventBasePtr newHandler, string newName, long newNumber, double weight); /** * Add a collision to this Event. */ void addCollision(tCollPtr c); /** * Set the primary collision in this Event. */ void primaryCollision(tCollPtr c); protected: /** * Add a range of particles to this Collision. */ template void addParticles(Iterator first, Iterator last) { while ( first != last ) addParticle(*first++); } /** * Add a particle to this Collision. */ void addParticle(tPPtr p); /** * Add a new SubProcess to this Event. For book keeping purposes * only. The sub-processes are accessed from the different * Collisions in this Event. */ void addSubProcess(tSubProPtr p) { if ( p ) allSubProcesses.insert(p); } /** * Remove a SubProcess from this Event. */ void removeSubProcess(tSubProPtr p) { allSubProcesses.erase(p); } /** * Add a new Step to this Collision. For book keeping purposes * only. The steps are accessed from the different Collisions in * this Event. */ void addStep(tStepPtr s) { if ( s ) allSteps.insert(s); } /** * Remove a given Particle entry. */ void removeEntry(tPPtr p); /** * Rebind to cloned objects. When an Event is cloned, a shallow * copy is done first, then all Particles etc, are * cloned, and finally this method is used to see to that the * pointers in the cloned Event points to the cloned * Particles etc. */ void rebind(const EventTranslationMap & trans); public: /** * Standard function for writing to a persistent stream. */ void persistentOutput(PersistentOStream &) const; /** * Standard functions for reading from a persistent stream. */ void persistentInput(PersistentIStream &, int); /** * Standard Init function. @see Base::Init(). */ static void Init(); private: /** * The pair of colliding particles. */ PPair theIncoming; /** * A vector of collisions in this Event. */ CollisionVector theCollisions; /** * A set of all particles in this Event. */ StepSet allSteps; /** * A set of all sub-processes in this Event. */ SubProcessSet allSubProcesses; /** * A set of all particles in this Event. */ ParticleSet allParticles; /** * A pointer to the EventHandler which performed the generation * of this Event. */ tcEventBasePtr theHandler; /** * Map of all registered colour lines to their index numbers. */ mutable ColourLineMap theColourLines; /** * The number assigned to this Event. */ long theNumber; /** * The weight associated with this event. */ double theWeight; /** * Optional named weights */ map theOptionalWeights; /** * Counter to keep track of particle numbering. */ long theParticleNumber; public: /** * Print out debugging information for this object on std::cerr. To * be called from within a debugger via the debug() function. */ virtual void debugme() const; private: /** * Describe concrete class with persistent data. */ static ClassDescription initEvent; /** * Private default constructor must only be used by the * PersistentIStream class via the ClassTraits class . */ Event() : theNumber(-1), theWeight(1.0), theParticleNumber(0) {} /** * The ClassTraits class must be a friend to be able to * use the private default constructor. */ friend struct ClassTraits; /** * The assignment operator is private and not implemented. */ Event & operator=(const Event&) = delete; }; /** Output a Event to a standard ostream. */ ostream & operator<<(ostream &, const Event &); /** Print event tree in Graphviz format, ready for plotting. */ void printGraphviz(ostream &, tcEventPtr); /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base class of Event. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of Collision. */ typedef EventRecordBase NthBase; }; /** This template specialization informs ThePEG about the name of * the Event class and how to create it. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "ThePEG::Event"; } /** Create a Event object. */ static TPtr create() { return TPtr::Create(Event()); } }; /** @endcond */ } #include "Collision.h" inline ThePEG::tSubProPtr ThePEG::Event::primarySubProcess() const { return collisions().empty() ? ThePEG::tSubProPtr() : ThePEG::tSubProPtr(primaryCollision()->primarySubProcess()); } namespace ThePEG { template void Event::select(OutputIterator r, const SelectorBase & s) const { if ( s.allCollisions() ) { for ( CollisionVector::const_iterator it = theCollisions.begin(); it != theCollisions.end(); ++it ) (**it).select(r, s); } else { primaryCollision()->select(r, s); } } } #endif /* ThePEG_Event_H */ diff --git a/EventRecord/EventConfig.cc b/EventRecord/EventConfig.cc --- a/EventRecord/EventConfig.cc +++ b/EventRecord/EventConfig.cc @@ -1,67 +1,67 @@ // -*- C++ -*- // // EventConfig.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the EventConfig class. // #include "EventConfig.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #ifdef ThePEG_TEMPLATES_IN_CC_FILE // #include "EventConfig.tcc" #endif using namespace ThePEG; tcEventBasePtr EventConfig::currentGenerator; void EventConfig::putHandler(PersistentOStream & os, tcEventBasePtr h) { if ( !currentGenerator ) os << "" << h; else { tcIPtr handler = dynamic_ptr_cast(h); if ( handler ) os << handler->fullName(); else os << ""; os << tcEventBasePtr(); } } void EventConfig::getHandler(PersistentIStream & is, tcEventBasePtr & h) { string pxh; is >> pxh >> h; if ( currentGenerator ) { tcEGPtr eg = dynamic_ptr_cast(currentGenerator); h = eg->getObject(pxh); } } void EventConfig::putParticleData(PersistentOStream & os, tcEventPDPtr pd) { if ( !currentGenerator ) os << 0 << pd; else os << pd->id() << tcEventPDPtr(); } void EventConfig::getParticleData(PersistentIStream & is, cEventPDPtr & pd) { long pid; is >> pid >> pd; if ( !pd && currentGenerator ) { tcEGPtr eg = dynamic_ptr_cast(currentGenerator); pd = eg->getParticleData(pid); } } string EventConfig::nameHandler(tcEventBasePtr h) { tcIPtr handler = dynamic_ptr_cast(h); if ( handler ) return handler->name(); return ""; } diff --git a/EventRecord/EventConfig.h b/EventRecord/EventConfig.h --- a/EventRecord/EventConfig.h +++ b/EventRecord/EventConfig.h @@ -1,133 +1,133 @@ // -*- C++ -*- // // EventConfig.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_EventConfig_H #define ThePEG_EventConfig_H /** \file EventConfig.h * This is the main config header file for the Event classes. Do not * make changes in this file. If these classes are used outside of * ThePEG you probably need to need to modify base classes persistency * scheme etc. If so, edit a copy of the file which can be included * instead of this file using the macro * ThePEG_ALTERNATIVE_EVENT_RECORD. */ #ifndef ThePEG_NOT_ThePEG #include "ThePEG/Config/ThePEG.h" #include "ThePEG/Utilities/Rebinder.fh" #include "ThePEG/Persistency/PersistentOStream.fh" #include "ThePEG/Persistency/PersistentIStream.fh" #ifndef ThePEG_ALTERNATIVE_EVENT_RECORD #include "ThePEG/Vectors/Lorentz5Vector.h" #include "ThePEG/Vectors/LorentzRotation.h" namespace ThePEG { /** EventRecordBase is the base class of all event record classes. It * must be typedefed to a class which allows for garbage * collection, since none of the event record classes are deleted * explicitly. */ typedef Base EventRecordBase; /** Alias for a reference counted pointer to EventRecordBase. */ typedef Ptr::pointer EventBasePtr; /** Alias for a reference counted pointer to const EventRecordBase. */ typedef Ptr::const_pointer cEventBasePtr; /** Alias for a transient pointer to EventRecordBase. */ typedef Ptr::transient_pointer tEventBasePtr; /** Alias for a transient pointer to const EventRecordBase. */ typedef Ptr::transient_const_pointer tcEventBasePtr; /** Alias for a rebinder object able to relate pointers to original * objects to pointers to their clones. */ typedef Rebinder EventTranslationMap; /** ParticleClass is the name used for Particle in the event record classes. */ typedef Particle ParticleClass; /** ParticleDataClass is the name used for ParticleData in the event * record classes. */ typedef ParticleData ParticleDataClass; /** Alias for a reference counted pointer to ParticleDataClass. */ typedef Ptr::pointer EventPDPtr; /** Alias for a reference counted pointer to const ParticleDataClass. */ typedef Ptr::const_pointer cEventPDPtr; /** Alias for a transient pointer to ParticleDataClass. */ typedef Ptr::transient_pointer tEventPDPtr; /** Alias for a transient pointer to const ParticleDataClass. */ typedef Ptr::transient_const_pointer tcEventPDPtr; /** A vector of transient pointers to Particle. */ typedef vector tParticleVector; /** A vector of pointers to Particle. */ typedef vector ParticleVector; /** A set of pointers to Particle. */ typedef set > ParticleSet; /** A set of transient pointers to Particle. */ typedef set > tParticleSet; /** A set of transient pointers to const Particle. */ typedef set > tcParticleSet; /** A vector of pointers to Step. */ typedef vector StepVector; /** A vector of pointers to SubProcess. */ typedef vector SubProcessVector; /** A vector of transient pointers to SubProcess. */ typedef vector tSubProcessVector; /** A vector of pointers to Collision. */ typedef vector CollisionVector; /** A set of pointers to Step. */ typedef set > StepSet; /** A set of pointers to SubProcess. */ typedef set > SubProcessSet; /** A helper class to facilitate persistent input and output. */ struct EventConfig { /** * Optional pointer to the current EventGenerator. * If \a currentGenerator is set during persistent output, only the * PDG number of a particle type is written rather than the full * ParticleData object. Also only the name of handlers is written * rather than the full objects. When this is read back in again, * the \a currentGenerator must be set so that conversion from * name/number back to objects can be done. */ static tcEventBasePtr currentGenerator; /** Write a handler object to a persistent stream. */ static void putHandler(PersistentOStream & os, tcEventBasePtr h); /** Read a handler object from a persistent stream. */ static void getHandler(PersistentIStream & is, tcEventBasePtr & h); /** Write a ParticleData object to a persistent stream. */ static void putParticleData(PersistentOStream & os, tcEventPDPtr pd); /** Read a ParticleData object from a persistent stream. */ static void getParticleData(PersistentIStream & is, cEventPDPtr & pd); /** Return the name of a handler object. */ static string nameHandler(tcEventBasePtr h); }; } #else #include ThePEG_ALTERNATIVE_EVENT_RECORD #endif #endif /* ThePEG_NOT_ThePEG */ #endif /* ThePEG_EventConfig_H */ diff --git a/EventRecord/EventInfoBase.cc b/EventRecord/EventInfoBase.cc --- a/EventRecord/EventInfoBase.cc +++ b/EventRecord/EventInfoBase.cc @@ -1,17 +1,17 @@ // -*- C++ -*- // // EventInfoBase.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the EventInfoBase class. // #include "EventInfoBase.h" using namespace ThePEG; NoPIOClassDescription EventInfoBase::initEventInfoBase; diff --git a/EventRecord/EventInfoBase.h b/EventRecord/EventInfoBase.h --- a/EventRecord/EventInfoBase.h +++ b/EventRecord/EventInfoBase.h @@ -1,70 +1,70 @@ // -*- C++ -*- // // EventInfoBase.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_EventInfoBase_H #define ThePEG_EventInfoBase_H // This is the declaration of the EventInfoBase class. #include "ThePEG/EventRecord/EventConfig.h" #include "ThePEG/Utilities/ClassDescription.h" namespace ThePEG { /** * EventInfoBase is a base class for information objects. It is used * as a base class for classes representing user-defined information * which may be associated with a Particle. The class itself is * practically empty. Information added in sub-classes can be accessed * from a Particle by the Particle::getInfo() function and the * resulting pointers need to be dynamically cast to check if they are * of a desired class. */ class EventInfoBase: public EventRecordBase { public: /** * Rebind to cloned objects. If an EventInfoBase is cloned together * with a whole Event and this has pointers to other event record * objects, these should be rebound to their clones in this * function. */ virtual void rebind(const EventTranslationMap & ) {} /** * Standard Init function. @see Base::Init(). */ static void Init() {} /** * Standard clone method. */ virtual EIPtr clone() const { return new_ptr(*this); } private: /** * Describe concrete class without persistent data. */ static NoPIOClassDescription initEventInfoBase; /** * Private and non-existent assignment operator. */ EventInfoBase & operator=(const EventInfoBase &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ ThePEG_DECLARE_CLASS_TRAITS(EventInfoBase,EventRecordBase); /** @endcond */ } #endif /* ThePEG_EventInfoBase_H */ diff --git a/EventRecord/HelicityVertex.cc b/EventRecord/HelicityVertex.cc --- a/EventRecord/HelicityVertex.cc +++ b/EventRecord/HelicityVertex.cc @@ -1,35 +1,35 @@ // -*- C++ -*- // // HelicityVertex.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the HelicityVertex class. // // Author: Peter Richardson // #include "SpinInfo.h" #include "HelicityVertex.h" using namespace ThePEG; AbstractNoPIOClassDescription HelicityVertex::initHelicityVertex; // Definition of the static class description member. void HelicityVertex::Init() {} void HelicityVertex::rebind(const EventTranslationMap & trans) { EventInfoBase::rebind(trans); for(unsigned int ix=0;ix<_incoming.size();++ix) { _incoming[ix]=trans.translate(_incoming[ix]); } for(unsigned int ix=0;ix<_outgoing.size();++ix) { _outgoing[ix]=trans.translate(_outgoing[ix]); } } diff --git a/EventRecord/HelicityVertex.h b/EventRecord/HelicityVertex.h --- a/EventRecord/HelicityVertex.h +++ b/EventRecord/HelicityVertex.h @@ -1,222 +1,222 @@ // -*- C++ -*- // // HelicityVertex.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_HelicityVertex_H #define ThePEG_HelicityVertex_H // This is the declaration of the HelicityVertex class. #include "HelicityVertex.fh" #include "ThePEG/EventRecord/EventConfig.h" #include "ThePEG/Utilities/ClassDescription.h" #include "RhoDMatrix.h" #include "ThePEG/Utilities/Rebinder.h" #include "ThePEG/Helicity/HelicityDefinitions.h" namespace ThePEG { /** * The HelicityVertex class is designed to store the helicity * amplitude expression for the matrix element for use by the spin * correlation algorithm. It implements the storage of the pointers * to the incoming and outgoing particles at the vertex and virtual * methods for calculating the rho and D matrices. The concrete * implementations of the vertices for specific processes, eg * production or decay, inherit from this and implement the storage * of the matrix element together with the set and get methods. * * These methods are then called by the SpinInfo class to perform the * calculations. * * * @see SpinInfo * * @author Peter Richardson * */ class HelicityVertex: public EventInfoBase { public: /** * Output the spin density matrix for debugging purposes. */ friend ostream & operator<<(ostream & os, const HelicityVertex & vert); public: /** A vector of SpinInfo objects. */ typedef vector SpinVector; public: /** * Standard Init function. */ static void Init(); /** * Rebind to cloned objects. If a HelicityVertex is cloned together * with a whole Event and this has pointers to other event record * objects, these should be rebound to their clones in this * function. */ virtual void rebind(const EventTranslationMap & trans); public: /** @name Access the incoming and outgoing particles. */ //@{ /** * Access the spin of the incoming particles. */ const SpinVector & incoming() const {return _incoming;} /** * Access the spin of the outgoing particles. */ const SpinVector & outgoing() const {return _outgoing;} /** * Add the spin of an incoming particle. * @param spin the spin of the particle. * @param loc is set to the position in the list of incoming spins. */ void addIncoming(tcSpinPtr spin, int & loc) { if(loc<0) { _incoming.push_back(spin); loc=_incoming.size()-1; } else { _incoming[loc] = spin; } } /** * Add the spin of an outgoing particle. * @param spin the spin of the particle. * @param loc is set to the position in the list of outgoing spins. */ void addOutgoing(tcSpinPtr spin, int & loc) { if(loc<0) { _outgoing.push_back(spin); loc=_outgoing.size()-1; } else { _outgoing[loc]= spin; } } /** * Reset the \a spin of the incoming particle at position \a loc. */ void resetIncoming(tcSpinPtr spin, int loc) { assert( loc < int(_incoming.size()) && loc >= 0 ); _incoming[loc]=spin; } /** * Reset the \a spin of the outgoing particle at position \a loc. */ void resetOutgoing(tcSpinPtr spin, int loc) { assert( loc < int(_outgoing.size()) && loc >= 0 ); _outgoing[loc]=spin; } //@} public: /** @name Mthods to calculate rho and D matrices. */ //@{ /** * Get the rho matrix for the outgoing particle at position \a loc. */ virtual RhoDMatrix getRhoMatrix(int loc,bool recursive) const = 0; /** * Get the D matrix for the incoming particle at position \a loc. */ virtual RhoDMatrix getDMatrix(int loc) const = 0; //@} private: /** * Describe an abstract base class without persistent data. */ static AbstractNoPIOClassDescription initHelicityVertex; /** * Private and non-existent assignment operator. */ HelicityVertex & operator=(const HelicityVertex &) = delete; private: /** * Pointers to the incoming particle spins at the vertex. */ SpinVector _incoming; /** * Pointers to the outgoing particle spins at the vertex. */ SpinVector _outgoing; }; /** * Output operator */ inline ostream & operator<<(ostream & os, const HelicityVertex & vert) { os << "the incoming particles at the vertex are" << endl; for(unsigned int ix=0;ix struct BaseClassTrait : public ClassTraitsType { /** Typedef of the base class of HelicityVertex. */ typedef EventInfoBase NthBase; }; /** * This template specialization informs ThePEG about the name of * the HelicityVertex class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** * Return the class name. */ static string className() { return "ThePEG::HelicityVertex"; } }; /** @endcond */ } #endif /* ThePEG_HelicityVertex_H */ diff --git a/EventRecord/MultiColour.cc b/EventRecord/MultiColour.cc --- a/EventRecord/MultiColour.cc +++ b/EventRecord/MultiColour.cc @@ -1,136 +1,136 @@ // -*- C++ -*- // // MultiColour.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MultiColour class. // #include "MultiColour.h" #include "ThePEG/Interface/ClassDocumentation.h" #include #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG; vector MultiColour::antiColourLines() const { return vector(theAntiColourLines.begin(), theAntiColourLines.end()); } vector MultiColour::colourLines() const { return vector(theColourLines.begin(), theColourLines.end()); } bool MultiColour::hasColourLine(tcColinePtr line, bool anti) const { return ( anti? ( find(theAntiColourLines.begin(),theAntiColourLines.end(),line) != theAntiColourLines.end() ): ( find(theColourLines.begin(),theColourLines.end(),line) != theColourLines.end() ) ); } void MultiColour::colourLine(tColinePtr line, bool anti) { if ( anti ) antiColourLine(line); else { if ( !colourLine() ) ColourBase::colourLine(line); if(find(theColourLines.begin(),theColourLines.end(),line)== theColourLines.end()) theColourLines.push_back(line); } } void MultiColour::colourLine(tColinePtr line, int index, bool anti) { if ( anti ) { antiColourLine(line,index); return; } if ( !colourLine() ) ColourBase::colourLine(line); if(find(theColourLines.begin(),theColourLines.end(),line)!=theColourLines.end()) return; int ix=0; for(list::iterator it=theColourLines.begin(); it!=theColourLines.end();++it) { ++ix; if(ix==index) { it = theColourLines.insert(it,line); ++it; removeColourLine(*it); if ( !colourLine() ) ColourBase::colourLine(line); return; } } for(;ix::iterator it=theAntiColourLines.begin(); it!=theAntiColourLines.end();++it) { ++ix; if(ix==index) { it = theAntiColourLines.insert(it,line); ++it; removeAntiColourLine(*it); if ( !antiColourLine() ) ColourBase::antiColourLine(line); return; } } for(;ix> theColourLines >> theAntiColourLines; } ClassDescription MultiColour::initMultiColour; // Definition of the static class description member. void MultiColour::Init() { static ClassDocumentation documentation ("There is no documentation for the MultiColour class"); } diff --git a/EventRecord/MultiColour.h b/EventRecord/MultiColour.h --- a/EventRecord/MultiColour.h +++ b/EventRecord/MultiColour.h @@ -1,183 +1,183 @@ // -*- C++ -*- // // MultiColour.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_MultiColour_H #define THEPEG_MultiColour_H // // This is the declaration of the MultiColour class. // #include "ThePEG/EventRecord/ColourBase.h" namespace ThePEG { /** * This class is used to store colour information of RemnantParticle * objects and other particle classes with complicated colour * structures. Rather than just having a */ class MultiColour: public ColourBase { public: using ColourBase::colourLine; using ColourBase::antiColourLine; /** * Return the anti-colour lines to which this particle is * connected. */ virtual vector antiColourLines() const; /** * Return the colour lines to which this particle is * connected. */ virtual vector colourLines() const; /** * Add the given (\a anti-) colour \a line to the particle. If the base * class has no (anti-) colour line, it will also be set. */ virtual void colourLine(tColinePtr line, bool anti = false); /** * Add the given (\a anti-) colour \a line to the particle. If the base * class has no (anti-) colour line, it will also be set. */ virtual void colourLine(tColinePtr line, int index, bool anti = false); /** * Add the given anti-colour \a line to the particle. If the base * class has no anti-colour line, it will also be set. */ virtual void antiColourLine(tColinePtr line); /** * Add the given anti-colour \a line to the particle. If the base * class has no anti-colour line, it will also be set. */ virtual void antiColourLine(tColinePtr line, int index); /** * Remove the given (\a anti-) colour \a line from the particle. If * the line is the colourLine() of the base class, it will be * removed there as well. */ virtual void removeColourLine(tcColinePtr line, bool anti = false); /** * Remove the given anti-colour \a line from the particle. If the * line is the antiColourLine() of the base class, it will be * removed there as well. */ virtual void removeAntiColourLine(tcColinePtr line); /** * Return true if the particle is connected to the given (\a anti-) * colour \a line. */ virtual bool hasColourLine(tcColinePtr line, bool anti = false) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); /** * Standard clone method. */ virtual EIPtr clone() const { return new_ptr(*this); } private: /** * The set of colour lines to which a particle is attached. */ list theColourLines; /** * The set of anti-colour lines to which a particle is attached. */ list theAntiColourLines; private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initMultiColour; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MultiColour & operator=(const MultiColour &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of MultiColour. */ template <> struct BaseClassTrait { /** Typedef of the first base class of MultiColour. */ typedef ColourBase NthBase; }; /** This template specialization informs ThePEG about the name of * the MultiColour 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::MultiColour"; } /** * The name of a file containing the dynamic library where the class * MultiColour is implemented. It may also include several, space-separated, * libraries if the class MultiColour depends on other classes (base classes * excepted). In this case the listed libraries will be dynamically * linked in the order they are specified. */ static string library() { return "MultiColour.so"; } }; /** @endcond */ } #endif /* THEPEG_MultiColour_H */ diff --git a/EventRecord/Particle.cc b/EventRecord/Particle.cc --- a/EventRecord/Particle.cc +++ b/EventRecord/Particle.cc @@ -1,525 +1,525 @@ // -*- C++ -*- // // Particle.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined member functions of // the Particle class. // #include "Particle.h" #include "ThePEG/EventRecord/Step.h" #include "ThePEG/EventRecord/Event.h" #include "ThePEG/EventRecord/ColourLine.h" #include "ThePEG/Utilities/Rebinder.h" #include "ThePEG/Config/algorithm.h" #include "ThePEG/EventRecord/ParticleTraits.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/DecayMode.h" #include #include #include #ifdef ThePEG_TEMPLATES_IN_CC_FILE #include "Particle.tcc" #endif using namespace ThePEG; Particle::ParticleRep::ParticleRep(const ParticleRep & p) : theParents(p.theParents), theChildren(p.theChildren), thePrevious(p.thePrevious), theNext(p.theNext), theBirthStep(p.theBirthStep), theVertex(p.theVertex), theLifeLength(p.theLifeLength), theScale(p.theScale), theVetoScale(p.theVetoScale), theNumber(p.theNumber), theExtraInfo(p.theExtraInfo.size()) { if ( p.theColourInfo ) theColourInfo = dynamic_ptr_cast(p.theColourInfo->clone()); if ( p.theSpinInfo ) theSpinInfo = dynamic_ptr_cast(p.theSpinInfo->clone()); for ( int i = 0, N = p.theExtraInfo.size(); i < N; ++i ) theExtraInfo[i] = p.theExtraInfo[i]->clone(); } Particle::Particle(const Particle & p) : Base(p), theData(p.theData), theMomentum(p.theMomentum), theRep(p.theRep), theStatus(p.theStatus) { if ( p.theRep ) { theRep = new ParticleRep(*p.theRep); theRep->theParents.clear(); } } Particle::~Particle() { if ( theRep ) { if ( colourLine() ) colourLine()->removeColoured(this); if ( antiColourLine() ) antiColourLine()->removeAntiColoured(this); delete theRep; } theRep = 0; theData = cEventPDPtr(); } void Particle::initFull() { if ( theRep ) return; theRep = new ParticleRep; Energy width = data().generateWidth(mass()); if ( width > ZERO ) { Time lifetime = data().generateLifeTime(mass(), width); theRep->theLifeLength.setTau(lifetime); theRep->theLifeLength. setVect((momentum().vect()*(lifetime / max(mass(), Constants::epsilon*GeV)))); theRep->theLifeLength.rescaleEnergy(); } } PPtr Particle::clone() const { return ptr_new(*this); } void Particle::rebind(const EventTranslationMap & trans) { for ( ParticleVector::iterator pit = rep().theChildren.begin(); pit != rep().theChildren.end(); ++pit ) *pit = trans.translate(*pit); for ( tParticleVector::iterator pit = rep().theParents.begin(); pit != rep().theParents.end(); ++pit ) *pit = trans.translate(*pit); rep().thePrevious = trans.translate(rep().thePrevious); rep().theNext = trans.translate(rep().theNext); if ( hasColourInfo() ) colourInfo()->rebind(trans); if ( spinInfo() ) spinInfo()->rebind(trans); rep().theBirthStep = trans.translate(rep().theBirthStep); for ( EIVector::const_iterator ie = rep().theExtraInfo.begin(); ie != rep().theExtraInfo.end(); ++ie ) (**ie).rebind(trans); } tParticleSet Particle::siblings() const { tParticleSet theSiblings; for ( tParticleVector::const_iterator pit = parents().begin(); pit != parents().end(); ++pit ) theSiblings.insert((*pit)->children().begin(), (*pit)->children().end()); theSiblings.erase(const_cast(this)); return theSiblings; } void Particle::colourNeighbour(tPPtr p, bool anti) { tColinePtr line = colourLine(!anti); if ( !line ) line = ColourLine::create(this, !anti); line->addColoured(p, anti); } void Particle::outgoingColour(tPPtr p, bool anti) { tColinePtr line = colourLine(anti); if ( !line ) line = ColourLine::create(this, anti); line->addColoured(p, anti); } tPPtr Particle::incomingColour(bool anti) const { if ( !hasColourInfo() ) return tPPtr(); tColinePtr line = colourLine(anti); if ( !line ) return tPPtr(); for ( int i = 0, N = parents().size(); i < N; ++i ) if ( parents()[i]->hasColourLine(line, anti) ) return parents()[i]; return tPPtr(); } tPPtr Particle::outgoingColour(bool anti) const { if ( !hasColourInfo() ) return tPPtr(); tColinePtr line = colourLine(anti); if ( !line ) return tPPtr(); for ( int i = 0, N = children().size(); i < N; ++i ) if ( children()[i]->hasColourLine(line, anti) ) return children()[i]; return tPPtr(); } LorentzPoint Particle::labVertex() const { LorentzPoint r(rep().theBirthStep && rep().theBirthStep->collision()? vertex() + rep().theBirthStep->collision()->vertex(): vertex()); return r; } void Particle::setLabVertex(const LorentzPoint & p) { rep().theVertex = ( rep().theBirthStep && rep().theBirthStep->collision()? p - rep().theBirthStep->collision()->vertex() : p ); } void Particle::transform(const LorentzRotation & r) { if ( hasRep() && spinInfo() ) spinInfo()->transform(momentum(), r); theMomentum.transform(r); if ( !hasRep() ) return; rep().theVertex.transform(r); rep().theLifeLength.transform(r); } void Particle::deepTransform(const LorentzRotation & r) { transform(r); if ( !theRep ) return; for ( int i = 0, N = children().size(); i < N; ++i ) rep().theChildren[i]->deepTransform(r); if ( rep().theNext ) rep().theNext->deepTransform(r); } void Particle::rotateX(double a) { LorentzRotation r; r.rotateX(a); transform(r); } void Particle::deepRotateX(double a) { LorentzRotation r; r.rotateX(a); deepTransform(r); } void Particle::rotateY(double a) { LorentzRotation r; r.rotateY(a); transform(r); } void Particle::deepRotateY(double a) { LorentzRotation r; r.rotateY(a); deepTransform(r); } void Particle::rotateZ(double a) { LorentzRotation r; r.rotateZ(a); transform(r); } void Particle::deepRotateZ(double a) { LorentzRotation r; r.rotateZ(a); deepTransform(r); } void Particle::rotate(double a, const Axis & axis) { LorentzRotation r; r.rotate(a, axis); transform(r); } void Particle::deepRotate(double a, const Axis & axis) { LorentzRotation r; r.rotate(a, axis); deepTransform(r); } string Particle::outputFormat = "%n3%s10 %i7 %p[,]0 %c(,) %^^0%vv0 %>>0%<>0 %l{,}0\n" " %x10.3%y10.3%z10.3%e10.3%m10.3\n"; int getNumber(string::const_iterator & pos, int def) { if ( !isdigit(*pos) ) return def; def = *pos++ - '0'; while ( isdigit(*pos) ) def = 10*def + *pos++ - '0'; return def; } void writePrecision(ostream & os, string::const_iterator & pos, int defw, int defp, double x) { defw = getNumber(pos, defw); if ( *pos == '.' ) defp = getNumber(++pos, defp); int oldp = os.precision(); os << setprecision(defp) << setw(defw) << x << setprecision(oldp); } void writeStringAdjusted(ostream & os, bool left, int w, string str) { while ( !left && w-- > int(str.size()) ) os << ' '; os << str; while ( left && w-- > int(str.size()) ) os << ' '; } template void writeParticleRanges(ostream & os, const Container & co, char sep, int w) { set cnum; for ( typename Container::const_iterator it = co.begin(); it != co.end(); ++it) cnum.insert((**it).number()); bool elipsis = false; int last = -10; for ( set::iterator it = cnum.begin(); it != cnum.end(); ++it) { int n = *it; int next = 0; set::iterator itn = it; if ( ++itn != cnum.end() ) next = *itn; bool writeit = true; bool writesep = false; if ( elipsis && ( n != last + 1 || n != next - 1 ) ) elipsis = false; else if ( !elipsis && n == last + 1 && n == next -1 ) { os << ".."; elipsis = true; writeit = false; } else if ( elipsis && n == last + 1 && n == next -1 ) writeit = false; else if ( it != cnum.begin() ) writesep = true; if ( writeit ) { if ( writesep ) os << sep; os << setw(w) << n; } last = n; } } ostream & ThePEG::operator<<(ostream & os, const Particle & p) { return p.print(os, p.birthStep()); } ostream & Particle::print(ostream & os, tcStepPtr step) const { if ( !step ) step = birthStep(); tCollPtr coll = step? step->collision(): tCollPtr(); tEventPtr event = coll? coll->event(): tEventPtr(); string::const_iterator pos = Particle::outputFormat.begin(); ios::fmtflags saveflags = os.setf(ios::fixed, ios::floatfield); while ( pos != Particle::outputFormat.end() ) { if ( *pos == '%' && ++pos != Particle::outputFormat.end() ) { bool left = false; if ( *pos == '-' ) { left = true; os.setf(ios::left, ios::adjustfield); ++pos; } else { os.setf(ios::right, ios::adjustfield); } char mark; char open; char close; char sep; int w; string str; string fill; if ( pos == Particle::outputFormat.end() ) break; bool fullColour = false; switch ( *pos ) { case 'n': os << setw(getNumber(++pos, 3)) << number(); break; case 'i': os << setw(getNumber(++pos, 8)) << id(); break; case 's': writeStringAdjusted(os, left, getNumber(++pos, 8), PDGName()); break; case 'x': writePrecision(os, ++pos, 10, 3, momentum().x()/GeV); break; case 'y': writePrecision(os, ++pos, 10, 3, momentum().y()/GeV); break; case 'z': writePrecision(os, ++pos, 10, 3, momentum().z()/GeV); break; case 'e': writePrecision(os, ++pos, 10, 3, momentum().e()/GeV); break; case 'm': writePrecision(os, ++pos, 10, 3, momentum().mass()/GeV); break; case 'P': fullColour = true; [[fallthrough]]; case 'p': open = *++pos; sep = *++pos; close = *++pos; w = getNumber(++pos, 0); if ( parents().empty() ) break; if ( open ) os << open; writeParticleRanges(os, parents(), sep, w); if ( fullColour && hasColourInfo() && ( incomingColour() || incomingAntiColour() ) ) { if ( close ) os << open; if ( incomingColour() ) os << "+" << incomingColour()->number(); if ( incomingAntiColour() ) os << "-" << incomingAntiColour()->number(); if ( close ) os << close; } if ( close ) os << close; break; case 'l': open = *++pos; sep = *++pos; close = *++pos; w = getNumber(++pos, 0); if ( hasColourInfo() && ( colourLine() || antiColourLine() ) && event) { if ( open ) os << open; vector clines = colourInfo()->colourLines(); for ( int i = 0, N = clines.size(); i < N; ++i ) { if ( i > 0 && sep ) os << sep; clines[i]->write(os, event, false); } vector aclines = colourInfo()->antiColourLines(); for ( int i = 0, N = aclines.size(); i < N; ++i ) { if ( ( i > 0 || clines.size() ) && sep ) os << sep; aclines[i]->write(os, event, true); } if ( close ) os << close; } break; case 'C': fullColour = true; [[fallthrough]]; case 'c': open = *++pos; sep = *++pos; close = *++pos; w = getNumber(++pos, 0); if ( children().empty() ) break; if ( open ) os << open; writeParticleRanges(os, children(), sep, w); if ( fullColour && hasColourInfo() && ( outgoingColour() || outgoingAntiColour() ) ) { if ( close ) os << open; if ( outgoingColour() ) os << "+" << outgoingColour()->number(); if ( outgoingAntiColour() ) os << "-" << outgoingAntiColour()->number(); if ( close ) os << close; } if ( close ) os << close; break; case '>': mark = *++pos; w = getNumber(++pos, 0); if ( hasColourInfo() && step && step->colourNeighbour(this) ) { os << setw(w-1) << step->colourNeighbour(this)->number() << mark; } break; case '<': mark = *++pos; w = getNumber(++pos, 0); if ( hasColourInfo() && step && step->antiColourNeighbour(this) ) { int n = step->antiColourNeighbour(this)->number(); ostringstream oss; oss << mark << n; writeStringAdjusted(os, left, w, oss.str()); } break; case 'v': mark = *++pos; w = getNumber(++pos, 0); if ( next() ) { if ( left && mark ) os << mark; os << setw(w) << next()->number(); if ( !left && mark ) os << mark; } break; case '^': mark = *++pos; w = getNumber(++pos, 0); if ( previous() ) { if ( left && mark ) os << mark; os << setw(w) << previous()->number(); if ( !left && mark ) os << mark; } break; case 'd': switch ( *++pos ) { case 'x': writePrecision(os, ++pos, 10, 3, lifeLength().x()/mm); break; case 'y': writePrecision(os, ++pos, 10, 3, lifeLength().y()/mm); break; case 'z': writePrecision(os, ++pos, 10, 3, lifeLength().z()/mm); break; case 't': writePrecision(os, ++pos, 10, 3, lifeLength().e()/mm); break; case 'T': writePrecision(os, ++pos, 10, 3, lifeLength().tau()/mm); break; } break; case 'V': switch ( *++pos ) { case 'x': writePrecision(os, ++pos, 10, 3, vertex().x()/mm); break; case 'y': writePrecision(os, ++pos, 10, 3, vertex().y()/mm); break; case 'z': writePrecision(os, ++pos, 10, 3, vertex().z()/mm); break; case 't': writePrecision(os, ++pos, 10, 3, vertex().e()/mm); break; } break; case 'L': switch ( *++pos ) { case 'x': writePrecision(os, ++pos, 10, 3, labVertex().x()/mm); break; case 'y': writePrecision(os, ++pos, 10, 3, labVertex().y()/mm); break; case 'z': writePrecision(os, ++pos, 10, 3, labVertex().z()/mm); break; case 't': writePrecision(os, ++pos, 10, 3, labVertex().e()/mm); break; } break; default: os << *pos++; } } else { if ( pos != Particle::outputFormat.end() ) os << *pos++; } } os.flags(saveflags); return os; } void Particle::debugme() const { cerr << *this; EventRecordBase::debugme(); } void Particle::persistentOutput(PersistentOStream & os) const { EventConfig::putParticleData(os, theData); os << ounit(theMomentum, GeV) << theStatus << bool( theRep != 0 ); if ( !theRep ) return; os << rep().theParents << rep().theChildren << rep().thePrevious << rep().theNext << rep().theBirthStep << ounit(rep().theVertex, mm) << ounit(rep().theLifeLength, mm) << ounit(rep().theScale, GeV2) << ounit(rep().theVetoScale, GeV2) << rep().theNumber << rep().theDecayMode << rep().theColourInfo << rep().theSpinInfo << rep().theExtraInfo; } void Particle::persistentInput(PersistentIStream & is, int) { bool readRep; EventConfig::getParticleData(is, theData); is >> iunit(theMomentum, GeV) >> theStatus >> readRep; if ( !readRep ) return; if ( !hasRep() ) theRep = new ParticleRep; is >> rep().theParents >> rep().theChildren >> rep().thePrevious >> rep().theNext >> rep().theBirthStep >> iunit(rep().theVertex, mm) >> iunit(rep().theLifeLength, mm) >> iunit(rep().theScale, GeV2) >> iunit(rep().theVetoScale, GeV2) >> rep().theNumber >> rep().theDecayMode >> rep().theColourInfo >> rep().theSpinInfo >> rep().theExtraInfo; } ClassDescription Particle::initParticle; void Particle::Init() {} diff --git a/EventRecord/Particle.h b/EventRecord/Particle.h --- a/EventRecord/Particle.h +++ b/EventRecord/Particle.h @@ -1,1195 +1,1195 @@ // -*- C++ -*- // // Particle.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_Particle_H #define ThePEG_Particle_H // This is the decalaration of the Particle class. #include "EventConfig.h" #include "ThePEG/Vectors/Lorentz5Vector.h" #include "ThePEG/Vectors/LorentzRotation.h" #include "ThePEG/Utilities/ClassDescription.h" #include "ThePEG/EventRecord/MultiColour.h" #include "ThePEG/EventRecord/SpinInfo.h" #include "ThePEG/PDT/ParticleData.h" namespace ThePEG { /** * The Particle class is used to describe an instance of a * particle. Properties of the corresponding particle type can be * accessed through a pointer to a ParticleData object. * * A Particle object contains pointers to other particles, such as a * list of parents and a list of children. It may also contain a * pointer to the previous or next instance of the same physical * particle if the properties of a given particle has been changed * during the generation. Coloured particles contains pointers to * ColourLine defining the colour connections to other particles. * * The Particle also has a pointer to the Step object where it was * first introduced in the Event. * * When printing a particle the format of the output is governed by * the static outputFormat string. When a particle is sent * to an ostream, the format string is written but with * keys prefixed by the \% character replaced with * infromation about the particle as follows:
\%\% is * replaced by a singel \%
\%C sets a flag so * that subsequent output of children and parents etc. will contain * colour information.
\%n is replaced by the particles * number in a fied ow width
\%s is replaced by the name * of the particle
\%i is replaced by the id number of * the particle type
\%x, \%y, \%z, \%e, \%m is replaced by * the x-, y-, z-, energy- and mass-component of the particles * momentum respectively
\%dx, \%dy, \%dz, \%dt, \%dT is * replaced by the x-, y-, z-, time- and invariant time-component of * the particles lifeLength respectively
\%Vx, \%Vy, \%Vz, * \%Vt is replaced by the x-, y-, z- and time-component of the * creation point relative to the vertex of the * collision.
\%Lx, \%Ly, \%Lz, \%Lt is replaced by the x-, * y-, z- and time-component of the creation point in the current * lab-system.
\%p[,] is replaced by a list (of numbers) * of the particles parents enclosed by [ and ] * and separated by ,, The parent from which the particle * inherits its (anti-) colour is marked by a (-)+
* \%c(,) is replaced by a list (of numbers) of the * particles children enclosed by ( and ) and * separated by ,, The child which inherits the particles * (anti-) colour is marked by a (-)+
\%> is replaced * by the number of the colour neighbor
\%< is * replaced by the number of the anti-colour neighbor
* \%^ is replaced by the number of the previous instance of * the same physical particle
\%v is replaced by the * number of the next instance of the same physical particle.
* \%l{,} is replaced by the indices of the colour lines to * which this particle is connected enclosed by { and * } and separated by ,, The line corresponding * to the (anti-) colour of the particle is prefixed by a (-)+ * * @see Event * @see Collision * @see Step * @see SubProcess * @see Lorentz5Vector * @see ColourLine * @see ColourBase */ class Particle: public EventRecordBase { public: /** Most of the Event classes are friends with each other. */ friend class Event; /** Most of the Event classes are friends with each other. */ friend class Collision; /** Most of the Event classes are friends with each other. */ friend class Step; /** Most of the Event classes are friends with each other. */ friend class SubProcess; /** ParticleData needs to be a friend. */ friend class ParticleData; struct ParticleRep; public: /** * Standard Constructor. Note that the default constructor is * private - there is no particle without a pointer to a * ParticleData object. */ Particle(tcEventPDPtr newData) : theData(newData), theRep(0), theStatus(0) {} /** * Copy constructor. */ Particle(const Particle &); /** * Destructor. */ virtual ~Particle(); //@} /** @name Functions relating to ancestry of particles. */ //@{ /** * Returns true if and only if this particle has decayed. */ bool decayed() const { return hasRep() && !rep().theChildren.empty(); } /** * The list of decay products. */ const ParticleVector & children() const { static const ParticleVector null; return hasRep() ? rep().theChildren : null; } /** * Add a child (the childs parent pointer will be set accordingly). */ void addChild(tPPtr c) { rep().theChildren.push_back(c); (c->rep()).theParents.push_back(this); } /** * Remove the given child from the list of children of this particle * (the corresponding parent pointer of the child will also be * removed). */ void abandonChild(tPPtr child) { removeChild(child); child->removeParent(this); } /** * The list of parent particles. */ const tParticleVector & parents() const { static const tParticleVector null; return hasRep() ? rep().theParents : null; } /** * Return a set of neighboring particles coming from the same decay * as this one. The return value is a newly recalculated set * every time. It must be stored to be used further, do not directly call * e.g. siblings().begin() or siblings().end()! */ tParticleSet siblings() const; /** * Undo the decay of this particle, removing all children (and * grand children ...) from the event record */ void undecay() { if ( hasRep() ) { rep().theChildren.clear(); rep().theNext = tPPtr(); } } /** * If this particle has decayed set the corresponding decay mode. */ void decayMode(tDMPtr dm) { rep().theDecayMode = dm; } /** * If this particle has decayed get the corresponding decay mode. */ tDMPtr decayMode() const { return hasRep() ? rep().theDecayMode : tDMPtr(); } /** * Next instance. Pointer to another instance of the same * physical particle in later steps. */ tPPtr next() const { return hasRep() ? rep().theNext : PPtr(); } /** * Previous instance. Pointer to another instance of the same * physical particle in earlier steps. */ tPPtr previous() const { return hasRep() ? rep().thePrevious : tPPtr(); } /** * Original instance. If there exists another previous instance of * this particle return this instance (recursively). */ tcPPtr original() const { return previous() ? tcPPtr(previous()->original()) : tcPPtr(this); } /** * Original instance. If there exists another previous instance of * this particle return this instance (recursively). */ tPPtr original() { return previous() ? previous()->original() : tPPtr(this); } /** * Final instance. If there exists another subsequent instance of * this particle return this instance (recursively). */ tcPPtr final() const { return next() ? tcPPtr(next()->final()) : tcPPtr(this); } /** * Final instance. If there exists another subsequent instance of * this particle return this instance (recursively). */ tPPtr final() { return next() ? next()->final() : tPPtr(this); } //@} /** @name Relations to the Event and Step. */ //@{ /** * Get the first Step object where this particle occurred. */ tStepPtr birthStep() const { return hasRep() ? rep().theBirthStep : tStepPtr(); } /** * Get the order-number for this particle in the current event. */ int number() const { return hasRep() ? rep().theNumber : 0; } /** * Get the status code of the particle */ int status() const { return theStatus; } /** * Set the status code of the particle */ void status(int n) { theStatus = n; } //@} /** @name Access the underlying ParticleData object. */ //@{ /** * Access the ParticleData object of this particle type */ const ParticleDataClass & data() const { return *theData; } /** * Access the ParticleData object of this particle type */ tcEventPDPtr dataPtr() const { return theData; } /** * Return the PDG name of this particle. */ const string & PDGName() const { return data().PDGName(); } /** * Return the PDG id number of this particle. */ long id() const { return data().id(); } //@} /** @name Functions to access the momentum. */ //@{ /** * Return the momentum of this particle. */ const Lorentz5Momentum & momentum() const { return theMomentum; } /** * Set the 3-momentum of this particle. The energy is set to be * consistent with the mass. */ void set3Momentum(const Momentum3 & p) { theMomentum.setVect(p); theMomentum.rescaleEnergy(); } /** * Set the momentum of this particle. Afterwards, the underlying * Lorentz5Momentum may have inconsistent mass. */ void setMomentum(const LorentzMomentum & p) { theMomentum = p; } /** * Set the momentum and mass. */ void set5Momentum(const Lorentz5Momentum & p) { theMomentum = p; } /** * Acces the mass of this particle. */ Energy mass() const { return momentum().mass(); } /** * Acces the mass of this particle type. */ Energy nominalMass() const { return data().mass(); } /** * Get the scale at which this particle is considered resolved. */ Energy2 scale() const { return hasRep() ? rep().theScale : -1.0*GeV2; } /** * Set the scale at which this particle is considered resolved. */ void scale(Energy2 q2) { rep().theScale = q2; } /** * Get the scale above which this particle should * not radiate. */ Energy2 vetoScale() const { return hasRep() ? rep().theVetoScale : -1.0*GeV2; } /** * Set the scale above which this particle should * not radiate. */ void vetoScale(Energy2 q2) { rep().theVetoScale = q2; } /** * Return the transverse mass (squared), calculated from the energy * and the longitudinal momentum. */ Energy2 mt2() const { return sqr(momentum().t()) - sqr(momentum().z()); } /** * Return the transverse mass (squared), calculated from the energy * and the longitudinal momentum. */ Energy mt() const { return sqrt(mt2()); } /** * Return the transverse mass (squared), calculated from the mass * and the transverse momentum. */ Energy2 perpmass2() const { return momentum().perp2() + momentum().mass2(); } /** * Return the transverse mass (squared), calculated from the mass * and the transverse momentum. */ Energy perpmass() const { return sqrt(perpmass2()); } /** * Return the (pseudo) rapidity. */ double rapidity() const { return ( Pplus() > ZERO && Pminus() > ZERO )? 0.5*log(Pplus()/Pminus()) : Constants::MaxFloat; } /** * Return the (pseudo) rapidity. */ double eta() const { Energy rho = momentum().rho(); return rho > abs(momentum().z())? 0.5*log((rho+momentum().z())/(rho-momentum().z())) : Constants::MaxFloat; } /** * Return the positive and negative light-cone momenta. */ Energy Pplus() const { return momentum().plus(); } /** * Return the positive and negative light-cone momenta. */ Energy Pminus() const { return momentum().minus(); } //@} /** @name Functions to access the position. */ //@{ /** * The creation vertex of this particle. The point is given * relative to the collision vertex. */ const LorentzPoint & vertex() const { static const LorentzPoint null; return hasRep() ? rep().theVertex : null; } /** * The creation vertex of this particle. The absolute * position in the lab is given. */ LorentzPoint labVertex() const; /** * The decay vertex of this particle. The point is given * relative to the collision vertex. */ LorentzPoint decayVertex() const { return vertex() + lifeLength(); } /** * The decay vertex of this particle. The absolute * position in the lab is given. */ LorentzPoint labDecayVertex() const { return labVertex() + lifeLength(); } /** * The life time/length. Return the Lorentz vector connecting the * creation to the decay vertes. */ const Lorentz5Distance & lifeLength() const { static const Lorentz5Distance null; return hasRep() ? rep().theLifeLength : null; } /** * Set the creation vertex relative to the collision vertex. */ void setVertex(const LorentzPoint & p) { rep().theVertex = p; } /** * Set the creation vertex in the lab frame of this particle. */ void setLabVertex(const LorentzPoint &); /** * Set the life length of this particle. The life time will be * automatically rescaled to be consistent with the invariant * distance. */ void setLifeLength(const Distance & d) { rep().theLifeLength.setVect(d); rep().theLifeLength.rescaleEnergy(); } /** * Set the life time/length of a particle. The invariant distance * may become inconsistent. */ void setLifeLength(const LorentzDistance & d) { rep().theLifeLength = d; } /** * Set the life time/length of a particle. */ void setLifeLength(const Lorentz5Distance & d) { rep().theLifeLength = d; } /** * The invariant life time of this particle. */ Time lifeTime() const { return lifeLength().m(); } //@} /** @name Functions for (Lorentz) transformations. */ //@{ /** * Do Lorentz transformations on this particle. */ void transform(const LorentzRotation & r); /** * Do Lorentz transformations on this particle. \a bx, \a by and \a * bz are the boost vector components. */ void boost(double bx, double by, double bz) { transform(LorentzRotation(Boost(bx, by, bz))); } /** * Do Lorentz transformations on this particle. \a b is the boost * vector. */ void boost(const Boost & b) { transform(LorentzRotation(b)); } /** * Rotate around the x-axis. */ void rotateX(double a); /** * Rotate around the y-axis. */ void rotateY(double a); /** * Rotate around the z-axis. */ void rotateZ(double a); /** * Rotate around the given \a axis. */ void rotate(double a, const Axis & axis); /** * Mirror in the xy-plane. */ void mirror() { theMomentum.setZ(-theMomentum.z()); } /** * Do Lorentz transformations on this particle and its decendants. */ void deepTransform(const LorentzRotation & r); /** * Do Lorentz transformations on this particle and its * decendants. \a bx, \a by and \a bz are the boost vector * components. */ void deepBoost(double bx, double by, double bz) { deepTransform(LorentzRotation(Boost(bx, by, bz))); } /** * Do Lorentz transformations on this particle and its * decendants. \a b is the boost vector. */ void deepBoost(const Boost & b) { deepTransform(LorentzRotation(b)); } /** * Rotate this particle and its decendants around the x-axis. */ void deepRotateX(double a); /** * Rotate this particle and its decendants around the y-axis. */ void deepRotateY(double a); /** * Rotate this particle and its decendants around the z-axis. */ void deepRotateZ(double a); /** * Rotate this particle and its decendants around the given \a axis. */ void deepRotate(double a, const Axis & axis); //@} /** @name Functions controlling possible mass/momentum inconsistencies. */ //@{ /** * Return the relative inconsistency in the mass component. */ double massError() const { return theMomentum.massError(); } /** * Return the relative inconsistency in the energy component. */ double energyError() const { return theMomentum.energyError(); } /** * Return the relative inconsistency in the spatial components. */ double rhoError() const { return theMomentum.rhoError(); } /** * Rescale energy, so that the invariant length/mass of the * LorentzVector agrees with the current one. */ void rescaleEnergy() { theMomentum.rescaleEnergy(); } /** * Rescale spatial component, so that the invariant length/mass of * the LorentzVector agrees with the current one. */ void rescaleRho() { theMomentum.rescaleRho(); } /** * Set the invariant length/mass member, so that it agrees with the * invariant length/mass of the LorentzVector. */ void rescaleMass() { theMomentum.rescaleMass(); } //@} /** @name Acces incormation about colour connections */ //@{ /** * True if this particle has colour information. To determine if * this particle is actually coloured, the coloured(), hasColour() or * hasAntiColour() methods should be used instead. */ bool hasColourInfo() const { return hasRep() && rep().theColourInfo; } /** * Return the colour lines to which this particles anti-colour is * connected. */ tColinePtr antiColourLine() const { return hasColourInfo() ? colourInfo()->antiColourLine() : tColinePtr(); } /** * Return the colour lines to which this particles (\a anti-)colour * is connected. */ tColinePtr colourLine(bool anti = false) const { if ( anti ) return antiColourLine(); return hasColourInfo() ? colourInfo()->colourLine() : tColinePtr(); } /** * Return true if the particle is connected to the given (\a anti-) * colour \a line. */ bool hasColourLine(tcColinePtr line, bool anti = false) const { return hasColourInfo() ? colourInfo()->hasColourLine(line, anti) : false; } /** * Return true if the particle is connected to the given anti-colour * \a line. */ bool hasAntiColourLine(tcColinePtr line) const { return hasColourLine(line, true); } /** * True if this particle type is not a colour singlet. */ bool coloured() const { return data().coloured(); } /** * True if this particle type carries (\a anti-)colour. */ bool hasColour(bool anti = false) const { return data().hasColour(anti); } /** * True if this particle type carries anti-colour. */ bool hasAntiColour() const { return data().hasAntiColour(); } /** * Get the ColourBase object. */ tcCBPtr colourInfo() const { return hasRep() ? rep().theColourInfo : CBPtr(); } /** * Get the ColourBase object. */ tCBPtr colourInfo() { if ( !rep().theColourInfo ) { switch(theData->iColour()) { case PDT::Colour6: case PDT::Colour6bar: rep().theColourInfo = new_ptr(MultiColour()); break; default: rep().theColourInfo = new_ptr(ColourBase()); } } return rep().theColourInfo; } /** * Set the ColourBase object. */ void colourInfo(tCBPtr c) { rep().theColourInfo = c; } /** * Get a pointer to the colour neighbor. Returns a particle in the * range \a first to \a last which colour is connected to the same * line as this particles anti-colour. If \a anti is true return * antiColourNeighbour(). */ template typename std::iterator_traits::value_type colourNeighbour(Iterator first, Iterator last, bool anti = false) const; /** * Get a pointer to the anti-colour neighbor. Returns a particle in * the range \a first to \a last which anti-colour is * connected to the same line as this particles colour. */ template typename std::iterator_traits::value_type antiColourNeighbour(Iterator first, Iterator last) const { return colourNeighbour(first, last, true); } /** * Set the colour neighbor. Connects the given particles colour to * the same colour line as this particles anti-colour. If \a anti is * true call antiColourNeighbour(tPPtr). */ void colourNeighbour(tPPtr, bool anti = false); /** * Set the anti-colour neighbor. Connects the given particles * anti-colour to the same colour line as this particles colour. */ void antiColourNeighbour(tPPtr p) { colourNeighbour(p, true); } /** * Connect colour. Create a colour line connecting to it this * particles colour and the given particles anti-colour. */ void antiColourConnect(tPPtr neighbour) { colourConnect(neighbour, true); } /** * Connect colour. Create a colour line connecting to it this * particles anti-colour and the given particles colour. If \a anti * is true call antiColourConnect(tPPtr). */ void colourConnect(tPPtr neighbour, bool anti = false) { colourNeighbour(neighbour, anti); } /** * Incoming colour. Return the parent particle which colour is * connected to the same colour line as this particle. If \a anti is * true return incomingAntiColour(). */ tPPtr incomingColour(bool anti = false) const; /** * Incoming anti-colour. Return the parent particle which * anti-colour is connected to the same colour line as this * particle. */ tPPtr incomingAntiColour() const { return incomingColour(true); } /** * Set incoming colour. Connect this particles colour to the same * colour line as the given particle. If \a anti * is true call incomingAntiColour(tPPtr). */ void incomingColour(tPPtr p, bool anti = false) { p->outgoingColour(this, anti); } /** * Set incoming anti-colour. Connect this particles anti colour to * the same colour line as the given particle. */ void incomingAntiColour(tPPtr p) { p->outgoingColour(this, true); } /** * Outgoing colour. Return the daughter particle which colour is * connected to the same colour line as this particle. If \a anti is * true return outgoingAntiColour(). */ tPPtr outgoingColour(bool anti = false) const; /** * Outgoing anti-colour. Return the daughter particle which * anti-colour is connected to the same colour line as this * particle. */ tPPtr outgoingAntiColour() const { return outgoingColour(true); } /** * Set outgoing colour. Connect this particles colour to the same * colour line as the given particle. If \a anti * is true call outgoingAntiColour(tPPtr). */ void outgoingColour(tPPtr, bool anti = false); /** * Set outgoing anti-colour. Connect this particles anti-colour to * the same colour line as the given particle. */ void outgoingAntiColour(tPPtr p) { outgoingColour(p, true); } /** * Specify colour flow. Calls outgoingColour(tPPtr,bool). */ void colourFlow(tPPtr child, bool anti = false) { outgoingColour(child, anti); } /** * Specify anticolour flow. Calls outgoingAntiColour(tPPtr,bool). */ void antiColourFlow(tPPtr child) { colourFlow(child, true); } /** * Remove all colour information; */ void resetColour() { if ( hasColourInfo() ) rep().theColourInfo = CBPtr(); } //@} /** @name Functions to access spin. */ //@{ /** * Return the Spin object. */ tcSpinPtr spinInfo() const { return hasRep() ? rep().theSpinInfo : SpinPtr(); } /** * Return the Spin object. */ tSpinPtr spinInfo() { return hasRep() ? rep().theSpinInfo : SpinPtr(); } /** * Set the Spin object. */ void spinInfo(tSpinPtr s) { rep().theSpinInfo = s; } //@} /** @name Accessing user-defined information. */ //@{ /** * Access user-defined information as a vector of EventInfoBase pointers. */ const EIVector & getInfo() const { static const EIVector null; return hasRep() ? rep().theExtraInfo : null; } /** * Access user-defined information as a vector of EventInfoBase pointers. */ EIVector & getInfo() { return rep().theExtraInfo; } //@} public: /** @name Accessing user-defined information. */ //@{ /** * True if this particle has instantiated the object with * information other than type and momentum. */ bool hasRep() const { return theRep; } /** * If this particle has only a type and momentum, instantiate the * rest of the information. */ void initFull(); //@} public: /** @name Input and output functions. */ //@{ /** * Standard function for writing to a persistent stream. */ void persistentOutput(PersistentOStream &) const; /** * Standard function for reading from a persistent stream. */ void persistentInput(PersistentIStream &, int); //@} /** * Print particle info to a stream \a os. The \a step is used to * access information about colour neighbors and other struff. */ ostream & print(ostream & os, tcStepPtr step = tcStepPtr()) const; /** * Print a range of particles. */ template static void PrintParticles(ostream & os, Iterator first, Iterator last, tcStepPtr step = tcStepPtr()); /** * Print a container of particles. */ template static inline void PrintParticles(ostream & os, const Cont & c, tcStepPtr step = tcStepPtr()) { PrintParticles(os, c.begin(), c.end(), step); } /** * Standard Init function. @see Base::Init(). */ static void Init(); /** * Specify how to print particles. The format string is analogous to * the one used by eg. the unix 'date' command as described above. */ static string outputFormat; private: /** * Standard clone function. */ virtual PPtr clone() const; /** * Rebind to cloned objects. When an Event is cloned, a shallow * copy is done first, then all Particles etc, are * cloned, and finally this method is used to see to that the * pointers in the cloned Particle points to the cloned objects. */ virtual void rebind(const EventTranslationMap &); /** * Set the order-number for this particle in the current event. */ void number(int n) { rep().theNumber = n; } /** * Remove the given particle from the list of children. */ void removeChild(tPPtr c) { if ( hasRep() ) rep().theChildren.erase(remove(rep().theChildren.begin(), rep().theChildren.end(), c), rep().theChildren.end()); } /** * Remove the given particle from the list of parents. */ void removeParent(tPPtr p) { if ( hasRep() ) rep().theParents.erase(remove(rep().theParents.begin(), rep().theParents.end(), p), rep().theParents.end()); } /** * Set the mass of this particle. */ void mass(Energy m) { theMomentum.setMass(m); } /** * Set the invaiant life time of this particle. */ void lifeTime(Length t) { rep().theLifeLength.setTau(t); } /** * Return a reference to the bulk information of this particle. if * no ParticleRep object exists, one is created. */ ParticleRep & rep() { if ( !hasRep() ) initFull(); return *theRep; } /** * Return a reference to the bulk information of this particle. if * no ParticleRep object exists, we return the default values. */ const ParticleRep & rep() const { static const ParticleRep null; return hasRep() ? *theRep : null; } /** * The pointer to the ParticleData object */ cEventPDPtr theData; /** * The momentum. */ Lorentz5Momentum theMomentum; /** * The rest of the information in this particle is only instantiated * if needed. */ ParticleRep * theRep; /** * The status code of the particle */ int theStatus; public: /** * This class is used internally in the Particle class to represent * information besides momentum and type. A corresponding object * will only be instantiated if needed to save memory and time when * temporarily creating particles. */ struct ParticleRep { /** * Default constructor. */ ParticleRep() : theScale(-1.0*GeV2), theVetoScale(-1.0*GeV2), theNumber(0) {} /** * Copy constructor. */ ParticleRep(const ParticleRep &); /** * The pointers to the parents. */ tParticleVector theParents; /** * The pointers to the children. */ ParticleVector theChildren; /** * The pointer to the previous instance. */ tPPtr thePrevious; /** * The pointer to the next instance. */ PPtr theNext; /** * If this particle has decayed this is the pointer to the * corresponding decay mode. */ tDMPtr theDecayMode; /** * The pointer to the first step where this particle occurred. */ tStepPtr theBirthStep; /** * The creation point. */ LorentzPoint theVertex; /** * The life time/length. */ Lorentz5Distance theLifeLength; /** * the resolution scale. */ Energy2 theScale; /** * the veto scale. */ Energy2 theVetoScale; /** * The order-number for this particle in the current event. */ int theNumber; /** * A pointer to the colour information object. */ CBPtr theColourInfo; /** * Spin information */ SpinPtr theSpinInfo; /** * Additional used-defined information. */ EIVector theExtraInfo; }; public: /** * Print out debugging information for this object on std::cerr. To * be called from within a debugger via the debug() function. */ virtual void debugme() const; protected: /** * Private default constructor must only be used by the * PersistentIStream class via the ClassTraits class. */ Particle() : theRep(0), theStatus(0) {} /** * The ClassTraits class must be a friend to be able to * use the private default constructor. */ friend struct ClassTraits; private: /** * Private and non-existent assignment. */ Particle & operator=(const Particle &) = delete; /** * Describe concrete class with persistent data. */ static ClassDescription initParticle; }; /** * Write a Particle object to a stream. */ ostream & operator<<(ostream &, const Particle &); /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base class of Particle. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of Collision. */ typedef EventRecordBase NthBase; }; /** This template specialization informs ThePEG about the name of * the Particle class and how to create it. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "ThePEG::Particle"; } /** Create a Particle object. */ static TPtr create() { return TPtr::Create(Particle()); } }; /** @endcond */ } #ifndef ThePEG_TEMPLATES_IN_CC_FILE #include "Particle.tcc" #endif #endif /* ThePEG_Particle_H */ diff --git a/EventRecord/Particle.tcc b/EventRecord/Particle.tcc --- a/EventRecord/Particle.tcc +++ b/EventRecord/Particle.tcc @@ -1,43 +1,43 @@ // -*- C++ -*- // // Particle.tcc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the templated member functions of // the Particle class. // namespace ThePEG { struct ParticleNumLess { bool operator() (tPPtr p1, tPPtr p2) const { return p1->number() < p2->number(); } }; template void Particle:: PrintParticles(ostream & os, Iterator first, Iterator last, tcStepPtr step) { typedef multiset NumSet; NumSet pset(first, last); for ( NumSet::iterator i = pset.begin(); i != pset.end(); ++i ) (**i).print(os, step); } template typename std::iterator_traits::value_type Particle:: colourNeighbour(Iterator first, Iterator last, bool anti) const { if ( !hasColourInfo() || !hasColour(!anti) ) return tPPtr(); tColinePtr line = colourLine(!anti); for ( ; first != last; ++first ) if ( (**first).hasColourInfo() && (**first).hasColourLine(line, anti) ) return *first; return tPPtr(); } } diff --git a/EventRecord/ParticleTraits.h b/EventRecord/ParticleTraits.h --- a/EventRecord/ParticleTraits.h +++ b/EventRecord/ParticleTraits.h @@ -1,480 +1,480 @@ // -*- C++ -*- // // ParticleTraits.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_ParticleTraits_H #define ThePEG_ParticleTraits_H // This is the declaration of the ParticleTraits class. #include "ThePEG/Config/ThePEG.h" // #include "ParticleTraits.fh" // #include "ParticleTraits.xh" namespace ThePEG { template /** * ParticleTraits is a templated class defining a general interface to * any particle class. To make another particle type * PType available to some general ThePEG routines, the * ParticleTraits should be specialized to that class implementing * relevant methods of the general ParticleTraits class * below. Typically one needs specialisation both for the class itself * and of pointers to the class. * * @see Particle * @see Lorentz5Vector * */ struct ParticleTraits: public TraitsType { /** * Return a reference to the particle. */ static PType & ref(PType & p) { return p; } /** * Return the momentum of particle \a p. */ static LorentzMomentum momentum(const PType & p) { return p.momentum(); } /** * Return the mass of particle \a p. */ static Energy mass(const PType & p) { return p.mass(); } /** * Perform a Lorentz transformation on particle \a p. */ static void transform(PType & p, const LorentzRotation & r) { p.transform(r); } /** * Set the momentum and mass of a particle. */ static void set5Momentum(PType & p, const Lorentz5Momentum & q) { p.set5Momentum(q); } /** * Set the 3-momentum of a particle. The energy is rescaled to * preserve invariant mass. */ static void set3Momentum(PType & p, const Momentum3 & q) { p.set3Momentum(q); } /** * Return charge of particle \a p in units of e/3. */ static int iCharge(const PType & p) { return p.data().iCharge(); } }; /** @cond TRAITSPECIALIZATIONS */ /** Specialization of ParticleTraits for pointer to Particle. */ template <> struct ParticleTraits: public TraitsType { /** * Return a reference to the particle. */ static Particle & ref(tPPtr p) { return *p; } /** * Return the momentum of particle \a p. */ static const LorentzMomentum & momentum(tPPtr p) { return p->momentum(); } /** * Return the mass of particle \a p. */ static Energy mass(tPPtr p) { return p->mass(); } /** * Perform a Lorentz transformation on particle \a p. */ static void transform(tPPtr p, const LorentzRotation & r) { p->transform(r); } /** * Set the momentum and mass of a particle. */ static void set5Momentum(tPPtr p, const Lorentz5Momentum & q) { p->set5Momentum(q); } /** * Set the 3-momentum of a particle. The energy is rescaled to * preserve invariant mass. */ static void set3Momentum(tPPtr p, const Momentum3 & q) { p->set3Momentum(q); } /** * Return charge of particle \a p in units of e/3. */ static int iCharge(tPPtr p) { return p->data().iCharge(); } }; /** Specialization of ParticleTraits for pointer to const Particle. */ template <> struct ParticleTraits: public TraitsType { /** * Return a const reference to the particle. */ static const Particle & ref(tcPPtr p) { return *p; } /** * Return the momentum of particle \a p. */ static const LorentzMomentum & momentum(tcPPtr & p) { return p->momentum(); } /** * Return the mass of particle \a p. */ static Energy mass(tcPPtr p) { return p->mass(); } /** * Return charge of particle \a p in units of e/3. */ static int iCharge(tcPPtr & p) { return p->data().iCharge(); } }; /** Specialization of ParticleTraits for transient pointer to Particle. */ template <> struct ParticleTraits: public TraitsType { /** * Return a reference to the particle. */ static Particle & ref(tPPtr p) { return *p; } /** * Return the momentum of particle \a p. */ static const LorentzMomentum & momentum(tPPtr p) { return p->momentum(); } /** * Return the mass of particle \a p. */ static Energy mass(tPPtr p) { return p->mass(); } /** * Perform a Lorentz transformation on particle \a p. */ static void transform(tPPtr p, const LorentzRotation & r) { p->transform(r); } /** * Set the momentum and mass of a particle. */ static void set5Momentum(tPPtr p, const Lorentz5Momentum & q) { p->set5Momentum(q); } /** * Set the 3-momentum of a particle. The energy is rescaled to * preserve invariant mass. */ static void set3Momentum(tPPtr p, const Momentum3 & q) { p->set3Momentum(q); } /** * Return charge of particle \a p in units of e/3. */ static int iCharge(tPPtr p) { return p->data().iCharge(); } }; /** Specialization of ParticleTraits for transient pointer to const Particle. */ template <> struct ParticleTraits: public TraitsType { /** * Return a const reference to the particle. */ static const Particle & ref(tcPPtr p) { return *p; } /** * Return the momentum of particle \a p. */ static const LorentzMomentum & momentum(tcPPtr p) { return p->momentum(); } /** * Return the mass of particle \a p. */ static Energy mass(tcPPtr p) { return p->mass(); } /** * Return charge of particle \a p in units of e/3. */ static int iCharge(tcPPtr p) { return p->data().iCharge(); } }; /** Partial specialization of ParticleTraits for bare pointer to anything. */ template struct ParticleTraits: public TraitsType { /** * Return a reference to the particle. */ static Particle & ref(T * p) { return *p; } /** * Return the momentum of particle \a p. */ static const LorentzMomentum & momentum(T * p) { return ParticleTraits::momentum(*p); } /** * Return the mass of particle \a p. */ static Energy mass(T * p) { return ParticleTraits::mass(*p); } /** * Perform a Lorentz transformation on particle \a p. */ static void transform(T * p, const LorentzRotation & r) { ParticleTraits::transform(*p, r); } /** * Set the momentum and mass of a particle. */ static void set5Momentum(T * p, const Lorentz5Momentum & q) { ParticleTraits::set5Momentum(*p, q); } /** * Set the 3-momentum of a particle. The energy is rescaled to * preserve invariant mass. */ static void set3Momentum(T * p, const Momentum3 & q) { ParticleTraits::set3Momentum(*p, q); } /** * Return charge of particle \a p in units of e/3. */ static int iCharge(T * p) { return ParticleTraits::iCharge(*p); } }; /** Partial specialization of ParticleTraits for bare pointer to const anything. */ template struct ParticleTraits: public TraitsType { /** * Return a const reference to the particle. */ static const Particle & ref(const T * p) { return *p; } /** * Return the momentum of particle \a p. */ static const LorentzMomentum & momentum(const T * p) { return ParticleTraits::momentum(*p); } /** * Return the mass of particle \a p. */ static Energy mass(const T * p) { return ParticleTraits::mass(*p); } /** * Return charge of particle \a p in units of e/3. */ static int iCharge(const T * p) { return ParticleTraits::iCharge(*p); } }; /** Specialization of ParticleTraits for LorentzMomentum. In this way * a LorentzMomentum can be used where only the momentum parts of a * Particle is required. */ template <> struct ParticleTraits: public TraitsType { /** * Return a reference to the LorentzMomentum. */ static LorentzMomentum & ref(LorentzMomentum & p) { return p; } /** * Return the momentum. */ static const LorentzMomentum & momentum(const LorentzMomentum & p) { return p; } /** * Return the mass. */ static Energy mass(const LorentzMomentum & p) { return p.m(); } /** * Perform a Lorentz transformation. */ static void transform(LorentzMomentum & p, const LorentzRotation & r) { p.transform(r); } /** * Set the momentum and mass. */ static void set5Momentum(LorentzMomentum & p, const Lorentz5Momentum & q) { p = q; } /** * Set the 3-momentum. The energy is rescaled to * preserve invariant mass. */ static void set3Momentum(LorentzMomentum & p, const Momentum3 & q) { p = LorentzMomentum(q, sqrt(q.mag2() + p.m2())); } }; /** Specialization of ParticleTraits for Lorentz5Momentum. In this way * a Lorentz5Momentum can be used where only the momentum parts of a * Particle is required. */ template <> struct ParticleTraits: public TraitsType { /** * Return a reference to the Lorentz5Momentum. */ static Lorentz5Momentum & ref(Lorentz5Momentum & p) { return p; } /** * Return the momentum. */ static const LorentzMomentum & momentum(const Lorentz5Momentum & p) { return p; } /** * Return the mass. */ static Energy mass(const Lorentz5Momentum & p) { return p.mass(); } /** * Perform a Lorentz transformation. */ static void transform(Lorentz5Momentum & p, const LorentzRotation & r) { p.transform(r); } /** * Set the momentum and mass. */ static void set5Momentum(Lorentz5Momentum & p, const Lorentz5Momentum & q) { p = q; } /** * Set the 3-momentum. The energy is rescaled to * preserve invariant mass. */ static void set3Momentum(Lorentz5Momentum & p, const Momentum3 & q) { p = Lorentz5Momentum(p.mass(), q); } }; /** @endcond */ /** A helper class to be used in std:: algorithms to * transform a range of particles. */ struct Transformer { /** Constructor taking a reference to the Lorentz rotation to be * performed. */ Transformer(const LorentzRotation & rin) : r(rin) {} /** Copy constructor. */ Transformer(const Transformer & t) : r(t.r) {} /** Perform the rotation on a given particle. */ template void operator()(const PType & p) { ParticleTraits::transform(p, r); } /** A reference to the Lorentz rotation to be performed. */ const LorentzRotation & r; }; } // #include "ParticleTraits.icc" #ifndef ThePEG_TEMPLATES_IN_CC_FILE // #include "ParticleTraits.tcc" #endif #endif /* ThePEG_ParticleTraits_H */ diff --git a/EventRecord/RemnantParticle.cc b/EventRecord/RemnantParticle.cc --- a/EventRecord/RemnantParticle.cc +++ b/EventRecord/RemnantParticle.cc @@ -1,100 +1,100 @@ // -*- C++ -*- // // RemnantParticle.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the RemnantParticle class. // #include "RemnantParticle.h" #include "ThePEG/PDT/RemnantData.h" #include "ThePEG/PDT/RemnantDecayer.h" #include "ThePEG/EventRecord/MultiColour.h" #include "ThePEG/Config/algorithm.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG; RemnantParticle:: RemnantParticle(const Particle & particle, RemDecPtr decayer, tPPtr parton) : Particle(new_ptr(RemnantData(particle.dataPtr(), decayer))) { remData = const_ptr_cast(dynamic_ptr_cast(dataPtr())); set5Momentum(particle.momentum()); colourInfo(new_ptr(MultiColour())); parent = &particle; if ( parton ) extract(parton); } bool RemnantParticle::extract(tPPtr parton, bool fixcolour) { LorentzMomentum pnew = momentum() - parton->momentum(); if ( !remData->decayer().checkExtract(parent, parton, pnew) ) return false; if ( !remData->extract(parton->dataPtr()) ) return false; theExtracted.push_back(parton); setMomentum(pnew); rescaleMass(); if ( fixcolour ) fixColourLines(parton); return true; } bool RemnantParticle::reextract(tPPtr oldp, tPPtr newp, bool fixcolour) { LorentzMomentum pnew = momentum() + oldp->momentum() - newp->momentum(); if ( !remData->decayer().checkExtract(parent, newp, pnew) ) return false; PVector::iterator it = find(theExtracted, oldp); if ( it == theExtracted.end() ) return false; if ( !remData->reextract(oldp->dataPtr(), newp->dataPtr()) ) return false; theExtracted[it - theExtracted.begin()] = newp; setMomentum(pnew); rescaleMass(); if ( oldp->colourLine() ) oldp->colourLine()->removeAntiColoured(this); if ( oldp->antiColourLine() ) oldp->antiColourLine()->removeColoured(this); if ( fixcolour ) fixColourLines(newp); return true; } bool RemnantParticle::remove(tPPtr oldp) { LorentzMomentum pnew = momentum() + oldp->momentum(); PVector::iterator it = find(theExtracted, oldp); if ( it == theExtracted.end() ) return false; if ( !remData->remove(oldp->dataPtr()) ) return false; theExtracted.erase(it); setMomentum(pnew); rescaleMass(); if ( oldp->colourLine() ) oldp->colourLine()->removeAntiColoured(this); if ( oldp->antiColourLine() ) oldp->antiColourLine()->removeColoured(this); return true; } void RemnantParticle::fixColourLines(tPPtr parton) { if ( parton->hasColour() ) { if ( parton->colourLine() ) parton->colourLine()->addAntiColoured(this); else ColourLine::create(parton, tPPtr(this)); } if ( parton->hasAntiColour() ) { if ( parton->antiColourLine() ) parton->antiColourLine()->addColoured(this); else ColourLine::create(this, parton); } } void RemnantParticle::persistentOutput(PersistentOStream & os) const { os << remData << parent << theExtracted; } void RemnantParticle::persistentInput(PersistentIStream & is, int) { is >> remData >> parent >> theExtracted; } ClassDescription RemnantParticle::initRemnantParticle; // Definition of the static class description member. void RemnantParticle::Init() {} diff --git a/EventRecord/RemnantParticle.h b/EventRecord/RemnantParticle.h --- a/EventRecord/RemnantParticle.h +++ b/EventRecord/RemnantParticle.h @@ -1,188 +1,188 @@ // -*- C++ -*- // // RemnantParticle.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_RemnantParticle_H #define THEPEG_RemnantParticle_H // // This is the declaration of the RemnantParticle class. // #include "ThePEG/EventRecord/Particle.h" #include "RemnantParticle.fh" #include "ThePEG/PDT/RemnantData.fh" #include "ThePEG/PDT/RemnantDecayer.fh" namespace ThePEG { /** * Here is the documentation of the RemnantParticle class. */ class RemnantParticle: public Particle { public: /** * RemnantDecayer is a friend. */ friend class RemnantDecayer; public: /** @name Standard constructors and destructors. */ //@{ /** * The standard constructor takes as argument the \a particle for * which this is the remnant and a \a decayer capable of performing * the decay. Optionally a \a parton that has been extracted. Note * that if the parton is given, the extraction may silently fail. */ RemnantParticle(const Particle & particle, RemDecPtr decayer, tPPtr parton = tPPtr()); public: /** * Modify the properties to reflect that the given \a parton was * extracted. If \a fixcolour is true a colour line is drawn from * the remnant to the extracted parton. */ bool extract(tPPtr parton, bool fixcolour = false); /** * Modify the properties to reflect that the previously extracted * parton, \a oldp, was evolved backwards to the the parton \a * newp. If \a fixcolour is true a colour line is drawn from the * remnant to the extracted parton. */ bool reextract(tPPtr oldp, tPPtr newp, bool fixcolour = false); /** * Modify the properties to reflect that the given \a parton which * was previously extracted is removed. */ bool remove(tPPtr parton); /** * Acces the extracted partons. */ const PVector & extracted() const { return theExtracted; } public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** * If necessary, colour-connect this remnant to the given \a parton. */ void fixColourLines(tPPtr parton); private: /** * The RemnantData object associated to this remnant. */ RemPDPtr remData; /** * The parent from which this remnant resulted. */ tcPPtr parent; /** * The set of extracted partons. */ PVector theExtracted; protected: /** * Private default constructor must only be used by the * PersistentIStream class via the ClassTraits class. */ RemnantParticle() {} /** * The ClassTraits class must be a friend to be able to * use the private default constructor. */ friend struct ClassTraits; private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initRemnantParticle; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ RemnantParticle & operator=(const RemnantParticle &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of RemnantParticle. */ template <> struct BaseClassTrait { /** Typedef of the first base class of RemnantParticle. */ typedef Particle NthBase; }; /** This template specialization informs ThePEG about the name of * the RemnantParticle 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::RemnantParticle"; } /** Create a Particle object. */ static TPtr create() { return TPtr::Create(RemnantParticle()); } }; /** @endcond */ } #endif /* THEPEG_RemnantParticle_H */ diff --git a/EventRecord/RhoDMatrix.h b/EventRecord/RhoDMatrix.h --- a/EventRecord/RhoDMatrix.h +++ b/EventRecord/RhoDMatrix.h @@ -1,158 +1,158 @@ // -*- C++ -*- // // RhoDMatrix.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_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() = 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 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; } //@} /** * Reset */ void reset(bool average = true) { for(size_t ix=0; ix<_ispin; ++ix) for(size_t iy=0; iy<_ispin; ++iy) _matrix[ix][iy]=0.; if ( average ) for(size_t ix=0; ix<_ispin; ++ix) _matrix[ix][ix] = 1./_ispin; } /** @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. 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/EventRecord/SelectorBase.h b/EventRecord/SelectorBase.h --- a/EventRecord/SelectorBase.h +++ b/EventRecord/SelectorBase.h @@ -1,363 +1,363 @@ // -*- C++ -*- // // SelectorBase.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_SelectorBase_H #define ThePEG_SelectorBase_H // This is the declaration of the SelectorBase class. #include "EventConfig.h" namespace ThePEG { /** * Classes derived from the SelectorBase class are used * to extract particles from an Event with * Event::select() method. There are five different kinds * of checks done by a selector object in the * Event::select method. If the * allCollisions() method returns false, only particles * which belongs to the primary collision in an event will be * considered for extraction. Furthermore if the * allSteps() method returns false, only particles * present in the final step of each collision will be considered. If * finalState() returns false, final state particles will * not be considered and if intermediate() returns false, * intermediate particles will not be considered. Finally among all * considered particles, only the ones for which the check(const * Particle &) returns true will be extracted. * * * * * @see StandardSelectors * @see Event * @see Collision * @see Step * @see Particle * */ class SelectorBase { public: /** * Virtual destructor. */ virtual ~SelectorBase() {} /** * Static method corresponding to the virtual check() method. */ static bool Check(const Particle &) { return true; } /** * Static method corresponding to the virtual intermediate() method. */ static bool Intermediate() { return true; } /** * Static method corresponding to the virtual finalState() method. */ static bool FinalState() { return true; } /** * Static method corresponding to the virtual allSteps() method. */ static bool AllSteps() { return true; } /** * Static method corresponding to the virtual allCollisions() method. */ static bool AllCollisions() { return true; } /** * Return true if the particle should be extracted. */ virtual bool check(const Particle & p) const { return Check(p); } /** * Return true if final state particles are to be considered. */ virtual bool finalState() const { return FinalState(); } /** * Return true if intermediate particles should be considered. */ virtual bool intermediate() const { return Intermediate(); } /** * Return true if all steps should be considered. Otherwise only the * last step in each collision is considered. */ virtual bool allSteps() const { return AllSteps(); } /** * Return ture if all collisions should be considered. Otherwise * only the primary collision will be considered. */ virtual bool allCollisions() const { return AllCollisions(); } }; /** * The templated ParticleSelector class may be used to * implement derived classes from the SelectorBase * class. The requirement on the template class is that it implements * the static AllCollisions(), AllSteps(), * FinalState(), Intermediate() and * Check(const Particle &) (corresponding to the virtual * ones in ParticleSelector). */ template struct ParticleSelector: public SelectorBase { /** * Static method corresponding to the virtual check() method. */ static bool Check(const Particle & p) { return T::Check(p); } /** * Static method corresponding to the virtual intermediate() method. */ static bool Intermediate() { return T::Intermediate(); } /** * Static method corresponding to the virtual finalState() method. */ static bool FinalState() { return T::FinalState(); } /** * Static method corresponding to the virtual allSteps() method. */ static bool AllSteps() { return T::AllSteps(); } /** * Static method corresponding to the virtual allCollisions() method. */ static bool AllCollisions() { return T::AllCollisions(); } /** * Return true if the particle should be extracted. */ virtual bool check(const Particle & p) const { return Check(p); } /** * Return true if final state particles are to be considered. */ virtual bool finalState() const { return FinalState(); } /** * Return true if intermediate particles should be considered. */ virtual bool intermediate() const { return Intermediate(); } /** * Return true if all steps should be considered. Otherwise only the * last step in each collision is considered. */ virtual bool allSteps() const { return AllSteps(); } /** * Return ture if all collisions should be considered. Otherwise * only the primary collision will be considered. */ virtual bool allCollisions() const { return AllCollisions(); } }; /** * The SelectIfNot classes can be used to negate the meaning of * another SelectorBase object. */ class SelectIfNot: public SelectorBase { public: /** Constructor taking the SelectorBase object to be negated. */ explicit SelectIfNot(const SelectorBase & S) : s(S) {} /** * Return true if the particle should be extracted. */ virtual bool check(const Particle & p) const { return !s.check(p); } /** * Return true if final state particles are to be considered. */ virtual bool finalState() const { return !s.finalState(); } /** * Return true if intermediate particles should be considered. */ virtual bool intermediate() const { return !s.intermediate(); } /** * Return true if all steps should be considered. Otherwise only the * last step in each collision is considered. */ virtual bool allSteps() const { return !s.allSteps(); } /** * Return ture if all collisions should be considered. Otherwise * only the primary collision will be considered. */ virtual bool allCollisions() const { return !s.allCollisions(); } private: /** * The selector to be negated. */ const SelectorBase & s; }; /** * The SelectIfBoth class can be used to combine other selector * objects. Particles which would be extracted with either selectors * will be extractor. */ class SelectIfBoth: public SelectorBase { public: /** * Constructor taking two SelectorBase object to be combiden. */ SelectIfBoth(const SelectorBase & S1, const SelectorBase & S2) : s1(S1), s2(S2) {} /** * Return true if the particle should be extracted. */ virtual bool check(const Particle & p) const { return s1.check(p) && s2.check(p); } /** * Return true if final state particles are to be considered. */ virtual bool finalState() const { return s1.finalState() && s2.finalState(); } /** * Return true if intermediate particles should be considered. */ virtual bool intermediate() const { return s1.intermediate() && s2.intermediate(); } /** * Return true if all steps should be considered. Otherwise only the * last step in each collision is considered. */ virtual bool allSteps() const { return s1.allSteps() && s2.allSteps(); } /** * Return ture if all collisions should be considered. Otherwise * only the primary collision will be considered. */ virtual bool allCollisions() const { return s1.allCollisions() && s2.allCollisions(); } private: /** * One selector to be combined. */ const SelectorBase & s1; /** * The other selector to be combined. */ const SelectorBase & s2; }; /** * The SelectIfEither class can be used to combine other selector * objects. Only particles which would be extracted with both selectors * will be extractor. */ class SelectIfEither: public SelectorBase { public: /** * Constructor taking two SelectorBase object to be combiden. */ SelectIfEither(const SelectorBase & S1, const SelectorBase & S2) : s1(S1), s2(S2) {} /** * Return true if the particle should be extracted. */ virtual bool check(const Particle & p) const { return s1.check(p) || s2.check(p); } /** * Return true if final state particles are to be considered. */ virtual bool finalState() const { return s1.finalState() || s2.finalState(); } /** * Return true if intermediate particles should be considered. */ virtual bool intermediate() const { return s1.intermediate() || s2.intermediate(); } /** * Return true if all steps should be considered. Otherwise only the * last step in each collision is considered. */ virtual bool allSteps() const { return s1.allSteps() || s2.allSteps(); } /** * Return ture if all collisions should be considered. Otherwise * only the primary collision will be considered. */ virtual bool allCollisions() const { return s1.allCollisions() || s2.allCollisions(); } private: /** * One selector to be combined. */ const SelectorBase & s1; /** * The other selector to be combined. */ const SelectorBase & s2; }; /** Helper function to be used together with SelectorBase objects. */ template inline void copyIfCheck(OutputIterator r, const Container & c, const SelectorBase & s) { for ( typename Container::const_iterator it = c.begin(); it != c.end(); ++it ) if ( s.check(**it) ) *r++ = *it; } } #endif /* ThePEG_SelectorBase_H */ diff --git a/EventRecord/SpinInfo.cc b/EventRecord/SpinInfo.cc --- a/EventRecord/SpinInfo.cc +++ b/EventRecord/SpinInfo.cc @@ -1,208 +1,208 @@ // -*- C++ -*- // // SpinInfo.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the SpinInfo class. // // Author: Peter Richardson // #include "SpinInfo.h" #include "ThePEG/Repository/CurrentGenerator.h" #include "ThePEG/Repository/EventGenerator.h" #include "Event.h" using namespace ThePEG; const double SpinInfo::_eps=1.0e-8; SpinInfo::SpinInfo(const SpinInfo & x) : EventInfoBase(x), _production(x._production), _decay(x._decay), _timelike(x._timelike), _prodloc(x._prodloc), _decayloc(x._decayloc), _decayed(x._decayed), _developed(x._developed), _oldDeveloped(x._oldDeveloped), _rhomatrix(x._rhomatrix), _Dmatrix(x._Dmatrix),_spin(x._spin), _productionmomentum(x._productionmomentum), _decaymomentum(x._decaymomentum), _currentmomentum(x._currentmomentum) { x._production=VertexPtr(); x._decay=VertexPtr(); // set the vertex so it now points to the copy if(_production) { // for timelike if(_timelike) _production->resetOutgoing(this,_prodloc); // for spacelike else _production->resetIncoming(this,_prodloc); } } EIPtr SpinInfo::clone() const { tcSpinPtr temp=this; return const_ptr_cast(temp); } void SpinInfo::rebind(const EventTranslationMap & trans) { if(_production) _production = trans.translate(_production); if(_decay) _decay = trans.translate(_decay); EventInfoBase::rebind(trans); } NoPIOClassDescription SpinInfo::initSpinInfo; // Definition of the static class description member. void SpinInfo::Init() {} void SpinInfo::update() const { // number of instances fo this object int nref=referenceCount(); if(nref<2||nref>3) return; // work out the number of references there should be int nmin=0; // check the production pointers if(_production) { if(_timelike) { if(_production->outgoing()[_prodloc]==this) ++nmin;} else { if(_production->incoming()[_prodloc]==this) ++nmin;} } // check the decay pointers if(_decay) { if(_decay->incoming()[_decayloc]==this) ++nmin; } // delete the pointers SpinPtr temp; if(nmin+1==nref) { // delete the production pointers if(_production) { if(_timelike) { if(_production->outgoing()[_prodloc]==this) _production->resetOutgoing(SpinPtr(),_prodloc); } else { if(_production->incoming()[_prodloc]==this) _production->resetIncoming(SpinPtr(),_prodloc); } } // delete the decay pointers if(_decay) { if(_decay->incoming()[_decayloc]==this) _decay->resetIncoming(SpinPtr(),_decayloc); } } } void SpinInfo::decay(bool recursive) const { // if the particle has already been decayed do nothing if(_decayed) return; // otherwise we need to obtain the correct rho (timelike) or D (spacelike) matrix assert(_developed!=NeedsUpdate); if(_timelike) { if(_developed==Developed&&iSpin()!=PDT::Spin0) { if(_developed!=NeedsUpdate) _oldDeveloped=_developed; _developed=NeedsUpdate; } if(productionVertex()) { if(recursive) redecay(); else _rhomatrix = productionVertex()->getRhoMatrix(_prodloc,true); } } else { if(_developed==Developed&&iSpin()!=PDT::Spin0) { if(_developed!=NeedsUpdate) _oldDeveloped=_developed; _developed=NeedsUpdate; } if(productionVertex()) { if (recursive) redecay(); else _Dmatrix = productionVertex()->getDMatrix(_prodloc); } } _decaymomentum = _currentmomentum; _decayed=true; } void SpinInfo::undecay() const { // if the particle has not been decayed do nothing if(!_decayed) return; _decayed=false; _developed=_oldDeveloped; } void SpinInfo::redevelop() const { assert(developed()==NeedsUpdate); // calculate rho/D matrix if(_timelike) { _Dmatrix = decayVertex() ? decayVertex()->getDMatrix(decayLocation()) : RhoDMatrix(iSpin()); } else { _rhomatrix = decayVertex() ? decayVertex()->getRhoMatrix(decayLocation(),false) : RhoDMatrix(iSpin()); } // update the D matrix of this spininfo if(_developed!=NeedsUpdate) _oldDeveloped=_developed; _developed = Developed; // update the parent if needed if(productionVertex() && productionVertex()->incoming().size()==1) { tcSpinPtr parent = _timelike ? productionVertex()->incoming()[0] : productionVertex()->outgoing()[0]; if ( parent->developed() != StopUpdate ) { parent->needsUpdate(); parent->redevelop(); } } } void SpinInfo::develop() const { // if the particle has already been developed do nothing switch(_developed) { case Developed: return; case StopUpdate: return; case NeedsUpdate: redevelop(); return; case Undeveloped: if(_timelike) { if(_decay) _Dmatrix = _decay->getDMatrix(_decayloc); else _Dmatrix = RhoDMatrix(iSpin()); } else { if(_decay) _rhomatrix = _decay->getRhoMatrix(_decayloc,false); else _rhomatrix = RhoDMatrix(iSpin()); } if(_developed!=NeedsUpdate) _oldDeveloped=_developed; _developed=Developed; return; } } void SpinInfo::redecay() const { if(!productionVertex()) return; if(productionVertex()->incoming().size()==1) { tcSpinPtr parent; if(productionVertex()->incoming()[0]->timelike()) parent = productionVertex()->incoming()[0]; else { if(productionVertex()->outgoing()[0]!=this) parent = productionVertex()->outgoing()[0]; else parent = productionVertex()->outgoing()[1]; } if ( parent->developed() != StopUpdate ) parent->redecay(); } if(timelike()) _rhomatrix = productionVertex()->getRhoMatrix(_prodloc,true); else _Dmatrix = productionVertex()->getDMatrix(_prodloc); } diff --git a/EventRecord/SpinInfo.h b/EventRecord/SpinInfo.h --- a/EventRecord/SpinInfo.h +++ b/EventRecord/SpinInfo.h @@ -1,480 +1,480 @@ // -*- C++ -*- // // SpinInfo.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_SpinInfo_H #define ThePEG_SpinInfo_H // This is the declaration of the SpinInfo class. #include "ThePEG/EventRecord/EventInfoBase.h" #include "ThePEG/PDT/PDT.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "HelicityVertex.h" namespace ThePEG { /** * The SpinInfo is the base class for the spin information for the * spin correlation algorithm. The implementations for different spin * states inherit from this. * * The class contains pointers to the vertex where the particle is * produced and where it decays, together with methods to set/get * these. * * There are two flags decayed which store information on the state * of the particle. * * The decayed() members provides access to the _decay data member * which is true if the spin density matrix required to perform the * decay of a timelike particle has been calculated (this would be a * decay matrix for a spacelike particle.) This is set by the * decay() method which calls a method from the production vertex to * calculate this matrix. The decay() method should be called by a * decayer which uses spin correlation method before it uses the * spin density matrix to calculate the matrix element for the * decay. * * The developed() member provides access to the _developed data * member which is true if the decay matrix required to perform the * decays of the siblings of a particle has been calculated (this * would a spin density matrix for a spacelike particle.) This is * set by the developed() method which calls a method from the decay * vertex to calculate the matrix. The developed() method is called * by a DecayHandler which is capable of performing spin * correlations after all the unstable particles produced by a * decaying particle are decayed. * * Methods are also provided to access the spin density and decay * matrices for a particle. * * @author Peter Richardson * */ class SpinInfo: public EventInfoBase { public: /** * Status for the implementation of spin correlations */ enum DevelopedStatus { Undeveloped=0, /**< Not developed. */ Developed=1, /**< Developed. */ NeedsUpdate=2, /**< Developed but needs recalculating due to some change. */ StopUpdate=3 /**< Stop recalculating at this spin info. */ }; public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ SpinInfo() : _timelike(false), _prodloc(-1), _decayloc(-1), _decayed(false), _developed(Undeveloped), _oldDeveloped(Undeveloped) {} /** * Standard Constructor. * @param s the spin. * @param p the production momentum. * @param time true if the particle is time-like. */ SpinInfo(PDT::Spin s, const Lorentz5Momentum & p = Lorentz5Momentum(), bool time = false) : _timelike(time), _prodloc(-1), _decayloc(-1), _decayed(false), _developed(Undeveloped), _oldDeveloped(Undeveloped), _rhomatrix(s), _Dmatrix(s), _spin(s), _productionmomentum(p), _currentmomentum(p) {} /** * Copy-constructor. */ SpinInfo(const SpinInfo &); //@} public: /** * Returns true if the polarization() has been implemented in a * subclass. This default version returns false. */ virtual bool hasPolarization() const { return false; } /** * Return the angles of the polarization vector as a pair of * doubles. first is the polar angle and second is the azimuth * wrt. the particles direction. This default version of the * function returns 0,0, and if a subclass implements a proper * function it should also implement 'hasPolarization()' to return * true. */ virtual DPair polarization() const { return DPair(); } public: /** * Standard Init function. */ static void Init(); /** * Rebind to cloned objects. If a FermionSpinInfo is cloned together * with a whole Event and this has pointers to other event record * objects, these should be rebound to their clones in this * function. */ virtual void rebind(const EventTranslationMap & trans); /** * Standard clone method. */ virtual EIPtr clone() const; /** * Method to handle the delelation */ void update() const; /** * Perform a lorentz rotation of the spin information */ virtual void transform(const LorentzMomentum & m, const LorentzRotation & r) { _currentmomentum = m; _currentmomentum.transform(r); } /** * Reset - Undoes any transformations and calls undecay. */ virtual void reset() { _currentmomentum = _productionmomentum; } public: /** @name Access the vertices. */ //@{ /** * Set the vertex at which the particle was produced. */ void productionVertex(VertexPtr in) const { _production=in; // add to the list of outgoing if timelike int temp(-1); if(_timelike) in->addOutgoing(this,temp); // or incoming if spacelike else in->addIncoming(this,temp); _prodloc=temp; } /** * Get the vertex at which the particle was produced. */ tcVertexPtr productionVertex() const { return _production; } /** * Set the vertex at which the particle decayed or branched. */ void decayVertex(VertexPtr in) const { if(in) { _decay=in; if(_timelike) { int temp(-1); in->addIncoming(this,temp); _decayloc=temp; assert(temp==0); } else { int temp(-1); in->addOutgoing(this,temp); _decayloc=temp; } } else { _decay=VertexPtr(); _decayloc=-1; } } /** * Get the vertex at which the particle decayed or branched. */ tcVertexPtr decayVertex() const { return _decay; } //@} /** @name Access information about the associated particle. */ //@{ /** * Has the particle decayed? */ bool decayed() const { return _decayed; } /** * Set if the particle has decayed. */ void decayed(bool b) const { _decayed = b; } /** * Return true if the decay matrix required to perform the decays of * the siblings of a particle has been calculated. */ DevelopedStatus developed() const { return _developed; } /** * Calculate the rho matrix for the decay if not already done. */ void decay(bool recursive=false) const ; /** * Calculate the rho matrix for the decay if not already done. */ virtual void undecay() const ; /** * Set the developed flag and calculate the D matrix for the decay. */ void develop() const ; /** * Needs update */ void needsUpdate() const { if(_developed!=NeedsUpdate) _oldDeveloped = _developed; _developed=NeedsUpdate; } /** * Used for an unstable particle to *temporarily* stop * redevelop and redecay at that particle */ void stopUpdate() const {_developed=StopUpdate;} /** * Return 2s+1 for the particle */ PDT::Spin iSpin() const { return _spin; } /** * Return the momentum of the particle when it was produced. */ const Lorentz5Momentum & productionMomentum() const { return _productionmomentum; } /** * The current momentum of the particle */ const Lorentz5Momentum & currentMomentum() const { return _currentmomentum; } /** * Return true if particle is timelike (rather than spacelike). */ bool timelike() const { return _timelike; } //@} /** * Access to the locations */ //@{ /** * Production Location */ int productionLocation() const {return _prodloc;} /** * Decay Location */ int decayLocation() const {return _decayloc;} //@} public: /** @name Access the rho and D matrices. */ //@{ /** * Access the rho matrix. */ RhoDMatrix rhoMatrix() const { return _rhomatrix; } /** * Access the rho matrix. */ RhoDMatrix & rhoMatrix() { return _rhomatrix; } /** * Access the D matrix. */ RhoDMatrix DMatrix() const { return _Dmatrix; } /** * Access the D matrix. */ RhoDMatrix & DMatrix() { return _Dmatrix; } //@} protected: /** * Check if momentum is near to the current momentum */ bool isNear(const Lorentz5Momentum & p) { return currentMomentum().isNear(p,_eps); } private: /** * Describe a concrete class without persistent data. */ static NoPIOClassDescription initSpinInfo; /** * Private and non-existent assignment operator. */ SpinInfo & operator=(const SpinInfo &) = delete; private: /** * Set the developed flag and calculate the D matrix for the decay, * and all decays further up the chain. */ void redevelop() const ; /** * Recursively recalulate all the rho matrices from the top of the chain */ void redecay() const ; private: /** * Pointer to the production vertex for the particle */ mutable VertexPtr _production; /** * Pointers to the decay vertex for the particle */ mutable VertexPtr _decay; /** * Is this is timelike (true) or spacelike (false ) particle? This * is used to decide if the particle is incoming or outgoing at the * production vertex */ bool _timelike; /** * Location in the hard vertex array at production. */ mutable int _prodloc; /** * Location in the hard vertex array at decay. */ mutable int _decayloc; /** * Has the particle been decayed? (I.e. has the rho matrix for the * decay been calculated.) */ mutable bool _decayed; /** * Has the particle been developed? (I.e. has the D matrix encoding * the info about the decay been calculated) */ mutable DevelopedStatus _developed; /** * Has the particle been developed? (I.e. has the D matrix encoding * the info about the decay been calculated) */ mutable DevelopedStatus _oldDeveloped; /** * Storage of the rho matrix. */ mutable RhoDMatrix _rhomatrix; /** * Storage of the decay matrix */ mutable RhoDMatrix _Dmatrix; /** * The spin of the particle */ PDT::Spin _spin; /** * Momentum of the particle when it was produced */ Lorentz5Momentum _productionmomentum; /** * Momentum of the particle when it decayed */ mutable Lorentz5Momentum _decaymomentum; /** * Current momentum of the particle */ Lorentz5Momentum _currentmomentum; /** * A small energy for comparing momenta to check if Lorentz Transformations * should be performed */ static const double _eps; }; } namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** * This template specialization informs ThePEG about the base class of * SpinInfo. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the base class of SpinInfo. */ typedef EventInfoBase NthBase; }; /** * This template specialization informs ThePEG about the name of the * SpinInfo class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** * Return the class name. */ static string className() { return "ThePEG::SpinInfo"; } }; /** @endcond */ } #endif /* ThePEG_SpinInfo_H */ diff --git a/EventRecord/StandardSelectors.h b/EventRecord/StandardSelectors.h --- a/EventRecord/StandardSelectors.h +++ b/EventRecord/StandardSelectors.h @@ -1,211 +1,211 @@ // -*- C++ -*- // // StandardSelectors.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_StandardSelectors_H #define ThePEG_StandardSelectors_H /** * @file StandardSelectors.h This file contains declarations of * standard selector classes. The classes contain only static * functions and are assumed to be used as template arguments to the * ParticleSelector class. */ #include "SelectorBase.h" #include "ParticleTraits.h" namespace ThePEG { /** * The AllSelector class is used to extract all particles from an event. * * @see SelectorBase * @see ParticleSelector */ struct AllSelector: public SelectorBase { /** * Static method corresponding to the virtual check() * method. Returns true. */ static bool Check(const Particle &) { return true; } /** * Static method corresponding to the virtual intermediate() * method. Returns true. */ static bool Intermediate() { return true; } /** * Static method corresponding to the virtual finalState() * method. Returns true. */ static bool FinalState() { return true; } /** * Static method corresponding to the virtual allSteps() * method. Returns true. */ static bool AllSteps() { return true; } /** * Static method corresponding to the virtual allCollisions() * method. Returns true. */ static bool AllCollisions() { return true; } }; /** Typedef to declare a selector used to extract all particles from an * event. */ typedef ParticleSelector SelectAll; /** * The FinalStateSelector class is used to extract all final state particles * from an event. * * @see SelectorBase * @see ParticleSelector */ struct FinalStateSelector: public SelectorBase { /** * Static method corresponding to the virtual intermediate() * method. Returns false. */ static bool Intermediate() { return false; } /** * Static method corresponding to the virtual allSteps() * method. Returns false. */ static bool AllSteps() { return false; } }; /** Typedef to declare a selector used to extract all final state * particles from an event. */ typedef ParticleSelector SelectFinalState; /** * The IntermediateSelector class is used to extract only intermediate * particles from an event. * * @see SelectorBase * @see ParticleSelector */ struct IntermediateSelector: public SelectorBase { /** * Static method corresponding to the virtual check() * method. Returns true. */ static bool Check(const Particle &) { return true; } /** * Static method corresponding to the virtual intermediate() * method. Returns true. */ static bool Intermediate() { return true; } /** * Static method corresponding to the virtual finalState() * method. Returns false. */ static bool FinalState() { return false; } /** * Static method corresponding to the virtual allSteps() * method. Returns true. */ static bool AllSteps() { return true; } /** * Static method corresponding to the virtual allCollisions() * method. Returns true. */ static bool AllCollisions() { return true; } }; /** Typedef to declare a selector used to extract all intermediate * particles from an event. */ typedef ParticleSelector SelectIntermediates; /** * The PrimaryCollisionSelector class is used to extract all particles * from the primary Collision of an event. * * @see SelectorBase * @see ParticleSelector */ struct PrimaryCollisionSelector: public SelectorBase { /** * Static method corresponding to the virtual check() * method. Returns true. */ static bool Check(const Particle &) { return true; } /** * Static method corresponding to the virtual intermediate() * method. Returns true. */ static bool Intermediate() { return true; } /** * Static method corresponding to the virtual finalState() * method. Returns true. */ static bool FinalState() { return true; } /** * Static method corresponding to the virtual allSteps() * method. Returns true. */ static bool AllSteps() { return true; } /** * Static method corresponding to the virtual allCollisions() * method. Returns false. */ static bool AllCollisions() { return false; } }; /** Typedef to declare a selector used to extract all particles from * the primary Collision of an event. */ typedef ParticleSelector SelectPrimaryCollision; /** * The ChargedSelector class is used to extract all charged particles * from an event. * * @see SelectorBase * @see ParticleSelector */ struct ChargedSelector: public SelectorBase { /** * Static method corresponding to the virtual check() * method. Returns true if the given particle is charged.. */ static bool Check(const Particle & p) { return ParticleTraits::iCharge(p); } }; /** Typedef to declare a selector used to extract all charged * particles from an event. */ typedef ParticleSelector SelectCharged; } #endif /* ThePEG_StandardSelectors_H */ diff --git a/EventRecord/Step.cc b/EventRecord/Step.cc --- a/EventRecord/Step.cc +++ b/EventRecord/Step.cc @@ -1,448 +1,448 @@ // -*- C++ -*- // // Step.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the Step class. // #include "Step.h" #include "ThePEG/Utilities/Rebinder.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Config/algorithm.h" #include #include #ifdef ThePEG_TEMPLATES_IN_CC_FILE #include "Step.tcc" #endif using namespace ThePEG; Step::Step(const Step & s) : Base(s), theParticles(s.theParticles), theIntermediates(s.theIntermediates), allParticles(s.allParticles), theCollision(s.theCollision), theHandler(s.theHandler) {} Step::~Step() { for ( ParticleSet::iterator it = allParticles.begin(); it != allParticles.end(); ++it ) if ( (**it).hasRep() && (**it).birthStep() == this ) (**it).rep().theBirthStep = tStepPtr(); theParticles.clear(); theIntermediates.clear(); theSubProcesses.clear(); allParticles.clear(); theCollision = tCollPtr(); theHandler = tcEventBasePtr(); } StepPtr Step::clone() const { return ptr_new(*this); } void Step::rebind(const EventTranslationMap & trans) { ParticleSet::const_iterator pit; allParticles.clear(); for ( pit = theParticles.begin(); pit != theParticles.end(); ++pit ) allParticles.insert(trans.translate(*pit)); theParticles.swap(allParticles); allParticles.clear(); for ( pit = theIntermediates.begin(); pit != theIntermediates.end(); ++pit ) allParticles.insert(trans.translate(*pit)); theIntermediates = allParticles; allParticles.insert(theParticles.begin(), theParticles.end()); for ( pit = allParticles.begin(); pit != allParticles.end(); ++pit ) (**pit).rebind(trans); } void Step::addParticle(tPPtr p) { if ( !p->birthStep() ) p->rep().theBirthStep = this; theParticles.insert(p); allParticles.insert(p); if ( collision() ) collision()->addParticle(p); } void Step::addSubProcess(tSubProPtr sp) { if (( !member(allParticles, sp->incoming().first) && collision() && sp->incoming().first != collision()->incoming().first) && std::find(sp->incoming().first->parents().begin(), sp->incoming().first->parents().end(), collision()->incoming().first)== sp->incoming().first->parents().end()) { collision()->incoming().first-> rep().theChildren.push_back(sp->incoming().first); sp->incoming().first->rep().theParents.push_back(collision()->incoming().first); } if (( !member(allParticles, sp->incoming().second) && collision() && sp->incoming().second != collision()->incoming().second) && std::find(sp->incoming().second->parents().begin(), sp->incoming().second->parents().end(),collision()->incoming().second)== sp->incoming().second->parents().end()) { collision()->incoming().second-> rep().theChildren.push_back(sp->incoming().second); sp->incoming().second->rep().theParents.push_back(collision()->incoming().second); } if ( !sp->incoming().first->birthStep() ) sp->incoming().first->rep().theBirthStep = this; if ( !sp->incoming().second->birthStep() ) sp->incoming().second->rep().theBirthStep = this; addIntermediate(sp->incoming().first); addIntermediate(sp->incoming().second); addIntermediates(sp->intermediates().begin(), sp->intermediates().end()); addParticles(sp->outgoing().begin(), sp->outgoing().end()); theSubProcesses.push_back(sp); if ( collision() ) collision()->addSubProcess(sp); } void Step::removeSubProcess(tSubProPtr sp) { SubProcessVector::iterator sit = ThePEG::find(theSubProcesses, sp); if ( sit == theSubProcesses.end() ) return; for ( int i = 0, N = sp->outgoing().size(); i < N; ++i ) removeParticle(sp->outgoing()[i]); for ( int i = 0, N = sp->intermediates().size(); i < N; ++i ) removeParticle(sp->intermediates()[i]); removeParticle(sp->incoming().first); removeParticle(sp->incoming().second); theSubProcesses.erase(sit); if ( collision() ) collision()->removeSubProcess(sp); } void Step::addIntermediate(tPPtr p) { theIntermediates.insert(p); ParticleSet::iterator pit = theParticles.find(p); if ( pit != theParticles.end() ) theParticles.erase(pit); else { if ( !p->birthStep() ) p->rep().theBirthStep = this; allParticles.insert(p); if ( collision() ) collision()->addParticle(p); } } void Step:: insertIntermediate(tPPtr p, tPPtr parent, tPPtr child) { if ( !p->birthStep() ) p->rep().theBirthStep = this; addIntermediate(p); parent->removeChild(child); child->removeParent(parent); if ( parent ) { parent->rep().theChildren.push_back(p); p->rep().theParents.push_back(parent); } if ( child ) { p->rep().theChildren.push_back(child); child->rep().theParents.push_back(p); } } void Step::removeEntry(tPPtr p) { ParticleSet::iterator it = allParticles.find(p); if ( it == allParticles.end() ) return; allParticles.erase(it); it = theParticles.find(p); if ( it != theParticles.end() ) theParticles.erase(it); if ( p->previous() ) { it = theIntermediates.find(p->previous()); if ( it != theIntermediates.end() ) theIntermediates.erase(it); theParticles.insert(p->previous()); allParticles.insert(p->previous()); } while ( !p->parents().empty() ) { PPtr parent = p->parents().back(); p->removeParent(parent); parent->removeChild(p); if ( !parent->children().empty() ) continue; it = theIntermediates.find(parent); if ( it != theIntermediates.end() ) theIntermediates.erase(it); theParticles.insert(parent); allParticles.insert(parent); } if ( p->hasColourInfo() ) { if ( colourNeighbour(p) ) colourNeighbour(p)->antiColourNeighbour(antiColourNeighbour(p)); if ( antiColourNeighbour(p) ) antiColourNeighbour(p)->colourNeighbour(colourNeighbour(p)); if ( p->incomingColour() ) p->outgoingColour(tPPtr()); if ( p->incomingAntiColour() ) p->outgoingAntiColour(tPPtr()); } it = theIntermediates.find(p); if ( it != theIntermediates.end() ) theIntermediates.erase(it); } void Step::removeParticle(tPPtr p) { if ( p->next() ) removeParticle(p->next()); while ( !p->children().empty() ) removeParticle(p->children().back()); removeEntry(p); } bool Step::nullStep() const { for ( ParticleSet::const_iterator it = allParticles.begin(); it != allParticles.end(); ++it ) if ( (**it).birthStep() == this ) return false; return true; } tPPtr Step::copyParticle(tcPPtr pin) { PPtr cp; tPPtr p = const_ptr_cast(pin); if ( !collision() ) return cp; ParticleSet::iterator pit = theParticles.find(p); if ( collision()->finalStep() != this || p->next() || ! p->children().empty() || pit == theParticles.end() ) return cp; cp = p->clone(); cp->rep().thePrevious = p; p->rep().theNext = cp; if ( p->hasColour() ) p->colourFlow(cp); if ( p->hasAntiColour() ) p->antiColourFlow(cp); cp->rep().theBirthStep = this; theParticles.erase(pit); if ( p->birthStep() == this ) theIntermediates.insert(p); addParticle(cp); return cp; } bool Step::setCopy(tcPPtr poldin, tPPtr pnew) { if ( poldin->id() != pnew->id() ) return false; tPPtr pold = const_ptr_cast(poldin); pold->rep().theNext = pnew; pnew->rep().thePrevious = pold; theParticles.erase(pold); if ( pold->birthStep() == this ) theIntermediates.insert(pold); pnew->rep().theBirthStep = this; addParticle(pnew); return true; } tPPtr Step::insertCopy(tcPPtr pin) { PPtr cp; tPPtr p = const_ptr_cast(pin); if ( !collision() ) return cp; if ( collision()->all().find(p) == collision()->all().end() ) return cp; cp = p->clone(); cp->rep().theNext = p; cp->rep().theChildren.clear(); if ( p->previous() ) { p->previous()->rep().theNext = cp; cp->rep().thePrevious = p->previous(); } else { for ( int i = 0, N = p->parents().size(); i < N; ++i ) { tPPtr parent = p->parents()[i]; for ( int j = 0, M = parent->children().size(); j < M; ++j ) if ( parent->children()[j] == p ) parent->rep().theChildren[j] = cp; } } p->rep().theParents.clear(); p->rep().thePrevious = cp; if ( p->hasColour() ) cp->colourFlow(p); if ( p->hasAntiColour() ) cp->antiColourFlow(p); cp->rep().theBirthStep = this; theIntermediates.insert(cp); return cp; } bool Step::removeDecayProduct(tcPPtr par, tPPtr child) { if ( !collision() ) return false; tPPtr parent = const_ptr_cast(par->final()); if ( collision()->all().find(parent) == collision()->all().end() ) return false; if ( !par->hasRep() ) return false; PVector::iterator it = ThePEG::find(parent->rep().theChildren, child); if ( it == parent->rep().theChildren.end() ) return false; parent->rep().theChildren.erase(it); ParticleSet::iterator cit = theParticles.find(child); if ( cit != theParticles.end() ) { theParticles.erase(cit); if ( child->birthStep() == this ) theIntermediates.insert(child); } return true; } bool Step::addDecayProduct(tcPPtr par, tPPtr child, bool fixColour) { if ( !collision() ) return false; tPPtr parent = const_ptr_cast(par->final()); if ( collision()->finalStep() != this || parent->next() ) return false; ParticleSet::iterator pit = theParticles.find(parent); if ( pit != theParticles.end() ) { theParticles.erase(pit); if ( parent->birthStep() == this ) theIntermediates.insert(parent); } else { if ( parent != collision()->incoming().first && parent != collision()->incoming().second && parent->children().empty() ) return false; } parent->rep().theChildren.push_back(child); child->rep().theParents.push_back(parent); child->rep().theBirthStep = this; addParticle(child); if ( !fixColour || !parent->hasColourInfo() || !parent->coloured() || !child->coloured() ) return true; if ( parent->hasColour() && child->hasColour() && !parent->outgoingColour() && !child->colourLine() ) parent->colourFlow(child); if ( parent->hasAntiColour() && child->hasAntiColour() && !child->antiColourLine() ) { if ( parent->outgoingAntiColour() ) parent->antiColourLine()-> removeAntiColoured(parent->outgoingAntiColour()); parent->antiColourFlow(child); } return true; } void Step::addDecayNoCheck(tPPtr parent, tPPtr child) { ParticleSet::iterator pit = theParticles.find(parent); if ( pit != theParticles.end() ) { theParticles.erase(pit); if ( parent->birthStep() == this ) theIntermediates.insert(parent); } child->rep().theBirthStep = this; addParticle(child); } void Step::addDecayProduct(tPPtr child) { for ( int i = 0, N = child->parents().size(); i < N; ++i ) { ParticleSet::iterator pit = theParticles.find(child->parents()[i]); if ( pit != theParticles.end() ) { theParticles.erase(pit); if ( child->parents()[i]->birthStep() == this ) theIntermediates.insert(child->parents()[i]); } } child->rep().theBirthStep = this; addParticle(child); } void Step::fixColourFlow() { tParticleVector news; for ( ParticleSet::iterator pi = theParticles.begin(); pi != theParticles.end(); ++pi ) if ( (**pi).birthStep() == this ) news.push_back(*pi); for ( int i = 0, N = news.size(); i < N; ++i ) { tPPtr p = news[i]; if ( p->hasColour() && !antiColourNeighbour(p) ) { tPPtr ng = p; while ( ( ng = ng->incomingColour() ) && !antiColourNeighbour(ng) ) {} if ( ng ) { ng = antiColourNeighbour(ng); if ( !ng->outgoingColour() ) ng = copyParticle(ng); while ( ng->outgoingColour() ) ng = ng->outgoingColour(); p->antiColourConnect(ng); } } if ( p->hasAntiColour() && !colourNeighbour(p) ) { tPPtr ng = p; while ( ( ng = ng->incomingAntiColour() ) && !colourNeighbour(ng) ) {} if ( ng ) { ng = colourNeighbour(ng); if ( !ng->outgoingAntiColour() ) ng = copyParticle(ng); while ( ng->outgoingAntiColour() ) ng = ng->outgoingAntiColour(); p->colourConnect(ng); } } } } tPPtr Step::antiColourNeighbour(tcPPtr p) const { return colourNeighbour(p, true); } tPPtr Step::colourNeighbour(tcPPtr p, bool anti) const { if ( !member(particles(), const_ptr_cast(p)) ) return tPPtr(); tColinePtr line = p->colourLine(!anti); if ( !line ) return tPPtr(); for ( ParticleSet::const_iterator it = particles().begin(); it != particles().end(); ++it ) if ( (**it).hasColourLine(line, anti) ) return *it; return tPPtr(); } vector Step::getSinglets(tParticleSet & left) { vector ret; while ( !left.empty() ) { tPPtr first = *left.begin(); left.erase(first); if ( !first->hasColourInfo() || !first->coloured() ) continue; tPPtr last = first; tPPtr test; while ( ( test = last->antiColourNeighbour(left.begin(), left.end()) ) && test != first ) last = test; while ( ( test = first->colourNeighbour(left.begin(), left.end()) ) && test != last ) first = test; ret.push_back(tPVector()); for ( ; first != last; first = first->antiColourNeighbour(left.begin(), left.end()) ) { left.erase(first); ret.back().push_back(first); } left.erase(first); ret.back().push_back(first); } return ret; } ostream & ThePEG::operator<<(ostream & os, const Step & s) { if ( !s.intermediates().empty() ) os << "--- intermediates:" << endl; Particle::PrintParticles(os, s.intermediates(), &s); os << "--- final:" << endl; LorentzMomentum sum; Energy2 sumx = Energy2(); Energy2 sumy = Energy2(); Energy2 sumz = Energy2(); Particle::PrintParticles(os, s.particles(), &s); for ( ParticleSet::const_iterator it = s.particles().begin(); it != s.particles().end(); ++it ) { sum += (**it).momentum(); sumx += sqr((**it).momentum().x()); sumy += sqr((**it).momentum().y()); sumz += sqr((**it).momentum().z()); } os << string(78, '-') << endl << " Sum of momenta: "; int oldprecision = os.precision(); Energy sumx1 = ( sqr(sum.x()) > Constants::epsilon*sumx ? sum.x(): ZERO ); Energy sumy1 = ( sqr(sum.y()) > Constants::epsilon*sumy ? sum.y(): ZERO ); Energy sumz1 = ( sqr(sum.z()) > Constants::epsilon*sumz ? sum.z(): ZERO ); os << setprecision(3) << setw(10) << sumx1/GeV << setw(10) << sumy1/GeV << setw(10) << sumz1/GeV << setw(10) << sum.e()/GeV << setw(10) << sum.m()/GeV << endl << setprecision(oldprecision); return os; } void Step::debugme() const { cerr << *this; EventRecordBase::debugme(); } void Step::persistentOutput(PersistentOStream & os) const { os << theParticles << theIntermediates << theSubProcesses << allParticles << theCollision; EventConfig::putHandler(os, theHandler); } void Step::persistentInput(PersistentIStream & is, int) { is >> theParticles >> theIntermediates >> theSubProcesses >> allParticles >> theCollision; EventConfig::getHandler(is, theHandler); } ClassDescription Step::initStep; void Step::Init() {} diff --git a/EventRecord/Step.h b/EventRecord/Step.h --- a/EventRecord/Step.h +++ b/EventRecord/Step.h @@ -1,544 +1,544 @@ // -*- C++ -*- // // Step.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_BasicStep_H #define ThePEG_BasicStep_H // This is the declaration of the Step class. #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/EventRecord/StandardSelectors.h" namespace ThePEG { /** * The Step class contains information of all particles present after * certain step in the event generation. There is also information * about particles which were introduced as intermediate ones in the * generation of the step. The Step may also contain one or more * SubProcesses which were generated in the step. The Step is linked * back to the Collision to which it belongs, and there may be a * pointer to the StepHandler which generated the step. * * @see Event * @see Collision * @see SubProcess * @see Particle * @see SelectorBase * @see SelectorBase */ class Step: public EventRecordBase { public: /** Most of the Event classes are friends with each other. */ friend class Collision; /** Most of the Event classes are friends with each other. */ friend class Event; public: /** * Standard constructor. * @param newCollision the Collision to which this Step belongs. * @param newHandler the handler object in charge of the generation * of this Step. */ Step(tCollPtr newCollision = tCollPtr(), tcEventBasePtr newHandler = tcEventBasePtr()) : theCollision(newCollision), theHandler(newHandler) {} /** * The copy constructor. */ Step(const Step &); /** * The destructor. */ ~Step(); /** * Return a pointer to the step handler which performed the * generation of this step. */ tcEventBasePtr handler() const { return theHandler; } /** * Return a pointer to the Collision to which this step belongs. */ tCollPtr collision() const { return theCollision; } /** * Extract particles from this Step which satisfies the * requirements given by an object of the SelectorBase class. * @param r an output iterator specifying where the extracted * (pointers to) particles will be appended. * @param s SelectorBase object defining which particles should be * extracted. */ template void select(OutputIterator r, const SelectorBase & s) const; /** * Extract all final state particles in this Step. * @param r an output iterator specifying where the extracted * (pointers to) particles will be appended. */ template void selectFinalState(OutputIterator r) const { select(r, SelectFinalState()); } /** * Extract all final state particles in this Step. * @return a vector of pointers to the extracted particles. */ tPVector getFinalState() const { tPVector ret; selectFinalState(back_inserter(ret)); return ret; } /** * Return a vector of particle vectors with colour-connected * partons, where each particle vector is in a colour singlet state. * @deprecated Use the corresponding functions in ColourLine instead. */ template static vector getSinglets(PIterator first, PIterator last) { tParticleSet left(first, last); return getSinglets(left); } /** * A reference to the set of all particles in this step. */ const ParticleSet & all() const { return allParticles; } /** * A reference to the set of outgoing particles in this step. */ const ParticleSet & particles() const { return theParticles; } /** * A reference to the set of intermediate particles in this step. */ const ParticleSet & intermediates() const { return theIntermediates; } /** * A reference to the vector of sub-processes introduced in this * step. */ const SubProcessVector & subProcesses() const { return theSubProcesses; } /** * Returns the colliding particles in the collision to which this * step belongs. (If this step does not belong to a collision, this * method will probably cause a segmentation fault - This should be * fixed. @deprecated Maybe this method is not needed at all.) */ const PPair & incoming() const; /** * Get mutable particle. If the given particle is present in this * step, return its pointer otherwise return the null pointer; */ tPPtr find(tcPPtr p) const { tPPtr r = const_ptr_cast(p); if ( !member(all(), r) ) return tPPtr(); return r; } /** * Copy a particle. If the given Particle is present in this step, * insert a copy and remove the original (or make it intermediate if * it was initially added to this step). Returns the new Particle if * the copy succeeded. If the copy fails, nothing is changed. For a * successful call copyParticle(p)->previous() == p is * true. */ tPPtr copyParticle(tcPPtr p); /** * Make particles copies of eachother. Declare that pold and pnew * are two instances of the same particle. If pnew is not present in * the step it will be afterwars. Afterwards pold == * pnew->previous() && pnew == pold->next() is true. Returns * false if something went wrong. */ bool setCopy(tcPPtr pold, tPPtr pnew); /** * Insert a copy. If the given particle is present in the current * Collision, insert copy of that particle 'before' the particle. If * the particle does not belong to the current collision or if the * copy failed, nothing is changed and the null pointer is * returned. If successful insertCopy(p)->next() == p * is true. The parents of the original particle will become the * parents of the copy. */ tPPtr insertCopy(tcPPtr p); /** * Add decay product. If the \a parent is present in this step or if * it has immediate children in this step, insert the \a child and * fix up references between the two. If the parent is among the * final state particles, remove it (or make it intermediate if it * was initially added to this step). The parent/child pointers of * the affected particles will be set accordingly. If both the * parent and child/children are coloured and \a fixColour is true, * the colour flow will be set. * @return true iff the addition succeeded. */ bool addDecayProduct(tcPPtr parent, tPPtr child, bool fixColour = true); /** * Add decay products. If the \a parent is present in this step or if * it has immediate children in this step, insert the range of * children and fix up references between the two. If the parent is * among the final state particles, remove it (or make it * intermediate if it was initially added to this step). The * parent/child pointers of the affected particles will be set * accordingly. If both the parent and children are coloured and \a * fixColour is true, the colour flow will be set. The colour of the * parent will then flow to the first added child, while the anti * colour will flow to the last added child. * @return true iff the addition succeeded. */ template bool addDecayProduct(tcPPtr parent, CIterator firstChild, CIterator lastChild, bool fixColour = true) { for ( ; firstChild != lastChild; ++firstChild ) if ( !addDecayProduct(parent, *firstChild, fixColour) ) return false; return true; } /** * Add a particle to this Step. It is assumed to be already setup as * a child to a parent particle. The parent is removed from the list * of final state particles in this step. No consistency checks are * performed. @deprecated Use addDecayProduct(tPPtr child) instead. */ void addDecayNoCheck(tPPtr parent, tPPtr child); /** * Add a particle to this Step. It is assumed to be already setup as * a child to parent particles. The parents are removed from the * list of final state particles in this step. No consistency checks * are performed. */ void addDecayProduct(tPPtr child); /** * Remove the \a child form the given \a parent. The \a child is not * removed from the decay record. */ bool removeDecayProduct(tcPPtr parent, tPPtr child); /** * Remove children form the given \a parent. The children are not * removed from the decay record. */ template bool removeDecayProduct(tcPPtr parent, CIterator firstChild, CIterator lastChild) { bool success = true; for ( ; firstChild != lastChild; ++firstChild ) if ( !removeDecayProduct(parent, *firstChild) ) success = false; return success; } /** * Add decay product. Add the \a child as a decay product of all the * listed parents. The parents must satisfy the same requirements as * in the addDecayProduct(tcPPtr,tPPtr,bool) function. If any of the * parents fail false is returned and nothing is changed. The * parent/child pointers of the affected particles will be set * accordingly, but no colour flow wll be set. If \a checkfinal is * true the parents or its immediate children must be in the final * state. */ template bool addDecayProduct(Iterator firstParent, Iterator lastParent, tPPtr child, bool checkfinal = true); /** * Add the children as a decay products of all the listed * particles. The parents must satisfy the same requirements as in * the addDecayProduct(tcPPtr,tPPtr,bool) function. If any of the * parents fail false is returned and nothing is changed. The * parent/child pointers of the affected particles will be set * accordingly, but no colour flow wll be set. */ template bool addDecayProduct(PIterator firstParent, PIterator lastParent, CIterator firstChild, CIterator lastChild); /** * Fix the colour flow of particles which have been added to this * step and which have not already had their colour neighbours set. * If a neighbor is found which has not been added in this step, it * is first cloned in order not to compromise the colour flow of * previous steps. @deprecated This method should not be needed with * the current ColourLine representation of colour. */ void fixColourFlow(); /** * Return the (\a anti-)colour neighbour of the given \a particle if * one exists in the final state of this Step. The colour neighbour * has its colour connected to the same colour line as the given \a * particles anti-colour. Will return null if the given \a particle * is not in the final state of this Step. */ tPPtr colourNeighbour(tcPPtr particle, bool anti = false) const; /** * Return the anti-colour neighbour of the given \a particle if one * exists in the final state of this Step. The anti-colour neighbour * has its anti-colour connected to the same colour line as the * given \a particles colour. Will return null if the given \a * particle is not in the final state of this Step. */ tPPtr antiColourNeighbour(tcPPtr particle) const; /** * Add a range of particles to this Step. If this step belongs * to a Collision, the paticle will also be added to the * Collision. If this particle has not previously been in a Step, * the birthStep pointer of the particle will be set. */ template void addParticles(Iterator first, Iterator last); /** * Add a particle to this step. If this step belongs to a Collision, * the paticle will also be added to the Collision. If this particle * has not previously been in a Step, the birthStep pointer of the * particle will be set. */ void addParticle(tPPtr p); /** * Add a range of intermediate particles in this step. If this step * belongs to a Collision, the particles will also be added to the * Collision. If any particle has not previously been in a Step, * the birthStep pointer of the particle will be set. The particles * will be removed from the list of final state particles if * present. */ template void addIntermediates(Iterator first, Iterator last); /** * Add an intermediate particle in this Step. If this Step belongs * to a Collision, the particle will also be added to the * Collision. If this particle has not previously been in a step, * the birthStep pointer of the particle will be set. The particle * will be removed from the list of final state particles if * present. */ void addIntermediate(tPPtr p); /** * Add an intermediate particle. Particle \a p is added so that if * \a child previously was the child of \a parent, afterwards \a p * will be the child of \a parent and \a child will be the child of * \a p. */ void insertIntermediate(tPPtr p, tPPtr parent, tPPtr child); /** * Add a sub-process. All outgoing particles are added to the list * of outgoing particles in the step. All other particles in the * sub-process will be added to the list of intermediates. */ void addSubProcess(tSubProPtr); /** * Remove a sub-process. All incoming and outgoing particles are * removed as well. */ void removeSubProcess(tSubProPtr); /** * Remove (recursively) the given Particle from the Step. If * this was the last daughter of the mother Particle, the latter is * added to the list of final state particles. */ void removeParticle(tPPtr p); /** * Return true if no new particles were introduced in this step. */ bool nullStep() const; /** * Get final state particles. Given a container, return the ones * which belongs to the final state of this step. If a particle does * not belong to these, it's children (or next instance) will be * checked and possibly added instead (recursively). */ template tParticleSet getCurrent(const Cont & c) const { return getCurrent(c.begin(), c.end()); } /** * Get final state particles. Given a range of particles, return the * ones which belongs to the final state of this step. If a particle * does not belong to these, it's children (or next instance) will * be checked and possibly added instead (recursively) */ template tParticleSet getCurrent(Iterator first, Iterator last) const; /** * Return a clone of this step. */ StepPtr clone() const; public: /** * Standard function for writing to a persistent stream. */ void persistentOutput(PersistentOStream &) const; /** * Standard function for reading from a persistent stream. */ void persistentInput(PersistentIStream &, int); /** * Standard Init function. @see Base::Init(). */ static void Init(); protected: /** * Used internally by the public getSinglets(...); @deprecated Use * the corresponding functions in ColourLine instead. */ static vector getSinglets(tParticleSet &); /** * Remove a particle entry from the step. Make its ancesters (if * any) present in this step. */ void removeEntry(tPPtr p); /** * Rebind to cloned objects. When a Step is cloned, a shallow copy * is done first, then all Particles etc, are cloned, * and finally this method is used to see to that the pointers in * the cloned Step points to the cloned Particles etc. */ void rebind(const EventTranslationMap & trans); /** * Get final state particles. Insert particle \a p into with the * Inserter \a o if \a p is a member of the final state of this * Step. Otherwise call the method for the children of \a p if any. */ template void addIfFinal(Inserter o, PPointer p); private: /** * Assignement is not allowed. */ Step & operator=(const Step &) = delete; /** * Setup pointer to the Collision. */ void collision(tCollPtr c) { theCollision = c; } /** * Setup pointer to the step handler. */ void handler(tcEventBasePtr sh) { theHandler = sh; } private: /** * The set of all outgoing particle in this step. */ ParticleSet theParticles; /** * The set of all intermediate particle in this step. */ ParticleSet theIntermediates; /** * The vector of all sub-processes introduced in this step. */ SubProcessVector theSubProcesses; /** * The set of all particles available in this step. */ ParticleSet allParticles; /** * Pointer to the collision to which this step belongs. */ tCollPtr theCollision; /** * Pointer ot the step handler which performed this step. */ tcEventBasePtr theHandler; public: /** * Print out debugging information for this object on std::cerr. To * be called from within a debugger via the debug() function. */ virtual void debugme() const; private: /** * Describe concrete class with persistent data. */ static ClassDescription initStep; }; /** Output a Step to an ostream */ ostream & operator<<(ostream &, const Step &); /** @cond TRAITSPECIALIZATIONS */ ThePEG_DECLARE_CLASS_TRAITS(Step,EventRecordBase); /** @endcond */ } #include "Collision.h" inline const ThePEG::PPair & ThePEG::Step::incoming() const { return collision()->incoming(); } #ifndef ThePEG_TEMPLATES_IN_CC_FILE #include "Step.tcc" #endif #endif /* ThePEG_BasicStep_H */ /** * Write a Step object to a stream */ diff --git a/EventRecord/Step.tcc b/EventRecord/Step.tcc --- a/EventRecord/Step.tcc +++ b/EventRecord/Step.tcc @@ -1,120 +1,120 @@ // -*- C++ -*- // // Step.tcc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined templated member // functions of the Step class. // namespace ThePEG { template void Step::select(OutputIterator r, const SelectorBase & s) const { if ( s.finalState() ) copyIfCheck(r, particles(), s); if ( s.intermediate() ) copyIfCheck(r, intermediates(), s); } template void Step::addParticles(Iterator first, Iterator last) { theParticles.insert(first, last); allParticles.insert(first, last); if ( collision() ) collision()->addParticles(first, last); for ( ; first != last; ++first ) if ( !(**first).birthStep() ) (**first).rep().theBirthStep = this; } template void Step::addIntermediates(Iterator first, Iterator last) { theIntermediates.insert(first, last); allParticles.insert(first, last); if ( collision() ) collision()->addParticles(first, last); for ( ; first != last; ++first ) { if ( !(**first).birthStep() ) (**first).rep().theBirthStep = this; ParticleSet::iterator pit = theParticles.find(*first); if ( pit != theParticles.end() ) theParticles.erase(pit); } } template bool Step:: addDecayProduct(Iterator firstParent, Iterator lastParent, tPPtr child, bool checkfinal) { if ( !collision() ) return false; if ( collision()->finalStep() != this ) return false; if ( checkfinal ) { for ( Iterator it = firstParent; it != lastParent; ++it ) { tPPtr parent = const_ptr_cast((**it).final()); if ( member(theParticles, parent) ) continue; if ( parent->children().empty() || !member(theParticles, parent->children()[0]->final()) ) return false; } } for ( Iterator it = firstParent; it != lastParent; ++it ) { tPPtr parent = const_ptr_cast((**it).final()); ParticleSet::iterator pit = theParticles.find(parent); if ( pit != theParticles.end() ) { theParticles.erase(pit); if ( parent->birthStep() == this ) theIntermediates.insert(parent); } parent->rep().theChildren.push_back(child); child->rep().theParents.push_back(parent); } child->rep().theBirthStep = this; addParticle(child); return true; } template bool Step::addDecayProduct(PIterator firstParent, PIterator lastParent, CIterator firstChild, CIterator lastChild) { if ( !collision() ) return false; if ( collision()->finalStep() != this ) return false; for ( PIterator it = firstParent; it != lastParent; ++it ) { tPPtr parent = const_ptr_cast((**it).final()); if ( member(theParticles, parent) ) continue; if ( parent->children().empty() || !member(theParticles, parent->children()[0]->final()) ) return false; } for ( PIterator it = firstParent; it != lastParent; ++it ) { tPPtr parent = const_ptr_cast((**it).final()); ParticleSet::iterator pit = theParticles.find(parent); if ( pit != theParticles.end() ) { theParticles.erase(pit); if ( parent->birthStep() == this ) theIntermediates.insert(parent); } for ( CIterator cit = firstChild; cit != lastChild; ++cit ) { parent->rep().theChildren.push_back(*cit); (**cit).rep().theParents.push_back(parent); } } for ( CIterator cit = firstChild; cit != lastChild; ++cit ) { (**cit).rep().theBirthStep = this; addParticle(*cit); } return true; } template tParticleSet Step::getCurrent(Iterator first, Iterator last) const { tParticleSet res; for ( Iterator i = first; i != last; ++i ) addIfFinal(inserter(res), *i); return res; } template void Step::addIfFinal(Inserter o, PPointer p) { if ( member(theParticles, p) ) *o++ = p; else if ( p->next() ) addIfFinal(o, p->next()); else for ( int i = 0, N = p->children().size(); i < N; ++i ) addIfFinal(o, p->children()[i]); } } diff --git a/EventRecord/SubProcess.cc b/EventRecord/SubProcess.cc --- a/EventRecord/SubProcess.cc +++ b/EventRecord/SubProcess.cc @@ -1,150 +1,150 @@ // -*- C++ -*- // // SubProcess.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad -// Copyright (C) 2009-2017 Simon Platzer +// Copyright (C) 1999-2019 Leif Lonnblad +// Copyright (C) 2009-2019 Simon Platzer // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the SubProcess class. // #include "SubProcess.h" #include "ThePEG/EventRecord/Collision.h" #include "ThePEG/Config/algorithm.h" #include "ThePEG/EventRecord/ParticleTraits.h" #include "ThePEG/Utilities/Rebinder.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include #ifdef ThePEG_TEMPLATES_IN_CC_FILE #include "SubProcess.tcc" #endif using namespace ThePEG; SubProcess:: SubProcess(const PPair & newIncoming, tCollPtr newCollision, tcEventBasePtr newHandler, tSubProPtr newHead, double newGroupWeight) : theHandler(newHandler), theCollision(newCollision), theIncoming(newIncoming), isDecayed(false), theHead(newHead), theGroupWeight(newGroupWeight) {} SubProcess::~SubProcess() {} SubProPtr SubProcess::clone() const { return ptr_new(*this); } void SubProcess::addIntermediate(tPPtr p, bool fixrelations) { if ( fixrelations ) { incoming().first->rep().theChildren.push_back(p); incoming().second->rep().theChildren.push_back(p); p->rep().theParents.push_back(incoming().first); p->rep().theParents.push_back(incoming().second); } theIntermediates.push_back(p); } void SubProcess::addOutgoing(tPPtr p, bool fixrelations) { if ( fixrelations ) { if ( intermediates().empty() ) { incoming().first->rep().theChildren.push_back(p); incoming().second->rep().theChildren.push_back(p); p->rep().theParents.push_back(incoming().first); p->rep().theParents.push_back(incoming().second); } else { for (ParticleVector::iterator it = theIntermediates.begin(); it != theIntermediates.end(); ++it ) { (**it).rep().theChildren.push_back(p); p->rep().theParents.push_back(*it); } } } theOutgoing.push_back(p); } void SubProcess::changeIncoming(tPPtr pnew, tPPtr pold) { if(pold==theIncoming.first) { theIntermediates.push_back(pold); theIncoming.first = pnew; } else if(pold==theIncoming.second) { theIntermediates.push_back(pold); theIncoming.second = pnew; } } void SubProcess::rebind(const EventTranslationMap & trans) { theIncoming.first = trans.translate(theIncoming.first); theIncoming.second = trans.translate(theIncoming.second); theCollision = trans.translate(theCollision); for ( ParticleVector::iterator pit = theOutgoing.begin(); pit != theOutgoing.end(); ++pit ) *pit = trans.translate(*pit); for ( ParticleVector::iterator pit = theIntermediates.begin(); pit != theIntermediates.end(); ++pit ) *pit = trans.translate(*pit); } void SubProcess::removeEntry(tPPtr p) { if ( p == theIncoming.first ) theIncoming.first = PPtr(); if ( p == theIncoming.second ) theIncoming.second = PPtr(); ParticleVector::iterator pit = theOutgoing.begin(); while ( pit != theOutgoing.end() ) { if ( *pit == p ) pit = theOutgoing.erase(pit); else ++pit; } pit = theIntermediates.begin(); while ( pit != theIntermediates.end() ) { if ( *pit == p ) pit = theIntermediates.erase(pit); else ++pit; } } void SubProcess::transform(const LorentzRotation & r) { incoming().first->transform(r); incoming().second->transform(r); for_each(intermediates(), Transformer(r)); for_each(outgoing(), Transformer(r)); } void SubProcess::printMe(ostream& os) const { os << "--- incoming:" << endl << *incoming().first << *incoming().second; if ( !intermediates().empty() ) os << "--- intermediates:" << endl; Particle::PrintParticles(os, intermediates().begin(), intermediates().end()); os << "--- outgoing:" << endl; Particle::PrintParticles(os, outgoing().begin(), outgoing().end()); } ostream & ThePEG::operator<<(ostream & os, const SubProcess & sp) { sp.printMe(os); return os; } void SubProcess::debugme() const { cerr << *this; EventRecordBase::debugme(); } void SubProcess::persistentOutput(PersistentOStream & os) const { EventConfig::putHandler(os, theHandler); os << theCollision << theIncoming << theIntermediates << theOutgoing << isDecayed << theHead << theGroupWeight; } void SubProcess::persistentInput(PersistentIStream & is, int) { EventConfig::getHandler(is, theHandler); is >> theCollision >> theIncoming >> theIntermediates >> theOutgoing >> isDecayed >> theHead >> theGroupWeight; } ClassDescription SubProcess::initSubProcess; void SubProcess::Init() {} diff --git a/EventRecord/SubProcess.h b/EventRecord/SubProcess.h --- a/EventRecord/SubProcess.h +++ b/EventRecord/SubProcess.h @@ -1,348 +1,348 @@ // -*- C++ -*- // // SubProcess.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad -// Copyright (C) 2009-2017 Simon Platzer +// Copyright (C) 1999-2019 Leif Lonnblad +// Copyright (C) 2009-2019 Simon Platzer // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_SubProcess_H #define ThePEG_SubProcess_H // This is the declaration of the SubProcess class. #include #include "ThePEG/EventRecord/Particle.h" namespace ThePEG { class SubProcessGroup; /** * A SubProcess object represents a hard \f$2\rightarrow n\f$ * sub-process in a collision. It carries information about the * incoming and outgoing particles, as well as possible intermediate * ones. It also has a pointer to the MEBase object which generated * the sub-process. * * @see Event * @see Particle * @see SubProcessGroup */ class SubProcess: public EventRecordBase { public: /** Most of the Event classes are friends with each other. */ friend class Step; /** Most of the Event classes are friends with each other. */ friend class Collision; /** Most of the Event classes are friends with each other. */ friend class SubProcessGroup; public: /** * Standard constructor. * @param newIncoming the two incoming partons. * @param newCollision the Collision to which this SubProcess belongs. * @param newHandler the MEBase object which generated this SubProcess. */ SubProcess(const PPair & newIncoming, tCollPtr newCollision = tCollPtr(), tcEventBasePtr newHandler = tcEventBasePtr(), tSubProPtr newHead = tSubProPtr(), double newGroupWeight = 1.0); /** * Destructor. */ virtual ~SubProcess(); /** * A pointer to the MEBase object which generated this SubProcess. */ tcEventBasePtr handler() const { return theHandler; } /** * A pointer to the collision to which this sub-process belongs. */ tCollPtr collision() const { return theCollision; } /** * The pair of incoming partons. */ const PPair & incoming() const { return theIncoming; } /** * A reference to the vector of intermediate partons. */ const ParticleVector & intermediates() const { return theIntermediates; } /** * A reference to the vector of outgoing particles. */ const ParticleVector & outgoing() const { return theOutgoing; } /** * Set the vector of outgoing particles. */ template void setOutgoing(InputIterator, InputIterator); /** * Add a particle to the list of outgoing ones. If \a fixrelations * is true the mother daughter pointers will be set to/from the * incoming partons. */ void addOutgoing(tPPtr p, bool fixrelations = true); /** * Change the incoming parton */ void changeIncoming(tPPtr pnew, tPPtr pold); /** * Set the vector of intermediate particles. */ template void setIntermediates(InputIterator, InputIterator); /** * Add a particle to the list of intermediate ones. If \a fixrelations * is true the mother daughter pointers will be set to/from the * incoming partons. */ void addIntermediate(tPPtr p, bool fixrelations = true); /** * Remove a particle entry from this sub-process. */ void removeEntry(tPPtr p); /** * Return a clone of this sub process. */ virtual SubProPtr clone() const; /** * True if a perturbative cascade has been applied to this sub * process. */ bool decayed() const { return isDecayed; } /** * Set to true if a perturbative cascade has been applied to this * sub process. */ void decayed(bool x) { isDecayed = x; } /** * Return the head SubProcess, if this SubProcess * object belongs to a SubProcessGroup. Return NULL * if head of a SubProcessGroup or not member of * a SubProcessGroup at all. */ tSubProPtr head() const { return theHead; } /** * Set the head SubProcess */ void head(tSubProPtr newHead) { theHead = newHead; } /** * If this SubProcess belongs to a SubProcessGroup, * return its relative weight w.r.t. the head's * weight. */ double groupWeight() const { return theGroupWeight; } /** * If this SubProcess belongs to a SubProcessGroup, * set its relative weight w.r.t. the head's * weight. */ void groupWeight(double w) { theGroupWeight = w; } protected: /** * Rebind to cloned objects. When a SubProcess is cloned, a shallow * copy is done first, then all Particles etc, are * cloned, and finally this method is used to see to that the * pointers in the cloned SubProcess points to the cloned * Particles etc. */ virtual void rebind(const EventTranslationMap & trans); public: /** * Perform a LorentzTransformation of all particles in the sub * process. */ virtual void transform(const LorentzRotation &); /** * Return the value of the Mandelstam variable \f$\hat{s}\f$ in this * SubProcess. It is calculated using the incoming particles. */ Energy2 shat() const { return (incoming().first->momentum() + incoming().second->momentum()).m2(); } /** * Return the value of the Mandelstam variable \f$\hat{t}\f$ in this * SubProcess. It is calculated using the first incoming and first outgoing * particle. */ Energy2 that() const { return (incoming().first->momentum() - outgoing()[0]->momentum()).m2(); } /** * Return the value of the Mandelstam variable \f$\hat{u}\f$ in this * SubProcess. It is calculated using the first incoming and last outgoing * particle. */ Energy2 uhat() const { return (incoming().second->momentum() - outgoing()[0]->momentum()).m2(); } public: /** * Standard function for writing to a persistent stream. */ void persistentOutput(PersistentOStream &) const; /** * Standard function for reading from a persistent stream. */ void persistentInput(PersistentIStream &, int); /** * Standard Init function. @see Base::Init(). */ static void Init(); private: /** * A pointer to the MEBase object which generated this sub-process. */ tcEventBasePtr theHandler; /** * A pointer to the collision to which this sub-process belongs. */ tCollPtr theCollision; /** * The pair of incoming particles. */ PPair theIncoming; /** * The vector of intermediate particles, */ ParticleVector theIntermediates; /** * The vector of outgoing particles. */ ParticleVector theOutgoing; /** * True if a perturbative cascade has been applied to this sub process. */ bool isDecayed; /** * The head SubProcess, if this SubProcess * object belongs to a SubProcessGroup. NULL * if head of a SubProcessGroup or not member of * a SubProcessGroup at all. */ tSubProPtr theHead; /** * If this SubProcess belongs to a SubProcessGroup, * this gives its relative weight w.r.t. the head's * weight. */ double theGroupWeight; public: /** * Print out debugging information for this object on std::cerr. To * be called from within a debugger via the debug() function. */ virtual void debugme() const; /** * Put to ostream */ virtual void printMe(ostream&) const; private: /** * Default constructor */ SubProcess() : isDecayed(false), theGroupWeight(1.0) {} /** * Describe concrete class with persistent data. */ static ClassDescription initSubProcess; /** * The ClassTraits class must be a friend to be able to * use the private default constructor. */ friend struct ClassTraits; /** * Assignment is forbidden. */ SubProcess & operator=(const SubProcess &) = delete; }; /** Output a SubProcess to an ostream. */ ostream & operator<<(ostream &, const SubProcess &); /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base class of Collision. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of SubProcess. */ typedef EventRecordBase NthBase; }; /** This template specialization informs ThePEG about the name of * the SubProcess class and how to create it. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "ThePEG::SubProcess"; } /** Create a SubProcess object. */ static TPtr create() { return TPtr::Create(SubProcess()); } }; /** @endcond */ } #ifndef ThePEG_TEMPLATES_IN_CC_FILE #include "SubProcess.tcc" #endif #endif /* ThePEG_SubProcess_H */ diff --git a/EventRecord/SubProcess.tcc b/EventRecord/SubProcess.tcc --- a/EventRecord/SubProcess.tcc +++ b/EventRecord/SubProcess.tcc @@ -1,26 +1,26 @@ // -*- C++ -*- // // SubProcess.tcc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined templated member // functions of the SubProcess class. // namespace ThePEG { template void SubProcess::setIntermediates(InputIterator first, InputIterator last) { theIntermediates = ParticleVector(first, last); } template void SubProcess::setOutgoing(InputIterator first, InputIterator last) { theOutgoing = ParticleVector(first, last); } } diff --git a/EventRecord/SubProcessGroup.cc b/EventRecord/SubProcessGroup.cc --- a/EventRecord/SubProcessGroup.cc +++ b/EventRecord/SubProcessGroup.cc @@ -1,81 +1,81 @@ // -*- C++ -*- // // SubProcessGroup.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad -// Copyright (C) 2009-2017 Simon Platzer +// Copyright (C) 1999-2019 Leif Lonnblad +// Copyright (C) 2009-2019 Simon Platzer // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the SubProcessGroup class. // #include "SubProcessGroup.h" #include "ThePEG/EventRecord/Collision.h" #include "ThePEG/Config/algorithm.h" #include "ThePEG/EventRecord/ParticleTraits.h" #include "ThePEG/Utilities/Rebinder.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include using namespace ThePEG; SubProcessGroup:: SubProcessGroup(const PPair & newIncoming, tCollPtr newCollision, tcEventBasePtr newHandler) : SubProcess(newIncoming,newCollision,newHandler) {} SubProcessGroup::~SubProcessGroup() {} SubProPtr SubProcessGroup::clone() const { return ptr_new::ptr>(*this); } void SubProcessGroup::rebind(const EventTranslationMap & trans) { SubProcess::rebind(trans); for ( SubProcessVector::iterator sub = dependent().begin(); sub != dependent().end(); ++sub ) (*sub = trans.translate(*sub))->rebind(trans); } void SubProcessGroup::transform(const LorentzRotation & r) { SubProcess::transform(r); for ( SubProcessVector::iterator sub = dependent().begin(); sub != dependent().end(); ++sub ) (**sub).transform(r); } void SubProcessGroup::printMe(ostream& os) const { os << "head sub-process of this group with relative weight " << groupWeight() << ":\n"; SubProcess::printMe(os); os << "dependent sub-processes in this group:\n"; for ( SubProcessVector::const_iterator sub = dependent().begin(); sub != dependent().end(); ++sub ) { os << "performed by " << EventConfig::nameHandler((**sub).handler()) << " with relative weight " << (**sub).groupWeight() << "\n"; (**sub).printMe(os); } } void SubProcessGroup::persistentOutput(PersistentOStream & os) const { os << theDependent; } void SubProcessGroup::persistentInput(PersistentIStream & is, int) { is >> theDependent; } ClassDescription SubProcessGroup::initSubProcessGroup; void SubProcessGroup::Init() {} diff --git a/EventRecord/SubProcessGroup.h b/EventRecord/SubProcessGroup.h --- a/EventRecord/SubProcessGroup.h +++ b/EventRecord/SubProcessGroup.h @@ -1,165 +1,165 @@ // -*- C++ -*- // // SubProcessGroup.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad -// Copyright (C) 2009-2017 Simon Platzer +// Copyright (C) 1999-2019 Leif Lonnblad +// Copyright (C) 2009-2019 Simon Platzer // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_SubProcessGroup_H #define ThePEG_SubProcessGroup_H // This is the declaration of the SubProcessGroup class. #include "ThePEG/EventRecord/SubProcess.h" namespace ThePEG { /** * A SubProcessGroup object represents a group of SubProcess * objects in dependence of a head SubProcess object. * * @see StdXCombGroup * @see MEGroup */ class SubProcessGroup: public SubProcess { public: /** * Standard constructor. * @param newIncoming the two incoming partons. * @param newCollision the Collision to which this SubProcessGroup belongs. * @param newHandler the MEBase object which generated this SubProcessGroup. */ SubProcessGroup(const PPair & newIncoming, tCollPtr newCollision = tCollPtr(), tcEventBasePtr newHandler = tcEventBasePtr()); /** * Destructor. */ virtual ~SubProcessGroup(); /** * Return a clone of this sub process group. */ virtual SubProPtr clone() const; protected: /** * Rebind to cloned objects. When a SubProcessGroup is cloned, a shallow * copy is done first, then all Particles etc, are * cloned, and finally this method is used to see to that the * pointers in the cloned SubProcessGroup points to the cloned * Particles etc. */ virtual void rebind(const EventTranslationMap & trans); public: /** * Perform a LorentzTransformation of all particles in the sub * process. */ virtual void transform(const LorentzRotation &); /** * Return the dependent SubProcess objects */ const SubProcessVector& dependent() const { return theDependent; } /** * Access the dependent SubProcess objects */ SubProcessVector& dependent() { return theDependent; } /** * Add a dependent SubProcess */ void add(tSubProPtr sub) { dependent().push_back(sub); } public: /** * Standard function for writing to a persistent stream. */ void persistentOutput(PersistentOStream &) const; /** * Standard function for reading from a persistent stream. */ void persistentInput(PersistentIStream &, int); /** * Standard Init function. @see Base::Init(). */ static void Init(); private: /** * The dependent subprocesses */ SubProcessVector theDependent; public: /** * Put to ostream */ virtual void printMe(ostream&) const; private: /** * Describe concrete class with persistent data. */ static ClassDescription initSubProcessGroup; /** * Private default constructor must only be used by the * PersistentIStream class via the ClassTraits class . */ SubProcessGroup() : SubProcess() {} /** * The ClassTraits class must be a friend to be able to * use the private default constructor. */ friend struct ClassTraits; /** * Assignment is forbidden. */ SubProcessGroup & operator=(const SubProcessGroup &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base class of Collision. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of SubProcessGroup. */ typedef EventRecordBase NthBase; }; /** This template specialization informs ThePEG about the name of * the SubProcessGroup class and how to create it. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "ThePEG::SubProcessGroup"; } /** Create a SubProcessGroup object. */ static TPtr create() { return TPtr::Create(SubProcessGroup()); } }; /** @endcond */ } #endif /* ThePEG_SubProcessGroup_H */ diff --git a/EventRecord/TmpTransform.h b/EventRecord/TmpTransform.h --- a/EventRecord/TmpTransform.h +++ b/EventRecord/TmpTransform.h @@ -1,89 +1,89 @@ // -*- C++ -*- // // TmpTransform.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_TmpTransform_H #define THEPEG_TmpTransform_H // // This is the declaration of the TmpTransform class. // #include "ThePEG/Config/ThePEG.h" namespace ThePEG { /** * This is a wrapper class to be used to temporarily make a Lorentz * transform of an object. When created a pointer to an object and a * LorentzRotation is provided, and the objects transform(const * LorentzRotation &) function is called. When the destructed the * inverse tansformation is performed. In this way one can make sure * that the inverse transformation is performed even if the function * where the TmpTransform is created returns or throws an exception. */ template class TmpTransform { public: /** * The contructor will call the transform(const LorentzRotation &) * of an object pointed to by \a p with \a r as argument. */ TmpTransform(Ptr p, const LorentzRotation & r) : ptr(p), rot(r) { ptr->transform(rot); } /** * The destructor performs the inverse of the transformation done in * the constructor. */ ~TmpTransform() { rot.invert(); ptr->transform(rot); } private: /** * A pointer to the object being transformed. */ Ptr ptr; /** * The rotation performed in the constructor. */ LorentzRotation rot; private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ TmpTransform & operator=(const TmpTransform &) = delete; /** * The default constructor is private and must never be called. * In fact, it should not even be implemented. */ TmpTransform(); /** * The copy constructor is private and must never be called. * In fact, it should not even be implemented. */ TmpTransform(const TmpTransform &); }; } #endif /* THEPEG_TmpTransform_H */ diff --git a/Handlers/ACDCSampler.cc b/Handlers/ACDCSampler.cc --- a/Handlers/ACDCSampler.cc +++ b/Handlers/ACDCSampler.cc @@ -1,185 +1,185 @@ // -*- C++ -*- // // ACDCSampler.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the ACDCSampler class. // #include "ThePEG/Handlers/ACDCSampler.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Utilities/Throw.h" using namespace ThePEG; ACDCSampler::~ACDCSampler() {} IBPtr ACDCSampler::clone() const { return new_ptr(*this); } IBPtr ACDCSampler::fullclone() const { return new_ptr(*this); } void ACDCSampler::initialize() { theSampler.clear(); theSampler.setRnd(0); theSampler.eps(theEps); theSampler.margin(theMargin); theSampler.nTry(2); theSampler.maxTry(eventHandler()->maxLoop()); bool nozero = false; for ( int i = 0, N = eventHandler()->nBins(); i < N; ++i ) { nozero |= theSampler.addFunction(eventHandler()->nDim(i), eventHandler()); } if( eventHandler()->nBins() ==0 ) Throw() << "The event handler '" << eventHandler()->name() << "' cannot be initialized because there are no selected subprocesses" << Exception::maybeabort; if ( !nozero ) Throw() << "The event handler '" << eventHandler()->name() << "' cannot be initialized because the cross-section for the selected " << "sub-processes was zero." << Exception::maybeabort; theSampler.clear(); } double ACDCSampler::generate() { if ( !theSampler.generate() ) throw EventLoopException() << "The maximum number of attempts (" << eventHandler()->maxLoop() << ") to generate the kinematics in the ACDCSampler was exceeded. For " << "the event handler '" << eventHandler()->name() << "'." << Exception::eventerror; lastPoint() = theSampler.lastPoint(); return 1.0; } void ACDCSampler::rejectLast() { theSampler.reject(); } CrossSection ACDCSampler::integratedXSec() const { return theSampler.integral()*nanobarn; } CrossSection ACDCSampler::integratedXSecErr() const { return theSampler.integralErr()*nanobarn; } int ACDCSampler::lastBin() const { return theSampler.last() - 1; } double ACDCSampler::sumWeights() const { return theSampler.n(); } double ACDCSampler::sumWeights2() const { return theSampler.n(); } void ACDCSampler::dofinish() { if ( theSampler.n() <= 0 && eventHandler() && eventHandler()->statLevel() > 1 ) { generator()->log() << "No events generated by the ACDC sampler '" << name() << "'" << endl; } else if ( eventHandler() && eventHandler()->statLevel() > 1 ) generator()->log() << "Statistics for the ACDC sampler '" << name() << "':" << endl << "Number of samplers: " << setw(14) << theSampler.size() << endl << "Number of bins: " << setw(14) << theSampler.nBins() << endl << "Depth of bins: " << setw(14) << theSampler.depth() << endl << "efficiency: " << setw(14) << theSampler.efficiency() << endl << "Total integrated xsec: " << setw(14) << theSampler.integral() << endl << " error in xsec: " << setw(14) << theSampler.integralErr() << endl; if ( theSampler.compensating() ) generator()->logWarning( ACDCStillCompensating() << "The run was ended while the ACDCSampler '" << name() << "' was still trying to compensate for weights larger than 1. " << "The cross section estimates may therefore be statistically " << "inaccurate. At least " << theSampler.compleft() << " additional " << "samplings are needed to get out of compensation mode. " << "This may be avoided if you increase the value of the " << "Ntry parameter determining how many points are presampled before " << "the run." << Exception::warning); SamplerBase::dofinish(); } void ACDCSampler::doinitrun() { SamplerBase::doinitrun(); eventHandler()->initrun(); theSampler.setRnd(0); theSampler.eps(theEps); theSampler.margin(theMargin); theSampler.nTry(theNTry); theSampler.maxTry(eventHandler()->maxLoop()); bool nozero = false; for ( int i = 0, N = eventHandler()->nBins(); i < N; ++i ) if ( theSampler.addFunction(eventHandler()->nDim(i), eventHandler()) ) nozero = true; if ( !nozero ) throw EventInitNoXSec() << "The event handler '" << eventHandler()->name() << "' cannot be initialized because the cross-section for the selected " << "sub-processes was zero." << Exception::maybeabort; } void ACDCSampler::persistentOutput(PersistentOStream & os) const { os << theEps << theMargin << theNTry; theSampler.output(os); } void ACDCSampler::persistentInput(PersistentIStream & is, int) { is >> theEps >> theMargin >> theNTry; theSampler.input(is); if ( generator() ) theSampler.setRnd(0); } ClassDescription ACDCSampler::initACDCSampler; // Definition of the static class description member. void ACDCSampler::Init() { static ClassDocumentation documentation ("This class inherits from ThePEG::SampleBase and implements " "the Auto Compensating Divide-and-Conquer phase space generator, " "ACDCGenerator::ACDCGen."); static Parameter interfaceMargin ("Margin", "The factor controlling the loss of efficiency when compensating " "for a previously underestimated phase space point. If close to one, " "the efficiency is increased at the expence of increased number " "of cells.", &ACDCSampler::theMargin, 1.1, 1.0, 2.0, true, false, true); static Parameter interfaceEps ("Epsilon", "The smallest possible cell division allowed.", &ACDCSampler::theEps, 100.0*Constants::epsilon, Constants::epsilon, 1.0e-6, true, false, true); static Parameter interfaceNTry ("Ntry", "The number of phase space points tried in the initialization.", &ACDCSampler::theNTry, 1000, 2, 1000000, true, false, true); interfaceNTry.rank(10); interfaceEps.rank(9); } diff --git a/Handlers/ACDCSampler.h b/Handlers/ACDCSampler.h --- a/Handlers/ACDCSampler.h +++ b/Handlers/ACDCSampler.h @@ -1,374 +1,374 @@ // -*- C++ -*- // // ACDCSampler.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_ACDCSampler_H #define ThePEG_ACDCSampler_H // This is the declaration of the ACDCSampler class. #include "ThePEG/Handlers/SamplerBase.h" #include "ThePEG/ACDC/ACDCGen.h" #include "ThePEG/Handlers/StandardEventHandler.h" #include "ThePEG/Repository/RandomGenerator.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Utilities/SimplePhaseSpace.xh" // #include "ACDCSampler.fh" // #include "ACDCSampler.xh" namespace ThePEG { /** * This class inherits from SampleBase and implements * the Auto Compensating Divide-and-Conquer phase space generator, * ACDCGen. * * @see \ref ACDCSamplerInterfaces "The interfaces" * defined for ACDCSampler. * @see ACDCGen */ class ACDCSampler: public SamplerBase { public: /** Typedef the underlying ACDCGen class. */ typedef ACDCGenerator::ACDCGen SamplerType; /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ ACDCSampler() : theEps(100*Constants::epsilon), theMargin(1.1), theNTry(1000) {} /** * The copy constructor. We don't copy theSampler. */ ACDCSampler(const ACDCSampler & x) : SamplerBase(x), theSampler(), theEps(x.theEps), theMargin(x.theMargin), theNTry(x.theNTry) {} /** * The destructor. */ virtual ~ACDCSampler(); //@} public: /** @name Virtual functions needed for SamplerBase */ //@{ /** * Initialize the the sampler, possibly doing presampling of the * phase space. */ virtual void initialize(); /** * Generarate a new phase space point and return a weight associated * with it. This weight should preferably be 1. */ virtual double generate(); /** * ACDCSampler is able to sample several different functions * separately. This function returns the last chosen * function. */ virtual int lastBin() const; /** * Reject the last chosen phase space point. */ virtual void rejectLast(); /** * Return the total integrated cross section determined from the * Monte Carlo sampling so far. */ virtual CrossSection integratedXSec() const; /** * Return the error on the total integrated cross section determined * from the Monte Carlo sampling so far. */ virtual CrossSection integratedXSecErr() const; /** * Return the sum of the weights returned by generate() so far (of * the events that were not rejeted). */ virtual double sumWeights() const; /** * Return the sum of the weights squared returned by generate() so far (of * the events that were not rejeted). */ virtual double sumWeights2() const; //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} protected: /** @name Standard Interfaced functions. */ //@{ /** * 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(); //@} private: /** * The actual sampler object. */ SamplerType theSampler; /** * The smallest possible division allowed. */ double theEps; /** * The factor controlling the loss of efficiency when compensating. */ double theMargin; /** * The number of points to use to find initial average. */ int theNTry; protected: /** @cond EXCEPTIONCLASSES */ /** Exception class used by ACDCSampler if the undelying ACDCGen was still in a compensating mode when the run was finished */ struct ACDCStillCompensating: public Exception {}; /** Exception class used by ACDCSampler if a StandardEventHandler was not able to produce a non-zero cross section. */ struct EventInitNoXSec: public InitException {}; /** Exception class used if ACDCSampler was not able to produce a phase space point within the maximum allowed number of attempts. */ struct EventLoopException: public Exception {}; /** @endcond */ private: /** * Describe a concrete class with persistent data. */ static ClassDescription initACDCSampler; /** * Private and non-existent assignment operator. */ ACDCSampler & operator=(const ACDCSampler &) = delete; }; } namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** * The following template specialization informs ThePEG about the * base class of ACDCSampler. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of ACDCSampler. */ typedef SamplerBase 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::ACDCSampler"; } /** Return the name of the shared library to be loaded to get * access to this class and every other class it uses * (except the base class). */ static string library() { return "ACDCSampler.so"; } }; /** @endcond */ } namespace ACDCGenerator { /** @cond TRAITSPECIALIZATIONS */ /** Specialized Traits class to define the interface to the * StandardEventHandler object to be sampled by ACDCGen. */ template <> struct ACDCFncTraits: public ACDCTraitsType { /** Convenient typdef. */ typedef ThePEG::tStdEHPtr tStdEHPtr; /** * Call a function to be sampled by ACDCGen. * @return (*f)(x). */ static inline double value(const tStdEHPtr & eh, const DVector & x) { using namespace ThePEG::Units; try { return eh->dSigDR(x)/nanobarn; } catch ( ThePEG::ImpossibleKinematics & v ) { breakThePEG(); } catch ( std::exception & e ) { breakThePEG(); } catch ( ... ) { breakThePEG(); } return 0.0; } }; /** Specialized Traits class to inform ACDCGen how to use the static UseRandom class. */ template <> struct ACDCRandomTraits: public ACDCTraitsType { /** Convenient typedef. */ typedef ThePEG::UseRandom UseRandom; /** * Return a flat random number in the interval ]0,1[. */ static inline double rnd(UseRandom *) { return UseRandom::rnd(); } /** * Return a flat random number in the interval ]\a xl,\a xu[. */ static inline double rnd(UseRandom * r, double xl, double xu) { return xl + (xu - xl)*rnd(r); } /** * Generate a set of random numbers. * @param r the random generator. * @param l an input iterator giving the lower limit of the interval * of the first requested random number. * @param lend an input iterator marking the end of the range of * requested random numbers. * @param u an input iterator giving the upper limit of the interval * of the first requested random number. * @param res the ouput iterator used to output the random numbers. */ template static inline void rnd(UseRandom * r, InputIterator l, InputIterator lend, InputIterator u, OutputIterator res) { for ( ; l != lend; ++l ) *res++ = *l + (*u++ - *l)*rnd(r); } /** * Generate \a D random numbers. The numbers are put into the * OutputIterator \a res. */ template static inline void rnd(UseRandom * r, int D, OutputIterator res) { for ( int d = 0; d < D; ++d ) *res++ = rnd(r); } /** * Return true with probability \a x. */ static inline bool rndBool(UseRandom, double x) { return UseRandom::rndbool(x); } /** * Return true with probability \a x(\a x + \a y). */ static inline bool rndBool(UseRandom *, double x, double y) { return UseRandom::rndbool(x, y); } /** * Return a random integer in the interval [0,\a x[. */ static inline long rndInt(UseRandom *, long x) { return UseRandom::irnd(x); } }; /** @endcond */ } #endif /* ThePEG_ACDCSampler_H */ diff --git a/Handlers/AnalysisHandler.cc b/Handlers/AnalysisHandler.cc --- a/Handlers/AnalysisHandler.cc +++ b/Handlers/AnalysisHandler.cc @@ -1,120 +1,120 @@ // -*- C++ -*- // // AnalysisHandler.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the AnalysisHandler class. // #include "AnalysisHandler.h" #include "ThePEG/EventRecord/Event.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/UtilityBase.h" using namespace ThePEG; bool AnalysisHandler::checkHistogramFactory(bool warn) const { if ( generator()->histogramFactory() ) return true; if ( warn ) generator()->logWarning( NoHistFactory() << "No histogram factory was assigned to the " << "EventGenerator, hence no histograms will be produced by " << name() << "." << Exception::warning); return false; } FactoryBase & AnalysisHandler::histogramFactory() { return *(generator()->histogramFactory()); } const FactoryBase & AnalysisHandler::histogramFactory() const { return *(generator()->histogramFactory()); } void AnalysisHandler::normalize(tH1DPtr h, CrossSection unit) const { histogramFactory().normalizeToXSec(h, unit); } void AnalysisHandler::unitNormalize(tH1DPtr h) const { histogramFactory().normalizeToUnity(h); } IBPtr AnalysisHandler::clone() const { return new_ptr(*this); } IBPtr AnalysisHandler::fullclone() const { return new_ptr(*this); } void AnalysisHandler::analyze(tEventPtr event, long, int loop, int state) { if ( loop > 0 || state != 0 || !event ) return; tcEventPtr cevent = event; LorentzRotation r = transform(cevent); tPVector particles; event->selectFinalState(back_inserter(particles)); Utilities::transform(particles, r); analyze(particles, event->weight()); for ( int i = 0, N = theSlaves.size(); i < N; ++i ) theSlaves[i]->analyze(particles, event->weight()); r.invert(); Utilities::transform(particles, r); } LorentzRotation AnalysisHandler::transform(tEventPtr) const { return LorentzRotation(); } LorentzRotation AnalysisHandler::transform(tcEventPtr) const { return LorentzRotation(); } void AnalysisHandler::analyze(const tPVector & particles) { for ( int i = 0, N = particles.size(); i < N; ++i ) analyze(particles[i]); } void AnalysisHandler::analyze(const tPVector & particles, double weight) { analyze(particles); for ( int i = 0, N = particles.size(); i < N; ++i ) analyze(particles[i], weight); } void AnalysisHandler::analyze(tPPtr) {} void AnalysisHandler::analyze(tPPtr, double) {} void AnalysisHandler::persistentOutput(PersistentOStream & os) const { os << theSlaves; } void AnalysisHandler::persistentInput(PersistentIStream & is, int) { is >> theSlaves; } ClassDescription AnalysisHandler::initAnalysisHandler; void AnalysisHandler::Init() { static ClassDocumentation documentation ("The ThePEG::AnalysisHandler class is the base class of all " "analysis handlers."); static RefVector interfaceSlaves ("Slaves", "ThePEG::AnalysisHandler objects to be called for the same extracted " "particles as this one.", &AnalysisHandler::theSlaves, 0, true, false, true, false); interfaceSlaves.rank(10); } diff --git a/Handlers/AnalysisHandler.h b/Handlers/AnalysisHandler.h --- a/Handlers/AnalysisHandler.h +++ b/Handlers/AnalysisHandler.h @@ -1,270 +1,270 @@ // -*- C++ -*- // // AnalysisHandler.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_AnalysisHandler_H #define ThePEG_AnalysisHandler_H // This is the declaration of the AnalysisHandler class. #include "HandlerBase.h" #include "AnalysisHandler.fh" #include "ThePEG/Vectors/LorentzRotation.h" #include "ThePEG/Analysis/FactoryBase.h" #include "ThePEG/EventRecord/Event.h" #include namespace ThePEG { /** * The AnalysisHandler is the base class of all analysis objects which * may be handled by the FullEventGenerator. The main function is the * virtual analyze() method which which is called for * each analysis handler after each event. The method may be called * several times for each event - this may be checked by the analysis * handler by looking at the ieve, loop and * state arguments to the analyze method. * * Initialization of histograms etc. should be made in the * doinitrun() function, while writing out of histograms * and analysis results should be performed in the * dofinish() function. * * @see \ref AnalysisHandlerInterfaces "The interfaces" * defined for AnalysisHandler. * @see FullEventGenerator * @see Event */ class AnalysisHandler: public HandlerBase { public: /** * Convenient typedef for pointer to AIDA::IHistogram1D. */ typedef FactoryBase::tH1DPtr tH1DPtr; /** * Convenient typedef for pointer to AIDA::IHistogram1D. */ typedef FactoryBase::tcH1DPtr tcH1DPtr; /** * Convenient typedef for pointer to AIDA::IHistogram1D. */ typedef FactoryBase::tH2DPtr tH2DPtr; /** * Convenient typedef for pointer to AIDA::IHistogram1D. */ typedef FactoryBase::tcH2DPtr tcH2DPtr; public: /** @name Virtual functions required by the AnalysisHandler class. */ //@{ /** * Analyze a given Event. Note that a fully generated event may be * presented several times, if it has been manipulated in * between. The default version of this function will extract all * final state particles, temporarily boost them according to the * transform(tEventPtr) function and call analyze(tPVector) of this * analysis object and those of all associated analysis objects. The * default version will not, however, do anything on events which * have not been fully generated, or have been manipulated in any * way. * @param event pointer to the Event to be analyzed. * @param ieve the event number. * @param loop the number of times this event has been presented. * If negative the event is now fully generated. * @param state a number different from zero if the * event has been manipulated in some way since it was last * presented. */ virtual void analyze(tEventPtr event, long ieve, int loop, int state); /** * Transform the event to the desired Lorentz frame and return the * corresponding LorentzRotation. * @param event a pointer to the Event to be transformed. * @return the LorentzRotation used in the transformation. * @deprecated Use transform(tcEventPtr) instead. This method is no * longer used automatically. */ virtual LorentzRotation transform(tEventPtr event) const; /** * Return a LorentzTransform which would put the event in the * desired Lorentz frame. * @param event a pointer to the Event to be considered. * @return the LorentzRotation used in the transformation. */ virtual LorentzRotation transform(tcEventPtr event) const; /** * Analyze the given vector of particles. The default version calls * analyze(tPPtr) for each of the particles. * @param particles the vector of pointers to particles to be analyzed * @deprecated Use analyze(const tPVector &, double) instead. */ virtual void analyze(const tPVector & particles); /** * Analyze the given vector of particles. The default version calls * analyze(tPPtr) for each of the particles. * @param particles the vector of pointers to particles to be analyzed * @param weight the weight of the current event. */ virtual void analyze(const tPVector & particles, double weight); /** * Analyze the given particle. * @param particle pointer to the particle to be analyzed. * @deprecated us analyze(tPPtr, double) instead. */ virtual void analyze(tPPtr particle); /** * Analyze the given particle. * @param particle pointer to the particle to be analyzed. * @param weight the weight of the current event. */ virtual void analyze(tPPtr particle, double weight); //@} /** @name Functions to access histograms. */ //@{ /** * Check if the associated EventGenerator has been assigned a * histogram factory. If \a warn is true also emit a warning saying * that no histograms will be generated. */ bool checkHistogramFactory(bool warn = false) const; /** * Access the HistogramFactory from the EventGenerator. */ FactoryBase & histogramFactory(); /** * Access the HistogramFactory from the EventGenerator. */ const FactoryBase & histogramFactory() const; /** * Access the underlying AIDA::IHistogramFactory in the * HistogramFactory from the EventGenerator. */ AIDA::IHistogramFactory & iHistogramFactory() const { return histogramFactory().histogramFactory(); } /** * Normalize the histogran \a h using the collected statistics from * the EventGenerator. If the histogram has been filled with the * Event::weight() as weight a plotted function will correspond to a * proper cross section distribution in units of \a unit. This only * works for evenly binned histograms. If not evenly binned, nothing * will be done. */ void normalize(tH1DPtr h, CrossSection unit = picobarn) const; /** * Normalize the histogran \a h to unit integral. */ void unitNormalize(tH1DPtr h) const; //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interface. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * A list of slave analysis objects which are called for the same * extracted particles and in the same Lorentz frame as this one. */ AnalysisVector theSlaves; //@} public: /** Exception class used if no histogram factory was found. */ class NoHistFactory: public InitException {}; private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initAnalysisHandler; }; /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of AnalysisHandler. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of AnalysisHandler. */ typedef HandlerBase NthBase; }; /** This template specialization informs ThePEG about the name of * the AnalysisHandler 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::AnalysisHandler"; } }; /** @endcond */ } #endif /* ThePEG_AnalysisHandler_H */ diff --git a/Handlers/CascadeHandler.cc b/Handlers/CascadeHandler.cc --- a/Handlers/CascadeHandler.cc +++ b/Handlers/CascadeHandler.cc @@ -1,74 +1,74 @@ // -*- C++ -*- // // CascadeHandler.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the CascadeHandler class. // #include "CascadeHandler.h" #include "ThePEG/Handlers/EventHandler.h" #include "ThePEG/Handlers/Hint.h" #include "ThePEG/Handlers/XComb.h" #include "ThePEG/PDF/PartonExtractor.h" #include "ThePEG/Interface/ClassDocumentation.h" using namespace ThePEG; CascadeHandler::~CascadeHandler() {} bool CascadeHandler::theDidRunCascade=false; void CascadeHandler:: handle(EventHandler & eh, const tPVector & tagged, const Hint & hint) { static tPVector notags; theLastXComb = eh.lastXCombPtr(); theHint = &hint; // if ( hint.tagged() ) theTagged = &tagged; // else // theTagged = ¬ags; // if ( !lastXComb().empty() ) thePDFs = make_pair(pdf(lastPartons().first), pdf(lastPartons().second)); cascade(); } void CascadeHandler::resetPDFs(const pair & pdfpair) { thePDFs.first = PDF(pdfpair.first, thePDFs.first.particle()); thePDFs.second = PDF(pdfpair.second, thePDFs.second.particle()); } void CascadeHandler::resetPDFs(const pair & pdfpair, PBPair ppair) { thePDFs.first = PDF(pdfpair.first, ppair.first->particle()); thePDFs.second = PDF(pdfpair.second, ppair.second->particle()); } double CascadeHandler::reweightCKKW(int, int) { return 1.0; } void CascadeHandler::setXComb(tXCombPtr xc) { theLastXComb = xc; } AbstractNoPIOClassDescription CascadeHandler::initCascadeHandler; void CascadeHandler::Init() { static ClassDocumentation documentation ("This is the base class to be used by all models of partonic cascades."); } diff --git a/Handlers/CascadeHandler.h b/Handlers/CascadeHandler.h --- a/Handlers/CascadeHandler.h +++ b/Handlers/CascadeHandler.h @@ -1,227 +1,227 @@ // -*- C++ -*- // // CascadeHandler.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_CascadeHandler_H #define ThePEG_CascadeHandler_H // This is the declaration of the CascadeHandler class. #include "StepHandler.h" #include "ThePEG/Handlers/LastXCombInfo.h" #include "ThePEG/PDF/PDF.h" namespace ThePEG { /** * The CascadeHandler is the base class of all handlers implementing * perturbative partonic cascade models. It is derived from the more * general StepHandler class, and implements the handle() function to * do some standard initialization before calling the main cascade() * function. * * @see \ref CascadeHandlerInterfaces "The interfaces" * defined for CascadeHandler. * @see StepHandler * @see EventHandler * @see SubProcessHandler */ class CascadeHandler: public StepHandler, public LastXCombInfo<> { public: /** @name Standard constructors and destructors. */ //@{ /** * The destructor. */ virtual ~CascadeHandler(); //@} public: /** @name Virtual functions required by the StepHandler class. */ //@{ /** * The main function called by the EventHandler class to * perform a step. * @param eh the EventHandler in charge of the Event generation. * @param tagged if not empty these are the only particles which should * be considered by the StepHandler. * @param hint a Hint object with possible information from previously * performed steps. * @throws Veto if the StepHandler requires the current step to be * discarded. * @throws Stop if the generation of the current Event should be stopped * after this call. * @throws Exception if something goes wrong. */ virtual void handle(EventHandler & eh, const tPVector & tagged, const Hint & hint); //@} /** * The main function to be overwritten by sub-classes. It is called * by handle() after storing some information which is then * available through simple access functions. */ virtual void cascade() = 0; /** * The CascadeHandler can be used inside the process generation to * do so-called CKKW reweighting of the hard sub-process. In this * case this function is called after information about the * sub-process is made available through the LastXCombInfo base * class. Only the function belonging to the primary CascadeHandler * for the event to be generated is called. Sub-classes may * implement it to give a suitable weight in return. The * CascadeHandler may store information about the generated * sub-process to be used in the subsequent cascade. It is however * not guaranteed that the reweightCKKW() will have been called for * the subprocess handed to the handle() function. This default * implementation of the function simply return one. The current * sub-process is mixed together with other processes with a * multiplicity of outgoing particles between \a minMult and \a * maxMult. */ virtual double reweightCKKW(int minMult, int maxMult); public: /** @name Access information stored by the handle() function. */ //@{ /** * Return the vector of tagged particles which should be * showered. It the vector is empty, the patons from the current * sub-process is supposed to be showered. */ const tPVector & tagged() const { return *theTagged; } /** * Return the int provided in the current call to handle(). */ const Hint & hint() const { return *theHint; } /** * Return references to the PDF used by the first incoming particle. */ const PDF & firstPDF() const { return pdfs().first; } /** * Return references to the PDF used by the first incoming particle. */ const PDF & secondPDF() const { return pdfs().second; } /** * Return references to the currently used PDF's. */ const pair & pdfs() const { return thePDFs; } /** * Set alternative PDFBase objects to be used for cascade. */ void resetPDFs(const pair & pdfpair); /** * Set alternative PDFBase objects to be used for cascade. */ void resetPDFs(const pair & pdfpair, PBPair ppair); /** * Set the XComb object with information about the sub-process * generation. */ void setXComb(tXCombPtr xc); /** * Return true, if this cascade handler will perform reshuffling from hard * process masses. */ virtual bool isReshuffling() const { return false; } /** * For multiple cascade calls, this flag tells * if cascade was called before. */ bool didRunCascade() const {return theDidRunCascade;} /** * Set the flag to inform if prior cascades had been called. */ static void setDidRunCascade(bool c){theDidRunCascade=c;} //@} public: /** * Standard Init function used to initialize the interface. */ static void Init(); private: /** * Store the tagged argument given to handle(). */ const tPVector * theTagged; /** * Store the Hint arguments given to handle(). */ const Hint * theHint; /** * The pdfs used to extract the incoming partons. */ pair thePDFs; /** * If there are multiple cascade calls, this flag tells * if cascade was called before. */ static bool theDidRunCascade; private: /** * The static object used to initialize the description of this class. * Indicates that this is an abstract class without persistent data. */ static AbstractNoPIOClassDescription initCascadeHandler; /** * Private and non-existent assignment operator. */ CascadeHandler & operator=(const CascadeHandler &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of CascadeHandler. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of CascadeHandler. */ typedef StepHandler NthBase; }; /** This template specialization informs ThePEG about the name of * the CascadeHandler 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::CascadeHandler"; } }; /** @endcond */ } #endif /* ThePEG_CascadeHandler_H */ diff --git a/Handlers/ClusterCollapser.cc b/Handlers/ClusterCollapser.cc --- a/Handlers/ClusterCollapser.cc +++ b/Handlers/ClusterCollapser.cc @@ -1,614 +1,614 @@ // -*- C++ -*- // // ClusterCollapser.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the ClusterCollapser class. // #include "ClusterCollapser.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/EventRecord/Step.h" #include "ThePEG/Utilities/UtilityBase.h" #include "ThePEG/Utilities/SimplePhaseSpace.h" #include "ThePEG/PDT/StandardMatchers.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Handlers/EventHandler.h" #include "ThePEG/Utilities/EnumIO.h" #include "ThePEG/Utilities/Throw.h" #ifdef ThePEG_TEMPLATES_IN_CC_FILE // #include "ClusterCollapser.tcc" #endif #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG; ClusterCollapser::~ClusterCollapser() {} IBPtr ClusterCollapser::clone() const { return new_ptr(*this); } IBPtr ClusterCollapser::fullclone() const { return new_ptr(*this); } void ClusterCollapser:: handle(EventHandler &, const tPVector & tagged, const Hint &) { collapse(tagged, newStep()); } vector ClusterCollapser:: collapse(tPVector tagged, tStepPtr newstep) { vector newTagged; SingletMap clusters = getSinglets(tagged); // Go through all clusters below the cut. while ( !clusters.empty() && clusters.begin()->first < cut() ) { SingletMap::iterator clit = clusters.begin(); ColourSinglet & cl = clit->second; // If a cluster contains too many junctions, split them into // several singlets. while ( cl.nPieces() > 3 ) insert(clusters, cl.splitInternal()); // If a cluster contains a junktion and a diquark, split the // diquark and make two simple strings. while ( diQuarkJunction(cl) ) insert(clusters, splitDiQuarkJunction(cl, newstep)); // First try to collapse into two particles. int ntry = nTry2(); while ( ntry > 0 ) { if ( collapse2(newstep, cl) ) break; --ntry; } // If that didn't work collapse into one particle and shuffle some // energy to or from the other tagged particles. if ( ntry == 0 ) { // If this was a di-diquark cluster, split it into two. if ( diDiQuark(cl) ) { insert(clusters, splitDiDiQuark(cl, newstep)); updateTagged(tagged); } collapse(newstep, cl, tagged); } updateTagged(tagged); // Remove the collapsed cluster. clusters.erase(clit); // Recalculate masses of the remaining clusters, insert them in a // temporary map and swap this map for the old map. multimap newClusters; while ( !clusters.empty() ) { ColourSinglet & cl = clusters.begin()->second; for ( int i = 0, N = cl.partons().size(); i < N; ++i ) cl.partons()[i] = cl.partons()[i]->final(); insert(newClusters, cl); clusters.erase(clusters.begin()); } clusters.swap(newClusters); } // Return the left-over clusters in a vector. newTagged.resize(clusters.size()); for ( int is = 0, NS = newTagged.size(); is < NS; ++is ) { newTagged[is].swap(clusters.begin()->second); clusters.erase(clusters.begin()); } return newTagged; } void ClusterCollapser::updateTagged(tPVector & tagged) const { tPVector::iterator it = tagged.begin(); set children; while ( it != tagged.end() ) { *it = (**it).final(); if ( (**it).decayed() ) { children.insert((**it).children().begin(), (**it).children().end()); it = tagged.erase(it); } else ++it; } tagged.insert(tagged.end(), children.begin(), children.end()); } Energy ClusterCollapser::mass(const ColourSinglet & cl) { LorentzMomentum sump; Energy summ = ZERO; for ( int i = 0, N = cl.partons().size(); i < N; ++i ) { summ += cl.parton(i)->data().constituentMass(); sump += cl.parton(i)->momentum(); } return sump.m() - summ; } void ClusterCollapser::insert(SingletMap & mmap, const ColourSinglet & cl) { mmap.insert(make_pair(mass(cl), cl)); } bool ClusterCollapser::diDiQuark(const ColourSinglet & cs) { return ( cs.nPieces() == 1 && DiquarkMatcher::Check(cs.piece(1).front()->data()) && DiquarkMatcher::Check(cs.piece(1).back()->data()) ); } ColourSinglet ClusterCollapser:: splitDiDiQuark(ColourSinglet & cs, tStepPtr newStep) const { ColourSinglet ret; // Split the first diquark tcPPtr diq = cs.piece(1).front(); PPair qq1; qq1.first = getParticle(diq->id()/1000); qq1.second = getParticle((diq->id()/100)%10); if ( qq1.first->mass() + qq1.second->mass() >= diq->mass() ) { // If the sum of the quarks masses is larger than the diuark mass, // set the new quark masses to zero. qq1.first->set5Momentum(Lorentz5Momentum()); qq1.second->set5Momentum(Lorentz5Momentum()); } // Distribut the quarks evenly in the cms of the diquark and add // them as children of the diquark to the new step. SimplePhaseSpace::CMS(sqr(diq->mass()), qq1.first, qq1.second); qq1.first->boost(diq->momentum().boostVector()); qq1.second->boost(diq->momentum().boostVector()); newStep->addDecayProduct(diq, qq1.first); newStep->addDecayProduct(diq, qq1.second); // Split the second diquark diq = cs.piece(1).back(); PPair qq2; qq2.first = getParticle(diq->id()/1000); qq2.second = getParticle((diq->id()/100)%10); if ( qq2.first->mass() + qq2.second->mass() >= diq->mass() ) { // If the sum of the quarks masses is larger than the diuark mass, // set the new quark masses to zero. qq2.first->set5Momentum(Lorentz5Momentum()); qq2.second->set5Momentum(Lorentz5Momentum()); } // Distribut the quarks evenly in the cms of the diquark and add // them as children of the diquark to the new step. SimplePhaseSpace::CMS(sqr(diq->mass()), qq2.first, qq2.second); qq2.first->boost(diq->momentum().boostVector()); qq2.second->boost(diq->momentum().boostVector()); newStep->addDecayProduct(diq, qq2.first); newStep->addDecayProduct(diq, qq2.second); if ( rndbool() ) swap(qq1.first, qq1.second); return ret = cs.splitDiDiQuark(qq1, qq2); } bool ClusterCollapser::diQuarkJunction(const ColourSinglet & cs) { if ( cs.nPieces() < 3 ) return false; for ( int i = 1, N = cs.nPieces(); i <= N; ++i ) if ( DiquarkMatcher::Check(cs.piece(i).front()->data()) || DiquarkMatcher::Check(cs.piece(i).back()->data()) ) return true; return false; } ColourSinglet ClusterCollapser:: splitDiQuarkJunction(ColourSinglet & cs, tStepPtr newStep) const { ColourSinglet ret; // Find the diquarks in the singlet and pick one randomly. vector diqs; for ( ColourSinglet::Index i = 1, N = cs.nPieces(); i <= N; ++i ) { if ( DiquarkMatcher::Check(cs.piece(i).front()->data()) ) diqs.push_back(-i); if ( DiquarkMatcher::Check(cs.piece(i).back()->data()) ) diqs.push_back(i); } if ( diqs.empty() ) return ret; ColourSinglet::Index seli = diqs[UseRandom::irnd(diqs.size())]; tcPPtr diq = seli > 0? cs.piece(seli).back(): cs.piece(seli).front(); // Create the to quarks PPair qq; qq.first = getParticle(diq->id()/1000); qq.second = getParticle((diq->id()/100)%10); if ( qq.first->mass() + qq.second->mass() >= diq->mass() ) { // If the sum of the quarks masses is larger than the diuark mass, // set the new quark masses to zero. qq.first->set5Momentum(Lorentz5Momentum()); qq.second->set5Momentum(Lorentz5Momentum()); } // Distribut the quarks evenly in the cms of the diquark and add // them as children of the diquark to the new step. SimplePhaseSpace::CMS(sqr(diq->mass()), qq.first, qq.second); qq.first->boost(diq->momentum().boostVector()); qq.second->boost(diq->momentum().boostVector()); newStep->addDecayProduct(diq, qq.first); newStep->addDecayProduct(diq, qq.second); ret = cs.splitDiQuarkJunction(seli, diq, qq); return ret; } ClusterCollapser::SingletMap ClusterCollapser::getSinglets(const tPVector & pv) const { SingletMap ret; // Get initial singlets vector clus = ColourSinglet::getSinglets(pv.begin(), pv.end()); // Return the singlets ordered in mass. for ( int i = 0, N = clus.size(); i < N; ++i ) if ( !clus[i].partons().empty() ) insert(ret, clus[i]); return ret; } tPVector ClusterCollapser:: getCompensators(Energy mh, const ColourSinglet & cs, const tPVector & tagged, tStepPtr newStep) const { tPVector ret; tcPVector comp; // First find the particles which are not a part of the collapsing // cluster. tParticleSet compset; for ( int i = 0, N = tagged.size(); i < N; ++i ) if ( !member(cs.partons(), tagged[i]) ) compset.insert(tagged[i]); LorentzMomentum pcomp; LorentzMomentum pc = cs.momentum(); // start by only looking at other strings. bool alsoSinglets = false; do { // Return an empty vector if no particles left. if ( compset.empty() ) break; // Now find the particle which is closest in phase space to the // cluster. Energy2 dist = Constants::MaxEnergy2; tParticleSet::iterator sel = compset.end(); for ( tParticleSet::iterator it = compset.begin(); it != compset.end(); ++it ) { if ( !(**it).coloured() && !alsoSinglets ) continue; if ( -(pc - (**it).momentum()).m2() < dist ) { dist = -(pc - (**it).momentum()).m2(); sel = it; } } if ( sel == compset.end() ) { if ( alsoSinglets ) break; else { alsoSinglets = true; continue; } } // Add to the temporary vector. comp.push_back(*sel); pcomp += (**sel).momentum(); compset.erase(sel); // If there was not enough energy, find an additional compensator // particle. Also check that compensators have mass to avoid boost // problems. } while ( comp.empty() || (pc + pcomp).m() <= mh + pcomp.m() || ( comp.size() > 1 && pcomp.m2() <= ZERO ) ); // If this didn't work, let's try to fix it by disregarding the // closest particle. tcPVector::size_type end = comp.size(); while ( (pc + pcomp).m() <= mh + pcomp.m() || ( comp.size() > 1 && pcomp.m2() <= ZERO ) ) { if ( end == comp.size() ) { if ( comp.size() < 2 ) return ret; comp.erase(comp.begin()); end = 1; } else ++end; pcomp = Utilities::sumMomentum(comp.begin(), comp.begin() + end); } // Now copy the compensators, add them to the new set and return them. ret.resize(end); for ( tcPVector::size_type i = 0; i < end; ++i ) ret[i] = newStep->copyParticle(comp[i]); return ret; } void ClusterCollapser:: collapse(tStepPtr newStep, const ColourSinglet & cs, const tPVector & tagged) const { // Produce the hadron to collapse into, set its momentum to the one // of the collapsing cluster and generate the mass to be set. tcPDPtr hd = getHadron(cs); LorentzMomentum pc = cs.momentum(); PPtr h = hd->produceParticle(pc); Energy mh = hd->generateMass(); // Select the partons to be used in momentum compensation tPVector comp = getCompensators(mh, cs, tagged, newStep); if ( comp.empty() ) { if ( errorlevel ) throw ClusterException(*this) << "Could not find particles to shuffle momentum." << errorlevel; h->set5Momentum(Lorentz5Momentum(pc, mh)); } else { // Boost the hadron and the compensating particles into their cms // with the hadon along the z-axis. comp.push_back(h); LorentzRotation R = Utilities::boostToCM(comp.begin(), comp.end(), comp.end() - 1).inverse(); // Give the hadron and the compensators their correct mass and // momentum and bost back LorentzMomentum pcomp = Utilities::sumMomentum(comp.begin(), comp.end() - 1); Energy2 s = (pcomp + h->momentum()).m2(); try { Energy pnew = SimplePhaseSpace::getMagnitude(s, mh, pcomp.m()); h->set5Momentum(R*Lorentz5Momentum(ZERO, ZERO, pnew, sqrt(sqr(pnew) + sqr(mh)), mh)); comp.pop_back(); R = R*LorentzRotation(0.0, 0.0, -(pcomp.e()*pcomp.z() + sqrt(sqr(pnew) + pcomp.m2())*pnew)/ (sqr(pnew) + sqr(pcomp.e()))); } catch ( ... ) { Throw() // *** TODO *** Check cicumstances for this. << "Impossible kinematics found in Ariadne5::DipoleState::purgeGluon." << Exception::eventerror; } Utilities::transform(comp, R); } // Add the new particle to the step. if ( !newStep-> addDecayProduct(cs.partons().begin(), cs.partons().end(), h) ) { throw ClusterException(*this) << "Could not add decay products to the new step" << Exception::abortnow; } } bool ClusterCollapser:: collapse2(tStepPtr newStep, const ColourSinglet & cs) const { // First get the two particles into which to decay the cluster. tcPDPair pdp = getHadrons(cs); PVector h(2); h[0] = pdp.first->produceParticle(); h[1] = pdp.second->produceParticle(); // Check the invariant mass of the cluster and return false if there // was not enough energy. LorentzMomentum pc = cs.momentum(); Energy2 s = pc.m2(); if ( sqr(h[0]->mass() + h[1]->mass()) >= s && diDiQuark(cs) ) { // In the special case of di-diquars we try to take the flavours // to create a meson pair instead. We begin by finding the quarks PDPair qq = make_pair(getParticleData(cs.piece(1).front()->id()/1000), getParticleData((cs.piece(1).front()->id()/100)%10)); PDPair aqq = make_pair(getParticleData(cs.piece(1).back()->id()/1000), getParticleData((cs.piece(1).back()->id()/100)%10)); if ( UseRandom::rndbool() ) swap(qq.first, qq.second); h[0] = flavGen->getHadron(qq.first, aqq.first)->produceParticle(); h[1] = flavGen->getHadron(qq.second, aqq.second)->produceParticle(); } if ( sqr(h[0]->mass() + h[1]->mass()) >= s ) return false; // Now set the momenta of the hadrons (distributed isotropically in // the cluster cm system). SimplePhaseSpace::CMS(s, h[0], h[1]); Utilities::transform(h, LorentzRotation(pc.boostVector())); // Add the hadrons as decay products of the partons in the // cluster. Returns false if it fails (although throwing an // exception may be more appropriate). if ( !newStep->addDecayProduct(cs.partons().begin(), cs.partons().end(), h.begin(), h.end()) ) { throw ClusterException(*this) << "Could not add decay products to the new step" << Exception::abortnow; } return true; } tcPDPair ClusterCollapser::getHadrons(const ColourSinglet & cs) const { tcPDPair ret; if ( cs.nPieces() == 3 ) { // This is a string with a junction. First find the tiplets. tcPDVector quarks = cs.getTripletData(); if ( quarks.size() == 3 ) { // Three-quark junction. Select a quark to join into a meson // with a randomly chosed flavour. int i = UseRandom::irnd(3); tcPDPtr q = pickFlavour(); if ( quarks[i]->iColour() == q->iColour() ) q = q->CC(); ret.first = flavGen->getHadron(quarks[i], q); quarks[i] = q->CC(); ret.second = flavGen->getBaryon(quarks[0], quarks[1], quarks[2]); } else if ( errorlevel ) throw ClusterException(*this) << "Too many diquarks in a junction string." << errorlevel; } else if ( cs.nPieces() != 1 ) { throw ClusterException(*this) << "Inconsistent number of string pieces in a cluster" << Exception::abortnow; } else if ( cs.piece(1).front()->data().iColour() == PDT::Colour8 ) { // This was a closed gluon loop. Create two random flavours. tcPDPtr q1 = pickFlavour(); tcPDPtr q2 = pickFlavour(); ret.first = flavGen->getHadron(q1, q2->CC()); ret.second = flavGen->getHadron(q1->CC(), q2); } else { // This was a simple flat string. Pick a new flavour. tcPDPtr q = pickFlavour(); if ( cs.piece(1).front()->data().iColour() == q->iColour() ) q = q->CC(); ret.first = flavGen->getHadron(cs.piece(1).front()->dataPtr(), q); ret.second = flavGen->getHadron(cs.piece(1).back()->dataPtr(), q->CC()); } if ( !ret.first || !ret.second ) throw ClusterException(*this) << "Could not generate hadrons from flavours " << cs.piece(1).front()->id() << " and " << cs.piece(1).back()->id() << "." << Exception::runerror; return ret; } tcPDPtr ClusterCollapser::pickFlavour() const { return getParticleData(2 + rndsign(1.0, 1.0, pStrange)); } tcPDPtr ClusterCollapser::getHadron(const ColourSinglet & cs) const { if ( cs.nPieces() == 3 ) { // This is a string with a junction. First find the tiplets. tcPDVector quarks = cs.getTripletData(); if ( quarks.size() == 3 ) { return flavGen->getBaryon(quarks[0], quarks[1], quarks[2]); } else if ( errorlevel ) throw ClusterException(*this) << "Too many diquarks in a junction string." << errorlevel; } else if ( cs.nPieces() != 1 ) { throw ClusterException(*this) << "Inconsistent number of string pieces in a cluster" << Exception::abortnow; } else if ( cs.piece(1).front()->data().iColour() == PDT::Colour8 ) { // This was a closed gluon loop. Create a random flavour. tcPDPtr q = pickFlavour(); return flavGen->getHadron(q, q->CC()); } // This was a simple flat string. return flavGen->getHadron(cs.piece(1).front()->dataPtr(), cs.piece(1).back()->dataPtr()); } void ClusterCollapser::persistentOutput(PersistentOStream & os) const { os << ounit(theEnergyCut, GeV) << theNTry2 << flavGen << oenum(errorlevel) << pStrange; } void ClusterCollapser::persistentInput(PersistentIStream & is, int) { is >> iunit(theEnergyCut, GeV) >> theNTry2 >> flavGen >> ienum(errorlevel) >> pStrange; } ClassDescription ClusterCollapser::initClusterCollapser; // Definition of the static class description member. void ClusterCollapser::Init() { static ClassDocumentation documentation ("The ThePEG::ClusterCollapser class can either be used as a " "preprocessor of a string fragmentation handler, or as a separate" "step handler to collapse small colour singlet systems of partons " "into one or two particles."); static Parameter interfaceEnergyCut ("EnergyCut", "If the invariant mass of a cluster, minus the constituent masses of its " "partons is below this cut (in GeV), it will be collapsed into one " "or two particles.", &ClusterCollapser::theEnergyCut, GeV, 1.0*GeV, ZERO, 10.0*GeV, false, false, true); static Parameter interfaceNTry2 ("NTry2", "The number of attempts to collapse a cluster into two particles, " "before it is collapsed into one particle.", &ClusterCollapser::theNTry2, 2, 0, 100, false, false, true); static Parameter interfacePStrange ("pStrange", "The relative probability to produce a s-sbar pair in a split as " "compared to a u-ubar or d-dbar pair.", &ClusterCollapser::pStrange, 1.0/3.0, 0.0, 2.0, false, false, true); static Switch interfaceLevel ("ErrorLevel", "What to do if a cluster could not be collapsed, or if momentum " "could not be conserved.", &ClusterCollapser::errorlevel, Exception::eventerror, true, false); static SwitchOption interfaceLevelNothing (interfaceLevel, "Nothing", "Do nothing, clusters may not collapse or momentum may not be conserved.", Exception::Severity(0)); static SwitchOption interfaceLevelWarning (interfaceLevel, "Warning", "Report a warning, clusters may not collapse or momentum may not " "be conserved.", Exception::warning); static SwitchOption interfaceLevelEventError (interfaceLevel, "EventError", "Discard the whole event.", Exception::eventerror); static SwitchOption interfaceLevelRunError (interfaceLevel, "RunError", "End the run, printout the offending event.", Exception::runerror); static SwitchOption interfaceLevelAbort (interfaceLevel, "Abort", "Abort and dump core.", Exception::abortnow); static Reference interfaceFlavGen ("FlavourGenerator", "The object used to combine quarks and diquarks into hadrons.", &ClusterCollapser::flavGen, true, false, true, false); interfaceEnergyCut.rank(10); interfacePStrange.rank(9); interfaceFlavGen.rank(8); interfaceNTry2.rank(7); interfaceLevel.rank(6); } diff --git a/Handlers/ClusterCollapser.h b/Handlers/ClusterCollapser.h --- a/Handlers/ClusterCollapser.h +++ b/Handlers/ClusterCollapser.h @@ -1,336 +1,336 @@ // -*- C++ -*- // // ClusterCollapser.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_ClusterCollapser_H #define ThePEG_ClusterCollapser_H // This is the declaration of the ClusterCollapser class. #include "ThePEG/Handlers/StepHandler.h" #include "ThePEG/Handlers/FlavourGenerator.h" #include "ThePEG/EventRecord/ColourSinglet.h" #include "ClusterCollapser.fh" // #include "ClusterCollapser.xh" namespace ThePEG { /** * ClusterCollapser is a general StepHandler which can be called * anywhere in the event generation (typically as a pre-handler to the * hadronization or a post-hadnler to the cascade) to find colour-less * clusters of partons which are deemed to have to small invariant * mass to be hadronized in the normal way. Instead these clusters are * allowed to collapse into hadrons. Possible energy imbalance du to * the clustering is compensated by shifting the momenta of nearby * particles. * * @see \ref ClusterCollapserInterfaces "The interfaces" * defined for ClusterCollapser. */ class ClusterCollapser: public StepHandler { public: /** Declare a pointer to a FlavourGenerator object. */ typedef Ptr::pointer FlavGenPtr; /** Declare a multimap of singlets indexed by their mass. */ typedef multimap SingletMap; public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ ClusterCollapser() : theEnergyCut(1.0*GeV), theNTry2(2), errorlevel(Exception::eventerror), pStrange(1.0/3.0) {} /** * The destructor. */ virtual ~ClusterCollapser(); //@} public: /** @name Virtual functions required by the StepHandler class. */ //@{ /** * The main function called by the EventHandler class to * perform a step. This function simply calls the collapse() function. * @param eh the EventHandler in charge of the Event generation. * @param tagged if not empty these are the only particles which should * be considered by the StepHandler. * @param hint a Hint object with possible information from previously * performed steps. * @throws Veto if the StepHandler requires the current step to be discarded. * @throws Stop if the generation of the current Event should be stopped * after this call. * @throws Exception if something goes wrong. */ virtual void handle(EventHandler & eh, const tPVector & tagged, const Hint & hint); //@} /** * Perform all necessary collapses. Return the uncollapsed clusters. */ virtual vector collapse(tPVector tagged, tStepPtr newstep); /** * Go through the tagged partons and extract all colour singlet * combination of partons. Order them in invariant mass (minus the * constituent masses of the partons). */ virtual SingletMap getSinglets(const tPVector & tagged) const; /** * If a singlet contains at least one diquark and a junction, split * the diquark and split off a new colour singlet. */ virtual ColourSinglet splitDiQuarkJunction(ColourSinglet & cs, tStepPtr newStep) const; /** * If a singlet contains a simple string with diquarks in both ends, * split them into quarks and split off a new colour singlet. */ virtual ColourSinglet splitDiDiQuark(ColourSinglet & cs, tStepPtr newStep) const; /** * Returns true iff the given singlet contains a junction and at * least one diquark. */ static bool diQuarkJunction(const ColourSinglet & cs); /** * Returns true iff the given singlet contains one string piece with * diquarks in both ends. */ static bool diDiQuark(const ColourSinglet & cs); /** * If the invariant mass of a cluster, minus the constituent masses * of its partons is below this cut, it will be collapsed into one * or two particles. */ Energy cut() const { return theEnergyCut; } /** * The number of attempts to collapse a cluster into two particles, * before it is collapsed into one particle. */ int nTry2() const { return theNTry2; } /** * Return the invariant mass of a cluster minus the constituent * masses of its partons. */ static Energy mass(const ColourSinglet & cl); /** * Insert a ColourSinglet object in a SingletMap. */ static void insert(SingletMap & mmap, const ColourSinglet & cl); /** * Pick a random flavour. Default version picks u,d or s with ratio * 3:3:1. */ virtual tcPDPtr pickFlavour() const; protected: /** * Perform the actual collapse of a cluster into one hadron. Add * the produced hadron to the given step as decay products of the * partons in the cluster. The \a tagged particles are used for * momentum compensation. */ virtual void collapse(tStepPtr newStep, const ColourSinglet & cs, const tPVector & tagged) const; /** * Perform the actual collapse of a cluster into two hadrons. Add * the produced hadrons to the given step as decay products of the * partons in the cluster. The \a tagged particles are used for * momentum compensation. @return false if the collapse failed in * some way. */ virtual bool collapse2(tStepPtr newStep, const ColourSinglet & cs) const; /** * Get particles for compensation. Look through the \a tagged vector * for particles (which are not in the colour singlet \a cs) which can * be used to compensate momentum when \a cs collapses into a hadron * with mass \a mh. These partons are then copied into the new step so * that their momentum can be changed and then returned. */ virtual tPVector getCompensators(Energy mh, const ColourSinglet & cs, const tPVector & tagged, tStepPtr newStep) const; /** * Return a hadron into which the given cluster may collapse. */ virtual tcPDPtr getHadron(const ColourSinglet & cs) const; /** * Return a pair of hadrons into which the given cluster may collapse. */ virtual tcPDPair getHadrons(const ColourSinglet & cs) const; /** * Uptate the vector of particles and remove partons which have * already collapsed and insert their children instead. */ void updateTagged(tPVector & tagged) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interfaces. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} /** @cond EXCEPTIONCLASSES */ /** Exception class used by ClusterCollapser. */ class ClusterException: public Exception { public: /** Standard constructor. */ ClusterException(const ClusterCollapser & cc) { theMessage << "In ClusterCollapser '" << cc.name() << "': "; } }; /** @endcond */ private: /** * Energy cut. If the invariant mass of a cluster, minus the * constituent masses of its partons is below this cut, it will be * collapsed into one or two particles. */ Energy theEnergyCut; /** * The number of attempts to collapse a cluster into two particles, * before it is collapsed into one particle. */ int theNTry2; /** * The flavour generator object to use to combine quarks and diqurks * into hadrons. */ FlavGenPtr flavGen; protected: /** * How should we respond to errors? 0 means do nothing, ie. the * cluster will not be collapsed, or the momentum will not be * consterved. Otherwise the severity will be what is defined in the * class Exception. */ Exception::Severity errorlevel; /** * The relative probability to produce a s-sbar pair in a split as * compared to a u-ubar or d-dbar pair. */ double pStrange; private: /** * Describe a concrete class with persistent data. */ static ClassDescription initClusterCollapser; /** * Private and non-existent assignment operator. */ ClusterCollapser & operator=(const ClusterCollapser &) = delete; }; } namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** * The following template specialization informs ThePEG about the * base class of ClusterCollapser. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of ClusterCollapser. */ typedef StepHandler NthBase; }; /** * The following template specialization informs ThePEG about the name * of the ClusterCollapser class and the shared object where it is * defined. */ template <> struct ClassTraits: public ClassTraitsBase { /** * Return the class name. */ static string className() { return "ThePEG::ClusterCollapser"; } }; /** @endcond */ } #endif /* ThePEG_ClusterCollapser_H */ diff --git a/Handlers/DecayHandler.cc b/Handlers/DecayHandler.cc --- a/Handlers/DecayHandler.cc +++ b/Handlers/DecayHandler.cc @@ -1,118 +1,118 @@ // -*- C++ -*- // // DecayHandler.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the DecayHandler class. // #include "DecayHandler.h" #include "Hint.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/PDT/DecayMode.h" #include "ThePEG/PDT/Decayer.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/EventRecord/Step.h" #include "ThePEG/EventRecord/Collision.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG; DecayHandler::~DecayHandler() {} IBPtr DecayHandler::clone() const { return new_ptr(*this); } IBPtr DecayHandler::fullclone() const { return new_ptr(*this); } void DecayHandler:: handle(EventHandler &, const tPVector & tagged, const Hint &) { // First go through to see which of the tagged particles should be // decayed: Exit if none are found. tPVector parents; for ( int i = 0, N = tagged.size(); i < N; ++i ) if ( tagged[i] && !tagged[i]->data().stable() ) parents.push_back(tagged[i]); if ( parents.empty() ) return; // Create a new step, decay all particles and add their children in // the new step. for ( int i = 0, N = parents.size(); i < N; ++i ) performDecay(newStep()->find(parents[i]->final()), *newStep()); } void DecayHandler:: performDecay(tPPtr parent, Step & s) const { if ( maxLifeTime() >= ZERO ) { if( ( lifeTimeOption() && parent->lifeLength().tau() > maxLifeTime())|| (!lifeTimeOption() && parent->data().cTau() > maxLifeTime()) ) { parent->setLifeLength(Distance()); return; } } ParticleVector children = Decayer::DecayParticle(parent, s, maxLoop()); for ( int i = 0, N = children.size(); i < N; ++i ) if ( !children[i]->data().stable() ) performDecay(children[i], s); } void DecayHandler::persistentOutput(PersistentOStream & os) const { os << theMaxLoop << ounit(theMaxLifeTime, mm) << theLifeTimeOption; } void DecayHandler::persistentInput(PersistentIStream & is, int) { is >> theMaxLoop >> iunit(theMaxLifeTime, mm) >> theLifeTimeOption; } ClassDescription DecayHandler::initDecayHandler; void DecayHandler::Init() { static ClassDocumentation documentation ("This is the main class handling the decay of unstable particles. Note " "that the actual decays will be performed by objects of the " "ThePEG::Decayer class."); static Parameter interfaceMaxLoop ("MaxLoop", "The maximum number of attempts per event when selecting a decay channel.", &DecayHandler::theMaxLoop, 100000, 100, 100000000, true, false, true); static Parameter interfaceMaxLifeTime ("MaxLifeTime", "The maximum lifetime (c*tau) in units of mm. Particles with longer " "lifetimes than this will not be decayed.", &DecayHandler::theMaxLifeTime, mm, -1.0*mm, -1.0*mm, ZERO, true, false, Interface::lowerlim); static Switch interfaceLifeTimeOption ("LifeTimeOption", "Option for how the maximum life time is interpreted", &DecayHandler::theLifeTimeOption, false, false, false); static SwitchOption interfaceLifeTimeOptionAverage (interfaceLifeTimeOption, "Average", "Cut on the average lifetime of the particle type", false); static SwitchOption interfaceLifeTimeOptionReal (interfaceLifeTimeOption, "Real", "Cut on the lifetime generated for the given instance", true); } diff --git a/Handlers/DecayHandler.h b/Handlers/DecayHandler.h --- a/Handlers/DecayHandler.h +++ b/Handlers/DecayHandler.h @@ -1,186 +1,186 @@ // -*- C++ -*- // // DecayHandler.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_DecayHandler_H #define ThePEG_DecayHandler_H // This is the declaration of the DecayHandler class. #include "StepHandler.h" namespace ThePEG { /** * The DecayHandler is the base class of all handlers implementing the * administration of decays of unstable particles. It is derived from * the more general StepHandler class, and overrides the handle() * method. This base class simply decays all unstable particle in the * current step. * * @see \ref DecayHandlerInterfaces "The interfaces" * defined for DecayHandler. * @see StepHandler * @see EventHandler * @see SubProcessHandler * */ class DecayHandler: public StepHandler { public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ DecayHandler() : theMaxLoop(100000), theMaxLifeTime(-1.0*mm), theLifeTimeOption(false) {} /** * Destructor. */ virtual ~DecayHandler(); //@} public: /** @name Virtual functions required by the StepHandler class. */ //@{ /** * Look through all \a tagged particled and decay all unstable ones. * @param eh the EventHandler in charge of the generation. * @param tagged the vector of particles to consider. If empty, all * final state particles in the current Step is considered. * @param hint a possible Hint which is ignored in this implementation. */ virtual void handle(EventHandler & eh, const tPVector & tagged, const Hint & hint); //@} /** * Perform the decay of one unstable particle. * @param parent the particle to be decayed. * @param s the Step where decay products are inserted. */ void performDecay(tPPtr parent, Step & s) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interface. */ static void Init(); /** * The maximum number of failed decay attempts allowed for each * particle. */ long maxLoop() const { return theMaxLoop; } /** * Get the maximum lifetime above which a particle is not decayed. */ Length maxLifeTime() const { return theMaxLifeTime; } /** * Option for whether the maximum lifetime should be applied to the * mean lifetime of the particle species or the lifetime of the particle * instance */ bool lifeTimeOption() const { return theLifeTimeOption; } protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * The maximum number of failed decay attempts allowed for each * particle. */ long theMaxLoop; /** * The maximum lifetime above which a particle is not decayed. */ Length theMaxLifeTime; /** * Option for how theMaxLifeTime should be interpreted */ bool theLifeTimeOption; private: /** * Describe a concrete class with persistent data. */ static ClassDescription initDecayHandler; /** * Private and non-existent assignment operator. */ DecayHandler & operator=(const DecayHandler &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** * This template specialization informs ThePEG about the * base class of DecayHandler. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the base class of DecayHandler. */ typedef StepHandler NthBase; }; /** * This template specialization informs ThePEG about the name of the * DecayHandler class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return the class name. */ static string className() { return "ThePEG::DecayHandler"; } }; /** @endcond */ } #endif /* ThePEG_DecayHandler_H */ diff --git a/Handlers/EventHandler.cc b/Handlers/EventHandler.cc --- a/Handlers/EventHandler.cc +++ b/Handlers/EventHandler.cc @@ -1,566 +1,566 @@ // -*- C++ -*- // // EventHandler.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the EventHandler class. // #include "EventHandler.h" #include "ThePEG/Handlers/XComb.h" #include "ThePEG/Handlers/Hint.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Handlers/CascadeHandler.h" #include "ThePEG/Handlers/MultipleInteractionHandler.h" #include "ThePEG/Handlers/HadronizationHandler.h" #include "ThePEG/Handlers/DecayHandler.h" #include "ThePEG/Handlers/SubProcessHandler.h" #include "ThePEG/Cuts/Cuts.h" #include "ThePEG/PDF/PartonExtractor.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/EventRecord/Event.h" #include "ThePEG/Utilities/Debug.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Handlers/LuminosityFunction.h" #include "ThePEG/Utilities/Throw.h" #include "ThePEG/Utilities/EnumIO.h" #include "ThePEG/Utilities/Rebinder.h" using namespace ThePEG; EventHandler::EventHandler(bool warnincomplete) : theMaxLoop(100000), weightedEvents(false), theStatLevel(2), theConsistencyLevel(clCollision), theConsistencyEpsilon(sqrt(Constants::epsilon)), warnIncomplete(warnincomplete) { setupGroups(); } EventHandler:: EventHandler(const EventHandler & x) : HandlerBase(x), LastXCombInfo<>(x), theMaxLoop(x.theMaxLoop), weightedEvents(x.weightedEvents), theStatLevel(x.theStatLevel), theConsistencyLevel(x.theConsistencyLevel), theConsistencyEpsilon(x.theConsistencyEpsilon), theLumiFn(x.theLumiFn), theCuts(x.theCuts), thePartonExtractor(x.thePartonExtractor), theSubprocessGroup(x.theSubprocessGroup), theCascadeGroup(x.theCascadeGroup), theMultiGroup(x.theMultiGroup), theHadronizationGroup(x.theHadronizationGroup), theDecayGroup(x.theDecayGroup), warnIncomplete(x.warnIncomplete), theIncoming(x.theIncoming) { setupGroups(); } EventHandler::~EventHandler() {} IBPtr EventHandler::clone() const { return new_ptr(*this); } IBPtr EventHandler::fullclone() const { return new_ptr(*this); } void EventHandler::lumiFn(LumiFnPtr newLumiFn) { if ( newLumiFn->canHandle(incoming()) ) theLumiFn = newLumiFn; else throw LumiFuncError() << "Cannot use '" << newLumiFn->name() << "' as the luminosity function in the event handler '" << name() << "' since it cannot handle the requested incoming particles." << Exception::warning; } void EventHandler::setupGroups() { theGroups.clear(); theGroups.push_back(&theSubprocessGroup); theGroups.push_back(&theCascadeGroup); theGroups.push_back(&theMultiGroup); theGroups.push_back(&theHadronizationGroup); theGroups.push_back(&theDecayGroup); optGroups.clear(); optGroups.push_back(&optSubprocessGroup); optGroups.push_back(&optCascadeGroup); optGroups.push_back(&optMultiGroup); optGroups.push_back(&optHadronizationGroup); optGroups.push_back(&optDecayGroup); } void EventHandler::initGroups() { for ( unsigned int i = 0; i < groups().size(); ++i ) groups()[i]->init(*optGroups[i]); } tCascHdlPtr EventHandler::cascadeHandler() const { return dynamic_ptr_cast(theCascadeGroup.defaultHandler()); } EventPtr EventHandler::generateEvent() { throw EventHandlerIncompleteError() << "The function generateEvent() was called for the EventHandler '" << name() << "' which is not capable of generating complete events." << Exception::runerror; } tEventPtr EventHandler::generateEvent(tStepPtr s) { EventPtr e = new_ptr(Event(PPair(), tcEventBasePtr(), generator()->runName(), generator()->currentEventNumber())); e->newCollision()->addStep(s); return generateEvent(tEventPtr(e)); } tEventPtr EventHandler::generateEvent(tEventPtr e) { clearEvent(); e->setInfo(this, generator()->runName(), generator()->currentEventNumber(), 1.0); currentEvent(e); if ( e->collisions().empty() || !e->collisions().back()->finalStep()) { throw EventHandlerIncompleteError() << "The function generateEvent() was called with an empty Event " << "for the EventHandler '" << name() << "' which is not capable of generating complete events." << Exception::runerror; } currentCollision(e->collisions().back()); currentStep(currentCollision()->finalStep()); EventHandler::initGroups(); continueCollision(); return currentEvent(); } tCollPtr EventHandler::continueCollision() { generator()->currentEventHandler(this); while (1) { if ( consistencyLevel() == clStep || consistencyLevel() == clPrintStep ) checkConsistency(); bool done = true; for ( GroupVector::iterator git = groups().begin(); git != groups().end(); ++git ) { HandlerGroupBase & group = **git; HandlerGroupBase::StepWithHint sh; sh = group.next(); if ( !group.empty() ) { performStep(sh.first, sh.second); done = false; break; } } if ( done ) break; } if ( consistencyLevel() == clCollision || consistencyLevel() == clPrintCollision ) checkConsistency(); return currentCollision(); } void EventHandler::clearEvent() { ThePEG::CascadeHandler::setDidRunCascade(false); for ( GroupVector::const_iterator git = groups().begin(); git != groups().end(); ++git ) (**git).clear(); } bool EventHandler::empty() const { for ( GroupVector::const_iterator git = groups().begin(); git != groups().end(); ++git ) if ( !(**git).empty() ) return false; return true; } void EventHandler::select(tXCombPtr newXComb) { theLastXComb = newXComb; lumiFn().select(newXComb); if ( CKKWHandler() ) CKKWHandler()->setXComb(newXComb); } void EventHandler:: performStep(tStepHdlPtr handler, tHintPtr hint) { if ( !lastXCombPtr() ) theLastXComb = new_ptr(XComb()); if ( hint->stop() ) throw Stop(); tStepPtr oldStep = currentStep(); currentStepHandler(handler); handler->eventHandler(this); try { generator()->currentStepHandler(handler); handler->handle(*this, hint->tagged(*oldStep), *hint); generator()->currentStepHandler(tStepHdlPtr()); } catch (...) { generator()->currentStepHandler(tStepHdlPtr()); if ( oldStep != currentStep() ) popStep(); throw; } while ( currentStep()->nullStep() ) popStep(); if ( ThePEG_DEBUG_ITEM(2) && oldStep != currentStep() ) generator()->logfile() << *currentStep(); } void EventHandler:: addStep(Group::Level level, Group::Handler group, tStepHdlPtr s, tHintPtr h) { if ( !h ) h = Hint::Default(); switch ( level ) { case Group::main: if ( s && !groups()[group]->setHandler(s, *optGroups[group]) ) throw EventHandlerStepError() << "Cannot add the StepHandler '" << s->name() << "' to the list of step handlers in the EventHandler '" << name() << "' because it is not of class '" << groups()[group]->handlerClass() << "'." << Exception::abortnow; groups()[group]->addHint(h, *optGroups[group]); break; case Group::before: groups()[group]->addPreHandler(s, h, *optGroups[group]); break; case Group::after: groups()[group]->addPostHandler(s, h, *optGroups[group]); break; } for ( long gr = group + 1; gr <= Group::decay; ++gr ) groups()[gr]->addHint(Hint::Default(), *optGroups[group]); } void EventHandler::throwCurrent() { clean(); } void EventHandler::clean() { currentEvent(EventPtr()); currentCollision(CollPtr()); currentStep(StepPtr()); } void EventHandler::statistics(ostream &) const {} void EventHandler::initialize() {} EventPtr EventHandler::continueEvent() { try { continueCollision(); } catch (Veto) { } catch (Stop) { } catch (Exception &) { throw; } return currentEvent(); } CrossSection EventHandler::histogramScale() const { generator()->logWarning( EventHandlerHistError() << "The event handler '" << name() << "' was not able give a cross " "section for scaling histograms. The resulting histograms will not " "yeald correct cross section." << Exception::warning); return 1.0*picobarn; } CrossSection EventHandler::integratedXSec() const { generator()->logWarning( EventHandlerHistError() << "The event handler '" << name() << "' was not able give the cross " "section for the generated processes." << Exception::warning); return 1.0*picobarn; } CrossSection EventHandler::integratedXSecErr() const { generator()->logWarning( EventHandlerHistError() << "The event handler '" << name() << "' was not able give the cross " "section error for the generated processes." << Exception::warning); return ZERO; } void EventHandler::checkConsistency() const { if ( !currentCollision() ) return; const Collision & c = *currentCollision(); if ( !c.incoming().first && !c.incoming().second ) return; if ( !c.finalStep() ) return; LorentzMomentum pi; if ( c.incoming().first ) pi = c.incoming().first->momentum(); if ( c.incoming().second ) pi += c.incoming().second->momentum(); int ci = 0; if ( c.incoming().first ) ci = c.incoming().first->data().iCharge(); if ( c.incoming().second ) ci += c.incoming().second->data().iCharge(); const ParticleSet & fs = c.finalStep()->particles(); LorentzMomentum pf; int cf = 0; for ( ParticleSet::const_iterator it = fs.begin(); it != fs.end(); ++it ) { pf += (**it).momentum(); cf += (**it).data().iCharge(); } if ( cf != ci ) { if(consistencyLevel() == clPrintStep || consistencyLevel() == clPrintCollision) { Throw() << "Event handler '" << name() << "' found charge non-conservation by " << cf - ci << "/3 units after generating step number " << c.steps().size() << ". Dump of event follows: \n\n" << *currentEvent() << "\n" << Exception::warning; } else { Throw() << "Event handler '" << name() << "' found charge non-conservation by " << cf - ci << "/3 units after generating step number " << c.steps().size() << ".\n" << Exception::warning; } } Energy eps = consistencyEpsilon()*pi.m()*sqrt(double(fs.size())); pf -= pi; if ( abs(pf.x()) > eps || abs(pf.y()) > eps || abs(pf.z()) > eps || abs(pf.e()) > eps ) { if(consistencyLevel() == clPrintStep || consistencyLevel() == clPrintCollision) { Throw() << "Event handler '" << name() << "' found energy-momentum non-" << "conservation by (" << pf.x()/GeV << "," << pf.y()/GeV << "," << pf.z()/GeV << ";" << pf.e()/GeV << ") GeV after generating step number " << c.steps().size() << ". Dump of event follows: \n\n" << *currentEvent() << "\n" << Exception::warning; } else { Throw() << "Event handler '" << name() << "' found energy-momentum non-" << "conservation by (" << pf.x()/GeV << "," << pf.y()/GeV << "," << pf.z()/GeV << ";" << pf.e()/GeV << ") GeV after generating step number " << c.steps().size() << ".\n" << Exception::warning; } } } void EventHandler::rebind(const TranslationMap & trans) { theIncoming.first = trans.translate(theIncoming.first); theIncoming.second = trans.translate(theIncoming.second); HandlerBase::rebind(trans); } IVector EventHandler::getReferences() { IVector ret = HandlerBase::getReferences(); ret.push_back(const_ptr_cast(theIncoming.first)); ret.push_back(const_ptr_cast(theIncoming.second)); return ret; } void EventHandler::persistentOutput(PersistentOStream & os) const { os << theLastXComb << theMaxLoop << weightedEvents << theStatLevel << oenum(theConsistencyLevel) << theConsistencyEpsilon << theLumiFn << theCuts << thePartonExtractor << theSubprocessGroup << theCascadeGroup << theMultiGroup << theHadronizationGroup << theDecayGroup << theCurrentEvent << theCurrentCollision << theCurrentStep << theCurrentStepHandler << warnIncomplete << theIncoming; } void EventHandler::persistentInput(PersistentIStream & is, int) { is >> theLastXComb >> theMaxLoop >> weightedEvents >> theStatLevel >> ienum(theConsistencyLevel) >> theConsistencyEpsilon >> theLumiFn >> theCuts >> thePartonExtractor >> theSubprocessGroup >> theCascadeGroup >> theMultiGroup >> theHadronizationGroup >> theDecayGroup >> theCurrentEvent >> theCurrentCollision >> theCurrentStep >> theCurrentStepHandler >> warnIncomplete >> theIncoming; } ThePEG_IMPLEMENT_CLASS_DESCRIPTION(EventHandler); void EventHandler::Init() { static ClassDocumentation documentation ("This is the base class controlling the generation of the event after " "the hard sub-process generation. To its help it has a number of step " "handler objects, most noticeable the " "CascadeHandler, the " "HadronizationHandler and the " "DecayHandler. Derived classes may " "also make use of the LuminosityFunction " "to specify the incoming beams, the " "PartonExtractor to administer the " "extraction of partons from incoming hadrons, and the " "Cuts to specify cuts on the primary sub-process."); static Parameter interfaceMaxLoop ("MaxLoop", "The maximum number of attempts per event when selecting a sub-process.", &EventHandler::theMaxLoop, 100000, 100, 100000000, true, false, true); static Switch interfaceWeighted ("Weighted", "If switched on, this event Handler will produce weighted events", &EventHandler::weightedEvents, false, false); static SwitchOption interfaceWeightedTrue (interfaceWeighted, "On", "This EventHandler produces weighted events.", true); static SwitchOption interfaceWeightedFalse (interfaceWeighted, "Off", "This EventHandler produces unweighted events.", false); static SwitchOption interfaceWeightedYes (interfaceWeighted, "Yes", "This EventHandler produces weighted events.", true); static SwitchOption interfaceWeightedNo (interfaceWeighted, "No", "This EventHandler produces unweighted events.", false); static Switch interfaceStatLevel ("StatLevel", "Controlls the amount of statistics written out after each run to " "the EventGenerators .out file.", &EventHandler::theStatLevel, 2, true, false); static SwitchOption interfaceStatLevelNone (interfaceStatLevel, "None", "No statistics is written out.", 0); static SwitchOption interfaceStatLevelTot (interfaceStatLevel, "TotalXSec", "Only the total cross-section is written out.", 1); static SwitchOption interfaceStatLevelME (interfaceStatLevel, "MatrixElements", "The cross-section for each subprocess group is written out.", 2); static SwitchOption interfaceStatLevelBins (interfaceStatLevel, "Bins", "The cross-sections for individual subprocesses are written out.", 3); static SwitchOption interfaceStatLevelFull (interfaceStatLevel, "Full", "A detailed account of the cross-sections of the generated sub-processes " "is written out.", 4); static Reference interfaceLumifn ("LuminosityFunction", "An object derived from the ThePEG::LuminosityFunction class, " "which describes the beams in the collider under study.", &EventHandler::theLumiFn, false, false, true, true, &EventHandler::lumiFn); static Reference interfaceCuts ("Cuts", "Kinematical cuts to be used by subclasses which do not provide " "their own. Note that this may be overridden by subclasses.", &EventHandler::theCuts, true, false, true, true, false); static Reference interfacePartonExtractor ("PartonExtractor", "A PartonExtractor object to be used by subclasses which do not " "provide their own. Note that this may be overridden by subclasses.", &EventHandler::thePartonExtractor, true, false, true, true, false); ThePEG_DECLARE_PREPOST_OBJECTS(EventHandler, SubProcessHandler, Post, after); ThePEG_DECLARE_GROUPINTERFACE_OBJECTS(EventHandler, CascadeHandler); ThePEG_DECLARE_GROUPINTERFACE_OBJECTS(EventHandler, MultipleInteractionHandler); ThePEG_DECLARE_GROUPINTERFACE_OBJECTS(EventHandler, HadronizationHandler); ThePEG_DECLARE_GROUPINTERFACE_OBJECTS(EventHandler, DecayHandler); static Switch interfaceWarnIncomplete ("WarnIncomplete", "Emit a warning during the initialization that this EventHandler is " "incomplete. Should only be manipulated if the object is in fact an " "incomlete EventHandler and you do not want a warning.", &EventHandler::warnIncomplete, true, true, false); static SwitchOption interfaceWarnIncompleteYes (interfaceWarnIncomplete, "Yes", "This is an incomplete EventHandler and warning should be emitted.", true); static SwitchOption interfaceWarnIncompleteNo (interfaceWarnIncomplete, "No", "This EventHandler is either complete or no warning should be emitted " "in either case.", false); interfaceWarnIncomplete.setHasDefault(false); static Switch interfaceConsistencyLevel ("ConsistencyLevel", "Determines how often the event handler should check for charge and " "energy-momentum conservation.", &EventHandler::theConsistencyLevel, clCollision, true, false); static SwitchOption interfaceConsistencyLevelNever (interfaceConsistencyLevel, "Never", "No consistency checks are made.", clNoCheck); static SwitchOption interfaceConsistencyLevelEveryCollision (interfaceConsistencyLevel, "EveryCollision", "Every collision is checked for consistency.", clCollision); static SwitchOption interfaceConsistencyLevelEveryStep (interfaceConsistencyLevel, "EveryStep", "Every step is checked for consistency.", clStep); static SwitchOption interfaceConsistencyLevelPrintEveryCollision (interfaceConsistencyLevel, "PrintEveryCollision", "Every collision is checked for consistency. If an inconsistency is " "found, the event is printed to the log file.", clPrintCollision); static SwitchOption interfaceConsistencyLevelPrintEveryStep (interfaceConsistencyLevel, "PrintEveryStep", "Every step is checked for consistency. If an inconsistency is " "found, the event is printed to the log file.", clPrintStep); interfaceConsistencyLevel.setHasDefault(false); static Parameter interfaceConsistencyEpsilon ("ConsistencyEpsilon", "The maximum fraction of the total invariant mass of a collision that " "any of the components of the summed momentum is allowed to change during " "the generation. Used if ConsistencyLevel is " "switched on.", &EventHandler::theConsistencyEpsilon, sqrt(Constants::epsilon), 0.0, 1.0, true, false, Interface::limited); interfaceLumifn.rank(10); interfaceCascadeHandler.rank(9); interfaceHadronizationHandler.rank(8); interfaceDecayHandler.rank(7); interfaceCuts.rank(6); interfacePartonExtractor.rank(5); } ThePEG_IMPLEMENT_PREPOST_GROUP(EventHandler,SubProcessHandler, theSubprocessGroup,Post) \ ThePEG_IMPLEMENT_GROUPINTERFACE(EventHandler,CascadeHandler, theCascadeGroup,CascHdlPtr) \ ThePEG_IMPLEMENT_GROUPINTERFACE(EventHandler, MultipleInteractionHandler, theMultiGroup,MIHdlPtr) \ ThePEG_IMPLEMENT_GROUPINTERFACE(EventHandler,HadronizationHandler, theHadronizationGroup,HadrHdlPtr) \ ThePEG_IMPLEMENT_GROUPINTERFACE(EventHandler,DecayHandler, theDecayGroup,DecayHdlPtr) \ EventHandler::EventLoopException:: EventLoopException(const EventHandler & eh) { theMessage << "The maximum number of attempts per event (" << eh.maxLoop() << ") in event handler '" << eh.name() << "' was exceeded."; severity(maybeabort); } diff --git a/Handlers/EventHandler.h b/Handlers/EventHandler.h --- a/Handlers/EventHandler.h +++ b/Handlers/EventHandler.h @@ -1,681 +1,681 @@ // -*- C++ -*- // // EventHandler.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_EventHandler_H #define ThePEG_EventHandler_H // This is the declaration of the EventHandler class. #include "ThePEG/Handlers/HandlerBase.h" #include "ThePEG/Handlers/HandlerGroup.h" #include "ThePEG/Handlers/StepHandler.h" #include "ThePEG/EventRecord/Event.h" #include "ThePEG/Handlers/LastXCombInfo.h" #include "ThePEG/Handlers/SubProcessHandler.fh" #include "ThePEG/Cuts/Cuts.fh" #include "EventHandler.fh" namespace ThePEG { /** * The EventHandler is the base class used to implement event handlers * in ThePEG. Objects of this class is assigned to an EventGenerator * object which supervises a run. This base class is not able to * generate complete events, although it does have a virtual * generateEvent(). If the EventGenerator to which an EventGenerator * is assinged is asked to generate a full event, it will call the * generateEvent() function which will write an error message and * abort the run. * * Objects of this base class can, however, be used to administer the * evolution of a partially generated event supplied from the * outside. To specify this event evolution the EventHandler maintains * five groups of so-called StepHandlers implemented as * HandlerGroups. Each group have a main step handler: * SubProcessHandler, CascadeHandler, MultipleInteractionHandler, * HadronizationHandler and DecayHandler respectively, whereof the * first group only uses the post-handler part of the group. * * The EventHandler class inherits from the LastXCombInfo class to * have easy interface to the information in the last selected XComb * which carries information about the hard sub-process in the event. * * If a sub-class implements the generation of sub-processes and thus * becomes a full event handler it should implement the * generateEvent() function appropriately. It should also set the flag * warnIncomplete to false, to avoid warnings when initialized as the main * EventHandler of an Eventgenerator. * * @see \ref EventHandlerInterfaces "The interfaces" defined for EventHandler. * @see Collision * @see StepHandler * @see HandlerGroup * @see SubProcessHandler * @see CascadeHandler * @see MultipleInteractionHandler * @see HadronizationHandler * @see DecayHandler */ class EventHandler: public HandlerBase, public LastXCombInfo<> { public: /** Enumerate the different levels of consistency checking. */ enum ConsistencyLevel { clNoCheck, /**< Do not perform consistency checks. */ clCollision, /**< Check every Collision. */ clStep, /**< Check every Step. */ clPrintCollision, /**< Check every Collision. Print event if inconsistent.*/ clPrintStep /**< Check every Step. Print event if inconsistent. */ }; /** A vector of HandlerGroups. */ typedef vector GroupVector; public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ EventHandler(bool warnincomplete = true); /** * Copy-constructor. */ EventHandler(const EventHandler &); /** * Destructor. */ virtual ~EventHandler(); //@} public: /** @name Main functions, some of which may be overridden by subclasses. */ //@{ /** * Initialize this event handler and all related objects needed to * generate events. */ virtual void initialize(); /** * Generate an event. This base class is not capable of generating * complete events and calling this function will result in an * exception. Sub-classes which are capable of generating complete * events from scratch must override this function. */ virtual EventPtr generateEvent(); /** * Generate an Event, where the initial state is supplied * from the outside. * @return a pointer to the generated Event. */ tEventPtr generateEvent(tEventPtr e); /** * Generate an Event, where the initial state is supplied as a * single step from the outside. * @return a pointer to the generated Event. */ tEventPtr generateEvent(tStepPtr s); /** * Continue generating an event if the generation has been stopped * before finishing. */ virtual EventPtr continueEvent(); /** * Continue the generation of a Collision. Used if the generation * was previously interrupted. */ tCollPtr continueCollision(); /** * Clear all step handlers, making the handler ready for a new event. */ void clearEvent(); /** * Change the XComb object */ virtual void select(tXCombPtr newXComb); /** * Returns true if there are no step handlers left to apply to the * current event; */ virtual bool empty() const; /** * 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. This version of * the function will produce an error message. It is up to a * sub-class able to generate full events to return the correct * value. */ virtual CrossSection histogramScale() const; /** * The total integrated cross section of the processes generated in * this run. This version of the function will produce an error * message. It is up to a sub-class able to generate full events to * return the correct value. * @return 0 if no integrated cross section could be estimated. */ virtual CrossSection integratedXSec() const; /** * The estimated error in the total integrated cross section of the * processes generated in this run. This version of the function * will produce an error message. It is up to a sub-class able to * generate full events to return the correct value. * @return 0 if no integrated cross section error could be estimated. */ virtual CrossSection integratedXSecErr() const; //@} /** @name Simple access functions. */ //@{ /** * Return the maximum number attemts allowed to select a sub-process * for each event. */ long maxLoop() const { return theMaxLoop; } /** * The pair of incoming particle types. These are null if not set by * a subclass. */ const cPDPair & incoming() const { return theIncoming; } /** * Access the luminosity function. */ const LuminosityFunction & lumiFn() const { return *theLumiFn; } /** * Access the luminosity function. */ tcLumiFnPtr lumiFnPtr() const{ return theLumiFn; } /** * Access to the luminosity function. */ tLumiFnPtr lumiFnPtr(){ return theLumiFn; } /** * The kinematical cuts to used by subclasses which do not provide their own. */ tCutsPtr cuts() const { return theCuts; } /** * A PartonExtractor object to be used by sub classes which do not * provide their own. */ tPExtrPtr partonExtractor() const { return thePartonExtractor; } /** * Return a pointer (possibly null) to the assigned main * CascadeHandler. */ tCascHdlPtr cascadeHandler() const; /** * Return a pointer (possibly null) to the assigned main * CascadeHandler to be used as CKKW-reweighter. */ tCascHdlPtr CKKWHandler() const { return cascadeHandler(); } /** * Gget current event. */ tEventPtr currentEvent() const { return theCurrentEvent; } /** * Get current collision. */ tCollPtr currentCollision() const { return theCurrentCollision; } /** * Get current step. */ tStepPtr currentStep() const { return theCurrentStep; } /** * Return true if this event handler should produce weightes events */ bool weighted() const { return weightedEvents; } /** * The level of statistics. Controlls the amount of statistics * written out after each run to the EventGenerators * .out file. */ int statLevel() const { return theStatLevel; } /** * Determines how often the event handler should check for charge * and energy-momentum conservation. */ ConsistencyLevel consistencyLevel() const { return theConsistencyLevel; } /** * The maximum fraction of the total invariant mass of a collision * that any of the components of the summed momentum is allowed to * change during the generation. */ double consistencyEpsilon() const { return theConsistencyEpsilon; } //@} /** @name Internal functions used by main functions and possibly from the outside. */ //@{ /** * Perform a given step using a handler and a hint. */ void performStep(tStepHdlPtr handler, tHintPtr hint); /** * In the curresnt list of step handlers to go through, add another * step handler and/or hint. */ void addStep(Group::Level, Group::Handler, tStepHdlPtr = tStepHdlPtr(), tHintPtr = tHintPtr()); /** * Create a new step and make it current. A StepHandler should be * supplied which will be set as the handler for the created * Step. */ tStepPtr newStep(tcStepHdlPtr sh) { currentStep(currentCollision()->newStep(sh)); return currentStep(); } /** * Remove the last step. */ void popStep() { currentCollision()->popStep(); currentStep(currentCollision()->finalStep()); } /** * Initialize the groups of step handlers. */ virtual void initGroups(); /** * Set current event. */ void currentEvent(tEventPtr e) { theCurrentEvent = e; } /** * Set current collision. */ void currentCollision(tCollPtr c) { theCurrentCollision = c; } /** * Set current step. */ void currentStep(tStepPtr s) { theCurrentStep = s; } /** * Get current StepHandler. */ tStepHdlPtr currentStepHandler() const { return theCurrentStepHandler; } /** * Set current StepHandler. */ void currentStepHandler(tStepHdlPtr sh) { theCurrentStepHandler = sh; } /** * Throw away the current event/collision. */ void throwCurrent(); /** * Throw away the last generated event before generating a new one. */ virtual void clean(); /** * Check that the charge and energy-momentum in the last step of the * current collision is consistent with the incoming particles. If * not, a warning will be generated. */ virtual void checkConsistency() const; //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interface. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} /** @name Standard Interfaced functions. */ //@{ /** * Finalize this object. Called in the run phase just after a * run has ended. Used eg. to write out statistics. */ virtual void dofinish() { clean(); HandlerBase::dofinish(); } /** * 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: /** * Access to the luminosity function. */ LuminosityFunction & lumiFn() { return *theLumiFn; } /** * Setup the step handler groups. */ void setupGroups(); /** * Access the step handler groups */ GroupVector & groups() { return theGroups; } /** * Access the step handler groups */ const GroupVector & groups() const { return theGroups; } protected: /** * Set the luminosity function */ void lumiFn(LumiFnPtr); private: /** * The maximum number of attempts to select a sub-process allowed * per event. */ long theMaxLoop; /** * True if this event handler should produce weightes events */ bool weightedEvents; /** * Controlls the amount of statistics written out after each run to * the EventGenerators .out file. */ int theStatLevel; /** * Determines how often the event handler should check for charge * and energy-momentum conservation. */ ConsistencyLevel theConsistencyLevel; /** * The maximum fraction of the total invariant mass of a collision * that any of the components of the summed momentum is allowed to * change during the generation. */ double theConsistencyEpsilon; /** * Pointer to a luminosity function tobe used by subclasses. */ LumiFnPtr theLumiFn; /** * The kinematical cuts to used by subclasses which do not provide * their own. */ CutsPtr theCuts; /** * A PartonExtractor object to be used by sub classes which do not * provide their own. */ PExtrPtr thePartonExtractor; /** * The SubProcessHandler group. */ HandlerGroup theSubprocessGroup; /** * The CascadeHandler group. */ HandlerGroup theCascadeGroup; /** * The MultipleInteractionHandler group. */ HandlerGroup theMultiGroup; /** * The HadronizationHandler group. */ HandlerGroup theHadronizationGroup; /** * The DecayHandler group. */ HandlerGroup theDecayGroup; /** * The step handler groups. */ GroupVector theGroups; /** * The current Event. */ EventPtr theCurrentEvent; /** * The current Collision. */ CollPtr theCurrentCollision; /** * The current Step. */ StepPtr theCurrentStep; /** * The current StepHandler. */ StepHdlPtr theCurrentStepHandler; protected: /** * Utility object to facilitate default selection of step handlers. */ HandlerGroup optSubprocessGroup; /** * Utility object to facilitate default selection of step handlers. */ HandlerGroup optCascadeGroup; /** * Utility object to facilitate default selection of step handlers. */ HandlerGroup optMultiGroup; /** * Utility object to facilitate default selection of step handlers. */ HandlerGroup optHadronizationGroup; /** * Utility object to facilitate default selection of step handlers. */ HandlerGroup optDecayGroup; protected: /** * Utility object to facilitate default selection of step handlers. */ GroupVector optGroups; protected: /** * Emit warning that this EventHandler is incomplete. */ bool warnIncomplete; /** * The pair of incoming particle types. Should be set by a subclass * which implements a complete EventHandler. */ cPDPair theIncoming; protected: /** @cond EXCEPTIONCLASSES */ /** * Exception class used by EventHandler when a StepHandler of the * wrong class was added. */ class EventHandlerStepError: public Exception {}; /** * Exception class used by EventHandler when not able to produce a * correct histogram scale. */ class EventHandlerHistError: public Exception {}; /** * Exception class used by EventHandler if asked to generate a * complete event. */ class EventHandlerIncompleteError: public Exception {}; /** Exception class used if too many attempts to generate an event * failed. */ struct EventLoopException: public Exception { /** Standard constructor. */ EventLoopException(const EventHandler &); }; /** * Exception class used if the assignment of a LuminosityFunction * failed */ struct LumiFuncError: public Exception {}; /** * Exception class used if inconsistent charge or energy-momentum was found. */ struct ConsistencyException: public Exception {}; /** @endcond */ private: ThePEG_DECLARE_PREPOST_GROUP(SubProcessHandler,Post); ThePEG_DECLARE_GROUPINTERFACE(CascadeHandler,CascHdlPtr); ThePEG_DECLARE_GROUPINTERFACE(MultipleInteractionHandler,MIHdlPtr); ThePEG_DECLARE_GROUPINTERFACE(HadronizationHandler,HadrHdlPtr); ThePEG_DECLARE_GROUPINTERFACE(DecayHandler,DecayHdlPtr); ThePEG_DECLARE_CLASS_DESCRIPTION(EventHandler); /** * Private and non-existent assignment operator. */ EventHandler & operator=(const EventHandler &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ ThePEG_DECLARE_CLASS_TRAITS(EventHandler,HandlerBase); /** @endcond */ } #endif /* ThePEG_EventHandler_H */ diff --git a/Handlers/EventManipulator.cc b/Handlers/EventManipulator.cc --- a/Handlers/EventManipulator.cc +++ b/Handlers/EventManipulator.cc @@ -1,28 +1,28 @@ // -*- C++ -*- // // EventManipulator.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the EventManipulator class. // #include "EventManipulator.h" #include "ThePEG/Interface/ClassDocumentation.h" using namespace ThePEG; AbstractNoPIOClassDescription EventManipulator::initEventManipulator; void EventManipulator::Init() { static ClassDocumentation documentation ("There is no documentation for the ThePEG::EventManipulator class"); } diff --git a/Handlers/EventManipulator.h b/Handlers/EventManipulator.h --- a/Handlers/EventManipulator.h +++ b/Handlers/EventManipulator.h @@ -1,105 +1,105 @@ // -*- C++ -*- // // EventManipulator.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_EventManipulator_H #define ThePEG_EventManipulator_H // This is the declaration of the EventManipulator class. #include "ThePEG/Interface/Interfaced.h" #include "ThePEG/Handlers/EventHandler.fh" #include namespace ThePEG { /** * An object of the EventManipulator class may be assigned to a * FullEventGenerator object. The manipulate() method is called for * each event generated, after the AnalysisHandlers have been called, * and may manipulate the event in any way needed. The manipulator may * alseo add StepHandlers to the EventHandler which produced the * event. The manipulate() method returns an integer which should be * zero if nothing was done to the event. If the EventHandler has * steps left to do, these are performed, after which the * AnalysisHandlers are called with the return value from * the previous manipulate() call. Then manipulate is called again and * the procedure is repeated until the EventHandler has no more steps * to do. * * @see \ref EventManipulatorInterfaces "The interfaces" * defined for EventManipulator. * @see FullEventGenerator * @see AnalysisHandler * @see EventHandler * @see StepHandler * */ class EventManipulator: public Interfaced { public: /** * Manipulate an event and the event handler. * @param eh the EventHandler in charge of the generation. * @param event the Event to be manipulated. * @return zero if the event was not manipulated. Otherwise return * an integer which will be given to the * AnalysisHandlers of the current FullEventGenerator. */ virtual int manipulate(tEHPtr eh, tEventPtr event) = 0; public: /** * Standard Init function used to initialize the interface. */ static void Init(); protected: private: /** * Describe an abstract class without persistent data. */ static AbstractNoPIOClassDescription initEventManipulator; /** * Private and non-existent assignment operator. */ EventManipulator & operator=(const EventManipulator &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** * This template specialization informs ThePEG about the * base class of EventManipulator. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the base class of EventManipulator. */ typedef Interfaced NthBase; }; /** * This template specialization informs ThePEG about the name of the * DecayHandler class and the shared object where it is defined. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return the class name. */ static string className() { return "ThePEG::EventManipulator"; } }; /** @endcond */ } #endif /* ThePEG_EventManipulator_H */ diff --git a/Handlers/FixedCMSLuminosity.cc b/Handlers/FixedCMSLuminosity.cc --- a/Handlers/FixedCMSLuminosity.cc +++ b/Handlers/FixedCMSLuminosity.cc @@ -1,64 +1,64 @@ // -*- C++ -*- // // FixedCMSLuminosity.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the FixedCMSLuminosity class. // #include "FixedCMSLuminosity.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/ClassDocumentation.h" using namespace ThePEG; FixedCMSLuminosity::~FixedCMSLuminosity() {} IBPtr FixedCMSLuminosity::clone() const { return new_ptr(*this); } IBPtr FixedCMSLuminosity::fullclone() const { return new_ptr(*this); } void FixedCMSLuminosity::setEnergy(Energy e) { beamEMaxA(e*0.5); beamEMaxB(e*0.5); } Energy FixedCMSLuminosity::getEnergy() const { return energy(); } NoPIOClassDescription FixedCMSLuminosity::initFixedCMSLuminosity; void FixedCMSLuminosity::Init() { static ClassDocumentation documentation ("The ThePEG::FixedCMSLuminosity class describes an experiment " "with incoming particles colliding with precicely defined and " "opposite momenta given by half the Energy."); static Parameter interfaceEnergy ("Energy", "The total energy in GeV in the cms of the colliding particles.", 0, GeV, 91.2*GeV, ZERO, ZERO, true, false, Interface::lowerlim, &FixedCMSLuminosity::setEnergy, &FixedCMSLuminosity::getEnergy, (Energy(FixedCMSLuminosity::*)()const)(0), (Energy(FixedCMSLuminosity::*)()const)(0), (Energy(FixedCMSLuminosity::*)()const)(0)); interfaceEnergy.setHasDefault(false); interfaceEnergy.rank(11); } diff --git a/Handlers/FixedCMSLuminosity.h b/Handlers/FixedCMSLuminosity.h --- a/Handlers/FixedCMSLuminosity.h +++ b/Handlers/FixedCMSLuminosity.h @@ -1,133 +1,133 @@ // -*- C++ -*- // // FixedCMSLuminosity.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_FixedCMSLuminosity_H #define ThePEG_FixedCMSLuminosity_H // This is the declaration of the FixedCMSLuminosity class. #include "LuminosityFunction.h" namespace ThePEG { /** * The FixedCMSLuminosity class describes an experiment with incoming * particles colliding with precicely defined and opposite momenta. It * is derived from the LuminosityFunction base class. * * \deprecated As the LuminosityFunction base class has increased * functionality (exceeding the functionality of this class) the use * of FixedCMSLuminosity is deprecated, and the class will be removed * in a future release. Note also that by setting the individual beam * energies in the base class, the behavior of this object may be * inconsistent, in that the collision will not, as specified, be in * the center-of-mass system. * * @see \ref FixedCMSLuminosityInterfaces "The interfaces" * defined for FixedCMSLuminosity. */ class FixedCMSLuminosity: public LuminosityFunction { public: /** @name Standard constructors and destructors. */ //@{ /** * Destructor. */ virtual ~FixedCMSLuminosity(); //@} public: /** * The total energy in the cms of the incoming particles. */ Energy energy() const { return maximumCMEnergy(); } public: /** * Standard Init function used to initialize the interface. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * Utility function used by the interface. */ void setEnergy(Energy); /** * Utility function used by the interface. */ Energy getEnergy() const; private: /** * Describe a concrete class with persistent data. */ static NoPIOClassDescription initFixedCMSLuminosity; /** * Private and non-existent assignment operator. */ FixedCMSLuminosity & operator=(const FixedCMSLuminosity &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** * This template specialization informs ThePEG about the * base class of FixedCMSLuminosity. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the base class of FixedCMSLuminosity. */ typedef LuminosityFunction NthBase; }; /** * This template specialization informs ThePEG about the name of the * FixedCMSLuminosity class and the shared object where it is defined. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return the class name. */ static string className() { return "ThePEG::FixedCMSLuminosity"; } /** Return the name of the shared library be loaded to get access to * the FixedCMSLuminosity class and every other class it uses * (except the base class). */ static string library() { return "FixedCMSLuminosity.so"; } }; /** @endcond */ } #endif /* ThePEG_FixedCMSLuminosity_H */ diff --git a/Handlers/FlavourGenerator.cc b/Handlers/FlavourGenerator.cc --- a/Handlers/FlavourGenerator.cc +++ b/Handlers/FlavourGenerator.cc @@ -1,95 +1,95 @@ // -*- C++ -*- // // FlavourGenerator.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the FlavourGenerator class. // #include "FlavourGenerator.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/PDT/ParticleData.h" using namespace ThePEG; tcPDPair FlavourGenerator::alwaysGenerateHadron(tcPDPtr q) const { tcPDPair hq = generateHadron(q); if ( !hq.first || ! hq.second ) throw FlavourGeneratorException() << "Flavour generator '" << name() << "' was not able to generate a " << "hadron from the flavour " << q->PDGName() << "." << Exception::runerror; return hq; } tcPDPtr FlavourGenerator::getBaryon(tcPDPtr q1, tcPDPtr q2, tcPDPtr q3) const { return getBaryon(q1->id(), q2->id(), q3->id()); } tcPDPtr FlavourGenerator::getBaryon(long iq1, long iq2, long iq3) const { return getBaryon(getParticleData(iq1), getParticleData(iq2), getParticleData(iq3)); } tcPDPtr FlavourGenerator:: alwaysGetBaryon(tcPDPtr q1, tcPDPtr q2, tcPDPtr q3) const { tcPDPtr ret = getBaryon(q1, q2, q3); if ( !ret ) throw FlavourGeneratorException() << "Flavour generator '" << name() << "' was not able to get a " << "baryon from the flavours " << q1->PDGName() << "," << q2->PDGName() << " and " << q3->PDGName() << "." << Exception::runerror; return ret; } tcPDPtr FlavourGenerator::alwaysGetBaryon(long iq1, long iq2, long iq3) const { tcPDPtr ret = getBaryon(iq1, iq2, iq3); if ( !ret ) throw FlavourGeneratorException() << "Flavour generator '" << name() << "' was not able to get a " << "baryon from the flavours " << iq1 << "," << iq2 << " and " << iq3 << "." << Exception::runerror; return ret; } tcPDPtr FlavourGenerator::getHadron(tcPDPtr q1, tcPDPtr q2) const { return getHadron(q1->id(), q2->id()); } tcPDPtr FlavourGenerator::getHadron(long iq1, long iq2) const { return getHadron(getParticleData(iq1), getParticleData(iq2)); } tcPDPtr FlavourGenerator::alwaysGetHadron(tcPDPtr q1, tcPDPtr q2) const { tcPDPtr ret = getHadron(q1, q2); if ( !ret ) throw FlavourGeneratorException() << "Flavour generator '" << name() << "' was not able to get a " << "hadron from the flavours " << q1->PDGName() << " and " << q2->PDGName() << "." << Exception::runerror; return ret; } tcPDPtr FlavourGenerator::alwaysGetHadron(long iq1, long iq2) const { tcPDPtr ret = getHadron(iq1, iq2); if ( !ret ) throw FlavourGeneratorException() << "Flavour generator '" << name() << "' was not able to get a " << "hadron from the flavours " << iq1 << " and " << iq2 << "." << Exception::runerror; return ret; } AbstractNoPIOClassDescription FlavourGenerator::initFlavourGenerator; void FlavourGenerator::Init() { static ClassDocumentation documentation ("This class is used to generate hadron types using a given flavour " "content."); } diff --git a/Handlers/FlavourGenerator.h b/Handlers/FlavourGenerator.h --- a/Handlers/FlavourGenerator.h +++ b/Handlers/FlavourGenerator.h @@ -1,223 +1,223 @@ // -*- C++ -*- // // FlavourGenerator.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_FlavourGenerator_H #define ThePEG_FlavourGenerator_H // This is the declaration of the FlavourGenerator class. #include "ThePEG/Config/ThePEG.h" #include "ThePEG/Handlers/HandlerBase.h" namespace ThePEG { /** * FlavourGenerator is an abstract base class to be used to implement * models describing the quark content of hadrons. FlavourGenerator * inherits from the HandlerBase class. * * The interface is based on the flavour generation implementation in * Pythia but is general enough to be used in other situations. The * main virtual functions to be overridden in subclasses are * generateHadron(tcPDPtr), getHadron(tcPDPtr, tcPDPtr), * getHadron(long, long) getBaryon(tcPDPtr, tcPDPtr, tcPDPtr), * getBaryon(long, long, long), selectQuark() and selectFlavour(). In * this base class the getHadron(tcPDPtr, tcPDPtr) and getHadron(long, * long) are implemented to call eachother, so a subclass must * implement at least one of them. The same thing is true for * getBaryon(tcPDPtr, tcPDPtr, tcPDPtr) and getBaryon(long, long, * long) * * @see \ref FlavourGeneratorInterfaces "The interfaces" * defined for FlavourGenerator. * @see HandlerBase */ class FlavourGenerator: public HandlerBase { public: /** @name Virtual functions to be overridden by subclasses. */ //@{ /** * Generate a hadron from a quark. Given a quark(antiquark, diquark * or antidiquark), choose a quark-antiquark (or * antidiquark-diquark) pair. Return (first) a hadron formed by the * original quark and the antiquark together with (second) the * generated quark. Returns null pointers if the generation failed. * @param quark a quark, antiquark, diquark or antidiquark. * @return a pair of ParticleData pointers. The \a first is the * hadron produced and the \a second is the anti-partner of the * (anti-)(di-)quark generated to form the hadron. */ virtual tcPDPair generateHadron(tcPDPtr quark) const = 0; /** * Same as generateHadron(tcPDPtr), but throws an exception if no * hadron could be produced. */ tcPDPair alwaysGenerateHadron(tcPDPtr quark) const; /** * Get hadron from flavours. Return a hadron with the flavour * content given by the (anti-)(di-)quarks in the argument. The * arguments are given as ParticleData pointers. The default * versions will call the getHadron(long, long). * @param q1 the first flavour. * @param q2 the second flavour. * @return the corresponding hadron type or null if none could be * generated. */ virtual tcPDPtr getHadron(tcPDPtr q1, tcPDPtr q2) const; /** * Get hadron from flavours. Return a hadron with the flavour * content given by the (anti-)(di-)quarks in the argument. The * arguments are given as PDG codes. The default * versions will call the getHadron(tcPDPtr, tcPDPtr). * @param iq1 the PDG code of the first flavour. * @param iq2 the PDG code of the second flavour. * @return the corresponding hadron type or null if none could be * generated. */ virtual tcPDPtr getHadron(long iq1, long iq2) const; /** * Same as getHadron(tcPDPtr, tcPDPtr) but thows an exception if no * hadron could be produced. */ tcPDPtr alwaysGetHadron(tcPDPtr q1, tcPDPtr q2) const; /** * Same as getHadron(long, long) but thows an exception if no hadron * could be produced. */ tcPDPtr alwaysGetHadron(long iq1, long iq2) const; /** * Return a baryon with the flavour content given by the * (anti)quarks in the argument. The arguments are given as * particle data pointers. The default versions will call * getBaryon(long, long, long). If no corresponding hadron was * formed it should return the null pointer. * @param q1 the first flavour. * @param q2 the second flavour. * @param q3 the third flavour. * @return the corresponding baryon type or null if none could be * generated. */ virtual tcPDPtr getBaryon(tcPDPtr q1, tcPDPtr q2, tcPDPtr q3) const; /** * Return a baryon with the flavour content given by the * (anti)quarks in the argument. The arguments are given as * particle data pointers. The default versions will call * getBaryon(tcPDPtr, tcPDPtr, tcPDPtr). If no corresponding hadron was * formed it should return the null pointer. * @param q1 the PDG code of the first flavour. * @param q2 the PDG code of the second flavour. * @param q3 the PDG code of the third flavour. * @return the corresponding baryon type or null if none could be * generated. */ virtual tcPDPtr getBaryon(long q1, long q2, long q3) const; /** * Same as getBaryon(tcPDPtr, tcPDPtr, tcPDPtr), but throws an * exception if no baryon could be produced. */ tcPDPtr alwaysGetBaryon(tcPDPtr q1, tcPDPtr q2, tcPDPtr q3) const; /** * Same as getBaryon(long, long, long), but throws an exception if * no baryon could be produced. */ tcPDPtr alwaysGetBaryon(long q1, long q2, long q3) const; /** * Generate a random quark flavour. */ virtual long selectQuark() const = 0; /** * Generate a random (di)quark flavour. */ virtual long selectFlavour() const = 0; //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interface. */ static void Init(); private: /** * Describe aa abstract class without persistent data. */ static AbstractNoPIOClassDescription initFlavourGenerator; /** * Private and non-existent assignment operator. */ FlavourGenerator & operator=(const FlavourGenerator &) = delete; }; /** @cond EXCEPTIONCLASSES */ /** An Exception class used by FlavourGenerator classes if no hadrons could be generated. */ class FlavourGeneratorException: public Exception {}; /** @endcond */ /** @cond TRAITSPECIALIZATIONS */ /** * This template specialization informs ThePEG about the * base class of FlavourGenerator. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the base class of FlavourGenerator. */ typedef HandlerBase NthBase; }; /** * This template specialization informs ThePEG about the name of the * DecayHandler class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return the class name. */ static string className() { return "ThePEG::FlavourGenerator"; } }; /** @endcond */ } #endif /* ThePEG_FlavourGenerator_H */ diff --git a/Handlers/GaussianPtGenerator.cc b/Handlers/GaussianPtGenerator.cc --- a/Handlers/GaussianPtGenerator.cc +++ b/Handlers/GaussianPtGenerator.cc @@ -1,79 +1,79 @@ // -*- C++ -*- // // GaussianPtGenerator.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the GaussianPtGenerator class. // #include "GaussianPtGenerator.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Vectors/Transverse.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG; GaussianPtGenerator::~GaussianPtGenerator() {} IBPtr GaussianPtGenerator::clone() const { return new_ptr(*this); } IBPtr GaussianPtGenerator::fullclone() const { return new_ptr(*this); } TransverseMomentum GaussianPtGenerator::generate() const { pair ret; Energy pt = ZERO; while ( ( pt = theSigma*sqrt(-log(rnd())) ) > theUpperCut ) {} double phi = rnd(2.0*Constants::pi); ret.first = pt*cos(phi); ret.second = pt*sin(phi); return ret; } void GaussianPtGenerator::persistentOutput(PersistentOStream & os) const { os << ounit(theSigma, GeV) << ounit(theUpperCut, GeV); } void GaussianPtGenerator::persistentInput(PersistentIStream & is, int) { is >> iunit(theSigma, GeV) >> iunit(theUpperCut, GeV); } ClassDescription GaussianPtGenerator::initGaussianPtGenerator; // Definition of the static class description member. void GaussianPtGenerator::Init() { static ClassDocumentation documentation ("The ThePEG::GaussianPtGenerator class generates a gaussian " "transverse momentum."); static Parameter interfaceSigma ("Sigma", "The width of the Gaussian distribution. The average squared transverse " "momentum is Sigma squared.", &GaussianPtGenerator::theSigma, GeV, 1.0*GeV, ZERO, 10.0*GeV, true, false, true); static Parameter interfaceUpperCut ("UpperCut", "Upper cutoff for the transverse momentum distribution.", &GaussianPtGenerator::theUpperCut, GeV, 5.0*GeV, ZERO, 50.0*GeV, true, false, true); interfaceSigma.rank(10); } diff --git a/Handlers/GaussianPtGenerator.h b/Handlers/GaussianPtGenerator.h --- a/Handlers/GaussianPtGenerator.h +++ b/Handlers/GaussianPtGenerator.h @@ -1,163 +1,163 @@ // -*- C++ -*- // // GaussianPtGenerator.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_GaussianPtGenerator_H #define THEPEG_GaussianPtGenerator_H // This is the declaration of the GaussianPtGenerator class. #include "ThePEG/Handlers/PtGenerator.h" namespace ThePEG { /** * GaussianPtGenerator inherits from the abstract PtGenerator * class. It will generate a transverse momentum distributed according * to a gaussian. * * @see \ref GaussianPtGeneratorInterfaces "The interfaces" * defined for GaussianPtGenerator. */ class GaussianPtGenerator: public PtGenerator { public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ GaussianPtGenerator() : theSigma(1.0*GeV), theUpperCut(5.0*GeV) {} /** * Destructor. */ virtual ~GaussianPtGenerator(); //@} public: /** @name Virtual functions required by the PtGenerator class. */ //@{ /** * Generate (\f$k_x, k_y\f$) components of the transverse * momentum. They will be distributed as * \f$\exp(-k_\perp^2/\sigma^2)k_\perp dk_\perp\f$ with * \f$k_\perp^2=k_x^2+k_y^2\f$ and \f$\sigma=\f$ theSigma. The * distribution is cutoff at \f$k_\perp=\f$ theUpperCut. */ virtual TransverseMomentum generate() const; //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interfaces. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * The width of the Gaussian distribution. The average squared * transverse momentum is theSigma squared. */ Energy theSigma; /** * Upper cutoff for the transverse momentum distribution. */ Energy theUpperCut; private: /** * Describe a concrete class with persistent data. */ static ClassDescription initGaussianPtGenerator; /** * Private and non-existent assignment operator. */ GaussianPtGenerator & operator=(const GaussianPtGenerator &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** * This template specialization informs ThePEG about the * base class of GaussianPtGenerator. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the base class of GaussianPtGenerator. */ typedef PtGenerator NthBase; }; /** * This template specialization informs ThePEG about the name of the * GaussianPtGenerator class and the shared object where it is * defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return the class name. */ static string className() { return "ThePEG::GaussianPtGenerator"; } /** Return the name of the shared library to be loaded to get access * to the GaussianPtGenerator class and every other class it uses * (except the base class). */ static string library() { return "GaussianPtGenerator.so"; } }; /** @endcond */ } #endif /* THEPEG_GaussianPtGenerator_H */ diff --git a/Handlers/HadronizationHandler.cc b/Handlers/HadronizationHandler.cc --- a/Handlers/HadronizationHandler.cc +++ b/Handlers/HadronizationHandler.cc @@ -1,28 +1,28 @@ // -*- C++ -*- // // HadronizationHandler.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the HadronizationHandler class. // #include "HadronizationHandler.h" #include "ThePEG/Interface/ClassDocumentation.h" using namespace ThePEG; AbstractNoPIOClassDescription HadronizationHandler::initHadronizationHandler; void HadronizationHandler::Init() { static ClassDocumentation documentation ("This is the base class to be used by all models for hadronization."); } diff --git a/Handlers/HadronizationHandler.h b/Handlers/HadronizationHandler.h --- a/Handlers/HadronizationHandler.h +++ b/Handlers/HadronizationHandler.h @@ -1,81 +1,81 @@ // -*- C++ -*- // // HadronizationHandler.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_HadronizationHandler_H #define ThePEG_HadronizationHandler_H // This is the declaration of the HadronizationHandler class. #include "StepHandler.h" namespace ThePEG { /** * The HadronizationHandler is the base class of all handlers * implementing models for hadronization of coloured particles. It is * derived from the more general StepHandler class, but does not * introduce more functioanality as it stands. * * @see \ref HadronizationHandlerInterfaces "The interfaces" * defined for HadronizationHandler. * @see StepHandler * @see EventHandler * @see SubProcessHandler * */ class HadronizationHandler: public StepHandler { public: /** * Standard Init function used to initialize the interface. */ static void Init(); private: /** * Describe an abstract class without persistent data. */ static AbstractNoPIOClassDescription initHadronizationHandler; /** * Private and non-existent assignment operator. */ HadronizationHandler & operator=(const HadronizationHandler &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** * This template specialization informs ThePEG about the * base class of HadronizationHandler. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the base class of HadronizationHandler. */ typedef StepHandler NthBase; }; /** * This template specialization informs ThePEG about the name of the * HadronizationHandler class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return the class name. */ static string className() { return "ThePEG::HadronizationHandler"; } }; /** @endcond */ } #endif /* ThePEG_HadronizationHandler_H */ diff --git a/Handlers/HandlerBase.cc b/Handlers/HandlerBase.cc --- a/Handlers/HandlerBase.cc +++ b/Handlers/HandlerBase.cc @@ -1,21 +1,21 @@ // -*- C++ -*- // // HandlerBase.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the HandlerBase class. // #include "HandlerBase.h" using namespace ThePEG; AbstractNoPIOClassDescription HandlerBase::initHandlerBase; void HandlerBase::Init() {} diff --git a/Handlers/HandlerBase.h b/Handlers/HandlerBase.h --- a/Handlers/HandlerBase.h +++ b/Handlers/HandlerBase.h @@ -1,201 +1,201 @@ // -*- C++ -*- // // HandlerBase.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_HandlerBase_H #define ThePEG_HandlerBase_H // This is the declaration of the HandlerBase class. #include "ThePEG/Interface/Interfaced.h" #include "ThePEG/Repository/UseRandom.fh" #include "ThePEG/Repository/EventGenerator.h" #include namespace ThePEG { template /** * HandlerBaseT is a dummy abstract templated class used as base class * to HandlerBase. HandlerBaseT inherits from the Interfaced class * adding some functionality such as easy acces to the RandomGenerator * and the StandardModel object of the controlling EventGenerator * object. The HandlerBaseT should only be used by the HandlerBase as * a base class. The fact that it is templated allows classes which in * turn inherits from HandlerBase to not explicitly depend on * EventGenerator class if the inlined accessor funtions are not * actually used. The only class which actually works as a template * argument is UseRandom, which is used to generate random numbers. * * @see Interfaced * @see RandomGenerator * @see StandardModel * @see EventGenerator * */ class HandlerBaseT: public Interfaced { public: /** HandlerBase is a friend. */ friend class HandlerBase; private: /** @name Standard constructors and destructors are private and can * only be used from the HandlerBase class. */ //@{ /** * Default constructor. */ HandlerBaseT() {} public: /** * Destructor. */ virtual ~HandlerBaseT() {} //@} public: /** * Return a simple flat random number in the range ]0,1[. */ double rnd() const { return T::rnd(); } /** * Return a simple flat random number in the range ]0,\a xu[. */ double rnd(double xu) const { return T::rnd(xu); } /** * Return a simple flat random number in the range ]\a xl,\a xu[. */ double rnd(double xl, double xu) const { return T::rnd(xl, xu); } /** * Return true with 50% probability. */ bool rndbool() const { return T::rndbool(); } /** * Return a true with probability \a p. */ bool rndbool(double p) const { return T::rndbool(p); } /** * Return a true with probability \a p1/(\a p1+\a p2). */ bool rndbool(double p1, double p2) const { return T::rndbool(p1, p2); } /** * Return -1, 0, or 1 with relative probabilities \a p1, \a p2, \a p3. */ int rndsign(double p1, double p2, double p3) const { return T::rndsign(p1, p2, p3); } /** * Return an integer \f$i\f$ with probability p\f$i\f$/(\a p0+\a p1). */ int rnd2(double p0, double p1) const { return T::rnd2(p0, p1); } /** * Return an integer \f$i\f$ with probability p\f$i\f$/(\a p0+\a * p1+\a p2). */ int rnd3(double p0, double p1, double p2) const { return T::rnd3(p0, p1, p2); } /** * Return an integer/ \f$i\f$ with probability p\f$i\f$(\a p0+\a * p1+\a p2+\a p3). */ int rnd4(double p0, double p1, double p2, double p3) const { return T::rnd4(p0, p1, p2, p3); } /** * Return a simple flat random integrer number in the range [0,\a xu[. */ long irnd(long xu = 2) const { return T::irnd(xu); } /** * Return a simple flat random integrer number in the range [\a xl,\a xu[. */ long irnd(long xl, long xu) const { return T::irnd(xl, xu); } /** * Return a reference to the object containing the standard model * parameters for this run. */ const StandardModelBase & SM() const { return *standardModel(); } /** * Return a pointer to the object containing the standard model * parameters for this run. */ tSMPtr standardModel() const { return generator()->standardModel(); } }; /** * HandlerBase is an abstract base class derived from the Interfaced * class via the HandlerBaseT class adding some functionality such as * easy acces to the RandomGenerator and the StandardModel object of * the controlling EventGenerator object. * * @see Interfaced * @see RandomGenerator * @see StandardModel * @see EventGenerator * */ class HandlerBase: public HandlerBaseT { public: /** * Standard Init function used to initialize the interface. */ static void Init(); private: /** * Describe an abstract class without persistent data. */ static AbstractNoPIOClassDescription initHandlerBase; /** * Private and non-existent assignment operator. */ HandlerBase & operator=(const HandlerBase &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** * This template specialization informs ThePEG about the * base class of HandlerBase. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the base class of HandlerBase. Note that HandlerBaseT * is not treated as a base class in this respect. */ typedef Interfaced NthBase; }; /** * This template specialization informs ThePEG about the name of the * HandlerBase class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return the class name. */ static string className() { return "ThePEG::HandlerBase"; } }; /** @endcond */ } #endif /* ThePEG_HandlerBase_H */ diff --git a/Handlers/HandlerGroup.cc b/Handlers/HandlerGroup.cc --- a/Handlers/HandlerGroup.cc +++ b/Handlers/HandlerGroup.cc @@ -1,224 +1,224 @@ // -*- C++ -*- // // HandlerGroup.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the HandlerGroup class. // #include "ThePEG/Handlers/HandlerGroup.h" #include "ThePEG/Handlers/StepHandler.h" #include "ThePEG/Handlers/Hint.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Utilities/Throw.h" #include #ifdef ThePEG_TEMPLATES_IN_CC_FILE #include "HandlerGroup.tcc" #endif using namespace ThePEG; HandlerGroupBase::HandlerGroupBase() : isEmpty(true) {} HandlerGroupBase::HandlerGroupBase(const HandlerGroupBase & hg) : isEmpty(hg.isEmpty), theDefaultPreHandlers(hg.theDefaultPreHandlers), theDefaultPostHandlers(hg.theDefaultPostHandlers), thePreHandlers(hg.thePreHandlers), theHints(hg.theHints), thePostHandlers(hg.thePostHandlers) {} HandlerGroupBase::~HandlerGroupBase() {} HandlerGroupBase::StepWithHint HandlerGroupBase::next() { StepWithHint sh = make_pair(StepHdlPtr(), HintPtr()); if ( isEmpty ) return sh; if ( !thePreHandlers.empty() ) { sh = thePreHandlers.back(); thePreHandlers.pop_back(); return sh; } if ( handler() ) { if ( !theHints.empty() ) { sh.first = handler(); sh.second = theHints.back(); theHints.pop_back(); return sh; } else setHandler(); } if ( !thePostHandlers.empty() ) { sh = thePostHandlers.back(); thePostHandlers.pop_back(); return sh; } isEmpty = true; return sh; } void HandlerGroupBase::addPreHandler(tStepHdlPtr s, tHintPtr h, const HandlerGroupBase & ext) { if ( !s ) return; if ( !handler() ) refillDefaults(ext); thePreHandlers.push_back(make_pair(s, h)); isEmpty = false; } void HandlerGroupBase::addPostHandler(tStepHdlPtr s, tHintPtr h, const HandlerGroupBase & ext) { if ( !s ) return; if ( empty() ) refillDefaults(ext); thePostHandlers.push_back(make_pair(s, h)); isEmpty = false; } void HandlerGroupBase:: addHint(tHintPtr h, const HandlerGroupBase & ext) { if ( !handler() || theHints.empty() ) refillDefaults(ext); if ( count(theHints.begin(), theHints.end(), h) ) return; theHints.push_back(h); isEmpty = false; } void HandlerGroupBase::clear() { thePreHandlers.clear(); theHints.clear(); thePostHandlers.clear(); isEmpty = true; } void HandlerGroupBase::refillDefaults(const HandlerGroupBase & ext) { checkInsert(thePreHandlers, preHandlers()); checkInsert(thePreHandlers, ext.preHandlers()); refillDefaultHandler(ext.defaultHandler()); checkInsert(thePostHandlers, postHandlers()); checkInsert(thePostHandlers, ext.postHandlers()); } void HandlerGroupBase:: checkInsert(StepHintVector & handlers, const StepVector & defHandlers) { for ( StepVector::const_reverse_iterator r = defHandlers.rbegin(); r != defHandlers.rend(); ++r ) { try { for ( StepHintVector::iterator i = handlers.begin(); i != handlers.end(); ++i ) if ( i->first == *r && i->second == Hint::Default() ) throw int(); handlers.push_back(make_pair(*r, Hint::Default())); isEmpty = false; } catch (int) {} } } namespace { void warning(tStepHdlPtr p, const HandlerGroupBase::StepVector & v) { for ( HandlerGroupBase::StepVector::const_iterator i = v.begin(); i != v.end(); ++i) { if ( p == *i ) { Throw() << "\n\nWarning: Double insertion of " << p->fullName() << ".\n" << " Do you intend to run the handler more than once?\n\n" << Exception::warning; break; } } } } void HandlerGroupBase::interfaceSetPrehandler(StepHdlPtr p, int i) { if ( i >= 0 && unsigned(i) < preHandlers().size() && preHandlers()[i] != p ) { warning( p, preHandlers() ); preHandlers()[i] = p; } } void HandlerGroupBase::interfaceSetPosthandler(StepHdlPtr p, int i) { if ( i >= 0 && unsigned(i) < postHandlers().size() && postHandlers()[i] != p ) { warning( p, postHandlers() ); postHandlers()[i] = p; } } void HandlerGroupBase::interfaceInsertPrehandler(StepHdlPtr p, int i) { if ( i >= 0 && unsigned(i) <= preHandlers().size() ) { warning( p, preHandlers() ); preHandlers().insert(preHandlers().begin() + i, p); } } void HandlerGroupBase::interfaceInsertPosthandler(StepHdlPtr p, int i) { if ( i >= 0 && unsigned(i) <= postHandlers().size() ) { warning( p, postHandlers() ); postHandlers().insert(postHandlers().begin() + i, p); } } void HandlerGroupBase::interfaceErasePrehandler(int i) { if ( i >= 0 && unsigned(i) < preHandlers().size() ) preHandlers().erase(preHandlers().begin() + i); } void HandlerGroupBase::interfaceErasePosthandler(int i) { if ( i >= 0 && unsigned(i) < postHandlers().size() ) postHandlers().erase(postHandlers().begin() + i); } vector HandlerGroupBase::interfaceGetPrehandlers() const { return preHandlers(); } vector HandlerGroupBase::interfaceGetPosthandlers() const { return postHandlers(); } void HandlerGroupBase::write(PersistentOStream & os) const { os << isEmpty << theDefaultPreHandlers << theDefaultPostHandlers; os << thePreHandlers.size(); for ( StepHintVector::const_iterator it = thePreHandlers.begin(); it != thePreHandlers.end(); ++it ) os << it->first << (it->second == Hint::Default()? HintPtr(): it->second); os << theHints.size(); for ( HintVector::const_iterator it = theHints.begin(); it != theHints.end(); ++it ) os << ( *it == Hint::Default()? HintPtr(): *it ); os << thePostHandlers.size(); for ( StepHintVector::const_iterator it = thePostHandlers.begin(); it != thePostHandlers.end(); ++it ) os << it->first << (it->second == Hint::Default()? HintPtr(): it->second); } void HandlerGroupBase::read(PersistentIStream & is) { is >> isEmpty >> theDefaultPreHandlers >> theDefaultPostHandlers; tStepHdlPtr sh; HintPtr h; long size; thePreHandlers.clear(); is >> size; while ( size-- ) { is >> sh >> h; if ( !h ) h = Hint::Default(); thePreHandlers.push_back(make_pair(sh,h)); } is >> size; while ( size-- ) { is >> h; if ( !h ) h = Hint::Default(); theHints.push_back(h); } is >> size; while ( size-- ) { is >> sh >> h; if ( !h ) h = Hint::Default(); thePostHandlers.push_back(make_pair(sh,h)); } } diff --git a/Handlers/HandlerGroup.h b/Handlers/HandlerGroup.h --- a/Handlers/HandlerGroup.h +++ b/Handlers/HandlerGroup.h @@ -1,545 +1,545 @@ // -*- C++ -*- // // HandlerGroup.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_HandlerGroup_H #define ThePEG_HandlerGroup_H // This is the declaration of the HandlerGroup class. #include "ThePEG/Config/ThePEG.h" // #include "HandlerGroup.fh" // #include "HandlerGroup.xh" namespace ThePEG { /** * HandlerGroupBase is the base class for the templated HandlerGroup * utility class to manage a group of StepHandlers. * * The derived StepHandler has a main StepHandler (CascadeHandler, * MultipleInteractionHandler, HadronizationHandler or DecayHandler) * while this bease class has a list of pre-hadlers and a list of * post-handlers. * * The HandlerGroup class is used in the * EventHandler and SubProcessHandler to manage the * post-sub-process handler, the cascade, multiple interaction, * hadronization and decay handler groups. When an event is generated, * after the main sub-process is performed, all handler groups are * processed in turn. In each group the pre-hadnlers are run first, * followed by the main handler (which may be run several times is * more than one Hint has been specified) and finally the * post-handlers are run. * * When a group is initialised before each run, an auxilliary * HandlerGroupBase object may be specified to override the default * handlers in this group. * * @see HandlerGroup */ class HandlerGroupBase { public: /** Associate a StepHandler with a Hint object. */ typedef pair StepWithHint; /** A vector of StepHandler objects. */ typedef vector StepVector; /** A vector of StepHandler objects associated with Hint objects. */ typedef vector StepHintVector; /** A vector of Hint objects. */ typedef deque HintVector; public: /** * Default constructor. */ HandlerGroupBase(); /** * Destructor. */ virtual ~HandlerGroupBase(); /** * Returns true if current selections in this group is empty. */ bool empty() const { return isEmpty; } /** * Initialize, taking the default StepHandlers as the current ones, * possibly overridden by the default ones in the auxilliary group * supplied in the argument. */ void init(const HandlerGroupBase & ext) { clear(); refillDefaults(ext); } /** * Return the next step; */ StepWithHint next(); /** * Add a step handler, \a sh to the current list of * pre-handlers. Optionally a \a hint may be specified. If the main * handler has already been executed, the object is reinitialized * using \a ext to override defaults. */ void addPreHandler(tStepHdlPtr sh, tHintPtr hint, const HandlerGroupBase & ext); /** * Add a step handler, \a sh, to the current list of * post-handlers. Optionally a \a hint may be specified. If the main * handler has already been executed, the object is reinitialized * using \a ext to override defaults. */ void addPostHandler(tStepHdlPtr sh, tHintPtr hint, const HandlerGroupBase &); /** * Add a \a hint to the currently selected main handler. If the main * handler has already been executed, the object is reinitialized * using \a ext to override defaults. */ void addHint(tHintPtr hint, const HandlerGroupBase & ext); /** * Return a reference to the list of default pre-handlers. */ StepVector & preHandlers() { return theDefaultPreHandlers; } /** * Return a reference to the list of default pre-handlers. */ const StepVector & preHandlers() const { return theDefaultPreHandlers; } /** * Return a pointer to the default main handler. */ virtual tStepHdlPtr defaultHandler() const = 0; /** * Return a reference to the list of default post-handlers. */ StepVector & postHandlers() { return theDefaultPostHandlers; } /** * Return a reference to the list of default post-handlers. */ const StepVector & postHandlers() const { return theDefaultPostHandlers; } /** * Return a pointer to the current main handler. */ virtual tStepHdlPtr handler() const = 0; /** * Unset the current main handler. */ virtual void setHandler() = 0; /** * Set the current main handler, but also refill the current pre- * and post- handlers with the defaults from \a ext. */ virtual bool setHandler(tStepHdlPtr, const HandlerGroupBase & ext) = 0; /** * Set the current main handler. If the null pointer use the default * main handler. */ virtual void refillDefaultHandler(tStepHdlPtr) = 0; /** * Fill main, pre- and post- handlers with the default ones. The * default handlers in the argument takes precedence to this. */ void refillDefaults(const HandlerGroupBase &); /** * Clear all current handlers, but don't touch the default ones. */ virtual void clear(); /** * Return the base class name of the main handler type. */ virtual string handlerClass() const = 0; /** * Utility function used for the interface. */ void interfaceSetPrehandler(StepHdlPtr p, int i); /** * Utility function used for the interface. */ void interfaceInsertPrehandler(StepHdlPtr p, int i); /** * Utility function used for the interface. */ void interfaceErasePrehandler(int i); /** * Utility function used for the interface. */ vector interfaceGetPrehandlers() const; /** * Utility function used for the interface. */ void interfaceSetPosthandler(StepHdlPtr p, int i); /** * Utility function used for the interface. */ void interfaceInsertPosthandler(StepHdlPtr p, int i); /** * Utility function used for the interface. */ void interfaceErasePosthandler(int i); /** * Utility function used for the interface. */ vector interfaceGetPosthandlers() const; /** * Write to persistent streams. */ virtual void write(PersistentOStream &) const; /** * Read from persistent streams. */ virtual void read(PersistentIStream &); protected: /** * The copy constructor is only used via subclasses. */ HandlerGroupBase(const HandlerGroupBase &); /** * True if the current handlers are empty. */ bool isEmpty; private: /** * Add handlers from the def vector to the current, supplying them * with default hints. */ void checkInsert(StepHintVector & current, const StepVector & def); protected: /** * The default pre-handlers with hints. */ StepVector theDefaultPreHandlers; /** * The default post-handlers with hints. */ StepVector theDefaultPostHandlers; /** * The current pre-handlers with hints. */ StepHintVector thePreHandlers; /** * The current hints for the main handler. */ HintVector theHints; /** * The current post-handlers with hints. */ StepHintVector thePostHandlers; private: /** * Assignment is private. */ HandlerGroupBase & operator=(const HandlerGroupBase &) = delete; }; /** * HandlerGroup is a templated utility class to manage a * group of StepHandlers. All HandlerGroup * classes are derived from the HandlerGroupBase class. As * an example the specialization * HandlerGroup keeps a * CascadeHandler object and associated pre- and * post- StepHandlers, defining shich steps should be * performed before the perturbative cascade, which object should be * used for the cascade and which steps should be performed after. * * The HandlerGroup keesp both a default main handler and * the corresponding default pre- and post- handlers as well as the * main handler and pre/post hadlers chosen for the current event. The * current handlers are accompanied by Hints. Handlers which are * copied from the default ones are accompanied by the default Hint, * while handlers supplied from the outside may be accompanied by any * kind of hint. The main handler can be supplied with several hints, * the pre- and post- handlers may only have one hint each. * * The HandlerGroup class is used in the * EventHandler and SubProcessHandler to manage the * post-sub-process handler, the cascade, multiple interaction, * hadronization and decay handler groups. * * @see EventHandler * @see SubProcessHandler * @see StepHandler * @see CascadeHandler * @see MultipleInteractionHandler * @see HadronizationHandler * @see DecayHandler * */ template class HandlerGroup: public HandlerGroupBase { public: /** A pointer to the template argument class. */ typedef typename Ptr::pointer HdlPtr; /** A transient pointer to the template argument class. */ typedef typename Ptr::transient_pointer tHdlPtr; public: /** * Destructor. */ virtual ~HandlerGroup(); /** * Set the current main handler. Also refill the current pre- and * post- handlers with the defaults from \a ext. */ virtual bool setHandler(tStepHdlPtr, const HandlerGroupBase & ext); /** * Unset the current main handler. */ virtual void setHandler() { theHandler = HdlPtr(); } /** * Return a pointer to the current main handler. */ virtual tStepHdlPtr handler() const { return dynamic_ptr_cast(theHandler); } /** * Return a pointer to the default main handler. */ virtual tStepHdlPtr defaultHandler() const { return dynamic_ptr_cast(theDefaultHandler); } /** * Set the current main handler. If the null pointer use the default * main handler. */ virtual void refillDefaultHandler(tStepHdlPtr); /** * Clear all current handlers, but don't touch the default ones. */ virtual void clear(); /** * Return the base class name of the main handler type. */ virtual string handlerClass() const; /** * Utility function used for the interface. */ void interfaceSetHandler(HdlPtr); /** * Utility function used for the interface. */ HdlPtr interfaceGetHandler() const; /** * Write to persistent streams. */ virtual void write(PersistentOStream & os) const { os << theDefaultHandler << theHandler; HandlerGroupBase::write(os); } /** * Read from persistent streams. */ virtual void read(PersistentIStream & is) { is >> theDefaultHandler >> theHandler; HandlerGroupBase::read(is); } private: /** * The default main handler. */ HdlPtr theDefaultHandler; /** * The current main handler. */ HdlPtr theHandler; private: /** * Assignment is private. */ HandlerGroup & operator=(const HandlerGroup &) = delete; }; /** Namespace to encapsulate enums related to HandlerGroups. */ namespace Group { /** * Enumeration for the type of HandlerGroups. */ enum Handler { subproc, /**< The sub-process group. */ cascade, /**< The CascadeHandler group. */ multi, /**< The MultipleInteractionHandler group. */ hadron, /**< The HadronizationHandler group. */ decay /**< The DecayHandler group. */ }; /** Enumeration for the type of step handler */ enum Level { before, /**< A pre-handler. */ main, /**< The mainhandler. */ after /**< A post-handler. */ }; } /** Output a HandlerGroup to a PersistentOStream. */ template inline PersistentOStream & operator<<(PersistentOStream & os, const HandlerGroup & hg) { hg.write(os); return os; } /** Input a HandlerGroup from a PersistentIStream. */ template inline PersistentIStream & operator>>(PersistentIStream & is, HandlerGroup & hg) { hg.read(is); return is; } } /** Macro for declaring a prepost group */ #define ThePEG_DECLARE_PREPOST_GROUP(HandlerClass,prepost) \ /** Utility function for the interface. */ \ void interfaceSet##prepost##HandlerClass(StepHdlPtr, int); \ /** Utility function for the interface. */ \ void interfaceInsert##prepost##HandlerClass(StepHdlPtr, int); \ /** Utility function for the interface. */ \ void interfaceErase##prepost##HandlerClass(int); \ /** Utility function for the interface. */ \ vector interfaceGet##prepost##HandlerClass() const /** Macro for declaring a group interface */ #define ThePEG_DECLARE_GROUPINTERFACE(HandlerClass,ptr) \ ThePEG_DECLARE_PREPOST_GROUP(HandlerClass,Pre); \ /** Utility function for the interface. */ \ void interfaceSet##HandlerClass(ptr); \ /** Utility function for the interface. */ \ ptr interfaceGet##HandlerClass() const; \ ThePEG_DECLARE_PREPOST_GROUP(HandlerClass,Post) /** Macro for implementing a prepost group. */ #define ThePEG_IMPLEMENT_PREPOST_GROUP(ThisClass,HandlerClass,member,pp) \ void ThisClass::interfaceSet##pp##HandlerClass(StepHdlPtr p , int i) { \ member.interfaceSet##pp##handler(p,i); \ } \ void ThisClass::interfaceInsert##pp##HandlerClass(StepHdlPtr p, int i) { \ member.interfaceInsert##pp##handler(p,i); \ } \ void ThisClass::interfaceErase##pp##HandlerClass(int i) { \ member.interfaceErase##pp##handler(i); \ } \ vector ThisClass::interfaceGet##pp##HandlerClass() const { \ return member.interfaceGet##pp##handlers(); \ } /** Macro for implementing a group interface. */ #define ThePEG_IMPLEMENT_GROUPINTERFACE(ThisClass,HandlerClass,member,ptr) \ ThePEG_IMPLEMENT_PREPOST_GROUP(ThisClass,HandlerClass,member,Pre) \ void ThisClass::interfaceSet##HandlerClass(ptr p) { \ member.interfaceSetHandler(p); \ } \ ptr ThisClass::interfaceGet##HandlerClass() const { \ return member.interfaceGetHandler(); \ } \ ThePEG_IMPLEMENT_PREPOST_GROUP(ThisClass,HandlerClass,member,Post) \ /** Macro for declaring prepost objects. */ #define ThePEG_DECLARE_PREPOST_OBJECTS(ThisClass,HandlerClass,pp,ba) \ static RefVector interface##pp##HandlerClass \ (#pp #HandlerClass "s", \ "A list of handlers to be called " #ba " the " #HandlerClass ". " \ "If handler objects are specified in a EventHandler and " \ "the SubProcessHandler chosen in a given collision also specifies some, " \ "the latter will caled first.", \ 0, 0, false, false, true, false, \ &ThisClass::interfaceSet##pp##HandlerClass, \ &ThisClass::interfaceInsert##pp##HandlerClass, \ &ThisClass::interfaceErase##pp##HandlerClass, \ &ThisClass::interfaceGet##pp##HandlerClass) /** Macro for declaring group interface objects. */ #define ThePEG_DECLARE_GROUPINTERFACE_OBJECTS(ThisClass,HandlerClass) \ ThePEG_DECLARE_PREPOST_OBJECTS(ThisClass,HandlerClass,Pre, before); \ static Reference interface ## HandlerClass \ (#HandlerClass, \ "The " #HandlerClass " object used in this " #ThisClass ". " \ "If a " #HandlerClass " object is specified in a EventHandler and " \ "the SubProcessHandler chosen in a given collision also specifies one," \ "the latter will be used.", \ 0, false, false, true, true, \ &ThisClass::interfaceSet ## HandlerClass, \ &ThisClass::interfaceGet ## HandlerClass); \ ThePEG_DECLARE_PREPOST_OBJECTS(ThisClass,HandlerClass,Post, after) #ifndef ThePEG_TEMPLATES_IN_CC_FILE #include "HandlerGroup.tcc" #endif #endif /* ThePEG_HandlerGroup_H */ diff --git a/Handlers/HandlerGroup.tcc b/Handlers/HandlerGroup.tcc --- a/Handlers/HandlerGroup.tcc +++ b/Handlers/HandlerGroup.tcc @@ -1,68 +1,68 @@ // -*- C++ -*- // // HandlerGroup.tcc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined templated member // functions of the HandlerGroup class. // #include "ThePEG/Utilities/ClassTraits.h" #include "ThePEG/Handlers/Hint.h" namespace ThePEG { template HandlerGroup::~HandlerGroup() {} template bool HandlerGroup::setHandler(tStepHdlPtr hin, const HandlerGroupBase & ext) { tHdlPtr h = dynamic_ptr_cast(hin); if ( !h ) return false; if ( !theHandler ) refillDefaults(ext); theHandler = h; isEmpty = false; return true; } template void HandlerGroup::refillDefaultHandler(tStepHdlPtr h) { tHdlPtr ext = dynamic_ptr_cast(h); if ( ext ) theHandler = ext; else theHandler = theDefaultHandler; if ( theHandler ) { for ( int i = 0, N = theHints.size(); i < N; ++i ) if ( theHints[i] == Hint::Default() ) return; theHints.push_front(Hint::Default()); isEmpty = false; } } template void HandlerGroup::clear() { theHandler = HdlPtr(); HandlerGroupBase::clear(); } template string HandlerGroup::handlerClass() const { return ClassTraits::className(); } template void HandlerGroup::interfaceSetHandler(HdlPtr p) { theDefaultHandler = p; } template typename HandlerGroup::HdlPtr HandlerGroup::interfaceGetHandler() const { return theDefaultHandler; } } diff --git a/Handlers/Hint.cc b/Handlers/Hint.cc --- a/Handlers/Hint.cc +++ b/Handlers/Hint.cc @@ -1,49 +1,49 @@ // -*- C++ -*- // // Hint.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the Hint class. // #include "Hint.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/EventRecord/Step.h" #include "ThePEG/EventRecord/Particle.h" using namespace ThePEG; tPVector Hint::tagged(const Step & s) const { tPVector tags; if ( stop() ) return tags; if ( !tagged() ) { tags.insert(tags.end(), s.particles().begin(), s.particles().end()); return tags; } for ( int i = 0, N = theTagged.size(); i < N; ++i ) { tPPtr p = theTagged[i]; while ( !s.find(p) && p->next() ) p = p->next(); if ( s.find(p) ) tags.push_back(p); } return tags; } void Hint::persistentOutput(PersistentOStream & os) const { os << ounit(theScale, GeV2) << theStopFlag << theTagged; } void Hint::persistentInput(PersistentIStream & is, int) { is >> iunit(theScale, GeV2) >> theStopFlag >> theTagged; } ClassDescription Hint::initHint; void Hint::Init() {} Hint Hint::theDefaultHint; diff --git a/Handlers/Hint.h b/Handlers/Hint.h --- a/Handlers/Hint.h +++ b/Handlers/Hint.h @@ -1,204 +1,204 @@ // -*- C++ -*- // // Hint.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_Hint_H #define ThePEG_Hint_H // This is the declaration of the Hint class. #include "ThePEG/Config/ThePEG.h" #include "ThePEG/Utilities/ClassDescription.h" namespace ThePEG { /** * Hint is a base class to be used to pass information * between StepHandler s, which cannot be convayed * through the Event record. The base class contains a vector of of * tagged particles. A StepHandler is always given a hint, and is only * allowed to treat Particles from the current Step which are listed * in the vector of tagged particles in the hint (if this vector is * empty the StepHandler may treat all particles in the Step. * * A Hint may have the stop flag set. In this case * the StepHandler to which the hint is assigned is * not called, and the event generation is stopped. * * A Hint may be given a scale, but what a StepHandler does with this * and other pieces of information possibly supplied by subclasses of * Hint, is not defined. * * There is a special Hint which is kept as the static member called * Hint::theDefaultHint. Although any default constructed Hint object * would work as a default hint, only pointers to this static object * should be used where a default hint is needed. * * * @see StepHandler * @see EventHandler * @see Particle * @see Event * @see Step * */ class Hint: public Base { public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ Hint() : theScale(Energy2()), theStopFlag(false) {} //@} public: /** * Return true if there are tagged particles in the hint. */ bool tagged() const { return !theTagged.empty(); } /** * Return a list of pointers to particles to be handled. A handler * is not allowed to touch other particles in the event record. If a * particle which has been flagged by the hint is no longer present * in the current Step, a null pointer is inserted in its place. */ tPVector tagged(const Step & s) const; /** * Add a range of particles to the list of tagged particles. */ template void tag(InputIterator first, InputIterator last) { theTagged.insert(theTagged.end(), first, last); } /** * Add a particle to the list of tagged particles. */ void tag(tPPtr p) { if (p) theTagged.push_back(p); } /** * Set the stop hint. */ void stop(bool newStopFlag) { theStopFlag = newStopFlag; if ( theStopFlag ) theTagged.clear(); } /** * Get the stop hint. */ bool stop() const { return theStopFlag; } /** * Set the scale. */ void scale(const Scale & newScale) { theScale = newScale; } /** * Get the scale. */ const Scale & scale() const { return theScale; } /** * Return a pointer to the default hint. */ static tHintPtr Default() { return tHintPtr(&theDefaultHint); } public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interface. */ static void Init(); private: /** * The vector of tagged particles. */ tPVector theTagged; /** * The scale. */ Scale theScale; /** * The stop hint. */ bool theStopFlag; /** * The default hint. */ static Hint theDefaultHint; private: /** * Describe a concrete class with persistent data. */ static ClassDescription initHint; /** * Assignment is private and non-existing. */ Hint & operator=(const Hint & h) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** * This template specialization informs ThePEG about the * base class of Hint. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the base class of Hint. */ typedef Base NthBase; }; /** * This template specialization informs ThePEG about the name of the * Hint class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return the class name. */ static string className() { return "ThePEG::Hint"; } }; /** @endcond */ } #endif /* ThePEG_Hint_H */ diff --git a/Handlers/LastXCombInfo.h b/Handlers/LastXCombInfo.h --- a/Handlers/LastXCombInfo.h +++ b/Handlers/LastXCombInfo.h @@ -1,277 +1,277 @@ // -*- C++ -*- // // LastXCombInfo.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_LastXCombInfo_H #define ThePEG_LastXCombInfo_H // This is the declaration of the LastXCombInfo class. #include "ThePEG/Config/ThePEG.h" #include "ThePEG/Cuts/Cuts.fh" #include "XComb.h" namespace ThePEG { /** * LastXCombInfo is a templated class giving easy access to the * information in an XComb object. The default template argument is * the basic XComb class, but also subclasses of XComb can be * used. Classes which need to have easy access to the last selected * XComb object with information about the sub-process which is being * generated, should (possibly multiple) inherit from the * LastXCombInfo class. The LastXCombInfo is templated to enable * derived classes to only include dependencies necessary for the * access function which are actually used. * */ template class LastXCombInfo { public: ThePEG_DECLARE_TEMPLATE_POINTERS(XC,XCPtr); public: /** @name Acces to the actual XComb object. */ //@{ /** * Return a reference to the last selected XComb. */ const XC & lastXComb() const { return *theLastXComb; } /** * Return a pointer to the last selected XComb. */ tXCPtr lastXCombPtr() const { return theLastXComb; } /** * If the last selected XComb object belongs to a * group of XComb's return a reference to the head * XComb object for this group. */ const XC& lastHeadXComb() const { return *lastXComb().head(); } /** * If the last selected XComb object belongs to a * group of XComb's return a pointer to the head * XComb object for this group. */ tXCPtr lastHeadXCombPtr() const { return lastXComb().head(); } //@} /** @name Access the objects used by the XComb object. */ //@{ /** * Return a reference to the currently used EventHandler */ const EventHandler & lastEventHandler() const { return lastXComb().eventHandler(); } /** * A pointer to the currently used parton extractor. */ tPExtrPtr lastExtractor() const { return lastXComb().pExtractor(); } /** * Return the parton density used to extract the given parton. This * function is templated to avoid having to include the PDF.h and * all its dependencies in this header. */ template PDFT pdf(tcPPtr parton) const { return PDFT(lastXComb().partonBinInstance(parton)); } /** * A reference to the currently used kinematical cuts. */ const Cuts & lastCuts() const { return *lastXComb().cuts(); } /** * A pointer to the currently used kinematical cuts. */ tCutsPtr lastCutsPtr() const { return lastXComb().cuts(); } //@} /** @name Access information about the incoming particles and partons. */ //@{ /** * Return the pair of incoming parton instances. */ const PPair & lastParticles() const { return lastXComb().lastParticles(); } /** * The last generated total energy squared of the incoming particles. */ Energy2 lastS() const { return lastXComb().lastS(); } /** * Return the pair of incoming parton instances. */ const PPair & lastPartons() const { return lastXComb().lastPartons(); } /** * The last used interval in total parton-parton energy squared */ Energy2 lastSHat() const { return lastXComb().lastSHat(); } /** * Return lastSHat()/lastS(). */ double lastTau() const { return lastXComb().lastTau(); } /** * The generated rapidity of the hard scattering sub-system. */ double lastY() const { return lastXComb().lastY(); } /** * Log of one over the momentum fraction of the first incoming * particle w.r.t. the maximum allowed energy. */ double lastP1() const { return lastXComb().lastP1(); } /** * Log of one over the momentum fraction of the second incoming * particle w.r.t. the maximum allowed energy. */ double lastP2() const { return lastXComb().lastP2(); } /** * Log of one over the first incoming parton momentum fraction w.r.t. the * first incoming particle. */ double lastL1() const { return lastXComb().lastL1(); } /** * Log of one over the second incoming parton momentum fraction * w.r.t. the second incoming particle. */ double lastL2() const { return lastXComb().lastL2(); } /** * The first incoming parton momentum fraction w.r.t. the * first incoming particle. */ double lastX1() const { return lastXComb().lastX1(); } /** * The second incoming parton momentum fraction * w.r.t. the second incoming particle. */ double lastX2() const { return lastXComb().lastX2(); } /** * Return 1-lastX1() to highest possible precision for * x \f$\rightarrow\f$ 1. */ double lastE1() const { return lastXComb().lastE1(); } /** * Return 1-lastX2() to highest possible precision for * x\f$\rightarrow\f$ 1. */ double lastE2() const { return lastXComb().lastE2(); } /** * The product of the parton density functions at the last generated * phase-space point. */ double lastFL1L2() const { return lastXComb().lastFL1L2(); } //@} /** @name Access information of the hard sub-process. */ //@{ /** * The chosen scale of the hard scattering. */ Energy2 lastScale() const { return lastXComb().lastScale(); } /** * Get the \f$\alpha_S\f$ used in the hard scattering. Is negative * if no value has been set. */ double lastAlphaS() const { return lastXComb().lastAlphaS(); } /** * Get the \f$\alpha_{EM}\f$ used in the hard scattering. Is negative * if no value has been set. */ double lastAlphaEM() const { return lastXComb().lastAlphaEM(); } /** * Return the momenta of the incoming and outgoing partons to be * used by the matrix element object, in the order specified by the * TreeDiagram objects given by the matrix element. */ const vector & meMomenta() const { return lastXComb().meMomenta(); } /** * Return the matrix element squared as calculated * for the last phase space point. This may optionally * be used by a matrix element for caching. */ double lastME2() const { return lastXComb().lastME2(); } /** * Return the last preweight factor */ double lastPreweight() const { return lastXComb().lastPreweight(); } /** * Get the last jacobian obtained when generating the kinematics * for the call to dSigHatDR. */ double jacobian() const { return lastXComb().jacobian(); } /** * Return the partonic cross section as calculated * for the last phase space point. This may optionally * be used by a matrix element for caching. */ CrossSection lastMECrossSection() const { return lastXComb().lastMECrossSection(); } /** * Return the PDF weight as calculated * for the last phase space point, if the matrix * element does supply PDF weights. This may optionally * be used by a matrix element for caching. */ double lastMEPDFWeight() const { return lastXComb().lastMEPDFWeight(); } /** * Return the coupling weight as calculated * for the last phase space point. */ double lastMECouplings() const { return lastXComb().lastMECouplings(); } /** * Return the SubProcess object corresponding to the last generated * sub-process. */ tSubProPtr subProcess() const { return lastXComb().subProcess(); } /** * Return the incoming and outgoing parton types to be used by the * matrix element object, in the order specified by the TreeDiagram * objects given by the matrix element. */ const cPDVector & mePartonData() const { return lastXComb().mePartonData(); } //@} protected: /** * The pointer to the last selected XComb. */ XCPtr theLastXComb; }; } #endif /* ThePEG_LastXCombInfo_H */ diff --git a/Handlers/LuminosityFunction.cc b/Handlers/LuminosityFunction.cc --- a/Handlers/LuminosityFunction.cc +++ b/Handlers/LuminosityFunction.cc @@ -1,112 +1,112 @@ // -*- C++ -*- // // LuminosityFunction.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the LuminosityFunction class. // #include "LuminosityFunction.h" #include "ThePEG/Handlers/XComb.h" #include "ThePEG/Vectors/LorentzRotation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #ifdef ThePEG_TEMPLATES_IN_CC_FILE // #include "LuminosityFunction.tcc" #endif using namespace ThePEG; IBPtr LuminosityFunction::clone() const { return new_ptr(*this); } IBPtr LuminosityFunction::fullclone() const { return new_ptr(*this); } LuminosityFunction::LuminosityFunction(Energy a, Energy b) : theBeamEMaxA(a), theBeamEMaxB(b) {} void LuminosityFunction::select(tXCombPtr xcomb) { theLastXComb = xcomb; } bool LuminosityFunction::canHandle(const cPDPair &) const { return true; } Energy LuminosityFunction::maximumCMEnergy() const { return sqrt(4.0*beamEMaxA()*beamEMaxB()); } LorentzRotation LuminosityFunction::getBoost() const { LorentzRotation r(0.0, 0.0, (beamEMaxA() - beamEMaxB())/ (beamEMaxA() + beamEMaxB())); return r; } double LuminosityFunction::Y() const { return 0.5*log(beamEMaxA()/beamEMaxB()); } int LuminosityFunction::nDim(const cPDPair &) const { return 0; } double LuminosityFunction:: value(const cPDPair &, double l1, double l2) const { return l1 == 0.0 && l2 == 0.0? 1.0: 0.0; } pair LuminosityFunction:: generateLL(const double *, double &) const { return make_pair(0.0, 0.0); } void LuminosityFunction::persistentOutput(PersistentOStream & os) const { os << theLastXComb << ounit(theBeamEMaxA, GeV) << ounit(theBeamEMaxB, GeV); } void LuminosityFunction::persistentInput(PersistentIStream & is, int) { is >> theLastXComb >> iunit(theBeamEMaxA, GeV) >> iunit(theBeamEMaxB, GeV); } ClassDescription LuminosityFunction::initLuminosityFunction; void LuminosityFunction::Init() { static ClassDocumentation documentation ("This base class should be used by all classes describing the luminosity " "and energy distribution of colliding particle beams."); static Parameter interfaceBeamEMaxA ("BeamEMaxA", "The maximum energy of the beam entering along the positive z-axis. " "Note that derived classes may shift the beams away from the z-axis.", &LuminosityFunction::theBeamEMaxA, GeV, 45.6*GeV, ZERO, ZERO, true, false, Interface::lowerlim); static Parameter interfaceBeamEMaxB ("BeamEMaxB", "The maximum energy of the beam entering along the negative z-axis. " "Note that derived classes may shift the beams away from the z-axis.", &LuminosityFunction::theBeamEMaxB, GeV, 45.6*GeV, ZERO, ZERO, true, false, Interface::lowerlim); interfaceBeamEMaxA.rank(10); interfaceBeamEMaxB.rank(9); interfaceBeamEMaxA.setHasDefault(false); interfaceBeamEMaxB.setHasDefault(false); } diff --git a/Handlers/LuminosityFunction.h b/Handlers/LuminosityFunction.h --- a/Handlers/LuminosityFunction.h +++ b/Handlers/LuminosityFunction.h @@ -1,232 +1,232 @@ // -*- C++ -*- // // LuminosityFunction.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_LuminosityFunction_H #define ThePEG_LuminosityFunction_H // This is the declaration of the LuminosityFunction class. #include "ThePEG/Handlers/HandlerBase.h" #include "ThePEG/Handlers/LastXCombInfo.h" #include "ThePEG/Vectors/LorentzRotation.fh" #include "ThePEG/Utilities/Interval.h" namespace ThePEG { /** * The LuminosityFunction describes the momentum distribution of the * incoming beams in an experiment. This is used by a EventHandler to * generate collisions in their CM system. The LuminosityFunction will * be asked to produce a LorentzRotation giving the transformation to * the laboratory system. * * The LuminosityFunction inherits from the LastXCombInfo class to * give easy access to the information of the generated primary * sub-process in the selected XComb. * * This base class implements simple fixed momentum beams with * energies given by the BeamEMaxA and BeamEMaxB interfaces. * * @see \ref LuminosityFunctionInterfaces "The interfaces" * defined for LuminosityFunction. * @see XComb * */ class LuminosityFunction: public HandlerBase, public LastXCombInfo<> { /** EventHandler is a friend. */ friend class EventHandler; public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. Optionally the maximum energy of beam \a a * and \a b can be given. */ LuminosityFunction(Energy a = 45.6*GeV, Energy b = 45.6*GeV); //@} /** @name Virtual functions to be overridden by sub-classes. */ //@{ /** * Return true if this luminosity function can actually handle a * given pair of incoming particles. */ virtual bool canHandle(const cPDPair &) const; /** * Return the maximum possible center of mass energy for an event. */ virtual Energy maximumCMEnergy() const; /** * Return the rotation needed to transform from the collision cm * system to the labotatory system. This default version returns the * unit transformation. */ virtual LorentzRotation getBoost() const; /** * Return the rapidity of the colliding particles (at the maximum * energy) in the laboratory system. This default version assumes * the CM system is the same as the lab system and returns zero. */ virtual double Y() const; /** * How many random numbers are needed to generate a phase space * point? Default is zero in which means the energy of the incoming * particles is fixed. The only other reasonable values are 1 and 2. */ virtual int nDim(const cPDPair &) const; /** * The value of the luminosity function for the given particle types * for the given energy fractions l1 and l2 (\f$l=\log(1/x)\f$). The * default version returns 1 if l1 and l2 are zero otherwize zero. */ virtual double value(const cPDPair &, double l1, double l2) const; /** * Generate energy fractions l1 and l2 (\f$l=\log(1/x)\f$) given * 'nDim()' random numbers in the range ]0,1[ given by the * iterators. The jacobian argument must be multiplied by the * jacobian of the variable transformation to l1 and l2. The default * version is just a delta function with a jacobian of 1. */ virtual pair generateLL(const double * r, double & jacobian) const; //@} public: /** @name Simple access functions */ //@{ /** * The maximum energy of the beam entering along the positive z-axis. */ Energy beamEMaxA() const { return theBeamEMaxA; } /** * The maximum energy of the beam entering along the negative z-axis. */ Energy beamEMaxB() const { return theBeamEMaxB; } //@} protected: /** * The maximum energy of the beam entering along the positive z-axis. */ void beamEMaxA(Energy x) { theBeamEMaxA = x; } /** * The maximum energy of the beam entering along the negative z-axis. */ void beamEMaxB(Energy x) { theBeamEMaxB = 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); //@} /** * Standard Init function used to initialize the interface. */ static void Init(); /** * Set information about the selected XComb. */ void select(tXCombPtr); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * The maximum energy of the beam entering along the positive z-axis. */ Energy theBeamEMaxA; /** * The maximum energy of the beam entering along the negative z-axis. */ Energy theBeamEMaxB; private: /** * Describe an abstract class with persistent data. */ static ClassDescription initLuminosityFunction; /** * Private and non-existent assignment operator. */ LuminosityFunction & operator=(const LuminosityFunction &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** * This template specialization informs ThePEG about the * base class of LuminosityFunction. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the base class of LuminosityFunction. */ typedef HandlerBase NthBase; }; /** * This template specialization informs ThePEG about the name of the * LuminosityFunction class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return the class name. */ static string className() { return "ThePEG::LuminosityFunction"; } }; /** @endcond */ } #endif /* ThePEG_LuminosityFunction_H */ diff --git a/Handlers/MultipleInteractionHandler.cc b/Handlers/MultipleInteractionHandler.cc --- a/Handlers/MultipleInteractionHandler.cc +++ b/Handlers/MultipleInteractionHandler.cc @@ -1,29 +1,29 @@ // -*- C++ -*- // // MultipleInteractionHandler.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MultipleInteractionHandler class. // #include "MultipleInteractionHandler.h" #include "ThePEG/Interface/ClassDocumentation.h" using namespace ThePEG; AbstractNoPIOClassDescription MultipleInteractionHandler::initMultipleInteractionHandler; void MultipleInteractionHandler::Init() { static ClassDocumentation documentation ("There is no documentation for the " "ThePEG::MultipleInteractionHandler class"); } diff --git a/Handlers/MultipleInteractionHandler.h b/Handlers/MultipleInteractionHandler.h --- a/Handlers/MultipleInteractionHandler.h +++ b/Handlers/MultipleInteractionHandler.h @@ -1,80 +1,80 @@ // -*- C++ -*- // // MultipleInteractionHandler.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_MultipleInteractionHandler_H #define ThePEG_MultipleInteractionHandler_H // This is the declaration of the MultipleInteractionHandler class. #include "StepHandler.h" namespace ThePEG { /** * The MultipleInteractionHandler is the base class of all * handlers implementing models for multiple interactions. It is * derived from the more general StepHandler class, * and does not introduce more functioanality as it stands. * * @see \ref MultipleInteractionHandlerInterfaces "The interfaces" * defined for MultipleInteractionHandler. * @see StepHandler * @see EventHandler * @see SubProcessHandler */ class MultipleInteractionHandler: public StepHandler { public: /** * Standard Init function used to initialize the interface. */ static void Init(); private: /** * Describe an abstract class without persistent data. */ static AbstractNoPIOClassDescription initMultipleInteractionHandler; /** * Private and non-existent assignment operator. */ MultipleInteractionHandler & operator=(const MultipleInteractionHandler &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** * This template specialization informs ThePEG about the * base class of MultipleInteractionHandler. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the base class of MultipleInteractionHandler. */ typedef StepHandler NthBase; }; /** * This template specialization informs ThePEG about the name of the * MultipleInteractionHandler class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return the class name. */ static string className() { return "ThePEG::MultipleInteractionHandler"; } }; /** @endcond */ } #endif /* ThePEG_MultipleInteractionHandler_H */ diff --git a/Handlers/PtGenerator.cc b/Handlers/PtGenerator.cc --- a/Handlers/PtGenerator.cc +++ b/Handlers/PtGenerator.cc @@ -1,33 +1,33 @@ // -*- C++ -*- // // PtGenerator.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // //$Id$ // -------------------------------------------------------- // // This is the implementation of the non-inlined, non-templated member // functions of the PtGenerator class. // #include "PtGenerator.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Interface/ClassDocumentation.h" using namespace ThePEG; // *** Standard Interfaced functions *** AbstractClassDescription PtGenerator::initPtGenerator; void PtGenerator::Init() { static ClassDocumentation documentation ("This base class should be used by models describing intrinsic " "transverse momenta distributions in hadrons."); } diff --git a/Handlers/PtGenerator.h b/Handlers/PtGenerator.h --- a/Handlers/PtGenerator.h +++ b/Handlers/PtGenerator.h @@ -1,91 +1,91 @@ // -*- C++ -*- // // PtGenerator.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_PtGenerator_H #define ThePEG_PtGenerator_H // This is the declaration of the PtGenerator class. #include "ThePEG/Config/ThePEG.h" #include "ThePEG/Handlers/HandlerBase.h" namespace ThePEG { /** * PtGenerator is the base for all classes implementing alternative * models for transverse momentum generation. It inherits from the * HandlerBase which among other things provides forward access to the * random number object held by the EventGenerator object. * * @see \ref PtGeneratorInterfaces "The interfaces" * defined for PtGenerator. * @see HandlerBase * @see EventGenerator */ class PtGenerator: public HandlerBase { public: /** @name Virtual functions to be implemented by sub-classes. */ //@{ /** * Generate (\f$k_x, k_y\f$) components of the transverse * momentum. */ virtual TransverseMomentum generate() const =0; //@} public: /** * Standard Init function used to initialize the interface. */ static void Init(); private: /** * Describe an abstract class without persistent data. */ static AbstractClassDescription initPtGenerator; /** * Private and non-existent assignment operator. */ PtGenerator & operator=(const PtGenerator &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** * This template specialization informs ThePEG about the * base class of PtGenerator. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the base class of PtGenerator. */ typedef HandlerBase NthBase; }; /** * This template specialization informs ThePEG about the name of the * PtGenerator class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return the class name. */ static string className() { return "ThePEG::PtGenerator"; } }; /** @endcond */ } #endif /* ThePEG_PtGenerator_H */ diff --git a/Handlers/SamplerBase.cc b/Handlers/SamplerBase.cc --- a/Handlers/SamplerBase.cc +++ b/Handlers/SamplerBase.cc @@ -1,45 +1,45 @@ // -*- C++ -*- // // SamplerBase.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the SamplerBase class. // #include "SamplerBase.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Handlers/StandardEventHandler.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG; SamplerBase::~SamplerBase() {} void SamplerBase::persistentOutput(PersistentOStream & os) const { os << theEventHandler << theLastPoint; // Add all member variable which should be written persistently here. } void SamplerBase::persistentInput(PersistentIStream & is, int) { is >> theEventHandler >> theLastPoint; // Add all member variable which should be read persistently here. } AbstractClassDescription SamplerBase::initSamplerBase; // Definition of the static class description member. void SamplerBase::Init() { static ClassDocumentation documentation ("This is the base class for all phase space sampler classes to be" "used by the ThePEG::StandardEventHandler class to sample the phase" "space according to the cross sections for the proceses in the" "ThePEG::StandardEventHandler."); } diff --git a/Handlers/SamplerBase.h b/Handlers/SamplerBase.h --- a/Handlers/SamplerBase.h +++ b/Handlers/SamplerBase.h @@ -1,399 +1,399 @@ // -*- C++ -*- // // SamplerBase.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_SamplerBase_H #define ThePEG_SamplerBase_H // This is the declaration of the SamplerBase class. #include "ThePEG/Interface/Interfaced.h" #include "SamplerBase.fh" #include "ThePEG/Handlers/StandardEventHandler.fh" // #include "SamplerBase.xh" namespace ThePEG { /** * This is the base class for all phase space sampler classes to be * used by the EventHandler class to sample the phase space according * to the cross sections for the processes in the EventHandler. The * class should be able to sample a unit hyper-cube in arbitrary * dimensions. The points need not necessarily be sampled with unit * weight. * * The virtual methods to be implemented by concrete sub-classes are * initialize(), generate() and rejectLast(). * * @see \ref SamplerBaseInterfaces "The interfaces" * defined for SamplerBase. * @see EventHandler */ class SamplerBase: public Interfaced { public: /** @name Standard constructors and destructors. */ //@{ /** * Constructor */ SamplerBase() : Interfaced(), theIntegrationList("") {} /** * Destructor. */ virtual ~SamplerBase(); //@} public: /** * Set the event handler for which the function * StandardEventHandler::dSigDR(const vector &) function * returns the cross section for the chosen phase space point. */ void setEventHandler(tStdEHPtr eh) { theEventHandler = eh; } /** @name Virtual functions to be overridden by sub-classes. */ //@{ /** * Initialize the the sampler, possibly doing presampling of the * phase space. */ virtual void initialize() = 0; /** * An external hook to prepare the sampler for generating events, e.g. by * combining grid files from parallel integration runs. */ virtual void prepare() {} /** * Generarate a new phase space point and return a weight associated * with it. This weight should preferably be 1. */ virtual double generate() = 0; /** * Reject the last chosen phase space point. */ virtual void rejectLast() = 0; /** * Return the last generated phase space point. */ const vector & lastPoint() const { return theLastPoint; } /** * If the sampler is able to sample several different functions * separately, this function should return the last chosen * function. This default version always returns 0. */ virtual int lastBin() const { return 0; } /** * Return the total integrated cross section determined from the * Monte Carlo sampling so far. */ virtual CrossSection integratedXSec() const = 0; /** * Return the error on the total integrated cross section determined * from the Monte Carlo sampling so far. */ virtual CrossSection integratedXSecErr() const = 0; /** * Return the reference cross section, a.k.a. maximum weight. When * not provided directly, this will be determined effectively from * the sum of weights and sum of weights squared to match up the * standard definition of a Monte Carlo cross section along with the * cross section and error quoted. */ virtual CrossSection maxXSec() const { if ( sumWeights2() <= 0.0 ) return ZERO; return integratedXSec()*attempts()/sumWeights(); } /** * Return the number of attempts. When not provided directly, this * will be determined effectively from the sum of weights and sum of * weights squared to match up the standard definition of a Monte * Carlo cross section along with the cross section and error * quoted. */ virtual double attempts() const { CrossSection sigma = integratedXSec(); CrossSection esigma = integratedXSecErr(); double sw = sumWeights(); double sw2 = sumWeights2(); if ( sw2 <= 0.0 ) return 0.0; return sqr(sw)*(sqr(esigma)-sqr(sigma))/(sqr(sw)*sqr(esigma) - sw2*sqr(sigma)); } /** * Return the sum of the weights returned by generate() so far (of * the events that were not rejeted). */ virtual double sumWeights() const = 0; /** * Return the sum of the weights squared returned by generate() so * far (of the events that were not rejeted). */ virtual double sumWeights2() const = 0; /** * Return true if this sampler is generating almost unweighted events. */ virtual bool almostUnweighted() const { return false; } //@} /** @name Controlling of run levels and grid handling*/ //@{ /** * Set a file containing a list of subprocesses to integrate */ void integrationList(const string& newIntegrationList) { theIntegrationList = newIntegrationList; } /** * Return a file containing a list of subprocesses to integrate */ const string& integrationList() const { return theIntegrationList; } /** * Enumerate the possible run levels */ enum RunLevels { UnknownMode = 0, InitMode, ReadMode, BuildMode, IntegrationMode, RunMode }; /** * Return the run level */ static int runLevel() { return theRunLevel(); } /** * Set the run level */ static void setRunLevel(int level) { theRunLevel() = level; } /** * Return true, if a setupfile is in use */ static bool hasSetupFile() { return theHasSetupFile(); } /** * Indicate that a setupfile is in use. */ static void setupFileUsed(bool yes = true) { theHasSetupFile() = yes; } /** * Return the seed that has been used for this run to disentangle * grids whihch have been adapted further */ static long seed() { return theSeed(); } /** * Set the seed that has been used for this run to disentangle * grids whihch have been adapted further */ static void setSeed(long s) { theSeed() = s; } /** * Return the number of subprocesses to be integrated per job. */ static unsigned int integratePerJob() { return theIntegratePerJob(); } /** * Set the number of subprocesses to be integrated per job. */ static void setIntegratePerJob(unsigned int s) { theIntegratePerJob() = s; } /** * Return the maximum number of integration jobs to be created. */ static unsigned int integrationJobs() { return theIntegrationJobs(); } /** * Set the maximum number of integration jobs to be created. */ static void setIntegrationJobs(unsigned int s) { theIntegrationJobs() = s; } //@} protected: /** * Return the last generated phase space point. */ vector & lastPoint() { return theLastPoint; } /** * Return the associated event handler. */ tStdEHPtr eventHandler() const { return theEventHandler; } 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(); private: /** * The associated event handler. */ tStdEHPtr theEventHandler; /** * The last generated phase space point. */ vector theLastPoint; /** * A file containing a list of subprocesses to integrate */ string theIntegrationList; /** * The run level */ static int& theRunLevel() { static int lvl = UnknownMode; return lvl; } /** * True, if a setupfile is in use */ static bool& theHasSetupFile() { static bool flag = false; return flag; } /** * The seed that has been used for this run to disentangle * grids whihch have been adapted further */ static long& theSeed() { static long s = 0; return s; } /** * The number of subprocesses to be integrated per job. */ static unsigned int& theIntegratePerJob() { static unsigned int s = 0; return s; } /** * The maximum number of integration jobs to be created. */ static unsigned int& theIntegrationJobs() { static unsigned int s = 0; return s; } private: /** * Describe an abstract base class with persistent data. */ static AbstractClassDescription initSamplerBase; /** * Private and non-existent assignment operator. */ SamplerBase & operator=(const SamplerBase &) = delete; }; } namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** * This template specialization informs ThePEG about the base class of * SamplerBase. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the base class of SamplerBase. */ typedef Interfaced NthBase; }; /** * This template specialization informs ThePEG about the name of the * SamplerBase class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return the class name. */ static string className() { return "ThePEG::SamplerBase"; } }; /** @endcond */ } #endif /* ThePEG_SamplerBase_H */ diff --git a/Handlers/SimpleFlavour.cc b/Handlers/SimpleFlavour.cc --- a/Handlers/SimpleFlavour.cc +++ b/Handlers/SimpleFlavour.cc @@ -1,524 +1,524 @@ // -*- C++ -*- // // SimpleFlavour.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the SimpleFlavour class. // #include "SimpleFlavour.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/PDT/StandardMatchers.h" #include "ThePEG/Repository/RandomGenerator.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/Triplet.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG; SimpleFlavour::SimpleFlavour() : theSSup(0.3), theDiSup(0.1), theDi1Sup(0.05), theDiSSup(0.4), theEtaSup(1.0), theEtaPSup(0.4), theBaryon10Sup(1.0), thePSpin1(0.5), thePSpinS1(0.6), thePSpinC1(0.75) {} SimpleFlavour::~SimpleFlavour() {} IBPtr SimpleFlavour::clone() const { return new_ptr(*this); } IBPtr SimpleFlavour::fullclone() const { return new_ptr(*this); } void SimpleFlavour::doinit() { FlavourGenerator::doinit(); clear(); } void SimpleFlavour::doinitrun() { FlavourGenerator::doinitrun(); clear(); } void SimpleFlavour::clear() { theFlavourSelector.clear(); theProbabilities.clear(); } long SimpleFlavour::selectQuark() const { return rndsign(1.0, 1.0, sSup()) + 2; } long SimpleFlavour::selectFlavour() const { if ( theFlavourSelector.empty() ) { theFlavourSelector.insert(1.0, 1); theFlavourSelector.insert(1.0, 2); theFlavourSelector.insert(sSup(), 3); for ( int ifla = 1; ifla <= 3; ++ifla ) for ( int iflb = 1; iflb <= ifla; ++iflb ) { double w = diSup(); if ( ifla == 3 ) w *= diSSup(); theFlavourSelector.insert(3.0*di1Sup()*w, 1000*ifla + 100*iflb + 3); if ( ifla != iflb ) theFlavourSelector.insert(w, 1000*ifla + 100*iflb + 1); } } return theFlavourSelector[rnd()]; } /* tcPDPair SimpleFlavour::generateOldHadron(tcPDPtr q) const { tcPDPair ret; bool isdiq = DiquarkMatcher::Check(*q); while ( true ) { long flav = selectFlavour(); if ( isdiq && DiquarkMatcher::Check(flav) ) continue; if ( isdiq ) ret.second = getParticleData(q->id() > 0? -flav: flav); else ret.second = getParticleData(q->id() > 0? flav: -flav); ret.first = getHadron(q->id(), ret.second->CC()->id()); if ( ret.first->id() == ParticleID::eta && !rndbool(etaSup()) ) continue; if ( ret.first->id() == ParticleID::etaprime && !rndbool(etaPSup()) ) continue; if ( DiquarkMatcher::Check(ret.second->id()) && !rndbool(weightSU6QDiQSpin(abs(q->id()), abs(ret.second->id()), 2) + weightSU6QDiQSpin(abs(q->id()), abs(ret.second->id()), 4)* baryon10Sup()) ) continue; return ret; } return tcPDPair(); } */ tcPDPair SimpleFlavour::generateHadron(tcPDPtr q) const { tcPDPair ret; ProbabilityMap::const_iterator it = theProbabilities.find(abs(q->id())); if ( it == theProbabilities.end() ) { setProbabilities(abs(q->id())); it = theProbabilities.find(abs(q->id())); if ( it == theProbabilities.end() ) return ret; } pair ids = it->second[rnd()]; ret.first = getParticleData(ids.first); ret.second = getParticleData(ids.second); if ( it->first != q->id() ) { if ( ret.first->CC() ) ret.first = ret.first->CC(); if ( ret.second->CC() ) ret.second = ret.second->CC(); } return ret; } void SimpleFlavour::setProbabilities(long iq) const { VSelector< pair > & sel = theProbabilities[iq]; sel.clear(); vector< pair > wts; if ( DiquarkMatcher::Check(iq) ) { vector flv = PDT::flavourContent(iq); // This is a di-quark, so we can only generate a q-qbar for ( long iqb = 1; iqb <= 3; ++iqb ) { double w = 1.0; // Suppress s-quarks if ( iqb == 3 ) w = sSup(); // Get the normalized probability for octet and decuplet double ow = weightSU6QDiQSpin(iqb, iq, 2); double dw = weightSU6QDiQSpin(iqb, iq, 4)*baryon10Sup(); w /= (ow + dw); long iq1 = max(flv[0], iqb); long iq3 = min(flv[1], iqb); long iq2 = flv[0] + flv[1] + iqb - iq1 - iq3; // Get possible Octets. wts = baryonOctetIds(iq1, iq2, iq3, iqb, (iq%10) == 3); for ( int i = 0, N = wts.size(); i < N; ++i ) sel.insert(w*ow*wts[i].second, make_pair(wts[i].first, -iqb)); // Get possible Decuplets. wts = baryonDecupletIds(iq1, iq2, iq3); for ( int i = 0, N = wts.size(); i < N; ++i ) sel.insert(w*dw*wts[i].second, make_pair(wts[i].first, -iqb)); } } else { // This is a quark so we can generate both q-qbar and diq-diqbar pairs. // We start with q-qbar pairs for ( long iqb = 1; iqb <= 3; ++iqb ) { int sign = ( iq >= iqb? 1: -1); double w = 1.0; // s-quark suppression. if ( iqb == 3 ) w = sSup(); long iqh = max(iq, iqb); long iql = min(iq, iqb); // Get relative vector meson probability. double vw = vectorMesonProbability(iqh, iql); // Get possible vector mesons. wts = vectorIds(iqh, iql); for ( int i = 0, N = wts.size(); i < N; ++i ) sel.insert(w*vw*wts[i].second, make_pair(sign*wts[i].first, iqb)); // Get pseudo scala vector mesons. wts = pseudoScalarIds(iqh, iql); for ( int i = 0, N = wts.size(); i < N; ++i ) sel.insert(w*(1.0 - vw)*wts[i].second, make_pair(sign*wts[i].first, iqb)); } // No we go through the possible di-quarks. for ( long ifla = 1; ifla <= 3; ++ifla ) for ( long iflb = 1; iflb <= ifla; ++iflb ) { // We have a general di-quark suppression. double w = diSup(); // Suppress strange di-quarks. if ( ifla == 3 ) w *= diSSup()*sSup(); long iqa = max(ifla, iq); long iqc = min(iflb, iq); long iqb = ifla + iflb + iq - iqa - iqc; // Get weight for spin-0 di-quark to octet baryons. long idiq = ifla*1000 + iflb*100 + 1; double ow = weightSU6QDiQSpin(iq, idiq, 2); // Get possible octet baryons for spin-0 di-quark. if ( ifla != iflb ) { wts = baryonOctetIds(iqa, iqb, iqc, iq, false); for ( int i = 0, N = wts.size(); i < N; ++i ) sel.insert(w*ow*wts[i].second, make_pair(wts[i].first, -idiq)); } // Spin-1 diquarks have three states. w *= 3.0; // Get weight for spin-1 di-quark to octet baryons. idiq += 2; ow = weightSU6QDiQSpin(iq, idiq, 2); // Get possible octet baryons for spin-1 di-quark. wts = baryonOctetIds(iqa, iqb, iqc, iq, true); for ( int i = 0, N = wts.size(); i < N; ++i ) sel.insert(w*ow*wts[i].second, make_pair(wts[i].first, -idiq)); // Get weight for spin-1 di-quark to decuplet baryons. double dw = weightSU6QDiQSpin(iq, idiq, 4)*baryon10Sup(); // Get possible decuplet baryons for spin-1 di-quark. wts = baryonDecupletIds(iqa, iqb, iqc); for ( int i = 0, N = wts.size(); i < N; ++i ) sel.insert(w*dw*wts[i].second, make_pair(wts[i].first, -idiq)); } } } double SimpleFlavour::vectorMesonProbability(long iq1, long iq2) const { switch ( max(abs(iq1), abs(iq2)) ) { case 1: case 2: return pSpin1(); case 3: return pSpinS1(); case 4: case 5: return pSpinC1(); default: return 0.0; } } double SimpleFlavour::weightSU6QDiQSpin(long iq, long idq, int spin) { typedef Triplet QDiQS; typedef map QDiQSpinMap; static QDiQSpinMap qDiQSpin; QDiQS i(iq, idq, spin); QDiQSpinMap::iterator it = qDiQSpin.find(i); if ( it != qDiQSpin.end() ) return it->second; long idq1 = (idq/1000)%10; long idq2 = (idq/100)%10; if ( idq1 == idq2 ) { // Two of the same flavour in diquark, only spin 1 if ( iq == idq1 ) return qDiQSpin[i] = (spin == 4? 1.0: 0.0); return qDiQSpin[i] = (spin == 4? 1.0/3.0: 1.0/6.0); } else if ( idq%10 == 1 ) { // Spin 0 diquarks: if ( iq == idq1 || iq == idq2 ) return qDiQSpin[i] = (spin == 4? 0.0: 0.75); return qDiQSpin[i] = (spin == 4? 0.0: 0.5); } else { // Spin 1 diquarks: if ( iq == idq1 || iq == idq2 ) return qDiQSpin[i] = (spin == 4? 2.0/3.0: 1.0/12.0); return qDiQSpin[i] = (spin == 4? 1.0/3.0: 1.0/6.0); } } double SimpleFlavour::baryonDecupletProbability(long iq1, long iq2) const { double pd = weightSU6QDiQSpin(iq1, iq2, 4)*baryon10Sup(); double po = weightSU6QDiQSpin(iq1, iq2, 2); return pd/(pd + po); } tcPDPtr SimpleFlavour::getBaryon(long iq1, long iq2, long iq3) const { if ( abs(iq1) >= 10 || abs(iq2) >= 10 || abs(iq3) ) return tcPDPtr(); if ( iq1*iq2*iq3 == 0 ) return tcPDPtr(); int sign = 0; if ( iq1 > 0 && iq2 > 0 && iq3 > 0 ) sign = 1; if ( iq1 < 0 && iq2 < 0 && iq3 < 0 ) sign = -1; if ( !sign ) return tcPDPtr(); VSelector< pair > sel; iq1 = abs(iq1); iq2 = abs(iq2); iq3 = abs(iq3); sel.insert(3.0, make_pair(iq1, 1000*max(iq2, iq3) + 100*min(iq2, iq3) + 3)); if ( iq2 != iq3 ) sel.insert(1.0, make_pair(iq1, 1000*max(iq2, iq3) + 100*min(iq2, iq3) + 1)); sel.insert(3.0, make_pair(iq2, 1000*max(iq3, iq1) + 100*min(iq3, iq1) + 3)); if ( iq3 != iq1 ) sel.insert(1.0, make_pair(iq2, 1000*max(iq3, iq1) + 100*min(iq3, iq1) + 1)); sel.insert(3.0, make_pair(iq3, 1000*max(iq1, iq2) + 100*min(iq1, iq2) + 3)); if ( iq1 != iq2 ) sel.insert(1.0, make_pair(iq3, 1000*max(iq1, iq2) + 100*min(iq1, iq2) + 1)); pair qdq = sel[rnd()]; return getHadron(qdq.first, qdq.second); } tcPDPtr SimpleFlavour::getHadron(long iq1, long iq2) const { if ( iq1*iq2 == 0 ) return tcPDPtr(); if ( DiquarkMatcher::Check(iq1) ) swap(iq1, iq2); if ( DiquarkMatcher::Check(iq2) ) { if ( abs(iq1) >= 10 || iq1*iq2 < 0 ) return tcPDPtr(); return rndbool(baryonDecupletProbability(abs(iq1), abs(iq2)))? baryonDecuplet(iq1, iq2): baryonOctet(iq1, iq2); } else { if ( abs(iq1) >= 10 || abs(iq2) >= 10 || iq1*iq2 > 0 ) return tcPDPtr(); return rndbool(vectorMesonProbability(iq1, iq2))? vectorMeson(iq1, iq2): pseudoScalarMeson(iq1, iq2); } } tcPDPtr SimpleFlavour::pseudoScalarMeson(long iq, long iqb) const { return getParticleData((iq + iqb < 0? -1: 1)* pseudoScalarId(max(abs(iq), abs(iqb)), min(abs(iq), abs(iqb)))); } long SimpleFlavour::pseudoScalarId(long iqh, long iql) const { if ( iql == iqh && iql <= 3 ) { if ( iql <= 2 ) return rndbool()? ParticleID::pi0: ( rndbool()? ParticleID::eta: ParticleID::etaprime ); else return rndbool()? ParticleID::eta: ParticleID::etaprime; } else return (iqh*100 + iql*10 + 1)*(iqh != iql && iqh%2? -1: 1); } vector< pair > SimpleFlavour:: pseudoScalarIds(long iqh, long iql) const { vector< pair > ret; if ( iql == iqh && iql <= 3 ) { if ( iql <= 2 ) { ret.push_back(make_pair(ParticleID::pi0, 0.5)); ret.push_back(make_pair(ParticleID::eta, 0.25*etaSup())); ret.push_back(make_pair(ParticleID::etaprime, 0.25*etaPSup())); } else { ret.push_back(make_pair(ParticleID::eta, 0.5*etaSup())); ret.push_back(make_pair(ParticleID::etaprime, 0.5*etaPSup())); } } else { ret.push_back(make_pair((iqh*100 + iql*10 + 1)* (iqh != iql && iqh%2? -1: 1), 1.0)); } return ret; } tcPDPtr SimpleFlavour::vectorMeson(long iq, long iqb) const { return getParticleData((iq + iqb < 0? -1: 1)* vectorId(max(abs(iq), abs(iqb)), min(abs(iq), abs(iqb)))); } long SimpleFlavour::vectorId(long iqh, long iql) const { if ( iql == iqh && iql <= 2 ) return rndbool()? ParticleID::rho0: ParticleID::omega; else return (iqh*100 + iql*10 + 3)*(iqh != iql && iqh%2? -1: 1); } vector< pair > SimpleFlavour::vectorIds(long iqh, long iql) const { vector< pair > ret; if ( iql == iqh && iql <= 2 ) { ret.push_back(make_pair(ParticleID::rho0, 0.5)); ret.push_back(make_pair(ParticleID::omega, 0.5)); } else { ret.push_back(make_pair((iqh*100 + iql*10 + 3)* (iqh != iql && iqh%2? -1: 1), 1.0)); } return ret; } tcPDPtr SimpleFlavour::baryonOctet(long iq, long idq) const { long aiq = abs(iq); vector flv = PDT::flavourContent(idq); long iqa = max(abs(flv[0]), aiq); long iqc = min(abs(flv[1]), aiq); long iqb = abs(flv[0]) + abs(flv[1]) + aiq - iqa - iqc; return getParticleData((iq > 0? 1: -1)* baryonOctetId(iqa, iqb, iqc, aiq, (abs(idq)%10) == 3)); } long SimpleFlavour:: baryonOctetId(long iqa, long iqb, long iqc, long iq, bool dqs1) const { if ( iqa > iqb && iqb > iqc && ( ( dqs1 && ( iqa == iq || rndbool(0.25) ) ) || ( !dqs1 && iqa != iq && rndbool(0.75) ) ) ) swap(iqb, iqc); return 1000*iqa + 100*iqb + 10*iqc + 2; } vector< pair > SimpleFlavour:: baryonOctetIds(long iqa, long iqb, long iqc, long iq, bool dqs1) const { vector< pair > ret; double lambda = 0.0; if ( iqa > iqb && iqb > iqc ) { if ( dqs1 && iqa == iq ) lambda = 0.25; else if ( !dqs1 && iqa != iq ) lambda = 0.75; } ret.push_back(make_pair(1000*iqa + 100*iqb + 10*iqc + 2, 1.0 - lambda)); if ( lambda > 0.0 ) ret.push_back(make_pair(1000*iqa + 100*iqc + 10*iqb + 2, lambda)); return ret; } tcPDPtr SimpleFlavour::baryonDecuplet(long iq, long idq) const { long aiq = abs(iq); vector flv = PDT::flavourContent(idq); long iqa = max(abs(flv[0]), aiq); long iqc = min(abs(flv[1]), aiq); long iqb = abs(flv[0]) + abs(flv[1]) + aiq - iqa - iqc; return getParticleData((iq > 0? 1: -1)*baryonDecupletId(iqa, iqb, iqc)); } long SimpleFlavour:: baryonDecupletId(long iqa, long iqb, long iqc) const { return 1000*iqa + 100*iqb + 10*iqc + 4; } vector< pair > SimpleFlavour:: baryonDecupletIds(long iqa, long iqb, long iqc) const { vector< pair > ret; ret.push_back(make_pair(1000*iqa + 100*iqb + 10*iqc + 4, 1.0)); return ret; } void SimpleFlavour::persistentOutput(PersistentOStream & os) const { os << theSSup << theDiSup << theDi1Sup << theDiSSup << theEtaSup << theEtaPSup << theBaryon10Sup << thePSpin1 << thePSpinS1 << thePSpinC1; } void SimpleFlavour::persistentInput(PersistentIStream & is, int) { is >> theSSup >> theDiSup >> theDi1Sup >> theDiSSup >> theEtaSup >> theEtaPSup >> theBaryon10Sup >> thePSpin1 >> thePSpinS1 >> thePSpinC1; clear(); } ClassDescription SimpleFlavour::initSimpleFlavour; // Definition of the static class description member. void SimpleFlavour::Init() { static ClassDocumentation documentation ("This is a simple class to generate hadrons given the quark " "flavours. It implements a simplified version of the model of the " "old fortran version of Pythia."); static Parameter interfaceSSup ("SSup", "Suppression factor of strange quarks w.r.t. u and d.", &SimpleFlavour::theSSup, 0.3, 0.0, 1.0, true, false, true); static Parameter interfaceDiSup ("DiSup", "Suppression factor for di-quarks w.r.t. quarks.", &SimpleFlavour::theDiSup, 0.1, 0.0, 1.0, true, false, true); static Parameter interfaceDi1Sup ("Di1Sup", "Suppression of spin-1 di-quarks w.r.t. spin-0 ones.", &SimpleFlavour::theDi1Sup, 0.05, 0.0, 1.0, true, false, true); static Parameter interfaceDiSSup ("DiSSup", "Suppression of strange di-quarks w.r.t. u and d ones in addition to " "the standard strangness suppression of quarks.", &SimpleFlavour::theDiSSup, 0.4, 0.0, 1.0, true, false, true); static Parameter interfaceEtaSup ("EtaSup", "Extra suppression of eta's.", &SimpleFlavour::theEtaSup, 1.0, 0.0, 1.0, true, false, true); static Parameter interfaceEtaPSup ("EtaPSup", "Extra suppression of ets-prime's.", &SimpleFlavour::theEtaPSup, 0.4, 0.0, 1.0, true, false, true); static Parameter interfaceBaryon10Sup ("Baryon10Sup", "Extra suppression for baryons of the spin 3/2 decuplet.", &SimpleFlavour::theBaryon10Sup, 1.0, 0.0, 1.0, true, false, true); static Parameter interfacePSpin1 ("PSpin1", "Probability that light (u/d) mesons has spin 1.", &SimpleFlavour::thePSpin1, 0.5, 0.0, 1.0, true, false, true); static Parameter interfacePSpinS1 ("PSpinS1", "Probability that strange mesons has spin 1.", &SimpleFlavour::thePSpinS1, 0.6, 0.0, 1.0, true, false, true); static Parameter interfacePSpinC1 ("PSpinC1", " Probability that charmed and heavier mesons has spin 1.", &SimpleFlavour::thePSpinC1, 0.75, 0.0, 1.0, true, false, true); interfaceSSup.rank(10); interfaceDiSup.rank(9); interfaceDi1Sup.rank(8); interfaceBaryon10Sup.rank(7); interfacePSpin1.rank(6); interfacePSpinS1.rank(5); interfacePSpinC1.rank(4); } diff --git a/Handlers/SimpleFlavour.h b/Handlers/SimpleFlavour.h --- a/Handlers/SimpleFlavour.h +++ b/Handlers/SimpleFlavour.h @@ -1,451 +1,451 @@ // -*- C++ -*- // // SimpleFlavour.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_SimpleFlavour_H #define THEPEG_SimpleFlavour_H // This is the declaration of the SimpleFlavour class. #include "ThePEG/Handlers/FlavourGenerator.h" #include "ThePEG/Utilities/VSelector.h" // #include "SimpleFlavour.fh" // #include "SimpleFlavour.xh" namespace ThePEG { /** * SimpleFlavour is a simple class to generate hadrons given the quark * flavours. It implements a simplified version of the model of the * old fortran version of Pythia. * * @see \ref SimpleFlavourInterfaces "The interfaces" * defined for SimpleFlavour. */ class SimpleFlavour: public FlavourGenerator { public: /** A map of Selectors. */ typedef map > > ProbabilityMap; public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ SimpleFlavour(); /** * Destructor. */ virtual ~SimpleFlavour(); //@} public: /** @name Virtual functions mandated by the FlavourGenerator base class. */ //@{ /** * Generate a hadron from a quark. Given a quark(antiquark, diquark * or antidiquark), choose a quark-antiquark (or * antidiquark-diquark) pair. Return (first) a hadron formed by the * original quark and the antiquark together with (second) the * generated quark. Returns null pointers if the generation failed. * @param quark a quark, antiquark, diquark or antidiquark. * @return a pair of ParticleData pointers. The \a first is the * hadron produced and the \a second is the anti-partner of the * (anti-)(di-)quark generated to form the hadron. */ virtual tcPDPair generateHadron(tcPDPtr quark) const; /** * Get hadron from flavours. Return a hadron with the flavour * content given by the (anti-)(di-)quarks in the argument. The * arguments are given as PDG codes. * @param iq1 the PDG code of the first flavour. * @param iq2 the PDG code of the second flavour. * @return the corresponding hadron type or null if none could be * generated. */ virtual tcPDPtr getHadron(long iq1, long iq2) const; using FlavourGenerator::getHadron; /** * Return a baryon with the flavour content given by the * (anti)quarks in the argument. The arguments are given as * particle data pointers. * @param q1 the PDG code of the first flavour. * @param q2 the PDG code of the second flavour. * @param q3 the PDG code of the third flavour. * @return the corresponding baryon type or null if none could be * generated. */ virtual tcPDPtr getBaryon(long q1, long q2, long q3) const; using FlavourGenerator::getBaryon; /** * Generate a random quark flavour. */ virtual long selectQuark() const; /** * Generate a random (di)quark flavour. */ virtual long selectFlavour() const; //@} public: /** @name Access the parameters controlling the generation. */ //@{ /** * Return the suppression factor of strange quarks w.r.t. u and d. */ double sSup() const { return theSSup; } /** * Return the suppression factor for di-quarks w.r.t. quarks */ double diSup() const { return theDiSup; } /** * Return the suppression of spin-1 di-quarks w.r.t. spin-0 ones; */ double di1Sup() const { return theDi1Sup; } /** * Return the suppression of strange di-quarks w.r.t. u and d ones * in addition to the standard strangness suppression of quarks. */ double diSSup() const { return theDiSSup; } /** * Return the extra suppression of eta's */ double etaSup() const { return theEtaSup; } /** * Return the extra suppression of ets-prime's */ double etaPSup() const { return theEtaPSup; } /** * Return the extra suppression for baryons of the spin 3/2 * decuplet. */ double baryon10Sup() const { return theBaryon10Sup; } /** * Return the probability that light (u/d) mesons has spin 1; */ double pSpin1() const { return thePSpin1; } /** * Return the probability that strange mesons has spin 1; */ double pSpinS1() const { return thePSpinS1; } /** * Return the probability that charmed and heavier mesons has spin * 1; */ double pSpinC1() const { return thePSpinC1; } //@} protected: /** * Calculate the probabilities for generateHadron for the given * flavour. */ virtual void setProbabilities(long iq) const; /** * Return the probability that the given quark flavours end up in a * vector meson rather than in a pseudo scalar meson. */ virtual double vectorMesonProbability(long iq1, long iq2) const; /** * Return the probability that the given quark and diquark flavours * end up in a spin 3/2 decuplet baryon rather than in a spin 1/2 * octet baryon. */ virtual double baryonDecupletProbability(long iq1, long iq2) const; /** * Return a pseudo scalar meson formed by the two quark flavours. */ virtual tcPDPtr pseudoScalarMeson(long iq, long iqbar) const; /** * Return a vector meson formed by the two quark flavours. */ virtual tcPDPtr vectorMeson(long iq, long iqbar) const; /** * Return a spin 1/2 octet baryon formed by the given quark and * diquark flavours. */ virtual tcPDPtr baryonOctet(long iq, long idq) const; /** * Return a spin 3/2 decuplet baryon formed by the given quark and * diquark flavours. */ virtual tcPDPtr baryonDecuplet(long iq, long idq) const; /** * Return the PDG code of a pseudo scalar meson formed by the two * quark flavours for \a iqh >= \a iql > 0. */ virtual long pseudoScalarId(long iqh, long iql) const; /** * Return the PDG code of a vector meson formed by the two quark * flavours for \a iqh >= \a iql > 0. */ virtual long vectorId(long iqh, long iql) const; /** * Return the PDG code for a spin 1/2 octet baryon formed by the * given quark flavours (\a iqa >= \a iqb >= \a iqc > 0). iq is one * of the flavours and the other two are assumed to be in a diquark * (in a spin-1 state if \a dqs1). */ virtual long baryonOctetId(long iqa, long iqb, long iqc, long iq, bool dqs1) const; /** * Return the PDG code for a spin 3/2 decuplet baryon formed by the * given quark flavours (\a iqa >= \a iqb >= \a iqc > 0). */ virtual long baryonDecupletId(long iqa, long iqb, long iqc) const; /** * Return the PDG code of pseudo scalar mesons formed by the two * quark flavours (for \a iqh >= \a iql > 0), together with suitable * weights. */ virtual vector< pair > pseudoScalarIds(long iqh, long iql) const; /** * Return the PDG codes of vector mesons formed by the two quark * flavours (for \a iqh >= \a iql > 0), together with * suitable weights. */ virtual vector< pair > vectorIds(long iqh, long iql) const; /** * Return the PDG codes for spin 1/2 octet baryons formed by the * given quark flavours (\a iqa >= \a iqb >= \a iqc > 0) together * with suitable weights. iq is one of the flavours and the other * two are assumed to be in a diquark (in a spin-1 state if \a dqs1). */ virtual vector< pair > baryonOctetIds(long iqa, long iqb, long iqc, long iq, bool dqs1) const; /** * Return the PDG codes for spin 3/2 decuplet baryons formed by * the given quark flavours (\a iqa >= \a iqb >= \a iqc > 0) together with * suitable weights. */ virtual vector< pair > baryonDecupletIds(long iqa, long iqb, long iqc) const; /** * Clear all cashed weights. */ void clear(); /** * Return the SU(6) weight for the given quark and di-quark flavours * to end up with in a baryon with the given spin (2S+1). */ static double weightSU6QDiQSpin(long iq, long idq, int spin); 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(); 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(); //@} private: /** * Suppression factor of strange quarks w.r.t. u and d. */ double theSSup; /** * Suppression factor for di-quarks w.r.t. quarks. */ double theDiSup; /** * Suppression of spin-1 di-quarks w.r.t. spin-0 ones. */ double theDi1Sup; /** * Suppression of strange di-quarks w.r.t. u and d ones in addition * to the standard strangness suppression of quarks. */ double theDiSSup; /** * Extra suppression of eta's. */ double theEtaSup; /** * Extra suppression of ets-prime's. */ double theEtaPSup; /** * Extra suppression for baryons of the spin 3/2 decuplet. */ double theBaryon10Sup; /** * Probability that light (u/d) mesons has spin 1. */ double thePSpin1; /** * Probability that strange mesons has spin 1. */ double thePSpinS1; /** * Probability that charmed and heavier mesons has spin 1. */ double thePSpinC1; /** * A selector used to weight the creation of (di)quark-anti(di)quark * pairs. */ mutable VSelector theFlavourSelector; /** * A map of selectors to cash probabilities for generateHadron. */ mutable ProbabilityMap theProbabilities; private: /** * Describe a concrete class with persistent data. */ static ClassDescription initSimpleFlavour; /** * Private and non-existent assignment operator. */ SimpleFlavour & operator=(const SimpleFlavour &) = delete; }; } namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** * This template specialization informs ThePEG about the base class of * SimpleFlavour. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the base class of SimpleFlavour. */ typedef FlavourGenerator NthBase; }; template <> /** * This template specialization informs ThePEG about the name of the * SimpleFlavour class and the shared object where it is defined. */ struct ClassTraits : public ClassTraitsBase { /** Return the class name. */ static string className() { return "ThePEG::SimpleFlavour"; } /** * Return the name of the shared library to be loaded to get access * to the SimpleFlavour class and every other class it uses (except * the base class). */ static string library() { return "SimpleFlavour.so"; } }; /** @endcond */ } #endif /* THEPEG_SimpleFlavour_H */ diff --git a/Handlers/SimpleZGenerator.cc b/Handlers/SimpleZGenerator.cc --- a/Handlers/SimpleZGenerator.cc +++ b/Handlers/SimpleZGenerator.cc @@ -1,62 +1,62 @@ // -*- C++ -*- // // SimpleZGenerator.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the SimpleZGenerator class. // #include "SimpleZGenerator.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/PDT/StandardMatchers.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG; SimpleZGenerator::~SimpleZGenerator() {} IBPtr SimpleZGenerator::clone() const { return new_ptr(*this); } IBPtr SimpleZGenerator::fullclone() const { return new_ptr(*this); } double SimpleZGenerator::generate(cPDPtr q1, cPDPtr q2, Energy2) const { if ( BaryonMatcher::Check(*q1) || DiquarkMatcher::Check(*q1) ) { if ( BaryonMatcher::Check(*q2) || DiquarkMatcher::Check(*q2) ) return rnd(); else return sqrt(rnd()); } else { if ( BaryonMatcher::Check(*q2) || DiquarkMatcher::Check(*q2) ) return 1.0 - sqrt(rnd()); else return rnd(); } } void SimpleZGenerator::persistentOutput(PersistentOStream &) const {} void SimpleZGenerator::persistentInput(PersistentIStream &, int) {} ClassDescription SimpleZGenerator::initSimpleZGenerator; // Definition of the static class description member. void SimpleZGenerator::Init() { static ClassDocumentation documentation ("Implements a naive unphysical model to generate the momentum fraction " "\\f$z\\f$ taken by hadrons produced in a hadronization scenario. It " "should only be used for testing purposes."); } diff --git a/Handlers/SimpleZGenerator.h b/Handlers/SimpleZGenerator.h --- a/Handlers/SimpleZGenerator.h +++ b/Handlers/SimpleZGenerator.h @@ -1,150 +1,150 @@ // -*- C++ -*- // // SimpleZGenerator.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_SimpleZGenerator_H #define THEPEG_SimpleZGenerator_H // This is the declaration of the SimpleZGenerator class. #include "ThePEG/Handlers/ZGenerator.h" namespace ThePEG { /** * SimpleZGenerator is a very simple concrete subclass of * ZGenerator. It implements a naive unphysical model to generate the * momentum fraction, \f$z\f$, taken by hadrons produced in a hadronization * scenario. It should only be used for testing purposes. * * @see \ref SimpleZGeneratorInterfaces "The interfaces" * defined for SimpleZGenerator. */ class SimpleZGenerator: public ZGenerator { public: /** @name Standard constructors and destructors. */ //@{ /** * Destructor. */ virtual ~SimpleZGenerator(); //@} public: /** @name Virtual functions mandated by the ZGenerator base class. */ //@{ /** * Return the momentum fraction. Assume that an initial * (anti-)(di-)quark \a q1 produces a hadron and leaves behind * another (anti-)(di-)quark \a q2. The hadron is assumed to have a * squared transverse mass, \a mT2, w.r.t. the initial quark * direction. * @return the energy fraction distributed as \f$\sqrt{z}\f$ (or * \f$1-\sqrt{z}\f$) if \a q1 (or \a q2) is a diquark. Otherwise a * flat distribution is used. */ virtual double generate(cPDPtr q1, cPDPtr q2, Energy2 mT2 ) const; //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interfaces. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * Describe a concrete class with persistent data. */ static ClassDescription initSimpleZGenerator; /** * Private and non-existent assignment operator. */ SimpleZGenerator & operator=(const SimpleZGenerator &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** * This template specialization informs ThePEG about the base class of * SimpleZGenerator. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the base class of SimpleZGenerator. */ typedef ZGenerator NthBase; }; /** * This template specialization informs ThePEG about the name of the * SimpleZGenerator class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return the class name. */ static string className() { return "ThePEG::SimpleZGenerator"; } /** * Return the name of the shared library to be loaded to get access * to the SimpleZGenerator class and every other class it uses * (except the base class). */ static string library() { return "SimpleZGenerator.so"; } }; /** @endcond */ } #endif /* THEPEG_SimpleZGenerator_H */ diff --git a/Handlers/StandardEventHandler.cc b/Handlers/StandardEventHandler.cc --- a/Handlers/StandardEventHandler.cc +++ b/Handlers/StandardEventHandler.cc @@ -1,592 +1,592 @@ // -*- C++ -*- // // StandardEventHandler.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the StandardEventHandler class. // #include "StandardEventHandler.h" #include "ThePEG/Handlers/StandardXComb.h" #include "ThePEG/Handlers/StdXCombGroup.h" #include "ThePEG/Handlers/SubProcessHandler.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Utilities/SimplePhaseSpace.h" #include "ThePEG/Utilities/LoopGuard.h" #include "ThePEG/Utilities/Debug.h" #include "ThePEG/PDF/PartonExtractor.h" #include "ThePEG/MatrixElement/MEBase.h" #include "ThePEG/MatrixElement/MEGroup.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Handlers/LuminosityFunction.h" #include "ThePEG/Handlers/SamplerBase.h" #include "ThePEG/Handlers/CascadeHandler.h" #include "ThePEG/Cuts/Cuts.h" #include "ThePEG/Config/algorithm.h" #include #include using namespace ThePEG; StandardEventHandler::StandardEventHandler() : EventHandler(false), collisionCuts(true), theLumiDim(0) { setupGroups(); } StandardEventHandler::~StandardEventHandler() {} void StandardEventHandler::reject(double w) { tStdXCombPtr last = dynamic_ptr_cast(lastXCombPtr()); if ( !last ) return; last->reject(w); xSecStats.reject(w); } void StandardEventHandler::reweight(double factor) const { tStdXCombPtr last = dynamic_ptr_cast(lastXCombPtr()); if ( !currentEvent() || !last ) return; double weight = currentEvent()->weight(); last->reweight(weight,factor*weight); xSecStats.reweight(weight,factor*weight); currentEvent()->weight(factor*weight); for ( map::iterator w = currentEvent()->optionalWeights().begin(); w != currentEvent()->optionalWeights().end(); ++w ) w->second *= factor; } void StandardEventHandler::doupdate() { EventHandler::doupdate(); bool redo = touched(); UpdateChecker::check(theIncomingA, redo); UpdateChecker::check(theIncomingB, redo); for_each(subProcesses(), UpdateChecker(redo)); if ( !redo ) return; theIncoming.first = theIncomingA; theIncoming.second = theIncomingB; for ( SubHandlerList::iterator sit = subProcesses().begin(); sit != subProcesses().end(); ++sit ) if ( !(**sit).pExtractor()->canHandle(incoming()) ) throw StandardEventHandlerUpdateException() << "Cannot use the parton extractor '" << (**sit).pExtractor()->name() << "' in the SubProcessHandler '" << (**sit).name() << "' in the " << "StandardEventHandler '" << name() << "' since it cannot handle " << "the requested types of incoming particles (" << theIncomingA->name() << "," << theIncomingB->name() << ")."; } void StandardEventHandler::doinit() { EventHandler::doinit(); if ( !lumiFnPtr() ) throw StandardEventHandlerUpdateException() << "The StandardEventHandler '" << name() << "' does not have any " << "LuminosityFunction object assigned to it, which it needs to be " << "able to generate events." << Exception::warning; } IBPtr StandardEventHandler::clone() const { return new_ptr(*this); } IBPtr StandardEventHandler::fullclone() const { return new_ptr(*this); } void StandardEventHandler:: addME(Energy maxEnergy, tSubHdlPtr sub, tPExtrPtr extractor, tCutsPtr cuts, tCascHdlPtr ckkw, tMEPtr me, const PBPair & pBins, const PartonPairVec& allPBins) { typedef MEBase::DiagramVector DiagramVector; typedef map DiagramMap; cPDPair pin(pBins.first->parton(), pBins.second->parton()); DiagramVector diag = me->diagrams(); DiagramMap tdiag; DiagramMap tmdiag; for ( int i = 0, N = diag.size(); i < N; ++i ) { cPDPair din(diag[i]->partons()[0], diag[i]->partons()[1]); if (!me->noMirror()) if ( din.first->id() < din.second->id() ) swap(din.first, din.second); if ( din == pin ) tdiag[diag[i]->getTag()].push_back(diag[i]); if (!me->noMirror()) if ( din.first == pin.second && din.second == pin.first ) tmdiag[diag[i]->getTag()].push_back(diag[i]); } if ( tdiag.empty() ) tdiag = tmdiag; for ( DiagramMap::iterator dit = tdiag.begin(); dit != tdiag.end(); ++dit ) { cPDPair din(dit->second.back()->partons()[0], dit->second.back()->partons()[1]); // check assert(me->noMirror() ? din == pin : true); StdXCombPtr xcomb = me->makeXComb(maxEnergy, incoming(), this, sub, extractor, ckkw, pBins, cuts, dit->second, din != pin, allPBins); if ( xcomb->checkInit() ) xCombs().push_back(xcomb); else generator()->logWarning( StandardEventHandlerInitError() << "The matrix element '" << xcomb->matrixElement()->name() << "' cannot generate the diagram '" << dit->first << "' when used together with the parton extractor '" << xcomb->pExtractor()->name() << "'.\nThe corresponding diagram is switched off, " << "check the collision energy and/or the cuts." << Exception::warning); } } void StandardEventHandler::initGroups() { tStdXCombPtr lastXC = dynamic_ptr_cast(lastXCombPtr()); if ( lastXC ) optGroups = lastXC->subProcessHandler()->groups(); EventHandler::initGroups(); } tCollPtr StandardEventHandler::performCollision() { tStdXCombPtr lastXC = dynamic_ptr_cast(lastXCombPtr()); if ( CKKWHandler() ) CKKWHandler()->setXComb(lastXCombPtr()); lastExtractor()->select(lastXC); currentCollision(new_ptr(Collision(lastParticles(), currentEvent(), this))); if ( currentEvent() ) currentEvent()->addCollision(currentCollision()); currentStep(new_ptr(Step(currentCollision()))); currentCollision()->addStep(currentStep()); currentStep()->addSubProcess(lastXC->construct()); if ( currentEvent() ) { map optionalWeights = lastXC->generateOptionalWeights(); for ( const auto& weight : optionalWeights ) currentEvent()->optionalWeights().insert(weight); } lastExtractor()->construct(lastXC->partonBinInstances(), currentStep()); if ( collisionCuts ) if ( !lastCuts().passCuts(*currentCollision()) ) throw Veto(); initGroups(); if ( ThePEG_DEBUG_ITEM(1) ) { if ( currentEvent() ) generator()->logfile() << *currentEvent(); else generator()->logfile() << *currentCollision(); } return continueCollision(); } void StandardEventHandler::setScale(Energy2 scale) { lastXCombPtr()->lastScale(scale); } void StandardEventHandler::initialize() { theLumiDim = lumiFn().nDim(incoming()); Energy maxEnergy = lumiFn().maximumCMEnergy(); xCombs().clear(); cuts()->initialize(sqr(maxEnergy), lumiFn().Y()); for ( SubHandlerList::const_iterator sit = subProcesses().begin(); sit != subProcesses().end(); ++sit ) { CutsPtr kincuts = (**sit).cuts()? (**sit).cuts(): cuts(); if ( (**sit).cuts() ) kincuts->initialize(sqr(maxEnergy), lumiFn().Y()); PExtrPtr pextract = (**sit).pExtractor(); tCascHdlPtr ckkw = (**sit).CKKWHandler(); if ( !ckkw ) ckkw = CKKWHandler(); PartonPairVec vpc = pextract->getPartons(maxEnergy, incoming(), *kincuts); // The last parton bin pair was in fact the bins corresponding to // the incoming particles, so we remove them, but save them to // keep them referenced. PBPair orig = vpc.back(); vpc.pop_back(); for ( PartonPairVec::iterator ppit = vpc.begin(); ppit != vpc.end(); ++ppit ) for ( MEVector::const_iterator meit = (**sit).MEs().begin(); meit != (**sit).MEs().end(); ++meit ) { addME(maxEnergy, *sit, pextract, kincuts, ckkw, *meit, *ppit,vpc); } } theMaxDims.clear(); for ( int i = 0, N = xCombs().size(); i < N; ++i ) theMaxDims.push_back(xCombs()[i]->nDim()); sampler()->setEventHandler(this); sampler()->initialize(); } CrossSection StandardEventHandler:: dSigDR(const pair ll, Energy2 maxS, int ibin, int nr, const double * r) { PPair inc = make_pair(incoming().first->produceParticle(), incoming().second->produceParticle()); SimplePhaseSpace::CMS(inc, maxS); xCombs()[ibin]->prepare(inc); return xCombs()[ibin]->dSigDR(ll, nr, r); } tStdXCombPtr StandardEventHandler::select(int bin, double & weight) { tStdXCombPtr lastXC = xCombs()[bin]; // clean up the old XComb object before switching to a new one if ( theLastXComb && theLastXComb != lastXC ) theLastXComb->clean(); theLastXComb = lastXC; weight /= lastXC->matrixElement()->preWeight(); lastXC->select(weight); xSecStats.select(weight); lastXC->accept(); xSecStats.accept(); return lastXC; } int StandardEventHandler::nBins() const { return xCombs().size(); } void StandardEventHandler::statistics(ostream & os) const { if ( statLevel() == 0 ) return; map partonMap; map meMap; map extractMap; XSecStat tot(sampler()->maxXSec()); for ( int i = 0, N = xCombs().size(); i < N; ++i ) { const StandardXComb & x = *xCombs()[i]; if ( partonMap.find(x.partons()) == partonMap.end() ) partonMap[x.partons()] = XSecStat(sampler()->maxXSec()); partonMap[x.partons()] += x.stats(); if ( meMap.find(x.matrixElement()) == meMap.end() ) meMap[x.matrixElement()] = XSecStat(sampler()->maxXSec()); meMap[x.matrixElement()] += x.stats(); if ( extractMap.find(x.pExtractor()) == extractMap.end() ) extractMap[x.pExtractor()] = XSecStat(sampler()->maxXSec()); extractMap[x.pExtractor()] += x.stats(); tot += x.stats(); } string line = string(78, '=') + "\n"; if ( tot.accepted() <= 0 ) { os << line << "No events generated by event handler '" << name() << "'." << endl; return; } os << line << "Statistics for event handler \'" << name() << "\':\n" << " " << "generated number of Cross-section\n" << " " << " events attempts (nb)\n"; os << line << "Total (from attempted events): including vetoed events" << setw(23) << ouniterr(sampler()->integratedXSec(), sampler()->integratedXSecErr(), nanobarn) << endl; os << line << "Total (from generated events):" << setw(17) << tot.accepted() << setw(13) << tot.attempts() << setw(17) << ouniterr(tot.xSec(sampler()->attempts()),tot.xSecErr(sampler()->attempts()) , nanobarn) << "\n"; os << "Events carry "; if ( weighted() ) os << "varying weights."; else if ( sampler()->almostUnweighted() ) os << "varying weights, most of which are unit weights."; else os << "unit weights."; os << endl << line; if ( statLevel() == 1 ) return; os << "Per matrix element breakdown:\n"; for ( map::iterator i = meMap.begin(); i != meMap.end(); ++i ) { string n = i->first->name(); n.resize(37, ' '); os << n << setw(11) << i->second.accepted() << setw(13) << i->second.attempts() << setw(17) << ouniterr(i->second.xSec(sampler()->attempts()), i->second.xSecErr(sampler()->attempts()), nanobarn) << endl; } os << line; if ( statLevel() == 2 ) return; os << "Per parton extractor breakdown:\n"; for ( map::iterator i = extractMap.begin(); i != extractMap.end(); ++i ) { string n = i->first->name(); n.resize(37, ' '); os << n << setw(11) << i->second.accepted() << setw(13) << i->second.attempts() << setw(17) << ouniterr(i->second.xSec(sampler()->attempts()), i->second.xSecErr(sampler()->attempts()), nanobarn) << endl; } os << line; os << "Per incoming partons breakdown:\n"; for ( map::iterator i = partonMap.begin(); i != partonMap.end(); ++i ) { string n = i->first.first->PDGName() + " " + i->first.second->PDGName(); n.resize(37, ' '); os << n << setw(11) << i->second.accepted() << setw(13) << i->second.attempts() << setw(17) << ouniterr(i->second.xSec(sampler()->attempts()), i->second.xSecErr(sampler()->attempts()), nanobarn) << endl; } os << line; if ( statLevel() == 3 ) return; os << "Detailed breakdown:\n"; for ( int i = 0, N = xCombs().size(); i < N; ++i ) { const StandardXComb & x = *xCombs()[i]; XSecStat xstat(sampler()->maxXSec()); xstat += x.stats(); os << "(" << x.pExtractor()->name() << ") " << x.partons().first->PDGName() << " " << x.partons().second->PDGName() << " (" << x.matrixElement()->name() << " " << x.lastDiagram()->getTag() << ") " << endl << setw(48) << xstat.accepted() << setw(13) << xstat.attempts() << setw(17) << ouniterr(xstat.xSec(sampler()->attempts()), xstat.xSecErr(sampler()->attempts()), nanobarn) << endl; } os << line; } CrossSection StandardEventHandler::histogramScale() const { xSecStats.maxXSec(sampler()->maxXSec()); return xSecStats.xSec(sampler()->attempts())/xSecStats.sumWeights(); } CrossSection StandardEventHandler::integratedXSec() const { xSecStats.maxXSec(sampler()->maxXSec()); return xSecStats.xSec(sampler()->attempts()); } CrossSection StandardEventHandler::integratedXSecErr() const { xSecStats.maxXSec(sampler()->maxXSec()); return xSecStats.xSecErr(sampler()->attempts()); } CrossSection StandardEventHandler::integratedXSecNoReweight() const { xSecStats.maxXSec(sampler()->maxXSec()); return xSecStats.xSecNoReweight(sampler()->attempts()); } CrossSection StandardEventHandler::integratedXSecErrNoReweight() const { xSecStats.maxXSec(sampler()->maxXSec()); return xSecStats.xSecErrNoReweight(sampler()->attempts()); } void StandardEventHandler::doinitrun() { EventHandler::doinitrun(); for ( SubHandlerList::iterator sit = subProcesses().begin(); sit != subProcesses().end(); ++sit ) (**sit).initrun(); sampler()->initrun(); for ( int i = 0, N = xCombs().size(); i < N; ++i ) xCombs()[i]->reset(); xSecStats.reset(); } CrossSection StandardEventHandler::dSigDR(const vector & r) { double jac = 1.0; pair ll = lumiFn().generateLL(&r[0], jac); Energy2 maxS = sqr(lumiFn().maximumCMEnergy())/exp(ll.first + ll.second); int bin = sampler()->lastBin(); CrossSection x = jac*lumiFn().value(incoming(), ll.first, ll.second) *dSigDR(ll, maxS, bin, nDim(bin) - lumiDim(), &r[lumiDim()]); return x; } EventPtr StandardEventHandler::generateEvent() { LoopGuard loopGuard(*this, maxLoop()); while (1) { loopGuard(); EventHandler::clean(); double weight = sampler()->generate(); tStdXCombPtr lastXC = select(sampler()->lastBin(), weight); try { lumiFn().select(lastXC); currentEventBoost() = lumiFn().getBoost(); currentEvent(new_ptr(Event(lastParticles(), this, generator()->runName(), generator()->currentEventNumber(), weight))); performCollision(); if ( !currentCollision() ) throw Veto(); currentEvent()->transform(currentEventBoost()); return currentEvent(); } catch (Veto) { reject(currentEvent()->weight()); } catch (Stop) { break; } catch (Exception &) { reject(currentEvent()->weight()); throw; } } return currentEvent(); } EventPtr StandardEventHandler::continueEvent() { if ( !generator() ) throw StandardEventHandlerInitError() << "The event handler '" << name() << "' had not been isolated " << "from the setup phase before it was used." << Exception::maybeabort; try { continueCollision(); } catch (Veto) { reject(currentEvent()->weight()); } catch (Stop) { } catch (Exception &) { reject(currentEvent()->weight()); throw; } return currentEvent(); } void StandardEventHandler::select(tXCombPtr newXComb) { EventHandler::select(newXComb); lastExtractor()->select(newXComb); } void StandardEventHandler::clean() { if ( theLastXComb ) theLastXComb->clean(); for (size_t i=0; i < theXCombs.size(); ++i ) if ( theXCombs[i] ) theXCombs[i]->clean(); EventHandler::clean(); } void StandardEventHandler::dofinish() { clean(); EventHandler::dofinish(); } ClassDescription StandardEventHandler::initStandardEventHandler; // void StandardEventHandler::setIncomingA(PDPtr p) { theIncomingA = p; theIncoming.first = p; } void StandardEventHandler::setIncomingB(PDPtr p) { theIncomingB = p; theIncoming.second = p; } void StandardEventHandler::Init() { static ClassDocumentation documentation ("This is the standard event handler to generate hard sub-processes " "within ThePEG. It must specify a pair of incoming particle beams " "in BeamA and BeamB " "and a suiteable LuminosityFunction. In " "addition at least one object describing the sub-processes to be " "generated must be specified in " "SubProcessHandlers."); static Reference interfaceIncomingA ("BeamA", "The type of particles in first beam", &StandardEventHandler::theIncomingA, false, false, true, false, &StandardEventHandler::setIncomingA); static Reference interfaceIncomingB ("BeamB", "The type of particles in second beam", &StandardEventHandler::theIncomingB, false, false, true, false, &StandardEventHandler::setIncomingB); static RefVector interfaceSubhandlers ("SubProcessHandlers", "The list of sub-process handlers used in this StandardEventHandler. ", &StandardEventHandler::theSubProcesses, 0, false, false, true, false); static Reference interfaceCuts ("Cuts", "Common kinematical cuts for this StandardEventHandler. These cuts " "may be overidden in individual sub-process handlers.", &StandardEventHandler::theCuts, false, false, true, false); static Switch interfaceCollisionCuts ("CollisionCuts", "Switch on or off cuts on collision objects", &StandardEventHandler::collisionCuts, true, false, false); static SwitchOption interfaceCollisionCutsOn (interfaceCollisionCuts, "On", "Switch on cuts on collision objects", true); static SwitchOption interfaceCollisionCutsOff (interfaceCollisionCuts, "Off", "Switch off cuts on collision cuts", false); static SwitchOption interfaceCollisionCutsYes (interfaceCollisionCuts, "Yes", "Switch on cuts on collision objects", true); static SwitchOption interfaceCollisionCutsNo (interfaceCollisionCuts, "No", "Switch off cuts on collision cuts", false); static Reference interfaceSampler ("Sampler", "The phase space sampler responsible for generating phase space" "points according to the cross section given by this event handler", &StandardEventHandler::theSampler, false, false, true, true); interfaceSubhandlers.rank(11); interfaceIncomingA.rank(3); interfaceIncomingB.rank(2); } void StandardEventHandler::persistentOutput(PersistentOStream & os) const { os << theIncomingA << theIncomingB << theSubProcesses << theCuts << collisionCuts << theXCombs << theMaxDims << theSampler << theLumiDim << xSecStats; } void StandardEventHandler::persistentInput(PersistentIStream & is, int) { is >> theIncomingA >> theIncomingB >> theSubProcesses >> theCuts >> collisionCuts >> theXCombs >> theMaxDims >> theSampler >> theLumiDim >> xSecStats; } diff --git a/Handlers/StandardEventHandler.h b/Handlers/StandardEventHandler.h --- a/Handlers/StandardEventHandler.h +++ b/Handlers/StandardEventHandler.h @@ -1,511 +1,511 @@ // -*- C++ -*- // // StandardEventHandler.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_StandardEventHandler_H #define ThePEG_StandardEventHandler_H // This is the declaration of the StandardEventHandler class. #include "ThePEG/Config/ThePEG.h" #include "ThePEG/Handlers/EventHandler.h" #include "ThePEG/Repository/Strategy.fh" #include "ThePEG/Handlers/SamplerBase.fh" #include "ThePEG/PDF/PartonBin.fh" #include "ThePEG/MatrixElement/MEBase.fh" #include "SubProcessHandler.fh" #include "StandardXComb.fh" #include "StandardEventHandler.fh" #include "ThePEG/Utilities/XSecStat.h" #include namespace ThePEG { /** * The StandardEventHandler class is the main class for generating simple * events without overlayed collisions. It is derived from the * basic EventHandler class. * * Besides the standard doinit() method, the StandardEventHandler needs to be * separately initialized with the initialize() method. In the * dofinish() method statistics is written out to the EventGenerators * default output file. * * @see \ref StandardEventHandlerInterfaces "The interfaces" * defined for StandardEventHandler. * @see EventHandler * @see EventGenerator * @see Event * */ class StandardEventHandler: public EventHandler { public: /** A vector of SubProcessHandlers. */ typedef vector SubHandlerList; /** A weighted list of pointers to StandardXComb objects. */ typedef Selector XSelector; /** A vector of pointers to StandardXComb objects. */ typedef vector XVector; /** A vector of cross sections. */ typedef vector XSVector; /** Map of pointers to StandardXComb objects indexed by pointers to * the corresponding MEBase object. */ typedef map MEXMap; public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ StandardEventHandler(); /** * Destructor. */ virtual ~StandardEventHandler(); //@} public: /** * 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; /** * Return the sampler assigned to this event handler. */ tSamplerPtr sampler() { return theSampler; } /** * Return the sampler assigned to this event handler. */ tcSamplerPtr sampler() const { return theSampler; } /** * 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 estimated error int 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; /** * The estimated total integrated cross section of the processes * generated in this run, excluding reweighting. * @return 0 if no integrated cross section could be estimated. */ virtual CrossSection integratedXSecNoReweight() const; /** * The estimated error int total integrated cross section of the * processes generated in this run, excluding reweighting. * @return 0 if no integrated cross section error could be estimated. */ virtual CrossSection integratedXSecErrNoReweight() const; /** @name Functions used for the actual generation */ //@{ /** * Return the cross section for the chosen phase space point. * @param r a vector of random numbers to be used in the generation * of a phase space point. */ virtual CrossSection dSigDR(const vector & r); /** * Generate an event. */ virtual EventPtr generateEvent(); /** * Continue generating an event if the generation has been stopped * before finishing. */ virtual EventPtr continueEvent(); /** * Reweight a partially generated event. */ void reweight(double factor) const; /** * Return the vector of StandardXComb objects. */ const XVector & xCombs() const { return theXCombs; } /** * Change the XComb object */ virtual void select(tXCombPtr newXComb); /** * Return the boost needed to transform the current event from the * CMS system to the lab system. */ const LorentzRotation & currentEventBoost() const { return theCurrentEventBoost; } //@} /** @name Simple access functions */ //@{ /** * Return a reference to the Cuts of this * EventHandler. Note that these cuts may be overridden by the * SubProcess chosen. */ tCutsPtr cuts() const { return theCuts; } /** * Return the number of separate bins of StandardXComb objects to * sample. */ int nBins() const; /** * Return the number of phase space dimensions needed for the * sampling of indicated bin of StandardXComb objects. */ int maxDim(int bin) const { return theMaxDims[bin]; } /** * The number of phase space dimensions used by the luminosity * function. */ int lumiDim() const { return theLumiDim; } /** * The number of dimensions of the basic phase space to generate * sub-processes in for a given bin of StandardXComb objects. */ int nDim(int bin) const { return lumiDim() + maxDim(bin); } //@} protected: /** * Generate a phase space point and return the corresponding cross * section. Is called from sSigDR(const vector &). * @param ll a pair of doubles giving the logarithms of the (inverse * energy fractions of the maximum CMS energy of the incoming * particles. * @param maxS the maximum squared CMS energy of the incoming particles. * @param ibin the preselected bin of StandardXComb objects to choose * sub-process from * @param nr the number of random numbers availiable in \a r. * @param r an array of random numbers to be used to generate a * phase-space point. */ virtual CrossSection dSigDR(const pair ll, Energy2 maxS, int ibin, int nr, const double * r); /** * Select an StandardXComb. Given a preselected bin, \a ibin of * StandardXComb objects pick one to generate the corresponding * sub-process with the given \a weight. */ tStdXCombPtr select(int bin, double & weight); /** * Create and add StandardXComb objects. * * @param maxEnergy the maximum CMS energy of the incoming particles. * @param sub a pointer to the SubProcessHandler object. * @param extractor a pointer to the PartonExtractor object. * @param cuts a pointer to the Cuts object. * @param ckkw a pointer to a CascadeHandler to be used for CKKW reweighting. * @param me a pointer to the MEBase object. * @param pBins a pair of PartonBins describing the * partons extracted from the particles * @param allPBins all available parton bins at the given energy */ void addME(Energy maxEnergy, tSubHdlPtr sub, tPExtrPtr extractor, tCutsPtr cuts, tCascHdlPtr ckkw, tMEPtr me, const PBPair & pBins, const PartonPairVec& allPBins); /** * For the sub-procss and phase-space point selected in the previous * call to dSigDR, produce the first step of an actual Collision. */ tCollPtr performCollision(); /** * Initialize groups of StepHandlers. This overrides * the method in the EventHandler, and the * StepHandlers given in the currently selected * SubProcess take precedence over the ones specified in the * EventHandler sub class. */ virtual void initGroups(); /** * Return the boost needed to transform the current collision from * the CMS system to the lab system. By default this is the unit * transformation, but an EventHandler derived from this class may * override it. */ LorentzRotation & currentEventBoost() { return theCurrentEventBoost; } /** * Set information about the current sub-process. */ void setScale(Energy2); /** * Return the vector of StandardXComb objects. */ XVector & xCombs() { return theXCombs; } /** * Throw away the last generated event before generating a new one. */ virtual void clean(); private: /** * Access the list of sub-process handlers. */ const SubHandlerList & subProcesses() const { return theSubProcesses; } /** * Access the list of sub-process handlers. */ SubHandlerList & subProcesses() { return theSubProcesses; } public: /** @name Standard Interfaced functions. */ //@{ /** * Check sanity of the object during the setup phase. */ virtual void doupdate(); /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * 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. Writes out statistics on the generation. */ virtual void dofinish(); //@} /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interface. */ static void Init(); 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; //@} /** * Reject a (partially) generated event. * @param weight the weight given for the event. */ void reject(double weight); private: /** * The first of the incoming particle types. */ PDPtr theIncomingA; /** * The second of the incoming particle types. */ PDPtr theIncomingB; /** * The list of SubProcessHandlers. */ SubHandlerList theSubProcesses; /** * The kinematical cuts used for this collision handler. */ CutsPtr theCuts; /** * True if cuts on collision objects should be performed */ bool collisionCuts; /** * The StandardXComb objects. */ XVector theXCombs; /** * The number of degrees of freedom needed to generate the phase * space for the different bins. */ vector theMaxDims; /** * The boost needed to transform the current collision from the CMS * system to the lab system. */ LorentzRotation theCurrentEventBoost; /** * The phase space sampler responsible for generating phase space * points according to the cross section given by this event * handler. */ SamplerPtr theSampler; /** * The number of phase space dimensions used by the luminosity * function. */ int theLumiDim; /** * The overall cross section statistics */ mutable XSecStat xSecStats; /** * Standard Initialization object. */ static ClassDescription initStandardEventHandler; /** * Helper function for the interface. */ void setIncomingA(PDPtr); /** * Helper function for the interface. */ void setIncomingB(PDPtr); protected: /** @cond EXCEPTIONCLASSES */ /** * Exception class used by EventHandler when a StepHandler of the * wrong class was added. */ class StandardEventHandlerUpdateException: public UpdateException {}; /** * Exception class used by EventHandler when a StepHandler of the * wrong class was added. */ class StandardEventHandlerInitError: public Exception {}; /** @endcond */ private: /** * Private and non-existent assignment operator. */ const StandardEventHandler & operator=(const StandardEventHandler &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** * The following template specialization informs ThePEG about the * base class of StandardEventHandler. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the base class of StandardEventHandler. */ typedef EventHandler NthBase; }; /** * The following template specialization informs ThePEG about the name * of theEventHandler class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** * Return the class name. */ static string className() { return "ThePEG::StandardEventHandler"; } }; /** @endcond */ } #endif /* ThePEG_StandardEventHandler_H */ diff --git a/Handlers/StandardXComb.cc b/Handlers/StandardXComb.cc --- a/Handlers/StandardXComb.cc +++ b/Handlers/StandardXComb.cc @@ -1,835 +1,835 @@ // -*- C++ -*- // // StandardXComb.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad -// Copyright (C) 2009-2017 Simon Platzer +// Copyright (C) 1999-2019 Leif Lonnblad +// Copyright (C) 2009-2019 Simon Platzer // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the 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 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; } 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 ( 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; } map StandardXComb::generateOptionalWeights() { matrixElement()->setXComb(this); return matrixElement()->generateOptionalWeights(); } 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()); lastPartons().first ->scale(partonBinInstances().first ->scale()); lastPartons().second->scale(partonBinInstances().second->scale()); 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/Handlers/StandardXComb.h b/Handlers/StandardXComb.h --- a/Handlers/StandardXComb.h +++ b/Handlers/StandardXComb.h @@ -1,767 +1,767 @@ // -*- C++ -*- // // StandardXComb.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad -// Copyright (C) 2009-2017 Simon Platzer +// Copyright (C) 1999-2019 Leif Lonnblad +// Copyright (C) 2009-2019 Simon Platzer // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_StandardXComb_H #define ThePEG_StandardXComb_H // This is the declaration of the StandardXComb class. #include "ThePEG/Config/ThePEG.h" #include "SubProcessHandler.fh" #include "ThePEG/PDF/PartonExtractor.fh" #include "ThePEG/PDF/PartonBin.h" #include "ThePEG/PDF/PartonBinInstance.h" #include "ThePEG/Utilities/VSelector.h" #include "ThePEG/Utilities/ClassDescription.h" #include "ThePEG/Utilities/Maths.h" #include "ThePEG/Utilities/XSecStat.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/MatrixElement/MEBase.h" #include "ThePEG/Handlers/XComb.h" #include "ThePEG/Handlers/StandardEventHandler.h" #include "ThePEG/Handlers/SubProcessHandler.fh" #include "StandardXComb.fh" namespace ThePEG { /** * The StandardXComb class inherits from the more general XComb class * which stores all information about the generation of a hard * sub-proces for a given pair of incoming particles, a pair of * extracted partons, etc. This class stores more information related * to thestandard process generation scheme in ThePEG, such as the * PartonExtractor and MEBase object used. It also does some of the * administration of the process generation. * * The main function is dSigDR() which returns the differential cross * section w.r.t. a given vector of random numbers in the interval * ]0,1[. In the initialization this is used to pre-sample the phase * space. In the generation phase it is used to give the cross section * for a phase space point, and if this StandardXComb is chosen the * construct() function is called to generate the actual sub-process. * * @see ParonExtractor * @see MEBase * @see Cuts * @see StdXCombGroup */ class StandardXComb: public XComb { public: /** A vector of DiagramBase objects. */ typedef MEBase::DiagramVector DiagramVector; /** A vector of indices. */ typedef MEBase::DiagramIndex DiagramIndex; /** MEBase needs to be a friend. */ friend class MEBase; public: /** @name Standard constructors and destructors. */ //@{ /** * Standard constructor. */ StandardXComb(Energy newMaxEnergy, const cPDPair & inc, tEHPtr newEventHandler,tSubHdlPtr newSubProcessHandler, tPExtrPtr newExtractor, tCascHdlPtr newCKKW, const PBPair & newPartonBins, tCutsPtr newCuts, tMEPtr newME, const DiagramVector & newDiagrams, bool mir, tStdXCombPtr newHead = tStdXCombPtr()); /** * Constructor given a head xcomb. */ StandardXComb(tStdXCombPtr newHead, const PBPair & newPartonBins, tMEPtr newME, const DiagramVector & newDiagrams); /** * Default constructor. */ StandardXComb(); /** * Destructor. */ virtual ~StandardXComb(); /** * Constructor used by MEBase to create a temporary object to store info. */ StandardXComb(tMEPtr me, const tPVector & parts, DiagramIndex i); //@} /** @name Utilities for incoming partons. */ //@{ /** * Properly setup the PartonBinInstance objects provided a sub * process has been constructed using this XComb. */ void recreatePartonBinInstances(Energy2 scale); /** * Fill the variables needed to generate remnants; momenta will be * used from the partons set in this xcomb, but random numbers need * to be provided to (re)generate variables not fixed by the * incoming partons. */ void refillPartonBinInstances(const double* r); /** * Setup information on incoming partons depending * on the information previously supplied through the * choice of diagram and incoming momenta in the first * two entries of meMomenta(). Partons are not actually * extracted from the incoming particles, though a subprocess * detached from the current Event may be created. */ bool setIncomingPartons(tStdXCombPtr labHead = tStdXCombPtr()); /** * Fill phase space information as far as possible */ void fill(const PPair& newParticles, const PPair& newPartons, const vector& newMEMomenta, const DVector& newLastRandomNumbers = DVector()); //@} /** @name Access the assigned objects used in the generation. */ //@{ /** * Return a pointer to the corresponding sub-process handler. May be * null if the standard process generation in ThePEG was not used. */ tcSubHdlPtr subProcessHandler() const { return theSubProcessHandler; } /** * The matrix element to be used. */ tMEPtr matrixElement() const { return theME; } /** * Return a pointer to the head XComb this XComb * depends on. May return NULL, if this is not a * member of a XComb group. */ tStdXCombPtr head() const { return theHead; } /** * Set the head XComb pointer. */ void head(tStdXCombPtr headXC) { theHead = headXC; } /** * Return a selector object of xcombs to choose subprocesses * different than the one currently integrated. */ Selector& projectors() { return theProjectors; } /** * Return a selector object of xcombs to choose subprocesses * different than the one currently integrated. */ const Selector& projectors() const { return theProjectors; } /** * Return a pointer to a projector xcomb which will generate a subprocess * different from the one just integrated. */ tStdXCombPtr lastProjector() const { return theProjector; } /** * Set a pointer to a projector xcomb which will generate a subprocess * different from the one just integrated. */ void lastProjector(tStdXCombPtr pxc) { theProjector = pxc; } //@} /** @name Main functions used for the generation. */ //@{ /** * Try to determine if this subprocess is at all possible. */ virtual bool checkInit(); /** * The number of dimensions of the phase space used to generate this * process. */ virtual int nDim() const { return theNDim; } /** * Return the parton extraction dimensions */ const pair& partonDimensions() const { return partonDims; } /** * Return true, if the current configuration will pass the cuts */ bool willPassCuts(); /** * Return the cut weight encountered from fuzzy cuts */ double cutWeight() const { return theCutWeight; } /** * Reset all saved data about last generated phasespace point; */ virtual void clean(); /** * Return true, if kinematics have already been generated */ bool kinematicsGenerated() const { return theKinematicsGenerated; } /** * Indicate that kinematics have been generated */ void didGenerateKinematics() { theKinematicsGenerated = true; } /** * Generate a phase space point from a vector \a r of \a nr numbers * in the interval ]0,1[ and return the corresponding differential * cross section. */ virtual CrossSection dSigDR(const pair ll, int nr, const double * r); /** * If this XComb has a head XComb, return the cross section * differential in the variables previously supplied. The PDF weight * is taken from the lastPDFWeight supplied by the head XComb * object. */ CrossSection dSigDR(const double * r); /** * If variations are available for the subprocess handled, generate * and return a map of optional weights to be included for the * event; this version defaults to an implementation in MEBase but * can be overloaded by inheriting XComb objects. */ virtual map generateOptionalWeights(); /** * Return the PDF weight used in the last call to dSigDR */ double lastPDFWeight() const { return theLastPDFWeight; } /** * Return the cross section calculated in the last call to dSigDR */ CrossSection lastCrossSection() const { return theLastCrossSection; } /** * Check if a reshuffling is required when constructing the hard * subprocess. */ void checkReshufflingNeeds(); /** * Return true if a reshuffling is required when constructing the hard * subprocess. */ bool needsReshuffling() const { return theNeedsReshuffling; } /** * Perform the reshuffling from hardProcessMass to mass values, * given outgoing momenta */ void reshuffle(vector&) const; /** * Construct a sub-process object from the information available. */ virtual tSubProPtr construct(); //@} /** @name Functions used for collecting statistics. */ //@{ /** * The statistics object for this XComb. */ virtual const XSecStat & stats() const { return theStats; } /** * Select the current event. It will later be rejected with a * probability given by \a weight. */ virtual void select(double weight) { theStats.select(weight); } /** * Accept the current event assuming it was previously selcted. */ virtual void accept() { theStats.accept(); } /** * Reweight a selected and accepted event. */ void reweight(double oldWeight, double newWeight) { theStats.reweight(oldWeight,newWeight); } /** * Reject the current event assuming it was previously accepted. If * weighted events are produced, the \a weight should be the same as * the previous call to select(double). */ virtual void reject(double weight = 1.0) { theStats.reject(weight); } /** * Reset statistics. */ virtual void reset() { theStats.reset(); } //@} /** @name Access information used by the MEBase object. */ //@{ /** * The diagrams used by the matrix element. */ const DiagramVector & diagrams() const { return theDiagrams; } /** * True if the TreeDiagram's for this matrix element should in fact * be mirrored before used to create an actual sub-rocess. */ bool mirror() const { return isMirror; } /** * Return the momenta of the partons to be used by the matrix * element object, in the order specified by the TreeDiagram objects * given by the matrix element. */ const vector & meMomenta() const { return theMEMomenta; } /** * Return the last selected diagram. */ tcDiagPtr lastDiagram() const { if ( !theExternalDiagram ) return diagrams()[lastDiagramIndex()]; return theExternalDiagram; } /** * Return the parton types to be used by the matrix element object, * in the order specified by the TreeDiagram objects given by the * matrix element. */ const cPDVector & mePartonData() const { return theMEPartonData; } /** * Return the index of the last selected diagram. */ DiagramIndex lastDiagramIndex() const { return theLastDiagramIndex; } /** * Get information saved by the matrix element in the calculation of * the cross section to be used later when selecting diagrams and * colour flow. */ const DVector & meInfo() const { return theMEInfo; } /** * Set information saved by the matrix element in the calculation of * the cross section to be used later when selecting diagrams and * colour flow. */ void meInfo(const DVector & info) { theMEInfo = info; } /** * Return the random numbers used to generate the * last phase space point, if the matrix element * requested so. */ const DVector& lastRandomNumbers() const { return theLastRandomNumbers; } /** * Get the last jacobian obtained when generating the kinematics * for the call to dSigHatDR. */ double jacobian() const { return theLastJacobian; } /** * Return the matrix element squared as calculated * for the last phase space point. This may optionally * be used by a matrix element for caching. */ double lastME2() const { return theLastME2; } /** * Return the last preweight factor */ double lastPreweight() const { return theLastPreweight; } /** * Return the partonic cross section as calculated * for the last phase space point. This may optionally * be used by a matrix element for caching. */ CrossSection lastMECrossSection() const { return theLastMECrossSection; } /** * Return the PDF weight as calculated * for the last phase space point, if the matrix * element does supply PDF weights. This may optionally * be used by a matrix element for caching. */ double lastMEPDFWeight() const { return theLastMEPDFWeight; } /** * Return the coupling factor as calculated for the lats phase space * point. */ double lastMECouplings() const { return theLastMECouplings; } //@} /** * Construct the corresponding SubProcess object if it hasn't been * done before. */ virtual void newSubProcess(bool group = false); /** * Return the momenta of the partons to be used by the matrix * element object, in the order specified by the TreeDiagram objects * given by the matrix element. */ vector & meMomenta() { return theMEMomenta; } /** * Access the random numbers used to generate the * last phase space point, if the matrix element * requested so. */ DVector& lastRandomNumbers() { return theLastRandomNumbers; } /** * Return the parton types to be used by the matrix element object, * in the order specified by the TreeDiagram objects given by the * matrix element. */ cPDVector & mePartonData() { return theMEPartonData; } /** * Set a diagram to be used instead of the one selected by the matrix * element. */ void externalDiagram(tcDiagPtr diag) { theExternalDiagram = diag; } /** * Set the last selected diagram. */ void lastDiagramIndex(DiagramIndex i) { theLastDiagramIndex = i; } /** * Set the PDF weight used in the last call to dSigDR */ void lastPDFWeight(double w) { theLastPDFWeight = w; } /** * Set the cross section calculated in the last call to dSigDR */ void lastCrossSection(CrossSection s) { theLastCrossSection = s; } /** * Set the last jacobian obtained when generating the kinematics for * the call to dSigHatDR. */ void jacobian(double j) { theLastJacobian = j; } /** * Set the matrix element squared as calculated * for the last phase space point. This may optionally * be used by a matrix element for caching. */ void lastME2(double v) { theLastME2 = v; } /** * Set the last preweight factor */ void lastPreweight(double w) { theLastPreweight = w; } /** * Set the partonic cross section as calculated * for the last phase space point. This may optionally * be used by a matrix element for caching. */ void lastMECrossSection(CrossSection v) { theLastMECrossSection = v; } /** * Set the PDF weight as calculated * for the last phase space point, if the matrix * element does supply PDF weights. This may optionally * be used by a matrix element for caching. */ void lastMEPDFWeight(double v) { theLastMEPDFWeight = v; } /** * Set the coupling factor */ void lastMECouplings(double v) { theLastMECouplings = v; } public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interface. */ static void Init(); private: /** * The corresponding sub-process handler */ tSubHdlPtr theSubProcessHandler; /** * The matrix element to be used. */ tMEPtr theME; /** * Statistics gathering for this XComb. */ XSecStat theStats; /** * The diagrams used by the matrix element. */ DiagramVector theDiagrams; /** * True if the TreeDiagram's for this matrix element should in fact * be mirrored before used to create an actual sub-rocess. */ bool isMirror; /** * The number of dimensions of the phase space used to generate this * process. */ int theNDim; protected: /** * The number of dimensions of the phase space used for each of the * incoming partons. */ pair partonDims; private: /** * True, if kinematics have already been generated */ bool theKinematicsGenerated; /** * The momenta of the partons to be used by the matrix element * object, in the order specified by the TreeDiagram objects given * by the matrix element. */ vector theMEMomenta; /** * The parton types to be used by the matrix element object, in the * order specified by the TreeDiagram objects given by the matrix * element. */ cPDVector theMEPartonData; /** * A diagram to be used instead of the one selected by the matrix element. */ tcDiagPtr theExternalDiagram; /** * The last selected tree diagram. */ DiagramIndex theLastDiagramIndex; /** * Information saved by the matrix element in the calculation of the * cross section to be used later when selecting diagrams and colour * flow. */ DVector theMEInfo; /** * The random numbers used to generate the * last phase space point, if the matrix element * requested so. */ DVector theLastRandomNumbers; /** * The PDF weight used in the last call to dSigDR */ double theLastPDFWeight; /** * The cross section calculated in the last call to dSigDR */ CrossSection theLastCrossSection; /** * Save the last jacobian obtained when generating the kinematics for * the call to dSigHatDR. */ double theLastJacobian; /** * The matrix element squared as calculated * for the last phase space point. This may optionally * be used by a matrix element for caching. */ double theLastME2; /** * The last preweight factor */ double theLastPreweight; /** * The partonic cross section as calculated * for the last phase space point. This may optionally * be used by a matrix element for caching. */ CrossSection theLastMECrossSection; /** * The PDF weight as calculated * for the last phase space point, if the matrix * element does supply PDF weights. This may optionally * be used by a matrix element for caching. */ double theLastMEPDFWeight; /** * The coupling factor */ double theLastMECouplings; /** * A pointer to the head XComb this XComb * depends on. May return NULL, if this is not a * member of a XComb group. */ tStdXCombPtr theHead; /** * A selector object of xcombs to choose subprocesses * different than the one currently integrated. */ Selector theProjectors; /** * A pointer to a projector xcomb which will generate a subprocess * different from the one just integrated. */ tStdXCombPtr theProjector; /** * True, if cuts have already been checked */ bool checkedCuts; /** * The result of the last call to willPassCuts */ bool passedCuts; /** * The cut weight encountered from fuzzy cuts */ double theCutWeight; /** * True if a reshuffling is required when constructing the hard * subprocess. */ bool theNeedsReshuffling; /** * Calculate the reshuffling equation given the coefficients */ double reshuffleEquation(double, const vector >&, Energy2) const; /** * Solve the reshuffling equation given the coefficients */ double solveReshuffleEquation(const vector >&, Energy2) const; private: /** * Describe a concrete class with persistent data. */ static ClassDescription initStandardXComb; /** * Private and non-existent assignment operator. */ StandardXComb & operator=(const StandardXComb &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** * This template specialization informs ThePEG about the base class of * StandardXComb. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the base class of StandardXComb. */ typedef XComb NthBase; }; /** * This template specialization informs ThePEG about the name of the * StandardXComb class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return the class name. */ static string className() { return "ThePEG::StandardXComb"; } }; /** @endcond */ } #endif /* ThePEG_StandardXComb_H */ diff --git a/Handlers/StdXCombGroup.cc b/Handlers/StdXCombGroup.cc --- a/Handlers/StdXCombGroup.cc +++ b/Handlers/StdXCombGroup.cc @@ -1,390 +1,390 @@ // -*- C++ -*- // // StdXCombGroup.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad -// Copyright (C) 2009-2017 Simon Platzer +// Copyright (C) 1999-2019 Leif Lonnblad +// Copyright (C) 2009-2019 Simon Platzer // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the StdXCombGroup class. // #include "StdXCombGroup.h" #include "ThePEG/MatrixElement/MEGroup.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" using namespace ThePEG; StdXCombGroup::StdXCombGroup(Energy newMaxEnergy, const cPDPair & inc, tEHPtr newEventHandler,tSubHdlPtr newSubProcessHandler, tPExtrPtr newExtractor, tCascHdlPtr newCKKW, const PBPair & newPartonBins, tCutsPtr newCuts, tMEGroupPtr newME, const DiagramVector & newDiagrams, bool mir, tStdXCombPtr newHead) : StandardXComb(newMaxEnergy,inc,newEventHandler,newSubProcessHandler, newExtractor, newCKKW, newPartonBins, newCuts, newME, newDiagrams, mir, newHead), theMEGroup(newME), theDependent(), theLastHeadCrossSection(ZERO) {} StdXCombGroup::StdXCombGroup() : StandardXComb(), theDependent() {} void StdXCombGroup::build(const PartonPairVec& allPBins) { for ( MEVector::const_iterator me = theMEGroup->dependent().begin(); me != theMEGroup->dependent().end(); ++me ) { vector dep = theMEGroup->makeDependentXCombs(this,diagrams().front()->partons(),*me,allPBins); copy(dep.begin(),dep.end(),back_inserter(theDependent)); } } StdXCombGroup::~StdXCombGroup() { } void StdXCombGroup::clean() { StandardXComb::clean(); theLastHeadCrossSection = ZERO; for ( vector::const_iterator dep = theDependent.begin(); dep != theDependent.end(); ++dep ) (**dep).clean(); } int StdXCombGroup::nDim() const { if ( meGroup()->willProject() ) return StandardXComb::nDim() + 1; return StandardXComb::nDim(); } CrossSection StdXCombGroup::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); double rProject = 0.0; size_t shift = 0; if ( meGroup()->willProject() ) { rProject = r[partonDims.first]; shift = 1; } 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 + shift) ) { 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 + shift; 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; } 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(); bool noHeadPass = !willPassCuts() || xsec == ZERO; if ( noHeadPass ) { xsec = ZERO; lastCrossSection(ZERO); } xsec *= cutWeight(); lastAlphaS(matrixElement()->alphaS()); lastAlphaEM(matrixElement()->alphaEM()); lastHeadCrossSection(xsec); CrossSection depxsec = ZERO; vector activeXCombs; for ( vector::const_iterator dep = theDependent.begin(); dep != theDependent.end(); ++dep ) { if ( noHeadPass && (**dep).matrixElement()->headCuts() ) continue; depxsec += (**dep).dSigDR(r + theMEGroup->dependentOffset((**dep).matrixElement())); if ( theMEGroup->groupReweighted() ) activeXCombs.push_back(*dep); } if ( xsec != ZERO && depxsec != ZERO ) { if ( abs(xsec) < abs(depxsec) ) { volatile double rw = (1.+depxsec/xsec); xsec = xsec*rw; } else { volatile double rw = (1.+xsec/depxsec); xsec = depxsec*rw; } } else if ( xsec == ZERO && depxsec != ZERO ) { xsec = depxsec; } lastCrossSection(xsec); if ( xsec != ZERO ) theMEGroup->lastEventStatistics(); matrixElement()->fillProjectors(); if ( !projectors().empty() ) { lastProjector(projectors().select(rProject)); } if ( theMEGroup->groupReweighted() && !activeXCombs.empty() ) { xsec = theMEGroup->reweightHead(activeXCombs)*lastHeadCrossSection(); depxsec = ZERO; for ( vector::const_iterator dep = activeXCombs.begin(); dep != activeXCombs.end(); ++dep ) { depxsec += theMEGroup->reweightDependent(*dep,activeXCombs)*(**dep).lastCrossSection(); } if ( xsec != ZERO ) { double rw = 1.0 + depxsec/xsec; xsec *= rw; } else { xsec = depxsec; } } subProcess(SubProPtr()); if ( CKKWHandler() && matrixElement()->maxMultCKKW() > 0 && matrixElement()->maxMultCKKW() > matrixElement()->minMultCKKW() ) { newSubProcess(theMEGroup->subProcessGroups()); CKKWHandler()->setXComb(this); xsec *= CKKWHandler()->reweightCKKW(matrixElement()->minMultCKKW(), matrixElement()->maxMultCKKW()); } if ( matrixElement()->reweighted() ) { newSubProcess(theMEGroup->subProcessGroups()); xsec *= matrixElement()->reWeight() * matrixElement()->preWeight(); } return xsec; } void StdXCombGroup::newSubProcess(bool) { StandardXComb::newSubProcess(theMEGroup->subProcessGroups()); if ( !theMEGroup->subProcessGroups() ) return; subProcess()->groupWeight(lastHeadCrossSection()/lastCrossSection()); Ptr::tptr group = dynamic_ptr_cast::tptr>(subProcess()); assert(group); for ( vector::iterator dep = theDependent.begin(); dep != theDependent.end(); ++dep ) { if ( (**dep).lastCrossSection() == ZERO ) continue; tSubProPtr ds; try { ds = (**dep).construct(); } catch(Veto&) { throw Exception() << "A veto was encountered while constructing a dependent sub process.\n" << "This situation should not have happened. Will veto the event." << Exception::eventerror; } if ( ds ) group->add(ds); } } tSubProPtr StdXCombGroup::construct() { matrixElement()->setXComb(this); setPartonBinInfo(); matrixElement()->setKinematics(); newSubProcess(theMEGroup->subProcessGroups()); return subProcess(); } void StdXCombGroup::Init() {} void StdXCombGroup::persistentOutput(PersistentOStream & os) const { os << theDependent << theMEGroup << ounit(theLastHeadCrossSection,nanobarn); } void StdXCombGroup::persistentInput(PersistentIStream & is, int) { is >> theDependent >> theMEGroup >> iunit(theLastHeadCrossSection,nanobarn); } ClassDescription StdXCombGroup::initStdXCombGroup; diff --git a/Handlers/StdXCombGroup.h b/Handlers/StdXCombGroup.h --- a/Handlers/StdXCombGroup.h +++ b/Handlers/StdXCombGroup.h @@ -1,193 +1,193 @@ // -*- C++ -*- // // StdXCombGroup.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad -// Copyright (C) 2009-2017 Simon Platzer +// Copyright (C) 1999-2019 Leif Lonnblad +// Copyright (C) 2009-2019 Simon Platzer // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_StdXCombGroup_H #define ThePEG_StdXCombGroup_H // This is the declaration of the StdXCombGroup class. #include "StandardXComb.h" #include "StdXCombGroup.fh" #include "ThePEG/MatrixElement/MEGroup.fh" namespace ThePEG { /** * The StdXCombGroup class represents a 'head' XComb object * in association with a group of dependent XComb objects. * * @see MEGroup */ class StdXCombGroup: public StandardXComb { /** MEBase needs to be a friend. */ friend class MEBase; public: /** @name Standard constructors and destructors. */ //@{ /** * Standard constructor. */ StdXCombGroup(Energy newMaxEnergy, const cPDPair & inc, tEHPtr newEventHandler,tSubHdlPtr newSubProcessHandler, tPExtrPtr newExtractor, tCascHdlPtr newCKKW, const PBPair & newPartonBins, tCutsPtr newCuts, tMEGroupPtr newME, const DiagramVector & newDiagrams, bool mir, tStdXCombPtr newHead = tStdXCombPtr()); /** * Default constructor. */ StdXCombGroup(); /** * Destructor. */ virtual ~StdXCombGroup(); public: /** * Reset all saved data about last generated phasespace point; */ virtual void clean(); /** * The number of dimensions of the phase space used to generate this * process. */ virtual int nDim() const; /** * Generate a phase space point from a vector \a r of \a nr numbers * in the interval ]0,1[ and return the corresponding differential * cross section. */ virtual CrossSection dSigDR(const pair ll, int nr, const double * r); /** * Return the cross section calculated from the head matrix element */ CrossSection lastHeadCrossSection() const { return theLastHeadCrossSection; } /** * Visit the dependent XComb objects */ const vector& dependent() const { return theDependent; } /** * Return the matrix element group steered by this * XComb group. */ tcMEGroupPtr meGroup() const { return theMEGroup; } /** * Initialize this XComb group */ void build(const PartonPairVec& allPBins); /** * Construct a sub-process object from the information available. */ virtual tSubProPtr construct(); /** * Construct the corresponding SubProcess object if it hasn't been * done before. */ virtual void newSubProcess(bool); /** * Set the cross section calculated from the head matrix element */ void lastHeadCrossSection(CrossSection xs) { theLastHeadCrossSection = xs; } public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interface. */ static void Init(); private: /** * The MEGroup object */ MEGroupPtr theMEGroup; /** * The dependent XComb objects */ vector theDependent; /** * The cross section calculated from the head matrix element */ CrossSection theLastHeadCrossSection; private: /** * Describe a concrete class with persistent data. */ static ClassDescription initStdXCombGroup; /** * Private and non-existent assignment operator. */ StdXCombGroup & operator=(const StdXCombGroup &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** * This template specialization informs ThePEG about the base class of * StdXCombGroup. */ template <> struct BaseClassTrait { /** Typedef of the base class of StdXCombGroup. */ typedef StandardXComb NthBase; }; /** * This template specialization informs ThePEG about the name of the * StdXCombGroup class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return the class name. */ static string className() { return "ThePEG::StdXCombGroup"; } }; /** @endcond */ } #endif /* ThePEG_StdXCombGroup_H */ diff --git a/Handlers/StepHandler.cc b/Handlers/StepHandler.cc --- a/Handlers/StepHandler.cc +++ b/Handlers/StepHandler.cc @@ -1,41 +1,41 @@ // -*- C++ -*- // // StepHandler.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the StepHandler class. // #include "StepHandler.h" #include "ThePEG/Handlers/EventHandler.h" #include "ThePEG/Interface/ClassDocumentation.h" using namespace ThePEG; StepHandler::~StepHandler() {} void StepHandler::eventHandler(tEHPtr eh) { theEventHandler = eh; theNewStep = tStepPtr(); theCurrentStep = eh->currentStep(); } void StepHandler::createNewStep() { useMe(); theNewStep = eventHandler()->newStep(this); } AbstractNoPIOClassDescription StepHandler::initStepHandler; void StepHandler::Init() { static ClassDocumentation documentation ("There is no documentation for the ThePEG::StepHandler class"); } diff --git a/Handlers/StepHandler.h b/Handlers/StepHandler.h --- a/Handlers/StepHandler.h +++ b/Handlers/StepHandler.h @@ -1,181 +1,181 @@ // -*- C++ -*- // // StepHandler.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_StepHandler_H #define ThePEG_StepHandler_H // This is the declaration of the StepHandler class. #include "ThePEG/Config/ThePEG.h" #include "ThePEG/Utilities/Exception.fh" #include "ThePEG/Handlers/HandlerBase.h" #include namespace ThePEG { /** * StepHandler is the base class for implementing any model for a step * in the event generation chain. It has one main virtual method, * handle(), which should be overridden by sub classes. The handle * method is given a reference to a EventHandler, a vector * of particles and a Hint as arguments. The handler is only allowed * to treat particles which are in the vector. The Hint may be cast * dynamically to a sub class and do whatever it wishes with the * information found there. The EventHandler can be used to * add other StepHandlers and Hints to modify the * subsequent generation. If the StepHandler actually performs some * action, the resulting particles should be added to a new Step which * should be aquired with the newStep() function. * * @see \ref StepHandlerInterfaces "The interfaces" * defined for StepHandler. * @see EventHandler * @see Hint * @see Step * */ class StepHandler: public HandlerBase { public: /** @name Standard constructors and destructors. */ //@{ /** * The destructor. */ virtual ~StepHandler(); //@} public: /** @name Virtual functions to be implemented by concrete sub-classes. */ //@{ /** * The main function called by the EventHandler class to * perform a step. * @param eh the EventHandler in charge of the Event generation. * @param tagged if not empty these are the only particles which should * be considered by the StepHandler. * @param hint a Hint object with possible information from previously * performed steps. * @throws Veto if the StepHandler requires the current step to be * discarded. * @throws Stop if the generation of the current Event should be stopped * after this call. * @throws Exception if something goes wrong. */ virtual void handle(EventHandler & eh, const tPVector & tagged, const Hint & hint) = 0; //@} /** @name Access to the calling EventHandler and current Step. */ //@{ /** * Get a pointer to the EventHandler which made the last call to * handle(). */ tEHPtr eventHandler() const { return theEventHandler; } /** * Set a pointer to the EventHandler which made the last call to * handle(). */ void eventHandler(tEHPtr); /** * Return a pointer to a new step. If one has alredy been created in * the last call to handle(), that step will be returned. */ tStepPtr newStep() { if ( !theNewStep ) createNewStep(); return theNewStep; } /** * If a new step has been created, return it, otherwise return the * current step from the eventHandler(). */ tStepPtr currentStep() { if ( theNewStep ) return theNewStep; return theCurrentStep; } //@} public: /** * Standard Init function used to initialize the interface. */ static void Init(); protected: /** * Use the collision handler to create a new step. */ void createNewStep(); private: /** * A pointer to the (partial) collision handler which made the current * call to handle(). */ tEHPtr theEventHandler; /** * A pointer to a new step if created in the last call to handle(). */ tStepPtr theNewStep; /** * A pointer to the current step. Is equal to theNewStep if one was * created in the current call to handle(). */ tStepPtr theCurrentStep; private: /** * Describe an abstract class without persistent data. */ static AbstractNoPIOClassDescription initStepHandler; /** * Private and non-existent assignment operator. */ StepHandler & operator=(const StepHandler &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** * This template specialization informs ThePEG about the base class of * StepHandler. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the base class of StepHandler. */ typedef HandlerBase NthBase; }; /** * This template specialization informs ThePEG about the name of the * StepHandler class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return the class name. */ static string className() { return "ThePEG::StepHandler"; } }; /** @endcond */ } #endif /* ThePEG_StepHandler_H */ diff --git a/Handlers/SubProcessHandler.cc b/Handlers/SubProcessHandler.cc --- a/Handlers/SubProcessHandler.cc +++ b/Handlers/SubProcessHandler.cc @@ -1,186 +1,186 @@ // -*- C++ -*- // // SubProcessHandler.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the SubProcessHandler class. // #include "SubProcessHandler.h" #include "ThePEG/PDF/PartonExtractor.h" #include "ThePEG/Handlers/Hint.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Handlers/CascadeHandler.h" #include "ThePEG/Handlers/MultipleInteractionHandler.h" #include "ThePEG/Handlers/HadronizationHandler.h" #include "ThePEG/Handlers/DecayHandler.h" #include "ThePEG/Cuts/Cuts.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/MatrixElement/MEBase.h" #include "ThePEG/MatrixElement/ReweightBase.h" using namespace ThePEG; SubProcessHandler::~SubProcessHandler() {} SubProcessHandler::SubProcessHandler() { setupGroups(); } SubProcessHandler::SubProcessHandler(const SubProcessHandler & sph) : HandlerBase(sph), thePartonExtractor(sph.thePartonExtractor), theMEs(sph.theMEs), theCuts(sph.theCuts), theSubprocessGroup(sph.theSubprocessGroup), theCascadeGroup(sph.theCascadeGroup), theMultiGroup(sph.theMultiGroup), theHadronizationGroup(sph.theHadronizationGroup), theDecayGroup(sph.theDecayGroup), reweights(sph.reweights), preweights(sph.preweights) { setupGroups(); } void SubProcessHandler::setupGroups() { theGroups.clear(); theGroups.push_back(&theSubprocessGroup); theGroups.push_back(&theCascadeGroup); theGroups.push_back(&theMultiGroup); theGroups.push_back(&theHadronizationGroup); theGroups.push_back(&theDecayGroup); } IBPtr SubProcessHandler::clone() const { return new_ptr(*this); } IBPtr SubProcessHandler::fullclone() const { return new_ptr(*this); } const HandlerGroupBase & SubProcessHandler::handlerGroup(Group::Handler group) const { return *(theGroups[group]); } tCascHdlPtr SubProcessHandler::CKKWHandler() const { return dynamic_ptr_cast(theCascadeGroup.defaultHandler()); } void SubProcessHandler::persistentOutput(PersistentOStream & os) const { os << thePartonExtractor << theCuts << theSubprocessGroup << theCascadeGroup << theMultiGroup << theHadronizationGroup << theDecayGroup << theMEs << reweights << preweights; } void SubProcessHandler::persistentInput(PersistentIStream & is, int) { is >> thePartonExtractor >> theCuts >> theSubprocessGroup >> theCascadeGroup >> theMultiGroup >> theHadronizationGroup >> theDecayGroup >> theMEs >> reweights >> preweights; } void SubProcessHandler::doinit() { for ( MEVector::iterator me = theMEs.begin(); me != theMEs.end(); ++me ) { (**me).init(); for ( ReweightVector::iterator i = reweights.begin(); i != reweights.end(); ++i ) (**me).addReweighter(*i); for ( ReweightVector::iterator i = preweights.begin(); i != preweights.end(); ++i ) (**me).addPreweighter(*i); } HandlerBase::doinit(); } void SubProcessHandler::doinitrun() { HandlerBase::doinitrun(); pExtractor()->initrun(); for ( MEVector::iterator me = theMEs.begin(); me != theMEs.end(); ++me ) (**me).initrun(); for ( ReweightVector::iterator i = reweights.begin(); i != reweights.end(); ++i ) (**i).initrun(); for ( ReweightVector::iterator i = preweights.begin(); i != preweights.end(); ++i ) (**i).initrun(); } ClassDescription SubProcessHandler::initSubProcessHandler; void SubProcessHandler::Init() { static ClassDocumentation documentation ("This object contains information about a set of possible sub-processes " "to be generated from inside ThePEG. It must contain a " "PartonExtractor do describe how the partons " "entering into the hard sub-process are extracted from the beam " "particles. It must also include at least one matrix element object " "in MatrixElements and a " "Cuts object describing the kinematical cuts " "imposed on the sub-process generation."); static Reference interfacePartonExtractor ("PartonExtractor", "The PartonExtractor object to describe the way partons are extracted " "from the incoming particles.", &SubProcessHandler::thePartonExtractor, false, false, true, false); static RefVector interfaceMEs ("MatrixElements", "A list of MEBase objects describing the \\f$2\\rightarrow n\\f$ hard " "matrix elements.", &SubProcessHandler::theMEs, 0, false, false, true, false); static Reference interfaceCuts ("Cuts", "Common kinematical cuts for this SubProcessHandler. These cuts " "overides those in a EventHandler.", &SubProcessHandler::theCuts, false, false, true, true); static RefVector interfaceReweights ("Reweights", "A list of ThePEG::ReweightBase objects to modify all matrix elements " "in this SubProcessHandler.", &SubProcessHandler::reweights, 0, false, false, true, false); static RefVector interfacePreweights ("Preweights", "A list of ThePEG::ReweightBase objects to bias the phase space for all " "matrix elements without in this SubProcessHandler influencing the " "actual cross section.", &SubProcessHandler::preweights, 0, false, false, true, false); ThePEG_DECLARE_PREPOST_OBJECTS(SubProcessHandler, SubProcessHandler, Post, after); ThePEG_DECLARE_GROUPINTERFACE_OBJECTS(SubProcessHandler, CascadeHandler); ThePEG_DECLARE_GROUPINTERFACE_OBJECTS(SubProcessHandler, MultipleInteractionHandler); ThePEG_DECLARE_GROUPINTERFACE_OBJECTS(SubProcessHandler, HadronizationHandler); ThePEG_DECLARE_GROUPINTERFACE_OBJECTS(SubProcessHandler, DecayHandler); interfacePartonExtractor.rank(10); interfaceMEs.rank(9); interfaceCuts.rank(8); } ThePEG_IMPLEMENT_PREPOST_GROUP(SubProcessHandler,SubProcessHandler, theSubprocessGroup,Post)\ ThePEG_IMPLEMENT_GROUPINTERFACE(SubProcessHandler,CascadeHandler, theCascadeGroup,CascHdlPtr) \ ThePEG_IMPLEMENT_GROUPINTERFACE(SubProcessHandler,MultipleInteractionHandler, theMultiGroup,MIHdlPtr) \ ThePEG_IMPLEMENT_GROUPINTERFACE(SubProcessHandler,HadronizationHandler, theHadronizationGroup,HadrHdlPtr) \ ThePEG_IMPLEMENT_GROUPINTERFACE(SubProcessHandler,DecayHandler, theDecayGroup,DecayHdlPtr) \ diff --git a/Handlers/SubProcessHandler.h b/Handlers/SubProcessHandler.h --- a/Handlers/SubProcessHandler.h +++ b/Handlers/SubProcessHandler.h @@ -1,287 +1,287 @@ // -*- C++ -*- // // SubProcessHandler.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_SubProcessHandler_H #define ThePEG_SubProcessHandler_H // This is the declaration of the SubProcessHandler class. #include "ThePEG/Config/ThePEG.h" #include "ThePEG/Utilities/Interval.h" #include "ThePEG/Handlers/HandlerGroup.h" #include "ThePEG/Handlers/HandlerBase.h" #include "ThePEG/MatrixElement/MEBase.fh" #include "ThePEG/Cuts/Cuts.fh" #include "SubProcessHandler.fh" namespace ThePEG { /** * The SubProcessHandler class is used to handle a set of MEBase * objects together with a PartonExtractor. It is used by the * StandardEventHandler to group together different ways of extracting * partons from incoming particles with associated hard parton-parton * matrix elements. * * Just as the EventHandler class, a SubProcessHandler keeps a full * set of HandlerGroups, which may be filled with * defaults which overrides the ones specified in the EventHandler in * each event the SubProcessHandler is chosen. * * The SubProcessHandler has also a Cuts object which is * responsible for restricting the kinematics of the sub-process and * produced collision. This object takes precedence over the one in * the EventHandler in each event the SubProcessHandler is chosen. * * @see \ref SubProcessHandlerInterfaces "The interfaces" * defined for SubProcessHandler. * @see MEBase * @see PartonExtractor * @see EventHandler * @see StandardEventHandler * @see HandlerGroup * @see Cuts */ class SubProcessHandler: public HandlerBase { public: /** A vector of HandlerGroup pointers. */ typedef vector GroupVector; /** A vector of ReweightBase pointers. */ typedef vector ReweightVector; public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ SubProcessHandler(); /** * Copy-constructor. */ SubProcessHandler(const SubProcessHandler &); /** * Default destructor. */ virtual ~SubProcessHandler(); //@} public: /** @name Access objects assigned to the SubProcessHandler. */ //@{ /** * Return a pointer to the parton extractor used. */ tPExtrPtr pExtractor() const { return thePartonExtractor; } /** * Return a reference to the vector of parton matrix elements used. */ const MEVector & MEs() const { return theMEs; } /** * Return a pointer to the kinematical cuts used. */ tCutsPtr cuts() const { return theCuts; } /** * Return a pointer (possibly null) to the assigned main * CascadeHandler to be used as CKKW-reweighter. */ tCascHdlPtr CKKWHandler() const; /** * Access a step handler group. */ const HandlerGroupBase & handlerGroup(Group::Handler) const; /** * Access the step handler groups. */ const GroupVector & groups() const { return theGroups; } /** * Return a reference to the vector of parton matrix elements used. */ MEVector & MEs() { return theMEs; } //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interface. */ static void Init(); 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; //@} /** @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(); //@} private: /** * Setup the step handler groups. */ void setupGroups(); private: /** * The pointer to the parton extractor used. */ PExtrPtr thePartonExtractor; /** * The vector of partonic matrix elements to be used. */ MEVector theMEs; /** * The pointer to the kinematical cuts used. */ CutsPtr theCuts; /** * The SubProcessHandler group. */ HandlerGroup theSubprocessGroup; /** * The CascadeHandler group. */ HandlerGroup theCascadeGroup; /** * The MultipleInteractionHandler group. */ HandlerGroup theMultiGroup; /** * The HadronizationHandler group. */ HandlerGroup theHadronizationGroup; /** * The DecayHandler group. */ HandlerGroup theDecayGroup; /** * The step handler groups. */ GroupVector theGroups; /** * The pre- and re-weight objects modifying all matrix element in * this sub-process hander. */ ReweightVector reweights; /** * The pre- and re-weight objects modifying all matrix element in * this sub-process hander. */ ReweightVector preweights; private: ThePEG_DECLARE_PREPOST_GROUP(SubProcessHandler,Post); ThePEG_DECLARE_GROUPINTERFACE(CascadeHandler,CascHdlPtr); ThePEG_DECLARE_GROUPINTERFACE(MultipleInteractionHandler,MIHdlPtr); ThePEG_DECLARE_GROUPINTERFACE(HadronizationHandler,HadrHdlPtr); ThePEG_DECLARE_GROUPINTERFACE(DecayHandler,DecayHdlPtr); /** * Describe a concreta class with persistent data. */ static ClassDescription initSubProcessHandler; private: /** * Private and non-existent assignment operator. */ const SubProcessHandler & operator=(const SubProcessHandler &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of SubProcessHandler. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of SubProcessHandler. */ typedef HandlerBase NthBase; }; /** This template specialization informs ThePEG about the name of * the SubProcessHandler 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::SubProcessHandler"; } }; /** @endcond */ } #endif /* ThePEG_SubProcessHandler_H */ diff --git a/Handlers/XComb.cc b/Handlers/XComb.cc --- a/Handlers/XComb.cc +++ b/Handlers/XComb.cc @@ -1,174 +1,174 @@ // -*- C++ -*- // // XComb.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the XComb class. // #include "XComb.h" #include "ThePEG/Handlers/EventHandler.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/SubProcess.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" using namespace ThePEG; XComb::XComb() : theLastS(Energy2()), theLastSHat(Energy2()), theLastY(0.0), theLastP1P2(make_pair(1.0, 1.0)), theLastL1L2(make_pair(1.0, 1.0)), theLastX1X2(make_pair(1.0, 1.0)), theLastE1E2(make_pair(0.0, 0.0)), theLastScale(ZERO), theLastCentralScale(ZERO), theLastShowerScale(ZERO), theLastAlphaS(-1.0), theLastAlphaEM(-1.0), theMaxEnergy(ZERO) {} XComb:: XComb(Energy newMaxEnergy, const cPDPair & inc, tEHPtr newEventHandler, tPExtrPtr newExtractor, tCascHdlPtr newCKKW, const PBPair & newPartonBins, tCutsPtr newCuts) : theEventHandler(newEventHandler), thePartonExtractor(newExtractor), theCKKW(newCKKW), theCuts(newCuts), theParticles(inc), thePartonBins(newPartonBins), theLastS(Energy2()), theLastSHat(Energy2()), theLastY(0.0), theLastP1P2(make_pair(1.0, 1.0)), theLastL1L2(make_pair(1.0, 1.0)), theLastX1X2(make_pair(1.0, 1.0)), theLastE1E2(make_pair(0.0, 0.0)), theLastScale(ZERO), theLastCentralScale(ZERO), theLastShowerScale(ZERO), theLastAlphaS(-1.0), theLastAlphaEM(-1.0), theMaxEnergy(newMaxEnergy) { thePartons = cPDPair(partonBins().first->parton(), partonBins().second->parton()); thePartonBinInstances.first = new_ptr(PartonBinInstance(partonBins().first)); thePartonBinInstances.second = new_ptr(PartonBinInstance(partonBins().second)); theParticleBins.first = thePartonBins.first->getFirst(); theParticleBins.second = thePartonBins.second->getFirst(); } XComb::~XComb() {} void XComb::clean() { theLastParticles = PPair(); theLastPartons = PPair(); theLastS = theLastSHat = theLastScale = theLastCentralScale = theLastShowerScale = ZERO; theLastAlphaS = theLastAlphaEM = -1.0; theLastY = 0.0; theLastP1P2 = theLastL1L2 = theLastX1X2 = theLastE1E2 = DPair(0.0, 0.0); theSub = SubProPtr(); thePartonBinInstances = PBIPair(); thePartonBinInstanceMap.clear(); } void XComb::prepare(const PPair & inc) { clean(); createPartonBinInstances(); theLastParticles = inc; pExtractor()->select(this); pExtractor()->prepare(partonBinInstances()); } void XComb::subProcess(tSubProPtr sp) { theSub = sp; } void XComb::setPartonBinInfo() { partonBinInstances().first->getFirst()->parton(lastParticles().first); partonBinInstances().second->getFirst()->parton(lastParticles().second); } void XComb::createPartonBinInstances() { thePartonBinInstances.first = new_ptr(PartonBinInstance(partonBins().first)); thePartonBinInstances.second = new_ptr(PartonBinInstance(partonBins().second)); } void XComb::setPartonBinInstances(PBIPair pbip, Energy2 scale) { clean(); thePartonBinInstances = pbip; theLastParticles = PPair(pbip.first->getFirst()->parton(), pbip.second->getFirst()->parton()); theLastPartons = PPair(pbip.first->parton(), pbip.second->parton()); lastS((lastParticles().first->momentum() + lastParticles().second->momentum()).m2()); lastSHat((lastPartons().first->momentum() + lastPartons().second->momentum()).m2()); lastP1P2(make_pair(0.0, 0.0)); 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); lastScale(scale); } void XComb::lastL1L2(pair ll) { theLastL1L2 = ll; theLastX1X2 = make_pair(exp(-ll.first), exp(-ll.second)); theLastE1E2 = make_pair(Math::exp1m(-ll.first), Math::exp1m(-ll.second)); } void XComb::lastX1X2(pair xx) { theLastX1X2 = xx; theLastL1L2 = make_pair(-log(xx.first), -log(xx.second)); theLastE1E2 = make_pair(1.0 - xx.first, 1.0 - xx.second); } void XComb::lastE1E2(pair ee) { theLastE1E2= ee; theLastL1L2 = make_pair(-Math::log1m(ee.first), -Math::log1m(ee.second)); theLastX1X2 = make_pair(1.0 - ee.first, 1.0 - ee.second); } tPBIPtr XComb::partonBinInstance(tcPPtr p) const { return pExtractor()->partonBinInstance(p); } void XComb::Init() {} void XComb::persistentOutput(PersistentOStream & os) const { os << theEventHandler << thePartonExtractor << theCKKW << theCuts << theParticles << thePartons << thePartonBins << theParticleBins << thePartonBinInstances << theLastParticles << theLastPartons << ounit(theLastS, GeV2) << ounit(theLastSHat, GeV2) << theLastY << theLastP1P2 << theLastL1L2 << theLastX1X2 << theLastE1E2 << ounit(theLastScale, GeV2) << ounit(theLastCentralScale, GeV2) << ounit(theLastShowerScale, GeV2) << theLastAlphaS << theLastAlphaEM << ounit(theMaxEnergy, GeV) << theMEInfo << theSub; } void XComb::persistentInput(PersistentIStream & is, int) { is >> theEventHandler >> thePartonExtractor >> theCKKW >> theCuts >> theParticles >> thePartons >> thePartonBins >> theParticleBins >> thePartonBinInstances >> theLastParticles >> theLastPartons >> iunit(theLastS, GeV2) >> iunit(theLastSHat, GeV2) >> theLastY >> theLastP1P2 >> theLastL1L2 >> theLastX1X2 >> theLastE1E2 >> iunit(theLastScale, GeV2) >> iunit(theLastCentralScale, GeV2) >> iunit(theLastShowerScale, GeV2) >> theLastAlphaS >> theLastAlphaEM >> iunit(theMaxEnergy, GeV) >> theMEInfo >> theSub; } ClassDescription XComb::initXComb; diff --git a/Handlers/XComb.h b/Handlers/XComb.h --- a/Handlers/XComb.h +++ b/Handlers/XComb.h @@ -1,640 +1,640 @@ // -*- C++ -*- // // XComb.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_XComb_H #define ThePEG_XComb_H // This is the declaration of the XComb class. #include "ThePEG/Config/ThePEG.h" #include "ThePEG/PDF/PartonExtractor.fh" #include "ThePEG/PDF/PartonBin.h" #include "ThePEG/PDF/PartonBinInstance.h" #include "ThePEG/Utilities/AnyReference.h" #include "ThePEG/Utilities/VSelector.h" #include "ThePEG/Utilities/ClassDescription.h" #include "ThePEG/Utilities/Maths.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Handlers/EventHandler.fh" #include "ThePEG/Cuts/Cuts.fh" namespace ThePEG { /** * The XComb class stores all information about the generation of a * hard sub-proces for a given pair of incoming particles, a pair of * extracted partons, total parton-parton energy squared and a * PartonExtractor object. * * When an event is generated, the objects used in the generation can * be assigned an XComb object for easy acces to the corresponding * information. To facilitate this, the corresponding classes inherits * from the LastXCombInfo class which provides the relefant access * functions. * * @see PartonExtractor * @see Cuts * @see LastXCombInfo */ class XComb: public Base { public: /** @name Standard constructors and destructors. */ //@{ /** * Standard constructor. */ XComb(Energy newMaxEnergy, const cPDPair & inc, tEHPtr newEventHandler, tPExtrPtr newExtractor, tCascHdlPtr newCKKW, const PBPair & newPartonBins, tCutsPtr newCuts); /** * Default constructor. */ XComb(); /** * Destructor. */ virtual ~XComb(); //@} /** @name Access the assigned objects used in the generation. */ //@{ /** * Return a reference to the corresponding collision handler */ const EventHandler & eventHandler() const { return *theEventHandler; } /** * Return a pointer to the corresponding collision handler */ tEHPtr eventHandlerPtr() const { return theEventHandler; } /** * A pointer to the parton extractor. */ tPExtrPtr pExtractor() const { return thePartonExtractor; } /** * A pointer to the kinematical cuts. */ tCutsPtr cuts() const { return theCuts; } /** * Return a possibly null pointer to a CascadeHandler to be used for * CKKW-reweighting. */ tCascHdlPtr CKKWHandler() const { return theCKKW; } //@} /** @name Access information about incoming particles and partons. */ //@{ /** * The incoming particle types. */ const cPDPair & particles() const { return theParticles; } /** * The incoming parton types. */ const cPDPair & partons() const { return thePartons; } /** * Additional information about the incoming partons. */ const PBPair & partonBins() const { return thePartonBins; } /** * The maximum cm energy for this process. */ Energy maxEnergy() const { return theMaxEnergy; } /** * Returns true if this XComb does not correspond to a proper * subprocess generation. I.e. if we are only generating a partial * event and the incoming particles and partons are not used * explicitly. */ bool empty() const { return !theEventHandler; } //@} /** @name Manipulate and acces information about the last selected phase space point. */ //@{ /** * Reset all saved data about last generated phasespace point; */ virtual void clean(); /** * Set information about currently generated partons. */ void setPartonBinInstances(PBIPair pbis, Energy2 scale); /** * Prepare this XComb for producing a sub-process. */ void prepare(const PPair &); /** * Return the pair of incoming particle instances. */ const PPair & lastParticles() const { return theLastParticles; } /** * Return the pair of incoming parton instances. */ const PPair & lastPartons() const { return theLastPartons; } /** * Set the pair of incoming parton instances. */ void lastPartons(PPair pp) { theLastPartons = pp; } /** * Return the SubProcess object corresponding to the last generated * sub-process. */ tSubProPtr subProcess() const { return theSub; } /** * Set the SubProcess object corresponding to the last generated * sub-process. */ void subProcess(tSubProPtr); /** A map of PartonBinInstance objects indexed by the extracted parton. */ typedef map PartonBinInstanceMap; /** * Access the parton bin instance map (used by the parton extractor) */ PartonBinInstanceMap& partonBinInstanceMap() { return thePartonBinInstanceMap; } /** * Return the parton bin instance map (used by the parton extractor) */ const PartonBinInstanceMap& partonBinInstanceMap() const { return thePartonBinInstanceMap; } /** * Additional information about the incoming partons. */ const PBIPair & partonBinInstances() const { return thePartonBinInstances; } /** * Additional information about the incoming partons. */ PBIPair & partonBinInstances() { return thePartonBinInstances; } /** * Return the corresponding parton bin instance for a given * extracted parton. */ tPBIPtr partonBinInstance(tcPPtr) const; /** * The last generated total energy squared of the incoming particles. */ Energy2 lastS() const { return theLastS; } /** * Set the last generated total energy squared of the incoming * particles. */ void lastS(Energy2 s) { theLastS = s; } /** * The last generated total energy squared of the incoming prtons. */ Energy2 lastSHat() const { return theLastSHat; } /** * Set the last generated total energy squared of the incoming * prtons. */ void lastSHat(Energy2 sh) { theLastSHat = sh; } /** * lastSHat()/lastS(). */ double lastTau() const { return lastSHat()/lastS(); } /** * The last generated rapidity of the hard scattering sub-system. */ double lastY() const { return theLastY; } /** * Set the last generated rapidity of the hard scattering sub-system. */ void lastY(double y) { theLastY = y; } /** * Log of one over the momentum fraction of the first incoming * particle w.r.t. the maximum allowed energy. */ double lastP1() const { return theLastP1P2.first; } /** * Log of one over the momentum fraction of the second incoming * particle w.r.t. the maximum allowed energy. */ double lastP2() const { return theLastP1P2.second; } /** * Set log of one over the momentum fraction of the incoming * particles w.r.t. the maximum allowed energy. */ void lastP1P2(pair pp) { theLastP1P2 = pp; } /** * Log of one over the first incoming parton momentum fraction * w.r.t. the first incoming particle. */ double lastL1() const { return theLastL1L2.first; } /** * Log of one over the second incoming parton momentum fraction * w.r.t. the second incoming particle. */ double lastL2() const { return theLastL1L2.second; } /** * Set log of one over the incoming parton momentum fractions * w.r.t. the incoming particles. */ void lastL1L2(pair); /** * The first incoming parton momentum fraction w.r.t. the * first incoming particle. */ double lastX1() const { return theLastX1X2.first; } /** * The second incoming parton momentum fraction * w.r.t. the second incoming particle. */ double lastX2() const { return theLastX1X2.second; } /** * Set the incoming parton momentum fractions w.r.t. the incoming * particles. */ void lastX1X2(pair); /** * Return 1-lastX1() to highest possible precision for * x\f$\rightarrow\f$ 1. */ double lastE1() const { return theLastE1E2.first; } /** * Return 1-lastX2() to highest possible precision for * x\f$\rightarrow\f$ 1. */ double lastE2() const { return theLastE1E2.second; } /** * Set one minus the incoming parton momentum fractions w.r.t. the * incoming particles. */ void lastE1E2(pair); /** * Get the last chosen scale of the hard scattering. */ Energy2 lastScale() const { return theLastScale; } /** * Set the last chosen scale of the hard scattering. */ void lastScale(Energy2 Q2) { theLastScale = Q2; } /** * Get the last chosen central scale of the hard scattering. */ Energy2 lastCentralScale() const { return theLastCentralScale != ZERO ? theLastCentralScale : lastScale(); } /** * Set the last chosen central scale of the hard scattering. */ void lastCentralScale(Energy2 Q2) { theLastCentralScale = Q2; } /** * Get the last chosen shower scale. */ Energy2 lastShowerScale() const { return theLastShowerScale != ZERO ? theLastShowerScale : lastCentralScale(); } /** * Set the last chosen showr scale. */ void lastShowerScale(Energy2 Q2) { theLastShowerScale = Q2; } /** * Get the \f$\alpha_S\f$ used in the hard scattering. Is negative * if no value has been set. */ double lastAlphaS() const { return theLastAlphaS; } /** * Set the \f$\alpha_S\f$ used in the hard scattering. */ void lastAlphaS(double a) { theLastAlphaS = a; } /** * Get the \f$\alpha_{EM}\f$ used in the hard scattering. Is negative * if no value has been set. */ double lastAlphaEM() const { return theLastAlphaEM; } /** * Set the \f$\alpha_{EM}\f$ used in the hard scattering. */ void lastAlphaEM(double a) { theLastAlphaEM = a; } //@} public: /** * Check for meta information */ bool hasMeta(int id) const { return theMeta.find(id) != theMeta.end(); } /** * Set meta information. */ template void meta(int id, T& ref) { theMeta[id] = AnyReference(ref); } /** * Erase meta information. */ void eraseMeta(int id) { theMeta.erase(id); } /** * Retrieve meta information. */ template T& meta(int id) const { return theMeta.find(id)->second.cast(); } /** * Set the local parton bin info objects for this XComb. */ void setPartonBinInfo(); /** * Create PartonBinInstance objects for this XComb. */ void createPartonBinInstances(); /** * Set the pair of incoming particle instances. */ void lastParticles(const PPair & p) { theLastParticles = p; } /** * Set information about currently generated partons. */ void resetPartonBinInstances(const PBIPair & newBins) { thePartonBinInstances = newBins; } public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interface. */ static void Init(); private: /** * The corresponding collision handler */ tEHPtr theEventHandler; /** * A pointer to the parton extractor. */ tPExtrPtr thePartonExtractor; /** * A pointer to a CascadeHandler to be used for CKKW-reweighting. */ tCascHdlPtr theCKKW; /** * A pointer to the kinematical cuts used. */ tCutsPtr theCuts; /** * The incoming particle types. */ cPDPair theParticles; /** * The incoming parton types. */ cPDPair thePartons; /** * The parton bin instance map (used by the parton extractor) */ PartonBinInstanceMap thePartonBinInstanceMap; /** * Additional information about the incoming partons. */ PBPair thePartonBins; /** * Additional information about the origins of the incoming partons. */ PBPair theParticleBins; /** * Additional information about the incoming partons. */ PBIPair thePartonBinInstances; /** * The pair of incoming particle instances. */ PPair theLastParticles; /** * The pair of incoming parton instances. */ PPair theLastPartons; /** * The last generated total energy squared of the incoming particles. */ Energy2 theLastS; /** * The last generated total energy squared of the incoming prtons. */ Energy2 theLastSHat; /** * The last rapidity of the sub process, log(x1/x2)/2. */ double theLastY; /** * Log of one over the momentum fraction of the incoming particles. */ DPair theLastP1P2; /** * Log of one over the incoming partons momentum fraction wrt. the * incoming particles. */ DPair theLastL1L2; /** * The incoming partons momentum fraction wrt. the incoming * particles. */ DPair theLastX1X2; /** * 1-lastX1() and 1-lastX2() to highest possible precision for * x\f$\rightarrow\f$ 1. */ DPair theLastE1E2; /** * The last chosen scale of the hard scattering. */ Energy2 theLastScale; /** * The last chosen central scale of the hard scattering. */ Energy2 theLastCentralScale; /** * The last chosen shower scale. */ Energy2 theLastShowerScale; /** * The \f$\alpha_S\f$ used in the hard scattering. */ double theLastAlphaS; /** * The \f$\alpha_{EM}\f$ used in the hard scattering. */ double theLastAlphaEM; /** * The maximum cm energy for this process. */ Energy theMaxEnergy; /** * Information saved by the matrix element in the calculation of the * cross section to be used later when selecting diagrams and colour * flow. */ DVector theMEInfo; /** * The SubProcess object corresponding to the last generated * sub-process. */ SubProPtr theSub; /** * The meta information */ map theMeta; private: /** * Describe a concrete class with persistent data. */ static ClassDescription initXComb; /** * Private and non-existent assignment operator. */ XComb & operator=(const XComb &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** * This template specialization informs ThePEG about the base class of * XComb. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the base class of XComb. */ typedef Base NthBase; }; /** * This template specialization informs ThePEG about the name of the * XComb class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return the class name. */ static string className() { return "ThePEG::XComb"; } }; /** @endcond */ } #endif /* ThePEG_XComb_H */ diff --git a/Handlers/ZGenerator.cc b/Handlers/ZGenerator.cc --- a/Handlers/ZGenerator.cc +++ b/Handlers/ZGenerator.cc @@ -1,33 +1,33 @@ // -*- C++ -*- // // ZGenerator.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // //$Id$ // ---------------------------------------------------- // // This is the implementation of the non-inlined, non-templated member // functions of the ZGenerator class. // #include "ZGenerator.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Interface/ClassDocumentation.h" using namespace ThePEG; AbstractClassDescription ZGenerator::initZGenerator; void ZGenerator::Init(){ static ClassDocumentation documentation ("The base class for all classes implementing models to generate the " "momentum fraction, \\f$z\\f$, taken by hadrons produced in a " "hadronization scenario."); } diff --git a/Handlers/ZGenerator.h b/Handlers/ZGenerator.h --- a/Handlers/ZGenerator.h +++ b/Handlers/ZGenerator.h @@ -1,91 +1,91 @@ // -*- C++ -*- // // ZGenerator.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_ZGenerator_H #define ThePEG_ZGenerator_H // This is the declaration of the ZGenerator class. #include "ThePEG/Config/ThePEG.h" #include "ThePEG/Handlers/HandlerBase.h" namespace ThePEG { /** * ZGenerator is the base class for all classes implementing models to * generate the momentum fraction, \f$z\f$, taken by hadrons produced in a * hadronization scenario. * * It inherits from HandlerBase class which among other * things provides forward access to the random number generator of * the EventGenerator class. * * @see \ref ZGeneratorInterfaces "The interfaces" * defined for ZGenerator. * @see HandlerBase * @see EventGenerator */ class ZGenerator: public HandlerBase { public: /** @name Virtual functions mandated by the ZGenerator base class. */ //@{ /** * Return the momentum fraction. Assume that an initial * (anti-)(di-)quark \a q1 produces a hadron and leaves behind * another (anti-)(di-)quark \a q2. The hadron is assumed to have a * squared transverse mass, \a mT2, w.r.t. the initial quark * direction. * @return the energy fraction. */ virtual double generate(cPDPtr q1, cPDPtr q2, Energy2 mT2 ) const =0; //@} /** * Standard Init function used to initialize the interface. */ static void Init(); private: /** * Describe an abstract class without persistent data. */ static AbstractClassDescription initZGenerator; }; /** @cond TRAITSPECIALIZATIONS */ /** * This template specialization informs ThePEG about the base class of * ZGenerator. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the base class of ZGenerator. */ typedef HandlerBase NthBase; }; /** * This template specialization informs ThePEG about the name of the * ZGenerator class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return the class name. */ static string className() { return "ThePEG::ZGenerator"; } }; /** @endcond */ } #endif /* ThePEG_ZGenerator_H */ diff --git a/Helicity/FermionSpinInfo.cc b/Helicity/FermionSpinInfo.cc --- a/Helicity/FermionSpinInfo.cc +++ b/Helicity/FermionSpinInfo.cc @@ -1,41 +1,41 @@ // -*- C++ -*- // // FermionSpinInfo.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the FermionSpinInfo class. // // Author: Peter Richardson // #include "FermionSpinInfo.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Repository/CurrentGenerator.h" using namespace ThePEG; using namespace ThePEG::Helicity; // The following static variable is needed for the type // description system in ThePEG. DescribeNoPIOClass describeThePEGFermionSpinInfo("ThePEG::FermionSpinInfo", "libThePEG.so"); void FermionSpinInfo::Init() {} void FermionSpinInfo::transform(const LorentzMomentum & m, const LorentzRotation & r) { if(isNear(m)) { for(unsigned int ix=0;ix<2;++ix) _currentstates[ix].transform(r); SpinInfo::transform(m,r); } } EIPtr FermionSpinInfo::clone() const { tcSpinPtr temp=this; return const_ptr_cast(temp); } diff --git a/Helicity/FermionSpinInfo.h b/Helicity/FermionSpinInfo.h --- a/Helicity/FermionSpinInfo.h +++ b/Helicity/FermionSpinInfo.h @@ -1,192 +1,192 @@ // -*- C++ -*- // // FermionSpinInfo.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_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), _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), _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 &); /** * Undecay */ virtual void undecay() const { _decaycalc=false; SpinInfo::undecay(); } /** * Reset */ virtual void reset() { undecay(); _currentstates = _productionstates; SpinInfo::reset(); } public: /** * Standard Init function. */ static void Init(); /** * Standard clone method. */ virtual EIPtr clone() const; private: /** * Private and non-existent assignment operator. */ FermionSpinInfo & operator=(const FermionSpinInfo &) = delete; private: /** * basis states in the frame in which the particle was produced */ mutable std::array,2> _productionstates; /** * basis states in the current frame of the particle */ mutable std::array,2> _currentstates; /** * basis states in the frame in which the particle decays */ mutable std::array,2> _decaystates; /** * True if the decay state has been set. */ mutable bool _decaycalc; }; } } namespace ThePEG { } #endif /* ThePEG_FermionSpinInfo_H */ diff --git a/Helicity/HelicityDefinitions.h b/Helicity/HelicityDefinitions.h --- a/Helicity/HelicityDefinitions.h +++ b/Helicity/HelicityDefinitions.h @@ -1,64 +1,64 @@ // -*- C++ -*- // // HelicityDefinitions.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_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 class SpinorType { u, /**< u spinor. */ v, /**< v spinor. */ unknown /**< Undefined spinor type. */ }; /** \ingroup Helicity * Definition of the enumerated values of the phase to include in the * calculation of the polarization vector. */ enum VectorPhase { vector_phase, /**< Include the phase factor.*/ vector_nophase, /**< No phase-factor. */ default_vector_phase=vector_nophase /**< Default option.*/ }; /** @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/HelicityFunctions.h b/Helicity/HelicityFunctions.h --- a/Helicity/HelicityFunctions.h +++ b/Helicity/HelicityFunctions.h @@ -1,285 +1,285 @@ // -*- C++ -*- // // HelicityFunctions.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_HelicityFunctions_H #define ThePEG_HelicityFunctions_H // // This is the declaration of the HelicityFunctions header for common functions // used in helicity calculations to avoid duplication of code #include "ThePEG/Vectors/LorentzVector.h" #include "LorentzSpinor.h" #include "LorentzSpinorBar.h" namespace ThePEG { namespace Helicity { namespace HelicityFunctions { inline LorentzPolarizationVector polarizationVector(const Lorentz5Momentum & p, unsigned int ihel, Direction dir, VectorPhase vphase=default_vector_phase) { // check the direction assert(dir!=intermediate); // special helicity combination for gauge invariance tests if(ihel==10) return p*UnitRemoval::InvE; // check a valid helicity combination assert(ihel==0 || ihel == 2 || ((ihel==1 || ihel==3) && p.mass()>ZERO )); // convert the helicitty from 0,1,2 to -1,0,1 int jhel=ihel-1; // extract the momentum components double fact = dir==outgoing ? -1 : 1; Energy ppx=fact*p.x(),ppy=fact*p.y(),ppz=fact*p.z(),pee=fact*p.e(),pmm=p.mass(); // calculate some kinematic quantites Energy2 pt2 = ppx*ppx+ppy*ppy; Energy pabs = sqrt(pt2+ppz*ppz); Energy pt = sqrt(pt2); // zero subtracted if(ihel==3) { InvEnergy pre = pmm/pabs/(pee+pabs); return LorentzPolarizationVector(double(pre*ppx),double(pre*ppy),double(pre*ppz),-double(pre*pabs)); } // overall phase of the vector Complex phase(1.); 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); } if(ihel!=1) phase = phase/sqrt(2.); // first the +/-1 helicity states if(ihel!=1) { // first the zero pt case if(pt==ZERO) { double sgnz = ppz(jhel)*phase, sgnz*phase*complex(0,-fact), 0.,0.); } else { InvEnergy opabs=1./pabs; InvEnergy opt =1./pt; return LorentzPolarizationVector(phase*complex(-jhel*ppz*ppx*opabs*opt, fact*ppy*opt), phase*complex(-jhel*ppz*ppy*opabs*opt,-fact*ppx*opt), double(jhel*pt*opabs)*phase,0.); } } // 0 component for massive vectors else { if(pabs==ZERO) { return LorentzPolarizationVector(0.,0.,1.,0.); } else { InvEnergy empabs=pee/pmm/pabs; return LorentzPolarizationVector(double(empabs*ppx),double(empabs*ppy), double(empabs*ppz),double(pabs/pmm)); } } } inline LorentzSpinor dimensionedSpinor(const Lorentz5Momentum & p, unsigned int ihel, Direction dir) { // check direction and helicity assert(dir!=intermediate); assert(ihel<=1); // extract the momentum components double fact = dir==incoming ? 1 : -1.; Energy ppx=fact*p.x(),ppy=fact*p.y(),ppz=fact*p.z(),pee=fact*p.e(),pmm=p.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] = Complex(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] = Complex(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; } } return LorentzSpinor(upper*hel_wf[0],upper*hel_wf[1], lower*hel_wf[0],lower*hel_wf[1], (dir==incoming) ? SpinorType::u : SpinorType::v); } inline LorentzSpinor spinor(const Lorentz5Momentum & p, unsigned int ihel, Direction dir) { LorentzSpinor temp = dimensionedSpinor(p,ihel,dir); return LorentzSpinor(temp.s1()*UnitRemoval::InvSqrtE, temp.s2()*UnitRemoval::InvSqrtE, temp.s3()*UnitRemoval::InvSqrtE, temp.s4()*UnitRemoval::InvSqrtE,temp.Type()); } inline LorentzSpinorBar dimensionedSpinorBar(const Lorentz5Momentum & p, unsigned int ihel, Direction dir) { // check direction and helicity assert(dir!=intermediate); assert(ihel<=1); // extract the momentum components double fact = dir==incoming ? 1. : -1.; Energy ppx=fact*p.x(),ppy=fact*p.y(),ppz=fact*p.z(),pee=fact*p.e(),pmm=p.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 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] = Complex(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] = Complex(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 return LorentzSpinorBar(upper*hel_wf[0], upper*hel_wf[1], lower*hel_wf[0], lower*hel_wf[1], (dir==incoming) ? SpinorType::v : SpinorType::u); } inline LorentzSpinorBar spinorBar(const Lorentz5Momentum & p, unsigned int ihel, Direction dir) { LorentzSpinorBar temp = dimensionedSpinorBar(p,ihel,dir); return LorentzSpinorBar(temp.s1()*UnitRemoval::InvSqrtE, temp.s2()*UnitRemoval::InvSqrtE, temp.s3()*UnitRemoval::InvSqrtE, temp.s4()*UnitRemoval::InvSqrtE,temp.Type()); } } } } #endif /* ThePEG_HelicityFunctions_H */ diff --git a/Helicity/LorentzPolarizationVector.h b/Helicity/LorentzPolarizationVector.h --- a/Helicity/LorentzPolarizationVector.h +++ b/Helicity/LorentzPolarizationVector.h @@ -1,25 +1,25 @@ // -*- C++ -*- // // LorentzPolarizationVector.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_LorentzPolarizationVector_H #define ThePEG_LorentzPolarizationVector_H // This is the declaration of the LorentzPolarizationVector class. #include "ThePEG/Config/Unitsystem.h" #include "ThePEG/Config/Complex.h" #include "ThePEG/Vectors/LorentzVector.h" namespace ThePEG { namespace Helicity { /// Convenience typedef. typedef LorentzVector > LorentzPolarizationVector; /// Convenience typedef. typedef LorentzVector > LorentzPolarizationVectorE; } } #endif diff --git a/Helicity/LorentzRSSpinor.cc b/Helicity/LorentzRSSpinor.cc --- a/Helicity/LorentzRSSpinor.cc +++ b/Helicity/LorentzRSSpinor.cc @@ -1,12 +1,12 @@ // -*- C++ -*- // // LorentzRSSpinor.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifdef ThePEG_TEMPLATES_IN_CC_FILE #include "LorentzRSSpinor.tcc" #include "ThePEG/Utilities/DescribeClass.h" #endif diff --git a/Helicity/LorentzRSSpinor.h b/Helicity/LorentzRSSpinor.h --- a/Helicity/LorentzRSSpinor.h +++ b/Helicity/LorentzRSSpinor.h @@ -1,571 +1,571 @@ // -*- C++ -*- // // LorentzRSSpinor.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_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 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 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 = 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=SpinorType::unknown) : _type(t), _spin{{ {{a1,b1,c1,d1}}, {{a2,b2,c2,d2}}, {{a3,b3,c3,d3}}, {{a4,b4,c4,d4}} }} {} template LorentzRSSpinor(const LorentzRSSpinor & other) : _type(other._type), _spin(other._spin) {} //@} /** @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 Mathematical assignment operators. //@{ template LorentzRSSpinor & operator+=(const LorentzRSSpinor & a) { for(unsigned int ix=0;ix<4;++ix) for(unsigned int iy=0;iy<4;++iy) _spin[ix][iy] += a._spin[ix][iy]; return *this; } template LorentzRSSpinor & operator-=(const LorentzRSSpinor & a) { for(unsigned int ix=0;ix<4;++ix) for(unsigned int iy=0;iy<4;++iy) _spin[ix][iy] -= a._spin[ix][iy]; return *this; } LorentzRSSpinor & operator*=(double a) { for(unsigned int ix=0;ix<4;++ix) for(unsigned int iy=0;iy<4;++iy) _spin[ix][iy] *=a; return *this; } LorentzRSSpinor & operator/=(double a) { for(unsigned int ix=0;ix<4;++ix) for(unsigned int iy=0;iy<4;++iy) _spin[ix][iy] /=a; return *this; } //@} /** @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 auto generalScalar(LorentzRSSpinorBar& fbar, Complex left, Complex right) -> decltype(left*fbar(3,0)*this->ts1()) { decltype(left*fbar(3,0)*ts1()) 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 auto generalCurrent(LorentzSpinorBar& fbar, Complex left, Complex right) -> LorentzVectorts1())> { typedef decltype(left*fbar.s1()*ts1()) 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. */ std::array,4>,4> _spin; }; /// @name Basic mathematical operations //@{ template inline LorentzRSSpinor operator/(const LorentzRSSpinor & v, Value a) { return LorentzRSSpinor(v.xs1()/a, v.xs2()/a, v.xs3()/a, v.xs4()/a, v.ys1()/a, v.ys2()/a, v.ys3()/a, v.ys4()/a, v.zs1()/a, v.zs2()/a, v.zs3()/a, v.zs4()/a, v.ts1()/a, v.ts2()/a, v.ts3()/a, v.ts4()/a, v.Type()); } inline LorentzRSSpinor operator/(const LorentzRSSpinor & v, Complex a) { return LorentzRSSpinor(v.xs1()/a, v.xs2()/a, v.xs3()/a, v.xs4()/a, v.ys1()/a, v.ys2()/a, v.ys3()/a, v.ys4()/a, v.zs1()/a, v.zs2()/a, v.zs3()/a, v.zs4()/a, v.ts1()/a, v.ts2()/a, v.ts3()/a, v.ts4()/a, v.Type()); } template inline LorentzRSSpinor operator-(const LorentzRSSpinor & v) { return LorentzRSSpinor(-v.xs1(),-v.xs2(),-v.xs3(),-v.xs4(), -v.ys1(),-v.ys2(),-v.ys3(),-v.ys4(), -v.zs1(),-v.zs2(),-v.zs3(),-v.zs4(), -v.ts1(),-v.ts2(),-v.ts3(),-v.ts4(), v.Type()); } template inline LorentzRSSpinor operator+(LorentzRSSpinor a, const LorentzRSSpinor & b) { return a += b; } template inline LorentzRSSpinor operator-(LorentzRSSpinor a, const LorentzRSSpinor & b) { return a -= b; } template inline LorentzRSSpinor operator*(const LorentzRSSpinor & a, double b) { return LorentzRSSpinor(a.xs1()*b, a.xs2()*b, a.xs3()*b, a.xs4()*b, a.ys1()*b, a.ys2()*b, a.ys3()*b, a.ys4()*b, a.zs1()*b, a.zs2()*b, a.zs3()*b, a.zs4()*b, a.ts1()*b, a.ts2()*b, a.ts3()*b, a.ts4()*b,a.Type()); } template inline LorentzRSSpinor operator*(double b, LorentzRSSpinor a) { return a *= b; } template inline LorentzRSSpinor operator*(const LorentzRSSpinor & a, Complex b) { return LorentzRSSpinor(a.xs1()*b, a.xs2()*b, a.xs3()*b, a.xs4()*b, a.ys1()*b, a.ys2()*b, a.ys3()*b, a.ys4()*b, a.zs1()*b, a.zs2()*b, a.zs3()*b, a.zs4()*b, a.ts1()*b, a.ts2()*b, a.ts3()*b, a.ts4()*b,a.Type()); } template inline auto operator*(complex a, const LorentzRSSpinor & v) -> LorentzRSSpinor { return {a*v.xs1(), a*v.xs2(), a*v.xs3(), a*v.xs4(), a*v.ys1(), a*v.ys2(), a*v.ys3(), a*v.ys4(), a*v.zs1(), a*v.zs2(), a*v.zs3(), a*v.zs4(), a*v.ts1(), a*v.ts2(), a*v.ts3(), a*v.ts4(),v.Type()}; } template inline auto operator*(const LorentzRSSpinor & v, complex b) -> LorentzRSSpinor { return b*v; } template inline auto operator/(const LorentzRSSpinor & v, complex b) -> LorentzRSSpinor { return {v.xs1()/b, v.xs2()/b, v.xs3()/b, v.xs4()/b, v.ys1()/b, v.ys2()/b, v.ys3()/b, v.ys4()/b, v.zs1()/b, v.zs2()/b, v.zs3()/b, v.zs4()/b, v.ts1()/b, v.ts2()/b, v.ts3()/b, v.ts4()/b,v.Type()}; } template inline auto operator*(ValueB a, const LorentzRSSpinor & v) -> LorentzRSSpinor { return {a*v.xs1(), a*v.xs2(), a*v.xs3(), a*v.xs4(), a*v.ys1(), a*v.ys2(), a*v.ys3(), a*v.ys4(), a*v.zs1(), a*v.zs2(), a*v.zs3(), a*v.zs4(), a*v.ts1(), a*v.ts2(), a*v.ts3(), a*v.ts4(),v.Type()}; } template inline auto operator*(const LorentzRSSpinor & v, ValueB b) -> LorentzRSSpinor { return b*v; } template inline auto operator/(const LorentzRSSpinor & v, ValueB b) -> LorentzRSSpinor { return {v.xs1()/b, v.xs2()/b, v.xs3()/b, v.xs4()/b, v.ys1()/b, v.ys2()/b, v.ys3()/b, v.ys4()/b, v.zs1()/b, v.zs2()/b, v.zs3()/b, v.zs4()/b, v.ts1()/b, v.ts2()/b, v.ts3()/b, v.ts4()/b,v.Type()}; } //@} } } #ifndef ThePEG_TEMPLATES_IN_CC_FILE #include "LorentzRSSpinor.tcc" #endif #endif diff --git a/Helicity/LorentzRSSpinor.tcc b/Helicity/LorentzRSSpinor.tcc --- a/Helicity/LorentzRSSpinor.tcc +++ b/Helicity/LorentzRSSpinor.tcc @@ -1,181 +1,181 @@ // -*- C++ -*- // // LorentzRSSpinor.tcc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the LorentzRSSpinor class. // // Author: Peter Richardson // #include "LorentzRSSpinor.h" #include "LorentzRSSpinorBar.h" using namespace ThePEG; using namespace ThePEG::Helicity; // return the barred spinor template LorentzRSSpinorBar LorentzRSSpinor::bar() const { complex out[4][4]; unsigned int ix; // HELAS for(ix=0;ix<4;++ix) { out[ix][0] = conj(_spin[ix][2]); out[ix][1] = conj(_spin[ix][3]); out[ix][2] = conj(_spin[ix][0]); out[ix][3] = conj(_spin[ix][1]); } return LorentzRSSpinorBar(out[0][0],out[0][1],out[0][2],out[0][3], out[1][0],out[1][1],out[1][2],out[1][3], out[2][0],out[2][1],out[2][2],out[2][3], out[3][0],out[3][1],out[3][2],out[3][3],_type); } // boost the spinor template LorentzRSSpinor & LorentzRSSpinor::boost(double bx,double by,double bz) { // work out beta and chi double b2(bx*bx+by*by+bz*bz),beta(sqrt(b2)),chi(atanh(beta)); double sinhchi(sinh(0.5*chi)/beta),coshchi(cosh(0.5*chi)); double gamma = 1.0/sqrt(1.0-b2); double gmmone = b2 >0 ? (gamma-1.)/b2 : 0.0; double bvec[3]={bx,by,bz}; unsigned int ix,iy,ixa,iya; // vector boost matrix double boostv[4][4]; for(ix=0;ix<3;++ix) { for(iy=0;iy<3;++iy){boostv[ix][iy]=bvec[ix]*bvec[iy]*gmmone;} boostv[ix][ix]+=1; boostv[ix][3]=gamma*bvec[ix]; boostv[3][ix]=boostv[ix][3]; } boostv[3][3]=gamma; // spinor boost matrix Complex boosts[4][4],ii(0.,1.),nxminy(bx-ii*by),nxpiny(bx+ii*by); boosts[0][0] = coshchi-sinhchi*bz; boosts[0][1] = -sinhchi*nxminy; boosts[0][2] = 0.; boosts[0][3] = 0.; boosts[1][0] = -sinhchi*nxpiny; boosts[1][1] = coshchi+sinhchi*bz; boosts[1][2] = 0.; boosts[1][3] = 0.; boosts[2][0] = 0.; boosts[2][1] = 0.; boosts[2][2] = coshchi+sinhchi*bz; boosts[2][3] = +sinhchi*nxminy; boosts[3][0] = 0.; boosts[3][1] = 0.; boosts[3][2] = +sinhchi*nxpiny; boosts[3][3] = coshchi-sinhchi*bz; Complex out[4][4]; // apply the boost for(ix=0;ix<4;++ix) { for(iy=0;iy<4;++iy) { out[ix][iy]=0.; for(ixa=0;ixa<4;++ixa) { for(iya=0;iya<4;++iya) {out[ix][iy]+=boostv[ix][ixa]*boosts[iy][iya]*_spin[ixa][iya];} } } } *this=LorentzRSSpinor(out[0][0],out[0][1],out[0][2],out[0][3], out[1][0],out[1][1],out[1][2],out[1][3], out[2][0],out[2][1],out[2][2],out[2][3], out[3][0],out[3][1],out[3][2],out[3][3],_type); return *this; } // boost the spinor template LorentzRSSpinor & LorentzRSSpinor::boost(const Boost & boostvec) { const double beta = boostvec.mag(),b2=beta*beta; const double bx=boostvec.x(),by=boostvec.y(),bz=boostvec.z(); const double boostvec1[3] = {bx, by, bz}; const double gamma = 1.0/sqrt(1.0-b2); const double gmmone = b2 >0 ? (gamma-1.)/b2 : 0.0; const double chi = atanh(beta); const double sinhchi = sinh(0.5*chi)/beta, coshchi = cosh(0.5*chi); complex out[4][4]; Complex ii(0.,1.); const Complex nxminy=bx-ii*by; const Complex nxpiny=bx+ii*by; unsigned int ix,iy,ixa,iya; // vector boost matrix double boostv[4][4]; for(ix=0;ix<3;++ix) { for(iy=0;iy<3;++iy){boostv[ix][iy]=boostvec1[ix]*boostvec1[iy]*gmmone;} boostv[ix][ix]+=1; boostv[ix][3]=gamma*boostvec1[ix]; boostv[3][ix]=boostv[ix][3]; } boostv[3][3]=gamma; // spinor boost matrix Complex boosts[4][4]; boosts[0][0] = coshchi-sinhchi*bz; boosts[0][1] = -sinhchi*nxminy; boosts[0][2] = 0.; boosts[0][3] = 0.; boosts[1][0] = -sinhchi*nxpiny; boosts[1][1] = coshchi+sinhchi*bz; boosts[1][2] = 0.; boosts[1][3] = 0.; boosts[2][0] = 0.; boosts[2][1] = 0.; boosts[2][2] = coshchi+sinhchi*bz; boosts[2][3] = +sinhchi*nxminy; boosts[3][0] = 0.; boosts[3][1] = 0.; boosts[3][2] = +sinhchi*nxpiny; boosts[3][3] = coshchi-sinhchi*bz; // apply the boost for(ix=0;ix<4;++ix) { for(iy=0;iy<4;++iy) { out[ix][iy]=complex(); for(ixa=0;ixa<4;++ixa) { for(iya=0;iya<4;++iya) {out[ix][iy]+=boostv[ix][ixa]*boosts[iy][iya]*_spin[ixa][iya];} } } } *this= LorentzRSSpinor(out[0][0],out[0][1],out[0][2],out[0][3], out[1][0],out[1][1],out[1][2],out[1][3], out[2][0],out[2][1],out[2][2],out[2][3], out[3][0],out[3][1],out[3][2],out[3][3],_type); return *this; } //general lorentz tranformation template LorentzRSSpinor & LorentzRSSpinor::transform(const LorentzRotation & r) { unsigned int ix,iy,ixa,iya; LorentzRSSpinor out; for(ix=0;ix<4;++ix) { for(iy=0;iy<4;++iy) { out(ix,iy)=complex(); for(ixa=0;ixa<4;++ixa) { for(iya=0;iya<4;++iya) {out(ix,iy)+=r.one()(ix,ixa)*r.half()(iy,iya)*_spin[ixa][iya];} } } } *this=out; return *this; } diff --git a/Helicity/LorentzRSSpinorBar.cc b/Helicity/LorentzRSSpinorBar.cc --- a/Helicity/LorentzRSSpinorBar.cc +++ b/Helicity/LorentzRSSpinorBar.cc @@ -1,12 +1,12 @@ // -*- C++ -*- // // LorentzRSSpinorBar.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifdef ThePEG_TEMPLATES_IN_CC_FILE #include "LorentzRSSpinorBar.tcc" #include "ThePEG/Utilities/DescribeClass.h" #endif diff --git a/Helicity/LorentzRSSpinorBar.h b/Helicity/LorentzRSSpinorBar.h --- a/Helicity/LorentzRSSpinorBar.h +++ b/Helicity/LorentzRSSpinorBar.h @@ -1,506 +1,506 @@ // -*- C++ -*- // // LorentzRSSpinorBar.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_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 = 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=SpinorType::unknown) : _type(t), _spin{{ {{a1,b1,c1,d1}}, {{a2,b2,c2,d2}}, {{a3,b3,c3,d3}}, {{a4,b4,c4,d4}} }} {} template LorentzRSSpinorBar(const LorentzRSSpinorBar & other) : _type(other._type), _spin(other._spin) {} //@} /** @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 Mathematical assignment operators. //@{ template LorentzRSSpinorBar & operator+=(const LorentzRSSpinorBar & a) { for(unsigned int ix=0;ix<4;++ix) for(unsigned int iy=0;iy<4;++iy) _spin[ix][iy] += a._spin[ix][iy]; return *this; } template LorentzRSSpinorBar & operator-=(const LorentzRSSpinorBar & a) { for(unsigned int ix=0;ix<4;++ix) for(unsigned int iy=0;iy<4;++iy) _spin[ix][iy] -= a._spin[ix][iy]; return *this; } LorentzRSSpinorBar & operator*=(double a) { for(unsigned int ix=0;ix<4;++ix) for(unsigned int iy=0;iy<4;++iy) _spin[ix][iy] *=a; return *this; } LorentzRSSpinorBar & operator/=(double a) { for(unsigned int ix=0;ix<4;++ix) for(unsigned int iy=0;iy<4;++iy) _spin[ix][iy] /=a; return *this; } //@} /** @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 auto generalCurrent(LorentzSpinor& f, Complex left, Complex right) -> LorentzVectorts1()*f.s1())> { typedef decltype(left*ts1()*f.s1()) 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. */ std::array,4>,4> _spin; }; /// @name Basic mathematical operations //@{ template inline LorentzRSSpinorBar operator/(const LorentzRSSpinorBar & v, Value a) { return LorentzRSSpinorBar(v.xs1()/a, v.xs2()/a, v.xs3()/a, v.xs4()/a, v.ys1()/a, v.ys2()/a, v.ys3()/a, v.ys4()/a, v.zs1()/a, v.zs2()/a, v.zs3()/a, v.zs4()/a, v.ts1()/a, v.ts2()/a, v.ts3()/a, v.ts4()/a, v.Type()); } inline LorentzRSSpinorBar operator/(const LorentzRSSpinorBar & v, Complex a) { return LorentzRSSpinorBar(v.xs1()/a, v.xs2()/a, v.xs3()/a, v.xs4()/a, v.ys1()/a, v.ys2()/a, v.ys3()/a, v.ys4()/a, v.zs1()/a, v.zs2()/a, v.zs3()/a, v.zs4()/a, v.ts1()/a, v.ts2()/a, v.ts3()/a, v.ts4()/a, v.Type()); } template inline LorentzRSSpinorBar operator-(const LorentzRSSpinorBar & v) { return LorentzRSSpinorBar(-v.xs1(),-v.xs2(),-v.xs3(),-v.xs4(), -v.ys1(),-v.ys2(),-v.ys3(),-v.ys4(), -v.zs1(),-v.zs2(),-v.zs3(),-v.zs4(), -v.ts1(),-v.ts2(),-v.ts3(),-v.ts4(), v.Type()); } template inline LorentzRSSpinorBar operator+(LorentzRSSpinorBar a, const LorentzRSSpinorBar & b) { return a += b; } template inline LorentzRSSpinorBar operator-(LorentzRSSpinorBar a, const LorentzRSSpinorBar & b) { return a -= b; } template inline LorentzRSSpinorBar operator*(const LorentzRSSpinorBar & a, double b) { return LorentzRSSpinorBar(a.xs1()*b, a.xs2()*b, a.xs3()*b, a.xs4()*b, a.ys1()*b, a.ys2()*b, a.ys3()*b, a.ys4()*b, a.zs1()*b, a.zs2()*b, a.zs3()*b, a.zs4()*b, a.ts1()*b, a.ts2()*b, a.ts3()*b, a.ts4()*b,a.Type()); } template inline LorentzRSSpinorBar operator*(double b, LorentzRSSpinorBar a) { return a *= b; } template inline LorentzRSSpinorBar operator*(const LorentzRSSpinorBar & a, Complex b) { return LorentzRSSpinorBar(a.xs1()*b, a.xs2()*b, a.xs3()*b, a.xs4()*b, a.ys1()*b, a.ys2()*b, a.ys3()*b, a.ys4()*b, a.zs1()*b, a.zs2()*b, a.zs3()*b, a.zs4()*b, a.ts1()*b, a.ts2()*b, a.ts3()*b, a.ts4()*b,a.Type()); } template inline auto operator*(complex a, const LorentzRSSpinorBar & v) -> LorentzRSSpinorBar { return {a*v.xs1(), a*v.xs2(), a*v.xs3(), a*v.xs4(), a*v.ys1(), a*v.ys2(), a*v.ys3(), a*v.ys4(), a*v.zs1(), a*v.zs2(), a*v.zs3(), a*v.zs4(), a*v.ts1(), a*v.ts2(), a*v.ts3(), a*v.ts4(),v.Type()}; } template inline auto operator*(const LorentzRSSpinorBar & v, complex b) -> LorentzRSSpinorBar { return b*v; } template inline auto operator/(const LorentzRSSpinorBar & v, complex b) -> LorentzRSSpinorBar { return {v.xs1()/b, v.xs2()/b, v.xs3()/b, v.xs4()/b, v.ys1()/b, v.ys2()/b, v.ys3()/b, v.ys4()/b, v.zs1()/b, v.zs2()/b, v.zs3()/b, v.zs4()/b, v.ts1()/b, v.ts2()/b, v.ts3()/b, v.ts4()/b,v.Type()}; } template inline auto operator*(ValueB a, const LorentzRSSpinorBar & v) -> LorentzRSSpinorBar { return {a*v.xs1(), a*v.xs2(), a*v.xs3(), a*v.xs4(), a*v.ys1(), a*v.ys2(), a*v.ys3(), a*v.ys4(), a*v.zs1(), a*v.zs2(), a*v.zs3(), a*v.zs4(), a*v.ts1(), a*v.ts2(), a*v.ts3(), a*v.ts4(),v.Type()}; } template inline auto operator*(const LorentzRSSpinorBar & v, ValueB b) -> LorentzRSSpinorBar { return b*v; } template inline auto operator/(const LorentzRSSpinorBar & v, ValueB b) -> LorentzRSSpinorBar { return {v.xs1()/b, v.xs2()/b, v.xs3()/b, v.xs4()/b, v.ys1()/b, v.ys2()/b, v.ys3()/b, v.ys4()/b, v.zs1()/b, v.zs2()/b, v.zs3()/b, v.zs4()/b, v.ts1()/b, v.ts2()/b, v.ts3()/b, v.ts4()/b,v.Type()}; } //@} } } #ifndef ThePEG_TEMPLATES_IN_CC_FILE #include "LorentzRSSpinorBar.tcc" #endif #endif diff --git a/Helicity/LorentzRSSpinorBar.tcc b/Helicity/LorentzRSSpinorBar.tcc --- a/Helicity/LorentzRSSpinorBar.tcc +++ b/Helicity/LorentzRSSpinorBar.tcc @@ -1,167 +1,167 @@ // -*- C++ -*- // // LorentzRSSpinorBar.tcc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the LorentzRSSpinorBar class. // // Author: Peter Richardson // #include "LorentzRSSpinorBar.h" #include "LorentzRSSpinor.h" using namespace ThePEG; using namespace ThePEG::Helicity; // return the unbarred spinor template LorentzRSSpinor LorentzRSSpinorBar::bar() const { complex out[4][4]; unsigned int ix; // HELAS for(ix=0;ix<4;++ix) { out[ix][0] = conj(_spin[ix][2]); out[ix][1] = conj(_spin[ix][3]); out[ix][2] = conj(_spin[ix][0]); out[ix][3] = conj(_spin[ix][1]); } return LorentzRSSpinor(out[0][0],out[0][1],out[0][2],out[0][3], out[1][0],out[1][1],out[1][2],out[1][3], out[2][0],out[2][1],out[2][2],out[2][3], out[3][0],out[3][1],out[3][2],out[3][3],_type); } template LorentzRSSpinorBar & LorentzRSSpinorBar::boost(double bx,double by,double bz) { // work out beta and chi double b2(bx*bx+by*by+bz*bz),beta(sqrt(b2)),chi(atanh(beta)); double sinhchi(sinh(0.5*chi)/beta),coshchi(cosh(0.5*chi)); // calculate the new spinor Complex out[4][4],ii(0.,1.),boosts[4][4]; Complex nxminy(bx-ii*by),nxpiny(bx+ii*by); double gamma(1.0/sqrt(1.0-b2)),gmmone(b2 >0 ? (gamma-1.)/b2 : 0.0); double bvec[3]={bx,by,bz},boostv[4][4]; unsigned int ix,iy,ixa,iya; // spin matrix boosts[0][0] = coshchi+sinhchi*bz; boosts[0][1] = sinhchi*nxminy; boosts[0][2] = 0.; boosts[0][3] = 0.; boosts[1][0] = sinhchi*nxpiny; boosts[1][1] = coshchi-sinhchi*bz; boosts[1][2] = 0.; boosts[1][3] = 0.; boosts[2][0] = 0.; boosts[2][1] = 0.; boosts[2][2] = coshchi-sinhchi*bz; boosts[2][3] =-sinhchi*nxminy; boosts[3][0] = 0.; boosts[3][1] = 0.; boosts[3][2] =-sinhchi*nxpiny; boosts[3][3] = coshchi+sinhchi*bz; // vector matrix for(ix=0;ix<3;++ix) { for(iy=0;iy<3;++iy) boostv[ix][iy]=bvec[ix]*bvec[iy]*gmmone; boostv[ix][ix]+=1; boostv[ix][3]=gamma*bvec[ix]; boostv[3][ix]=boostv[ix][3]; } boostv[3][3]=gamma; // apply the boost for(ix=0;ix<4;++ix) { for(iy=0;iy<4;++iy) { out[ix][iy]=0.; for(ixa=0;ixa<4;++ixa) { for(iya=0;iya<4;++iya) { out[ix][iy] += boostv[ix][ixa]*boosts[iya][iy]*_spin[ixa][iya]; } } } } *this= LorentzRSSpinorBar(out[0][0],out[0][1],out[0][2],out[0][3], out[1][0],out[1][1],out[1][2],out[1][3], out[2][0],out[2][1],out[2][2],out[2][3], out[3][0],out[3][1],out[3][2],out[3][3],_type); return *this; } template LorentzRSSpinorBar & LorentzRSSpinorBar::boost(const Boost & boostvec) { double beta = boostvec.mag(),b2(beta*beta); double bx(boostvec.x()),by(boostvec.y()),bz(boostvec.z()); double boostvec1[3] = {bx, by, bz}; double chi(atanh(beta)),sinhchi(sinh(0.5*chi)/beta),coshchi(cosh(0.5*chi)); complex out[4][4]; Complex ii(0.,1.); Complex nxminy(bx-ii*by),nxpiny(bx+ii*by),boosts[4][4]; double gamma(1.0/sqrt(1.0-b2)),gmmone(b2 >0 ? (gamma-1.)/b2 : 0.0),boostv[4][4]; unsigned int ix,iy,ixa,iya; // spin matrix boosts[0][0] = coshchi+sinhchi*bz; boosts[0][1] = sinhchi*nxminy; boosts[0][2] = 0.; boosts[0][3] = 0.; boosts[1][0] = sinhchi*nxpiny; boosts[1][1] = coshchi-sinhchi*bz; boosts[1][2] = 0.; boosts[1][3] = 0.; boosts[2][0] = 0.; boosts[2][1] = 0.; boosts[2][2] = coshchi-sinhchi*bz; boosts[2][3] =-sinhchi*nxminy; boosts[3][0] = 0.; boosts[3][1] = 0.; boosts[3][2] =-sinhchi*nxpiny; boosts[3][3] = coshchi+sinhchi*bz; // vector matrix for(ix=0;ix<3;++ix) { for(iy=0;iy<3;++iy) boostv[ix][iy]=boostvec1[ix]*boostvec1[iy]*gmmone; boostv[ix][ix]+=1; boostv[ix][3]=gamma*boostvec1[ix]; boostv[3][ix]=boostv[ix][3]; } boostv[3][3]=gamma; // apply the boost for(ix=0;ix<4;++ix) { for(iy=0;iy<4;++iy) { out[ix][iy]=complex(); for(ixa=0;ixa<4;++ixa) { for(iya=0;iya<4;++iya) { out[ix][iy]+=boostv[ix][ixa]*boosts[iya][iy]*_spin[ixa][iya]; } } } } *this= LorentzRSSpinorBar(out[0][0],out[0][1],out[0][2],out[0][3], out[1][0],out[1][1],out[1][2],out[1][3], out[2][0],out[2][1],out[2][2],out[2][3], out[3][0],out[3][1],out[3][2],out[3][3],_type); return *this; } template LorentzRSSpinorBar & LorentzRSSpinorBar::transform(const LorentzRotation & r) { SpinHalfLorentzRotation t(r.half().inverse()); unsigned int ix,iy,ixa,iya; LorentzRSSpinorBar out; for(ix=0;ix<4;++ix) { for(iy=0;iy<4;++iy) { out(ix,iy)=0.; for(ixa=0;ixa<4;++ixa) { for(iya=0;iya<4;++iya) { out(ix,iy)+=r.one()(ix,ixa)*t(iya,iy)*_spin[ixa][iya]; } } } } *this=out; return *this; } diff --git a/Helicity/LorentzSpinor.cc b/Helicity/LorentzSpinor.cc --- a/Helicity/LorentzSpinor.cc +++ b/Helicity/LorentzSpinor.cc @@ -1,12 +1,12 @@ // -*- C++ -*- // // LorentzSpinor.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifdef ThePEG_TEMPLATES_IN_CC_FILE #include "LorentzSpinor.tcc" #include "ThePEG/Utilities/DescribeClass.h" #endif diff --git a/Helicity/LorentzSpinor.h b/Helicity/LorentzSpinor.h --- a/Helicity/LorentzSpinor.h +++ b/Helicity/LorentzSpinor.h @@ -1,626 +1,626 @@ // -*- C++ -*- // // LorentzSpinor.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_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 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 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 = 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 = SpinorType::unknown) : _type(s), _spin{{a,b,c,d}} {} //@} template LorentzSpinor(const LorentzSpinor & other) : _type(other._type), _spin(other._spin) {} /** @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 Mathematical assignment operators. //@{ template LorentzSpinor & operator+=(const LorentzSpinor & a) { for(unsigned int ix=0;ix<4;++ix) _spin[ix] += a._spin[ix]; return *this; } template LorentzSpinor & operator-=(const LorentzSpinor & a) { for(unsigned int ix=0;ix<4;++ix) _spin[ix] -= a._spin[ix]; return *this; } LorentzSpinor & operator*=(double a) { for(unsigned int ix=0;ix<4;++ix) _spin[ix] *=a; return *this; } LorentzSpinor & operator/=(double a) { for(unsigned int ix=0;ix<4;++ix) _spin[ix] /=a; return *this; } //@} /** @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 auto projectionOperator(const LorentzVector & p, const ValueB & m) const -> LorentzSpinor { 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 auto slash(const LorentzVector & p) const -> LorentzSpinor { 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 auto slash(const LorentzVector > & p) const -> LorentzSpinor { 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 auto leftCurrent(const LorentzSpinorBar& fb) const -> LorentzVectors2())> { typedef decltype(fb.s3()*s2()) 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 auto rightCurrent(const LorentzSpinorBar& fb) const -> LorentzVectors4())> { typedef decltype(fb.s1()*s4()) 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 auto vectorCurrent(const LorentzSpinorBar& fb) const -> LorentzVectors4())> { typedef decltype(fb.s1()*this->s4()) 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 auto generalCurrent(const LorentzSpinorBar& fb, Complex left, Complex right) const -> LorentzVectors2())> { typedef decltype(fb.s3()*this->s2()) 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 auto leftScalar(const LorentzSpinorBar& fb) const -> decltype(fb.s1()*this->s1()) { return fb.s1()*s1()+fb.s2()*s2(); } /** * Calculate the right-handed scalar \f$\bar{f}P_Rf\f$. * @param fb The barred spinor. */ template auto rightScalar(const LorentzSpinorBar& fb) const -> decltype(fb.s3()*this->s3()) { return fb.s3()*s3()+fb.s4()*s4(); } /** * Calculate the scalar \f$\bar{f}f\f$. * @param fb The barred spinor. */ template auto scalar(const LorentzSpinorBar& fb) const -> decltype(fb.s1()*this->s1()) { 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 auto pseudoScalar(const LorentzSpinorBar& fb) const -> decltype(fb.s1()*this->s1()) { 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 auto generalScalar(const LorentzSpinorBar& fb, Complex left, Complex right) const -> decltype(left*fb.s1()*this->s1()) { 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 auto sigma(const LorentzSpinorBar& fb) const -> LorentzTensors1())> { typedef decltype(fb.s1()*this->s1()) ResultT; LorentzTensor output; ResultT 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.); ResultT 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. */ std::array,4> _spin; }; /// @name Basic mathematical operations //@{ template inline LorentzSpinor operator/(const LorentzSpinor & v, Value a) { return LorentzSpinor(v.s1()/a, v.s2()/a, v.s3()/a, v.s4()/a,v.Type()); } inline LorentzSpinor operator/(const LorentzSpinor & v, Complex a) { return LorentzSpinor(v.s1()/a, v.s2()/a, v.s3()/a, v.s4()/a,v.Type()); } template inline LorentzSpinor operator-(const LorentzSpinor & v) { return LorentzSpinor(-v.s1(),-v.s2(),-v.s3(),-v.s4(),v.Type()); } template inline LorentzSpinor operator+(LorentzSpinor a, const LorentzSpinor & b) { return a += b; } template inline LorentzSpinor operator-(LorentzSpinor a, const LorentzSpinor & b) { return a -= b; } template inline LorentzSpinor operator*(const LorentzSpinor & a, double b) { return LorentzSpinor(a.s1()*b, a.s2()*b, a.s3()*b, a.s4()*b,a.Type()); } template inline LorentzSpinor operator*(double b, LorentzSpinor a) { return a *= b; } template inline LorentzSpinor operator*(const LorentzSpinor & a, Complex b) { return LorentzSpinor(a.s1()*b, a.s2()*b, a.s3()*b, a.s4()*b,a.Type()); } template inline auto operator*(complex a, const LorentzSpinor & v) -> LorentzSpinor { return {a*v.s1(), a*v.s2(), a*v.s3(), a*v.s4(),v.Type()}; } template inline auto operator*(const LorentzSpinor & v, complex b) -> LorentzSpinor { return b*v; } template inline auto operator/(const LorentzSpinor & v, complex b) -> LorentzSpinor { return {v.s1()/b, v.s2()/b, v.s3()/b, v.s4()/b,v.Type()}; } template inline auto operator*(ValueB a, const LorentzSpinor & v) -> LorentzSpinor { return {a*v.s1(), a*v.s2(), a*v.s3(), a*v.s4(),v.Type()}; } template inline auto operator*(const LorentzSpinor & v, ValueB b) -> LorentzSpinor { return b*v; } template inline auto operator/(const LorentzSpinor & v, ValueB b) -> LorentzSpinor { return {v.s1()/b, v.s2()/b, v.s3()/b, v.s4()/b,v.Type()}; } } } #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-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined member // functions of the 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 SpinorType::u: new_type=SpinorType::v; break; case SpinorType::v: new_type=SpinorType::u; break; case SpinorType::unknown: default: 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.cc b/Helicity/LorentzSpinorBar.cc --- a/Helicity/LorentzSpinorBar.cc +++ b/Helicity/LorentzSpinorBar.cc @@ -1,12 +1,12 @@ // -*- C++ -*- // // LorentzSpinorBar.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifdef ThePEG_TEMPLATES_IN_CC_FILE #include "LorentzSpinorBar.tcc" #include "ThePEG/Utilities/DescribeClass.h" #endif diff --git a/Helicity/LorentzSpinorBar.h b/Helicity/LorentzSpinorBar.h --- a/Helicity/LorentzSpinorBar.h +++ b/Helicity/LorentzSpinorBar.h @@ -1,355 +1,355 @@ // -*- C++ -*- // // LorentzSpinorBar.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_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 = 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 = SpinorType::unknown) : _type(t), _spin{{a,b,c,d}} {} template LorentzSpinorBar(const LorentzSpinorBar & other) : _type(other._type), _spin(other._spin) {} //@} /** @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 Mathematical assignment operators. //@{ template LorentzSpinorBar & operator+=(const LorentzSpinorBar & a) { for(unsigned int ix=0;ix<4;++ix) _spin[ix] += a._spin[ix]; return *this; } template LorentzSpinorBar & operator-=(const LorentzSpinorBar & a) { for(unsigned int ix=0;ix<4;++ix) _spin[ix] -= a._spin[ix]; return *this; } LorentzSpinorBar & operator*=(double a) { for(unsigned int ix=0;ix<4;++ix) _spin[ix] *=a; return *this; } LorentzSpinorBar & operator/=(double a) { for(unsigned int ix=0;ix<4;++ix) _spin[ix] /=a; return *this; } //@} /** @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 auto projectionOperator(const LorentzVector & p, const ValueB & m) const -> LorentzSpinorBar { typedef decltype(m*Value()) 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. */ std::array,4> _spin; }; /// @name Basic mathematical operations //@{ template inline LorentzSpinorBar operator/(const LorentzSpinorBar & v, Value a) { return LorentzSpinorBar(v.s1()/a, v.s2()/a, v.s3()/a, v.s4()/a,v.Type()); } inline LorentzSpinorBar operator/(const LorentzSpinorBar & v, Complex a) { return LorentzSpinorBar(v.s1()/a, v.s2()/a, v.s3()/a, v.s4()/a,v.Type()); } template inline LorentzSpinorBar operator-(const LorentzSpinorBar & v) { return LorentzSpinorBar(-v.s1(),-v.s2(),-v.s3(),-v.s4(),v.Type()); } template inline LorentzSpinorBar operator+(LorentzSpinorBar a, const LorentzSpinorBar & b) { return a += b; } template inline LorentzSpinorBar operator-(LorentzSpinorBar a, const LorentzSpinorBar & b) { return a -= b; } template inline LorentzSpinorBar operator*(const LorentzSpinorBar & a, double b) { return LorentzSpinorBar(a.s1()*b, a.s2()*b, a.s3()*b, a.s4()*b,a.Type()); } template inline LorentzSpinorBar operator*(double b, LorentzSpinorBar a) { return a *= b; } template inline LorentzSpinorBar operator*(const LorentzSpinorBar & a, Complex b) { return LorentzSpinorBar(a.s1()*b, a.s2()*b, a.s3()*b, a.s4()*b,a.Type()); } template inline auto operator*(complex a, const LorentzSpinorBar & v) -> LorentzSpinorBar { return {a*v.s1(), a*v.s2(), a*v.s3(), a*v.s4(),v.Type()}; } template inline auto operator*(const LorentzSpinorBar & v, complex b) -> LorentzSpinorBar { return b*v; } template inline auto operator/(const LorentzSpinorBar & v, complex b) -> LorentzSpinorBar { return {v.s1()/b, v.s2()/b, v.s3()/b, v.s4()/b,v.Type()}; } template inline auto operator*(ValueB a, const LorentzSpinorBar & v) -> LorentzSpinorBar { return {a*v.s1(), a*v.s2(), a*v.s3(), a*v.s4(),v.Type()}; } template inline auto operator*(const LorentzSpinorBar & v, ValueB b) -> LorentzSpinorBar { return b*v; } template inline auto operator/(const LorentzSpinorBar & v, ValueB b) -> LorentzSpinorBar { return {v.s1()/b, v.s2()/b, v.s3()/b, v.s4()/b,v.Type()}; } } } #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-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined member // functions of the 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 SpinorType::u: new_type=SpinorType::v; break; case SpinorType::v: new_type=SpinorType::u; break; case SpinorType::unknown: default: 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.cc b/Helicity/LorentzTensor.cc --- a/Helicity/LorentzTensor.cc +++ b/Helicity/LorentzTensor.cc @@ -1,12 +1,12 @@ // -*- C++ -*- // // LorentzTensor.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifdef ThePEG_TEMPLATES_IN_CC_FILE #include "LorentzTensor.tcc" #include "ThePEG/Utilities/DescribeClass.h" #endif diff --git a/Helicity/LorentzTensor.h b/Helicity/LorentzTensor.h --- a/Helicity/LorentzTensor.h +++ b/Helicity/LorentzTensor.h @@ -1,533 +1,533 @@ // -*- C++ -*- // // LorentzTensor.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_LorentzTensor_H #define ThePEG_LorentzTensor_H // This is the declaration of the LorentzTensor class. #include "ThePEG/Config/PhysicalQtyComplex.h" #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() = 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{{ {{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 auto operator*(const LorentzTensor & t, const LorentzTensor & u) -> decltype(t.xx()*u.xx()) ; /** * 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 */ auto preDot (const Lorentz5Momentum & vec) const -> LorentzVectorxx())> { LorentzVectorxx())> 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 */ auto postDot(const Lorentz5Momentum & vec) const -> LorentzVectorxx())> { LorentzVectorxx())> 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. */ std::array,4>,4> _tensor; }; /** * Multiplication by a complex number. */ template inline auto operator*(complex a, const LorentzTensor & t) -> LorentzTensor { return {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()}; } /** * Multiplication by a complex number. */ template inline auto operator*(const LorentzTensor & t,complex a) -> LorentzTensor { return {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 auto operator*(const LorentzVector & v, const LorentzTensor & t) -> LorentzVector { LorentzVector outvec; outvec.setX( v.t()*t(3,0)-v.x()*t(0,0) -v.y()*t(1,0)-v.z()*t(2,0)); outvec.setY( v.t()*t(3,1)-v.x()*t(0,1) -v.y()*t(1,1)-v.z()*t(2,1)); outvec.setZ( v.t()*t(3,2)-v.x()*t(0,2) -v.y()*t(1,2)-v.z()*t(2,2)); outvec.setT( v.t()*t(3,3)-v.x()*t(0,3) -v.y()*t(1,3)-v.z()*t(2,3)); return outvec; } /** * Multiply a LorentzTensor by a LorentzVector. */ template inline auto operator*(const LorentzTensor & t, const LorentzVector & v) -> LorentzVector { LorentzVector outvec; outvec.setX( v.t()*t(0,3)-v.x()*t(0,0) -v.y()*t(0,1)-v.z()*t(0,2)); outvec.setY( v.t()*t(1,3)-v.x()*t(1,0) -v.y()*t(1,1)-v.z()*t(1,2)); outvec.setZ( v.t()*t(2,3)-v.x()*t(2,0) -v.y()*t(2,1)-v.z()*t(2,2)); outvec.setT( v.t()*t(3,3)-v.x()*t(3,0) -v.y()*t(3,1)-v.z()*t(3,2)); return outvec; } /** * Multiply a LorentzTensor by a LorentzTensor */ template inline auto operator*(const LorentzTensor & t, const LorentzTensor & u) -> decltype(t.xx()*u.xx()) { using RetT = decltype(t.xx()*u.xx()); 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/LorentzTensor.tcc b/Helicity/LorentzTensor.tcc --- a/Helicity/LorentzTensor.tcc +++ b/Helicity/LorentzTensor.tcc @@ -1,48 +1,48 @@ // -*- C++ -*- // // LorentzTensor.tcc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // namespace ThePEG { namespace Helicity { // general boost template LorentzTensor & LorentzTensor::boost(double bx, double by, double bz) { // basic definitions double boostm[4][4]; double b2 = bx*bx+by*by+bz*bz; double gamma = 1.0/sqrt(1.0-b2); double gmmone = b2 >0 ? (gamma-1.)/b2 : 0.0; double vec[3]={bx,by,bz}; // compute the lorentz boost matrix for(unsigned int ix=0;ix<3;++ix) { for(unsigned int iy=0;iy<3;++iy){boostm[ix][iy]=vec[ix]*vec[iy]*gmmone;} boostm[ix][ix]+=1; boostm[ix][3]=gamma*vec[ix]; boostm[3][ix]=boostm[ix][3]; } boostm[3][3]=gamma; // apply the boost LorentzTensor output; complex temp; unsigned int ix,iy,ixa,iya; for(ix=0;ix<4;++ix) { for(iy=0;iy<4;++iy) { temp=0.; for(ixa=0;ixa<4;++ixa) { for(iya=0;iya<4;++iya) {temp+=boostm[ix][ixa]*boostm[iy][iya]*(*this)(ixa,iya);} } output(ix,iy)=temp; } } *this=output; return *this; } } } diff --git a/Helicity/RSFermionSpinInfo.cc b/Helicity/RSFermionSpinInfo.cc --- a/Helicity/RSFermionSpinInfo.cc +++ b/Helicity/RSFermionSpinInfo.cc @@ -1,48 +1,48 @@ // -*- C++ -*- // // RSFermionSpinInfo.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the RSFermionSpinInfo class. // // Author: Peter Richardson // #include "RSFermionSpinInfo.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Repository/CurrentGenerator.h" #include "ThePEG/Interface/ClassDocumentation.h" using namespace ThePEG; using namespace ThePEG::Helicity; // The following static variable is needed for the type // description system in ThePEG. DescribeNoPIOClass describeThePEGRSFermionSpinInfo("ThePEG::RSFermionSpinInfo", "libThePEG.so"); void RSFermionSpinInfo::Init() { static ClassDocumentation documentation ("The RSFermionSpinInfo class implements the SpinInfo for spin-3/2" " particles"); } void RSFermionSpinInfo::transform(const LorentzMomentum & m, const LorentzRotation & r) { if(isNear(m)) { for(unsigned int ix=0;ix<4;++ix) _currentstates[ix].transform(r); SpinInfo::transform(m,r); } } EIPtr RSFermionSpinInfo::clone() const { tcSpinPtr temp=this; return const_ptr_cast(temp); } diff --git a/Helicity/RSFermionSpinInfo.h b/Helicity/RSFermionSpinInfo.h --- a/Helicity/RSFermionSpinInfo.h +++ b/Helicity/RSFermionSpinInfo.h @@ -1,196 +1,196 @@ // -*- C++ -*- // // RSFermionSpinInfo.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_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), _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), _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 current for the given helicity, \a * hel (0,1,2,3 as described above.) */ const LorentzRSSpinor & getCurrentBasisState(unsigned int hel) const { assert(hel<4); return _currentstates[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 &); //@} /** * Undecay */ virtual void undecay() const { _decaycalc=false; SpinInfo::undecay(); } /** * Reset */ virtual void reset() { undecay(); _currentstates = _productionstates; SpinInfo::reset(); } public: /** * Standard Init function used to initialize the interfaces. */ static void Init(); /** * Standard clone method. */ virtual EIPtr clone() const; private: /** * Private and non-existent assignment operator. */ RSFermionSpinInfo & operator=(const RSFermionSpinInfo &) = delete; private: /** * Basis states in the frame in which the particle was produced. */ mutable std::array,4> _productionstates; /** * Basis states in the frame in which the particle decays. */ mutable std::array,4> _decaystates; /** * Basis states in the current frame of the particle */ mutable std::array,4> _currentstates; /** * True if the decay state has been set. */ mutable bool _decaycalc; }; } } namespace ThePEG { } #endif /* THEPEG_RSFermionSpinInfo_H */ diff --git a/Helicity/ScalarSpinInfo.cc b/Helicity/ScalarSpinInfo.cc --- a/Helicity/ScalarSpinInfo.cc +++ b/Helicity/ScalarSpinInfo.cc @@ -1,33 +1,33 @@ // -*- C++ -*- // // ScalarSpinInfo.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the ScalarSpinInfo class. // // Author: Peter Richardson // #include "ScalarSpinInfo.h" #include "ThePEG/Utilities/DescribeClass.h" using namespace ThePEG; using namespace ThePEG::Helicity; // The following static variable is needed for the type // description system in ThePEG. DescribeNoPIOClass describeThePEGScalarSpinInfo("ThePEG::ScalarSpinInfo", "libThePEG.so"); void ScalarSpinInfo::Init() {} void ScalarSpinInfo::transform(const LorentzMomentum & m, const LorentzRotation & r) { if(isNear(m)) SpinInfo::transform(m,r); } diff --git a/Helicity/ScalarSpinInfo.h b/Helicity/ScalarSpinInfo.h --- a/Helicity/ScalarSpinInfo.h +++ b/Helicity/ScalarSpinInfo.h @@ -1,84 +1,84 @@ // -*- C++ -*- // // ScalarSpinInfo.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_ScalarSpinInfo_H #define ThePEG_ScalarSpinInfo_H // This is the declaration of the ScalarSpinInfo class. #include "ThePEG/EventRecord/SpinInfo.h" #include "ScalarSpinInfo.fh" namespace ThePEG { namespace Helicity { /** * The ScalarSpinInfo class is designed to be the implementation of * the spin information for a scalar particle. Obviously it is pretty * trival in this case. * * @author Peter Richardson * */ class ScalarSpinInfo: public SpinInfo { public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ ScalarSpinInfo() : SpinInfo(PDT::Spin0) {} /** * Standard Constructor. * @param p the production momentum. * @param time true if the particle is time-like. */ ScalarSpinInfo(const Lorentz5Momentum & p, bool time) : SpinInfo(PDT::Spin0, p, time) {} //@} public: /** * Standard Init function. */ static void Init(); /** * Standard clone methods. */ virtual EIPtr clone() const { tcSpinPtr temp = this; return const_ptr_cast(temp); } /** * Perform a lorentz rotation of the spin information */ virtual void transform(const LorentzMomentum &,const LorentzRotation &); private: /** * Private and non-existent assignment operator. */ ScalarSpinInfo & operator=(const ScalarSpinInfo &) = delete; }; } } namespace ThePEG { } #endif /* ThePEG_ScalarSpinInfo_H */ diff --git a/Helicity/TensorSpinInfo.cc b/Helicity/TensorSpinInfo.cc --- a/Helicity/TensorSpinInfo.cc +++ b/Helicity/TensorSpinInfo.cc @@ -1,41 +1,41 @@ // -*- C++ -*- // // TensorSpinInfo.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the TensorSpinInfo class. // // Author: Peter Richardson // #include "TensorSpinInfo.h" #include "ThePEG/Utilities/DescribeClass.h" using namespace ThePEG; using namespace ThePEG::Helicity; // The following static variable is needed for the type // description system in ThePEG. DescribeNoPIOClass describeThePEGTensorSpinInfo("ThePEG::TensorSpinInfo", "libThePEG.so"); void TensorSpinInfo::Init() {} void TensorSpinInfo::transform(const LorentzMomentum & m, const LorentzRotation & r) { if(isNear(m)) { for(unsigned int ix=0;ix<5;++ix) _currentstates[ix].transform(r.one()); SpinInfo::transform(m,r); } } EIPtr TensorSpinInfo::clone() const { tcSpinPtr temp=this; return const_ptr_cast(temp); } diff --git a/Helicity/TensorSpinInfo.h b/Helicity/TensorSpinInfo.h --- a/Helicity/TensorSpinInfo.h +++ b/Helicity/TensorSpinInfo.h @@ -1,194 +1,194 @@ // -*- C++ -*- // // TensorSpinInfo.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_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), _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), _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 current for the given helicity, \a * hel (0,1,2,3,4 as described above.) */ const LorentzTensor & getCurrentBasisState(unsigned int hel) const { assert(hel<5); return _currentstates[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 &); /** * Undecay */ virtual void undecay() const { _decaycalc=false; SpinInfo::undecay(); } /** * Reset */ virtual void reset() { undecay(); _currentstates = _productionstates; SpinInfo::reset(); } public: /** * Standard Init function. */ static void Init(); /** * Standard clone method. */ virtual EIPtr clone() const; private: /** * Private and non-existent assignment operator. */ TensorSpinInfo & operator=(const TensorSpinInfo &) = delete; private: /** * Basis states in the frame in which the particle was produced. */ mutable std::array,5> _productionstates; /** * Basis states in the frame in which the particle decays. */ mutable std::array,5> _decaystates; /** * Basis states in the current frame of the particle */ mutable std::array,5> _currentstates; /** * True if the decay state has been set. */ mutable bool _decaycalc; }; } } namespace ThePEG { } #endif /* THEPEG_TensorSpinInfo_H */ diff --git a/Helicity/VectorSpinInfo.cc b/Helicity/VectorSpinInfo.cc --- a/Helicity/VectorSpinInfo.cc +++ b/Helicity/VectorSpinInfo.cc @@ -1,40 +1,40 @@ // -*- C++ -*- // // VectorSpinInfo.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the VectorSpinInfo class. // // Author: Peter Richardson // #include "VectorSpinInfo.h" #include "ThePEG/Utilities/DescribeClass.h" using namespace ThePEG; using namespace ThePEG::Helicity; EIPtr VectorSpinInfo::clone() const { tcSpinPtr temp=this; return const_ptr_cast(temp); } // The following static variable is needed for the type // description system in ThePEG. DescribeNoPIOClass describeThePEGVectorSpinInfo("ThePEG::VectorSpinInfo", "libThePEG.so"); void VectorSpinInfo::Init() {} void VectorSpinInfo::transform(const LorentzMomentum & m, const LorentzRotation & r) { if(isNear(m)) { for(unsigned int ix=0;ix<3;++ix) _currentstates[ix].transform(r.one()); SpinInfo::transform(m,r); } } diff --git a/Helicity/VectorSpinInfo.h b/Helicity/VectorSpinInfo.h --- a/Helicity/VectorSpinInfo.h +++ b/Helicity/VectorSpinInfo.h @@ -1,193 +1,193 @@ // -*- C++ -*- // // VectorSpinInfo.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_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), _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), _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 current for the given helicity, \a * hel (0,1,2 as described above.) */ const LorentzPolarizationVector & getCurrentBasisState(unsigned int hel) const { assert(hel<3); return _currentstates[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 & ); /** * Undecay */ virtual void undecay() const { _decaycalc=false; SpinInfo::undecay(); } /** * Reset */ virtual void reset() { undecay(); _currentstates = _productionstates; SpinInfo::reset(); } public: /** * Standard Init function used to initialize the interfaces. */ static void Init(); /** * Standard clone method. */ virtual EIPtr clone() const; private: /** * Private and non-existent assignment operator. */ VectorSpinInfo & operator=(const VectorSpinInfo &) = delete; private: /** * Basis states in the frame in which the particle was produced. */ mutable std::array _productionstates; /** * Basis states in the frame in which the particle decays. */ mutable std::array _decaystates; /** * Basis states in the current frame of the particle */ mutable std::array _currentstates; /** * True if the decay state has been set. */ mutable bool _decaycalc; }; } } namespace ThePEG { } #endif /* THEPEG_VectorSpinInfo_H */ diff --git a/Helicity/Vertex/AbstractSSSSVertex.cc b/Helicity/Vertex/AbstractSSSSVertex.cc --- a/Helicity/Vertex/AbstractSSSSVertex.cc +++ b/Helicity/Vertex/AbstractSSSSVertex.cc @@ -1,26 +1,34 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the AbstractSSSSVertex class. // #include "AbstractSSSSVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" using namespace ThePEG; using namespace Helicity; // The following static variable is needed for the type // description system in ThePEG. DescribeAbstractNoPIOClass describeThePEGAbstractSSSSVertex("ThePEG::AbstractSSSSVertex", "libThePEG.so"); void AbstractSSSSVertex::Init() { static ClassDocumentation documentation ("The AbstractSSSSVertex class is the base class for all " "scalar-scalar-scalar-scalar interactions"); } +ScalarWaveFunction AbstractSSSSVertex::evaluate(Energy2,int, tcPDPtr, + const ScalarWaveFunction & , + const ScalarWaveFunction & , + const ScalarWaveFunction & , + complex , + complex) { + assert(false); +} diff --git a/Helicity/Vertex/AbstractSSSSVertex.h b/Helicity/Vertex/AbstractSSSSVertex.h --- a/Helicity/Vertex/AbstractSSSSVertex.h +++ b/Helicity/Vertex/AbstractSSSSVertex.h @@ -1,88 +1,90 @@ // -*- C++ -*- #ifndef HELICITY_AbstractSSSSVertex_H #define HELICITY_AbstractSSSSVertex_H // // This is the declaration of the AbstractSSSSVertex class. // #include "VertexBase.h" #include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h" #include "AbstractSSSSVertex.fh" namespace ThePEG { namespace Helicity { /** * The AbstractSSSSVertex class is the base class for all scalar-scalar-scalar * interactions in ThePEG */ class AbstractSSSSVertex: public VertexBase { public: /** * Default constructor */ AbstractSSSSVertex() : VertexBase(VertexType::SSSS) {} /** * Members to calculate the helicity amplitude expressions for vertices * and off-shell particles. */ //@{ /** * Evaluate the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param sca1 The wavefunction for the first scalar. * @param sca2 The wavefunction for the second scalar. * @param sca3 The wavefunction for the third scalar. * @param sca4 The wavefunction for the fourth scalar. */ virtual Complex evaluate(Energy2 q2,const ScalarWaveFunction & sca1, const ScalarWaveFunction & sca2, const ScalarWaveFunction & sca3, const ScalarWaveFunction & sca4) = 0; /** * Evaluate the off-shell scalar coming from the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param iopt Option of the shape of the Breit-Wigner for the off-shell scalar. * @param out The ParticleData pointer for the off-shell scalar. * @param sca1 The wavefunction for the first scalar. * @param sca2 The wavefunction for the second scalar. * @param sca3 The wavefunction for the third scalar. */ virtual ScalarWaveFunction evaluate(Energy2 q2,int iopt, tcPDPtr out, const ScalarWaveFunction & sca1, const ScalarWaveFunction & sca2, - const ScalarWaveFunction & sca3)=0; + const ScalarWaveFunction & sca3, + complex mass=-GeV, + complex width=-GeV); //@} public: /** * 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(); private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ AbstractSSSSVertex & operator=(const AbstractSSSSVertex &) = delete; }; } } namespace ThePEG { } #endif /* HELICITY_AbstractSSSSVertex_H */ diff --git a/Helicity/Vertex/Scalar/FFSVertex.cc b/Helicity/Vertex/Scalar/FFSVertex.cc --- a/Helicity/Vertex/Scalar/FFSVertex.cc +++ b/Helicity/Vertex/Scalar/FFSVertex.cc @@ -1,121 +1,121 @@ // -*- C++ -*- // // FFSVertex.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the FFSVertex class. // #include "FFSVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" using namespace ThePEG; using namespace ThePEG::Helicity; // The following static variable is needed for the type // description system in ThePEG. DescribeAbstractNoPIOClass describeThePEGFFSVertex("ThePEG::FFSVertex", "libThePEG.so"); void FFSVertex::Init() { static ClassDocumentation documentation ("The FFSVertex class is the implementation of the FFS" "vertex. All such vertices shoud inherit from it"); } // evaluate the full vertex Complex FFSVertex::evaluate(Energy2 q2, const SpinorWaveFunction & sp, const SpinorBarWaveFunction & sbar, const ScalarWaveFunction & sca) { // calculate the couplings setCoupling(q2,sp.particle(),sbar.particle(),sca.particle()); Complex vertex( _left*(sbar.s1()*sp.s1()+sbar.s2()*sp.s2()) +_right*(sbar.s3()*sp.s3()+sbar.s4()*sp.s4()) ); // final factors return Complex(0.,1.)*norm()*sca.wave()*vertex; } // off-shell scalar ScalarWaveFunction FFSVertex::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 setCoupling(q2,sp.particle(),sbar.particle(),out); Energy2 p2 = pout.m2(); Complex fact = -norm()*propagator(iopt,p2,out,mass,width); Complex output = _left*(sbar.s1()*sp.s1()+sbar.s2()*sp.s2()) +_right*(sbar.s3()*sp.s3()+sbar.s4()*sp.s4()); // final factors and output output*=fact; return ScalarWaveFunction(pout,out,output); } // off-shell spinor SpinorWaveFunction FFSVertex::evaluate(Energy2 q2, int iopt,tcPDPtr out, const SpinorWaveFunction & sp, const ScalarWaveFunction & sca, complex mass, complex width) { // work out the momentum of the off-shell particle Lorentz5Momentum pout = sp.momentum()+sca.momentum(); // first calculate the couplings setCoupling(q2,sp.particle(),out,sca.particle()); Energy2 p2 = pout.m2(); Complex fact = -norm()*sca.wave()*propagator(iopt,p2,out,mass,width); Complex ii(0.,1.); // useful combinations of the momenta if(mass.real() < ZERO) mass = out->mass(); complex p1p2 = pout.x()+ii*pout.y(); complex p1m2 = pout.x()-ii*pout.y(); 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(); s1 = Complex(UnitRemoval::InvE * fact*( _left*mass*spt.s1()+_right*(p0m3*spt.s3()-p1m2*spt.s4()))); s2 = Complex(UnitRemoval::InvE * fact*( _left*mass*spt.s2()+_right*(p0p3*spt.s4()-p1p2*spt.s3()))); s3 = Complex(UnitRemoval::InvE * fact*(_right*mass*spt.s3()+ _left*(p0p3*spt.s1()+p1m2*spt.s2()))); s4 = Complex(UnitRemoval::InvE * fact*(_right*mass*spt.s4()+ _left*(p0m3*spt.s2()+p1p2*spt.s1()))); return SpinorWaveFunction(pout,out,s1,s2,s3,s4); } // off-shell SpinorBar SpinorBarWaveFunction FFSVertex::evaluate(Energy2 q2,int iopt,tcPDPtr out, const SpinorBarWaveFunction & sbar, const ScalarWaveFunction & sca, complex mass, complex width) { // work out the momentum of the off-shell particle Lorentz5Momentum pout = sbar.momentum()+sca.momentum(); // first calculate the couplings setCoupling(q2,out,sbar.particle(),sca.particle()); Energy2 p2 = pout.m2(); Complex fact = -norm()*sca.wave()*propagator(iopt,p2,out,mass,width); Complex ii(0.,1.); // momentum components if(mass.real() < ZERO) mass = 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(); complex p0p3=pout.e() + pout.z(); complex p0m3=pout.e() - pout.z(); s1 = Complex(UnitRemoval::InvE * fact*( mass*_left*sbart.s1()-_right*(p0p3*sbart.s3()+p1p2*sbart.s4()))); s2 = Complex(UnitRemoval::InvE * fact*( mass*_left*sbart.s2()-_right*(p1m2*sbart.s3()+p0m3*sbart.s4()))); s3 = Complex(UnitRemoval::InvE * fact*(mass*_right*sbart.s3()- _left*(p0m3*sbart.s1()-p1p2*sbart.s2()))); s4 = Complex(UnitRemoval::InvE * fact*(mass*_right*sbart.s4()+ _left*(p1m2*sbart.s1()-p0p3*sbart.s2()))); return SpinorBarWaveFunction(pout,out,s1,s2,s3,s4); } diff --git a/Helicity/Vertex/Scalar/FFSVertex.h b/Helicity/Vertex/Scalar/FFSVertex.h --- a/Helicity/Vertex/Scalar/FFSVertex.h +++ b/Helicity/Vertex/Scalar/FFSVertex.h @@ -1,200 +1,200 @@ // -*- C++ -*- // // FFSVertex.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_FFSVertex_H #define ThePEG_FFSVertex_H // // This is the declaration of the FFSVertex class. #include "ThePEG/Helicity/Vertex/AbstractFFSVertex.h" #include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h" #include "FFSVertex.fh" namespace ThePEG { namespace Helicity{ /** \ingroup Helicity * * The FFSVertex class is the implementation of the interact of a * scalar boson and a fermion-antifermion pair. It inherits from the AbstractFFSVertex * class for storage of the particles interacting at the vertex and implements * the helicity calculations. * * Implementations of specific interactions should inherit from this and implement * the virtual setCoupling member. * * The form of the vertex is * \f[ic\bar{f_2}a^\lambda P_\lambda f_1\phi_3\f] * where \f$a^\pm\f$ are the right and left couplings and \f$P_\pm=(1\pm\gamma_5)\f$ * are the chirality projection operators. * * @see AbstractFFSVertex */ class FFSVertex: public AbstractFFSVertex { public: /** * Standard Init function used to initialize the interfaces. */ static void Init(); public: /** * Members to calculate the helicity amplitude expressions for vertices * and off-shell particles. */ //@{ /** * Evalulate the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param sp1 The wavefunction for the ferimon. * @param sbar2 The wavefunction for the antifermion. * @param sca3 The wavefunction for the scalar. */ Complex evaluate(Energy2 q2,const SpinorWaveFunction & sp1, const SpinorBarWaveFunction & sbar2, const ScalarWaveFunction & sca3); /** * Evaluate the off-shell spinor coming from the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param iopt Option of the shape of the Breit-Wigner for the off-shell spinor. * @param out The ParticleData pointer for the off-shell spinor. * @param sp1 The wavefunction for the ferimon. * @param sca3 The wavefunction for the scalar. * @param mass The mass of the off-shell particle if not taken from the ParticleData * object * @param width The width of the off-shell particle if not taken from the ParticleData * object */ SpinorWaveFunction evaluate(Energy2 q2,int iopt,tcPDPtr out, const SpinorWaveFunction & sp1, const ScalarWaveFunction & sca3, complex mass=-GeV, complex width=-GeV); /** * Evaluate the off-shell barred spinor coming from the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param iopt Option of the shape of the Breit-Wigner for the off-shell barred spinor. * @param out The ParticleData pointer for the off-shell barred spinor. * @param sbar2 The wavefunction for the antifermion. * @param sca3 The wavefunction for the scalar. * @param mass The mass of the off-shell particle if not taken from the ParticleData * object * @param width The width of the off-shell particle if not taken from the ParticleData * object */ SpinorBarWaveFunction evaluate(Energy2 q2,int iopt,tcPDPtr out, const SpinorBarWaveFunction & sbar2, const ScalarWaveFunction & sca3, complex mass=-GeV, complex width=-GeV); /** * Evaluate the off-shell scalar coming from the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param iopt Option of the shape of the Breit-Wigner for the off-shell scalar. * @param out The ParticleData pointer for the off-shell scalar. * @param sp1 The wavefunction for the ferimon. * @param sbar2 The wavefunction for the antifermion. * @param mass The mass of the off-shell particle if not taken from the ParticleData * object * @param width The width of the off-shell particle if not taken from the ParticleData * object */ ScalarWaveFunction evaluate(Energy2 q2,int iopt,tcPDPtr out, const SpinorWaveFunction & sp1, const SpinorBarWaveFunction & sbar2, complex mass=-GeV, complex width=-GeV); /** * 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; /** * Dummy setCouplings for a four point interaction * This method is virtual and must be implemented in * classes inheriting from this. */ virtual void setCoupling(Energy2,tcPDPtr,tcPDPtr,tcPDPtr,tcPDPtr) { assert(false); } //@} /** * Get the couplings */ //@{ /** * Get the left coupling. */ Complex left() { return _left; } /** * Get the right coupling. */ Complex right() { return _right; } //@} protected: /** * Set the couplings */ //@{ /** * Set the left coupling. */ void left(Complex in) { _left = in; } /** * Set the right coupling. */ void right(Complex in) { _right = in; } //@} private: /** * Private and non-existent assignment operator. */ FFSVertex & operator=(const FFSVertex &) = delete; private: /** * Storage of the left coupling. */ Complex _left; /** * Storage of the right coupling. */ Complex _right; }; } } #endif /* ThePEG_FFSVertex_H */ diff --git a/Helicity/Vertex/Scalar/RFSVertex.cc b/Helicity/Vertex/Scalar/RFSVertex.cc --- a/Helicity/Vertex/Scalar/RFSVertex.cc +++ b/Helicity/Vertex/Scalar/RFSVertex.cc @@ -1,104 +1,104 @@ // -*- C++ -*- // // RFSVertex.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the RFSVertex class. // #include "RFSVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" using namespace ThePEG; using namespace ThePEG::Helicity; // The following static variable is needed for the type // description system in ThePEG. DescribeAbstractNoPIOClass describeThePEGRFSVertex("ThePEG::RFSVertex", "libThePEG.so"); void RFSVertex::Init() { static ClassDocumentation documentation ("The RFSVertex class is the implementation of the RFS" "vertex. All such vertices shoud inherit from it"); } Complex RFSVertex::evaluate(Energy2 q2,const RSSpinorWaveFunction & sp, const SpinorBarWaveFunction & sbar, const ScalarWaveFunction & sca) { // calculate the couplings setCoupling(q2,sp.particle(),sbar.particle(),sca.particle()); LorentzSpinor wdot = sp.wave().dot(sbar.momentum()); Complex lS = wdot. leftScalar(sbar.wave()); Complex rS = wdot.rightScalar(sbar.wave()); swap(lS,rS); return Complex(0.,1.)*norm()*sca.wave()*(lS*left()+rS*right()); } Complex RFSVertex::evaluate(Energy2 q2,const SpinorWaveFunction & sp, const RSSpinorBarWaveFunction & sbar, const ScalarWaveFunction & sca) { // calculate the couplings setCoupling(q2,sbar.particle(),sp.particle(),sca.particle()); LorentzSpinorBar wdot = sbar.wave().dot(sp.momentum()); Complex lS = sp.wave(). leftScalar(wdot); Complex rS = sp.wave().rightScalar(wdot); return Complex(0.,1.)*norm()*sca.wave()*(lS*left()+rS*right()); } SpinorWaveFunction RFSVertex::evaluate(Energy2 ,int ,tcPDPtr , const RSSpinorWaveFunction & , const ScalarWaveFunction & , complex , complex ) { assert(false); return SpinorWaveFunction(); } RSSpinorWaveFunction RFSVertex::evaluate(Energy2 ,int ,tcPDPtr , const SpinorWaveFunction & , const ScalarWaveFunction & , complex , complex ) { assert(false); return RSSpinorWaveFunction(); } SpinorBarWaveFunction RFSVertex::evaluate(Energy2 ,int ,tcPDPtr , const RSSpinorBarWaveFunction & , const ScalarWaveFunction & , complex , complex ) { assert(false); return SpinorBarWaveFunction(); } RSSpinorBarWaveFunction RFSVertex::evaluate(Energy2 ,int ,tcPDPtr , const SpinorBarWaveFunction & , const ScalarWaveFunction & , complex , complex ) { assert(false); return RSSpinorBarWaveFunction(); } ScalarWaveFunction RFSVertex::evaluate(Energy2 ,int ,tcPDPtr , const RSSpinorWaveFunction & , const SpinorBarWaveFunction & , complex , complex ) { assert(false); return ScalarWaveFunction(); } ScalarWaveFunction RFSVertex::evaluate(Energy2 ,int ,tcPDPtr , const SpinorWaveFunction & , const RSSpinorBarWaveFunction & , complex , complex ) { assert(false); return ScalarWaveFunction(); } diff --git a/Helicity/Vertex/Scalar/RFSVertex.h b/Helicity/Vertex/Scalar/RFSVertex.h --- a/Helicity/Vertex/Scalar/RFSVertex.h +++ b/Helicity/Vertex/Scalar/RFSVertex.h @@ -1,263 +1,263 @@ // -*- C++ -*- // // RFSVertex.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_RFSVertex_H #define ThePEG_RFSVertex_H // // This is the declaration of the RFSVertex class. #include "ThePEG/Helicity/Vertex/AbstractRFSVertex.h" #include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h" #include "RFSVertex.fh" namespace ThePEG { namespace Helicity{ /** \ingroup Helicity * * The RFSVertex class is the implementation of the interact of a * scalar boson and a spin-3/2 fermion-antifermion pair. It inherits from the AbstractRFSVertex * class for storage of the particles interacting at the vertex and implements * the helicity calculations. * * Implementations of specific interactions should inherit from this and implement * the virtual setCoupling member. * * The form of the vertex is * \f[ic\bar{f_2}_\mu p_{1}^\mu a^\lambda P_\lambda f_1\phi_3\f] * where \f$a^\pm\f$ are the right and left couplings and \f$P_\pm=(1\pm\gamma_5)\f$ * are the chirality projection operators. * * @see AbstractRFSVertex */ class RFSVertex: public AbstractRFSVertex { public: /** * Standard Init function used to initialize the interfaces. */ static void Init(); public: /** * Members to calculate the helicity amplitude expressions for vertices * and off-shell particles. */ //@{ /** * Evalulate the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param sp1 The wavefunction for the RS ferimon. * @param sbar2 The wavefunction for the antifermion. * @param sca3 The wavefunction for the scalar. */ Complex evaluate(Energy2 q2,const RSSpinorWaveFunction & sp1, const SpinorBarWaveFunction & sbar2, const ScalarWaveFunction & sca3); /** * Evalulate the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param sp1 The wavefunction for the ferimon. * @param sbar2 The wavefunction for the RS antifermion. * @param sca3 The wavefunction for the scalar. */ Complex evaluate(Energy2 q2,const SpinorWaveFunction & sp1, const RSSpinorBarWaveFunction & sbar2, const ScalarWaveFunction & sca3); /** * Evaluate the off-shell spinor coming from the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param iopt Option of the shape of the Breit-Wigner for the off-shell spinor. * @param out The ParticleData pointer for the off-shell spinor. * @param sp1 The wavefunction for the ferimon. * @param sca3 The wavefunction for the scalar. * @param mass The mass of the off-shell particle if not taken from the ParticleData * object * @param width The width of the off-shell particle if not taken from the ParticleData * object */ SpinorWaveFunction evaluate(Energy2 q2,int iopt,tcPDPtr out, const RSSpinorWaveFunction & sp1, const ScalarWaveFunction & sca3, complex mass=-GeV, complex width=-GeV); /** * Evaluate the off-shell spinor coming from the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param iopt Option of the shape of the Breit-Wigner for the off-shell spinor. * @param out The ParticleData pointer for the off-shell spinor. * @param sp1 The wavefunction for the ferimon. * @param sca3 The wavefunction for the scalar. * @param mass The mass of the off-shell particle if not taken from the ParticleData * object * @param width The width of the off-shell particle if not taken from the ParticleData * object */ RSSpinorWaveFunction evaluate(Energy2 q2,int iopt,tcPDPtr out, const SpinorWaveFunction & sp1, const ScalarWaveFunction & sca3, complex mass=-GeV, complex width=-GeV); /** * Evaluate the off-shell barred spinor coming from the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param iopt Option of the shape of the Breit-Wigner for the off-shell barred spinor. * @param out The ParticleData pointer for the off-shell barred spinor. * @param sbar2 The wavefunction for the antifermion. * @param sca3 The wavefunction for the scalar. * @param mass The mass of the off-shell particle if not taken from the ParticleData * object * @param width The width of the off-shell particle if not taken from the ParticleData * object */ SpinorBarWaveFunction evaluate(Energy2 q2,int iopt,tcPDPtr out, const RSSpinorBarWaveFunction & sbar2, const ScalarWaveFunction & sca3, complex mass=-GeV, complex width=-GeV); /** * Evaluate the off-shell barred spinor coming from the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param iopt Option of the shape of the Breit-Wigner for the off-shell barred spinor. * @param out The ParticleData pointer for the off-shell barred spinor. * @param sbar2 The wavefunction for the antifermion. * @param sca3 The wavefunction for the scalar. * @param mass The mass of the off-shell particle if not taken from the ParticleData * object * @param width The width of the off-shell particle if not taken from the ParticleData * object */ RSSpinorBarWaveFunction evaluate(Energy2 q2,int iopt,tcPDPtr out, const SpinorBarWaveFunction & sbar2, const ScalarWaveFunction & sca3, complex mass=-GeV, complex width=-GeV); /** * Evaluate the off-shell scalar coming from the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param iopt Option of the shape of the Breit-Wigner for the off-shell scalar. * @param out The ParticleData pointer for the off-shell scalar. * @param sp1 The wavefunction for the RS ferimon. * @param sbar2 The wavefunction for the antifermion. * @param mass The mass of the off-shell particle if not taken from the ParticleData * object * @param width The width of the off-shell particle if not taken from the ParticleData * object */ ScalarWaveFunction evaluate(Energy2 q2,int iopt,tcPDPtr out, const RSSpinorWaveFunction & sp1, const SpinorBarWaveFunction & sbar2, complex mass=-GeV, complex width=-GeV); /** * Evaluate the off-shell scalar coming from the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param iopt Option of the shape of the Breit-Wigner for the off-shell scalar. * @param out The ParticleData pointer for the off-shell scalar. * @param sp1 The wavefunction for the ferimon. * @param sbar2 The wavefunction for the RS antifermion. * @param mass The mass of the off-shell particle if not taken from the ParticleData * object * @param width The width of the off-shell particle if not taken from the ParticleData * object */ ScalarWaveFunction evaluate(Energy2 q2,int iopt,tcPDPtr out, const SpinorWaveFunction & sp1, const RSSpinorBarWaveFunction & sbar2, complex mass=-GeV, complex width=-GeV); //@} /** * 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; /** * Dummy setCouplings for a four point interaction * This method is virtual and must be implemented in * classes inheriting from this. */ virtual void setCoupling(Energy2,tcPDPtr,tcPDPtr,tcPDPtr,tcPDPtr) { assert(false); } //@} /** * Get the couplings */ //@{ /** * Get the left coupling. */ Complex left() { return _left; } /** * Get the right coupling. */ Complex right() { return _right; } //@} protected: /** * Set the couplings */ //@{ /** * Set the left coupling. */ void left(Complex in) { _left = in; } /** * Set the right coupling. */ void right(Complex in) { _right = in; } //@} private: /** * Private and non-existent assignment operator. */ RFSVertex & operator=(const RFSVertex &) = delete; private: /** * Storage of the left coupling. */ Complex _left; /** * Storage of the right coupling. */ Complex _right; }; } } #endif /* ThePEG_RFSVertex_H */ diff --git a/Helicity/Vertex/Scalar/SSSSVertex.cc b/Helicity/Vertex/Scalar/SSSSVertex.cc --- a/Helicity/Vertex/Scalar/SSSSVertex.cc +++ b/Helicity/Vertex/Scalar/SSSSVertex.cc @@ -1,60 +1,60 @@ // -*- C++ -*- // // SSSSVertex.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the SSSSVertex class. // #include "SSSSVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" using namespace ThePEG; using namespace Helicity; // The following static variable is needed for the type // description system in ThePEG. DescribeAbstractNoPIOClass describeThePEGSSSSVertex("ThePEG::SSSSVertex", "libThePEG.so"); void SSSSVertex::Init() { static ClassDocumentation documentation ("The SSSSVertex class is the implementation" "of the helicity amplitude for the four scalar vertex" "all vertices of trhis type should inherit from it"); } // evaluate the vertex Complex SSSSVertex::evaluate(Energy2 q2, const ScalarWaveFunction & sca1, const ScalarWaveFunction & sca2, const ScalarWaveFunction & sca3, const ScalarWaveFunction & sca4) { // calculate the coupling setCoupling(q2,sca1.particle(),sca2.particle(), sca3.particle(),sca4.particle()); // return the answer return Complex(0.,1.)*norm()*sca1.wave()*sca2.wave()*sca3.wave()*sca4.wave(); } // off-shell scalar ScalarWaveFunction SSSSVertex::evaluate(Energy2 q2, int iopt, tcPDPtr out, const ScalarWaveFunction & sca1, const ScalarWaveFunction & sca2, const ScalarWaveFunction & sca3) { // outgoing momentum Lorentz5Momentum pout = sca1.momentum()+sca2.momentum()+sca3.momentum(); // calculate the coupling setCoupling(q2,sca1.particle(),sca2.particle(),sca3.particle(),out); // wavefunction Energy2 p2 = pout.m2(); Complex fact = -norm()*sca1.wave()*sca2.wave()*sca3.wave()* propagator(iopt,p2,out); return ScalarWaveFunction(pout,out,fact); } diff --git a/Helicity/Vertex/Scalar/SSSSVertex.h b/Helicity/Vertex/Scalar/SSSSVertex.h --- a/Helicity/Vertex/Scalar/SSSSVertex.h +++ b/Helicity/Vertex/Scalar/SSSSVertex.h @@ -1,115 +1,115 @@ // -*- C++ -*- // // SSSSVertex.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_SSSSVertex_H #define ThePEG_SSSSVertex_H // // This is the declaration of the SSSSVertex class. // #include "ThePEG/Helicity/Vertex/AbstractSSSSVertex.h" #include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h" #include "SSSSVertex.fh" namespace ThePEG { namespace Helicity { /** \ingroup Helicity * * The SSSSVertex class is the implementation of the interaction of * four scalars. It inherits from the AbstractSSSSVertex class for the storage * of the particles interacting at the vertex and implements the * helicity calculations. * * Any classes implementating the vertex should inherit from it and implement * the virtual set Coupling member. * * The form of the vertex is * \f[ic\phi_1\phi_2\phi_3\phi_4\f] * * @see AbstractSSSSVertex */ class SSSSVertex: public AbstractSSSSVertex { public: /** * Standard Init function used to initialize the interfaces. */ static void Init(); public: /** * Members to calculate the helicity amplitude expressions for vertices * and off-shell particles. */ //@{ /** * Evaluate the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param sca1 The wavefunction for the first scalar. * @param sca2 The wavefunction for the second scalar. * @param sca3 The wavefunction for the third scalar. * @param sca4 The wavefunction for the fourth scalar. */ Complex evaluate(Energy2 q2, const ScalarWaveFunction & sca1, const ScalarWaveFunction & sca2, const ScalarWaveFunction & sca3, const ScalarWaveFunction & sca4); /** * Evaluate the off-shell scalar coming from the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param iopt Option of the shape of the Breit-Wigner for the off-shell scalar. * @param out The ParticleData pointer for the off-shell scalar. * @param sca1 The wavefunction for the first scalar. * @param sca2 The wavefunction for the second scalar. * @param sca3 The wavefunction for the third scalar. */ ScalarWaveFunction evaluate(Energy2 q2,int iopt, tcPDPtr out, const ScalarWaveFunction & sca1, const ScalarWaveFunction & sca2, const ScalarWaveFunction & sca3); //@} /** * Set coupling methods */ //@{ /** * Dummy for a three point interaction. */ virtual void setCoupling(Energy2,tcPDPtr,tcPDPtr,tcPDPtr) { assert(false); } /** * 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; //@} private: /** * Private and non-existent assignment operator. */ SSSSVertex & operator=(const SSSSVertex &) = delete; }; } } #endif /* ThePEG_SSSSVertex_H */ diff --git a/Helicity/Vertex/Scalar/SSSVertex.cc b/Helicity/Vertex/Scalar/SSSVertex.cc --- a/Helicity/Vertex/Scalar/SSSVertex.cc +++ b/Helicity/Vertex/Scalar/SSSVertex.cc @@ -1,60 +1,60 @@ // -*- C++ -*- // // SSSVertex.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the SSSVertex class. // #include "SSSVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" using namespace ThePEG; using namespace Helicity; // The following static variable is needed for the type // description system in ThePEG. DescribeAbstractNoPIOClass describeThePEGSSSVertex("ThePEG::SSSVertex", "libThePEG.so"); void SSSVertex::Init() { static ClassDocumentation documentation ("The SSSVertex class is the implementation of the SSS" "vertex. All such vertices shoud inherit from it"); } // evaluate the vertex Complex SSSVertex::evaluate(Energy2 q2, const ScalarWaveFunction & sca1, const ScalarWaveFunction & sca2, const ScalarWaveFunction & sca3) { if(kinematics()) calculateKinematics(sca1.momentum(),sca2.momentum(),sca3.momentum()); // calculate the coupling setCoupling(q2,sca1.particle(),sca2.particle(),sca3.particle()); // return the answer return Complex(0.,1.)*norm()*sca1.wave()*sca2.wave()*sca3.wave(); } // off-shell scalar ScalarWaveFunction SSSVertex::evaluate(Energy2 q2,int iopt, tcPDPtr out, const ScalarWaveFunction & sca1, const ScalarWaveFunction & sca2, complex mass, complex width) { // outgoing momentum Lorentz5Momentum pout = sca1.momentum()+sca2.momentum(); if(kinematics()) calculateKinematics(sca1.momentum(),sca2.momentum(),-pout); // calculate the coupling setCoupling(q2,sca1.particle(),sca2.particle(),out); // wavefunction Energy2 p2=pout.m2(); Complex fact=-norm()*sca1.wave()*sca2.wave()*propagator(iopt,p2,out,mass,width); return ScalarWaveFunction(pout,out,fact); } diff --git a/Helicity/Vertex/Scalar/SSSVertex.h b/Helicity/Vertex/Scalar/SSSVertex.h --- a/Helicity/Vertex/Scalar/SSSVertex.h +++ b/Helicity/Vertex/Scalar/SSSVertex.h @@ -1,117 +1,117 @@ // -*- C++ -*- // // SSSVertex.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_SSSVertex_H #define ThePEG_SSSVertex_H // // This is the declaration of the SSSVertex class. // #include "ThePEG/Helicity/Vertex/AbstractSSSVertex.h" #include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h" #include "SSSVertex.fh" namespace ThePEG { namespace Helicity { /** \ingroup Helicity * * The SSSVertex class is the implementation of the interaction of * three scalars. It inherits from the AbstractSSSVertex class for the storage of the * particles interacting at the vertex and implements the helicity calculations. * * Any classes implementating the vertex should inherit from it and implement * the virtual set Coupling member. * * The form of the vertex is * \f[ic\phi_1\phi_2\phi_3\f] * * @see AbstractSSSVertex */ class SSSVertex: public AbstractSSSVertex { public: /** * Standard Init function used to initialize the interfaces. */ static void Init(); public: /** * Members to calculate the helicity amplitude expressions for vertices * and off-shell particles. */ //@{ /** * Evaluate the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param sca1 The wavefunction for the first scalar. * @param sca2 The wavefunction for the second scalar. * @param sca3 The wavefunction for the third scalar. */ Complex evaluate(Energy2 q2,const ScalarWaveFunction & sca1, const ScalarWaveFunction & sca2,const ScalarWaveFunction & sca3); /** * Evaluate the off-shell scalar coming from the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param iopt Option of the shape of the Breit-Wigner for the off-shell scalar. * @param out The ParticleData pointer for the off-shell scalar. * @param sca1 The wavefunction for the first scalar. * @param sca2 The wavefunction for the second scalar. * @param mass The mass of the off-shell particle if not taken from the ParticleData * object * @param width The width of the off-shell particle if not taken from the ParticleData * object */ ScalarWaveFunction evaluate(Energy2 q2,int iopt, tcPDPtr out, const ScalarWaveFunction & sca1, const ScalarWaveFunction & sca2, complex mass=-GeV, complex width=-GeV); //@} /** * 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; /** * Dummy setCouplings for a four point interaction * This method is virtual and must be implemented in * classes inheriting from this. */ virtual void setCoupling(Energy2,tcPDPtr,tcPDPtr,tcPDPtr,tcPDPtr) { assert(false); } //@} private: /** * Private and non-existent assignment operator. */ SSSVertex & operator=(const SSSVertex &) = delete; }; } } #endif /* ThePEG_SSSVertex_H */ diff --git a/Helicity/Vertex/Scalar/VSSVertex.cc b/Helicity/Vertex/Scalar/VSSVertex.cc --- a/Helicity/Vertex/Scalar/VSSVertex.cc +++ b/Helicity/Vertex/Scalar/VSSVertex.cc @@ -1,32 +1,32 @@ // -*- C++ -*- // // VSSVertex.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the VSSVertex class. // #include "VSSVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" using namespace ThePEG; using namespace Helicity; // The following static variable is needed for the type // description system in ThePEG. DescribeAbstractNoPIOClass describeThePEGVSSVertex("ThePEG::VSSVertex", "libThePEG.so"); void VSSVertex::Init() { static ClassDocumentation documentation ("The VSSVertex class is hte implementation of the" "vector-scalar-scalar vertex for helicity amplitude calculations." " all such vertices should inherit from it"); } diff --git a/Helicity/Vertex/Scalar/VSSVertex.h b/Helicity/Vertex/Scalar/VSSVertex.h --- a/Helicity/Vertex/Scalar/VSSVertex.h +++ b/Helicity/Vertex/Scalar/VSSVertex.h @@ -1,55 +1,55 @@ // -*- C++ -*- // // VSSVertex.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_VSSVertex_H #define ThePEG_VSSVertex_H // // This is the declaration of the VSSVertex class. // #include "GeneralVSSVertex.h" #include "VSSVertex.fh" namespace ThePEG { namespace Helicity { /** \ingroup Helicity * * The VSSVertex class is the implementation of the vector-scalar-scalar * vertex. It inherits from the AbstractVSSVertex class for storage of the particles * and implements the helicity calculations. * * All such vertices should inherit from this class and implement the virtual * setCoupling member * * The form of the vertex is * \f[-ic\left(p_2-p_3\right)\cdot\epsilon_1\phi_2\phi_3\f] * * @see GeneralVSSVertex */ class VSSVertex: public GeneralVSSVertex { public: /** * Standard Init function used to initialize the interfaces. */ static void Init(); private: /** * Private and non-existent assignment operator. */ VSSVertex & operator=(const VSSVertex &) = delete; }; } } #endif /* ThePEG_VSSVertex_H */ diff --git a/Helicity/Vertex/Scalar/VVSSVertex.cc b/Helicity/Vertex/Scalar/VVSSVertex.cc --- a/Helicity/Vertex/Scalar/VVSSVertex.cc +++ b/Helicity/Vertex/Scalar/VVSSVertex.cc @@ -1,94 +1,94 @@ // -*- C++ -*- // // VVSSVertex.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the VVSSVertex class. // #include "VVSSVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" using namespace ThePEG; using namespace Helicity; // The following static variable is needed for the type // description system in ThePEG. DescribeAbstractNoPIOClass describeThePEGVVSSVertex("ThePEG::VVSSVertex", "libThePEG.so"); void VVSSVertex::Init() { static ClassDocumentation documentation ("The VVSSVertex class is the implementation of helicity" "amplitude calculation of the vector-vector-scalar-scalar vertex." "All classes for this type of vertex should inherit from it."); } // evaluate the vertex Complex VVSSVertex::evaluate(Energy2 q2,const VectorWaveFunction & vec1, const VectorWaveFunction & vec2, const ScalarWaveFunction & sca1, const ScalarWaveFunction & sca2) { // calculate the coupling setCoupling(q2,vec1.particle(),vec2.particle(), sca1.particle(),sca2.particle()); // evaluate the vertex return Complex(0.,1.)*norm()*sca1.wave()*sca2.wave()* vec1.wave().dot(vec2.wave()); } // evaluate an off-shell vector VectorWaveFunction VVSSVertex::evaluate(Energy2 q2, int iopt, tcPDPtr out, const VectorWaveFunction & vec, const ScalarWaveFunction & sca1, const ScalarWaveFunction & sca2, complex mass, complex width) { // outgoing momentum Lorentz5Momentum pout = vec.momentum()+sca1.momentum()+sca2.momentum(); // calculate the coupling setCoupling(q2,out,vec.particle(),sca1.particle(),sca2.particle()); // prefactor Energy2 p2 = pout.m2(); if(mass.real() < ZERO) mass = out->mass(); complex mass2 = sqr(mass); Complex fact = norm()*sca1.wave()*sca2.wave()*propagator(iopt,p2,out,mass,width); // evaluate the wavefunction LorentzPolarizationVector vect; // massless case if(mass.real()==ZERO) { vect = fact*vec.wave(); } // massive case else { complex dot = vec.wave().dot(pout)/mass2; vect = fact*(vec.wave()-(dot*pout)); } return VectorWaveFunction(pout,out,vect); } // off-shell scalar ScalarWaveFunction VVSSVertex::evaluate(Energy2 q2, int iopt,tcPDPtr out, const VectorWaveFunction & vec1, const VectorWaveFunction & vec2, const ScalarWaveFunction & sca, complex mass, complex width) { // outgoing momentum Lorentz5Momentum pout = vec1.momentum()+vec2.momentum()+sca.momentum(); // calculate the coupling setCoupling(q2,vec1.particle(),vec2.particle(),out,sca.particle()); // prefactor Energy2 p2 = pout.m2(); Complex fact = -norm()*sca.wave()*propagator(iopt,p2,out,mass,width); // evaluate the wavefunction Complex output = fact*vec1.wave().dot(vec2.wave()); return ScalarWaveFunction(pout,out,output); } diff --git a/Helicity/Vertex/Scalar/VVSSVertex.h b/Helicity/Vertex/Scalar/VVSSVertex.h --- a/Helicity/Vertex/Scalar/VVSSVertex.h +++ b/Helicity/Vertex/Scalar/VVSSVertex.h @@ -1,139 +1,139 @@ // -*- C++ -*- // // VVSSVertex.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_VVSSVertex_H #define ThePEG_VVSSVertex_H // // This is the declaration of the VVSSVertex class. // #include "ThePEG/Helicity/Vertex/AbstractVVSSVertex.h" #include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h" #include "VVSSVertex.fh" namespace ThePEG { namespace Helicity { /** \ingroup Helicity * * The VVSSVertex class is the implementation of the coupling of two * vectors and two scalars. It inherits from the AbstractVVSSVertex class for the * storage of the particles and implements the helicity calculations. * * All classes implementing the vertex should inherit from it and implement the * virtual setCoupling member. * * The form of the vertex is \f[icg^{\mu\nu}\epsilon_{1\mu}\epsilon_{2\nu}\f] * * @see AbstractVVSSVertex */ class VVSSVertex: public AbstractVVSSVertex { public: /** * Standard Init function used to initialize the interfaces. */ static void Init(); public: /** * Members to calculate the helicity amplitude expressions for vertices * and off-shell particles. */ //@{ /** * Evaluate the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param vec1 The wavefunction for the first vector. * @param vec2 The wavefunction for the second vector. * @param sca3 The wavefunction for the first scalar. * @param sca4 The wavefunction for the second scalar. */ Complex evaluate(Energy2 q2, const VectorWaveFunction & vec1, const VectorWaveFunction & vec2, const ScalarWaveFunction & sca3, const ScalarWaveFunction & sca4); /** * Evaluate the off-shell vector coming from the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param iopt Option of the shape of the Breit-Wigner for the off-shell vector. * @param out The ParticleData pointer for the off-shell vector. * @param vec2 The wavefunction for the second vector. * @param sca3 The wavefunction for the first scalar. * @param sca4 The wavefunction for the second scalar. * @param mass The mass of the off-shell particle if not taken from the ParticleData * object * @param width The width of the off-shell particle if not taken from the ParticleData * object */ VectorWaveFunction evaluate(Energy2 q2, int iopt,tcPDPtr out, const VectorWaveFunction & vec2, const ScalarWaveFunction & sca3, const ScalarWaveFunction & sca4, complex mass=-GeV, complex width=-GeV); /** * Evaluate the off-shell scalar coming from the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param iopt Option of the shape of the Breit-Wigner for the off-shell scalar. * @param out The ParticleData pointer for the off-shell scalar. * @param vec1 The wavefunction for the first vector. * @param vec2 The wavefunction for the second vector. * @param sca3 The wavefunction for the second scalar. * @param mass The mass of the off-shell particle if not taken from the ParticleData * object * @param width The width of the off-shell particle if not taken from the ParticleData * object */ ScalarWaveFunction evaluate(Energy2 q2, int iopt,tcPDPtr out, const VectorWaveFunction & vec1, const VectorWaveFunction & vec2, const ScalarWaveFunction & sca3, complex mass=-GeV, complex width=-GeV); //@} /** * Set coupling methods */ //@{ /** * Dummy for a three point interaction. */ virtual void setCoupling(Energy2,tcPDPtr,tcPDPtr,tcPDPtr) { assert(false); } /** * 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; //@} private: /** * Private and non-existent assignment operator. */ VVSSVertex & operator=(const VVSSVertex &) = delete; }; } } #endif /* ThePEG_VVSSVertex_H */ diff --git a/Helicity/Vertex/Scalar/VVSVertex.cc b/Helicity/Vertex/Scalar/VVSVertex.cc --- a/Helicity/Vertex/Scalar/VVSVertex.cc +++ b/Helicity/Vertex/Scalar/VVSVertex.cc @@ -1,91 +1,91 @@ // -*- C++ -*- // // VVSVertex.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the VVSVertex class. // #include "VVSVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Reference.h" using namespace ThePEG; using namespace Helicity; // The following static variable is needed for the type // description system in ThePEG. DescribeAbstractNoPIOClass describeThePEGVVSVertex("ThePEG::VVSVertex", "libThePEG.so"); void VVSVertex::Init() { static ClassDocumentation documentation ("The VVSVertex class is the implementation of the" "vector-vector-scalar vertex. All such vertices should inherit" "from it."); } // evaluate the vertex Complex VVSVertex::evaluate(Energy2 q2,const VectorWaveFunction & vec1, const VectorWaveFunction & vec2, const ScalarWaveFunction & sca) { // calculate the coupling setCoupling(q2,vec1.particle(),vec2.particle(),sca.particle()); // evaluate the vertex return Complex(0.,1.)*norm()*sca.wave()*vec1.wave().dot(vec2.wave()); } // evaluate an off-shell vector VectorWaveFunction VVSVertex::evaluate(Energy2 q2, int iopt,tcPDPtr out, const VectorWaveFunction & vec, const ScalarWaveFunction & sca, complex mass, complex width) { // outgoing momentum Lorentz5Momentum pout = vec.momentum()+sca.momentum(); // calculate the coupling setCoupling(q2,out,vec.particle(),sca.particle()); // prefactor Energy2 p2 = pout.m2(); if(mass.real() < ZERO) mass = out->mass(); complex mass2 = sqr(mass); Complex fact = norm()*sca.wave()*propagator(iopt,p2,out,mass,width); // evaluate the wavefunction LorentzPolarizationVector vect; // massless case if(mass.real()==ZERO) { vect = fact*vec.wave(); } // massive case else { complex dot = vec.wave().dot(pout)/mass2; vect = fact*(vec.wave()-dot*pout); } return VectorWaveFunction(pout,out,vect); } // off-shell scalar ScalarWaveFunction VVSVertex::evaluate(Energy2 q2, int iopt,tcPDPtr out, const VectorWaveFunction & vec1, const VectorWaveFunction & vec2, complex mass, complex width) { // outgoing momentum Lorentz5Momentum pout = vec1.momentum()+vec2.momentum(); // calculate the coupling setCoupling(q2,vec1.particle(),vec2.particle(),out); // prefactor Energy2 p2 = pout.m2(); Complex fact = -norm()*propagator(iopt,p2,out,mass,width); // evaluate the wavefunction Complex output = fact*vec1.wave().dot(vec2.wave()); return ScalarWaveFunction(pout,out,output); } diff --git a/Helicity/Vertex/Scalar/VVSVertex.h b/Helicity/Vertex/Scalar/VVSVertex.h --- a/Helicity/Vertex/Scalar/VVSVertex.h +++ b/Helicity/Vertex/Scalar/VVSVertex.h @@ -1,135 +1,135 @@ // -*- C++ -*- // // VVSVertex.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_VVSVertex_H #define ThePEG_VVSVertex_H // // This is the declaration of the VVSVertex class. #include "ThePEG/Helicity/Vertex/AbstractVVSVertex.h" #include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h" #include "VVSVertex.fh" namespace ThePEG { namespace Helicity { /** \ingroup Helicity * * The VVSVertex class is the implementation of the vector-vector-scalar. * It inherits from the AbstractVVSVertex class for the storage of the particles and * implements the helicity calculations. * * All interactions of this type should inherit from it and implement the virtual * setCoupling member. * * The form of the vertex is * \f[icg^{\mu\nu}\epsilon_{1\mu}\epsilon_{2\nu}\f] * * @see AbstractVVSVertex */ class VVSVertex: public AbstractVVSVertex { public: /** * Standard Init function used to initialize the interfaces. */ static void Init(); public: /** * Members to calculate the helicity amplitude expressions for vertices * and off-shell particles. */ //@{ /** * Evaluate the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param vec1 The wavefunction for the first vector. * @param vec2 The wavefunction for the second vector. * @param sca3 The wavefunction for the scalar. */ Complex evaluate(Energy2 q2,const VectorWaveFunction & vec1, const VectorWaveFunction & vec2, const ScalarWaveFunction & sca3); /** * Evaluate the off-shell vector coming from the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param iopt Option of the shape of the Breit-Wigner for the off-shell vector. * @param out The ParticleData pointer for the off-shell vector. * @param vec2 The wavefunction for the vector. * @param sca3 The wavefunction for the scalar. * @param mass The mass of the off-shell particle if not taken from the ParticleData * object * @param width The width of the off-shell particle if not taken from the ParticleData * object */ VectorWaveFunction evaluate(Energy2 q2,int iopt,tcPDPtr out, const VectorWaveFunction & vec2, const ScalarWaveFunction & sca3, complex mass=-GeV, complex width=-GeV); /** * Evaluate the off-shell scalar coming from the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param iopt Option of the shape of the Breit-Wigner for the off-shell scalar. * @param out The ParticleData pointer for the off-shell scalar. * @param vec1 The wavefunction for the first vector. * @param vec2 The wavefunction for the second vector. * @param mass The mass of the off-shell particle if not taken from the ParticleData * object * @param width The width of the off-shell particle if not taken from the ParticleData * object */ ScalarWaveFunction evaluate(Energy2 q2,int iopt, tcPDPtr out, const VectorWaveFunction & vec1, const VectorWaveFunction & vec2, complex mass=-GeV, complex width=-GeV); //@} /** * 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; /** * Dummy setCouplings for a four point interaction * This method is virtual and must be implemented in * classes inheriting from this. */ virtual void setCoupling(Energy2,tcPDPtr,tcPDPtr,tcPDPtr,tcPDPtr) { assert(false); } //@} private: /** * Private and non-existent assignment operator. */ VVSVertex & operator=(const VVSVertex &) = delete; }; } } #endif /* ThePEG_VVSVertex_H */ diff --git a/Helicity/Vertex/Scalar/VVVSVertex.cc b/Helicity/Vertex/Scalar/VVVSVertex.cc --- a/Helicity/Vertex/Scalar/VVVSVertex.cc +++ b/Helicity/Vertex/Scalar/VVVSVertex.cc @@ -1,197 +1,197 @@ // -*- C++ -*- // // VVVSVertex.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the VVVSVertex class. // #include "VVVSVertex.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Helicity/epsilon.h" using namespace ThePEG; using namespace Helicity; void VVVSVertex::persistentOutput(PersistentOStream & os) const { os << scalar_; } void VVVSVertex::persistentInput(PersistentIStream & is, int) { is >> scalar_; } DescribeAbstractClass describeAbstractVVVSVertex("Helicity::VVVSVertex","libThePEG.so"); void VVVSVertex::Init() { static ClassDocumentation documentation ("The VVVSVertex class implements the helicity amplitude" "calculations for the triple gauge boson scalar vertex. Any " "implementation of such a vertex should inherit from in and implement" " the virtual setCoupling member to calculate the coupling." "As this vertex is not present in renormalisabe theories we assume the form from Higgs" "effective theory, i.e. the triple vector vertex multiplied by the scale wavefunction."); } // evaluate the vertex Complex VVVSVertex::evaluate(Energy2 q2, const VectorWaveFunction & vec1, const VectorWaveFunction & vec2, const VectorWaveFunction & vec3, const ScalarWaveFunction & sca) { // calculate the coupling setCoupling(q2,vec1.particle(),vec2.particle(),vec3.particle(),sca.particle()); // the scalar form ofr the vertex if(scalar_) { complex alpha1(ZERO); // decide if we need to use special treatment to avoid gauge cancelations // first vector if(abs(vec1.t())!=0.) { if(abs(vec1.t())>0.1*max( max(abs(vec1.x()),abs(vec1.y())),abs(vec1.z()))) alpha1=vec1.e()/vec1.t(); } // second vector if(abs(vec2.t())!=0.) { if(abs(vec2.t())>0.1*max( max(abs(vec2.x()),abs(vec2.y())),abs(vec2.z()))) alpha1=vec2.e()/vec2.t(); } // third vector if(abs(vec3.t())!=0.) { if(abs(vec3.t())>0.1*max( max(abs(vec3.x()),abs(vec3.y())),abs(vec3.z()))) alpha1=vec3.e()/vec3.t(); } // dot products of the polarization vectors Complex dot12 = vec1.wave().dot(vec2.wave()); Complex dot13 = vec1.wave().dot(vec3.wave()); Complex dot23 = vec3.wave().dot(vec2.wave()); // dot products of polarization vectors and momentum complex dotp13 = vec3.wave().dot(LorentzPolarizationVectorE(vec1.momentum()) - alpha1 * vec1.wave()); complex dotp23 = vec3.wave().dot(LorentzPolarizationVectorE(vec2.momentum()) - alpha1 * vec2.wave()); complex dotp21 = vec1.wave().dot(LorentzPolarizationVectorE(vec2.momentum()) - alpha1 * vec2.wave()); complex dotp31 = vec1.wave().dot(LorentzPolarizationVectorE(vec3.momentum()) - alpha1 * vec3.wave()); complex dotp32 = vec2.wave().dot(LorentzPolarizationVectorE(vec3.momentum()) - alpha1 * vec3.wave()); complex dotp12 = vec2.wave().dot(LorentzPolarizationVectorE(vec1.momentum()) - alpha1 * vec1.wave()); // finally calculate the vertex return Complex(0.,1.)*norm()*UnitRemoval::InvE*sca.wave()* (dot12*(dotp13-dotp23)+dot23*(dotp21-dotp31)+dot13*(dotp32-dotp12)); } else { LorentzPolarizationVector eps = epsilon(vec1.wave(),vec2.wave(),vec3.wave()); complex dot = eps.dot(vec1.momentum()+vec2.momentum()+vec3.momentum()); return norm()*Complex(0.,1.) * sca.wave() * dot *UnitRemoval::InvE; } } // off-shell vector VectorWaveFunction VVVSVertex::evaluate(Energy2 q2,int iopt, tcPDPtr out, const VectorWaveFunction & vec1, const VectorWaveFunction & vec2, const ScalarWaveFunction & sca, complex mass, complex width) { // output momenta Lorentz5Momentum pout =vec1.momentum()+vec2.momentum()+sca.momentum(); // calculate the coupling setCoupling(q2,out,vec1.particle(),vec2.particle(),sca.particle()); // prefactor Energy2 p2 = pout.m2(); Complex fact = norm()*propagator(iopt,p2,out,mass,width); if(mass.real() < ZERO) mass = out->mass(); complex mass2 = sqr(mass); LorentzPolarizationVector vect; if(scalar_) { // dot products we need Complex dot12 = vec1.wave().dot(vec2.wave()); complex dota = vec1.wave().dot(pout+vec2.momentum()); complex dotb = vec2.wave().dot(pout+vec1.momentum()); // compute the polarization vector vect = UnitRemoval::InvE*fact*sca.wave()* (dot12*(vec1.momentum()-vec2.momentum())-dotb*vec1.wave()+dota*vec2.wave()); } else { vect = -UnitRemoval::InvE*fact*sca.wave()* epsilon(vec1.momentum()+vec2.momentum()+pout,vec1.wave(),vec2.wave()); } // scalar piece for massive case if(mass.real()!=ZERO) { complex dot = vect.dot(pout)/mass2; vect -= dot*pout; } return VectorWaveFunction(pout,out,vect); } // evaluate the off-shell scalar wavefunction ScalarWaveFunction VVVSVertex::evaluate(Energy2 q2,int iopt, tcPDPtr out, const VectorWaveFunction & vec1, const VectorWaveFunction & vec2, const VectorWaveFunction & vec3, complex mass, complex width) { // calculate the coupling setCoupling(q2,vec1.particle(),vec2.particle(),vec3.particle(),out); // outgoing momentum Lorentz5Momentum pout = vec1.momentum()+vec2.momentum()+vec3.momentum(); Complex fact(0.); // wavefunction Energy2 p2 = pout.m2(); if(scalar_) { // calculate the triple vector piece complex alpha1(ZERO); // decide if we need to use special treatment to avoid gauge cancelations // first vector if(abs(vec1.t())!=0.) { if(abs(vec1.t())>0.1*max( max(abs(vec1.x()),abs(vec1.y())),abs(vec1.z()))) alpha1=vec1.e()/vec1.t(); } // second vector if(abs(vec2.t())!=0.) { if(abs(vec2.t())>0.1*max( max(abs(vec2.x()),abs(vec2.y())),abs(vec2.z()))) alpha1=vec2.e()/vec2.t(); } // third vector if(abs(vec3.t())!=0.) { if(abs(vec3.t())>0.1*max( max(abs(vec3.x()),abs(vec3.y())),abs(vec3.z()))) alpha1=vec3.e()/vec3.t(); } // dot products of the polarization vectors Complex dot12 = vec1.wave().dot(vec2.wave()); Complex dot13 = vec1.wave().dot(vec3.wave()); Complex dot23 = vec3.wave().dot(vec2.wave()); // dot products of polarization vectors and momentum complex dotp13 = vec3.wave().dot(LorentzPolarizationVectorE(vec1.momentum()) - alpha1 * vec1.wave()); complex dotp23 = vec3.wave().dot(LorentzPolarizationVectorE(vec2.momentum()) - alpha1 * vec2.wave()); complex dotp21 = vec1.wave().dot(LorentzPolarizationVectorE(vec2.momentum()) - alpha1 * vec2.wave()); complex dotp31 = vec1.wave().dot(LorentzPolarizationVectorE(vec3.momentum()) - alpha1 * vec3.wave()); complex dotp32 = vec2.wave().dot(LorentzPolarizationVectorE(vec3.momentum()) - alpha1 * vec3.wave()); complex dotp12 = vec2.wave().dot(LorentzPolarizationVectorE(vec1.momentum()) - alpha1 * vec1.wave()); // finally calculate and return the wavefunction fact = -Complex(norm()*UnitRemoval::InvE*propagator(iopt,p2,out,mass,width)* (dot12*(dotp13-dotp23)+dot23*(dotp21-dotp31)+dot13*(dotp32-dotp12))); } else { LorentzPolarizationVector eps = epsilon(vec1.wave(),vec2.wave(),vec3.wave()); complex dot = eps.dot(pout); fact = Complex(norm()*UnitRemoval::InvE*propagator(iopt,p2,out,mass,width)*dot); } return ScalarWaveFunction(pout,out,fact); } diff --git a/Helicity/Vertex/Scalar/VVVSVertex.h b/Helicity/Vertex/Scalar/VVVSVertex.h --- a/Helicity/Vertex/Scalar/VVVSVertex.h +++ b/Helicity/Vertex/Scalar/VVVSVertex.h @@ -1,184 +1,184 @@ // -*- C++ -*- // // VVVSVertex.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_VVVSVertex_H #define ThePEG_VVVSVertex_H // // This is the declaration of the VVVSVertex class. #include "ThePEG/Helicity/Vertex/AbstractVVVSVertex.h" #include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h" #include "VVVSVertex.fh" namespace ThePEG { namespace Helicity{ /** \ingroup Helicity * * The VVVSVertex class is the base class for triple vector scalar vertices. * It inherits from the AbstractVVVSVertex class for the storage of the * particles allowed at the vertex. Given this vertice has dimenison * 5 the two forms possible for either a scalar or pseudoscalar particle. * * Classes which implement a specific vertex should inherit from this and * implement the virtual setCoupling member. * * The form of the vertex is * \f[ig\left[ (p_1-p_2)^\gamma g^{\alpha\beta } * +(p_2-p_3)^\alpha g^{\beta \gamma} * +(p_3-p_1)^\beta g^{\alpha\gamma} * \right]\epsilon_{1\alpha}\epsilon_{2\beta}\epsilon_{3\gamma}\f] * for a scalar particle and * \f[ig\epsilon^{\delta\alpha\beta\gamma}\epsilon_{1\alpha}\epsilon_{2\beta}\epsilon_{3\gamma} * (p_1+p_2+p_3)_\delta\f] * @see AbstractVVVSVertex */ class VVVSVertex: public AbstractVVVSVertex { public : /** * Default constructor */ VVVSVertex() : scalar_(true) {} 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: /** * Members to calculate the helicity amplitude expressions for vertices * and off-shell particles. */ //@{ /** * Evaluate the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param vec1 The wavefunction for the first vector. * @param vec2 The wavefunction for the second vector. * @param vec3 The wavefunction for the third vector. * @param sca The wavefunction for the scalar particle */ Complex evaluate(Energy2 q2, const VectorWaveFunction & vec1, const VectorWaveFunction & vec2, const VectorWaveFunction & vec3, const ScalarWaveFunction & sca); /** * Evaluate the off-shell vector coming from the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param iopt Option of the shape of the Breit-Wigner for the off-shell vector. * @param out The ParticleData pointer for the off-shell vector. * @param vec2 The wavefunction for the second vector. * @param vec3 The wavefunction for the third vector. * @param sca The wavefunction for the scalar particle * @param mass The mass of the off-shell particle if not taken from the ParticleData * object * @param width The width of the off-shell particle if not taken from the ParticleData * object */ VectorWaveFunction evaluate(Energy2 q2,int iopt, tcPDPtr out, const VectorWaveFunction & vec2, const VectorWaveFunction & vec3, const ScalarWaveFunction & sca, complex mass=-GeV, complex width=-GeV); /** * Evaluate the off-shell scalar coming from the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param iopt Option of the shape of the Breit-Wigner for the off-shell scalar. * @param out The ParticleData pointer for the off-shell scalar. * @param vec1 The wavefunction for the first vector. * @param vec2 The wavefunction for the second vector. * @param vec3 The wavefunction for the third vector. * @param mass The mass of the off-shell particle if not taken from the ParticleData * object * @param width The width of the off-shell particle if not taken from the ParticleData * object */ ScalarWaveFunction evaluate(Energy2 q2,int iopt, tcPDPtr out, const VectorWaveFunction & vec1, const VectorWaveFunction & vec2, const VectorWaveFunction & vec3, complex mass=-GeV, complex width=-GeV); //@} /** * 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 vector. * @param part2 The ParticleData pointer for the second vector. * @param part3 The ParticleData pointer for the third vector. * @param part4 The ParticleData pointer for the scalar */ virtual void setCoupling(Energy2 q2,tcPDPtr part1, tcPDPtr part2,tcPDPtr part3, tcPDPtr part4)=0; /** * Dummy setCouplings for a three point interaction * This method is virtual and must be implemented in * classes inheriting from this. */ virtual void setCoupling(Energy2,tcPDPtr,tcPDPtr,tcPDPtr) { assert(false); } //@} protected: /** * Set the type of the vertex */ void scalar(bool in) {scalar_=in;} private: /** * Private and non-existent assignment operator. */ VVVSVertex & operator=(const VVVSVertex &) = delete; /** * Whether or ont the vertex has a scalar or pseudoscalr particle */ bool scalar_; }; } } #endif /* ThePEG_VVVSVertex_H */ diff --git a/Helicity/Vertex/Tensor/FFTVertex.cc b/Helicity/Vertex/Tensor/FFTVertex.cc --- a/Helicity/Vertex/Tensor/FFTVertex.cc +++ b/Helicity/Vertex/Tensor/FFTVertex.cc @@ -1,296 +1,296 @@ // -*- C++ -*- // // FFTVertex.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the FFTVertex class. // #include "FFTVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" using namespace ThePEG; using namespace Helicity; // Definition of the static class description member // The following static variable is needed for the type // description system in ThePEG. DescribeAbstractNoPIOClass describeThePEGFFTVertex("ThePEG::FFTVertex", "libThePEG.so"); void FFTVertex::Init() { static ClassDocumentation documentation ("The FFTVertex class is the implementation of" "the fermion-antifermion tensor vertices for helicity " "amplitude calculations. All such vertices should inherit" "from it."); } // function to evaluate the vertex Complex FFTVertex::evaluate(Energy2 q2,const SpinorWaveFunction & sp, const SpinorBarWaveFunction & sbar, const TensorWaveFunction & ten) { // set the couplings setCoupling(q2,sp.particle(),sbar.particle(),ten.particle()); // vector current LorentzPolarizationVector as = sp.wave().vectorCurrent(sbar.wave()); // momentum difference Lorentz5Momentum vdiff = sp.momentum()-sbar.momentum(); // first term LorentzPolarizationVectorE test = ten.wave().postDot(vdiff) + ten.wave().preDot(vdiff); complex term1 = as.dot(test); // trace of polarization tensor Complex trace = ten.wave().trace(); // dot products with polarization tensor // product of spinors Complex ffbar= sp.wave().scalar(sbar.wave()); // put everything together return -0.125*Complex(0.,1.)*norm()*UnitRemoval::InvE* ( term1 + 4.0*(sp.particle()->mass())*trace*ffbar ); } // member function to evaluate an off-shell spinor SpinorWaveFunction FFTVertex::evaluate(Energy2 q2, int iopt, tcPDPtr out, const SpinorWaveFunction & sp, const TensorWaveFunction & ten, complex mass, complex width) { // momentum of the outgoing fermion Lorentz5Momentum pout = ten.momentum()+sp.momentum(); // set the couplings setCoupling(q2,sp.particle(),out,ten.particle()); Complex ii(0.,1.); // trace of the tensor Complex trace = ten.tt()-ten.xx()-ten.yy()-ten.zz(); // mass of the fermion if(mass.real() < ZERO) mass = out->mass(); // overall factor Energy2 p2 = pout.m2(); Complex fact = 0.125*norm()*propagator(iopt,p2,out,mass,width); // compute the vector we need complex dot[4]; for(int ix=0;ix<4;++ix) { // evaluate the products we need dot[ix] =(ten(ix,3)+ten(3,ix))*(pout.e()+sp.e()); dot[ix]-=(ten(ix,0)+ten(0,ix))*(pout.x()+sp.px()); dot[ix]-=(ten(ix,1)+ten(1,ix))*(pout.y()+sp.py()); dot[ix]-=(ten(ix,2)+ten(2,ix))*(pout.z()+sp.pz()); } LorentzVector > vec(dot[0],dot[1],dot[2],dot[3]); vec -= 2.0 * trace * (pout + sp.momentum()); // combinations of the vector complex a1p2=vec.x()+ii*vec.y(); complex a1m2=vec.x()-ii*vec.y(); LorentzSpinor spt =sp .wave(); // now compute the first stage of the spinor wavefunction complex a0p3=vec.t()+vec.z(); complex a0m3=vec.t()-vec.z(); vec.setX(a0m3*spt.s3()-a1m2*spt.s4()); vec.setY(a0p3*spt.s4()-a1p2*spt.s3()); vec.setZ(a0p3*spt.s1()+a1m2*spt.s2()); vec.setT(a0m3*spt.s2()+a1p2*spt.s1()); if(mass.real()!=ZERO) { complex dot = 4.*mass*trace; vec.setX(vec.x() + dot*spt.s1()); vec.setY(vec.y() + dot*spt.s2()); vec.setZ(vec.z() + dot*spt.s3()); vec.setT(vec.t() + dot*spt.s4()); } // combinations of the momentum complex p1p2=pout.x()+ii*pout.y(); complex p1m2=pout.x()-ii*pout.y(); // finally put everything together as the spinor Complex ferm[4]; complex p0p3=pout.e() + pout.z(); complex p0m3=pout.e() - pout.z(); ferm[0] = Complex(UnitRemoval::InvE2 * fact*( p0m3*vec.z()-p1m2*vec.t())); ferm[1] = Complex(UnitRemoval::InvE2 * fact*(-p1p2*vec.z()+p0p3*vec.t())); ferm[2] = Complex(UnitRemoval::InvE2 * fact*( p0p3*vec.x()+p1m2*vec.y())); ferm[3] = Complex(UnitRemoval::InvE2 * fact*( p1p2*vec.x()+p0m3*vec.y())); if(mass.real()!=ZERO) { ferm[0] += Complex(UnitRemoval::InvE2 * fact*(mass*vec.x())); ferm[1] += Complex(UnitRemoval::InvE2 * fact*(mass*vec.y())); ferm[2] += Complex(UnitRemoval::InvE2 * fact*(mass*vec.z())); ferm[3] += Complex(UnitRemoval::InvE2 * fact*(mass*vec.t())); } // return the wavefunction return SpinorWaveFunction(pout,out,ferm[0],ferm[1],ferm[2],ferm[3]); } // member function to evaluate an off-shell spinor bar SpinorBarWaveFunction FFTVertex::evaluate(Energy2 q2, int iopt, tcPDPtr out, const SpinorBarWaveFunction & sbar, const TensorWaveFunction & ten, complex mass, complex width) { // momentum of the outgoing fermion Lorentz5Momentum pout = ten.momentum()+sbar.momentum(); // set the couplings setCoupling(q2,out,sbar.particle(),ten.particle()); Complex ii(0.,1.); // trace of the tensor Complex trace = ten.tt()-ten.xx()-ten.yy()-ten.zz(); // mass of the fermion if(mass.real() < ZERO) mass = out->mass(); // overall factor Energy2 p2 = pout.m2(); Complex fact=0.125*norm()*propagator(iopt,p2,out,mass,width); // vector complex dot[4]; for(int ix=0;ix<4;++ix) { // evaluate the products we need dot[ix] =-(ten(ix,3)+ten(3,ix))*(pout.e()+sbar.e()); dot[ix]+= (ten(ix,0)+ten(0,ix))*(pout.x()+sbar.px()); dot[ix]+= (ten(ix,1)+ten(1,ix))*(pout.y()+sbar.py()); dot[ix]+= (ten(ix,2)+ten(2,ix))*(pout.z()+sbar.pz()); } LorentzVector > vec(dot[0],dot[1],dot[2],dot[3]); vec += 2.*trace*(pout+sbar.momentum()); // combinations of the vector complex a1p2=vec.x()+ii*vec.y(); complex a1m2=vec.x()-ii*vec.y(); LorentzSpinorBar sbart=sbar.wave(); // now compute the first stage of the spinorbar wavefunction complex a0p3=vec.t()+vec.z(); complex a0m3=vec.t()-vec.z(); vec.setX(a0p3*sbart.s3()+a1p2*sbart.s4()); vec.setY(a0m3*sbart.s4()+a1m2*sbart.s3()); vec.setZ(a0m3*sbart.s1()-a1p2*sbart.s2()); vec.setT(a0p3*sbart.s2()-a1m2*sbart.s1()); if(mass.real()!=ZERO) { complex dot = 4.*mass*trace; vec.setX(vec.x() + dot*sbart.s1()); vec.setY(vec.y() + dot*sbart.s2()); vec.setZ(vec.z() + dot*sbart.s3()); vec.setT(vec.t() + dot*sbart.s4()); } // combinations of the momentum complex p1p2=pout.x()+ii*pout.y(); complex p1m2=pout.x()-ii*pout.y(); // finally put everything together as the spinor Complex ferm[4]; complex p0p3=pout.e() + pout.z(); complex p0m3=pout.e() - pout.z(); ferm[0] = Complex(UnitRemoval::InvE2 * fact*(-p0p3*vec.z()-p1p2*vec.t())); ferm[1] = Complex(UnitRemoval::InvE2 * fact*(-p1m2*vec.z()-p0m3*vec.t())); ferm[2] = Complex(UnitRemoval::InvE2 * fact*(-p0m3*vec.x()+p1p2*vec.y())); ferm[3] = Complex(UnitRemoval::InvE2 * fact*( p1m2*vec.x()-p0p3*vec.y())); if(mass.real()!=ZERO) { ferm[0] += Complex(UnitRemoval::InvE2 * fact*mass*vec.x()); ferm[1] += Complex(UnitRemoval::InvE2 * fact*mass*vec.y()); ferm[2] += Complex(UnitRemoval::InvE2 * fact*mass*vec.z()); ferm[3] += Complex(UnitRemoval::InvE2 * fact*mass*vec.t()); } // return the wavefunction return SpinorBarWaveFunction(pout,out,ferm[0],ferm[1],ferm[2],ferm[3]); } // member function to evaluate an off-shell tensor TensorWaveFunction FFTVertex::evaluate(Energy2 q2, int iopt, tcPDPtr out, const SpinorWaveFunction & sp, const SpinorBarWaveFunction & sbar, complex mass, complex width) { // calculating the couplings setCoupling(q2,sp.particle(),sbar.particle(),out); Complex ii(0.,1.); // momentum of the outgoing tensor Lorentz5Momentum pout = sp.momentum()+sbar.momentum(); // calculate the prefactor Energy2 p2 = pout.m2(); Complex fact = 0.0625*norm()*propagator(iopt,p2,out,mass,width); if(mass.real() < ZERO) mass = out->mass(); complex mass2 = sqr(mass); // spinor vector Complex aspin[4]; LorentzSpinorBar sbart=sbar.wave(); LorentzSpinor spt =sp .wave(); aspin[3] = sbart.s1()*spt.s3()+sbart.s2()*spt.s4() +sbart.s3()*spt.s1()+sbart.s4()*spt.s2(); // spatial components are the same in both conventions aspin[0] = +sbart.s1()*spt.s4()+sbart.s2()*spt.s3() -sbart.s3()*spt.s2()-sbart.s4()*spt.s1(); aspin[1] = ii*(-sbart.s1()*spt.s4()+sbart.s2()*spt.s3() +sbart.s3()*spt.s2()-sbart.s4()*spt.s1()); aspin[2] = +sbart.s1()*spt.s3()-sbart.s2()*spt.s4() -sbart.s3()*spt.s1()+sbart.s4()*spt.s2(); // mass dependent term Complex ffbar; if(sp.particle()->mass()!=ZERO) { ffbar = Complex(UnitRemoval::InvE * (sp.particle()->mass())* (sp.s1()*sbar.s1()+sp.s2()*sbar.s2()+sp.s3()*sbar.s3()+sp.s4()*sbar.s4())); } else { ffbar = 0.; } // dot products for the calculation complex dotka = +aspin[3]*pout.e()-aspin[0]*pout.x() -aspin[1]*pout.y()-aspin[2]*pout.z(); complex dot12a = +aspin[3]*(sp.e() -sbar.e() )-aspin[0]*(sp.px()-sbar.px()) -aspin[1]*(sp.py()-sbar.py())-aspin[2]*(sp.pz()-sbar.pz()); complex diff=sp.m2()-sbar.m2(); complex dotkam=dotka/mass2; Complex diffm =diff/mass2; Complex p2m = p2/mass2; // construct the vectors for the first two terms Complex veca[4],vecb[4]; veca[0] = aspin[0]-UnitRemoval::InvE2*dotka*pout.x(); vecb[0] = Complex(UnitRemoval::InvE*(sp.px()-sbar.px()-diffm*pout.x())); veca[1] = aspin[1]-UnitRemoval::InvE2*dotka*pout.y(); vecb[1] = Complex(UnitRemoval::InvE*(sp.py()-sbar.py()-diffm*pout.y())); veca[2] = aspin[2]-UnitRemoval::InvE2*dotka*pout.z(); vecb[2] = Complex(UnitRemoval::InvE*(sp.pz()-sbar.pz()-diffm*pout.z())); veca[3] = aspin[3]-UnitRemoval::InvE2*dotka*pout.e(); vecb[3] = Complex(UnitRemoval::InvE*(sp.e()-sbar.e()-diffm*pout.e())); // coefficients fr hte second two terms Complex temp = UnitRemoval::InvE*(p2m*dot12a-dotkam*diff); Complex coeff1 = -4./3.*(2.*ffbar*(1.-p2m) + temp); temp = Complex(UnitRemoval::InvE*(-3.*dot12a+2.*p2m*dot12a+diffm*dotka)); Complex coeff2 = -4./3./mass2*( 4.*ffbar*(1.-p2m) + temp)*UnitRemoval::E2; // construct the tensor Complex ten[4][4]; const complex pout_tmp[4] = {pout.x(), pout.y(), pout.z(), pout.e()}; for(int ix=0;ix<4;++ix) { for(int iy=0;iy<4;++iy) { Complex temp = coeff2*pout_tmp[ix]*pout_tmp[iy]*UnitRemoval::InvE2; ten[ix][iy] = 2.*(veca[ix]*vecb[iy]+veca[iy]*vecb[ix]) + temp; } } ten[0][0]=ten[0][0]-coeff1; ten[1][1]=ten[1][1]-coeff1; ten[2][2]=ten[2][2]-coeff1; ten[3][3]=ten[3][3]+coeff1; // multiply by final prefactor for(int ix=0;ix<4;++ix) { for(int iy=0;iy<4;++iy) { ten[ix][iy] = fact*ten[ix][iy]; } } // return the wavefunction return TensorWaveFunction(pout,out, ten[0][0],ten[0][1],ten[0][2],ten[0][3], ten[1][0],ten[1][1],ten[1][2],ten[1][3], ten[2][0],ten[2][1],ten[2][2],ten[2][3], ten[3][0],ten[3][1],ten[3][2],ten[3][3]); } diff --git a/Helicity/Vertex/Tensor/FFTVertex.h b/Helicity/Vertex/Tensor/FFTVertex.h --- a/Helicity/Vertex/Tensor/FFTVertex.h +++ b/Helicity/Vertex/Tensor/FFTVertex.h @@ -1,157 +1,157 @@ // -*- C++ -*- // // FFTVertex.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_FFTVertex_H #define ThePEG_FFTVertex_H // // This is the declaration of the FFTVertex class. // #include "ThePEG/Helicity/Vertex/AbstractFFTVertex.h" #include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/TensorWaveFunction.h" #include "FFTVertex.fh" namespace ThePEG { namespace Helicity { /** \ingroup Helicity * * The FFTVertex class is the implementation of the fermion-fermion-tensor * vertex. It inherits from the AbstractFFTVertex class for the storage of the particles * interacting at the vertex and implements the helicity amplitude calculations. * * All implementations of this vertex should inherit from it and implement the * virtual setCoupling member. * * The vertex has the form * \f[-\frac{i\kappa}8\bar{f_2}\left[ * \gamma_\mu(k_1-k_2)_\nu+\gamma_\nu(k_1-k_2)_\mu * -2g_{\mu\nu}(k\!\!\!\!\!\not\,\,\,_1-k\!\!\!\!\!\not\,\,\,_2)+4g_{\mu\nu}m_{f} * \right]f_1\epsilon^{\mu\nu}_3\f] * * @see AbstractFFTVertex */ class FFTVertex: public AbstractFFTVertex { public: /** * Standard Init function used to initialize the interfaces. */ static void Init(); public: /** * Members to calculate the helicity amplitude expressions for vertices * and off-shell particles. */ //@{ /** * Evalulate the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param sp1 The wavefunction for the ferimon. * @param sbar2 The wavefunction for the antifermion. * @param ten3 The wavefunction for the tensor. */ Complex evaluate(Energy2 q2,const SpinorWaveFunction & sp1, const SpinorBarWaveFunction & sbar2, const TensorWaveFunction & ten3); /** * Evaluate the off-shell tensor coming from the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param iopt Option of the shape of the Breit-Wigner for the off-shell tensor. * @param out The ParticleData pointer for the off-shell tensor. * @param sp1 The wavefunction for the ferimon. * @param sbar2 The wavefunction for the antifermion. * @param mass The mass of the off-shell particle if not taken from the ParticleData * object * @param width The width of the off-shell particle if not taken from the ParticleData * object */ TensorWaveFunction evaluate(Energy2 q2, int iopt,tcPDPtr out, const SpinorWaveFunction & sp1, const SpinorBarWaveFunction & sbar2, complex mass=-GeV, complex width=-GeV); /** * Evaluate the off-shell spinor coming from the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param iopt Option of the shape of the Breit-Wigner for the off-shell spinor. * @param out The ParticleData pointer for the off-shell spinor. * @param sp1 The wavefunction for the ferimon. * @param ten3 The wavefunction for the tensor. * @param mass The mass of the off-shell particle if not taken from the ParticleData * object * @param width The width of the off-shell particle if not taken from the ParticleData * object */ SpinorWaveFunction evaluate(Energy2 q2,int iopt,tcPDPtr out, const SpinorWaveFunction & sp1, const TensorWaveFunction & ten3, complex mass=-GeV, complex width=-GeV); /** * Evaluate the off-shell barred spinor coming from the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param iopt Option of the shape of the Breit-Wigner for the off-shell barred spinor. * @param out The ParticleData pointer for the off-shell barred spinor. * @param sbar2 The wavefunction for the antifermion. * @param ten3 The wavefunction for the tensor. * @param mass The mass of the off-shell particle if not taken from the ParticleData * object * @param width The width of the off-shell particle if not taken from the ParticleData * object */ SpinorBarWaveFunction evaluate(Energy2 q2,int iopt, tcPDPtr out, const SpinorBarWaveFunction & sbar2, const TensorWaveFunction& ten3, complex mass=-GeV, complex width=-GeV); //@} /** * 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; /** * Dummy setCouplings for a four point interaction * This method is virtual and must be implemented in * classes inheriting from this. */ virtual void setCoupling(Energy2,tcPDPtr,tcPDPtr,tcPDPtr,tcPDPtr) { assert(false); } //@} private: /** * Private and non-existent assignment operator. */ FFTVertex & operator=(const FFTVertex &) = delete; }; } } #endif /* ThePEG_FFTVertex_H */ diff --git a/Helicity/Vertex/Tensor/FFVTVertex.cc b/Helicity/Vertex/Tensor/FFVTVertex.cc --- a/Helicity/Vertex/Tensor/FFVTVertex.cc +++ b/Helicity/Vertex/Tensor/FFVTVertex.cc @@ -1,58 +1,58 @@ // -*- C++ -*- // // FFVTVertex.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the FFVTVertex class. // #include "FFVTVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" using namespace ThePEG; using namespace Helicity; // The following static variable is needed for the type // description system in ThePEG. DescribeAbstractNoPIOClass describeThePEGFFVTVertex("ThePEG::FFVTVertex", "libThePEG.so"); void FFVTVertex::Init() { static ClassDocumentation documentation ("The FFVTVertex class is the implementation of the" "helicity amplitude calculation of the fermion-antifermion-vector-tensor" "vertex. All such vertices should inherit from it."); } // function to evaluate the vertex Complex FFVTVertex::evaluate(Energy2 q2, const SpinorWaveFunction & sp, const SpinorBarWaveFunction & sbar, const VectorWaveFunction & vec, const TensorWaveFunction & ten) { // set the couplings setCoupling(q2,sp.particle(),sbar.particle(), vec.particle(),ten.particle()); Complex ii(0.,1.); // vector current LorentzPolarizationVector as = left_ *sp.wave(). leftCurrent(sbar.wave()) + right_*sp.wave().rightCurrent(sbar.wave()); // trace of the tensor Complex trace = ten.wave().trace(); // dot product Complex dotav = as.dot(vec.wave()); // product with tensor and current LorentzPolarizationVector preDot = ten.wave(). preDot(as); LorentzPolarizationVector postDot = ten.wave().postDot(as); Complex tenav = preDot.dot(vec.wave())+postDot.dot(vec.wave()); // return the vertex return ii*0.25*norm()*(tenav-2.*trace*dotav); } diff --git a/Helicity/Vertex/Tensor/FFVTVertex.h b/Helicity/Vertex/Tensor/FFVTVertex.h --- a/Helicity/Vertex/Tensor/FFVTVertex.h +++ b/Helicity/Vertex/Tensor/FFVTVertex.h @@ -1,150 +1,150 @@ // -*- C++ -*- // // FFVTVertex.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_FFVTVertex_H #define ThePEG_FFVTVertex_H // // This is the declaration of the FFVTVertex class. // #include "ThePEG/Helicity/Vertex/AbstractFFVTVertex.h" #include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/TensorWaveFunction.h" #include "FFVTVertex.fh" namespace ThePEG { namespace Helicity { /** \ingroup Helicity * * The FFVTVertex class is the implementation of the * fermion-fermion--vector-tensor vertex. * It inherits from the AbstractFFVTVertex class for the storage of the particles * interacting at the vertex and implements the helicity amplitude calculations. * * All implementations of this vertex should inherit from it and implement the * virtual setCoupling member. * * The form of the vertex is * \f[\frac{ig\kappa}4t^a_{nm}\bar{f_2}(C_{\mu\nu,\rho\sigma}-g_{\mu\nu}g_{\rho\sigma}) * \gamma^\sigma f_1\epsilon_{3\rho}\epsilon_4^{\mu\nu}\f] * where * -\f$C_{\mu\nu,\rho\sigma}=g_{\mu\rho}g_{\nu\sigma}+g_{\mu\sigma}g_{\nu\rho} * -g_{\mu\nu}g_{\rho\sigma}\f$. * * @see AbstractFFVTVertex */ class FFVTVertex: public AbstractFFVTVertex { public: /** * Default constructor */ FFVTVertex() : left_(1.), right_(1.) {} /** * Standard Init function used to initialize the interfaces. */ static void Init(); public: /** * Members to calculate the helicity amplitude expressions for vertices * and off-shell particles. */ //@{ /** * Evalulate the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param sp1 The wavefunction for the ferimon. * @param sbar2 The wavefunction for the antifermion. * @param vec3 The wavefunction for the vector. * @param ten4 The wavefunction for the tensor. */ Complex evaluate(Energy2 q2,const SpinorWaveFunction & sp1, const SpinorBarWaveFunction & sbar2, const VectorWaveFunction & vec3, const TensorWaveFunction & ten4); //@} /** * Set coupling methods */ //@{ /** * Dummy for a three point interaction. */ virtual void setCoupling(Energy2,tcPDPtr,tcPDPtr,tcPDPtr) { assert(false); } /** * 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; //@} /** * Left and right couplings */ //@{ /** * Get left */ Complex left() const {return left_;} /** * Set left */ void left(Complex in) {left_ = in;} /** * Get right */ Complex right() const {return right_;} /** * Set right */ void right(Complex in) {right_ = in;} //@} private: /** * Private and non-existent assignment operator. */ FFVTVertex & operator=(const FFVTVertex &) = delete; private: /** * Left coupling */ Complex left_; /** * Right coupling */ Complex right_; }; } } #endif /* ThePEG_FFVTVertex_H */ diff --git a/Helicity/Vertex/Tensor/SSTVertex.cc b/Helicity/Vertex/Tensor/SSTVertex.cc --- a/Helicity/Vertex/Tensor/SSTVertex.cc +++ b/Helicity/Vertex/Tensor/SSTVertex.cc @@ -1,161 +1,161 @@ // -*- C++ -*- // // SSTVertex.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the SSTVertex class. // #include "SSTVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" using namespace ThePEG; using namespace Helicity; // The following static variable is needed for the type // description system in ThePEG. DescribeAbstractNoPIOClass describeThePEGSSTVertex("ThePEG::SSTVertex", "libThePEG.so"); void SSTVertex::Init() { static ClassDocumentation documentation ("The SSTVertex class is the implementation of the " "helicity amplitude calculation for the scalar-scalar-tensor vertex" ", all such vertices should inherit from it"); } // evaluate the vertex Complex SSTVertex::evaluate(Energy2 q2, const ScalarWaveFunction & sca1, const ScalarWaveFunction & sca2, const TensorWaveFunction & ten) { // obtain the coupling setCoupling(q2,sca1.particle(),sca2.particle(),ten.particle()); Complex ii(0.,1.); // evaluate the trace of the tensor Complex trace = ten.tt()-ten.xx()-ten.yy()-ten.zz(); // dot product of the two momenta Energy2 dot = sca1.momentum()*sca2.momentum(); Energy mass = sca1.particle()->mass(); // second term complex second = +2.*ten.tt()*sca1.e()*sca2.e() +2.*ten.xx()*sca1.px()*sca2.px() +2.*ten.yy()*sca1.py()*sca2.py()+2.*ten.zz()*sca1.pz()*sca2.pz() -(ten.tx()+ten.xt())*(sca1.e()*sca2.px() +sca1.px()*sca2.e()) -(ten.ty()+ten.yt())*(sca1.e()*sca2.py() +sca1.py()*sca2.e()) -(ten.tz()+ten.zt())*(sca1.e()*sca2.pz() +sca1.pz()*sca2.e()) +(ten.xy()+ten.yx())*(sca1.py()*sca2.px()+sca1.px()*sca2.py()) +(ten.xz()+ten.zx())*(sca1.pz()*sca2.px()+sca1.px()*sca2.pz()) +(ten.yz()+ten.zy())*(sca1.pz()*sca2.py()+sca1.py()*sca2.pz()); // return the answer return -0.5*ii*norm()*UnitRemoval::InvE2* (trace*(mass*mass-dot)+second)*sca1.wave()*sca2.wave(); } // off-shell tensor TensorWaveFunction SSTVertex::evaluate(Energy2 q2, int iopt, tcPDPtr out, const ScalarWaveFunction & sca1, const ScalarWaveFunction & sca2, complex mass, complex width) { // obtain the coupling setCoupling(q2,sca1.particle(),sca2.particle(),out); // array for the tensor Complex ten[4][4]; // calculate the outgoing momentum Lorentz5Momentum pout = sca1.momentum()+sca2.momentum(); // prefactor if(mass.real() < ZERO) mass = out->mass(); complex mass2 = sqr(mass); Energy2 p2 = pout.m2(); Complex fact = 0.25*norm()*sca1.wave()*sca2.wave()* propagator(iopt,p2,out,mass,width); // dot products we need Energy2 dot12 = sca1.momentum()*sca2.momentum(); Energy2 dot1 = sca1.momentum()*pout; Energy2 dot2 = pout*sca2.momentum(); // the vectors that we need for the tensor LorentzPolarizationVectorE vec1,vec2; Complex a,b; Energy2 mphi2 = sqr(sca1.particle()->mass()); // massive case if(mass.real()!=ZERO) { Complex norm1=dot1/mass2; Complex norm2=dot2/mass2; a = Complex(UnitRemoval::InvE2 * ((mphi2+dot12)*(Complex(2.*p2/mass2)-5.) +4.*(dot12-dot1*dot2/mass2)))/3.; b = -(-(mphi2+dot12)*(2.+p2/mass2)+4.*(dot12-dot1*(dot2/mass2)))/3./mass2; vec1 = LorentzPolarizationVectorE(sca1.momentum()) - LorentzPolarizationVectorE(norm1 * pout); vec2 = LorentzPolarizationVectorE(sca2.momentum()) - LorentzPolarizationVectorE(norm2 * pout); } // massless case else { a = UnitRemoval::InvE2 * (-5.*(mphi2+dot12)+4.*dot12)/3.; b = 0.; vec1 = sca1.momentum(); vec2 = sca2.momentum(); } // calculate the wavefunction complex vec1_tmp[4] = {vec1.x(), vec1.y(), vec1.z(), vec1.t()}; complex vec2_tmp[4] = {vec2.x(), vec2.y(), vec2.z(), vec2.t()}; complex pout_tmp[4] = {pout.x(), pout.y(), pout.z(), pout.t()}; for(int ix=0;ix<4;++ix) { for(int iy=0;iy<4;++iy) { complex temp = -2.*( vec1_tmp[ix]*vec2_tmp[iy] + vec1_tmp[ix]*vec2_tmp[iy]) -b*pout_tmp[ix]*pout_tmp[iy]; ten[ix][iy]= Complex(UnitRemoval::InvE2 * temp); } } ten[3][3]=ten[3][3]-a; for(int ix=0;ix<3;++ix){ten[ix][ix]=ten[ix][ix]+a;} // prefactor for(int ix=0;ix<4;++ix){for(int iy=0;iy<4;++iy){ten[ix][iy]=fact*ten[ix][iy];}} // return the wavefunction return TensorWaveFunction(pout,out, ten[0][0],ten[0][1],ten[0][2],ten[0][3], ten[1][0],ten[1][1],ten[1][2],ten[1][3], ten[2][0],ten[2][1],ten[2][2],ten[2][3], ten[3][0],ten[3][1],ten[3][2],ten[3][3]); } // off-shell scalar ScalarWaveFunction SSTVertex::evaluate(Energy2 q2,int iopt, tcPDPtr out, const ScalarWaveFunction & sca, const TensorWaveFunction & ten, complex mass, complex width) { // obtain the coupling setCoupling(q2,sca.particle(),out,ten.particle()); // calculate the outgoing momentum Lorentz5Momentum pout = sca.momentum()+ten.momentum(); // prefactors if(mass.real() < ZERO) mass = out->mass(); complex mass2 = sqr(mass); Energy2 p2 = pout.m2(); Complex fact = 0.5*norm()*sca.wave()*propagator(iopt,p2,out,mass,width); // trace of the tensor Complex trace1 = ten.tt()-ten.xx()-ten.yy()-ten.zz(); // dot product of the two momenta Energy2 dot = sca.momentum()*pout; // first term complex trace = trace1*(mass2-dot); // second term complex second = +2.*ten.tt()*sca.e()*pout.e() +2.*ten.xx()*sca.px()*pout.x() +2.*ten.yy()*sca.py()*pout.y()+2.*ten.zz()*sca.pz()*pout.z() -(ten.tx()+ten.xt())*( sca.e()*pout.x()+sca.px()*pout.e()) -(ten.ty()+ten.yt())*( sca.e()*pout.y()+sca.py()*pout.e()) -(ten.tz()+ten.zt())*( sca.e()*pout.z()+sca.pz()*pout.e()) +(ten.xy()+ten.yx())*(sca.py()*pout.x()+sca.px()*pout.y()) +(ten.xz()+ten.zx())*(sca.pz()*pout.x()+sca.px()*pout.z()) +(ten.yz()+ten.zy())*(sca.py()*pout.z()+sca.pz()*pout.y()); // put it all together second = fact*(trace+second); Complex result = second * UnitRemoval::InvE2; return ScalarWaveFunction(pout,out,result); } diff --git a/Helicity/Vertex/Tensor/SSTVertex.h b/Helicity/Vertex/Tensor/SSTVertex.h --- a/Helicity/Vertex/Tensor/SSTVertex.h +++ b/Helicity/Vertex/Tensor/SSTVertex.h @@ -1,140 +1,140 @@ // -*- C++ -*- // // SSTVertex.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_SSTVertex_H #define ThePEG_SSTVertex_H // // This is the declaration of the SSTVertex class. // #include "ThePEG/Helicity/Vertex/AbstractSSTVertex.h" #include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/TensorWaveFunction.h" #include "SSTVertex.fh" namespace ThePEG { namespace Helicity { /** \ingroup Helicity * * The VVTVertexclass is the implementation of the * scalar-scalar-tensor vertex. * It inherits from the AbstractSSTVertex class for the storage of the particles * interacting at the vertex and implements the helicity amplitude calculations. * * All implementations of this vertex should inherit from it and implement the * virtual setCoupling member. * * The form of the vertex is * \f[ * -\frac{i\kappa}2\left[m^2_Sg_{\mu\nu}-k_{1\mu}k_{2\nu}-k_{1\nu}k_{2\mu} * +g_{\mu\nu}k_1\cdot k_2\right]\epsilon^{\mu\nu}_3\phi_1\phi_2 * * \f] * * @see AbstractSSTVertex */ class SSTVertex: public AbstractSSTVertex { public: /** * Standard Init function used to initialize the interfaces. */ static void Init(); public: /** * Members to calculate the helicity amplitude expressions for vertices * and off-shell particles. */ //@{ /** * Evalulate the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param sca1 The wavefunction for the first scalar. * @param sca2 The wavefunction for the second scalar * @param ten3 The wavefunction for the tensor. */ Complex evaluate(Energy2 q2, const ScalarWaveFunction & sca1, const ScalarWaveFunction & sca2, const TensorWaveFunction & ten3); /** * Evaluate the off-shell scalar coming from the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param iopt Option of the shape of the Breit-Wigner for the off-shell scalar. * @param out The ParticleData pointer for the off-shell scalar. * @param sca1 The wavefunction for the first scalar. * @param ten3 The wavefunction for the tensor. * @param mass The mass of the off-shell particle if not taken from the ParticleData * object * @param width The width of the off-shell particle if not taken from the ParticleData * object */ ScalarWaveFunction evaluate(Energy2 q2,int iopt,tcPDPtr out, const ScalarWaveFunction & sca1, const TensorWaveFunction & ten3, complex mass=-GeV, complex width=-GeV); /** * Evaluate the off-shell tensor coming from the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param iopt Option of the shape of the Breit-Wigner for the off-shell tensor. * @param out The ParticleData pointer for the off-shell tensor. * @param sca1 The wavefunction for the first scalar. * @param sca2 The wavefunction for the second scalar. * @param mass The mass of the off-shell particle if not taken from the ParticleData * object * @param width The width of the off-shell particle if not taken from the ParticleData * object */ TensorWaveFunction evaluate(Energy2 q2,int iopt,tcPDPtr out, const ScalarWaveFunction & sca1, const ScalarWaveFunction & sca2, complex mass=-GeV, complex width=-GeV); //@} /** * 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; /** * Dummy setCouplings for a four point interaction * This method is virtual and must be implemented in * classes inheriting from this. */ virtual void setCoupling(Energy2,tcPDPtr,tcPDPtr,tcPDPtr,tcPDPtr) { assert(false); } //@} private: /** * Private and non-existent assignment operator. */ SSTVertex & operator=(const SSTVertex &) = delete; }; } } #endif /* ThePEG_SSTVertex_H */ diff --git a/Helicity/Vertex/Tensor/VVTVertex.cc b/Helicity/Vertex/Tensor/VVTVertex.cc --- a/Helicity/Vertex/Tensor/VVTVertex.cc +++ b/Helicity/Vertex/Tensor/VVTVertex.cc @@ -1,277 +1,277 @@ // -*- C++ -*- // // VVTVertex.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the VVTVertex class. // #include "VVTVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" using namespace ThePEG; using namespace Helicity; // The following static variable is needed for the type // description system in ThePEG. DescribeAbstractNoPIOClass describeThePEGVVTVertex("ThePEG::VVTVertex", "libThePEG.so"); void VVTVertex::Init() { static ClassDocumentation documentation ("The VVTVertex class is the implementation of" "the vector-vector tensor vertices for helicity " "amplitude calculations. All such vertices should inherit" "from it."); } // function to evaluate the vertex Complex VVTVertex::evaluate(Energy2 q2, const VectorWaveFunction & vec1, const VectorWaveFunction & vec2, const TensorWaveFunction & ten, Energy vmass) { // set the couplings setCoupling(q2,vec1.particle(),vec2.particle(),ten.particle()); // mass of the vector if(vmassmass(); // mass+k1.k2 Energy2 mdot = vec1.momentum()*vec2.momentum(); if(vmass!=ZERO) mdot += sqr(vmass); // dot product of wavefunctions and momenta Complex dotv1v2 = vec1.wave().dot(vec2.wave()); complex dotk1v2 = vec1.momentum()*vec2.wave(); complex dotk2v1 = vec1.wave()*vec2.momentum(); // dot product of wavefunctions and momenta with the tensor LorentzPolarizationVector tv1 = ten.wave().postDot(vec1.wave()); LorentzPolarizationVector tv2 = ten.wave().postDot(vec2.wave()); LorentzPolarizationVectorE tk1 = ten.wave().postDot(vec1.momentum()); LorentzPolarizationVectorE tk2 = ten.wave().postDot(vec2.momentum()); Complex tenv1v2 = vec1.wave ().dot(tv2) + vec2.wave ().dot(tv1); complex tenk1v2 = vec1.momentum().dot(tv2) + vec2.wave ().dot(tk1); complex tenk2v1 = vec2.momentum().dot(tv1) + vec1.wave ().dot(tk2); complex tenk1k2 = vec2.momentum().dot(tk1) + vec1.momentum().dot(tk2); // trace of the tensor Complex trace = ten.tt()-ten.xx()-ten.yy()-ten.zz(); // evaluate the vertex return -0.5*Complex(0.,1.)*norm()*UnitRemoval::InvE2 * (trace*(dotk1v2*dotk2v1-dotv1v2*mdot) +mdot*tenv1v2-dotk2v1*tenk1v2 -dotk1v2*tenk2v1+dotv1v2*tenk1k2); } // evaluate an off-shell vector VectorWaveFunction VVTVertex::evaluate(Energy2 q2, int iopt, tcPDPtr out, const VectorWaveFunction & vec, const TensorWaveFunction & ten, complex mass, complex width) { // evaluate the couplings setCoupling(q2,vec.particle(),out,ten.particle()); // outgoing momentum Lorentz5Momentum pout = ten.momentum()+vec.momentum(); // normalisation factor if(mass.real() < ZERO) mass = out->mass(); complex mass2 = sqr(mass); Energy2 p2 = pout.m2(); Complex fact = -0.5*norm()*propagator(iopt,p2,out,mass,width); // dot product of wavefunctions and momenta complex dotk1k2 = vec.momentum()*pout; complex dotk2v1 = vec.wave() *pout; // mass-k1.k2 complex mdot = -dotk1k2; if(mass.real()!=ZERO) mdot += mass2; // components of the tensor Complex tentx = ten.tx()+ten.xt(); Complex tenty = ten.ty()+ten.yt(); Complex tentz = ten.tz()+ten.zt(); Complex tenxy = ten.xy()+ten.yx(); Complex tenxz = ten.xz()+ten.zx(); Complex tenyz = ten.yz()+ten.zy(); // dot product of momenta and polarization vectors with the tensor complex tenk2v1 = 2.*(+ten.tt()*vec.t()*pout.e() +ten.xx()*vec.x()*pout.x() +ten.yy()*vec.y()*pout.y()+ten.zz()*vec.z()*pout.z()) -tentx*(vec.t()*pout.x()+vec.x()*pout.e()) -tenty*(vec.t()*pout.y()+vec.y()*pout.e()) -tentz*(vec.t()*pout.z()+vec.z()*pout.e()) +tenxy*(vec.x()*pout.y()+vec.y()*pout.x()) +tenxz*(vec.x()*pout.z()+vec.z()*pout.x()) +tenyz*(vec.y()*pout.z()+vec.z()*pout.y()); complex tenk1k2 = 2.*(+ten.tt()*vec.e()*pout.e() +ten.xx()*vec.px()*pout.x() +ten.yy()*vec.py()*pout.y()+ten.zz()*vec.pz()*pout.z()) -tentx*(vec.e()*pout.x() +vec.px()*pout.e()) -tenty*(vec.e()*pout.y() +vec.py()*pout.e()) -tentz*(vec.e()*pout.z() +vec.pz()*pout.e()) +tenxy*(vec.px()*pout.y()+vec.py()*pout.x()) +tenxz*(vec.px()*pout.z()+vec.pz()*pout.x()) +tenyz*(vec.py()*pout.z()+vec.pz()*pout.y()); // trace of the tensor Complex trace = ten.tt()-ten.xx()-ten.yy()-ten.zz(); // compute the vector Complex vec1[4]; vec1[0] = Complex(UnitRemoval::InvE2* (mdot*(+ tentx* vec.t()-2.*ten.xx()*vec.x() - tenxy* vec.y()- tenxz* vec.z()-trace*vec.x()) +(tenk2v1-trace*dotk2v1)*vec.px()-tenk1k2*vec.x() +dotk2v1*(+ tentx* vec.e() -2.*ten.xx()*vec.px() - tenxy* vec.py()- tenxz* vec.pz()))); vec1[1] = Complex(UnitRemoval::InvE2*( mdot * (+ tenty* vec.t() - tenxy* vec.x() -2.*ten.yy()*vec.y() - tenyz* vec.z()-trace*vec.y() ) +(tenk2v1-trace*dotk2v1)*vec.py() -tenk1k2*vec.y() +dotk2v1*(+ tenty* vec.e() - tenxy* vec.px() -2.*ten.yy()*vec.py() - tenyz* vec.pz()))); vec1[2] = Complex(UnitRemoval::InvE2* (mdot* (+ tentz* vec.t()- tenxz* vec.x() - tenyz* vec.y()-2.*ten.zz()*vec.z()-trace*vec.z()) +(tenk2v1-trace*dotk2v1)*vec.pz()-tenk1k2*vec.z() +dotk2v1*(+ tentz* vec.e() - tenxz *vec.px() - tenyz* vec.py()-2.*ten.zz()*vec.pz()))); vec1[3] = Complex(UnitRemoval::InvE2* (mdot*(+2.*ten.tt()*vec.t()- tentx* vec.x() - tenty* vec.y()- tentz* vec.z()-trace*vec.t()) +(tenk2v1-trace*dotk2v1)*vec.e() -tenk1k2*vec.t() +dotk2v1*(+2.*ten.tt()*vec.e() - tentx* vec.px() - tenty* vec.py()- tentz* vec.pz()))); // now add the piece for massive bosons if(mass.real()!=ZERO) { // DGRELL unit problem? Complex dot = tenk2v1 * UnitRemoval::InvE - dotk1k2 * trace * UnitRemoval::InvE2; vec1[0] -= Complex(dot*pout.x() * UnitRemoval::InvE); vec1[1] -= Complex(dot*pout.y() * UnitRemoval::InvE); vec1[2] -= Complex(dot*pout.z() * UnitRemoval::InvE); vec1[3] -= Complex(dot*pout.e() * UnitRemoval::InvE); } // return the VectorWaveFunction for(int ix=0;ix<4;++ix){vec1[ix]=vec1[ix]*fact;} return VectorWaveFunction(pout,out,vec1[0],vec1[1],vec1[2],vec1[3]); } // off-shell tensor TensorWaveFunction VVTVertex::evaluate(Energy2 q2, int iopt,tcPDPtr out, const VectorWaveFunction & vec1, const VectorWaveFunction & vec2, Energy vmass, complex tmass, complex width) { // coupling setCoupling(q2,vec1.particle(),vec2.particle(),out); // momenta of the outgoing tensor // outgoing momentum Lorentz5Momentum pout= vec1.momentum()+vec2.momentum(); // overall normalisation if(tmass.real() < ZERO) tmass = out->mass(); complex tmass2 = sqr(tmass); if(vmassmass(); Energy2 vmass2 = sqr(vmass); Energy2 p2 = pout.m2(); Complex fact = 0.25*norm()*propagator(iopt,p2,out,tmass,width); // dot products we need to construct the tensor complex dotk1k2 = vec1.momentum()*vec2.momentum(); complex dotv1k2 = vec1.wave()*vec2.momentum(); Complex dotv1v2 = vec1.wave().dot(vec2.wave()); complex dotk1v2 = vec1.momentum()*vec2.wave(); complex dotkk1 = vec1.momentum()*pout; complex dotkk2 = vec2.momentum()*pout; complex dotkv1 = vec1.wave()*pout; complex dotkv2 = vec2.wave()*pout; // dot product ma^2+k1.k2 complex mdot = vmass2+dotk1k2; // vectors to help construct the tensor Complex vecv1[4],vecv2[4]; complex veck1[4],veck2[4]; complex tmass2inv(ZERO); if(tmass.real()> ZERO) tmass2inv = 1./tmass2; vecv1[0]=vec1.x() -pout.x()*dotkv1*tmass2inv; vecv2[0]=vec2.x() -pout.x()*dotkv2*tmass2inv; veck1[0]=vec1.px()-pout.x()*dotkk1*tmass2inv; veck2[0]=vec2.px()-pout.x()*dotkk2*tmass2inv; vecv1[1]=vec1.y() -pout.y()*dotkv1*tmass2inv; vecv2[1]=vec2.y() -pout.y()*dotkv2*tmass2inv; veck1[1]=vec1.py()-pout.y()*dotkk1*tmass2inv; veck2[1]=vec2.py()-pout.y()*dotkk2*tmass2inv; vecv1[2]=vec1.z() -pout.z()*dotkv1*tmass2inv; vecv2[2]=vec2.z() -pout.z()*dotkv2*tmass2inv; veck1[2]=vec1.pz()-pout.z()*dotkk1*tmass2inv; veck2[2]=vec2.pz()-pout.z()*dotkk2*tmass2inv; vecv1[3]=vec1.t() -pout.e()*dotkv1*tmass2inv; vecv2[3]=vec2.t() -pout.e()*dotkv2*tmass2inv; veck1[3]=vec1.e() -pout.e()*dotkk1*tmass2inv; veck2[3]=vec2.e() -pout.e()*dotkk2*tmass2inv; // coefficient of g(nu,mu)-k^muk^nu/m^2 Complex omp2 = 1.-Complex(p2*tmass2inv); Complex coeff1 = UnitRemoval::InvE2 * ( +4./3.*mdot*(-2.*dotv1v2+Complex((dotkv1*dotkv2+p2*dotv1v2)*tmass2inv)) +4./3.*(dotv1k2*(dotk1v2-dotkk1*dotkv2*tmass2inv) +dotk1v2*(dotv1k2-dotkk2*dotkv1*tmass2inv) -dotv1v2*(dotk1k2-dotkk1*dotkk2*tmass2inv) +omp2*dotk1v2*dotv1k2) ); // coefficient of g(nu,mu) Complex coeff2 = UnitRemoval::InvE2 * ( 2.*mdot*omp2*dotv1v2 -2.*omp2*dotk1v2*dotv1k2 ); // construct the tensor Complex ten[4][4]; const Energy pout_tmp[4] = {pout.x(), pout.y(), pout.z(), pout.e()}; for(int ix=0;ix<4;++ix) { for(int iy=0;iy<4;++iy) { complex temp; temp = 2.*mdot* (vecv1[ix]*vecv2[iy]+vecv1[iy]*vecv2[ix]); temp -= 2.*dotv1k2*(veck1[ix]*vecv2[iy]+veck1[iy]*vecv2[ix]); temp -= 2.*dotk1v2*(veck2[ix]*vecv1[iy]+veck2[iy]*vecv1[ix]); temp += 2.*dotv1v2*(veck1[ix]*veck2[iy]+veck1[iy]*veck2[ix]); ten[ix][iy] = Complex(UnitRemoval::InvE2 * temp) -coeff1*tmass2inv*pout_tmp[ix]*pout_tmp[iy]; } } // add the g(mu,nu) term ten[0][0] = ten[0][0]-(coeff1+coeff2); ten[1][1] = ten[1][1]-(coeff1+coeff2); ten[2][2] = ten[2][2]-(coeff1+coeff2); ten[3][3] = ten[3][3]+(coeff1+coeff2); // overall coefficent for(int ix=0;ix<4;++ix) { for(int iy=0;iy<4;++iy) { ten[ix][iy] = fact*ten[ix][iy]; } } // return the wavefunction return TensorWaveFunction(pout,out, ten[0][0],ten[0][1],ten[0][2],ten[0][3], ten[1][0],ten[1][1],ten[1][2],ten[1][3], ten[2][0],ten[2][1],ten[2][2],ten[2][3], ten[3][0],ten[3][1],ten[3][2],ten[3][3]); } diff --git a/Helicity/Vertex/Tensor/VVTVertex.h b/Helicity/Vertex/Tensor/VVTVertex.h --- a/Helicity/Vertex/Tensor/VVTVertex.h +++ b/Helicity/Vertex/Tensor/VVTVertex.h @@ -1,149 +1,149 @@ // -*- C++ -*- // // VVTVertex.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_VVTVertex_H #define ThePEG_VVTVertex_H // // This is the declaration of the VVTVertex class. #include "ThePEG/Helicity/Vertex/AbstractVVTVertex.h" #include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/TensorWaveFunction.h" #include "VVTVertex.fh" namespace ThePEG { namespace Helicity { /** \ingroup Helicity * * The VVTVertex class is the implementation of the * vector-vector-tensor vertex. * It inherits from the AbstractVVTVertex class for the storage of the particles * interacting at the vertex and implements the helicity amplitude calculations. * * All implementations of this vertex should inherit from it and implement the * virtual setCoupling member. * * The vertex has the form * \f[ * \left[m^2_v+k_1\cdot k_2)C_{\mu\nu,\rho\sigma}+D_{\mu\nu,\rho\sigma}\right] * \epsilon_1^\rho\epsilon_2^\sigma \epsilon_3^{\mu\nu} * \f] * where * - \f$C_{\mu\nu,\rho\sigma}=g_{\mu\rho}g_{\nu\sigma}+g_{\mu\sigma}g_{\nu\rho} * -g_{\mu\nu}g_{\rho\sigma}\f$ * - \f$D_{\mu\nu,\rho\sigma}= * g_{\mu\nu}k_{1\sigma}k_{2\rho}-\left[g_{\mu\sigma}k_{1\nu}k_{2\rho}+g_{\mu\rho}k_{1\sigma}k_{2\nu}-g_{\rho\sigma}k_{1\mu}k_{2\nu}+(\mu\leftrightarrow\nu)\right] * \f$ * * @see AbstractVVTVertex */ class VVTVertex: public AbstractVVTVertex { public: /** * Standard Init function used to initialize the interfaces. */ static void Init(); public: /** * Members to calculate the helicity amplitude expressions for vertices * and off-shell particles. */ //@{ /** * Evalulate the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param vec1 The wavefunction for the first vector. * @param vec2 The wavefunction for the second vector. * @param ten3 The wavefunction for the tensor. * @param vmass The mass of the vector boson. */ Complex evaluate(Energy2 q2,const VectorWaveFunction & vec1, const VectorWaveFunction & vec2, const TensorWaveFunction & ten3, Energy vmass=-GeV); /** * Evaluate the off-shell tensor coming from the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param iopt Option of the shape of the Breit-Wigner for the off-shell tensor. * @param out The ParticleData pointer for the off-shell tensor. * @param vec1 The wavefunction for the first vector. * @param vec2 The wavefunction for the second vector. * @param vmass The mass of the vector boson. * @param mass The mass of the off-shell particle if not taken from the ParticleData * object * @param width The width of the off-shell particle if not taken from the ParticleData * object */ TensorWaveFunction evaluate(Energy2 q2,int iopt, tcPDPtr out, const VectorWaveFunction & vec1, const VectorWaveFunction & vec2, Energy vmass=-GeV, complex mass=-GeV, complex width=-GeV); /** * Evaluate the off-shell vector coming from the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param iopt Option of the shape of the Breit-Wigner for the off-shell vector. * @param out The ParticleData pointer for the off-shell vector. * @param vec1 The wavefunction for the first vector. * @param ten3 The wavefunction for the tensor. * @param mass The mass of the off-shell particle if not taken from the ParticleData * object * @param width The width of the off-shell particle if not taken from the ParticleData * object */ VectorWaveFunction evaluate(Energy2 q2,int iopt, tcPDPtr out, const VectorWaveFunction & vec1, const TensorWaveFunction & ten3, complex mass=-GeV, complex width=-GeV); //@} /** * 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; /** * Dummy setCouplings for a four point interaction * This method is virtual and must be implemented in * classes inheriting from this. */ virtual void setCoupling(Energy2,tcPDPtr,tcPDPtr,tcPDPtr,tcPDPtr) { assert(false); } private: /** * Private and non-existent assignment operator. */ VVTVertex & operator=(const VVTVertex &) = delete; }; } } #endif /* ThePEG_VVTVertex_H */ diff --git a/Helicity/Vertex/Tensor/VVVTVertex.cc b/Helicity/Vertex/Tensor/VVVTVertex.cc --- a/Helicity/Vertex/Tensor/VVVTVertex.cc +++ b/Helicity/Vertex/Tensor/VVVTVertex.cc @@ -1,131 +1,131 @@ // -*- C++ -*- // // VVVTVertex.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the VVVTVertex class. // #include "VVVTVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" using namespace ThePEG; using namespace Helicity; // The following static variable is needed for the type // description system in ThePEG. DescribeAbstractNoPIOClass describeThePEGVVVTVertex("ThePEG::VVVTVertex", "libThePEG.so"); void VVVTVertex::Init() { static ClassDocumentation documentation ("The VVVTVertex class is the implementation f the" " helicity amplitude calculation of the vector-vector-vector-tensor" " vertex. All such vertices should inherit from it."); } // function to evaluate the vertex Complex VVVTVertex::evaluate(Energy2 q2, const VectorWaveFunction & vec1, const VectorWaveFunction & vec2, const VectorWaveFunction & vec3, const TensorWaveFunction & ten) { // set the couplings setCoupling(q2,vec1.particle(),vec2.particle(), vec3.particle(),ten.particle()); Complex ii(0.,1.); // dot products of the wavefunctions Complex dotv1v2 = vec1.wave().dot(vec2.wave()); Complex dotv1v3 = vec1.wave().dot(vec3.wave()); Complex dotv2v3 = vec2.wave().dot(vec3.wave()); // dot product of wavefunctions and momenta complex dotv1k23 = vec1.wave().dot(vec2.momentum()-vec3.momentum()); complex dotv2k31 = vec2.wave().dot(vec3.momentum()-vec1.momentum()); complex dotv3k12 = vec3.wave().dot(vec1.momentum()-vec2.momentum()); // components of the tensor Complex tentx = ten.tx()+ten.xt(); Complex tenty = ten.ty()+ten.yt(); Complex tentz = ten.tz()+ten.zt(); Complex tenxy = ten.xy()+ten.yx(); Complex tenxz = ten.xz()+ten.zx(); Complex tenyz = ten.yz()+ten.zy(); // dot product of wavefunctions and momenta with the tensor Complex tenv1v2 = 2.*(+ten.tt()*vec1.t()*vec2.t()+ten.xx()*vec1.x()*vec2.x() +ten.yy()*vec1.y()*vec2.y()+ten.zz()*vec1.z()*vec2.z()) -tentx*(vec1.t()*vec2.x()+vec1.x()*vec2.t()) -tenty*(vec1.t()*vec2.y()+vec1.y()*vec2.t()) -tentz*(vec1.t()*vec2.z()+vec1.z()*vec2.t()) +tenxy*(vec1.x()*vec2.y()+vec1.y()*vec2.x()) +tenxz*(vec1.x()*vec2.z()+vec1.z()*vec2.x()) +tenyz*(vec1.y()*vec2.z()+vec1.z()*vec2.y()); Complex tenv1v3 = 2.*(+ten.tt()*vec1.t()*vec3.t()+ten.xx()*vec1.x()*vec3.x() +ten.yy()*vec1.y()*vec3.y()+ten.zz()*vec1.z()*vec3.z()) -tentx*(vec1.t()*vec3.x()+vec1.x()*vec3.t()) -tenty*(vec1.t()*vec3.y()+vec1.y()*vec3.t()) -tentz*(vec1.t()*vec3.z()+vec1.z()*vec3.t()) +tenxy*(vec1.x()*vec3.y()+vec1.y()*vec3.x()) +tenxz*(vec1.x()*vec3.z()+vec1.z()*vec3.x()) +tenyz*(vec1.y()*vec3.z()+vec1.z()*vec3.y()); Complex tenv2v3 = 2.*(+ten.tt()*vec2.t()*vec3.t()+ten.xx()*vec2.x()*vec3.x() +ten.yy()*vec2.y()*vec3.y()+ten.zz()*vec2.z()*vec3.z()) -tentx*(vec2.t()*vec3.x()+vec2.x()*vec3.t()) -tenty*(vec2.t()*vec3.y()+vec2.y()*vec3.t()) -tentz*(vec2.t()*vec3.z()+vec2.z()*vec3.t()) +tenxy*(vec2.x()*vec3.y()+vec2.y()*vec3.x()) +tenxz*(vec2.x()*vec3.z()+vec2.z()*vec3.x()) +tenyz*(vec2.y()*vec3.z()+vec2.z()*vec3.y()); complex tenv1k23 = 2.*(+ten.tt()*vec1.t()*(vec2.e() -vec3.e() ) +ten.xx()*vec1.x()*(vec2.px()-vec3.px()) +ten.yy()*vec1.y()*(vec2.py()-vec3.py()) +ten.zz()*vec1.z()*(vec2.pz()-vec3.pz())) -tentx*(vec1.t()*(vec2.px()-vec3.px())+vec1.x()*(vec2.e() -vec3.e() )) -tenty*(vec1.t()*(vec2.py()-vec3.py())+vec1.y()*(vec2.e() -vec3.e() )) -tentz*(vec1.t()*(vec2.pz()-vec3.pz())+vec1.z()*(vec2.e() -vec3.e() )) +tenxy*(vec1.x()*(vec2.py()-vec3.py())+vec1.y()*(vec2.px()-vec3.px())) +tenxz*(vec1.x()*(vec2.pz()-vec3.pz())+vec1.z()*(vec2.px()-vec3.px())) +tenyz*(vec1.y()*(vec2.pz()-vec3.pz())+vec1.z()*(vec2.py()-vec3.py())); complex tenv2k31 = 2.*(+ten.tt()*vec2.t()*(vec3.e() -vec1.e() ) +ten.xx()*vec2.x()*(vec3.px()-vec1.px()) +ten.yy()*vec2.y()*(vec3.py()-vec1.py()) +ten.zz()*vec2.z()*(vec3.pz()-vec1.pz())) -tentx*(vec2.t()*(vec3.px()-vec1.px())+vec2.x()*(vec3.e() -vec1.e() )) -tenty*(vec2.t()*(vec3.py()-vec1.py())+vec2.y()*(vec3.e() -vec1.e() )) -tentz*(vec2.t()*(vec3.pz()-vec1.pz())+vec2.z()*(vec3.e() -vec1.e() )) +tenxy*(vec2.x()*(vec3.py()-vec1.py())+vec2.y()*(vec3.px()-vec1.px())) +tenxz*(vec2.x()*(vec3.pz()-vec1.pz())+vec2.z()*(vec3.px()-vec1.px())) +tenyz*(vec2.y()*(vec3.pz()-vec1.pz())+vec2.z()*(vec3.py()-vec1.py())); complex tenv3k12 = 2.*(+ten.tt()*vec3.t()*(vec1.e() -vec2.e() ) +ten.xx()*vec3.x()*(vec1.px()-vec2.px()) +ten.yy()*vec3.y()*(vec1.py()-vec2.py()) +ten.zz()*vec3.z()*(vec1.pz()-vec2.pz())) -tentx*(vec3.t()*(vec1.px()-vec2.px())+vec3.x()*(vec1.e() -vec2.e() )) -tenty*(vec3.t()*(vec1.py()-vec2.py())+vec3.y()*(vec1.e() -vec2.e() )) -tentz*(vec3.t()*(vec1.pz()-vec2.pz())+vec3.z()*(vec1.e() -vec2.e() )) +tenxy*(vec3.x()*(vec1.py()-vec2.py())+vec3.y()*(vec1.px()-vec2.px())) +tenxz*(vec3.x()*(vec1.pz()-vec2.pz())+vec3.z()*(vec1.px()-vec2.px())) +tenyz*(vec3.y()*(vec1.pz()-vec2.pz())+vec3.z()*(vec1.py()-vec2.py())); // trace of the tensor Complex trace = ten.tt()-ten.xx()-ten.yy()-ten.zz(); // compute the vertex Complex vertex= -0.5 * ii * norm() * UnitRemoval::InvE * ( +dotv3k12*(tenv1v2-trace*dotv1v2) +dotv2k31*(tenv1v3-trace*dotv1v3) +dotv1k23*(tenv2v3-trace*dotv2v3) +dotv2v3*tenv1k23+dotv1v3*tenv2k31+dotv1v2*tenv3k12 ); // return the answer return vertex; } diff --git a/Helicity/Vertex/Tensor/VVVTVertex.h b/Helicity/Vertex/Tensor/VVVTVertex.h --- a/Helicity/Vertex/Tensor/VVVTVertex.h +++ b/Helicity/Vertex/Tensor/VVVTVertex.h @@ -1,155 +1,155 @@ // -*- C++ -*- // // VVVTVertex.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_VVVTVertex_H #define ThePEG_VVVTVertex_H // // This is the declaration of the VVVTVertex class. // #include "ThePEG/Helicity/Vertex/AbstractVVVTVertex.h" #include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/TensorWaveFunction.h" #include "VVVTVertex.fh" namespace ThePEG { namespace Helicity { /** \ingroup Helicity * * The VVTVertex class is the implementation of the * vector-vector-vector-tensor vertex. * It inherits from the AbstractVVVTVertex class for the storage of the particles * interacting at the vertex and implements the helicity amplitude calculations. * * All implementations of this vertex should inherit from it and implement the * virtual setCoupling member. * * The vertex has the form * \f[ * g\frac\kappa2f^{abc}\left[ * C_{\mu\nu,\rho\sigma}(k_1-k_2)_\lambda+C_{\mu\nu,\rho\lambda}(k_3-k_1)_\sigma * +C_{\mu\nu,\sigma\lambda}(k_2-k_3)_\rho+F_{\mu\nu,\rho\sigma\lambda} * \right]\epsilon_1^\rho\epsilon^\sigma_2\epsilon^\lambda_3 * \epsilon^{\mu\nu}_4 * \f] * where * -\f$C_{\mu\nu,\rho\sigma}=g_{\mu\rho}g_{\nu\sigma}+g_{\mu\sigma}g_{\nu\rho} * -g_{\mu\nu}g_{\rho\sigma}\f$ * -\f$F_{\mu\nu,\rho\sigma\lambda} = * g_{\mu\rho}g_{\sigma\lambda}(k_2-k_3)_\nu * +g_{\mu\sigma}g_{\rho\lambda}(k_3-k_1)_\nu * +g_{\mu\lambda}g_{\rho\sigma}(k_1-k_2)_\nu+(\mu\leftrightarrow\nu) * \f$ * * @see AbstractVVVTVertex */ class VVVTVertex: public AbstractVVVTVertex { public: /** * Standard Init function used to initialize the interfaces. */ static void Init(); public: /** * Members to calculate the helicity amplitude expressions for vertices * and off-shell particles. */ //@{ /** * Evalulate the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param vec1 The wavefunction for the first vector. * @param vec2 The wavefunction for the second vector. * @param vec3 The wavefunction for the third vector. * @param ten4 The wavefunction for the tensor. */ Complex evaluate(Energy2 q2,const VectorWaveFunction & vec1, const VectorWaveFunction & vec2, const VectorWaveFunction & vec3, const TensorWaveFunction & ten4); /** * Evaluate the off-shell tensor coming from the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param iopt Option of the shape of the Breit-Wigner for the off-shell tensor. * @param out The ParticleData pointer for the off-shell tensor. * @param vec1 The wavefunction for the first vector. * @param vec2 The wavefunction for the second vector. * @param vec3 The wavefunction for the third vector. * @param mass The mass of the off-shell particle if not taken from the ParticleData * object * @param width The width of the off-shell particle if not taken from the ParticleData * object */ TensorWaveFunction evaluate(Energy2 q2,int iopt, tcPDPtr out, const VectorWaveFunction & vec1, const VectorWaveFunction & vec2, const VectorWaveFunction & vec3, complex mass=-GeV, complex width=-GeV); /** * Evaluate the off-shell vector coming from the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param iopt Option of the shape of the Breit-Wigner for the off-shell vector. * @param out The ParticleData pointer for the off-shell vector. * @param vec1 The wavefunction for the first vector. * @param vec2 The wavefunction for the second vector. * @param ten4 The wavefunction for the tensor. * @param mass The mass of the off-shell particle if not taken from the ParticleData * object * @param width The width of the off-shell particle if not taken from the ParticleData * object */ VectorWaveFunction evaluate(Energy2 q2,int iopt, tcPDPtr out, const VectorWaveFunction & vec1, const VectorWaveFunction & vec2, const TensorWaveFunction & ten4, complex mass=-GeV, complex width=-GeV); //@} /** * Set coupling methods */ //@{ /** * Dummy for a three point interaction. */ virtual void setCoupling(Energy2,tcPDPtr,tcPDPtr,tcPDPtr) { assert(false); } /** * 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; //@} private: /** * Private and non-existent assignment operator. */ VVVTVertex & operator=(const VVVTVertex &) = delete; }; } } #endif /* ThePEG_VVVTVertex_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,475 +1,475 @@ // -*- C++ -*- // // FFVVertex.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the FFVVertex class. // #include "FFVVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" using namespace ThePEG; using namespace Helicity; // Definition of the static class description member // The following static variable is needed for the type // description system in ThePEG. DescribeAbstractNoPIOClass describeThePEGFFVVertex("ThePEG::FFVVertex", "libThePEG.so"); 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 += Complex(UnitRemoval::InvE * (p0m3*a3-p1m2*a4)); s2 += Complex(UnitRemoval::InvE * (-p1p2*a3+p0p3*a4)); s3 += Complex(UnitRemoval::InvE * a3*mass); s4 += Complex(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 += Complex(UnitRemoval::InvE * a1*mass); s2 += Complex(UnitRemoval::InvE * a2*mass); s3 += Complex(UnitRemoval::InvE * (p0p3*a1+p1m2*a2)); s4 += Complex(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 += Complex(UnitRemoval::InvE*a1*mass); s2 += Complex(UnitRemoval::InvE*a2*mass); s3 += Complex(UnitRemoval::InvE*(-p0m3*a1+p1p2*a2)); s4 += Complex(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 += Complex(UnitRemoval::InvE*(-p0p3*a3-p1p2*a4)); s2 += Complex(UnitRemoval::InvE*(-p1m2*a3-p0m3*a4)); s3 += Complex(UnitRemoval::InvE*a3*mass); s4 += Complex(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()==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()==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()==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()==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/Vector/FFVVertex.h b/Helicity/Vertex/Vector/FFVVertex.h --- a/Helicity/Vertex/Vector/FFVVertex.h +++ b/Helicity/Vertex/Vector/FFVVertex.h @@ -1,269 +1,269 @@ // -*- C++ -*- // // FFVVertex.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_FFVVertex_H #define ThePEG_FFVVertex_H // // This is the declaration of the FFVVertex class. #include #include #include #include #include "FFVVertex.fh" namespace ThePEG { namespace Helicity{ /** \ingroup Helicity * * The FFVVertex class is the base class for all helicity amplitude * vertices which use the renormalisable form for the * fermion-fermion-vector vertex. * * Any such vertices should inherit from this class and implement the virtual * setcoupling member function. The base AbstractFFVVertex class is used to store the * particles allowed to interact at the vertex. * * The form of the vertex is * \f[ic\bar{f_2}\gamma^\mu a^\lambda P_\lambda f_1\epsilon_{3\mu}\f] * * @see AbstractFFVVertex */ class FFVVertex: public AbstractFFVVertex { public: /** * Standard Init function used to initialize the interfaces. */ static void Init(); public: /** * Members to calculate the helicity amplitude expressions for vertices * and off-shell particles. */ //@{ /** * Evalulate the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param sp1 The wavefunction for the ferimon. * @param sbar2 The wavefunction for the antifermion. * @param vec3 The wavefunction for the vector. */ virtual Complex evaluate(Energy2 q2,const SpinorWaveFunction & sp1, const SpinorBarWaveFunction & sbar2, const VectorWaveFunction & vec3); /** * Evaluate the off-shell barred spinor coming from the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param iopt Option of the shape of the Breit-Wigner for the off-shell barred spinor. * @param out The ParticleData pointer for the off-shell barred spinor. * @param sbar2 The wavefunction for the antifermion. * @param vec3 The wavefunction for the vector. * @param mass The mass of the off-shell particle if not taken from the ParticleData * object * @param width The width of the off-shell particle if not taken from the ParticleData * object */ virtual SpinorBarWaveFunction evaluate(Energy2 q2,int iopt,tcPDPtr out, const SpinorBarWaveFunction & sbar2, const VectorWaveFunction & vec3, complex mass=-GeV, complex width=-GeV); /** * Evaluate the off-shell vector coming from the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param iopt Option of the shape of the Breit-Wigner for the off-shell vector. * @param out The ParticleData pointer for the off-shell vector. * @param sp1 The wavefunction for the ferimon. * @param sbar2 The wavefunction for the antifermion. * @param mass The mass of the off-shell particle if not taken from the ParticleData * object * @param width The width of the off-shell particle if not taken from the ParticleData * object */ virtual VectorWaveFunction evaluate(Energy2 q2,int iopt,tcPDPtr out, const SpinorWaveFunction & sp1, const SpinorBarWaveFunction & sbar2, complex mass=-GeV, complex width=-GeV); /** * Evaluate the off-shell spinor coming from the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param iopt Option of the shape of the Breit-Wigner for the off-shell spinor. * @param out The ParticleData pointer for the off-shell spinor. * @param sp1 The wavefunction for the ferimon. * @param vec3 The wavefunction for the vector. * @param mass The mass of the off-shell particle if not taken from the ParticleData * object * @param width The width of the off-shell particle if not taken from the ParticleData * object */ virtual SpinorWaveFunction evaluate(Energy2 q2,int iopt,tcPDPtr out, const SpinorWaveFunction & sp1, const VectorWaveFunction & vec3, complex mass=-GeV, complex width=-GeV); //@} /** * Special members for off-shell fermion wavefunctions with massless * gauge bosons at small angles in the small angle limit for * numerical accuracy. In order to get sufficient accuracy it is * assumed that the fermion lies along either the positive or negative z * axis. */ //@{ /** Small angle approx for an off-shell spinor * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param iopt Option of the shape of the Breit-Wigner for the off-shell spinor. * @param out The ParticleData pointer for the off-shell spinor. * @param sp1 The wavefunction for the ferimon. * @param vec3 The wavefunction for the vector. * @param fhel Helicity of the fermion * @param vhel Helicity of the vector * @param ctheta The cosine of the * polar angle of the photon with respect to the fermion * @param phi The azimuthal angle of the photon with respect to the fermion * @param stheta The sine of the * polar angle of the photon with respect to the fermion * @param includeEikonal Whether or not to include the eikonal piece * @param direction Whether fermion along + or - z direction * @param mass The mass of the off-shell particle if not taken from the ParticleData * object * @param width The width of the off-shell particle if not taken from the ParticleData * object */ virtual SpinorWaveFunction evaluateSmall(Energy2 q2,int iopt, tcPDPtr out, const SpinorWaveFunction & sp1, const VectorWaveFunction & vec3, unsigned int fhel, unsigned int vhel, double ctheta, double phi, double stheta, bool includeEikonal = true, SmallAngleDirection direction = PostiveZDirection, Energy mass=-GeV, Energy width=-GeV); /** Small angle approx for an off-shell spinor * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param iopt Option of the shape of the Breit-Wigner for the off-shell spinor. * @param out The ParticleData pointer for the off-shell spinor. * @param sbar2 The wavefunction for the antifermion. * @param vec3 The wavefunction for the vector. * @param fhel Helicity of the fermion * @param vhel Helicity of the vector * @param ctheta The cosine of the * polar angle of the photon with respect to the fermion * @param phi The azimuthal angle of the photon with respect to the fermion * @param stheta The sine of the * polar angle of the photon with respect to the fermion * @param includeEikonal Whether or not to include the eikonal piece * @param direction Whether fermion along + or - z direction * @param mass The mass of the off-shell particle if not taken from the ParticleData * object * @param width The width of the off-shell particle if not taken from the ParticleData * object */ virtual SpinorBarWaveFunction evaluateSmall(Energy2 q2,int iopt, tcPDPtr out, const SpinorBarWaveFunction & sbar2, const VectorWaveFunction & vec3, unsigned int fhel, unsigned int vhel, double ctheta, double phi, double stheta, bool includeEikonal = true, SmallAngleDirection direction = PostiveZDirection, Energy mass=-GeV, Energy width=-GeV); //@} /** * 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; /** * Dummy setCouplings for a four point interaction * This method is virtual and must be implemented in * classes inheriting from this. */ virtual void setCoupling(Energy2,tcPDPtr,tcPDPtr,tcPDPtr,tcPDPtr) { assert(false); } //@} /** * Get the Couplings */ //@{ /** * Get the left coupling. */ const Complex & left() const { return _left; } /** * Get the right coupling. */ const Complex & right() const { return _right; } //@} protected: /** * Set the couplings */ //@{ /** * Set the left coupling. */ void left(const Complex & in) { _left = in; } /** * Set the right coupling. */ void right(const Complex & in) { _right = in; } //@} private: /** * Private and non-existent assignment operator. */ FFVVertex & operator=(const FFVVertex &) = delete; private: /** * Left coupling. */ Complex _left; /** * Right coupling. */ Complex _right; }; } } #endif /* ThePEG_FFVVertex_H */ diff --git a/Helicity/Vertex/Vector/GeneralFFVVertex.cc b/Helicity/Vertex/Vector/GeneralFFVVertex.cc --- a/Helicity/Vertex/Vector/GeneralFFVVertex.cc +++ b/Helicity/Vertex/Vector/GeneralFFVVertex.cc @@ -1,348 +1,348 @@ // -*- C++ -*- // // GeneralFFVVertex.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the GeneralFFVVertex class. // #include "GeneralFFVVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" using namespace ThePEG; using namespace Helicity; // Definition of the static class description member // The following static variable is needed for the type // description system in ThePEG. DescribeAbstractNoPIOClass describeThePEGGeneralFFVVertex("ThePEG::GeneralFFVVertex", "libThePEG.so"); void GeneralFFVVertex::Init() { static ClassDocumentation documentation ("The GeneralFFVVertex 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 GeneralFFVVertex::evaluate(Energy2 q2, const SpinorWaveFunction & sp, const SpinorBarWaveFunction & sbar, const VectorWaveFunction & vec) { // first calculate the couplings setCoupling(q2,sp.particle(),sbar.particle(),vec.particle()); const Complex ii(0.,1.); const complex zero(ZERO,ZERO); // 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 p0p3=vec. e()+vec.pz(); complex p0m3=vec. e()-vec.pz(); complex p1p2=vec.px()+ii*vec.py(); complex p1m2=vec.px()-ii*vec.py(); // get both the spinors in the same representation (using the default choice) Complex vertex(0.); // first the left piece as this is virtually always needed 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)); } // left sigma piece if(_leftSigma!=zero) { vertex -= Complex(ii * _leftSigma * (sbar.s1()*sp.s1()*(-vec. e()*vec.z() + vec.pz()*vec.t() -ii*(vec.py()*vec.x()-vec.px()*vec.y()))+ sbar.s2()*sp.s1()*( p1p2*e0p3 - p0p3*e1p2 ) + sbar.s1()*sp.s2()*( + p1m2*e0m3 - p0m3*e1m2 ) + sbar.s2()*sp.s2()*( vec. e()*vec.z() - vec.pz()*vec.t() -ii*(vec.px()*vec.y()-vec.py()*vec.x())))); } // right sigma piece if(_rightSigma!=zero) { vertex += Complex(ii * _rightSigma * (sbar.s3()*sp.s3()*(-vec.e()*vec.z()+vec.pz()*vec.t() -ii*(vec.px()*vec.y()-vec.py()*vec.x()))+ sbar.s4()*sp.s3()*( p1p2*e0m3 - p0m3*e1p2 ) + sbar.s3()*sp.s4()*( p1m2*e0p3 - p0p3*e1m2 ) + sbar.s4()*sp.s4()*( vec.e()*vec.z()-vec.pz()*vec.t() +ii*(vec.px()*vec.y()-vec.py()*vec.x())))); } vertex *= ii; // final factors return vertex*norm(); } // evaluate an off-shell spinor SpinorWaveFunction GeneralFFVVertex::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(); // first calculate the couplings setCoupling(q2,Psp,out,Pvec); const Complex ii(0.,1.); const complex zero(ZERO,ZERO); // work out the momentum of the off-shell particle Lorentz5Momentum pout = sp.momentum()+vec.momentum(); // 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 p0p3 = pout.e() + pout.z(); complex p0m3 = pout.e() - pout.z(); 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.); Complex a1 = fact*( sp.s3()*e0m3-sp.s4()*e1m2); Complex a2 = fact*(-sp.s3()*e1p2+sp.s4()*e0p3); Complex a3 = fact*( sp.s1()*e0p3+sp.s2()*e1m2); Complex a4 = fact*( sp.s1()*e1p2+sp.s2()*e0m3); // left piece if(_left!=0.) { s1 += Complex(UnitRemoval::InvE * _left * (p0m3*a3-p1m2*a4)); s2 += Complex(UnitRemoval::InvE * _left * (-p1p2*a3+p0p3*a4)); s3 += Complex(UnitRemoval::InvE * _left * a3*mass); s4 += Complex(UnitRemoval::InvE * _left * a4*mass); } // right piece if(_right!=0.) { s1 += Complex(UnitRemoval::InvE * _right * a1*mass); s2 += Complex(UnitRemoval::InvE * _right * a2*mass); s3 += Complex(UnitRemoval::InvE * _right * (p0p3*a1+p1m2*a2)); s4 += Complex(UnitRemoval::InvE * _right * (p1p2*a1+p0m3*a2)); } complex p0p3b = vec. e() + vec.pz(); complex p0m3b = vec. e() - vec.pz(); complex p1p2b = vec.px() + ii*vec.py(); complex p1m2b = vec.px() - ii*vec.py(); complex b1 = fact*( sp.s3()*p0m3b - sp.s4()*p1m2b); complex b2 = fact*(-sp.s3()*p1p2b + sp.s4()*p0p3b); complex b3 = fact*( sp.s1()*p0p3b + sp.s2()*p1m2b); complex b4 = fact*( sp.s1()*p1p2b + sp.s2()*p0m3b); // left sigma piece if(_leftSigma!=zero) { s1 += Complex(-0.5*ii*UnitRemoval::InvE *mass*_leftSigma* ( - a3*p0m3b + a4*p1m2b + b3*e0m3 - b4*e1m2)); s2 += Complex( 0.5*ii*UnitRemoval::InvE *mass*_leftSigma* ( - a3*p1p2b + a4*p0p3b + b3*e1p2 - b4*e0p3)); s3 += Complex(-0.5*ii*UnitRemoval::InvE*_leftSigma* ( + p0p3*( - a3*p0m3b + a4*p1m2b + b3*e0m3 - b4*e1m2 ) + p1m2*( a3*p1p2b - a4*p0p3b - b3*e1p2 + b4*e0p3 ) )); s4 += Complex( 0.5*ii*UnitRemoval::InvE*_leftSigma* ( + p1p2*( + a3*p0m3b - a4*p1m2b - b3*e0m3 + b4*e1m2 ) + p0m3*( - a3*p1p2b + a4*p0p3b + b3*e1p2 - b4*e0p3 ) )); } // right sigma piece if(_rightSigma!=zero) { s1 +=Complex( 0.5*ii*UnitRemoval::InvE *_rightSigma* ( + p0m3*( + a1*p0p3b + a2*p1m2b - b1*e0p3 - b2*e1m2 ) + p1m2*( - a1*p1p2b - a2*p0m3b + b1*e1p2 + b2*e0m3 ) )); s2 +=Complex( -0.5*ii*UnitRemoval::InvE *_rightSigma* ( + p1p2*( + a1*p0p3b + a2*p1m2b - b1*e0p3 - b2*e1m2 ) + p0p3*( - a1*p1p2b - a2*p0m3b + b1*e1p2 + b2*e0m3 ) )); s3 += Complex( 0.5*ii*UnitRemoval::InvE *mass*_rightSigma* ( a1*p0p3b + a2*p1m2b - b1*e0p3 - b2*e1m2 )); s4 +=Complex( -0.5*ii*UnitRemoval::InvE *mass*_rightSigma* ( -a1*p1p2b - a2*p0m3b + b2*e0m3 + b1*e1p2 )); } // return the wavefunction return SpinorWaveFunction(pout,out,s1,s2,s3,s4); } // evaluate an off-shell SpinorBar SpinorBarWaveFunction GeneralFFVVertex::evaluate(Energy2 q2,int iopt,tcPDPtr out, const SpinorBarWaveFunction & sbar, const VectorWaveFunction & vec, complex mass, complex width) { // first calculate the couplings setCoupling(q2,out,sbar.particle(),vec.particle()); const Complex ii(0.,1.); const complex zero(ZERO,ZERO); // work out the momentum of the off-shell particle Lorentz5Momentum pout = sbar.momentum()+vec.momentum(); // 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 p0p3=pout.e() + pout.z(); complex p0m3=pout.e() - pout.z(); // complex numbers for the spinor Complex s1(0.),s2(0.),s3(0.),s4(0.); Complex a1 = fact*( sbar.s3()*e0p3+sbar.s4()*e1p2); Complex a2 = fact*( sbar.s3()*e1m2+sbar.s4()*e0m3); Complex a3 = fact*( sbar.s1()*e0m3-sbar.s2()*e1p2); Complex a4 = fact*(-sbar.s1()*e1m2+sbar.s2()*e0p3); complex p0p3b = vec. e() + vec.pz(); complex p0m3b = vec. e() - vec.pz(); complex p1p2b = vec.px() + ii*vec.py(); complex p1m2b = vec.px() - ii*vec.py(); complex b1 = fact*( sbar.s3()*p0p3b+sbar.s4()*p1p2b); complex b2 = fact*( sbar.s3()*p1m2b+sbar.s4()*p0m3b); complex b3 = fact*( sbar.s1()*p0m3b-sbar.s2()*p1p2b); complex b4 = fact*(-sbar.s1()*p1m2b+sbar.s2()*p0p3b); // left piece if(_left!=0.) { s1 += Complex(UnitRemoval::InvE*_left*a1*mass); s2 += Complex(UnitRemoval::InvE*_left*a2*mass); s3 += Complex(UnitRemoval::InvE*_left*(-p0m3*a1+p1p2*a2)); s4 += Complex(UnitRemoval::InvE*_left*(+p1m2*a1-p0p3*a2)); } // right piece if(_right!=0.) { s1 += Complex(UnitRemoval::InvE*_right*(-p0p3*a3-p1p2*a4)); s2 += Complex(UnitRemoval::InvE*_right*(-p1m2*a3-p0m3*a4)); s3 += Complex(UnitRemoval::InvE*_right*a3*mass); s4 += Complex(UnitRemoval::InvE*_right*a4*mass); } // left sigma piece if(_leftSigma!=zero) { s1 +=Complex( 0.5*ii*UnitRemoval::InvE*_leftSigma*mass* ( + a3*p0p3b + a4*p1p2b - b3*e0p3 - b4*e1p2)); s2 +=Complex( -0.5*ii*UnitRemoval::InvE*_leftSigma*mass* ( - a3*p1m2b - a4*p0m3b + b3*e1m2 + b4*e0m3)); s3 +=Complex( -0.5*ii*UnitRemoval::InvE*_leftSigma* (+p0m3*( + a3*p0p3b + a4*p1p2b - b3*e0p3 - b4*e1p2) +p1p2*( - a3*p1m2b - a4*p0m3b + b3*e1m2 + b4*e0m3))); s4 +=Complex( +0.5*ii*UnitRemoval::InvE*_leftSigma* (+p1m2*( + a3*p0p3b + a4*p1p2b - b3*e0p3 - b4*e1p2) +p0p3*( - a3*p1m2b - a4*p0m3b + b3*e1m2 + b4*e0m3))); } // right sigma piece if(_rightSigma!=zero) { s1 +=Complex( +0.5*ii*UnitRemoval::InvE*_rightSigma* (+p0p3*( - a1*p0m3b + a2*p1p2b + b1*e0m3 - b2*e1p2) +p1p2*( + a1*p1m2b - a2*p0p3b - b1*e1m2 + b2*e0p3))); s2 +=Complex( -0.5*ii*UnitRemoval::InvE*_rightSigma* (+p1m2*( + a1*p0m3b - a2*p1p2b - b1*e0m3 + b2*e1p2) +p0m3*( - a1*p1m2b + a2*p0p3b + b1*e1m2 - b2*e0p3))); s3 +=Complex( -0.5*ii*UnitRemoval::InvE*_rightSigma*mass* ( - a1*p0m3b + a2*p1p2b + b1*e0m3 - b2*e1p2 )); s4 +=Complex( 0.5*ii*UnitRemoval::InvE*_rightSigma*mass* ( - a1*p1m2b + a2*p0p3b + b1*e1m2 - b2*e0p3 )); } return SpinorBarWaveFunction(pout,out,s1,s2,s3,s4); } // off-shell vector VectorWaveFunction GeneralFFVVertex::evaluate(Energy2 q2,int iopt,tcPDPtr out, const SpinorWaveFunction & sp, const SpinorBarWaveFunction & sbar, complex mass, complex width) { // first calculate the couplings setCoupling(q2,sp.particle(),sbar.particle(),out); const Complex ii(0.,1.); const complex zero(ZERO,ZERO); // work out the momentum of the off-shell particle Lorentz5Momentum pout = sbar.momentum()+sp.momentum(); // 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]; complex p1p2=pout.x() + ii*pout.y(); complex p1m2=pout.x() - ii*pout.y(); complex p0p3=pout.e() + pout.z(); complex p0m3=pout.e() - pout.z(); // 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()); } // left sigma if(_leftSigma==zero) { vec[0] +=Complex( -0.5*ii*_leftSigma* (+sp.s1()*sbar.s1()*(p1p2-p1m2)+2.*sp.s1()*sbar.s2()*p0p3 -sp.s2()*sbar.s2()*(p1p2-p1m2)+2.*sp.s2()*sbar.s1()*p0m3)); vec[1] +=Complex( -0.5 *_leftSigma* (+sp.s1()*sbar.s1()*(p1m2-p1p2)+2.*sp.s1()*sbar.s2()*p0p3 +sp.s2()*sbar.s2()*(p1p2+p1m2)-2.*sp.s2()*sbar.s1()*p0m3)); vec[2] +=Complex( -0.5*ii*_leftSigma* (+sp.s1()*sbar.s1()*(p0p3+p0m3)-2.*sp.s1()*sbar.s2()*p1p2 -sp.s2()*sbar.s2()*(p0p3+p0m3)+2.*sp.s2()*sbar.s1()*p1m2)); vec[3] +=Complex( 0.5*ii*_leftSigma* (-sp.s1()*sbar.s1()*(p0p3-p0m3)-2.*sp.s1()*sbar.s2()*p1p2 +sp.s2()*sbar.s2()*(p0p3-p0m3)-2.*sp.s2()*sbar.s1()*p1m2)); } // right sigma if(_rightSigma==zero) { vec[0] +=Complex( 0.5*ii*_rightSigma* (-sp.s3()*sbar.s3()*(p1p2-p1m2)+2.*sp.s3()*sbar.s4()*p0m3 +sp.s4()*sbar.s4()*(p1p2-p1m2)+2.*sp.s4()*sbar.s3()*p0p3)); vec[1] +=Complex( 0.5* _rightSigma* (-sp.s3()*sbar.s3()*(p1p2+p1m2)-2.*sp.s3()*sbar.s4()*p0m3 +sp.s4()*sbar.s4()*(p1p2+p1m2)+2.*sp.s4()*sbar.s3()*p0p3)); vec[2] +=Complex( 0.5*ii*_rightSigma* (+sp.s3()*sbar.s3()*(p0p3+p0m3)+2.*sp.s3()*sbar.s4()*p1p2 -sp.s4()*sbar.s4()*(p0p3+p0m3)-2.*sp.s4()*sbar.s3()*p1m2)); vec[3] +=Complex( -0.5*ii*_rightSigma* (-sp.s3()*sbar.s3()*(p0p3-p0m3)-2.*sp.s3()*sbar.s4()*p1p2 +sp.s4()*sbar.s4()*(p0p3-p0m3)-2.*sp.s4()*sbar.s3()*p1m2)); } // 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]); } diff --git a/Helicity/Vertex/Vector/GeneralFFVVertex.h b/Helicity/Vertex/Vector/GeneralFFVVertex.h --- a/Helicity/Vertex/Vector/GeneralFFVVertex.h +++ b/Helicity/Vertex/Vector/GeneralFFVVertex.h @@ -1,225 +1,225 @@ // -*- C++ -*- // // GeneralFFVVertex.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_GeneralFFVVertex_H #define ThePEG_GeneralFFVVertex_H // // This is the declaration of the GeneralFFVVertex class. #include #include #include #include #include "GeneralFFVVertex.fh" namespace ThePEG { namespace Helicity{ /** \ingroup Helicity * * The GeneralFFVVertex class is the base class for all helicity amplitude * vertices which use a general form of the fermion-fermion-vector vertex. * * Any such vertices should inherit from this class and implement the virtual * setcoupling member function. The base AbstractFFVVertex class is * used to store the particles allowed to interact at the vertex. * * The form of the vertex is * \f[ic\bar{f_2}\gamma^\mu a^\lambda P_\lambda f_1\epsilon_{3\mu}\f] * * @see AbstractFFVVertex */ class GeneralFFVVertex: public AbstractFFVVertex { public: /** * Standard Init function used to initialize the interfaces. */ static void Init(); /** * Members to calculate the helicity amplitude expressions for vertices * and off-shell particles. */ //@{ /** * Evalulate the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param sp1 The wavefunction for the ferimon. * @param sbar2 The wavefunction for the antifermion. * @param vec3 The wavefunction for the vector. */ Complex evaluate(Energy2 q2,const SpinorWaveFunction & sp1, const SpinorBarWaveFunction & sbar2,const VectorWaveFunction & vec3); /** * Evaluate the off-shell barred spinor coming from the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param iopt Option of the shape of the Breit-Wigner for the off-shell barred spinor. * @param out The ParticleData pointer for the off-shell barred spinor. * @param sbar2 The wavefunction for the antifermion. * @param vec3 The wavefunction for the vector. * @param mass The mass of the off-shell particle if not taken from the ParticleData * object * @param width The width of the off-shell particle if not taken from the ParticleData * object */ SpinorBarWaveFunction evaluate(Energy2 q2,int iopt,tcPDPtr out, const SpinorBarWaveFunction & sbar2, const VectorWaveFunction & vec3, complex mass=-GeV, complex width=-GeV); /** * Evaluate the off-shell vector coming from the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param iopt Option of the shape of the Breit-Wigner for the off-shell vector. * @param out The ParticleData pointer for the off-shell vector. * @param sp1 The wavefunction for the ferimon. * @param sbar2 The wavefunction for the antifermion. * @param mass The mass of the off-shell particle if not taken from the ParticleData * object * @param width The width of the off-shell particle if not taken from the ParticleData * object */ VectorWaveFunction evaluate(Energy2 q2,int iopt,tcPDPtr out, const SpinorWaveFunction & sp1, const SpinorBarWaveFunction & sbar2, complex mass=-GeV, complex width=-GeV); /** * Evaluate the off-shell spinor coming from the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param iopt Option of the shape of the Breit-Wigner for the off-shell spinor. * @param out The ParticleData pointer for the off-shell spinor. * @param sp1 The wavefunction for the ferimon. * @param vec3 The wavefunction for the vector. * @param mass The mass of the off-shell particle if not taken from the ParticleData * object * @param width The width of the off-shell particle if not taken from the ParticleData * object */ SpinorWaveFunction evaluate(Energy2 q2,int iopt,tcPDPtr out, const SpinorWaveFunction & sp1, const VectorWaveFunction & vec3, complex mass=-GeV, complex width=-GeV); //@} /** * 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; /** * Dummy setCouplings for a four point interaction * This method is virtual and must be implemented in * classes inheriting from this. */ virtual void setCoupling(Energy2,tcPDPtr,tcPDPtr,tcPDPtr,tcPDPtr) { assert(false); } //@} /** * Get the Couplings */ //@{ /** * Get the left coupling. */ const Complex & getLeft() { return _left; } /** * Get the right coupling. */ const Complex & getRight() { return _right; } /** * Get the left coupling for the \f$\sigma^{\mu\nu}\f$ term */ const complex getLeftSigma() { return _leftSigma; } /** * Get the right coupling for the \f$\sigma^{\mu\nu}\f$ term */ const complex getRightSigma() { return _rightSigma; } //@} protected: /** * Set the couplings */ //@{ /** * Set the left coupling. */ void setLeft(const Complex & in) { _left = in; } /** * Set the right coupling. */ void setRight(const Complex & in) { _right = in; } /** * Set the left coupling for the \f$\sigma^{\mu\nu}\f$ term */ void setLeftSigma(const complex & in) { _leftSigma = in; } /** * Set the right coupling for the \f$\sigma^{\mu\nu}\f$ term */ void setRightSigma(const complex & in) { _rightSigma = in; } //@} private: /** * Private and non-existent assignment operator. */ GeneralFFVVertex & operator=(const GeneralFFVVertex &) = delete; private: /** * Left \f$\gamma^\mu\f$ coupling. */ Complex _left; /** * Right \f$\gamma^\mu\f$ coupling. */ Complex _right; /** * Left \f$\sigma^{\mu\nu}\f$ coupling */ complex _leftSigma; /** * Right \f$\sigma^{\mu\nu}\f$ coupling */ complex _rightSigma; }; } } #endif /* ThePEG_GeneralFFVVertex_H */ diff --git a/Helicity/Vertex/Vector/RFVVertex.cc b/Helicity/Vertex/Vector/RFVVertex.cc --- a/Helicity/Vertex/Vector/RFVVertex.cc +++ b/Helicity/Vertex/Vector/RFVVertex.cc @@ -1,124 +1,124 @@ // -*- C++ -*- // // RFVVertex.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the RFVVertex class. // #include "RFVVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" using namespace ThePEG; using namespace Helicity; // Definition of the static class description member // The following static variable is needed for the type // description system in ThePEG. DescribeAbstractNoPIOClass describeThePEGRFVVertex("ThePEG::RFVVertex", "libThePEG.so"); void RFVVertex::Init() { static ClassDocumentation documentation ("The RFVVertex class implements the helicity amplitude" "calculations for a spin-3/2 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"); } Complex RFVVertex::evaluate(Energy2 q2,const RSSpinorWaveFunction & sp, const SpinorBarWaveFunction & sbar, const VectorWaveFunction & vec) { // calculate the couplings setCoupling(q2,sp.particle(),sbar.particle(),vec.particle()); LorentzSpinor wdot1 = sp.wave().dot(vec.wave()); Complex lS1 = wdot1. leftScalar(sbar.wave()); Complex rS1 = wdot1.rightScalar(sbar.wave()); LorentzSpinor wdot2 = sp.wave().dot(sbar.momentum()); Complex lS2 = wdot2. leftCurrent(sbar.wave()).dot(vec.wave()); Complex rS2 = wdot2.rightCurrent(sbar.wave()).dot(vec.wave()); swap(lS2,rS2); Complex dot = sbar.momentum().dot(vec.wave())*UnitRemoval::InvE; Complex lS3 = wdot2. leftScalar(sbar.wave())*dot; Complex rS3 = wdot2.rightScalar(sbar.wave())*dot; return Complex(0.,1.)*norm()* (lS1*left()[0]+rS1*right()[0]+ lS2*left()[1]+rS2*right()[1]+ lS3*left()[2]+rS3*right()[2]); } Complex RFVVertex::evaluate(Energy2 q2,const SpinorWaveFunction & sp, const RSSpinorBarWaveFunction & sbar, const VectorWaveFunction & vec) { // calculate the couplings setCoupling(q2,sbar.particle(),sp.particle(),vec.particle()); LorentzSpinorBar wdot1 = sbar.wave().dot(vec.wave()); Complex lS1 = sp.wave(). leftScalar(wdot1); Complex rS1 = sp.wave().rightScalar(wdot1); LorentzSpinorBar wdot2 = sbar.wave().dot(sp.momentum()); Complex lS2 = sp.wave(). leftCurrent(wdot2).dot(vec.wave()); Complex rS2 = sp.wave().rightCurrent(wdot2).dot(vec.wave()); Complex dot = sbar.momentum().dot(vec.wave())*UnitRemoval::InvE; Complex lS3 = sp.wave(). leftScalar(wdot2)*dot; Complex rS3 = sp.wave().rightScalar(wdot2)*dot; return Complex(0.,1.)*norm()* (lS1*left()[0]+rS1*right()[0]+ lS2*left()[1]+rS2*right()[1]+ lS3*left()[2]+rS3*right()[2]); } SpinorBarWaveFunction RFVVertex::evaluate(Energy2 ,int ,tcPDPtr , const RSSpinorBarWaveFunction & , const VectorWaveFunction & , complex , complex ) { assert(false); return SpinorBarWaveFunction(); } RSSpinorBarWaveFunction RFVVertex::evaluate(Energy2 ,int ,tcPDPtr , const SpinorBarWaveFunction & , const VectorWaveFunction & , complex , complex ) { assert(false); return RSSpinorBarWaveFunction(); } VectorWaveFunction RFVVertex::evaluate(Energy2 ,int ,tcPDPtr , const RSSpinorWaveFunction & , const SpinorBarWaveFunction & , complex , complex ) { assert(false); return VectorWaveFunction(); } VectorWaveFunction RFVVertex::evaluate(Energy2 ,int ,tcPDPtr , const SpinorWaveFunction & , const RSSpinorBarWaveFunction & , complex , complex ) { assert(false); return VectorWaveFunction(); } RSSpinorWaveFunction RFVVertex::evaluate(Energy2 ,int ,tcPDPtr , const SpinorWaveFunction & , const VectorWaveFunction & , complex , complex ) { assert(false); return RSSpinorWaveFunction(); } SpinorWaveFunction RFVVertex::evaluate(Energy2 ,int ,tcPDPtr , const RSSpinorWaveFunction & , const VectorWaveFunction & , complex , complex ) { assert(false); return SpinorWaveFunction(); } diff --git a/Helicity/Vertex/Vector/RFVVertex.h b/Helicity/Vertex/Vector/RFVVertex.h --- a/Helicity/Vertex/Vector/RFVVertex.h +++ b/Helicity/Vertex/Vector/RFVVertex.h @@ -1,264 +1,264 @@ // -*- C++ -*- // // RFVVertex.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_RFVVertex_H #define ThePEG_RFVVertex_H // // This is the declaration of the RFVVertex class. #include #include #include #include #include "RFVVertex.fh" namespace ThePEG { namespace Helicity{ /** \ingroup Helicity * * The RFVVertex class is the base class for all helicity amplitude * vertices which use the renormalisable form for the * spin-3/2 fermion-fermion-vector vertex. * * Any such vertices should inherit from this class and implement the virtual * setcoupling member function. The base AbstractRFVVertex class is used to store the * particles allowed to interact at the vertex. * * The form of the vertex is * \f[ic\bar{f_2}_\mu \left[ g^{\mu\nu} a^{1\lambda} P_\lambda * +\gamma^\nu p_{1}^\mu a^{2\lambda} P_\lambda * +p_{1}^\mu p_{2}^\nu a^{3\lambda} P_\lambda * \right]f_1\epsilon_{3\nu}\f] * * @see AbstractRFVVertex */ class RFVVertex: public AbstractRFVVertex { public: /** * Standard Init function used to initialize the interfaces. */ static void Init(); public: /** * Members to calculate the helicity amplitude expressions for vertices * and off-shell particles. */ //@{ /** * Evalulate the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param sp1 The wavefunction for the ferimon. * @param sbar2 The wavefunction for the antifermion. * @param vec3 The wavefunction for the vector. */ Complex evaluate(Energy2 q2,const RSSpinorWaveFunction & sp1, const SpinorBarWaveFunction & sbar2, const VectorWaveFunction & vec3); /** * Evalulate the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param sp1 The wavefunction for the ferimon. * @param sbar2 The wavefunction for the antifermion. * @param vec3 The wavefunction for the vector. */ Complex evaluate(Energy2 q2,const SpinorWaveFunction & sp1, const RSSpinorBarWaveFunction & sbar2, const VectorWaveFunction & vec3); /** * Evaluate the off-shell barred spinor coming from the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param iopt Option of the shape of the Breit-Wigner for the off-shell barred spinor. * @param out The ParticleData pointer for the off-shell barred spinor. * @param sbar2 The wavefunction for the antifermion. * @param vec3 The wavefunction for the vector. * @param mass The mass of the off-shell particle if not taken from the ParticleData * object * @param width The width of the off-shell particle if not taken from the ParticleData * object */ SpinorBarWaveFunction evaluate(Energy2 q2,int iopt,tcPDPtr out, const RSSpinorBarWaveFunction & sbar2, const VectorWaveFunction & vec3, complex mass=-GeV, complex width=-GeV); /** * Evaluate the off-shell barred spinor coming from the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param iopt Option of the shape of the Breit-Wigner for the off-shell barred spinor. * @param out The ParticleData pointer for the off-shell barred spinor. * @param sbar2 The wavefunction for the antifermion. * @param vec3 The wavefunction for the vector. * @param mass The mass of the off-shell particle if not taken from the ParticleData * object * @param width The width of the off-shell particle if not taken from the ParticleData * object */ RSSpinorBarWaveFunction evaluate(Energy2 q2,int iopt,tcPDPtr out, const SpinorBarWaveFunction & sbar2, const VectorWaveFunction & vec3, complex mass=-GeV, complex width=-GeV); /** * Evaluate the off-shell vector coming from the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param iopt Option of the shape of the Breit-Wigner for the off-shell vector. * @param out The ParticleData pointer for the off-shell vector. * @param sp1 The wavefunction for the ferimon. * @param sbar2 The wavefunction for the antifermion. * @param mass The mass of the off-shell particle if not taken from the ParticleData * object * @param width The width of the off-shell particle if not taken from the ParticleData * object */ VectorWaveFunction evaluate(Energy2 q2,int iopt,tcPDPtr out, const RSSpinorWaveFunction & sp1, const SpinorBarWaveFunction & sbar2, complex mass=-GeV, complex width=-GeV); /** * Evaluate the off-shell vector coming from the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param iopt Option of the shape of the Breit-Wigner for the off-shell vector. * @param out The ParticleData pointer for the off-shell vector. * @param sp1 The wavefunction for the ferimon. * @param sbar2 The wavefunction for the antifermion. * @param mass The mass of the off-shell particle if not taken from the ParticleData * object * @param width The width of the off-shell particle if not taken from the ParticleData * object */ VectorWaveFunction evaluate(Energy2 q2,int iopt,tcPDPtr out, const SpinorWaveFunction & sp1, const RSSpinorBarWaveFunction & sbar2, complex mass=-GeV, complex width=-GeV); /** * Evaluate the off-shell spinor coming from the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param iopt Option of the shape of the Breit-Wigner for the off-shell spinor. * @param out The ParticleData pointer for the off-shell spinor. * @param sp1 The wavefunction for the ferimon. * @param vec3 The wavefunction for the vector. * @param mass The mass of the off-shell particle if not taken from the ParticleData * object * @param width The width of the off-shell particle if not taken from the ParticleData * object */ RSSpinorWaveFunction evaluate(Energy2 q2,int iopt,tcPDPtr out, const SpinorWaveFunction & sp1, const VectorWaveFunction & vec3, complex mass=-GeV, complex width=-GeV); /** * Evaluate the off-shell spinor coming from the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param iopt Option of the shape of the Breit-Wigner for the off-shell spinor. * @param out The ParticleData pointer for the off-shell spinor. * @param sp1 The wavefunction for the ferimon. * @param vec3 The wavefunction for the vector. * @param mass The mass of the off-shell particle if not taken from the ParticleData * object * @param width The width of the off-shell particle if not taken from the ParticleData * object */ SpinorWaveFunction evaluate(Energy2 q2,int iopt,tcPDPtr out, const RSSpinorWaveFunction & sp1, const VectorWaveFunction & vec3, complex mass=-GeV, complex width=-GeV); //@} /** * 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; /** * Dummy setCouplings for a four point interaction * This method is virtual and must be implemented in * classes inheriting from this. */ virtual void setCoupling(Energy2,tcPDPtr,tcPDPtr,tcPDPtr,tcPDPtr) { assert(false); } //@} /** * Get the Couplings */ //@{ /** * Get the left coupling. */ const vector & left() const { return _left; } /** * Get the right coupling. */ const vector & right() const { return _right; } //@} protected: /** * Set the couplings */ //@{ /** * Set the left coupling. */ void left(const vector & in) { _left = in; } /** * Set the right coupling. */ void right(const vector & in) { _right = in; } //@} private: /** * Private and non-existent assignment operator. */ RFVVertex & operator=(const RFVVertex &) = delete; private: /** * Left coupling. */ vector _left; /** * Right coupling. */ vector _right; }; } } #endif /* ThePEG_RFVVertex_H */ diff --git a/Helicity/Vertex/Vector/VVVVVertex.cc b/Helicity/Vertex/Vector/VVVVVertex.cc --- a/Helicity/Vertex/Vector/VVVVVertex.cc +++ b/Helicity/Vertex/Vector/VVVVVertex.cc @@ -1,313 +1,313 @@ // -*- C++ -*- // // VVVVVertex.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the VVVVVertex class. // #include "VVVVVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" using namespace ThePEG; using namespace Helicity; // The following static variable is needed for the type // description system in ThePEG. DescribeAbstractNoPIOClass describeThePEGVVVVVertex("ThePEG::VVVVVertex", "libThePEG.so"); void VVVVVertex::Init() { static ClassDocumentation documentation ("The VVVVVertex class is the implementation of the 4-vector vertex"); } // calculate the vertex Complex VVVVVertex::evaluate(Energy2 q2 , int iopt, const VectorWaveFunction & vec1, const VectorWaveFunction & vec2, const VectorWaveFunction & vec3, const VectorWaveFunction & vec4) { // workout the coupling setCoupling(q2,vec1.particle(),vec2.particle(), vec3.particle(),vec4.particle()); Complex vertex,ii(0.,1.); // calculate the vertex // QCD type vertex assert(_itype>=1&&_itype<=2); if(_itype==1) { // dot products we need Complex dotv1v2 = vec1.wave().dot(vec2.wave()); Complex dotv3v4 = vec3.wave().dot(vec4.wave()); Complex dotv1v4 = vec1.wave().dot(vec4.wave()); Complex dotv2v3 = vec3.wave().dot(vec2.wave()); // first the 4-point part of the vertex vertex = dotv1v2*dotv3v4-dotv1v4*dotv2v3; // now the virtual gluon exchange if needed if(iopt!=0) { // dot products Complex dotv1v3 = vec1.wave().dot(vec3.wave()); Complex dotv2v4 = vec4.wave().dot(vec2.wave()); complex dotv1p13 = vec1.wave().dot(2.*vec3.momentum() + vec1.momentum()); complex dotv2p24 = vec2.wave().dot(2.*vec4.momentum() + vec2.momentum()); complex dotv3p13 = vec3.wave().dot(2.*vec1.momentum() + vec3.momentum()); complex dotv4p24 = vec4.wave().dot(2.*vec2.momentum() + vec4.momentum()); LorentzPolarizationVectorE veca = dotv3p13*vec1.wave() - dotv1p13*vec3.wave() + dotv1v3*(vec3.momentum()-vec1.momentum()); LorentzPolarizationVectorE vecb = dotv4p24*vec2.wave() - dotv2p24*vec4.wave() + dotv2v4*(vec4.momentum()-vec2.momentum()); InvEnergy2 numerator = 1./(vec1.momentum()+vec3.momentum()).m2(); vertex += Complex(numerator*veca.dot(vecb)); } } // EW type vertex else if(_itype==2) { Complex dotv1v2 = vec1.wave().dot(vec2.wave()); Complex dotv1v3 = vec1.wave().dot(vec3.wave()); Complex dotv1v4 = vec1.wave().dot(vec4.wave()); Complex dotv2v3 = vec2.wave().dot(vec3.wave()); Complex dotv2v4 = vec2.wave().dot(vec4.wave()); Complex dotv3v4 = vec3.wave().dot(vec4.wave()); // evaluate the vertex // need to sort the order out here if(( _iorder[0]==0 && _iorder[1]==1 && _iorder[2]==2 && _iorder[3]==3)|| ( _iorder[0]==1 && _iorder[1]==0 && _iorder[2]==2 && _iorder[3]==3)|| ( _iorder[0]==0 && _iorder[1]==1 && _iorder[2]==3 && _iorder[3]==2)|| ( _iorder[0]==1 && _iorder[1]==0 && _iorder[2]==3 && _iorder[3]==2)|| ( _iorder[0]==2 && _iorder[1]==3 && _iorder[2]==0 && _iorder[3]==1)|| ( _iorder[0]==2 && _iorder[1]==3 && _iorder[2]==1 && _iorder[3]==0)|| ( _iorder[0]==3 && _iorder[1]==2 && _iorder[2]==0 && _iorder[3]==1)|| ( _iorder[0]==3 && _iorder[1]==2 && _iorder[2]==1 && _iorder[3]==0)) { // contact term vertex = 2.*dotv1v2*dotv3v4-dotv1v3*dotv2v4-dotv1v4*dotv2v3; // now for the u- and t-channel terms if needed if(iopt!=0) { // dot products of momenta and wavefunction complex dotv1p13 = +vec1.wave().dot(vec1.momentum() + 2.*vec3.momentum() ); complex dotv1p14 = +vec1.wave().dot(vec1.momentum() + 2.*vec4.momentum() ); complex dotv2p23 = +vec2.wave().dot(vec2.momentum() + 2.*vec3.momentum() ); complex dotv2p24 = +vec2.wave().dot(vec2.momentum() + 2.*vec4.momentum() ); complex dotv3p31 = +vec3.wave().dot(vec3.momentum() + 2.*vec1.momentum() ); complex dotv3p32 = +vec3.wave().dot(vec3.momentum() + 2.*vec2.momentum() ); complex dotv4p41 = +vec4.wave().dot(vec4.momentum() + 2.*vec1.momentum() ); complex dotv4p42 = +vec4.wave().dot(vec4.momentum() + 2.*vec2.momentum() ); LorentzPolarizationVectorE ja = (vec3.momentum()-vec1.momentum())*dotv1v3 +dotv3p31*vec1.wave()-dotv1p13*vec3.wave(); LorentzPolarizationVectorE jb = (vec4.momentum()-vec2.momentum())*dotv2v4 +dotv4p42*vec2.wave()-dotv2p24*vec4.wave(); LorentzPolarizationVectorE jc = (vec4.momentum()-vec1.momentum())*dotv1v4 +dotv4p41*vec1.wave()-dotv1p14*vec4.wave(); LorentzPolarizationVectorE jd = (vec3.momentum()-vec2.momentum())*dotv2v3 +dotv3p32*vec2.wave()-dotv2p23*vec3.wave(); // dot products of these vectors complex dotjajb = ja.dot(jb); complex dotjcjd = jc.dot(jd); complex dotjaq = ja.dot(vec1.momentum()+vec3.momentum()); complex dotjbq = jb.dot(vec1.momentum()+vec3.momentum()); complex dotjck = jc.dot(vec1.momentum()+vec4.momentum()); complex dotjdk = jd.dot(vec1.momentum()+vec4.momentum()); Energy2 q2 = (vec1.momentum()+vec3.momentum()).m2(); Energy2 k2 = (vec1.momentum()+vec4.momentum()).m2(); // compute the term we need Energy2 mass2; for(int ix=0;ix<2;++ix) { if(_inter[ix]) { mass2 = sqr(_inter[ix]->mass()); if(mass2!=Energy2()) { vertex += Complex(UnitRemoval::InvE2 * _coup[ix]*propagator(iopt,q2,_inter[ix])* (dotjajb-dotjaq*dotjbq/mass2)); vertex += Complex(UnitRemoval::InvE2 * _coup[ix]*propagator(iopt,k2,_inter[ix])* (dotjcjd-dotjck*dotjdk/mass2)); } else { vertex+= Complex(UnitRemoval::InvE2 *_coup[ix]* propagator(iopt,q2,_inter[ix])*dotjajb); vertex+= Complex(UnitRemoval::InvE2 *_coup[ix]* propagator(iopt,k2,_inter[ix])*dotjcjd); } } } } } else if(( _iorder[0]==0 && _iorder[1]==2 && _iorder[2]==1 && _iorder[3]==3)|| ( _iorder[0]==2 && _iorder[1]==0 && _iorder[2]==1 && _iorder[3]==3)|| ( _iorder[0]==0 && _iorder[1]==2 && _iorder[2]==3 && _iorder[3]==1)|| ( _iorder[0]==2 && _iorder[1]==0 && _iorder[2]==3 && _iorder[3]==1)|| ( _iorder[0]==1 && _iorder[1]==3 && _iorder[2]==0 && _iorder[3]==2)|| ( _iorder[0]==1 && _iorder[1]==3 && _iorder[2]==2 && _iorder[3]==0)|| ( _iorder[0]==3 && _iorder[1]==1 && _iorder[2]==0 && _iorder[3]==2)|| ( _iorder[0]==3 && _iorder[1]==1 && _iorder[2]==2 && _iorder[3]==0)) { // contact term vertex = 2.*dotv1v3*dotv2v4-dotv1v2*dotv3v4-dotv1v4*dotv2v3; // now for the u- and t-channel terms if needed if(iopt!=0) { // dot products of momenta and wavefunction complex dotv1p12 = vec1.wave().dot(vec1.momentum() + 2.*vec2.momentum() ); complex dotv1p14 = vec1.wave().dot(vec1.momentum() + 2.*vec4.momentum() ); complex dotv3p32 = vec3.wave().dot(vec3.momentum() + 2.*vec2.momentum() ); complex dotv3p34 = vec3.wave().dot(vec3.momentum() + 2.*vec4.momentum() ); complex dotv2p21 = vec2.wave().dot(vec2.momentum() + 2.*vec1.momentum() ); complex dotv2p23 = vec2.wave().dot(vec2.momentum() + 2.*vec3.momentum() ); complex dotv4p41 = vec4.wave().dot(vec4.momentum() + 2.*vec1.momentum() ); complex dotv4p43 = vec4.wave().dot(vec4.momentum() + 2.*vec3.momentum() ); LorentzPolarizationVectorE ja = (vec2.momentum() - vec1.momentum() )*dotv1v2 + dotv2p21*vec1.wave() - dotv1p12*vec2.wave(); LorentzPolarizationVectorE jb = (vec4.momentum() - vec3.momentum())*dotv3v4 + dotv4p43*vec3.wave() - dotv3p34*vec4.wave(); LorentzPolarizationVectorE jc = (vec4.momentum() - vec1.momentum())*dotv1v4 + dotv4p41*vec1.wave() - dotv1p14*vec4.wave(); LorentzPolarizationVectorE jd = (vec2.momentum() - vec3.momentum())*dotv2v3 + dotv2p23*vec3.wave() - dotv3p32*vec2.wave(); // dot products of these vectors complex dotjajb = ja.dot(jb); complex dotjcjd = jc.dot(jd); complex dotjaq = ja.dot(vec1.momentum()+vec2.momentum()); complex dotjbq = jb.dot(vec1.momentum()+vec2.momentum()); complex dotjck = jc.dot(vec1.momentum()+vec4.momentum()); complex dotjdk = jd.dot(vec1.momentum()+vec4.momentum()); Energy2 q2 = (vec1.momentum()+vec2.momentum()).m2(); Energy2 k2 = (vec1.momentum()+vec4.momentum()).m2(); // compute the term we need Energy2 mass2; for(int ix=0;ix<2;++ix) { if(_inter[ix]) { mass2 = (_inter[ix]->mass())*(_inter[ix]->mass()); if(mass2!=Energy2()) { vertex+=Complex(UnitRemoval::InvE2 * _coup[ix]*propagator(iopt,q2,_inter[ix])* (dotjajb-dotjaq*dotjbq/mass2)); vertex+=Complex(UnitRemoval::InvE2 * _coup[ix]*propagator(iopt,k2,_inter[ix])* (dotjcjd-dotjck*dotjdk/mass2)); } else { vertex+=Complex(UnitRemoval::InvE2 *_coup[ix]* propagator(iopt,q2,_inter[ix])*dotjajb); vertex+=Complex(UnitRemoval::InvE2 *_coup[ix]* propagator(iopt,k2,_inter[ix])*dotjcjd); } } } } } else if(( _iorder[0]==0 && _iorder[1]==3 && _iorder[2]==1 && _iorder[3]==2)|| ( _iorder[0]==3 && _iorder[1]==0 && _iorder[2]==1 && _iorder[3]==2)|| ( _iorder[0]==0 && _iorder[1]==3 && _iorder[2]==2 && _iorder[3]==1)|| ( _iorder[0]==3 && _iorder[1]==0 && _iorder[2]==2 && _iorder[3]==1)|| ( _iorder[0]==1 && _iorder[1]==2 && _iorder[2]==0 && _iorder[3]==3)|| ( _iorder[0]==2 && _iorder[1]==1 && _iorder[2]==0 && _iorder[3]==3)|| ( _iorder[0]==1 && _iorder[1]==2 && _iorder[2]==3 && _iorder[3]==0)|| ( _iorder[0]==2 && _iorder[1]==1 && _iorder[2]==3 && _iorder[3]==0)) { // contact term vertex = 2.*dotv1v4*dotv2v3-dotv1v3*dotv2v4-dotv1v2*dotv3v4; // now for the u- and t-channel terms if needed if(iopt!=0) { // dot products of momenta and wavefunction complex dotv1p12 = vec1.wave().dot(vec1.momentum() + 2.*vec2.momentum() ); complex dotv1p13 = vec1.wave().dot(vec1.momentum() + 2.*vec3.momentum() ); complex dotv2p24 = vec2.wave().dot(vec2.momentum() + 2.*vec4.momentum() ); complex dotv2p21 = vec2.wave().dot(vec2.momentum() + 2.*vec1.momentum() ); complex dotv3p31 = vec3.wave().dot(vec3.momentum() + 2.*vec1.momentum() ); complex dotv3p34 = vec3.wave().dot(vec3.momentum() + 2.*vec4.momentum() ); complex dotv4p43 = vec4.wave().dot(vec4.momentum() + 2.*vec3.momentum() ); complex dotv4p42 = vec4.wave().dot(vec4.momentum() + 2.*vec2.momentum() ); LorentzPolarizationVectorE ja = (vec2.momentum()-vec1.momentum())*dotv1v2 +dotv2p21*vec1.wave()-dotv1p12*vec2.wave(); LorentzPolarizationVectorE jb = (vec3.momentum()-vec4.momentum())*dotv3v4 +dotv3p34*vec4.wave()-dotv4p43*vec3.wave(); LorentzPolarizationVectorE jc = (vec3.momentum()-vec1.momentum())*dotv1v3 +dotv3p31*vec1.wave()-dotv1p13*vec3.wave(); LorentzPolarizationVectorE jd = (vec2.momentum()-vec4.momentum())*dotv2v4 +dotv2p24*vec4.wave()-dotv4p42*vec2.wave(); // dot products of these vectors complex dotjajb = ja.dot(jb); complex dotjcjd = jc.dot(jd); complex dotjaq = ja.dot(vec1.momentum()+vec2.momentum()); complex dotjbq = jb.dot(vec1.momentum()+vec2.momentum()); complex dotjck = jc.dot(vec1.momentum()+vec3.momentum()); complex dotjdk = jd.dot(vec1.momentum()+vec3.momentum()); Energy2 q2 = (vec1.momentum()+vec2.momentum()).m2(); Energy2 k2 = (vec1.momentum()+vec3.momentum()).m2(); // compute the term we need Energy2 mass2; for(int ix=0;ix<2;++ix) { if(_inter[ix]) { mass2 = sqr(_inter[ix]->mass()); if(mass2!=Energy2()) { vertex+=Complex(UnitRemoval::InvE2 * _coup[ix]*propagator(iopt,q2,_inter[ix])* (dotjajb-dotjaq*dotjbq/mass2)); vertex+=Complex(UnitRemoval::InvE2 * _coup[ix]*propagator(iopt,k2,_inter[ix])* (dotjcjd-dotjck*dotjdk/mass2)); } else { vertex+=Complex(UnitRemoval::InvE2 *_coup[ix]* propagator(iopt,q2,_inter[ix])*dotjajb); vertex+=Complex(UnitRemoval::InvE2 *_coup[ix]* propagator(iopt,k2,_inter[ix])*dotjcjd); } } } } } else throw HelicityConsistencyError() << "Unknown order of particles in " << "VVVVVertex::evaluate()" << Exception::runerror; } // return the answer return -ii*norm()*vertex; } diff --git a/Helicity/Vertex/Vector/VVVVVertex.h b/Helicity/Vertex/Vector/VVVVVertex.h --- a/Helicity/Vertex/Vector/VVVVVertex.h +++ b/Helicity/Vertex/Vector/VVVVVertex.h @@ -1,169 +1,169 @@ // -*- C++ -*- // // VVVVVertex.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_VVVVVertex_H #define ThePEG_VVVVVertex_H // // This is the declaration of the VVVVVertex class. #include "ThePEG/Helicity/Vertex/AbstractVVVVVertex.h" #include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h" #include "VVVVVertex.fh" namespace ThePEG { namespace Helicity{ /** \ingroup Helicity * * This is the implementation of the four vector vertex. * It is based on the AbstractVVVVVertex class for the storage of particles * which are allowed to interact at the vertex. * Classes implementation a specific vertex should inherit from this * one and implement the virtual setCoupling member. * * The form of the vertex is * \f[ic^2\left[ * 2\epsilon_1\cdot\epsilon_2\epsilon_3\cdot\epsilon_4- * \epsilon_1\cdot\epsilon_3\epsilon_2\cdot\epsilon_4- * \epsilon_1\cdot\epsilon_4\epsilon_2\cdot\epsilon_3 * \right]\f] * optional the additional diagrams from the three point vertices can be included. * * @see AbstractVVVVVertex */ class VVVVVertex: public AbstractVVVVVertex { public: /** * Standard Init function used to initialize the interfaces. */ static void Init(); public: /** * Members to calculate the helicity amplitude expressions for vertices * and off-shell particles. */ //@{ /** * Evaluate the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param iopt Evaluation option, 0 just evaluate the four point vertex, 1 * include all the three point diagrams as well. * @param vec1 The wavefunction for the first vector. * @param vec2 The wavefunction for the second vector. * @param vec3 The wavefunction for the third vector. * @param vec4 The wavefunction for the fourth vector. */ Complex evaluate(Energy2 q2, int iopt, const VectorWaveFunction & vec1, const VectorWaveFunction & vec2, const VectorWaveFunction & vec3, const VectorWaveFunction & vec4); //@} /** * Set coupling methods */ //@{ /** * Dummy for a three point interaction. */ virtual void setCoupling(Energy2,tcPDPtr,tcPDPtr,tcPDPtr) { assert(false); } /** * 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: /** * Set the order of the particles. * @param id1 The PDG code of the first particle. * @param id2 The PDG code of the second particle. * @param id3 The PDG code of the third particle. * @param id4 The PDG code of the fourth particle. */ void setOrder(int id1,int id2,int id3,int id4) { _iorder[0]=id1; _iorder[1]=id2; _iorder[2]=id3; _iorder[3]=id4; } /** * Set the type of the vertex. * @param itype The type of vertex (QCD=1 or electroweak=2). */ void setType(int itype) { _itype=itype; } /** * Set the intermediate particles if including s/u/t channel terms. * @param part1 The ParticleData pointer for the first particle. * @param part2 The ParticleData pointer for the second particle. * @param c1 The coupling for the first particle. * @param c2 The coupling for the second particle. */ void setIntermediate(tcPDPtr part1,tcPDPtr part2,Complex c1,Complex c2) { _inter[0]=part1; _inter[1]=part2; _coup[0]=c1; _coup[1]=c2; } private: /** * Private and non-existent assignment operator. */ VVVVVertex & operator=(const VVVVVertex &) = delete; private: /** * Type of vertex 1=QCD 2=EW. */ int _itype; /** * Order of the particles. */ array _iorder; /** * Intermediate particles */ array _inter; /** * Couplings of the intermediate particles. */ array _coup; }; } } namespace ThePEG { } #endif /* ThePEG_VVVVVertex_H */ diff --git a/Helicity/Vertex/Vector/VVVVertex.cc b/Helicity/Vertex/Vector/VVVVertex.cc --- a/Helicity/Vertex/Vector/VVVVertex.cc +++ b/Helicity/Vertex/Vector/VVVVertex.cc @@ -1,108 +1,108 @@ // -*- C++ -*- // // VVVVertex.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the VVVVertex class. // #include "VVVVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" using namespace ThePEG; using namespace Helicity; // The following static variable is needed for the type // description system in ThePEG. DescribeAbstractNoPIOClass describeThePEGVVVVertex("ThePEG::VVVVertex", "libThePEG.so"); void VVVVertex::Init() { static ClassDocumentation documentation ("The VVVVertex class implements the helicity amplitude" "calculations for the triple gauge boson vertex. Any " "implementation of such a vertex should inherit from in and implement" " the virtual setCoupling member to calculate the coupling"); } // evaluate the vertex Complex VVVVertex::evaluate(Energy2 q2, const VectorWaveFunction & vec1, const VectorWaveFunction & vec2, const VectorWaveFunction & vec3) { // calculate the coupling setCoupling(q2,vec1.particle(),vec2.particle(),vec3.particle()); complex alpha1(ZERO); // decide if we need to use special treatment to avoid gauge cancelations // first vector if(abs(vec1.t())!=0.) { if(abs(vec1.t())>0.1*max( max(abs(vec1.x()),abs(vec1.y())),abs(vec1.z()))) alpha1=vec1.e()/vec1.t(); } // second vector if(abs(vec2.t())!=0.) { if(abs(vec2.t())>0.1*max( max(abs(vec2.x()),abs(vec2.y())),abs(vec2.z()))) alpha1=vec2.e()/vec2.t(); } // third vector if(abs(vec3.t())!=0.) { if(abs(vec3.t())>0.1*max( max(abs(vec3.x()),abs(vec3.y())),abs(vec3.z()))) alpha1=vec3.e()/vec3.t(); } // dot products of the polarization vectors Complex dot12 = vec1.wave().dot(vec2.wave()); Complex dot13 = vec1.wave().dot(vec3.wave()); Complex dot23 = vec3.wave().dot(vec2.wave()); // dot products of polarization vectors and momentum complex dotp13 = vec3.wave().dot(LorentzPolarizationVectorE(vec1.momentum()) - alpha1 * vec1.wave()); complex dotp23 = vec3.wave().dot(LorentzPolarizationVectorE(vec2.momentum()) - alpha1 * vec2.wave()); complex dotp21 = vec1.wave().dot(LorentzPolarizationVectorE(vec2.momentum()) - alpha1 * vec2.wave()); complex dotp31 = vec1.wave().dot(LorentzPolarizationVectorE(vec3.momentum()) - alpha1 * vec3.wave()); complex dotp32 = vec2.wave().dot(LorentzPolarizationVectorE(vec3.momentum()) - alpha1 * vec3.wave()); complex dotp12 = vec2.wave().dot(LorentzPolarizationVectorE(vec1.momentum()) - alpha1 * vec1.wave()); // finally calculate the vertex return Complex(0.,1.)*norm()*UnitRemoval::InvE* (dot12*(dotp13-dotp23)+dot23*(dotp21-dotp31)+dot13*(dotp32-dotp12)); } // off-shell vector VectorWaveFunction VVVVertex::evaluate(Energy2 q2,int iopt, tcPDPtr out, const VectorWaveFunction & vec1, const VectorWaveFunction & vec2, complex mass, complex width) { // output momenta Lorentz5Momentum pout =vec1.momentum()+vec2.momentum(); // calculate the coupling setCoupling(q2,out,vec1.particle(),vec2.particle()); // prefactor Energy2 p2 = pout.m2(); Complex fact = norm()*propagator(iopt,p2,out,mass,width); if(mass.real() < ZERO) mass = out->mass(); complex mass2 = sqr(mass); // dot products we need Complex dot12 = vec1.wave().dot(vec2.wave()); complex dota = vec1.wave().dot(pout+vec2.momentum()); complex dotb = vec2.wave().dot(pout+vec1.momentum()); // compute the polarization vector LorentzPolarizationVector vect = UnitRemoval::InvE*fact* (dot12*(vec1.momentum()-vec2.momentum())-dotb*vec1.wave()+dota*vec2.wave()); // scalar piece for massive case if(mass.real()!=ZERO) { complex dot = vect.dot(pout)/mass2; vect -= dot*pout; } return VectorWaveFunction(pout,out,vect); } diff --git a/Helicity/Vertex/Vector/VVVVertex.h b/Helicity/Vertex/Vector/VVVVertex.h --- a/Helicity/Vertex/Vector/VVVVertex.h +++ b/Helicity/Vertex/Vector/VVVVertex.h @@ -1,121 +1,121 @@ // -*- C++ -*- // // VVVVertex.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_VVVVertex_H #define ThePEG_VVVVertex_H // // This is the declaration of the VVVVertex class. #include "ThePEG/Helicity/Vertex/AbstractVVVVertex.h" #include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h" #include "VVVVertex.fh" namespace ThePEG { namespace Helicity{ /** \ingroup Helicity * * The VVVVertex class is the base class for triple vector vertices * using the perturbative form. * It inherits from the AbstractVVVVertex class for the storage of the * particles allowed at the vertex. * * Classes which implement a specific vertex should inherit from this and * implement the virtual setCoupling member. * * The form of the vertex is * \f[ig\left[ (p_1-p_2)^\gamma g^{\alpha\beta } * +(p_2-p_3)^\alpha g^{\beta \gamma} * +(p_3-p_1)^\beta g^{\alpha\gamma} * \right]\epsilon_{1\alpha}\epsilon_{2\beta}\epsilon_{3\gamma}\f] * * @see AbstractVVVVertex */ class VVVVertex: public AbstractVVVVertex { public: /** * Standard Init function used to initialize the interfaces. */ static void Init(); public: /** * Members to calculate the helicity amplitude expressions for vertices * and off-shell particles. */ //@{ /** * Evaluate the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param vec1 The wavefunction for the first vector. * @param vec2 The wavefunction for the second vector. * @param vec3 The wavefunction for the third vector. */ Complex evaluate(Energy2 q2, const VectorWaveFunction & vec1, const VectorWaveFunction & vec2, const VectorWaveFunction & vec3); /** * Evaluate the off-shell vector coming from the vertex. * @param q2 The scale \f$q^2\f$ for the coupling at the vertex. * @param iopt Option of the shape of the Breit-Wigner for the off-shell vector. * @param out The ParticleData pointer for the off-shell vector. * @param vec2 The wavefunction for the second vector. * @param vec3 The wavefunction for the third vector. * @param mass The mass of the off-shell particle if not taken from the ParticleData * object * @param width The width of the off-shell particle if not taken from the ParticleData * object */ VectorWaveFunction evaluate(Energy2 q2,int iopt, tcPDPtr out, const VectorWaveFunction & vec2, const VectorWaveFunction & vec3, complex mass=-GeV, complex width=-GeV); //@} /** * 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; /** * Dummy setCouplings for a four point interaction * This method is virtual and must be implemented in * classes inheriting from this. */ virtual void setCoupling(Energy2,tcPDPtr,tcPDPtr,tcPDPtr,tcPDPtr) { assert(false); } //@} private: /** * Private and non-existent assignment operator. */ VVVVertex & operator=(const VVVVertex &) = delete; }; } } #endif /* ThePEG_VVVVertex_H */ diff --git a/Helicity/Vertex/VertexBase.cc b/Helicity/Vertex/VertexBase.cc --- a/Helicity/Vertex/VertexBase.cc +++ b/Helicity/Vertex/VertexBase.cc @@ -1,322 +1,322 @@ // -*- C++ -*- // // VertexBase.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the 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(), _theName(name), _coupopt(0), _gs(sqrt(4.*Constants::pi*0.3)), _ee(sqrt(4.*Constants::pi/137.04)), _sw(sqrt(0.232)) { couplingOrders_[CouplingType::QED]=0; couplingOrders_[CouplingType::QCD]=0; // may break overloaded use cases 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 ) 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 ( 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(); //assert(colourStructure_ != ColourStructure::UNDEFINED); // set up the incoming and outgoing particles if ( !_outpart.empty() || !_inpart.empty() ) return; for ( const auto & pvec : _particles ) { for ( tPDPtr p : pvec ) { assert( p ); tPDPtr cc = p->CC(); _inpart.insert( cc ? cc : p ); _outpart.insert(p); } } // check the couplings if(Debug::level>1&&int(_npoint)!=2+ orderInAllCouplings()) generator()->log() << fullName() << " has inconsistent number of " << "external particles and coupling order = " << orderInAllCouplings() << " for a perturbative interaction. Either it's an" << " effective vertex or something is wrong.\n"; if(int(_npoint)>2+orderInAllCouplings()) { generator()->log() << fullName() << " has inconsistent number of " << "external particles and coupling order " << orderInAllCouplings() << " for a perturbative interaction. Either it's a BSM " << " effective vertex or something is wrong.\n"; } } void VertexBase::persistentOutput(PersistentOStream & os) const { os << _npoint << _inpart << _outpart << _particles << _calckinematics << _coupopt << _gs << _ee << _sw << couplingOrders_ << colourStructure_; } void VertexBase::persistentInput(PersistentIStream & is, int) { is >> _npoint >> _inpart >> _outpart >> _particles >> _calckinematics >> _coupopt >> _gs >> _ee >> _sw >> couplingOrders_ >> colourStructure_; } // 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(const auto & pvec : _particles ) { bool found = pvec[iloc]->id() == idd; if(found) { 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(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) { for (auto cit = _particles.begin(); cit != _particles.end(); ++cit) { for (auto cjt = cit->begin(); cjt != cit->end(); ++cjt) { *cjt = trans.translate(*cjt); } } set newinpart; for (auto it = _inpart.begin(); it != _inpart.end(); ++it) { newinpart.insert(trans.translate(*it)); } _inpart = newinpart; set newoutpart; 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(); for (auto cit = _particles.begin(); cit != _particles.end(); ++cit) { for (auto cjt = cit->begin(); cjt != cit->end(); ++cjt) { ret.push_back(*cjt); } } for (auto it = _inpart.begin(); it != _inpart.end(); ++it) { ret.push_back(*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,602 +1,602 @@ // -*- C++ -*- // // VertexBase.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_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; } /** * Namespace for naming types of colour structures to allow models to define new type */ namespace ColourStructure { typedef unsigned T; const T UNDEFINED = 0; const T SINGLET = 1; const T SU3TFUND = 2; const T SU3F = 3; const T SU3T6 = 4; const T SU3K6 = 5; const T EPS = 6; const T DELTA = 7; const T SU3FF = 8; const T SU3TTFUNDS = 9; const T SU3TTFUNDD = 10; const T SU3TT6 = 11; const T SU3I12I34 = 12; const T SU3I14I23 = 13; const T SU3T21T43 = 14; const T SU3T23T41 = 15; } /** * Namespace for naming types of couplings to allow models to define new type */ namespace CouplingType { typedef unsigned T; const T UNDEFINED = 0; const T QED = 1; const T QCD = 2; } /** \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$ */ int orderInGem() const { return couplingOrders_.at(CouplingType::QED); } /** * Get the order in \f$g_s\f$ */ int orderInGs() const { return couplingOrders_.at(CouplingType::QCD); } /** * Get the order in a specific coupling */ int orderInCoupling(CouplingType::T cType) const { if(couplingOrders_.find(cType) !=couplingOrders_.end()) return couplingOrders_.at(cType); else return 0; } /** * Get the total order of the vertex */ int orderInAllCouplings() const { int output(0); for(auto & p : couplingOrders_) output += p.second; return output; } /** * Get the colour structure */ ColourStructure::T colourStructure() const {return colourStructure_;} //@} 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) { for(size_t ix=0;ix > _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 */ std::array,5> _kine; /** * Name of vertex */ VertexType::T _theName; /** * Colour structure of the vertex */ ColourStructure::T colourStructure_; /** * The order of the vertex in specific couplings */ map couplingOrders_; /** * 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,282 +1,282 @@ // -*- C++ -*- // // RSSpinorBarWaveFunction.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the RSSpinorBarWaveFunction class. // #include "RSSpinorBarWaveFunction.h" #include "ThePEG/Helicity/HelicityFunctions.h" using namespace ThePEG; using namespace ThePEG::Helicity; // calculate the Wavefunction void RSSpinorBarWaveFunction::calculateWaveFunction(unsigned int ihel) { // if rest frame, make sure speical case is used Lorentz5Momentum ptemp=momentum(); double pr = ptemp.vect().mag2()/sqr(momentum().e()); if(pr<1e-20) { ptemp.setX(ZERO); ptemp.setY(ZERO); ptemp.setZ(ZERO); } assert(direction()!=intermediate); assert(ihel<=3); // only two valid helicities in massless case assert( mass()>ZERO || (ihel == 0 || ihel == 3 ) ); // new direct calculation _wf = LorentzRSSpinorBar(direction()==outgoing ? SpinorType::u : SpinorType::v); // compute the spinors std::array,2> spin; if(ihel!=0) spin[0] = HelicityFunctions::spinorBar(ptemp,1,direction()); if(ihel!=3) spin[1] = HelicityFunctions::spinorBar(ptemp,0,direction()); // compute the polarization vectors to construct the RS spinor std::array eps; if(ihel>=2) eps[0] = HelicityFunctions::polarizationVector(ptemp,2,direction(),vector_phase); else eps[2] = HelicityFunctions::polarizationVector(ptemp,0,direction(),vector_phase); if(mass()!=ZERO&&ihel!=0&&ihel!=3) eps[1] = HelicityFunctions::polarizationVector(ptemp,1,direction()); // 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(unsigned int iy=0;iy<4;++iy) { _wf(0,iy) = eps[0].x()*spin[0][iy]; _wf(1,iy) = eps[0].y()*spin[0][iy]; _wf(2,iy) = eps[0].z()*spin[0][iy]; _wf(3,iy) = eps[0].t()*spin[0][iy]; } } else if(ihel==2) { for(unsigned int iy=0;iy<4;++iy) { _wf(0,iy) = or3*eps[0].x()*spin[1][iy]+tor3*eps[1].x()*spin[0][iy]; _wf(1,iy) = or3*eps[0].y()*spin[1][iy]+tor3*eps[1].y()*spin[0][iy]; _wf(2,iy) = or3*eps[0].z()*spin[1][iy]+tor3*eps[1].z()*spin[0][iy]; _wf(3,iy) = or3*eps[0].t()*spin[1][iy]+tor3*eps[1].t()*spin[0][iy]; } } else if(ihel==1) { for(unsigned int iy=0;iy<4;++iy) { _wf(0,iy) = or3*eps[2].x()*spin[0][iy]+tor3*eps[1].x()*spin[1][iy]; _wf(1,iy) = or3*eps[2].y()*spin[0][iy]+tor3*eps[1].y()*spin[1][iy]; _wf(2,iy) = or3*eps[2].z()*spin[0][iy]+tor3*eps[1].z()*spin[1][iy]; _wf(3,iy) = or3*eps[2].t()*spin[0][iy]+tor3*eps[1].t()*spin[1][iy]; } } else if(ihel==0) { for(unsigned int iy=0;iy<4;++iy) { _wf(0,iy) = eps[2].x()*spin[1][iy]; _wf(1,iy) = eps[2].y()*spin[1][iy]; _wf(2,iy) = eps[2].z()*spin[1][iy]; _wf(3,iy) = eps[2].t()*spin[1][iy]; } } // this makes the phase choice the same as madgraph, useful for debugging only // Energy pt = ptemp.perp(); // double fact = direction()==incoming ? 1. : -1.; // Complex emphi(fact*ptemp.x()/pt,-fact*ptemp.y()/pt); // if(ihel==3) { // for(unsigned int ix=0;ix<4;++ix) // for(unsigned int iy=0;iy<4;++iy) // _wf(ix,iy) /= emphi; // } // else if(ihel==1) { // for(unsigned int ix=0;ix<4;++ix) // for(unsigned int iy=0;iy<4;++iy) // _wf(ix,iy) *= emphi; // } // else if(ihel==0) { // for(unsigned int ix=0;ix<4;++ix) // for(unsigned int iy=0;iy<4;++iy) // _wf(ix,iy) *= sqr(emphi); // } } 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()); calculateWaveFunctions(waves,particle->momentum(),particle->dataPtr(),dir); } } void RSSpinorBarWaveFunction:: calculateWaveFunctions(vector & waves, const Lorentz5Momentum & momentum, tcPDPtr parton,Direction dir) { waves.resize(4); RSSpinorBarWaveFunction wave(momentum,parton,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/RSSpinorBarWaveFunction.h b/Helicity/WaveFunction/RSSpinorBarWaveFunction.h --- a/Helicity/WaveFunction/RSSpinorBarWaveFunction.h +++ b/Helicity/WaveFunction/RSSpinorBarWaveFunction.h @@ -1,378 +1,378 @@ // -*- C++ -*- // // RSSpinorBarWaveFunction.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_RSSpinorBarWaveFunction_H #define ThePEG_RSSpinorBarWaveFunction_H // // This is the declaration of the RSSpinorBarWaveFunction class. // #include "WaveFunctionBase.h" #include #include #include #include namespace ThePEG { namespace Helicity { /** \ingroup Helicity * * The RSSpinorBarWaveFunction class is designed to * store the wavefunction of a spin-\f$\frac32\f$ particle in a form * suitable for use in helicity amplitude calculations of the matrix * element using a similar philosophy to the FORTRAN HELAS code. * * In addition to storing the barred spinor using the * LorentzRSSpinorBar class it inherits from the * WaveFunctionBase class to provide storage of the * momentum and ParticleData for the fermion. * * This class also contains the code which does the actually * calculation of the barred spinor for an external particle * * When calculating the wavefunction the direction of the particle is used, * * \e i.e. * - incoming calculates a \f$\bar{v}\f$ spinor. * - outgoing calculates a \f$\bar{u}\f$ spinor. * * The barred spinors are calculated using a Clebsch-Gordon decomposition * in the rest-frame for a massive particle and boosted to the lab-frame. * For massless particles the calculation is performed in the lab-frame * (N.B. there are only two helicities \f$\pm\frac32\f$ in this case.) * * 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 and * * @see WaveFunctionBase * @see LorentzRSSpinorBar * @see HelicityDefinitions * */ class RSSpinorBarWaveFunction: public WaveFunctionBase { public: /** @name Standard constructors and destructors. */ //@{ /** * Constructor, set the momentum and the components of the spinor * @param p The momentum. * @param part The ParticleData pointer. * @param xs1 The first spinor component of the \f$x\f$ vector. * @param xs2 The second spinor component of the \f$x\f$ vector. * @param xs3 The third spinor component of the \f$x\f$ vector. * @param xs4 The fourth spinor component of the \f$x\f$ vector. * @param ys1 The first spinor component of the \f$y\f$ vector. * @param ys2 The second spinor component of the \f$y\f$ vector. * @param ys3 The third spinor component of the \f$y\f$ vector. * @param ys4 The fourth spinor component of the \f$y\f$ vector. * @param zs1 The first spinor component of the \f$z\f$ vector. * @param zs2 The second spinor component of the \f$z\f$ vector. * @param zs3 The third spinor component of the \f$z\f$ vector. * @param zs4 The fourth spinor component of the \f$z\f$ vector. * @param ts1 The first spinor component of the \f$t\f$ vector. * @param ts2 The second spinor component of the \f$t\f$ vector. * @param ts3 The third spinor component of the \f$t\f$ vector. * @param ts4 The fourth spinor component of the \f$t\f$ vector. */ RSSpinorBarWaveFunction(const Lorentz5Momentum & p,tcPDPtr part, complex xs1, complex xs2, complex xs3, complex xs4, complex ys1, complex ys2, complex ys3, complex ys4, complex zs1, complex zs2, complex zs3, complex zs4, complex ts1, complex ts2, complex ts3, complex ts4) : WaveFunctionBase(p,part), _wf(xs1,xs2,xs3,xs4, ys1,ys2,ys3,ys4, zs1,zs2,zs3,zs4, ts1,ts2,ts3,ts4) { assert(iSpin()==4); } /** * Constructor, set the momentum and the wavefunction. * @param p The momentum. * @param part The ParticleData pointer. * @param wave The wavefunction. */ RSSpinorBarWaveFunction(const Lorentz5Momentum & p,tcPDPtr part, const LorentzRSSpinorBar & wave, Direction dir=intermediate) : WaveFunctionBase(p,part,dir), _wf(wave) { assert(iSpin()==4); } /** * Constructor, set the particle and the wavefunction. * @param p Particle * @param wave The wavefunction. * @param dir The direction of the particle */ RSSpinorBarWaveFunction(const tPPtr & p, const LorentzRSSpinorBar & wave, Direction dir=intermediate) : WaveFunctionBase(p->momentum(),p->dataPtr(),dir), _wf(wave.Type()) { assert(iSpin()==4); for (unsigned int i=0; i<4; ++i) for(unsigned int j=0; j<4; ++j) _wf(i,j)=Complex(wave(i,j)*UnitRemoval::InvSqrtE); } /** * Constructor, set the momentum, helicity, direction. * @param p The momentum. * @param part The ParticleData pointer. * @param ihel The helicity (0,1,2,3 as described above.) * @param dir The direction. */ RSSpinorBarWaveFunction(const Lorentz5Momentum & p,tcPDPtr part, unsigned int ihel,Direction dir) : WaveFunctionBase(p,part,dir) { assert(iSpin()==4); calculateWaveFunction(ihel); } /** * Constructor, set the momentum, direction, zero the * wavefunction. * @param p The momentum. * @param part The ParticleData pointer. * @param dir The direction. */ RSSpinorBarWaveFunction(Lorentz5Momentum p,tcPDPtr part,Direction dir) : WaveFunctionBase(p,part,dir), _wf() { assert(iSpin()==4); } /** * Default constructor */ RSSpinorBarWaveFunction() : WaveFunctionBase(), _wf() {} /** * Special for spin correlations */ RSSpinorBarWaveFunction(vector & wave, tPPtr part,Direction dir,bool time,bool=true) { calculateWaveFunctions(wave,part,dir); constructSpinInfo(wave,part,dir,time); } //@} /** * Access to the wavefunction and its components. */ //@{ /** * subscript operator for the wavefunction * Set components by index. */ complex operator ()(int i, int j) const { assert( i>=0 && i<=3 && j>=0 && j<=3 ); return _wf(i,j); } /** * return wavefunction as LorentzRSSpinorBar */ const LorentzRSSpinorBar & wave() const {return _wf;} /// Return wavefunction as LorentzRSSpinorBar LorentzRSSpinorBar dimensionedWf() const { LorentzRSSpinorBar temp(_wf.Type()); for (unsigned int i=0; i<4; ++i) for (unsigned int j=0; j<4; ++j) temp(i,j) = _wf(i,j)*UnitRemoval::SqrtE; return temp; } /** * Get first spinor component for the x vector */ complex xs1() const {return _wf.xs1();} /** * Get second spinor component for the x vector */ complex xs2() const {return _wf.xs2();} /** * Get third spinor component for the x vector */ complex xs3() const {return _wf.xs3();} /** * Get fourth spinor component for the x vector */ complex xs4() const {return _wf.xs4();} /** * Get first spinor component for the y vector */ complex ys1() const {return _wf.ys1();} /** * Get second spinor component for the y vector */ complex ys2() const {return _wf.ys2();} /** * Get third spinor component for the y vector */ complex ys3() const {return _wf.ys3();} /** * Get fourth spinor component for the y vector */ complex ys4() const {return _wf.ys4();} /** * Get first spinor component for the z vector */ complex zs1() const {return _wf.zs1();} /** * Get second spinor component for the z vector */ complex zs2() const {return _wf.zs2();} /** * Get third spinor component for the z vector */ complex zs3() const {return _wf.zs3();} /** * Get fourth spinor component for the z vector */ complex zs4() const {return _wf.zs4();} /** * Get first spinor component for the t vector */ complex ts1() const {return _wf.ts1();} /** * Get second spinor component for the t vector */ complex ts2() const {return _wf.ts2();} /** * Get third spinor component for the t vector */ complex ts3() const {return _wf.ts3();} /** * Get fourth spinor component for the t vector */ complex ts4() const {return _wf.ts4();} //@} /** * reset functions */ //@{ /** * Reset the helicity (calculates the new spinor). * @param ihel The helicity (0,1,2,3 as described above.) */ void reset(unsigned int ihel) { calculateWaveFunction(ihel); } //@} public: /** * Perform the Lorentz transformation of the wave function */ void transform(const LorentzRotation & r) { _wf.transform(r); transformMomentum(r); } public: /** * Calculate the wavefunctions */ static void calculateWaveFunctions(vector > & waves, tPPtr particle,Direction); /** * Calculate the wavefunctions */ static void calculateWaveFunctions(vector & waves, tPPtr particle,Direction); /** * Calculate the wavefunctions */ static void calculateWaveFunctions(vector & waves, const Lorentz5Momentum & momentum, tcPDPtr parton,Direction); /** * Calculate the wavefunctions */ static void calculateWaveFunctions(vector > & waves, RhoDMatrix & rho, tPPtr particle,Direction); /** * Calculate the wavefunctions */ static void calculateWaveFunctions(vector & waves, RhoDMatrix & rho, tPPtr particle,Direction); /** * Construct the SpinInfo object */ static void constructSpinInfo(const vector > & waves, tPPtr part,Direction dir, bool time); /** * Construct the SpinInfo object */ static void constructSpinInfo(const vector & waves, tPPtr part,Direction dir, bool time); private: /** * Calcuate the wavefunction. * @param ihel The helicity (0,1,2,3 as described above.) */ void calculateWaveFunction(unsigned int ihel); private: /** * storage of the Lorentz RSSpinorBar */ LorentzRSSpinorBar _wf; }; } } #endif /* ThePEG_RSSpinorBarWaveFunction_H */ diff --git a/Helicity/WaveFunction/RSSpinorWaveFunction.cc b/Helicity/WaveFunction/RSSpinorWaveFunction.cc --- a/Helicity/WaveFunction/RSSpinorWaveFunction.cc +++ b/Helicity/WaveFunction/RSSpinorWaveFunction.cc @@ -1,277 +1,277 @@ // -*- C++ -*- // // RSSpinorWaveFunction.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the RSSpinorWaveFunction class. // #include "RSSpinorWaveFunction.h" #include "ThePEG/Helicity/HelicityFunctions.h" using namespace ThePEG; using namespace ThePEG::Helicity; // calculate the Wavefunction void RSSpinorWaveFunction::calculateWaveFunction(unsigned int ihel) { // if rest frame, make sure speical case is used Lorentz5Momentum ptemp=momentum(); double pr = ptemp.vect().mag2()/sqr(momentum().e()); if(pr<1e-20) { ptemp.setX(ZERO); ptemp.setY(ZERO); ptemp.setZ(ZERO); } assert(direction()!=intermediate); assert(ihel<=3); // only two valid helicities in massless case assert( mass()>ZERO || (ihel == 0 || ihel == 3 ) ); // new direct calculation _wf = LorentzRSSpinor(direction()==outgoing ? SpinorType::v : SpinorType::u); // compute the spinors std::array,2> spin; if(ihel!=0) spin[0] = HelicityFunctions::spinor(ptemp,1,direction()); if(ihel!=3) spin[1] = HelicityFunctions::spinor(ptemp,0,direction()); // compute the polarization vectors to construct the RS spinor std::array eps; if(ihel>=2) eps[0] = HelicityFunctions::polarizationVector(ptemp,2,direction(),vector_phase); else eps[2] = HelicityFunctions::polarizationVector(ptemp,0,direction(),vector_phase); if(mass()!=ZERO&&ihel!=0&&ihel!=3) eps[1] = HelicityFunctions::polarizationVector(ptemp,1,direction()); // 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(unsigned int iy=0;iy<4;++iy) { _wf(0,iy) = eps[0].x()*spin[0][iy]; _wf(1,iy) = eps[0].y()*spin[0][iy]; _wf(2,iy) = eps[0].z()*spin[0][iy]; _wf(3,iy) = eps[0].t()*spin[0][iy]; } } else if(ihel==2) { for(unsigned int iy=0;iy<4;++iy) { _wf(0,iy) = or3*eps[0].x()*spin[1][iy]+tor3*eps[1].x()*spin[0][iy]; _wf(1,iy) = or3*eps[0].y()*spin[1][iy]+tor3*eps[1].y()*spin[0][iy]; _wf(2,iy) = or3*eps[0].z()*spin[1][iy]+tor3*eps[1].z()*spin[0][iy]; _wf(3,iy) = or3*eps[0].t()*spin[1][iy]+tor3*eps[1].t()*spin[0][iy]; } } else if(ihel==1) { for(unsigned int iy=0;iy<4;++iy) { _wf(0,iy) = or3*eps[2].x()*spin[0][iy]+tor3*eps[1].x()*spin[1][iy]; _wf(1,iy) = or3*eps[2].y()*spin[0][iy]+tor3*eps[1].y()*spin[1][iy]; _wf(2,iy) = or3*eps[2].z()*spin[0][iy]+tor3*eps[1].z()*spin[1][iy]; _wf(3,iy) = or3*eps[2].t()*spin[0][iy]+tor3*eps[1].t()*spin[1][iy]; } } else if(ihel==0) { for(unsigned int iy=0;iy<4;++iy) { _wf(0,iy) = eps[2].x()*spin[1][iy]; _wf(1,iy) = eps[2].y()*spin[1][iy]; _wf(2,iy) = eps[2].z()*spin[1][iy]; _wf(3,iy) = eps[2].t()*spin[1][iy]; } } // this makes the phase choice the same as madgraph, useful for debugging only // Energy pt = ptemp.perp(); // double fact = direction()==incoming ? 1. : -1.; // Complex emphi(fact*ptemp.x()/pt,-fact*ptemp.y()/pt); // if(ihel==3) { // for(unsigned int ix=0;ix<4;++ix) // for(unsigned int iy=0;iy<4;++iy) // _wf(ix,iy) /= emphi; // } // else if(ihel==1) { // for(unsigned int ix=0;ix<4;++ix) // for(unsigned int iy=0;iy<4;++iy) // _wf(ix,iy) *= emphi; // } // else if(ihel==0) { // for(unsigned int ix=0;ix<4;++ix) // for(unsigned int iy=0;iy<4;++iy) // _wf(ix,iy) *= sqr(emphi); // } } 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()); calculateWaveFunctions(waves,particle->momentum(),particle->dataPtr(),dir); } } void RSSpinorWaveFunction:: calculateWaveFunctions(vector & waves, const Lorentz5Momentum & momentum, tcPDPtr parton,Direction dir) { waves.resize(4); RSSpinorWaveFunction wave(momentum,parton,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/RSSpinorWaveFunction.h b/Helicity/WaveFunction/RSSpinorWaveFunction.h --- a/Helicity/WaveFunction/RSSpinorWaveFunction.h +++ b/Helicity/WaveFunction/RSSpinorWaveFunction.h @@ -1,376 +1,376 @@ // -*- C++ -*- // // RSSpinorWaveFunction.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_RSSpinorWaveFunction_H #define ThePEG_RSSpinorWaveFunction_H // This is the declaration of the RSSpinorWaveFunction class. #include "WaveFunctionBase.h" #include #include #include #include namespace ThePEG { namespace Helicity { /** \ingroup Helicity * * The RSSpinorWaveFunction class is designed to store the wavefunction * of a spin-3/2 particle in a form suitable for use in helicity amplitude * calculations of the matrix element using a similar philosophy to the * FORTRAN HELAS code. * * In addition to storing the spinor using the LorentzRSSpinor class * it inherits from the WaveFunctionBase class to provide storage of * the momentum and ParticleData for the fermion. * * This class also contains the code which does the actually calculation of the * spinor for an external particle. * * When calculating the wavefunction the direction of the particle is used, * * \e i.e. * - incoming calculates a \f$u\f$ spinor. * - outgoing calculates a \f$v\f$ spinor. * * The spinors are calculated using a Clebsch-Gordon decomposition in the rest-frame * for a massive particle and boosted to the lab-frame. For massless particles the * calculation is performed in the lab-frame (N.B. there are only two helicities * \f$\pm\frac32\f$ in this case.) * * 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 and * * @see WaveFunctionBase * @see LorentzRSSpinor * @see HelicityDefinitions * */ class RSSpinorWaveFunction: public WaveFunctionBase { public: /** @name Standard constructors and destructors. */ //@{ /** * Constructor, set the momentum and the components of the spinor. * @param p The momentum. * @param part The ParticleData pointer. * @param xs1 The first spinor component of the \f$x\f$ vector. * @param xs2 The second spinor component of the \f$x\f$ vector. * @param xs3 The third spinor component of the \f$x\f$ vector. * @param xs4 The fourth spinor component of the \f$x\f$ vector. * @param ys1 The first spinor component of the \f$y\f$ vector. * @param ys2 The second spinor component of the \f$y\f$ vector. * @param ys3 The third spinor component of the \f$y\f$ vector. * @param ys4 The fourth spinor component of the \f$y\f$ vector. * @param zs1 The first spinor component of the \f$z\f$ vector. * @param zs2 The second spinor component of the \f$z\f$ vector. * @param zs3 The third spinor component of the \f$z\f$ vector. * @param zs4 The fourth spinor component of the \f$z\f$ vector. * @param ts1 The first spinor component of the \f$t\f$ vector. * @param ts2 The second spinor component of the \f$t\f$ vector. * @param ts3 The third spinor component of the \f$t\f$ vector. * @param ts4 The fourth spinor component of the \f$t\f$ vector. */ RSSpinorWaveFunction(const Lorentz5Momentum & p,tcPDPtr part, complex xs1, complex xs2, complex xs3, complex xs4, complex ys1, complex ys2, complex ys3, complex ys4, complex zs1, complex zs2, complex zs3, complex zs4, complex ts1, complex ts2, complex ts3, complex ts4) : WaveFunctionBase(p,part), _wf(xs1,xs2,xs3,xs4, ys1,ys2,ys3,ys4, zs1,zs2,zs3,zs4, ts1,ts2,ts3,ts4) { assert(iSpin()==4); } /** * Constructor, set the momentum and the wavefunction. * @param p The momentum. * @param part The ParticleData pointer. * @param wave The wavefunction. * @param dir The direction of the particle */ RSSpinorWaveFunction(const Lorentz5Momentum & p, tcPDPtr part, const LorentzRSSpinor & wave, Direction dir=intermediate) : WaveFunctionBase(p,part,dir), _wf(wave) { assert(iSpin()==4); } /** * Constructor, set the momentum and the wavefunction. * @param p The Particle pointer. * @param wave The wavefunction. * @param dir The direction of the particle */ RSSpinorWaveFunction(const tPPtr & p, const LorentzRSSpinor & wave, Direction dir=intermediate) : WaveFunctionBase(p->momentum(),p->dataPtr(),dir), _wf(wave.Type()) { assert(iSpin()==4); for (unsigned int i=0; i<4; ++i) for(unsigned int j=0; j<4; ++j) _wf(i,j)=Complex(wave(i,j)*UnitRemoval::InvSqrtE); } /** * Constructor, set the momentum, helicity, direction. * @param p The momentum. * @param part The ParticleData pointer. * @param ihel The helicity (0,1,2,3 as described above.) * @param dir The direction. */ RSSpinorWaveFunction(const Lorentz5Momentum & p,tcPDPtr part, unsigned int ihel, Direction dir) : WaveFunctionBase(p,part,dir) { assert(iSpin()==4); calculateWaveFunction(ihel); } /** * Constructor, set the momentum, direction, zero the * wavefunction. * @param p The momentum. * @param part The ParticleData pointer. * @param dir The direction. */ RSSpinorWaveFunction(const Lorentz5Momentum & p,tcPDPtr part,Direction dir) : WaveFunctionBase(p,part,dir), _wf() { assert(iSpin()==4); } /** * Default constructor */ RSSpinorWaveFunction() : WaveFunctionBase(), _wf() {} /** * Special for spin correlations */ RSSpinorWaveFunction(vector & wave, tPPtr part,Direction dir,bool time,bool=true) { calculateWaveFunctions(wave,part,dir); constructSpinInfo(wave,part,dir,time); } //@} /** * Access to the wavefunction and its components. */ //@{ /** * subscript operator for the wavefunction * Set components by index. */ complex operator ()(int i, int j) const { assert( i>=0 && i<=3 && j>=0 && j<=3); return _wf(i,j); } /** * return wavefunction as LorentzRSSpinor */ const LorentzRSSpinor & wave() const {return _wf;} /// Return wavefunction as LorentzRSSpinor LorentzRSSpinor dimensionedWf() const { LorentzRSSpinor temp(_wf.Type()); for (unsigned int i=0; i<4; ++i) for (unsigned int j=0; j<4; ++j) temp(i,j) = _wf(i,j)*UnitRemoval::SqrtE; return temp; } /** * Get first spinor component for the x vector */ complex xs1() const {return _wf.xs1();} /** * Get second spinor component for the x vector */ complex xs2() const {return _wf.xs2();} /** * Get third spinor component for the x vector */ complex xs3() const {return _wf.xs3();} /** * Get fourth spinor component for the x vector */ complex xs4() const {return _wf.xs4();} /** * Get first spinor component for the y vector */ complex ys1() const {return _wf.ys1();} /** * Get second spinor component for the y vector */ complex ys2() const {return _wf.ys2();} /** * Get third spinor component for the y vector */ complex ys3() const {return _wf.ys3();} /** * Get fourth spinor component for the y vector */ complex ys4() const {return _wf.ys4();} /** * Get first spinor component for the z vector */ complex zs1() const {return _wf.zs1();} /** * Get second spinor component for the z vector */ complex zs2() const {return _wf.zs2();} /** * Get third spinor component for the z vector */ complex zs3() const {return _wf.zs3();} /** * Get fourth spinor component for the z vector */ complex zs4() const {return _wf.zs4();} /** * Get first spinor component for the t vector */ complex ts1() const {return _wf.ts1();} /** * Get second spinor component for the t vector */ complex ts2() const {return _wf.ts2();} /** * Get third spinor component for the t vector */ complex ts3() const {return _wf.ts3();} /** * Get fourth spinor component for the t vector */ complex ts4() const {return _wf.ts4();} //@} /** * reset functions */ //@{ /** * Reset the helicity (calculates the new spinor). * @param ihel The helicity (0,1,2,3 as described above.) */ void reset(unsigned int ihel) { calculateWaveFunction(ihel); } //@} public: /** * Perform the Lorentz transformation of the wave function */ void transform(const LorentzRotation & r) { _wf.transform(r); transformMomentum(r); } public: /** * Calculate the wavefunctions */ static void calculateWaveFunctions(vector > & waves, tPPtr particle,Direction); /** * Calculate the wavefunctions */ static void calculateWaveFunctions(vector & waves, tPPtr particle,Direction); /** * Calculate the wavefunctions */ static void calculateWaveFunctions(vector & waves, const Lorentz5Momentum & momentum, tcPDPtr parton,Direction); /** * Calculate the wavefunctions */ static void calculateWaveFunctions(vector > & waves, RhoDMatrix & rho, tPPtr particle,Direction); /** * Calculate the wavefunctions */ static void calculateWaveFunctions(vector & waves, RhoDMatrix & rho, tPPtr particle,Direction); /** * Construct the SpinInfo object */ static void constructSpinInfo(const vector > & waves, tPPtr part,Direction dir, bool time); /** * Construct the SpinInfo object */ static void constructSpinInfo(const vector & waves, tPPtr part,Direction dir, bool time); private: /** * Calcuate the wavefunction. * @param ihel The helicity (0,1,2,3 as described above.) */ void calculateWaveFunction(unsigned int ihel); private: /** * storage of the Lorentz RSSpinor */ LorentzRSSpinor _wf; }; } } #endif /* ThePEG_RSSpinorWaveFunction_H */ diff --git a/Helicity/WaveFunction/ScalarWaveFunction.h b/Helicity/WaveFunction/ScalarWaveFunction.h --- a/Helicity/WaveFunction/ScalarWaveFunction.h +++ b/Helicity/WaveFunction/ScalarWaveFunction.h @@ -1,120 +1,120 @@ // -*- C++ -*- // // ScalarWaveFunction.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_ScalarWaveFunction_H #define ThePEG_ScalarWaveFunction_H // // This is the declaration of the ScalarWaveFunction class. #include "WaveFunctionBase.h" #include #include #include namespace ThePEG { namespace Helicity { /** \ingroup Helicity * \author Peter Richardson * * This class is the base class for scalar wavefunctions for use in * helicity amplitude calculations. The general approach * is to use a similar philosophy to the FORTRAN HELAS code but with * additional structure. * * This class stores the scalar wavefunction as a complex number and inherits * from the WaveFunctionBase class for the storage of the particles * momentum and type. * * @see WaveFunctionBase */ class ScalarWaveFunction : public WaveFunctionBase { public: /** @name Standard constructors and destructors. */ //@{ /** * Constructor, set the momentum, direction and Wavefunction. * @param p The momentum. * @param part The ParticleData pointer * @param wave The wavefunction. * @param dir The direction of the particle. */ ScalarWaveFunction(const Lorentz5Momentum & p,tcPDPtr part, Complex wave,Direction dir=intermediate) : WaveFunctionBase(p,part,dir), _wf(wave) { assert(iSpin()==1); } /** * Constructor,set the 5-momentum and zero the wavefunction. * @param p The 5-momentum. * @param part The ParticleData pointer. * @param dir The direction of the particle. */ ScalarWaveFunction(const Lorentz5Momentum & p,tcPDPtr part,Direction dir) : WaveFunctionBase(p,part,dir), _wf(1.0) { assert(iSpin()==1); } static void calculateWaveFunctions(RhoDMatrix & rho, tPPtr, Direction) { rho=RhoDMatrix(PDT::Spin0); } static void constructSpinInfo(tPPtr part,Direction, bool time) { tScalarSpinPtr inspin; if(part->spinInfo()) inspin=dynamic_ptr_cast(part->spinInfo()); if(inspin) return; assert(!part->spinInfo()); ScalarSpinPtr temp = new_ptr(ScalarSpinInfo(part->momentum(),time)); part->spinInfo(temp); } /** * Default constructor. */ ScalarWaveFunction() : WaveFunctionBase(), _wf(1.0) {} /** * Special for spin correlations */ ScalarWaveFunction(tPPtr p,Direction dir,bool time) : WaveFunctionBase(p->momentum(), p->dataPtr(), dir), _wf(1.0) { assert(iSpin()==1); constructSpinInfo(p,dir,time); } /** * Return the wavefunction. */ const Complex & wave() const {return _wf;} public: void transform(const LorentzRotation & r) { transformMomentum(r); } private: /** * Complex number to store the wavefunction. */ Complex _wf; }; } } #endif diff --git a/Helicity/WaveFunction/SpinorBarWaveFunction.cc b/Helicity/WaveFunction/SpinorBarWaveFunction.cc --- a/Helicity/WaveFunction/SpinorBarWaveFunction.cc +++ b/Helicity/WaveFunction/SpinorBarWaveFunction.cc @@ -1,260 +1,260 @@ // -*- C++ -*- // // SpinorBarWaveFunction.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the SpinorBarWaveFunction class. // // Author: Peter Richardson // #include "SpinorBarWaveFunction.h" #include "SpinorWaveFunction.h" #include "ThePEG/Helicity/HelicityFunctions.h" using namespace ThePEG; using namespace Helicity; // calculate the Wavefunction void SpinorBarWaveFunction::calculateWaveFunction(unsigned int ihel) { _wf = HelicityFunctions::spinorBar(momentum(),ihel,direction()); } 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()!=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()!=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()); calculateWaveFunctions(waves,particle->momentum(),particle->dataPtr(),dir); } } void SpinorBarWaveFunction::calculateWaveFunctions(vector & waves, const Lorentz5Momentum & momentum, tcPDPtr parton,Direction dir) { waves.resize(2); SpinorBarWaveFunction wave(momentum,parton,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()!=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()!=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) || ( 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) || ( 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 && 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) || ( dir == incoming && !time)) temp->setBasisState(ix,waves[ix].dimensionedWf().bar()); else temp->setDecayState(ix,waves[ix].dimensionedWf().bar()); } } } diff --git a/Helicity/WaveFunction/SpinorBarWaveFunction.h b/Helicity/WaveFunction/SpinorBarWaveFunction.h --- a/Helicity/WaveFunction/SpinorBarWaveFunction.h +++ b/Helicity/WaveFunction/SpinorBarWaveFunction.h @@ -1,308 +1,308 @@ // -*- C++ -*- // // SpinorBarWaveFunction.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_SpinorBarWaveFunction_H #define ThePEG_SpinorBarWaveFunction_H // // This is the declaration of the SpinorBarWaveFunction class. #include "WaveFunctionBase.h" #include #include #include #include namespace ThePEG { namespace Helicity { /** * Forward declaration of the SpinorWaveFunction class */ class SpinorWaveFunction; /** \ingroup Helicity * \author Peter Richardson * * The SpinorBarWaveFunction class is designed to store the wavefunction * of a barred spinor in a form suitable for use in helicity amplitude * calculations of the matrix element using a similar philosophy to the * FORTRAN HELAS code. * * In addition to storing the spinor using the LorentzSpinorBar class * it inherits from the WaveFunctionBase class to provide storage of * the momentum and ParticleData for the fermion. * * This class also contains the code which does the actually calculation * of the barred spinor for an external particle. * * When calculating the wavefunction the direction of the particle is used, * * \e i.e. * - incoming calculates a \f$\bar{v}\f$ spinor. * - outgoing calculates a \f$\bar{u}\f$ spinor. * * N.B. In our convention 0 is the \f$-\frac12\f$ helicity state and * 1 is the \f$+\frac12\f$ helicity state * * @see WaveFunctionBase * @see LorentzSpinorBar * @see HelicityDefinitions */ class SpinorBarWaveFunction : public WaveFunctionBase { public: /** @name Standard constructors and destructors. */ //@{ /** * Constructor, set the momentum and the components of the spinor. * @param p The momentum. * @param part The ParticleData pointer. * @param s1 The first component * @param s2 The second component * @param s3 The third component * @param s4 The fourth component */ SpinorBarWaveFunction(const Lorentz5Momentum & p,tcPDPtr part, complex s1,complex s2, complex s3,complex s4) : WaveFunctionBase(p,part), _wf(s1,s2,s3,s4) { assert(iSpin()==2); } /** * Constructor, set the momentum and the wavefunction. * @param p The momentum. * @param part The ParticleData pointer. * @param wave The wavefunction. * @param dir The direction of the particle */ SpinorBarWaveFunction(const Lorentz5Momentum & p,tcPDPtr part, const LorentzSpinorBar & wave, Direction dir=intermediate) : WaveFunctionBase(p,part,dir), _wf(wave) { assert(iSpin()==2); } SpinorBarWaveFunction(const tPPtr & p, const LorentzSpinorBar & wave, Direction dir=intermediate) : WaveFunctionBase(p->momentum(),p->dataPtr(),dir), _wf(wave.Type()) { assert(iSpin()==2); for (unsigned int i=0; i<4; ++i) _wf[i]=Complex(wave[i]*UnitRemoval::InvSqrtE); } /** * Constructor, set the momentum, helicity, direction. * @param p The momentum. * @param part The ParticleData pointer. * @param ihel The helicity (0,1 as described above.) * @param dir The direction. */ SpinorBarWaveFunction(const Lorentz5Momentum & p,tcPDPtr part, unsigned int ihel,Direction dir) : WaveFunctionBase(p,part,dir) { assert(iSpin()==2); calculateWaveFunction(ihel); } /** * Constructor, set the momentum, direction, zero the * wavefunction. * @param p The momentum. * @param part The ParticleData pointer. * @param dir The direction. */ SpinorBarWaveFunction(const Lorentz5Momentum & p,tcPDPtr part, Direction dir) : WaveFunctionBase(p,part,dir), _wf() { assert(iSpin()==2); } /** * Default constructor. */ SpinorBarWaveFunction() : WaveFunctionBase(), _wf() {} /** * Special for spin correlations */ SpinorBarWaveFunction(vector & wave, tPPtr part,Direction dir,bool time,bool=true) { calculateWaveFunctions(wave,part,dir); constructSpinInfo(wave,part,dir,time); } //@} /** * Access to the wavefunction and its components. */ //@{ /** * Subscript operator for the wavefunction. */ complex operator ()(int i) const { assert(i>=0 &&i<=3); return _wf(i); } /** * Return wavefunction as LorentzSpinorBar. */ const LorentzSpinorBar & wave() const {return _wf;} /// Return wavefunction as LorentzSpinorBar LorentzSpinorBar dimensionedWave() const { return dimensionedWf(); } /** * Get the first spin component component. */ complex s1() const {return _wf.s1();} /** * Get the second spin component component. */ complex s2() const {return _wf.s2();} /** * Get the third spin component component. */ complex s3() const {return _wf.s3();} /** * Get the fourth spin component component. */ complex s4() const {return _wf.s4();} /** * Take the conjugate of the 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. */ void conjugate(); /** * Return the barred spinor */ SpinorWaveFunction bar(); /** * Reset functions. */ //@{ /** * Reset the helicity (calculates the new spinor). * @param ihel The helicity (0,1 as described above.) */ void reset(unsigned int ihel) { calculateWaveFunction(ihel); } //@} private: /** * Calcuate the wavefunction. * @param ihel The helicity (0,1 as described above.) */ void calculateWaveFunction(unsigned int ihel); public: /** * Perform the Lorentz transformation of the wave function */ void transform(const LorentzRotation & r) { _wf.transform(r); transformMomentum(r); } public: /** * Calculate the wavefunctions */ static void calculateWaveFunctions(vector > & waves, tPPtr particle,Direction); /** * Calculate the wavefunctions */ static void calculateWaveFunctions(vector & waves, tPPtr particle,Direction); /** * Calculate the wavefunctions */ static void calculateWaveFunctions(vector & waves, const Lorentz5Momentum & momentum, tcPDPtr parton,Direction); /** * Calculate the wavefunctions */ static void calculateWaveFunctions(vector > & waves, RhoDMatrix & rho, tPPtr particle,Direction); /** * Calculate the wavefunctions */ static void calculateWaveFunctions(vector & waves, RhoDMatrix & rho, tPPtr particle,Direction); /** * Construct the SpinInfo object */ static void constructSpinInfo(const vector > & waves, tPPtr part,Direction dir, bool time); /** * Construct the SpinInfo object */ static void constructSpinInfo(const vector & waves, tPPtr part,Direction dir, bool time); private: /** * Storage of the Lorentz SpinorBar wavefunction. */ LorentzSpinorBar _wf; /// Return wavefunction as LorentzSpinorBar LorentzSpinorBar dimensionedWf() const { LorentzSpinorBar temp(_wf.Type()); for (unsigned int i=0; i<4; ++i) temp(i) = _wf(i)*UnitRemoval::SqrtE; return temp; } }; } } #endif diff --git a/Helicity/WaveFunction/SpinorWaveFunction.cc b/Helicity/WaveFunction/SpinorWaveFunction.cc --- a/Helicity/WaveFunction/SpinorWaveFunction.cc +++ b/Helicity/WaveFunction/SpinorWaveFunction.cc @@ -1,257 +1,257 @@ // -*- C++ -*- // // SpinorWaveFunction.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the SpinorWaveFunction class. // // Author: Peter Richardson // #include "SpinorWaveFunction.h" #include "ThePEG/Repository/CurrentGenerator.h" #include "SpinorBarWaveFunction.h" #include "ThePEG/Helicity/HelicityFunctions.h" using namespace ThePEG; using namespace Helicity; // calculate the Wavefunction void SpinorWaveFunction::calculateWaveFunction(unsigned int ihel) { _wf = HelicityFunctions::spinor(momentum(),ihel,direction()); } 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()!=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()!=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()); calculateWaveFunctions(waves,particle->momentum(),particle->dataPtr(),dir); } } void SpinorWaveFunction:: calculateWaveFunctions(vector & waves, const Lorentz5Momentum & momentum, tcPDPtr parton,Direction dir) { waves.resize(2); SpinorWaveFunction wave(momentum,parton,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()!=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()!=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/SpinorWaveFunction.h b/Helicity/WaveFunction/SpinorWaveFunction.h --- a/Helicity/WaveFunction/SpinorWaveFunction.h +++ b/Helicity/WaveFunction/SpinorWaveFunction.h @@ -1,315 +1,315 @@ // -*- C++ -*- // // SpinorWaveFunction.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_SpinorWaveFunction_H #define ThePEG_SpinorWaveFunction_H // // This is the declaration of the SpinorWaveFunction class. // #include "WaveFunctionBase.h" #include #include #include #include namespace ThePEG { namespace Helicity { /** * Forward declaration of the SpinorBarWaveFunction class */ class SpinorBarWaveFunction; /** \ingroup Helicity * \author Peter Richardson * * The SpinorWaveFunction class is designed to store the wavefunction * of a spinor in a form suitable for use in helicity amplitude calculations * of the matrix element using a similar philosophy to the FORTRAN HELAS code. * * In addition to storing the spinor using the LorentzSpinor class * it inherits from the WaveFunctionBase class to provide storage of * the momentum and getParticleData for the fermion. * * This class also contains the code which does the actually calculation * of the spinor for an external particle. * * When calculating the wavefunction the direction of the particle is used, * * \e i.e. * - incoming calculates a \f$u\f$ spinor. * - outgoing calculates a \f$v\f$ spinor. * * N.B. In our convention 0 is the \f$-\frac12\f$ helicity state and * 1 is the \f$+\frac12\f$ helicity state * * @see WaveFunctionBase * @see LorentzSpinor * @see HelicityDefinitions */ class SpinorWaveFunction : public WaveFunctionBase { public: /** @name Standard constructors and destructors. */ //@{ /** * Constructor, set the momentum and the components of the spinor. * @param p The momentum. * @param part The ParticleData pointer. * @param s1 The first component * @param s2 The second component * @param s3 The third component * @param s4 The fourth component */ SpinorWaveFunction(const Lorentz5Momentum & p,tcPDPtr part,complex s1, complex s2,complex s3,complex s4) : WaveFunctionBase(p,part), _wf(s1,s2,s3,s4) { assert(iSpin()==2); } /** * Constructor, set the momentum and the wavefunction. * @param p The momentum. * @param part The ParticleData pointer. * @param wave The wavefunction. * @param dir The direction of the particle */ SpinorWaveFunction(const Lorentz5Momentum & p, tcPDPtr part, const LorentzSpinor & wave, Direction dir=intermediate) : WaveFunctionBase(p,part,dir), _wf(wave) { assert(iSpin()==2); } /** * Constructor, set the momentum and the wavefunction. * @param p The particle * @param wave The wavefunction. * @param dir The direction of the particle */ SpinorWaveFunction(const tPPtr & p, const LorentzSpinor & wave, Direction dir=intermediate) : WaveFunctionBase(p->momentum(), p->dataPtr(), dir), _wf(wave.Type()) { assert(iSpin()==2); for (unsigned int i=0; i<4; ++i) _wf[i]=Complex(wave[i]*UnitRemoval::InvSqrtE); } /** * Constructor, set the momentum, helicity, direction. * @param p The momentum. * @param part The ParticleData pointer. * @param ihel The helicity (0,1 as described above.) * @param dir The direction. */ SpinorWaveFunction(const Lorentz5Momentum & p,tcPDPtr part, unsigned int ihel, Direction dir) : WaveFunctionBase(p,part,dir) { assert(iSpin()==2); calculateWaveFunction(ihel); } /** * Constructor, set the momentum, direction, zero the * wavefunction. * @param p The momentum. * @param part The ParticleData pointer. * @param dir The direction. */ SpinorWaveFunction(const Lorentz5Momentum & p, tcPDPtr part,Direction dir) : WaveFunctionBase(p,part,dir), _wf() { assert(iSpin()==2); } /** * Default constructor. */ SpinorWaveFunction() : WaveFunctionBase(), _wf() {} /** * Special for spin correlations */ SpinorWaveFunction(vector & wave, tPPtr part,Direction dir,bool time,bool=true) { calculateWaveFunctions(wave,part,dir); constructSpinInfo(wave,part,dir,time); } //@} /** * Access to the wavefunction and its components. */ //@{ /** * Subscript operator for the wavefunction. */ complex operator ()(int i) const { assert(i>=0 &&i<=3); return _wf(i); } /** * Return wavefunction as LorentzSpinor. */ const LorentzSpinor & wave() const {return _wf;} /** * Return wavefunction as LorentzSpinor. */ LorentzSpinor dimensionedWave() const {return dimensionedWf();} /** * Get the first spin component component. */ complex s1() const {return _wf.s1();} /** * Get the second spin component component. */ complex s2() const {return _wf.s2();} /** * Get the third spin component component. */ complex s3() const {return _wf.s3();} /** * Get the fourth spin component component. */ complex s4() const {return _wf.s4();} //@} /** * Take the conjugate of the 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. */ void conjugate() { _wf=_wf.conjugate(); } /** * Return the barred spinor */ SpinorBarWaveFunction bar(); /** * Reset functions. */ //@{ /** * Reset the helicity (calculates the new spinor). * @param ihel The helicity (0,1 as described above.) */ void reset(unsigned int ihel) { calculateWaveFunction(ihel); } //@} public: /** * Perform the Lorentz transformation of the wave function */ void transform(const LorentzRotation & r) { _wf.transform(r); transformMomentum(r); } public: /** * Calculate the wavefunctions */ static void calculateWaveFunctions(vector > & waves, tPPtr particle,Direction); /** * Calculate the wavefunctions */ static void calculateWaveFunctions(vector & waves, tPPtr particle,Direction); /** * Calculate the wavefunctions */ static void calculateWaveFunctions(vector & waves, const Lorentz5Momentum & momentum, tcPDPtr parton,Direction); /** * Calculate the wavefunctions */ static void calculateWaveFunctions(vector > & waves, RhoDMatrix & rho, tPPtr particle,Direction); /** * Calculate the wavefunctions */ static void calculateWaveFunctions(vector & waves, RhoDMatrix & rho, tPPtr particle,Direction); /** * Construct the SpinInfo object */ static void constructSpinInfo(const vector > & waves, tPPtr part,Direction dir, bool time); /** * Construct the SpinInfo object */ static void constructSpinInfo(const vector & waves, tPPtr part,Direction dir, bool time); private: /** * Calcuate the wavefunction. * @param ihel The helicity (0,1 as described above.) */ void calculateWaveFunction(unsigned int ihel); private: /** * Storage of the Lorentz Spinor. */ LorentzSpinor _wf; /// Return wavefunction as LorentzSpinor LorentzSpinor dimensionedWf() const { LorentzSpinor temp(_wf.Type()); for (unsigned int i=0; i<4; ++i) temp(i) = _wf(i)*UnitRemoval::SqrtE; return temp; } }; } } #endif diff --git a/Helicity/WaveFunction/TensorWaveFunction.cc b/Helicity/WaveFunction/TensorWaveFunction.cc --- a/Helicity/WaveFunction/TensorWaveFunction.cc +++ b/Helicity/WaveFunction/TensorWaveFunction.cc @@ -1,338 +1,338 @@ // -*- C++ -*- // // TensorWaveFunction.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the TensorWaveFunction class. // // Author: Peter Richardson // #include "TensorWaveFunction.h" using namespace ThePEG; using namespace ThePEG::Helicity; // calculate the actual wavefunction void TensorWaveFunction::calculateWaveFunction(unsigned int ihel, TensorPhase tphase) { int jhel=ihel-2; assert(direction()!=intermediate); // check for a valid helicty combination assert((jhel<=2 && jhel>=-2 && mass() >ZERO) || ((jhel==2 || jhel==-2) && mass()==ZERO)); // extract the momentum components double fact = direction()==outgoing ? -1. : 1; Energy ppx=fact*px(),ppy=fact*py(),ppz=fact*pz(),pee=fact*e(),pmm=mass(); // calculate some kinematic quantites; Energy2 pt2 = sqr(ppx)+sqr(ppy); Energy pabs = sqrt(pt2+sqr(ppz)); Energy pt = sqrt(pt2); // polarization vectors complex epsp[4],epsm[4],eps0[4]; // + helicity vector if needed if(jhel>=0) { // calculate the overall phase complexphase; if(tphase==tensor_phase) { phase = pt==ZERO ? 1. : complex(ppx/pt,-fact*ppy/pt); } else phase = 1.; phase = phase*sqrt(0.5); // first the no pt case if(pt==ZERO) { double sgnz = ppz(0,-fact); epsp[2]=0.; epsp[3]=0.; } else { InvEnergy opabs=1./pabs; InvEnergy opt =1./pt; epsp[0]=phase*complex(-ppz*ppx*opabs*opt, fact*ppy*opt); epsp[1]=phase*complex(-ppz*ppy*opabs*opt, -fact*ppx*opt); epsp[2]=Complex(pt*opabs*phase); epsp[3]=0.; } } // - helicity vector if needed if(jhel<=0) { // calculate the overall phase complex phase; if(tphase==tensor_phase) { phase = pt==ZERO ? 1. : complex(ppx/pt,fact*ppy/pt); } else phase = 1.; phase = phase*sqrt(0.5); // first the no pt case if(pt==ZERO) { double sgnz; if(ppz(0,-fact); epsm[2]=0.; epsm[3]=0.; } else { InvEnergy opabs=1./pabs; InvEnergy opt =1./pt; epsm[0]=phase*complex(ppz*ppx*opabs*opt, fact*ppy*opt); epsm[1]=phase*complex(ppz*ppy*opabs*opt, -fact*ppx*opt); epsm[2]=-Complex(pt*opabs*phase); epsm[3]=0.; } } // 0 helicity vector if needed if(jhel<=1 && jhel>=-1) { if(pabs==ZERO) { eps0[0] = 0.; eps0[1] = 0.; eps0[2] = 1.; eps0[3] = 0.; } else { InvEnergy empabs=pee/pmm/pabs; eps0[0] = empabs*ppx; eps0[1] = empabs*ppy; eps0[2] = empabs*ppz; eps0[3] = pabs/pmm; } } // put the polarization vectors together to get the wavefunction double ort; switch (jhel) { case 2: for(int ix=0;ix<4;++ix) for(int iy=0;iy<4;++iy) _wf(ix,iy)=epsp[ix]*epsp[iy]; break; case 1: ort = sqrt(0.5); for(int ix=0;ix<4;++ix) for(int iy=0;iy<4;++iy) _wf(ix,iy)=ort*( epsp[ix]*eps0[iy]+ eps0[ix]*epsp[iy]); break; case 0: ort = 1./sqrt(6.); for(int ix=0;ix<4;++ix) for(int iy=0;iy<4;++iy) _wf(ix,iy)=ort*( epsp[ix]*epsm[iy] + epsm[ix]*epsp[iy] +2.*eps0[ix]*eps0[iy]); break; case -1: ort = 1./sqrt(2.); for(int ix=0;ix<4;++ix) for(int iy=0;iy<4;++iy) _wf(ix,iy)=ort*( epsm[ix]*eps0[iy]+ eps0[ix]*epsm[iy]); break; case -2: for(int ix=0;ix<4;++ix) for(int iy=0;iy<4;++iy) _wf(ix,iy)=epsm[ix]*epsm[iy]; break; default: ThePEG::Helicity::HelicityConsistencyError() << "Invalid Helicity = " << jhel << " requested for Tensor" << Exception::abortnow; break; } } void TensorWaveFunction:: calculateWaveFunctions(vector > & waves, tPPtr particle,Direction dir, bool massless, TensorPhase phase) { tTensorSpinPtr inspin = !particle->spinInfo() ? tTensorSpinPtr() : dynamic_ptr_cast(particle->spinInfo()); waves.resize(5); if(inspin) { if(dir==outgoing) { for(unsigned int ix=0;ix<5;++ix) waves[ix]=inspin->getProductionBasisState(ix); } else { inspin->decay(); for(unsigned int ix=0;ix<5;++ix) waves[ix]=inspin->getDecayBasisState(ix); } } else { assert(!particle->spinInfo()); TensorWaveFunction wave(particle->momentum(),particle->dataPtr(),0, dir,phase); for(unsigned int ix=0;ix<5;++ix) { if(massless&&ix>0&&ix<5) { waves[ix] = LorentzTensor(); } else { if(ix!=0) wave.reset(ix); waves[ix] = wave.wave(); } } } } void TensorWaveFunction:: calculateWaveFunctions(vector & waves, tPPtr particle, Direction dir, bool massless, TensorPhase phase) { tTensorSpinPtr inspin = !particle->spinInfo() ? tTensorSpinPtr() : dynamic_ptr_cast(particle->spinInfo()); waves.resize(5); if(inspin) { if(dir==outgoing) { for(unsigned int ix=0;ix<5;++ix) waves[ix]=TensorWaveFunction(particle->momentum(), particle->dataPtr(), inspin->getProductionBasisState(ix),dir); } else { inspin->decay(); for(unsigned int ix=0;ix<5;++ix) waves[ix]=TensorWaveFunction(particle->momentum(), particle->dataPtr(), inspin->getDecayBasisState(ix),dir); } } else { assert(!particle->spinInfo()); TensorWaveFunction wave(particle->momentum(),particle->dataPtr(),0, dir,phase); for(unsigned int ix=0;ix<5;++ix) { if(massless&&ix>0&&ix<5) { waves[ix] = TensorWaveFunction(particle->momentum(),particle->dataPtr(),dir); } else { if(ix!=0) wave.reset(ix); waves[ix] = wave; } } } } void TensorWaveFunction:: calculateWaveFunctions(vector > & waves, RhoDMatrix & rho, tPPtr particle,Direction dir,bool massless, TensorPhase phase) { tTensorSpinPtr inspin = !particle->spinInfo() ? tTensorSpinPtr() : dynamic_ptr_cast(particle->spinInfo()); waves.resize(5); if(inspin) { if(dir==outgoing) { for(unsigned int ix=0;ix<5;++ix) waves[ix]=inspin->getProductionBasisState(ix); rho = RhoDMatrix(PDT::Spin2); } else { inspin->decay(); for(unsigned int ix=0;ix<5;++ix) waves[ix]=inspin->getDecayBasisState(ix); rho = inspin->rhoMatrix(); } } else { assert(!particle->spinInfo()); TensorWaveFunction wave(particle->momentum(),particle->dataPtr(),0, dir,phase); for(unsigned int ix=0;ix<5;++ix) { if(massless&&ix>0&&ix<5) { waves[ix] = LorentzTensor(); } else { if(ix!=0) wave.reset(ix); waves[ix] = wave.wave(); } } rho = RhoDMatrix(PDT::Spin2); } } void TensorWaveFunction:: calculateWaveFunctions(vector & waves, RhoDMatrix & rho, tPPtr particle, Direction dir, bool massless, TensorPhase phase) { tTensorSpinPtr inspin = !particle->spinInfo() ? tTensorSpinPtr() : dynamic_ptr_cast(particle->spinInfo()); waves.resize(5); if(inspin) { if(dir==outgoing) { for(unsigned int ix=0;ix<5;++ix) waves[ix]=TensorWaveFunction(particle->momentum(), particle->dataPtr(), inspin->getProductionBasisState(ix),dir); rho = RhoDMatrix(PDT::Spin2); } else { inspin->decay(); for(unsigned int ix=0;ix<5;++ix) waves[ix]=TensorWaveFunction(particle->momentum(), particle->dataPtr(), inspin->getDecayBasisState(ix),dir); rho = inspin->rhoMatrix(); } } else { assert(!particle->spinInfo()); TensorWaveFunction wave(particle->momentum(),particle->dataPtr(),0, dir,phase); for(unsigned int ix=0;ix<5;++ix) { if(massless&&ix>0&&ix<5) { waves[ix] = TensorWaveFunction(particle->momentum(),particle->dataPtr(),dir); } else { if(ix!=0) wave.reset(ix); waves[ix] = wave; } } rho = RhoDMatrix(PDT::Spin2); } } void TensorWaveFunction:: constructSpinInfo(const vector > & waves, tPPtr part,Direction dir, bool time,bool ) { assert(waves.size()==5); tTensorSpinPtr inspin = !part->spinInfo() ? tTensorSpinPtr() : dynamic_ptr_cast(part->spinInfo()); if(inspin) { for(unsigned int ix=0;ix<5;++ix) if(dir==outgoing) inspin->setBasisState(ix,waves[ix]); else inspin->setDecayState(ix,waves[ix]); } else { TensorSpinPtr temp = new_ptr(TensorSpinInfo(part->momentum(),time)); part->spinInfo(temp); for(unsigned int ix=0;ix<5;++ix) if(dir==outgoing) temp->setBasisState(ix,waves[ix]); else temp->setDecayState(ix,waves[ix]); } } void TensorWaveFunction:: constructSpinInfo(const vector & waves, tPPtr part,Direction dir, bool time,bool ) { assert(waves.size()==5); tTensorSpinPtr inspin = !part->spinInfo() ? tTensorSpinPtr() : dynamic_ptr_cast(part->spinInfo()); if(inspin) { for(unsigned int ix=0;ix<5;++ix) if(dir==outgoing) inspin->setBasisState(ix,waves[ix].wave()); else inspin->setDecayState(ix,waves[ix].wave()); } else { TensorSpinPtr temp = new_ptr(TensorSpinInfo(part->momentum(),time)); part->spinInfo(temp); for(unsigned int ix=0;ix<5;++ix) if(dir==outgoing) temp->setBasisState(ix,waves[ix].wave()); else temp->setDecayState(ix,waves[ix].wave()); } } diff --git a/Helicity/WaveFunction/TensorWaveFunction.h b/Helicity/WaveFunction/TensorWaveFunction.h --- a/Helicity/WaveFunction/TensorWaveFunction.h +++ b/Helicity/WaveFunction/TensorWaveFunction.h @@ -1,364 +1,364 @@ // -*- C++ -*- // // TensorWaveFunction.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_TensorWaveFunction_H #define ThePEG_TensorWaveFunction_H // // This is the declaration of the TensorWaveFunction class. // #include "WaveFunctionBase.h" #include "VectorWaveFunction.h" #include #include #include #include namespace ThePEG { namespace Helicity { /**\ingroup Helicity * Definition of the enumerated values of the phase to include in the * calculation of the polarization tensor. */ enum TensorPhase { tensor_phase, /**< Include the phase factor.*/ tensor_nophase, /**< No phase-factor. */ default_tensor_phase=tensor_nophase /**< Default option.*/ }; /** \ingroup Helicity * \author Peter Richardson * * The TensorWaveFunction class is designed to store the wavefunction * of a tensor in a form suitable for use in helicity amplitude * calculations of the matrix element using a similar philosophy to the * FORTRAN HELAS code. * * In addition to storing the tensor using the LorentzTensor class * it inherits from the WaveFunctionBase class to provide storage of * the momentum and ParticleData for the tensor particle. * * This class also contains the code which does the actually * calculation of the tensor wavefunction. * * There are two choices available for the calculation of the * wavefunction. These are set using the TensorPhase enumeration * which specifies a default choice. * The first choice, tensor_phase, includes a phase factor * \f$\exp(\pm i \phi)\f$ for the \f$\pm\f$ helicity states while the second, * tensor_nophase, does not. * * 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. * * @see WaveFunctionBase * @see LorentzTensor * @see VectorWaveFunction */ class TensorWaveFunction : public WaveFunctionBase { public: /** @name Standard constructors and destructors. */ //@{ /** * Constructor, set the momentum and Wavefunction, the direction can also * be specified. * @param p The momentum. * @param part The ParticleData pointer * @param wave The wavefunction, \e i.e. the polarization vector. * @param dir The direction of the particle. */ TensorWaveFunction(const Lorentz5Momentum & p,tcPDPtr part, const LorentzTensor & wave, Direction dir=intermediate) : WaveFunctionBase(p,part,dir), _wf(wave) { assert(iSpin()==PDT::Spin2); } /** * Constructor, set the momentum and the components of the tensor. * @param p The momentum. * @param part The ParticleData pointer * @param xx The \f$xx\f$ component. * @param xy The \f$xy\f$ component. * @param xz The \f$xz\f$ component. * @param xt The \f$xt\f$ component. * @param yx The \f$yx\f$ component. * @param yy The \f$yy\f$ component. * @param yz The \f$yz\f$ component. * @param yt The \f$yt\f$ component. * @param zx The \f$zx\f$ component. * @param zy The \f$zy\f$ component. * @param zz The \f$zz\f$ component. * @param zt The \f$zt\f$ component. * @param tx The \f$tx\f$ component. * @param ty The \f$ty\f$ component. * @param tz The \f$tz\f$ component. * @param tt The \f$tt\f$ component. */ TensorWaveFunction(const Lorentz5Momentum & p,tcPDPtr part, 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) : WaveFunctionBase(p,part), _wf(xx,xy,xz,xt, yx,yy,yz,yt, zx,zy,zz,zt, tx,ty,tz,tt) { assert(iSpin()==PDT::Spin2); } /** * Constructor, set the momentum, helicity, direction and optionally the phase * @param p The momentum. * @param part The ParticleData pointer * @param ihel The helicity (0,1,2,3,4 as described above.) * @param dir The direction. * @param phase The phase choice. */ TensorWaveFunction(const Lorentz5Momentum & p,tcPDPtr part, unsigned int ihel,Direction dir, TensorPhase phase=default_tensor_phase) : WaveFunctionBase(p,part,dir) { assert(iSpin()==PDT::Spin2); calculateWaveFunction(ihel,phase); } /** * Constructor, set the 5-momentum and direction, zero the wavefunction. * @param p The momentum. * @param part The ParticleData pointer. * @param dir The direction. */ TensorWaveFunction(const Lorentz5Momentum & p, tcPDPtr part,Direction dir) : WaveFunctionBase(p,part,dir), _wf() { assert(iSpin()==PDT::Spin2); } /** * Default constructor. */ TensorWaveFunction() {} /** * Special for spin correlations \todo make static? */ TensorWaveFunction(vector & wave, tPPtr part,Direction dir,bool time,bool massless, bool=true, TensorPhase phase=default_tensor_phase) { calculateWaveFunctions(wave,part,dir,massless,phase); constructSpinInfo(wave,part,dir,time,massless); } //@} /** * Access to the wavefunction and its components. */ //@{ /** * Subscript operator for the wavefunction. */ Complex operator ()(int i, int j) const { return _wf(i,j); } /** * Set components by index. */ Complex & operator () (int i, int j) { return _wf(i,j); } /** * Return wavefunction as polarization vector. */ const LorentzTensor & wave() const {return _wf;} /** * Get the \f$xx\f$ component. */ Complex xx() const {return _wf.xx();} /** * Get the \f$yx\f$ component. */ Complex yx() const {return _wf.yx();} /** * Get the \f$zx\f$ component. */ Complex zx() const {return _wf.zx();} /** * Get the \f$tx\f$ component. */ Complex tx() const {return _wf.tx();} /** * Get the \f$xy\f$ component. */ Complex xy() const {return _wf.xy();} /** * Get the \f$yy\f$ component. */ Complex yy() const {return _wf.yy();} /** * Get the \f$zy\f$ component. */ Complex zy() const {return _wf.zy();} /** * Get the \f$ty\f$ component. */ Complex ty() const {return _wf.ty();} /** * Get the \f$xz\f$ component. */ Complex xz() const {return _wf.xz();} /** * Get the \f$yz\f$ component. */ Complex yz() const {return _wf.yz();} /** * Get the \f$zz\f$ component. */ Complex zz() const {return _wf.zz();} /** * Get the \f$tz\f$ component. */ Complex tz() const {return _wf.tz();} /** * Get the \f$xt\f$ component. */ Complex xt() const {return _wf.xt();} /** * Get the \f$yt\f$ component. */ Complex yt() const {return _wf.yt();} /** * Get the \f$zt\f$ component. */ Complex zt() const {return _wf.zt();} /** * Get the \f$tt\f$ component. */ Complex tt() const {return _wf.tt();} //@} /** * Reset functions. */ //@{ /** * Reset helicity (recalculate the tensor ). * @param ihel The new helicity (0,1,2,3,4 as described above.) * @param phase The phase choice. */ void reset(unsigned int ihel,TensorPhase phase=default_tensor_phase) { calculateWaveFunction(ihel,phase); } //@} public: /** * Perform the Lorentz transformation of the wave function */ void transform(const LorentzRotation & r) { _wf.transform(r); transformMomentum(r); } public: /** * Calculate the wavefunctions */ static void calculateWaveFunctions(vector > & waves, tPPtr particle,Direction,bool massless, TensorPhase phase=default_tensor_phase); /** * Calculate the wavefunctions */ static void calculateWaveFunctions(vector & waves, tPPtr particle,Direction,bool massless, TensorPhase phase=default_tensor_phase); /** * Calculate the wavefunctions */ static void calculateWaveFunctions(vector > & waves, RhoDMatrix & rho, tPPtr particle,Direction,bool massless, TensorPhase phase=default_tensor_phase); /** * Calculate the wavefunctions */ static void calculateWaveFunctions(vector & waves, RhoDMatrix & rho, tPPtr particle,Direction,bool massless, TensorPhase phase=default_tensor_phase); /** * Construct the SpinInfo object */ static void constructSpinInfo(const vector > & waves, tPPtr part,Direction dir, bool time,bool massless); /** * Construct the SpinInfo object */ static void constructSpinInfo(const vector & waves, tPPtr part,Direction dir, bool time,bool massless); private: /** * Calculate the wavefunction. * @param ihel The helicity (0,1,2,3,4 as described above.) * @param phase The phase choice. */ void calculateWaveFunction(unsigned int ihel, TensorPhase phase=default_tensor_phase); private: /** * Storage of the wavefunction as a Lorentz Tensor. */ LorentzTensor _wf; }; } } #endif diff --git a/Helicity/WaveFunction/VectorWaveFunction.cc b/Helicity/WaveFunction/VectorWaveFunction.cc --- a/Helicity/WaveFunction/VectorWaveFunction.cc +++ b/Helicity/WaveFunction/VectorWaveFunction.cc @@ -1,240 +1,240 @@ // -*- C++ -*- // // VectorWaveFunction.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the VectorWaveFunction class. // // Author: Peter Richardson // #include "VectorWaveFunction.h" #include "ThePEG/Helicity/HelicityFunctions.h" using namespace ThePEG; using namespace ThePEG::Helicity; // calculate the Wavefunction void VectorWaveFunction::calculateWaveFunction(unsigned int ihel,VectorPhase vphase) { _wf = HelicityFunctions::polarizationVector(momentum(),ihel,direction(),vphase); } 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()); calculateWaveFunctions(waves,particle->momentum(),particle->dataPtr(), dir,massless,phase); } } void VectorWaveFunction:: calculateWaveFunctions(vector & waves, const Lorentz5Momentum & momentum, tcPDPtr parton, Direction dir, bool massless, VectorPhase phase) { waves.resize(3); VectorWaveFunction wave(momentum,parton,0,dir,phase); for(unsigned int ix=0;ix<3;++ix) { if(massless&&ix==1) { waves[ix] = VectorWaveFunction(momentum,parton,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 && 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 && 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 && 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 && time) || ( dir == incoming && !time)) temp->setBasisState(ix,waves[ix].wave()); else temp->setDecayState(ix,waves[ix].wave()); } } diff --git a/Helicity/WaveFunction/VectorWaveFunction.h b/Helicity/WaveFunction/VectorWaveFunction.h --- a/Helicity/WaveFunction/VectorWaveFunction.h +++ b/Helicity/WaveFunction/VectorWaveFunction.h @@ -1,263 +1,263 @@ // -*- C++ -*- // // VectorWaveFunction.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_VectorWaveFunction_H #define ThePEG_VectorWaveFunction_H // // This is the declaration of the VectorWaveFunction class. // #include "WaveFunctionBase.h" #include #include #include #include namespace ThePEG { namespace Helicity { /** \ingroup Helicity * * \author Peter Richardson * * The VectorWaveFunction class is designed to store the wavefunction * of a vector in a form suitable for use in helicity amplitude calculations * of the matrix element using a similar philosophy to the FORTRAN HELAS code. * * In addition to storing the vector using the LorentzPolarizationVector class * it inherits from the WaveFunctionBase class to provide storage of the * momentum and ParticleData for the vector boson. * * This class also contains the code which does the actually calculation of the * vector wavefunction. * * There are two choices available for the calculation of the wavefunction. * These are set using the VectorPhase enumeration which specifies a default choice. * The first choice, vector_phase, includes a phase factor \f$\exp(\pm i \phi)\f$ * for the \f$\pm\f$ helicity states while the second, vector_nophase, does not. * * N.B. In our convention 0 is the \f$-1\f$ helicity state and * 1 is the \f$0\f$ helicity state * 2 is the \f$+1\f$ helicity state * * @see WaveFunctionBase * @see LorentzPolarizationVector */ class VectorWaveFunction : public WaveFunctionBase { public: /** @name Standard constructors and destructors. */ //@{ /** * Constructor, set the momentum and Wavefunction, the direction can also * be specified. * @param p The momentum. * @param part The ParticleData pointer * @param wave The wavefunction, \e i.e. the polarization vector. * @param dir The direction of the particle. */ VectorWaveFunction(const Lorentz5Momentum & p,tcPDPtr part, const LorentzPolarizationVector & wave, Direction dir=intermediate) : WaveFunctionBase(p,part,dir), _wf(wave) { assert(iSpin()==3); } /** * Constructor, set the momentum and components of the wavefunction. * @param p The momentum. * @param part The ParticleData pointer * @param x The x component of the polarization vector * @param y The y component of the polarization vector * @param z The z component of the polarization vector * @param t The t component of the polarization vector */ VectorWaveFunction(const Lorentz5Momentum & p,tcPDPtr part,const Complex & x, const Complex & y,const Complex & z, const Complex & t) : WaveFunctionBase(p,part), _wf(x,y,z,t) { assert(iSpin()==3); } /** * Constructor, set the momentum, helicity and direction, optionally the choice * of the phase. * @param p The momentum. * @param part The ParticleData pointer. * @param ihel The helicity (0,1,2 as described above.) * @param dir The direction. * @param phase The phase choice. */ VectorWaveFunction(const Lorentz5Momentum & p,tcPDPtr part, unsigned int ihel,Direction dir, VectorPhase phase=default_vector_phase) : WaveFunctionBase(p,part,dir) { assert(iSpin()==3); calculateWaveFunction(ihel,phase); } /** * Constructor, set the 5-momentum and direction, zero the wavefunction. * @param p The 5-momentum. * @param part The ParticleData pointer. * @param dir The direction. */ VectorWaveFunction(const Lorentz5Momentum &p, tcPDPtr part,Direction dir) : WaveFunctionBase(p,part,dir), _wf() { assert(iSpin()==3); } /** * Default constructor. */ VectorWaveFunction() {} /** * Special for spin correlations \todo make static? */ VectorWaveFunction(vector & wave, tPPtr part,Direction dir,bool time,bool massless, bool=true, VectorPhase phase=default_vector_phase) { calculateWaveFunctions(wave,part,dir,massless,phase); constructSpinInfo(wave,part,dir,time,massless); } //@} /** * Access to the wavefunction and its components. */ //@{ /** * Return wavefunction as polarization vector. */ const LorentzPolarizationVector & wave() const { return _wf;} /** * Get x component. */ Complex x() const {return _wf.x();} /** * Get y component. */ Complex y() const {return _wf.y();} /** * Get z component. */ Complex z() const {return _wf.z();} /** * Get t component. */ Complex t() const {return _wf.t();} /** * Reset functions. */ //@{ /** * Reset the helicity (recalculation the polarization vector). * @param ihel The new helicity (0,1,2 as described above.) * @param phase The phase choice. */ void reset(unsigned int ihel,VectorPhase phase=default_vector_phase) { calculateWaveFunction(ihel,phase); } //@} public: /** * Perform the Lorentz transformation of the wave function */ void transform(const LorentzRotation & r) { _wf.transform(r); transformMomentum(r); } public: /** * Calculate the wavefunctions */ static void calculateWaveFunctions(vector & waves, tPPtr particle,Direction,bool massless, VectorPhase phase=default_vector_phase); /** * Calculate the wavefunctions */ static void calculateWaveFunctions(vector & waves, tPPtr particle,Direction,bool massless, VectorPhase phase=default_vector_phase); /** * Calculate the wavefunctions */ static void calculateWaveFunctions(vector & waves, const Lorentz5Momentum & momentum, tcPDPtr parton, Direction,bool massless, VectorPhase phase=default_vector_phase); /** * Calculate the wavefunctions */ static void calculateWaveFunctions(vector & waves, RhoDMatrix & rho, tPPtr particle,Direction,bool massless, VectorPhase phase=default_vector_phase); /** * Calculate the wavefunctions */ static void calculateWaveFunctions(vector & waves, RhoDMatrix & rho, tPPtr particle,Direction,bool massless, VectorPhase phase=default_vector_phase); /** * Construct the SpinInfo object */ static void constructSpinInfo(const vector & waves, tPPtr part,Direction dir, bool time,bool massless); /** * Construct the SpinInfo object */ static void constructSpinInfo(const vector & waves, tPPtr part,Direction dir, bool time,bool massless); private: /** * Calculate the wavefunction * @param ihel The helicity (0,1,2 as described above.) * @param phase The phase choice. */ void calculateWaveFunction(unsigned int ihel, VectorPhase phase=default_vector_phase); private: /** * Storage of the wavefunction as a Lorentz Vector. */ LorentzPolarizationVector _wf; }; } } #endif diff --git a/Helicity/WaveFunction/WaveFunctionBase.h b/Helicity/WaveFunction/WaveFunctionBase.h --- a/Helicity/WaveFunction/WaveFunctionBase.h +++ b/Helicity/WaveFunction/WaveFunctionBase.h @@ -1,186 +1,186 @@ // -*- C++ -*- // // WaveFunctionBase.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_WaveFunctionBase_H #define ThePEG_WaveFunctionBase_H // // This is the declaration of the WaveFunctionBase class. #include #include #include #include namespace ThePEG { namespace Helicity { /** \ingroup Helicity * Definition of the enumerated values used for the direction of the * particles in the calculation of the wavefunction. */ enum Direction { incoming, /**< An incoming particle. */ outgoing, /**< An outgoing particle. */ intermediate /**< An intermediate particle. */ }; /** \ingroup Helicity * \author Peter Richardson * * This class is the base class for all wavefunctions for use in helicity amplitude * calculations. The general approach is to use a similar philosophy * to the FORTRAN HELAS code but with additional structure. * * This class contains the storage of the particle type and 5-momentum * and methods to set/access this information. * * The methods for the wavefunction itself will be implemented in the classes * derived from this one for the specific spin type, for example scalar, spinor, * vector and tensor. * * @see ScalarWaveFunction * @see SpinorWaveFunction * @see SpinorBarWaveFunction * @see VectorWaveFunction * @see RSSpinorWaveFunction * @see RSSpinorBarWaveFunction * @see TensorWaveFunction */ class WaveFunctionBase{ public: /// Constructors //@{ /** * Default constructor */ WaveFunctionBase() : _particle(), _momentum(), _dir(intermediate) {} /** * */ WaveFunctionBase(const Lorentz5Momentum & p, tcPDPtr pd, Direction dir = intermediate) : _particle(pd), _momentum(p), _dir(dir) { if(_dir==outgoing) _momentum *= -1.0; if ( dir != outgoing ) { tcPDPtr anti = pd->CC(); if ( anti ) _particle = anti; } } //@} /** * Access to the momentum components and mass */ //@{ /** * Get the x component of the momentum. */ Energy px() const {return _momentum.x();} /** * Get the y component of the momentum. */ Energy py() const {return _momentum.y();} /** * Get the z component of the momentum. */ Energy pz() const {return _momentum.z();} /** * Get the energy. */ Energy e() const {return _momentum.e();} /** * Get the mass. */ Energy mass() const {return _momentum.mass();} /** * Get off-shell mass squared. */ Energy2 m2() const {return _momentum.m2();} /** * Access to the 5-momentum */ const Lorentz5Momentum & momentum() const {return _momentum;} //@} /** * Access to the particle properties */ //@{ /** * Get the particle id. */ long id() const {return _particle->id();} /** * Get 2s+1 for the particle. */ PDT::Spin iSpin() const {return _particle->iSpin();} /** * Get the particle pointer. */ tcPDPtr particle() const {return _particle;} /** * Get the direction of particle. */ ThePEG::Helicity::Direction direction() const {return _dir;} /** * Set the direction of the particle */ void direction(ThePEG::Helicity::Direction in) {_dir=in;} //@} protected: /** * Perform the Lorentz transformation of the wave function */ void transformMomentum(const LorentzRotation & r) { _momentum.transform(r); } private: /** * Constant pointer to the particle info. */ tcPDPtr _particle; /** * Lorentz 5 momentum. */ Lorentz5Momentum _momentum; /** * Incoming or outgoing. */ Direction _dir; }; } } #endif diff --git a/Helicity/epsilon.h b/Helicity/epsilon.h --- a/Helicity/epsilon.h +++ b/Helicity/epsilon.h @@ -1,66 +1,66 @@ // -*- C++ -*- // // epsilon.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2003-2017 Peter Richardson, Leif Lonnblad +// Copyright (C) 2003-2019 Peter Richardson, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_epsilon_H #define ThePEG_epsilon_H // // This is the declaration of the epsilon class. #include "ThePEG/Vectors/LorentzVector.h" namespace ThePEG { namespace Helicity { /** \ingroup Helicity * \author Peter Richardson * * This class is designed to combine 5-momenta and polarization * vectors together with the result being the product with the * eps function. The class is purely static and contains no data. * * @see LorentzPolarizationVector * @see Lorentz5Vector */ /** * Return the product * \f$\epsilon^{\mu\alpha\beta\gamma}v_{1\alpha}v_{2\beta}v_{3\gamma}\f$. * @param a The first vector \f$v_{1\alpha}\f$. * @param b The second vector \f$v_{2\alpha}\f$. * @param c The third vector \f$v_{3\alpha}\f$. * @return The product * \f$\epsilon^{\mu\alpha\beta\gamma}v_{1\alpha}v_{2\beta}v_{3\gamma}\f$. */ template auto epsilon(const LorentzVector & a, const LorentzVector & b, const LorentzVector & c) -> LorentzVector { auto diffxy = a.x() * b.y() - a.y() * b.x(); auto diffxz = a.x() * b.z() - a.z() * b.x(); auto diffxt = a.x() * b.t() - a.t() * b.x(); auto diffyz = a.y() * b.z() - a.z() * b.y(); auto diffyt = a.y() * b.t() - a.t() * b.y(); auto diffzt = a.z() * b.t() - a.t() * b.z(); using ResultType = LorentzVector; ResultType result; result.setX( c.z() * diffyt - c.t() * diffyz - c.y() * diffzt); result.setY( c.t() * diffxz - c.z() * diffxt + c.x() * diffzt); result.setZ(-c.t() * diffxy + c.y() * diffxt - c.x() * diffyt); result.setT(-c.z() * diffxy + c.y() * diffxz - c.x() * diffyz); return result; } } } #endif /* ThePEG_epsilon_H */ diff --git a/Interface/ClassDocumentation.cc b/Interface/ClassDocumentation.cc --- a/Interface/ClassDocumentation.cc +++ b/Interface/ClassDocumentation.cc @@ -1,34 +1,34 @@ // -*- C++ -*- // // ClassDocumentation.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the ClassDocumentation class. // #include "ClassDocumentation.h" #include "ThePEG/Repository/BaseRepository.h" #ifdef ThePEG_TEMPLATES_IN_CC_FILE // #include "ClassDocumentation.tcc" #endif using namespace ThePEG; ClassDocumentationBase:: ClassDocumentationBase(string newDocumentation, string newModelDescription, string newModelReferences, const type_info & newTypeInfo) : theDocumentation(newDocumentation), theModelDescription(newModelDescription), theModelReferences(newModelReferences) { BaseRepository::Register(*this, newTypeInfo); } diff --git a/Interface/ClassDocumentation.h b/Interface/ClassDocumentation.h --- a/Interface/ClassDocumentation.h +++ b/Interface/ClassDocumentation.h @@ -1,200 +1,200 @@ // -*- C++ -*- // // ClassDocumentation.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_ClassDocumentation_H #define ThePEG_ClassDocumentation_H // This is the declaration of the ClassDocumentation class. #include "ThePEG/Config/ThePEG.h" #include "ClassDocumentation.fh" namespace ThePEG { /** * The ClassDocumentationBase class is used to communicate * documetation about an Interfaced class to the Repository. * Similarly to classes inheriting from InterfaceBase, only one static * object of the templated ClassDocumentation, which inherits from * ClassDocumentationBase, should be created for each Interfaced * class. This object will then automatically register itself with the * static Repository. * * The ClassDocumentationBase contains three strings with information * which are all specified in the constructor: * * The documentation contains a brief description of the * corresponding class which can be displayed by the Repository (or * user interfaces derived from it). * * The model description contains a very brief description of * the model of the process implemented in the step handler, given in * the form of a LaTeX \\item. This is written to a file after a run * by an EventGenerator. * * The model references contains possible LaTeX \\bibitems * corresponding to \\cite commands in the model * description. This is also written to a file after a run by an * EventGenerator. * * @see Interfaced * @see Repository * */ class ClassDocumentationBase { protected: /** * The standard constructor can only be used from subclasses. * @param newDocumentation the documentation for the * corresponding class. * @param newModelDescription the model description for the * corresponding class. * @param newModelReferences the model references of the * corresponding class.. * @param newTypeInfo the type_info object of the corresponding * class. */ ClassDocumentationBase(string newDocumentation, string newModelDescription, string newModelReferences, const type_info & newTypeInfo); public: /** * The destructor. */ virtual ~ClassDocumentationBase() {} public: /** * Return the brief documentation of the corresponding class. */ string documentation() const { return theDocumentation; } /** * Return the model description of the corresponding class. */ string modelDescription() const { return theModelDescription; } /** * Return the model references of the corresponding class. */ string modelReferences() const { return theModelReferences; } private: /** * The brief documentation of the corresponding class. */ string theDocumentation; /** * The model description of the corresponding class. */ string theModelDescription; /** * The model references of the corresponding class. */ string theModelReferences; private: /** * Private and unimplemented default constructor. */ ClassDocumentationBase(); /** * Private and unimplemented copy constructor. */ ClassDocumentationBase(const ClassDocumentationBase &); /** * Private and unimplemented assignment operator. */ ClassDocumentationBase & operator=(const ClassDocumentationBase &) = delete; }; /** * The ClassDocumentation class is used to communicate * documetation about an Interfaced class to the Repository. * Similarly to classes inheriting from InterfaceBase, only one static * object of the templated ClassDocumentation, which inherits from * ClassDocumentationBase, should be created for each Interfaced * class. This object will then automatically register itself with * the static Repository. * * The ClassDocumentation should in the constructor specify three * strings with information: * * The documentation contains a brief description of the * corresponding class which can be displayed by the Repository (or * user interfaces derived from it). * * The model description contains a very brief description of * the model of the process implemented in the step handler, given in * the form of a LaTeX \\item. This is written to a file after a run * by an EventGenerator. * * The model references contains possible LaTeX \\bibitems * corresponding to \\cite commands in the model * description. This is also written to a file after a run by an * EventGenerator. * * @see Interfaced * @see Repository * */ template class ClassDocumentation: public ClassDocumentationBase { public: /** * The standard constructor. All other constructors are private. * @param newDocumentation the documentation for the * corresponding class. * @param newModelDescription the model description for the * corresponding class. * @param newModelReferences the model references of the * corresponding class.. */ ClassDocumentation(string newDocumentation, string newModelDescription = "", string newModelReferences = "") : ClassDocumentationBase(newDocumentation, newModelDescription, newModelReferences, typeid(T)) {} private: /** * Private and unimplemented default constructor. */ ClassDocumentation(); /** * Private and unimplemented copy constructor. */ ClassDocumentation(const ClassDocumentation &); /** * Private and unimplemented assignment operator. */ ClassDocumentation & operator=(const ClassDocumentation &) = delete; }; } #endif /* ThePEG_ClassDocumentation_H */ diff --git a/Interface/Command.cc b/Interface/Command.cc --- a/Interface/Command.cc +++ b/Interface/Command.cc @@ -1,44 +1,44 @@ // -*- C++ -*- // // Command.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the CommandBase class. // #include "InterfacedBase.h" #include "Command.h" using namespace ThePEG; string CommandBase::exec(InterfacedBase & i, string action, string arguments) const { if ( action != "do" ) return ""; return cmd(i, arguments); } string CommandBase::type() const { return "Cm"; } string CommandBase::doxygenType() const { return "Command"; } CmdExUnknown::CmdExUnknown(const InterfaceBase & i, const InterfacedBase & o, string c) { theMessage << "Could execute the command \"" << i.name() << "\" for the object \"" << o.name() << "\" with argument " << c << "because the command function threw an unknown exception."; severity(warning); } #ifdef ThePEG_TEMPLATES_IN_CC_FILE #include "Command.tcc" #endif diff --git a/Interface/Command.h b/Interface/Command.h --- a/Interface/Command.h +++ b/Interface/Command.h @@ -1,200 +1,200 @@ // -*- C++ -*- // // Command.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_Command_H #define ThePEG_Command_H // This is the declaration of the Command and CommandBase classes. #include "ThePEG/Config/ThePEG.h" #include "InterfaceBase.h" #include "Command.fh" #include "Command.xh" namespace ThePEG { /** * The CommandBase and its templated Command sub-class defines an * interface to a class derived from the InterfacedBase, through which * arbitratry command strings can be sent and * received. Command is templated and is derived from the * InterfaceBase class via CommandBase. * * For each command interface to be defined for a class * T, exactly one static object of the Command must be * created and initialized as follows: * * Command comint(name, description, &T::memberfn, * depsafe); * * Where name is an identifier std::string which * should only contain letters [a-zA-z0-9_], description is * an arbitrary std::string, memberfn should be * a non-static member function of T and defined as * std::string T::memberfn(std::string). Finally if * depsafe is true it can be assumed that a call to the * memberfn for an object does not influence other objects * which may depend on the first. * * The Command class, as all other * InterfaceBase classes are mainly used in the * BaseRepository class. * * * @see InterfacedBase * @see InterfaceBase * @see BaseRepository * */ class CommandBase: public InterfaceBase { public: /** * Standard constructor. * * @param newName the name of the interface, may only contain * letters [a-zA-z0-9_]. * * @param newDescription a brief description of the interface. * * @param newClassName the name of the corresponding class. * * @param newTypeInfo the type_info object of the corresponding * class. * * @param depSafe set to true if calls to this interface for one * object does not influence other objects. */ CommandBase(string newName, string newDescription, string newClassName, const type_info & newTypeInfo, bool depSafe) : InterfaceBase(newName, newDescription, newClassName, newTypeInfo, depSafe, false) { hasDefault = false; } /** * The general interface method overriding the one in * InterfaceBase. For this class, the \a action and \a argument * arguments are concatenated (with a space character inserted) and * sent to the cmd() function. */ virtual string exec(InterfacedBase &ib, string action, string arguments) const ; /** * Return a string describing the type of interface to be included * in the Doxygen documentation. */ virtual string doxygenType() const; /** * Return a code for the type of this interface. */ virtual string type() const; /** * Execute the member function. For the object \a ib execute the * memberfunction (defined in the derived class) with \a c as * argument and return the return value. */ virtual string cmd(InterfacedBase & ib, string c) const = 0; }; /** * The CommandBase and its templated Command sub-class defines an * interface to a class derived from the InterfacedBase, through which * arbitratry command strings can be sent and * received. Command is templated and is derived from the * InterfaceBase class via CommandBase. * * For each command interface to be defined for a class * T, exactly one static object of the Command must be * created and initialized as follows: * * Command comint(name, description, &T::memberfn, * depsafe); * * Where name is an identifier std::string which * should only contain letters [a-zA-z0-9_], description is * an arbitrary std::string, memberfn should be * a non-static member function of T and defined as * std::string T::memberfn(std::string). Finally if * depsafe is true it can be assumed that a call to the * memberfn for an object does not influence other objects * which may depend on the first. * * The Command class, as all other * InterfaceBase classes are mainly used in the * BaseRepository class. * * * @see InterfacedBase * @see InterfaceBase * @see BaseRepository * */ template class Command: public CommandBase { public: /** * The declaration of member functions which can be used by this * Command interface. */ typedef string (T::*ExeFn)(string); public: /** * Standard constructor. * * @param newName the name of the interface, may only contain * letters [a-zA-z0-9_]. * * @param newDescription a brief description of the interface. * * @param newExeFn pointer to the function to be called in the * corresponding class. * * @param depSafe set to true if calls to this interface for one * object does not influence other objects. */ Command(string newName, string newDescription, ExeFn newExeFn, bool depSafe = false) : CommandBase(newName, newDescription, ClassTraits::className(), typeid(T), depSafe), theExeFn(newExeFn) {} /** * Execute the member function. For the object \a ib execute the * memberfunction with \a c as argument and return the return value. */ virtual string cmd(InterfacedBase & ib, string) const; private: /** * The pointer to the member function. */ ExeFn theExeFn; }; } #ifndef ThePEG_TEMPLATES_IN_CC_FILE #include "Command.tcc" #endif #endif /* ThePEG_Command_H */ diff --git a/Interface/Command.tcc b/Interface/Command.tcc --- a/Interface/Command.tcc +++ b/Interface/Command.tcc @@ -1,32 +1,32 @@ // -*- C++ -*- // // Command.tcc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined templated member // functions of the Command class. // namespace ThePEG { template string Command::cmd(InterfacedBase & i, string arg) const { T * t = dynamic_cast(&i); if ( !t ) throw InterExClass(*this, i); if ( theExeFn ) { try { string r = (t->*theExeFn)(arg); if ( r != "" ) i.touch(); return r; } catch (InterfaceException & e) { throw e; } catch ( ... ) { throw CmdExUnknown(*this, i, arg); } } else throw InterExSetup(*this, i); } } diff --git a/Interface/Command.xh b/Interface/Command.xh --- a/Interface/Command.xh +++ b/Interface/Command.xh @@ -1,33 +1,33 @@ // -*- C++ -*- // // Command.xh is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_Command_XH #define ThePEG_Command_XH // // This is the declarations of the exception classes used by the // Command class. // #include "InterfaceBase.xh" namespace ThePEG { /** @cond EXCEPTIONCLASSES */ /** Exception class used by the Command class if something unexpected * happens. */ struct CmdExUnknown: public InterfaceException { /** Standard constructor. */ CmdExUnknown(const InterfaceBase & i, const InterfacedBase & o, string); }; /** @endcond */ } #endif /* ThePEG_Command_XH */ diff --git a/Interface/Deleted.cc b/Interface/Deleted.cc --- a/Interface/Deleted.cc +++ b/Interface/Deleted.cc @@ -1,35 +1,35 @@ // -*- C++ -*- // // Deleted.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the DeletedBase class. // #include "InterfacedBase.h" #include "Deleted.h" #include "ThePEG/Utilities/Throw.h" using namespace ThePEG; string DeletedBase::exec(InterfacedBase &, string, string) const { Throw() << "The interface '" << name() << "' has been removed. " << description() << Exception::runerror; return ""; } string DeletedBase::type() const { return "Dd"; } string DeletedBase::doxygenType() const { return "Deleted"; } diff --git a/Interface/Deleted.h b/Interface/Deleted.h --- a/Interface/Deleted.h +++ b/Interface/Deleted.h @@ -1,140 +1,140 @@ // -*- C++ -*- // // Deleted.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_Deleted_H #define ThePEG_Deleted_H // This is the declaration of the Deleted and DeletedBase classes. #include "ThePEG/Config/ThePEG.h" #include "InterfaceBase.h" namespace ThePEG { /** * The DeletedBase and its templated Deleted sub-class defines an * interface to a class derived from the InterfacedBase. It should be * used when an interface is removed to provide a user-friendly * message indicating why it was removed and possibly which interface * should be used instead. * * For each deleted interface to be defined for a class * T, exactly one static object of the Deleted must be * created and initialized as follows: * * Deleted delint(name, description); * * Where name is an identifier std::string which * should only contain letters [a-zA-z0-9_] and description is * an arbitrary std::string * * The Deleted class, as all other InterfaceBase classes * are mainly used in the BaseRepository class. * * * @see InterfacedBase * @see InterfaceBase * @see BaseRepository * */ class DeletedBase: public InterfaceBase { public: /** * Standard constructor. * * @param newName the name of the interface, may only contain * letters [a-zA-z0-9_]. * * @param newDescription a brief description of the interface. * * @param newClassName the name of the corresponding class. * * @param newTypeInfo the type_info object of the corresponding * class. * */ DeletedBase(string newName, string newDescription, string newClassName, const type_info & newTypeInfo) : InterfaceBase(newName, newDescription, newClassName, newTypeInfo, true, false) { rank(-1.0e10); } /** * The general interface method overriding the one in * InterfaceBase. For this class, an exception will be thrown with a * message given by the description string provided in the * constructor. */ virtual string exec(InterfacedBase &ib, string action, string arguments) const ; /** * Return a string describing the type of interface to be included * in the Doxygen documentation. */ virtual string doxygenType() const; /** * Return a code for the type of this interface. */ virtual string type() const; }; /** * The DeletedBase and its templated Deleted sub-class defines an * interface to a class derived from the InterfacedBase. It should be * used when an interface is removed to provide a user-friendly * message indicating why it was removed and possibly which interface * should be used instead. * * For each deleted interface to be defined for a class * T, exactly one static object of the Deleted must be * created and initialized as follows: * * Deleted delint(name, description); * * Where name is an identifier std::string which * should only contain letters [a-zA-z0-9_] and description is * an arbitrary std::string * * The Deleted class, as all other InterfaceBase classes * are mainly used in the BaseRepository class. * * * @see InterfacedBase * @see InterfaceBase * @see BaseRepository * */ template class Deleted: public DeletedBase { public: /** * Standard constructor. * * @param newName the name of the interface, may only contain * letters [a-zA-z0-9_]. * * @param newDescription a brief description of the interface. * */ Deleted(string newName, string newDescription) : DeletedBase(newName, newDescription, ClassTraits::className(), typeid(T)) {} }; } #endif /* ThePEG_Deleted_H */ diff --git a/Interface/Interface.h b/Interface/Interface.h --- a/Interface/Interface.h +++ b/Interface/Interface.h @@ -1,85 +1,85 @@ // -*- C++ -*- // // Interface.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_Interface_H #define THEPEG_Interface_H // // This is the declaration of the Interface namespace. // namespace ThePEG { /** * The Interface namespace declares a number of enums to set options * for subclasses of InteracedBase. */ namespace Interface { /** * Determine whether an interface is dependency safe or * not. Dependency safe means that other objects do not depend on the * variable being interfaced. */ enum DepSafe { unsafe = false, /**< The interface is not dependency safe. */ safe = true /**< The interface is dependency safe. */ }; /** * Determine whether an interface is read-only or not. */ enum ReadOnly { readwrite = false, /**< The interface is mutable. */ readonly = true /**< The interface is read-only. */ }; /** * Determine whether a Parameter or ParVector is limited, either * upper, lower or both. */ enum Limits { nolimits = 0, /**< The parameter is not limited. */ limited = 1, /**< The parameter is limited (both up- and downwards. */ upperlim = 2, /**< The parameter has only an upper limit. */ lowerlim = 3 /**< The parameter has only an lower limit. */ }; /** * Determine whether a the objects referred to by a Reference or a * RefVector should be automaticlly rebound (i.e. do not need to be * explicitly rebound in the rebind() function). */ enum Rebind { norebind = true, /**< The reference is not automatically rebound. */ rebind = false /**< The reference is automatically rebound. */ }; /** * Determine whether a Reference or RefVector object may be null. */ enum Nullable { nonull = false, /**< The reference may not be null. */ nullok = true /**< The reference may be null. */ }; /** * Determine whether a null reference should be given a default value * if suitable object is registered as default in the Strategy object * of a run. */ enum NullDefault { nodefnull = false, /**< The reference will not be set to default if null. */ defnull = true /**< The reference will be set to default if null. */ }; } } #endif /* THEPEG_Interface_H */ diff --git a/Interface/InterfaceBase.cc b/Interface/InterfaceBase.cc --- a/Interface/InterfaceBase.cc +++ b/Interface/InterfaceBase.cc @@ -1,117 +1,117 @@ // -*- C++ -*- // // InterfaceBase.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the InterfaceBase class. // #include "InterfaceBase.h" #include "InterfacedBase.h" #include "ThePEG/Repository/BaseRepository.h" namespace ThePEG { InterfaceBase::InterfaceBase(string newName, string newDescription, string newClassName, const type_info & newTypeInfo, bool depSafe, bool readonly) : Named(newName), theDescription(newDescription), theClassName(newClassName), theRank(-1.0), hasDefault(true), isDependencySafe(depSafe), isReadOnly(readonly) { BaseRepository::Register(*this, newTypeInfo); } string InterfaceBase::tag(int pos) const { if ( pos == -1 ) return name(); ostringstream os; os << name() << "[" << pos << "]"; return os.str(); } bool InterfaceBase::notDefault(InterfacedBase & ib) const { return exec(ib, "notdef", "") != "" ; } map & InterfaceBase::objectDefaults(InterfacedBase & ib) const { return ib.objectDefaults; } string InterfaceBase::fullDescription(const InterfacedBase &) const { return type() + '\n' + name() + '\n' + description() + ( readOnly()? "\n-*-readonly-*-\n": "\n-*-mutable-*-\n" ); } void InterfaceBase::doxygenDescription(ostream & os) const { os << "\n
Name:
" << name() << "
\n" << "Type: " << doxygenType(); if ( readOnly() ) os << " (read-only)"; os << "
\n" << "\\par Description:\n" << description() << "
\n"; } bool InterfaceBase::NoReadOnly = false; InterExClass::InterExClass(const InterfaceBase & i, const InterfacedBase & o) { theMessage << "Could not access the interface \"" << i.name() << "\" of the object \"" << o.name() << "\" because the object " << "is not of the required class (" << i.className() << ")."; severity(setuperror); } InterExSetup::InterExSetup(const InterfaceBase & i, const InterfacedBase & o) { theMessage << "Could not access the interface \"" << i.name() << "\" for the object \"" << o.name() << "\" since no get/set member function or variable was found."; severity(setuperror); } InterExUnknown::InterExUnknown(const InterfaceBase & i, const InterfacedBase & o) { theMessage << "Could not perform action on the interface \"" << i.name() << "\" for the object \"" << o.name() << "\" because the requested action was not recognized"; severity(setuperror); } InterExReadOnly::InterExReadOnly(const InterfaceBase & i, const InterfacedBase & o) { theMessage << "Could not perform action on the interface \"" << i.name() << "\" for the object \"" << o.name() << "\" because this interface is read-only."; severity(setuperror); } InterExNoNull::InterExNoNull(const InterfaceBase & i, const InterfacedBase & o) { theMessage << "Could not set reference \"" << i.name() << "\" for the object \"" << o.name() << "\" to because null pointers are explicitly " << "disallowed."; severity(setuperror); } RefInterfaceBase:: RefInterfaceBase(string newName, string newDescription, string newClassName, const type_info & newTypeInfo, string newRefClassName, const type_info & newRefTypeInfo, bool depSafe, bool readonly, bool norebind, bool nullable, bool defnull) : InterfaceBase(newName, newDescription, newClassName, newTypeInfo, depSafe, readonly), theRefClassName(newRefClassName), theRefTypeInfo(newRefTypeInfo), dontRebind(norebind), isNullable(nullable), theDefaultIfNull(defnull) { hasDefault = false; } } diff --git a/Interface/InterfaceBase.h b/Interface/InterfaceBase.h --- a/Interface/InterfaceBase.h +++ b/Interface/InterfaceBase.h @@ -1,436 +1,436 @@ // -*- C++ -*- // // InterfaceBase.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_InterfaceBase_H #define ThePEG_InterfaceBase_H // This is the declaration of the InterfaceBase and RefInterfaceBase classes. #include "ThePEG/Config/ThePEG.h" #include "InterfaceBase.fh" #include "InterfaceBase.xh" #include "ThePEG/Utilities/Named.h" #include "ThePEG/Utilities/ClassTraits.h" #include "Interface.h" namespace ThePEG { /** * The InterfaceBase class defines a generic interface to any class * derived from the InterfacedBase class. Using the pure virtual * exec() function, it is possible to manipulate any InterfacedBase * object. InterfaceBase is an abstract base class for derived classes * such as Command, Parameter and Reference. * * InterfaceBase objects are managed by the BaseRepository. * * InterfaceBase is derived from the Named to manage the name of the * interface. * * From the Repository it is possible to generate a file with doxygen * comments which can be included in the documentation describing the * InterfaceBase objects defined for a class. For each class, * ClassName, there will be produced a file called * ClassNameInterfaces.html which can be referred to with * a standard html href anchor. Also a specific * interface, InterfaceName can be referred to with * ClassNameInterfaces.html#InterfaceName. The file can * also be referred to with the doxygen \\ref * command. Inside the description of an interface, other interfaces * in the same class can be tagged with * \InterfaceName\ or, if the interface * belongs to another class, * \ClassName::InterfaceName\. By running the * script in ThePEG/Doc/fixinterfaces.pl these tags will * be converted to proper href anchors. * * @see InterfacedBase * @see Command * @see Parameter * @see Reference * @see BaseRepository * @see Named * */ class InterfaceBase: public Named { public: /** * Standard constructor. * * @param newName the name of the interface, may only contain * letters [a-zA-z0-9_]. * * @param newDescription a brief description of the interface. * * @param newClassName the name of the corresponding class. * * @param newTypeInfo the type_info object of the corresponding * class. * * @param depSafe set to true if calls to this interface for one * object does not influence other objects. * * @param readonly if this is set true the interface will not be * able to manipulate objects of the corresponding class, but will * still be able to access information. */ InterfaceBase(string newName, string newDescription, string newClassName, const type_info & newTypeInfo, bool depSafe, bool readonly); /** * The destructor. */ virtual ~InterfaceBase() {} /** * Create a tag for this interface using its name and optional * poisitional argument. */ string tag(int pos = -1) const; /** * Manipulate an object of the corresponding class. Execute the \a * action command with the given \a arguments for the given object * \a ib. */ virtual string exec(InterfacedBase & ib, string action, string arguments) const = 0; /** * Return a code for the type of this interface. */ virtual string type() const = 0; /** * Returns true if the setting for this interface has been changed * from its default value. */ virtual bool notDefault(InterfacedBase &) const; /** * Returns the map of objectDefaults of the given object. */ map & objectDefaults(InterfacedBase &) const; /** * Rebind all references in ib according to the translation * map. Only used by derived classed interfacing references. */ virtual void rebind(InterfacedBase &, const TranslationMap &, const IVector & = IVector()) const {} /** * For derived classes interfacing references between Interfaced * objects, return the references for this interface. */ virtual IVector getReferences(const InterfacedBase &) const { return IVector(); } /** * Return the description of this interface. */ string description() const { return theDescription; } /** * Return a complete description of this interface. */ virtual string fullDescription(const InterfacedBase & ib) const; /** * Print a description to be included in the Doxygen documentation * to the given \a stream. */ virtual void doxygenDescription(ostream & stream) const; /** * Return a string describing the type of interface to be included * in the Doxygen documentation. */ virtual string doxygenType() const = 0; /** * Return the class name for the class this interface is defined * for. */ string className() const { return theClassName; } /** * Get the flag saying whether changing an object with this * interface may change the state of a dependent object . */ bool dependencySafe() const { return isDependencySafe; } /** * Set the flag saying whether changing an object with this * interface may change the state of a dependent object . */ void setDependencySafe() { isDependencySafe = true; } /** * Set the flag saying whether changing an object with this * interface may change the state of a dependent object . */ void setDependencySensitive() { isDependencySafe = false; } /** * Get the flag saying whether this interface is allowed to change * an object. */ bool readOnly() const { return isReadOnly && (!NoReadOnly); } /** * Set the flag saying that this interface is allowed to * change an object. */ void setReadOnly() { isReadOnly = true; } /** * Unset the flag saying that this interface is allowed to change an * object. */ void setReadWrite() { isReadOnly = false; } /** * Return true if this interface is anonyous, ie. invisible for the * user interface. */ bool anonymous() const { return description().empty(); } /** * Get the rank for this interface. Used for sorting by user * interface. */ double rank() const { return theRank; } /** * Set the rank for this interface. Used for sorting by user * interface. */ void rank(double r) { theRank = r; } /** * Indicate that this interface has a default value. */ void setHasDefault(bool b) { hasDefault = b; } /** * If set to true, all read-only interfaces can be changed. */ static bool NoReadOnly; private: /** * The description of this interface. */ string theDescription; /** * The class name and for the class this interface is defined for. */ string theClassName; /** * A rank assigned to this interface. Used for sorting by user * interface. */ double theRank; protected: /** * A flag indicating whether this interface has a default setting. */ bool hasDefault; /** * The flag saying whether changing an object with this interface * may change the state of a dependent object . */ mutable bool isDependencySafe; /** * The flag saying whether this interface is allowed to change an * object. */ mutable bool isReadOnly; }; /** * RefInterfaceBase is an abstract base class inheriting from * InterfaceBase used for subclasses dealing with interfaces to do * with references in one Interfaced object to another. */ class RefInterfaceBase: public InterfaceBase { public: /** * Standard constructor. * * @param newName the name of the interface, may only contain * letters [a-zA-z0-9_]. * * @param newDescription a brief description of the interface. * * @param newClassName the name of the corresponding class. * * @param newTypeInfo the type_info object of the corresponding * class. * * @param newRefClassName the name of the class referred to by the * corresponding class.. * * @param newRefTypeInfo the type_info object of the class referred * to by the corresponding class. * * @param depSafe set to true if calls to this interface for one * object does not influence other objects. * * @param readonly if this is set true the interface will not be * able to manipulate objects of the corresponding class, but will * still be able to access information. * * @param norebind if set to true, this interface is not responsible * for the rebinding of corresponding objects. * * @param nullable if set to true this corresponding references may * be null. * * @param defnull if set to true and a corresponding reference is * null it may be given a a default value in the initialization of * an EventGenerator. */ RefInterfaceBase(string newName, string newDescription, string newClassName, const type_info & newTypeInfo, string newRefClassName, const type_info & newRefTypeInfo, bool depSafe, bool readonly, bool norebind, bool nullable, bool defnull); /** * Return the class name of the class referred to by * this interface. */ string refClassName() const { return theRefClassName; } /** * Return the type_info object of the class referred to by this * interface. */ const type_info & refTypeInfo() const { return theRefTypeInfo; } /** * Get the flag saying whether the interface is responsible for * rebinding of the corresponding refenerces. */ bool noRebind() const { return dontRebind; } /** * Set the flag saying that the interface is not responsible for * rebinding refenerces. */ void setNoRebind() { dontRebind = true; } /** * Set the flag saying that the interface is responsible for * rebinding refenerces. */ void setRebind() { dontRebind = false; } /** * Get the flag saying whether the interface is allowed to set the * reference to null. */ bool noNull() const { return !isNullable; } /** * Set the flag saying that the interface it is allowed to set the * reference to null. */ void setNullable() { isNullable = true; } /** * Set the flag saying that the interface it is not allowed to set * the reference to null. */ void setNotNullable() { isNullable = false; } /** * Get the flag saying wether a null pointer should be replaced by a * default of suitable class when rebind is called. */ bool defaultIfNull() const { return theDefaultIfNull; } /** * Set the flag saying that a null pointer should be replaced by a * default of suitable class when rebind is called. */ void setDefaultIfNull() { theDefaultIfNull = true; } /** * Set the flag saying that a null pointer should not be replaced by * a default of suitable class when rebind is called. */ void setNoDefaultIfNull() { theDefaultIfNull = false; } private: /** * The class name of the class referred to by this * interface. */ string theRefClassName; /** * The type_info object of the class referred to by this interface. */ const type_info & theRefTypeInfo; /** * The flag saying whether the interface is responsible for * rebinding refenerces. */ bool dontRebind; /** * The flag saying whether the interface is allowed to set a * reference to null. */ bool isNullable; /** * The flag saying wether a null pointer should be replaced * by a default of suitable class when rebind is called. */ bool theDefaultIfNull; }; /** Dummy function to ensure that strings can be used as arguments * also where numbers are assumed. */ inline double operator/(string,string) { return 0.0; } /** Dummy function to ensure that strings can be used as arguments * also where numbers are assumed. */ inline string operator*(double,string) { return ""; } } #endif /* ThePEG_InterfaceBaseH */ diff --git a/Interface/InterfaceBase.xh b/Interface/InterfaceBase.xh --- a/Interface/InterfaceBase.xh +++ b/Interface/InterfaceBase.xh @@ -1,67 +1,67 @@ // -*- C++ -*- // // InterfaceBase.xh is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_InterfaceBase_XH #define ThePEG_InterfaceBase_XH // // This is the declarations of the exception classes used by the // InterfaceBase class. // #include "InterfaceBase.fh" #include "ThePEG/Utilities/Exception.h" namespace ThePEG { /** @cond EXCEPTIONCLASSES */ /** Exception class used as base class for errors detected by * interface classes. */ struct InterfaceException: public Exception { /** Standard constructor. */ InterfaceException() {}; }; /** Exception class used when an interface is called for an object of * the wrong class. */ struct InterExClass: public InterfaceException { /** Standard constructor. */ InterExClass(const InterfaceBase & i, const InterfacedBase & o); }; /** Exception class used in case an interface is not properly * setup. */ struct InterExSetup: public InterfaceException { /** Standard constructor. */ InterExSetup(const InterfaceBase & i, const InterfacedBase & o); }; /** Exception class used in case of an unkown error whenn accessing an * object via an interface. */ struct InterExUnknown: public InterfaceException { /** Standard constructor. */ InterExUnknown(const InterfaceBase & i, const InterfacedBase & o); }; /** Exception class used in case an a read-only interface is used to * try to change an object. */ struct InterExReadOnly: public InterfaceException { /** Standard constructor. */ InterExReadOnly(const InterfaceBase & i, const InterfacedBase & o); }; /** Exception class used when a reference non-nullable interface tries to set a reference to null. */ struct InterExNoNull: public InterfaceException { /** Standard constructor. */ InterExNoNull(const InterfaceBase & i, const InterfacedBase & o); }; /** @endcond */ } #endif /* ThePEG_InterfaceBase_XH */ diff --git a/Interface/Interfaced.cc b/Interface/Interfaced.cc --- a/Interface/Interfaced.cc +++ b/Interface/Interfaced.cc @@ -1,93 +1,93 @@ // -*- C++ -*- // // Interfaced.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the Interfaced class. // #include "Interfaced.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Repository/Repository.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Interface/Command.h" using namespace ThePEG; Interfaced::~Interfaced() {} void Interfaced::registerRepository(IBPtr i) { Repository::Register(i); } void Interfaced::registerRepository(IBPtr i, string newName) { Repository::Register(i, newName); } void Interfaced::reporeg(IBPtr object, string name) const { Repository::CreateDirectory(fullName()); string full = fullName() + "/" + name; IBPtr old = Repository::GetPointer(full); if ( old ) { if ( Repository::GetObjectsReferringTo(old).empty() ) Repository::remove(old); else Repository::rename(old, fullName() + "/old-" + name); } Repository::Register(object, full); } bool Interfaced::defaultInit() { return true; } void Interfaced::setUsed() const { theUseFlag = true; if ( generator() ) generator()->use(*this); } PPtr Interfaced::getParticle(PID newId) const { PPtr p(generator()? generator()->getParticle(newId): PPtr()); return p; } PDPtr Interfaced::getParticleData(PID newId) const { PDPtr p(generator()? generator()->getParticleData(newId): Repository::defaultParticle(newId)); return p; } void Interfaced::persistentOutput(PersistentOStream & os) const { os << theGenerator << theUseFlag; } void Interfaced::persistentInput(PersistentIStream & is , int) { is >> theGenerator >> theUseFlag; } AbstractClassDescription Interfaced::initInterfaced; string Interfaced::doDefaultInit(string) { if ( !defaultInit() ) return "Default initialization failed."; return ""; } void Interfaced::Init() { static Command interfaceDefaultInit ("DefaultInit", "Perform a default initialization of this object. This typically " "involves creating sub-objects which are needed. In this case the " "objects can be added to the repository in a sub-directory with the " "same name as this object.", &Interfaced::doDefaultInit, true); } diff --git a/Interface/Interfaced.h b/Interface/Interfaced.h --- a/Interface/Interfaced.h +++ b/Interface/Interfaced.h @@ -1,252 +1,252 @@ // -*- C++ -*- // // Interfaced.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_Interfaced_H #define ThePEG_Interfaced_H // This is the declaration of the Interfaced class. #include "ThePEG/Config/ThePEG.h" #include "InterfacedBase.h" #include "ThePEG/PDT/PID.h" namespace ThePEG { /** * The Interfaced class is derived from the InterfacedBase class * adding a couple of things particular to ThePEG, in an attempt to * keep the InterfacedBase class as generic as possible. * * The main addition is that the Interfaced class has a pointer to an * EventGenerator object. During the run-phase this points to the * EventGenerator controlling the run in which the Interfaced object * is used. Through this EventGenerator there is quick access to * eg. the set of ParticleData objects used, and the default * RandomGenerator for the run. Note that no EventGenerator object is * available to the Interfaced object during the setup * phase. * * @see InterfacedBase * @see EventGenerator * @see ParticleData * @see RandomGenerator */ class Interfaced: public InterfacedBase { /** Repository is a friend. */ friend class Repository; /** EventGenerator is a friend. */ friend class EventGenerator; public: /** * Empty virtual destructor */ virtual ~Interfaced(); /** * Functions which are to be used during the actual event * generation, after the setup is complete. */ public: /** * A sub class can implement this function to implement some default * initialization for this object during the setup phase. A typical * example is if this object need some references to other objects * and if these can be easily created. In this case the objects can * be added to the repository in a sub-directory with the same name * as this object. * @return false if the initialization failed. */ virtual bool defaultInit(); /** @name Functions used during the actual event generation, after the setup is complete. */ //@{ /** * Create a new Particle instance given a id number. */ PPtr getParticle(PID) const; /** * Return a pointer to the ParticleData object corresponding to the * given id number. */ PDPtr getParticleData(PID) const; /** * Returns true if this object has actally been used. */ bool used() const { return theUseFlag; } /** * Should be called to indicate that this object has actually been * used. */ void useMe() const { if ( !used() ) setUsed(); } /** * Return a pointer to the EventGenerator controlling the run. * During the setup phase this returns a null pointer. */ tEGPtr generator() const { return theGenerator; } //@} 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. */ static void Init(); protected: /** * Register an Interfaced object with the Repository. */ static void registerRepository(IBPtr); /** * Register an Interfaced object with the Repository, giving it a * name. */ static void registerRepository(IBPtr, string newName); /** * Register the given \a object in the Repository with the given \a * name in a subdirectory with the same name as this object. If an * object with that name already exists it will be removed unless * there are other objects referring to it, in which case it will be * renamed. */ void reporeg(IBPtr object, string name) const; /** * If the pointer, \a ptr, to an object is not set, create an object * of class \a classname and register it with the Repository with * the given \a objectname in a sib-directory with the same name as * this object. */ template bool setDefaultReference(PtrT & ptr, string classname, string objectname) { if ( ptr ) return true; const ClassDescriptionBase * db = DescriptionList::find(classname); if ( !db ) return false; ptr = dynamic_ptr_cast(db->create()); if ( !ptr ) return false; reporeg(ptr, objectname); if ( !ptr->defaultInit() ) return false; return true; } /** * Protected default constructor. */ Interfaced() : theUseFlag(false) {} /** * Protected constructor taking a name as argument. */ Interfaced(const string & newName) : InterfacedBase(newName), theUseFlag(false) {} /** * Protected copy-constructor. */ Interfaced(const Interfaced & i) : InterfacedBase(i), theGenerator(i.theGenerator), theUseFlag(false) {} protected: /** * Protected function to reset the generator pointer, required * for automatic decayer generation in Herwig++ BSM models */ void setGenerator(tEGPtr generator) { theGenerator=generator; } private: /** * Used internally by 'useMe' */ void setUsed() const; /** * A pointer to the EventGenerator controlling the run. */ tEGPtr theGenerator; /** * Flag to tell whether this object has been used or not. */ mutable bool theUseFlag; /** * Command interface function which calls defaultInit(). */ string doDefaultInit(string); private: /** * Standard Initialization object. */ static AbstractClassDescription initInterfaced; /** * Private and non-existent assignment operator. */ Interfaced & operator=(const Interfaced &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** * This template specialization informs ThePEG about the * base class of Interfaced. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the base class of Interfaced. */ typedef InterfacedBase NthBase; }; /** * This template specialization informs ThePEG about the name of the * Interfaced class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return the class name. */ static string className() { return "ThePEG::Interfaced"; } }; /** @endcond */ } #endif /* ThePEG_Interfaced_H */ diff --git a/Interface/InterfacedBase.cc b/Interface/InterfacedBase.cc --- a/Interface/InterfacedBase.cc +++ b/Interface/InterfacedBase.cc @@ -1,81 +1,81 @@ // -*- C++ -*- // // InterfacedBase.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the InterfacedBase class. // #include "InterfacedBase.h" #include "ThePEG/Repository/BaseRepository.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Utilities/EnumIO.h" #include "ThePEG/Utilities/StringUtils.h" #include "ThePEG/Utilities/DescriptionList.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Command.h" using namespace ThePEG; InterfacedBase::~InterfacedBase() {} void InterfacedBase::readSetup(istream &) {} bool InterfacedBase::preInitialize() const { return false; } void InterfacedBase::persistentOutput(PersistentOStream & os) const { os << fullName() << isLocked << isTouched << oenum(initState) << theComment << objectDefaults; } void InterfacedBase::persistentInput(PersistentIStream & is, int) { string n; is >> n >> isLocked >> isTouched >> ienum(initState) >> theComment >> objectDefaults; name(n); } string InterfacedBase::addComment(string c) { if ( theComment.length() ) theComment += "\n"; theComment += StringUtils::stripws(c); return ""; } AbstractClassDescription InterfacedBase::initInterfacedBase; void InterfacedBase::debugme() const { cerr << name() << " [" << DescriptionList::find(typeid(*this))->name() << "] "; PersistentBase::debugme(); } void InterfacedBase::Init() { static Parameter interfaceComment ("Comment", "A comment assigned to this object.", &InterfacedBase::theComment, "", true, false); interfaceComment.setHasDefault(false); static Command interfaceAddComment ("AddComment", "Add a comment to this object. Will be concatenated with the exixting " "comment.", &InterfacedBase::addComment, true); } void InterfacedBase::UpdateChecker::check(tIBPtr ip, bool & touch) { if ( !ip ) return; ip->update(); if ( ip->touched() ) touch = true; } diff --git a/Interface/InterfacedBase.h b/Interface/InterfacedBase.h --- a/Interface/InterfacedBase.h +++ b/Interface/InterfacedBase.h @@ -1,512 +1,512 @@ // -*- C++ -*- // // InterfacedBase.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_InterfacedBase_H #define ThePEG_InterfacedBase_H // This is the declaration of the InterfacedBase class. #include "ThePEG/Config/ThePEG.h" #include "ThePEG/Utilities/Named.h" #include "ThePEG/Utilities/ClassDescription.h" #include "ThePEG/Utilities/HoldFlag.h" #include "InterfacedBase.xh" namespace ThePEG { /** * InterfacedBase is the base class of all Interfaced objects to be * handled by the BaseRepository class. InterfacedBase * objects can be manipulated through objects of the InterfaceBase * class dealing with setting parameters, switches and pointers to * other InterfacedBase objects. * * The InterfacedBase has a number of virtual methods to be * implemented by sub classes for checking the state of the object, * initializing the object etc. * * The InterfacedBase is derived from the PersistentBase class to * allow for persistent I/O, and from the Named for handling the name * of the object. The full name of the object is of the form * /dir/subdir/name analogous to the file name in a Unix * file system. * * It is possible to lock an InterfacedBase object in which case the * BaseRepository will not do anything that will change the state of * this object. * * @see BaseRepository * @see InterfaceBase */ class InterfacedBase: public PersistentBase, public Named { /** The BaseRepository is a close friend. */ friend class BaseRepository; /** The InterfaceBase is a close friend. */ friend class InterfaceBase; /** The EventGenerator is a friend. */ friend class EventGenerator; public: /** * Enumeration reflecting the state of an InterfacedBase object. */ enum InitState { initializing = -1, /**< The object is currently being initialized. I.e. either of update(), init(), initrun() or finish() are being run. */ uninitialized = 0, /**< The object has not been initialized. */ initialized = 1, /**< The object has been initialized. */ runready = 2 /**< The object is initialized and the initrun() method has been called. */ }; public: /** * The virtual (empty) destructor; */ virtual ~InterfacedBase(); /** * Returns the full name of this object including its path, e.g. * /directory/subdirectory/name. */ string fullName() const { return Named::name(); } /** * Returns the name of this object, without the path. */ string name() const { return Named::name().substr(Named::name().rfind('/')+1); } /** * Returns the path to this object including the trailing * '/'. fullName() = path() + name(). */ string path() const { string::size_type slash = Named::name().rfind('/'); string ret; if ( slash != string::npos ) ret = Named::name().substr(0,slash); return ret; } /** * Returns a comment assigned to this object. */ string comment() const { return theComment; } /** * Read setup info from a standard istream \a is. May be called by * the Repository to initialize an object. This function first calls * the virtual readSetup() function to allow the sub classes the * part \a is to initialize themselves. What ever is left in \a is * after that will be assigned to the comment() of the object. */ void setup(istream & is) { readSetup(is); getline(is, theComment); } protected: /** @name Standard InterfacedBase virtual functions. */ //@{ /** * Read setup info from a standard istream \a is. May be called by * the Repository to initialize an object. This function is called * by the non virtual setup() function. A sub-class implementing it * should first call the base class version before parsing the \a * is. If the \a is is not empty after readSetup is called the * remaining string will be assigned to the comment() of the object. */ virtual void readSetup(istream & is); /** * Check sanity of the object during the setup phase. This function * is called everytime the object is changed through an interface * during the setup phase. Also if the setup is changed for an * object on which this is dependent. Note that the generator() is * not available when this method is called. * * This method may be called by the user interface during the setup phase * through the update() method after manipulating objects to check * the sanity of the object. When implemented by a sub class it is * important that the doupdate() method of the base class is called, * then if the sanity of this object depend on other objects, the * update() method of these should be called. Then if touched() is * true for this object or for the ones on which this depends, it is * an indication that some things have changed since last time * doupdate() was called, and the actual checking of the state of * this object is called for. To avoid circular loops, it is * important that the doupdate() method is called for the base * class, while the update() method is called for other objects. * @throws UpdateException if the setup is such that the object * would not work properly. */ virtual void doupdate() {} /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. Nothing should have changed since the * last update() call. * * This method is called after the setup * phase through the init() method to indicate that the setup of a * run is finished. This is typpically done in a setup program * before this object has been saved to a run file. It must * therefore be made sure that the state of this object after this * method has been executed will not be changed if it is written to * a file and read in again. When implemented by a sub class it is * important that the doinit() method of the base class is called * first and then, if the initialization of this object depends on * other objects, that the init() method of these objects are * called. Only then should the class-local initialization * proceed. To avoid circular loops, it is important that the * doinit() method is called for the base class, while the init() * method is called for other objects. * @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. * * This method is called just before * running starts through the initrun() method to indicate that the * actual running is to start. When implemented by a sub class it is * important that the doinitrun() method of the base class is called * first and then, if the initialization of this object depends on * other objects, that the initrun() method of these objects are * called. Only then should the class-local initialization * proceed. To avoid circular loops, it is important that the * doinitrun() method is called for the base class, while the * initrun() method is called for other objects. */ virtual void doinitrun() {} /** * Finalize this object. Called in the run phase just after a * run has ended. Used eg. to write out statistics. * * This method is called after the running * phase through the finish() and can eg. be used to write out * statistics. When implemented by a sub class it is important that * the dofinish() method of the base class is called while the * finish() methd is called for other objects. */ virtual void dofinish() {} /** * Return a vector of all pointers to Interfaced objects used in this * object. * @return a vector of pointers. */ virtual IVector getReferences() { return IVector(); } /** * 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. * @throws RebindException if no cloned object was found for a given * pointer. */ virtual void rebind(const TranslationMap &) {} //@} public: /** @name Inlined access function. */ //@{ /** * Calls the doupdate() function with recursion prevention. */ void update() { if ( initState ) return; HoldFlag hold(initState, initializing, initialized); doupdate(); } /** * Calls the doinit() function with recursion prevention. */ void init() { if ( initState ) return; HoldFlag hold(initState, initializing, initialized); doinit(); } /** * Return true if this object needs to be initialized before all * other objects (except those for which this function also returns * true). This default version always returns false, but subclasses * may override it to return true. */ virtual bool preInitialize() const; /** * Calls the doinitrun() function with recursion prevention. */ void initrun() { if ( initState == runready || initState == initializing ) return; HoldFlag hold(initState, initializing, runready); doinitrun(); } /** * Calls the dofinish() function with recursion prevention. */ void finish() { if ( initState == uninitialized || initState == initializing ) return; HoldFlag hold(initState, initializing, uninitialized); dofinish(); } /** * This function should be called every time something in this * object has changed in a way that a sanity check with update() is * needed */ void touch() { isTouched = true; } /** * Set the state of this object to uninitialized. */ void reset() { initState = uninitialized; } /** * Calls reset() and unTouch(). */ void clear() { reset(); untouch(); } /** * Return the state of initialization of this object. */ InitState state() const { return initState; } /** * Return true if the BaseRepository is not allowed to change the * state of this object. */ bool locked() const { return isLocked; } /** * Return true if the state of this object has been changed since * the last call to update(). */ bool touched() const { return isTouched; } //@} /** * Return a full clone of this object possibly doing things to the * clone to make it sane. */ virtual IBPtr fullclone() const { return clone(); } /** @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. */ static void Init(); protected: /** * Return a simple clone of this object. Should be implemented as * return new_ptr(*this); by a derived class. */ virtual IBPtr clone() const = 0; /** * Protected default constructor. */ InterfacedBase() : Named(""), isLocked(false), isTouched(true), initState(uninitialized) {} /** * Protected constructor with the name given as argument. */ InterfacedBase(string newName) : Named(newName), isLocked(false), isTouched(true), initState(uninitialized) {} /** * Protected copy-constructor. */ InterfacedBase(const InterfacedBase & i) : Base(i), Named(i), isLocked(false), isTouched(true), initState(uninitialized), theComment(i.theComment), objectDefaults(i.objectDefaults) {} private: /** * Set a new name (full name including path). */ void name(string newName) { Named::name(newName); } /** * Lock this object. */ void lock() { isLocked = true; } /** * Unlock this object. */ void unlock() { isLocked = false; } /** * Clear the isTouched flag. */ void untouch() { isTouched = false; } private: /** * Used by the interface to add comments. */ string addComment(string); private: /** * True if this object is not to be changed by the user interface. */ bool isLocked; /** * True if this object has been chaged since the last call to * update(). */ bool isTouched; /** * Indicate if this object has been initialized or not, or if it is * being initialized. */ InitState initState; /** * A comment assigned to this object. */ string theComment; /** * A map listing object-specific defaults set for the given interfaces. */ map objectDefaults; public: /** * Print out debugging information for this object on std::cerr. To * be called from within a debugger via the debug() function. */ virtual void debugme() const; private: /** * Standard Initialization object. */ static AbstractClassDescription initInterfacedBase; /** * Private and non-existent assignment operator. */ InterfacedBase & operator=(const InterfacedBase &) = delete; protected: /** * Functor class to be used to update a range of dependent object. */ struct UpdateChecker { /** Constructor. */ UpdateChecker(bool & touched) : isTouched(touched) {} /** Constructor. */ UpdateChecker(const UpdateChecker & uc) : isTouched(uc.isTouched) {} /** Call the check function for an object. */ static void check(tIBPtr, bool &); /** Function call operator. */ template void operator()(const ptr & i) { check(i, isTouched); } /** set to false if any check() call fails. */ bool & isTouched; }; /** * Functor class to be used to update a range of dependent object in a map. */ struct UpdateMapChecker { /** Constructor. */ UpdateMapChecker(bool & touched) : isTouched(touched) {} /** Constructor. */ UpdateMapChecker(const UpdateMapChecker & uc) : isTouched(uc.isTouched) {} /** Function call operator. */ template void operator()(const ref & i) { UpdateChecker::check(i.second, isTouched); } /** Reference to the bool variable to be set. */ bool & isTouched; }; }; /** @cond TRAITSPECIALIZATIONS */ /** * This template specialization informs ThePEG about the * base class of InterfacedBase. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the base class of InterfacedBase. */ typedef PersistentBase NthBase; }; /** * This template specialization informs ThePEG about the name of the * InterfacedBase class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return the class name. */ static string className() { return "ThePEG::InterfacedBase"; } }; /** @endcond */ } #endif /* ThePEG_InterfacedBase_H */ diff --git a/Interface/InterfacedBase.xh b/Interface/InterfacedBase.xh --- a/Interface/InterfacedBase.xh +++ b/Interface/InterfacedBase.xh @@ -1,51 +1,51 @@ // -*- C++ -*- // // InterfacedBase.xh is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_InterfacedBase_XH #define ThePEG_InterfacedBase_XH // // This is the declarations of the exception classes used by the // InterfacedBase class. // // #include "InterfacedBase.fh" #include "InterfaceBase.h" namespace ThePEG { /** @cond EXCEPTIONCLASSES */ /** Exception base class used if something goes wrong in the setup phase. */ struct SetupException: public InterfaceException { /** Constructor. */ SetupException() {}; }; /** Exception base class used if something goes wrong in the setup phase. */ struct UpdateException: public InterfaceException { /** Constructor. */ UpdateException() {}; }; /** Exception base class used if something goes wrong with rebinding pointers in the setup phase. */ struct RebindException: public InterfaceException { /** Constructor. */ RebindException() {}; }; /** Exception base class used if something goes wrong in the setup phase. */ struct InitException: public InterfaceException { /** Constructor. */ InitException() {}; }; /** @endcond */ } #endif /* ThePEG_InterfacedBase_XH */ diff --git a/Interface/ParVector.cc b/Interface/ParVector.cc --- a/Interface/ParVector.cc +++ b/Interface/ParVector.cc @@ -1,141 +1,141 @@ // -*- C++ -*- // // ParVector.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the ParVectorBase class. // #include "InterfacedBase.h" #include "ParVector.h" #include "ParVector.xh" #ifdef ThePEG_TEMPLATES_IN_CC_FILE #include "ParVector.tcc" #endif namespace ThePEG { string ParVectorBase:: exec(InterfacedBase & i, string action, string arguments) const { istringstream arg(arguments.c_str()); int place = 0; if ( !(arg >> place) ) place = -1; ostringstream ret; if ( action == "get" ) { StringVector v = get(i); if ( place >= 0 ) return v[place]; for ( StringVector::const_iterator it = v.begin(); it != v.end(); ++it ) { if ( it != v.begin() ) ret << ", "; ret << *it; } } else if ( action == "erase" ) { erase(i, place); } else if ( action == "clear" ) { clear(i); } else if ( action == "min" ) { return minimum(i, place); } else if ( action == "max" ) { return maximum(i, place); } else if ( action == "def" ) { return def(i, place); } else if ( action == "setdef" ) { if ( objectDefaults(i).find(tag(place)) == objectDefaults(i).end() ) setDef(i, place); else set(i, objectDefaults(i)[tag(place)], place); } else if ( action == "set" || action == "insert" || action == "newdef") { string val; arg >> val; if ( action == "insert" ) insert(i, val, place); else set(i, val, place); if ( action == "newdef" ) objectDefaults(i)[tag(place)] = get(i)[place]; } else if ( action == "notdef" ) { StringVector v = get(i); for ( place = 0; unsigned(place) < v.size(); ++place ) { string deflt = def(i, place); if ( objectDefaults(i).find(tag(place)) != objectDefaults(i).end() ) deflt = objectDefaults(i)[tag(place)]; else if ( !hasDefault ) continue; if ( v[place] == deflt ) continue; ret << "[" << place << "] " << v[place] << " (" << deflt << ") "; } } else throw InterExUnknown(*this, i); return ret.str(); } string ParVectorBase::fullDescription(const InterfacedBase & ib) const { ostringstream os; StringVector vals = get(ib); os << InterfaceBase::fullDescription(ib) << size() << "\n" << vals.size() << "\n"; for ( int i = 0, N = vals.size(); i < N; ++i ) { string min = minimum(ib, i); if ( min.empty() ) min = "-inf"; string max = maximum(ib, i); if ( max.empty() ) max = "inf"; os << vals[i] << "\n" << min << "\n" << def(ib, i) << "\n" << max << "\n"; } return os.str(); } ParVExIndex::ParVExIndex(const InterfaceBase & i, const InterfacedBase & o, int j) { theMessage << "Could not access element " << j << " of the parameter vector \"" << i.name() << "\" for the object \"" << o.name() << "\" because the index was outside of the allowed range."; severity(setuperror); } ParVExFixed::ParVExFixed(const InterfaceBase & i, const InterfacedBase & o) { theMessage << "Cannot insert or delete in the parameter vector \"" << i.name() << "\" for the object \"" << o.name() << "\" since the vector is of fixed size."; severity(setuperror); } ParVExDelUnknown::ParVExDelUnknown(const InterfaceBase & i, const InterfacedBase & o, int j) { theMessage << "Could not delete the value at position " << j << " from the parameter vector \"" << i.name() << "\" for the object \"" << o.name() << "\" because the delete function threw an unknown exception."; severity(setuperror); } ParVExGetUnknown::ParVExGetUnknown(const InterfaceBase & i, const InterfacedBase & o, const char * s) { theMessage << "Could not get the " << s << " values from the parameter vector\"" << i.name() << "\" for the object \"" << o.name() << "\" because the get function threw an unknown exception."; severity(setuperror); } } #ifdef ThePEG_TEMPLATES_IN_CC_FILE #include "ParVector.tcc" #endif diff --git a/Interface/ParVector.h b/Interface/ParVector.h --- a/Interface/ParVector.h +++ b/Interface/ParVector.h @@ -1,1068 +1,1068 @@ // -*- C++ -*- // // ParVector.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_ParVector_H #define ThePEG_ParVector_H // This is the declaration of the ParVector, ParVectorTBase and // ParVectorBase classes. #include "ThePEG/Config/ThePEG.h" #include "InterfaceBase.h" #include "ParVector.fh" #include namespace ThePEG { /// Helper functions for putUnit namespace { template /** * Helper function for putUnit */ inline void putUnitImpl2(ostream & os, T v, T u, DimensionT) { os << v/u; } template /** * Helper function for putUnit */ inline void putUnitImpl2(ostream & os, T v, T u, StandardT) { if ( u > T() ) os << v/u; else os << v; } } /** * The ParVector and its base classes ParVectorTBase and ParVectorBase * defines an interface to a class derived from the InterfacedBase, * through which vectors (or any other container) of simple member * variables can be manuipulated. ParVector is templated on the type * of the member variable and the type of the InterfacedBase class, * and is derived from the InterfaceBase class via * ParVectorTBase (which is templated only on the class * of the member variable) and ParVectorBase. * * For each InterfacedBase class exactly one static ParVector object * should created for each member variable of container type which * should be interfaced. This object will automatically register * itself with the BaseRepository class. * * @see Parameter * @see InterfacedBase * @see InterfaceBase * */ class ParVectorBase: public InterfaceBase { public: /** A vector of strings. */ typedef vector StringVector; public: /** * Standard constructor. * * @param newName the name of the interface, may only contain * letters [a-zA-z0-9_]. * * @param newDescription a brief description of the interface. * * @param newClassName the name of the corresponding class. * * @param newTypeInfo the type_info object of the corresponding * class. * * @param newSize the size of the container or -1 if varying. * * @param depSafe set to true if calls to this interface for one * object does not influence other objects. * * @param readonly if this is set true the interface will not be * able to manipulate objects of the corresponding class, but will * still be able to access information. * * @param limits determines if the values of the parameters are * limited from above and/or below. The possible values are given by * Interface::Limits. */ ParVectorBase(string newName, string newDescription, string newClassName, const type_info & newTypeInfo, int newSize, bool depSafe, bool readonly, int limits) : InterfaceBase(newName, newDescription, newClassName, newTypeInfo, depSafe, readonly), limit(limits), theSize(newSize) { hasDefault = false; } /** * Destructor. */ virtual ~ParVectorBase() {} /** * The general interface method overriding the one in * InterfaceBase. For this class, \a action can be any of "set", * "insert", "erase", "get", "min", "max", "def" and "setdef" and \a * argument should be a something which can be read into an integer * and into a variable through a stringstream with the standard '>>' * operator. */ virtual string exec(InterfacedBase &, string action, string arguments) const; /** * Return a complete description of this parameter vector. */ virtual string fullDescription(const InterfacedBase & ib) const; /** * Set the \a i'th element of a container of member variables of \a * ib to \a val. \a val should be able to be read into the * corresponding variable type through a stringstream with the * standard '>>' operator. */ virtual void set(InterfacedBase & ib, string val, int i) const = 0; /** * Insert a new object before the \a i'th element of a container of * member variables of \a ib and set it to \a val. \a val should be * able to be read into the corresponding variable type through a * stringstream with the standard '>>' operator. */ virtual void insert(InterfacedBase & ib, string val, int i) const = 0; /** * Remove the \a i'th element of a container of member variables of * \a ib. */ virtual void erase(InterfacedBase & ib, int i) const = 0; /** * Clear the container of pointers of \a ib. */ virtual void clear(InterfacedBase & ib) const = 0; /** * Return the values of a container of member variables of \a ib. */ virtual StringVector get(const InterfacedBase & ib) const = 0; /** * Return the minimum value allowed for the \a i'th element of a * container of member variables of \a ib. */ virtual string minimum(const InterfacedBase & ib, int i) const = 0; /** * Return the maximum value allowed for the \a i'th element of a * container of member variables of \a ib. */ virtual string maximum(const InterfacedBase & ib, int i) const = 0; /** * Return the default value for the \a i'th element of a container * of member variables of \a ib. */ virtual string def(const InterfacedBase & ib, int i) const = 0; /** * Return the general default value for this parameter vector. */ virtual string def() const = 0; /** * Set the \a i'th element of a container of member variables of \a * ib to its default value. */ virtual void setDef(InterfacedBase & ib, int i) const = 0; /** * True if there the variable is limited from above and below. */ bool limited() const { return limit != Interface::nolimits; } /** * True if there the variable is limited from abovew. */ bool upperLimit() const { return limit == Interface::limited || limit == Interface::upperlim; } /** * True if there the variable is limited from below. */ bool lowerLimit() const { return limit == Interface::limited || limit == Interface::lowerlim; } /** * Set a flag indicating that there are limits associated with the * variables. */ void setLimited() { limit = Interface::limited; } /** * Set a flag indicating if there are no limits associated with the * variables. */ void setUnlimited() { limit = Interface::nolimits; } /** * Get the size of the container being interfaced. If the size() is * less than 0, the size is allowed to vary. */ int size() const { return theSize; } /** * Set the size of the container being interfaced. If the size is * less than 0, the size is allowed to vary. */ void setSize(int sz) { theSize = sz; } /** * Set the size of the container being interfaced to -1, i.e. the * size is allowed to vary. */ void setVariableSize() { theSize = 0; } private: /** * True if there are limits associated with the * variables. */ int limit; /** * The size of the container being interfaced. */ int theSize; }; /** * The ParVector and its base classes ParVectorTBase and ParVectorBase * defines an interface to a class derived from the InterfacedBase, * through which vectors (or any other container) of simple member * variables can be manuipulated. ParVector is templated on the type * of the member variable and the type of the InterfacedBase class, * and is derived from the InterfaceBase class via * ParVectorTBase (which is templated only on the class * of the member variable) and ParVectorBase. * * For each InterfacedBase class exactly one static ParVector object * should created for each member variable of container type which * should be interfaced. This object will automatically register * itself with the BaseRepository class. * * @see Parameter * @see InterfacedBase * @see InterfaceBase * */ template class ParVectorTBase: public ParVectorBase { public: /** A vector of objects of the template argument type. */ typedef vector TypeVector; public: /** * Standard constructor. * * @param newName the name of the interface, may only contain * letters [a-zA-z0-9_]. * * @param newDescription a brief description of the interface. * * @param newClassName the name of the corresponding class. * * @param newTypeInfo the type_info object of the corresponding * class. * * @param newUnit the unit assumed when a number is read or written * to a stream. * * @param newSize the size of the container or -1 if varying. * * @param depSafe set to true if calls to this interface for one * object does not influence other objects. * * @param readonly if this is set true the interface will not be * able to manipulate objects of the corresponding class, but will * still be able to access information. * * @param limits determines if the values of the parameters are * limited from above and/or below. The possible values are given by * Interface::Limits. */ ParVectorTBase(string newName, string newDescription, string newClassName, const type_info & newTypeInfo, Type newUnit, int newSize, bool depSafe, bool readonly, int limits) : ParVectorBase(newName, newDescription, newClassName, newTypeInfo, newSize, depSafe, readonly, limits), theUnit(newUnit) {} /** * Destructor. */ virtual ~ParVectorTBase() {} /** * Return a code for the type of this parameter. */ virtual string type() const; /** * Return a string describing the type of interface to be included * in the Doxygen documentation. */ virtual string doxygenType() const; /** * Return a complete description of this parameter vector. */ virtual string fullDescription(const InterfacedBase & ib) const; /** * Set the \a i'th element of a container of member variables of \a * ib to val. Uses a stringstream to read the \a val into a Type * object and then calls tset(InterfacedBase &, Type, int). */ virtual void set(InterfacedBase & ib, string val, int i) const ; /** * Set the \a i'th element of a container of member variables of \a * ib to \a val. */ virtual void tset(InterfacedBase & ib, Type val, int i) const = 0; /** * Insert a new object before the \a i'th element of a container of * member variables of \a ib and set it to \a val. Uses a * stringstream to read the \a val into a Type object and then calls * tinsert(InterfacedBase &, Type, int). */ virtual void insert(InterfacedBase & ib, string val, int i) const ; private: /// Implementation of set() for standard types. void setImpl(InterfacedBase & ib, string val, int i, StandardT) const; /// Implementation of set() for dimensioned types. void setImpl(InterfacedBase & ib, string val, int i, DimensionT) const; /// Implementation of insert() for standard types. void insertImpl(InterfacedBase & ib, string val, int i, StandardT) const; /// Implementation of insert() for dimensioned types. void insertImpl(InterfacedBase & ib, string val, int i, DimensionT) const; public: /** * Insert a new object before the \a i'th element of a container of * member variables of \a ib and set it to \a val. */ virtual void tinsert(InterfacedBase & ib, Type val, int i) const = 0; /** * Return the values of a container of member variables of \a ib in * a vector of strings. Calls the The tget(const InterfacedBase &) * and returns a vector of strings converted with ostringstreams. */ virtual StringVector get(const InterfacedBase & ib) const ; /** * Return the values of a container of member variables of \a ib in a * vector of Type. */ virtual TypeVector tget(const InterfacedBase & ib) const = 0; /** * Return the minimum value allowed for the \a i'th element of a * container of member variables of \a ib. Calls tminimum(const * InterfacedBase &, int) and converts the returned value with an * ostringstream. * */ virtual string minimum(const InterfacedBase & ib, int i) const ; /** * Return the minimum value allowed for the \a i'th element of a * container of member variables of \a ib. */ virtual Type tminimum(const InterfacedBase & ib, int i) const = 0; /** * Return the maximum value allowed for the \a i'th element of a * container of member variables of \a ib. Calls tmaximum(const * InterfacedBase &, int) and converts the returned value with an * ostringstream. */ virtual string maximum(const InterfacedBase & ib, int i) const ; /** * Return the maximum value allowed for the \a i'th element of a * container of member variables of \a ib. */ virtual Type tmaximum(const InterfacedBase & ib, int i) const = 0; /** * Return the default value for the \a i'th element of a container * of member variables of \a ib. Calls tdef(const InterfacedBase &, * int) and converts the returned value with an ostringstream. */ virtual string def(const InterfacedBase & ib, int i) const ; /** * Return the default value for the \a i'th element of a container of * member variables of \a ib. */ virtual Type tdef(const InterfacedBase & ib, int i) const = 0; /** * Return the general default value for this parameter vector. Calls * tdef() and converts the returned value with an ostringstream. */ virtual string def() const; /** * Return the general default value for this parameter vector. */ virtual Type tdef() const = 0; /** * set the \a i'th element of a container of member variables of \a ib to * its default value. */ virtual void setDef(InterfacedBase & ib, int i) const ; /** * Get the unit which an Type object is divided (multiplied) by when * written to (read from) a stream via a double. If unit() is zero, * the Type object is written/read directly. */ Type unit() const { return theUnit; } /** * Set the unit which an Type object is divided (multiplied) by when * written to (read from) a stream via a double. If unit() is zero, * the Type object is written/read directly. */ void unit(Type u) { theUnit = u; } protected: /** * Write a numer to a stream with the unit specified with unit(). */ void putUnit(ostream & os, Type val) const { putUnitImpl2(os, val, unit(), typename TypeTraits::DimType()); } private: /** * The unit which an Type object is divided (multiplied) by * when written to (read from) a stream via a double. If unit() is * zero, the Type object is written/read directly. */ Type theUnit; }; /** * The ParVector and its base classes ParVectorTBase and ParVectorBase * defines an interface to a class derived from the InterfacedBase, * through which vectors (or any other container) of simple member * variables can be manuipulated. ParVector is templated on the type * of the member variable and the type of the InterfacedBase class, * and is derived from the InterfaceBase class via * ParVectorTBase (which is templated only on the class * of the member variable) and ParVectorBase. * * For each InterfacedBase class exactly one static ParVector object * should created for each member variable of container type which * should be interfaced. This object will automatically register * itself with the BaseRepository class. * * @see Parameter * @see InterfacedBase * @see InterfaceBase * */ template class ParVector: public ParVectorTBase { public: /** * The declaration of member functions which can be used by this * ParVector interface for 'set' actions. */ typedef void (T::*SetFn)(Type, int); /** * The declaration of member functions which can be used by this * ParVector interface for 'insert' actions. */ typedef void (T::*InsFn)(Type, int); /** * The declaration of member functions which can be used by this * ParVector interface for 'erase' actions. */ typedef void (T::*DelFn)(int); /** * A vector of objects of the template parameter Type. */ typedef vector TypeVector; /** * The declaration of member functions which can be used by this * ParVector interface for 'get' actions. */ typedef TypeVector (T::*GetFn)() const; /** * A vector of strings. */ typedef vector StringVector; /** * The declaration of member functions which can be used by this * ParVector interface for 'get' actions. */ typedef StringVector (T::*StringGetFn)() const; /** * The declaration of member functions which can be used by this * ParVector interface for 'erase' actions. */ typedef Type (T::*DefFn)(int) const; /** * Declaration of a direct pointer to the member variable in case it * is a vector. */ typedef TypeVector T::* Member; public: /** * Standard constructor. * * @param newName the name of the interface, may only contain * letters [a-zA-z0-9_]. * * @param newDescription a brief description of the interface. * * @param newMember a pointer to a Member which is a TypeVector. May * be null, in which case the pointers to member functions must be * specified. * * @param newSize the size of the container or -1 if varying. * * @param newDef the default value of the corresponding parameters. * * @param newMin the minimum value of the corresponding parameters. * * @param newMax the maximum value of the corresponding parameters. * * @param depSafe set to true if calls to this interface for one * object does not influence other objects. * * @param readonly if this is set true the interface will not be * able to manipulate objects of the corresponding class, but will * still be able to access information. * * @param limits determines if the values of the parameters are * limited from above and below. * * @param newSetFn optional pointer to member function for the 'set' * action. * * @param newInsFn optional pointer to member function for the * 'insert' action. * * @param newDelFn optional pointer to member function for the * 'erase' action. * * @param newDefFn optional pointer to member function for the * 'default' action. * * @param newGetFn optional pointer to member function for the * 'get' action. * * @param newMinFn optional pointer to member function for the * 'minimum' action. * * @param newMaxFn optional pointer to member function for the * 'maximum' action. * * @param newStringGetFn optional pointer to member function for the * 'get' action. */ ParVector(string newName, string newDescription, Member newMember, int newSize, Type newDef, Type newMin, Type newMax, bool depSafe = false, bool readonly = false, bool limits = true, SetFn newSetFn = 0, InsFn newInsFn = 0, DelFn newDelFn = 0, GetFn newGetFn = 0, DefFn newDefFn = 0, DefFn newMinFn = 0, DefFn newMaxFn = 0, StringGetFn newStringGetFn = 0) : ParVectorTBase(newName, newDescription, ClassTraits::className(), typeid(T), Type(), newSize, depSafe, readonly, limits), theMember(newMember), theDef(newDef), theMin(newMin), theMax(newMax), theSetFn(newSetFn), theInsFn(newInsFn), theDelFn(newDelFn), theGetFn(newGetFn), theDefFn(newDefFn), theMinFn(newMinFn), theMaxFn(newMaxFn), theStringGetFn(newStringGetFn) {} /** * Standard constructor. * * @param newName the name of the interface, may only contain * letters [a-zA-z0-9_]. * * @param newDescription a brief description of the interface. * * @param newMember a pointer to a Member which is a TypeVector. May * be null, in which case the pointers to member functions must be * specified. * * @param newUnit the unit assumed when a number is read or written * to a stream. * * @param newSize the size of the container or -1 if varying. * * @param newDef the default value of the corresponding parameters. * * @param newGetFn optional pointer to member function for the * 'get' action. * * @param newMin the minimum value of the corresponding parameters. * * @param newMax the maximum value of the corresponding parameters. * * @param depSafe set to true if calls to this interface for one * object does not influence other objects. * * @param readonly if this is set true the interface will not be * able to manipulate objects of the corresponding class, but will * still be able to access information. * * @param limits determines if the values of the parameters are * limited from above and below. * * @param newSetFn optional pointer to member function for the 'set' * action. * * @param newInsFn optional pointer to member function for the * 'insert' action. * * @param newDelFn optional pointer to member function for the * 'erase' action. * * @param newDefFn optional pointer to member function for the * 'default' action. * * @param newMinFn optional pointer to member function for the * 'minimum' action. * * @param newMaxFn optional pointer to member function for the * 'maximum' action. * * @param newStringGetFn optional pointer to member function for the * 'get' action. */ ParVector(string newName, string newDescription, Member newMember, Type newUnit, int newSize, Type newDef, Type newMin, Type newMax, bool depSafe = false, bool readonly = false, bool limits = true, SetFn newSetFn = 0, InsFn newInsFn = 0, DelFn newDelFn = 0, GetFn newGetFn = 0, DefFn newDefFn = 0, DefFn newMinFn = 0, DefFn newMaxFn = 0, StringGetFn newStringGetFn = 0) : ParVectorTBase(newName, newDescription, ClassTraits::className(), typeid(T), newUnit, newSize, depSafe, readonly, limits), theMember(newMember), theDef(newDef), theMin(newMin), theMax(newMax), theSetFn(newSetFn), theInsFn(newInsFn), theDelFn(newDelFn), theGetFn(newGetFn), theDefFn(newDefFn), theMinFn(newMinFn), theMaxFn(newMaxFn), theStringGetFn(newStringGetFn) {} /** * Standard constructor. * * @param newName the name of the interface, may only contain * letters [a-zA-z0-9_]. * * @param newDescription a brief description of the interface. * * @param newMember a pointer to a Member which is a TypeVector. May * be null, in which case the pointers to member functions must be * specified. * * @param newSize the size of the container or -1 if varying. * * @param newDef the default value of the corresponding parameters. * * @param newMin the minimum value of the corresponding parameters. * * @param newMax the maximum value of the corresponding parameters. * * @param depSafe set to true if calls to this interface for one * object does not influence other objects. * * @param readonly if this is set true the interface will not be * able to manipulate objects of the corresponding class, but will * still be able to access information. * * @param limits determines if the values of the parameters are * limited from above and/or below. The possible values are given by * Interface::Limits. * * @param newSetFn optional pointer to member function for the 'set' * action. * * @param newInsFn optional pointer to member function for the * 'insert' action. * * @param newDelFn optional pointer to member function for the * 'erase' action. * * @param newDefFn optional pointer to member function for the * 'default' action. * * @param newGetFn optional pointer to member function for the * 'get' action. * * @param newMinFn optional pointer to member function for the * 'minimum' action. * * @param newMaxFn optional pointer to member function for the * 'maximum' action. * * @param newStringGetFn optional pointer to member function for the * 'get' action. */ ParVector(string newName, string newDescription, Member newMember, int newSize, Type newDef, Type newMin, Type newMax, bool depSafe = false, bool readonly = false, int limits = Interface::limited, SetFn newSetFn = 0, InsFn newInsFn = 0, DelFn newDelFn = 0, GetFn newGetFn = 0, DefFn newDefFn = 0, DefFn newMinFn = 0, DefFn newMaxFn = 0, StringGetFn newStringGetFn = 0) : ParVectorTBase(newName, newDescription, ClassTraits::className(), typeid(T), Type(), newSize, depSafe, readonly, limits), theMember(newMember), theDef(newDef), theMin(newMin), theMax(newMax), theSetFn(newSetFn), theInsFn(newInsFn), theDelFn(newDelFn), theGetFn(newGetFn), theDefFn(newDefFn), theMinFn(newMinFn), theMaxFn(newMaxFn), theStringGetFn(newStringGetFn) {} /** * Standard constructor. * * @param newName the name of the interface, may only contain * letters [a-zA-z0-9_]. * * @param newDescription a brief description of the interface. * * @param newMember a pointer to a Member which is a TypeVector. May * be null, in which case the pointers to member functions must be * specified. * * @param newUnit the unit assumed when a number is read or written * to a stream. * * @param newSize the size of the container or -1 if varying. * * @param newDef the default value of the corresponding parameters. * * @param newGetFn optional pointer to member function for the * 'get' action. * * @param newMin the minimum value of the corresponding parameters. * * @param newMax the maximum value of the corresponding parameters. * * @param depSafe set to true if calls to this interface for one * object does not influence other objects. * * @param readonly if this is set true the interface will not be * able to manipulate objects of the corresponding class, but will * still be able to access information. * * @param limits determines if the values of the parameters are * limited from above and/or below. The possible values are given by * Interface::Limits. * * @param newSetFn optional pointer to member function for the 'set' * action. * * @param newInsFn optional pointer to member function for the * 'insert' action. * * @param newDelFn optional pointer to member function for the * 'erase' action. * * @param newDefFn optional pointer to member function for the * 'default' action. * * @param newMinFn optional pointer to member function for the * 'minimum' action. * * @param newMaxFn optional pointer to member function for the * 'maximum' action. * * @param newStringGetFn optional pointer to member function for the * 'get' action. */ ParVector(string newName, string newDescription, Member newMember, Type newUnit, int newSize, Type newDef, Type newMin, Type newMax, bool depSafe = false, bool readonly = false, int limits = Interface::limited, SetFn newSetFn = 0, InsFn newInsFn = 0, DelFn newDelFn = 0, GetFn newGetFn = 0, DefFn newDefFn = 0, DefFn newMinFn = 0, DefFn newMaxFn = 0, StringGetFn newStringGetFn = 0) : ParVectorTBase(newName, newDescription, ClassTraits::className(), typeid(T), newUnit, newSize, depSafe, readonly, limits), theMember(newMember), theDef(newDef), theMin(newMin), theMax(newMax), theSetFn(newSetFn), theInsFn(newInsFn), theDelFn(newDelFn), theGetFn(newGetFn), theDefFn(newDefFn), theMinFn(newMinFn), theMaxFn(newMaxFn), theStringGetFn(newStringGetFn) {} /** * Set the \a i'th element of a container of member variables of \a * ib to \a val. */ virtual void tset(InterfacedBase & ib, Type val, int i) const ; /** * Insert a new object before the \a i'th element of a container of * member variables of \a ib and set it to \a val. */ virtual void tinsert(InterfacedBase & ib, Type val, int i) const ; /** * Remove the \a i'th element of a container of * member variables of \a ib. */ virtual void erase(InterfacedBase & ib, int i) const; /** * Clear the container of pointers of \a ib. */ virtual void clear(InterfacedBase & ib) const; /** * Return the values of a container of member variables of \a ib in * a vector of strings. Calls the The tget(const InterfacedBase &) * and returns a vector of strings converted with ostringstreams. */ virtual StringVector get(const InterfacedBase & ib) const ; /** * Return the values of a container of member variables of \a ib in a * vector of Type. */ virtual TypeVector tget(const InterfacedBase & ib) const ; /** * Return the minimum value allowed for the \a i'th element of a * container of member variables of \a ib. */ virtual Type tminimum(const InterfacedBase & ib, int i) const ; /** * Return the maximum value allowed for the \a i'th element of a * container of member variables of \a ib. */ virtual Type tmaximum(const InterfacedBase & ib, int i) const ; /** * Return the default value for the \a i'th element of a container of * member variables of \a ib. */ virtual Type tdef(const InterfacedBase &, int) const ; /** * Return the general default value for this parameter vector. */ virtual Type tdef() const; /** * Give a pointer to a member function to be used by tset(). */ void setSetFunction(SetFn sf) { theSetFn = sf; } /** * Give a pointer to a member function to be used by tinsert(). */ void setInsertFunction(InsFn ifn) { theInsFn = ifn; } /** * Give a pointer to a member function to be used by tget(). */ void setGetFunction(GetFn gf) { theGetFn = gf; } /** * Give a pointer to a member function to be used by terase(). */ void setEraseFunction(DelFn df) { theDelFn = df; } /** * Give a pointer to a member function to be used by tdef(). */ void setDefaultFunction(GetFn df) { theDefFn = df; } /** * Give a pointer to a member function to be used by tminimum(). */ void setMinFunction(GetFn mf) { theMinFn = mf; } /** * Give a pointer to a member function to be used by tmaximum(). */ void setMaxFunction(GetFn mf) { theMaxFn = mf; } /** * Give a pointer to a member function to be used by get(). */ void setStringGetFunction(StringGetFn gf) { theStringGetFn = gf; } /** * Print a description to be included in the Doxygen documentation * to the given \a stream. */ virtual void doxygenDescription(ostream & stream) const; private: /** * The pointer to the member variable. */ Member theMember; /** * Default value to be used if no corresponding member function * pointer is given. */ Type theDef; /** * Minimum value to be used if no corresponding member function * pointer is given. */ Type theMin; /** * Maximum value to be used if no * corresponding member function pointer is given. */ Type theMax; /** * A pointer to a member function to be used by tset(). */ SetFn theSetFn; /** * A pointer to a member function to be used by tinsert(). */ InsFn theInsFn; /** * A pointer to a member function to be used by terase(). */ DelFn theDelFn; /** * A pointer to a member function to be used by tget(). */ GetFn theGetFn; /** * Pointer to member function to be used by tdef(). */ DefFn theDefFn; /** * Pointer to member function to be used by tminimum(). */ DefFn theMinFn; /** * Pointer to member function to be used by tmaximum(). */ DefFn theMaxFn; /** * A pointer to a member function to be used by set(). */ StringGetFn theStringGetFn; }; } #ifndef ThePEG_TEMPLATES_IN_CC_FILE #include "ParVector.tcc" #endif #endif /* ThePEG_ParVector_H */ diff --git a/Interface/ParVector.tcc b/Interface/ParVector.tcc --- a/Interface/ParVector.tcc +++ b/Interface/ParVector.tcc @@ -1,384 +1,384 @@ // -*- C++ -*- // // ParVector.tcc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined templated member // functions of the ParVector and ParVectorTBase classes. // #include "ParVector.xh" namespace ThePEG { template string ParVectorTBase::type() const { if ( std::numeric_limits::is_integer ) return "Vi"; if ( typeid(Type) == typeid(string) ) return "Vs"; return "Vf"; } template string ParVectorTBase::doxygenType() const { ostringstream os; if ( size() <= 0 ) os << "Varying size "; else os << "Fixed size (" << size() << ") "; os << "vector of "; string lim = ""; if ( !limited() ) lim = " unlimited"; if ( std::numeric_limits::is_integer ) os << lim << "integer "; else if ( typeid(Type) == typeid(string) ) os << "string "; else os << lim; os << "parameters"; return os.str(); } template string ParVectorTBase::fullDescription(const InterfacedBase & ib) const { return ParVectorBase::fullDescription(ib) + def() + "\n"; } template void ParVectorTBase::setDef(InterfacedBase & i, int place) const { if ( place >= 0 ) tset(i, tdef(i, place), place); int sz = get(i).size(); for ( int j = 0; j < sz; ++j ) tset(i, tdef(i, j), j); } template inline void ParVectorTBase:: setImpl(InterfacedBase & i, string newValue, int place, StandardT) const { istringstream is(newValue); if ( unit() > Type() ) { double t; is >> t; tset(i, Type(t*unit()), place); } else { Type t = Type(); is >> t; tset(i, t, place); } } template<> inline void ParVectorTBase:: setImpl(InterfacedBase & i, string newValue, int place, StandardT) const { istringstream is(newValue); bool t; is >> t; tset(i, t, place); } template inline void ParVectorTBase:: setImpl(InterfacedBase & i, string newValue, int place, DimensionT) const { istringstream is(newValue); double t; is >> t; tset(i, t*unit(), place); } template void ParVectorTBase:: set(InterfacedBase & i, string newValue, int place) const { setImpl(i, newValue, place, typename TypeTraits::DimType()); } template inline void ParVectorTBase:: insertImpl(InterfacedBase & i, string newValue, int place, StandardT) const { istringstream is(newValue); if ( unit() > Type() ) { double t; is >> t; tinsert(i, Type(t*unit()), place); } else { Type t = Type(); is >> t; tinsert(i, t, place); } } template <> inline void ParVectorTBase:: insertImpl(InterfacedBase & i, string newValue, int place, StandardT) const { istringstream is(newValue); bool t; is >> t; tinsert(i, t, place); } template inline void ParVectorTBase:: insertImpl(InterfacedBase & i, string newValue, int place, DimensionT) const { istringstream is(newValue); double t; is >> t; tinsert(i, t*unit(), place); } template void ParVectorTBase:: insert(InterfacedBase & i, string newValue, int place) const { insertImpl(i, newValue, place, typename TypeTraits::DimType()); } template typename ParVectorTBase::StringVector ParVectorTBase:: get(const InterfacedBase & i) const { TypeVector tres = tget(i); StringVector res; for ( typename TypeVector::iterator it = tres.begin(); it != tres.end(); ++it ) { ostringstream os; putUnit(os, *it); res.push_back(os.str()); } return res; } template string ParVectorTBase:: minimum(const InterfacedBase & i, int place) const { ostringstream os; putUnit(os, tminimum(i,place)); return os.str(); } template string ParVectorTBase:: maximum(const InterfacedBase & i, int place) const { ostringstream os; putUnit(os, tmaximum(i, place)); return os.str(); } template string ParVectorTBase:: def(const InterfacedBase & i, int place) const { ostringstream os; putUnit(os, tdef(i,place)); return os.str(); } template string ParVectorTBase::def() const { ostringstream os; putUnit(os, tdef()); return os.str(); } template Type ParVector::tdef() const { return theDef; } template void ParVector::tset(InterfacedBase & i, Type newValue, int place) const { if ( InterfaceBase::readOnly() ) throw InterExReadOnly(*this, i); T * t = dynamic_cast(&i); if ( !t ) throw InterExClass(*this, i); if ( ( ParVectorBase::lowerLimit() && newValue < tminimum(*t, place) ) || ( ParVectorBase::upperLimit() && newValue > tmaximum(*t, place) ) ) throw ParVExLimit(*this, i, newValue); TypeVector oldVector = tget(i); if ( theSetFn ) { try { (t->*theSetFn)(newValue, place); } catch (InterfaceException & e) { throw e; } catch ( ... ) { throw ParVExUnknown(*this, i, newValue, place, "set"); } } else { if ( !theMember ) throw InterExSetup(*this, i); if ( place < 0 || unsigned(place) >= (t->*theMember).size() ) throw ParVExIndex(*this, i, place); (t->*theMember)[place] = newValue; } if ( !InterfaceBase::dependencySafe() && oldVector != tget(i) ) i.touch(); } template void ParVector:: tinsert(InterfacedBase & i, Type newValue, int place) const { if ( InterfaceBase::readOnly() ) throw InterExReadOnly(*this, i); if ( ParVectorBase::size() > 0 ) throw ParVExFixed(*this, i); T * t = dynamic_cast(&i); if ( !t ) throw InterExClass(*this, i); if ( ( ParVectorBase::lowerLimit() && newValue < tminimum(*t, place) ) || ( ParVectorBase::upperLimit() && newValue > tmaximum(*t, place) ) ) throw ParVExLimit(*this, i, newValue); TypeVector oldVector = tget(i); if ( theInsFn ) { try { (t->*theInsFn)(newValue, place); } catch (InterfaceException & e) { throw e; } catch ( ... ) { throw ParVExUnknown(*this, i, newValue, place, "insert"); } } else { if ( !theMember ) throw InterExSetup(*this, i); if ( place < 0 || unsigned(place) > (t->*theMember).size() ) throw ParVExIndex(*this, i, place); (t->*theMember).insert((t->*theMember).begin()+place, newValue); } if ( !InterfaceBase::dependencySafe() && oldVector != tget(i) ) i.touch(); } template void ParVector:: erase(InterfacedBase & i, int place) const { if ( InterfaceBase::readOnly() ) throw InterExReadOnly(*this, i); if ( ParVectorBase::size() > 0 ) throw ParVExFixed(*this, i); T * t = dynamic_cast(&i); if ( !t ) throw InterExClass(*this, i); TypeVector oldVector = tget(i); if ( theDelFn ) { try { (t->*theDelFn)(place); } catch (InterfaceException & e) { throw e; } catch ( ... ) { throw ParVExDelUnknown(*this, i, place); } } else { if ( !theMember ) throw InterExSetup(*this, i); if ( place < 0 || unsigned(place) >= (t->*theMember).size() ) throw ParVExIndex(*this, i, place); (t->*theMember).erase((t->*theMember).begin()+place); } if ( !InterfaceBase::dependencySafe() && oldVector != tget(i) ) i.touch(); } template void ParVector::clear(InterfacedBase & i) const { if ( ParVectorBase::readOnly() ) throw InterExReadOnly(*this, i); if ( ParVectorBase::size() > 0 ) throw ParVExFixed(*this, i); T * t = dynamic_cast(&i); if ( !t ) throw InterExClass(*this, i); (t->*theMember).clear(); if ( !InterfaceBase::dependencySafe() ) i.touch(); } template typename ParVector::TypeVector ParVector:: tget(const InterfacedBase & i) const { const T * t = dynamic_cast(&i); if ( !t ) throw InterExClass(*this, i); if ( theGetFn ) { try { return (t->*theGetFn)(); } catch (InterfaceException & e) { throw e; } catch ( ... ) { throw ParVExGetUnknown(*this, i, "current"); } } if ( theMember ) return t->*theMember; throw InterExSetup(*this, i); } template typename ParVector::StringVector ParVector:: get(const InterfacedBase & i) const { if ( !theStringGetFn ) return ParVectorTBase::get(i); const T * t = dynamic_cast(&i); if ( !t ) throw InterExClass(*this, i); try { return (t->*theStringGetFn)(); } catch (InterfaceException & e) { throw e; } catch ( ... ) { throw ParVExGetUnknown(*this, i, "current"); } } template Type ParVector::tdef(const InterfacedBase & i, int place) const { if ( place < 0 || !theDefFn ) return theMin; const T * t = dynamic_cast(&i); if ( !t ) throw InterExClass(*this, i); try { return (t->*theDefFn)(place); } catch (InterfaceException & e) { throw e; } catch ( ... ) { throw ParVExGetUnknown(*this, i, "default"); } } template Type ParVector::tminimum(const InterfacedBase & i, int place) const { if ( place < 0 || !theMinFn ) return theMin; const T * t = dynamic_cast(&i); if ( !t ) throw InterExClass(*this, i); try { return (t->*theMinFn)(place); } catch (InterfaceException & e) { throw e; } catch ( ... ) { throw ParVExGetUnknown(*this, i, "minimum"); } } template Type ParVector::tmaximum(const InterfacedBase & i, int place) const { if ( place < 0 || !theMaxFn ) return theMax; const T * t = dynamic_cast(&i); if ( !t ) throw InterExClass(*this, i); try { return (t->*theMaxFn)(place); } catch (InterfaceException & e) { throw e; } catch ( ... ) { throw ParVExGetUnknown(*this, i, "maximum"); } } template void ParVector::doxygenDescription(ostream & os) const { ParVectorTBase::doxygenDescription(os); os << "Default value: "; this->putUnit(os, theDef); if ( theDefFn ) os << " (May be changed by member function.)"; if ( ParVectorBase::lowerLimit() ) { os << "
\nMinimum value: "; this->putUnit(os, theMin); if ( theMinFn ) os << " (May be changed by member function.)"; } if ( ParVectorBase::upperLimit() ) { os << "
\nMaximum value: "; this->putUnit(os, theMax); if ( theMaxFn ) os << " (May be changed by member function.)"; } os << "
\n"; } namespace { template inline void ostreamInsert2(ostream & os, T v, DimensionT) { os << ounit(v, T::baseunit()); } template inline void ostreamInsert2(ostream & os, T v, StandardT) { os << v; } } template ParVExLimit::ParVExLimit(const InterfaceBase & i, const InterfacedBase & o, T v) { theMessage << "Could not set/insert "; ostreamInsert2(theMessage,v,typename TypeTraits::DimType() ); theMessage << " in the parameter vector \"" << i.name() << "\" for the object \"" << o.name() << "\" because the value is outside the specified limits."; severity(setuperror); } template ParVExUnknown::ParVExUnknown(const InterfaceBase & i, const InterfacedBase & o, T v, int j, const char * s) { theMessage << "Could not " << s << " the value "; ostreamInsert2(theMessage,v,typename TypeTraits::DimType() ); theMessage << " at position " << j << " in the parameter vector \"" << i.name() << "\" for the object \"" << o.name() << "\" because the " << s << " function threw an unknown exception."; severity(setuperror); } } diff --git a/Interface/ParVector.xh b/Interface/ParVector.xh --- a/Interface/ParVector.xh +++ b/Interface/ParVector.xh @@ -1,68 +1,68 @@ // -*- C++ -*- // // ParVector.xh is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_ParVector_XH #define ThePEG_ParVector_XH // // This is the declarations of the exception classes used by the // ParVector class. // #include "InterfaceBase.xh" namespace ThePEG { /** @cond EXCEPTIONCLASSES */ /** Exception class used by ParVector if a value is set outside the * given limits. */ struct ParVExLimit: public InterfaceException { /** Standard constructor. */ template ParVExLimit(const InterfaceBase & i, const InterfacedBase & o, T v); }; /** Exception class used by ParVector if an unknown error was encountered. */ struct ParVExUnknown: public InterfaceException { /** Standard constructor. */ template ParVExUnknown(const InterfaceBase & i, const InterfacedBase & o, T v, int j, const char * s); }; /** Exception class used by ParVector if an index is outside the given * limits. */ struct ParVExIndex: public InterfaceException { /** Standard constructor. */ ParVExIndex(const InterfaceBase & i, const InterfacedBase & o, int index); }; /** Exception class used by ParVector if the size of a fixed-size * container is changed. */ struct ParVExFixed: public InterfaceException { /** Standard constructor. */ ParVExFixed(const InterfaceBase & i, const InterfacedBase & o); }; /** Exception class used by ParVector if an unknown error was encountered. */ struct ParVExDelUnknown: public InterfaceException { /** Standard constructor. */ ParVExDelUnknown(const InterfaceBase & i, const InterfacedBase & o, int j); }; /** Exception class used by ParVector if an unknown error was encountered. */ struct ParVExGetUnknown: public InterfaceException { /** Standard constructor. */ ParVExGetUnknown(const InterfaceBase & i, const InterfacedBase & o, const char * s); }; /** @endcond */ } #endif /* ThePEG_ParVector_XH */ diff --git a/Interface/Parameter.cc b/Interface/Parameter.cc --- a/Interface/Parameter.cc +++ b/Interface/Parameter.cc @@ -1,164 +1,164 @@ // -*- C++ -*- // // Parameter.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the ParameterBase class. // #include "InterfacedBase.h" #include "Parameter.h" #include "Parameter.xh" namespace ThePEG { ParameterBase::~ParameterBase() {} string ParameterBase::exec(InterfacedBase & i, string action, string arguments) const { if ( action == "get" ) { return get(i); } else if ( action == "min" ) { return minimum(i); } else if ( action == "max" ) { return maximum(i); } else if ( action == "def" ) { return def(i); } else if ( action == "setdef" ) { if ( objectDefaults(i).find(name()) == objectDefaults(i).end() ) setDef(i); else set(i, objectDefaults(i)[name()]); } else if ( action == "set" || action == "newdef" ) { set(i, arguments); if ( action == "newdef" ) objectDefaults(i)[name()] = get(i); } else if ( action == "notdef" ) { string deflt = def(i); if ( objectDefaults(i).find(name()) != objectDefaults(i).end() ) deflt = objectDefaults(i)[name()]; else if ( !hasDefault ) return ""; if ( deflt != get(i) ) return get(i) + " (" + deflt + ")"; } else throw InterExUnknown(*this, i); return ""; } string ParameterBase::fullDescription(const InterfacedBase & ib) const { string min = minimum(ib); if ( min.empty() ) min = "-inf"; string max = maximum(ib); if ( max.empty() ) max = "inf"; return InterfaceBase::fullDescription(ib) + get(ib) + '\n' + min + '\n' + def(ib) + '\n' + max + '\n'; } ParExGetUnknown::ParExGetUnknown(const InterfaceBase & i, const InterfacedBase & o, const char * s) { theMessage << "Could not get the " << s << " value of parameter \"" << i.name() << "\" for the object \"" << o.name() << "\" because the get function threw an unknown exception."; severity(setuperror); } } namespace { const std::map energymapping = { {"TeV",ThePEG::TeV}, {"GeV",ThePEG::GeV}, {"MeV",ThePEG::MeV} }; const std::map energy2mapping = { {"GeV2",ThePEG::GeV2}, {"MeV2",ThePEG::MeV2} }; const std::map lengthmapping = { {"mm",ThePEG::mm}, {"millimeter",ThePEG::mm} }; } namespace ThePEG { template <> void ParameterTBase:: checkUnitConsistency(string suffix) const { // for now, we don't require units to be specified if ( suffix.empty() ) return; const auto requestedUnit = energymapping.find(suffix); if ( requestedUnit != energymapping.end() && requestedUnit->second == unit() ) return; // all is fine else Throw() << name() << ": the unit suffix " << suffix << " does not match the unit\n" << "specified in the parameter definition (" << unit()/GeV << " GeV).\n\n" << "To proceed, fix the unit suffix in the input file.\n\n" << Exception::setuperror; } template <> void ParameterTBase:: checkUnitConsistency(string suffix) const { // for now, we don't require units to be specified if ( suffix.empty() ) return; const auto requestedUnit = energy2mapping.find(suffix); if ( requestedUnit != energy2mapping.end() && requestedUnit->second == unit() ) return; // all is fine else Throw() << name() << ": the unit suffix " << suffix << " does not match the unit\n" << "specified in the parameter definition (" << unit()/GeV2 << " GeV2).\n\n" << "To proceed, fix the unit suffix in the input file.\n\n" << Exception::setuperror; } template <> void ParameterTBase:: checkUnitConsistency(string suffix) const { // for now, we don't require units to be specified if ( suffix.empty() ) return; const auto requestedUnit = lengthmapping.find(suffix); if ( requestedUnit != lengthmapping.end() && requestedUnit->second == unit() ) return; // all is fine else Throw() << name() << ": the unit suffix " << suffix << " does not match the unit\n" << "specified in the parameter definition (" << unit()/mm << " mm).\n\n" << "To proceed, fix the unit suffix in the input file.\n\n" << Exception::setuperror; } } #ifdef ThePEG_TEMPLATES_IN_CC_FILE #include "Parameter.tcc" #endif diff --git a/Interface/Parameter.h b/Interface/Parameter.h --- a/Interface/Parameter.h +++ b/Interface/Parameter.h @@ -1,1139 +1,1139 @@ // -*- C++ -*- // // Parameter.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_Parameter_H #define ThePEG_Parameter_H // This is the declaration of the Parameter, ParameterTBase and // ParameterBase classes. #include "ThePEG/Config/ThePEG.h" #include "ThePEG/Utilities/Throw.h" #include "InterfaceBase.h" #include "Parameter.xh" #include "Parameter.fh" #include "ThePEG/Utilities/StringUtils.h" #include namespace ThePEG { /// Helper functions for putUnit() namespace { template /** * Helper functions for putUnit */ inline void putUnitImpl(ostream & os, T v, T u, DimensionT) { os << v/u; } template /** * Helper functions for putUnit */ inline void putUnitImpl(ostream & os, T v, T u, StandardT) { if ( u > T() ) os << v/u; else os << v; } template /** * Helper functions for putUnit */ inline void putUnitImpl(ostream & os, T v, T, EnumT) { os << v; } } /// Helper functions for unit multiplication. namespace { template U umult(const T & t, const U & u) { return t*u; } template bool umult(bool b, U) { return b; } } /** * The Parameter and its base classes ParameterTBase and ParameterBase * defines an interface to a class derived from the InterfacedBase, * through which simple member variables can be * manuipulated. Parameter is templated on the type of the member * variable and the type of the InterfacedBase class, and is derived * from the InterfaceBase class via ParameterTBase (which is templated * only on the type of the member variable) and ParameterBase. * * For each InterfacedBase class exactly one static Parameter object * should created for each member variable which should be * interfaced. This object will automatically register itself with the * BaseRepository class. * * @see InterfacedBase * @see InterfaceBase * */ class ParameterBase: public InterfaceBase { public: /** * Standard constructor. * * @param newName the name of the interface, may only contain * letters [a-zA-z0-9_]. * * @param newDescription a brief description of the interface. * * @param newClassName the name of the corresponding class. * * @param newTypeInfo the type_info object of the corresponding * class. * * @param depSafe set to true if calls to this interface for one * object does not influence other objects. * * @param readonly if this is set true the interface will not be * able to manipulate objects of the corresponding class, but will * still be able to access information. * * @param limits determines if the values of the parameters are * limited from above and/or below. The possible values are given by * Interface::Limits. */ ParameterBase(string newName, string newDescription, string newClassName, const type_info & newTypeInfo, bool depSafe, bool readonly, int limits) : InterfaceBase(newName, newDescription, newClassName, newTypeInfo, depSafe, readonly), limit(limits) {} /** * The destructor. */ virtual ~ParameterBase(); /** * The general interface method overriding the one in * InterfaceBase. For this class, \a action can be any of "set", * "get", "min", "max", "def" and "setdef" and \a argument should be * a something which can be read into a variable through a * stringstream with the standard '>>' operator. */ virtual string exec(InterfacedBase & ib, string action, string arguments) const; /** * Return a complete description of this parameter. */ virtual string fullDescription(const InterfacedBase & ib) const; /** * Set the member variable of \a ib to \a val. */ virtual void set(InterfacedBase & ib, string) const = 0; /** * Return the minimum value allowed for the member variable of \a ib. */ virtual string minimum(const InterfacedBase & ib) const = 0; /** * Return the maximum value allowed for the member variable of \a ib. */ virtual string maximum(const InterfacedBase & ib) const = 0; /** * Return the value of the member variable of \a ib. */ virtual string get(const InterfacedBase & ib) const = 0; /** * Return the default value for the member variable of \a ib. */ virtual string def(const InterfacedBase & ib) const = 0; /** * Set the member variable of \a ib to its default value. */ virtual void setDef(InterfacedBase & ib) const = 0; /** * True if there the variable is limited from above and below. */ bool limited() const { return limit != Interface::nolimits; } /** * True if there the variable is limited from abovew. */ bool upperLimit() const { return limit == Interface::limited || limit == Interface::upperlim; } /** * True if there the variable is limited from below. */ bool lowerLimit() const { return limit == Interface::limited || limit == Interface::lowerlim; } /** * Set flag indicating that there are limits associated with the * variable. */ void setLimited() { limit = Interface::limited; } /** * Set flag indicating that there are no limits associated with the * variable. */ void setUnlimited() { limit = Interface::nolimits; } private: /** * Determines if the values of the parameters are * limited from above and/or below. The possible values are given by * Interface::Limits. */ int limit; }; /** * The Parameter and its base classes ParameterTBase and ParameterBase * defines an interface to a class derived from the InterfacedBase, * through which simple member variables can be * manuipulated. Parameter is templated on the type of the member * variable and the type of the InterfacedBase class, and is derived * from the InterfaceBase class via ParameterTBase (which is templated * only on the type of the member variable) and ParameterBase. * * For each InterfacedBase class exactly one static Parameter object * should created for each member variable which should be * interfaced. This object will automatically register itself with the * BaseRepository class. * * @see InterfacedBase * @see InterfaceBase * */ template class ParameterTBase: public ParameterBase { public: /** * Standard constructor. * * @param newName the name of the interface, may only contain * letters [a-zA-z0-9_]. * * @param newDescription a brief description of the interface. * * @param newClassName the name of the corresponding class. * * @param newTypeInfo the type_info object of the corresponding * class. * * @param newUnit the unit assumed when a number is read or written * to a stream. * * @param depSafe set to true if calls to this interface for one * object does not influence other objects. * * @param readonly if this is set true the interface will not be * able to manipulate objects of the corresponding class, but will * still be able to access information. * * @param limits determines if the values of the parameters are * limited from above and/or below. The possible values are given by * Interface::Limits. */ ParameterTBase(string newName, string newDescription, string newClassName, const type_info & newTypeInfo, Type newUnit, bool depSafe, bool readonly, int limits) : ParameterBase(newName, newDescription, newClassName, newTypeInfo, depSafe, readonly, limits), theUnit(newUnit) {} /** * Destructor. */ virtual ~ParameterTBase() {} /** * Return a code for the type of this parameter. */ virtual string type() const; private: /// Implementation of set() for standard types. void setImpl (InterfacedBase & i, string newValue, StandardT) const; /// Implementation of set() for dimensioned types. void setImpl (InterfacedBase & i, string newValue, DimensionT) const; /// Implementation of set() for dimensioned types. void setImpl (InterfacedBase & i, string newValue, EnumT) const; public: /** * Set the member variables of \a ib to \a val. Uses a stringstream * to read the \a val into a Type object and then calls * tset(InterfacedBase &, Type). */ virtual void set(InterfacedBase & ib, string newValue) const; /** * Set the member variables of \a ib to \a val. */ virtual void tset(InterfacedBase & ib, Type) const = 0; /** * Return the value of the member variable of \a ib. Calls * tget(const InterfacedBase &) and converts the returned value with * an ostringstream. */ virtual string get(const InterfacedBase & ib) const ; /** * Return the value of the member variable of \a ib. */ virtual Type tget(const InterfacedBase & ib) const = 0; /** * Return the minimum value allowed for the member variable of \a * ib. Calls tmimimum(const InterfacedBase &) and converts the * returned value with an ostringstream. */ virtual string minimum(const InterfacedBase & ib) const ; /** * Return the minimum value allowed for the member variable of \a * ib. */ virtual Type tminimum(const InterfacedBase & ib) const = 0; /** * Return the maximum value allowed for the member variable of \a * ib. Calls tmaximum(const InterfacedBase &) and converts the * returned value with an ostringstream. */ virtual string maximum(const InterfacedBase & ib) const ; /** * Return the maximum value allowed for the member variable of * \a ib. */ virtual Type tmaximum(const InterfacedBase & ib) const = 0; /** * Return the default value for the member variables of \a ib. Calls * tdef(const InterfacedBase &) and converts the returned value with * an ostringstream. */ virtual string def(const InterfacedBase & ib) const ; /** * Return the default value for the member variables of \a ib. */ virtual Type tdef(const InterfacedBase &ib) const = 0; /** * set the member variable of \a ib to its default value. */ virtual void setDef(InterfacedBase & ib) const { tset(ib, tdef(ib)); } /** * Get the unit which an Type object is divided (multiplied) by when * written to (read from) a stream via a double. If unit() is zero, * the Type object is written/read directly. */ Type unit() const { return theUnit; } /** * Set the unit which an Type object is divided (multiplied) by when * written to (read from) a stream via a double. If unit() is zero, * the Type object is written/read directly. */ void unit(Type u) { theUnit = u; } /** * Return a string describing the type of interface to be included * in the Doxygen documentation. */ virtual string doxygenType() const; protected: /** * Write a number to a stream with the unit specified with unit(). */ void putUnit(ostream & os, Type val) const { putUnitImpl(os, val, unit(), typename TypeTraits::DimType()); } private: /** * The unit which an Type object is divided (multiplied) by * when written to (read from) a stream via a double. If unit() is * zero, the Type object is written/read directly. */ Type theUnit; /** * Helper to check the unit consistency in set() operations */ void checkUnitConsistency(string suffix) const; }; /** * The Parameter and its base classes ParameterTBase and ParameterBase * defines an interface to a class derived from the InterfacedBase, * through which simple member variables can be * manuipulated. Parameter is templated on the type of the member * variable and the type of the InterfacedBase class, and is derived * from the InterfaceBase class via ParameterTBase (which is templated * only on the type of the member variable) and ParameterBase. * * For each InterfacedBase class exactly one static Parameter object * should created for each member variable which should be * interfaced. This object will automatically register itself with the * BaseRepository class. * * @see InterfacedBase * @see InterfaceBase * */ template class Parameter: public ParameterTBase { public: /** * The declaration of member functions which can be used by this * Switch interface for the 'set' action. */ typedef void (T::*SetFn)(Type); /** * The declaration of member functions which can be used by this * Switch interface for the 'get', 'def', 'min' and 'max' actions. */ typedef Type (T::*GetFn)() const; /** * Declaration of a direct pointer to the member variable. */ typedef Type T::* Member; public: /** * Standard constructor. * * @param newName the name of the interface, may only contain * letters [a-zA-z0-9_]. * * @param newDescription a brief description of the interface. * * @param newMember a pointer to the member variable. May be null if * corresponding set/get functions are provided. * * @param newDef the default value for the member variable. * * @param newMin the minimum value for the member variable. * * @param newMax the maximum value for the member variable. * * @param depSafe set to true if calls to this interface for one * object does not influence other objects. * * @param readonly if this is set true the interface will not be * able to manipulate objects of the corresponding class, but will * still be able to access information. * * @param limits determines if the values of the parameters are * limited from above and below. * * @param newSetFn optional pointer to the member function for the * 'set' action. * * @param newGetFn optional pointer to the member function for the * 'get' action. * * @param newMinFn optional pointer to the member function for the * 'min' action. * * @param newMaxFn optional pointer to the member function for the * 'max' action. * * @param newDefFn optional pointer to the member function for the * 'def' action. */ Parameter(string newName, string newDescription, Member newMember, Type newDef, Type newMin, Type newMax, bool depSafe = false, bool readonly = false, bool limits = true, SetFn newSetFn = 0, GetFn newGetFn = 0, GetFn newMinFn = 0, GetFn newMaxFn = 0, GetFn newDefFn = 0) : ParameterTBase(newName, newDescription, ClassTraits::className(), typeid(T), Type(), depSafe, readonly, limits), theMember(newMember), theDef(newDef), theMin(newMin), theMax(newMax), theSetFn(newSetFn), theGetFn(newGetFn), theDefFn(newDefFn), theMinFn(newMinFn), theMaxFn(newMaxFn) {} /** * Standard constructor. * * @param newName the name of the interface, may only contain * letters [a-zA-z0-9_]. * * @param newDescription a brief description of the interface. * * @param newMember a pointer to the member variable. May be null if * corresponding set/get functions are provided. * * @param newUnit the unit assumed when a number is read or written * to a stream. * * @param newDef the default value for the member variable. * * @param newMin the minimum value for the member variable. * * @param newMax the maximum value for the member variable. * * @param depSafe set to true if calls to this interface for one * object does not influence other objects. * * @param readonly if this is set true the interface will not be * able to manipulate objects of the corresponding class, but will * still be able to access information. * * @param limits determines if the values of the parameters are * limited from above and below. * * @param newSetFn optional pointer to the member function for the * 'set' action. * * @param newGetFn optional pointer to the member function for the * 'get' action. * * @param newMinFn optional pointer to the member function for the * 'min' action. * * @param newMaxFn optional pointer to the member function for the * 'max' action. * * @param newDefFn optional pointer to the member function for the * 'def' action. */ Parameter(string newName, string newDescription, Member newMember, Type newUnit, Type newDef, Type newMin, Type newMax, bool depSafe = false, bool readonly = false, bool limits = true, SetFn newSetFn = 0, GetFn newGetFn = 0, GetFn newMinFn = 0, GetFn newMaxFn = 0, GetFn newDefFn = 0) : ParameterTBase(newName, newDescription, ClassTraits::className(), typeid(T), newUnit, depSafe, readonly, limits), theMember(newMember), theDef(newDef), theMin(newMin), theMax(newMax), theSetFn(newSetFn), theGetFn(newGetFn), theDefFn(newDefFn), theMinFn(newMinFn), theMaxFn(newMaxFn) {} /** * Standard constructor. * * @param newName the name of the interface, may only contain * letters [a-zA-z0-9_]. * * @param newDescription a brief description of the interface. * * @param newMember a pointer to the member variable. May be null if * corresponding set/get functions are provided. * * @param newDef the default value for the member variable. * * @param newMin the minimum value for the member variable. * * @param newMax the maximum value for the member variable. * * @param depSafe set to true if calls to this interface for one * object does not influence other objects. * * @param readonly if this is set true the interface will not be * able to manipulate objects of the corresponding class, but will * still be able to access information. * * @param limits determines if the values of the parameters are * limited from above and/or below. The possible values are given by * Interface::Limits. * * @param newSetFn optional pointer to the member function for the * 'set' action. * * @param newGetFn optional pointer to the member function for the * 'get' action. * * @param newMinFn optional pointer to the member function for the * 'min' action. * * @param newMaxFn optional pointer to the member function for the * 'max' action. * * @param newDefFn optional pointer to the member function for the * 'def' action. */ Parameter(string newName, string newDescription, Member newMember, Type newDef, Type newMin, Type newMax, bool depSafe = false, bool readonly = false, int limits = Interface::limited, SetFn newSetFn = 0, GetFn newGetFn = 0, GetFn newMinFn = 0, GetFn newMaxFn = 0, GetFn newDefFn = 0) : ParameterTBase(newName, newDescription, ClassTraits::className(), typeid(T), Type(), depSafe, readonly, limits), theMember(newMember), theDef(newDef), theMin(newMin), theMax(newMax), theSetFn(newSetFn), theGetFn(newGetFn), theDefFn(newDefFn), theMinFn(newMinFn), theMaxFn(newMaxFn) {} /** * Standard constructor. * * @param newName the name of the interface, may only contain * letters [a-zA-z0-9_]. * * @param newDescription a brief description of the interface. * * @param newMember a pointer to the member variable. May be null if * corresponding set/get functions are provided. * * @param newUnit the unit assumed when a number is read or written * to a stream. * * @param newDef the default value for the member variable. * * @param newMin the minimum value for the member variable. * * @param newMax the maximum value for the member variable. * * @param depSafe set to true if calls to this interface for one * object does not influence other objects. * * @param readonly if this is set true the interface will not be * able to manipulate objects of the corresponding class, but will * still be able to access information. * * @param limits determines if the values of the parameters are * limited from above and/or below. The possible values are given by * Interface::Limits. * * @param newSetFn optional pointer to the member function for the * 'set' action. * * @param newGetFn optional pointer to the member function for the * 'get' action. * * @param newMinFn optional pointer to the member function for the * 'min' action. * * @param newMaxFn optional pointer to the member function for the * 'max' action. * * @param newDefFn optional pointer to the member function for the * 'def' action. */ Parameter(string newName, string newDescription, Member newMember, Type newUnit, Type newDef, Type newMin, Type newMax, bool depSafe = false, bool readonly = false, int limits = Interface::limited, SetFn newSetFn = 0, GetFn newGetFn = 0, GetFn newMinFn = 0, GetFn newMaxFn = 0, GetFn newDefFn = 0) : ParameterTBase(newName, newDescription, ClassTraits::className(), typeid(T), newUnit, depSafe, readonly, limits), theMember(newMember), theDef(newDef), theMin(newMin), theMax(newMax), theSetFn(newSetFn), theGetFn(newGetFn), theDefFn(newDefFn), theMinFn(newMinFn), theMaxFn(newMaxFn) {} /** * Default dtor. */ virtual ~Parameter() {} /** * Set the member variable of \a ib to \a val. */ virtual void tset(InterfacedBase & ib, Type val) const; /** * Return the value of the member variable of ib. */ virtual Type tget(const InterfacedBase & ib) const; /** * Return the minimum value allowed for the member variable of \a ib. */ virtual Type tminimum(const InterfacedBase & ib) const ; /** * Return the miaximum value allowed for the member variable of \a ib. */ virtual Type tmaximum(const InterfacedBase & ib) const ; /** * Return the default value for the member variable of \a ib. */ virtual Type tdef(const InterfacedBase & ib) const ; /** * Give a pointer to a member function to be used by tset(). */ void setSetFunction(SetFn sf) { theSetFn = sf; } /** * Give a pointer to a member function to be used by tget(). */ void setGetFunction(GetFn gf) { theGetFn = gf; } /** * Give a pointer to a member function to be used by tdef(). */ void setDefaultFunction(GetFn df) { theDefFn = df; } /** * Give a pointer to a member function to be used by tminimum(). */ void setMinFunction(GetFn mf) { theMinFn = mf; } /** * Give a pointer to a member function to be used by tmaximum(). */ void setMaxFunction(GetFn mf) { theMaxFn = mf; } /** * Print a description to be included in the Doxygen documentation * to the given \a stream. */ virtual void doxygenDescription(ostream & stream) const; private: /** * The pointer to the member variable. */ Member theMember; /** * Default value to be used if no corresponding member function * pointer is given. */ Type theDef; /** * Minimum value to be used if no corresponding member function * pointer is given. */ Type theMin; /** * Maximum value to be used if no corresponding member function * pointer is given. */ Type theMax; /** * A pointer to a member function to be used by tset(). */ SetFn theSetFn; /** * Pointer to member function to be used by tget(). */ GetFn theGetFn; /** * Pointer to member function to be used by tdef(). */ GetFn theDefFn; /** * Pointer to member function to be used by tminimum(). */ GetFn theMinFn; /** * Pointer to member function to be used by tmaximum(). */ GetFn theMaxFn; }; /** * This is a specialization of ParameterTBase for the string case. * * @see ParameterTBase * */ template <> class ParameterTBase: public ParameterBase { public: /** * Enumerated variables to determine of a string parameter * corresponds to a file or a directory. */ enum FileType { NoFile, /**< Neither file nor directory. */ File, /**< The parameter corresponds to a file. */ Directory /**< The parameter corresponds to a directory. */ }; public: /** * Standard constructor. * * @param newName the name of the interface, may only contain * letters [a-zA-z0-9_]. * * @param newDescription a brief description of the interface. * * @param newClassName the name of the corresponding class. * * @param newTypeInfo the type_info object of the corresponding * class. * * @param depSafe set to true if calls to this interface for one * object does not influence other objects. * * @param readonly if this is set true the interface will not be * able to manipulate objects of the corresponding class, but will * still be able to access information. */ ParameterTBase(string newName, string newDescription, string newClassName, const type_info & newTypeInfo, bool depSafe, bool readonly) : ParameterBase(newName, newDescription, newClassName, newTypeInfo, depSafe, readonly, false), isFileType(NoFile) { hasDefault = false; } /** * Destructor. */ virtual ~ParameterTBase() {} /** * Return a code for the type of this parameter. */ virtual string type() const { switch ( file() ) { case File: return "PF"; case Directory: return "PD"; default: return "Ps"; } } /** * Indicate that this parameter corresponds to a file. */ void fileType() { file(File); } /** * Indicate that this parameter corresponds to a directory. */ void directoryType() { file(Directory); } /** * Indicate if this parameter corresponds to a file or directory. */ void file(FileType t) { isFileType = t; } /** * See if this parameter corresponds to a file or directory. */ FileType file() const { return isFileType; } /** * Set the member variables of \a ib to \a val. Uses a stringstream * to read the \a val into a Type object and then calls * tset(InterfacedBase &, Type). */ virtual void set(InterfacedBase & ib, string newValue) const { tset(ib, StringUtils::stripws(newValue)); } /** * Set the member variables of \a ib to \a val. */ virtual void tset(InterfacedBase & ib, string) const = 0; /** * Return the value of the member variable of \a ib. Calls * tget(const InterfacedBase &) and converts the returned value with * an ostringstream. */ virtual string get(const InterfacedBase & ib) const { return tget(ib); } /** * Return the value of the member variable of \a ib. */ virtual string tget(const InterfacedBase & ib) const = 0; /** * Return the minimum value allowed for the member variable of \a * ib. Not relevant for strings. Returns the empty string. */ virtual string minimum(const InterfacedBase &) const { return ""; } /** * Return the maximum value allowed for the member variable of \a * ib. Not relevant for strings. Returns the empty string. */ virtual string maximum(const InterfacedBase &) const { return ""; } /** * Return the default value for the member variables of \a ib. Calls * tdef(const InterfacedBase &) and converts the returned value with * an ostringstream. */ virtual string def(const InterfacedBase & ib) const { return tdef(ib); } /** * Return the default value for the member variables of \a ib. */ virtual string tdef(const InterfacedBase &ib) const = 0; /** * set the member variable of \a ib to its default value. */ virtual void setDef(InterfacedBase & i) const { tset(i, tdef(i)); } /** * Return a string describing the type of interface to be included * in the Doxygen documentation. */ virtual string doxygenType() const { return "Character string parameter"; } private: /** * Indicates if this parameter corresponds to a file or directory. */ FileType isFileType; }; /** * This is a partial specialization of Parameter for the string case. * * @see Parameter * */ template class Parameter: public ParameterTBase { public: /** * The declaration of member functions which can be used by this * Switch interface for the 'set' action. */ typedef void (T::*SetFn)(string); /** * The declaration of member functions which can be used by this * Switch interface for the 'get', 'def', 'min' and 'max' actions. */ typedef string (T::*GetFn)() const; /** * Declaration of a direct pointer to the member variable. */ typedef string T::* Member; public: /** * Standard constructor. * * @param newName the name of the interface, may only contain * letters [a-zA-z0-9_]. * * @param newDescription a brief description of the interface. * * @param newMember a pointer to the member variable. May be null if * corresponding set/get functions are provided. * * @param newDef the default value for the member variable. * * @param depSafe set to true if calls to this interface for one * object does not influence other objects. * * @param readonly if this is set true the interface will not be * able to manipulate objects of the corresponding class, but will * still be able to access information. * * @param newSetFn optional pointer to the member function for the * 'set' action. * * @param newGetFn optional pointer to the member function for the * 'get' action. * * @param newDefFn optional pointer to the member function for the * 'def' action. */ Parameter(string newName, string newDescription, Member newMember, string newDef, bool depSafe = false, bool readonly = false, SetFn newSetFn = 0, GetFn newGetFn = 0, GetFn newDefFn = 0) : ParameterTBase(newName, newDescription, ClassTraits::className(), typeid(T), depSafe, readonly), theMember(newMember), theDef(newDef), theSetFn(newSetFn), theGetFn(newGetFn), theDefFn(newDefFn) {} /** * Default dtor. */ virtual ~Parameter() {} /** * Set the member variable of \a ib to \a val. */ virtual void tset(InterfacedBase & ib, string val) const; /** * Return the value of the member variable of ib. */ virtual string tget(const InterfacedBase & ib) const ; /** * Return the default value for the member variable of \a ib. */ virtual string tdef(const InterfacedBase & ib) const ; /** * Give a pointer to a member function to be used by tset(). */ void setSetFunction(SetFn sf) { theSetFn = sf; } /** * Give a pointer to a member function to be used by tget(). */ void setGetFunction(GetFn gf) { theGetFn = gf; } /** * Give a pointer to a member function to be used by tdef(). */ void setDefaultFunction(GetFn df) { theDefFn = df; } /** * Print a description to be included in the Doxygen documentation * to the given \a stream. */ virtual void doxygenDescription(ostream & stream) const; private: /** * The pointer to the member variable. */ Member theMember; /** * Default, minimum and maximum values to be used if no * corresponding member function pointers are given. */ string theDef; /** * A pointer to a member function to be used by tset(). */ SetFn theSetFn; /** * Pointer to member function to be used by tget(). */ GetFn theGetFn; /** * Pointer to member function to be used by tdef(). */ GetFn theDefFn; }; } #ifndef ThePEG_TEMPLATES_IN_CC_FILE #include "Parameter.tcc" #endif #endif /* ThePEG_Parameter_H */ diff --git a/Interface/Parameter.tcc b/Interface/Parameter.tcc --- a/Interface/Parameter.tcc +++ b/Interface/Parameter.tcc @@ -1,331 +1,331 @@ // -*- C++ -*- // // Parameter.tcc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined templated member // functions of the Parameter and ParameterTBase classes. // namespace ThePEG { template string ParameterTBase::type() const { if ( std::numeric_limits::is_integer ) return "Pi"; if ( typeid(Type) == typeid(string) ) return "Ps"; return "Pf"; } template string ParameterTBase::doxygenType() const { string lim = ""; if ( !limited() ) lim = "Unlimited "; if ( std::numeric_limits::is_integer ) return lim + "Integer parameter"; if ( typeid(Type) == typeid(string) ) return "Character string parameter"; return lim + "Parameter"; } template inline void ParameterTBase::setImpl(InterfacedBase & i, string newValue, StandardT) const { istringstream is(newValue); if ( unit() > Type() ) { double t; is >> t; tset(i, umult(t, unit())); } else { Type t = Type(); is >> t; tset(i, t); } } template inline void ParameterTBase::setImpl(InterfacedBase & i, string newValue, DimensionT) const { istringstream is(newValue); double t; is >> t; // if 'is' has no more chars, all stream ops below are no-ops is.ignore(); // skip the connecting char string suffix; is >> suffix; checkUnitConsistency(suffix); tset(i, umult(t, unit())); } template inline void ParameterTBase::setImpl(InterfacedBase & i, string newValue, EnumT) const { istringstream is(newValue); int t; is >> t; tset(i, Type(t)); } // Macs need a visible template specialization. template <> void ParameterTBase:: checkUnitConsistency(string suffix) const; template <> void ParameterTBase:: checkUnitConsistency(string suffix) const; template <> void ParameterTBase:: checkUnitConsistency(string suffix) const; template void ParameterTBase:: checkUnitConsistency(string suffix) const { if ( ! suffix.empty() ) { Throw() << name() << ": unit suffix " << suffix << " will be ignored.\n" << "The unit specified in the parameter definition is used instead.\n\n" << "To proceed, remove the unit suffix in the input file or \n" << "request unit support for " << suffix << " to be added.\n\n" << Exception::setuperror; } } template void ParameterTBase:: set(InterfacedBase & i, string newValue) const { setImpl(i, newValue, typename TypeTraits::DimType()); } template string ParameterTBase:: get(const InterfacedBase & i) const { ostringstream os; putUnit(os, tget(i)); return os.str(); } template string ParameterTBase:: minimum(const InterfacedBase & i) const { ostringstream os; if ( ParameterBase::lowerLimit() ) putUnit(os, tminimum(i)); return os.str(); } template string ParameterTBase:: maximum(const InterfacedBase & i) const { ostringstream os; if ( ParameterBase::upperLimit() ) putUnit(os, tmaximum(i)); return os.str(); } template string ParameterTBase:: def(const InterfacedBase & i) const { ostringstream os; putUnit(os, tdef(i)); return os.str(); } template void Parameter::tset(InterfacedBase & i, Type newValue) const { if ( InterfaceBase::readOnly() ) throw InterExReadOnly(*this, i); T * t = dynamic_cast(&i); if ( !t ) throw InterExClass(*this, i); if ( ( ParameterBase::lowerLimit() && newValue < tminimum(i) ) || ( ParameterBase::upperLimit() && newValue > tmaximum(i) ) ) throw ParExSetLimit(*this, i, newValue); Type oldValue = tget(i); if ( theSetFn ) { try { (t->*theSetFn)(newValue); } catch (InterfaceException & e) { throw e; } catch ( ... ) { throw ParExSetUnknown(*this, i, newValue); } } else { if ( theMember ) t->*theMember = newValue; else throw InterExSetup(*this, i); } if ( !InterfaceBase::dependencySafe() && oldValue != tget(i)) i.touch(); } template void Parameter::tset(InterfacedBase & i, string newValue) const { if ( InterfaceBase::readOnly() ) throw InterExReadOnly(*this, i); T * t = dynamic_cast(&i); if ( !t ) throw InterExClass(*this, i); string oldValue = tget(i); if ( theSetFn ) { try { (t->*theSetFn)(newValue); } catch (InterfaceException & e) { throw e; } catch ( ... ) { throw ParExSetUnknown(*this, i, newValue); } } else { if ( theMember ) t->*theMember = newValue; else throw InterExSetup(*this, i); } if ( !InterfaceBase::dependencySafe() && oldValue != tget(i)) i.touch(); } template Type Parameter::tget(const InterfacedBase & i) const { const T * t = dynamic_cast(&i); if ( !t ) throw InterExClass(*this, i); if ( theGetFn ) { try { return (t->*theGetFn)(); } catch (InterfaceException & e) { throw e; } catch ( ... ) { throw ParExGetUnknown(*this, i, "current"); } } if ( theMember ) return t->*theMember; else throw InterExSetup(*this, i); } template string Parameter::tget(const InterfacedBase & i) const { const T * t = dynamic_cast(&i); if ( !t ) throw InterExClass(*this, i); if ( theGetFn ) { try { return (t->*theGetFn)(); } catch (InterfaceException & e) { throw e; } catch ( ... ) { throw ParExGetUnknown(*this, i, "current"); } } if ( theMember ) return t->*theMember; else throw InterExSetup(*this, i); } template Type Parameter::tminimum(const InterfacedBase & i) const { if ( theMinFn ) { const T * t = dynamic_cast(&i); if ( !t ) throw InterExClass(*this, i); try { return max(theMin, (t->*theMinFn)()); } catch (InterfaceException & e) { throw e; } catch ( ... ) { throw ParExGetUnknown(*this, i, "minimum"); } } return theMin; } template Type Parameter::tmaximum(const InterfacedBase & i) const { if ( theMaxFn ) { const T * t = dynamic_cast(&i); if ( !t ) throw InterExClass(*this, i); try { return min(theMax, (t->*theMaxFn)()); } catch (InterfaceException & e) { throw e; } catch ( ... ) { throw ParExGetUnknown(*this, i, "maximum"); } } return theMax; } template Type Parameter::tdef(const InterfacedBase & i) const { if ( theDefFn ) { const T * t = dynamic_cast(&i); if ( !t ) throw InterExClass(*this, i); try { return (t->*theDefFn)(); } catch (InterfaceException & e) { throw e; } catch ( ... ) { throw ParExGetUnknown(*this, i, "default"); } } return theDef; } template string Parameter::tdef(const InterfacedBase & i) const { if ( theDefFn ) { const T * t = dynamic_cast(&i); if ( !t ) throw InterExClass(*this, i); try { return (t->*theDefFn)(); } catch (InterfaceException & e) { throw e; } catch ( ... ) { throw ParExGetUnknown(*this, i, "default"); } } return theDef; } template void Parameter::doxygenDescription(ostream & os) const { ParameterTBase::doxygenDescription(os); os << "Default value: "; this->putUnit(os, theDef); if ( theDefFn ) os << " (May be changed by member function.)"; if ( ParameterBase::lowerLimit() ) { os << "
\nMinimum value: "; this->putUnit(os, theMin); if ( theMinFn ) os << " (May be changed by member function.)"; } if ( ParameterBase::upperLimit() ) { os << "
\nMaximum value: "; this->putUnit(os, theMax); if ( theMaxFn ) os << " (May be changed by member function.)"; } os << "
\n"; } template void Parameter::doxygenDescription(ostream & os) const { ParameterTBase::doxygenDescription(os); os << "Default value: " << theDef; if ( theDefFn ) os << " (May be changed by member function.)"; os << "
\n"; } namespace { template inline void ostreamInsert(ostream & os, T v, DimensionT) { os << ounit(v, T::baseunit()); } template inline void ostreamInsert(ostream & os, T v, StandardT) { os << v; } template inline void ostreamInsert(ostream & os, T v, EnumT) { os << v; } } template ParExSetLimit::ParExSetLimit(const InterfaceBase & i, const InterfacedBase & o, T v) { theMessage << "Could not set the parameter \"" << i.name() << "\" for the object \"" << o.name() << "\" to "; ostreamInsert(theMessage,v,typename TypeTraits::DimType() ); theMessage << " because the value is outside the specified limits."; severity(setuperror); } template ParExSetUnknown::ParExSetUnknown(const InterfaceBase & i, const InterfacedBase & o, T v) { theMessage << "Could not set the parameter \"" << i.name() << "\" for the object \"" << o.name() << "\" to "; ostreamInsert(theMessage,v,typename TypeTraits::DimType() ); theMessage << " because the set function threw an unknown exception."; severity(setuperror); } } diff --git a/Interface/Parameter.xh b/Interface/Parameter.xh --- a/Interface/Parameter.xh +++ b/Interface/Parameter.xh @@ -1,51 +1,51 @@ // -*- C++ -*- // // Parameter.xh is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_Parameter_XH #define ThePEG_Parameter_XH // // This is the declarations of the exception classes used by the // Parameter class. // #include "InterfaceBase.xh" namespace ThePEG { /** @cond EXCEPTIONCLASSES */ /** Exception class used by Parameter if variable is set outside the * specified limits. */ struct ParExSetLimit: public InterfaceException { /** Standard constructor. */ template ParExSetLimit(const InterfaceBase & i, const InterfacedBase & o, T v); }; /** Exception class used by Parameter if an unkown error * occurs. */ struct ParExSetUnknown: public InterfaceException { /** Standard constructor. */ template ParExSetUnknown(const InterfaceBase & i, const InterfacedBase & o, T val); }; /** Exception class used by Parameter if an unkown error * occurs. */ struct ParExGetUnknown: public InterfaceException { /** Standard constructor. */ ParExGetUnknown(const InterfaceBase & i, const InterfacedBase & o, const char *); }; /** @endcond */ } #endif /* ThePEG_Parameter_XH */ diff --git a/Interface/RefVector.cc b/Interface/RefVector.cc --- a/Interface/RefVector.cc +++ b/Interface/RefVector.cc @@ -1,262 +1,262 @@ // -*- C++ -*- // // RefVector.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the RefVector class. // #include "InterfacedBase.h" #include "RefVector.h" #include "RefVector.xh" #include "ThePEG/Utilities/HoldFlag.h" #include "ThePEG/Utilities/Rebinder.h" #include "ThePEG/Repository/BaseRepository.h" #include "ThePEG/Repository/EventGenerator.h" using namespace ThePEG; RefVectorBase:: RefVectorBase(string newName, string newDescription, string newClassName, const type_info & newTypeInfo, string newRefClassName, const type_info & newRefTypeInfo, int newSize, bool depSafe, bool readonly, bool norebind, bool nullable, bool defnull) : RefInterfaceBase(newName, newDescription, newClassName, newTypeInfo, newRefClassName, newRefTypeInfo, depSafe, readonly, norebind, nullable, defnull), theSize(newSize) {} IVector RefVectorBase::getReferences(const InterfacedBase & i) const { return get(i); } string RefVectorBase::exec(InterfacedBase & i, string action, string arguments) const { istringstream arg(arguments.c_str()); int place = -1; if ( !( arg >> place ) ) place = -1; ostringstream ret; if ( action == "get" ) { IVector refvec = get(i); if ( place >= 0 && unsigned(place) < refvec.size() ) { if ( refvec[place] ) return refvec[place]->fullName(); else return "*** NULL Reference ***"; } for ( IVector::size_type j = 0; j < refvec.size(); ++j ) { if ( j != 0 ) ret << ", "; if ( refvec[j] ) ret << refvec[j]->fullName(); else ret << "*** NULL Reference ***"; } } else if ( action == "erase" ) { erase(i, place); } else if ( action == "clear" ) { clear(i); } else if ( action == "set" || action == "insert" || action == "newdef" || action == "setdef" ) { string refname; arg >> refname; if ( action == "setdef" ) { if ( objectDefaults(i).find(tag(place)) == objectDefaults(i).end() ) return "Error: No default value defined for this object."; refname = objectDefaults(i)[tag(place)]; } IBPtr ip; if ( refname.size() && refname != "NULL") { Interfaced * ii = dynamic_cast(&i); if ( ii && ii->generator() ) ip = ii->generator()->getObject(refname); else ip = BaseRepository::TraceObject(refname); } if ( action == "insert" ) insert(i, ip, place); else set(i, ip, place); if ( action == "newdef" ) { IVector refvec = get(i); if ( place >= 0 && unsigned(place) < refvec.size() ) objectDefaults(i)[tag(place)] = refvec[place]? refvec[place]->fullName(): string("NULL"); } } else if ( action == "notdef" ) { IVector refvec = get(i); for ( place = 0; unsigned(place) < refvec.size(); ++place ) { if ( objectDefaults(i).find(tag(place)) == objectDefaults(i).end() ) continue; string refname = refvec[place]? refvec[place]->fullName(): string("NULL"); if ( refname == objectDefaults(i)[tag(place)] ) continue; ret << "[" << place << "] " << refname << " (" << objectDefaults(i)[tag(place)] << ") "; } } else throw InterExUnknown(*this, i); return ret.str(); } string RefVectorBase::fullDescription(const InterfacedBase & ib) const { ostringstream os; os << InterfaceBase::fullDescription(ib) << ( noNull()? "nevernull\n": "nullable\n" ) << ( defaultIfNull()? "defnull\n": "nodefnull\n" ); IVector refs = get(ib); os << size() << '\n' << refs.size() << '\n'; for ( int i = 0, N = refs.size(); i < N; ++i ) if ( !refs[i] ) os << "NULL\n"; else os << refs[i]->fullName() << '\n'; return os.str(); } string RefVectorBase::type() const { return string("V<") + refClassName() + ">"; } string RefVectorBase::doxygenType() const { ostringstream os; if ( size() <= 0 ) os << "Varying size "; else os << "Fixed size (" << size() << ") "; os << "vector of references to objects of class " << refClassName(); return os.str(); } void RefVectorBase:: rebind(InterfacedBase & i, const TranslationMap & trans, const IVector & defs) const { if ( noRebind() ) return; IVector oldrefs = get(i); IVector newRefs; for ( unsigned int ir = 0; ir < oldrefs.size(); ++ir ) { IBPtr oldref = oldrefs[ir];; IBPtr newref; if ( oldref ) { newref = trans.translate(oldref); if ( !dependencySafe() && newref->fullName() != oldref->fullName() ) i.touch(); } else if ( defaultIfNull() ) { for ( IVector::const_iterator p = defs.begin(); p != defs.end(); ++p ) { try { if ( *p && check(i, *p, ir) ) { newref = *p; i.touch(); break; } } catch ( ... ) {} } } newRefs.push_back(newref); } HoldFlag<> depflag(isDependencySafe); HoldFlag<> roflag(isReadOnly, false); if ( size() <= 0 ) for ( IVector::size_type j = oldrefs.size(); j > 0; --j ) erase(i, j - 1); for ( IVector::size_type j = 0; j < oldrefs.size(); ++j ) if ( size() > 0 ) set(i, newRefs[j], j, false); else insert(i, newRefs[j], j, false); } RefVExRefClass::RefVExRefClass(const RefInterfaceBase & i, const InterfacedBase & o, cIBPtr r, const char * s) { theMessage << "Could not " << s << " the object \"" << (r? r->name().c_str(): "") << "\" in the reference vector \"" << i.name() << "\" for the object \"" << o.name() << "\" because it is not of the required class (" << i.refClassName() << ")."; severity(setuperror); } RefVExSetUnknown::RefVExSetUnknown(const RefInterfaceBase & i, const InterfacedBase & o, cIBPtr r, int j, const char * s) { theMessage << "Could not " << s << " the object \"" << (r? r->name().c_str(): "") << " at position " << j << " in the reference vector \"" << i.name() << "\" for the object \"" << o.name() << "\" because the " << s << " function threw an unknown exception."; severity(setuperror); } RefVExSetUnfound::RefVExSetUnfound(const InterfaceBase & i, const InterfacedBase & o, string n) { theMessage << "Could not set the object named \"" << n << " in the reference vector \"" << i.name() << "\" of \"" << o.name() << "\"because the object was not found."; severity(setuperror); } RefVExIndex::RefVExIndex(const InterfaceBase & i, const InterfacedBase & o, int j) { theMessage << "Could not access element " << j << " of the reference vector \"" << i.name() << "\" for the object \"" << o.name() << "\" because the index was outside of the allowed range."; severity(setuperror); } RefVExFixed::RefVExFixed(const InterfaceBase & i, const InterfacedBase & o) { theMessage << "Cannot insert or delete in the reference vector \"" << i.name() << "\" for the object \"" << o.name() << "\" since the vector is of fixed size."; severity(setuperror); } RefVExDelUnknown::RefVExDelUnknown(const InterfaceBase & i, const InterfacedBase & o, int j) { theMessage << "Could not delete the value at position " << j << " from the reference vector \"" << i.name() << "\" for the object \"" << o.name() << "\" because the delete function threw an unknown exception."; severity(setuperror); } RefVExGetUnknown::RefVExGetUnknown(const InterfaceBase & i, const InterfacedBase & o) { theMessage << "Could not get the reference vector \"" << i.name() << "\" for the object \"" << o.name() << "\" because the get function threw an unknown exception."; severity(setuperror); } RefVExNoSet::RefVExNoSet(const InterfaceBase & i, const InterfacedBase & o) { theMessage << "Could not set an object in the reference vector \"" << i.name() << "\" for the object \"" << o.name() << "\" because no set function has been specified."; severity(setuperror); } RefVExNoIns::RefVExNoIns(const InterfaceBase & i, const InterfacedBase & o) { theMessage << "Could not insert an object in the reference vector \"" << i.name() << "\" for the object \"" << o.name() << "\" because no insert function has been specified."; severity(setuperror); } RefVExNoDel::RefVExNoDel(const InterfaceBase & i, const InterfacedBase & o) { theMessage << "Could not erase an object in the reference vector \"" << i.name() << "\" for the object \"" << o.name() << "\" because no erase function has been specified."; severity(setuperror); } diff --git a/Interface/RefVector.h b/Interface/RefVector.h --- a/Interface/RefVector.h +++ b/Interface/RefVector.h @@ -1,444 +1,444 @@ // -*- C++ -*- // // RefVector.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_RefVector_H #define ThePEG_RefVector_H // This is the declaration of the RefVector and RefVectorBase classes. #include "ThePEG/Config/ThePEG.h" #include "InterfaceBase.h" #include "RefVector.xh" #include "RefVector.fh" namespace ThePEG { /** * The RefVector and its base class RefVectorBase defines an interface * to a class derived from the InterfacedBase, through which vectors * (or any other container) of pointers to other InterfacedBase * objects may be manipulated. RefVector is templated on the type of * the class and the class of the objects pointed to, and is derived * from the InterfaceBase class via RefVectorBase and * RefInterfaceBase. * * For each InterfacedBase class exactly one static RefVector object * should created for each member variable of container type which * should be interfaced. This object will automatically register * itself with the BaseRepository class. * * @see InterfacedBase * @see InterfaceBase * */ class RefVectorBase: public RefInterfaceBase { public: /** * Standard constructor. * * @param newName the name of the interface, may only contain * letters [a-zA-z0-9_]. * * @param newDescription a brief description of the interface. * * @param newClassName the name of the corresponding class. * * @param newTypeInfo the type_info object of the corresponding * class. * * @param newRefClassName the name of the class pointed to. * * @param newRefTypeInfo the type_info object of the class pointed * to. * * @param newSize the size of the container or -1 if varying. * * @param depSafe set to true if calls to this interface for one * object does not influence other objects. * * @param readonly if this is set true the interface will not be * able to manipulate objects of the corresponding class, but will * still be able to access information. * * @param norebind if set to true, this interface is not responsible * for the rebinding of corresponding objects. * * @param nullable if set to true this corresponding references may * be null. * * @param defnull if set to true and a corresponding reference is * null it may be given a a default value in the initialization of * an EventGenerator. */ RefVectorBase(string newName, string newDescription, string newClassName, const type_info & newTypeInfo, string newRefClassName, const type_info & newRefTypeInfo, int newSize, bool depSafe, bool readonly, bool norebind, bool nullable, bool defnull); /** * The general interface method overriding the one in * InterfaceBase. For this class, \a action can be any of "set", * "get", "erase" and "insert" and \a argument should be a something * which can be read into an integer while the rest of \a argument * should correspond to the name of an InterfacedBase object in the * BaseRepository. */ virtual string exec(InterfacedBase & ib, string action, string arguments) const; /** * Return a complete description of this reference vector. */ virtual string fullDescription(const InterfacedBase & ib) const; /** * Return a code for the type of this reference. */ virtual string type() const; /** * Return a string describing the type of interface to be included * in the Doxygen documentation. */ virtual string doxygenType() const; /** * Set the \a i'th element of a container of pointers of \a ib * to \a ip. */ virtual void set(InterfacedBase & ib, IBPtr ip, int i, bool chk = true) const = 0; /** * Insert a new pointer before the \a i'th element of a container of * pointers of \a ib and set it to \a ip. */ virtual void insert(InterfacedBase & ib, IBPtr ip, int i, bool chk = true) const = 0; /** * Remove the \a i'th element of a container of pointers of \a ib. */ virtual void erase(InterfacedBase & ib, int i) const = 0; /** * Clear the container of pointers of \a ib. */ virtual void clear(InterfacedBase & ib) const = 0; /** * Return a vector of pointers corresponding to the container of * pointers of \a ib. */ virtual IVector get(const InterfacedBase & ib) const = 0; /** * Check if set(ib, ip, i) will be successfull but do not do * anything. */ virtual bool check(const InterfacedBase & ib, cIBPtr ip, int i) const = 0; /** * In the object \a ib, replace all pointers to objects in this * interface with the translated ones provided by \a trans. If a * pointer is null, and defaultIfNull() is true, replace it with * the first alowed object found in \a defs. */ virtual void rebind(InterfacedBase & ib, const TranslationMap & trans, const IVector & defs) const; /** * Return pointers to other objects in \a ib. */ virtual IVector getReferences(const InterfacedBase & ib) const; /** * Get the size of the container being interfaced. If the size() is * less than 0, the size is allowed to vary. */ int size() const { return theSize; } /** * Set the size of the container being interfaced. If the size is * less than 0, the size is allowed to vary. */ void setSize(int sz) { theSize = sz; } /** * Set the size of the container being interfaced to -1, i.e. the * size is allowed to vary. */ void setVariableSize() { theSize = 0; } private: /** * The size of the container being interfaced. */ int theSize; }; /** * The RefVector and its base class RefVectorBase defines an interface * to a class derived from the InterfacedBase, through which vectors * (or any other container) of pointers to other InterfacedBase * objects may be manipulated. RefVector is templated on the type of * the class and the class of the objects pointed to, and is derived * from the InterfaceBase class via RefVectorBase and * RefInterfaceBase. * * For each InterfacedBase class exactly one static RefVector object * should created for each member variable of container type which * should be interfaced. This object will automatically register * itself with the BaseRepository class. * * @see InterfacedBase * @see InterfaceBase * */ template class RefVector: public RefVectorBase { public: /** A pointer to the class of objects referred to. */ typedef typename Ptr::pointer RefPtr; /** A const pointer to the class of objects referred to. */ typedef typename Ptr::const_pointer cRefPtr; /** A pointer to a menberfunction to be used for the 'set' action. */ typedef void (T::*SetFn)(RefPtr, int); /** A pointer to a menberfunction to be used for the 'insert' action. */ typedef void (T::*InsFn)(RefPtr, int); /** A pointer to a menberfunction to be used for the 'erase' action. */ typedef void (T::*DelFn)(int); /** A pointer to a menberfunction to be used for the 'check' action. */ typedef bool (T::*CheckFn)(cRefPtr, int) const; /** A pointer to a menberfunction to be used for the 'get' action. */ typedef vector (T::*GetFn)() const; /** * Declaration of a direct pointer to the member variable in case it * is a vector. */ typedef vector T::* Member; public: /** * Standard constructor. * * @param newName the name of the interface, may only contain * letters [a-zA-z0-9_]. * * @param newDescription a brief description of the interface. * * @param newMember a pointer to a Member which is a TypeVector. May * be null, in which case the pointers to member functions must be * specified. * * @param newSize the size of the container or -1 if varying. * * @param depSafe set to true if calls to this interface for one * object does not influence other objects. * * @param readonly if this is set true the interface will not be * able to manipulate objects of the corresponding class, but will * still be able to access information. * * @param rebind if set to true, this interface is responsible * for the rebinding of corresponding objects. * * @param nullable if set to true this corresponding references may * be null. * * @param newSetFn optional pointer to member function for the 'set' * action. * * @param newInsFn optional pointer to member function for the * 'insert' action. * * @param newDelFn optional pointer to member function for the * 'erase' action. * * @param newGetFn optional pointer to member function for the * 'get' action. * * @param newCheckFn optional pointer to member function for the * 'check' action. */ RefVector(string newName, string newDescription, Member newMember, int newSize, bool depSafe = false, bool readonly = false, bool rebind = true, bool nullable = true, SetFn newSetFn = 0, InsFn newInsFn = 0, DelFn newDelFn = 0, GetFn newGetFn = 0, CheckFn newCheckFn = 0); /** * Standard constructor. * * @param newName the name of the interface, may only contain * letters [a-zA-z0-9_]. * * @param newDescription a brief description of the interface. * * @param newMember a pointer to a Member which is a TypeVector. May * be null, in which case the pointers to member functions must be * specified. * * @param newSize the size of the container or -1 if varying. * * @param depSafe set to true if calls to this interface for one * object does not influence other objects. * * @param readonly if this is set true the interface will not be * able to manipulate objects of the corresponding class, but will * still be able to access information. * * @param rebind if set to true, this interface is responsible * for the rebinding of corresponding objects. * * @param nullable if set to true this corresponding references may * be null. * * @param defnull if set to true and a corresponding reference is * null it may be given a a default value in the initialization of * an EventGenerator. * * @param newSetFn optional pointer to member function for the 'set' * action. * * @param newInsFn optional pointer to member function for the * 'insert' action. * * @param newDelFn optional pointer to member function for the * 'erase' action. * * @param newGetFn optional pointer to member function for the * 'get' action. * * @param newCheckFn optional pointer to member function for the * 'check' action. */ RefVector(string newName, string newDescription, Member newMember, int newSize, bool depSafe, bool readonly, bool rebind, bool nullable, bool defnull, SetFn newSetFn = 0, InsFn newInsFn = 0, DelFn newDelFn = 0, GetFn newGetFn = 0, CheckFn newCheckFn = 0); /** * Set the \a i'th element of a container of pointers of \a ib * to \a ip. */ virtual void set(InterfacedBase & ib, IBPtr ip, int i, bool chk = true) const; /** * Insert a new pointer before the \a i'th element of a container of * pointers of \a ib and set it to \a ip. */ virtual void insert(InterfacedBase & ib, IBPtr ip, int i, bool chk = true) const; /** * Remove the \a i'th element of a container of pointers of \a ib. */ virtual void erase(InterfacedBase & ib, int i) const; /** * Clear the container of pointers of \a ib. */ virtual void clear(InterfacedBase & ib) const; /** * Return a vector of pointers corresponding to the container of * pointers of \a ib. */ virtual IVector get(const InterfacedBase & ib) const ; /** * Check if set(ib, ip, i) will be successfull but do not do * anything. */ virtual bool check(const InterfacedBase & ib, cIBPtr, int i) const ; /** * Give a pointer to a member function to be used by 'set()'. */ void setSetFunction(SetFn sf) { theSetFn = sf; } /** * Give a pointer to a member function to be used by 'insert()'. */ void setInsertFunction(InsFn ifn) { theInsFn = ifn; } /** * Give a pointer to a member function to be used by 'get()'. */ void setGetFunction(GetFn gf) { theGetFn = gf; } /** * Give a pointer to a member function to be used by 'erase()'. */ void setEraseFunction(DelFn df) { theDelFn = df; } /** * Give a pointer to a member function to be used by 'check()'. */ void setCheckFunction(CheckFn cf) { theCheckFn = cf; } private: /** * The pointer to the member variable. */ Member theMember; /** * A pointer to a member function to be used by 'set()'. */ SetFn theSetFn; /** * Give a pointer to a member function to be used by 'insert()'. */ InsFn theInsFn; /** * Give a pointer to a member function to be used by 'erase()'. */ DelFn theDelFn; /** * Give a pointer to a member function to be used by 'get()'. */ GetFn theGetFn; /** * Give a pointer to a member function to be used by 'check()'. */ CheckFn theCheckFn; }; } #include "RefVector.tcc" #endif /* ThePEG_RefVector_H */ diff --git a/Interface/RefVector.tcc b/Interface/RefVector.tcc --- a/Interface/RefVector.tcc +++ b/Interface/RefVector.tcc @@ -1,155 +1,155 @@ // -*- C++ -*- // // RefVector.tcc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined templated member // functions of the RefVector class. // namespace ThePEG { template RefVector:: RefVector(string newName, string newDescription, Member newMember, int newSize, bool depSafe, bool readonly, bool rebind, bool nullable, SetFn newSetFn, InsFn newInsFn, DelFn newDelFn, GetFn newGetFn, CheckFn newCheckFn) : RefVectorBase(newName, newDescription, ClassTraits::className(), typeid(T), ClassTraits::className(), typeid(R), newSize, depSafe, readonly, !rebind, nullable, false), theMember(newMember), theSetFn(newSetFn), theInsFn(newInsFn), theDelFn(newDelFn), theGetFn(newGetFn), theCheckFn(newCheckFn) {} template RefVector:: RefVector(string newName, string newDescription, Member newMember, int newSize, bool depSafe, bool readonly, bool rebind, bool nullable, bool defnull, SetFn newSetFn, InsFn newInsFn, DelFn newDelFn, GetFn newGetFn, CheckFn newCheckFn) : RefVectorBase(newName, newDescription, ClassTraits::className(), typeid(T), ClassTraits::className(), typeid(R), newSize, depSafe, readonly, !rebind, nullable, defnull), theMember(newMember), theSetFn(newSetFn), theInsFn(newInsFn), theDelFn(newDelFn), theGetFn(newGetFn), theCheckFn(newCheckFn) {} template void RefVector:: set(InterfacedBase & i, IBPtr newRef, int place, bool chk) const { if ( readOnly() ) throw InterExReadOnly(*this, i); T * t = dynamic_cast(&i); if ( !t ) throw InterExClass(*this, i); if ( noNull() && !newRef ) throw InterExNoNull(*this, i); RefPtr r = dynamic_ptr_cast(newRef); if ( !r && newRef ) throw RefVExRefClass(*this, i, newRef, "set"); IVector oldVector = get(i); if ( theSetFn && ( chk || !theMember ) ) { try { (t->*theSetFn)(r, place); } catch (InterfaceException & e) { throw e; } catch ( ... ) { throw RefVExSetUnknown(*this, i, r, place, "set"); } } else { if ( !theMember ) throw RefVExNoSet(*this, i); if ( place < 0 || static_cast(place) >= (t->*theMember).size() ) throw RefVExIndex(*this, i, place); (t->*theMember)[place] = r; } if ( !InterfaceBase::dependencySafe() && oldVector != get(i) ) i.touch(); } template void RefVector:: insert(InterfacedBase & i, IBPtr newRef, int place, bool chk) const { if ( readOnly() ) throw InterExReadOnly(*this, i); if ( size() > 0 ) throw RefVExFixed(*this, i); T * t = dynamic_cast(&i); if ( !t ) throw InterExClass(*this, i); if ( noNull() && !newRef ) throw InterExNoNull(*this, i); RefPtr r = dynamic_ptr_cast(newRef); if ( !r && newRef ) throw RefVExRefClass(*this, i, newRef, "insert"); IVector oldVector = get(i); if ( theInsFn && ( chk || !theMember ) ) { try { (t->*theInsFn)(r, place); } catch (InterfaceException & e) { throw e; } catch ( ... ) { throw RefVExSetUnknown(*this, i, r, place, "insert"); } } else { if ( !theMember ) throw RefVExNoIns(*this, i); if ( place < 0 || static_cast(place) > (t->*theMember).size() ) throw RefVExIndex(*this, i, place); (t->*theMember).insert((t->*theMember).begin()+place, r); } if ( !InterfaceBase::dependencySafe() && oldVector != get(i) ) i.touch(); } template void RefVector::erase(InterfacedBase & i, int place) const { if ( readOnly() ) throw InterExReadOnly(*this, i); if ( size() > 0 ) throw RefVExFixed(*this, i); T * t = dynamic_cast(&i); if ( !t ) throw InterExClass(*this, i); IVector oldVector = get(i); if ( theDelFn ) { try { (t->*theDelFn)(place); } catch (InterfaceException & e) { throw e; } catch ( ... ) { throw RefVExDelUnknown(*this, i, place); } } else { if ( !theMember ) throw RefVExNoDel(*this, i); if ( place < 0 || static_cast(place) >= (t->*theMember).size() ) throw RefVExIndex(*this, i, place); (t->*theMember).erase((t->*theMember).begin()+place); } if ( !InterfaceBase::dependencySafe() && oldVector != get(i) ) i.touch(); } template void RefVector::clear(InterfacedBase & i) const { if ( readOnly() ) throw InterExReadOnly(*this, i); if ( size() > 0 ) throw RefVExFixed(*this, i); T * t = dynamic_cast(&i); if ( !t ) throw InterExClass(*this, i); if ( !theMember ) throw RefVExNoDel(*this, i); (t->*theMember).clear(); if ( !InterfaceBase::dependencySafe() ) i.touch(); } template IVector RefVector::get(const InterfacedBase & i) const { const T * t = dynamic_cast(&i); if ( !t ) throw InterExClass(*this, i); if ( theGetFn ) { try { vector ret = (t->*theGetFn)(); return IVector(ret.begin(), ret.end()); } catch (InterfaceException & e) { throw e; } catch ( ... ) { throw RefVExGetUnknown(*this, i); } } if ( theMember ) return IVector((t->*theMember).begin(), (t->*theMember).end()); throw InterExSetup(*this, i); } template bool RefVector::check(const InterfacedBase & i, cIBPtr ir, int place) const { const T * t = dynamic_cast(&i); if ( !t ) throw InterExClass(*this, i); if ( noNull() && !ir ) return false; cRefPtr r = dynamic_ptr_cast(ir); if ( !r && ir ) return false; if ( theCheckFn ) return (t->*theCheckFn)(r, place); if ( !theMember ) return true; return place >= 0 && static_cast(place) <= (t->*theMember).size(); } } diff --git a/Interface/RefVector.xh b/Interface/RefVector.xh --- a/Interface/RefVector.xh +++ b/Interface/RefVector.xh @@ -1,94 +1,94 @@ // -*- C++ -*- // // RefVector.xh is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_RefVector_XH #define ThePEG_RefVector_XH // // This is the declarations of the exception classes used by the // RefVector class. // #include "InterfaceBase.xh" namespace ThePEG { /** @cond EXCEPTIONCLASSES */ /** Exception class used by RefVector if trying to set a pointer of * the wrong type. */ struct RefVExRefClass: public InterfaceException { /** Standard constructor. */ RefVExRefClass(const RefInterfaceBase & i, const InterfacedBase & o, cIBPtr r, const char *); }; /** Exception class used by RefVector if an unknown error occurs. */ struct RefVExSetUnknown: public InterfaceException { /** Standard constructor. */ RefVExSetUnknown(const RefInterfaceBase & i, const InterfacedBase & o, cIBPtr r, int j, const char *); }; /** Exception class used by RefVector of a specified object was not * found. */ struct RefVExSetUnfound: public InterfaceException { /** Standard constructor. */ RefVExSetUnfound(const InterfaceBase & i, const InterfacedBase & o, string); }; /** Exception class used by RefVector if a given index was out of * bounds. */ struct RefVExIndex: public InterfaceException { /** Standard constructor. */ RefVExIndex(const InterfaceBase & i, const InterfacedBase & o, int j); }; /** Exception class used by RefVector if trying to change the size of * a fixed size container. */ struct RefVExFixed: public InterfaceException { /** Standard constructor. */ RefVExFixed(const InterfaceBase & i, const InterfacedBase & o); }; /** Exception class used by RefVector if an unknown error occurs. */ struct RefVExDelUnknown: public InterfaceException { /** Standard constructor. */ RefVExDelUnknown(const InterfaceBase & i, const InterfacedBase & o, int j); }; /** Exception class used by RefVector if an unknown error occurs. */ struct RefVExGetUnknown: public InterfaceException { /** Standard constructor. */ RefVExGetUnknown(const InterfaceBase & i, const InterfacedBase & o); }; /** Exception class used by RefVector if manipulating through a null * member function */ struct RefVExNoSet: public InterfaceException { /** Standard constructor. */ RefVExNoSet(const InterfaceBase & i, const InterfacedBase & o); }; /** Exception class used by RefVector if manipulating through a null * member function */ struct RefVExNoIns: public InterfaceException { /** Standard constructor. */ RefVExNoIns(const InterfaceBase & i, const InterfacedBase & o); }; /** Exception class used by RefVector if manipulating through a null * member function */ struct RefVExNoDel: public InterfaceException { /** Standard constructor. */ RefVExNoDel(const InterfaceBase & i, const InterfacedBase & o); }; /** @endcond */ } #endif /* ThePEG_RefVector_XH */ diff --git a/Interface/Reference.cc b/Interface/Reference.cc --- a/Interface/Reference.cc +++ b/Interface/Reference.cc @@ -1,170 +1,170 @@ // -*- C++ -*- // // Reference.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the ReferenceBase class. // #include "InterfacedBase.h" #include "Reference.h" #include "Reference.xh" #include "ThePEG/Utilities/HoldFlag.h" #include "ThePEG/Utilities/Rebinder.h" #include "ThePEG/Repository/BaseRepository.h" #include "ThePEG/Repository/EventGenerator.h" using namespace ThePEG; ReferenceBase:: ReferenceBase(string newName, string newDescription, string newClassName, const type_info & newTypeInfo, string newRefClassName, const type_info & newRefTypeInfo, bool depSafe, bool readonly, bool norebind, bool nullable, bool defnull) : RefInterfaceBase(newName, newDescription, newClassName, newTypeInfo, newRefClassName, newRefTypeInfo, depSafe, readonly, norebind, nullable, defnull) {} IVector ReferenceBase::getReferences(const InterfacedBase & i) const { IVector r; r.push_back(get(i)); return r; } string ReferenceBase::exec(InterfacedBase & i, string action, string arguments) const { ostringstream ret; istringstream arg(arguments.c_str()); if ( action == "get" ) { cIBPtr ref = get(i); if ( ref ) ret << ref->fullName(); else ret << "*** NULL Reference ***"; } else if ( action == "set" || action == "newdef" || action == "setdef" ) { string refname; arg >> refname; if ( action == "setdef" ) { if ( objectDefaults(i).find(name()) == objectDefaults(i).end() ) return "Error: No default value defined for this object."; refname = objectDefaults(i)[name()]; } IBPtr ip; if ( refname.size() && refname != "NULL") { Interfaced * ii = dynamic_cast(&i); if ( ii && ii->generator() ) ip = ii->generator()->getObject(refname); else ip = BaseRepository::TraceObject(refname); } set(i, ip); if ( action == "newdef" ) objectDefaults(i)[name()] = get(i)? get(i)->fullName(): string("NULL"); } else if ( action == "notdef" ) { if ( objectDefaults(i).find(name()) == objectDefaults(i).end() ) return ""; string curr = get(i)? get(i)->fullName(): string("NULL"); if ( curr == objectDefaults(i)[name()] ) return ""; return curr + " (" + objectDefaults(i)[name()] + ")"; } else throw InterExUnknown(*this, i); return ret.str(); } string ReferenceBase::fullDescription(const InterfacedBase & ib) const { string ret = InterfaceBase::fullDescription(ib) + ( noNull()? "nevernull\n": "nullable\n" ) + ( defaultIfNull()? "defnull\n": "nodefnull\n" ); tIBPtr ref = get(ib); if ( !ref ) ret += "NULL\n"; else ret += ref->fullName() + '\n'; return ret; } string ReferenceBase::type() const { return string("R<") + refClassName() + ">"; } string ReferenceBase::doxygenType() const { return "Reference to objects of class " + refClassName(); } void ReferenceBase:: rebind(InterfacedBase & i, const TranslationMap & trans, const IVector & defs) const { if ( noRebind() ) return; IBPtr oldref = get(i); IBPtr newref; if ( oldref ) { newref = trans.translate(oldref); if ( !dependencySafe() && oldref && newref && newref->fullName() != oldref->fullName() ) i.touch(); } else if ( defaultIfNull() ) { try { for ( IVector::const_iterator p = defs.begin(); p != defs.end(); ++p ) { if ( *p && check(i, *p) ) { newref = *p; i.touch(); break; } } } catch ( ... ) {} } HoldFlag<> depflag(isDependencySafe); HoldFlag<> roflag(isReadOnly, false); set(i, newref, false); } RefExSetRefClass::RefExSetRefClass(const RefInterfaceBase & i, const InterfacedBase & o, cIBPtr r) { theMessage << "Could not set the reference \"" << i.name() << "\" for the object \"" << o.name() << "\" to the object \"" << (r? r->name().c_str(): "") << "\" because it is not of the required class (" << i.refClassName() << ")."; severity(setuperror); } RefExSetUnknown::RefExSetUnknown(const InterfaceBase & i, const InterfacedBase & o, cIBPtr r) { theMessage << "Could not set the reference \"" << i.name() << "\" for the object \"" << o.name() << "\" to the object \"" << (r? r->name().c_str(): "") << "\" because the set function threw an unknown exception."; severity(setuperror); } RefExGetUnknown::RefExGetUnknown(const InterfaceBase & i, const InterfacedBase & o) { theMessage << "Could not get the reference \"" << i.name() << "\" for the object \"" << o.name() << "\" because the get function threw an unknown exception."; severity(setuperror); } RefExSetNoobj::RefExSetNoobj(const InterfaceBase & i, const InterfacedBase & o, string n) { theMessage << "Could not set the reference \"" << i.name() << "\" for the object \"" << o.name() << "\" because the specified object \"" << n << "\" does not exist."; severity(setuperror); } RefExSetMessage:: RefExSetMessage(string ref, const InterfacedBase & o, const InterfacedBase & o2, string m) { theMessage << "Could not set the reference \"" << ref << "\" for the object \"" << o.name() << "\" to \"" << o2.name() << "\"." << m; severity(setuperror); } diff --git a/Interface/Reference.h b/Interface/Reference.h --- a/Interface/Reference.h +++ b/Interface/Reference.h @@ -1,340 +1,340 @@ // -*- C++ -*- // // Reference.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_Reference_H #define ThePEG_Reference_H // This is the declaration of the Reference and ReferenceBase classes. #include "ThePEG/Config/ThePEG.h" #include "InterfaceBase.h" #include "Reference.xh" #include "Reference.fh" namespace ThePEG { /** * The Reference class and its base class ReferenceBase defines an * interface to a class derived from the InterfacedBase, through which * pointers to other InterfacedBase objects may be manipulated. * Reference is templated on the type of the class and the class of * the objects pointed to, and is derived from the InterfaceBase class * via ReferenceBase and RefInterfaceBase. * * For each InterfacedBase class exactly one static Reference object * should created for each member variable which should be * interfaced. This object will automatically register itself with the * BaseRepository class. * * @see InterfacedBase * @see InterfaceBase * */ class ReferenceBase: public RefInterfaceBase { public: /** * Standard constructor. * * @param newName the name of the interface, may only contain * letters [a-zA-z0-9_]. * * @param newDescription a brief description of the interface. * * @param newClassName the name of the corresponding class. * * @param newTypeInfo the type_info object of the corresponding * class. * * @param newRefClassName the name of the class pointed to. * * @param newRefTypeInfo the type_info object of the class pointed * to. * * @param depSafe set to true if calls to this interface for one * object does not influence other objects. * * @param readonly if this is set true the interface will not be * able to manipulate objects of the corresponding class, but will * still be able to access information. * * @param norebind if set to true, this interface is not responsible * for the rebinding of corresponding objects. * * @param nullable if set to true this corresponding references may * be null. * * @param defnull if set to true and a corresponding reference is * null it may be given a a default value in the initialization of * an EventGenerator. */ ReferenceBase(string newName, string newDescription, string newClassName, const type_info & newTypeInfo, string newRefClassName, const type_info & newRefTypeInfo, bool depSafe, bool readonly, bool norebind, bool nullable, bool defnull); /** * The general interface method overriding the one in * InterfaceBase. For this class, \a action can be any of "set" and * "get" and \a argument should correspond to the name of an * InterfacedBase object in the BaseRepository. */ virtual string exec(InterfacedBase & ib, string action, string arguments) const; /** * Return a complete description of this reference. */ virtual string fullDescription(const InterfacedBase & ib) const; /** * Return a code for the type of this reference. */ virtual string type() const; /** * Return a string describing the type of interface to be included * in the Doxygen documentation. */ virtual string doxygenType() const; /** * Set the pointer of \a ib to \a ip. */ virtual void set(InterfacedBase & ib, IBPtr ip, bool chk = true) const = 0; /** * Return the pointer of \a ib. */ virtual IBPtr get(const InterfacedBase & ib) const = 0; /** * Check if set(ib, ip) will be successfull but do not do * anything. */ virtual bool check(const InterfacedBase & ib, cIBPtr ip) const = 0; /** * In the object \a ib, replace the pointer in this interface with one * of the translated ones provided by trans. If the pointer is null, * and defaultIfNull() is true, replace it with the first allowed * object found in \a defs. */ virtual void rebind(InterfacedBase & ib, const TranslationMap & trans, const IVector & defs) const; /** * Return the pointer to another object in \a ib (in a vector). */ virtual IVector getReferences(const InterfacedBase & ib) const; }; /** * The Reference and its base class ReferenceBase defines an interface * to a class derived from the InterfacedBase, through which pointers * to other InterfacedBase objects may be manipulated. Reference is * templated on the type of the class and the class of the objects * pointed to, and is derived from the InterfaceBase class via * ReferenceBase and RefInterfaceBase. * * For each InterfacedBase class exactly one static Reference object * should created for each member variable which should be * interfaced. This object will automatically register itself with the * BaseRepository class. * * @see InterfacedBase * @see InterfaceBase * */ template class Reference: public ReferenceBase { public: /** A pointer to the class of objects referred to. */ typedef typename Ptr::pointer RefPtr; /** A const pointer to the class of objects referred to. */ typedef typename Ptr::const_pointer cRefPtr; /** A pointer to a menberfunction to be used for the 'set' action. */ typedef void (T::*SetFn)(RefPtr); /** A pointer to a menberfunction to be used for the 'check' action. */ typedef bool (T::*CheckFn)(cRefPtr) const; /** A pointer to a menberfunction to be used for the 'get' action. */ typedef RefPtr (T::*GetFn)() const; /** Declaration of a direct pointer to the member variable. */ typedef RefPtr T::* Member; public: /** * Standard constructor. * * @param newName the name of the interface, may only contain * letters [a-zA-z0-9_]. * * @param newDescription a brief description of the interface. * * @param newMember a pointer to a Member which is a TypeVector. May * be null, in which case the pointers to member functions must be * specified. * * @param depSafe set to true if calls to this interface for one * object does not influence other objects. * * @param readonly if this is set true the interface will not be * able to manipulate objects of the corresponding class, but will * still be able to access information. * * @param rebind if set to true, this interface is responsible * for the rebinding of corresponding objects. * * @param nullable if set to true this corresponding references may * be null. * * @param newSetFn optional pointer to member function for the 'set' * action. * * @param newGetFn optional pointer to member function for the * 'get' action. * * @param newCheckFn optional pointer to member function for the * 'check' action. */ Reference(string newName, string newDescription, Member newMember, bool depSafe = false, bool readonly = false, bool rebind = true, bool nullable = true, SetFn newSetFn = 0, GetFn newGetFn = 0, CheckFn newCheckFn = 0) : ReferenceBase(newName, newDescription, ClassTraits::className(), typeid(T), ClassTraits::className(), typeid(R), depSafe, readonly, !rebind, nullable, false), theMember(newMember), theSetFn(newSetFn), theGetFn(newGetFn), theCheckFn(newCheckFn) {} /** * Standard constructor. * * @param newName the name of the interface, may only contain * letters [a-zA-z0-9_]. * * @param newDescription a brief description of the interface. * * @param newMember a pointer to a Member which is a TypeVector. May * be null, in which case the pointers to member functions must be * specified. * * @param depSafe set to true if calls to this interface for one * object does not influence other objects. * * @param readonly if this is set true the interface will not be * able to manipulate objects of the corresponding class, but will * still be able to access information. * * @param rebind if set to true, this interface is responsible * for the rebinding of corresponding objects. * * @param nullable if set to true this corresponding references may * be null. * * @param defnull if set to true and a corresponding reference is * null it may be given a a default value in the initialization of * an EventGenerator. * * @param newSetFn optional pointer to member function for the 'set' * action. * * @param newGetFn optional pointer to member function for the * 'get' action. * * @param newCheckFn optional pointer to member function for the * 'check' action. */ Reference(string newName, string newDescription, Member newMember, bool depSafe, bool readonly, bool rebind, bool nullable, bool defnull, SetFn newSetFn = 0, GetFn newGetFn = 0, CheckFn newCheckFn = 0) : ReferenceBase(newName, newDescription, ClassTraits::className(), typeid(T), ClassTraits::className(), typeid(R), depSafe, readonly, !rebind, nullable, defnull), theMember(newMember), theSetFn(newSetFn), theGetFn(newGetFn), theCheckFn(newCheckFn) {} /** * Set the pointer of \a ib to \a ip. */ virtual void set(InterfacedBase & ib, IBPtr ip, bool chk = true) const ; /** * Return the pointer of \a ib. */ virtual IBPtr get(const InterfacedBase & ib) const ; /** * Check if set(ib, ip) will be successfull but do not do * anything. */ virtual bool check(const InterfacedBase & ib, cIBPtr newRef) const ; /** * Give a pointer to a member function to be used by 'set()'. */ void setSetFunction(SetFn sf) { theSetFn = sf; } /** * Give a pointer to a member function to be used by 'get()'. */ void setGetFunction(GetFn gf) { theGetFn = gf; } /** * Give a pointer to a member function to be used by 'check()'. */ void setCheckFunction(CheckFn cf) { theCheckFn = cf; } private: /** * The pointer to the member variable. */ Member theMember; /** * A pointer to a member function to be used by 'set()'. */ SetFn theSetFn; /** * Give a pointer to a member function to be used by 'get()'. */ GetFn theGetFn; /** * Give a pointer to a member function to be used by 'check()'. */ CheckFn theCheckFn; }; } #include "Reference.tcc" #endif /* ThePEG_Reference_H */ diff --git a/Interface/Reference.tcc b/Interface/Reference.tcc --- a/Interface/Reference.tcc +++ b/Interface/Reference.tcc @@ -1,64 +1,64 @@ // -*- C++ -*- // // Reference.tcc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined templated member // functions of the Reference class. // namespace ThePEG { template void Reference::set(InterfacedBase & i, IBPtr newRef, bool chk) const { if ( readOnly() ) throw InterExReadOnly(*this, i); T * t = dynamic_cast(&i); if ( !t ) throw InterExClass(*this, i); if ( noNull() && !newRef ) throw InterExNoNull(*this, i); RefPtr r = dynamic_ptr_cast(newRef); if ( !r && newRef) throw RefExSetRefClass(*this, i, newRef); RefPtr oldRef = dynamic_ptr_cast(get(i)); if ( theSetFn && ( chk || !theMember ) ) { try { (t->*theSetFn)(r); } catch (InterfaceException & e) { throw e; } catch ( ... ) { throw RefExSetUnknown(*this, i, r); } } else { if ( theMember ) t->*theMember = r; else throw InterExSetup(*this, i); } if ( !InterfaceBase::dependencySafe() && oldRef != get(i) ) i.touch(); } template IBPtr Reference::get(const InterfacedBase & i) const { const T * t = dynamic_cast(&i); if ( !t ) throw InterExClass(*this, i); if ( theGetFn ) { try { return (t->*theGetFn)(); } catch (InterfaceException & e) { throw e; } catch ( ... ) { throw RefExGetUnknown(*this, i); } } if ( theMember ) return t->*theMember; throw InterExSetup(*this, i); } template bool Reference::check(const InterfacedBase & i, cIBPtr ir) const { const T * t = dynamic_cast(&i); if ( !t ) throw InterExClass(*this, i); if ( noNull() && !ir ) return false; cRefPtr r = dynamic_ptr_cast(ir); if ( !r && ir ) return false; if ( !theCheckFn ) return true; return (t->*theCheckFn)(r); } } diff --git a/Interface/Reference.xh b/Interface/Reference.xh --- a/Interface/Reference.xh +++ b/Interface/Reference.xh @@ -1,60 +1,60 @@ // -*- C++ -*- // // Reference.xh is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_Reference_XH #define ThePEG_Reference_XH // // This is the declarations of the exception classes used by the // Reference class. // #include "InterfaceBase.xh" namespace ThePEG { /** @cond EXCEPTIONCLASSES */ /** Exception class used by Reference if trying to set a pointer of * the wrong type. */ struct RefExSetRefClass: public InterfaceException { /** Standard constructor. */ RefExSetRefClass(const RefInterfaceBase & i, const InterfacedBase & o, cIBPtr r); }; /** Exception class used by Referenceif an unknown error occurs. */ struct RefExSetUnknown: public InterfaceException { /** Standard constructor. */ RefExSetUnknown(const InterfaceBase & i, const InterfacedBase & o, cIBPtr r); }; /** Exception class used by Reference if an unknown error occurs. */ struct RefExGetUnknown: public InterfaceException { /** Standard constructor. */ RefExGetUnknown(const InterfaceBase & i, const InterfacedBase & o); }; /** Exception class used by Reference of a specified object was not * found. */ struct RefExSetNoobj: public InterfaceException { /** Standard constructor. */ RefExSetNoobj(const InterfaceBase & i, const InterfacedBase & o, string); }; /** Exception class used by Reference for issuing warnings. */ struct RefExSetMessage: public InterfaceException { /** Standard constructor. */ RefExSetMessage(string ref, const InterfacedBase & o, const InterfacedBase & o2, string); }; /** @endcond */ } #endif /* ThePEG_Reference_XH */ diff --git a/Interface/Switch.cc b/Interface/Switch.cc --- a/Interface/Switch.cc +++ b/Interface/Switch.cc @@ -1,144 +1,144 @@ // -*- C++ -*- // // Switch.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the SwitchBase class. // #include "InterfacedBase.h" #include "Switch.h" #include "ThePEG/Utilities/StringUtils.h" namespace ThePEG { string SwitchBase::opttag(long opt) const { ostringstream ret; ret << opt; OptionMap::const_iterator oit = theOptions.find(opt); if ( oit == theOptions.end() ) ret << " [Not a registered option] "; else ret << " [" << (oit->second).name() << "]"; return ret.str(); } string SwitchBase::exec(InterfacedBase & i, string action, string arguments) const { ostringstream ret; if ( action == "get" ) { return opttag(get(i)); } else if ( action == "def" ) { return opttag(def(i)); } else if ( action == "setdef" && objectDefaults(i).find(name()) == objectDefaults(i).end() ) { setDef(i); } else if ( action == "set" || action == "newdef" || action == "setdef" ) { if ( action == "setdef" ) arguments = objectDefaults(i)[name()]; istringstream arg(arguments); long val; arg >> val; if ( !arg || theOptions.find(val) == theOptions.end() ) { string sval = StringUtils::car(arguments); StringMap::const_iterator sit = theOptionNames.find(sval); if ( sit == theOptionNames.end() ) { if ( sval == "true" && theOptions.find(1) != theOptions.end() ) val = 1; else if ( sval == "false" && theOptions.find(0) != theOptions.end() ) val = 0; else { string errortext = "Error: no option '" + StringUtils::car(arguments) + "' found for switch\n'" + i.fullName() + ":" +name() + "'\nValid options are: "; for (StringMap::const_iterator it = theOptionNames.begin(); it != theOptionNames.end(); ++it ) errortext += it->first + ' '; return errortext + '\n'; } } else val = sit->second.value(); } try { set(i, val); if ( action == "newdef" ) objectDefaults(i)[name()] = opttag(val); return ret.str(); } catch ( Exception & ex ) { ex.handle(); } istringstream arg2(arguments.c_str()); string sval; arg2 >> sval; StringMap::const_iterator optit = theOptionNames.find(sval); if ( optit != theOptionNames.end() ) val = optit->second.value(); set(i, val); if ( action == "newdef" ) objectDefaults(i)[name()] = opttag(val); } else if ( action == "notdef" ) { string deflt = opttag(def(i)); if ( objectDefaults(i).find(name()) != objectDefaults(i).end() ) deflt = objectDefaults(i)[name()]; else if ( !hasDefault ) return ""; if ( deflt != opttag(get(i)) ) return opttag(get(i)) + " (" + deflt + ")"; } else throw InterExUnknown(*this, i); return ret.str(); } string SwitchBase::type() const { return "Sw"; } string SwitchBase::doxygenType() const { return "Switch"; } string SwitchBase::fullDescription(const InterfacedBase & ib) const { ostringstream os; os << InterfaceBase::fullDescription(ib) << get(ib) << '\n' << def(ib) << '\n' << options().size() << '\n'; for ( OptionMap::const_iterator it = options().begin(); it != options().end(); ++it ) os << it->second.value() << '\n' << it->second.name() << '\n' << it->second.description() << endl; return os .str(); } SwExSetOpt::SwExSetOpt(const InterfaceBase & i, const InterfacedBase & o, long v) { theMessage << "Could not set the switch \"" << i.name() << "\" for the object \"" << o.name() << "\" to " << v << "because it is not a registered option."; severity(setuperror); } SwExSetUnknown::SwExSetUnknown(const InterfaceBase & i, const InterfacedBase & o, long v) { theMessage << "Could not set the switch \"" << i.name() << "\" for the object \"" << o.name() << "\" to " << v << " because the set function threw an unknown exception."; severity(setuperror); } SwExGetUnknown::SwExGetUnknown(const InterfaceBase & i, const InterfacedBase & o, const char * s) { theMessage << "Could not get the " << s << " value of switch \"" << i.name() << "\" for the object \"" << o.name() << "\" because the get function threw an unknown exception."; severity(setuperror); } } #ifdef ThePEG_TEMPLATES_IN_CC_FILE #include "Switch.tcc" #endif diff --git a/Interface/Switch.h b/Interface/Switch.h --- a/Interface/Switch.h +++ b/Interface/Switch.h @@ -1,406 +1,406 @@ // -*- C++ -*- // // Switch.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_Switch_H #define ThePEG_Switch_H // This is the declaration of the Switch, SwitchBase and SwitchOption classes. #include "ThePEG/Config/ThePEG.h" #include "Switch.fh" #include "Switch.xh" #include "InterfaceBase.h" namespace ThePEG { /** * SwitchOption is used by the Switch class and its base class * SwitchBase to define valid options in a switch. * * For each InterfacedBase class exactly one static Switch object * should created for each member variable which should be * interfaced. This object will automatically register itself with the * BaseRepository class. Also for each Switch object exactly one * static SwitchOption object should be created for each valid integer * option. * * @see InterfacedBase * @see InterfacedBase * @see Named * */ class SwitchOption: public Named { public: /** * Standard constructor. * * @param theSwitch the Switch object for which this option is * defined. Note thet the static Switch object must be created * before this is created. * * @param newName the name of the option, may only contain * letters [a-zA-z0-9_]. * * @param newDescription a brief description of the option. * * @param newValue the integer value corresponding to this option. */ template SwitchOption(SwitchBase & theSwitch, string newName, string newDescription, EnumT newValue); /** * Default constructor. */ SwitchOption() : theValue(-999) {} /** * The description of this option */ const string & description() const { return theDescription; } /** * The value of this option. */ long value() const { return theValue; } /** * The value of this option. */ operator long () const; protected: private: /** * The description of this option */ string theDescription; /** * The value of this option. */ long theValue; }; /** * The Switch class and its base class SwitchBase defines an interface * to a class derived from the InterfacedBase, through which simple * integer member variables can be manuipulated and set to a * pre-defined set of values (options). Switch is * templated on the type of the integer member variable and the type * of the class, and is derived from the InterfaceBase class via * SwitchBase. * * The Switch class has a set of Named SwitchOptions, * which limits the values possible to set. * * For each InterfacedBase class exactly one static Switch object * should created for each member variable which should be * interfaced. This object will automatically register itself with the * BaseRepository class. Also for each Switch object exactly one * static SwitchOption object should be created for each valid integer * option. * * @see InterfacedBase * @see InterfacedBase * @see Named * */ class SwitchBase: public InterfaceBase { public: /** A map with SwitchOptions indexed by their values. */ typedef map OptionMap; /** A map with SwitchOptions indexed by their names. */ typedef map StringMap; /** SwitchOption is a friend. */ friend class SwitchOption; public: /** * Standard constructor. * * @param newName the name of the interface, may only contain * letters [a-zA-z0-9_]. * * @param newDescription a brief description of the interface. * * @param newClassName the name of the corresponding class. * * @param newTypeInfo the type_info object of the corresponding * class. * * @param depSafe set to true if calls to this interface for one * object does not influence other objects. * * @param readonly if this is set true the interface will not be * able to manipulate objects of the corresponding class, but will * still be able to access information. */ SwitchBase(string newName, string newDescription, string newClassName, const type_info & newTypeInfo, bool depSafe, bool readonly) : InterfaceBase(newName, newDescription, newClassName, newTypeInfo, depSafe, readonly) {} /** * The general interface method overriding the one in * InterfaceBase. For this class, \a action can be any of "set", * "get", "def" and "setdef" and \a argument should be a something * which can be read into an integer variable through a stringstream * with the standard '>>' operator. */ virtual string exec(InterfacedBase & ib, string action, string arguments) const; /** * Return a complete description of this switch. */ virtual string fullDescription(const InterfacedBase & ib) const; /** * Return a code for the type of this switch. */ virtual string type() const; /** * Set the member variable of \a ib to \a val. */ virtual void set(InterfacedBase & ib, long val) const = 0; /** * Return the value of the member variable of \a ib. */ virtual long get(const InterfacedBase & ib) const = 0; /** * Return the default value for the member variable of \a ib. */ virtual long def(const InterfacedBase & ib) const = 0; /** * Set the member variable of \a ib to its default value. */ void setDef(InterfacedBase & i) const { set(i, def(i)); } /** * Check if \a val is among the listed options. */ bool check(long newValue) const { return member(theOptions, newValue); } /** * Return the map relating options to their values */ const OptionMap & options() const { return theOptions; } /** * Return a string describing the type of interface to be included * in the Doxygen documentation. */ virtual string doxygenType() const; /** * Return a string with the option index and its associated tag. */ string opttag(long opt) const; protected: /** * Register a new option. */ void registerOption(const SwitchOption & o) { theOptions[o.value()] = o; theOptionNames[o.name()] = o; } private: /** * The map relating options to their values */ OptionMap theOptions; /** * The map relating options to their names */ StringMap theOptionNames; }; /** * The Switch class and its base class SwitchBase defines an interface * to a class derived from the InterfacedBase, through which simple * integer member variables can be manuipulated and set to a * pre-defined set of values (options). Switch is templated on the * type of the integer member variable (also enums and bool are * allowed) and the type of the class, and is derived from the * InterfaceBase class via SwitchBase. * * The Switch class has a set of Named SwitchOptions, * which limits the values possible to set. * * For each InterfacedBase class exactly one static Switch object * should created for each member variable which should be * interfaced. This object will automatically register itself with the * BaseRepository class. Also for each Switch object exactly one * static SwitchOption object should be created for each valid integer * option. * * @see InterfacedBase * @see InterfacedBase * @see Named * */ template class Switch: public SwitchBase { public: /** * The declaration of member functions which can be used by this * Switch interface for the 'set' action. */ typedef void (T::*SetFn)(Int); /** * The declaration of member functions which can be used by this * Switch interface for the 'get' action. */ typedef Int (T::*GetFn)() const; /** * Declaration of a direct pointer to the member variable. */ typedef Int T::* Member; public: /** * Standard constructor. * * @param newName the name of the interface, may only contain * letters [a-zA-z0-9_]. * * @param newDescription a brief description of the interface. * * @param newMember a pointer to the member variable. May be null if * corresponding set/get functions are provided. * * @param newDef the default value for the member variable. * * @param depSafe set to true if calls to this interface for one * object does not influence other objects. * * @param readonly if this is set true the interface will not be * able to manipulate objects of the corresponding class, but will * still be able to access information. * * @param newSetFn optional pointer to the member function for the * 'set' action. * * @param newGetFn optional pointer to the member function for the * 'get' action. * * @param newDefFn optional pointer to the member function for the * 'def' action. */ Switch(string newName, string newDescription, Member newMember, Int newDef, bool depSafe = false, bool readonly = false, SetFn newSetFn = 0, GetFn newGetFn = 0, GetFn newDefFn = 0) : SwitchBase(newName, newDescription, ClassTraits::className(), typeid(T), depSafe, readonly), theMember(newMember), theDef(newDef), theSetFn(newSetFn), theGetFn(newGetFn), theDefFn(newDefFn) {} /** * Set the member variable of \a ib to \a val. */ virtual void set(InterfacedBase & ib, long val) const ; /** * Return the value of the member variable of \a ib. */ virtual long get(const InterfacedBase & ib) const; /** * Return the default value for the member variable of \a ib. */ virtual long def(const InterfacedBase & ib) const; /** * Give a pointer to a member function to be used by 'set()'. */ void setSetFunction(SetFn sf) { theSetFn = sf; } /** * Give a pointer to a member function to be used by 'get()'. */ void setGetFunction(GetFn gf) { theGetFn = gf; } /** * Give a pointer to a member function to be used by 'def()'. */ void setDefaultFunction(GetFn df) { theDefFn = df; } /** * Print a description to be included in the Doxygen documentation * to the given \a stream. */ virtual void doxygenDescription(ostream & stream) const; private: /** * The pointer to the member variable. */ Member theMember; /** * Default value to be used if no corresponding member function * pointers are given. */ Int theDef; /** * A pointer to a member function to be used by 'set()'. */ SetFn theSetFn; /** * Pointer to member function to be used by get(). */ GetFn theGetFn; /** * Pointer to member function to be used by def(). */ GetFn theDefFn; }; } #ifndef ThePEG_TEMPLATES_IN_CC_FILE #include "Switch.tcc" #endif #endif /* ThePEG_Switch_H */ diff --git a/Interface/Switch.tcc b/Interface/Switch.tcc --- a/Interface/Switch.tcc +++ b/Interface/Switch.tcc @@ -1,85 +1,85 @@ // -*- C++ -*- // // Switch.tcc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined templated member // functions of the Switch class. // namespace ThePEG { template SwitchOption::SwitchOption(SwitchBase & theSwitch, string newName, string newDescription, EnumT newValue) : Named(newName), theDescription(newDescription), theValue(static_cast(newValue)) { theSwitch.registerOption(*this); } template void Switch::set(InterfacedBase & i, long newValue) const { T * t = dynamic_cast(&i); if ( readOnly() ) throw InterExReadOnly(*this, i); if ( !t ) throw InterExClass(*this, i); if ( !check(newValue) ) throw SwExSetOpt(*this, i, newValue); long oldValue = get(i); if ( theSetFn ) { try { (t->*theSetFn)(Int(newValue)); } catch (InterfaceException & e) { throw e; } catch ( ... ) { throw SwExSetUnknown(*this, i, newValue); } } else { if ( theMember ) t->*theMember = Int(newValue); else throw InterExSetup(*this, i); } if ( !InterfaceBase::dependencySafe() && oldValue != get(i) ) i.touch(); } template long Switch::get(const InterfacedBase & i) const { const T * t = dynamic_cast(&i); if ( !t ) throw InterExClass(*this, i); if ( theGetFn ) { try { return static_cast((t->*theGetFn)()); } catch (InterfaceException & e) { throw e; } catch ( ... ) { throw SwExGetUnknown(*this, i, "current"); } } if ( theMember ) return static_cast(t->*theMember); throw InterExSetup(*this, i); } template long Switch::def(const InterfacedBase & i) const { if ( theDefFn ) { const T * t = dynamic_cast(&i); if ( !t ) throw InterExClass(*this, i); try { return static_cast((t->*theDefFn)()); } catch (InterfaceException & e) { throw e; } catch ( ... ) { throw SwExGetUnknown(*this, i, "default"); } } return static_cast(theDef); } template void Switch::doxygenDescription(ostream & os) const { SwitchBase::doxygenDescription(os); os << "Registered options:\n
\n"; for ( OptionMap::const_iterator it = options().begin(); it != options().end(); ++it ) os << "
" << it->first << "(" << it->second.name() << ")
" << "
" << it->second.description() << "\n"; os << "
\nDefault value: " << static_cast(theDef); if ( theDefFn ) os << " (May be changed by member function.)"; os << "\n\n"; } } diff --git a/Interface/Switch.xh b/Interface/Switch.xh --- a/Interface/Switch.xh +++ b/Interface/Switch.xh @@ -1,48 +1,48 @@ // -*- C++ -*- // // Switch.xh is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_Switch_XH #define ThePEG_Switch_XH // // This is the declarations of the exception classes used by the // Switch class. // #include "InterfaceBase.xh" namespace ThePEG { /** @cond EXCEPTIONCLASSES */ /** Exception class used by Switch if variable is set to a value which * is not a listed option. */ struct SwExSetOpt: public InterfaceException { /** Standard constructor. */ SwExSetOpt(const InterfaceBase & i, const InterfacedBase & o, long v); }; /** Exception class used by Switch if an unkown error * occurs. */ struct SwExSetUnknown: public InterfaceException { /** Standard constructor. */ SwExSetUnknown(const InterfaceBase & i, const InterfacedBase & o, long v); }; /** Exception class used by Switch if an unkown error * occurs. */ struct SwExGetUnknown: public InterfaceException { /** Standard constructor. */ SwExGetUnknown(const InterfaceBase & i, const InterfacedBase & o, const char * s); }; /** @endcond */ } #endif /* ThePEG_Switch_XH */ diff --git a/LesHouches/LesHouches.h b/LesHouches/LesHouches.h --- a/LesHouches/LesHouches.h +++ b/LesHouches/LesHouches.h @@ -1,253 +1,253 @@ // -*- C++ -*- // // LesHouches.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_LesHouches_H #define THEPEG_LesHouches_H // // This is the declaration of the LesHouches class. // #include "ThePEG/Config/ThePEG.h" namespace ThePEG { /** * The HEPRUP class is a simple container corresponding to the Les * Houches accord (hep-ph/0109068) common block with the same * name. The members are named in the same way as in the common * block. However, fortran arrays are represented by vectors, except * for the arrays of length two which are represented by pair objects. */ class HEPRUP { public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ HEPRUP() : IDWTUP(0), NPRUP(0) {} //@} public: /** * Set the NPRUP variable, corresponding to the number of * sub-processes, to \a nrup, and resize all relevant vectors * accordingly. */ void resize(int nrup) { NPRUP = nrup; resize(); } /** * Assuming the NPRUP variable, corresponding to the number of * sub-processes, is correctly set, resize the relevant vectors * accordingly. */ void resize() { XSECUP.resize(NPRUP); XERRUP.resize(NPRUP); XMAXUP.resize(NPRUP); LPRUP.resize(NPRUP); } /** * PDG id's of beam particles. (first/second is in +/-z direction). */ pair IDBMUP; /** * Energy of beam particles given in GeV. */ pair EBMUP; /** * The author group for the PDF used for the beams according to the * PDFLib specification. */ pair PDFGUP; /** * The id number the PDF used for the beams according to the * PDFLib specification. */ pair PDFSUP; /** * Master switch indicating how the ME generator envisages the * events weights should be interpreted according to the Les Houches * accord. */ int IDWTUP; /** * The number of different subprocesses in this file (should * typically be just one) */ int NPRUP; /** * The cross sections for the different subprocesses in pb. */ vector XSECUP; /** * The statistical error in the cross sections for the different * subprocesses in pb. */ vector XERRUP; /** * The maximum event weights (in XWGTUP) for different subprocesses. */ vector XMAXUP; /** * The subprocess code for the different subprocesses. */ vector LPRUP; }; /** * The HEPEUP class is a simple container corresponding to the Les * Houches accord (hep-ph/0109068) common block with the same * name. The members are named in the same way as in the common * block. However, fortran arrays are represented by vectors, except * for the arrays of length two which are represented by pair objects. */ class HEPEUP { public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ HEPEUP() : NUP(0), IDPRUP(0), XWGTUP(0.0), XPDWUP(0.0, 0.0), SCALUP(0.0), AQEDUP(0.0), AQCDUP(0.0) {} //@} public: /** * Set the NUP variable, corresponding to the number of particles in * the current event, to \a nup, and resize all relevant vectors * accordingly. */ void resize(int nup) { NUP = nup; resize(); } /** * Assuming the NUP variable, corresponding to the number of * particles in the current event, is correctly set, resize the * relevant vectors accordingly. */ void resize() { IDUP.resize(NUP); ISTUP.resize(NUP); MOTHUP.resize(NUP); ICOLUP.resize(NUP); PUP.resize(NUP); VTIMUP.resize(NUP); SPINUP.resize(NUP); } /** * The number of particle entries in the current event. */ int NUP; /** * The subprocess code for this event (as given in LPRUP). */ int IDPRUP; /** * The weight for this event. */ double XWGTUP; /** * The PDF weights for the two incoming partons. Note that this * variable is not present in the current LesHouches accord * (hep-ph/0109068), hopefully it will be present in a future * accord. */ pair XPDWUP; /** * The scale in GeV used in the calculation of the PDF's in this * event. */ double SCALUP; /** * The value of the QED coupling used in this event. */ double AQEDUP; /** * The value of the QCD coupling used in this event. */ double AQCDUP; /** * The PDG id's for the particle entries in this event. */ vector IDUP; /** * The status codes for the particle entries in this event. */ vector ISTUP; /** * Indices for the first and last mother for the particle entries in * this event. */ vector< pair > MOTHUP; /** * The colour-line indices (first(second) is (anti)colour) for the * particle entries in this event. */ vector< pair > ICOLUP; /** * Lab frame momentum (Px, Py, Pz, E and M in GeV) for the particle * entries in this event. */ vector< array > PUP; /** * Invariant lifetime (c*tau, distance from production to decay im * mm) for the particle entries in this event. */ vector VTIMUP; /** * Spin info for the particle entries in this event given as the * cosine of the angle between the spin vector of a particle and the * 3-momentum of the decaying particle, specified in the lab frame. */ vector SPINUP; }; } #endif /* THEPEG_LesHouches_H */ diff --git a/LesHouches/LesHouchesEventHandler.cc b/LesHouches/LesHouchesEventHandler.cc --- a/LesHouches/LesHouchesEventHandler.cc +++ b/LesHouches/LesHouchesEventHandler.cc @@ -1,621 +1,621 @@ // -*- C++ -*- // // LesHouchesEventHandler.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the 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*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) { const double fact = theNormWeight ? double(selector().sum()/picobarn) : 1.; reject(currentEvent()->weight()/fact); } catch (Stop) { } catch (Exception &) { 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 << theNormWeight; } void LesHouchesEventHandler::persistentInput(PersistentIStream & is, int) { is >> stats >> histStats >> theReaders >> theSelector >> 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,474 +1,474 @@ // -*- C++ -*- // // LesHouchesEventHandler.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_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), 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 &) = delete; }; } // 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/LesHouchesFileReader.cc b/LesHouches/LesHouchesFileReader.cc --- a/LesHouches/LesHouchesFileReader.cc +++ b/LesHouches/LesHouchesFileReader.cc @@ -1,942 +1,942 @@ // -*- C++ -*- // // LesHouchesFileReader.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the LesHouchesFileReader class. // #include "LesHouchesFileReader.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Utilities/Throw.h" #include "ThePEG/PDT/DecayMode.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include #include using namespace ThePEG; LesHouchesFileReader:: LesHouchesFileReader(const LesHouchesFileReader & x) : LesHouchesReader(x), neve(x.neve), ieve(0), LHFVersion(x.LHFVersion), outsideBlock(x.outsideBlock), headerBlock(x.headerBlock), initComments(x.initComments), initAttributes(x.initAttributes), eventComments(x.eventComments), eventAttributes(x.eventAttributes), theFileName(x.theFileName), theQNumbers(x.theQNumbers), theIncludeFxFxTags(x.theIncludeFxFxTags), theIncludeCentral(x.theIncludeCentral), theDecayer(x.theDecayer) {} LesHouchesFileReader::~LesHouchesFileReader() {} IBPtr LesHouchesFileReader::clone() const { return new_ptr(*this); } IBPtr LesHouchesFileReader::fullclone() const { return new_ptr(*this); } bool LesHouchesFileReader::preInitialize() const { return true; } void LesHouchesFileReader::doinit() { LesHouchesReader::doinit(); //cout << "theDecayer->fullName() = " << theDecayer->fullName() << endl; //if(theDecayer) { // cout << "DECAYER RETURNS TRUE" << endl; // } // are we using QNUMBERS if(!theQNumbers) return; // parse the header block and create // any new particles needed in QNUMBERS blocks string block = headerBlock; string line = ""; bool readingSLHA = false; int (*pf)(int) = tolower; unsigned int newNumber(0); do { line = StringUtils::car(block,"\r\n"); block = StringUtils::cdr(block,"\r\n"); if(line[0]=='#') continue; // are we reading the SLHA block if(readingSLHA) { // reached the end of slha block ? if(line.find(" split = StringUtils::split(line,"#"); // check for a qnumbers block transform(split[0].begin(), split[0].end(), split[0].begin(), pf); // if not contine if(split[0].find("block qnumbers")==string::npos) continue; // get name from comment string name; if(split.size()>=2) { name = StringUtils::stripws(split[1]); } else { ++newNumber; ostringstream tname; tname << "NP" << newNumber; name = tname.str(); } // extract the PDG code split = StringUtils::split(split[0]," "); istringstream is(split[2]); long PDGCode(0); is >> PDGCode; // get the charge, spin, colour and whether an antiparticle int charge(0),spin(0),colour(0),anti(0); for(unsigned int ix=0;ix<4;++ix) { line = StringUtils::car(block,"\r\n"); block = StringUtils::cdr(block,"\r\n"); int dummy[2]; istringstream is(line); is >> dummy[0] >> dummy[1]; switch (dummy[0]) { case 1: charge = dummy[1]; break; case 2: spin = dummy[1]; break; case 3: colour = dummy[1]; break; case 4: anti = dummy[1]; break; default: assert(false); } } // check if particles already exist PDPair newParticle; newParticle.first = getParticleData(PDGCode); if(newParticle.first) Throw() << "Particle with PDG code " << PDGCode << " whose creation was requested in a QNUMBERS Block" << " already exists. Retaining the original particle" << Exception::warning; if(anti) { newParticle.second = getParticleData(-PDGCode); if(newParticle.second) Throw() << "Anti-particle with PDG code " << -PDGCode << " whose creation was requested in a QNUMBERS Block" << " already exists. Retaining the original particle" << Exception::warning; if(( newParticle.first && !newParticle.second ) || ( newParticle.second && !newParticle.first ) ) Throw() << "Either particle or anti-particle with PDG code " << PDGCode << " whose creation was requested in a QNUMBERS Block" << " already exists, but not both the particle and antiparticle. " << " Something dodgy here stopping" << Exception::runerror; } // already exists continue if(newParticle.first) continue; // create the particles // particle with no anti particle if( anti == 0 ) { // construct the name if(name=="") { ostringstream temp; temp << PDGCode; name = temp.str(); } // create the ParticleData object newParticle.first = ParticleData::Create(PDGCode,name); } // particle anti-particle pair else { // construct the names string nameAnti; if(name=="") { ostringstream temp; temp << PDGCode; name = temp.str(); ostringstream temp2; temp << -PDGCode; nameAnti = temp2.str(); } else { nameAnti=name; for(string::iterator it=nameAnti.begin();it!=nameAnti.end();++it) { if(*it=='+') nameAnti.replace(it,it+1,"-"); else if(*it=='-') nameAnti.replace(it,it+1,"+"); } if(nameAnti==name) nameAnti += "bar"; } // create the ParticleData objects newParticle = ParticleData::Create(PDGCode,name,nameAnti); } // set the particle properties if(colour==1) colour = 0; newParticle.first->iColour(PDT::Colour(colour)); newParticle.first->iSpin (PDT::Spin (spin )); newParticle.first->iCharge(PDT::Charge(charge)); // register it generator()->preinitRegister(newParticle.first, "/Herwig/Particles/"+newParticle.first->PDGName()); // set the antiparticle properties if(newParticle.second) { if(colour==3||colour==6) colour *= -1; charge = -charge; newParticle.second->iColour(PDT::Colour(colour)); newParticle.second->iSpin (PDT::Spin (spin )); newParticle.second->iCharge(PDT::Charge(charge)); // register it generator()->preinitRegister(newParticle.second, "/Herwig/Particles/"+newParticle.second->PDGName()); } } // start of SLHA block ? else if(line.find("> id >> mass; // skip resetting masses on SM particles // as it can cause problems later on in event generation if(abs(id)<=6 || (abs(id)>=11 && abs(id)<=16) || abs(id)==23 || abs(id)==24) { // Throw() << "Standard model mass for PID " // << id // << " will not be changed." // << Exception::warning; block = StringUtils::cdr(block,"\r\n"); line = StringUtils::car(block,"\r\n"); continue; } // magnitude of mass for susy models mass = abs(mass); // set the mass tPDPtr particle = getParticleData(id); if(!particle) throw SetupException() << "LesHouchesFileReader::doinit() - Particle with PDG code not" << id << " not found." << Exception::runerror; const InterfaceBase * ifb = BaseRepository::FindInterface(particle, "NominalMass"); ostringstream os; os << mass; ifb->exec(*particle, "set", os.str()); // read the next line block = StringUtils::cdr(block,"\r\n"); line = StringUtils::car(block,"\r\n"); }; } // found a decay block else if(line.find("decay") == 0) { // get PGD code and width istringstream iss(line); string dummy; long parent(0); Energy width(ZERO); iss >> dummy >> parent >> iunit(width, GeV); // get the ParticleData object PDPtr inpart = getParticleData(parent); if(!inpart) { throw SetupException() << "LesHouchesFileReader::doinit() - A ParticleData object with the PDG code " << parent << " does not exist. " << Exception::runerror; return; } if ( abs(inpart->id()) == 6 || abs(inpart->id()) == 15 || abs(inpart->id()) == 23 || abs(inpart->id()) == 24 || abs(inpart->id()) == 25 ) { Throw() << "\n" "************************************************************************\n" "* Your LHE file changes the width of " << inpart->PDGName() << ".\n" "* This can cause serious problems in the event generation!\n" "************************************************************************\n" "\n" << Exception::warning; } else if (inpart->width() > ZERO && width <= ZERO) { Throw() << "\n" "************************************************************************\n" "* Your LHE file zeroes the non-zero width of " << inpart->PDGName() << ".\n" "* If " << inpart->PDGName() << " is a decaying SM particle,\n" "* this can cause serious problems in the event generation!\n" "************************************************************************\n" "\n" << Exception::warning; } // set the width inpart->width(width); if( width > ZERO ) { inpart->cTau(hbarc/width); inpart->widthCut(5.*width); inpart->stable(false); } // construct prefix for DecayModes string prefix(inpart->name() + "->"), tag(prefix),line(""); unsigned int nmode(0); // read any decay modes line = StringUtils::car(block,"\r\n"); while(line[0] != 'D' && line[0] != 'B' && line[0] != 'd' && line[0] != 'b' && line[0] != '<' && line != "") { // skip comments if(line[0] == '#') { block = StringUtils::cdr(block,"\r\n"); line = StringUtils::car(block,"\r\n"); continue; } // read decay mode and construct the tag istringstream is(line); double brat(0.); unsigned int nda(0),npr(0); is >> brat >> nda; while( true ) { long t; is >> t; if( is.fail() ) break; if( t == abs(parent) ) throw SetupException() << "An error occurred while read a decay of the " << inpart->PDGName() << ". One of its products has the same PDG code " << "as the parent particle in LesHouchesFileReader::doinit()." << " Please check the Les Houches file.\n" << Exception::runerror; tcPDPtr p = getParticleData(t); if( !p ) throw SetupException() << "LesHouchesFileReader::doinit() -" << " An unknown PDG code has been encounterd " << "while reading a decay mode. ID: " << t << Exception::runerror; ++npr; tag += p->name() + ","; } if( npr != nda ) throw SetupException() << "LesHouchesFileReader::doinit() - While reading a decay of the " << inpart->PDGName() << " from an SLHA file, an inconsistency " << "between the number of decay products and the value in " << "the 'NDA' column was found. Please check if the spectrum " << "file is correct.\n" << Exception::warning; // create the DecayMode if( npr > 1 ) { if( nmode==0 ) { generator()->preinitInterface(inpart, "VariableRatio" , "set","false"); if(inpart->massGenerator()) { ok = false; Throw() << inpart->PDGName() << " already has a MassGenerator set" << " this is incompatible with using QNUMBERS " << "Use\n" << "set " << inpart->fullName() << ":Mass_generator NULL\n" << "to fix this." << Exception::warning; } if(inpart->widthGenerator()) { ok = false; Throw() << inpart->PDGName() << " already has a WidthGenerator set" << " this is incompatible with using QNUMBERS " << "Use\n" << "set " << inpart->fullName() << ":Width_generator NULL\n" << "to fix this." << Exception::warning; } unsigned int ntemp=0; for(DecaySet::const_iterator dit = inpart->decayModes().begin(); dit != inpart->decayModes().end(); ++dit ) { if((**dit).on()) ++ntemp; } if(ntemp!=0) { ok = false; Throw() << inpart->PDGName() << " already has DecayModes" << " this is incompatible with using QNUMBERS " << "Use\n" << "do " << inpart->fullName() << ":SelectDecayModes none\n" << " to fix this." << Exception::warning; } } inpart->stable(false); tag.replace(tag.size() - 1, 1, ";"); DMPtr dm = generator()->findDecayMode(tag); if(!theDecayer) Throw() << "LesHouchesFileReader::doinit() Decayer must be set using the " << "LesHouchesFileReader:Decayer" << " must be set to allow the creation of new" << " decay modes." << Exception::runerror; if(!dm) { dm = generator()->preinitCreateDecayMode(tag); if(!dm) Throw() << "LesHouchesFileReader::doinit() - Needed to create " << "new decaymode but one could not be created for the tag " << tag << Exception::warning; } generator()->preinitInterface(dm, "Decayer", "set", theDecayer->fullName()); ostringstream br; br << setprecision(13) << brat; generator()->preinitInterface(dm, "BranchingRatio", "set", br.str()); generator()->preinitInterface(dm, "Active", "set", "Yes"); if(dm->CC()) { generator()->preinitInterface(dm->CC(), "BranchingRatio", "set", br.str()); generator()->preinitInterface(dm->CC(), "Active", "set", "Yes"); } ++nmode; } tag=prefix; // read the next line block = StringUtils::cdr(block,"\r\n"); line = StringUtils::car(block,"\r\n"); }; if(nmode>0) { inpart->update(); if(inpart->CC()) inpart->CC()->update(); } } } // start of SLHA block ? else if(line.find("() << "The file associated with '" << name() << "' does not contain a " << "proper formatted Les Houches event file. The events may not be " << "properly sampled." << Exception::warning; } //vector LesHouchesFileReader::optWeightNamesFunc() { return optionalWeightsNames; } vector LesHouchesFileReader::optWeightsNamesFunc() { return optionalWeightsNames; } void LesHouchesFileReader::open() { if ( filename().empty() ) throw LesHouchesFileError() << "No Les Houches file name. " << "Use 'set " << name() << ":FileName'." << Exception::runerror; cfile.open(filename()); if ( !cfile ) throw LesHouchesFileError() << "The LesHouchesFileReader '" << name() << "' could not open the " << "event file called '" << theFileName << "'." << Exception::runerror; cfile.readline(); if ( !cfile.find(" attributes = StringUtils::xmlAttributes("LesHouchesEvents", cfile.getline()); LHFVersion = attributes["version"]; if ( LHFVersion.empty() ) return; bool readingHeader = false; bool readingInit = false; headerBlock = ""; // char (cwgtinfo_weights_info[250][15]); string hs; // int cwgtinfo_nn(0); // Loop over all lines until we hit the tag. bool readingInitWeights = false, readingInitWeights_sc = false; string weightinfo; while ( cfile.readline() ) { // found the init block for multiple weights if(cfile.find("> sub; if(ws==1) { string str_arrow = ">"; erase_substr(sub, str_arrow); scalename = sub; break; } ++ws; } while (isc); /* now get the relevant information * e.g. scales or PDF sets used */ string startDEL = "'>"; //starting delimiter string stopDEL = ""; //end delimiter int firstLim = hs.find(startDEL); //find start of delimiter if(firstLim == -1) { startDEL = ">"; firstLim = hs.find(startDEL); } // unsigned lastLim = hs.find(stopDEL); //find end of delimitr string scinfo = hs.substr(firstLim); //define the information for the scale erase_substr(scinfo,stopDEL); erase_substr(scinfo,startDEL); scinfo = StringUtils::stripws(scinfo); /* fill in the map * indicating the information to be appended to each scale * i.e. scinfo for each scalname */ scalemap[scalename] = scinfo.c_str(); string str_id = "id="; string str_prime = "'"; erase_substr(scalename, str_id); erase_substr(scalename, str_prime); optionalWeightsNames.push_back(scalename); } } if ( cfile.find("") ) { //cout << "found init block" << endl; // We have hit the init block, so we should expect to find the // standard information in the following. But first check for // attributes. initAttributes = StringUtils::xmlAttributes("init", cfile.getline()); readingInit = true; cfile.readline(); if ( !( cfile >> heprup.IDBMUP.first >> heprup.IDBMUP.second >> heprup.EBMUP.first >> heprup.EBMUP.second >> heprup.PDFGUP.first >> heprup.PDFGUP.second >> heprup.PDFSUP.first >> heprup.PDFSUP.second >> heprup.IDWTUP >> heprup.NPRUP ) ) { heprup.NPRUP = -42; LHFVersion = ""; return; } heprup.resize(); for ( int i = 0; i < heprup.NPRUP; ++i ) { cfile.readline(); if ( !( cfile >> heprup.XSECUP[i] >> heprup.XERRUP[i] >> heprup.XMAXUP[i] >> heprup.LPRUP[i] ) ) { heprup.NPRUP = -42; LHFVersion = ""; return; } } } if ( cfile.find("> sub; if(we==2) { npLO = atoi(sub.c_str()); } if(we==5) { npNLO = atoi(sub.c_str()); } ++we; } while (ievat); optionalnpLO = npLO; optionalnpNLO = npNLO; std::stringstream npstringstream; npstringstream << "np " << npLO << " " << npNLO; std::string npstrings = npstringstream.str(); /* the FxFx merging information * becomes part of the optionalWeights, labelled -999 * for future reference */ if(theIncludeFxFxTags) optionalWeights[npstrings.c_str()] = -999; if ( !cfile.readline() ) return false; // The first line determines how many subsequent particle lines we // have. if ( !( cfile >> hepeup.NUP >> hepeup.IDPRUP >> hepeup.XWGTUP >> hepeup.SCALUP >> hepeup.AQEDUP >> hepeup.AQCDUP ) ) return false; hepeup.resize(); // Read all particle lines. for ( int i = 0; i < hepeup.NUP; ++i ) { if ( !cfile.readline() ) return false; if ( !( cfile >> hepeup.IDUP[i] >> hepeup.ISTUP[i] >> hepeup.MOTHUP[i].first >> hepeup.MOTHUP[i].second >> hepeup.ICOLUP[i].first >> hepeup.ICOLUP[i].second >> hepeup.PUP[i][0] >> hepeup.PUP[i][1] >> hepeup.PUP[i][2] >> hepeup.PUP[i][3] >> hepeup.PUP[i][4] >> hepeup.VTIMUP[i] >> hepeup.SPINUP[i] ) ) return false; //print momenta for debugging // cout << hepeup.PUP[i][0] << " " << hepeup.PUP[i][1] << " " << hepeup.PUP[i][2] << " " << hepeup.PUP[i][3] << " " << hepeup.PUP[i][4] << endl; if(std::isnan(hepeup.PUP[i][0])||std::isnan(hepeup.PUP[i][1])|| std::isnan(hepeup.PUP[i][2])||std::isnan(hepeup.PUP[i][3])|| std::isnan(hepeup.PUP[i][4])) throw Exception() << "nan's as momenta in Les Houches file " << Exception::eventerror; if(hepeup.MOTHUP[i].first -1==i || hepeup.MOTHUP[i].second-1==i) { throw Exception() << "Particle has itself as a mother in Les Houches " << "file, this is not allowed\n" << Exception::eventerror; } } // Now read any additional comments and named weights. // read until the end of rwgt is found bool readingWeights = false, readingaMCFast = false, readingMG5ClusInfo = false; while ( cfile.readline() && !cfile.find("
")) { if(cfile.find("> sub; if(wi==1) { string str_arrow = ">" ; erase_substr(sub, str_arrow); weightName = sub; } if(wi==2) weightValue = atof(sub.c_str()); ++wi; } while (iss); // store the optional weights found in the temporary map optionalWeightsTemp[weightName] = weightValue; } /* reading of aMCFast weights */ if(readingaMCFast) { std::stringstream amcfstringstream; amcfstringstream << "aMCFast " << cfile.getline(); std::string amcfstrings = amcfstringstream.str(); string str_newline = "\n"; erase_substr(amcfstrings,str_newline); optionalWeights[amcfstrings.c_str()] = -111; //for the aMCFast we give them a weight -111 for future identification } /* read additional MG5 Clustering information * used in LO merging */ if(readingMG5ClusInfo) { string hs = cfile.getline(); string startDEL = ""; //end delimiter unsigned firstLim = hs.find(startDEL); //find start of delimiter // unsigned lastLim = hs.find(stopDEL); //find end of delimitr string mg5clusinfo = hs.substr(firstLim); //define the information for the scale erase_substr(mg5clusinfo,stopDEL); erase_substr(mg5clusinfo,startDEL); string str_arrow = ">"; erase_substr(mg5clusinfo,str_arrow); string str_quotation = "\""; erase_substr(mg5clusinfo,str_quotation); optionalWeights[mg5clusinfo.c_str()] = -222; //for the mg5 scale info weights we give them a weight -222 for future identification } //store MG5 clustering information if(cfile.find("::const_iterator it=optionalWeightsTemp.begin(); it!=optionalWeightsTemp.end(); ++it){ //to avoid issues with inconsistencies of defining the weight ids, remove "" and '' string id_1 = it->first; erase_substr(id_1, str_quote); erase_substr(id_1, str_doublequote); for (map::const_iterator it2=scalemap.begin(); it2!=scalemap.end(); ++it2){ //find the scale id in the scale information and add this information string id_2 = it2->first; erase_substr(id_2, str_quote); erase_substr(id_2, str_doublequote); if(id_1==id_2) { string info = it2->second; string str_newline = "\n"; erase_substr(info, str_newline); //set the optional weights optionalWeights[info] = it->second; } } } /* additionally, we set the "central" scale * this is actually the default event weight */ string central = "central"; if (theIncludeCentral) optionalWeights[central] = hepeup.XWGTUP; if ( !cfile ) return false; return true; } void LesHouchesFileReader::close() { cfile.close(); } void LesHouchesFileReader::persistentOutput(PersistentOStream & os) const { os << neve << LHFVersion << outsideBlock << headerBlock << initComments << initAttributes << eventComments << eventAttributes << theFileName << theQNumbers << theIncludeFxFxTags << theIncludeCentral << theDecayer ; } void LesHouchesFileReader::persistentInput(PersistentIStream & is, int) { is >> neve >> LHFVersion >> outsideBlock >> headerBlock >> initComments >> initAttributes >> eventComments >> eventAttributes >> theFileName >> theQNumbers >> theIncludeFxFxTags >> theIncludeCentral >> theDecayer; ieve = 0; } ClassDescription LesHouchesFileReader::initLesHouchesFileReader; // Definition of the static class description member. void LesHouchesFileReader::Init() { static ClassDocumentation documentation ("ThePEG::LesHouchesFileReader is an base class to be used for objects " "which reads event files from matrix element generators. This class is " "able to read plain event files conforming to the Les Houches Event File " "accord."); static Parameter interfaceFileName ("FileName", "The name of a file containing events conforming to the Les Houches " "protocol to be read into ThePEG. A file name ending in " ".gz will be read from a pipe which uses " "zcat. If a file name ends in | the " "preceeding string is interpreted as a command, the output of which " "will be read through a pipe.", &LesHouchesFileReader::theFileName, "", false, false); interfaceFileName.fileType(); interfaceFileName.rank(11); static Switch interfaceQNumbers ("QNumbers", "Whether or not to read search for and read a QNUMBERS" " block in the header of the file.", &LesHouchesFileReader::theQNumbers, false, false, false); static SwitchOption interfaceQNumbersYes (interfaceQNumbers, "Yes", "Use QNUMBERS", true); static SwitchOption interfaceQNumbersNo (interfaceQNumbers, "No", "Don't use QNUMBERS", false); static Switch interfaceIncludeFxFxTags ("IncludeFxFxTags", "Include FxFx tags", &LesHouchesFileReader::theIncludeFxFxTags, false, true, false); static SwitchOption interfaceIncludeFxFxTagsYes (interfaceIncludeFxFxTags, "Yes", "Use the FxFx tags", true); static SwitchOption interfaceIncludeFxFxTagsNo (interfaceIncludeFxFxTags, "No", "Don't use the FxFx tags", false); static Switch interfaceIncludeCentral ("IncludeCentral", "Include definition of central weight", &LesHouchesFileReader::theIncludeCentral, false, true, false); static SwitchOption interfaceIncludeCentralYes (interfaceIncludeCentral, "Yes", "include definition of central weight", true); static SwitchOption interfaceIncludeCentralNo (interfaceIncludeCentral, "No", "Don't include definition of central weight", false); static Reference interfaceDecayer ("Decayer", "Decayer to use for any decays read from the QNUMBERS Blocks", &LesHouchesFileReader::theDecayer, false, false, true, true, false); } void LesHouchesFileReader::erase_substr(std::string& subject, const std::string& search) { size_t pos = 0; while((pos = subject.find(search, pos)) != std::string::npos) { subject.erase( pos, search.length() ); } } diff --git a/LesHouches/LesHouchesFileReader.h b/LesHouches/LesHouchesFileReader.h --- a/LesHouches/LesHouchesFileReader.h +++ b/LesHouches/LesHouchesFileReader.h @@ -1,335 +1,335 @@ // -*- C++ -*- // // LesHouchesFileReader.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_LesHouchesFileReader_H #define THEPEG_LesHouchesFileReader_H // This is the declaration of the LesHouchesFileReader class. #include "LesHouchesReader.h" #include "LesHouchesFileReader.fh" #include "ThePEG/PDT/Decayer.h" #include "ThePEG/Utilities/CFileLineReader.h" #include #include namespace ThePEG { /** * LesHouchesFileReader is an base class to be used for objects which * reads event files from matrix element generators. It inherits from * LesHouchesReader and extends it by defining a file handle to be * read from, which is opened and closed by the open() and close() * functions. Note that the file handle is a standard C filehandle and * not a C++ stream. This is because there is no standard way in C++ * to connect a pipe to a stream for reading eg. gzipped files. This * class is able to read plain event files conforming to the Les * Houches Event File accord. * * @see \ref LesHouchesFileReaderInterfaces "Th1e interfaces" * defined for LesHouchesFileReader. * @see Event * @see LesHouchesReader */ class LesHouchesFileReader: public LesHouchesReader { public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ LesHouchesFileReader() : neve(0), ieve(0), theQNumbers(false), theIncludeFxFxTags(false), theIncludeCentral(false) {} /** * Copy-constructor. Note that a file which is opened in the object * copied from will have to be reopened in this. */ LesHouchesFileReader(const LesHouchesFileReader &); /** * Destructor. */ virtual ~LesHouchesFileReader(); //@} public: /** @name Virtual functions specified by the LesHouchesReader base class. */ //@{ /** * Initialize. This function is called by the LesHouchesEventHandler * to which this object is assigned. */ virtual void initialize(LesHouchesEventHandler & eh); /** * Open a file with events. Derived classes should overwrite it and * first calling it before reading in the run information into the * corresponding protected variables. */ virtual void open(); /** * Close the file from which events have been read. */ virtual void close(); /** * Read the next event from the file or stream into the * corresponding protected variables. Return false if there is no * more events or if this was not a LHF event file. */ virtual bool doReadEvent(); //@} /** * Return the name of the file from where to read events. */ string filename() const { return theFileName; } /** * Return the optional weights information string ("Names") */ virtual vector optWeightsNamesFunc(); 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(); /** * Erases all occurences of a substring from a string */ void erase_substr(std::string& subject, const std::string& search); 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; //@} /** @name Standard (and non-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(); /** * Return true if this object needs to be initialized before all * other objects because it needs to extract PDFs from the event file. */ virtual bool preInitialize() const; //@ protected: /** * The wrapper around the C FILE stream from which to read */ CFileLineReader cfile; protected: /** * The number of events in this file. */ long neve; /** * The current event number. */ long ieve; /** * If the file is a standard Les Houches formatted file (LHF) this * is its version number. If empty, this is not a Les Houches * formatted file */ string LHFVersion; /** * If LHF. All lines (since the last open() or readEvent()) outside * the header, init and event tags. */ string outsideBlock; /** * If LHF. All lines from the header block. */ string headerBlock; /** * If LHF. Additional comments found in the init block. */ string initComments; /** * If LHF. Map of attributes (name-value pairs) found in the init * tag. */ map initAttributes; /** * If LHF. Additional comments found with the last read event. */ string eventComments; /** * If LHF. Map of attributes (name-value pairs) found in the last * event tag. */ map eventAttributes; private: /** * The name of the file from where to read events. */ string theFileName; /** * Whether or not to search for QNUMBERS stuff */ bool theQNumbers; /** * Include/Read FxFx tags */ bool theIncludeFxFxTags; /** * Include central weight (for backup use) */ bool theIncludeCentral; /** * Decayer for any decay modes read from the file */ DecayerPtr theDecayer; /** * Further information on the weights */ map scalemap; /** * Temporary holder for optional weights */ map optionalWeightsTemp; private: /** * Describe an abstract base class with persistent data. */ static ClassDescription initLesHouchesFileReader; /** * Private and non-existent assignment operator. */ LesHouchesFileReader & operator=(const LesHouchesFileReader &) = delete; public: /** @cond EXCEPTIONCLASSES */ /** Exception class used by LesHouchesFileReader if reading the file * fails. */ class LesHouchesFileError: public Exception {}; /** @endcond */ }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** * This template specialization informs ThePEG about the * base class of LesHouchesFileReader. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the base class of LesHouchesFileReader. */ typedef LesHouchesReader NthBase; }; /** * This template specialization informs ThePEG about the name of the * LesHouchesFileReader class and the shared object where it is * defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** * Return the class name. */ static string className() { return "ThePEG::LesHouchesFileReader"; } /** * Return the name of the shared library to be loaded to get access * to the LesHouchesFileReader class and every other class it uses * (except the base class). */ static string library() { return "LesHouches.so"; } }; /** @endcond */ } #endif /* THEPEG_LesHouchesFileReader_H */ diff --git a/LesHouches/LesHouchesReader.cc b/LesHouches/LesHouchesReader.cc --- a/LesHouches/LesHouchesReader.cc +++ b/LesHouches/LesHouchesReader.cc @@ -1,1592 +1,1592 @@ // -*- C++ -*- // // LesHouchesReader.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the 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; // 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); 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/LesHouchesReader.h b/LesHouches/LesHouchesReader.h --- a/LesHouches/LesHouchesReader.h +++ b/LesHouches/LesHouchesReader.h @@ -1,1003 +1,1003 @@ // -*- C++ -*- // // LesHouchesReader.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_LesHouchesReader_H #define THEPEG_LesHouchesReader_H // This is the declaration of the LesHouchesReader class. #include "LesHouches.h" #include "ThePEG/Handlers/HandlerBase.h" #include "ThePEG/Utilities/ObjectIndexer.h" #include "ThePEG/Utilities/Exception.h" #include "ThePEG/Utilities/XSecStat.h" #include "ThePEG/PDF/PartonBinInstance.h" #include "ThePEG/PDF/PartonBin.fh" #include "ThePEG/MatrixElement/ReweightBase.h" #include "LesHouchesEventHandler.fh" #include "LesHouchesReader.fh" #include "ThePEG/Utilities/CFile.h" #include #include namespace ThePEG { /** * LesHouchesReader is an abstract base class to be used for objects * which reads event files or streams from matrix element * generators. Derived classes must at least implement the open() and * doReadEvent() methods to read in information about the whole run into * the HEPRUP variable and next event into the HEPEUP variable * respectively. Also the close() function to close the file or stream * read must be implemented. Although these functions are named as if * we are reading from event files, they could just as well implement * the actual generation of events. * * After filling the HEPRUP and HEPEUP variables, which are protected * and easily accesible from the sub-class, this base class will then * be responsible for transforming this data to the ThePEG Event * record in the getEvent() method. LesHouchesReaders can * only be used inside LesHouchesEventHandler objects. * * In the initialization the virtual open() and scan() functions are * called. Here the derived class must provide the information about * the processes in the variables corresponding to the HEPRUP common * block. Note that the IDWTUP is required to be +/- 1, and sub * classes are required to change the information accordingly to * ensure the correct corss section sampling. Note also that the * controlling LesHouchesEventHandler may choose to generate weighted * events even if IDWTUP is 1. * * Note that the information given per process in e.g. the XSECUP and * XMAXUP vectors is not used by the LesHouchesEventHandler and by * default the LesHouchesReader is not assumed to be able to actively * choose between the sub-processes. Instead, the * LesHouchesEventHandler can handle several LesHouchesReader objects * and choose between them. However, a sub-class of LesHouchesReader * may set the flag isActive, in which case it is assumed to be able * to select between its sub-processes itself. * * The LesHouchesReader may be assigned a number ReweightBase objects * which either completely reweights the events produced (in the * reweights vector), or only biases the selection without influencing * the cross section (in the preweights vector). Note that it is the * responsibility of a sub-class to call the reweight() function and * multiply the weight according to its return value (typically done * in the readEvent() function). * * @see \ref LesHouchesReaderInterfaces "The interfaces" * defined for LesHouchesReader. * @see Event * @see LesHouchesEventHandler */ class LesHouchesReader: public HandlerBase, public LastXCombInfo<> { /** * LesHouchesEventHandler should have access to our private parts. */ friend class LesHouchesEventHandler; /** * Map for accumulating statistics of cross sections per process * number. */ typedef map StatMap; /** * Map of XComb objects describing the incoming partons indexed by * the corresponding PartonBin pair. */ typedef map XCombMap; /** * A vector of pointers to ReweightBase objects. */ typedef vector ReweightVector; public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. If the optional argument is true, the reader * is assumed to be able to produce events on demand for a given * process. */ LesHouchesReader(bool active = false); /** * Copy-constructor. */ LesHouchesReader(const LesHouchesReader &); /** * Destructor. */ virtual ~LesHouchesReader(); //@} public: /** @name Main virtual fuctions to be overridden in * sub-classes. They are named as if we are reading from event * files, but could equally well implement the actual generation of * events. */ //@{ /** * Open a file or stream with events and read in the run information * into the heprup variable. */ virtual void open() = 0; /** * Read the next event from the file or stream into the * corresponding protected variables. Return false if there is no * more events. */ virtual bool doReadEvent() = 0; /** * Close the file or stream from which events have been read. */ virtual void close() = 0; /** * return the weight names */ virtual vector optWeightsNamesFunc() = 0; /** * vector with the optional weights names */ vector optionalWeightsNames; //@} /** @name Other important function which may be overridden in * sub-classes which wants to bypass the basic HEPRUP or HEPEUP * variables or otherwise facilitate the conversion to ThePEG * objects. */ //@{ /** * Initialize. This function is called by the LesHouchesEventHandler * to which this object is assigned. */ virtual void initialize(LesHouchesEventHandler & eh); /** * Calls readEvent() or uncacheEvent() to read information into the * LesHouches common block variables. This function is called by the * LesHouchesEventHandler if this reader has been selectod to * produce an event. * * @return the weight asociated with this event. If negative weights * are allowed it should be between -1 and 1, otherwise between 0 * and 1. If outside these limits the previously estimated maximum * is violated. Note that the estimated maximum then should be * updated from the outside. */ virtual double getEvent(); /** * Calls doReadEvent() and performs pre-defined reweightings. A * sub-class overrides this function it must make sure that the * corresponding reweightings are done. */ virtual bool readEvent(); /** * Skip \a n events. Used by LesHouchesEventHandler to make sure * that a file is scanned an even number of times in case the events * are not ramdomly distributed in the file. */ virtual void skip(long n); /** * Get an XComb object. Converts the information in the Les Houches * common block variables to an XComb object describing the sub * process. This is the way information is conveyed from the reader * to the controlling LesHouchesEventHandler. */ tXCombPtr getXComb(); /** * Get a SubProcess object corresponding to the information in the * Les Houches common block variables. */ tSubProPtr getSubProcess(); /** * Scan the file or stream to obtain information about cross section * weights and particles etc. This function should fill the * variables corresponding to the /HEPRUP/ common block. The * function returns the number of events scanned. */ virtual long scan(); /** * Take the information corresponding to the HEPRUP common block and * initialize the statistics for this reader. */ virtual void initStat(); /** * Reweights the current event using the reweights and preweights * vectors. It is the responsibility of the sub-class to call this * function after the HEPEUP information has been retrieved. */ double reweight(); /** * Converts the information in the Les Houches common block * variables into a Particle objects. */ virtual void fillEvent(); /** * Removes the particles created in the last generated event, * preparing to produce a new one. */ void reset(); /** * Possibility for subclasses to recover from non-conformant * settings of XMAXUP when an event file has been scanned with \a * neve events. Should set weightScale so that the average XMAXUP * times weightScale gives the cross section for a process. (This is * needed for MadEvent). */ virtual void setWeightScale(long neve); //@} /** @name Access information about the current event. */ //@{ /** * Return the size of this event in bytes. To be used for the cache * file. \a npart is the number of particles. If \a npart is 0, the * number is taken from NUP. */ static size_t eventSize(int N) { return (N + 1)*sizeof(int) + // IDPRUP, ISTUP (7*N + 4)*sizeof(double) + // XWGTUP, SCALUP, AQEDUP, AQCDUP, PUP, // VTIMUP, SPINUP N*sizeof(long) + // IDUP 2*N*sizeof(pair) + // MOTHUP, ICOLUP sizeof(pair) + // XPDWUP. 2*sizeof(double); // lastweight and preweight } /** * The current event weight given by XWGTUP times possible * reweighting. Note that this is not necessarily the same as what * is returned by getEvent(), which is scaled with the maximum * weight. */ double eventWeight() const { return hepeup.XWGTUP*lastweight; } /** * Return the optional named weights associated to the current event. */ const map& optionalEventWeights() const { return optionalWeights; } /** * Return the optional npLO and npNLO */ const int& optionalEventnpLO() const { return optionalnpLO; } const int& optionalEventnpNLO() const { return optionalnpNLO; } /** * The pair of PartonBinInstance objects describing the current * incoming partons in the event. */ const PBIPair & partonBinInstances() const { return thePartonBinInstances; } /** * Return the instances of the beam particles for the current event. */ const PPair & beams() const { return theBeams; } /** * Return the instances of the incoming particles to the sub process * for the current event. */ const PPair & incoming() const { return theIncoming; } /** * Return the instances of the outgoing particles from the sub process * for the current event. */ const PVector & outgoing() const { return theOutgoing; } /** * Return the instances of the intermediate particles in the sub * process for the current event. */ const PVector & intermediates() const { return theIntermediates; } /** * 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. */ int maxMultCKKW() const { return theMaxMultCKKW; } /** * 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. */ int minMultCKKW() const { return theMinMultCKKW; } //@} /** @name Other inlined access functions. */ //@{ /** * The number of events found in this reader. If less than zero the * number of events are unlimited. */ long NEvents() const { return theNEvents; } /** * The number of events produced so far. Is reset to zero if an * event file is reopened. */ long currentPosition() const { return position; } /** * The maximum number of events to scan to collect information about * processes and cross sections. If less than 0, all events will be * scanned. */ long maxScan() const { return theMaxScan; } /** * Return true if this reader is active. */ bool active() const { return isActive; } /** * True if negative weights may be produced. */ bool negativeWeights() const { return heprup.IDWTUP < 0; } /** * The collected cross section statistics for this reader. */ const XSecStat & xSecStats() const { return stats; } /** * Collected statistics about the individual processes. */ const StatMap & processStats() const { return statmap; } /** * Select the current event. It will later be rejected with a * probability given by \a weight. */ void select(double weight) { stats.select(weight); statmap[hepeup.IDPRUP].select(weight); } /** * Accept the current event assuming it was previously selcted. */ void accept() { stats.accept(); statmap[hepeup.IDPRUP].accept(); } /** * Reject the current event assuming it was previously accepted. */ void reject(double w) { stats.reject(w); statmap[hepeup.IDPRUP].reject(w); } /** * Increase the overestimated cross section for this reader. */ virtual void increaseMaxXSec(CrossSection maxxsec); /** * The PartonExtractor object used to construct remnants. */ tPExtrPtr partonExtractor() const { return thePartonExtractor; } /** * Return a possibly null pointer to a CascadeHandler to be used for * CKKW-reweighting. */ tCascHdlPtr CKKWHandler() const { return theCKKW; } /** * The pairs of PartonBin objects describing the partons which can * be extracted by the PartonExtractor object. */ const PartonPairVec & partonBins() const { return thePartonBins; } /** * The map of XComb objects indexed by the corresponding PartonBin * pair. */ const XCombMap & xCombs() const { return theXCombs; } /** * The Cuts object to be used for this reader. */ const Cuts & cuts() const { return *theCuts; } //@} protected: /** @name Functions for manipulating cache files. */ //@{ /** * Name of file used to cache the events form the reader in a * fast-readable form. If empty, no cache file will be generated. */ string cacheFileName() const { return theCacheFileName; } /** * Determines whether to apply cuts to events converting them to * ThePEG format. */ bool cutEarly() const { return doCutEarly; } /** * File stream for the cache. */ CFile cacheFile() const { return theCacheFile;} /** * Open the cache file for reading. */ void openReadCacheFile(); /** * Open the cache file for writing. */ void openWriteCacheFile(); /** * Close the cache file; */ void closeCacheFile(); /** * Write the current event to the cache file. */ void cacheEvent() const; /** * Read an event from the cache file. Return false if something went wrong. */ bool uncacheEvent(); /** * Reopen a reader. If we have reached the end of an event file, * reopen it and issue a warning if we have used up a large fraction * of it. */ void reopen(); /** * Helper function to write a variable to a memory location */ template static char * mwrite(char * pos, const T & t, size_t n = 1) { std::memcpy(pos, &t, n*sizeof(T)); return pos + n*sizeof(T); } /** * Helper function to read a variable from a memory location */ template static const char * mread(const char * pos, T & t, size_t n = 1) { std::memcpy(&t, pos, n*sizeof(T)); return pos + n*sizeof(T); } //@} /** @name Auxilliary virtual methods which may be verridden by sub-classes. */ //@{ /** * Check the existence of a pair of PartonBin objects corresponding * to the current event. * * @return false if no pair of suitable PartonBin objects was found. */ virtual bool checkPartonBin(); /** * Create instances of all particles in the event and store them * in particleIndex. */ virtual void createParticles(); /** * Using the already created particles create a pair of * PartonBinInstance objects corresponding to the incoming * partons. Return the corresponding PartonBin objects. */ virtual tcPBPair createPartonBinInstances(); /** * Create instances of the incoming beams in the event and store * them in particleIndex. If no beam particles are included in the * event they are created from the run info. */ virtual void createBeams(); /** * Go through the mother indices and connect up the Particles. */ virtual void connectMothers(); //@} 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(); protected: /** @name Set functions for some variables not in the Les Houches accord. */ //@{ /** * The number of events in this reader. If less than zero the number * of events is unlimited. */ void NEvents(long x) { theNEvents = x; } /** * The map of XComb objects indexed by the corresponding PartonBin * pair. */ XCombMap & xCombs() { return theXCombs; } //@} /** @name Standard (and non-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() { close(); HandlerBase::dofinish(); } /** * Return true if this object needs to be initialized before all * other objects because it needs to extract PDFs from the event file. */ virtual bool preInitialize() const; /** * Called from doinit() to extract PDFs from the event file and add * the corresponding objects to the current EventGenerator. */ virtual void initPDFs(); //@} protected: /** * The HEPRUP common block. */ HEPRUP heprup; /** * The HEPEUP common block. */ HEPEUP hepeup; /** * The ParticleData objects corresponding to the incoming particles. */ tcPDPair inData; /** * The PDFBase objects which has been used for the beam particle * when generating the events being read. Specified in the interface * or derived from PDFGUP and PDFSUP. */ pair inPDF; /** * The PDFBase object to be used in the subsequent generation. */ pair outPDF; /** * The PartonExtractor object used to construct remnants. */ PExtrPtr thePartonExtractor; /** * A pointer to a CascadeHandler to be used for CKKW-reweighting. */ tCascHdlPtr theCKKW; /** * The pairs of PartonBin objects describing the partons which can * be extracted by the PartonExtractor object. */ PartonPairVec thePartonBins; /** * The map of XComb objects indexed by the corresponding PartonBin * pair. */ XCombMap theXCombs; /** * The Cuts object to be used for this reader. */ CutsPtr theCuts; /** * The number of events in this reader. If less than zero the number * of events is unlimited. */ long theNEvents; /** * The number of events produced by this reader so far. Is reset * every time an event file is reopened. */ long position; /** * The number of times this reader has been reopened. */ int reopened; /** * The maximum number of events to scan to collect information about * processes and cross sections. If less than 0, all events will be * scanned. */ long theMaxScan; /** * Flag to tell whether we are in the process of scanning. */ bool scanning; /** * True if this is an active reader. */ bool isActive; /** * Name of file used to cache the events form the reader in a * fast-readable form. If empty, no cache file will be generated. */ string theCacheFileName; /** * Determines whether to apply cuts to events before converting them * to ThePEG format. */ bool doCutEarly; /** * Collect statistics for this reader. */ XSecStat stats; /** * Collect statistics for each individual process. */ StatMap statmap; /** * The pair of PartonBinInstance objects describing the current * incoming partons in the event. */ PBIPair thePartonBinInstances; /** * Association between ColourLines and colour indices in the current * translation. */ ObjectIndexer colourIndex; /** * Association between Particles and indices in the current * translation. */ ObjectIndexer particleIndex; /** * The instances of the beam particles for the current event. */ PPair theBeams; /** * The instances of the incoming particles to the sub process for * the current event. */ PPair theIncoming; /** * The instances of the outgoing particles from the sub process for * the current event. */ PVector theOutgoing; /** * The instances of the intermediate particles in the sub process for * the current event. */ PVector theIntermediates; /** * File stream for the cache. */ CFile theCacheFile; /** * The reweight objects modifying the weights of this reader. */ ReweightVector reweights; /** * The preweight objects modifying the weights of this reader. */ ReweightVector preweights; /** * The factor with which this reader was last pre-weighted. */ double preweight; /** * Should the event be reweighted by PDFs used by the PartonExtractor? */ bool reweightPDF; /** * Should PDFBase objects be constructed from the information in the * event file in the initialization? */ bool doInitPDFs; /** * 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. */ int theMaxMultCKKW; /** * 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. */ int theMinMultCKKW; /** * The weight multiplying the last read event due to PDF * reweighting, CKKW reweighting or assigned reweight and preweight * objects. */ double lastweight; /** * The optional weights associated to the last read events. */ map optionalWeights; /** * If the maximum cross section of this reader has been increased * with increaseMaxXSec(), this is the total factor with which it * has been increased. */ double maxFactor; /** * npLO for LesHouches merging */ int optionalnpLO; /** * npNLO for LesHouches merging */ int optionalnpNLO; /** * The (reweighted) XWGTUP value should be scaled with this cross * section when compared to the overestimated cross section. */ CrossSection weightScale; /** * Individual scales for different sub-processes if reweighted. */ vector xSecWeights; /** * Individual maximum weights for individual (possibly reweighted) * processes. */ map maxWeights; /** * Is set to true when getEvent() is called from skip(int). */ bool skipping; /** * Option for the treatment of the momenta supplied */ unsigned int theMomentumTreatment; /** * Set to true if warnings about possible weight incompatibilities * should be issued. */ bool useWeightWarnings; /** * Option to allow reopening of the file */ bool theReOpenAllowed; /** * Use the spin information */ bool theIncludeSpin; private: /** Access function for the interface. */ void setBeamA(long id); /** Access function for the interface. */ long getBeamA() const; /** Access function for the interface. */ void setBeamB(long id); /** Access function for the interface. */ long getBeamB() const; /** Access function for the interface. */ void setEBeamA(Energy e); /** Access function for the interface. */ Energy getEBeamA() const; /** Access function for the interface. */ void setEBeamB(Energy e); /** Access function for the interface. */ Energy getEBeamB() const; /** Access function for the interface. */ void setPDFA(PDFPtr); /** Access function for the interface. */ PDFPtr getPDFA() const; /** Access function for the interface. */ void setPDFB(PDFPtr); /** Access function for the interface. */ PDFPtr getPDFB() const; private: /** * Describe an abstract base class with persistent data. */ static AbstractClassDescription initLesHouchesReader; /** * Private and non-existent assignment operator. */ LesHouchesReader & operator=(const LesHouchesReader &) = delete; public: /** @cond EXCEPTIONCLASSES */ /** Exception class used by LesHouchesReader in case inconsistencies * are encountered. */ class LesHouchesInconsistencyError: public Exception {}; /** Exception class used by LesHouchesReader in case more events than available are requested. */ class LesHouchesReopenWarning: public Exception {}; /** Exception class used by LesHouchesReader in case reopening an event file fails. */ class LesHouchesReopenError: public Exception {}; /** Exception class used by LesHouchesReader in case there is information missing in the initialization phase. */ class LesHouchesInitError: public InitException {}; /** @endcond */ }; /// Stream output for HEPEUP ostream & operator<<(ostream & os, const HEPEUP & h); } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** * This template specialization informs ThePEG about the * base class of LesHouchesReader. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the base class of LesHouchesReader. */ typedef HandlerBase NthBase; }; /** * This template specialization informs ThePEG about the name of the * LesHouchesReader class and the shared object where it is * defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** * Return the class name. */ static string className() { return "ThePEG::LesHouchesReader"; } /** * Return the name of the shared library to be loaded to get access * to the LesHouchesReader class and every other class it uses * (except the base class). */ static string library() { return "LesHouches.so"; } }; /** @endcond */ } #endif /* THEPEG_LesHouchesReader_H */ diff --git a/LesHouches/MadGraphOneCut.cc b/LesHouches/MadGraphOneCut.cc --- a/LesHouches/MadGraphOneCut.cc +++ b/LesHouches/MadGraphOneCut.cc @@ -1,170 +1,170 @@ // -*- C++ -*- // // MadGraphOneCut.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MadGraphOneCut class. // #include "MadGraphOneCut.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/Utilities/EnumIO.h" #include "ThePEG/Cuts/Cuts.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG; IBPtr MadGraphOneCut::clone() const { return new_ptr(*this); } IBPtr MadGraphOneCut::fullclone() const { return new_ptr(*this); } Energy MadGraphOneCut::minKT(tcPDPtr p) const { if ( cutType != Cut::PT || !checkType(p) ) return ZERO; return theCut*GeV; } double MadGraphOneCut::minEta(tcPDPtr p) const { if ( cutType != Cut::ETA || !checkType(p) ) return -Constants::MaxRapidity; return -theCut; } double MadGraphOneCut::maxEta(tcPDPtr p) const { if ( cutType != Cut::ETA || !checkType(p) ) return Constants::MaxRapidity; return theCut; } Energy MadGraphOneCut::minMaxKT(tcPDPtr p) const { if ( cutType != Cut::XPT || !checkType(p) ) return ZERO; return theCut*GeV; } bool MadGraphOneCut::passCuts(tcCutsPtr parent, tcPDPtr ptype, LorentzMomentum p) const { if ( !checkType(ptype) ) return true; if ( cutType == Cut::PT ) return p.perp() > theCut*GeV; if ( cutType == Cut::ETA ) { double y = p.rapidity() + parent->Y() + parent->currentYHat(); return abs(p.mt()*sinh(y)) < p.perp()*sinh(theCut); } return true; } bool MadGraphOneCut::checkType(tcPDPtr p) const { switch ( abs(p->id()) ) { case ParticleID::d: case ParticleID::u: case ParticleID::s: case ParticleID::c: case ParticleID::g: return particleType == P::JET; case ParticleID::b: return particleType == P::JET || particleType == P::BOT; case ParticleID::gamma: return particleType == P::PHO; case ParticleID::eminus: case ParticleID::nu_e: case ParticleID::muminus: case ParticleID::nu_mu: case ParticleID::tauminus: case ParticleID::nu_tau: return particleType == P::LEP; default: return false; } } void MadGraphOneCut::persistentOutput(PersistentOStream & os) const { os << oenum(cutType) << oenum(particleType) << theCut; } void MadGraphOneCut::persistentInput(PersistentIStream & is, int) { is >> ienum(cutType) >> ienum(particleType) >> theCut; } ClassDescription MadGraphOneCut::initMadGraphOneCut; // Definition of the static class description member. void MadGraphOneCut::Init() { static ClassDocumentation documentation ("Objects of the MadGraphOneCut class can be created automatically by " "the MadGraphReader class when scanning event files for information " "about cuts. It is also possible to create objects by hand and use " "it as any other OneCutBase object."); static Switch interfaceCutType ("CutType", "The type of cut this object will do.", &MadGraphOneCut::cutType, Cut::PT, true, false); static SwitchOption interfaceCutTypePT (interfaceCutType, "MinPT", "The minimum transverse momentum of a particle.", Cut::PT); static SwitchOption interfaceCutTypeMaxEta (interfaceCutType, "MaxEta", "The maximum (absolute value of) pseudo-rapidity of a particle.", Cut::ETA); static SwitchOption interfaceCutTypeMinMaxPT (interfaceCutType, "MinMaxPT", "The minimum transverse momentum of the particle with largest " "transverse momentum.", Cut::XPT); static Switch interfaceParticleType ("ParticleType", "The types of particles this cut is applied to.", &MadGraphOneCut::particleType, P::JET, true, false); static SwitchOption interfaceParticleTypeJets (interfaceParticleType, "Jets", "The cut applies only to coloured particles (jets).", P::JET); static SwitchOption interfaceParticleTypeLeptons (interfaceParticleType, "Leptons", "The cut applies only to leptons.", P::LEP); static SwitchOption interfaceParticleTypePhotons (interfaceParticleType, "Photons", "The cut applies only to photons.", P::PHO); static SwitchOption interfaceParticleTypeBottom (interfaceParticleType, "Bottom", "The cut applies only to bottom quarks.", P::BOT); static Parameter interfaceCut ("Cut", "The value of the cut to be applied (in units of GeV in case of a " "transverse momentum).", &MadGraphOneCut::theCut, 0.0, 0.0, 0, true, false, Interface::lowerlim); interfaceCut.rank(10); interfaceCutType.rank(9); interfaceParticleType.rank(8); interfaceCut.setHasDefault(false); interfaceCutType.setHasDefault(false); interfaceParticleType.setHasDefault(false); } diff --git a/LesHouches/MadGraphOneCut.h b/LesHouches/MadGraphOneCut.h --- a/LesHouches/MadGraphOneCut.h +++ b/LesHouches/MadGraphOneCut.h @@ -1,227 +1,227 @@ // -*- C++ -*- // // MadGraphOneCut.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_MadGraphOneCut_H #define THEPEG_MadGraphOneCut_H // // This is the declaration of the MadGraphOneCut class. // #include "ThePEG/Cuts/OneCutBase.h" namespace ThePEG { /** * Objects of the MadGraphOneCut class can be created automatically by * the MadGraphReader class when scanning event files for information * about cuts. It is also possible to create objects by hand and use * it as any other OneCutBase object. * * @see \ref MadGraphOneCutInterfaces "The interfaces" * defined for MadGraphOneCut. */ class MadGraphOneCut: public OneCutBase { public: /** * Enumerate the different kinds of cuts made by MadGraph. */ enum class Cut { PT, /**< The minimum transverse momentum of a particle. */ ETA, /**< The maximum (absolute value of) pseudo-rapidity of a particle. */ XPT /**< The minimum transverse momentum of the particle with largest transverse momentum. */ }; /** * Enumerate the types of particles the cut is made on. */ enum class P { JET, /**< The cut applies only to coloured particles. */ LEP, /**< The cut applies only to leptons. */ PHO, /**< The cut applies only to photons. */ BOT /**< The cut applies only to bottom quarks. */ }; public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ MadGraphOneCut() : cutType(Cut::PT), particleType(P::JET), theCut(0.0) {} /** * The constructor used by the MadGraphReader. * @param t is the type of the cut. * @param p is the type of particles the cut is applied to. * @param c is the value of the cut (in units of GeV where applicable). */ MadGraphOneCut(Cut t, P p, double c) : cutType(t), particleType(p), theCut(c) {} //@} public: /** @name Virtual functions mandated by the base class. */ //@{ /** * Return the minimum allowed value of the transverse momentum of an * outgoing parton. */ virtual Energy minKT(tcPDPtr p) const; /** * Return the minimum allowed pseudo-rapidity of an outgoing parton * of the given type. The pseudo-rapidity is measured in the lab * system. */ virtual double minEta(tcPDPtr p) const; /** * Return the maximum allowed pseudo-rapidity of an outgoing parton * of the given type. The pseudo-rapidity is measured in the lab * system. */ virtual double maxEta(tcPDPtr p) const; /** * Return the minimum allowed value of the transverse momentum of * the outgoing parton with the lagrest transverse momentum. This * version simply returns minKt(). */ virtual Energy minMaxKT(tcPDPtr p) const; /** * Return true if a particle with type \a ptype and momentum \a p * passes the cuts. The \a parent contains information about the * kinematics of the hard sub-process. */ virtual bool passCuts(tcCutsPtr parent, tcPDPtr ptype, LorentzMomentum p) const; //@} protected: /** * Returns true if cut should be applied to a particle of type \a p. */ bool checkType(tcPDPtr p) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * The type of this cut. */ Cut cutType; /** * The type of particles this cut applies to. */ P particleType; /** * The value of the cut to be applied. */ double theCut; private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initMadGraphOneCut; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MadGraphOneCut & operator=(const MadGraphOneCut &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of MadGraphOneCut. */ template <> struct BaseClassTrait { /** Typedef of the first base class of MadGraphOneCut. */ typedef OneCutBase NthBase; }; /** This template specialization informs ThePEG about the name of * the MadGraphOneCut 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::MadGraphOneCut"; } /** Return the name(s) of the shared library (or libraries) be loaded to get * access to the MadGraphOneCut class and any other class on which it depends * (except the base class). */ static string library() { return "MadGraphReader.so"; } }; /** @endcond */ } #endif /* THEPEG_MadGraphOneCut_H */ diff --git a/LesHouches/MadGraphReader.cc b/LesHouches/MadGraphReader.cc --- a/LesHouches/MadGraphReader.cc +++ b/LesHouches/MadGraphReader.cc @@ -1,618 +1,618 @@ // -*- C++ -*- // // MadGraphReader.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MadGraphReader class. // #include "MadGraphReader.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Command.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/PDF/PDFBase.h" #include "ThePEG/LesHouches/MadGraphOneCut.h" #include "ThePEG/LesHouches/MadGraphTwoCut.h" #include "ThePEG/Cuts/Cuts.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/Throw.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG; using std::fgetc; using std::fgets; IBPtr MadGraphReader::clone() const { return new_ptr(*this); } IBPtr MadGraphReader::fullclone() const { return new_ptr(*this); } void MadGraphReader::open() { LesHouchesFileReader::open(); heprup.IDWTUP = 1; static const int ntags = 33; static const char * cuttags[] = {"ptj", "ptb", "pta", "ptl", "etaj", "etab", "etaa", "etal", "drjj", "drbb", "draa", "drll", "drbj", "draj", "drjl", "drab", "drbl", "dral", "mmjj", "mmbb", "mmaa", "mmll", "mmbj", "mmaj", "mmjl", "mmab", "mmbl", "mmal", "xptj", "xptb", "xpta", "xptl", "xetamin"}; ieve = neve = 0; // If we are reading a LHF formatted file things are rather easy. if ( LHFVersion.size() ) { // extract the number of events neve = numberOfEvents(outsideBlock); string madheader = outsideBlock; if ( neve == 0 ) { neve = numberOfEvents(headerBlock); madheader = headerBlock; } if ( neve == 0 ) Throw() << "The MadGraphReader '" << name() << "' expected the LHE file '" << filename() << "' to include MadGraph-specific header information, " << "but did not find any. The events may not be properly sampled." << Exception::warning; if ( neve != 0 ) NEvents(neve); // MadEvent has gives wrong values for XMAXUP and XWGTUP, they // need to be multiplied by the number of events to be LHEF // compliant. weightScale = neve*picobarn; // Scan information about cuts. for ( int itag = 0; itag < ntags; ++itag ) { string::size_type pos = madheader.find(string("= ") + cuttags[itag]); if ( pos != string::npos ) { string::size_type beg = max(madheader.rfind("#", pos) + 1, madheader.rfind("\n", pos) + 1); string value = madheader.substr(beg, pos - beg); for ( string::size_type i = 0; i < value.length(); ++i ) if ( value[i] == 'd' || value[i] == 'D' ) value[i] = 'e'; cuts[cuttags[itag]] = std::strtod(value.c_str(), NULL); } } return; } double xsec = -1.0; double maxw = -1.0; double ebeam1 = -1.0; double ebeam2 = -1.0; int lpp1 = 0; int lpp2 = 0; string pdftag; // First scan banner to extract some information // (LesHoushesFileReader::open has already read in the first line). cfile.resetline(); do { if ( !cfile ) break; if ( cfile.getc() != '#' ) { int test; cfile >> test; if ( cfile ) { cfile.resetline(); break; } } if ( cfile.find("# Number of Events") ) { cfile.skip(':'); cfile >> neve; } else if ( cfile.find("Integrated weight") ) { cfile.skip(':'); cfile >> xsec; } else if ( cfile.find("Max wgt") ) { cfile.skip(':'); cfile >> maxw; } else if ( cfile.find("ebeam(1)") || cfile.find("ebeam1") ) { cfile >> ebeam1; } else if ( cfile.find("ebeam(2)") || cfile.find("ebeam2") ) { cfile >> ebeam2; } else if ( cfile.find("lpp(1)") || cfile.find("lpp1") ) { cfile >> lpp1; } else if ( cfile.find("lpp(2)") || cfile.find("lpp2") ) { cfile >> lpp2; } else if ( cfile.find("PDF set") ) { cfile.skip('\''); cfile >> pdftag; pdftag = pdftag.substr(0, 7); } else if ( cfile.find("Number of Events Written ") ) { cfile.skip(':'); cfile >> neve; maxw = xsec/double(neve); } else { for ( int itag = 0; itag < ntags; ++itag ) { if ( cfile.find(string("= ") + cuttags[itag]) ) { cfile >> cuts[cuttags[itag]]; if ( cfile.getc() == 'd' ) { long x = 0; cfile >> x; cuts[cuttags[itag]] *= pow(10.0, double(x)); } break; } } } } while ( cfile.readline() ); // Return here if no comment block was found. if ( neve <= 0 ) return; // Convert the extracted information to LesHouches format. heprup.NPRUP = 1; heprup.LPRUP.push_back(0); heprup.XSECUP.push_back(xsec); heprup.XERRUP.push_back(0.0); heprup.XMAXUP.push_back(maxw); NEvents(neve); // MadEvent has gives wrong values for XMAXUP and XWGTUP, they // need to be multiplied by the number of events to be LHEF // compliant. weightScale = neve*picobarn; if ( !heprup.IDBMUP.first ) { if ( lpp1 == 1 ) heprup.IDBMUP.first = ParticleID::pplus; else if ( lpp1 == -1 ) heprup.IDBMUP.first = ParticleID::pbarminus; } if ( !heprup.IDBMUP.second ) { if ( lpp2 == 1 ) heprup.IDBMUP.second = ParticleID::pplus; else if ( lpp2 == -1 ) heprup.IDBMUP.second = ParticleID::pbarminus; } if ( heprup.EBMUP.first <= 0.0 ) heprup.EBMUP.first = ebeam1; if ( heprup.EBMUP.second <= 0.0 ) heprup.EBMUP.second = ebeam2; if ( !cfile ) throw LesHouchesFileError() << "An error occurred while '" << name() << "' was reading the file '" << filename() << "'." << Exception::runerror; if ( heprup.PDFSUP.first != 0 || heprup.PDFSUP.first != 0 ) return; // If we have an old MadGraph we have to try to figure out which PDF // codes to use. heprup.PDFGUP.first = heprup.PDFGUP.second = 0; if ( pdftag == "mrs02nl" ) heprup.PDFSUP.first = heprup.PDFSUP.second = 20200; else if ( pdftag == "mrs02nn" ) heprup.PDFSUP.first = heprup.PDFSUP.second = 20270; else if ( pdftag == "cteq6_m" ) heprup.PDFSUP.first = heprup.PDFSUP.second = 10050; else if ( pdftag == "cteq6_l" ) heprup.PDFSUP.first = heprup.PDFSUP.second = 10041; else if ( pdftag == "cteq6l1" ) heprup.PDFSUP.first = heprup.PDFSUP.second = 10042; else if ( pdftag == "cteq5_m" ) heprup.PDFSUP.first = heprup.PDFSUP.second = 19050; else if ( pdftag == "cteq5_d" ) heprup.PDFSUP.first = heprup.PDFSUP.second = 19060; else if ( pdftag == "cteq5_l" ) heprup.PDFSUP.first = heprup.PDFSUP.second = 19070; else if ( pdftag == "cteq4_m" ) heprup.PDFSUP.first = heprup.PDFSUP.second = 19150; else if ( pdftag == "cteq4_d" ) heprup.PDFSUP.first = heprup.PDFSUP.second = 19160; else if ( pdftag == "cteq4_l" ) heprup.PDFSUP.first = heprup.PDFSUP.second = 19170; } long MadGraphReader::scan() { bool fixscale = !NEvents(); long neve = LesHouchesFileReader::scan(); if ( fixscale ) { // MadEvent has gives wrong values for XMAXUP and XWGTUP, they // need to be multiplied by the number of events to be LHEF // compliant. weightScale = neve*picobarn; if ( heprup.NPRUP > 1 ) weightScale /= heprup.NPRUP; } return neve; } bool MadGraphReader::doReadEvent() { if ( LesHouchesFileReader::doReadEvent() ) return true; if ( !cfile ) return false; hepeup.NUP = 0; ieve = 0; long evno = 0; hepeup.XWGTUP = 0.0; double scale = 0.0; double aEM = 0.0; double aS = 0.0; bool oldformat = false; cfile >> hepeup.NUP >> evno >> hepeup.XWGTUP >> scale >> aEM >> aS; if ( !cfile ) { hepeup.IDPRUP = evno; hepeup.SCALUP = fixedScale/GeV; hepeup.AQEDUP = fixedAEM; hepeup.AQCDUP = fixedAS; ++ieve; oldformat = true; } else { hepeup.IDPRUP = 0; ieve = evno; hepeup.SCALUP = scale; hepeup.AQEDUP = aEM; hepeup.AQCDUP = aS; } hepeup.IDUP.resize(hepeup.NUP); if ( !cfile.readline() ) return false; for ( int i = 0; i < hepeup.NUP; ++i ) cfile >> hepeup.IDUP[i]; hepeup.MOTHUP.resize(hepeup.NUP); if ( !cfile.readline() ) return false; for ( int i = 0; i < hepeup.NUP; ++i ) cfile >> hepeup.MOTHUP[i].first; if ( !cfile.readline() ) return false; for ( int i = 0; i < hepeup.NUP; ++i ) cfile >> hepeup.MOTHUP[i].second; hepeup.ICOLUP.resize(hepeup.NUP); if ( !cfile.readline() ) return false; for ( int i = 0; i < hepeup.NUP; ++i ) cfile >> hepeup.ICOLUP[i].first; if ( !cfile.readline() ) return false; for ( int i = 0; i < hepeup.NUP; ++i ) cfile >> hepeup.ICOLUP[i].second; // Try to figure out if the colour lines are reversed bool colrev = false; for ( int i = 0; i < hepeup.NUP; ++i ) if ( abs(hepeup.IDUP[i]) < 10 && hepeup.IDUP[i] < 0 && !hepeup.ICOLUP[i].second ) colrev = true; if ( colrev ) for ( int i = 0; i < hepeup.NUP; ++i ) swap(hepeup.ICOLUP[i].first, hepeup.ICOLUP[i].second); if ( oldformat ) { hepeup.ISTUP.assign(hepeup.NUP, 1); hepeup.ISTUP[0] = hepeup.ISTUP[1] = -1; hepeup.SPINUP.assign(hepeup.NUP, 9); } else { hepeup.ISTUP.resize(hepeup.NUP); if ( !cfile.readline() ) return false; for ( int i = 0; i < hepeup.NUP; ++i ) cfile >> hepeup.ISTUP[i]; hepeup.SPINUP.resize(hepeup.NUP, 9); if ( !cfile.readline() ) return false; for ( int i = 0; i < hepeup.NUP; ++i ) cfile >> hepeup.SPINUP[i]; } hepeup.PUP.resize(hepeup.NUP); for ( int i = 0; i < hepeup.NUP; ++i ) { if ( !cfile.readline() ) return false; int dummy = 0; cfile >> dummy >> hepeup.PUP[i][3] >> hepeup.PUP[i][0] >> hepeup.PUP[i][1] >> hepeup.PUP[i][2]; hepeup.PUP[i][4] = sqrt(max(sqr(hepeup.PUP[i][3]) - sqr(hepeup.PUP[i][0]) - sqr(hepeup.PUP[i][1]) - sqr(hepeup.PUP[i][2]), 0.0)); } if ( !cfile ) return false; // Set info not obtained from MadGraph. hepeup.VTIMUP = vector(hepeup.NUP, -1.0); // Deduce positions of incoming beams and corresponding partons. pair beampos(-1, -1); for ( int i = 0; i < hepeup.NUP; ++i ) { if ( hepeup.ISTUP[i] != -9 ) continue; if ( beampos.first < 0 ) beampos.first = i; else if ( beampos.second < 0 ) beampos.second = i; } pair partpos(-1, -1); for ( int i = hepeup.NUP - 1; i >= 0; --i ) { if ( hepeup.ISTUP[i] != -1 ) continue; if ( hepeup.MOTHUP[i].first > 0 && hepeup.MOTHUP[i].first == beampos.first ) partpos.first = i; else if ( hepeup.MOTHUP[i].first > 0 && hepeup.MOTHUP[i].first == beampos.second ) partpos.second = i; else if ( partpos.second < 0 ) partpos.second = i; else if ( partpos.first < 0 ) partpos.first = i; } // We set these to -1 to let the base class do the work. hepeup.XPDWUP.first = -1.0; hepeup.XPDWUP.second = -1.0; cfile.readline(); // Return true even if last read failed. return true; } void MadGraphReader::persistentOutput(PersistentOStream & os) const { os << ounit(fixedScale, GeV) << fixedAEM << fixedAS << cuts << doInitCuts; } void MadGraphReader::persistentInput(PersistentIStream & is, int) { is >> iunit(fixedScale, GeV) >> fixedAEM >> fixedAS >> cuts >> doInitCuts; } bool MadGraphReader::preInitialize() const { if ( LesHouchesFileReader::preInitialize() ) return true; if ( doInitCuts && !theCuts ) return true; return false; } void MadGraphReader::doinit() { LesHouchesFileReader::doinit(); if ( doInitCuts && !theCuts ) { theCuts = initCuts(); if ( !theCuts ) Throw() << "MadGraphReader '" << name() << "' could not create cut objects in pre-initialization." << Exception::warning; } } void MadGraphReader::initPDFs() { LesHouchesFileReader::initPDFs(); } CutsPtr MadGraphReader::initCuts() { CutsPtr newCuts; open(); close(); if ( cuts.empty() ) return CutsPtr(); vector ones; vector twos; vector onames; vector tnames; for ( map::iterator i = cuts.begin(); i != cuts.end(); ++i ) { if ( i->second <= 0.0 ) continue; MadGraphOneCut::Cut t = MadGraphOneCut::Cut::PT; char p = 0; if ( i->first.substr(0, 2) == "pt" ) { t = MadGraphOneCut::Cut::PT; p = i->first[2]; } else if ( i->first.substr(0, 3) == "eta" ) { t = MadGraphOneCut::Cut::ETA; p = i->first[3]; } else if ( i->first.substr(0, 3) == "xpt" ) { t = MadGraphOneCut::Cut::XPT; p = i->first[3]; } if ( p ) { MadGraphOneCut::P pt = MadGraphOneCut::P::JET; switch ( p ) { case 'j': pt = MadGraphOneCut::P::JET; break; case 'b': pt = MadGraphOneCut::P::BOT; break; case 'a': pt = MadGraphOneCut::P::PHO; break; case 'l': pt = MadGraphOneCut::P::LEP; break; } ones.push_back(new_ptr(MadGraphOneCut(t, pt, i->second))); onames.push_back(i->first); continue; } if ( i->first.substr(0, 2) == "dr" || i->first.substr(0, 2) == "mm" ) { MadGraphTwoCut::Cut tt = MadGraphTwoCut::Cut::DELTAR; if ( i->first.substr(0, 2) == "mm" ) tt = MadGraphTwoCut::Cut::INVMASS; MadGraphTwoCut::PP pp = MadGraphTwoCut::PP::JETJET; if ( i->first.substr(2, 2) == "jj" ) pp = MadGraphTwoCut::PP::JETJET; else if ( i->first.substr(2, 2) == "bb" ) pp = MadGraphTwoCut::PP::BOTBOT; else if ( i->first.substr(2, 2) == "aa" ) pp = MadGraphTwoCut::PP::PHOPHO; else if ( i->first.substr(2, 2) == "ll" ) pp = MadGraphTwoCut::PP::LEPLEP; else if ( i->first.substr(2, 2) == "bj" ) pp = MadGraphTwoCut::PP::BOTJET; else if ( i->first.substr(2, 2) == "aj" ) pp = MadGraphTwoCut::PP::PHOJET; else if ( i->first.substr(2, 2) == "jl" ) pp = MadGraphTwoCut::PP::JETLEP; else if ( i->first.substr(2, 2) == "ab" ) pp = MadGraphTwoCut::PP::PHOBOT; else if ( i->first.substr(2, 2) == "bl" ) pp = MadGraphTwoCut::PP::BOTLEP; else if ( i->first.substr(2, 2) == "al" ) pp = MadGraphTwoCut::PP::PHOLEP; twos.push_back(new_ptr(MadGraphTwoCut(tt, pp, i->second))); tnames.push_back(i->first); } } if ( ones.empty() && twos.empty() ) return CutsPtr(); newCuts = new_ptr(Cuts()); generator()->preinitRegister(newCuts, fullName() + "/ExtractedCuts"); for ( int i = 0, N = ones.size(); i < N; ++i ) { generator()->preinitRegister(ones[i], fullName() + "/" + onames[i]); generator()->preinitInterface (newCuts, "OneCuts", 0, "insert", ones[i]->fullName()); // newCuts->add(tOneCutPtr(ones[i])); } for ( int i = 0, N = twos.size(); i < N; ++i ) { reporeg(twos[i], tnames[i]); generator()->preinitInterface (newCuts, "TwoCuts", 0, "insert", twos[i]->fullName()); // newCuts->add(tTwoCutPtr(twos[i])); } return newCuts; } string MadGraphReader::scanCuts(string) { if ( theCuts ) return "A Cuts object has already been assigned to this reader."; open(); close(); if ( cuts.empty() ) return "No information about cuts were found. " "Maybe the file was from an old version of MadGraph"; vector ones; vector twos; vector onames; vector tnames; for ( map::iterator i = cuts.begin(); i != cuts.end(); ++i ) { if ( i->second <= 0.0 ) continue; MadGraphOneCut::Cut t = MadGraphOneCut::Cut::PT; char p = 0; if ( i->first.substr(0, 2) == "pt" ) { t = MadGraphOneCut::Cut::PT; p = i->first[2]; } else if ( i->first.substr(0, 3) == "eta" ) { t = MadGraphOneCut::Cut::ETA; p = i->first[3]; } else if ( i->first.substr(0, 3) == "xpt" ) { t = MadGraphOneCut::Cut::XPT; p = i->first[3]; } if ( p ) { MadGraphOneCut::P pt = MadGraphOneCut::P::JET; switch ( p ) { case 'j': pt = MadGraphOneCut::P::JET; break; case 'b': pt = MadGraphOneCut::P::BOT; break; case 'a': pt = MadGraphOneCut::P::PHO; break; case 'l': pt = MadGraphOneCut::P::LEP; break; } ones.push_back(new_ptr(MadGraphOneCut(t, pt, i->second))); onames.push_back(i->first); continue; } if ( i->first.substr(0, 2) == "dr" || i->first.substr(0, 2) == "mm" ) { MadGraphTwoCut::Cut tt = MadGraphTwoCut::Cut::DELTAR; if ( i->first.substr(0, 2) == "mm" ) tt = MadGraphTwoCut::Cut::INVMASS; MadGraphTwoCut::PP pp = MadGraphTwoCut::PP::JETJET; if ( i->first.substr(2, 2) == "jj" ) pp = MadGraphTwoCut::PP::JETJET; else if ( i->first.substr(2, 2) == "bb" ) pp = MadGraphTwoCut::PP::BOTBOT; else if ( i->first.substr(2, 2) == "aa" ) pp = MadGraphTwoCut::PP::PHOPHO; else if ( i->first.substr(2, 2) == "ll" ) pp = MadGraphTwoCut::PP::LEPLEP; else if ( i->first.substr(2, 2) == "bj" ) pp = MadGraphTwoCut::PP::BOTJET; else if ( i->first.substr(2, 2) == "aj" ) pp = MadGraphTwoCut::PP::PHOJET; else if ( i->first.substr(2, 2) == "jl" ) pp = MadGraphTwoCut::PP::JETLEP; else if ( i->first.substr(2, 2) == "ab" ) pp = MadGraphTwoCut::PP::PHOBOT; else if ( i->first.substr(2, 2) == "bl" ) pp = MadGraphTwoCut::PP::BOTLEP; else if ( i->first.substr(2, 2) == "al" ) pp = MadGraphTwoCut::PP::PHOLEP; twos.push_back(new_ptr(MadGraphTwoCut(tt, pp, i->second))); tnames.push_back(i->first); } } if ( ones.empty() && twos.empty() ) return "No non-zero cuts found."; theCuts = new_ptr(Cuts()); reporeg(theCuts, "ExtractedCuts"); for ( int i = 0, N = ones.size(); i < N; ++i ) { reporeg(ones[i], onames[i]); theCuts->add(tOneCutPtr(ones[i])); } for ( int i = 0, N = twos.size(); i < N; ++i ) { reporeg(twos[i], tnames[i]); theCuts->add(tTwoCutPtr(twos[i])); } return ""; } ClassDescription MadGraphReader::initMadGraphReader; // Definition of the static class description member. void MadGraphReader::Init() { static ClassDocumentation documentation ("ThePEG::MadGraphReader is used together with the LesHouchesEventHandler " "to read event files generated with the MadGraph/MadEvent program.", "Events were read from event files generated " "with the MadGraph/MadEvent\\cite{ThePEG::MadGraph} program.", "\\bibitem{ThePEG::MadGraph} F. Maltoni and T. Stelzer, " "hep-ph/0208156;\\\\" "T. Stelzer and W.F. Long, \\textit{Comput.~Phys.~Commun.} " "\\textbf{81} (1994) 357-371."); static Parameter interfaceFixedScale ("FixedScale", "Old MadGraph files do not necessarily contain information about " "the factorization (or renormalization) scale. In this case this " "is used instead.", &MadGraphReader::fixedScale, GeV, 91.188*GeV, ZERO, 1000.0*GeV, true, false, true); interfaceFixedScale.setHasDefault(false); static Parameter interfaceFixedAlphaEM ("FixedAlphaEM", "Old MadGraph files do not necessarily contain information about " "the value of \\f$\\alpha_{EM}\\f$. In this case this is used instead.", &MadGraphReader::fixedAEM, 0.007546772, 0.0, 1.0, true, false, true); interfaceFixedAlphaEM.setHasDefault(false); static Parameter interfaceFixedAlphaS ("FixedAlphaS", "Old MadGraph files do not necessarily contain information about " "the value of \\f$\\alpha_S\\f$. In this case this is used instead.", &MadGraphReader::fixedAS, 0.12, 0.0, 1.0, true, false, true); interfaceFixedAlphaS.setHasDefault(false); static Command interfaceScanCuts ("ScanCuts", "If no LesHouchesReader::Cuts has been assigned, " "the event file is scanned for information about generation cuts. If cuts " "are found, the corresponding objects will be created in a sub-directory " "with the same name as this object and assigned as the " "LesHouchesReader::Cuts of this reader.", &MadGraphReader::scanCuts, true); static Switch interfaceInitCuts ("InitCuts", "If no cuts were specified for this reader, try to extract cut " "information from the MadGraph file and assign the relevant cut " "objects when the reader is initialized.", &MadGraphReader::doInitCuts, false, true, false); static SwitchOption interfaceInitCutsYes (interfaceInitCuts, "Yes", "Extract cuts during initialization.", true); static SwitchOption interfaceInitCutsNo (interfaceInitCuts, "No", "Do not extract cuts during initialization.", false); interfaceScanCuts.rank(10.5); interfaceInitCuts.rank(10.6); } long MadGraphReader::numberOfEvents(string block) { long output(0); // Check for number of events in the file. string::size_type pos = block.find("## Number of Events :"); if ( pos == string::npos ) pos = block.find("# Number of Events :"); if ( pos != string::npos ) { pos += 28; output = std::strtol(block.c_str() + pos, NULL, 0); } return output; } diff --git a/LesHouches/MadGraphReader.h b/LesHouches/MadGraphReader.h --- a/LesHouches/MadGraphReader.h +++ b/LesHouches/MadGraphReader.h @@ -1,257 +1,257 @@ // -*- C++ -*- // // MadGraphReader.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_MadGraphReader_H #define THEPEG_MadGraphReader_H // This is the declaration of the MadGraphReader class. #include "ThePEG/LesHouches/LesHouchesFileReader.h" namespace ThePEG { /** * MadGraphReader inherits from LesHouchesFileReader and is able to * read event files produced by the MadGraph/MadEvent program. * * @see \ref MadGraphReaderInterfaces "The interfaces" * defined for MadGraphReader. */ class MadGraphReader: public LesHouchesFileReader { public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ MadGraphReader() : fixedScale(91.188*GeV), fixedAEM(0.007546772), fixedAS(0.12), doInitCuts(false) {} //@} public: /** @name Virtual functions specified by the LesHouchesReader base class. */ //@{ /** * Open a file or stream with events and read in the run information * into the corresponding protected variables. */ virtual void open(); /** * Scan the file or stream to obtain information about cross section * weights and particles etc. This function should fill the * variables corresponding to the /HEPRUP/ common block. The * function returns the number of events scanned. This version calls * the base class function and the readjusts the values in HEPRUP to * cure some inconsistencies in the MadGraph files. */ virtual long scan(); /** * Read the next event form the file or stream into the * corresponding protected variables. Return false if there is no * more events. */ virtual bool doReadEvent(); //@} 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(); 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(); /** * Called from doinit() to extract cuts from the event file and add * the corresponding objects to the current EventGenerator. */ CutsPtr initCuts(); /** * Called from LesHouchesReader::doinit() to extract PDFs from the * event file and add the corresponding objects to the current * EventGenerator. */ virtual void initPDFs(); /** * Return true if this object needs to be initialized before all * other objects because it needs to extract cuts from the event file. */ virtual bool preInitialize() const; /** * Finalize this object. Called in the run phase just after a * run has ended. Used eg. to write out statistics. */ virtual void dofinish() { LesHouchesFileReader::dofinish(); if ( stats.accepted() > 0 ) useMe(); } //@} protected: /** * Interface function to scan a madgraph file and extract * information about used cuts. The corresponding cut objects are * created in the Repository and assigned to this reader. */ string scanCuts(string); /** * Function to extract the number of events from a string */ long numberOfEvents(string); protected: /** * Fixed scale. Old MadGraph files do not necessarily contain * information about the factorization (or renormalization) * scale. In this case this is used instead. */ Energy fixedScale; /** * Fixed \f$\alpha_{EM}\f$. Old MadGraph files do not necessarily * contain information about the value of \f$\alpha_{EM}\f$. In this * case this is used instead. */ double fixedAEM; /** * Fixed \f$\alpha_S\f$. Old MadGraph files do not necessarily * contain information about the value of \f$\alpha_S\f$. In this * case this is used instead. */ double fixedAS; /** * New MadGraph files contain suitable information about cuts used * in the generation. The non-zero ones are stored in this map. */ map cuts; /** * If true, cuts may be extracted from the event file during initialization. */ bool doInitCuts; public: /** * Exception class used to inform about inability to work with some * weighted event files. */ struct WeightedException: public Exception {}; private: /** * Describe a concrete class with persistent data. */ static ClassDescription initMadGraphReader; /** * Private and non-existent assignment operator. */ MadGraphReader & operator=(const MadGraphReader &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** * This template specialization informs ThePEG about the * base class of MadGraphReader. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the base class of MadGraphReader. */ typedef LesHouchesFileReader NthBase; }; /** * This template specialization informs ThePEG about the name of the * MadGraphReader class and the shared object where it is * defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return the class name. */ static string className() { return "ThePEG::MadGraphReader"; } /** Return the name of the shared library to be loaded to get * access to the MadGraphReader class and every other class it uses * (except the base class). */ static string library() { return "MadGraphReader.so"; } }; /** @endcond */ } #endif /* THEPEG_MadGraphReader_H */ diff --git a/LesHouches/MadGraphTwoCut.cc b/LesHouches/MadGraphTwoCut.cc --- a/LesHouches/MadGraphTwoCut.cc +++ b/LesHouches/MadGraphTwoCut.cc @@ -1,242 +1,242 @@ // -*- C++ -*- // // MadGraphTwoCut.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MadGraphTwoCut class. // #include "MadGraphTwoCut.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/Utilities/EnumIO.h" #include "ThePEG/Cuts/Cuts.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG; IBPtr MadGraphTwoCut::clone() const { return new_ptr(*this); } IBPtr MadGraphTwoCut::fullclone() const { return new_ptr(*this); } Energy2 MadGraphTwoCut::minSij(tcPDPtr pi, tcPDPtr pj) const { if ( !checkType(pi, pj) || cutType != Cut::INVMASS ) return ZERO; return sqr(theCut*GeV); } Energy2 MadGraphTwoCut::minTij(tcPDPtr, tcPDPtr) const { return ZERO; } double MadGraphTwoCut::minDeltaR(tcPDPtr pi, tcPDPtr pj) const { if ( !checkType(pi, pj) || cutType != Cut::DELTAR ) return 0.0; return theCut; } Energy MadGraphTwoCut::minKTClus(tcPDPtr, tcPDPtr) const { return ZERO; } double MadGraphTwoCut::minDurham(tcPDPtr, tcPDPtr) const { return 0.0; } bool MadGraphTwoCut::passCuts(tcCutsPtr, tcPDPtr pitype, tcPDPtr pjtype, LorentzMomentum pi, LorentzMomentum pj, bool inci, bool incj) const { if ( inci || incj || !checkType(pitype, pjtype) ) return true; if ( cutType == Cut::INVMASS ) return (pi + pj).m2() > sqr(theCut*GeV); if ( cutType == Cut::DELTAR ) { double deta2 = sqr(pi.eta() - pj.eta()); double dphi = abs(pi.phi() - pj.phi()); if ( dphi > Constants::pi ) dphi = 2.0*Constants::pi - dphi; return sqrt(deta2 + sqr(dphi)) > theCut; } return true; } MadGraphTwoCut::P MadGraphTwoCut::getType(tcPDPtr p) const { switch ( abs(p->id()) ) { case ParticleID::d: case ParticleID::u: case ParticleID::s: case ParticleID::c: case ParticleID::g: return P::JET; case ParticleID::b: return P::BOT; case ParticleID::gamma: return P::PHO; case ParticleID::eminus: case ParticleID::nu_e: case ParticleID::muminus: case ParticleID::nu_mu: case ParticleID::tauminus: case ParticleID::nu_tau: return P::LEP; default: return P::NOT; } } bool MadGraphTwoCut::checkType(tcPDPtr pi, tcPDPtr pj) const { switch ( pairType ) { case PP::JETJET: return getType(pi) == P::JET && getType(pj) == P::JET; case PP::LEPLEP: if ( getType(pi) != P::LEP || getType(pj) != P::LEP ) return false; if ( cutType == Cut::DELTAR ) return true; // Special treatment for Cut::INVMASS. if ( pi->id()*pj->id() >= 0 ) return false; // OK we have a lepton-anti-lepton pair. I it the same lepton if ( pi->id() == -pj->id() ) return true; // NO, well is it the same family? if ( max(abs(pi->id()), abs(pj->id()))%2 ) return false; return abs(pi->id() + pj->id()) == 1 ; case PP::PHOPHO: return getType(pi) == P::PHO && getType(pj) == P::PHO; case PP::BOTBOT: return getType(pi) == P::BOT && getType(pj) == P::BOT; case PP::BOTJET: return ( getType(pi) == P::BOT && getType(pj) == P::JET ) || ( getType(pi) == P::JET && getType(pj) == P::BOT ); case PP::PHOJET: return ( getType(pi) == P::PHO && getType(pj) == P::JET ) || ( getType(pi) == P::JET && getType(pj) == P::PHO ); case PP::JETLEP: return ( getType(pi) == P::LEP && getType(pj) == P::JET ) || ( getType(pi) == P::JET && getType(pj) == P::LEP ); case PP::PHOBOT: return ( getType(pi) == P::PHO && getType(pj) == P::BOT ) || ( getType(pi) == P::BOT && getType(pj) == P::PHO ); case PP::BOTLEP: return ( getType(pi) == P::BOT && getType(pj) == P::LEP ) || ( getType(pi) == P::LEP && getType(pj) == P::BOT ); case PP::PHOLEP: return ( getType(pi) == P::PHO && getType(pj) == P::LEP ) || ( getType(pi) == P::LEP && getType(pj) == P::PHO ); } return false; } void MadGraphTwoCut::persistentOutput(PersistentOStream & os) const { os << oenum(cutType) << oenum(pairType) << theCut; } void MadGraphTwoCut::persistentInput(PersistentIStream & is, int) { is >> ienum(cutType) >> ienum(pairType) >> theCut; } ClassDescription MadGraphTwoCut::initMadGraphTwoCut; // Definition of the static class description member. void MadGraphTwoCut::Init() { static ClassDocumentation documentation ("Objects of the MadGraphTwoCut class can be created automatically by " "the MadGraphReader class when scanning event files for information " "about cuts. It is also possible to create objects by hand and use " "it as any other MadGraphTwoCut object."); static Switch interfaceCutType ("CutType", "The kind of cut this object will do.", &MadGraphTwoCut::cutType, Cut::DELTAR, true, false); static SwitchOption interfaceCutTypeInvariantMass (interfaceCutType, "InvariantMass", "The minimum invariant mass of two particles.", Cut::INVMASS); static SwitchOption interfaceCutTypeDeltaR (interfaceCutType, "DeltaR", "The minimum pseudo-rapidity--azimuth-angle distance between two " "particles.", Cut::DELTAR); static Switch interfacePairType ("PairType", "The type of particle pairs this cut is applied to.", &MadGraphTwoCut::pairType, PP::JETJET, true, false); static SwitchOption interfacePairTypeJetJet (interfacePairType, "JetJet", "The cut applies only to pairs of coloured particles (jets).", PP::JETJET); static SwitchOption interfacePairTypeLeptonLepton (interfacePairType, "LeptonLepton", "The cut applies only to lepton pairs (in case of invariant mass, " "lepton--anti-lepton pairs of same flavour).", PP::LEPLEP); static SwitchOption interfacePairTypePhotonPhoton (interfacePairType, "PhotonPhoton", "The cut applies only to pairs photons.", PP::PHOPHO); static SwitchOption interfacePairTypeBottomPairs (interfacePairType, "BottomPairs", "The cut applies only to pairs of bottom quarks.", PP::BOTBOT); static SwitchOption interfacePairTypeJetBottom (interfacePairType, "JetBottom", "The cut applies only to bottom quarks paired with another coloured " "particle (jet).", PP::BOTJET); static SwitchOption interfacePairTypePhotonJet (interfacePairType, "PhotonJet", "The cut applies only to a photon paired with a coloured particle (jet).", PP::PHOJET); static SwitchOption interfacePairTypeJetLepton (interfacePairType, "JetLepton", "The cut applies only to a coloured particle (jet) paired with a lepton.", PP::JETLEP); static SwitchOption interfacePairTypePhotonBottom (interfacePairType, "PhotonBottom", "The cut applies only to a photon paired with a bottom quark.", PP::PHOBOT); static SwitchOption interfacePairTypeBottomLepton (interfacePairType, "BottomLepton", "The cut applies only to bottom quarks paired with a lepton.", PP::BOTLEP); static SwitchOption interfacePairTypePhotonLepton (interfacePairType, "PhotonLepton", "The cut applies only to a photon paired with a lepton.", PP::PHOLEP); static Parameter interfaceCut ("Cut", "The value of the cut to be applied (in units of GeV in case of " "minimum invariant mass).", &MadGraphTwoCut::theCut, 0.0, 0.0, 0, true, false, Interface::lowerlim); interfaceCut.rank(10); interfaceCutType.rank(9); interfacePairType.rank(8); interfaceCut.setHasDefault(false); interfaceCutType.setHasDefault(false); interfacePairType.setHasDefault(false); } diff --git a/LesHouches/MadGraphTwoCut.h b/LesHouches/MadGraphTwoCut.h --- a/LesHouches/MadGraphTwoCut.h +++ b/LesHouches/MadGraphTwoCut.h @@ -1,270 +1,270 @@ // -*- C++ -*- // // MadGraphTwoCut.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_MadGraphTwoCut_H #define THEPEG_MadGraphTwoCut_H // // This is the declaration of the MadGraphTwoCut class. // #include "ThePEG/Cuts/TwoCutBase.h" namespace ThePEG { /** * Objects of the MadGraphTwoCut class can be created automatically by * the MadGraphReader class when scanning event files for information * about cuts. It is also possible to create objects by hand and use * it as any other OneCutBase object. * * @see \ref MadGraphTwoCutInterfaces "The interfaces" * defined for MadGraphTwoCut. */ class MadGraphTwoCut: public TwoCutBase { public: /** * Enumerate the different kinds of cuts made by MadGraph. */ enum class Cut { INVMASS, /**< The minimum invariant mass of two particles. */ DELTAR /**< The minimum pseudo-rapidity--azimuth-angle distance between two particles. */ }; /** * Enumerate the types of particles the cut is made on. */ enum class P { JET, /**< Coloured particles (jets). */ LEP, /**< Leptons. */ PHO, /**< Photons. */ BOT, /**< Bottom quarks. */ NOT /**< Other types not cut on. */ }; /** * Enumerate the types of particles pairs the cut is made on. */ enum class PP { JETJET, /**< The cut applies only to pairs of coloured particles (jets). */ LEPLEP, /**< The cut applies only to lepton pairs (in case of INVMASS lepton--anti-lepton pairs of same flavour). */ PHOPHO, /**< The cut applies only to pairs photons. */ BOTBOT, /**< The cut applies only to pairs of bottom quarks. */ BOTJET, /**< The cut applies only to bottom quarks paired with another coloured particle (jet). */ PHOJET, /**< The cut applies only to a photon paired with a coloured particle (jet). */ JETLEP, /**< The cut applies only to a coloured particle (jet) paired with a lepton. */ PHOBOT, /**< The cut applies only to a photon paired with a bottom quark. */ BOTLEP, /**< The cut applies only to bottom quarks paired with a lepton. */ PHOLEP /**< The cut applies only to a photon paired with a lepton. */ }; public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ MadGraphTwoCut() : cutType(Cut::DELTAR), pairType(PP::JETJET), theCut(0.0) {} /** * The constructor used by the MadGraphReader. * @param t is the type of the cut. * @param p is the type of particles the cut is applied to. * @param c is the value of the cut (in units of GeV where applicable). */ MadGraphTwoCut(Cut t, PP p, double c) : cutType(t), pairType(p), theCut(c) {} //@} public: /** @name Virtual functions mandated by the base class. */ //@{ /** * Return the minimum allowed squared invariant mass of two outgoing * partons of type \a pi and \a pj. */ virtual Energy2 minSij(tcPDPtr pi, tcPDPtr pj) const; /** * Return the minimum allowed value of the negative of the squared * invariant mass of an incoming parton of type \a pi and an * outgoing parton of type \a po. */ virtual Energy2 minTij(tcPDPtr pi, tcPDPtr po) const; /** * Return the minimum allowed value of \f$\Delta * R_{ij}=\sqrt{\Delta\eta_{ij}^2+\Delta\phi_{ij}^2}\f$ of two * outgoing partons of type \a pi and \a pj. */ virtual double minDeltaR(tcPDPtr pi, tcPDPtr pj) const; /** * Return the minimum allowed value of the longitudinally invariant * \f$k_\perp\f$-algorithms distance measure. This is defined as * \f$\min(p_{\perp i}, p_{\perp * j})\sqrt{\Delta\eta_{ij}^2+\Delta\phi_{ij}^2}\f$ for two outgoing * partons, or simply \f$p_{\perp i}\f$ or \f$p_{\perp j}\f$ for a * single outgoing parton. Returns 0 if both partons are incoming. A * null pointer indicates an incoming parton, hence the type of the * incoming parton is irrelevant. */ virtual Energy minKTClus(tcPDPtr pi, tcPDPtr pj) const; /** * Return the minimum allowed value of the Durham * \f$k_\perp\f$-algorithms distance measure. This is defined as * \f$2\min(E_j^2, E_j^2)(1-\cos\theta_{ij})/\hat{s}\f$ for two * outgoing partons. */ virtual double minDurham(tcPDPtr pi, tcPDPtr pj) const; /** * Return true if a pair of particles with type \a pitype and \a * pjtype and momenta \a pi and \a pj respectively passes the * cuts. \a inci and \a inj indicates if the corresponding particles * are incoming. */ virtual bool passCuts(tcCutsPtr parent, tcPDPtr pitype, tcPDPtr pjtype, LorentzMomentum pi, LorentzMomentum pj, bool inci = false, bool incj = false) const; //@} protected: /** * Returns true if cut should be applied to pair of particles of * type \a pi and \a pj. */ bool checkType(tcPDPtr pi, tcPDPtr pj) const; /** * Get the type of particle \a p. */ P getType(tcPDPtr p) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * The type of this cut. */ Cut cutType; /** * The type of particle pairs this cut applies to. */ PP pairType; /** * The value of the cut to be applied. */ double theCut; private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initMadGraphTwoCut; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MadGraphTwoCut & operator=(const MadGraphTwoCut &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of MadGraphTwoCut. */ template <> struct BaseClassTrait { /** Typedef of the first base class of MadGraphTwoCut. */ typedef TwoCutBase NthBase; }; /** This template specialization informs ThePEG about the name of * the MadGraphTwoCut 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::MadGraphTwoCut"; } /** Return the name(s) of the shared library (or libraries) be loaded to get * access to the MadGraphTwoCut class and any other class on which it depends * (except the base class). */ static string library() { return "MadGraphReader.so"; } }; /** @endcond */ } #endif /* THEPEG_MadGraphTwoCut_H */ diff --git a/MatrixElement/Amplitude.cc b/MatrixElement/Amplitude.cc --- a/MatrixElement/Amplitude.cc +++ b/MatrixElement/Amplitude.cc @@ -1,64 +1,64 @@ // -*- C++ -*- // // Amplitude.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the Amplitude class. // #include "Amplitude.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG; AbstractNoPIOClassDescription Amplitude::initAmplitude; // Definition of the static class description member. void Amplitude::Init() { static ClassDocumentation documentation ("This the abstract class from which any amplitude class, associated with ", "a vertex inherits from."); } Complex Amplitude::overestimateValue( const tcPDVector & particles, const vector & momenta, const vector & helicities ) { return value(particles,momenta,helicities); } Complex Amplitude::value( const PVector & particles, const vector & helicities ) { tcPDVector dataParticles; vector momenta; for ( PVector::const_iterator cit = particles.begin(); cit != particles.end(); ++cit ) { dataParticles.push_back( (*cit)->dataPtr() ); momenta.push_back( (*cit)->momentum() ); } return value(dataParticles,momenta,helicities); } Complex Amplitude::overestimateValue( const PVector & particles, const vector & helicities ) { tcPDVector dataParticles; vector momenta; for ( PVector::const_iterator cit = particles.begin(); cit != particles.end(); ++cit ) { dataParticles.push_back( (*cit)->dataPtr() ); momenta.push_back( (*cit)->momentum() ); } return overestimateValue(dataParticles,momenta,helicities); } diff --git a/MatrixElement/Amplitude.h b/MatrixElement/Amplitude.h --- a/MatrixElement/Amplitude.h +++ b/MatrixElement/Amplitude.h @@ -1,138 +1,138 @@ // -*- C++ -*- // // Amplitude.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_Amplitude_H #define ThePEG_Amplitude_H // This is the declaration of the Amplitude class. #include "ThePEG/Handlers/HandlerBase.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/EventRecord/Particle.h" namespace ThePEG { /** * The Amplitude class is the abstract base class for all the classes * representing complex amplitudes associated with either a hard * 2\f$\rightarrow\f$ N subprocess or a decay 1\f$\rightarrow\f$ N * process. The returned value should be dimensionless suitable * scaled by the total invariant mass squared (shat), which is always * computable from the specified momenta of the particles in the * vertex. Notice that the amplitude for splitting * 1\f$\rightarrow\f$ N processes is instead represented in other * classes (derived from the SplitFun class). * * @see \ref AmplitudeInterfaces "The interfaces" * defined for Amplitude. */ class Amplitude: public HandlerBase { /** @name Main virtual functions to be overridden by sub-classes. */ //@{ /** * Return the amplitude. Given the ParticleData objects in \a * particles, their \a momenta and \a helicities of all the * particles in the vertex, return the complex amplitude. The * convention is the order of the vectors is that first there is the * incoming particle(s) and then the outgoing ones. For the * helicities, the convention is to number them starting from 0 (no * negative values, because they are used as vector indeces), for * example, for a massive particle of spin S, 0 <= helicity <= 2*S. * The returned value should be dimensionless suitable scaled by the * total invariant mass squared (\f$\hat{s}\f$), which is always * computable from the specified \a momenta of the particles in the * vertex. */ virtual Complex value(const tcPDVector & particles, const vector & momenta, const vector & helicities) = 0; /** * Return an overestimated amplitude. Same as value(const tcPDVector * &, const vector &, const vector &), but it * provides an overestimate of the complex amplitude, that is: * abs( overestimaValue() ) >= abs(value()) The * default definition just returns value(), but it can be overriden * by derived classes. */ virtual Complex overestimateValue(const tcPDVector & particles, const vector & momenta, const vector & helicities); //@} /** @name Alternative interface to main virtual functions. */ //@{ /** * Return the amplitude. Calls value(const tcPDVector &, const * vector &, const vector &) and should not * be overridden. */ Complex value(const PVector & particles, const vector & helicities); /** * Return an overestimated amplitude. Calls overestimateValue(const * tcPDVector &, const vector &, const vector * &) */ Complex overestimateValue(const PVector & particles, const vector & helicities); //@} public: /** * Standard Init function used to initialize the interfaces. */ static void Init(); /** * Describe an abstract base class with persistent data. */ static AbstractNoPIOClassDescription initAmplitude; /** * Private and non-existent assignment operator. */ Amplitude & operator=(const Amplitude &) = delete; }; } namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** * This template specialization informs ThePEG about the * base class of Amplitude. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the base class of Amplitude. */ typedef HandlerBase NthBase; }; /** * This template specialization informs ThePEG about the name of the * Amplitude class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return the class name. */ static string className() { return "ThePEG::Amplitude"; } }; /** @endcond */ } #endif /* ThePEG_Amplitude_H */ diff --git a/MatrixElement/BlobDiagram.cc b/MatrixElement/BlobDiagram.cc --- a/MatrixElement/BlobDiagram.cc +++ b/MatrixElement/BlobDiagram.cc @@ -1,82 +1,82 @@ // -*- C++ -*- // // BlobDiagram.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the BlobDiagram class. // #include "BlobDiagram.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/Utilities/Exception.h" #include "ThePEG/Handlers/StandardXComb.h" #include "ThePEG/PDT/EnumParticles.h" using namespace ThePEG; BlobDiagram::~BlobDiagram() {} tPVector BlobDiagram:: 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() != partons()[0] || in.second->dataPtr() != partons()[1] ) throw Exception() << "incoming partons in XComb do not match incoming partons in BlobDiagram" << Exception::setuperror; PVector slike; slike.push_back(in.first); 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(partons().size() - 2); ParticleSet done; for ( int i = partons().size() - 1; i >= 2; --i ) { int it = i - 2; tlike[it] = partons()[i]->produceParticle(pout[--io]); done.insert(tlike[it]); // add the time-like parton as the child of both incoming (space-like) partons. slike[0]->addChild(tlike[it]); slike[1]->addChild(tlike[it]); out.push_back(tlike[it]); } 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); cl.connect(ret); return out; } ClassDescription BlobDiagram::initBlobDiagram; void BlobDiagram::persistentInput(PersistentIStream &, int) {} void BlobDiagram::persistentOutput(PersistentOStream &) const {} diff --git a/MatrixElement/BlobDiagram.h b/MatrixElement/BlobDiagram.h --- a/MatrixElement/BlobDiagram.h +++ b/MatrixElement/BlobDiagram.h @@ -1,181 +1,181 @@ // -*- C++ -*- // // BlobDiagram.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_BlobDiagram_H #define ThePEG_BlobDiagram_H // This is the declaration of the BlobDiagram class. #include "ThePEG/MatrixElement/DiagramBase.h" #include "ThePEG/MatrixElement/ColourLines.h" #include "ThePEG/Handlers/StandardXComb.fh" namespace ThePEG { /** * The BlobDiagram class inherits from DiagramBase and represents a general * Feynman diagram of which no further substructure is assumed. * * @see DiagramBase * @see ColourLines * */ class BlobDiagram: public DiagramBase { public: /** The integer type reresenting vector sizes. */ typedef cPDVector::size_type size_type; public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor */ BlobDiagram() : DiagramBase() {} /** * Constructor specifiying incoming partons */ BlobDiagram(int id, tcPDPtr first, tcPDPtr second) : DiagramBase() { addParton(first); addParton(second); diagramInfo(2,id); } /** * Destructor. */ ~BlobDiagram(); //@} public: /** * Add a space- or time-like parton. */ BlobDiagram& operator,(PDPtr pd) { addParton(pd); return *this; } /** * Add a space- or time-like parton. */ BlobDiagram& operator,(cPDPtr pd) { addParton(pd); return *this; } /** * Add a space- or time-like parton. */ BlobDiagram& operator,(tPDPtr pd) { addParton(pd); return *this; } /** * Add a space- or time-like parton. */ BlobDiagram& operator,(tcPDPtr pd) { addParton(pd); return *this; } /** * Construct a sub process corresponding to this diagram. The * incoming partons, and the momenta of the outgoing ones, are given * by the XComb object. All parent/children pointers should be set * correspondingly and the partons should be colour connected as * specified by the ColourLines object. */ virtual tPVector construct(SubProPtr sb, const StandardXComb&, const ColourLines&) const; /** * Return the types of the incoming partons. */ tcPDPair incoming() const { return tcPDPair(partons()[0],partons()[1]); } /** * Return the outgoing parton types of this tree diagram. */ tcPDVector outgoing() const { return tcPDVector(partons().begin()+2,partons().end()); } /** * Return the incoming followed by the outgoing parton types of this * tree diagram. */ tcPDVector external() const { return tcPDVector(partons().begin(),partons().end()); } /** * Return the number of outgoing partons. */ size_type nOutgoing() const { return partons().size() - 2; } 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); //@} private: /** * Describe a concrete class with persistent data. */ static ClassDescription initBlobDiagram; /** * Private and non-existent assignment operator. */ BlobDiagram & operator=(const BlobDiagram &) = delete; }; } namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** * This template specialization informs ThePEG about the * base class of BlobDiagram. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the base class of BlobDiagram. */ typedef DiagramBase NthBase; }; /** * This template specialization informs ThePEG about the name of the * BlobDiagram class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return the class name. */ static string className() { return "ThePEG::BlobDiagram"; } }; /** @endcond */ } #endif /* ThePEG_BlobDiagram_H */ diff --git a/MatrixElement/ColourLines.cc b/MatrixElement/ColourLines.cc --- a/MatrixElement/ColourLines.cc +++ b/MatrixElement/ColourLines.cc @@ -1,142 +1,142 @@ // -*- C++ -*- // // ColourLines.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the 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; if(is>int(sources.size())) 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; if(is>int(sinks.size())) 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/ColourLines.h b/MatrixElement/ColourLines.h --- a/MatrixElement/ColourLines.h +++ b/MatrixElement/ColourLines.h @@ -1,89 +1,89 @@ // -*- C++ -*- // // ColourLines.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_ColourLines_H #define ThePEG_ColourLines_H // This is the declaration of the ColourLines class. #include "ThePEG/Config/ThePEG.h" namespace ThePEG { /** * The ColourLines class defines the colour flow in a SubProcess. It * defines a number of colour lines and specifies which particles are * connected to them. * */ class ColourLines: public Base { public: /** A single colour line */ typedef vector > Line; /** A vector of colour lines. */ typedef vector LineVector; /** A vector of ColourLine. */ typedef vector Vertex; /** A vector of vertices. */ typedef vector VertexVector; public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ ColourLines() {} /** * The standard constructor. The string \a s should contain a * comma-separated sequence of integers. Each sequence of numbers * indicates a colour line and the integer represents a parton * connected to it. If the integer is negative, it means that the * line is the corresponding partons anti-colour. Note that the * partons are numbered from 1: The first spacelike particle is 1, the second * is 2 and the internal time-like and outgoing are numbered after all * the spacelike particles. */ ColourLines(string s); //@} /** * Reset this ColourLines object. The string \a s should contain a * comma-separated sequence of integers. Each sequence of numbers * indicates a colour line and the integer represents a parton * connected to it. If the integer is negative, it means that the * line is the corresponding partons anti-colour. Note that the * partons are numbered from 1: The first incoming is 1, the second * is 2 and the internal and outgoing are numbered 3 and upwards. */ void reset(string s); public: /** * Create the corresponding ColourLines and connect the * given \a partons. The partons are assumed to be in the same order * as the numbers specified in the constructor. */ void connect(const tPVector & partons) const; private: /** * The vector of colour lines. */ LineVector theLines; }; } #endif /* ThePEG_ColourLines_H */ diff --git a/MatrixElement/ColourLines.xh b/MatrixElement/ColourLines.xh --- a/MatrixElement/ColourLines.xh +++ b/MatrixElement/ColourLines.xh @@ -1,32 +1,32 @@ // -*- C++ -*- // // ColourLines.xh is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_ColourLines_XH #define ThePEG_ColourLines_XH// // This is the declarations of the exception classes used by the // ColourLines class. // #include "ThePEG/Utilities/Exception.h" namespace ThePEG { /** @cond EXCEPTIONCLASSES */ /** Exception class used by ColourLines in case of inconsistent colour * flows. */ struct ColourGeometryException: public Exception { /** Standard constructor. */ ColourGeometryException(const tPVector &, const vector > & ); }; /** @endcond */ } #endif /* ThePEG_ColourLines_XH */ diff --git a/MatrixElement/DiagramBase.cc b/MatrixElement/DiagramBase.cc --- a/MatrixElement/DiagramBase.cc +++ b/MatrixElement/DiagramBase.cc @@ -1,73 +1,73 @@ // -*- C++ -*- // // DiagramBase.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the DiagramBase class. // #include "DiagramBase.h" #include "ThePEG/Utilities/ClassDescription.h" #include "ThePEG/Utilities/DescriptionList.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG; DiagramBase::~DiagramBase() {} struct ParticleOrdering { bool operator()(tcPDPtr p1, tcPDPtr p2) const { return abs(p1->id()) > abs(p2->id()) || ( abs(p1->id()) == abs(p2->id()) && p1->id() > p2->id() ) || ( p1->id() == p2->id() && p1->fullName() > p2->fullName() ); } }; string DiagramBase::getTag() const { string tag; if ( !done() ) throw DiagramBaseSetupException(*this); for ( int i = 0; i < nIncoming(); ++i ) { if ( i ) tag += ","; tag += partons()[i]->PDGName(); } tag += "->"; multiset out; for ( int i = nIncoming(), N = partons().size(); i < N; ++i ) out.insert(partons()[i]); for ( multiset::iterator i = out.begin(); i != out.end(); ++i ) { if ( i != out.begin() ) tag += ","; tag += (**i).PDGName(); } return tag; } void DiagramBase::persistentOutput(PersistentOStream & os) const { os << theNIncoming << thePartons << theId; } void DiagramBase::persistentInput(PersistentIStream & is, int) { is >> theNIncoming >> thePartons >> theId; } AbstractClassDescription DiagramBase::initDiagramBase; // Definition of the static class description member. void DiagramBase::Init() {} DiagramBaseSetupException::DiagramBaseSetupException(const DiagramBase & db) { const ClassDescriptionBase * cd = DescriptionList::find(typeid(db)); if ( !cd ) theMessage << "Tried to use an unknown sub class of DiagramBase."; else theMessage << "The '" << cd->name() << "' sub class did not setup the DiagramBase class correctly."; severity(abortnow); } diff --git a/MatrixElement/DiagramBase.h b/MatrixElement/DiagramBase.h --- a/MatrixElement/DiagramBase.h +++ b/MatrixElement/DiagramBase.h @@ -1,235 +1,235 @@ // -*- C++ -*- // // DiagramBase.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_DiagramBase_H #define ThePEG_DiagramBase_H // This is the declaration of the DiagramBase class. #include "ThePEG/Config/ThePEG.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/MatrixElement/ColourLines.h" #include "ThePEG/Handlers/StandardXComb.fh" #include "DiagramBase.fh" #include "DiagramBase.xh" namespace ThePEG { /** * DiagramBase is the base class of all classes which describes * Feynman diagrams which can be generated by a matrix element class * inheriting from MEBase, as reported by the * MEBase::includedDiagrams() method. * * To work properly, a sub-class must in its constructor report the * incoming and outgoing parton types with the partons(int, const * cPDVector &, int) method. Also an id number should be given to be * used internally by the matrix element class. In addition, the * construct() method must be implemented to construct the actual * partons and connect them together in a SubProcess object, also * performing the colour connections using a given ColourLines object. * * @see MEBase * @see SubProcess * @see ColourLines * */ class DiagramBase: public Base { public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ DiagramBase() : theNIncoming(-1), theId(0) {} /** * Destructor. */ virtual ~DiagramBase(); //@} public: /** @name Main virtual function to be overridden in sub-classes. */ //@{ /** * Construct a sub process corresponding to this diagram. The * incoming partons, and the momenta of the outgoing ones, are given * by the XComb object. All parent/children pointers should be set * correspondingly and the partons should be colour connected as * specified by the ColourLines object. */ virtual tPVector construct(SubProPtr sb, const StandardXComb &, const ColourLines &) const = 0; //@} /** @name Access the underlying information. */ //@{ /** * Return the number of incoming partons for this diagram. I.e. the * incoming partons plus the number of space-like lines. */ int nIncoming() const { return theNIncoming; } /** * Return the incoming, followed by the outgoing partons for this * diagram. */ const cPDVector& partons() const { return thePartons; } /** * Return the id number of this diagram. */ int id() const { return theId; } /** * Generate a tag which is unique for diagrams with the same * type of incoming and outgoing partons. */ string getTag() const; /** * Compare this diagram to another one modulo * the ids of the diagrams. */ virtual bool isSame (tcDiagPtr other) const { return nIncoming() == other->nIncoming() && partons() == other->partons(); } //@} protected: /** * To be used by sub classes to report the incoming and outgoing * particle types, and an id number. * * @param ninc the number of incoming and other space-like lines in * the diagram. * * @param parts the types of partons for each external line in the * diagram. * * @param newId the id number of this diagram. */ void partons(int ninc, const cPDVector & parts, int newId) { theNIncoming = ninc; thePartons = parts; theId = newId; } /** * Complete the missing information, provided partons() has already been * filled */ void diagramInfo(int ninc, int newId) { theNIncoming = ninc; theId = newId; } /** * Returns true if the partons(int, const cPDVector &, int) function * has been called properly from the sub class. */ bool done() const { return nIncoming() >= 0; } /** * Add to the partons */ void addParton(tcPDPtr pd) { thePartons.push_back(pd); } 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. */ static void Init(); private: /** * The number of incoming partons for this diagram. */ int theNIncoming; /** * The incoming, followed by the outgoing partons for this * diagram. */ cPDVector thePartons; /** * The id number of this diagram. */ int theId; private: /** * Describe an abstract base class with persistent data. */ static AbstractClassDescription initDiagramBase; /** * Private and non-existent assignment operator. */ DiagramBase & operator=(const DiagramBase &) = delete; }; } namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** * This template specialization informs ThePEG about the * base class of DiagramBase. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the base class of DiagramBase. */ typedef Base NthBase; }; /** * This template specialization informs ThePEG about the name of the * DiagramBase class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return the class name. */ static string className() { return "ThePEG::DiagramBase"; } }; /** @endcond */ } #endif /* ThePEG_DiagramBase_H */ diff --git a/MatrixElement/DiagramBase.xh b/MatrixElement/DiagramBase.xh --- a/MatrixElement/DiagramBase.xh +++ b/MatrixElement/DiagramBase.xh @@ -1,31 +1,31 @@ // -*- C++ -*- // // DiagramBase.xh is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_DiagramBase_XH #define ThePEG_DiagramBase_XH// // This is the declarations of the exception classes used by the // DiagramBase class. // #include "ThePEG/Utilities/Exception.h" namespace ThePEG { /** @cond EXCEPTIONCLASSES */ /** Exception class used by DiagramBase if an object was not correctly * set up. */ struct DiagramBaseSetupException: public Exception { /** Standard constructor. */ DiagramBaseSetupException(const DiagramBase &); }; /** @endcond */ } #endif /* ThePEG_DiagramBase_XH */ diff --git a/MatrixElement/ME2to2Base.cc b/MatrixElement/ME2to2Base.cc --- a/MatrixElement/ME2to2Base.cc +++ b/MatrixElement/ME2to2Base.cc @@ -1,202 +1,202 @@ // -*- C++ -*- // // ME2to2Base.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the ME2to2Base class. // #include "ME2to2Base.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Utilities/SimplePhaseSpace.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Handlers/StandardXComb.h" #include "ThePEG/Cuts/Cuts.h" using namespace ThePEG; ME2to2Base::~ME2to2Base() {} Energy2 ME2to2Base::scale() const { switch ( scaleChoice() ) { case 1: return -tHat()*uHat()/(tHat() + uHat()); default: return tHat()*uHat()/sHat(); } } void ME2to2Base::setKinematics() { MEBase::setKinematics(); theLastTHat = (meMomenta()[0] - meMomenta()[2]).m2(); theLastUHat = (meMomenta()[1] - meMomenta()[2]).m2(); theLastPhi = meMomenta()[2].phi(); } bool ME2to2Base::generateKinematics(const double * r) { // generate the masses of the particles for ( int i = 2, N = meMomenta().size(); i < N; ++i ) { meMomenta()[i] = Lorentz5Momentum(mePartonData()[i]->generateMass()); } double ctmin = -1.0; double ctmax = 1.0; Energy q = ZERO; try { q = SimplePhaseSpace:: getMagnitude(sHat(), meMomenta()[2].mass(), meMomenta()[3].mass()); } catch ( ImpossibleKinematics & e ) { return false; } Energy e = sqrt(sHat())/2.0; Energy2 m22 = meMomenta()[2].mass2(); Energy2 m32 = meMomenta()[3].mass2(); Energy2 e0e2 = 2.0*e*sqrt(sqr(q) + m22); Energy2 e1e2 = 2.0*e*sqrt(sqr(q) + m22); Energy2 e0e3 = 2.0*e*sqrt(sqr(q) + m32); Energy2 e1e3 = 2.0*e*sqrt(sqr(q) + m32); Energy2 pq = 2.0*e*q; Energy2 thmin = lastCuts().minTij(mePartonData()[0], mePartonData()[2]); if ( thmin > ZERO ) ctmax = min(ctmax, (e0e2 - m22 - thmin)/pq); thmin = lastCuts().minTij(mePartonData()[1], mePartonData()[2]); if ( thmin > ZERO ) ctmin = max(ctmin, (thmin + m22 - e1e2)/pq); thmin = lastCuts().minTij(mePartonData()[1], mePartonData()[3]); if ( thmin > ZERO ) ctmax = min(ctmax, (e1e3 - m32 - thmin)/pq); thmin = lastCuts().minTij(mePartonData()[0], mePartonData()[3]); if ( thmin > ZERO ) ctmin = max(ctmin, (thmin + m32 - e0e3)/pq); Energy ptmin = max(lastCuts().minKT(mePartonData()[2]), lastCuts().minKT(mePartonData()[3])); if ( ptmin > ZERO ) { double ctm = 1.0 - sqr(ptmin/q); if ( ctm <= 0.0 ) return false; ctmin = max(ctmin, -sqrt(ctm)); ctmax = min(ctmax, sqrt(ctm)); } double ymin2 = lastCuts().minYStar(mePartonData()[2]); double ymax2 = lastCuts().maxYStar(mePartonData()[2]); double ymin3 = lastCuts().minYStar(mePartonData()[3]); double ymax3 = lastCuts().maxYStar(mePartonData()[3]); double ytot = lastCuts().Y() + lastCuts().currentYHat(); if ( ymin2 + ytot > -0.9*Constants::MaxRapidity ) ctmin = max(ctmin, sqrt(sqr(q) + m22)*tanh(ymin2)/q); if ( ymax2 + ytot < 0.9*Constants::MaxRapidity ) ctmax = min(ctmax, sqrt(sqr(q) + m22)*tanh(ymax2)/q); if ( ymin3 + ytot > -0.9*Constants::MaxRapidity ) ctmax = min(ctmax, sqrt(sqr(q) + m32)*tanh(-ymin3)/q); if ( ymax3 + ytot < 0.9*Constants::MaxRapidity ) ctmin = max(ctmin, sqrt(sqr(q) + m32)*tanh(-ymax3)/q); if ( ctmin >= ctmax ) return false; double cth = getCosTheta(ctmin, ctmax, r); Energy pt = q*sqrt(1.0-sqr(cth)); theLastPhi = rnd(2.0*Constants::pi); meMomenta()[2].setVect(Momentum3( pt*sin(phi()), pt*cos(phi()), q*cth)); meMomenta()[3].setVect(Momentum3(-pt*sin(phi()), -pt*cos(phi()), -q*cth)); meMomenta()[2].rescaleEnergy(); meMomenta()[3].rescaleEnergy(); vector out(2); out[0] = meMomenta()[2]; out[1] = meMomenta()[3]; tcPDVector tout(2); tout[0] = mePartonData()[2]; tout[1] = mePartonData()[3]; if ( !lastCuts().passCuts(tout, out, mePartonData()[0], mePartonData()[1]) ) return false; theLastTHat = pq*cth + m22 - e0e2; theLastUHat = m22 + m32 - sHat() - theLastTHat; jacobian((pq/sHat())*Constants::pi*jacobian()); return true; } double ME2to2Base::getCosTheta(double ctmin, double ctmax, const double * r) { double cth = 0.0; static const double eps = 1.0e-6; if ( 1.0 + ctmin <= eps && 1.0 - ctmax <= eps ) { jacobian(ctmax - ctmin); cth = ctmin + (*r)*jacobian(); } else if ( 1.0 + ctmin <= eps ) { cth = 1.0 - (1.0 - ctmax)*pow((1.0 - ctmin)/(1.0 - ctmax), *r); jacobian(log((1.0 - ctmin)/(1.0 - ctmax))*(1.0 - cth)); } else if ( 1.0 - ctmax <= eps ) { cth = -1.0 + (1.0 + ctmin)*pow((1.0 + ctmax)/(1.0 + ctmin), *r); jacobian(log((1.0 + ctmax)/(1.0 + ctmin))*(1.0 + cth)); } else { double zmin = 0.5*(1.0 - ctmax); double zmax = 0.5*(1.0 - ctmin); double A1 = -ctmin/(zmax*(1.0-zmax)); double A0 = -ctmax/(zmin*(1.0-zmin)); double A = *r*(A1 - A0) + A0; double z = A < 2.0? 2.0/(sqrt(sqr(A) + 4.0) + 2 - A): 0.5*(A - 2.0 + sqrt(sqr(A) + 4.0))/A; cth = 1.0 - 2.0*z; jacobian(2.0*(A1 - A0)*sqr(z)*sqr(1.0 - z)/(sqr(z) + sqr(1.0 - z))); } return cth; } CrossSection ME2to2Base::dSigHatDR() const { return me2()*jacobian()/(16.0*sqr(Constants::pi)*sHat())*sqr(hbarc); } void ME2to2Base::persistentOutput(PersistentOStream & os) const { os << theScaleChoice << ounit(theLastTHat, GeV2) << ounit(theLastUHat, GeV2) << theLastPhi; } void ME2to2Base::persistentInput(PersistentIStream & is, int) { is >> theScaleChoice >> iunit(theLastTHat, GeV2) >> iunit(theLastUHat, GeV2) >> theLastPhi; } AbstractClassDescription ME2to2Base::initME2to2Base; // Definition of the static class description member. Switch & ME2to2Base::interfaceScaleChoice() { static Switch dummy ("ScaleChoice", "Different options for calculating the scale of the generated " "hard sub-process.", &ME2to2Base::theScaleChoice, 0, false, false); return dummy; } void ME2to2Base::Init() { static ClassDocumentation documentation ("The ThePEG::ME2to2Base class may be used as a base class " "for all \\f$2\\rightarrow 2\\f$ matrix elements."); static SwitchOption interfaceScaleChoice0 (interfaceScaleChoice(), "that.uhat/shat", "\\f$\\hat{t}\\hat{u}/\\hat{s}\\f$", 0); static SwitchOption interfaceScaleChoice1 (interfaceScaleChoice(), "that.uhat/(that+uhat)", "\\f$-\\hat{t}\\hat{u}/(\\hat{t}+\\hat{u})\\f$", 1); } diff --git a/MatrixElement/ME2to2Base.h b/MatrixElement/ME2to2Base.h --- a/MatrixElement/ME2to2Base.h +++ b/MatrixElement/ME2to2Base.h @@ -1,241 +1,241 @@ // -*- C++ -*- // // ME2to2Base.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_ME2to2Base_H #define ThePEG_ME2to2Base_H // This is the declaration of the ME2to2Base class. #include "ThePEG/MatrixElement/MEBase.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "ThePEG/Interface/Switch.fh" namespace ThePEG { /** * ME2to2Base can be used as a base class for any matrix element class * implementing 2\f$\rightarrow\f$ 2 processes. It extends the MEBase * base class by implementing the virtual scale() method to return the * assumed scale of a given process according to several options. It * also caches some useful characteristics of the chosen phase space * point, such as tHat(), uHat() and the masses of the external * partons. * * @see \ref ME2to2BaseInterfaces "The interfaces" * defined for ME2to2Base. * @see MEBase */ class ME2to2Base: public MEBase { public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ ME2to2Base() : theScaleChoice(0), theLastTHat(ZERO), theLastUHat(ZERO), theLastPhi(0.0) {} /** * Destructor. */ virtual ~ME2to2Base(); //@} public: /** @name Virtual functions required by the MEBase class. */ //@{ /** * The number of internal degreed of freedom used in the matrix * element. */ virtual int nDim() const { return 1; } /** * Generate internal degrees of freedom given 'nDim()' uniform * random numbers in the interval ]0,1[. To help the phase space * generator, the 'dSigHatDR()' should be a smooth function of these * numbers, although this is not strictly necessary. Return * false if the chosen points failed the kinematical cuts. */ virtual bool generateKinematics(const double * r); /** * Return the matrix element for the kinematical configuation * previously provided by the last call to setKinematics(). Uses * me(). */ virtual CrossSection dSigHatDR() const; /** * Return the scale associated with the last set phase space point. */ virtual Energy2 scale() const; /** * Set the typed and momenta of the incoming and outgoing partons to * be used in subsequent calls to me() and colourGeometries() * according to the associated XComb object. */ virtual void setKinematics(); //@} /** * Used internally by generateKinematics, after calculating the * limits on cos(theta). */ virtual double getCosTheta(double cthmin, double cthmax, const double * r); /** * Give the option corresponding to the way the scale of an * interaction is calculated. */ int scaleChoice() const { return theScaleChoice; } public: /** @name Access cached values in of the last set phase space point. */ //@{ /** * Return the \f$\hat{t}\f$ of the last set phase space point. */ Energy2 tHat() const { return theLastTHat; } /** * Return the \f$\hat{u}\f$ of the last set phase space point. */ Energy2 uHat() const { return theLastUHat; } /** * Return the azimuth angle of the last set phase space point. */ double phi() const { return theLastPhi; } //@} 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(); protected: /** @name Set the cached values in of the last set phase space point. */ //@{ /** * Set the \f$\hat{t}\f$ of the last set phase space point. */ void tHat(Energy2 e2) { theLastTHat = e2; } /** * Set the \f$\hat{u}\f$ of the last set phase space point. */ void uHat(Energy2 e2) { theLastUHat = e2; } /** * Set the azimuth angle of the last set phase space point. */ void phi(double phi) { theLastPhi = phi; } //@} protected: /** * Access to the acutal Switch object used to determine the choice * of scale. */ static Switch & interfaceScaleChoice(); private: /** * The option indicating how to calculate the scale of an interaction. */ int theScaleChoice; /** * The \f$\hat{t}\f$ of the last set phase space point. */ Energy2 theLastTHat; /** * The \f$\hat{u}\f$ of the last set phase space point. */ Energy2 theLastUHat; /** * The azimuth angle of the last set phase space point. */ double theLastPhi; private: /** * Describe an abstract base class with persistent data. */ static AbstractClassDescription initME2to2Base; /** * Private and non-existent assignment operator. */ ME2to2Base & operator=(const ME2to2Base &) = delete; }; } namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** * This template specialization informs ThePEG about the * base class of ME2to2Base. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the base class of ME2to2Base. */ typedef MEBase NthBase; }; /** * This template specialization informs ThePEG about the name of the * ME2to2Base class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return the class name. */ static string className() { return "ThePEG::ME2to2Base"; } }; /** @endcond */ } #endif /* ThePEG_ME2to2Base_H */ diff --git a/MatrixElement/ME2to2QCD.cc b/MatrixElement/ME2to2QCD.cc --- a/MatrixElement/ME2to2QCD.cc +++ b/MatrixElement/ME2to2QCD.cc @@ -1,95 +1,95 @@ // -*- C++ -*- // // ME2to2QCD.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the ME2to2QCD class. // #include "ME2to2QCD.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/StandardModel/StandardModelBase.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG; ME2to2QCD::~ME2to2QCD() {} unsigned int ME2to2QCD::orderInAlphaS() const { return 2; } unsigned int ME2to2QCD::orderInAlphaEW() const { return 0; } double ME2to2QCD::comfac() const { return 32.0*sqr(Constants::pi*SM().alphaS(scale())); } void ME2to2QCD::persistentOutput(PersistentOStream & os) const { os << theMaxFlavour << theKfac << theKfacA << useInterference; } void ME2to2QCD::persistentInput(PersistentIStream & is, int) { is >> theMaxFlavour >> theKfac >> theKfacA >> useInterference; } AbstractClassDescription ME2to2QCD::initME2to2QCD; // Definition of the static class description member. void ME2to2QCD::Init() { static ClassDocumentation documentation ("There is no documentation for the ThePEG::ME2to2QCD class"); static Parameter interfaceMaxFlavour ( "MaxFlavour", "The heaviest quark flavour this matrix element is allowed to handle " "(if applicable). This applies fo both incoming an outgoing partons.", &ME2to2QCD::theMaxFlavour, 5, 0, 8, false, false, true); static Parameter interfaceKfac ("K-factor", "A K-factor for artificially boosting this cross-section.", &ME2to2QCD::theKfac, 1.0, 0.0, Constants::MaxFloat, true, false, true); static Parameter interfaceKfacA ("K-factor-A", "A K-factor for artificially boosting the colour annihilation terms " "in this cross-section. If less than one, the " "K-factor will " "be used instead.", &ME2to2QCD::theKfacA, 1.0, -1.0, Constants::MaxFloat, true, false, true); static Switch interfaceUseInterfecence ("Interference", "Use of interference terms in the matrix elements. If included the terms " "are divided between the differenct possible colour configurations " "according to the pole structure of the (string-inspired) matrix " "elements for the different colour configurations.", &ME2to2QCD::useInterference, true, false, false); static SwitchOption interfaceInterferenceOff (interfaceUseInterfecence, "Excluded", "Only the parts of the matrix elements with a well-defined colour " "structure is used.", false); static SwitchOption interfaceInterferenceOn (interfaceUseInterfecence, "Included", "Use the full matrix element.", true); interfaceMaxFlavour.rank(10); } diff --git a/MatrixElement/ME2to2QCD.h b/MatrixElement/ME2to2QCD.h --- a/MatrixElement/ME2to2QCD.h +++ b/MatrixElement/ME2to2QCD.h @@ -1,192 +1,192 @@ // -*- C++ -*- // // ME2to2QCD.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_ME2to2QCD_H #define ThePEG_ME2to2QCD_H // This is the declaration of the ME2to2QCD class. #include "ThePEG/MatrixElement/ME2to2Base.h" namespace ThePEG { /** * The ME2to2QCD class inherits from the ME2to2Base class and can be * used as a sub class for all QCD 2\f$\rightarrow\f$ 2 processes. It * implements some common functions such as common pre-factors, * maximum number of flavours, treatment of interference terms and * possibility to enhance certain terms. * * @see \ref ME2to2QCDInterfaces "The interfaces" * defined for ME2to2QCD. * @see ME2to2Base */ class ME2to2QCD: public ME2to2Base { public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ ME2to2QCD() : theMaxFlavour(5), theKfac(1.0), theKfacA(1.0), useInterference(true) {} /** * Destructor. */ virtual ~ME2to2QCD(); //@} public: /** @name Virtual functions required by the MEBase class. */ //@{ /** * Return the order in \f$\alpha_S\f$ in which this matrix element * is given. Returns 2. */ virtual unsigned int orderInAlphaS() const; /** * Return the order in \f$\alpha_{EM}\f$ in which this matrix * element is given. Returns 0. */ virtual unsigned int orderInAlphaEW() const; /** * The common prefactor for all 2\f$\rightarrow\f$ 2 QCD sub-processes * ie. \f$\alpha_S^2\f$. */ double comfac() const; /** * Return the heaviest flavour allowed for this matrix element. */ int maxFlavour() const { return theMaxFlavour; } /** * K-factor for artificially boosting the cross-section. */ double Kfac() const { return theKfac; } /** * K-factor for artificially boosting colour-annihilation diagrams. */ double KfacA() const { return theKfacA >= 0.0? theKfacA: theKfac; } /** * Return true if interference terms should be used. */ bool interference() const { return useInterference; } /** * Return true if argument is a quark. */ bool isQuark(const ParticleData & p) const { return ( p.id() && abs(p.id()) <= maxFlavour() ); } /** * Return the quark with flavour i (or gluon if i = 0); */ tcPDPtr quark(int i) const; //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interfaces. */ static void Init(); private: /** * The heaviest flavour allowed for incoming and outgoing partons. */ int theMaxFlavour; /** * Overall K-factor used to boost this cross-section. */ double theKfac; /** * Overall K-factors used to boost the colour annihilation diagram * in the cross-section. */ double theKfacA; /** * Flag so tell whether interference should be used or not. */ bool useInterference; private: /** * Describe an abstract base class with persistent data. */ static AbstractClassDescription initME2to2QCD; /** * Private and non-existent assignment operator. */ ME2to2QCD & operator=(const ME2to2QCD &) = delete; }; } namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** * This template specialization informs ThePEG about the * base class of ME2to2QCD. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the base class of ME2to2QCD. */ typedef ME2to2Base NthBase; }; /** * This template specialization informs ThePEG about the name of the * ME2to2QCD class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return the class name. */ static string className() { return "ThePEG::ME2to2QCD"; } }; /** @endcond */ } #endif /* ThePEG_ME2to2QCD_H */ diff --git a/MatrixElement/MEBase.cc b/MatrixElement/MEBase.cc --- a/MatrixElement/MEBase.cc +++ b/MatrixElement/MEBase.cc @@ -1,305 +1,305 @@ // -*- C++ -*- // // MEBase.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MEBase class. // #include "MEBase.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Utilities/Rebinder.h" #include "ThePEG/MatrixElement/ReweightBase.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Handlers/XComb.h" #include "ThePEG/Handlers/StandardXComb.h" #include "ThePEG/StandardModel/StandardModelBase.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG; MEBase::MEBase() : theMaxMultCKKW(0), theMinMultCKKW(0) {} MEBase::~MEBase() {} void MEBase::use(tcMEPtr other) { if (other == this) return; theDiagrams = other->theDiagrams; reweights = other->reweights; preweights = other->preweights; theAmplitude = other->theAmplitude; theMaxMultCKKW = other->theMaxMultCKKW; theMinMultCKKW = other->theMinMultCKKW; } void MEBase::useDiagrams(tcMEPtr other) const { if (other == this) return; theDiagrams = other->theDiagrams; } void MEBase::doinit() { if ( theAmplitude ) theAmplitude->init(); for ( ReweightVector::iterator i = reweights.begin(); i != reweights.end(); ++i ) (**i).init(); for ( ReweightVector::iterator i = preweights.begin(); i != preweights.end(); ++i ) (**i).init(); HandlerBase::doinit(); } void MEBase::doinitrun() { if ( theAmplitude ) theAmplitude->initrun(); for ( ReweightVector::iterator i = reweights.begin(); i != reweights.end(); ++i ) (**i).initrun(); for ( ReweightVector::iterator i = preweights.begin(); i != preweights.end(); ++i ) (**i).initrun(); HandlerBase::doinitrun(); } void MEBase::addReweighter(tReweightPtr rw) { if ( rw && find(reweights.begin(), reweights.end(), rw) == reweights.end() ) reweights.push_back(rw); } void MEBase::addPreweighter(tReweightPtr rw) { if ( rw && find(preweights.begin(), preweights.end(), rw) == preweights.end()) preweights.push_back(rw); } void MEBase::setKinematics(tPPair in, const PVector & out) { theLastXComb = tStdXCombPtr(); for ( int i = 0, N = diagrams().size(); i < N; ++i ) { tPVector parts; const DiagramBase & diag = *(diagrams()[i]); if (diag.partons().size() != out.size() + 2 ) continue; if ( in.first->dataPtr() == diag.partons()[0] ) { parts.push_back(in.first); if ( in.second->dataPtr() != diag.partons()[1] ) continue; parts.push_back(in.second); } else if ( in.second->dataPtr() == diag.partons()[0] ) { parts.push_back(in.second); if ( in.first->dataPtr() != diag.partons()[1] ) continue; parts.push_back(in.first); } else continue; typedef multimap MMap; #ifdef _LIBCPP_VERSION typedef MMap::const_iterator Iterator; #else typedef MMap::iterator Iterator; #endif MMap omap; for ( int j = 0, M = out.size(); j < M; ++j ) omap.insert(make_pair(out[j]->dataPtr(), out[j])); for ( int j = 2, M = diag.partons().size(); j < M; ++j ) { Iterator it = omap.find(diag.partons()[j]); if ( it == omap.end() ) break; parts.push_back(it->second); omap.erase(it); } if ( !omap.empty() ) continue; theLastXComb = new_ptr(StandardXComb(this, parts, i)); setKinematics(); return; } throw Exception() << "In 'MEBase::setKinematics(...)' for the object '" << name() << "': Could not set the kinematics according to the specified partons " << "since no matching diagram was found." << Exception::abortnow; } void MEBase::constructVertex(tSubProPtr) {} void MEBase::constructVertex(tSubProPtr sub, const ColourLines*) { constructVertex(sub); } void MEBase::clearKinematics() { theLastXComb = tStdXCombPtr(); } MEBase::DiagramIndex MEBase::diagram(const DiagramVector & dv) const { Selector sel = diagrams(dv); if ( sel.size() > 1 ) return sel.select(rnd()); if ( sel.size() == 1 ) return sel.begin()->second; return DiagramIndex(rnd(dv.size())); } const ColourLines & MEBase:: selectColourGeometry(tcDiagPtr diag) const { Selector sel = colourGeometries(diag); if ( sel.size() == 1 ) return *sel.begin()->second; return *sel.select(rnd()); } int MEBase::nDim() const { return 0; } StdXCombPtr MEBase::makeXComb(Energy newMaxEnergy, const cPDPair & inc, tEHPtr newEventHandler,tSubHdlPtr newSubProcessHandler, tPExtrPtr newExtractor, tCascHdlPtr newCKKW, const PBPair & newPartonBins, tCutsPtr newCuts, const DiagramVector & newDiagrams, bool mir, const PartonPairVec&, tStdXCombPtr newHead, tMEPtr newME) { if ( !newME ) newME = this; return new_ptr(StandardXComb(newMaxEnergy, inc, newEventHandler, newSubProcessHandler, newExtractor, newCKKW, newPartonBins, newCuts, newME, newDiagrams, mir, newHead)); } StdXCombPtr MEBase::makeXComb(tStdXCombPtr newHead, const PBPair & newPartonBins, const DiagramVector & newDiagrams, tMEPtr newME) { if ( !newME ) newME = this; return new_ptr(StandardXComb(newHead, newPartonBins, newME, newDiagrams)); } void MEBase::setXComb(tStdXCombPtr xc) { theLastXComb = xc; } vector & MEBase::meMomenta() { return lastXCombPtr()->meMomenta(); } void MEBase::lastME2(double v) const { lastXCombPtr()->lastME2(v); } void MEBase::lastPreweight(double v) const { lastXCombPtr()->lastPreweight(v); } void MEBase::lastMECrossSection(CrossSection v) const { lastXCombPtr()->lastMECrossSection(v); } void MEBase::lastMEPDFWeight(double v) const { lastXCombPtr()->lastMEPDFWeight(v); } void MEBase::lastMECouplings(double v) const { lastXCombPtr()->lastMECouplings(v); } void MEBase::jacobian(double j) { lastXCombPtr()->jacobian(j); } double MEBase::reWeight() const { double w = 1.0; for ( int i = 0, N = reweights.size(); i < N; ++i ) { reweights[i]->setXComb(lastXCombPtr()); w *= reweights[i]->weight(); } return w; } double MEBase::preWeight() const { double w = 1.0; for ( int i = 0, N = preweights.size(); i < N; ++i ) { preweights[i]->setXComb(lastXCombPtr()); w *= preweights[i]->weight(); } lastPreweight(w); return lastPreweight(); } void MEBase::generateSubCollision(SubProcess &) {} const DVector & MEBase::meInfo() const { return lastXCombPtr()->meInfo(); } void MEBase::meInfo(const DVector & info) const { lastXCombPtr()->meInfo(info); } double MEBase::alphaS() const { return SM().alphaS(scale()); } double MEBase::alphaEM() const { return SM().alphaEM(scale()); } void MEBase::persistentOutput(PersistentOStream & os) const { os << theDiagrams << reweights << preweights << theAmplitude << theLastXComb << theMaxMultCKKW << theMinMultCKKW; } void MEBase::persistentInput(PersistentIStream & is, int) { is >> theDiagrams >> reweights >> preweights >> theAmplitude >> theLastXComb >> theMaxMultCKKW >> theMinMultCKKW; } AbstractClassDescription MEBase::initMEBase; // Definition of the static class description member. void MEBase::Init() { static ClassDocumentation documentation ("The ThePEG::MEBase class is the base class for all matrix elements " "to be used for generating sub processes in ThePEG"); static RefVector interfaceReweights ("Reweights", "A list of ThePEG::ReweightBase objects to modify this matrix elements.", &MEBase::reweights, 0, false, false, true, false); static RefVector interfacePreweights ("Preweights", "A list of ThePEG::ReweightBase objects to bias the phase space for this " "matrix elements without influencing the actual cross section.", &MEBase::preweights, 0, false, false, true, false); static Reference interfaceAmplitude ("Amplitude", "The eventual amplitude associated to this matrix element.", &MEBase::theAmplitude, false, false, true, true); static Parameter interfaceMaxMultCKKW ("MaxMultCKKW", "If this matrix element is to be used 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.", &MEBase::theMaxMultCKKW, 0, 0, 0, true, false, Interface::lowerlim); static Parameter interfaceMinMultCKKW ("MinMultCKKW", "If this matrix element is to be used 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.", &MEBase::theMinMultCKKW, 0, 0, 0, true, false, Interface::lowerlim); interfaceMaxMultCKKW.rank(2.0); interfaceMinMultCKKW.rank(1.0); } diff --git a/MatrixElement/MEBase.h b/MatrixElement/MEBase.h --- a/MatrixElement/MEBase.h +++ b/MatrixElement/MEBase.h @@ -1,675 +1,675 @@ // -*- C++ -*- // // MEBase.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_MEBase_H #define ThePEG_MEBase_H // This is the declaration of the MEBase class. #include "ThePEG/Handlers/HandlerBase.h" #include "ThePEG/EventRecord/SubProcess.h" #include "ThePEG/MatrixElement/DiagramBase.h" #include "ThePEG/MatrixElement/ColourLines.h" #include "ThePEG/MatrixElement/Amplitude.h" #include "ThePEG/Handlers/LastXCombInfo.h" #include "ThePEG/Handlers/StandardXComb.fh" #include "ReweightBase.h" #include "ThePEG/Handlers/EventHandler.fh" #include "ThePEG/Handlers/StandardEventHandler.fh" #include "ThePEG/Handlers/SubProcessHandler.fh" #include "ThePEG/PDF/PartonBin.fh" #include "MEBase.fh" namespace ThePEG { /** * The MEBase class is the base class of all objects * representing hard matrix elements in ThePEG. There are three * methods which must be overridden by a concrete subclass:
* * includedDiagrams(tcPDPair) should return a vector of DiagramBase * objects describing the diagrams used for this matrix element for * the given pair of incoming parton types. These DiagramBases are * used to identify the incoming and outgoing partons which can be * handled by the process generation scheme, and is also used to * cnstruct a corresponding SubProcess object. * * scale() should return the scale associated with the phase space * point set with the last call to setKinematics(...) or * generateKinematics(...). * * me() should return the the matrix element squared using the the * type and momentum of the incoming and outgoing partons, previously * set by the setKinematics(...) or generateKinematics(...) member * functions, accessible through the methods meMomenta() and * mePartonData() inherited from LastXCombInfo, and/or from * information stored by sub classes. The returned value should be * dimensionless suitable scaled by the total invariant mass squared * (accessible through the sHat() member function). Any user of this * method must make sure that the setKinematics(...) member function * has been appropriately called before. * * colourGeometries() should return a Selector with the possible * ColourLines objects weighted by their relative probabilities given * the information set by the last call to setKinematics(...) or * generateKinematics(...). * * There are other virtula functions which may be overridden as listed * below. * * @see \ref MEBaseInterfaces "The interfaces" * defined for MEBase. * @see DiagramBase * @see ColourLines * */ class MEBase: public HandlerBase, public LastXCombInfo { public: /** A vector of pointers to DiagramBase objects. */ typedef vector DiagramVector; /** The size_type used in the DiagramVector. */ typedef DiagramVector::size_type DiagramIndex; /** A vector of pointers to ReweightBase objects. */ typedef vector ReweightVector; public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ MEBase(); /** * Destructor. */ virtual ~MEBase(); //@} public: /** @name Virtual functions to be overridden by sub-classes.. */ //@{ /** * Return the order in \f$\alpha_S\f$ in which this matrix element * is given. */ virtual unsigned int orderInAlphaS() const = 0; /** * Return the order in \f$\alpha_{EM}\f$ in which this matrix * element is given. Returns 0. */ virtual unsigned int orderInAlphaEW() const = 0; /** * Return the matrix element for the kinematical configuation * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. */ virtual double me2() const = 0; /** * Return the scale associated with the phase space point provided * by the last call to setKinematics(). */ virtual Energy2 scale() const = 0; /** * Return the value of \f$\alpha_S\f$ associated with the phase * space point provided by the last call to setKinematics(). This * versions returns SM().alphaS(scale()). */ virtual double alphaS() const; /** * Return the value of \f$\alpha_EM\f$ associated with the phase * space point provided by the last call to setKinematics(). This * versions returns SM().alphaEM(scale()). */ virtual double alphaEM() const; /** * Set the typed and momenta of the incoming and outgoing partons to * be used in subsequent calls to me() and colourGeometries(). */ void setKinematics(tPPair in, const PVector & out); /** * Set the typed and momenta of the incoming and outgoing partons to * be used in subsequent calls to me() and colourGeometries() * according to the associated XComb object. If the function is * overridden in a sub class the new function must call the base * class one first. */ virtual void setKinematics() {} /** * construct the spin information for the interaction */ virtual void constructVertex(tSubProPtr sub); /** * construct the spin information for the interaction */ virtual void constructVertex(tSubProPtr sub, const ColourLines* cl); /** * The number of internal degreed of freedom used in the matrix * element. This default version returns 0; */ virtual int nDim() const; /** * Generate internal degrees of freedom given nDim() uniform random * numbers in the interval ]0,1[. To help the phase space generator, * the 'dSigHatDR' should be a smooth function of these numbers, * although this is not strictly necessary. The return value should * be true of the generation succeeded. If so the generated momenta * should be stored in the meMomenta() vector. */ virtual bool generateKinematics(const double * r) = 0; /** * Return true, if this matrix element expects * the incoming partons in their center-of-mass system */ virtual bool wantCMS() const { return true; } /** * If this is a dependent matrix element in a ME group, return true, * if cuts should be inherited from the head matrix element, i.e. no * cut is being applied to the dependent matrix element if the head * configuration has passed the cuts. */ virtual bool headCuts() const { return false; } /** * If this is a dependent matrix element in a ME group, return true, * if cuts should be ignored. */ virtual bool ignoreCuts() const { return false; } /** * If this is a dependent matrix element in a ME group, return true, * if it applies to the process set in lastXComb() */ virtual bool apply() const { return true; } /** * Return the matrix element squared differential in the variables * given by the last call to generateKinematics(). */ virtual CrossSection dSigHatDR() const = 0; /** * If variations are available for the subprocess handled, generate * and return a map of optional weights to be included for the * event. */ virtual map generateOptionalWeights() { return map(); } /** * Return true, if this matrix element will generate momenta for the * incoming partons itself. The matrix element is required to store * the incoming parton momenta in meMomenta()[0,1]. No mapping in * tau and y is performed by the PartonExtractor object, if a * derived class returns true here. The phase space jacobian is to * include a factor 1/(x1 x2). */ virtual bool haveX1X2() const { return false; } /** * Return true, if this matrix element provides the PDF * weight for the first incoming parton itself. */ virtual bool havePDFWeight1() const { return false; } /** * Return true, if this matrix element provides the PDF * weight for the second incoming parton itself. */ virtual bool havePDFWeight2() const { return false; } /** * Return true, if the XComb steering this matrix element * should keep track of the random numbers used to generate * the last phase space point */ virtual bool keepRandomNumbers() const { return false; } /** * Comlete a SubProcess object using the internal degrees of freedom * generated in the last generateKinematics() (and possible other * degrees of freedom which was intergated over in dSigHatDR(). This * default version does nothing. Will be made purely virtual in the * future. */ virtual void generateSubCollision(SubProcess &); /** * Clear the information previously provided by a call to * setKinematics(...). */ virtual void clearKinematics(); /** * Add all possible diagrams with the add() function. */ virtual void getDiagrams() const = 0; /** * Return true, if this matrix element does not want to * make use of mirroring processes; in this case all * possible partonic subprocesses with a fixed assignment * of incoming particles need to be provided through the diagrams * added with the add(...) method. */ virtual bool noMirror () const { return false; } /** * Return all possible diagrams. */ const DiagramVector & diagrams() const { if ( theDiagrams.empty() ) getDiagrams(); return theDiagrams; } /** * Return a Selector with possible colour geometries for the selected * diagram weighted by their relative probabilities. */ virtual Selector colourGeometries(tcDiagPtr diag) const = 0; /** * Select a ColpurLines geometry. The default version returns a * colour geometry selected among the ones returned from * colourGeometries(tcDiagPtr). */ virtual const ColourLines & selectColourGeometry(tcDiagPtr diag) const; /** * 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. */ virtual Selector diagrams(const DiagramVector &) const { return Selector(); } /** * Select a diagram. Default version uses diagrams(const * DiagramVector &) to select a diagram according to the * weights. This is the only method used that should be outside of * MEBase. */ virtual DiagramIndex diagram(const DiagramVector &) const; /** * Return true if this matrix element has associated (p)reWeight * objects assigned. */ inline bool reweighted() const { return reweights.size() > 0 || preweights.size() > 0; } /** * With the information previously supplied with the * setKinematics(...) methods, return the combined effects of the * reweighters. */ double reWeight() const; /** * With the information previously supplied with the * setKinematics(...) methods, return the comined effects of the * peweighters. */ double preWeight() const; /** * Add objects to the list of reweighters. */ void addReweighter(tReweightPtr rw); /** * Add objects to the list of preweighters. */ void addPreweighter(tReweightPtr rw); /** * Return the amplitude associated with this matrix element. This * function is allowed to return the null pointer if the amplitude * is not available. */ Ptr::pointer amplitude() const { return theAmplitude; } /** * Set the amplitude associated with this matrix element. */ void amplitude(Ptr::pointer amp) { theAmplitude = amp; } //@} public: /** @name Acces information about the last generated phase space point. */ //@{ /** * Return the last set invariant mass squared. */ Energy2 sHat() const { return lastSHat(); } /** * Return the factor with which this matrix element was last * pre-weighted. */ double preweight() const { return lastPreweight(); } /** * Inform this matrix element that a new phase space * point is about to be generated, so all caches should * be flushed. */ virtual void flushCaches() {} /** * For the given event generation setup return a xcomb object * appropriate to this matrix element. */ virtual StdXCombPtr makeXComb(Energy newMaxEnergy, const cPDPair & inc, tEHPtr newEventHandler,tSubHdlPtr newSubProcessHandler, tPExtrPtr newExtractor, tCascHdlPtr newCKKW, const PBPair & newPartonBins, tCutsPtr newCuts, const DiagramVector & newDiagrams, bool mir, const PartonPairVec& allPBins, tStdXCombPtr newHead = tStdXCombPtr(), tMEPtr newME = tMEPtr()); /** * For the given event generation setup return a dependent xcomb object * appropriate to this matrix element. */ virtual StdXCombPtr makeXComb(tStdXCombPtr newHead, const PBPair & newPartonBins, const DiagramVector & newDiagrams, tMEPtr newME = tMEPtr()); /** * Fill the projectors object of xcombs to choose subprocesses * different than the one currently integrated. */ virtual void fillProjectors() { } /** * Set the XComb object to be used in the next call to * generateKinematics() and dSigHatDR(). */ virtual void setXComb(tStdXCombPtr); /** * Retrieve information obtained in the calculation of the cross * section to be used later when selecting diagrams and colour flow. */ const DVector & meInfo() const; /** * Save information obtained in the calculation of the cross * section to be used later when selecting diagrams and colour flow. */ void meInfo(const DVector & info) const; /** * If this matrix element is to be used 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. */ virtual int maxMultCKKW() const { return theMaxMultCKKW; } /** * If this matrix element is to be used 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. */ virtual int minMultCKKW() const { return theMinMultCKKW; } /** * If this matrix element is to be used together with others for * CKKW reweighting and veto, this will set the multiplicity of * outgoing particles in the highest multiplicity matrix element in * the group. */ virtual void maxMultCKKW(int mult) { theMaxMultCKKW = mult; } /** * If this matrix element is to be used together with others for * CKKW reweighting and veto, this will set the multiplicity of * outgoing particles in the lowest multiplicity matrix element in * the group. */ virtual void minMultCKKW(int mult) { theMinMultCKKW = mult; } /** * Set veto scales on the particles at the given * SubProcess which has been generated using this * matrix element. */ virtual void setVetoScales(tSubProPtr) const {} //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interfaces. */ static void Init(); protected: /** * To be used by sub classes in the getDiagrams() method to add * included diagrams. */ void add(DiagPtr dp) const { theDiagrams.push_back(dp); } /** * Access the momenta set by the last call to generateKinematics(). */ vector & meMomenta(); using LastXCombInfo::meMomenta; /** * Set the matrix element squared as calculated * for the last phase space point. This may optionally * be used by a matrix element for caching. */ void lastME2(double v) const; using LastXCombInfo::lastME2; /** * Set the last preweight factor */ void lastPreweight(double w) const; using LastXCombInfo::lastPreweight; /** * Set the partonic cross section as calculated * for the last phase space point. This may optionally * be used by a matrix element for caching. */ void lastMECrossSection(CrossSection v) const; using LastXCombInfo::lastMECrossSection; /** * Set the PDF weight as calculated * for the last phase space point, if the matrix * element does supply PDF weights. This may optionally * be used by a matrix element for caching. */ void lastMEPDFWeight(double v) const; using LastXCombInfo::lastMEPDFWeight; /** * Set the coupling weight as calculated * for the last phase space point */ void lastMECouplings(double v) const; using LastXCombInfo::lastMECouplings; /** * Set the last jacobian obtained when generating the kinematics for * the call to dSigHatDR. */ void jacobian(double j); using LastXCombInfo::jacobian; /** * Initialize all member variables from another * MEBase object. * * @TODO remove? */ void use(tcMEPtr other); /** * Initialize the diagrams from another MEBase object. */ void useDiagrams(tcMEPtr other) 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(); //@} private: /** * The diagrams included for this matrix element. */ mutable DiagramVector theDiagrams; /** * The reweight objects modifying this matrix element. */ ReweightVector reweights; /** * The preweight objects modifying this matrix element. */ ReweightVector preweights; /** * The amplitude associated with this matrix element. */ Ptr::pointer theAmplitude; /** * If this matrix element is to be used 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. */ int theMaxMultCKKW; /** * If this matrix element is to be used 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. */ int theMinMultCKKW; private: /** * Describe an abstract base class with persistent data. */ static AbstractClassDescription initMEBase; /** * Private and non-existent assignment operator. */ MEBase & operator=(const MEBase &) = delete; }; } namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** * This template specialization informs ThePEG about the base class of * MEBase. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the base class of MEBase. */ typedef HandlerBase NthBase; }; /** * This template specialization informs ThePEG about the name of the * MEBase class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return the class name. */ static string className() { return "ThePEG::MEBase"; } }; /** @endcond */ } #include "ThePEG/Handlers/StandardXComb.h" #endif /* ThePEG_MEBase_H */ diff --git a/MatrixElement/MECuts.cc b/MatrixElement/MECuts.cc --- a/MatrixElement/MECuts.cc +++ b/MatrixElement/MECuts.cc @@ -1,263 +1,263 @@ // -*- C++ -*- // // MECuts.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MECuts class. // #include "MECuts.h" #include "MECuts.xh" #include "ThePEG/EventRecord/SubProcess.h" #include "ThePEG/EventRecord/Collision.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/StandardMatchers.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/ClassDocumentation.h" using namespace ThePEG; MECuts::MECuts() : theMHatMin(2.0*GeV), theMHatMax(-1.0*GeV), thePTHatMin(ZERO), thePTHatMax(-1.0*GeV), thePTHatSingularMin(1.0*GeV), theSingularMassMax(1.0*GeV), theCTHMin(-1.0), theCTHMax(1.0), theTHatMin(ZERO), theTHatMax(-1.0*GeV2), theUHatMin(ZERO), theUHatMax(-1.0*GeV2), theScaleMin(ZERO), theScaleMax(-1.0*GeV2) {} void MECuts::newcut(const SubProcess &) const {} void MECuts::cut(const SubProcess & sp) const { newcut(sp); const ParticleVector & out = sp.outgoing(); int N = out.size(); if ( N < 1 ) throw MECutSetup(); if ( !sp.incoming().first || !sp.incoming().second ) throw MECutSetup(); // General cuts: if ( sp.shat() < sHatMin() || sp.shat() >= sHatMax() ) throw Veto(); // Now check 2->2 proceses: if ( N != 2 ) return; if ( -sp.that() < tHatMin() || -sp.that() >= tHatMax() ) throw Veto(); if ( -sp.uhat() < uHatMin() || -sp.uhat() >= uHatMax() ) throw Veto(); double cth = out[0]->momentum().cosTheta(); if ( cth < cTHMin() || cth >= cTHMax() ) throw Veto(); Energy pt = out[0]->momentum().perp(); if ( pt < pTHatMin() || pt >= pTHatMax() ) throw Veto(); } IBPtr MECuts::clone() const { return new_ptr(*this); } void MECuts::doupdate() { Interfaced::doupdate(); if ( cTHMax() <= cTHMin() ) throw MECutZeroInterval(*this, "CTHMax <= CTHMin"); } void MECuts::persistentOutput(PersistentOStream & os) const { os << ounit(theMHatMin, GeV) << ounit(theMHatMax, GeV) << ounit(thePTHatMin, GeV) << ounit(thePTHatMax, GeV) << ounit(thePTHatSingularMin, GeV) << ounit(theSingularMassMax, GeV) << theCTHMin << theCTHMax << ounit(theTHatMin, GeV2) << ounit(theTHatMax, GeV2) << ounit(theUHatMin, GeV2) << ounit(theUHatMax, GeV2) << ounit(theScaleMin, GeV2) << ounit(theScaleMax, GeV2); } void MECuts::persistentInput(PersistentIStream & is, int) { is >> iunit(theMHatMin, GeV) >> iunit(theMHatMax, GeV) >> iunit(thePTHatMin, GeV) >> iunit(thePTHatMax, GeV) >> iunit(thePTHatSingularMin, GeV) >> iunit(theSingularMassMax, GeV) >> theCTHMin >> theCTHMax >> iunit(theTHatMin, GeV2) >> iunit(theTHatMax, GeV2) >> iunit(theUHatMin, GeV2) >> iunit(theUHatMax, GeV2) >> iunit(theScaleMin, GeV2) >> iunit(theScaleMax, GeV2); } ClassDescription MECuts::initMECuts; void MECuts::Init() { static ClassDocumentation documentation ("There is no documentation for the ThePEG::MECuts class"); static Parameter interfaceMHatMin ("SubProcess/MHatMin", "The minimum value allowed for \\f$\\hat{m}=\\sqrt{\\hat{s}}\\f$ in GeV " "in the hard subprocess. If the upper limit in " "SubProcess/MHatMax " "is less than this, the upper limit is inactive. " "This limit is automatically checked by the event handler.", &MECuts::theMHatMin, GeV, 2.0*GeV, 1.0*MeV, Constants::MaxEnergy, false, false, true); static Parameter interfaceMHatMax ("SubProcess/MHatMax", "The minimum value allowed for \\f$\\hat{m}=\\sqrt{\\hat{s}}\\f$ in GeV " "in the hard subprocess If the lower limit in " "SubProcess/MHatMin " "is larger than this, the upper limit is inactive. " "This limit is automatically checked by the event handler.", &MECuts::theMHatMax, GeV, -1.0*GeV, -1.0*GeV, Constants::MaxEnergy, false, false, true); static Parameter interfacePTHatMin ("SubProcess/PTHatMin", "The minimum value allowed for \\f$\\hat{p_\\perp}\\f$ in GeV " "in the hard subprocess. If the upper limit in " "SubProcess/PTHatMax " "is less than this, the upper limit is inactive. " "This limit is automatically checked by the event handler", &MECuts::thePTHatMin, GeV, ZERO, ZERO, Constants::MaxEnergy, false, false, true); static Parameter interfacePTHatMax ("SubProcess/PTHatMax", "The minimum value allowed for \\f$\\hat{p_\\perp}\\f$ in GeV " "in the hard subprocess If the lower limit in " "SubProcess/PTHatMin " "is larger than this, the upper limit is inactive. " "This limit is automatically checked by the event handler.", &MECuts::thePTHatMax, GeV, -1.0*GeV, -1.0*GeV, Constants::MaxEnergy, false, false, true); static Parameter interfacePTHatSingularMin ("SubProcess/PTHatSingularMin", "The minimum value allowed for \\f$\\hat{p_\\perp}\\f$ in GeV for " "processes which are singular in the limit " "\\f$\\hat{p_\\perp}\\rightarrow 0\\f$. This " "cut is in addition to PTHatMin. Hard \\f$2\\rightarrow 2\\f$ " "processes which do not proceed via intermediate resonances are " "considered singular if either or both final-state products have a mass " "less than SingularMassMax. This limit is not checked " "automatically, but is assumed to be checked by the relevant " "ThePEG::PartonXSecFn objects.", &MECuts::thePTHatSingularMin, GeV, 1.0*GeV, ZERO, Constants::MaxEnergy, false, false, true); static Parameter interfaceSingularMassMax ("SubProcess/SingularMassMax", "Hard \\f$2\\rightarrow 2\\f$ processes which do not proceed via " "intermediate resonances are considered singular if either or both " "final-state products have a mass less than this limit (int GeV). " "For singular processes the aditional \\f$\\hat{p_\\perp}\\f$ cut in " "PTHatSingularMin should be applied. This limit is not " "checked automatically, but is assumed to be checked by the relevant " "ThePEG::PartonXSecFn objects.", &MECuts::theSingularMassMax, GeV, 1.0*GeV, ZERO, Constants::MaxEnergy, false, false, true); static Parameter interfaceCTHMin ("SubProcess/CosThetaHatMin", "The minimum allowed value of \\f$\\cos{\\hat{\\theta}}\\f$, where " "\\f$\\hat{\\theta}\\f$ is the scattering angle in the restframe of a " "hard \\f$2\\rightarrow 2\\f$ scattering. " "This limit is automatically checked by the event handler.", &MECuts::theCTHMin, -1.0, -1.0, 1.0, false, false, true, 0, 0, 0, &MECuts::cTHMax); static Parameter interfaceCTHMax ("SubProcess/CosThetaHatMax", "The maximum allowed value of \\f$\\cos{\\hat{\\theta}}\\f$, where " "\\f$\\hat{\\theta}\\f$ is the scattering angle in the restframe of a " "hard \\f$2\\rightarrow 2\\f$ scattering. " "This limit is automatically checked by the event handler.", &MECuts::theCTHMax, 1.0, -1.0, 1.0, false, false, true, 0, 0, &MECuts::cTHMin, 0); static Parameter interfaceTHatMin ("SubProcess/THatMin", "The minimum allowed value of \\f$|\\hat{t}|=-\\hat{t}\\f$ in " "GeV2 in a hard \\f$2\\rightarrow 2\\f$ scattering. If the " "upper limit in SubProcess/THatMax " "is less than this, the upper limit is inactive. " "This limit is automatically checked by the event handler.", &MECuts::theTHatMin, GeV2, ZERO, ZERO, Constants::MaxEnergy2, false, false, true); static Parameter interfaceTHatMax ("SubProcess/THatMax", "The maximum allowed value of \\f$|\\hat{t}|=-\\hat{t}\\f$ in " "GeV2 in a hard \\f$2\\rightarrow 2\\f$ scattering. If the " "lower limit in SubProcess/THatMin " "is larger than this, the upper limit is inactive. " "This limit is automatically checked by the event handler.", &MECuts::theTHatMax, GeV2, -1.0*GeV, -1.0*GeV, Constants::MaxEnergy2, false, false, true); static Parameter interfaceUHatMin ("SubProcess/UHatMin", "The minimum allowed value of \\f$|\\hat{u}|=-\\hat{u}\\f$ in " "GeV2 in a hard \\f$2\\rightarrow 2\\f$ scattering. If the " "upper limit in SubProcess/UHatMax " "is less than this, the upper limit is inactive. " "This limit is automatically checked by the event handler.", &MECuts::theUHatMin, GeV2, ZERO, ZERO, Constants::MaxEnergy2, false, false, true); static Parameter interfaceUHatMax ("SubProcess/UHatMax", "The maximum allowed value of \\f$|\\hat{u}|=-\\hat{u}\\f$ in " "GeV2 in a hard \\f$2\\rightarrow 2\\f$ scattering. If the " "lower limit in SubProcess/UHatMin " "is larger than this, the upper limit is inactive. " "This limit is automatically checked by the event handler.", &MECuts::theUHatMax, GeV2, -1.0*GeV, -1.0*GeV, Constants::MaxEnergy2, false, false, true); static Parameter interfaceScaleMin ("SubProcess/ScaleMin", "The minimum allowed value of the user-defined scale in GeV2 " "in a hard scattering. If the upper limit in " "SubProcess/ScaleMax " "is less than this, the upper limit is " "inactive. This limit is automatically checked by the event handler.", &MECuts::theScaleMin, GeV2, ZERO, ZERO, Constants::MaxEnergy2, false, false, true); static Parameter interfaceScaleMax ("SubProcess/ScaleMax", "The maximum allowed value of user defined scale in GeV2 in a " "hard scattering. If the lower limit in " "SubProcess/ScaleMin " "is larger than this, the upper limit is inactive. " "This limit is automatically checked by the event handler.", &MECuts::theScaleMax, GeV2, -1.0*GeV, -1.0*GeV, Constants::MaxEnergy2, false, false, true); } MECutSetup::MECutSetup() { theMessage << "MECuts was asked to check an icomplete " << "SubProcess/Collision/Event. This should never happen." << " the run will be aborted immediately."; severity(abortnow); } MECutZeroInterval::MECutZeroInterval(const MECuts & i, string s) { theMessage << "The MECuts object '" << i.name() << "' is not " << "Properly set up since an interval was non-existent :" << s << "."; severity(warning); } diff --git a/MatrixElement/MECuts.h b/MatrixElement/MECuts.h --- a/MatrixElement/MECuts.h +++ b/MatrixElement/MECuts.h @@ -1,313 +1,313 @@ // -*- C++ -*- // // MECuts.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_MECuts_H #define ThePEG_MECuts_H // This is the declaration of the MECuts class. #include "ThePEG/Interface/Interfaced.h" #include "ThePEG/Vectors/LorentzRotation.fh" #include "ThePEG/Utilities/Triplet.h" #include "ThePEG/PDT/StandardMatchers.h" namespace ThePEG { /** * The MECuts class is (currently not at all) used to make cuts on * generated phase space points for the hard interaction. A MECuts * object is selected for each matrix element. The EventHandler * has a default MECuts object, which may be overridden by the * selected SubProcessHandler object, which in turn may be overridden * by the selected MEBase object. * * The MECuts is used in two different ways. Individual handlers may * use the specific member functions which specify cuts on individual * variables. In addition the cut() member functions are always called * by the EventHandler to automatically check that all cuts are * passed. It is possible to derive new classes from the MECuts class, * in which case the virtual newcut() methods may be overridden and * will be called from the cut() methods. * * * @see EventHandler * @see SubProcessHandler * @see MEBase * @see Collision * @see SubProcess * */ class MECuts: public Interfaced { public: /** * Standard ctors and dtor */ MECuts(); public: /** * This method is called by the EventHandler with the primary * SubProcess provided in its cm frame. */ void cut(const SubProcess &) const; public: /** * The minimum and maximum values of the invariant mass (squared) of * the hard sub-process. */ Energy mHatMin() const { return theMHatMin; } /** * The minimum and maximum values of the invariant mass (squared) of * the hard sub-process. */ Energy mHatMax() const { theMHatMax > mHatMin()? theMHatMax: Constants::MaxEnergy; } /** * The minimum and maximum values of the invariant mass (squared) of * the hard sub-process. */ Energy sHatMin() const { return sqr(mHatMin()); } /** * The minimum and maximum values of the invariant mass (squared) of * the hard sub-process. */ Energy sHatMax() const { return sqr(mHatMax()); } /** * The minimum and maximum values of the transverse momentum of the * outgoing particles in the hard sub-process. */ Energy pTHatMin() const { return thePTHatMin; } /** * The minimum and maximum values of the transverse momentum of the * outgoing particles in the hard sub-process. */ Energy pTHatMax() const { return thePTHatMax > pTHatMin()? thePTHatMax: Constants::MaxEnergy; } /** * Additional cut on the transverse momenta of the hard sub-process * for s-channel hard sub-processes for outgoing particles of mass * less than singularMassMax(). */ Energy pTHatSingularMin() const { return thePTHatSingularMin; } /** * Additional cut on the transverse momenta of the hard sub-process * for s-channel hard sub-processes for outgoing particles of mass * less than singularMassMax(). */ Energy singularMassMax() const { return theSingularMassMax; } /** * The minimum and maximum value of cosine of the scattering angle * in the restframe of a hard 2->2 scattering. */ double cTHMin() const { return theCTHMin; } /** * The minimum and maximum value of cosine of the scattering angle * in the restframe of a hard 2->2 scattering. */ double cTHMax() const { return theCTHMax; } /** * The minimum and maximum value of that of a hard 2->2 scattering. */ Energy2 tHatMin() const { return theTHatMin; } /** * The minimum and maximum value of that of a hard 2->2 scattering. */ Energy2 tHatMax() const { return theTHatMax > tHatMin()? theTHatMax: Constants::MaxEnergy2; } /** * The minimum and maximum value of uhat of a hard 2->2 scattering. */ Energy2 uHatMin() const { return theUHatMin; } /** * The minimum and maximum value of uhat of a hard 2->2 scattering. */ Energy2 uHatMax() const { return theUHatMax > uHatMin()? theUHatMax: Constants::MaxEnergy2; } /** * The minimum and maximum value of the scale in a hard scattering * as defined by the Handlers which performed the hard scattering. */ Energy2 scaleMin() const { return theScaleMin; } /** * The minimum and maximum value of the scale in a hard scattering * as defined by the Handlers which performed the hard scattering. */ Energy2 scaleMax() const { return theScaleMax > scaleMin()? theScaleMax: Constants::MaxEnergy2; } public: /** * Standard functions for writing and reading from persistent streams. */ void persistentOutput(PersistentOStream &) const; /** * Standard functions for writing and reading from persistent streams. */ void persistentInput(PersistentIStream &, int); /** * Standard Init function used to initialize the interface. */ static void Init(); protected: /** * This method is called by the corresponding cut method with the * primary SubProcess provided in its cm frame. This bas-class * method does nothing. */ virtual void newcut(const SubProcess &) const; protected: /** * Standard Interfaced virtual functions. */ virtual void doupdate(); /** * Standard clone method. */ virtual IBPtr clone() const; private: /** * The minimum and maximum values of the invariant mass of * the hard sub-process. */ Energy theMHatMin; /** * The minimum and maximum values of the invariant mass of * the hard sub-process. */ Energy theMHatMax; /** * The minimum and maximum values of the transverse momentum of the * outgoing particles in the hard sub-process. */ Energy thePTHatMin; /** * The minimum and maximum values of the transverse momentum of the * outgoing particles in the hard sub-process. */ Energy thePTHatMax; /** * Additional cut on the transverse momenta of the hard sub-process * for s-channel hard sub-processes for outgoing particles of mass * less than theSingularMassMax. */ Energy thePTHatSingularMin; /** * Additional cut on the transverse momenta of the hard sub-process * for s-channel hard sub-processes for outgoing particles of mass * less than theSingularMassMax. */ Energy theSingularMassMax; /** * The minimum and maximum value of cosine of the scattering angle * in the restframe of a hard 2->2 scattering. */ double theCTHMin; /** * The minimum and maximum value of cosine of the scattering angle * in the restframe of a hard 2->2 scattering. */ double theCTHMax; /** * The minimum and maximum value of that of a hard 2->2 scattering. */ Energy2 theTHatMin; /** * The minimum and maximum value of that of a hard 2->2 scattering. */ Energy2 theTHatMax; /** * The minimum and maximum value of uhat of a hard 2->2 scattering. */ Energy2 theUHatMin; /** * The minimum and maximum value of uhat of a hard 2->2 scattering. */ Energy2 theUHatMax; /** * The minimum and maximum value of the scale in a hard scattering * as defined by the Handlers which performed the hard scattering. */ Energy2 theScaleMin; /** * The minimum and maximum value of the scale in a hard scattering * as defined by the Handlers which performed the hard scattering. */ Energy2 theScaleMax; private: /** * Describe a concrete class with persistent data. */ static ClassDescription initMECuts; /** * Private and non-existent assignment operator. */ MECuts & operator=(const MECuts &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** * This template specialization informs ThePEG about the base class of * MECuts. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the base class of MECuts. */ typedef Interfaced NthBase; }; /** * This template specialization informs ThePEG about the name of the * MECuts class. */ template <> struct ClassTraits: /** Return the class name. */ public ClassTraitsBase { static string className() { return "ThePEG::MECuts"; } }; /** @endcond */ } #endif /* ThePEG_MECuts_H */ diff --git a/MatrixElement/MECuts.xh b/MatrixElement/MECuts.xh --- a/MatrixElement/MECuts.xh +++ b/MatrixElement/MECuts.xh @@ -1,37 +1,37 @@ // -*- C++ -*- // // MECuts.xh is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_MECuts_XH #define ThePEG_MECuts_XH // // This is the declarations of the exception classes used by the // MECuts class. // #include "ThePEG/Interface/Command.xh" namespace ThePEG { /** @cond EXCEPTIONCLASSES */ /** Exception class used by MECuts to signal inconsistent cuts. */ struct MECutSetup: public Exception { /** Default constuctor. */ MECutSetup(); }; /** Exception class used by MECuts to signal zero intervals. */ struct MECutZeroInterval: public UpdateException { /** Standard constuctor. */ MECutZeroInterval(const MECuts &, string); }; /** @endcond */ } #endif /* ThePEG_MECuts_XH */ diff --git a/MatrixElement/MEGG2GG.cc b/MatrixElement/MEGG2GG.cc --- a/MatrixElement/MEGG2GG.cc +++ b/MatrixElement/MEGG2GG.cc @@ -1,98 +1,98 @@ // -*- C++ -*- // // MEGG2GG.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MEGG2GG class. // #include "MEGG2GG.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/PDT/EnumParticles.h" using namespace ThePEG; IBPtr MEGG2GG::clone() const { return new_ptr(*this); } IBPtr MEGG2GG::fullclone() const { return new_ptr(*this); } void MEGG2GG::getDiagrams() const { tcPDPtr g = getParticleData(ParticleID::g); add(new_ptr((Tree2toNDiagram(3), g, g, g, 1, g, 2, g, -1))); add(new_ptr((Tree2toNDiagram(3), g, g, g, 2, g, 1, g, -2))); add(new_ptr((Tree2toNDiagram(2), g, g, 1, g, 3, g, 3, g, -3))); } double MEGG2GG::me2() const { return 9.0*comfac()*((colA1() + colA2() + colB1() + colB2())*KfacA() + (colC1() + colC2())*Kfac())/16.0; } Selector MEGG2GG::colourGeometries(tcDiagPtr diag) const { static ColourLines ctST("1 -2 -3, 3 5, -5 2 4, -4 -1"); static ColourLines ctTS("1 4, -4 -2 5, -5 -3, 3 2 -1"); static ColourLines ctUT("1 -2 5, -5 -3, 3 2 4, -4 -1"); static ColourLines ctTU("1 4, -4 -2 -3, 3 5, -5 2 -1"); static ColourLines cuSU("1 -2 -3, 3 4, -4 2 5, -5 -1"); static ColourLines cuUS("1 5, -5 -2 4, -4 -3, 3 2 -1"); static ColourLines cuTU("1 -2 4, -4 -3, 3 2 5, -5 -1"); static ColourLines cuUT("1 5, -5 -2 -3, 3 4, -4 2 -1"); static ColourLines csTS("1 3 4, -4 5, -5 -3 -2, 2 -1"); static ColourLines csST("1 -2, 2 3 5, -5 4, -4 -3 -1"); static ColourLines csUS("1 3 5, -5 4, -4 -3 -2, 2 -1"); static ColourLines csSU("1 -2, 2 3 4, -4 5, -5 -3 -1"); Selector sel; if ( diag->id() == -1 ) { sel.insert(colA1(), &ctST); sel.insert(colA1(), &ctTS); sel.insert(colC2(), &ctUT); sel.insert(colC2(), &ctTU); } else if ( diag->id() == -2 ) { sel.insert(colB2(), &cuSU); sel.insert(colB2(), &cuUS); sel.insert(colC1(), &cuTU); sel.insert(colC1(), &cuUT); } else { sel.insert(colA2(), &csST); sel.insert(colA2(), &csTS); sel.insert(colB1(), &csSU); sel.insert(colB1(), &csUS); } return sel; } Selector MEGG2GG::diagrams(const DiagramVector & diags) const { Selector sel; for ( DiagramIndex i = 0; i < diags.size(); ++i ) if ( diags[i]->id() == -1 ) sel.insert(colA1() + colC2(), i); else if ( diags[i]->id() == -2 ) sel.insert(colC1() + colB2(), i); else sel.insert(colB1() + colA2(), i); return sel; } NoPIOClassDescription MEGG2GG::initMEGG2GG; // Definition of the static class description member. void MEGG2GG::Init() { static ClassDocumentation documentation ("The ThePEG::MEGG2GG class describes the standard QCD " "\\f$gg \\rightarrow gg\\f$ matrix element."); } diff --git a/MatrixElement/MEGG2GG.h b/MatrixElement/MEGG2GG.h --- a/MatrixElement/MEGG2GG.h +++ b/MatrixElement/MEGG2GG.h @@ -1,177 +1,177 @@ // -*- C++ -*- // // MEGG2GG.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_MEGG2GG_H #define ThePEG_MEGG2GG_H // This is the declaration of the MEGG2GG class. #include "ThePEG/MatrixElement/ME2to2QCD.h" namespace ThePEG { /** * MEGG2GG inherits from ME2to2QCD and implements the standard * \f$gg\rightarrow gg\f$ matrix element. * * @see \ref MEGG2GGInterfaces "The interfaces" * defined for MEGG2GG. * @see ME2to2QCD */ class MEGG2GG: public ME2to2QCD { public: /** @name Virtual functions required by the MEBase class. */ //@{ /** * The matrix element for the kinematical configuration * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. * @return the matrix element scaled with sHat() to give a * dimensionless number. */ virtual double me2() const; /** * Add all possible diagrams with the add() function. */ virtual void getDiagrams() 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; /** * 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; //@} protected: /** @name Internal functions returning the matrix element squared * for different colour configurations. */ //@{ /** * Return the matrix element squared (without common pre-factors) * for the specific colour configuration. */ double colA1() const { return sqr(1.0 + sHat()/tHat()) + 0.5; } /** * Return the matrix element squared (without common pre-factors) * for the specific colour configuration. */ double colB1() const { return sqr(1.0 + uHat()/sHat()) + 0.5; } /** * Return the matrix element squared (without common pre-factors) * for the specific colour configuration. */ double colC1() const { return sqr(1.0 + tHat()/uHat()) + 0.5; } /** * Return the matrix element squared (without common pre-factors) * for the specific colour configuration. */ double colA2() const { return 0.5 + sqr(1.0 + tHat()/sHat()); } /** * Return the matrix element squared (without common pre-factors) * for the specific colour configuration. */ double colB2() const { return 0.5 + sqr(1.0 + sHat()/uHat()); } /** * Return the matrix element squared (without common pre-factors) * for the specific colour configuration. */ double colC2() const { return 0.5 + sqr(1.0 + uHat()/tHat()); } //@} public: /** * Standard Init function used to initialize the interfaces. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * Describe a concrete class without persistent data. */ static NoPIOClassDescription initMEGG2GG; /** * Private and non-existent assignment operator. */ MEGG2GG & operator=(const MEGG2GG &) = delete; }; } namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of MEGG2GG. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of MEGG2GG. */ typedef ME2to2QCD NthBase; }; /** This template specialization informs ThePEG about the name of * the MEGG2GG 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::MEGG2GG"; } /** Return the name of the shared library be loaded to get * access to the MEGG2GG class and every other class it uses * (except the base class). */ static string library() { return "MEQCD.so"; } }; /** @endcond */ } #endif /* ThePEG_MEGG2GG_H */ diff --git a/MatrixElement/MEGG2QQ.cc b/MatrixElement/MEGG2QQ.cc --- a/MatrixElement/MEGG2QQ.cc +++ b/MatrixElement/MEGG2QQ.cc @@ -1,75 +1,75 @@ // -*- C++ -*- // // MEGG2QQ.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MEGG2QQ class. // #include "MEGG2QQ.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/PDT/EnumParticles.h" using namespace ThePEG; IBPtr MEGG2QQ::clone() const { return new_ptr(*this); } IBPtr MEGG2QQ::fullclone() const { return new_ptr(*this); } void MEGG2QQ::getDiagrams() const { tcPDPtr g = getParticleData(ParticleID::g); for ( int i = 1; i <= maxFlavour(); ++i ) { tcPDPtr q = getParticleData(i); tcPDPtr qb = q->CC(); add(new_ptr((Tree2toNDiagram(3), g, q, g, 1, q, 2, qb, -1))); add(new_ptr((Tree2toNDiagram(3), g, qb, g, 2, q, 1, qb, -2))); } } double MEGG2QQ::me2() const { return comfac()*(colA() + colB())*KfacA()/12.0; } Selector MEGG2QQ::colourGeometries(tcDiagPtr diag) const { static ColourLines ctST("1 4, -5 -3, 3 2 -1"); static ColourLines cuSU("1 -2 -3, 3 4, -5 -1"); Selector sel; if ( diag->id() == -1 ) sel.insert(1.0, &ctST); else sel.insert(1.0, &cuSU); return sel; } Selector MEGG2QQ::diagrams(const DiagramVector & diags) const { Selector sel; for ( DiagramIndex i = 0; i < diags.size(); ++i ) if ( diags[i]->id() == -1 ) sel.insert(colA(), i); else if ( diags[i]->id() == -2 ) sel.insert(colB(), i); return sel; } NoPIOClassDescription MEGG2QQ::initMEGG2QQ; // Definition of the static class description member. void MEGG2QQ::Init() { static ClassDocumentation documentation ("The ThePEG::MEGG2QQ class describes the standard QCD " "\\f$gg\\rightarrow q\\bar{q}\\f$ matrix element."); } diff --git a/MatrixElement/MEGG2QQ.h b/MatrixElement/MEGG2QQ.h --- a/MatrixElement/MEGG2QQ.h +++ b/MatrixElement/MEGG2QQ.h @@ -1,159 +1,159 @@ // -*- C++ -*- // // MEGG2QQ.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_MEGG2QQ_H #define ThePEG_MEGG2QQ_H // This is the declaration of the MEGG2QQ class. #include "ThePEG/MatrixElement/ME2to2QCD.h" namespace ThePEG { /** * MEGG2QQ inherits from ME2to2QCD and implements the standard * \f$gg\rightarrow gq\bar{q}\f$ matrix element. * * @see \ref MEGG2QQInterfaces "The interfaces" * defined for MEGG2QQ. * @see ME2to2QCD */ class MEGG2QQ: public ME2to2QCD { public: /** @name Virtual functions required by the MEBase class. */ //@{ /** * The matrix element for the kinematical configuration * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. * @return the matrix element scaled with sHat() to give a * dimensionless number. */ virtual double me2() const; /** * Add all possible diagrams with the add() function. */ virtual void getDiagrams() 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; /** * 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; //@} protected: /** @name Internal functions returning the matrix element squared * for different colour configurations. */ //@{ /** * Return the matrix element squared (without common pre-factors) * for the specific colour configuration. */ double colA() const { return uHat()/tHat() - 2.0*sqr(uHat()/sHat()); } /** * Return the matrix element squared (without common pre-factors) * for the specific colour configuration. */ double colB() const { return tHat()/uHat() - 2.0*sqr(tHat()/sHat()); } //@} public: /** * Standard Init function used to initialize the interfaces. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * Describe a concrete class without persistent data. */ static NoPIOClassDescription initMEGG2QQ; /** * Private and non-existent assignment operator. */ MEGG2QQ & operator=(const MEGG2QQ &) = delete; }; } namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of MEGG2QQ. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of MEGG2QQ. */ typedef ME2to2QCD NthBase; }; /** This template specialization informs ThePEG about the name of * the MEGG2QQ 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::MEGG2QQ"; } /** Return the name of the shared library be loaded to get * access to the MEGG2QQ class and every other class it uses * (except the base class). */ static string library() { return "MEQCD.so"; } }; /** @endcond */ } #endif /* ThePEG_MEGG2QQ_H */ diff --git a/MatrixElement/MEGroup.cc b/MatrixElement/MEGroup.cc --- a/MatrixElement/MEGroup.cc +++ b/MatrixElement/MEGroup.cc @@ -1,214 +1,214 @@ // -*- C++ -*- // // MEGroup.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad -// Copyright (C) 2009-2017 Simon Platzer +// Copyright (C) 1999-2019 Leif Lonnblad +// Copyright (C) 2009-2019 Simon Platzer // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MEGroup class. // #include "MEGroup.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/Utilities/Rebinder.h" #include "ThePEG/PDF/PartonBin.h" #include "ThePEG/PDF/PartonExtractor.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Handlers/StdXCombGroup.h" using namespace ThePEG; MEGroup::MEGroup() : theDependent(), theNDimMap(), theNDim(0) {} MEGroup::~MEGroup() {} void MEGroup::doinit() { MEBase::doinit(); head()->init(); for ( MEVector::iterator me = theDependent.begin(); me != theDependent.end(); ++me ) (**me).init(); use(head()); theNDim = head()->nDim(); if (!uniformAdditional()) { int off = theNDim; for ( MEVector::iterator me = theDependent.begin(); me != theDependent.end(); ++me ) if ( (**me).nDim() > head()->nDim() ) { theNDimMap[*me] = off; off += ((**me).nDim() - head()->nDim()); theNDim += ((**me).nDim() - head()->nDim()); } } else { int maxadd = 0; for ( MEVector::iterator me = theDependent.begin(); me != theDependent.end(); ++me ) if ( (**me).nDim() - head()->nDim() > maxadd ) { maxadd = ((**me).nDim() - head()->nDim()); } theNDim += maxadd; } } void MEGroup::doinitrun() { MEBase::doinitrun(); head()->initrun(); for ( MEVector::iterator me = theDependent.begin(); me != theDependent.end(); ++me ) (**me).initrun(); } void MEGroup::rebind(const TranslationMap & trans) { map rebound; for (map::iterator it = theNDimMap.begin(); it != theNDimMap.end(); ++it) { rebound.insert(make_pair(trans.translate(it->first),it->second)); } theNDimMap = rebound; MEBase::rebind(trans); } IVector MEGroup::getReferences() { IVector ret = MEBase::getReferences(); for (map::iterator it = theNDimMap.begin(); it != theNDimMap.end(); ++it) ret.push_back(it->first); return ret; } int MEGroup::dependentOffset(tMEPtr dep) const { if ( uniformAdditional() ) return head()->nDim(); map::const_iterator it = theNDimMap.find(dep); if (it == theNDimMap.end()) return 0; return it->second; } StdXCombPtr MEGroup::makeXComb(Energy newMaxEnergy, const cPDPair & inc, tEHPtr newEventHandler,tSubHdlPtr newSubProcessHandler, tPExtrPtr newExtractor, tCascHdlPtr newCKKW, const PBPair & newPartonBins, tCutsPtr newCuts, const DiagramVector & newDiagrams, bool mir, const PartonPairVec& allPBins, tStdXCombPtr newHead, tMEPtr newME) { tMEGroupPtr newMEGroup = dynamic_ptr_cast(newME); if ( !newMEGroup ) newMEGroup = this; StdXCombGroupPtr res = new_ptr(StdXCombGroup(newMaxEnergy, inc, newEventHandler, newSubProcessHandler, newExtractor, newCKKW, newPartonBins, newCuts, newMEGroup, newDiagrams, mir, newHead)); res->build(allPBins); return res; } vector MEGroup::makeDependentXCombs(tStdXCombPtr xcHead, const cPDVector& proc, tMEPtr depME, const PartonPairVec& pbs) const { MEBase::DiagramVector depDiags = dependentDiagrams(proc,depME); if ( depDiags.empty() ) return vector(); map depProcs; for ( MEBase::DiagramVector::const_iterator d = depDiags.begin(); d != depDiags.end(); ++d ) { depProcs[(**d).partons()].push_back(*d); } vector ret; for ( map::const_iterator pr = depProcs.begin(); pr != depProcs.end(); ++pr ) { PartonPairVec::const_iterator ppit = pbs.begin(); for ( ; ppit != pbs.end(); ++ppit ) { if ( ppit->first->parton() == pr->second.front()->partons()[0] && ppit->second->parton() == pr->second.front()->partons()[1] ) break; } if ( ppit == pbs.end() ) { generator()->logWarning( Exception() << "Could not create a dependent XComb object" << " for the MEGroup '" << name() << "' since the dependent matrix element '" << depME->name() << "' did not match any of the incoming partons." << Exception::warning); continue; } StdXCombPtr dxc = depME->makeXComb(xcHead,*ppit,pr->second); ret.push_back(dxc); } return ret; } bool MEGroup::generateKinematics(const double * r) { if (!head()->generateKinematics(r)) return false; return true; } void MEGroup::clearKinematics() { MEBase::clearKinematics(); head()->clearKinematics(); for ( MEVector::iterator me = theDependent.begin(); me != theDependent.end(); ++me ) (**me).clearKinematics(); } void MEGroup::persistentOutput(PersistentOStream & os) const { os << theHead << theDependent << theNDimMap << theNDim; } void MEGroup::persistentInput(PersistentIStream & is, int) { is >> theHead >> theDependent >> theNDimMap >> theNDim; } AbstractClassDescription MEGroup::initMEGroup; // Definition of the static class description member. void MEGroup::Init() { static ClassDocumentation documentation ("The ThePEG::MEGroup class is the base class for all matrix elements " "to be used for generating sub process groups in ThePEG"); static Reference interfaceHead ("Head", "The head matrix element for this matrix element group.", &MEGroup::theHead, false, false, true, false, false); static RefVector interfaceDependent ("Dependent", "The vector of dependent matrix elements in this matrix element group.", &MEGroup::theDependent, -1, false, false, true, false, false); } diff --git a/MatrixElement/MEGroup.h b/MatrixElement/MEGroup.h --- a/MatrixElement/MEGroup.h +++ b/MatrixElement/MEGroup.h @@ -1,527 +1,527 @@ // -*- C++ -*- // // MEGroup.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad -// Copyright (C) 2009-2017 Simon Platzer +// Copyright (C) 1999-2019 Leif Lonnblad +// Copyright (C) 2009-2019 Simon Platzer // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_MEGroup_H #define ThePEG_MEGroup_H // This is the declaration of the MEGroup class. #include "ThePEG/MatrixElement/MEBase.h" #include "ThePEG/Cuts/Cuts.fh" #include "MEGroup.fh" namespace ThePEG { /** * The MEGroup class represents a 'head' matrix element * in association with a group of dependent matrix elements. * It basically acts as a wrapper around its head matrix element * however supplying additional information to the corresponding * StdXCombGroup object. * * @see StdXCombGroup * */ class MEGroup: public MEBase { public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ MEGroup(); /** * Destructor. */ virtual ~MEGroup(); //@} public: /** @name Virtual functions from MEBase. */ //@{ /** * Return the order in \f$\alpha_S\f$ in which this matrix element * is given. */ virtual unsigned int orderInAlphaS() const { return head()->orderInAlphaS(); } /** * Return the order in \f$\alpha_{EM}\f$ in which this matrix * element is given. Returns 0. */ virtual unsigned int orderInAlphaEW() const { return head()->orderInAlphaEW(); } /** * Return the matrix element for the kinematical configuation * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. */ virtual double me2() const { return head()->me2(); } /** * Return the scale associated with the phase space point provided * by the last call to setKinematics(). */ virtual Energy2 scale() const { return head()->scale(); } /** * Return the value of \f$\alpha_S\f$ associated with the phase * space point provided by the last call to setKinematics(). This * versions returns SM().alphaS(scale()). */ virtual double alphaS() const { return head()->alphaS(); } /** * Return the value of \f$\alpha_EM\f$ associated with the phase * space point provided by the last call to setKinematics(). This * versions returns SM().alphaEM(scale()). */ virtual double alphaEM() const { return head()->alphaEM(); } /** * Set the typed and momenta of the incoming and outgoing partons to * be used in subsequent calls to me() and colourGeometries() * according to the associated XComb object. If the function is * overridden in a sub class the new function must call the base * class one first. */ virtual void setKinematics() { MEBase::setKinematics(); head()->setKinematics(); } /** * construct the spin information for the interaction */ virtual void constructVertex(tSubProPtr sub) { head()->constructVertex(sub); } /** * construct the spin information for the interaction */ virtual void constructVertex(tSubProPtr sub, const ColourLines* cl) { head()->constructVertex(sub,cl); } /** * The number of internal degreed of freedom used in the matrix * element. This default version returns 0; */ virtual int nDim() const { return theNDim; } /** * Generate internal degrees of freedom given nDim() uniform random * numbers in the interval ]0,1[. To help the phase space generator, * the 'dSigHatDR' should be a smooth function of these numbers, * although this is not strictly necessary. The return value should * be true of the generation succeeded. If so the generated momenta * should be stored in the meMomenta() vector. */ virtual bool generateKinematics(const double * r); /** * Return true, if this matrix element expects * the incoming partons in their center-of-mass system */ virtual bool wantCMS () const { return head()->wantCMS(); } /** * Return the matrix element squared differential in the variables * given by the last call to generateKinematics(). */ virtual CrossSection dSigHatDR() const { return head()->dSigHatDR(); } /** * Return true, if this matrix element will generate momenta for the * incoming partons itself. The matrix element is required to store * the incoming parton momenta in meMomenta()[0,1]. No mapping in * tau and y is performed by the PartonExtractor object, if a * derived class returns true here. The phase space jacobian is to * include a factor 1/(x1 x2). */ virtual bool haveX1X2() const { return head()->haveX1X2(); } /** * Return true, if this matrix element provides the PDF * weight for the first incoming parton itself. */ virtual bool havePDFWeight1 () const { return head()->havePDFWeight1(); } /** * Return true, if this matrix element provides the PDF * weight for the second incoming parton itself. */ virtual bool havePDFWeight2 () const { return head()->havePDFWeight2(); } /** * Return true, if the XComb steering this matrix element * should keep track of the random numbers used to generate * the last phase space point */ virtual bool keepRandomNumbers() const { return head()->keepRandomNumbers(); } /** * Comlete a SubProcess object using the internal degrees of freedom * generated in the last generateKinematics() (and possible other * degrees of freedom which was intergated over in dSigHatDR(). This * default version does nothing. Will be made purely virtual in the * future. */ virtual void generateSubCollision(SubProcess & sub) { head()->generateSubCollision(sub); } /** * Clear the information previously provided by a call to * setKinematics(...). */ virtual void clearKinematics(); /** * Add all possible diagrams with the add() function. */ virtual void getDiagrams() const { head()->diagrams(); useDiagrams(head()); } /** * Return true, if this matrix element does not want to * make use of mirroring processes; in this case all * possible partonic subprocesses with a fixed assignment * of incoming particles need to be provided through the diagrams * added with the add(...) method. */ virtual bool noMirror () const { return head()->noMirror(); } /** * Return a Selector with possible colour geometries for the selected * diagram weighted by their relative probabilities. */ virtual Selector colourGeometries(tcDiagPtr diag) const { return head()->colourGeometries(diag); } /** * Select a ColpurLines geometry. The default version returns a * colour geometry selected among the ones returned from * colourGeometries(tcDiagPtr). */ virtual const ColourLines & selectColourGeometry(tcDiagPtr diag) const { return head()->selectColourGeometry(diag); } /** * 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. */ virtual Selector diagrams(const DiagramVector & dv) const { return head()->diagrams(dv); } /** * Select a diagram. Default version uses diagrams(const * DiagramVector &) to select a diagram according to the * weights. This is the only method used that should be outside of * MEBase. */ virtual DiagramIndex diagram(const DiagramVector & dv) const { DiagramIndex res = head()->diagram(dv); return res; } /** * Set the XComb object to be used in the next call to * generateKinematics() and dSigHatDR(). */ virtual void setXComb(tStdXCombPtr xc) { MEBase::setXComb(xc); head()->setXComb(xc); } /** * If this matrix element is to be used 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. */ virtual int maxMultCKKW() const { return head()->maxMultCKKW(); } /** * If this matrix element is to be used 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. */ virtual int minMultCKKW() const { return head()->minMultCKKW(); } /** * If this matrix element is to be used together with others for * CKKW reweighting and veto, this will set the multiplicity of * outgoing particles in the highest multiplicity matrix element in * the group. */ virtual void maxMultCKKW(int mult) { head()->maxMultCKKW(mult); } /** * If this matrix element is to be used together with others for * CKKW reweighting and veto, this will set the multiplicity of * outgoing particles in the lowest multiplicity matrix element in * the group. */ virtual void minMultCKKW(int mult) { head()->minMultCKKW(mult); } /** * Inform this matrix element that a new phase space * point is about to be generated, so all caches should * be flushed. */ virtual void flushCaches() { head()->flushCaches(); } /** * Collect information on the last evaluated phasespace * point for verification or debugging purposes. This * only called, if the StdXCombGroup did accumulate * a non-zero cross section from this ME group. */ virtual void lastEventStatistics() {} //@} public: /** * Return the head matrix element. */ tMEPtr head() const { return theHead; } /** * Visit the dependent matrix elements */ const MEVector& dependent() const { return theDependent; } /** * Set the head matrix element. */ void head(tMEPtr me) { theHead = me; } /** * Access the dependent matrix elements */ MEVector& dependent() { return theDependent; } /** * Return the random number offset to access the random * numbers provided for the given matrix element to generate * dependent kinematics. */ int dependentOffset(tMEPtr dep) const; /** * For the given event generation setup return an xcomb object * appropriate to this matrix element. */ virtual StdXCombPtr makeXComb(Energy newMaxEnergy, const cPDPair & inc, tEHPtr newEventHandler,tSubHdlPtr newSubProcessHandler, tPExtrPtr newExtractor, tCascHdlPtr newCKKW, const PBPair & newPartonBins, tCutsPtr newCuts, const DiagramVector & newDiagrams, bool mir, const PartonPairVec& allPBins, tStdXCombPtr newHead = tStdXCombPtr(), tMEPtr newME = tMEPtr()); /** * Create a dependent xcomb object to be used * for the given process steered bythe head object and * dependent matrix element. */ virtual vector makeDependentXCombs(tStdXCombPtr xcHead, const cPDVector& proc, tMEPtr depME, const PartonPairVec& allPBins) const; /** * Fill the projectors object of xcombs to choose subprocesses * different than the one currently integrated. */ virtual void fillProjectors() { head()->fillProjectors(); } /** * Return true, if projectors will be used */ virtual bool willProject() const { return false; } /** * Return true, if this MEGroup will reweight the contributing cross * sections. */ virtual bool groupReweighted() const { return false; } /** * Reweight the head cross section */ virtual double reweightHead(const vector&) { return 1.; } /** * Reweight the dependent cross section */ virtual double reweightDependent(tStdXCombPtr, const vector&) { return 1.; } /** * Return true, if SubProcessGroups should be * setup from this MEGroup. If not, a single SubProcess * is constructed from the data provided by the * head matrix element. */ virtual bool subProcessGroups() const { return true; } public: /** * Return true, if the same additional random numbers * should be presented to any of the dependent * matrix elements. */ virtual bool uniformAdditional() const = 0; /** * Given a process from the head matrix element, * return a list of diagrams which should be considered for * the given dependent matrix element. */ virtual MEBase::DiagramVector dependentDiagrams(const cPDVector& proc, tMEPtr depME) const = 0; 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(); 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(); /** * 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(); //@} private: /** * The head matrix element. */ MEPtr theHead; /** * The dependent matrix elements. */ MEVector theDependent; /** * Offsets to access additional random numbers * required by the dependent matrix elements. */ map theNDimMap; /** * The total number of random numbers required. */ int theNDim; private: /** * Describe a class with persistent data. */ static AbstractClassDescription initMEGroup; /** * Private and non-existent assignment operator. */ MEGroup & operator=(const MEGroup &) = delete; }; } namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** * This template specialization informs ThePEG about the base class of * MEGroup. */ template <> struct BaseClassTrait { /** Typedef of the base class of MEGroup. */ typedef MEBase NthBase; }; /** * This template specialization informs ThePEG about the name of the * MEGroup class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return the class name. */ static string className() { return "ThePEG::MEGroup"; } }; /** @endcond */ } #endif /* ThePEG_MEGroup_H */ diff --git a/MatrixElement/MENCDIS.cc b/MatrixElement/MENCDIS.cc --- a/MatrixElement/MENCDIS.cc +++ b/MatrixElement/MENCDIS.cc @@ -1,163 +1,163 @@ // -*- C++ -*- // // MENCDIS.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MENCDIS class. // #include "MENCDIS.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/StandardModel/StandardModelBase.h" #include "ThePEG/Handlers/StandardXComb.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG; MENCDIS::MENCDIS() : mZ2(ZERO) {} MENCDIS::MENCDIS(const MENCDIS & x) : ME2to2QCD(x), mZ2(x.mZ2) {} MENCDIS::~MENCDIS() {} unsigned int MENCDIS::orderInAlphaS() const { return 0; } unsigned int MENCDIS::orderInAlphaEW() const { return 2; } void MENCDIS::getDiagrams() const { tcPDPtr gamma = getParticleData(ParticleID::gamma); tcPDPtr Z0 = getParticleData(ParticleID::Z0); tcPDPtr ep = getParticleData(ParticleID::eplus); tcPDPtr em = getParticleData(ParticleID::eminus); for ( int i = -maxFlavour(); i <= maxFlavour(); ++i ) { if ( !i ) continue; tcPDPtr q = getParticleData(i); add(new_ptr((Tree2toNDiagram(3), q, gamma, em, 1, q, 2, em, -1))); add(new_ptr((Tree2toNDiagram(3), q, Z0, em, 1, q, 2, em, -2))); add(new_ptr((Tree2toNDiagram(3), q, gamma, ep, 1, q, 2, ep, -1))); add(new_ptr((Tree2toNDiagram(3), q, Z0, ep, 1, q, 2, ep, -2))); } } Energy2 MENCDIS::scale() const { return -tHat(); } double MENCDIS::me2() const { double lastG = 0.0; double lastIntr = 0.0; double lastZ = 0.0; //pq is a vector in the same direction as the quark with zero mass. Lorentz5Momentum pq = meMomenta()[0]; pq.setMass(ZERO); pq.rescaleEnergy(); double y = 1.0 - pq.dot(meMomenta()[3]) / pq.dot(meMomenta()[1]); Energy4 F2Coeff = sqr(sHat()) * (1 + sqr(1-y)); Energy4 F3Coeff = sqr(sHat()) * (1 - sqr(1-y)); double C = 16 * SM().sin2ThetaW() * ( 1.0 - SM().sin2ThetaW() ); if(mePartonData()[0]->id() < 0){ F3Coeff = -F3Coeff; } if(mePartonData()[1]->id() < 0){ F3Coeff = -F3Coeff; } if( abs(mePartonData()[0]->id())%2 == 0 ){ lastG = F2Coeff * sqr(SM().eu()) / sqr(tHat()); lastIntr = -2*SM().eu()*(F2Coeff*SM().ve()*SM().vu() + 2*F3Coeff*SM().ae()*SM().au()) / (-tHat() * (-tHat() + mZ2) * C); lastZ = ( F2Coeff * (sqr(SM().ae())+sqr(SM().ve())) * (sqr(SM().au())+sqr(SM().vu())) + 4.0 * F3Coeff*SM().ve()* SM().ae()*SM().au()*SM().vu() ) / sqr((-tHat() + mZ2) * C); } else{ lastG = F2Coeff * sqr(SM().ed()) / sqr(tHat()); lastIntr = -2*SM().ed()*(F2Coeff*SM().ve()*SM().vd() + 2*F3Coeff*SM().ae()*SM().ad()) / (-tHat() * (-tHat() + mZ2) * C); lastZ = ( F2Coeff * (sqr(SM().ae())+sqr(SM().ve())) * (sqr(SM().ad())+sqr(SM().vd())) + 4.0 * F3Coeff*SM().ve()* SM().ae()*SM().ad()*SM().vd() ) / sqr((-tHat() + mZ2) * C); } DVector save; meInfo(save << lastG << lastZ); return (lastG + lastIntr + lastZ) * sqr(SM().alphaEM(scale())) * 32.0 * sqr(Constants::pi); } Selector MENCDIS::diagrams(const DiagramVector & diags) const { if ( lastXCombPtr() ) { lastG = meInfo()[0]; lastZ = meInfo()[1]; } Selector sel; for ( DiagramIndex i = 0; i < diags.size(); ++i ) { if ( diags[i]->id() == -1 ) sel.insert(lastG, i); else if ( diags[i]->id() == -2 ) sel.insert(lastZ, i); } return sel; } Selector MENCDIS::colourGeometries(tcDiagPtr diag) const { static ColourLines c("1 4"); static ColourLines cb("-1 -4"); Selector sel; if ( diag->partons()[0]->id() > 0 ) sel.insert(1.0, &c); else sel.insert(1.0, &cb); return sel; } IBPtr MENCDIS::clone() const { return new_ptr(*this); } IBPtr MENCDIS::fullclone() const { return new_ptr(*this); } void MENCDIS::doinit() { ME2to2QCD::doinit(); tcPDPtr Z0 = getParticleData(ParticleID::Z0); mZ2 = sqr(Z0->mass()); } void MENCDIS::persistentOutput(PersistentOStream & os) const { os << ounit(mZ2, GeV2) << lastG << lastZ; } void MENCDIS::persistentInput(PersistentIStream & is, int) { is >> iunit(mZ2, GeV2) >> lastG >> lastZ; } ClassDescription MENCDIS::initMENCDIS; void MENCDIS::Init() { static ClassDocumentation documentation ("The ThePEG::MENCDIS class implements the full" "\\f$e^\\pm q \\rightarrow e^\\pm q\\f$ " "matrix element including the interference terms."); } diff --git a/MatrixElement/MENCDIS.h b/MatrixElement/MENCDIS.h --- a/MatrixElement/MENCDIS.h +++ b/MatrixElement/MENCDIS.h @@ -1,215 +1,215 @@ // -*- C++ -*- // // MENCDIS.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_MENCDIS_H #define ThePEG_MENCDIS_H // This is the declaration of the MENCDIS class. #include "ThePEG/MatrixElement/ME2to2QCD.h" // #include "MENCDIS.fh" // #include "MENCDIS.xh" namespace ThePEG { /** * The MENCDIS class implements the \f$e^\pm q\rightarrow e^\pm q\f$ * matrix element. Both the gamma and \f$Z^0\f$ terms as well * as the interference term is included. Although not a strict QCD * matrix element the class inherits from ME2to2QCD, mainly to inherit * the parameter for the number of active quark flavours. * * @see \ref MENCDISInterfaces "The interfaces" * defined for MENCDIS. * @see ME2to2QCD */ class MENCDIS: public ME2to2QCD { public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ MENCDIS(); /** * Copy-constructor. */ MENCDIS(const MENCDIS &); /** * Destructor. */ virtual ~MENCDIS(); //@} public: /** @name Virtual functions required by the MEBase class. */ //@{ /** * Return the order in \f$\alpha_S\f$ in which this matrix element * is given. Returns . */ virtual unsigned int orderInAlphaS() const; /** * Return the order in \f$\alpha_{EM}\f$ in which this matrix * element is given. Returns 2. */ virtual unsigned int orderInAlphaEW() const; /** * The matrix element for the kinematical configuration * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. * @return the matrix element scaled with sHat() to give a * dimensionless number. */ virtual double me2() const; /** * Add all possible diagrams with the add() function. */ virtual void getDiagrams() 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; /** * 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 the scale associated with the last set phase space point. */ virtual Energy2 scale() const; //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interface. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); //@} protected: /** * The squared mass of the Z0. */ Energy2 mZ2; /** * The last gamma term to be used to select primary diagram. */ mutable double lastG; /** * The last Z0 term to be used to select primary diagram. */ mutable double lastZ; private: /** * Describe a concrete class with persistent data. */ static ClassDescription initMENCDIS; /** * Private and non-existent assignment operator. */ MENCDIS & operator=(const MENCDIS &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of MENCDIS. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of MENCDIS. */ typedef ME2to2QCD NthBase; }; /** This template specialization informs ThePEG about the name of the * MENCDIS 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::MENCDIS"; } /** Return the name of the shared library be loaded to get * access to the MENCDIS class and every other class it uses * (except the base class). */ static string library() { return "MENCDIS.so"; } }; /** @endcond */ } #endif /* ThePEG_MENCDIS_H */ diff --git a/MatrixElement/MEQG2QG.cc b/MatrixElement/MEQG2QG.cc --- a/MatrixElement/MEQG2QG.cc +++ b/MatrixElement/MEQG2QG.cc @@ -1,98 +1,98 @@ // -*- C++ -*- // // MEQG2QG.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MEQG2QG class. // #include "MEQG2QG.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/Utilities/Exception.h" using namespace ThePEG; IBPtr MEQG2QG::clone() const { return new_ptr(*this); } IBPtr MEQG2QG::fullclone() const { return new_ptr(*this); } void MEQG2QG::getDiagrams() const { tcPDPtr g = getParticleData(ParticleID::g); for ( int i = -maxFlavour(); i <= maxFlavour(); ++i ) { if ( i == 0 ) continue; tcPDPtr q = getParticleData(i); tcPDPtr qb = q->CC(); add(new_ptr((Tree2toNDiagram(3), q, g, g, 1, q, 2, g, -1))); add(new_ptr((Tree2toNDiagram(3), q, q, g, 2, q, 1, g, -2))); add(new_ptr((Tree2toNDiagram(2), q, g, 1, q, 3, q, 3, g, -3))); } } double MEQG2QG::me2() const { return 2.0*comfac()*((colA1() + colA2())*KfacA() + (colB1() + colB2())*Kfac())/9.0; } Selector MEQG2QG::colourGeometries(tcDiagPtr diag) const { static ColourLines ctST("1 -2 -3, 3 5, -5 2 4"); static ColourLines ctTS("-4 -2 5, -5 -3, 3 2 -1"); static ColourLines ctUT("1 -2 5, -5 -3, 3 4"); static ColourLines ctTU("-4 -3, 3 5, -5 2 -1"); static ColourLines cuTU("1 5, -5 2 -3, 3 4"); static ColourLines cuUT("-4 -3, 3 -2 5, -1 -5"); static ColourLines csST("1 -2, 2 3 5, -5 4"); static ColourLines csTS("-4 5, -5 -3 -2, 2 -1"); Selector sel; int q = diag->partons()[0]->id(); if ( diag->id() == -1 ) { if ( q > 0 ) { sel.insert(colA1(), &ctST); sel.insert(colB1(), &ctUT); } else { sel.insert(colA1(), &ctTS); sel.insert(colB1(), &ctTU); } } else if ( diag->id() == -2 ) { if ( q > 0 ) sel.insert(1.0, &cuTU); else sel.insert(1.0, &cuUT); } else { if ( q > 0 ) sel.insert(1.0, &csST); else sel.insert(1.0, &csTS); } return sel; } Selector MEQG2QG::diagrams(const DiagramVector & diags) const { Selector sel; for ( DiagramIndex i = 0; i < diags.size(); ++i ) if ( diags[i]->id() == -1 ) sel.insert(colA1() + colB1(), i); else if ( diags[i]->id() == -2 ) sel.insert(colB2(), i); else sel.insert(colA2(), i); return sel; } NoPIOClassDescription MEQG2QG::initMEQG2QG; // Definition of the static class description member. void MEQG2QG::Init() { static ClassDocumentation documentation ("The ThePEG::MEQG2QG class describes the standard QCD " "\\f$qg\\rightarrow qg\\f$ matrix element."); } diff --git a/MatrixElement/MEQG2QG.h b/MatrixElement/MEQG2QG.h --- a/MatrixElement/MEQG2QG.h +++ b/MatrixElement/MEQG2QG.h @@ -1,171 +1,171 @@ // -*- C++ -*- // // MEQG2QG.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_MEQG2QG_H #define ThePEG_MEQG2QG_H // This is the declaration of the MEQG2QG class. #include "ThePEG/MatrixElement/ME2to2QCD.h" namespace ThePEG { /** * MEQG2QG inherits from ME2to2QCD and implements the * standard \f$qg\rightarrow qg\f$ matrix element. * * @see \ref MEQG2QGInterfaces "The interfaces" * defined for MEQG2QG. * @see ME2to2QCD */ class MEQG2QG: public ME2to2QCD { public: /** @name Virtual functions required by the MEBase class. */ //@{ /** * The matrix element for the kinematical configuration * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. * @return the matrix element scaled with sHat() to give a * dimensionless number. */ virtual double me2() const; /** * Add all possible diagrams with the add() function. */ virtual void getDiagrams() 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; /** * 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; //@} protected: /** @name Internal functions returning the matrix element squared * for different colour configurations. */ //@{ /** * Return the matrix element squared (without common pre-factors) * for the specific colour configuration. */ double colA1() const { return ( interference()? 2.25: 2.0 )*sqr(uHat()/tHat()); } /** * Return the matrix element squared (without common pre-factors) * for the specific colour configuration. */ double colB1() const { return ( interference()? 2.25: 2.0 )*sqr(sHat()/tHat()); } /** * Return the matrix element squared (without common pre-factors) * for the specific colour configuration. */ double colA2() const { return -uHat()/sHat(); } /** * Return the matrix element squared (without common pre-factors) * for the specific colour configuration. */ double colB2() const { return -sHat()/uHat(); } //@} public: /** * Standard Init function used to initialize the interfaces. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * Describe a concrete class without persistent data. */ static NoPIOClassDescription initMEQG2QG; /** * Private and non-existent assignment operator. */ MEQG2QG & operator=(const MEQG2QG &) = delete; }; } namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of MEQG2QG. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of MEQG2QG. */ typedef ME2to2QCD NthBase; }; /** This template specialization informs ThePEG about the name of * the MEQG2QG 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::MEQG2QG"; } /** Return the name of the shared library be loaded to get * access to the MEQG2QG class and every other class it uses * (except the base class). */ static string library() { return "MEQCD.so"; } }; /** @endcond */ } #endif /* ThePEG_MEQG2QG_H */ diff --git a/MatrixElement/MEQQ2GG.cc b/MatrixElement/MEQQ2GG.cc --- a/MatrixElement/MEQQ2GG.cc +++ b/MatrixElement/MEQQ2GG.cc @@ -1,75 +1,75 @@ // -*- C++ -*- // // MEQQ2GG.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MEQQ2GG class. // #include "MEQQ2GG.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/PDT/EnumParticles.h" using namespace ThePEG; IBPtr MEQQ2GG::clone() const { return new_ptr(*this); } IBPtr MEQQ2GG::fullclone() const { return new_ptr(*this); } void MEQQ2GG::getDiagrams() const { tcPDPtr g = getParticleData(ParticleID::g); for ( int i = 1; i <= maxFlavour(); ++i ) { tcPDPtr q = getParticleData(i); tcPDPtr qb = q->CC(); add(new_ptr((Tree2toNDiagram(3), q, q, qb, 1, g, 2, g, -1))); add(new_ptr((Tree2toNDiagram(3), q, q, qb, 2, g, 1, g, -2))); } } double MEQQ2GG::me2() const { return comfac()*(colA() + colB())*KfacA()*16.0/27.0; } Selector MEQQ2GG::colourGeometries(tcDiagPtr diag) const { static ColourLines ctST("1 4, -4 2 5, -5 -3"); static ColourLines ctSU("1 5, -5 2 4, -4 -3"); Selector sel; if ( diag->id() == -1 ) sel.insert(1.0, &ctST); else sel.insert(1.0, &ctSU); return sel; } Selector MEQQ2GG::diagrams(const DiagramVector & diags) const { Selector sel; for ( DiagramIndex i = 0; i < diags.size(); ++i ) if ( diags[i]->id() == -1 ) sel.insert(colA(), i); else if ( diags[i]->id() == -2 ) sel.insert(colB(), i); return sel; } NoPIOClassDescription MEQQ2GG::initMEQQ2GG; // Definition of the static class description member. void MEQQ2GG::Init() { static ClassDocumentation documentation ("The ThePEG::MEQQ2GG class describes the standard QCD " "\\f$q\\bar{q} \\rightarrow gg\\f$ matrix element."); } diff --git a/MatrixElement/MEQQ2GG.h b/MatrixElement/MEQQ2GG.h --- a/MatrixElement/MEQQ2GG.h +++ b/MatrixElement/MEQQ2GG.h @@ -1,161 +1,161 @@ // -*- C++ -*- // // MEQQ2GG.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_MEQQ2GG_H #define ThePEG_MEQQ2GG_H // This is the declaration of the MEQQ2GG class. #include "ThePEG/MatrixElement/ME2to2QCD.h" namespace ThePEG { /** * MEQQ2GG inherits from ME2to2QCD and implements the standard * \f$q\bar{q}\rightarrow gg\f$ matrix element. * * @see \ref MEQQ2GGInterfaces "The interfaces" * defined for MEQQ2GG. * @see ME2to2QCD */ class MEQQ2GG: public ME2to2QCD { public: /** @name Virtual functions required by the MEBase class. */ //@{ /** * The matrix element for the kinematical configuration * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. * @return the matrix element scaled with sHat() to give a * dimensionless number. */ virtual double me2() const; /** * Add all possible diagrams with the add() function. */ virtual void getDiagrams() 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; /** * 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; //@} protected: /** @name Internal functions returning the matrix element squared * for different colour configurations. */ //@{ /** * Return the matrix element squared (without common pre-factors) * for the specific colour configuration. */ double colA() const { return uHat()/tHat() - 2.0*sqr(uHat()/sHat()); } /** * Return the matrix element squared (without common pre-factors) * for the specific colour configuration. */ double colB() const { return tHat()/uHat() - 2.0*sqr(tHat()/sHat()); } //@} public: /** * Standard Init function used to initialize the interfaces. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * Describe a concrete class without persistent data. */ static NoPIOClassDescription initMEQQ2GG; /** * Private and non-existent assignment operator. */ MEQQ2GG & operator=(const MEQQ2GG &) = delete; }; } namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of MEQQ2GG. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of MEQQ2GG. */ typedef ME2to2QCD NthBase; }; /** This template specialization informs ThePEG about the name of * the MEQQ2GG 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::MEQQ2GG"; } /** Return the name of the shared library be loaded to get * access to the MEQQ2GG class and every other class it uses * (except the base class). */ static string library() { return "MEQCD.so"; } }; /** @endcond */ } #endif /* ThePEG_MEQQ2GG_H */ diff --git a/MatrixElement/MEQQ2QQ3.cc b/MatrixElement/MEQQ2QQ3.cc --- a/MatrixElement/MEQQ2QQ3.cc +++ b/MatrixElement/MEQQ2QQ3.cc @@ -1,84 +1,84 @@ // -*- C++ -*- // // MEQQ2QQ3.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MEQQ2QQ class. // #include "MEQQ2QQ3.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/PDT/EnumParticles.h" using namespace ThePEG; IBPtr MEQQ2QQ::clone() const { return new_ptr(*this); } IBPtr MEQQ2QQ::fullclone() const { return new_ptr(*this); } void MEQQ2QQ::getDiagrams() const { tcPDPtr g = getParticleData(ParticleID::g); for ( int i = 1; i <= maxFlavour(); ++i ) { tcPDPtr q = getParticleData(i); tcPDPtr qb = q->CC(); add(new_ptr((Tree2toNDiagram(3), q, g, q, 1, q, 2, q, -1))); add(new_ptr((Tree2toNDiagram(3), q, g, q, 2, q, 1, q, -2))); add(new_ptr((Tree2toNDiagram(3), qb, g, qb, 1, qb, 2, qb, -3))); add(new_ptr((Tree2toNDiagram(3), qb, g, qb, 2, qb, 1, qb, -4))); } } double MEQQ2QQ::me2() const { return comfac()*(colA() + colB())*KfacA()/9.0; } Selector MEQQ2QQ::colourGeometries(tcDiagPtr diag) const { static ColourLines ctTU("1 -2 5, 2 3 4"); static ColourLines ctUT("-4 -3 -2, -5 2 -1"); static ColourLines cuTU("1 -2 4, 2 3 5"); static ColourLines cuUT("-5 -3 -2, -4 2 -1"); Selector sel; if ( diag->id() == -1 ) sel.insert(1.0, &ctTU); else if ( diag->id() == -2) sel.insert(1.0, &cuTU); else if ( diag->id() == -3 ) sel.insert(1.0, &ctUT); else if ( diag->id() == -4) sel.insert(1.0, &cuUT); return sel; } Selector MEQQ2QQ::diagrams(const DiagramVector & diags) const { Selector sel; for ( DiagramIndex i = 0; i < diags.size(); ++i ) if ( diags[i]->id() == -1 || diags[i]->id() == -3 ) sel.insert(colA(), i); else if ( diags[i]->id() == -2 || diags[i]->id() == -4 ) sel.insert(colB(), i); return sel; } NoPIOClassDescription MEQQ2QQ::initMEQQ2QQ; // Definition of the static class description member. void MEQQ2QQ::Init() { static ClassDocumentation documentation ("The ThePEG::MEQQ2QQ class describes the standard QCD " "\\f$qq \\rightarrow qq\\f$ matrix element."); } diff --git a/MatrixElement/MEQQ2QQ3.h b/MatrixElement/MEQQ2QQ3.h --- a/MatrixElement/MEQQ2QQ3.h +++ b/MatrixElement/MEQQ2QQ3.h @@ -1,162 +1,162 @@ // -*- C++ -*- // // MEQQ2QQ3.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_MEQQ2QQ_H #define ThePEG_MEQQ2QQ_H // This is the declaration of the MEQQ2QQ class. #include "ThePEG/MatrixElement/ME2to2QCD.h" // #include "MEQQ2QQ.fh" // #include "MEQQ2QQ.xh" namespace ThePEG { /** * MEQQ2QQ inherits from ME2to2QCD and implements the standard * \f$q_iq_i\rightarrow q_iq_i\f$ matrix element. * * @see \ref MEQQ2QQInterfaces "The interfaces" * defined for MEQQ2QQ. * @see ME2to2QCD */ class MEQQ2QQ: public ME2to2QCD { public: /** @name Virtual functions required by the MEBase class. */ //@{ /** * The matrix element for the kinematical configuration * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. * @return the matrix element scaled with sHat() to give a * dimensionless number. */ virtual double me2() const; /** * Add all possible diagrams with the add() function. */ virtual void getDiagrams() 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; /** * 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; //@} protected: /** @name Internal functions returning the matrix element squared * for different colour configurations. */ //@{ /** * Return the matrix element squared (without common pre-factors) * for the specific colour configuration. */ double colA() const { return (sqr(uHat()) + sqr(sHat()))/sqr(tHat()); } /** * Return the matrix element squared (without common pre-factors) * for the specific colour configuration. */ double colB() const { return (sqr(tHat()) + sqr(sHat()))/sqr(uHat()); } //@} public: /** * Standard Init function used to initialize the interfaces. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * Describe a concrete class without persistent data. */ static NoPIOClassDescription initMEQQ2QQ; /** * Private and non-existent assignment operator. */ MEQQ2QQ & operator=(const MEQQ2QQ &) = delete; }; } namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of MEQQ2QQ. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of MEQQ2QQ. */ typedef ME2to2QCD NthBase; }; /** This template specialization informs ThePEG about the name of * the MEQQ2QQ 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::MEQQ2QQ"; } /** Return the name of the shared library be loaded to get * access to the MEQQ2QQ class and every other class it uses * (except the base class). */ static string library() { return "MEQCD.so"; } }; /** @endcond */ } #endif /* ThePEG_MEQQ2QQ_H */ diff --git a/MatrixElement/MEQQ2qq2.cc b/MatrixElement/MEQQ2qq2.cc --- a/MatrixElement/MEQQ2qq2.cc +++ b/MatrixElement/MEQQ2qq2.cc @@ -1,65 +1,65 @@ // -*- C++ -*- // // MEQQ2qq2.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MEQQ2qq class. // #include "MEQQ2qq2.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/PDT/EnumParticles.h" using namespace ThePEG; void MEQQ2qq::getDiagrams() const { tcPDPtr g = getParticleData(ParticleID::g); for ( int i = 1; i <= maxFlavour(); ++i ) { tcPDPtr q = getParticleData(i); tcPDPtr qb = q->CC(); for ( int j = 1; j <= maxFlavour(); ++j ) { if ( i == j ) continue; tcPDPtr qp = getParticleData(j); tcPDPtr qbp = qp->CC(); add(new_ptr((Tree2toNDiagram(2), q, qb, 1, g, 3, qp, 3, qbp, -1))); } } } double MEQQ2qq::me2() const { return comfac()*colA()*KfacA()*2.0/9.0; } Selector MEQQ2qq::colourGeometries(tcDiagPtr) const { Selector sel; static ColourLines csST("1 3 4, -5 -3 -2"); sel.insert(1.0, &csST); return sel; } Selector MEQQ2qq::diagrams(const DiagramVector & diags) const { Selector sel; for ( DiagramIndex i = 0; i < diags.size(); ++i ) if ( diags[i]->id() == -1 ) sel.insert(1.0, i); return sel; } NoPIOClassDescription MEQQ2qq::initMEQQ2qq; // Definition of the static class description member. void MEQQ2qq::Init() { static ClassDocumentation documentation ("The ThePEG::MEQQ2qq class describes the standard QCD " "\\f$q\\bar{q} \\rightarrow q' + \\bar{q}'\\f$ matrix element."); } diff --git a/MatrixElement/MEQQ2qq2.h b/MatrixElement/MEQQ2qq2.h --- a/MatrixElement/MEQQ2qq2.h +++ b/MatrixElement/MEQQ2qq2.h @@ -1,150 +1,150 @@ // -*- C++ -*- // // MEQQ2qq2.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_MEQQ2qq_H #define ThePEG_MEQQ2qq_H // This is the declaration of the MEQQ2qq class. #include "ThePEG/MatrixElement/ME2to2QCD.h" namespace ThePEG { /** * MEQQ2qq inherits from ME2to2QCD and implements the standard * \f$q\bar{q}\rightarrow q'\bar{q'}\f$ matrix element. * * @see \ref MEQQ2qqInterfaces "The interfaces" * defined for MEQQ2qq. * @see ME2to2QCD */ class MEQQ2qq: public ME2to2QCD { public: /** @name Virtual functions required by the MEBase class. */ //@{ /** * The matrix element for the kinematical configuration * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. * @return the matrix element scaled with sHat() to give a * dimensionless number. */ virtual double me2() const; /** * Add all possible diagrams with the add() function. */ virtual void getDiagrams() 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; /** * 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; //@} protected: /** @name Internal functions returning the matrix element squared * for different colour configurations. */ //@{ /** * Return the matrix element squared (without common pre-factors) * for the specific colour configuration. */ double colA() const { return (sqr(uHat()) + sqr(tHat()))/sqr(sHat()); } //@} public: /** * Standard Init function used to initialize the interfaces. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const { return new_ptr(*this); } /** 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 { return new_ptr(*this); } //@} private: /** * Describe a concrete class without persistent data. */ static NoPIOClassDescription initMEQQ2qq; /** * Private and non-existent assignment operator. */ MEQQ2qq & operator=(const MEQQ2qq &) = delete; }; } namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of MEQQ2qq. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of MEQQ2qq. */ typedef ME2to2QCD NthBase; }; /** This template specialization informs ThePEG about the name of * the MEQQ2qq 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::MEQQ2qq"; } /** Return the name of the shared library be loaded to get * access to the MEQQ2qq class and every other class it uses * (except the base class). */ static string library() { return "MEQCD.so"; } }; /** @endcond */ } #endif /* ThePEG_MEQQ2qq_H */ diff --git a/MatrixElement/MEQq2Qq4.cc b/MatrixElement/MEQq2Qq4.cc --- a/MatrixElement/MEQq2Qq4.cc +++ b/MatrixElement/MEQq2Qq4.cc @@ -1,79 +1,79 @@ // -*- C++ -*- // // MEQq2Qq4.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MEQq2Qq class. // #include "MEQq2Qq4.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/PDT/EnumParticles.h" using namespace ThePEG; void MEQq2Qq::getDiagrams() const { tcPDPtr g = getParticleData(ParticleID::g); for ( int i = 1; i <= maxFlavour(); ++i ) { tcPDPtr q = getParticleData(i); tcPDPtr qb = q->CC(); for ( int j = 1; j <= maxFlavour(); ++j ) { if ( i == j ) continue; tcPDPtr qp = getParticleData(j); tcPDPtr qbp = qp->CC(); add(new_ptr((Tree2toNDiagram(3), q, g, qp, 1, q, 2, qp, -1))); add(new_ptr((Tree2toNDiagram(3), qb, g, qp, 1, qb, 2, qp, -2))); add(new_ptr((Tree2toNDiagram(3), q, g, qbp, 1, q, 2, qbp, -3))); add(new_ptr((Tree2toNDiagram(3), qb, g, qbp, 1, qb, 2, qbp, -4))); } } } double MEQq2Qq::me2() const { return comfac()*colA()*KfacA()*2.0/9.0; } Selector MEQq2Qq::colourGeometries(tcDiagPtr diag) const { static ColourLines ctUT("1 -2 5, 3 2 4"); static ColourLines ctST("3 2 -1, -4 -2 5"); static ColourLines ctTS("1 -2 -3, -5 2 4"); static ColourLines ctTU("-4 -2 -3, -5 2 -1"); Selector sel; if ( diag->id() == -1 ) sel.insert(1.0, &ctUT); else if ( diag->id() == -2 ) sel.insert(1.0, &ctST); else if ( diag->id() == -3 ) sel.insert(1.0, &ctTS); else if ( diag->id() == -4 ) sel.insert(1.0, &ctTU); return sel; } Selector MEQq2Qq::diagrams(const DiagramVector & diags) const { Selector sel; for ( DiagramIndex i = 0; i < diags.size(); ++i ) if ( diags[i]->id() == -1 || diags[i]->id() == -2 || diags[i]->id() == -3 || diags[i]->id() == -4 ) sel.insert(1.0, i); return sel; } NoPIOClassDescription MEQq2Qq::initMEQq2Qq; // Definition of the static class description member. void MEQq2Qq::Init() { static ClassDocumentation documentation ("The ThePEG::MEQq2Qq class describes the standard QCD " "\\f$qq' \\rightarrow qq'\\f$ matrix element."); } diff --git a/MatrixElement/MEQq2Qq4.h b/MatrixElement/MEQq2Qq4.h --- a/MatrixElement/MEQq2Qq4.h +++ b/MatrixElement/MEQq2Qq4.h @@ -1,150 +1,150 @@ // -*- C++ -*- // // MEQq2Qq4.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_MEQq2Qq_H #define ThePEG_MEQq2Qq_H // This is the declaration of the MEQq2Qq class. #include "ThePEG/MatrixElement/ME2to2QCD.h" namespace ThePEG { /** * MEQq2Qq inherits from ME2to2QCD and implements the standard * \f$q_iq_j\rightarrow q_iq_j\f$ mmatrix element. * * @see \ref MEQq2QqInterfaces "The interfaces" * defined for MEQq2Qq. * @see ME2to2QCD */ class MEQq2Qq: public ME2to2QCD { public: /** @name Virtual functions required by the MEBase class. */ //@{ /** * The matrix element for the kinematical configuration * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. * @return the matrix element scaled with sHat() to give a * dimensionless number. */ virtual double me2() const; /** * Add all possible diagrams with the add() function. */ virtual void getDiagrams() 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; /** * 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; //@} protected: /** @name Internal functions returning the matrix element squared * for different colour configurations. */ //@{ /** * Return the matrix element squared (without common pre-factors) * for the specific colour configuration. */ double colA() const { return (sqr(uHat()) + sqr(sHat()))/sqr(tHat()); } //@} public: /** * Standard Init function used to initialize the interfaces. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const { return new_ptr(*this); } /** 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 { return new_ptr(*this); } //@} private: /** * Describe a concrete class without persistent data. */ static NoPIOClassDescription initMEQq2Qq; /** * Private and non-existent assignment operator. */ MEQq2Qq & operator=(const MEQq2Qq &) = delete; }; } namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of MEQq2Qq. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of MEQq2Qq. */ typedef ME2to2QCD NthBase; }; /** This template specialization informs ThePEG about the name of * the MEQq2Qq 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::MEQq2Qq"; } /** Return the name of the shared library be loaded to get * access to the MEQq2Qq class and every other class it uses * (except the base class). */ static string library() { return "MEQCD.so"; } }; /** @endcond */ } #endif /* ThePEG_MEQq2Qq_H */ diff --git a/MatrixElement/MEee2gZ2qq.cc b/MatrixElement/MEee2gZ2qq.cc --- a/MatrixElement/MEee2gZ2qq.cc +++ b/MatrixElement/MEee2gZ2qq.cc @@ -1,172 +1,172 @@ // -*- C++ -*- // // MEee2gZ2qq.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MEee2gZ2qq class. // #include "MEee2gZ2qq.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/StandardModel/StandardModelBase.h" #include "ThePEG/Handlers/StandardXComb.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG; MEee2gZ2qq::MEee2gZ2qq() : coefs(20), mZ2(ZERO), GZ2(ZERO), lastCont(0.0), lastBW(0.0) {} unsigned int MEee2gZ2qq::orderInAlphaS() const { return 0; } unsigned int MEee2gZ2qq::orderInAlphaEW() const { return 2; } void MEee2gZ2qq::getDiagrams() const { tcPDPtr gamma = getParticleData(ParticleID::gamma); tcPDPtr Z0 = getParticleData(ParticleID::Z0); tcPDPtr ep = getParticleData(ParticleID::eplus); tcPDPtr em = getParticleData(ParticleID::eminus); for ( int i = 1; i <= maxFlavour(); ++i ) { tcPDPtr q = getParticleData(i); tcPDPtr qb = q->CC(); add(new_ptr((Tree2toNDiagram(2), em, ep, 1, gamma, 3, q, 3, qb, -1))); add(new_ptr((Tree2toNDiagram(2), em, ep, 1, Z0, 3, q, 3, qb, -2))); } } Energy2 MEee2gZ2qq::scale() const { return sHat(); } double MEee2gZ2qq::me2() const { Energy2 m2 = meMomenta()[2].mass2(); // Energy2 p1p3 = 0.5*(m2 - tHat()); // Energy2 p1p2 = 0.5*sHat(); Energy2 p1p3 = meMomenta()[0].dot(meMomenta()[2]); Energy2 p1p2 = meMomenta()[0].dot(meMomenta()[1]); Energy4 pt2 = sqr(p1p3); Energy4 pts = p1p3*p1p2; Energy4 ps2 = sqr(p1p2); Energy4 psm = p1p2*m2; int up = abs(mePartonData()[2]->id() + 1)%2; lastCont = (coefs[0 + up]*(pt2 - pts) + coefs[2 + up]*(ps2 + psm))/sqr(sHat()); double intr = 0.25*(coefs[4 + up]*pt2 + coefs[6 + up]*pts + coefs[8 + up]*ps2 + coefs[10 + up]*psm)* (sHat() - mZ2)/(sHat()*(sqr(sHat() - mZ2) + mZ2*GZ2)); lastBW = 0.25*(coefs[12 + up]*pt2 + coefs[14 + up]*pts + coefs[16 + up]*ps2 + coefs[18 + up]*psm)/ (sqr(sHat() - mZ2) + mZ2*GZ2); double alphaS = SM().alphaS(scale()); int Nf = SM().Nf(scale()); DVector save; meInfo(save << lastCont << lastBW); return (lastCont + intr + lastBW)*sqr(SM().alphaEM(scale()))* (1.0 + alphaS/Constants::pi + (1.986-0.115*Nf)*sqr(alphaS/Constants::pi)); } Selector MEee2gZ2qq::diagrams(const DiagramVector & diags) const { if ( lastXCombPtr() ) { lastCont = meInfo()[0]; lastBW = meInfo()[1]; } Selector sel; for ( DiagramIndex i = 0; i < diags.size(); ++i ) { if ( diags[i]->id() == -1 ) sel.insert(lastCont, i); else if ( diags[i]->id() == -2 ) sel.insert(lastBW, i); } return sel; } Selector MEee2gZ2qq::colourGeometries(tcDiagPtr) const { static ColourLines c("-5 4"); Selector sel; sel.insert(1.0, &c); return sel; } IBPtr MEee2gZ2qq::clone() const { return new_ptr(*this); } IBPtr MEee2gZ2qq::fullclone() const { return new_ptr(*this); } void MEee2gZ2qq::doinit() { double C = sqr(4.0*Constants::pi)/3.0; double SW2 = SM().sin2ThetaW(); double SW4 = sqr(SW2); double SW6 = SW2*SW4; double SW8 = SW2*SW6; double CW2 = 1.0 - SW2; coefs[0] = 16.0*C; coefs[1] = 64.0*C; coefs[2] = 8.0*C; coefs[3] = 32.0*C; C /= (CW2*SW2); coefs[4] = 4.0*(32.0*SW4 - 32.0*SW2 + 6.0)*C; coefs[5] = 8.0*(64.0*SW4 - 40.0*SW2 + 6.0)*C; coefs[6] = -4.0*(32.0*SW4 - 32.0*SW2 + 12.0)*C; coefs[7] = -8.0*(64.0*SW4 - 40.0*SW2 + 12.0)*C; coefs[8] = 4.0*(16.0*SW4 - 16.0*SW2 + 6.0)*C; coefs[9] = 8.0*(32.0*SW4 - 20.0*SW2 + 6.0)*C; coefs[10] = 4.0*(16.0*SW4 - 16.0*SW2 + 3.0)*C; coefs[11] = 8.0*(32.0*SW4 - 20.0*SW2 + 3.0)*C; C /= (CW2*SW2); coefs[12] = ( 64.0*SW8 - 128.0*SW6 + 128.0*SW4 - 48.0*SW2 + 9.0)*C; coefs[13] = (256.0*SW8 - 320.0*SW6 + 200.0*SW4 - 60.0*SW2 + 9.0)*C; coefs[14] = -( 64.0*SW8 - 128.0*SW6 + 176.0*SW4 - 96.0*SW2 + 18.0)*C; coefs[15] = -(256.0*SW8 - 320.0*SW6 + 296.0*SW4 - 120.0*SW2 + 18.0)*C; coefs[16] = ( 32.0*SW8 - 64.0*SW6 + 88.0*SW4 - 48.0*SW2 + 9.0)*C; coefs[17] = (128.0*SW8 - 160.0*SW6 + 148.0*SW4 - 60.0*SW2 + 9.0)*C; coefs[18] = ( 32.0*SW8 - 64.0*SW6 + 28.0*SW4 - 6.0*SW2)*C; coefs[19] = (128.0*SW8 - 160.0*SW6 + 64.0*SW4 - 12.0*SW2)*C; tcPDPtr Z0 = getParticleData(ParticleID::Z0); mZ2 = sqr(Z0->mass()); GZ2 = sqr(Z0->width()); ME2to2QCD::doinit(); } void MEee2gZ2qq::persistentOutput(PersistentOStream & os) const { os << coefs << ounit(mZ2, GeV2) << ounit(GZ2, GeV2) << lastCont << lastBW; } void MEee2gZ2qq::persistentInput(PersistentIStream & is, int) { is >> coefs >> iunit(mZ2, GeV2) >> iunit(GZ2, GeV2) >> lastCont >> lastBW; } ClassDescription MEee2gZ2qq::initMEee2gZ2qq; void MEee2gZ2qq::Init() { static ClassDocumentation documentation ("The ThePEG::MEee2gZ2qq class implements the full" "\\f$e^+e^- \\rightarrow \\gamma/Z^0 \\rightarrow q\\bar{q}\\f$ " "matrix element including the interference terms."); } diff --git a/MatrixElement/MEee2gZ2qq.h b/MatrixElement/MEee2gZ2qq.h --- a/MatrixElement/MEee2gZ2qq.h +++ b/MatrixElement/MEee2gZ2qq.h @@ -1,215 +1,215 @@ // -*- C++ -*- // // MEee2gZ2qq.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_MEee2gZ2qq_H #define ThePEG_MEee2gZ2qq_H // This is the declaration of the MEee2gZ2qq class. #include "ThePEG/MatrixElement/ME2to2QCD.h" namespace ThePEG { /** * The MEee2gZ2qq class implements the * \f$e^+e^-\rightarrow\gamma/Z^0\rightarrow q\bar{q}\f$ matrix * element. Both the continuum and \f$Z^0\f$ pole term as well as the * interference term is included. Although not a strict QCD matrix * element the class inherits from ME2to2QCD, mainly to inherit the * parameter for the number of active quark flavours. * * @see \ref MEee2gZ2qqInterfaces "The interfaces" * defined for MEee2gZ2qq. * @see ME2to2QCD */ class MEee2gZ2qq: public ME2to2QCD { public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ MEee2gZ2qq(); //@} public: /** @name Virtual functions required by the MEBase class. */ //@{ /** * Return the order in \f$\alpha_S\f$ in which this matrix element * is given. Returns . */ virtual unsigned int orderInAlphaS() const; /** * Return the order in \f$\alpha_{EM}\f$ in which this matrix * element is given. Returns 2. */ virtual unsigned int orderInAlphaEW() const; /** * The matrix element for the kinematical configuration * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. * @return the matrix element scaled with sHat() to give a * dimensionless number. */ virtual double me2() const; /** * Add all possible diagrams with the add() function. */ virtual void getDiagrams() 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; /** * 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 the scale associated with the last set phase space point. */ virtual Energy2 scale() const; //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interface. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); //@} protected: /** * Constants for the different terms set from the StandardModel in * the init() function. */ vector coefs; /** * The squared mass of the Z0. */ Energy2 mZ2; /** * The squared width of the Z0. */ Energy2 GZ2; /** * The last continuum term to be used to select primary diagram. */ mutable double lastCont; /** * The last Breit-Wigner term to be used to select primary diagram. */ mutable double lastBW; private: /** * Describe a concrete class with persistent data. */ static ClassDescription initMEee2gZ2qq; /** * Private and non-existent assignment operator. */ MEee2gZ2qq & operator=(const MEee2gZ2qq &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of MEee2gZ2qq. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of MEee2gZ2qq. */ typedef ME2to2QCD NthBase; }; /** This template specialization informs ThePEG about the name of the * MEee2gZ2qq 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::MEee2gZ2qq"; } /** Return the name of the shared library be loaded to get * access to the MEee2gZ2qq class and every other class it uses * (except the base class). */ static string library() { return "MEee2gZ2qq.so"; } }; /** @endcond */ } #endif /* ThePEG_MEee2gZ2qq_H */ diff --git a/MatrixElement/MEqq2qq1.cc b/MatrixElement/MEqq2qq1.cc --- a/MatrixElement/MEqq2qq1.cc +++ b/MatrixElement/MEqq2qq1.cc @@ -1,76 +1,76 @@ // -*- C++ -*- // // MEqq2qq1.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MEqq2qq class. // #include "MEqq2qq1.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/PDT/EnumParticles.h" using namespace ThePEG; IBPtr MEqq2qq::clone() const { return new_ptr(*this); } IBPtr MEqq2qq::fullclone() const { return new_ptr(*this); } void MEqq2qq::getDiagrams() const { tcPDPtr g = getParticleData(ParticleID::g); for ( int i = 1; i <= maxFlavour(); ++i ) { tcPDPtr q = getParticleData(i); tcPDPtr qb = q->CC(); add(new_ptr((Tree2toNDiagram(3), q, g, qb, 1, q, 2, qb, -1))); add(new_ptr((Tree2toNDiagram(2), q, qb, 1, g, 3, q, 3, qb, -2))); } } double MEqq2qq::me2() const { return comfac()*(colA()*Kfac() + colB()*KfacA())*2.0/9.0; } Selector MEqq2qq::colourGeometries(tcDiagPtr diag) const { static ColourLines ctST("1 -2 -3, -5 2 4"); static ColourLines csST("1 3 4, -5 -3 -2"); Selector sel; if ( diag->id() == -1 ) sel.insert(1.0, &ctST); else sel.insert(1.0, &csST); return sel; } Selector MEqq2qq::diagrams(const DiagramVector & diags) const { Selector sel; for ( DiagramIndex i = 0; i < diags.size(); ++i ) if ( diags[i]->id() == -1 ) sel.insert(colB(), i); else if ( diags[i]->id() == -2 ) sel.insert(colA(), i); return sel; } NoPIOClassDescription MEqq2qq::initMEqq2qq; // Definition of the static class description member. void MEqq2qq::Init() { static ClassDocumentation documentation ("The ThePEG::MEqq2qq class describes the standard QCD " "\\f$q\\bar{q} \\rightarrow q\\bar{q}\\f$ matrix element."); } diff --git a/MatrixElement/MEqq2qq1.h b/MatrixElement/MEqq2qq1.h --- a/MatrixElement/MEqq2qq1.h +++ b/MatrixElement/MEqq2qq1.h @@ -1,161 +1,161 @@ // -*- C++ -*- // // MEqq2qq1.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_MEqq2qq_H #define ThePEG_MEqq2qq_H // This is the declaration of the MEqq2qq class. #include "ThePEG/MatrixElement/ME2to2QCD.h" namespace ThePEG { /** * MEqq2qq inherits from the ME2to2QCD and implements the standard * \f$q_i\bar{q}_i\rightarrow q_i\bar{q}_i\f$ matrix element. * * @see \ref MEqq2qqInterfaces "The interfaces" * defined for MEqq2qq. * @see ME2to2QCD */ class MEqq2qq: public ME2to2QCD { public: /** @name Virtual functions required by the MEBase class. */ //@{ /** * The matrix element for the kinematical configuration * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. * @return the matrix element scaled with sHat() to give a * dimensionless number. */ virtual double me2() const; /** * Add all possible diagrams with the add() function. */ virtual void getDiagrams() 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; /** * 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; //@} protected: /** @name Internal functions returning the matrix element squared * for different colour configurations. */ //@{ /** * Return the matrix element squared (without common pre-factors) * for the specific colour configuration. */ double colA() const { return (sqr(tHat()) + sqr(uHat()))/sqr(sHat()) + (interference()? -double(sqr(uHat())/(3.0*sHat()*tHat())): 0.0); } /** * Return the matrix element squared (without common pre-factors) * for the specific colour configuration. */ double colB() const { return (sqr(uHat()) + sqr(sHat()))/sqr(tHat()) + (interference()? -double(sqr(uHat())/(3.0*sHat()*tHat())): 0.0); } //@} public: /** * Standard Init function used to initialize the interfaces. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * Describe a concrete class without persistent data. */ static NoPIOClassDescription initMEqq2qq; /** * Private and non-existent assignment operator. */ MEqq2qq & operator=(const MEqq2qq &) = delete; }; } namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of MEqq2qq. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of MEqq2qq. */ typedef ME2to2QCD NthBase; }; /** This template specialization informs ThePEG about the name of * the MEqq2qq 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::MEqq2qq"; } /** Return the name of the shared library be loaded to get * access to the MEqq2qq class and every other class it uses * (except the base class). */ static string library() { return "MEQCD.so"; } }; /** @endcond */ } #endif /* ThePEG_MEqq2qq_H */ diff --git a/MatrixElement/ReweightBase.cc b/MatrixElement/ReweightBase.cc --- a/MatrixElement/ReweightBase.cc +++ b/MatrixElement/ReweightBase.cc @@ -1,45 +1,45 @@ // -*- C++ -*- // // ReweightBase.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the ReweightBase class. // #include "ReweightBase.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Handlers/StandardXComb.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG; ReweightBase::~ReweightBase() {} void ReweightBase::persistentOutput(PersistentOStream & os) const { os << theLastXComb; } void ReweightBase::persistentInput(PersistentIStream & is, int) { is >> theLastXComb; } void ReweightBase::setXComb(tXCombPtr xc) { theLastXComb = xc; } AbstractClassDescription ReweightBase::initReweightBase; // Definition of the static class description member. void ReweightBase::Init() { static ClassDocumentation documentation ("There is no documentation for the ThePEG::ReweightBase class"); } diff --git a/MatrixElement/ReweightBase.h b/MatrixElement/ReweightBase.h --- a/MatrixElement/ReweightBase.h +++ b/MatrixElement/ReweightBase.h @@ -1,134 +1,134 @@ // -*- C++ -*- // // ReweightBase.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_ReweightBase_H #define ThePEG_ReweightBase_H // This is the declaration of the ReweightBase class. #include "ThePEG/Handlers/HandlerBase.h" #include "ThePEG/EventRecord/SubProcess.h" #include "ThePEG/Handlers/LastXCombInfo.h" #include "ThePEG/Handlers/StandardXComb.fh" namespace ThePEG { /** * The ReweightBase class is the base class of all objects * representing external biases to matrix elements. These can be used * to enhance certain matrix elements or certain phase space * regions. They can be used in two ways, either to completely change * the matrix element (re-weight), in which case the total cross * section will be affected or, when using weighted events in an * EventHandler, to pre-weight certain events but leaving the cross * section unchanged * * There is only one virtual function which must be overridden in * derived classes: weight(). * * @see \ref ReweightBaseInterfaces "The interfaces" * defined for ReweightBase. * @see MEBase * @see EventHandler * @see SubProcessHandler */ class ReweightBase: public HandlerBase, public LastXCombInfo<> { public: /** @name Standard constructors and destructors. */ //@{ /** * Destructor. */ virtual ~ReweightBase(); //@} public: /** * Return the wieght for the kinematical configuation provided by * the assigned XComb object (in the LastXCombInfo base class). */ virtual double weight() const = 0; /** * Assigne an XComb object with information about the sub-process to * be used in the reweighting. */ void setXComb(tXCombPtr xc); 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(); private: /** * Describe an abstract base class with persistent data. */ static AbstractClassDescription initReweightBase; /** * Private and non-existent assignment operator. */ ReweightBase & operator=(const ReweightBase &) = delete; }; } namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** * This template specialization informs ThePEG about the base class of * ReweightBase. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the base class of ReweightBase. */ typedef HandlerBase NthBase; }; /** * This template specialization informs ThePEG about the name of the * ReweightBase class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return the class name. */ static string className() { return "ThePEG::ReweightBase"; } }; /** @endcond */ } #endif /* ThePEG_ReweightBase_H */ diff --git a/MatrixElement/ReweightConstant.cc b/MatrixElement/ReweightConstant.cc --- a/MatrixElement/ReweightConstant.cc +++ b/MatrixElement/ReweightConstant.cc @@ -1,61 +1,61 @@ // -*- C++ -*- // // ReweightConstant.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the ReweightConstant class. // #include "ReweightConstant.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Interface/Parameter.h" using namespace ThePEG; IBPtr ReweightConstant::clone() const { return new_ptr(*this); } IBPtr ReweightConstant::fullclone() const { return new_ptr(*this); } double ReweightConstant::weight() const { return C; } void ReweightConstant::persistentOutput(PersistentOStream & os) const { os << C; } void ReweightConstant::persistentInput(PersistentIStream & is, int) { is >> C; } ClassDescription ReweightConstant::initReweightConstant; // Definition of the static class description member. void ReweightConstant::Init() { static ClassDocumentation documentation ("The ReweightConstant class is a simple ReweightBase sub-class which " "simply reweight an event with a constant"); static Parameter interfaceC ("C", "The constant with which to reweight an event.", &ReweightConstant::C, 1.0, 0, 0, true, false, Interface::nolimits); interfaceC.rank(10); } diff --git a/MatrixElement/ReweightConstant.h b/MatrixElement/ReweightConstant.h --- a/MatrixElement/ReweightConstant.h +++ b/MatrixElement/ReweightConstant.h @@ -1,145 +1,145 @@ // -*- C++ -*- // // ReweightConstant.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_ReweightConstant_H #define THEPEG_ReweightConstant_H // // This is the declaration of the ReweightConstant class. // #include "ThePEG/MatrixElement/ReweightBase.h" namespace ThePEG { /** * The ReweightConstant class is a simple ReweightBase sub-class which * simply reweight an event with a constant. * * @see \ref ReweightConstantInterfaces "The interfaces" * defined for ReweightConstant. */ class ReweightConstant: public ReweightBase { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ ReweightConstant() : C(1.0) {} //@} public: /** * Return the wieght for the kinematical configuation provided by * the assigned XComb object (in the LastXCombInfo base class). */ virtual double weight() const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * The constant to reweight with. */ double C; private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initReweightConstant; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ ReweightConstant & operator=(const ReweightConstant &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of ReweightConstant. */ template <> struct BaseClassTrait { /** Typedef of the first base class of ReweightConstant. */ typedef ReweightBase NthBase; }; /** This template specialization informs ThePEG about the name of * the ReweightConstant 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::ReweightConstant"; } /** Return the name of the shared library be loaded to get * access to the ReweightConstant class and every other class it uses * (except the base class). */ static string library() { return "ReweightConstant.so"; } }; /** @endcond */ } #endif /* THEPEG_ReweightConstant_H */ diff --git a/MatrixElement/ReweightMinPT.cc b/MatrixElement/ReweightMinPT.cc --- a/MatrixElement/ReweightMinPT.cc +++ b/MatrixElement/ReweightMinPT.cc @@ -1,102 +1,102 @@ // -*- C++ -*- // // ReweightMinPT.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the ReweightMinPT class. // #include "ReweightMinPT.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Handlers/StandardXComb.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG; IBPtr ReweightMinPT::clone() const { return new_ptr(*this); } IBPtr ReweightMinPT::fullclone() const { return new_ptr(*this); } double ReweightMinPT::weight() const { Energy minPt = Constants::MaxEnergy; for ( int i = 0, N = subProcess()->outgoing().size(); i < N; ++i ) if ( !onlyColoured || subProcess()->outgoing()[i]->coloured() ) minPt = min(minPt, subProcess()->outgoing()[i]->momentum().perp()); return pow(minPt/scale, power); } void ReweightMinPT::persistentOutput(PersistentOStream & os) const { os << power << ounit(scale,GeV) << onlyColoured; } void ReweightMinPT::persistentInput(PersistentIStream & is, int) { is >> power >> iunit(scale,GeV) >> onlyColoured; } ClassDescription ReweightMinPT::initReweightMinPT; // Definition of the static class description member. void ReweightMinPT::Init() { static ClassDocumentation documentation ("There is no documentation for the ThePEG::ReweightMinPT class"); static Parameter interfacePower ("Power", "The power to which the minimum tranverse momentum (divided by a " "Scale) is raised to give the weight.", &ReweightMinPT::power, 4.0, -10.0, 10.0, false, false, true); static Parameter interfaceScale ("Scale", "The scale with which the minimum transverse momentum is divided " "befor it is raised to a Power to give the " "weight..", &ReweightMinPT::scale, GeV, 50.0*GeV, ZERO, ZERO, false, false, Interface::lowerlim); static Switch interfaceOnlyColoured ("OnlyColoured", "Only consider coloured particles in the SubProcess when finding the minimum transverse momentum.", &ReweightMinPT::onlyColoured, false, true, false); static SwitchOption interfaceOnlyColouredTrue (interfaceOnlyColoured, "True", "Use only coloured particles.", true); static SwitchOption interfaceOnlyColouredFalse (interfaceOnlyColoured, "False", "Use all particles.", false); static SwitchOption interfaceOnlyColouredYes (interfaceOnlyColoured, "Yes", "Use only coloured particles.", true); static SwitchOption interfaceOnlyColouredNo (interfaceOnlyColoured, "No", "Use all particles.", false); interfacePower.rank(10); interfaceScale.rank(9); interfaceOnlyColoured.rank(8); } diff --git a/MatrixElement/ReweightMinPT.h b/MatrixElement/ReweightMinPT.h --- a/MatrixElement/ReweightMinPT.h +++ b/MatrixElement/ReweightMinPT.h @@ -1,147 +1,147 @@ // -*- C++ -*- // // ReweightMinPT.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_ReweightMinPT_H #define ThePEG_ReweightMinPT_H // This is the declaration of the ReweightMinPT class. #include "ThePEG/MatrixElement/ReweightBase.h" namespace ThePEG { /** * The ReweightMinPT class reweights matrix elements with the minimum * of the transverse momenta of the outgoing partons to some power. * * @see ReweightBase * */ class ReweightMinPT: public ReweightBase { public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ ReweightMinPT() : power(4.0), scale(50.0*GeV), onlyColoured(false) {} //@} public: /** * Return the wieght for the kinematical configuation provided by * the assigned XComb object (in the LastXCombInfo base class). */ virtual double weight() const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interfaces. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * The weight is the minimum pt/scale to a \a power. */ double power; /** * The weight is the minimum pt/\a scale to a power. */ Energy scale; /** * Flag to indicate that only coloured partons should be considered. */ bool onlyColoured; private: /** * Describe a concrete base class with persistent data. */ static ClassDescription initReweightMinPT; /** * Private and non-existent assignment operator. */ ReweightMinPT & operator=(const ReweightMinPT &) = delete; }; } namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of ReweightMinPT. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of ReweightMinPT. */ typedef ReweightBase NthBase; }; /** This template specialization informs ThePEG about the name of * the ReweightMinPT 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::ReweightMinPT"; } /** Return the name of the shared library be loaded to get * access to the ReweightMinPT class and every other class it uses * (except the base class). */ static string library() { return "ReweightMinPT.so"; } }; /** @endcond */ } #endif /* ThePEG_ReweightMinPT_H */ diff --git a/MatrixElement/Tree2toNDiagram.cc b/MatrixElement/Tree2toNDiagram.cc --- a/MatrixElement/Tree2toNDiagram.cc +++ b/MatrixElement/Tree2toNDiagram.cc @@ -1,454 +1,454 @@ // -*- C++ -*- // // Tree2toNDiagram.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the 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 { // 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 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 { // 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 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/MatrixElement/Tree2toNDiagram.h b/MatrixElement/Tree2toNDiagram.h --- a/MatrixElement/Tree2toNDiagram.h +++ b/MatrixElement/Tree2toNDiagram.h @@ -1,351 +1,351 @@ // -*- C++ -*- // // Tree2toNDiagram.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_Tree2toNDiagram_H #define ThePEG_Tree2toNDiagram_H // This is the declaration of the Tree2toNDiagram class. #include "ThePEG/MatrixElement/DiagramBase.h" #include "ThePEG/MatrixElement/ColourLines.h" #include "ThePEG/Handlers/StandardXComb.fh" #include "Tree2toNDiagram.xh" namespace ThePEG { /** * The Tree2toNDiagram class inherits from DiagramBase and represents * a Feynman tree diagram. It is represented by a chain of \f$n\f$ * space-like propagators, where one incoming particle has index 1 and * other incoming one index \f$n\f$. For adiagram with in total * \f$m\f$ propagators the timelike propagators are then numbered * \f$n+1\f$ through \f$m\f$. The vector of type of the propagators * are accessible from the partons() method, and the parents of * propagator \f$i\f$ form the parents(int) method. The parent of a * space-like propagator is simply the previous space-like one. The * parent of a time-like propagator is either a previous time-like * propagator or the first of the connecting space-like ones. * * A Tree2toNDiagram is created by first constructing it with an * integer corresponding to the number of space-like propagators. Then * the comma operator is used to add first the particle data objects * corresponding to the space-like propagators, then the time-like * ones preceeded with the index of their parents. To complete a * Tree2toNDiagram, a negative integer is added with the comma * operator. This number is then used as an identifier. Note that the * parent must have been added before a child is. As an example, the * s-channel diagram \f$e \nu_e \rightarrow u \bar{d}\f$ is created * thus:
* Tree2toNDiagram(2),eplus,nue,1,Wplus,3,u,3,dbar.
* Similarly the t-channel diagram \f$e d \rightarrow \nu_e u\f$ is * created thus:
* Tree2toNDiagram(3),eplus,Wplus,d,1,nu,2,u. Note that * only two chidren are allowed per propagator. This means that * four-propagator vertices are not allowed, but must be represented * by two three-propagator ones. * * Please note that for technical reasons, when specifying the * diagrams with the comma operator the numbering of the particles is * \f$1\ldots m\f$, while the internal representation (in the * parent(int) and children(int) function) is using \f$0\ldots m-1\f$ * * @see DiagramBase * @see ColourLines * */ class Tree2toNDiagram: public DiagramBase { public: /** The integer type reresenting vector sizes. */ typedef cPDVector::size_type size_type; /** A multi-set of particle data objects. */ typedef multiset PDMSet; public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ Tree2toNDiagram() : theNSpace(0), theNOutgoing(0), nextOrig(0) {} /** * Destructor. */ ~Tree2toNDiagram(); /** * The standard constructor giving the number of \a space-like * propagators. */ explicit Tree2toNDiagram(int space) : theNSpace(space), theNOutgoing(0), nextOrig(-1) {} //@} public: /** * If less than zero indicate that this tree is competed. Otherwise * signal the parent of the next added parton. */ Tree2toNDiagram & operator,(int o) { nextOrig = o - 1; if ( o < 0 ) check(); return *this; } /** * Add a space- or time-like parton. */ Tree2toNDiagram & operator,(PDPtr pd) { return add(pd); } /** * Add a space- or time-like parton. */ Tree2toNDiagram & operator,(cPDPtr pd) { return add(pd); } /** * Add a space- or time-like parton. */ Tree2toNDiagram & operator,(tPDPtr pd) { return add(pd); } /** * Add a space- or time-like parton. */ Tree2toNDiagram & operator,(tcPDPtr pd) { return add(pd); } /** * Construct a sub process corresponding to this diagram. The * incoming partons, and the momenta of the outgoing ones, are given * by the XComb object. All parent/children pointers should be set * correspondingly and the partons should be colour connected as * specified by the ColourLines object. */ virtual tPVector construct(SubProPtr sb, const StandardXComb &, const ColourLines &) const; /** * Return the types of the incoming partons. */ tcPDPair incoming() const; /** * Return the complete vector of partons in this tree diagram. */ const cPDVector & allPartons() const { return thePartons; } /** * Return the outgoing parton types of this tree diagram. */ tcPDVector outgoing() const; /** * Return the incoming followed by the outgoing parton types of this * tree diagram. */ tcPDVector external() const; /** * Return the index of the parent of the given parton. */ int parent(int i) const { return theParents[i]; } /** * Return the indices of the children of the given parton. */ pair children(int) const; /** * Return the number of space-like partons */ int nSpace() const { return theNSpace; } /** * Extend this diagram to accomodate the given number of space-like lines */ void resize(size_type nSpace) { theNSpace = max(nSpace,theNSpace); } /** * Return the number of outgoing partons. */ int nOutgoing() const { return theNOutgoing; } private: /** * Check the consistency of this tree diagram. */ void check(); /** * Add a space-like parton to this diagram. */ void addSpacelike(tcPDPtr pd) { if ( thePartons.size() >= theNSpace ) throw Tree2toNDiagramError(); theParents.push_back(thePartons.size() - 1); thePartons.push_back(pd); } /** * Add a time-like parton to this diagram. */ void addTimelike(tcPDPtr); /** * Add a time-like parton to this diagram indicating its \a origin. */ void addTimelike(tcPDPtr, size_type origin); /** * Add a parton to this diagram. */ Tree2toNDiagram & add(tcPDPtr); public: /** * Compare this diagram's topology to another one. */ virtual bool isSame(tcDiagPtr) const; /** * Compare this diagram's topology to another one modulo * permutations of external legs; provide a map of this diagram's * external legs to the other diagram's external legs. */ virtual bool isSame(tcDiagPtr, map&) const; /** * Check for equality. */ bool equals(Ptr::tcptr, int start=0, int startCmp=0) const; /** * Check for equality modulo permutations of external legs. */ bool equals(Ptr::tcptr, map&, int start=0, int startCmp=0) const; /** * Merge the two external partons referred to by indices as in the * partons() vector returned by DiagramBase. If both are timelike, * the parent will become the new outgoing parton, if one is space- * and the other timelike, the spacelike child will become the new * incoming parton. Return the position of the merged parton in the * resulting diagram or -1 if the merging is not possible. In * addition, return a mapping of a certain (non-merged) external leg * id to the id in the merged diagram. */ int mergeEmission(int emitter, int id, map& remap); /** * Translate a parton's id in the diagram to a parton's id in a * vector of incoming followed by outgoing partons. */ int externalId(int id) const; /** * Translate a parton's id in a vector of incoming followed by * outgoing partons to a parton's id in the diagram. */ int diagramId(int id) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} private: /** * The number of space-like partons */ size_type theNSpace; /** * The number of outgoing partons. */ int theNOutgoing; /** * The parent of the next added parton. */ int nextOrig; /** * The complete vector of partons in this tree diagram. */ cPDVector thePartons; /** * The index of the parents. */ vector theParents; private: /** * Describe a concrete class with persistent data. */ static ClassDescription initTree2toNDiagram; /** * Private and non-existent assignment operator. */ Tree2toNDiagram & operator=(const Tree2toNDiagram &) = delete; }; } namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** * This template specialization informs ThePEG about the * base class of Tree2toNDiagram. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the base class of Tree2toNDiagram. */ typedef DiagramBase NthBase; }; /** * This template specialization informs ThePEG about the name of the * Tree2toNDiagram class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return the class name. */ static string className() { return "ThePEG::Tree2toNDiagram"; } }; /** @endcond */ } #endif /* ThePEG_Tree2toNDiagram_H */ diff --git a/MatrixElement/Tree2toNDiagram.xh b/MatrixElement/Tree2toNDiagram.xh --- a/MatrixElement/Tree2toNDiagram.xh +++ b/MatrixElement/Tree2toNDiagram.xh @@ -1,31 +1,31 @@ // -*- C++ -*- // // Tree2toNDiagram.xh is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_Tree2toNDiagram_XH #define ThePEG_Tree2toNDiagram_XH // // This is the declarations of the exception classes used by the // Tree2toNDiagram class. // #include "ThePEG/Utilities/Exception.h" namespace ThePEG { /** @cond EXCEPTIONCLASSES */ /** Exception class used by Tree2toNDiagram to signal inconsistencies. */ struct Tree2toNDiagramError: public Exception { /** Default constructor. */ Tree2toNDiagramError(); }; /** @endcond */ } #endif /* ThePEG_Tree2toNDiagram_XH */ diff --git a/NEWS b/NEWS --- a/NEWS +++ b/NEWS @@ -1,985 +1,991 @@ ThePEG News -*- outline -*- =============================== Numbered bugs can be found at https://phab.hepforge.org/TNN where NN is the bug number. The latest version of ThePEG can be found at http://www.thep.lu.se/ThePEG or at https:///herwig.hepforge.org/ +* ThePEG-2.2.0 release: 2019-12-06 + +** Improvements to the unit templates, building with gcc 4.8 is no longer possible + +** Several smaller bug fixes and additions, to allow new features in Herwig 7.2 + * ThePEG-2.1.5 release: 2019-04-04 ** Improvements to template instantation of templates with gcc9 and icc T23 ** Change in assignment operator definition, add delete, to avoid warnings with gcc9 ** Minor changes for compilation with gcc8,9, icc and clang * ThePEG-2.1.4 release: 2018-28-06 ** Improvements to helicity libraries to support more BSM models ** Added FixedTargetLuminosity for fixed target collisions * ThePEG-2.1.3 release: 2018-04-05 ** Use std::array<> where suitable * ThePEG-2.1.2 release: 2017-11-01 ** Allow LHAPDF6 interface to return photon pdf. ** Sign fix in GeneralVVSVertex ** Fix multiple weight reading from LHE files ** Preparations for Rivet 3 * ThePEG-2.1.1 release: 2017-07-14 ** Added missing evaluate() option to GeneralVVSVertex ** More robust reading of LHE files ** Warn about duplicate PDG names in user input ** Write current timestamp into log files ** Calling 'read' in an input file will no longer change the repository directory you're in * ThePEG-2.1.0 release: 2017-05-19 ** Transition to C++-11 code, building with C++-98 is no longer possible ** Interfaces with two choices now consistently accept Yes/No as answer ** Several smaller bug fixes and additions, to allow new features in Herwig 7.1 * 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/PDF/BeamParticleData.cc b/PDF/BeamParticleData.cc --- a/PDF/BeamParticleData.cc +++ b/PDF/BeamParticleData.cc @@ -1,80 +1,80 @@ // -*- C++ -*- // // BeamParticleData.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the BeamParticleData class. // #include "BeamParticleData.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/PDT/DecayMode.h" using namespace ThePEG; BeamParticleData::BeamParticleData(long newId, string newPDGName) : ParticleData(newId, newPDGName) {} PDPtr BeamParticleData:: Create(long newId, string newPDGName) { return new_ptr(BeamParticleData(newId, newPDGName)); } PDPair BeamParticleData:: Create(long newId, string newPDGName, string newAntiPDGName) { PDPair pap; pap.first = new_ptr(BeamParticleData(newId, newPDGName)); pap.second = new_ptr(BeamParticleData(-newId, newAntiPDGName)); antiSetup(pap); return pap; } PDPtr BeamParticleData::pdclone() const { return new_ptr(*this); } void BeamParticleData::persistentOutput(PersistentOStream & os) const { os << thePDF; } void BeamParticleData::persistentInput(PersistentIStream & is, int) { is >> thePDF; } ClassDescription BeamParticleData::initBeamParticleData; void BeamParticleData::setPDF(PDFPtr pdf) { if ( pdf && !pdf->canHandle(tcPDPtr(dynamic_cast(this))) ) throw BeamParticleWrongPDF(name(), pdf? pdf->name(): string("")); thePDF = pdf; } void BeamParticleData::Init() { static ClassDocumentation documentation ("There is no documentation for the ThePEG::BeamParticleData class"); static Reference interfacePDF ("PDF", "The parton densities for this beam particle.", &BeamParticleData::thePDF, false, false, true, true, &BeamParticleData::setPDF, 0, 0); interfacePDF.rank(15); } BeamParticleWrongPDF::BeamParticleWrongPDF(string p, string pdf) { theMessage << "The parton density object '" << pdf << "' cannot be used to " << "handle densities of particle '" << p << "'. (Possibly due to " << "the remnant handler assigned to the parton density.)"; severity(warning); } diff --git a/PDF/BeamParticleData.h b/PDF/BeamParticleData.h --- a/PDF/BeamParticleData.h +++ b/PDF/BeamParticleData.h @@ -1,152 +1,152 @@ // -*- C++ -*- // // BeamParticleData.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_BeamParticleData_H #define ThePEG_BeamParticleData_H // This is the declaration of the BeamParticleData class. #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/PDF/PDFBase.h" #include "BeamParticleData.xh" namespace ThePEG { /** * BeamParticleData inherits from the ParticleData class and is used * for particles which have information about their sub-structure * implemented as a pointer to a PDFBase object. * * @see \ref BeamParticleDataInterfaces "The interfaces" * defined for BeamParticleData. * @see ParticleData * @see PDFBase */ class BeamParticleData: public virtual ParticleData { public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ BeamParticleData() {} //@} /** @name The Create methods are special interfaces for ParticleData classes. */ //@{ /** * Create a Particle which is its own anti-particle. */ static PDPtr Create(long newId, string newPDGName); /** * Create a particle - anti particle pair. Note that setting the * parton density object on this particle does not change the parton * density of the anti particle iven if synchronized() is true. */ static PDPair Create(long newId, string newPDGName, string newAntiPDGName); //@} public: /** * Return a pointer to the parton density object describing the * sub-structure of this particle type. */ tcPDFPtr pdf() const { return thePDF; } public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interface. */ static void Init(); protected: /** * Protected constructor only to be used by subclasses or by the * Create method. */ BeamParticleData(long newId, string newPDGName); /** * ParticleData clone method */ virtual PDPtr pdclone() const; private: /** * Set the parton density object. */ void setPDF(PDFPtr); private: /** * The pointer to the parton density object. */ PDFPtr thePDF; private: /** * Describe a concrete class with persistent data. */ static ClassDescription initBeamParticleData; /** * Private and non-existent assignment operator. */ BeamParticleData & operator=(const BeamParticleData &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of BeamParticleData. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of BeamParticleData. */ typedef ParticleData NthBase; }; /** This template specialization informs ThePEG about the name of the * BeamParticleData class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "ThePEG::BeamParticleData"; } }; /** @endcond */ } #endif /* ThePEG_BeamParticleData_H */ diff --git a/PDF/BeamParticleData.xh b/PDF/BeamParticleData.xh --- a/PDF/BeamParticleData.xh +++ b/PDF/BeamParticleData.xh @@ -1,33 +1,33 @@ // -*- C++ -*- // // BeamParticleData.xh is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_BeamParticleData_XH #define ThePEG_BeamParticleData_XH // // This is the declarations of the exception classes used by the // BeamParticleData class. // // #include "BeamParticleData.fh" #include "ThePEG/Interface/InterfaceBase.xh" namespace ThePEG { /** @cond EXCEPTIONCLASSES */ /** Exception class used by BeamParticleData if a specified PDF cannot * handle the particle. */ struct BeamParticleWrongPDF: public InterfaceException { /** Standard constructor. */ BeamParticleWrongPDF(string p, string pdf); }; /** @endcond */ } #endif /* ThePEG_BeamParticleData_XH */ diff --git a/PDF/GRV94L.cc b/PDF/GRV94L.cc --- a/PDF/GRV94L.cc +++ b/PDF/GRV94L.cc @@ -1,131 +1,131 @@ // -*- C++ -*- // // GRV94L.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the GRV94L class. // #include "GRV94L.h" #include "ThePEG/Interface/ClassDocumentation.h" using namespace ThePEG; IBPtr GRV94L::clone() const { return new_ptr(*this); } IBPtr GRV94L::fullclone() const { return new_ptr(*this); } void GRV94L::setup(double l, Energy2 scale) const { GRVBase::setup(l, scale, mu2(), lam2()); } double GRV94L::uv() const { return valens(2.284 + 0.802*S() + 0.055*S2(), 0.590 - 0.024*S(), 0.131 + 0.063*S(), -0.449 - 0.138*S() - 0.076*S2(), 0.213 + 2.669*S() - 0.728*S2(), 8.854 - 9.135*S() + 1.979*S2(), 2.997 + 0.753*S() - 0.076*S2()); } double GRV94L::dv() const { return valens(0.371 + 0.083*S() + 0.039*S2(), 0.376, 0.486 + 0.062*S(), -0.509 + 3.310*S() - 1.248*S2(), 12.41 - 10.52*S() + 2.267*S2(), 6.373 - 6.208*S() + 1.418*S2(), 3.691 + 0.799*S() - 0.071*S2()); } double GRV94L::del() const { return 0.5*valens(0.082 + 0.014*S() + 0.008*S2(), 0.409 - 0.005*S(), 0.799 + 0.071*S(), -38.07 + 36.13*S() - 0.656*S2(), 90.31 - 74.15*S() + 7.645*S2(), 0.0, 7.486 + 1.217*S() - 0.159*S2()); } double GRV94L::udb() const { return 0.5*lightsea(1.451, 0.271, 0.410 - 0.232*S(), 0.534 - 0.457*S(), 0.890 - 0.140*S(), -0.981, 0.320 + 0.683*S(), 4.752 + 1.164*S() + 0.286*S2(), 4.119 + 1.713*S(), 0.682 + 2.978*S()); } double GRV94L::sb() const { return heavysea(0.0, 0.914, 0.577, 1.798 - 0.596*S(), -5.548 + 3.669*rootS() - 0.616*S(), 18.92 - 16.73*rootS() + 5.168*S(), 6.379 - 0.350*S() + 0.142*S2(), 3.981 + 1.638*S(), 6.402); } double GRV94L::cb() const { return heavysea(0.888, 1.01, 0.37, 0.0, 0.0, 4.24 - 0.804*S(), 3.46 - 1.076*S(), 4.61 + 1.49 *S(), 2.555 + 1.961*S()); } double GRV94L::bb() const { return heavysea(1.351, 1.00, 0.51, 0.0, 0.0, 1.848, 2.929 + 1.396*S(), 4.71 + 1.514*S(), 4.02 + 1.239*S()); } double GRV94L::gl() const { return lightsea(0.524, 1.088, 1.742 - 0.930*S(), - 0.399*S2(), 7.486 - 2.185*S(), 16.69 - 22.74*S() + 5.779*S2(), -25.59 + 29.71*S() - 7.296*S2(), 2.792 + 2.215*S() + 0.422*S2() - 0.104*S3(), 0.807 + 2.005*S(), 3.841 + 0.316*S()); } NoPIOClassDescription GRV94L::initGRV94L; void GRV94L::Init() { static ClassDocumentation documentation ("Implements the GRV94L PDF parameterization."); } diff --git a/PDF/GRV94L.h b/PDF/GRV94L.h --- a/PDF/GRV94L.h +++ b/PDF/GRV94L.h @@ -1,156 +1,156 @@ // -*- C++ -*- // // GRV94L.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_GRV94L_H #define ThePEG_GRV94L_H // This is the declaration of the GRV94L class. #include "ThePEG/PDF/GRVBase.h" namespace ThePEG { /** * GRV94L inherits from PDFBase via the GRVBase class and implements * the GRV94L parton densities for (anti) protons and neutrons. * * @see \ref GRV94LInterfaces "The interfaces" * defined for GRV94L. */ class GRV94L: public GRVBase { /** * Return the cutoff scale. */ Energy2 mu2() const { return 0.23*GeV2; } /** * Return the square of \f$\Lambda_{QCD}\f$ used. */ Energy2 lam2() const { return sqr(0.2322*GeV); } protected: /** * Setup the \a l\f$=\log{1/x}\f$ and \a scale \f$Q^2\f$ to be used * in the following call to uv(), dv)=, etc. */ virtual void setup(double l, Energy2 scale) const; /** * Return the value of the u valens density for the values previously given * by setup(). */ virtual double uv() const; /** * Return the value of the d valens density for the values previously given * by setup(). */ virtual double dv() const; /** * Return the value of the difference between the u and d sea * densities for the values previously given by setup(). */ virtual double del() const; /** * Return the value of the average u and d sea densities for the * values previously given by setup(). */ virtual double udb() const; /** * Return the value of the s density for the values previously given by * setup(). */ virtual double sb() const; /** * Return the value of the c density for the values previously given by * setup(). */ virtual double cb() const; /** * Return the value of the b density for the values previously given by * setup(). */ virtual double bb() const; /** * Return the value of the gluon densities for the values previously * given by setup(). */ virtual double gl() const; public: /** * Standard Init function used to initialize the interface. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * Describe a concrete class without persistent data. */ static NoPIOClassDescription initGRV94L; /** * Private and non-existent assignment operator. */ GRV94L & operator=(const GRV94L &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of GRV94L. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of GRV94L. */ typedef GRVBase NthBase; }; /** This template specialization informs ThePEG about the name of the * GRV94L 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::GRV94L"; } /** Return the name of the shared library be loaded to get access to * the GRV94L class and every other class it uses (except * the base class). */ static string library() { return "GRV94L.so"; } }; /** @endcond */ } #endif /* ThePEG_GRV94L_H */ diff --git a/PDF/GRV94M.cc b/PDF/GRV94M.cc --- a/PDF/GRV94M.cc +++ b/PDF/GRV94M.cc @@ -1,131 +1,131 @@ // -*- C++ -*- // // GRV94M.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the GRV94M class. // #include "GRV94M.h" #include "ThePEG/Interface/ClassDocumentation.h" using namespace ThePEG; IBPtr GRV94M::clone() const { return new_ptr(*this); } IBPtr GRV94M::fullclone() const { return new_ptr(*this); } void GRV94M::setup(double l, Energy2 scale) const { GRVBase::setup(l, scale, mu2(), lam2()); } double GRV94M::uv() const { return valens(1.304 + 0.863*S(), 0.558 - 0.020*S(), 0.183*S(), -0.113 + 0.283*S() - 0.321*S2(), 6.843 - 5.089*S() + 2.647*S2() - 0.527*S3(), 7.771 - 10.09*S() + 2.630*S2(), 3.315 + 1.145*S() - 0.583*S2() + 0.154*S3()); } double GRV94M::dv() const { return valens(0.102 - 0.017*S() + 0.005*S2(), 0.270 - 0.019*S(), 0.260, 2.393 + 6.228*S() - 0.881*S2(), 46.06 + 4.673*S() - 14.98*S2() + 1.331*S3(), 17.83 - 53.47*S() + 21.24*S2(), 4.081 + 0.976*S() - 0.485*S2() + 0.152*S3()); } double GRV94M::del() const { return 0.5*valens(0.070 + 0.042*S() - 0.011*S2() + 0.004*S3(), 0.409 - 0.007*S(), 0.782 + 0.082*S(), -29.65 + 26.49*S() + 5.429*S2(), 90.20 - 74.97*S() + 4.526*S2(), 0.0, 8.122 + 2.120*S() - 1.088*S2() + 0.231*S3()); } double GRV94M::udb() const { return 0.5*lightsea(0.877, 0.561, 0.275, 0.0, 0.997, 3.210 - 1.866*S(), 7.300, 9.010 + 0.896*rootS() + 0.222*S2(), 3.077 + 1.446*S(), 3.173 - 2.445*rootS() + 2.207*S()); } double GRV94M::sb() const { return heavysea(0.0, 0.756, 0.216, 1.690 + 0.650*rootS() - 0.922*S(), -4.329 + 1.131*S(), 9.568 - 1.744*S(), 9.377 + 1.088*rootS() - 1.320*S() + 0.130*S2(), 3.031 + 1.639*S(), 5.837 + 0.815*S()); } double GRV94M::cb() const { return heavysea(0.820, 0.98, 0.0, -0.625 - 0.523*S(), 0.0, 1.896 + 1.616*S(), 4.12 + 0.683*S(), 4.36 + 1.328*S(), 0.677 + 0.679*S()); } double GRV94M::bb() const { return heavysea(1.297, 0.99, 0.0, - 0.193*S(), 0.0, 0.0, 3.447 + 0.927*S(), 4.68 + 1.259*S(), 1.892 + 2.199*S()); } double GRV94M::gl() const { return lightsea(1.014, 1.738, 1.724 + 0.157*S(), 0.800 + 1.016*S(), 7.517 - 2.547*S(), 34.09 - 52.21*rootS() + 17.47*S(), 4.039 + 1.491*S(), 3.404 + 0.830*S(), -1.112 + 3.438*S() - 0.302*S2(), 3.256 - 0.436*S()); } NoPIOClassDescription GRV94M::initGRV94M; void GRV94M::Init() { static ClassDocumentation documentation ("Implements the GRV94M PDF parameterization."); } diff --git a/PDF/GRV94M.h b/PDF/GRV94M.h --- a/PDF/GRV94M.h +++ b/PDF/GRV94M.h @@ -1,156 +1,156 @@ // -*- C++ -*- // // GRV94M.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_GRV94M_H #define ThePEG_GRV94M_H // This is the declaration of the GRV94M class. #include "ThePEG/PDF/GRVBase.h" namespace ThePEG { /** * GRV94M iherits from PDFBase via the GRVBase class and implements * the GRV94M parton densities for (anti) protons ad neutrons. * * @see \ref GRV94MInterfaces "The interfaces" * defined for GRV94M. */ class GRV94M: public GRVBase { /** * Return the cutoff scale. */ Energy2 mu2() const { return 0.34*GeV2; } /** * Return the square of \f$\Lambda_{QCD}\f$ used. */ Energy2 lam2() const { return sqr(0.248*GeV); } protected: /** * Setup the \a l\f$=\log{1/x}\f$ and \a scale \f$Q^2\f$ to be used * in the following call to uv(), dv)=, etc. */ virtual void setup(double l, Energy2 scale) const; /** * Return the value of the u valens density for the values previously given * by setup(). */ virtual double uv() const; /** * Return the value of the d valens density for the values previously given * by setup(). */ virtual double dv() const; /** * Return the value of the difference between the u and d sea * densities for the values previously given by setup(). */ virtual double del() const; /** * Return the value of the average u and d sea densities for the * values previously given by setup(). */ virtual double udb() const; /** * Return the value of the s density for the values previously given by * setup(). */ virtual double sb() const; /** * Return the value of the c density for the values previously given by * setup(). */ virtual double cb() const; /** * Return the value of the b density for the values previously given by * setup(). */ virtual double bb() const; /** * Return the value of the gluon densities for the values previously * given by setup(). */ virtual double gl() const; public: /** * Standard Init function used to initialize the interface. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * Describe a concrete class without persistent data. */ static NoPIOClassDescription initGRV94M; /** * Private and non-existent assignment operator. */ GRV94M & operator=(const GRV94M &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of GRV94M. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of GRV94M. */ typedef GRVBase NthBase; }; /** This template specialization informs ThePEG about the name of the * GRV94M 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::GRV94M"; } /** Return the name of the shared library be loaded to get access to * the GRV94M class and every other class it uses (except * the base class). */ static string library() { return "GRV94M.so"; } }; /** @endcond */ } #endif /* ThePEG_GRV94M_H */ diff --git a/PDF/GRVBase.cc b/PDF/GRVBase.cc --- a/PDF/GRVBase.cc +++ b/PDF/GRVBase.cc @@ -1,173 +1,173 @@ // -*- C++ -*- // // GRVBase.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the GRVBase class. // #include "GRVBase.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Utilities/Rebinder.h" #include "ThePEG/Utilities/Maths.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" using namespace ThePEG; GRVBase::GRVBase() : theLx(-1.0), thex(-1.0), theEps(-1.0), theRootx(-1.0), Q2(-GeV2), theLam2(-GeV2), theMu2(-GeV2), theS(-1.0), theS2(-1.0), theS3(-1.0), theRootS(-1.0), uvSave(-1.0), dvSave(-1.0), delSave(-1.0), udbSave(-1.0), sbSave(-1.0), cbSave(-1.0), bbSave(-1.0), glSave(-1.0) {} GRVBase::~GRVBase() {} bool GRVBase::canHandleParticle(tcPDPtr particle) const { return ( abs(particle->id()) == abs(long(ParticleID::pplus)) || abs(particle->id()) == abs(long(ParticleID::n0)) ); } cPDVector GRVBase::partons(tcPDPtr p) const { cPDVector ret; if ( canHandleParticle(p) ) { ret.push_back(getParticleData(ParticleID::g)); for ( int i = 1; i <= 5; ++i ) { ret.push_back(getParticleData(i)); ret.push_back(getParticleData(-i)); } } return ret; } double GRVBase::xfl(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale, double l, Energy2) const { setup(l, partonScale); if ( S() < 0.0 ) return 0.0; using namespace ParticleID; bool anti = particle->id() < 0; bool neutron = abs(particle->id()) == n0; switch ( parton->id() ) { case b: case bbar: return max(fbb(), 0.0); case c: case cbar: return max(fcb(), 0.0); case s: case sbar: return max(fsb(), 0.0); case u: return max(neutron? (fudb() + fdel() + (anti? 0.0: fdv())): (fudb() - fdel() + (anti? 0.0: fuv())), 0.0); case ubar: return max(neutron? (fudb() + fdel() + (anti? fdv(): 0.0)): (fudb() - fdel() + (anti? fuv(): 0.0)), 0.0); case d: return max(neutron? (fudb() - fdel() + (anti? 0.0: fuv())): (fudb() + fdel() + (anti? 0.0: fdv())), 0.0); case dbar: return max(neutron? (fudb() - fdel() + (anti? fuv(): 0.0)): (fudb() + fdel() + (anti? fdv(): 0.0)), 0.0); case g: return max(fgl(), 0.0); } return 0.0; } double GRVBase::xfvl(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale, double l, Energy2) const { setup(l, partonScale); if ( S() < 0.0 ) return 0.0; using namespace ParticleID; bool anti = particle->id() < 0; bool neutron = abs(particle->id()) == n0; switch ( parton->id() ) { case u: return max(neutron? (anti? 0.0: fdv()): (anti? 0.0: fuv()), 0.0); case ubar: return max(neutron? (anti? fdv(): 0.0): (anti? fuv(): 0.0), 0.0); case d: return max(neutron? (anti? 0.0: fuv()): (anti? 0.0: fdv()), 0.0); case dbar: return max(neutron? (anti? fuv(): 0.0): (anti? fdv(): 0.0), 0.0); } return 0.0; } double GRVBase::valens(double N, double ak, double bk, double a, double b, double c, double d) const { return N*pow(x(), ak)*pow(eps(), d)* (1.0 + a*pow(x(), bk) + x()*(b + c*sqrt(x()))); } double GRVBase:: lightsea(double al, double be, double ak, double bk, double a, double b, double c, double d, double e, double es) const { return (pow(x(), ak)*(a + x()*(b + x()*c))*pow(lx(), bk) + pow(S(), al)*exp(sqrt(es*pow(S(), be)*lx()) - e))*pow(eps(), d); } double GRVBase:: heavysea(double sth, double al, double be, double ak, double ag, double b, double d, double e, double es) const { return S() <= sth? 0.0: pow(S() - sth, al)*(1.0 + rootx()*ag + x()*b)*pow(eps(), d)* exp(sqrt(es*pow(S(), be)*lx()) - e)/pow(lx(),ak); } void GRVBase:: setup(double l, Energy2 scale, Energy2 mu2, Energy2 lam2) const { if ( l == lx() && scale == Q2 && mu2 == theMu2 && lam2 == theLam2 ) return; if ( l != lx() || scale != Q2 || mu2 != theMu2 || lam2 != theLam2 ) { uvSave = dvSave = delSave = udbSave = -1.0; sbSave = cbSave = bbSave = glSave = -1.0; } if ( l != lx() ) { theLx = l; thex = exp(-l); if ( l < 0.0 ) throw PDFRange(name(), "momentum fraction", thex, 1.0); theEps = Math::exp1m(-l); theRootx = sqrt(x()); } if ( scale != Q2 || mu2 != theMu2 || lam2 != theLam2 ) { Q2 = scale; theMu2 = mu2; theLam2 = lam2; if ( scale <= mu2 ) { switch ( rangeException ) { case rangeThrow: throw PDFRange(name(), "scale (in GeV^2)", scale/GeV2, mu2/GeV2); case rangeZero: theS = -1.0; return; case rangeFreeze: theS = 0.0; } } else theS = log(log(scale/lam2)/log(mu2/lam2)); theS2 = sqr(S()); theS3 = S()*S2(); theRootS = sqrt(S()); } } DescribeAbstractNoPIOClass describeGRVBase("ThePEG::GRVBase", "GRVBase.so"); void GRVBase::Init() { static ClassDocumentation documentation ("This is the base class used by different GRV PDF parameterizations."); } diff --git a/PDF/GRVBase.h b/PDF/GRVBase.h --- a/PDF/GRVBase.h +++ b/PDF/GRVBase.h @@ -1,372 +1,372 @@ // -*- C++ -*- // // GRVBase.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_GRVBase_H #define ThePEG_GRVBase_H // This is the declaration of the GRVBase class. #include "ThePEG/PDF/PDFBase.h" namespace ThePEG { /** * GRVBase inherits from PDFBase and is used as a base class for all * GRV parton densities. * * @see \ref GRVBaseInterfaces "The interfaces" * defined for GRVBase. */ class GRVBase: public PDFBase { public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ GRVBase(); /** * Destructor. */ virtual ~GRVBase(); //@} public: /** @name Virtual functions required by the PDFBase class. */ //@{ /** * Return true if this PDF can handle the extraction of parton from the * given particle, ie. if the particle is a proton or neutron. */ virtual bool canHandleParticle(tcPDPtr particle) const; /** * Return the parton types which are described by these parton * densities. */ virtual cPDVector partons(tcPDPtr p) const; /** * Return the value of the density of parton at the given a scale * and log fractional momentum l (the optional virtuality of the * incoming particle is not used). */ virtual double xfl(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale, double l, Energy2 particleScale) const; /** * Return the valaens partof the density of parton at the given a * scale and log fractional momentum l (the optional virtuality of * the incoming particle is not used). */ virtual double xfvl(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale, double l, Energy2 particleScale) const; //@} public: /** @name Access derived kinematical quantities. */ //@{ /** * Return last selected * \f$S\f$. \f$S=\log(\log(Q^2/\mu^2)/\log(Q^2/\Lambda_{QCD}^2))\f$ */ double S() const { return theS; } /** * Return last selected * \f$S^2\f$. \f$S=\log(\log(Q^2/\mu^2)/\log(Q^2/\Lambda_{QCD}^2))\f$ */ double S2() const { return theS2; } /** * Return last selected * \f$S^3\f$. \f$S=\log(\log(Q^2/\mu^2)/\log(Q^2/\Lambda_{QCD}^2))\f$ */ double S3() const { return theS3; } /** * Return last selected * \f$\sqrt{S}\f$. \f$S=\log(\log(Q^2/\mu^2)/\log(Q^2/\Lambda_{QCD}^2))\f$ */ double rootS() const { return theRootS; } /** * Return last selected momentum fraction, \f$x\f$. */ double x() const { return thex; } /** * Return last selected logarithmic momentum fraction * \f$l=\log(1/x)\f$. */ double lx() const { return theLx; } /** * Return one minus the last selected momentum fraction, eps\f$=1-x\f$. */ double eps() const { return theEps; } /** * Return the square root of the last selected momentum fraction, * \f$x\f$. */ double rootx() const { return theRootx; } //@} protected: /** * Setup the \a l\f$=\log{1/x}\f$ and \a scale \f$Q^2\f$ to be used * in the following call to uv(), dv)=, etc. */ virtual void setup(double l, Energy2 scale) const = 0; /** * Setup the \a l\f$=\log{1/x}\f$ and \a scale \f$Q^2\f$ to be used * in the following call to uv(), dv)=, etc. */ void setup(double l, Energy2 scale, Energy2 mu2, Energy2 lam2) const; /** * The form of the valens density functions. */ double valens(double N, double ak, double bk, double a, double b, double c, double d) const; /** * The form of the light sea and gluon density * functions. */ double lightsea(double al, double be, double ak, double bk, double a, double b, double c, double d, double e, double es) const; /** * The form of the heavy sea density functions. */ double heavysea(double sth, double al, double be, double ak, double ag, double b, double d, double e, double es) const; /** * Return the value of the u valens density for the values previously given * by setup(). */ virtual double uv() const = 0; /** * Return the value of the d valens density for the values previously given * by setup(). */ virtual double dv() const = 0; /** * Return the value of the difference between the u and d sea * densities for the values previously given by setup(). */ virtual double del() const = 0; /** * Return the value of the average u and d sea densities for the * values previously given by setup(). */ virtual double udb() const = 0; /** * Return the value of the s density for the values previously given by * setup(). */ virtual double sb() const = 0; /** * Return the value of the c density for the values previously given by * setup(). */ virtual double cb() const = 0; /** * Return the value of the b density for the values previously given by * setup(). */ virtual double bb() const = 0; /** * Return the value of the gluon densities for the values previously * given by setup(). */ virtual double gl() const = 0; /** * fuv() returns the saved values from the quv() functions if * present. Otherwise uv() is called, saved and returned. */ double fuv() const { return uvSave >= 0.0? uvSave: ( uvSave = uv() ); } /** * fdv() returns the saved values from the dv() functions if * present. Otherwise dv() is called, saved and returned. */ double fdv() const { return dvSave >= 0.0? dvSave: ( dvSave = dv() ); } /** * fdel() returns the saved values from the del() functions if * present. Otherwise del() is called, saved and returned. */ double fdel() const { return delSave >= 0.0? delSave: ( delSave = del() ); } /** * fudb() returns the saved values from the udb() functions if * present. Otherwise udb() is called, saved and returned. */ double fudb() const { return udbSave >= 0.0? udbSave: ( udbSave = udb() ); } /** * fsb() returns the saved values from the sb() functions if * present. Otherwise sb() is called, saved and returned. */ double fsb() const { return sbSave >= 0.0? sbSave: ( sbSave = sb() ); } /** * fcb() returns the saved values from the cb() functions if * present. Otherwise cb() is called, saved and returned. */ double fcb() const { return cbSave >= 0.0? cbSave: ( cbSave = cb() ); } /** * fbb() returns the saved values from the bb() functions if * present. Otherwise bb() is called, saved and returned. */ double fbb() const { return bbSave >= 0.0? bbSave: ( bbSave = bb() ); } /** * fgl() returns the saved values from the gl() functions if * present. Otherwise gl() is called, saved and returned. */ double fgl() const { return glSave >= 0.0? glSave: ( glSave = gl() ); } public: /** * Standard Init function used to initialize the interface. */ static void Init(); private: /** * The last selected logarithmic momentum fraction * \f$l=\log(1/x)\f$. */ mutable double theLx; /** * THe last selected momentum fraction, \f$x\f$. */ mutable double thex; /** * One minus the last selected momentum fraction, eps\f$=1-x\f$. */ mutable double theEps; /** * The square root of the last selected momentum fraction, \f$x\f$. */ mutable double theRootx; /** * The last selected scale. */ mutable Energy2 Q2; /** * The last used \f$\Lambda_{QCD}^2\f$. */ mutable Energy2 theLam2; /** * The last used \f$\mu^2\f$. */ mutable Energy2 theMu2; /** * The last selected * \f$S\f$. \f$S=\log(\log(Q^2/\mu^2)/\log(Q^2/\Lambda_{QCD}^2))\f$ */ mutable double theS; /** * Return last selected \f$S^2\f$. */ mutable double theS2; /** * Return last selected \f$S^3\f$. */ mutable double theS3; /** * Return last selected \f$\sqrt{S}\f$. */ mutable double theRootS; /** * Saved values from the different functions. */ mutable double uvSave; /** * Saved values from the different functions. */ mutable double dvSave; /** * Saved values from the different functions. */ mutable double delSave; /** * Saved values from the different functions. */ mutable double udbSave; /** * Saved values from the different functions. */ mutable double sbSave; /** * Saved values from the different functions. */ mutable double cbSave; /** * Saved values from the different functions. */ mutable double bbSave; /** * Saved values from the different functions. */ mutable double glSave; private: /** * Private and non-existent assignment operator. */ GRVBase & operator=(const GRVBase &) = delete; }; } #endif /* ThePEG_GRVBase_H */ diff --git a/PDF/LHAPDF6.cc b/PDF/LHAPDF6.cc --- a/PDF/LHAPDF6.cc +++ b/PDF/LHAPDF6.cc @@ -1,478 +1,478 @@ // -*- C++ -*- // // LHAPDF6.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2014 Leif Lonnblad, David Grellscheid +// // Copyright (C) 2014-2019 Leif Lonnblad, David Grellscheid // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the LHAPDF class. // #include "LHAPDF6.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Command.h" #include "ThePEG/Interface/Deleted.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/Utilities/Throw.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "LHAPDF/LHAPDF.h" using std::vector; using std::string; using std::pair; using ThePEG::GeV2; using ThePEG::cPDVector; ThePEG::LHAPDF::LHAPDF() : thePDF(), thePDFName("THEPEG_NO_PDFSET_CHOSEN"), theMember(0), theMaxFlav(5), xMin(0.0), xMax(1.0), Q2Min(ZERO), Q2Max(Constants::MaxEnergy2) {} ThePEG::LHAPDF::LHAPDF(const LHAPDF & x) : PDFBase(x), thePDF(), thePDFName(x.thePDFName), theMember(x.theMember), theMaxFlav(x.theMaxFlav), xMin(x.xMin), xMax(x.xMax), Q2Min(x.Q2Min), Q2Max(x.Q2Max) {} ThePEG::IBPtr ThePEG::LHAPDF::clone() const { return new_ptr(*this); } ThePEG::IBPtr ThePEG::LHAPDF::fullclone() const { return new_ptr(*this); } void ThePEG::LHAPDF::initPDFptr() { ::LHAPDF::setVerbosity(std::max(0, ThePEG::Debug::level - 1)); if ( thePDF && thePDF->set().name() == thePDFName && thePDF->memberID() == theMember ) return; delete thePDF; thePDF = ::LHAPDF::mkPDF(thePDFName, theMember); xMin = thePDF->xMin(); xMax = thePDF->xMax(); Q2Min = thePDF->q2Min() * GeV2; Q2Max = thePDF->q2Max() * GeV2; } void ThePEG::LHAPDF::doinit() { PDFBase::doinit(); initPDFptr(); } void ThePEG::LHAPDF::dofinish() { PDFBase::dofinish(); delete thePDF; thePDF = 0; } void ThePEG::LHAPDF::doinitrun() { PDFBase::doinitrun(); initPDFptr(); } void ThePEG::LHAPDF::setPDFName(string name) { if ( ::LHAPDF::endswith(name, ".LHgrid") ) { name = name.substr(0, name.size() - 7); } else if ( ::LHAPDF::endswith(name, ".LHpdf") ) { name = name.substr(0, name.size() - 6); } // fix the eternal typo if ( name == "cteq6ll" ) name = "cteq6l1"; if ( ::LHAPDF::contains(::LHAPDF::availablePDFSets(), name) ) { thePDFName = name; theMember = 0; } else { Throw() << "'set " << fullName() << ":PDFName " << name << "': PDF not installed. Try 'lhapdf install'.\n" << Exception::setuperror; } } void ThePEG::LHAPDF::setPDFMember(int member) { try { ::LHAPDF::PDFInfo * test = ::LHAPDF::mkPDFInfo(thePDFName, member); if ( test ) theMember = member; delete test; } catch (::LHAPDF::ReadError & e) { Throw() << e.what() << Exception::setuperror; } } string ThePEG::LHAPDF::doTest(string input) { double x = 0; Energy2 Q2 = ZERO; Energy2 P2 = ZERO; istringstream is(input); is >> x >> iunit(Q2, GeV2) >> iunit(P2, GeV2); initPDFptr(); ostringstream os; for ( int i = 0; i < 13; ++i ) os << " " << thePDF->xfxQ2(i,x,Q2/GeV2); return os.str(); } bool ThePEG::LHAPDF::canHandleParticle(tcPDPtr particle) const { using namespace ParticleID; return abs(particle->id()) == pplus || abs(particle->id()) == n0; } cPDVector ThePEG::LHAPDF::partons(tcPDPtr particle) const { // We assume that all standard partons can be extracted. const ::LHAPDF::PDFSet & pdfset = ::LHAPDF::getPDFSet(thePDFName); const vector & flavs = pdfset.get_entry_as< vector >("Flavors"); cPDVector ret; ret.reserve( flavs.size() ); if ( canHandleParticle(particle) ) { for ( size_t i=0; i < flavs.size(); ++i ) { ret.push_back(getParticleData(flavs[i])); } } assert( ret.size() == flavs.size() ); return ret; } double ThePEG::LHAPDF::xfx(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale, double x, double, Energy2) const { // Here we should return the actual density. using namespace ThePEG::ParticleID; double Q2 = partonScale/GeV2; if ( ! thePDF->inRangeXQ2(x, Q2) ) { switch ( rangeException ) { case rangeThrow: Throw() << "Momentum fraction (x=" << x << ") or scale (Q2=" << Q2 << " GeV^2) was outside of limits in PDF " << name() << "." << Exception::eventerror; break; case rangeZero: return 0.0; case rangeFreeze: x = min(max(x, xMin), xMax); Q2 = min(max(Q2, Q2Min/GeV2), Q2Max/GeV2); } } int pid = parton->id(); int abspid = abs(pid); switch ( pid ) { case t: case tbar: case b: case bbar: case c: case cbar: return maxFlav() < abspid ? 0.0 : thePDF->xfxQ2(pid,x,Q2); case s: case sbar: return thePDF->xfxQ2(pid,x,Q2); case u: switch ( particle->id() ) { case n0: return thePDF->xfxQ2(d ,x,Q2); case pbarminus: return thePDF->xfxQ2(ubar,x,Q2); case nbar0: return thePDF->xfxQ2(dbar,x,Q2); case pplus: default: return thePDF->xfxQ2(u ,x,Q2); } case ubar: switch ( particle->id() ) { case n0: return thePDF->xfxQ2(dbar,x,Q2); case pbarminus: return thePDF->xfxQ2(u ,x,Q2); case nbar0: return thePDF->xfxQ2(d ,x,Q2); case pplus: default: return thePDF->xfxQ2(ubar,x,Q2); } case d: switch ( particle->id() ) { case n0: return thePDF->xfxQ2(u ,x,Q2); case pbarminus: return thePDF->xfxQ2(dbar,x,Q2); case nbar0: return thePDF->xfxQ2(ubar,x,Q2); case pplus: default: return thePDF->xfxQ2(d ,x,Q2); } case dbar: switch ( particle->id() ) { case n0: return thePDF->xfxQ2(ubar,x,Q2); case pbarminus: return thePDF->xfxQ2(d ,x,Q2); case nbar0: return thePDF->xfxQ2(u ,x,Q2); case pplus: default: return thePDF->xfxQ2(dbar,x,Q2); } case g: return thePDF->xfxQ2(g,x,Q2); case ParticleID::gamma: return thePDF->xfxQ2(ParticleID::gamma,x,Q2); } return 0.0; } double ThePEG::LHAPDF::xfvl(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale, double l, Energy2 particleScale) const { using Math::exp1m; return xfvx(particle, parton, partonScale, exp(-l), exp1m(-l), particleScale); } double ThePEG::LHAPDF::xfvx(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale, double x, double, Energy2) const { // Here we should return the actual valence density. This will only // work properly for nucleons using namespace ThePEG::ParticleID; double Q2 = partonScale / GeV2; if ( ! thePDF->inRangeXQ2(x, Q2) ) { switch ( rangeException ) { case rangeThrow: Throw() << "Momentum fraction (x=" << x << ") or scale (Q2=" << Q2 << " GeV^2) was outside of limits in PDF " << name() << "." << Exception::eventerror; break; case rangeZero: return 0.0; case rangeFreeze: x = min(max(x, xMin), xMax); Q2 = min(max(Q2, Q2Min/GeV2), Q2Max/GeV2); } } switch ( parton->id() ) { case t: case tbar: case b: case bbar: case c: case cbar: case s: case sbar: case ParticleID::gamma: return 0.0; case u: switch ( particle->id() ) { case n0: return thePDF->xfxQ2(d,x,Q2) - thePDF->xfxQ2(dbar,x,Q2); case pbarminus: return 0.0; case nbar0: return 0.0; case pplus: return thePDF->xfxQ2(u,x,Q2) - thePDF->xfxQ2(ubar,x,Q2); default: return 0.0; } case ubar: switch ( particle->id() ) { case n0: return 0.0; case pbarminus: return thePDF->xfxQ2(u,x,Q2) - thePDF->xfxQ2(ubar,x,Q2); case nbar0: return thePDF->xfxQ2(d,x,Q2) - thePDF->xfxQ2(dbar,x,Q2); case pplus: default: return 0.0; } case d: switch ( particle->id() ) { case n0: return thePDF->xfxQ2(u,x,Q2) - thePDF->xfxQ2(ubar,x,Q2); case pbarminus: return 0.0; case nbar0: return 0.0; case pplus: return thePDF->xfxQ2(d,x,Q2) - thePDF->xfxQ2(dbar,x,Q2); default: return 0.0; } case dbar: switch ( particle->id() ) { case n0: return 0.0; case pbarminus: return thePDF->xfxQ2(d,x,Q2) - thePDF->xfxQ2(dbar,x,Q2); case nbar0: return thePDF->xfxQ2(u,x,Q2) - thePDF->xfxQ2(ubar,x,Q2); case pplus: default: return 0.0; } case ParticleID::g: return 0.0; } return 0.0; } double ThePEG::LHAPDF::xfsx(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale, double x, double, Energy2) const { // Here we should return the actual density. using namespace ThePEG::ParticleID; double Q2 = partonScale / GeV2; if ( ! thePDF->inRangeXQ2(x, Q2) ) { switch ( rangeException ) { case rangeThrow: Throw() << "Momentum fraction (x=" << x << ") or scale (Q2=" << Q2 << " GeV^2) was outside of limits in PDF " << name() << "." << Exception::eventerror; break; case rangeZero: return 0.0; case rangeFreeze: x = min(max(x, xMin), xMax); Q2 = min(max(Q2, Q2Min/GeV2), Q2Max/GeV2); } } int pid = parton->id(); int abspid = abs(pid); switch ( pid ) { case t: case tbar: case b: case bbar: case c: case cbar: return maxFlav() < abspid ? 0.0 : thePDF->xfxQ2(pid,x,Q2); case s: case sbar: return thePDF->xfxQ2(pid,x,Q2); case u: switch ( particle->id() ) { case n0: return thePDF->xfxQ2(dbar,x,Q2); case pbarminus: return thePDF->xfxQ2(ubar,x,Q2); case nbar0: return thePDF->xfxQ2(dbar,x,Q2); case pplus: return thePDF->xfxQ2(ubar,x,Q2); default: return thePDF->xfxQ2(u ,x,Q2); } case ubar: switch ( particle->id() ) { case n0: return thePDF->xfxQ2(dbar,x,Q2); case pbarminus: return thePDF->xfxQ2(ubar,x,Q2); case nbar0: return thePDF->xfxQ2(dbar,x,Q2); case pplus: default: return thePDF->xfxQ2(ubar,x,Q2); } case d: switch ( particle->id() ) { case n0: return thePDF->xfxQ2(ubar,x,Q2); case pbarminus: return thePDF->xfxQ2(dbar,x,Q2); case nbar0: return thePDF->xfxQ2(ubar,x,Q2); case pplus: return thePDF->xfxQ2(dbar,x,Q2); default: return thePDF->xfxQ2(d ,x,Q2); } case dbar: switch ( particle->id() ) { case n0: return thePDF->xfxQ2(ubar,x,Q2); case pbarminus: return thePDF->xfxQ2(dbar,x,Q2); case nbar0: return thePDF->xfxQ2(ubar,x,Q2); case pplus: default: return thePDF->xfxQ2(dbar,x,Q2); } case g: return thePDF->xfxQ2(g,x,Q2); case ParticleID::gamma: return thePDF->xfxQ2(ParticleID::gamma,x,Q2); } return 0.0; } void ThePEG::LHAPDF::persistentOutput(PersistentOStream & os) const { os << thePDFName << theMember << theMaxFlav << xMin << xMax << ounit(Q2Min, GeV2) << ounit(Q2Max, GeV2); } void ThePEG::LHAPDF::persistentInput(PersistentIStream & is, int) { is >> thePDFName >> theMember >> theMaxFlav >> xMin >> xMax >> iunit(Q2Min, GeV2) >> iunit(Q2Max, GeV2); initPDFptr(); } ThePEG::DescribeClass describeLHAPDF("ThePEG::LHAPDF", "ThePEGLHAPDF.so"); void ThePEG::LHAPDF::Init() { static ClassDocumentation documentation ("The LHAPDF class inherits from PDFBase and implements an interface " "to the LHAPDF library of parton density function parameterizations. " "This class is available even if LHAPDF was not properly installed " "when ThePEG was installed, but will then produce an error in the " "initialization. Note that the valence densities from the xfvx() and " "xfvl() function will only work properly for nucleons. All other " "particles will have zero valence densities."); static Deleted interfacePType ("PType", "The LHAPDFv6 interface currently does not support pi."); static Parameter interfacePDFName ("PDFName", "The name of the PDF set to be used. Should correspond to " "the LHAPDF v6 name.", &ThePEG::LHAPDF::thePDFName, "THEPEG_NO_PDFSET_CHOSEN", true, false, &ThePEG::LHAPDF::setPDFName); static Deleted interfacePDFNumber ("PDFNumber", "Not implemented in the LHAPDFv6 interface. " "Use :PDFName and :Member instead."); static Parameter interfaceMember ("Member", "The chosen member of the selected PDF set.", &ThePEG::LHAPDF::theMember, 0, 0, 0, true, false, Interface::lowerlim, &ThePEG::LHAPDF::setPDFMember); static Deleted interfacePDFLIBNumbers ("PDFLIBNumbers", "Not implemented in the LHAPDFv6 interface. " "Use :PDFName and :Member instead."); static Deleted interfaceEnablePartonicGamma ("EnablePartonicGamma", "Not required in LHAPDFv6."); static Deleted interfacePhotonOption ("PhotonOption", "Not required in LHAPDFv6."); static Deleted interfaceMaxNSet ("MaxNSet", "Not required in LHAPDFv6."); static Command interfaceTest ("Test", "Write out the values of the chosen PDF set using the x, Q2 and P2 " "parameters supplied.", &ThePEG::LHAPDF::doTest, true); static Deleted interfaceVerboseLevel ("VerboseLevel", "LHAPDFv6 uses general debug level instead."); static Parameter interfaceMaxFlav ("MaxFlav", "The maximum number of flavours for which non-zero densities are " "reported. The actual number of flavours may be less depending on " "the chosen PDF set.", &ThePEG::LHAPDF::theMaxFlav, 5, 3, 0, true, false, Interface::lowerlim); interfacePDFName.rank(9); interfaceMember.rank(8); } diff --git a/PDF/LHAPDF6.h b/PDF/LHAPDF6.h --- a/PDF/LHAPDF6.h +++ b/PDF/LHAPDF6.h @@ -1,299 +1,299 @@ // -*- C++ -*- // // LHAPDF6.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2014 Leif Lonnblad, David Grellscheid +// Copyright (C) 2014-2019 Leif Lonnblad, David Grellscheid // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_LHAPDF6_H #define THEPEG_LHAPDF6_H // // This is the declaration of the LHAPDF class. // #include "ThePEG/PDF/PDFBase.h" namespace LHAPDF { class PDF; } namespace ThePEG { /** * The LHAPDF class inherits from PDFBase and implements an interface * to the LHAPDF library of parton density function * parameterizations. This class is available even if LHAPDF was not * properly installed when ThePEG was installed, but will then produce * an error in the initialization. * * Note that the valence densities from the xfvx() and xfvl() function * will only work properly for nucleons. All other particles will have * zero valence densities. * * @see \ref LHAPDFInterfaces "The interfaces" * defined for LHAPDF. */ class LHAPDF: public PDFBase { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ LHAPDF(); /** * The copy constructor. */ LHAPDF(const LHAPDF &); //@} public: /** @name Virtual functions to be overridden by sub-classes. */ //@{ /** * Return true if this PDF can handle the extraction of partons from * the given \a particle. */ virtual bool canHandleParticle(tcPDPtr particle) const; /** * Return the partons which this PDF may extract from the given * \a particle. */ virtual cPDVector partons(tcPDPtr particle) const; /** * The density. Return the pdf for the given \a parton inside the * given \a particle for the virtuality \a partonScale and momentum * fraction \a x (with x = 1-\a eps). The \a particle is assumed to * have a virtuality \a particleScale. */ virtual double xfx(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale, double x, double eps = 0.0, Energy2 particleScale = ZERO) const; /** * The valence density. Return the pdf for the given cvalence \a * parton inside the given \a particle for the virtuality \a * partonScale and logarithmic momentum fraction \a l. The \a * particle is assumed to have a virtuality \a particleScale. This * will only work properly for nucleons. All other particles will * have zero valence densities */ virtual double xfvl(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale, double l, Energy2 particleScale = ZERO) const; /** * The valence density. Return the pdf for the given cvalence \a * parton inside the given \a particle for the virtuality \a * partonScale and momentum fraction \a x (with x = 1-\a eps). The * \a particle is assumed to have a virtuality \a * particleScale. This will only work properly for nucleons. All * other particles will have zero valence densities */ virtual double xfvx(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale, double x, double eps = 0.0, Energy2 particleScale = ZERO) const; /** * The sea density. Return the pdf for the given cvalence \a * parton inside the given \a particle for the virtuality \a * partonScale and momentum fraction \a x. The \a particle is * assumed to have a virtuality \a particleScale. If not overidden * by a sub class this implementation will assume that the * difference between a quark and anti-quark distribution is due do * valense quarks. */ virtual double xfsx(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale, double x, double eps = 0.0, Energy2 particleScale = ZERO) const; //@} /** @name Simple access function. */ //@{ /** * The name if the PDF set to be used. The full name including the * .LHpdf or .LHgrid suffix. */ const string & PDFName() const { return thePDFName; } /** * The chosen member of the selected PDF set. */ int member() const { return theMember; } /** * The maximum number of flavours for which non-zero densities are * reported. The actual number of flavours may be less depending on * the chosen PDF set. */ int maxFlav() const { return theMaxFlav; } //@} protected: /** @name Internal helper functions. */ //@{ /** * Initialize the LHAPDF library for the chosen PDF set if it has * not been done before. */ void initPDFptr(); /** * Used by the interface to select a set according to a file name. */ void setPDFName(string name); /** * Used by the interface to select a member in the current set. */ void setPDFMember(int n); /** * Interface for simple tests. */ string doTest(string input); //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} public: /** @cond EXCEPTIONCLASSES */ /** Exception class used if the LHAPDF library was not installed. */ class NotInstalled: public InterfaceException {}; /** @endcond */ // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). 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(); //@} private: /** * LHAPDF member object */ ::LHAPDF::PDF * thePDF; /** * The name of the selected PDF set. */ string thePDFName; /** * The chosen member of the selected PDF set. */ int theMember; /** * The maximum number of flavours for which non-zero densities are * reported. The actual number of flavours may be less depending on * the chosen PDF set. */ int theMaxFlav; /** * The minimum \f$x\f$-value for the current PDF set. */ double xMin; /** * The maximum \f$x\f$-value for the current PDF set. */ double xMax; /** * The minimum \f$Q^2\f$-value for the current PDF set. */ Energy2 Q2Min; /** * The maximum \f$Q^2\f$-value for the current PDF set. */ Energy2 Q2Max; private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ LHAPDF & operator=(const LHAPDF &) = delete; }; } #endif /* THEPEG_LHAPDF6_H */ diff --git a/PDF/LeptonLeptonPDF.cc b/PDF/LeptonLeptonPDF.cc --- a/PDF/LeptonLeptonPDF.cc +++ b/PDF/LeptonLeptonPDF.cc @@ -1,115 +1,115 @@ // -*- C++ -*- // // LeptonLeptonPDF.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the LeptonLeptonPDF class. // #include "LeptonLeptonPDF.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Utilities/Maths.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/StandardModel/StandardModelBase.h" #include "ThePEG/Interface/ClassDocumentation.h" #include using namespace ThePEG; IBPtr LeptonLeptonPDF::clone() const { return new_ptr(*this); } IBPtr LeptonLeptonPDF::fullclone() const { return new_ptr(*this); } bool LeptonLeptonPDF::canHandleParticle(tcPDPtr particle) const { return ( abs(particle->id()) < 20 || abs(particle->id()) > 10 ); } bool LeptonLeptonPDF::hasPoleIn1(tcPDPtr particle, tcPDPtr parton) const { return particle == parton; } cPDVector LeptonLeptonPDF::partons(tcPDPtr p) const { cPDVector ret; if ( canHandleParticle(p) ) ret.push_back(p); return ret; } double LeptonLeptonPDF:: xfl(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale, double l, Energy2) const { using namespace Constants; static const double gf = 3.0/4.0 - EulerGamma; static const double cut = 1.0e-300; static const double del = 1000.0*cut; if ( parton != particle || l <= cut ) return 0.0; const double x = exp(-l); const double eps = Math::exp1m(-l); const double lx = -l; const double l1x = log(eps); const double beta2 = SM().alphaEM()*(log(partonScale/sqr(particle->mass()))-1.0)/pi; double corr = 0.0; double integral = exp(beta2*gf)*pow(cut,beta2)/std::tgamma(beta2+1.0) - beta2*cut*(4.0 - 3.0*beta2 + 4.0*beta2*log(cut))/4.0; if ( l < cut + del ) corr = integral/del; return x*(exp(l1x*(beta2 - 1.0) + log(beta2) + gf*beta2)/std::tgamma(beta2+1.0) - 0.5*beta2*(1.0+x) + sqr(beta2)*((1.0+x)*(-4.0*l1x+3.0*lx) - 4.0*lx/eps - 5.0 - x)/8.0) + corr; } double LeptonLeptonPDF:: xfvl(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale, double l, Energy2 particleScale) const { return xfl(particle, parton, partonScale, l, particleScale); } double LeptonLeptonPDF:: xfvx(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale, double x, double eps, Energy2 particleScale) const { using Math::log1m; return xfl(particle, parton, partonScale, (x < 0.5 || eps <= 0.0)? -log(x): -log1m(eps), particleScale); } double LeptonLeptonPDF:: flattenL(tcPDPtr particle, tcPDPtr, const PDFCuts & c, double z, double & jacobian) const { using namespace Constants; using Math::log1m; Energy2 scale = min(c.sMax(), c.scaleMax()); if ( c.scaleMin() > ZERO ) scale = min(scale, c.scaleMin()); double beta2 = SM().alphaEM()*(log(scale/sqr(particle->mass()))-1.0)/pi; // double zpow = pow(z, 1.0/beta2); // jacobian = zpow/(1.0/beta2+1); // return z*zpow; // double l = pow(z, 1.0/beta2); // jacobian = l/(z*beta2); // z = max(z, pow(std::numeric_limits::min()*1.5, beta2)); double eps = pow(z, 1.0/beta2); double l = -log1m(eps); jacobian *= eps/(beta2*z*(1.0 - eps)); return l; } NoPIOClassDescription LeptonLeptonPDF::initLeptonLeptonPDF; void LeptonLeptonPDF::Init() { static ClassDocumentation documentation ("Describes the distribution of leptons within leptons, ie. the energy " "loss of leptons due to radiation of soft photons."); } diff --git a/PDF/LeptonLeptonPDF.h b/PDF/LeptonLeptonPDF.h --- a/PDF/LeptonLeptonPDF.h +++ b/PDF/LeptonLeptonPDF.h @@ -1,150 +1,150 @@ // -*- C++ -*- // // LeptonLeptonPDF.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_LeptonLeptonPDF_H #define ThePEG_LeptonLeptonPDF_H // This is the declaration of the LeptonLeptonPDF class. #include "ThePEG/PDF/PDFBase.h" namespace ThePEG { /** * LeptonLeptonPDF inherits from PDFBase and encodes the distribution * of leptons within leptons, ie. the energy loss of leptons due to * radiation of soft photons. * * @see \ref LeptonLeptonPDFInterfaces "The interfaces" * defined for LeptonLeptonPDF. */ class LeptonLeptonPDF: public PDFBase { public: /** @name Virtual functions required by the PDFBase class. */ //@{ /** * Return true if this PDF can handle the extraction of parton from the * given particle ie. if the particle is a lepton. */ virtual bool canHandleParticle(tcPDPtr particle) const; /** * Return true if this PDF has a pole at $x=1$ for the given \a * particle and \a parton. Returns true if \a parton and \a particle * are the same. */ virtual bool hasPoleIn1(tcPDPtr particle, tcPDPtr parton) const; /** * Return a vector of partons handled by this PDF (always the same * lepton as the incoming particle). */ virtual cPDVector partons(tcPDPtr p) const; /** * Return the value of the density function at a given * l\f$=\log(1/x)\f$ and scale for the given parton. */ virtual double xfl(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale, double l, Energy2 particleScale = ZERO) const; /** * Return the the valens part of the true pdf for the given * parameters, with the momentum fraction given as * l\f$=\log(1/x)\f$. This version simply returns the full pdf. */ virtual double xfvl(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale, double l, Energy2 particleScale = ZERO) const; /** * Return the the valens part of the true pdf for the given * parameters, with the momentum fraction given as x. This version * simply returns the full pdf. */ virtual double xfvx(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale, double x, double eps, Energy2 particleScale) const; /** * If the PDF contains strange peaks which can be difficult to * handle, this function may be overwritten to return an appropriate * l\f$=\log(1/x)\f$ for a z given by a flat distribution in * ]0,1[. Also the jacobobian of the l(z) function must be * returned. The default version will simly use the function l(z) = * lmin + z*(lmax-lmin). */ virtual double flattenL(tcPDPtr particle, tcPDPtr parton, const PDFCuts &, double z, double & jacobian) const; //@} public: /** * Standard Init function used to initialize the interface. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * Describe a concrete class without persistent data. */ static NoPIOClassDescription initLeptonLeptonPDF; /** * Private and non-existent assignment operator. */ LeptonLeptonPDF & operator=(const LeptonLeptonPDF &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the base classes * of LeptonLeptonPDF. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of LeptonLeptonPDF. */ typedef PDFBase NthBase; }; /** This template specialization informs ThePEG about the name of the * LeptonLeptonPDF 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::LeptonLeptonPDF"; } /** Return the name of the shared library be loaded to get access to * the LeptonLeptonPDF class and every other class it uses (except * the base class). */ static string library() { return "LeptonLeptonPDF.so"; } }; /** @endcond */ } #endif /* ThePEG_LeptonLeptonPDF_H */ diff --git a/PDF/NoPDF.cc b/PDF/NoPDF.cc --- a/PDF/NoPDF.cc +++ b/PDF/NoPDF.cc @@ -1,55 +1,55 @@ // -*- C++ -*- // // NoPDF.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the NoPDF class. // #include "NoPDF.h" #include "ThePEG/Utilities/Interval.h" #include "ThePEG/PDF/RemnantHandler.h" #include "ThePEG/PDT/ParticleData.h" using namespace ThePEG; IBPtr NoPDF::clone() const { return new_ptr(*this); } IBPtr NoPDF::fullclone() const { return new_ptr(*this); } bool NoPDF::canHandleParticle(tcPDPtr) const { return true; } bool NoPDF::canHandle(tcPDPtr particle) const { return canHandleParticle(particle) && remnantHandler() && remnantHandler()->canHandle(particle, cPDVector()); } bool NoPDF::hasPoleIn1(tcPDPtr particle, tcPDPtr parton) const { return particle == parton; } cPDVector NoPDF::partons(tcPDPtr p) const { return cPDVector(1, p); } double NoPDF:: xfl(tcPDPtr particle, tcPDPtr parton, Energy2, double l, Energy2) const { return ( l == 0 && particle == parton )? 1.0: 0.0; } NoPIOClassDescription NoPDF::initNoPDF; void NoPDF::Init() {} diff --git a/PDF/NoPDF.h b/PDF/NoPDF.h --- a/PDF/NoPDF.h +++ b/PDF/NoPDF.h @@ -1,125 +1,125 @@ // -*- C++ -*- // // NoPDF.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_NoPDF_H #define ThePEG_NoPDF_H // This is the declaration of the NoPDF class. #include "ThePEG/PDF/PDFBase.h" // #include "NoPDF.fh" // #include "NoPDF.xh" namespace ThePEG { /** * NoPDF inherits from PDFBase and represents particles without * sub-structure. The only parton which can be extracted is the * incoming particle itself with a momentum distribution which is a * delta-function at \f$x=1\f$ (\f$l=0\f$). * * @see PDFBase * @see NoRemnants * */ class NoPDF: public PDFBase { public: /** @name Virtual functions mandated by the PDFBase base class. */ //@{ /** * Return true because we can handle any particle. */ virtual bool canHandleParticle(tcPDPtr particle) const; /** * Return true if canHandleParticle() and if the corresponding * method for remnantHandler() returns true. */ virtual bool canHandle(tcPDPtr particle) const; /** * Return true if this PDF has a pole at $x=1$ for the given \a * particle and \a parton. This default version of the function * returns true if \a particle and \a parton is the same. */ virtual bool hasPoleIn1(tcPDPtr particle, tcPDPtr parton) const; /** * Simply return the particle. */ virtual cPDVector partons(tcPDPtr p) const; /** * The delta function. */ virtual double xfl(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale, double l, Energy2 particleScale = ZERO) const; //@} public: /** * Standard Init function used to initialize the interface. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * Describe a concrete class without persistent data. */ static NoPIOClassDescription initNoPDF; /** * Private and non-existent assignment operator. */ NoPDF & operator=(const NoPDF &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the base classes * of NoPDF. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of NoPDF. */ typedef PDFBase NthBase; }; /** This template specialization informs ThePEG about the name of the * NoPDF class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "ThePEG::NoPDF"; } }; /** @endcond */ } #endif /* ThePEG_NoPDF_H */ diff --git a/PDF/NoRemnants.cc b/PDF/NoRemnants.cc --- a/PDF/NoRemnants.cc +++ b/PDF/NoRemnants.cc @@ -1,52 +1,52 @@ // -*- C++ -*- // // NoRemnants.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the NoRemnants class. // #include "NoRemnants.h" #include "ThePEG/Vectors/LorentzVector.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/EventRecord/Particle.h" using namespace ThePEG; IBPtr NoRemnants::clone() const { return new_ptr(*this); } IBPtr NoRemnants::fullclone() const { return new_ptr(*this); } Lorentz5Momentum NoRemnants:: generate(PartonBinInstance & pb, const double *, Energy2, const LorentzMomentum & p, bool) const { if ( pb.particleData() != pb.partonData() || pb.li() > 0.0 ) throw RemnantHandlerException (pb.particleData()->name(), pb.partonData()->name(), name(), "This remnant handler cannot handle any remnants!"); return p; } Lorentz5Momentum NoRemnants:: generate(PartonBinInstance & pb, const double *, Energy2, Energy2, const LorentzMomentum & p, bool) const { if ( pb.particleData() != pb.partonData() || pb.li() > 0.0 ) throw RemnantHandlerException (pb.particleData()->name(), pb.partonData()->name(), name(), "This remnant handler cannot handle any remnants!"); return p; } NoPIOClassDescription NoRemnants::initNoRemnants; void NoRemnants::Init() {} diff --git a/PDF/NoRemnants.h b/PDF/NoRemnants.h --- a/PDF/NoRemnants.h +++ b/PDF/NoRemnants.h @@ -1,134 +1,134 @@ // -*- C++ -*- // // NoRemnants.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_NoRemnants_H #define ThePEG_NoRemnants_H // This is the declaration of the NoRemnants class. #include "ThePEG/PDF/RemnantHandler.h" // #include "NoRemnants.fh" // #include "NoRemnants.xh" namespace ThePEG { /** * NoRemnants inherits from RemnantHandler but can only handle * particles without sub-structure with the parton density given by a * NoPDF object and will never give any remnants. * * * @see RemnantHandler * @see NoPDF * */ class NoRemnants: public RemnantHandler { public: /** @name Virtual functions mandated by the RemnantHandler base class. */ //@{ /** * Return true if this remnant handler can handle extracting all * specified partons. The NoRemnants will return false if any * partons are given. */ virtual bool canHandle(tcPDPtr, const cPDVector & partons) const { return partons.empty(); } /** * Generate Remnants. Will not generate remnants and will throw a * RemnantHandlerException if the extracted parton is not the * incomining particle with x=1. */ virtual Lorentz5Momentum generate(PartonBinInstance & pb, const double * r, Energy2 scale, const LorentzMomentum & p, bool fixedPartonMomentum = false) const; /** * Generate the momentum of the extracted parton with the \a parent * momentum given by the last argument. If the \a scale is negative, * it means that the doScale in the previous call to nDim() was * true, otherwise the given \a scale should be the virtuality of * the extracted parton. \a shat is the total invariant mass squared * of the hard sub-system produced by the extracted parton and the * primary parton entering from the other side. Generated quantities * which are not returned in the momentum may be saved in the * PartonBinInstance, \a pb, for later use. In particular, if the * nDim() random numbers, \a r, are not enough to generate with * weight one, the resulting weight should be stored with the * remnantWeight() method of the parton bin. */ virtual Lorentz5Momentum generate(PartonBinInstance & pb, const double * r, Energy2 scale, Energy2 shat, const LorentzMomentum & parent, bool fixedPartonMomentum = false) const; //@} public: /** * Standard Init function used to initialize the interface. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * Describe a concrete class without persistent data. */ static NoPIOClassDescription initNoRemnants; /** * Private and non-existent assignment operator. */ NoRemnants & operator=(const NoRemnants &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of NoRemnants. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of NoRemnants. */ typedef RemnantHandler NthBase; }; /** This template specialization informs ThePEG about the name of the * NoRemnants class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "ThePEG::NoRemnants"; } }; /** @endcond */ } #endif /* ThePEG_NoRemnants_H */ diff --git a/PDF/PDF.h b/PDF/PDF.h --- a/PDF/PDF.h +++ b/PDF/PDF.h @@ -1,184 +1,184 @@ // -*- C++ -*- // // PDF.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_PDF_H #define ThePEG_PDF_H // This is the declaration of the PDF class. #include "ThePEG/PDF/PartonBinInstance.h" namespace ThePEG { /** * PDF is a simple wrapper class with normal copy-semantics which * holds a PDFBase object and a ParticleData object for which to * determine parton densities. */ class PDF { public: /** @name Standard constructors, assignment and destructors. */ //@{ /** * Default constructor. */ PDF() {} /** * Constructor from a given PartonBinInstance. */ PDF(tcPBIPtr pb) { if ( !pb ) return; thePDF = pb->pdf(); theParticle = pb->particleData(); } /** * Constructor from a given PDFBase and ParticleData object. */ PDF(tcPDFPtr pdf, tcPDPtr pd) : thePDF(pdf), theParticle(pd) {} //@} public: /** @name Access the parton densities. */ //@{ /** * Return the density for the given \a parton, for a given \a * partonScale and logarithmic momentum fraction \a l assuming the * particle has a virtuality \a particleScale. */ double xfl(tcPPtr parton, Energy2 partonScale, double l, Energy2 particleScale = ZERO) const { return xfl(parton->dataPtr(), partonScale, l, particleScale); } /** * Return the density for the given \a parton, for a given \a * partonScale and momentum fraction \a x assuming the * particle has a virtuality \a particleScale. */ double xfx(tcPPtr parton, Energy2 partonScale, double x, double eps = 0.0, Energy2 particleScale = ZERO) const { return xfx(parton->dataPtr(), partonScale, x, eps, particleScale); } /** * Return the valence density for the given \a parton, for a given * \a partonScale and logarithmic momentum fraction \a l assuming * the particle has a virtuality \a particleScale. */ double xfvl(tcPPtr parton, Energy2 partonScale, double l, Energy2 particleScale = ZERO) const { return xfvl(parton->dataPtr(), partonScale, l, particleScale); } /** * Return the valence density for the given \a parton, for a given * \a partonScale and momentum fraction \a x assuming the particle * has a virtuality \a particleScale. */ double xfvx(tcPPtr parton, Energy2 partonScale, double x, double eps = 0.0, Energy2 particleScale = ZERO) const { return xfvx(parton->dataPtr(), partonScale, x, eps, particleScale); } /** * Return the density for the given \a parton, for a given \a * partonScale and logarithmic momentum fraction \a l assuming the * particle has a virtuality \a particleScale. */ double xfl(tcPDPtr parton, Energy2 partonScale, double l, Energy2 particleScale = ZERO) const { return thePDF? thePDF->xfl(theParticle, parton, partonScale, l, particleScale): 0.0; } /** * Return the density for the given \a parton, for a given \a * partonScale and momentum fraction \a x assuming the * particle has a virtuality \a particleScale. */ double xfx(tcPDPtr parton, Energy2 partonScale, double x, double eps = 0.0, Energy2 particleScale = ZERO) const { return thePDF? thePDF->xfx(theParticle, parton, partonScale, x, eps, particleScale): 0.0; } /** * Return the valence density for the given \a parton, for a given * \a partonScale and logarithmic momentum fraction \a l assuming * the particle has a virtuality \a particleScale. */ double xfvl(tcPDPtr parton, Energy2 partonScale, double l, Energy2 particleScale = ZERO) const { return thePDF? thePDF->xfvl(theParticle, parton, partonScale, l, particleScale): 0.0; } /** * Return the valence density for the given \a parton, for a given * \a partonScale and momentum fraction \a x assuming the particle * has a virtuality \a particleScale. */ double xfvx(tcPDPtr parton, Energy2 partonScale, double x, double eps = 0.0, Energy2 particleScale = ZERO) const { return thePDF? thePDF->xfvx(theParticle, parton, partonScale, x, eps, particleScale): 0.0; } //@} /** * The parton density object. */ tcPDFPtr pdf() const { return thePDF; } /** * The particle for which the parton density is used. */ tcPDPtr particle() const { return theParticle; } /** * Compare for equality. */ bool operator==(const PDF& x) const { return pdf() == x.pdf() && particle() == x.particle(); } /** * Compare for ordering. */ bool operator<(const PDF& x) const { return pdf() == x.pdf() ? particle() < x.particle() : pdf() < x.pdf(); } private: /** * The parton density object. */ tcPDFPtr thePDF; /** * The particle for which the parton density is used. */ tcPDPtr theParticle; }; } #endif /* ThePEG_PDF_H */ diff --git a/PDF/PDFBase.cc b/PDF/PDFBase.cc --- a/PDF/PDFBase.cc +++ b/PDF/PDFBase.cc @@ -1,173 +1,173 @@ // -*- C++ -*- // // PDFBase.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the PDFBase class. // #include "PDFBase.h" #include "ThePEG/PDF/RemnantHandler.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Utilities/Debug.h" #include "ThePEG/Repository/Repository.h" #include "ThePEG/Utilities/EnumIO.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/PDT/StandardMatchers.h" using namespace ThePEG; PDFBase::PDFBase() : rangeException(rangeZero) {} PDFBase::PDFBase(const PDFBase & x) : HandlerBase(x), theRemnantHandler(x.theRemnantHandler), rangeException(x.rangeException) {} PDFBase::~PDFBase() {} bool PDFBase::canHandle(tcPDPtr particle) const { return canHandleParticle(particle) && remnantHandler() && remnantHandler()->canHandle(particle, partons(particle)); } bool PDFBase::hasPoleIn1(tcPDPtr, tcPDPtr) const { return false; } double PDFBase:: xfx(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale, double x, double eps, Energy2 particleScale) const { using Math::log1m; return xfl(particle, parton, partonScale, (x < 0.5 || eps <= 0.0)? -log(x): -log1m(eps), particleScale); } double PDFBase:: xfl(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale, double l, Energy2 particleScale) const { using Math::exp1m; return xfx(particle, parton, partonScale, exp(-l), exp1m(-l), particleScale); } double PDFBase:: xfvx(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale, double x, double eps, Energy2 particleScale) const { if ( !QuarkMatcher::Check(*parton) ) return 0.0; return max(0.0, xfx(particle, parton, partonScale, x, eps, particleScale) - xfx(particle, parton->CC(), partonScale, x, eps, particleScale)); } double PDFBase:: xfvl(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale, double l, Energy2 particleScale) const { if ( !QuarkMatcher::Check(*parton) ) return 0.0; return max(0.0, xfl(particle, parton, partonScale, l, particleScale) - xfl(particle, parton->CC(), partonScale, l, particleScale)); } double PDFBase:: xfsx(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale, double x, double eps, Energy2 particleScale) const { return max(0., xfx(particle,parton,partonScale,x,eps,particleScale)- xfvx(particle,parton,partonScale,x,eps,particleScale)); } double PDFBase:: xfsl(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale, double l, Energy2 particleScale) const { return max(0., xfl(particle,parton,partonScale,l,particleScale)- xfvl(particle,parton,partonScale,l,particleScale)); } double PDFBase::flattenL(tcPDPtr, tcPDPtr, const PDFCuts & c, double z, double & jacobian) const { jacobian *= c.lMax() - c.lMin(); return c.lMin() + z*(c.lMax() - c.lMin()); } double PDFBase:: flattenScale(tcPDPtr, tcPDPtr, const PDFCuts & c, double l, double z, double & jacobian) const { if ( c.scaleMin() > ZERO ) { double r = c.scaleMaxL(l)/c.scaleMin(); double ret = pow(r, z - 1.0); jacobian *= log(r)*ret; return ret; } else { return z; } } void PDFBase::doinit() { HandlerBase::doinit(); } void PDFBase::persistentOutput(PersistentOStream & os) const { os << theRemnantHandler << oenum(rangeException); } void PDFBase::persistentInput(PersistentIStream & is, int) { is >> theRemnantHandler >> ienum(rangeException); } AbstractClassDescription PDFBase::initPDFBase; void PDFBase::Init() { static ClassDocumentation documentation ("There is no documentation for the ThePEG::PDFBase class"); static Reference interfaceRemnantHandler ("RemnantHandler", "A remnant handler capable of generating remnants for the partons " "which can be extracted with this PDF.", &PDFBase::theRemnantHandler, false, false, true, false); static Switch interfaceRangeException ("RangeException", "How to handle cases when momentum fractions or scales are " "outside of limits. Note that this switch may be ignored in sub-classes.", &PDFBase::rangeException, rangeZero, true, false); static SwitchOption interfaceRangeExceptionFreeze (interfaceRangeException, "Freeze", "Values are frozen outside the given ranges.", rangeFreeze); static SwitchOption interfaceRangeExceptionZero (interfaceRangeException, "Zero", "Values are zero outside the given ranges.", rangeZero); static SwitchOption interfaceRangeExceptionThrow (interfaceRangeException, "Throw", "An exception is thrown outside the given ranges.", rangeThrow); } RemnantHandlerCantHandle::RemnantHandlerCantHandle(string pdf, string rh) { theMessage << "Cannot assign '" << rh << "' as remnant handler for the " << "parton density object '" << pdf << "' because the remnant handler does not feel up to the job."; severity(warning); } PDFWrongParticle::PDFWrongParticle(string p, string pdf, string mess) { theMessage << "Cannot assign particle '" << p << "' to be handled by the " << "parton density object '" << pdf << "'. " << mess; severity(warning); } PDFRange::PDFRange(string pdf, string var, double val, double lim) { theMessage << "In parton density function '" << pdf << "': the value of " << var << ", " << val << ", was out of range (" << lim << ")."; severity(eventerror); } diff --git a/PDF/PDFBase.h b/PDF/PDFBase.h --- a/PDF/PDFBase.h +++ b/PDF/PDFBase.h @@ -1,278 +1,278 @@ // -*- C++ -*- // // PDFBase.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_PDFBase_H #define ThePEG_PDFBase_H // This is the declaration of the PDFBase class. #include "ThePEG/Config/ThePEG.h" #include "ThePEG/Handlers/HandlerBase.h" #include "ThePEG/PDF/PDFCuts.h" #include "PDFBase.xh" namespace ThePEG { /** * PDFBase is the base class for implementing parton density functions * for particles with sub-structure. A number of of virtual methods * are defined which should be overridden by sub-classes. * * It is essential that either xfx or xfl is overidden to avoid * infinite recursive function calls. * * A PDFBase object can be assigned to a BeamParticleData object * and/or to a PartonExtractor object. A PDFBase has a pointer to a * RemnantHandler object which should be capable of generating * remnants for all partons which may be extracted by the PDF. * * @see \ref PDFBaseInterfaces "The interfaces" * defined for PDFBase. * @see BeamParticleData * @see PartonExtractor * @see RemnantHandler * @see PDFCuts */ class PDFBase: public HandlerBase { public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ PDFBase(); /** * Copy-constructor. */ PDFBase(const PDFBase &); /** * Destructor. */ virtual ~PDFBase(); //@} public: /** @name Virtual functions to be overridden by sub-classes. */ //@{ /** * Return true if this PDF can handle the extraction of partons from * the given \a particle. */ virtual bool canHandleParticle(tcPDPtr particle) const = 0; /** * Return true if canHandleParticle() and if the corresponding * method for remnantHandler() returns true for the given \a * particle. */ virtual bool canHandle(tcPDPtr particle) const; /** * Return true if this PDF has a pole at $x=1$ for the given \a * particle and \a parton. This default version of the function * returns false. */ virtual bool hasPoleIn1(tcPDPtr particle, tcPDPtr parton) const; /** * Return the partons which this PDF may extract from the given * \a particle. */ virtual cPDVector partons(tcPDPtr particle) const = 0; /** * The density. Return the pdf for the given \a parton inside the * given \a particle for the virtuality \a partonScale and * logarithmic momentum fraction \a l \f$(l=\log(1/x)\f$. The \a * particle is assumed to have a virtuality \a particleScale. */ virtual double xfl(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale, double l, Energy2 particleScale = ZERO) const; /** * The density. Return the pdf for the given \a parton inside the * given \a particle for the virtuality \a partonScale and momentum * fraction \a x. The \a particle is assumed to have a virtuality \a * particleScale. */ virtual double xfx(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale, double x, double eps = 0.0, Energy2 particleScale = ZERO) const; /** * The valence density. Return the pdf for the given cvalence \a * parton inside the given \a particle for the virtuality \a * partonScale and logarithmic momentum fraction \a l * \f$(l=\log(1/x)\f$. The \a particle is assumed to have a * virtuality \a particleScale. If not overidden by a sub class this * implementation will assume that the difference between a quark * and anti-quark distribution is due do valense quarks, but return * zero for anything else. */ virtual double xfvl(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale, double l, Energy2 particleScale = ZERO) const; /** * The valence density. Return the pdf for the given cvalence \a * parton inside the given \a particle for the virtuality \a * partonScale and momentum fraction \a x. The \a particle is * assumed to have a virtuality \a particleScale. If not overidden * by a sub class this implementation will assume that the * difference between a quark and anti-quark distribution is due do * valense quarks, but return zero for anything else. */ virtual double xfvx(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale, double x, double eps = 0.0, Energy2 particleScale = ZERO) const; /** * The sea density. Return the pdf for the given cvalence \a * parton inside the given \a particle for the virtuality \a * partonScale and logarithmic momentum fraction \a l * \f$(l=\log(1/x)\f$. The \a particle is assumed to have a * virtuality \a particleScale. If not overidden by a sub class this * implementation will assume that the difference between a quark * and anti-quark distribution is due do valense quarks. */ virtual double xfsl(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale, double l, Energy2 particleScale = ZERO) const; /** * The sea density. Return the pdf for the given cvalence \a * parton inside the given \a particle for the virtuality \a * partonScale and momentum fraction \a x. The \a particle is * assumed to have a virtuality \a particleScale. If not overidden * by a sub class this implementation will assume that the * difference between a quark and anti-quark distribution is due do * valense quarks. */ virtual double xfsx(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale, double x, double eps = 0.0, Energy2 particleScale = ZERO) const; /** * Generate a momentum fraction. If the PDF contains strange peaks * which can be difficult to handle, this function may be * overwritten to return an appropriate \f$l=\log(1/x)\f$ for a \a z * uniformly distributed in ]0,1[. Also the jacobobian of the * \f$l\rightarrow z\f$ variable transformation must in the function * multiply the \a jacobian argument. The default version will * simply use the function \f$l(z) = l_{\min} + * z*(l_{\max}-l_{\min})\f$ (where the limits are set by \a cut). */ virtual double flattenL(tcPDPtr particle, tcPDPtr parton, const PDFCuts &cut, double z, double & jacobian) const; /** * Generate scale (as a fraction of the maximum scale). If the PDF * contains strange peaks which can be difficult to handle, this * function may be overwritten to return an appropriate scale * \f$Q^2/Q^2_{\max}\f$ for a \a z uniformly distributed in * ]0,1[. Also the jacobobian of the \f$Q^2/Q^2_{\max}\rightarrow * z\f$ variable transformation must multiply the \a jacobian * argument. The default version will simply use the function * \f$Q^2/Q^2_{\max} = (Q^2_{\max}/Q^2_{\min})^(z-1)\f$ or, if * \f$Q^2_{\min}\f$ is zero, \f$Q^2/Q^2_{\max} = z\f$ (where the * limits are set by \a cut). */ virtual double flattenScale(tcPDPtr particle, tcPDPtr parton, const PDFCuts & cut, double l, double z, double & jacobian) const; //@} /** * Pointer to the remnant handler to handle remnant when extracting * partons according to these densities. */ tcRemHPtr remnantHandler() const { return theRemnantHandler; } public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interface. */ static void Init(); protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); protected: /** * A remnant handler which can generate remnants for the parton * extracted withfor this PDF */ RemHPtr theRemnantHandler; protected: /** * Indicate how to deal with x and Q2 which are out of range. */ enum RangeException { rangeFreeze, /**> Freeze the value of the PDF outside the limits. */ rangeZero, /**> Set the PDF to zero outside the limits. */ rangeThrow /**> Throw an exception if outside the limits. */ }; /** * Indicate to subclasses how to deal with x and Q2 which are out of * range. */ RangeException rangeException; private: /** * The static object used to initialize the description of this class. * Indicates that this is an abstract class with persistent data. */ static AbstractClassDescription initPDFBase; /** * Private and non-existent assignment operator. */ PDFBase & operator=(const PDFBase &) = delete; }; ThePEG_DECLARE_CLASS_TRAITS(PDFBase,HandlerBase); } #endif /* ThePEG_PDFBase_H */ diff --git a/PDF/PDFBase.xh b/PDF/PDFBase.xh --- a/PDF/PDFBase.xh +++ b/PDF/PDFBase.xh @@ -1,45 +1,45 @@ // -*- C++ -*- // // PDFBase.xh is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_PDFBase_XH #define ThePEG_PDFBase_XH // // This is the declarations of the exception classes used by the // PDFBase class. // #include "ThePEG/Interface/InterfaceBase.xh" namespace ThePEG { /** @cond EXCEPTIONCLASSES */ /** Exception class used by RemnantHandler if unable to handle a specified particle. */ struct RemnantHandlerCantHandle: public InterfaceException { /** Standard constructor. */ RemnantHandlerCantHandle(string, string); }; /** Exception class used by PDFBase if unable to handle a specified particle. */ struct PDFWrongParticle: public InterfaceException { /** Standard constructor. */ PDFWrongParticle(string p, string pdf, string mess); }; /** Exception class used by PDFBase if values were outside limits. */ struct PDFRange: public Exception { /** Standard constructor. */ PDFRange(string pdf, string var, double val, double lim); }; /** @endcond */ } #endif /* ThePEG_PDFBase_XH */ diff --git a/PDF/PDFCuts.cc b/PDF/PDFCuts.cc --- a/PDF/PDFCuts.cc +++ b/PDF/PDFCuts.cc @@ -1,72 +1,72 @@ // -*- C++ -*- // // PDFCuts.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the PDFCuts class. // #include "PDFCuts.h" #include "ThePEG/Cuts/Cuts.h" #ifdef ThePEG_TEMPLATES_IN_CC_FILE // #include "PDFCuts.tcc" #endif using namespace ThePEG; PDFCuts:: PDFCuts(const Cuts & kc, bool first, const SInterval & S, const SInterval & sHatIn) { SInterval sHat(max(sHatIn.lower(), kc.sHatMin()), min(sHatIn.upper(), kc.sHatMax())); double xmin = sqrt(sHat.lower()/S.upper()); double xmax = sqrt(sHat.upper()/S.lower()); theScale = SInterval(kc.scaleMin(), kc.scaleMax()); double x1max = min(xmax*exp( 2.*kc.yHatMax()), kc.x1Max()); double x2max = min(xmax*exp(-2.*kc.yHatMin()), kc.x2Max()); x1max = min(xmax,x1max); x2max = min(xmax,x2max); if ( first ) { double x1min = max(xmin*exp(2.*kc.yHatMin()), kc.x1Min()); x1min = max(sqr(xmin),x1min); theSMax = x2max*S.upper(); theL = Interval(log(1.0/x1max), log(1.0/x1min)); } else { double x2min = max(xmin*exp(-2.*kc.yHatMax()), kc.x2Min()); x2min = max(sqr(xmin),x2min); theSMax = x1max*S.upper(); theL = Interval(-log(x2max), -log(x2min)); } } PDFCuts:: PDFCuts(const Cuts & kc, bool first, Energy maxEnergy) { SInterval sHat(kc.sHatMin(), kc.sHatMax()); double xmin = sqrt(sHat.lower())/maxEnergy; double xmax = 1.0; theScale = SInterval(kc.scaleMin(), kc.scaleMax()); double x1max = min(xmax*exp( 2.*kc.yHatMax()), kc.x1Max()); double x2max = min(xmax*exp(-2.*kc.yHatMin()), kc.x2Max()); x1max = min(xmax,x1max); x2max = min(xmax,x2max); if ( first ) { double x1min = max(xmin*exp(2.*kc.yHatMin()), kc.x1Min()); x1min = max(sqr(xmin),x1min); theSMax = x2max*sqr(maxEnergy); theL = Interval(-log(x1max), -log(x1min)); } else { double x2min = max(xmin*exp(-2.*kc.yHatMax()), kc.x2Min()); x2min = max(sqr(xmin),x2min); theSMax = x1max*sqr(maxEnergy); theL = Interval(-log(x2max), -log(x2min)); } } diff --git a/PDF/PDFCuts.h b/PDF/PDFCuts.h --- a/PDF/PDFCuts.h +++ b/PDF/PDFCuts.h @@ -1,139 +1,139 @@ // -*- C++ -*- // // PDFCuts.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_PDFCuts_H #define ThePEG_PDFCuts_H // This is the declaration of the PDFCuts class. #include "ThePEG/Config/ThePEG.h" #include "ThePEG/Utilities/Interval.h" #include "ThePEG/Cuts/Cuts.fh" namespace ThePEG { /** * The PDFCuts class is used to specify cuts on scale and momentum * fractions for which a PDFBase object is expected to give parton * densities. It is used to estimate upper limits on the parton * densities to be generated by a PDFBase object. * * @see PDFBase */ class PDFCuts { public: /** @name Standard constructors, assignment and destructors. */ //@{ /** * Default constructor. */ PDFCuts() : theSMax() {} /** * Construction from members. */ PDFCuts(const Interval & newL, const SInterval & newScale, const Energy2 & newSMax) : theL(newL), theScale(newScale), theSMax(newSMax) {} /** * Construction from a Cuts object, using the values for * the first incoming parton (or not). */ PDFCuts(const Cuts &, bool first, const SInterval & S, const SInterval & sHat); /** * Construction from a Cuts object, using the values for * the first incoming parton (or not). */ PDFCuts(const Cuts &, bool first, Energy maxEnergy); //@} public: /** @name Access the individual limits. */ //@{ /** * The minimum value of \f$\log(1/x)\f$. */ double lMin() const { return theL.lower(); } /** * The maximum value of \f$\log(1/x)\f$. */ double lMax() const { return theL.upper(); } /** * The minimum value of x. */ double xMin() const { return exp(-lMax()); } /** * The maximum value of x. */ double xMax() const { return exp(-lMin()); } /** * The lower limit on the scale to be used. */ Energy2 scaleMin() const { return theScale.lower(); } /** * The upper limit on the scale to be used. */ Energy2 scaleMax() const { return theScale.upper(); } /** * The maximum scale for a given momentum fraction. */ Energy2 scaleMax(double x) const { return min(scaleMax(), sMax()*x); } /** * The maximum scale for a given logarithmic momentum fraction. */ Energy2 scaleMaxL(double l) const { return scaleMax(exp(-l)); } /** * The maximum invariant mass squared of the colliding particles. */ Energy2 sMax() const { return theSMax; } //@} private: /** * The minimum and maximum values of \f$\log(1/x)\f$. */ Interval theL; /** * The limits on the scale to be used. */ SInterval theScale; /** * The maximum invariant mass squared of the colliding particles. */ Energy2 theSMax; }; } #endif /* ThePEG_PDFCuts_H */ diff --git a/PDF/PartonBin.cc b/PDF/PartonBin.cc --- a/PDF/PartonBin.cc +++ b/PDF/PartonBin.cc @@ -1,75 +1,75 @@ // -*- C++ -*- // // PartonBin.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the PartonBin class. // #include "PartonBin.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/PDF/PDFBase.h" #include "ThePEG/PDF/NoPDF.h" #include "ThePEG/PDF/RemnantHandler.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Utilities/UtilityBase.h" #include "ThePEG/Utilities/Maths.h" using namespace ThePEG; PartonBin::PartonBin() : thePDFDim(), theRemDim() {} PartonBin:: PartonBin(tcPDPtr p, tPBPtr inc, tcPDPtr pi, tcPDFPtr pdf, const PDFCuts & newCuts) : theParticle(p), theIncomingBin(inc), theParton(pi), thePDF(pdf), thePDFDim(0), theRemDim(0), theCuts(newCuts) { if ( pdf ) theRemnantHandler = pdf->remnantHandler(); } PartonBin::~PartonBin() {} int PartonBin::nDim(bool doscale) { if ( !incoming() ) return 0; if ( dynamic_ptr_cast::tcp>(pdf()) ) thePDFDim = 0; else if ( doscale ) thePDFDim = 2; else thePDFDim = 1; theRemDim = remnantHandler()->nDim(*this, !doscale); return pdfDim() + remDim() + incoming()->nDim(true); } tPBPtr PartonBin::getFirst() { return incoming()? incoming()->getFirst(): tPBPtr(this); } void PartonBin::persistentOutput(PersistentOStream & os) const { os << theParticle << theIncomingBin << theOutgoing << theParton << thePDF << theRemnantHandler << thePDFDim << theRemDim << cuts().lMin() << cuts().lMax() << ounit(cuts().scaleMin(), GeV2) << ounit(cuts().scaleMax(), GeV2) << ounit(cuts().sMax(), GeV2); } void PartonBin::persistentInput(PersistentIStream & is, int) { double lmin = 0.0; double lmax = 0.0; Energy2 scmin = ZERO; Energy2 scmax = ZERO; Energy2 smax = ZERO; is >> theParticle >> theIncomingBin >> theOutgoing >> theParton >> thePDF >> theRemnantHandler >> thePDFDim >> theRemDim >> lmin >> lmax >> iunit(scmin, GeV2) >> iunit(scmax, GeV2) >> iunit(smax, GeV2); theCuts = PDFCuts(Interval(lmin, lmax), SInterval(scmin, scmax), smax); } ClassDescription PartonBin::initPartonBin; void PartonBin::Init() {} diff --git a/PDF/PartonBin.h b/PDF/PartonBin.h --- a/PDF/PartonBin.h +++ b/PDF/PartonBin.h @@ -1,263 +1,263 @@ // -*- C++ -*- // // PartonBin.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_PartonBin_H #define ThePEG_PartonBin_H // This is the declaration of the PartonBin class. #include "ThePEG/Config/ThePEG.h" #include "ThePEG/Utilities/ClassDescription.h" #include "ThePEG/Utilities/Maths.h" #include "ThePEG/PDF/PDFBase.h" #include "ThePEG/PDF/PDFCuts.h" #include "ThePEG/Vectors/Transverse.h" #include "ThePEG/EventRecord/Particle.h" #include "PartonBin.fh" namespace ThePEG { /** * The PartonBin class is used by the PartonExtractor class to store * information about the extraction of a parton from a * particle. Several PartonBin objects can be used to specify a whole * chain of partons extracted from particles extracted from other * particles. A PartonBin without an incoming() PartonBin represents * the incoming particle itself and is used to stop recursion. * * After the extraction of a parton, the kinematical variables of that * extraction is stored in a orresponding PartonBinInfo object. * * @see PartonExtractor * */ class PartonBin: public Base { public: /** A vector of pointers to PartonBin objects. */ typedef vector PBVector; public: /** @name Standard constructors, assignment and destructors. */ //@{ /** * Standard constructor. * @param p the incoming particle type. Possibly null if this bin * represents the incoming particle itself. * @param prev the PartonBin of the incoming particle. Possibly null * if this bin represents the incoming particle itself. * @param pi the parton to be extracted. * @param pdf the density function to be used. Possibly null if this * bin represents the incoming particle itself. * @param newCuts the kinematical cuts on the extraction. */ PartonBin(tcPDPtr p, tPBPtr prev, tcPDPtr pi, tcPDFPtr pdf, const PDFCuts & newCuts); /** * Default constructor. */ PartonBin(); /** * Destructor. */ virtual ~PartonBin(); //@} public: /** @name Access the information in this ParticleBin. */ //@{ /** * The incoming particle type. */ tcPDPtr particle() const { return theParticle; } /** * In the case the incoming particle in turn is extracted from * another particle, return the PartonBin for that extraction. */ tPBPtr incoming() const { return theIncomingBin; } /** * The parton bins corresponding to the extracted parton if it in * turn can be extracted from. */ const PBVector & outgoing() const { return theOutgoing; } /** * Add a parton bin corresponding to the extracted parton if it in * turn can be extracted from. */ void addOutgoing(tPBPtr pb) { theOutgoing.push_back(pb); } /** * The extracted parton type. */ tcPDPtr parton() const { return theParton; } /** * The PDFBase object describing the momentum distribution of the * parton within the particle in this PartonBin. */ tcPDFPtr pdf() const { return thePDF; } /** * The remnant handler associated with the pdf(). */ tcRemHPtr remnantHandler() const { return theRemnantHandler; } /** * Detemine the number of degrees of freedom needed to generate the * phase space of this and parent partons. If doscale is true this * bin is expected to generate the scale in addition to the momentum * fraction. */ int nDim(bool doscale); /** * Return the number of degrees of freedom used by the parton * density and remnant handler. */ int pdfDim() const { return thePDFDim; } /** * Return the number of degrees of freedom used by the parton * density and remnant handler. */ int remDim() const { return theRemDim; } //@} /** @name Functions used in the generation. */ //@{ /** * Return the cuts specified for this bin. */ const PDFCuts & cuts() const { return theCuts; } /** * Return the parton bin corresponding to the first incoming particle. */ tPBPtr getFirst(); //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interface. */ static void Init(); private: /** * The incoming particle type. */ cPDPtr theParticle; /** * In the case the incoming particle in turn is extracted from * another particle, return the PartonBin for that extraction. */ tPBPtr theIncomingBin; /** * The parton bins corresponding to the extracted parton if it * itself can be extracted from. */ PBVector theOutgoing; /** * The extracted parton type. */ cPDPtr theParton; /** * The PDFBase object describing the momentum distribution of the * parton within the particle in this PartonBin. */ cPDFPtr thePDF; /** * The remnant handler associated with the pdf(). */ cRemHPtr theRemnantHandler; /** * The number of degrees of freedom needed to generate the phase * space for this parton for the parton density. */ int thePDFDim; /** * The number of degrees of freedom needed to generate the phase * space for this parton for the remnant handler. */ int theRemDim; /** * The cuts specified for this bin. */ PDFCuts theCuts; private: /** * Describe a concrete class with persistent data. */ static ClassDescription initPartonBin; /** * Private and non-existent assignment operator. */ PartonBin & operator=(const PartonBin &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the base classes * of PartonBin. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of PartonBin. */ typedef Base NthBase; }; /** This template specialization informs ThePEG about the name of the * PartonBin class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "ThePEG::PartonBin"; } }; /** @endcond */ } #endif /* ThePEG_PartonBin_H */ diff --git a/PDF/PartonBinInstance.cc b/PDF/PartonBinInstance.cc --- a/PDF/PartonBinInstance.cc +++ b/PDF/PartonBinInstance.cc @@ -1,145 +1,145 @@ // -*- C++ -*- // // PartonBinInstance.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the PartonBinInstance class. // #include "PartonBinInstance.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG; PartonBinInstance::PartonBinInstance() : theJacobian(1.0), theXi(-1.0), theEps(-1.0), theLi(-1.0), theX(-1.0), theL(-1.0), theScale(ZERO), theRemnantWeight(0.0) {} PartonBinInstance::PartonBinInstance(const PartonBinInstance & x) : Base(x), theBin(x.theBin), theBins(x.theBins), theIncoming(x.theIncoming), theJacobian(x.theJacobian), theParticle(x.theParticle), theParton(x.theParton), thePartons(x.thePartons), theXi(x.theXi), theEps(x.theEps), theLi(x.theLi), theX(x.theX), theL(x.theL), theScale(x.theScale), theKT(x.theKT), theRemnantWeight(x.theRemnantWeight), theRemnants(x.theRemnants), theRemInfo(x.theRemInfo) {} PartonBinInstance::PartonBinInstance(tcPBPtr pb, tPBIPtr pbi) : theBin(pb), theJacobian(1.0), theXi(-1.0), theEps(-1.0), theLi(-1.0), theX(-1.0), theL(-1.0), theScale(ZERO), theRemnantWeight(0.0) { if ( pbi ) theIncoming = pbi; else if ( bin()->incoming() ) theIncoming = new_ptr(PartonBinInstance(bin()->incoming())); } PartonBinInstance::PartonBinInstance(tPPtr part, tcPBPtr pb, Energy2 scale) : theBin(pb), theJacobian(1.0), theParton(part), theXi(1.0), theEps(0.0), theLi(0.0), theX(1.0), theL(0.0), theScale(scale), theRemnantWeight(1.0) { if ( !pb->incoming() || part->parents().empty() ) return; particle(parton()->parents()[0]); Energy2 P2 = max(-particle()->momentum().m2(), ZERO); theXi = parton()->momentum().dirPlus()/particle()->momentum().dirPlus(); theLi = -log(xi()); theIncoming = new_ptr(PartonBinInstance(particle(), pb->incoming(), P2)); theX = xi()*incoming()->x(); theL = li() + incoming()->li(); theEps = Math::exp1m(-li()); } PartonBinInstance::PartonBinInstance(tPPtr Part, tPPtr part, tcPBPtr pb, Energy2 scale) : theBin(pb), theJacobian(1.0), theParton(part), theXi(1.0), theEps(0.0), theLi(0.0), theX(1.0), theL(0.0), theScale(scale), theRemnantWeight(1.0) { if ( !pb->incoming() ) return; particle(Part); Energy2 P2 = max(-particle()->momentum().m2(), ZERO); theXi = parton()->momentum().dirPlus()/particle()->momentum().dirPlus(); theLi = -log(xi()); theIncoming = new_ptr(PartonBinInstance(particle(), pb->incoming(), P2)); theX = xi()*incoming()->x(); theL = li() + incoming()->li(); theEps = Math::exp1m(-li()); } PartonBinInstance::~PartonBinInstance() {} tPBIPtr PartonBinInstance::getFirst() { return incoming()? incoming()->getFirst(): tPBIPtr(this); } // TAKE AWAY ? void PartonBinInstance::reset(double lx, Energy2 Q2) { l(lx); li(lx); scale(Q2); particle(tPPtr()); parton(tPPtr()); theRemnants.clear(); thePartons.clear(); remnantWeight(1.0); } void PartonBinInstance::prepare() { li(-1.0); l(0.0); if ( !incoming() ) return; // li(-1.0); // l(-1.0); reset(-1.0, ZERO); incoming()->prepare(); } bool PartonBinInstance::hasPoleIn1() const { return ( !incoming() || incoming()->hasPoleIn1()) && (!pdf() || pdf()->hasPoleIn1(particleData(), partonData()) ); } // TAKE AWAY ? void PartonBinInstance::generate(const double * r) { scale(ZERO); if ( !incoming() ) return; if ( li() >= 0 ) return; li(0.0); jacobian(1.0); remnantWeight(1.0); if ( bin()->pdfDim() ) li(pdf()->flattenL(particleData(), partonData(), bin()->cuts(), *r++, theJacobian)); if ( bin()->pdfDim() > 1 ) scale(pdf()->flattenScale(particleData(), partonData(), bin()->cuts(), li(), *r++, theJacobian) *bin()->cuts().scaleMaxL(li())); incoming()->generate(r); l(li() + incoming()->l()); } void PartonBinInstance::persistentOutput(PersistentOStream & os) const { os << theBin << theBins << theIncoming << theJacobian << theParticle << theParton << thePartons << theXi << theEps << theLi << theX << theL << ounit(theScale, GeV2) << ounit(theKT, GeV) << theRemnantWeight << theRemnants; } void PartonBinInstance::persistentInput(PersistentIStream & is, int) { is >> theBin >> theBins >> theIncoming >> theJacobian >> theParticle >> theParton >> thePartons >> theXi >> theEps >> theLi >> theX >> theL >> iunit(theScale, GeV2) >> iunit(theKT, GeV) >> theRemnantWeight >> theRemnants; theRemInfo = RemIPtr(); } ClassDescription PartonBinInstance::initPartonBinInstance; // Definition of the static class description member. void PartonBinInstance::Init() { } diff --git a/PDF/PartonBinInstance.h b/PDF/PartonBinInstance.h --- a/PDF/PartonBinInstance.h +++ b/PDF/PartonBinInstance.h @@ -1,481 +1,481 @@ // -*- C++ -*- // // PartonBinInstance.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_PartonBinInstance_H #define THEPEG_PartonBinInstance_H // This is the declaration of the PartonBinInstance class. #include "ThePEG/Config/ThePEG.h" #include "ThePEG/PDF/PartonBin.h" namespace ThePEG { ThePEG_DECLARE_CLASS_POINTERS(PartonBinInstance,PBIPtr); /** A pair of pointers to PartonBinInstance objects. */ typedef pair PBIPair; ThePEG_DECLARE_CLASS_POINTERS(RemInfoBase,RemIPtr); /** * PartonBinInstance is used to store information about the generation * of a given parton extraction for a corresponding PartonBin object. */ class PartonBinInstance: public PersistentBase { public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ PartonBinInstance(); /** * Copy-constructor. */ PartonBinInstance(const PartonBinInstance &); /** * Destructor. */ virtual ~PartonBinInstance(); /** * Constructor taking a PartonBin as argument. The second argument * should be used if the incoming bin is already known and exists. */ PartonBinInstance(tcPBPtr, tPBIPtr = tPBIPtr()); /** * Constructor using an already prepared extracted parton. This will * also initialize the x, and scale values. To calculate the * momentum fractions, a Direction<0> object must have been properly * initialized. * * @param parton the extracted parton which must have its first * parent set to define the particle extracted from. * * @param pb the PartonBin object corresponding to the extracted \a * parton. If the particle extracted from in turn has been * extracted, the incoming() member of the PartonBin must point to * the corresponding PartonBin. * * @param scale the resolution scale at which the \a parton was * extracted. */ PartonBinInstance(tPPtr parton, tcPBPtr pb, Energy2 scale = ZERO); /** * Constructor using a parton which is to be extracted from the * given particle, but no mother-child relations exist, yet. This * will also initialize the x, and scale values. To calculate the * momentum fractions, a Direction<0> object must have been properly * initialized. */ PartonBinInstance(tPPtr particle, tPPtr parton, tcPBPtr pb, Energy2 scale = ZERO); //@} public: /** @name Access information about the corresponding PartonBin object. */ //@{ /** * Return a pointer to the PartonBin this instance refer to. */ tcPBPtr bin() const { return theBin; } /** * Return pointers to the bins this instance refer to in case more * than one parton has been extracted. */ const PartonVector & bins() const { return theBins; } /** * Return a pointer to the data object of the incoming particle. */ tcPDPtr particleData() const { return bin()->particle(); } /** * Return a pointer to the data object of the extracted parton. */ tcPDPtr partonData() const { return bin()->parton(); } /** * In the case the incoming particle in turn is extracted from * another particle, return the PartonBinInstance for that * extraction. */ tPBIPtr incoming() const { return theIncoming; } /** * Return the parton bin instance corresponding to the first * incoming particle for this bin. */ tPBIPtr getFirst(); /** * The PDFBase object describing the momentum distribution of the * parton within the particle in this PartonBin. */ tcPDFPtr pdf() const { return bin()->pdf(); } /** * The remnant handler associated with the pdf(). */ tcRemHPtr remnantHandler() const { return bin()->remnantHandler(); } /** * Return true if the corresponding PDFs has a pole at $x=1$ for the * current particle/parton combination. */ bool hasPoleIn1() const; //@} /** @name Functions used for the generation. */ //@{ /** * Reset the current PartonBin, making room for a new event. */ void reset(double lx = 0, Energy2 Q2 = ZERO); /** * Reset last generated l and Q2 values of this and parent bins. */ void prepare(); /** * Generate l and Q2 of this and parent bins. */ void generate(const double * r); /** * Get the jacobian associated with the phase space point generated. */ double jacobian() const { return theJacobian; } /** * Set the jacobian associated with the phase space point generated. */ void jacobian(double j) { theJacobian = j; } //@} /** @name Access information about the generated extraction. */ //@{ /** * Get the current particle instance. */ tPPtr particle() const { return theParticle; } /** * Set the current particle instance. */ void particle(tPPtr p) { theParticle = p; } /** * Get the current parton instance. */ tPPtr parton() const { return theParton; } /** * Set the current parton instance. */ void parton(tPPtr p) { theParton = p; } /** * The currently extracted partons (in case of multiple * interactions. */ const PVector & partons() const { return thePartons; } /** * Get the momentum fraction of this parton w.r.t. the incoming * particle in this bin. */ double xi() const { if ( theXi < 0.0 ) theXi = exp(-li()); return theXi; } /** * Get one minus the momentum fraction of this parton w.r.t. the * incoming particle in this bin. */ double eps() const { if ( theEps < 0.0 ) theEps = Math::exp1m(-li()); return theEps; } /** * Get the logarithmic momentum fraction of this parton w.r.t. the * incoming particle in this bin. */ double li() const { return theLi; } /** * Set the logarithmic momentum fraction of this parton w.r.t. the * incoming particle in this bin. */ void li(double lx) { theLi = lx; theXi = theEps = -1.0; } /** * Get the momentum fraction of this parton w.r.t. the collidig * particles. */ double x() const { if ( theX < 0.0 ) theX = exp(-l()); return theX; } /** * Get the logarithmic momentum fraction of this parton w.r.t. the * collidig particles. */ double l() const { return theL; } /** * Set the logarithmic momentum fraction of this parton w.r.t. the * collidig particles. */ void l(double lx) { theL = lx; theX = -1.0; } /** * Get the scale at which the current parton was extracted. */ Energy2 scale() const { return theScale; } /** * Set the scale at which the current parton was extracted. */ void scale(Energy2 s) { theScale = s; } /** * Return the transverse momentum of the extracted parton. */ const TransverseMomentum & kT() const { return theKT; } /** * Get the weight associated with the remnant generation. */ double remnantWeight() const { return theRemnantWeight; } /** * Set the weight associated with the remnant generation. */ void remnantWeight(double w) { theRemnantWeight = w; } /** * Get the current remnants. */ const PVector & remnants() const { return theRemnants; } /** * Set the current remnants. */ void remnants(const PVector & rems) { theRemnants = rems; } /** * Get information saved by the remnant handler from the generation, * to be used in the construction of the remnants. (In addition the * remnantWeight and remnants() may be used for this purpose.) */ tRemIPtr remnantInfo() const { return theRemInfo; } /** * Set information saved by the remnant handler from the generation, * to be used in the construction of the remnants. (In addition the * remnantWeight and remnants() may be used for this purpose.) */ void remnantInfo(tRemIPtr ri) { theRemInfo = ri; } //@} 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(); private: /** * Pointer to the main bin this instance refer to. */ cPBPtr theBin; /** * Pointer to the main bin (and secondary in case several partons * have been extracted this instance refer to. */ PartonVector theBins; /** * In the case the incoming particle in turn is extracted from * another particle, this is the PartonBinInstance for that * extraction. */ PBIPtr theIncoming; /** * The jacobian associated with the phase space point generated. */ double theJacobian; /** * The current particle instance. */ PPtr theParticle; /** * The current parton instance. */ PPtr theParton; /** * The currently extracted partons (in case of multiple * interactions. */ PVector thePartons; /** * The momentum fraction (xi, li=log(xi), eps=1-xi), of this * parton w.r.t. the incoming particle in this * bin. */ mutable double theXi; /** * The momentum fraction (xi, li=log(xi), eps=1-xi), of this * parton w.r.t. the incoming particle in this * bin. */ mutable double theEps; /** * The momentum fraction (xi, li=log(xi), eps=1-xi), of this * parton w.r.t. the incoming particle in this * bin. */ double theLi; /** * The momentum fraction (x, l=log(x)) of this parton * w.r.t. the collidig particles. */ mutable double theX; /** * The momentum fraction (x, l=log(x)) of this parton * w.r.t. the collidig particles. */ double theL; /** * The scale at which the current parton was extracted. */ Energy2 theScale; /** * The transverse momentum of the extracted parton. */ TransverseMomentum theKT; /** * The weight associated with the remnant generation. */ double theRemnantWeight; /** * The current remnants. */ PVector theRemnants; /** * The information saved by the remnant handler from the generation, * to be used in the construction of the remnants. (In addition the * remnantWeight and lastRemnants() may be used for this purpose.) */ RemIPtr theRemInfo; private: /** * Describe a concrete class with persistent data. */ static ClassDescription initPartonBinInstance; /** * Private and non-existent assignment operator. */ PartonBinInstance & operator=(const PartonBinInstance &) = delete; }; /** Empty base class. A RemnantHandler may use sub-classes to store information about the generation of remnants. */ class RemInfoBase: public Base { public: /** The descructor. */ virtual ~RemInfoBase() {} }; } namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the base classes * of PartonBinInstance. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of PartonBinInstance. */ typedef Base NthBase; }; /** This template specialization informs ThePEG about the name of the * PartonBinInstance class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "ThePEG::PartonBinInstance"; } }; /** @endcond */ } #endif /* THEPEG_PartonBinInstance_H */ diff --git a/PDF/PartonExtractor.cc b/PDF/PartonExtractor.cc --- a/PDF/PartonExtractor.cc +++ b/PDF/PartonExtractor.cc @@ -1,654 +1,654 @@ // -*- C++ -*- // // PartonExtractor.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the PartonExtractor class. // #include "PartonExtractor.h" #include "ThePEG/Handlers/XComb.h" #include "ThePEG/Cuts/Cuts.h" #include "ThePEG/PDF/NoPDF.h" #include "ThePEG/PDF/RemnantHandler.h" #include "ThePEG/PDF/BeamParticleData.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/EventRecord/Step.h" #include "ThePEG/EventRecord/SubProcess.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/SimplePhaseSpace.h" #include "ThePEG/Utilities/UtilityBase.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/PDT/EnumParticles.h" using namespace ThePEG; PartonExtractor::PartonExtractor() : theMaxTries(100), flatSHatY(false) {} PartonExtractor::~PartonExtractor() {} IBPtr PartonExtractor::clone() const { return new_ptr(*this); } IBPtr PartonExtractor::fullclone() const { return new_ptr(*this); } PartonPairVec PartonExtractor:: getPartons(Energy maxEnergy, const cPDPair & incoming, const Cuts & kc) const { PartonPairVec result; PartonVector first; PDFCuts cuts1(kc, true, maxEnergy); PBPtr p1 = new_ptr(PartonBin(PDPtr(), PBPtr(), incoming.first, PDFPtr(), cuts1)); addPartons(p1, cuts1, theFirstPDF, first); PartonVector second; PDFCuts cuts2(kc, false, maxEnergy); PBPtr p2 = new_ptr(PartonBin(PDPtr(), PBPtr(), incoming.second, PDFPtr(), cuts2)); addPartons(p2, cuts2, theSecondPDF, second); for ( PartonVector::iterator it1 = first.begin(); it1 != first.end(); ++it1 ) for ( PartonVector::iterator it2 = second.begin(); it2 != second.end(); ++it2 ) result.push_back(PBPair(*it1, *it2)); // We add the original parton bins as well to avoid them being // deleted. result.push_back(PBPair(p1, p2)); return result; } void PartonExtractor:: addPartons(tPBPtr incoming, const PDFCuts & cuts, tcPDFPtr pdf, PartonVector & pbins) const { if(!pdf) pdf = getPDF(incoming->parton()); if ( dynamic_ptr_cast::tcp>(pdf) || incoming->parton() == incoming->particle() ) { pbins.push_back(incoming); return; } cPDVector partons = pdf->partons(incoming->parton()); for ( int i = 0, N = partons.size(); i < N; ++i ) { PBPtr pb = new_ptr(PartonBin(incoming->parton(), incoming, partons[i], pdf, cuts)); incoming->addOutgoing(pb); addPartons(pb, cuts, PDFPtr(), pbins); } } tcPDFPtr PartonExtractor::getPDF(tcPDPtr particle) const { for ( vector::const_iterator it = theSpecialDensities.begin(); it != theSpecialDensities.end(); ++it ) if ( (**it).canHandle(particle) ) return *it; Ptr::tcp p = dynamic_ptr_cast::tcp>(particle); if ( !p || !p->pdf() ) return noPDF(); return p->pdf(); } void PartonExtractor::select(tXCombPtr newXComb) { theLastXComb = newXComb; } tPBIPtr PartonExtractor::partonBinInstance(tcPPtr p) const { PartonBinInstanceMap::const_iterator it = partonBinInstances().find(p); return it == partonBinInstances().end()? PBIPtr(): it->second; } void PartonExtractor:: colourConnect(tPPtr particle, tPPtr parton, const tPVector & remnants) const { // Sorry cannot handle coloured resolved particles. if ( particle->coloured() ) throw RemColException(*this); // First connect the loose colour line from the extacted parton. if ( parton->hasColour() ) findConnect(parton->colourLine(), parton, true, remnants.rbegin(), remnants.rend()); // First connect the loose anti-colour line from the extacted parton. if ( parton->hasAntiColour() ) findConnect(parton->antiColourLine(), parton, false, remnants.begin(), remnants.end()); // Go through the rest of the remnants and create new colour lines // if needed. Go through it forwards and backwards to catch possible // inconsistencies. for ( tPVector::const_iterator it = remnants.begin(); it != remnants.end(); ++it ) { if ( (**it).hasAntiColour() && !(**it).antiColourLine() ) findConnect(ColourLine::create(*it, true), *it, false, it + 1, remnants.end()); } for ( tPVector::const_reverse_iterator it = remnants.rbegin(); it != remnants.rend(); ++it ) { if ( (**it).hasColour() && !(**it).colourLine() ) findConnect(ColourLine::create(*it), *it, true, it + 1, remnants.rend()); } } Energy2 PartonExtractor::newScale() { return lastScale(); } pair PartonExtractor::nDims(const PBPair & pbins) { // if photon from a lepton or proton generate scale bool genscale[2]={false,false}; for(unsigned int ix=0;ix<2;++ix) { PBPtr bin = ix==0 ? pbins.first : pbins.second; if (!bin || !bin->particle() || !bin->parton()) continue; if(bin->pdf()->partons(bin->particle()).size()==1 && bin->particle()->id()!=bin->parton()->id()) genscale[ix]=true; } return make_pair(pbins.first ->nDim(genscale[0]), pbins.second->nDim(genscale[1])); } void PartonExtractor::prepare(const PBIPair & pbins) { partonBinInstances().clear(); pbins.first->prepare(); pbins.second->prepare(); } void PartonExtractor::updatePartonBinInstances(const PBIPair & pbins) { partonBinInstances().clear(); tPBIPtr current = pbins.first; while ( current->incoming() ) { partonBinInstances()[current->parton()] = current; current = current->incoming(); } current = pbins.second; while ( current->incoming() ) { partonBinInstances()[current->parton()] = current; current = current->incoming(); } } bool PartonExtractor:: generateL(const PBIPair & pbins, const double * r1, const double * r2) { Direction<0> dir(true); generateL(*pbins.first, r1); dir.reverse(); generateL(*pbins.second, r2); if ( !flatSHatY || pbins.first->hasPoleIn1() || pbins.second->hasPoleIn1() ) return true; Energy2 shmax = lastCuts().sHatMax(); Energy2 shmin = lastCuts().sHatMin(); Energy2 sh = shmin*pow(shmax/shmin, *r1); double ymax = lastCuts().yHatMax(); double ymin = lastCuts().yHatMin(); double km = log(shmax/shmin); ymax = min(ymax, log(lastCuts().x1Max()*sqrt(lastS()/sh))); ymin = max(ymin, -log(lastCuts().x2Max()*sqrt(lastS()/sh))); double y = ymin + (*r2)*(ymax - ymin); double l1 = 0.5*log(lastS()/sh) - y; double l2 = 0.5*log(lastS()/sh) + y; pbins.first->li(l1 - pbins.first->l() + pbins.first->li()); pbins.first->l(l1); pbins.first->jacobian(km*(ymax - ymin)); pbins.second->li(l2 - pbins.second->l() + pbins.second->li()); pbins.second->l(l2); pbins.second->jacobian(1.0); return ( pbins.first->li() >= 0.0 && pbins.second->li() >= 0.0 ); } Energy2 PartonExtractor:: generateSHat(Energy2, const PBIPair & pbins, const double * r1, const double * r2, bool haveMEPartons) { Direction<0> dir(true); if(pbins.first->bin()->pdfDim()<=1) pbins.first->scale(-lastScale()); if ( !generate(*pbins.first, r1, lastSHat(), pbins.first->getFirst()->parton()->momentum(), haveMEPartons) ) return -1.0*GeV2; dir.reverse(); if(pbins.second->bin()->pdfDim()<=1) pbins.second->scale(-lastScale()); if ( !generate(*pbins.second, r2, lastSHat(), pbins.second->getFirst()->parton()->momentum(), haveMEPartons) ) return -1.0*GeV2; return (pbins.first->parton()->momentum() + pbins.second->parton()->momentum()).m2(); } void PartonExtractor:: generateL(PartonBinInstance & pb, const double * r) { if ( !pb.incoming() ) return; pb.parton(pb.partonData()->produceParticle(Lorentz5Momentum())); generateL(*pb.incoming(), r + pb.bin()->pdfDim() + pb.bin()->remDim()); pb.particle(pb.incoming()->parton()); if ( pb.li() >= 0 ) return; double jac = 1.0; if ( pb.bin()->pdfDim() ) pb.li(pb.pdf()->flattenL(pb.particleData(), pb.partonData(), pb.bin()->cuts(), *r++, jac)); pb.scale(-1.0*GeV2); if ( pb.bin()->pdfDim() > 1 ) pb.scale(pb.pdf()->flattenScale(pb.particleData(), pb.partonData(), pb.bin()->cuts(), pb.li(), *r++, jac) *pb.bin()->cuts().scaleMaxL(pb.li())); pb.jacobian(jac); pb.l(pb.incoming()->l() + pb.li()); } bool PartonExtractor:: generate(PartonBinInstance & pb, const double * r, Energy2 shat, const Lorentz5Momentum & first, bool haveMEPartons) { if ( !pb.incoming() ) return true; if ( !generate(*pb.incoming(), r + pb.bin()->pdfDim() + pb.bin()->remDim(), shat/pb.xi(), first) ) return false; pb.remnantWeight(1.0); pb.parton()->set5Momentum (pb.remnantHandler()->generate(pb, r + pb.bin()->pdfDim(), pb.scale(), shat, pb.particle()->momentum(),haveMEPartons)); if ( pb.remnantWeight() <= 0.0 ) return false; partonBinInstances()[pb.parton()] = &pb; return true; } void PartonExtractor:: constructRemnants(const PBIPair & pbins, tSubProPtr sub, tStepPtr step) const { partonBinInstances().clear(); LorentzMomentum k1 = pbins.first->parton()->momentum(); LorentzMomentum k2 = pbins.second->parton()->momentum(); LorentzMomentum Ph = k1 + k2; LorentzMomentum Phold = Ph; LorentzRotation Rh = Utilities::getBoostToCM(make_pair(k1, k2)); bool pickside = rndbool(); if ( pickside && pbins.first->incoming() ) { Direction<0> dir(true); constructRemnants(*pbins.first, Ph, k2); construct(*pbins.first, step, false); } if ( pbins.second->incoming() ) { Direction<0> dir(false); constructRemnants(*pbins.second, Ph, pbins.first->parton()->momentum()); construct(*pbins.second, step, false); } if ( (!pickside) && pbins.first->incoming() ) { Direction<0> dir(true); constructRemnants(*pbins.first, Ph, pbins.second->parton()->momentum()); construct(*pbins.first, step, false); } // LorentzRotation rot = Utilities::transformToMomentum(Phold, Ph); k1 = pbins.first->parton()->momentum(); k2 = pbins.second->parton()->momentum(); LorentzRotation rot = Utilities::getBoostFromCM(make_pair(k1, k2))*Rh; Utilities::transform(sub->outgoing(), rot); Utilities::transform(sub->intermediates(), rot); Ph = k1 + k2; if ( abs(Ph.m2() - Phold.m2())/Phold.m2() > 0.000001 ) cerr << Ph.m2()/GeV2 << " was (" << Phold.m2()/GeV2 << ")" << endl; } void PartonExtractor:: constructRemnants(PartonBinInstance & pb, LorentzMomentum & Ph, const LorentzMomentum & k) const { LorentzMomentum P = pb.particle()->momentum(); DVector r = UseRandom::rndvec(pb.bin()->remDim()); if ( r.empty() ) r.push_back(0.0); pb.parton()->setMomentum(pb.remnantHandler()-> generate(pb, &r[0], pb.scale(), Ph.m2(), P)); if ( pb.remnantWeight() <= 0.0 ) throw Veto(); pb.remnantHandler()->boostRemnants(pb); LorentzMomentum Pr = Utilities::sumMomentum(pb.remnants()); transformRemnants(Ph, Pr, k, pb.particle()->momentum()); pb.parton()->setMomentum(pb.particle()->momentum() - Pr); try { Utilities::setMomentum(pb.remnants().begin(), pb.remnants().end(), static_cast(Pr)); } catch ( ThePEG::Exception & e) { throw e; } catch ( ThePEG::Veto ) { throw; } catch ( std::exception & e ) { throw Exception() << "Caught non-ThePEG exception " << e.what() << "in " << "PartonExtractor::constructRemnants" << Exception::eventerror; } partonBinInstances()[pb.parton()] = &pb; if ( !pb.incoming()->incoming() ) return; // We get here if we need to construct remnants recursively. LorentzMomentum Phnew = Ph + Pr; constructRemnants(*pb.incoming(), Phnew, k); LorentzRotation rot = Utilities::transformToMomentum(Ph + Pr, Phnew); Utilities::transform(pb.remnants(), rot); Ph.transform(rot); } LorentzRotation PartonExtractor:: boostRemnants(PBIPair & bins, LorentzMomentum k1, LorentzMomentum k2, bool side1, bool side2) const { if ( !side1 && !side2 ) return LorentzRotation(); LorentzMomentum P1 = bins.first? LorentzMomentum(bins.first->parton()->momentum()): k1; LorentzMomentum Pr1; if ( side1 ) { P1 = bins.first->particle()->momentum(); Pr1 = Utilities::sumMomentum(bins.first->remnants()); } LorentzMomentum P2 = bins.second? LorentzMomentum(bins.second->parton()->momentum()): k2; LorentzMomentum Pr2; if ( side2 ) { P2 = bins.second->particle()->momentum(); Pr2 = Utilities::sumMomentum(bins.second->remnants()); } LorentzRotation Rh = Utilities::getBoostToCM(make_pair(k1, k2)); LorentzMomentum Ph = k1 + k2; // LorentzMomentum Phold = Ph; bool otherside = rndbool(); if ( otherside && side2 ){ Direction<0> dir(false); transformRemnants(Ph, Pr2, k1, P2); k2 = P2 - Pr2; } if ( side1 ){ Direction<0> dir(true); transformRemnants(Ph, Pr1, k2, P1); k1 = P1 - Pr1; } if ( side2 && !otherside ) { Direction<0> dir(false); transformRemnants(Ph, Pr2, k1, P2); k2 = P2 - Pr2; } if ( bins.first ) { if ( bins.first->remnants().size() == 1 ) bins.first->remnants()[0]->setMomentum(Pr1); else Utilities::setMomentum(bins.first->remnants().begin(), bins.first->remnants().end(), static_cast(Pr1)); bins.first->parton()->setMomentum(k1); } if ( bins.second ) { if ( bins.second->remnants().size() == 1 ) bins.second->remnants()[0]->setMomentum(Pr2); else Utilities::setMomentum(bins.second->remnants().begin(), bins.second->remnants().end(), static_cast(Pr2)); bins.second->parton()->setMomentum(k2); } Rh.transform(Utilities::getBoostFromCM(make_pair(k1, k2))); // LorentzMomentum phh = Rh*Phold; return Rh; // return Utilities::transformToMomentum(Phold, Ph); } void PartonExtractor:: transformRemnants(LorentzMomentum & Ph, LorentzMomentum & Pr, const LorentzMomentum & k, const LorentzMomentum & P) const { // don't do this for very soft remnants, as // we may run into numerical troubles; threshold // needs to become a parameter at some point if ( Pr.vect().mag2()/k.vect().mag2() < 1e-10 && sqr(Pr.e()/k.e()) < 1e-10 ) return; TransverseMomentum pt = Pr; try { if ( Direction<0>::pos() ) SimplePhaseSpace::CMS(Pr, Ph, (P + k).m2(), 1.0, 0.0); else SimplePhaseSpace::CMS(Ph, Pr, (k + P).m2(), 1.0, 0.0); LorentzRotation rpt; if ( sqr(Pr.z()) > ZERO ) rpt.rotateY(asin(pt.pt()/Pr.z())); rpt.rotateZ(pt.phi()); rpt = Direction<0>::pos()? Utilities::getBoostFromCM(make_pair(P, k))*rpt: Utilities::getBoostFromCM(make_pair(k, P))*rpt; Ph.transform(rpt); Pr.transform(rpt); } catch ( ImpossibleKinematics & e ) {} } double PartonExtractor::fullFn(const PBIPair & pbins, Energy2 scale, pair noLastPDF) { if(pbins.first->bin()->pdfDim()<=1) pbins.first->scale(scale); if(pbins.second->bin()->pdfDim()<=1) pbins.second->scale(scale); return fullFn(*pbins.first,noLastPDF.first)*fullFn(*pbins.second,noLastPDF.second); } double PartonExtractor::fullFn(const PartonBinInstance & pb, bool noLastPDF) { if ( !pb.incoming() ) return 1.0; if (noLastPDF) return fullFn(*pb.incoming(),false) * pb.jacobian() * pb.remnantWeight() * exp(-pb.li()); return fullFn(*pb.incoming(),false) * pb.jacobian() * pb.remnantWeight() * pb.pdf()->xfl(pb.particleData(), pb.partonData(), pb.scale(), pb.li(), pb.incoming()->scale()); } void PartonExtractor:: construct(const PBIPair & pbins, tStepPtr step) const { // if a long chain we need to break some mother/child relationships if(pbins.first->incoming()) { if(pbins.first->incoming()->incoming()) { if(!pbins.first->parton()->parents().empty()) { tParticleVector parents=pbins.first->parton()->parents(); tPPtr parton = pbins.first->parton(); for(unsigned int ix=0;ixabandonChild(parton); } } } if(pbins.second->incoming()) { if(pbins.second->incoming()->incoming()) { if(!pbins.second->parton()->parents().empty()) { tParticleVector parents=pbins.second->parton()->parents(); tPPtr parton = pbins.second->parton(); for(unsigned int ix=0;ixabandonChild(parton); } } } Direction<0> dir(true); construct(*pbins.first, step); dir.reverse(); construct(*pbins.second, step); } void PartonExtractor:: construct(PartonBinInstance & pb, tStepPtr step, bool boost) const { if ( !pb.incoming() ) return; if ( boost ) pb.remnantHandler()->boostRemnants(pb); if ( pb.incoming()->incoming() ) { step->insertIntermediate(pb.particle(),pb.incoming()->particle(),pb.parton()); } tPVector rem(pb.remnants().begin(), pb.remnants().end()); if ( !step->addDecayProduct(pb.particle(), rem.begin(), rem.end(), false) ) {} colourConnect(pb.particle(), pb.parton(), rem); construct(*pb.incoming(), step); } PBIPair PartonExtractor::newRemnants(tPPair oldp, tPPair newp, tStepPtr step) { PBIPair pb; Direction<0> dir(true); pb.first = newRemnants(partonBinInstance(oldp.first), newp.first, newp.second->momentum()); dir.reverse(); pb.second = newRemnants(partonBinInstance(oldp.second), newp.second, newp.first->momentum()); addNewRemnants(partonBinInstance(oldp.first), pb.first, step); addNewRemnants(partonBinInstance(oldp.second), pb.second, step); return pb; } PBIPtr PartonExtractor:: newRemnants(tPBIPtr oldpb, tPPtr newp, const LorentzMomentum & k) { if ( ! oldpb || !oldpb->incoming() ) return oldpb; Energy2 shat = (k + newp->momentum()).m2(); // Loop over all possible PartonBin sisters to find the one // corresponding to the newly extracted parton. const PartonBin::PBVector & sisters = oldpb->incoming()->bin()->outgoing(); for ( int i = 0, N = sisters.size(); i < N; ++i ) if ( sisters[i]->parton() == newp->dataPtr() ) { // Setup necessary info in new PartonBinInstance object. PBIPtr newpb = new_ptr(PartonBinInstance(sisters[i], oldpb->incoming())); newpb->particle(oldpb->particle()); newpb->parton(newp); newpb->li(log(oldpb->particle()->momentum().dirPlus()/ newp->momentum().dirPlus())); newpb->l(oldpb->l() - oldpb->li() + newpb->li()); Energy2 sc = -newp->scale(); newpb->scale(newp->scale()); if ( oldpb->incoming()->incoming() ) sc = -newpb->particle()->momentum().m2(); // Now we can construct the new remnants. newpb->remnantWeight(1.0); if ( !newpb->remnantHandler()-> recreateRemnants(*newpb, oldpb->parton(), newp, newpb->li(), sc, shat, newpb->particle()->momentum()) ) throw Veto(); if ( newpb->remnantWeight() <= 0.0 ) throw Veto(); return newpb; } throw Veto(); } void PartonExtractor:: addNewRemnants(tPBIPtr oldpb, tPBIPtr newpb, tStepPtr step) { if ( oldpb == newpb ) return; if ( oldpb->parton() != newpb->parton() ) { step->removeDecayProduct(newpb->particle(), oldpb->parton()); if ( !step->addDecayProduct(newpb->particle(), newpb->parton()) ) throw Veto(); } tPVector rem(newpb->remnants().begin(), newpb->remnants().end()); colourConnect(newpb->particle(), newpb->parton(), rem); partonBinInstances()[newpb->parton()] = newpb; if ( !step->addDecayProduct(oldpb->remnants().begin(), oldpb->remnants().end(), rem.begin(), rem.end()) ) throw Veto(); } void PartonExtractor::persistentOutput(PersistentOStream & os) const { os << theLastXComb << theSpecialDensities << theNoPDF << theMaxTries << flatSHatY << theFirstPDF << theSecondPDF; } void PartonExtractor::persistentInput(PersistentIStream & is, int) { is >> theLastXComb >> theSpecialDensities >> theNoPDF >> theMaxTries >> flatSHatY >> theFirstPDF >> theSecondPDF; } ClassDescription PartonExtractor::initPartonExtractor; void PartonExtractor::Init() { static ClassDocumentation documentation ("There is no documentation for the ThePEG::PartonExtractor class"); static RefVector interfaceSpecialDensities ("SpecialDensities", "A list of parton density objects to be used for incoming particles " "overriding possible densities given for particles of the " "BeamParticleData class.", &PartonExtractor::theSpecialDensities, 0, false, false, true, false); static Reference interfaceNoPDF ("NoPDF", "A fixed reference to a NoPDF object to be used for particles without " "substructure.", &PartonExtractor::theNoPDF, true, true, true, false); static Parameter interfaceMaxTries ("MaxTries", "The maximum number of attempts allowed when trying to generate " "remnants.", &PartonExtractor::theMaxTries, 100, 1, 1000, false, false, true); static Switch interfaceFlatSHatY ("FlatSHatY", "The possibility to override the l-generation in the PDFs and generate " "a flat distribution in \\f$\\log(\\hat{s})\\f$ and \\f$y\\f$. This only " "applies if the parton densities do not have poles in \\f$x=1\\f$.", &PartonExtractor::flatSHatY, false, false, false); static SwitchOption interfaceFlatSHatY0 (interfaceFlatSHatY, "Off", "Use the l-generation defined by the PDFs", false); static SwitchOption interfaceFlatSHatY1 (interfaceFlatSHatY, "On", "Generate flat rapidity and \\f$\\log(\\hat{s})\\f$", true); static SwitchOption interfaceFlatSHatNo (interfaceFlatSHatY, "No", "Use the l-generation defined by the PDFs", false); static SwitchOption interfaceFlatSHatYes (interfaceFlatSHatY, "Yes", "Generate flat rapidity and \\f$\\log(\\hat{s})\\f$", true); static Reference interfaceFirstPDF ("FirstPDF", "PDF to override the default PDF for the first beam particle", &PartonExtractor::theFirstPDF, false, false, true, true, false); static Reference interfaceSecondPDF ("SecondPDF", "PDF to override the default PDF for the second beam particle", &PartonExtractor::theSecondPDF, false, false, true, true, false); } RemColException::RemColException(const PartonExtractor & pe) { theMessage << "Parton extractor '" << pe.name() << "' failed to connect " << "the colours of the outgoing partons and the remnants."; severity(maybeabort); } void PartonExtractor::dofinish() { // Only clear partonBinInstances if we have a lastXCombPtr if(lastXCombPtr()) partonBinInstances().clear(); HandlerBase::dofinish(); } diff --git a/PDF/PartonExtractor.h b/PDF/PartonExtractor.h --- a/PDF/PartonExtractor.h +++ b/PDF/PartonExtractor.h @@ -1,458 +1,458 @@ // -*- C++ -*- // // PartonExtractor.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_PartonExtractor_H #define ThePEG_PartonExtractor_H // This is the declaration of the PartonExtractor class. #include "ThePEG/Handlers/HandlerBase.h" #include "ThePEG/Handlers/LastXCombInfo.h" #include "ThePEG/PDF/PartonBin.h" #include "ThePEG/PDF/PartonBinInstance.h" #include "ThePEG/PDF/PDFBase.h" #include "ThePEG/PDT/ParticleData.h" #include "PartonExtractor.xh" namespace ThePEG { /** * The PartonExtractor is a base class defining the interface to * objects responsible for extracting partons from particles. It is * used by a SubProcessHandler which combines one PartonExtractor with * a number of MEBase objects which are the used in an XComb in a * StandardEventHandler to generate hard sub-processes. * * PartonExtractor inherits from the general HandlerBase class and * from the LastXCombInfo class to have easy acces to information * about the currently chosen hard sub-process. * * @see \ref PartonExtractorInterfaces "The interfaces" * defined for PartonExtractor. * @see SubProcessHandler * @see MEBase * @see EventHandler * @see StandardEventHandler * @see XComb * @see HandlerBase * */ class PartonExtractor: public HandlerBase, public LastXCombInfo<> { /** XComb is a friend. */ friend class XComb; public: /** A map of PartonBinInstance objects indexed by the extracted parton. */ typedef map PartonBinInstanceMap; public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ PartonExtractor(); /** * Destructor. */ virtual ~PartonExtractor(); //@} public: /** @name Virtual functions which may be overridden in sub-classes. */ //@{ /** * Return true if this parton extractor can handle the given types * of incoming particles. */ virtual bool canHandle(const cPDPair &) { return true; } /** * Return a vector of possible pairs of parton bins which can be * produced within a given maximum total particle-particle * invariant mass squared, \a maxEnergy sBin. */ virtual PartonPairVec getPartons(Energy maxEnergy, const cPDPair &, const Cuts &) const; /** * May be overriden by sub-classes which have their own oppinion * about what scale to use in a hard subprocess. The default version * simply returns the previously selected scale. */ virtual Energy2 newScale(); /** * Connect the remnants with the colour lines of the extracted * parton. */ virtual void colourConnect(tPPtr particle, tPPtr parton, const tPVector & remnants) const; /** * If remnants has already been created for the given parton, remove * them from the given step and generate new remnants corresponding * to the parton newp and add them to the step. The new parton bins * are returned. * @throws Veto if remnant generation failed for whatever reason. */ virtual PBIPair newRemnants(tPPair oldp, tPPair newp, tStepPtr step); /** * Determine the number of random numbers needed to calculate * \f$\hat{s}\f$ and the product of all densitiy functions. */ virtual pair nDims(const PBPair & pbins); /** * Prepare the given parton bin instances for generating a new * event. */ virtual void prepare(const PBIPair & pbins); /** * Update information on the given parton bin instances */ virtual void updatePartonBinInstances(const PBIPair & pbins); /** * Generate \f$l=\log(1/x)\f$ for all parton extractions. */ virtual bool generateL(const PBIPair & pbins, const double * r1, const double * r2); /** * Used by generateL() for each of the final parton * bins. Direction<0> is set to positive(negative) for the * first(second) final bin. */ virtual void generateL(PartonBinInstance & pb, const double * r); /** * Generate the rest of the degrees of freedom to calculate * \f$\hat{s}\f$ and the product of all densitiy functions. */ virtual Energy2 generateSHat(Energy2 s, const PBIPair & pbins, const double * r1, const double * r2, bool mepartons = false); /** * Return the product of all density functions. If noLastPDF.first * (.second) is true, then the PDF value multiplied by the momentum * fraction for the last extracted parton from the first (second) * incoming particle will be excluded. */ virtual double fullFn(const PBIPair & pbins, Energy2 scale, pair noLastPDF = make_pair(false,false)); /** * Construct remnants and add them to the step. */ virtual void construct(const PBIPair & pbins, tStepPtr step) const; /** * Construct remnants for partons created outside of this * extractor. Information about the incoming partons should be set * in \a pbins and the hard subprocess should be present in \a * sub. Generated remnants will be added to the \a step. * @throws Veto if remnant generation failed for whatever reason. */ virtual void constructRemnants(const PBIPair & pbins, tSubProPtr sub, tStepPtr step) const; /** * Get boost for hard subsystem and boost remnants. To be called * after re-constructing remnants and obtaining new momenta of the * partons entering the hard subsystem, but ignoring detailed energy * and momentum conservation. Perform boosts of the remnants to * conserve energy and momentum and return the boost needed for the * hard subsystem. \a bins contains the current state of the * incoming partons, including the momenta obtained after the * remnant generation. \a k1 and \a k2 contains the momenta of the * incoming partons before the remnant generation. If either side * has no new remnants, \a side1 and/or \a side2 should be false. */ virtual LorentzRotation boostRemnants(PBIPair & bins, LorentzMomentum k1, LorentzMomentum k2, bool side1, bool side2) const; //@} /** @name Access information about the current paron extraction. */ //@{ /** * Return the corresponding parton bin instance for a given * extracted parton. */ tPBIPtr partonBinInstance(tcPPtr) const; /** * Set the XComb object describing the current hard sub-process. */ void select(tXCombPtr newXComb); //@} /** * The maximum number of attempts allowed when trying to generate * remnants. */ int maxTries() const { return theMaxTries; } /** * Return the PDFBase object to be used for the incoming particle * type. If one of theSpecialDensities matches the particle type it * is returned, otherwise if particle is a BeamParticleData use the * PDFBase object specified there. If also this fails, return a * NoPDF object. */ tcPDFPtr getPDF(tcPDPtr particle) const; protected: /** @name Functions used by the main virtual functions. Some of these may be overridden in sub-classes. */ //@{ /** * Used by generateSHat() for each of the final parton * bins. Direction<0> is set to positive(negative) for the * first(second) final bin, \a pb. Should ask the remnant handler to * generate what is needed to construct the extracted parton * momentum. \a r is a pointer to an array of random numbers to be * used and \a shat is the approximate invariant mass squared of the * hard system produced by the extracted parton and the primary * parton from the other side. \a first is the momentum of the * original incoming particle. * * @return false if no remnants could be generated. */ virtual bool generate(PartonBinInstance & pb, const double * r, Energy2 shat, const Lorentz5Momentum & first, bool haveMEPartons = false); /** * Used by the public fullFn() for each of the final parton bins. */ virtual double fullFn(const PartonBinInstance & pb, bool noLastPDF = false); /** * Used by the public construct() for each of the final parton * bins. If boost is false, no boost is necessary to give the * remnants proper momenta. */ virtual void construct(PartonBinInstance & pb, tStepPtr step, bool boost = true) const; /** * Used by the public newRemnants() for each of the parton bins. * @throws Veto if remnant generation failed for whatever reason. */ PBIPtr newRemnants(tPBIPtr oldpb, tPPtr newp, const LorentzMomentum & k); /** * Used by the public newRemnants() for each of the parton bins. */ void addNewRemnants(tPBIPtr oldpb, tPBIPtr newpb, tStepPtr step); /** * Transform remnant momentum. Assuming remnants have been generated * with momentum \a Pr without considering energy-momentum * conservation, shift the momentum, possibly compensating with the * momentum of the hard subsystem, \a Ph. For information the * momentum of the parton entering the hard subsystem from the other * side, \a k, and the momentum of the remnants parent particle , \a * P is given. Note that Direction<0> must be set to determine if * the parent particle is to be assumed to go in the positive or * negative direction. */ virtual void transformRemnants(LorentzMomentum & Ph, LorentzMomentum & Pr, const LorentzMomentum & k, const LorentzMomentum & P) const; /** * Construct remnants recursively for the parton represented by \a * pb. Used by constructRemnants(const PBIPair &, tSubProPtr, tStepPtr). * Shift the momentum, \a Ph, of the hard subsystem to conserve * energy and momentum if necessary. The momentum, \a k, of the * parton coming into the hard subsystem from the other side is * given for information. Note that Direction<0> must be set to * determine if the parent particle is to be assumed to go in the * positive or negative direction. * @throws Veto if remnant generation failed for whatever reason. */ virtual void constructRemnants(PartonBinInstance & pb, LorentzMomentum & Ph, const LorentzMomentum & k) const; //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interface. */ static void Init(); protected: /** * Add parton bins to pbins for the given incoming particle and the * specified cuts. */ virtual void addPartons(tPBPtr incoming ,const PDFCuts & cuts, tcPDFPtr pdf ,PartonVector & pbins) const; /** * The NoPDF object. */ tcPDFPtr noPDF() const { return theNoPDF; } /** * Connect the first (\a anti) coloured particle in the given range * (not equal to \a parton) and connect it to the colour \a line. */ template void findConnect(tColinePtr line, tPPtr parton, bool anti, Iterator first, Iterator last) const { for ( ; first != last; ++first ) { if ( *first != parton && (**first).hasColour(anti) && !(**first).colourLine(anti) ) { line->addColoured(*first, anti); return; } } throw RemColException(*this); } 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; //@} /** @name Standard Interfaced functions. */ //@{ /** * Finalize this object. Called in the run phase just after a * run has ended. Used eg. to write out statistics. */ virtual void dofinish(); //@} private: /** * The PartonBinInstance's used mapped to the respective partons. */ PartonBinInstanceMap& partonBinInstances() const { assert(lastXCombPtr()); return lastXCombPtr()->partonBinInstanceMap(); } /** * A list of special PDFBase objects to be used. */ vector theSpecialDensities; /** * PDFBase object to override first PDF */ PDFPtr theFirstPDF; /** * PDFBase object to override second PDF */ PDFPtr theSecondPDF; /** * The NoPDF object. */ PDFPtr theNoPDF; /** * The maximum number of tries allowed when trying to produce * remnants. */ int theMaxTries; /** * True if this extractor should override the \f$l\f$-generation in * the PDFs and generate a flat distribution in \f$\log(\hat{s})\f$ * and y. */ bool flatSHatY; private: /** * Describe a concrete class with persistent data. */ static ClassDescription initPartonExtractor; /** * Private and non-existent assignment operator. */ PartonExtractor & operator=(const PartonExtractor &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the base classes * of PartonExtractor. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of PartonExtractor. */ typedef HandlerBase NthBase; }; /** This template specialization informs ThePEG about the name of the * PartonExtractor class. */ template <> /** Return a platform-independent class name */ struct ClassTraits: public ClassTraitsBase { static string className() { return "ThePEG::PartonExtractor"; } }; /** @endcond */ } #endif /* ThePEG_PartonExtractor_H */ diff --git a/PDF/PartonExtractor.xh b/PDF/PartonExtractor.xh --- a/PDF/PartonExtractor.xh +++ b/PDF/PartonExtractor.xh @@ -1,32 +1,32 @@ // -*- C++ -*- // // PartonExtractor.xh is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_PartonExtractor_XH #define ThePEG_PartonExtractor_XH // // This is the declarations of the exception classes used by the // PartonExtractor class. // #include "ThePEG/Utilities/Exception.h" namespace ThePEG { /** @cond EXCEPTIONCLASSES */ /** Exception class used by PartonExtractor if the colour connections to the remnants fails. */ struct RemColException: public Exception { /** Standard constructor. */ RemColException(const PartonExtractor &); }; /** @endcond */ } #endif /* ThePEG_PartonExtractor_XH */ diff --git a/PDF/PolarizedBeamParticleData.cc b/PDF/PolarizedBeamParticleData.cc --- a/PDF/PolarizedBeamParticleData.cc +++ b/PDF/PolarizedBeamParticleData.cc @@ -1,79 +1,79 @@ // -*- C++ -*- // // PolarizedBeamParticleData.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the PolarizedBeamParticleData class. // #include "PolarizedBeamParticleData.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/PDT/DecayMode.h" using namespace ThePEG; PolarizedBeamParticleData::PolarizedBeamParticleData(long newId, string newPDGName) : BeamParticleData(newId, newPDGName), theLongPolarization(0.0) {} PDPtr PolarizedBeamParticleData:: Create(long newId, string newPDGName) { return new_ptr(PolarizedBeamParticleData(newId, newPDGName)); } PDPair PolarizedBeamParticleData:: Create(long newId, string newPDGName, string newAntiPDGName) { PDPair pap; pap.first = new_ptr(PolarizedBeamParticleData(newId, newPDGName)); pap.second = new_ptr(PolarizedBeamParticleData(-newId, newAntiPDGName)); antiSetup(pap); return pap; } PDPtr PolarizedBeamParticleData::pdclone() const { return new_ptr(*this); } void PolarizedBeamParticleData::persistentOutput(PersistentOStream & os) const { os << theLongPolarization; } void PolarizedBeamParticleData::persistentInput(PersistentIStream & is, int) { is >> theLongPolarization; } ClassDescription PolarizedBeamParticleData::initPolarizedBeamParticleData; void PolarizedBeamParticleData::Init() { static ClassDocumentation documentation ("There is no documentation for the ThePEG::PolarizedBeamParticleData class"); static Parameter interfaceLongitudinalPolarization ("LongitudinalPolarization", "The longitudinal polarization", &PolarizedBeamParticleData::theLongPolarization, 0.0, -1.0, 1.0, false, false, Interface::limited); interfaceLongitudinalPolarization.rank(15); } RhoDMatrix PolarizedBeamParticleData::rhoMatrix() const { if(iSpin()!=PDT::Spin1Half) { throw Exception() << "Polarized Beams are currently only available for fermions\n" << Exception::runerror; } RhoDMatrix output(PDT::Spin1Half); output(0,0) = 0.5*(1.-theLongPolarization); output(1,1) = 0.5*(1.+theLongPolarization); return output; } diff --git a/PDF/PolarizedBeamParticleData.h b/PDF/PolarizedBeamParticleData.h --- a/PDF/PolarizedBeamParticleData.h +++ b/PDF/PolarizedBeamParticleData.h @@ -1,146 +1,146 @@ // -*- C++ -*- // // PolarizedBeamParticleData.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_PolarizedPolarizedBeamParticleData_H #define ThePEG_PolarizedPolarizedBeamParticleData_H // This is the declaration of the PolarizedBeamParticleData class. #include "BeamParticleData.h" #include "ThePEG/EventRecord/RhoDMatrix.h" #include "PolarizedBeamParticleData.fh" namespace ThePEG { /** * PolarizedBeamParticleData inherits from the BeamParticleData class and is used * for polarized beam particles * * @see \ref PolarizedBeamParticleDataInterfaces "The interfaces" * defined for PolarizedBeamParticleData. * @see BeamParticleData * @see PDFBase */ class PolarizedBeamParticleData: public virtual BeamParticleData { public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ PolarizedBeamParticleData() : theLongPolarization(0.0) {} //@} /** @name The Create methods are special interfaces for ParticleData classes. */ //@{ /** * Create a Particle which is its own anti-particle. */ static PDPtr Create(long newId, string newPDGName); /** * Create a particle - anti particle pair. Note that setting the * parton density object on this particle does not change the parton * density of the anti particle iven if synchronized() is true. */ static PDPair Create(long newId, string newPDGName, string newAntiPDGName); //@} /** * Set-up the spin density matrix */ RhoDMatrix rhoMatrix() const; /** * The longitudinal polarization */ double longitudinalPolarization() const {return theLongPolarization;} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interface. */ static void Init(); protected: /** * Protected constructor only to be used by subclasses or by the * Create method. */ PolarizedBeamParticleData(long newId, string newPDGName); /** * ParticleData clone method */ virtual PDPtr pdclone() const; private: /** * The longitudinal polarization */ double theLongPolarization; private: /** * Describe a concrete class with persistent data. */ static ClassDescription initPolarizedBeamParticleData; /** * Private and non-existent assignment operator. */ PolarizedBeamParticleData & operator=(const PolarizedBeamParticleData &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of PolarizedBeamParticleData. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of PolarizedBeamParticleData. */ typedef BeamParticleData NthBase; }; /** This template specialization informs ThePEG about the name of the * PolarizedBeamParticleData class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "ThePEG::PolarizedBeamParticleData"; } }; /** @endcond */ } #endif /* ThePEG_PolarizedBeamParticleData_H */ diff --git a/PDF/RemnantHandler.cc b/PDF/RemnantHandler.cc --- a/PDF/RemnantHandler.cc +++ b/PDF/RemnantHandler.cc @@ -1,82 +1,82 @@ // -*- C++ -*- // // RemnantHandler.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the RemnantHandler class. // #include "RemnantHandler.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Interface/ClassDocumentation.h" using namespace ThePEG; RemnantHandler::RemnantHandler(bool multi) : isMultiCapable(multi) {} int RemnantHandler::nDim(const PartonBin &, bool) const { return 0; } void RemnantHandler:: boostRemnants(PartonBinInstance &) const {} void RemnantHandler::persistentOutput(PersistentOStream & os) const { os << isMultiCapable; } void RemnantHandler::persistentInput(PersistentIStream & is, int) { is >> isMultiCapable; } bool RemnantHandler:: recreateRemnants(PartonBinInstance & pb, tPPtr oldp, tPPtr newp, double, Energy2 scale, const LorentzMomentum & p, const PVector & prev) const { if ( !oldp || !prev.empty() ) return false; vector rv; for ( int i = 0, N = pb.bin()->remDim(); i < N; ++i) rv.push_back(rnd()); newp->set5Momentum(generate(pb, pb.bin()->remDim()? &rv[0]: 0, scale, p)); boostRemnants(pb); return true; } bool RemnantHandler:: recreateRemnants(PartonBinInstance & pb, tPPtr oldp, tPPtr newp, double, Energy2 scale, Energy2 shat, const LorentzMomentum & p, const PVector & prev) const { if ( !oldp || !prev.empty() ) return false; vector rv; int rd = pb.bin()->remDim(); for ( int i = 0; i < rd; ++i) rv.push_back(rnd()); newp->set5Momentum(generate(pb, rd > 0? &rv[0]: 0, scale, shat, p)); boostRemnants(pb); return true; } AbstractClassDescription RemnantHandler::initRemnantHandler; void RemnantHandler::Init() { static ClassDocumentation documentation ("This is the base class to be used by models describing remnants."); } RemnantHandlerException:: RemnantHandlerException(string p0, string p, string r, string mess) { theMessage << "Creating remnants for particle '" << p0 << "' when extracting " << "parton '" << p << "' using remnant handler '" << r << "' failed. " << mess; severity(warning); } diff --git a/PDF/RemnantHandler.h b/PDF/RemnantHandler.h --- a/PDF/RemnantHandler.h +++ b/PDF/RemnantHandler.h @@ -1,213 +1,213 @@ // -*- C++ -*- // // RemnantHandler.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_RemnantHandler_H #define ThePEG_RemnantHandler_H // This is the declaration of the RemnantHandler class. #include "ThePEG/Handlers/HandlerBase.h" #include "ThePEG/PDF/PartonBin.h" #include "ThePEG/PDF/PartonBinInstance.h" #include "ThePEG/Vectors/Transverse.h" #include "RemnantHandler.xh" namespace ThePEG { /** * RemnantHandler is an abstract base class for implementing classes * used to generate remnants when partons are extracted from * particles. * * @see \ref RemnantHandlerInterfaces "The interfaces" * defined for RemnantHandler. * @see PartonExtractor * @see PDFBase */ class RemnantHandler: public HandlerBase { public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. If \a multi is true the derived class can be * used to extract more than one parton. */ RemnantHandler(bool multi = false); //@} public: /** @name Virtual functions to be overridden by sub-classes. */ //@{ /** * Return true if this remnant handler can handle extracting all * specified \a partons from the given \a particle. */ virtual bool canHandle(tcPDPtr particle, const cPDVector & partons) const = 0; /** * If the generation of remnants is expected to influence the actual * cross section of the hard sub process, the degrees of freedom * generated by this remnant handler may be included in the general * phase space sampling for the subprocess. In this case this * function should be overridden to return the number of degrees of * freedom used in the generation. If \a doScale is false, it means * that the actual virtuality of the extracted parton will be * obtained from another source. */ virtual int nDim(const PartonBin & pb, bool doScale) const; /** * Generate the momentum of the extracted parton with the \a parent * momentum given by the last argument. If the \a scale is negative, * it means that the doScale in the previous call to nDim() was * true, otherwise the given \a scale should be the virtuality of * the extracted parton. Generated quantities which are not returned * in the momentum may be saved in the PartonBinInstance, \a pb, for * later use. In particular, if the nDim() random numbers, \a r, are * not enough to generate with weight one, the resulting weight * should be stored with the remnantWeight() method of the parton * bin. */ virtual Lorentz5Momentum generate(PartonBinInstance & pb, const double * r, Energy2 scale, const LorentzMomentum & parent, bool fixedPartonMomentum = false) const = 0; /** * Generate the momentum of the extracted parton with the \a parent * momentum given by the last argument. If the \a scale is negative, * it means that the doScale in the previous call to nDim() was * true, otherwise the given \a scale should be the virtuality of * the extracted parton. \a shat is the total invariant mass squared * of the hard sub-system produced by the extracted parton and the * primary parton entering from the other side. Generated quantities * which are not returned in the momentum may be saved in the * PartonBinInstance, \a pb, for later use. In particular, if the * nDim() random numbers, \a r, are not enough to generate with * weight one, the resulting weight should be stored with the * remnantWeight() method of the parton bin. */ virtual Lorentz5Momentum generate(PartonBinInstance & pb, const double * r, Energy2 scale, Energy2 shat, const LorentzMomentum & parent, bool fixedPartonMomentum = false) const = 0; /** * Boost the generated remnants to the proper momentum given the * information in the parton bin, \a pb. */ virtual void boostRemnants(PartonBinInstance & pb) const; /** * Redo the remnant generation for the given particle bin, \a pb. If * \a oldp is non-null it corresponds to the previously extracted * parton which should be replaced by \a newp. If \a oldp is null it * means \a newp should be extracted in addition to the previously * extracted ones available in \a prev. * @return false if the generation failed. */ virtual bool recreateRemnants(PartonBinInstance & pb, tPPtr oldp, tPPtr newp, double newl, Energy2 scale, const LorentzMomentum & p, const PVector & prev = PVector()) const; /** * Redo the remnant generation for the given particle bin, \a pb. If * \a oldp is non-null it corresponds to the previously extracted * parton which should be replaced by \a newp. If \a oldp is null it * means \a newp should be extracted in addition to the previously * extracted ones available in \a prev. In either case \a shat is * the total invariant mass squared of the hard sub-system produced * by the extracted parton and the primary parton entering from the other * side. * * @return false if the generation failed. */ virtual bool recreateRemnants(PartonBinInstance & pb, tPPtr oldp, tPPtr newp, double newl, Energy2 scale, Energy2 shat, const LorentzMomentum & p, const PVector & prev = PVector()) const; //@} /** * Return true if this remnant handler is able to handle multiple * extractions of partons from the same particle. */ bool multiCapable() const { return isMultiCapable; } public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interface. */ static void Init(); protected: /** * True if this handler can generate remnants also if several * partons have been extracted. */ bool isMultiCapable; private: /** * The static object used to initialize the description of this class. * Indicates that this is an abstract class with persistent data. */ static AbstractClassDescription initRemnantHandler; /** * Private and non-existent assignment operator. */ RemnantHandler & operator=(const RemnantHandler &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the base classes * of RemnantHandler. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of RemnantHandler. */ typedef HandlerBase NthBase; }; /** This template specialization informs ThePEG about the name of the * RemnantHandler class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "ThePEG::RemnantHandler"; } }; /** @endcond */ } #endif /* ThePEG_RemnantHandler_H */ diff --git a/PDF/RemnantHandler.xh b/PDF/RemnantHandler.xh --- a/PDF/RemnantHandler.xh +++ b/PDF/RemnantHandler.xh @@ -1,33 +1,33 @@ // -*- C++ -*- // // RemnantHandler.xh is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_RemnantHandler_XH #define ThePEG_RemnantHandler_XH // // This is the declarations of the exception classes used by the // RemnantHandler class. // // #include "RemnantHandler.fh" #include "ThePEG/Utilities/Exception.h" namespace ThePEG { /** @cond EXCEPTIONCLASSES */ /** Exception class used by RemnantHandler if something goes wrong. */ struct RemnantHandlerException: public Exception { /** Standard constructor. */ RemnantHandlerException(string p0, string p, string r, string mess); }; /** @endcond */ } #endif /* ThePEG_RemnantHandler_XH */ diff --git a/PDF/SoftRemnantHandler.cc b/PDF/SoftRemnantHandler.cc --- a/PDF/SoftRemnantHandler.cc +++ b/PDF/SoftRemnantHandler.cc @@ -1,134 +1,134 @@ // -*- C++ -*- // // SoftRemnantHandler.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the SoftRemnantHandler class. // #include "SoftRemnantHandler.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Utilities/Direction.h" #include "ThePEG/Utilities/Maths.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/PDT/RemnantDecayer.h" #include "ThePEG/PDT/RemnantData.h" #include "ThePEG/EventRecord/RemnantParticle.h" using namespace ThePEG; IBPtr SoftRemnantHandler::clone() const { return new_ptr(*this); } IBPtr SoftRemnantHandler::fullclone() const { return new_ptr(*this); } bool SoftRemnantHandler:: canHandle(tcPDPtr particle, const cPDVector & partons) const { if ( !remdec ) return false; for ( int i = 0, N = partons.size(); i < N; ++i ) if ( !remdec->canHandle(particle, partons[i]) ) return false; return true; } Lorentz5Momentum SoftRemnantHandler:: generate(PartonBinInstance & pb, const double *, Energy2, const LorentzMomentum & parent, bool fixedPartonMomentum) const { if ( !fixedPartonMomentum ) { LorentzMomentum p = lightCone((parent.rho() + parent.e())*pb.xi(), Energy()); p.rotateY(parent.theta()); p.rotateZ(parent.phi()); pb.parton()->setMomentum(p); } RemPPtr rem = new_ptr(RemnantParticle(*pb.particle(), remdec, pb.parton())); if ( rem->extracted().empty() ) pb.remnantWeight(0.0); pb.remnants(PVector(1, rem)); return pb.parton()->momentum(); } bool SoftRemnantHandler:: recreateRemnants(PartonBinInstance & pb, tPPtr oldp, tPPtr newp, double, Energy2, const LorentzMomentum &, const PVector &) const { // First find the old remnant. RemPPtr rem; for ( int i = 0, N = pb.particle()->children().size(); i < N; ++i ) if ( dynamic_ptr_cast(pb.particle()->children()[i]) ) rem = dynamic_ptr_cast(pb.particle()->children()[i]); if ( !rem ) return false; // LorentzMomentum p(0.0, 0.0, parent.rho(), parent.e()); // pb.parton()->setMomentum // (lightCone(p.plus()*pb.x(), ZERO, ZERO, ZERO)); // pb.parton()->rotateY(parent.theta()); // pb.parton()->rotateZ(parent.phi()); rem = new_ptr(*rem); if ( !rem->reextract(oldp, newp) ) return false; pb.remnants(PVector(1, rem)); return true; } Lorentz5Momentum SoftRemnantHandler:: generate(PartonBinInstance & pb, const double *, Energy2, Energy2, const LorentzMomentum & parent, bool fixedPartonMomentum) const { return generate(pb, 0, ZERO, parent, fixedPartonMomentum); } bool SoftRemnantHandler:: recreateRemnants(PartonBinInstance & pb, tPPtr oldp, tPPtr newp, double l, Energy2 scale, Energy2, const LorentzMomentum & p, const PVector & prev) const { return recreateRemnants(pb, oldp, newp, l, scale, p, prev); } void SoftRemnantHandler::persistentOutput(PersistentOStream & os) const { os << remdec; } void SoftRemnantHandler::persistentInput(PersistentIStream & is, int) { is >> remdec; } void SoftRemnantHandler::setDecayer(RemDecPtr rd) { remdec = rd; isMultiCapable = rd->multiCapable(); } ClassDescription SoftRemnantHandler::initSoftRemnantHandler; void SoftRemnantHandler::Init() { static ClassDocumentation documentation ("SoftRemnantHandler inherits from the RemnantHandler and implements " "the generation of a single collinear RemnantParticle when anything " "is extracted from anything else. Such a RemnantParticle needs to be " "decayed by a special RemnantDecayer and the SoftRemnantHandler " "needs to be assign such a decayer to work properly."); static Reference interfaceRemnantDecayer ("RemnantDecayer", "A RemnantDecayer object which is able to decay the produced " "RemnantParticle objects.", &SoftRemnantHandler::remdec, false, false, true, false, true, &SoftRemnantHandler::setDecayer); } diff --git a/PDF/SoftRemnantHandler.h b/PDF/SoftRemnantHandler.h --- a/PDF/SoftRemnantHandler.h +++ b/PDF/SoftRemnantHandler.h @@ -1,201 +1,201 @@ // -*- C++ -*- // // SoftRemnantHandler.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_SoftRemnantHandler_H #define ThePEG_SoftRemnantHandler_H // This is the declaration of the SoftRemnantHandler class. #include "ThePEG/PDF/RemnantHandler.h" #include "ThePEG/PDT/RemnantDecayer.fh" namespace ThePEG { /** * SoftRemnantHandler inherits from the RemnantHandler and implements * the generation of a single collinear RemnantParticle when anything * is extracted from anything else. Such a RemnantParticle needs to be * decayed by a special RemnantDecayer and the SoftRemnantHandler * needs to be assign such a decayer to work properly. * * @see \ref SoftRemnantHandlerInterfaces "The interfaces" * defined for SoftRemnantHandler. */ class SoftRemnantHandler: public RemnantHandler { public: /** @name Virtual functions mandated by the RemnantHandler base class. */ //@{ /** * Return true if this remnant handler can handle extracting all * specified \a partons form the given \a particle. */ virtual bool canHandle(tcPDPtr particle, const cPDVector & partons) const; /** * Generate momenta. Generates the momenta of the extracted parton * in the particle cms (but with the parton \f$x\f$ still the * positive light-cone fraction) as given by the last argument, \a * p. If the particle is space-like the positive and negative * light-cone momenta are \f$\sqrt{-m^2}\f$ and \f$-sqrt{-m^2}\f$ * respectively. If the \a scale is negative, it means that the \a * doScale in the previous call to nDim() was true, otherwise the * given scale should be the virtuality of the extracted * parton. Generated quantities which are not returned in the * momentum may be saved in the PartonBin, \a pb, for later use. In * particular, if the nDim() random numbers, \a r, are not enough to * generate with weight one, the resulting weight should be stored * with the remnantWeight() method of the parton bin. */ virtual Lorentz5Momentum generate(PartonBinInstance & pb, const double * r, Energy2 scale, const LorentzMomentum & p, bool fixedPartonMomentum = false) const; /** * Generate the momentum of the extracted parton with the \a parent * momentum given by the last argument. If the \a scale is negative, * it means that the doScale in the previous call to nDim() was * true, otherwise the given \a scale should be the virtuality of * the extracted parton. \a shat is the total invariant mass squared * of the hard sub-system produced by the extracted parton and the * primary parton entering from the other side. Generated quantities * which are not returned in the momentum may be saved in the * PartonBinInstance, \a pb, for later use. In particular, if the * nDim() random numbers, \a r, are not enough to generate with * weight one, the resulting weight should be stored with the * remnantWeight() method of the parton bin. */ virtual Lorentz5Momentum generate(PartonBinInstance & pb, const double * r, Energy2 scale, Energy2 shat, const LorentzMomentum & parent, bool fixedPartonMomentum = false) const; /** * Redo the remnant generation for the given particle bin, \a pb. If * \a oldp is non-null it corresponds to the previously extracted * parton which should be replaced by \a newp. If \a oldp is null it * means \a newp should be extracted in addition to the previously * extracted ones available in \a prev. * @return false if the generation failed. */ virtual bool recreateRemnants(PartonBinInstance & pb, tPPtr oldp, tPPtr newp, double newl, Energy2 scale, const LorentzMomentum & p, const PVector & prev = PVector()) const; /** * Redo the remnant generation for the given particle bin, \a pb. If * \a oldp is non-null it corresponds to the previously extracted * parton which should be replaced by \a newp. If \a oldp is null it * means \a newp should be extracted in addition to the previously * extracted ones available in \a prev. In either case \a shat is * the total invariant mass squared of the hard sub-system produced * by the extracted parton and the primary parton entering from the other * side. * * @return false if the generation failed. */ virtual bool recreateRemnants(PartonBinInstance & pb, tPPtr oldp, tPPtr newp, double newl, Energy2 scale, Energy2 shat, const LorentzMomentum & p, const PVector & prev = PVector()) const; //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interface. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * A pointer to a RemnantDecayer object which is able to decay the * produced RemnantParticle objects. */ RemDecPtr remdec; /** * Utility function for the interface. */ void setDecayer(RemDecPtr rd); private: /** * Describe a concrete class with persistent data. */ static ClassDescription initSoftRemnantHandler; /** * Private and non-existent assignment operator. */ SoftRemnantHandler & operator=(const SoftRemnantHandler &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of SoftRemnantHandler. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of SoftRemnantHandler. */ typedef RemnantHandler NthBase; }; /** This template specialization informs ThePEG about the name of the * SoftRemnantHandler 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::SoftRemnantHandler"; } }; /** @endcond */ } #endif /* ThePEG_SoftRemnantHandler_H */ diff --git a/PDF/UnResolvedRemnant.cc b/PDF/UnResolvedRemnant.cc --- a/PDF/UnResolvedRemnant.cc +++ b/PDF/UnResolvedRemnant.cc @@ -1,249 +1,249 @@ // -*- C++ -*- // // UnResolvedRemnant.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the UnResolvedRemnant class. // #include "UnResolvedRemnant.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Utilities/Direction.h" #include "ThePEG/Utilities/Maths.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/ClassDocumentation.h" using namespace ThePEG; IBPtr UnResolvedRemnant::clone() const { return new_ptr(*this); } IBPtr UnResolvedRemnant::fullclone() const { return new_ptr(*this); } UnResolvedRemnant::UnResolvedRemnant() : minX(1.0e-10) {} void UnResolvedRemnant::doinit() { thePhoton = getParticleData(ParticleID::gamma); RemnantHandler::doinit(); } bool UnResolvedRemnant:: canHandle(tcPDPtr particle, const cPDVector & partons) const { for ( cPDVector::const_iterator it = partons.begin(); it != partons.end(); ++it ) { if ( (**it).id() != particle->id() && ( (**it).id() != ParticleID::gamma && (**it).id() != ParticleID::pomeron && (**it).id() != ParticleID::reggeon) ) return false; } return true; } int UnResolvedRemnant::nDim(const PartonBin &, bool) const { return 1; } Lorentz5Momentum UnResolvedRemnant:: generate(PartonBinInstance & pb, const double *r, Energy2 scale, const LorentzMomentum & parent, bool fixedPartonMomentum) const { // photon into hard process and lepton remnant if ( pb.particleData() != pb.partonData()) { scale = abs(scale); Energy ppl = pb.xi()*(abs(parent.z())+parent.t()); Energy2 qt2 = pb.eps()*scale-sqr(pb.xi()*parent.m()); if(qt2momentum(); } Lorentz5Momentum prem=parent-pgam; PPtr rem = pb.particleData()->produceParticle(prem, pb.particleData()->mass()); pb.remnants(PVector(1, rem)); return pgam; } else { if ( pb.eps() < minX ) { pb.remnants(PVector()); return parent; } LorentzMomentum p(ZERO, ZERO, parent.rho(), parent.e()); TransverseMomentum qt; Energy2 qt2 = ZERO; if ( scale >= ZERO ) { qt2 = pb.eps()*(pb.xi()*parent.m2() + scale); double phi = r[0]*Constants::twopi; qt = TransverseMomentum(sqrt(qt2)*cos(phi), sqrt(qt2)*sin(phi)); } Energy pl = p.plus()*pb.eps(); LorentzMomentum prem; if ( !fixedPartonMomentum ) { prem = lightCone(pl, qt2/pl, qt); prem.rotateY(parent.theta()); prem.rotateZ(parent.phi()); } else { prem = parent - pb.parton()->momentum(); } PPtr rem = thePhoton->produceParticle(prem, ZERO); pb.remnants(PVector(1, rem)); return parent - rem->momentum(); } } Lorentz5Momentum UnResolvedRemnant:: generate(PartonBinInstance & pb, const double *r, Energy2 scale, Energy2, const LorentzMomentum & parent, bool fixedPartonMomentum) const { // photon into hard process and lepton remnant if ( pb.particleData() != pb.partonData()) { scale = abs(scale); Energy ppl = pb.xi()*(abs(parent.z())+parent.t()); Energy2 qt2 = pb.eps()*scale-sqr(pb.xi()*parent.m()); if(qt2momentum(); } Lorentz5Momentum prem=parent-pgam; PPtr rem = pb.particleData()->produceParticle(prem, pb.particleData()->mass()); pb.remnants(PVector(1, rem)); return pgam; } else { if ( pb.eps() < minX ) { pb.remnants(PVector()); return parent; } LorentzMomentum p(ZERO, ZERO, parent.rho(), parent.e()); TransverseMomentum qt; Energy2 qt2 = ZERO; if ( scale >= ZERO ) { qt2 = pb.eps()*(pb.xi()*parent.m2() + scale); double phi = r[0]*Constants::twopi; qt = TransverseMomentum(sqrt(qt2)*cos(phi), sqrt(qt2)*sin(phi)); } Energy pl = p.plus()*pb.eps(); LorentzMomentum prem; if ( !fixedPartonMomentum ) { prem = lightCone(pl, qt2/pl, qt); prem.rotateY(parent.theta()); prem.rotateZ(parent.phi()); } else { prem = parent - pb.parton()->momentum(); } PPtr rem = thePhoton->produceParticle(prem, ZERO); pb.remnants(PVector(1, rem)); return parent - rem->momentum(); } } void UnResolvedRemnant::persistentOutput(PersistentOStream & os) const { os << minX << thePhoton; } void UnResolvedRemnant::persistentInput(PersistentIStream & is, int) { is >> minX >> thePhoton; } ClassDescription UnResolvedRemnant::initUnResolvedRemnant; void UnResolvedRemnant::Init() { static ClassDocumentation documentation ("UnResolvedRemnant inherits from the RemnantHandler and implements" "the generation of either the incoming particle as the remnant" "with the emission of a photon, pomeron or reggeon, or" "a photon remnant for the particle entering the hard process."); static Parameter interfaceMinX ("MinX", "The minimum energy fraction allowed for a photon remnant. " "If less than this no remnant will be emitted.", &UnResolvedRemnant::minX, 1.0e-10, 0.0, 1.0, true, false, true); interfaceMinX.rank(10); } bool UnResolvedRemnant:: recreateRemnants(PartonBinInstance & pb, tPPtr oldp, tPPtr newp, double, Energy2 scale, const LorentzMomentum & p, const PVector & prev) const { if ( !oldp || !prev.empty() ) return false; // get the same random number used for the azimuth last time Lorentz5Momentum pgam=oldp->momentum(); pgam.rotateZ(-p.phi()); pgam.rotateY(-p.theta()); double test = atan2(pgam.y(),pgam.x())/Constants::twopi; if(test<0.) test+=1.; vector rv; int rd = pb.bin()->remDim(); for ( int i = 0; i < rd; ++i) rv.push_back(test); // compute the momentum newp->set5Momentum(generate(pb, pb.bin()->remDim()? &rv[0]: 0, scale, p)); boostRemnants(pb); return true; } bool UnResolvedRemnant:: recreateRemnants(PartonBinInstance & pb, tPPtr oldp, tPPtr newp, double, Energy2 scale, Energy2 shat, const LorentzMomentum & p, const PVector & prev) const { if ( !oldp || !prev.empty() ) return false; // get the same random number used for the azimuth last time Lorentz5Momentum pgam=oldp->momentum(); pgam.rotateZ(-p.phi()); pgam.rotateY(-p.theta()); double test = atan2(pgam.y(),pgam.x())/Constants::twopi; if(test<0.) test+=1.; vector rv; int rd = pb.bin()->remDim(); for ( int i = 0; i < rd; ++i) rv.push_back(test); // compute the momentum newp->set5Momentum(generate(pb, rd > 0? &rv[0]: 0, scale, shat, p)); boostRemnants(pb); return true; } diff --git a/PDF/UnResolvedRemnant.h b/PDF/UnResolvedRemnant.h --- a/PDF/UnResolvedRemnant.h +++ b/PDF/UnResolvedRemnant.h @@ -1,233 +1,233 @@ // -*- C++ -*- // // UnResolvedRemnant.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_UnResolvedRemnant_H #define ThePEG_UnResolvedRemnant_H #include "ThePEG/PDF/RemnantHandler.h" namespace ThePEG { /** * UnResolvedRemnant inherits from the RemnantHandler and implements * the generation of either the incoming particle as the remnant * with the emission of a photon, pomeron or reggeon, or * a photon remnant for the particle entering the hard process. * * @see \ref UnResolvedRemnantInterfaces "The interfaces" * defined for UnResolvedRemnant. * @see UnResolvedPDF */ class UnResolvedRemnant: public RemnantHandler { public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ UnResolvedRemnant(); //@} public: /** @name Virtual functions mandated by the RemnantHandler base class. */ //@{ /** * Return true if this remnant handler can handle extracting all * specified \a partons form the given \a particle. */ virtual bool canHandle(tcPDPtr particle, const cPDVector & partons) const; /** * If the generation of remnants is expected to influence the actual * cross section of the hard sub process, the degrees of freedom * generated by this remnant handler may be included in the general * phase space sampling for the subprocess. In this case this * function should be overridden to return the number of degrees of * freedom used in the generation. If \a doScale is false, it means * that the actual virtuality of the extracted parton will be * obtained from another source. */ virtual int nDim(const PartonBin & pb, bool doScale) const; /** * Redo the remnant generation for the given particle bin, \a pb. If * \a oldp is non-null it corresponds to the previously extracted * parton which should be replaced by \a newp. If \a oldp is null it * means \a newp should be extracted in addition to the previously * extracted ones available in \a prev. * @return false if the generation failed. */ virtual bool recreateRemnants(PartonBinInstance & pb, tPPtr oldp, tPPtr newp, double newl, Energy2 scale, const LorentzMomentum & p, const PVector & prev = PVector()) const; /** * Redo the remnant generation for the given particle bin, \a pb. If * \a oldp is non-null it corresponds to the previously extracted * parton which should be replaced by \a newp. If \a oldp is null it * means \a newp should be extracted in addition to the previously * extracted ones available in \a prev. In either case \a shat is * the total invariant mass squared of the hard sub-system produced * by the extracted parton and the primary parton entering from the other * side. * * @return false if the generation failed. */ virtual bool recreateRemnants(PartonBinInstance & pb, tPPtr oldp, tPPtr newp, double newl, Energy2 scale, Energy2 shat, const LorentzMomentum & p, const PVector & prev = PVector()) const; /** * Generate momenta. Generates the momenta of the extracted parton * in the particle cms (but with the parton \f$x\f$ still the * positive light-cone fraction) as given by the last argument, \a * p. If the particle is space-like the positive and negative * light-cone momenta are \f$\sqrt{-m^2}\f$ and \f$-sqrt{-m^2}\f$ * respectively. If the \a scale is negative, it means that the \a * doScale in the previous call to nDim() was true, otherwise the * given scale should be the virtuality of the extracted * parton. Generated quantities which are not returned in the * momentum may be saved in the PartonBin, \a pb, for later use. In * particular, if the nDim() random numbers, \a r, are not enough to * generate with weight one, the resulting weight should be stored * with the remnantWeight() method of the parton bin. */ virtual Lorentz5Momentum generate(PartonBinInstance & pb, const double * r, Energy2 scale, const LorentzMomentum & p, bool fixedPartonMomentum = false) const; /** * Generate the momentum of the extracted parton with the \a parent * momentum given by the last argument. If the \a scale is negative, * it means that the doScale in the previous call to nDim() was * true, otherwise the given \a scale should be the virtuality of * the extracted parton. \a shat is the total invariant mass squared * of the hard sub-system produced by the extracted parton and the * primary parton entering from the other side. Generated quantities * which are not returned in the momentum may be saved in the * PartonBinInstance, \a pb, for later use. In particular, if the * nDim() random numbers, \a r, are not enough to generate with * weight one, the resulting weight should be stored with the * remnantWeight() method of the parton bin. */ virtual Lorentz5Momentum generate(PartonBinInstance & pb, const double * r, Energy2 scale, Energy2 shat, const LorentzMomentum & parent, bool fixedPartonMomentum = false) const; //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interface. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); //@} private: /** * The minimum energy fraction allowed for a photon remnant. */ double minX; /** * Easy access to a photon data object. */ tPDPtr thePhoton; private: /** * Describe a concrete class with persistent data. */ static ClassDescription initUnResolvedRemnant; /** * Private and non-existent assignment operator. */ UnResolvedRemnant & operator=(const UnResolvedRemnant &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of UnResolvedRemnant. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of UnResolvedRemnant. */ typedef RemnantHandler NthBase; }; /** This template specialization informs ThePEG about the name of the * UnResolvedRemnant 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::UnResolvedRemnant"; } /** Return the name of the shared library be loaded to get access to * the UnResolvedRemnant class and every other class it uses * (except the base class). */ static string library() { return "UnResolvedRemnant.so"; } }; /** @endcond */ } #endif /* ThePEG_UnResolvedRemnant_H */ diff --git a/PDT/BreitWignerMass.cc b/PDT/BreitWignerMass.cc --- a/PDT/BreitWignerMass.cc +++ b/PDT/BreitWignerMass.cc @@ -1,47 +1,47 @@ // -*- C++ -*- // // BreitWignerMass.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the BreitWignerMass class. // #include "BreitWignerMass.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Repository/UseRandom.h" using namespace ThePEG; IBPtr BreitWignerMass::clone() const { return new_ptr(*this); } IBPtr BreitWignerMass::fullclone() const { return new_ptr(*this); } Energy BreitWignerMass::mass(const ParticleData & pd) const { Energy ret = ZERO; do { ret = UseRandom::rndRelBW(pd.mass(), pd.width(), pd.widthCut()); } while ( ret > pd.massMax() || ret < pd.massMin() ); return ret; } NoPIOClassDescription BreitWignerMass::initBreitWignerMass; void BreitWignerMass::Init() { static ClassDocumentation documentation ("Generates masses of particle instances according to a Breit-Wigner " "distribution."); } diff --git a/PDT/BreitWignerMass.h b/PDT/BreitWignerMass.h --- a/PDT/BreitWignerMass.h +++ b/PDT/BreitWignerMass.h @@ -1,90 +1,90 @@ // -*- C++ -*- // // BreitWignerMass.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_BreitWignerMass_H #define ThePEG_BreitWignerMass_H // This is the declaration of the BreitWignerMass class. #include "ThePEG/PDT/MassGenerator.h" namespace ThePEG { /** * BreitWignerMass is derived from MassGenerator and is able to * generate the mass for a particle given its nominal mass and its * with. * * * @see MassGenerator * @see ParticleData * */ class BreitWignerMass: public MassGenerator { public: /** @name Virtual methods required by the MassGenerator base class. */ //@{ /** * Return true if this mass generator can handle the given particle * type. */ virtual bool accept(const ParticleData &) const { return true; } /** * Generate a mass for an instance of a given particle type. */ virtual Energy mass(const ParticleData &) const; //@} public: /** * Standard Init function used to initialize the interface. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * Describe concrete class without persistent data. */ static NoPIOClassDescription initBreitWignerMass; /** * Private and non-existent assignment operator. */ BreitWignerMass & operator=(const BreitWignerMass &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ ThePEG_DECLARE_DYNAMIC_CLASS_TRAITS(BreitWignerMass,MassGenerator,"BreitWignerMass.so"); /** @endcond */ } #endif /* ThePEG_BreitWignerMass_H */ diff --git a/PDT/ColourPairDecayer.cc b/PDT/ColourPairDecayer.cc --- a/PDT/ColourPairDecayer.cc +++ b/PDT/ColourPairDecayer.cc @@ -1,109 +1,109 @@ // -*- C++ -*- // // ColourPairDecayer.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the ColourPairDecayer class. // #include "ColourPairDecayer.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/PDT/DecayMode.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Handlers/HandlerGroup.h" #include "ThePEG/Handlers/Hint.h" #include "ThePEG/Handlers/EventHandler.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG; IBPtr ColourPairDecayer::clone() const { return new_ptr(*this); } IBPtr ColourPairDecayer::fullclone() const { return new_ptr(*this); } bool ColourPairDecayer::accept(const DecayMode & dm) const { if ( !FlatDecayer::accept(dm) ) return false; for ( int i = 0, N = dm.orderedProducts().size(); i < N; ++i ) { if ( !dm.orderedProducts()[i]->coloured() ) continue; if ( i == N - 1 ) return false; if ( dm.orderedProducts()[i]->hasColour() && !dm.orderedProducts()[i + 1]->hasAntiColour() ) return false; if ( dm.orderedProducts()[i]->hasAntiColour() && !dm.orderedProducts()[i + 1]->hasColour() ) return false; ++i; } return true; } ParticleVector ColourPairDecayer::getChildren(const DecayMode & dm, const Particle & parent) const { ParticleVector children = dm.produceProducts(); for ( int i = 0, N = children.size(); i < N; ++i ) { children[i]->scale(sqr(parent.mass())); if ( !children[i]->coloured() ) continue; if ( children[i]->hasColour() ) children[i]->antiColourNeighbour(children[i + 1]); if ( children[i]->hasAntiColour() ) children[i]->colourNeighbour(children[i + 1]); ++i; } HintPtr h = ptr_new(); h->tag(children.begin(), children.end()); using namespace Group; generator()->currentEventHandler()-> addStep(main, shower()? cascade: hadron, tStepHdlPtr(), h); return children; } void ColourPairDecayer::persistentOutput(PersistentOStream & os) const { os << doShower; } void ColourPairDecayer::persistentInput(PersistentIStream & is, int) { is >> doShower; } ClassDescription ColourPairDecayer::initColourPairDecayer; // Definition of the static class description member. void ColourPairDecayer::Init() { static ClassDocumentation documentation ("This class performs decays according to phase space into two or " "more particles, some of which may be coloured. The coloured " "particles must come in pairs and will be colour connected " "pair-wise."); static Switch interfaceShower ("Shower", "Should the produced partons be showered or only hadronized?", &ColourPairDecayer::doShower, true, true, false); static SwitchOption interfaceShowerYes (interfaceShower, "Yes", "The produced partons should be showered before hadronization.", true); static SwitchOption interfaceShowerNo (interfaceShower, "No", "The produced partons should be hadronized whithout preceeding shower.", false); interfaceShower.rank(10); } diff --git a/PDT/ColourPairDecayer.h b/PDT/ColourPairDecayer.h --- a/PDT/ColourPairDecayer.h +++ b/PDT/ColourPairDecayer.h @@ -1,161 +1,161 @@ // -*- C++ -*- // // ColourPairDecayer.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_ColourPairDecayer_H #define THEPEG_ColourPairDecayer_H // This is the declaration of the ColourPairDecayer class. #include "ThePEG/PDT/FlatDecayer.h" namespace ThePEG { /** * ColourPairDecayer inherits from the FlatDecayer class and performs * decays according to phase space into two or more particles, some of * which may be coloured. The coloured particles must come in pairs * and will be colour connected pair-wise. * * @see \ref ColourPairDecayerInterfaces "The interfaces" * defined for ColourPairDecayer. */ class ColourPairDecayer: public FlatDecayer { public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ ColourPairDecayer() : doShower(true) {} //@} public: /** @name Virtual functions required by the Decayer and FlatDecayer classes. */ //@{ /** * Check if this decayer can perfom the decay specified by the * given decay mode. * @param dm the DecayMode describing the decay. * @return true if this decayer can handle the given mode, otherwise false. */ virtual bool accept(const DecayMode & dm) const; /** * Produce children. Used by the FlatDecayer::decay() to produce * instances of the children given a DecayMode \a dm and the * decaying particle \a parent.. */ virtual ParticleVector getChildren(const DecayMode & dm, const Particle & parent) const; //@} /** * Return true if the produced gluons and quarks should be * showered. The corresponding flag is set though the interface. */ bool shower() const { return doShower; } 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(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * If true the produced gluons and quarks should be showered. */ bool doShower; private: /** * Describe a concrete class with persistent data. */ static ClassDescription initColourPairDecayer; /** * Private and non-existent assignment operator. */ ColourPairDecayer & operator=(const ColourPairDecayer &) = delete; }; } namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the base classes * of ColourPairDecayer. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of ColourPairDecayer. */ typedef FlatDecayer NthBase; }; /** This template specialization informs ThePEG about the name of the * ColourPairDecayer 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::ColourPairDecayer"; } /** Return the name of the shared library be loaded to get access to * the ColourPairDecayer class and every other class it uses * (except the base class). */ static string library() { return "ColourPairDecayer.so"; } }; /** @endcond */ } #endif /* THEPEG_ColourPairDecayer_H */ diff --git a/PDT/CombinedMatcher.h b/PDT/CombinedMatcher.h --- a/PDT/CombinedMatcher.h +++ b/PDT/CombinedMatcher.h @@ -1,96 +1,96 @@ // -*- C++ -*- // // CombinedMatcher.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_CombinedMatcher_H #define ThePEG_CombinedMatcher_H // This is the declaration of the AndMatcher, OrMatcher and NotMatcher. #include "Matcher.h" namespace ThePEG { /** * The AndMatcher class represents the boolean and operation between * its two template argument classes of base type MatcherBase. * * @see MatcherBase */ template struct AndMatcher: public MatcherType { /** * Typedef for the class representing the matcher for the * charge-gonjugate of particles matched by this class. */ typedef AndMatcher CC; /** * Check match. Return true if the particle type \a pd is matched by * this class (ie. by both of the template argument classes). */ static bool Check(const ParticleData & pd) { return T1::Check(pd) && T2::Check(pd); } }; /** * The OrMatcher class represents the boolean or operation * between its two template argument classes of base type MatcherBase. * * @see MatcherBase */ template struct OrMatcher: public MatcherType { /** * Typedef for the class representing the matcher for the * charge-gonjugate of particles matched by this class. */ typedef OrMatcher CC; /** * Check match. Return true if the particle type \a pd is matched by * this class (ie. by either of the template argument classes). */ static bool Check(const ParticleData & pd) { return T1::Check(pd) || T2::Check(pd); } }; /** * The NotMatcher class represents the boolean not operation * for its template argument class of base type MatcherBase. * * @see MatcherBase */ template struct NotMatcher: public MatcherType { /** * Typedef for the class representing the matcher for the * charge-gonjugate of particles matched by this class. */ typedef NotMatcher CC; /** * Check match. Return true if the particle type \a pd is matched by * this class (ie. if it is not matched by the template argument * class). */ static bool Check(const ParticleData & pd) { return !T::Check(pd); } }; } #endif /* ThePEG_CombinedMatcher_H */ diff --git a/PDT/ConstituentParticleData.cc b/PDT/ConstituentParticleData.cc --- a/PDT/ConstituentParticleData.cc +++ b/PDT/ConstituentParticleData.cc @@ -1,91 +1,91 @@ // -*- C++ -*- // // ConstituentParticleData.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the ConstituentParticleData class. // #include "ConstituentParticleData.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/PDT/DecayMode.h" using namespace ThePEG; ConstituentParticleData::ConstituentParticleData(long newId, string newPDGName) : ParticleData(newId, newPDGName), theConstituentMass(ZERO), theDefaultConstituentMass(ZERO) {} PDPtr ConstituentParticleData:: Create(long newId, string newPDGName) { return new_ptr(ConstituentParticleData(newId, newPDGName)); } PDPair ConstituentParticleData:: Create(long newId, string newPDGName, string newAntiPDGName) { PDPair pap; pap.first = new_ptr(ConstituentParticleData(newId, newPDGName)); pap.second = new_ptr(ConstituentParticleData(-newId, newAntiPDGName)); antiSetup(pap); return pap; } void ConstituentParticleData::readSetup(istream & is) { ParticleData::readSetup(is); is >> iunit(theDefaultConstituentMass, GeV); theConstituentMass = theDefaultConstituentMass; } PDPtr ConstituentParticleData::pdclone() const { return new_ptr(*this); } void ConstituentParticleData::persistentOutput(PersistentOStream & os) const { os << ounit(theConstituentMass, GeV) << ounit(theDefaultConstituentMass, GeV); } void ConstituentParticleData::persistentInput(PersistentIStream & is, int) { is >> iunit(theConstituentMass, GeV) >> iunit(theDefaultConstituentMass, GeV); } void ConstituentParticleData::setConstituentMass(Energy m) { theConstituentMass = m; ConstituentParticleData * apd = dynamic_cast(CC().operator->()); if ( synchronized() && apd ) apd->theConstituentMass = m; } Energy ConstituentParticleData::defConstituentMass() const { return theDefaultConstituentMass; } ClassDescription ConstituentParticleData::initConstituentParticleData; void ConstituentParticleData::Init() { static ClassDocumentation documentation ("There is no documentation for the ThePEG::ConstituentParticleData class"); static Parameter interfaceMass ("ConstituentMass", "The constituent mass of the particle in GeV.", &ConstituentParticleData::theConstituentMass, GeV, ZERO, ZERO, Constants::MaxEnergy, false, false, Interface::lowerlim, &ConstituentParticleData::setConstituentMass, 0, 0, 0, &ConstituentParticleData::defConstituentMass); interfaceMass.rank(11.5); } diff --git a/PDT/ConstituentParticleData.h b/PDT/ConstituentParticleData.h --- a/PDT/ConstituentParticleData.h +++ b/PDT/ConstituentParticleData.h @@ -1,163 +1,163 @@ // -*- C++ -*- // // ConstituentParticleData.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_ConstituentParticleData_H #define ThePEG_ConstituentParticleData_H // This is the declaration of the ConstituentParticleData class. #include "ThePEG/PDT/ParticleData.h" namespace ThePEG { /** * ConstituentParticleData inherits from the ParticleData class and is * used for quarks, diquarks and gluons to store information about * their constituent mass. * * @see \ref ConstituentParticleDataInterfaces "The interfaces" * defined for ConstituentParticleData. */ class ConstituentParticleData: public virtual ParticleData { public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ ConstituentParticleData() : theConstituentMass(ZERO), theDefaultConstituentMass(ZERO) {} //@} /** @name The Create methods are special interfaces for ParticleData classes. */ //@{ /** * Create a Particle which is its own anti-particle. */ static PDPtr Create(long newId, string newPDGName); /** * Create a particle - anti particle pair. */ static PDPair Create(long newId, string newPDGName, string newAntiPDGName); //@} public: /** * Return the constituent mass of this parton. */ virtual Energy constituentMass() const { return theConstituentMass; } public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interface. */ static void Init(); protected: /** * Protected constructor only to be used by subclasses or by the * Create method. */ ConstituentParticleData(long newId, string newPDGName); /** * Read setup info from a standard stream. The information that must * be supplied is the same as for ParticleData::readSetup with an * additional constituent mass (in GeV) added in the end. */ virtual void readSetup(istream & is); /** * ParticleData clone method */ virtual PDPtr pdclone() const; private: /** * Utility function for the interface. */ void setConstituentMass(Energy m); /** * Utility function for the interface. */ Energy defConstituentMass() const; private: /** * The constituent mass of this parton. */ Energy theConstituentMass; /** * The default constituent mass of this parton. */ Energy theDefaultConstituentMass; private: /** * Describe a concrete class with persistent data. */ static ClassDescription initConstituentParticleData; /** * Private and non-existent assignment operator. */ ConstituentParticleData & operator=(const ConstituentParticleData &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of ConstituentParticleData. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of ConstituentParticleData. */ typedef ParticleData NthBase; }; /** This template specialization informs ThePEG about the name of the * ConstituentParticleData class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "ThePEG::ConstituentParticleData"; } }; /** @endcond */ } #endif /* ThePEG_ConstituentParticleData_H */ diff --git a/PDT/DalitzDecayer.cc b/PDT/DalitzDecayer.cc --- a/PDT/DalitzDecayer.cc +++ b/PDT/DalitzDecayer.cc @@ -1,133 +1,133 @@ // -*- C++ -*- // // DalitzDecayer.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the DalitzDecayer class. // #include "DalitzDecayer.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/PDT/DecayMode.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/PDT/StandardMatchers.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Utilities/SimplePhaseSpace.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/Rebinder.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG; DalitzDecayer::~DalitzDecayer() {} IBPtr DalitzDecayer::clone() const { return new_ptr(*this); } IBPtr DalitzDecayer::fullclone() const { return new_ptr(*this); } void DalitzDecayer::doinit() { Decayer::doinit(); rho = getParticleData(ParticleID::rho0); } bool DalitzDecayer::accept(const DecayMode & dm) const { if ( dm.products().size() != 3 || !dm.cascadeProducts().empty() || !dm.productMatchers().empty() || dm.wildProductMatcher() ) return false; bool ep = false, em = false, gam = false; for ( ParticleMSet::const_iterator pit = dm.products().begin(); pit != dm.products().end(); ++pit ) { if ( (**pit).id() == ParticleID::eplus ) ep = true; else if ( (**pit).id() == ParticleID::eminus ) em = true; else if ( (**pit).id() == ParticleID::gamma ) gam = true; } return ep && em && gam; } ParticleVector DalitzDecayer::decay(const DecayMode & dm, const Particle & parent) const { ParticleVector children = getChildren(dm, parent); tPPtr ep; tPPtr em; tPPtr gam; for ( int i = 0, N = children.size(); i < N; ++i ) { if ( children[i]->id() == ParticleID::eplus ) ep = children[i]; else if ( children[i]->id() == ParticleID::eminus ) em = children[i]; else if ( children[i]->id() == ParticleID::gamma ) gam = children[i]; } Energy2 mee2 = ZERO; Energy2 me2 = ep->mass()*em->mass(); Energy2 mm2 = sqr(parent.mass()); Energy2 mr2 = sqr(rho->mass()); Energy2 gr2 = sqr(rho->width()); Energy2 mee2min = 4.0*me2; do { mee2 = mee2min*pow(mm2/mee2min, rnd()); } while ( rnd() > (1.0 - 2.0*me2/mee2)*sqrt(max(0.0, 1.0 - mee2min/mee2))* pow(1.0 - mee2/mm2, 3.0)* (1.0 + gr2/mr2)/(sqr(1.0 - mee2/mr2) + gr2/mr2) ); LorentzMomentum pee, p0, pp, pm; do { SimplePhaseSpace::CMS(mee2, ep, em); pee = ep->momentum() + em->momentum(); p0 = gam->momentum(); SimplePhaseSpace::CMS(mm2, p0, pee); LorentzRotation r (0.0, 0.0, pee.rho()/pee.e()); r.rotateY(pee.theta()); r.rotateZ(pee.phi()); ep->transform(r); em->transform(r); gam->setMomentum(p0); pp = ep->momentum(); pm = em->momentum(); } while ( rnd() > ((mee2 - 2.0*me2)*(sqr(p0*pp) + sqr(p0*pm)) + mee2min*((p0*pp)*(p0*pm) + sqr(p0*pp) + sqr(p0*pm)))*4.0/ (mee2*sqr(mm2 - mee2)) ); finalBoost(parent, children); setScales(parent, children); return children; } void DalitzDecayer::persistentOutput(PersistentOStream & os) const { os << rho; } void DalitzDecayer::persistentInput(PersistentIStream & is, int) { is >> rho; } void DalitzDecayer::rebind(const TranslationMap & trans) { rho = trans.translate(rho); Decayer::rebind(trans); } IVector DalitzDecayer::getReferences() { IVector ret = Decayer::getReferences(); ret.push_back(rho); return ret; } ClassDescription DalitzDecayer::initDalitzDecayer; // Definition of the static class description member. void DalitzDecayer::Init() { static ClassDocumentation documentation ("This class performs Dalitz decays into gamma e+ e-."); } diff --git a/PDT/DalitzDecayer.h b/PDT/DalitzDecayer.h --- a/PDT/DalitzDecayer.h +++ b/PDT/DalitzDecayer.h @@ -1,186 +1,186 @@ // -*- C++ -*- // // DalitzDecayer.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_DalitzDecayer_H #define THEPEG_DalitzDecayer_H // This is the declaration of the DalitzDecayer class. #include "ThePEG/PDT/Decayer.h" // #include "DalitzDecayer.fh" // #include "DalitzDecayer.xh" namespace ThePEG { /** * The DalitzDecayer inherits from the Decayer class and performs * Dalitz decays into \f$\gamma e^+ e^-\f$. * * @see \ref DalitzDecayerInterfaces "The interfaces" * defined for DalitzDecayer. */ class DalitzDecayer: public Decayer { public: /** @name Standard constructors and destructors. */ //@{ /** * Destructor. */ virtual ~DalitzDecayer(); //@} public: /** @name Virtual functions required by the Decayer class. */ //@{ /** * Check if this decayer can perfom the decay specified by the * given decay mode. * @param dm the DecayMode describing the decay. * @return true if this decayer can handle the given mode, otherwise false. */ virtual bool accept(const DecayMode & dm) const; /** * Perform a decay for a given DecayMode and a given Particle instance. * @param dm the DecayMode describing the decay. * @param p the Particle instance to be decayed. * @return a ParticleVector containing the decay products. */ virtual ParticleVector decay(const DecayMode & dm, const Particle & p) const; //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interfaces. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} 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(); //@} private: /** * Quick access to the rho particle data. */ PDPtr rho; private: /** * Describe a concrete class with persistent data. */ static ClassDescription initDalitzDecayer; /** * Private and non-existent assignment operator. */ DalitzDecayer & operator=(const DalitzDecayer &) = delete; }; } namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the base classes * of DalitzDecayer. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of DalitzDecayer. */ typedef Decayer NthBase; }; /** This template specialization informs ThePEG about the name of the * DalitzDecayer 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::DalitzDecayer"; } /** Return the name of the shared library be loaded to get access to * the DalitzDecayer class and every other class it uses * (except the base class). */ static string library() { return "DalitzDecayer.so"; } }; /** @endcond */ } #endif /* THEPEG_DalitzDecayer_H */ diff --git a/PDT/DecayMode.cc b/PDT/DecayMode.cc --- a/PDT/DecayMode.cc +++ b/PDT/DecayMode.cc @@ -1,692 +1,692 @@ // -*- C++ -*- // // DecayMode.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the DecayMode class. // #include "DecayMode.h" #include "DecayMode.xh" #include "ThePEG/Repository/Repository.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Utilities/Rebinder.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/EnumIO.h" using namespace ThePEG; DecayMode::DecayMode() : theBrat(0.0), isOn(false) {} DecayMode::DecayMode(tPDPtr newParticle, double newBrat, bool newOn) : theBrat(newBrat), isOn(newOn), theParent(newParticle) {} DecayMode::DecayMode(const DecayMode & dm) : Interfaced(dm), theTag(dm.theTag), theBrat(dm.theBrat), isOn(dm.isOn), theParent(dm.theParent), theProducts(dm.theProducts), theOrderedProducts(dm.theOrderedProducts), theCascadeProducts(dm.theCascadeProducts), theMatchers(dm.theMatchers), theWildMatcher(dm.theWildMatcher), theExcluded(dm.theExcluded), theOverlap(dm.theOverlap), theDecayer(dm.theDecayer), theAntiPartner(dm.theAntiPartner), theLinks(dm.theLinks) {} DecayMode::~DecayMode() {} DMPtr DecayMode::Create(tPDPtr newParent, double newBrat, bool newOn) { DMPtr dm = new_ptr(DecayMode(newParent, newBrat, newOn)); Repository::Register(dm, newParent->fullName() + "/NEWMODE"); if ( !newParent->CC() ) return dm; DMPtr adm = new_ptr(DecayMode(newParent->CC(), newBrat, newOn)); Repository::Register(adm, newParent->CC()->fullName() + "/NEWMODE"); dm->theAntiPartner = adm; adm->theAntiPartner = dm; return dm; } void DecayMode::readSetup(istream & is) { string decnam; is >> theBrat >> ienum(isOn) >> decnam; if ( decnam.empty() ) return; BaseRepository::DirectoryAppend(decnam); setDecayer(BaseRepository::GetObject(decnam)); } IBPtr DecayMode::clone() const { return dmclone(); } DMPtr DecayMode::dmclone() const { return new_ptr(*this); } IBPtr DecayMode::fullclone() const { DMPtr dm = dmclone(); Repository::Register(dm); if ( !CC() ) return dm; DMPtr adm = CC()->dmclone(); Repository::Register(adm); dm->theAntiPartner = adm; adm->theAntiPartner = dm; return dm; } void DecayMode::doupdate() { Interfaced::doupdate(); bool redo = touched(); UpdateChecker::check(decayer(), redo); if ( !redo ) return; if ( theBrat > 0.0 && isOn && !decayer()->accept(*this) ) throw DecModNoAccept(tag(), decayer()->name()); } void DecayMode::rebind(const TranslationMap & trans) { try { theParent = trans.alwaysTranslate(theParent); ParticleMSet newProducts; trans.alwaysTranslate(inserter(newProducts), products().begin(), products().end()); products().swap(newProducts); tPDVector newOrdered; trans.alwaysTranslate(inserter(newOrdered), orderedProducts().begin(), orderedProducts().end()); theOrderedProducts.swap(newOrdered); ModeMSet newCasc; trans.alwaysTranslate(inserter(newCasc), cascadeProducts().begin(), cascadeProducts().end()); cascadeProducts().swap(newCasc); MatcherMSet newMatchers; trans.alwaysTranslate(inserter(newMatchers), productMatchers().begin(), productMatchers().end()); productMatchers().swap(newMatchers); wildProductMatcher() = trans.alwaysTranslate(wildProductMatcher()); ParticleMSet newExclude; trans.alwaysTranslate(inserter(newExclude), excluded().begin(), excluded().end()); excluded().swap(newExclude); theAntiPartner = trans.alwaysTranslate(CC()); for ( int i = 0, N = theLinks.size(); i < N; ++i ) { theLinks[i].first = trans.alwaysTranslate(theLinks[i].first); theLinks[i].second = trans.alwaysTranslate(theLinks[i].second); } } catch (IBPtr ip) { throw DecModRebind(name(), ip->name()); } catch (...) { throw DecModRebind(name(), ""); } } IVector DecayMode::getReferences() { IVector ret; ret.push_back(theParent); ret.insert(ret.end(), products().begin(), products().end()); ret.insert(ret.end(), cascadeProducts().begin(), cascadeProducts().end()); ret.insert(ret.end(), productMatchers().begin(), productMatchers().end()); if ( wildProductMatcher() ) ret.push_back(wildProductMatcher()); ret.insert(ret.end(), excluded().begin(), excluded().end()); if ( CC() ) ret.push_back(CC()); return ret; } bool DecayMode::addOverlap(tcDMPtr d) { bool inc = includes(*d); if ( !inc ) return false; if ( find(theOverlap.begin(), theOverlap.end(), d) != theOverlap.end() ) return true; theOverlap.push_back(d); return true; } void DecayMode::resetOverlap() { theOverlap.clear(); } bool DecayMode:: compareId(const ParticleMSet & s1, const ParticleMSet & si2) const { if ( generator() ) return s1 == si2; ParticleMSet s2 = si2; for ( ParticleMSet::const_iterator p1 = s1.begin(); p1 != s1.end(); ++p1 ) { ParticleMSet::const_iterator p2 = s2.begin(); while ( p2 != s2.end() && (**p2).id() != (**p1).id() ) ++p2; if ( p2 == s2.end() ) return false; s2.erase(p2); } return s2.empty(); } ParticleMSet::const_iterator DecayMode::findId(const ParticleMSet & s, const ParticleData & p) const { for ( ParticleMSet::const_iterator pit = s.begin(); pit != s.end(); ++pit ) if ( (**pit).id() == p.id() ) return pit; return s.end(); } struct IdCmp { bool operator()(tcPDPtr p1, tcPDPtr p2) const { return p1->id() == p2->id(); } }; bool DecayMode::includes(const DecayMode & d) const { // Fast check for ordinary decay modes. if ( cascadeProducts().empty() && productMatchers().empty() && excluded().empty() && !wildProductMatcher() && d.cascadeProducts().empty() && d.productMatchers().empty() && d.excluded().empty() && !d.wildProductMatcher() ) { if ( links().size() != d.links().size() ) return false; if ( !compareId(products(), d.products()) ) return false; LinkVector dlinks = d.links(); for ( int i = 0, N = links().size(); i < N; ++i ) { for ( int j = 0, M = dlinks.size(); j < M; ++j ) { if ( ( links()[i].first->id() == dlinks[j].first->id() && links()[i].second->id() == dlinks[j].second->id() ) || ( links()[i].first->id() == dlinks[j].second->id() && links()[i].second->id() == dlinks[j].first->id() ) ) { dlinks.erase(dlinks.begin() + j); break; } } return false; } return dlinks.empty(); } // First check that none of the excluded products in this are // present in the other. ParticleMSet::const_iterator pit; for ( pit = excluded().begin(); pit != excluded().end(); ++pit ) { if ( findId(d.products(), **pit ) != d.products().end() ) return false; for ( ModeMSet::const_iterator mit = d.cascadeProducts().begin(); mit != d.cascadeProducts().end(); ++mit ) if ( (**pit).id() == (**mit).parent()->id() ) return false; } // Check that all cascade decays in this overlaps with one in the // other. Save the ones that are left ModeMSet cascleft = d.cascadeProducts(); for ( ModeMSet::iterator mit = cascadeProducts().begin(); mit != cascadeProducts().end(); ++mit ) { ModeMSet::iterator mit2 = cascleft.begin(); while ( mit2 != cascleft.end() && !(**mit).includes(**mit2) ) ++mit2; if ( mit2 == cascleft.end() ) return false; } // Check that all cascade product parents in the other matches // something in this. Otherwise expand the cascade product. ParticleMSet partleft = d.products(); MatcherMSet matchleft = d.productMatchers(); ParticleMSet excludeleft = d.excluded(); MatcherMSet wildleft; if ( d.wildProductMatcher() ) wildleft.insert(wildProductMatcher()); ParticleMSet part = products(); MatcherMSet match = productMatchers(); while ( cascleft.size() ) { ModeMSet::iterator cdmit = cascleft.begin(); cDMPtr cdm = *cdmit; ParticleMSet::iterator pit = findId(part, *(cdm->parent())); if ( pit != part.end() ) { cascleft.erase(cdmit); part.erase(pit); } else { MatcherMSet::iterator mit = match.begin(); while ( mit != match.end() && !(**mit).matches(*(cdm->parent())) ) ++mit; if ( mit != match.end() ) { cascleft.erase(cdmit); match.erase(mit); } else { if ( wildProductMatcher() && wildProductMatcher()->matches(*(cdm->parent())) ) { cascleft.erase(cdmit); } else { cascleft.erase(cdmit); partleft.insert(cdm->products().begin(), cdm->products().end()); matchleft.insert(cdm->productMatchers().begin(), cdm->productMatchers().end()); if ( cdm->wildProductMatcher() ) wildleft.insert(cdm->wildProductMatcher()); excludeleft.insert(cdm->excluded().begin(), cdm->excluded().end()); cascleft.insert(cdm->cascadeProducts().begin(), cdm->cascadeProducts().end()); } } } } // Check that all excluded left in the other are absent in this. if ( find_first_of(excludeleft.begin(), excludeleft.end(), part.begin(), part.end(), IdCmp()) != excludeleft.end() ) return false; // Now all particles and matches left in this must match something // in the other. pit = part.begin(); while ( pit != part.end() ) { ParticleMSet::iterator pit2 = findId(partleft, **pit++); if ( pit2 == partleft.end() ) return false; partleft.erase(pit2); } MatcherMSet::const_iterator pmit = match.begin(); while ( pmit != match.end() ) { ParticleMSet::iterator pit2 = partleft.begin(); while ( pit2 != partleft.end() && ! (**pmit).matches(**pit2) ) ++pit2; if ( pit2 != partleft.end() ) { partleft.erase(pit2); } else { MatcherMSet::iterator pmit2 = matchleft.begin(); while ( pmit2 != matchleft.end() && ! (**pmit).matches(**pmit2) ) ++pmit2; if ( pmit2 != matchleft.end() ) { matchleft.erase(pmit2); } else return false; } } // Now all particles and matchers left in the other must be matched // by the wild match in this. if ( wildProductMatcher() ) { pit = partleft.begin(); while ( pit != partleft.end() ) if ( !(wildProductMatcher()->matches(**pit++)) ) return false; pmit = matchleft.begin(); while (pmit != matchleft.end() ) if ( !(wildProductMatcher()->matches(**pmit++)) ) return false; pmit = wildleft.begin(); while (pmit != wildleft.end() ) if ( !(wildProductMatcher()->matches(**pmit++)) ) return false; } else return partleft.empty() && matchleft.empty() && wildleft.empty(); return true; } DMPtr DecayMode::clone(tPDPtr pd) const { DMPtr dm = dmclone(); dm->theParent = pd; Repository::Register(dm, pd->fullName() + "/" + dm->name()); if ( !theDecayer || !theDecayer->accept(*dm) ) dm->isOn = false; if ( pd->CC() ) { DMPtr adm = CC()? CC()->dmclone(): dmclone(); adm->theParent = pd->CC(); Repository::Register(adm, pd->CC()->fullName() + "/" + adm->name()); dm->theAntiPartner = adm; adm->theAntiPartner = dm; if ( !adm->theDecayer->accept(*adm) ) adm->isOn = false; } else dm->theAntiPartner = DMPtr(); return dm; } void DecayMode::synchronize() { if ( !CC() ) return; theBrat = CC()->theBrat; isOn = CC()->isOn; theDecayer = CC()->theDecayer; } struct ParticleOrdering { bool operator()(tcPDPtr p1, tcPDPtr p2) const { return abs(p1->id()) > abs(p2->id()) || ( abs(p1->id()) == abs(p2->id()) && p1->id() > p2->id() ) || ( p1->id() == p2->id() && p1->fullName() > p2->fullName() ); } }; struct ModeOrdering { bool operator()(tcDMPtr d1, tcDMPtr d2) const { ParticleOrdering ord; return ord(d1->parent(), d2->parent()) || ( !ord(d2->parent(), d1->parent()) && ( d1->tag() < d2->tag() || ( d1->tag() == d2->tag() && d1->fullName() < d2->fullName() ) ) ); } }; struct MatcherOrdering { bool operator()(tcPMPtr m1, tcPMPtr m2) const { return m1->name() < m2->name() || ( m1->name() == m2->name() && m1->fullName() < m2->fullName() ); } }; PVector DecayMode::produceProducts() const { PVector ret; for ( int i = 0, N = orderedProducts().size(); i < N; ++i ) ret.push_back(orderedProducts()[i]->produceParticle()); return ret; } string DecayMode::makeTag() const { string ret; typedef multiset OrderedParticles; typedef multiset OrderedMatchers; typedef multiset OrderedModes; LinkVector dlinks = links(); ret = theParent->PDGName() + "->"; if ( dlinks.empty() ) { OrderedParticles prod(products().begin(), products().end()); for (OrderedParticles::iterator pit = prod.begin(); pit != prod.end(); ++pit ) ret += (**pit).PDGName() + ","; } else { unsigned int dl = 0; for ( int i = 0, N = orderedProducts().size(); i < N; ++i ) { if ( dl < dlinks.size() && orderedProducts()[i] == dlinks[dl].first ) { ret += orderedProducts()[i]->PDGName() + "="; ++dl; } else ret += orderedProducts()[i]->PDGName() + ","; } } OrderedModes casc(cascadeProducts().begin(), cascadeProducts().end()); for ( OrderedModes::iterator dmit = casc.begin();dmit != casc.end(); ++dmit ) ret += "[" + (**dmit).tag() + "],"; OrderedMatchers match(productMatchers().begin(), productMatchers().end()); for ( OrderedMatchers::iterator mit = match.begin(); mit != match.end(); ++mit ) ret += "?" +(**mit).name() + ","; if ( theWildMatcher ) ret += "*" + theWildMatcher->name() + ","; OrderedParticles ex(excluded().begin(), excluded().end()); for ( OrderedParticles::iterator pit = ex.begin(); pit != ex.end(); ++pit ) ret += "!" + (**pit).PDGName() + ","; ret[ret.size()-1] = ';'; return ret; } void DecayMode::brat(double newBrat) { theBrat = newBrat; if ( theBrat <= 0.0 ) switchOff(); if ( CC() && parent()->synchronized() ) CC()->theBrat = newBrat; } double DecayMode::brat() const { return isOn? theDecayer->brat(*this, *theParent, theBrat): 0.0; } double DecayMode::brat(const Particle & p) const { return isOn && p.dataPtr() == parent()? theDecayer->brat(*this, p, theBrat): 0.0; } void DecayMode::switchOn() { isOn = true; if ( CC() && parent()->synchronized() ) CC()->isOn = true; } void DecayMode::switchOff() { isOn = false; if ( CC() && parent()->synchronized() ) CC()->isOn = false; } void DecayMode::addProduct(tPDPtr pd) { products().insert(pd); theOrderedProducts.push_back(pd); if ( CC() ) { CC()->products().insert(pd->CC()? pd->CC(): pd); CC()->theOrderedProducts.push_back(pd->CC()? pd->CC(): pd); } resetTag(); } void DecayMode::addLink(tPDPtr a, tPDPtr b) { theLinks.push_back(make_pair(a, b)); if ( CC() ) CC()->theLinks.push_back(make_pair(a->CC()? a->CC(): a, b->CC()? b->CC(): b)); resetTag(); } void DecayMode::addCascadeProduct(tDMPtr dm) { cascadeProducts().insert(dm); if ( CC() ) CC()->cascadeProducts().insert(dm->CC()? dm->CC(): dm); resetTag(); } void DecayMode::addProductMatcher( tPMPtr pm) { productMatchers().insert(pm); if ( CC() ) CC()->productMatchers().insert(pm->CC()? pm->CC(): pm); resetTag(); } void DecayMode::setWildMatcher(tPMPtr pm) { wildProductMatcher() = pm; if ( CC() ) CC()->wildProductMatcher() = pm->CC()? pm->CC(): pm; resetTag(); } void DecayMode::addExcluded(tPDPtr pd) { excluded().insert(pd); if ( CC() ) CC()->excluded().insert(pd->CC()? pd->CC(): pd); resetTag(); } void DecayMode::decayer(tDecayerPtr dec) { if ( !dec || !dec->accept(*this) ) throw DecModSetupNoAccept(tag(), dec->name()); if ( CC() && parent()->synchronized() ) { if ( !dec->accept(*CC()) ) throw DecModSetupNoAccept(CC()->tag(), dec->name()); CC()->theDecayer = dec; } theDecayer = dec; } DMPtr DecayMode::constructDecayMode(string & tag, vector * save) { DMPtr rdm; DMPtr adm; int level = 0; string::size_type end = 0; while ( end < tag.size() && ( tag[end] != ']' || level ) ) { switch ( tag[end++] ) { case '[': ++level; break; case ']': --level; break; } } string::size_type next = tag.find("->"); if ( next == string::npos ) return rdm; if ( tag.find(';') == string::npos ) return rdm; tPDPtr pd = Repository::findParticle(tag.substr(0,next)); if ( !pd ) return rdm; rdm = ptr_new(); rdm->parent(pd); if ( pd->CC() ) { adm = ptr_new(); adm->parent(pd->CC()); rdm->theAntiPartner = adm; adm->theAntiPartner = rdm; } bool error = false; tag = tag.substr(next+2); tPDPtr lastprod; bool dolink = false; do { switch ( tag[0] ) { case '[': { tag = tag.substr(1); DMPtr cdm = constructDecayMode(tag, save); if ( save ) save->push_back(cdm); if ( cdm ) rdm->addCascadeProduct(cdm); else error = true; } break; case '=': dolink = true; [[fallthrough]]; case ',': case ']': tag = tag.substr(1); break; case '?': { next = min(tag.find(','), tag.find(';')); tPMPtr pm = Repository::findMatcher(tag.substr(1,next-1)); if ( pm ) rdm->addProductMatcher(pm); else error = true; tag = tag.substr(next); } break; case '!': { next = min(tag.find(','), tag.find(';')); tPDPtr pd = Repository::findParticle(tag.substr(1,next-1)); if ( pd ) rdm->addExcluded(pd); else error = true; tag = tag.substr(next); } break; case '*': { next = min(tag.find(','), tag.find(';')); tPMPtr pm = Repository::findMatcher(tag.substr(1,next-1)); if ( pm ) rdm->setWildMatcher(pm); else error = true; tag = tag.substr(next); } break; default: { next = min(tag.find('='), min(tag.find(','), tag.find(';'))); tPDPtr pdp = Repository::findParticle(tag.substr(0,next)); if ( pdp ) rdm->addProduct(pdp); else error = true; tag = tag.substr(next); if ( dolink && lastprod ) { rdm->addLink(lastprod, pdp); dolink = false; } lastprod = pdp; } break; } } while ( tag[0] != ';' && tag.size() ); if ( tag[0] != ';' || error ) { return DMPtr(); } tag = tag.substr(1); for ( DecaySet::const_iterator dit = pd->decayModes().begin(); dit != pd->decayModes().end(); ++dit ) if ( (**dit).tag() == rdm->tag() ) return *dit; if ( save ) { save->push_back(rdm); save->push_back(adm); } else { pd->addDecayMode(rdm); Repository::Register(rdm, pd->fullName() + "/" + rdm->tag()); if ( adm ) Repository::Register(adm, pd->CC()->fullName() + "/" + adm->tag()); } return rdm; } void DecayMode::persistentOutput(PersistentOStream & os) const { multiset prod(products().begin(), products().end()); multiset casc(cascadeProducts().begin(), cascadeProducts().end()); multiset match(productMatchers().begin(), productMatchers().end()); multiset ex(excluded().begin(), excluded().end()); multiset ovlap(overlap().begin(), overlap().end()); os << theTag << theBrat << isOn << theParent << prod << theOrderedProducts << casc << match << theWildMatcher << ex << ovlap << theDecayer << theAntiPartner << theLinks; } void DecayMode::persistentInput(PersistentIStream & is, int) { is >> theTag >> theBrat >> isOn >> theParent >> theProducts >> theOrderedProducts >> theCascadeProducts >> theMatchers >> theWildMatcher >> theExcluded >> theOverlap >> theDecayer >> theAntiPartner >> theLinks; } ClassDescription DecayMode::initDecayMode; void DecayMode::setOn(long i) { isOn = i; } long DecayMode::getOn() const { return isOn; } void DecayMode::setDecayer(DecayerPtr dp) { decayer(dp); } void DecayMode::Init() { static ClassDocumentation documentation ("Represents a specific decay channel of a particle."); static Parameter interfaceBrat ("BranchingRatio", "The branching fraction for this decay mode. Note that if the sum of " "branching ratios for one particle is always renormalized to 1. Also, " "the decaying particle may change this branching ratio if it has a " "ThePEG::WidthGenerator object assigned to it. ", &DecayMode::theBrat, 0.0, 0.0, 1.0, false, false, true); interfaceBrat.setHasDefault(false); static Switch interfaceOn ("OnOff", "Indicates if the decay mode is switched on or off.", 0, 0, false, false, &DecayMode::setOn, &DecayMode::getOn); static SwitchOption interfaceOnYes (interfaceOn, "On", "The decay channel is switched on.", 1); static SwitchOption interfaceOnNo (interfaceOn, "Off", "The decay channel is switched off.", 0); interfaceOn.setHasDefault(false); static Switch interfaceActive ("Active", "Indicates if the decay mode is switched on or off.", 0, 0, false, false, &DecayMode::setOn, &DecayMode::getOn); static SwitchOption interfaceActiveYes (interfaceActive, "Yes", "The decay channel is switched on.", 1); static SwitchOption interfaceActiveNo (interfaceActive, "No", "The decay channel is switched off.", 0); interfaceActive.setHasDefault(false); static Reference interfaceDecayer ("Decayer", "The ThePEG::Decayer object responsible for performing this decay.", &DecayMode::theDecayer, false, false, true, false, &DecayMode::setDecayer); interfaceBrat.rank(10); interfaceDecayer.rank(9); interfaceOn.rank(8); interfaceActive.rank(8); } DecModNoAccept::DecModNoAccept(string tag, string dec) { theMessage << "The Decayer '" << dec << "' is not capable to " << "perform the decay in the DecayMode '" << tag << "'."; severity(warning); } DecModSetupNoAccept::DecModSetupNoAccept(string tag, string dec) { theMessage << "The Decayer '" << dec << "' is not capable to " << "perform the decay in the DecayMode '" << tag << "'."; severity(warning); } DecModRebind::DecModRebind(string tag, string obj) { theMessage << "'Rebind' of DecayMode '" << tag << "' failed because " << "the object '" << obj << "' refered to lacked a translation."; severity(abortnow); } diff --git a/PDT/DecayMode.h b/PDT/DecayMode.h --- a/PDT/DecayMode.h +++ b/PDT/DecayMode.h @@ -1,607 +1,607 @@ // -*- C++ -*- // // DecayMode.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_DecayMode_H #define ThePEG_DecayMode_H // This is the declaration of the DecayMode class. #include "ThePEG/Config/ThePEG.h" #include "ThePEG/Interface/Interfaced.h" #include "DecayMode.fh" #include "MatcherBase.h" #include "Decayer.h" namespace ThePEG { ThePEG_DECLARE_MULTISET(tPDPtr,ParticleMSet); ThePEG_DECLARE_MULTISET(tPMPtr,MatcherMSet); ThePEG_DECLARE_MULTISET(tDMPtr,ModeMSet); /** * The DecayMode class describes a decay channel of a particle. In its * simplest form it contains simply a parent ParticleData object and a * list of decay products, but it can also specify a set of * MatcherBase objects each representing one of a set of possible * decay products. A matcher can also be specified to represents an * unlimited set of decay products. Decay chains can be represented by * specifying other decay channels where the parents are taken to be * intermediate resonances. It is also possible to specify the absence * of intermediate resonances. * * Each decay mode can be uniquely described by a character string on * the form * {decaying-particle-name}->{decay-product-specifier}[,{decay-product-specifier},...]; * where no spaces are allowed anywhere. The decaying-particle-name * should be a path to a particle in the Repository or a * PDG-standardized particle name (see ParticleData::PDGName()) and * the decay-product-specifier can be one of the following: * *
    * *
  • a path to a particle in the Repository or a PDG-standardized * particle name if it is a specific decay product, * *
  • a question mark followed by the name of a particle matcher * object in the Repository if representing one of several different * alternative decay products, * *
  • a star followed by the name of a particle matcher object in * the Repository if representing any number of several different * alternative decay products (note that only one of these * wild-card matchers may be specified, if several are given * only the last one will be taken into account), * *
  • a whole decay mode string enclosed in square brackets if * representing a resonance decay product with a specified decay mode, * *
  • an exclamation mark followed by a path to a particle in the * Repository or a PDG-standardized particle name representing the * exclusion of an intermediate resonance decaying into the other * specified decay products. * *
  • two paths to particles in the Repository or PDG-standardized * particle names with an equal sign between, indicating two coloured * particles which are in a colour-singlet state. * *
* * Note that the order of the specified decay products will be * preserved when the corresponding particles are produced in a decay. * * The possibility of specifying matchers as decay products means that * one decay mode may overlap with another one. When an EventGenerator * is initialized all decay modes are checked so that a given decay * mode afterwards will report if there are other modes which are * matched by its matchers through the overlap() function. * * @see \ref DecayModeInterfaces "The interfaces" * defined for DecayMode. * @see ParticleData * @see MatcherBase */ class DecayMode: public Interfaced { public: /** ParticleData is a friend. */ friend class ParticleData; /** RemnantData is a friend. */ friend class RemnantData; /** The EventGenerator is a friend. */ friend class EventGenerator; public: /** A vector of DecayMode pointers. */ typedef vector ModeVector; /** A vector of pairs of ParticleData pointers. */ typedef vector LinkVector; public: /** * Create a decay mode from a given tag. This function is used * directly by the Repository. If name of the decaying particle is a * valid path to a particle object, the decaymode will be added to * that particle, otherwise it will be added to the default particle * of that name. */ static DMPtr constructDecayMode(string & tag, vector * save = 0); /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ DecayMode(); /** * Copy-constructor. */ DecayMode(const DecayMode &); /** * Destructor. */ ~DecayMode(); //@} /** * Return a clone of this decay mode with \a pd as the decaying * particle. */ virtual DMPtr clone(tPDPtr pd) const; public: /** * Return the tag for this decay mode. This string is a unique * identifier for this decay mode. */ const string & tag() const { return theTag.size() ? theTag : ( theTag = makeTag() ); } /** * Get a pointer to the particle data object corresponding to * the decaying particle. */ tcPDPtr parent() const { return theParent; } /** * The set of identified decay products. */ const ParticleMSet & products() const { return theProducts; } /** * The set of identified decay products in the order they were specified. */ const tPDVector & orderedProducts() const { return theOrderedProducts; } /** * Produce particles corresponding to the identified decay * products. They will be orderd in the same order they were * sspecified. */ PVector produceProducts() const; /** * The set of identified resonance products with specified decay * modes */ const ModeMSet & cascadeProducts() const { return theCascadeProducts; } /** * The set of matchers each corresponding to one decay product. */ const MatcherMSet & productMatchers() const { return theMatchers; } /** * The pointer to a matcher corresponding to any number of decay * products */ tPMPtr wildProductMatcher() const { return theWildMatcher; } /** * The set particles corresponding to excluded intermediate * resonances. */ const ParticleMSet & excluded() const { return theExcluded; } /** * Return the branching ratio to be used. */ double brat() const; /** * Calculate the branching ratio for a particular particle instance. */ double brat(const Particle &) const; /** * Get the decayer assigned to this mode. */ tDecayerPtr decayer() const { return theDecayer; } /** * Check if another decay mode is included in this one. */ bool includes(const DecayMode &) const; /** * Return a pointer to the corresponding decaymode for the * antiparticle decay. */ tDMPtr CC() const { return theAntiPartner; } /** * Check if another decay mode has the same final state as this * one. */ bool operator == (const DecayMode & d) const { return tag() == d.tag() ; } /** * Return a vector of pairs of decay products which are linked * together (e.g. colourless q-qbar pairs). */ const LinkVector & links() const { return theLinks; } /** * Return the list of overlapping decay modes. */ const ModeVector & overlap() const { return theOverlap; } /** * Modify this mode to have properties corresponding to its anti-partner. */ void synchronize(); /** * Check whether this decay mode is switched on */ bool on() const { return isOn; } public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interface. */ static void Init(); protected: /** @name Standard Interfaced functions. */ //@{ /** * Check sanity of the object during the setup phase. */ virtual void doupdate(); /** * 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: /** * Set a pointer to the particle data object corresponding to * the decaying particle. */ void parent(tPDPtr pd) { theParent = pd; } /** * Set the branching ratio to be used. */ void brat(double); /** * Switch on this decay mode. */ void switchOn(); /** * Switch off this decay mode. */ void switchOff(); /** * Set the decayer. The set method returns false if the decayer * does not claim to be able to handle the decay. */ void decayer(tDecayerPtr); /** * Add identified decay products. */ void addProduct(tPDPtr); /** * Add a pair of decay products which are linked together * (e.g. colourless q-qbar pairs). */ void addLink(tPDPtr a, tPDPtr b); /** * Add identified resonant product with specified decay mode. */ void addCascadeProduct(tDMPtr); /** * Add a mathcer corresponding to one decay product. */ void addProductMatcher(tPMPtr); /** * Add a matcher corresponding to any number of decay products. */ void setWildMatcher(tPMPtr); /** * Add a particle corresponding to an excluded intermediate * resonance. */ void addExcluded(tPDPtr); /** * Protected creation and clone methods. */ static DMPtr Create(tPDPtr newParent, double newBrat = 0.0, bool newOn = false); /** * Protected constructor. */ DecayMode(tPDPtr newParticle, double newBrat, bool newOn); /** @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 special clone function. */ DMPtr dmclone() const; /** * Read setup info from a standard stream used by the * Repository. The following information must be supplied in a * white-space separated list: the branching ratio, on or off (true * or false), and the name of a Decayer. */ virtual void readSetup(istream & is); /** * The set of identified decay products. */ ParticleMSet & products() { return theProducts; } /** * The set of identified resonant products with specified decay * modes */ ModeMSet & cascadeProducts() { return theCascadeProducts; } /** * The set of matchers each corresponding to one decay product. */ MatcherMSet & productMatchers() { return theMatchers; } /** * The pointer to a matcher corresponding to any number of decay * products */ tPMPtr & wildProductMatcher() { return theWildMatcher; } /** * The set particles corresponding to excluded intermediate * resonances. */ ParticleMSet & excluded() { return theExcluded; } /** * Set the pointer to the corresponding decaymode for the * antiparticle decay. */ void CC(tDMPtr cc) {theAntiPartner = cc;} private: /** * Add a decay mode to the list of overlapping modes if included. */ bool addOverlap(tcDMPtr); /** * Remove all decay modes from the list of overlapping modes. */ void resetOverlap(); /** * Check if two sets of particles have equivalent types. */ bool compareId(const ParticleMSet &, const ParticleMSet &) const; /** * Check if a particle set contains a given particle ID. */ ParticleMSet::const_iterator findId(const ParticleMSet &, const ParticleData &) const; /** * Use the members in this decay channel and generate the * corresponding tag. */ string makeTag() const; /** * Delete the tag (it will be regenerated later if asked for). */ void resetTag() { theTag = ""; if ( CC() ) CC()->theTag = ""; } private: /** * Utility function for the interface. */ void setOn(long); /** * Utility function for the interface. */ long getOn() const; /** * Utility function for the interface. */ void setDecayer(DecayerPtr); private: /** * The tag. */ mutable string theTag; /** * The branching ratio. */ double theBrat; /** * True if this mode is switched on. */ bool isOn; /** * Pointer to a particle data object corresponding to the decaying * particle. */ tPDPtr theParent; /** * The set of specified decay particles. */ ParticleMSet theProducts; /** * The set of specified decay particles in the order they was specified. */ tPDVector theOrderedProducts; /** * The set of matching decay channels corresponding to a specified * with a specified subsequent decay mode. */ ModeMSet theCascadeProducts; /** * The set of matching decay products. Each of the matchers * correspond to one particle. */ MatcherMSet theMatchers; /** * A particle matcher which corresponds to zero or more particles. */ tPMPtr theWildMatcher; /** * A set of particles which are not allowed as intermediate * resonances. */ ParticleMSet theExcluded; /** * A list of decay modes which are included in this one. */ ModeVector theOverlap; /** * The decayer object responsible for performing the decay. */ DecayerPtr theDecayer; /** * The corresponding decay mode of the anti particle. */ tDMPtr theAntiPartner; /** * The vector of pairs of decay products which are linked together * (e.g. colourless q-qbar pairs). */ LinkVector theLinks; private: /** * Describe a concrete class with persistent data. */ static ClassDescription initDecayMode; /** * Private and non-existent assignment operator. */ DecayMode & operator=(const DecayMode &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of DecayMode. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of DecayMode. */ typedef Interfaced NthBase; }; /** This template specialization informs ThePEG about the name of the * DecayMode class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "ThePEG::DecayMode"; } }; /** @endcond */ } #endif /* ThePEG_DecayMode_H */ diff --git a/PDT/DecayMode.xh b/PDT/DecayMode.xh --- a/PDT/DecayMode.xh +++ b/PDT/DecayMode.xh @@ -1,48 +1,48 @@ // -*- C++ -*- // // DecayMode.xh is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_DecayMode_XH #define ThePEG_DecayMode_XH // // This is the declarations of the exception classes used by the // DecayMode class. // #include "ThePEG/Interface/InterfaceBase.xh" namespace ThePEG { /** @cond EXCEPTIONCLASSES */ /** Exception class used if a DecayMode is found to be inconsistent during the setup phase. */ class DecModNoAccept: public UpdateException { public: /** Standard constructor. */ DecModNoAccept(string, string); }; /** Exception class used if a DecayMode is found to be inconsistent during the setup phase. */ class DecModSetupNoAccept: public SetupException { public: /** Standard constructor. */ DecModSetupNoAccept(string, string); }; /** Exception class used by DecayMode if rebinding fails. */ class DecModRebind: public RebindException { public: /** Standard constructor. */ DecModRebind(string, string); }; /** @endcond */ } #endif /* ThePEG_DecayMode_XH */ diff --git a/PDT/Decayer.cc b/PDT/Decayer.cc --- a/PDT/Decayer.cc +++ b/PDT/Decayer.cc @@ -1,127 +1,127 @@ // -*- C++ -*- // // Decayer.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the Decayer class. // #include "Decayer.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/PDT/DecayMode.h" #include "ThePEG/Utilities/UtilityBase.h" #include "ThePEG/Utilities/Throw.h" #include "ThePEG/EventRecord/Step.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/PDT/DecayMode.h" using namespace ThePEG; double Decayer::brat(const DecayMode &, const ParticleData &, double b) const { return b; } ParticleVector Decayer::getChildren(const DecayMode & dm, const Particle &) const { return dm.produceProducts(); } void Decayer::finalBoost(const Particle & parent, const ParticleVector & children) const { Utilities::setMomentum(children.begin(), children.end(), parent.momentum().vect(), 1.0e-12); } void Decayer::setScales(const Particle & parent, const ParticleVector & children) const { for ( ParticleVector::size_type i = 0; i < children.size(); ++i ) children[i]->scale(parent.momentum().mass2()); } double Decayer::brat(const DecayMode &, const Particle &, double b) const { return b; } bool Decayer::needsFullStep() const { return false; } ParticleVector Decayer:: decay(const DecayMode & dm, const Particle & p, Step &) const { return decay(dm, p); } AbstractNoPIOClassDescription Decayer::initDecayer; void Decayer::Init() { static ClassDocumentation documentation ("There is no documentation for the ThePEG::Decayer class"); static Reference interfaceAmplitude ("Amplitude", "The eventual amplitude associated to this decay matrix element.", &Decayer::theAmplitude, false, false, true, true); } void Decayer::persistentOutput(PersistentOStream & os) const { os << theAmplitude; } void Decayer::persistentInput(PersistentIStream & is, int) { is >> theAmplitude; } ParticleVector Decayer::DecayParticle(tPPtr parent, Step & s, long maxtry) { ParticleVector children; if ( !parent ) return children; parent = parent->final(); if ( parent->decayed() ) return children; long itry = 0; while ( true ) { if ( itry++ >= maxtry ) Throw() << "Could not decay particle " << parent->data().PDGName() << " after " << maxtry << " attempts. Giving up." << Exception::eventerror; tDMPtr dm = parent->data().selectMode(*parent); if ( !dm ) Throw() << "Could not decay particle " << parent->data().PDGName() << " since " << " no decay mode was found." << Exception::runerror; if ( !dm->decayer() ) Throw() << "Could not perform the decay " << dm->tag() << " since the decay mode was not associated with a decayer." << Exception::runerror; try { if ( dm->decayer()->needsFullStep() ) children = dm->decayer()->decay(*dm, *parent, s); else children = dm->decayer()->decay(*dm, *parent); if ( !children.empty() ) { parent->decayMode(dm); for ( int i = 0, N = children.size(); i < N; ++i ) if ( !s.addDecayProduct(parent, children[i]) )Throw() << "An error occurred when tryin to decay an unstable particle " << "of type " << parent->data().PDGName() << ". One of the " << "produced children (of type " << children[i]->data().PDGName() << ") could not be added to the current step." << Exception::abortnow; parent->scale(ZERO); return children; } } catch (DecayFailure & e) { throw e; } catch (Veto) {} } } diff --git a/PDT/Decayer.h b/PDT/Decayer.h --- a/PDT/Decayer.h +++ b/PDT/Decayer.h @@ -1,211 +1,211 @@ // -*- C++ -*- // // Decayer.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_Decayer_H #define ThePEG_Decayer_H // This is the declaration of the Decayer class. #include "ThePEG/Config/ThePEG.h" #include "Decayer.fh" #include "ThePEG/Handlers/HandlerBase.h" #include "ThePEG/MatrixElement/Amplitude.h" namespace ThePEG { /** * Decayer is an abstract base class to specify objects modelling the * decay of a particle. * * @see \ref DecayerInterfaces "The interfaces" * defined for Decayer. * @see ParticleData * @see DecayMode */ class Decayer: public HandlerBase { public: /** @name Virtual functions to be overridden in sub-classes. */ //@{ /** * Check if this decayer can perfom the decay specified by the * given decay mode. * @param dm the DecayMode describing the decay. * @return true if this decayer can handle the given mode, otherwise false. */ virtual bool accept(const DecayMode & dm) const = 0; /** * Return true if this Decayer need to access the full current step * when a particle is decayed. If true is returned the standard * Decay Handler will call the decay(const DecayMode&,const * Particle&,Step&) function rather than the decay(const * DecayMode&,const Particle&) function. */ virtual bool needsFullStep() const; /** * Perform a decay for a given DecayMode and a given Particle instance. * @param dm the DecayMode describing the decay. * @param p the Particle instance to be decayed. * @return a ParticleVector containing the decay products. */ virtual ParticleVector decay(const DecayMode & dm, const Particle & p) const = 0; /** * Perform a decay for a given DecayMode and a given Particle * instance. This version allows the decaying particle to borrow * energy/momentum from its sublings in the current step. This will * be called by the standard DecayHandler if the needsFullStep() * function returns true. * * @param dm the DecayMode describing the decay. * @param p the Particle instance to be decayed. * @param step the current step in which to find possible siblings to * shuffle energy with. * @return a ParticleVector containing the decay products. */ virtual ParticleVector decay(const DecayMode & dm, const Particle & p, Step & step) const; /** * Calculate branching ratio. If this model has any oppinions on the * decay rate for a given decay mode \a dm, for a given particle * type \a pd, this method may be overriden to return this * oppinion. \a oldbrat is the branching ratio specified in the * DecayMode or by asking the WidthGenerator of \a pd. */ virtual double brat(const DecayMode & dm, const ParticleData & pd, double oldbrat) const; /** * Calculate branching ratio. If this model has any oppinions on the * decay rate for a given decay mode \a dm, for a given particle \a * p, this method may be overriden to return this oppinion. \a * oldbrat is the branching ratio specified in the DecayMode or by * asking the WidthGenerator of \a p. */ virtual double brat(const DecayMode & dm, const Particle & p, double oldbrat) const; /** * Produce the children. Can be used by sub-class decay() functions * to produce instances of the children. This default implementation * just calls the produceProducts() of the specified decay products * in DecayMode object, \a dm. */ virtual ParticleVector getChildren(const DecayMode & dm, const Particle & parent) const; /** * Boost the decay products. Can be used by sub-classes to perform * the final boost back from the parents cms. This default version * does just that. */ virtual void finalBoost(const Particle & parent, const ParticleVector & children) const; /** * Set the scales. Can be used by sub classes to set the production * scale of the children. This default version sets the scale to the * parents mass. */ virtual void setScales(const Particle & parent, const ParticleVector & children) const; //@} /** * Return an amplitude associated with this decay matrix * element. May return null. */ Ptr::pointer amplitude() const { return theAmplitude; } /** * Static function to administer the decay of a \a particle. The * children are properly added to the particle and to the given \a * step. Maximum \a maxtry attempts to decay the particle is * performed. * @return the produced children. */ static ParticleVector DecayParticle(tPPtr parent, Step & step, long maxtry = 1000); /** * Exception class used if something goes wrong in DecayParticle(). */ struct DecayFailure: public Exception {}; 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(); private: /** * The static object used to initialize the description of this class. * Indicates that this is an abstract class without persistent data. */ static AbstractNoPIOClassDescription initDecayer; /** * Private and non-existent assignment operator. */ Decayer & operator=(const Decayer &) = delete; /** * A possible null pointer to an amplitude associated with this * matrix element. */ Ptr::pointer theAmplitude; }; /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the base classes * of Decayer. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of Decayer. */ typedef HandlerBase NthBase; }; /** This template specialization informs ThePEG about the name of the * Decayer class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "ThePEG::Decayer"; } }; /** @endcond */ } #endif /* ThePEG_Decayer_H */ diff --git a/PDT/DummyDecayer.cc b/PDT/DummyDecayer.cc --- a/PDT/DummyDecayer.cc +++ b/PDT/DummyDecayer.cc @@ -1,57 +1,57 @@ // -*- C++ -*- // // DummyDecayer.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the DummyDecayer class. // #include "DummyDecayer.h" #include "ThePEG/Interface/ClassDocumentation.h" using namespace ThePEG; IBPtr DummyDecayer::clone() const { return new_ptr(*this); } IBPtr DummyDecayer::fullclone() const { return new_ptr(*this); } bool DummyDecayer::accept(const DecayMode &) const { return true; } ParticleVector DummyDecayer::decay(const DecayMode &, const Particle &) const { throw std::logic_error("Tried to decay with the DummyDecayer class."); } double DummyDecayer:: brat(const DecayMode &, const ParticleData &, double) const { return 0.0; } double DummyDecayer::brat(const DecayMode &, const Particle &, double) const { return 0.0; } NoPIOClassDescription DummyDecayer::initDummyDecayer; // Definition of the static class description member. void DummyDecayer::Init() { static ClassDocumentation documentation ("This is a dummy decayer class to be used for symbolic decay " "channels. If it for some reason is called to perform a decay, it " "will throw a std::logic_error."); } diff --git a/PDT/DummyDecayer.h b/PDT/DummyDecayer.h --- a/PDT/DummyDecayer.h +++ b/PDT/DummyDecayer.h @@ -1,132 +1,132 @@ // -*- C++ -*- // // DummyDecayer.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_DummyDecayer_H #define THEPEG_DummyDecayer_H // This is the declaration of the DummyDecayer class. #include "ThePEG/PDT/Decayer.h" namespace ThePEG { /** * DummyDecayer inherits from Decayer and is a dummy decayer class to * be used for symbolic decay channels. If it for some reason is * called to perform a decay, it will throw a std::logic_error. * * @see \ref DummyDecayerInterfaces "The interfaces" * defined for DummyDecayer. */ class DummyDecayer: public Decayer { public: /** @name Virtual functions required by the Decayer class. */ //@{ /** * Check if this decayer can perfom the decay specified by the * given decay mode. * @param dm the DecayMode describing the decay. * @return true always. */ virtual bool accept(const DecayMode & dm) const; /** * Perform a decay for a given DecayMode and a given Particle * instance. Will throw std::logic_error if called. * @param dm the DecayMode describing the decay. * @param p the Particle instance to be decayed. * @return a ParticleVector containing the decay products. */ virtual ParticleVector decay(const DecayMode & dm, const Particle & p) const; /** * Will always return zero, since no decay can ever be performed * with this decayer. */ virtual double brat(const DecayMode &, const ParticleData &, double) const; /** * Will always return zero, since no decay can ever be performed * with this decayer. */ virtual double brat(const DecayMode &, const Particle &, double) const; //@} public: /** * Standard Init function used to initialize the interfaces. */ static void Init(); protected: protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * Describe a concrete class without persistent data. */ static NoPIOClassDescription initDummyDecayer; /** * Private and non-existent assignment operator. */ DummyDecayer & operator=(const DummyDecayer &) = delete; }; } namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the base classes * of DummyDecayer. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of DummyDecayer. */ typedef Decayer NthBase; }; /** This template specialization informs ThePEG about the name of the * DummyDecayer class. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "ThePEG::DummyDecayer"; } }; /** @endcond */ } #endif /* THEPEG_DummyDecayer_H */ diff --git a/PDT/EnumParticles.h b/PDT/EnumParticles.h --- a/PDT/EnumParticles.h +++ b/PDT/EnumParticles.h @@ -1,1558 +1,1558 @@ // -*- C++ -*- // // EnumParticles.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_EnumParticles_H #define ThePEG_EnumParticles_H namespace ThePEG { /** * The ParticleID namespace defines the ParticleCodes enumeration. */ namespace ParticleID { /** * Enumeration to give identifiers to PDG id numbers. */ enum ParticleCodes { d = 1, /**< \f$\mbox{d}\f$ (d) */ dbar = -1, /**< \f$\overline{\mbox{d}}\f$ (dbar) */ u = 2, /**< \f$\mbox{u}\f$ (u) */ ubar = -2, /**< \f$\overline{\mbox{u}}\f$ (ubar) */ s = 3, /**< \f$\mbox{s}\f$ (s) */ sbar = -3, /**< \f$\overline{\mbox{s}}\f$ (sbar) */ c = 4, /**< \f$\mbox{c}\f$ (c) */ cbar = -4, /**< \f$\overline{\mbox{c}}\f$ (cbar) */ b = 5, /**< \f$\mbox{b}\f$ (b) */ bbar = -5, /**< \f$\overline{\mbox{b}}\f$ (bbar) */ t = 6, /**< \f$\mbox{t}\f$ (t) */ tbar = -6, /**< \f$\overline{\mbox{t}}\f$ (tbar) */ bprime = 7, /**< \f$\mbox{b}^{\prime }\f$ (b') */ bprimebar = -7, /**< \f$\overline{\mbox{b}}^{\prime }\f$ (b'bar) */ tprime = 8, /**< \f$\mbox{t}^{\prime }\f$ (t') */ tprimebar = -8, /**< \f$\overline{\mbox{t}}^{\prime }\f$ (t'bar) */ eminus = 11, /**< \f$\mbox{e}^{-}\f$ (e-) */ eplus = -11, /**< \f$\mbox{e}^{+}\f$ (e+) */ nu_e = 12, /**< \f$\nu _{e}\f$ (nu_e) */ nu_ebar = -12, /**< \f$\overline{\nu }_{e}\f$ (nu_ebar) */ muminus = 13, /**< \f$\mu ^{-}\f$ (mu-) */ muplus = -13, /**< \f$\mu ^{+}\f$ (mu+) */ nu_mu = 14, /**< \f$\nu _{\mu }\f$ (nu_mu) */ nu_mubar = -14, /**< \f$\overline{\nu }_{\mu }\f$ (nu_mubar) */ tauminus = 15, /**< \f$\tau ^{-}\f$ (tau-) */ tauplus = -15, /**< \f$\tau ^{+}\f$ (tau+) */ nu_tau = 16, /**< \f$\nu _{\tau }\f$ (nu_tau) */ nu_taubar = -16, /**< \f$\overline{\nu }_{\tau }\f$ (nu_taubar) */ tauprimeminus = 17, /**< \f$\tau ^{\prime -}\f$ (tau'-) */ tauprimeplus = -17, /**< \f$\tau ^{\prime +}\f$ (tau'+) */ nuprime_tau = 18, /**< \f$\nu ^{\prime }_{\tau }\f$ (nu'_tau) */ nuprime_taubar = -18, /**< \f$\overline{\nu }^{\prime }_{\tau }\f$ (nu'_taubar) */ g = 21, /**< \f$\mbox{g}\f$ (g) */ gamma = 22, /**< \f$\gamma \f$ (gamma) */ Z0 = 23, /**< \f$\mbox{Z}^{0 }\f$ (Z0) */ Wplus = 24, /**< \f$\mbox{W}^{+}\f$ (W+) */ Wminus = -24, /**< \f$\mbox{W}^{-}\f$ (W-) */ h0 = 25, /**< \f$\mbox{h}^{0 }\f$ (h0) */ Zprime0 = 32, /**< \f$\mbox{Z}^{\prime 0 }\f$ (Z'0) */ Zbis0 = 33, /**< \f$\mbox{Z}^{\prime\prime 0 }\f$ (Z"0) */ Wprimeplus = 34, /**< \f$\mbox{W}^{\prime +}\f$ (W'+) */ Wprimeminus = -34, /**< \f$\mbox{W}^{\prime -}\f$ (W'-) */ H0 = 35, /**< \f$\mbox{H}^{0 }\f$ (H0) */ A0 = 36, /**< \f$\mbox{A}^{0 }\f$ (A0) */ Hplus = 37, /**< \f$\mbox{H}^{+}\f$ (H+) */ Hminus = -37, /**< \f$\mbox{H}^{-}\f$ (H-) */ Graviton = 39, /**< \f${\cal G}\f$ (Graviton) */ R0 = 41, /**< \f$\mbox{R}^{0 }\f$ (R0) */ Rbar0 = -41, /**< \f$\overline{\mbox{R}}^{0 }\f$ (Rbar0) */ LQ_ue = 42, /**< \f$\mbox{L}_{Que}\f$ (LQ_ue) */ LQ_uebar = -42, /**< \f$\overline{\mbox{L}}_{Que}\f$ (LQ_uebar) */ reggeon = 110, /**< \f$I\!\!R\f$ (reggeon) */ pi0 = 111, /**< \f$\pi ^{0 }\f$ (pi0) */ rho0 = 113, /**< \f$\rho ^{0 }\f$ (rho0) */ a_20 = 115, /**< \f$\mbox{a}^{0 }_{2}\f$ (a_20) */ K_L0 = 130, /**< \f$\mbox{K}^{0 }_{L}\f$ (K_L0) */ piplus = 211, /**< \f$\pi ^{+}\f$ (pi+) */ piminus = -211, /**< \f$\pi ^{-}\f$ (pi-) */ rhoplus = 213, /**< \f$\rho ^{+}\f$ (rho+) */ rhominus = -213, /**< \f$\rho ^{-}\f$ (rho-) */ a_2plus = 215, /**< \f$\mbox{a}^{+}_{2}\f$ (a_2+) */ a_2minus = -215, /**< \f$\mbox{a}^{-}_{2}\f$ (a_2-) */ eta = 221, /**< \f$\eta \f$ (eta) */ omega = 223, /**< \f$\omega \f$ (omega) */ f_2 = 225, /**< \f$\mbox{f}_{2}\f$ (f_2) */ K_S0 = 310, /**< \f$\mbox{K}^{0 }_{S}\f$ (K_S0) */ K0 = 311, /**< \f$\mbox{K}^{0 }\f$ (K0) */ Kbar0 = -311, /**< \f$\overline{\mbox{K}}^{0 }\f$ (Kbar0) */ Kstar0 = 313, /**< \f$\mbox{K}^{*0 }\f$ (K*0) */ Kstarbar0 = -313, /**< \f$\overline{\mbox{K}}^{*0 }\f$ (K*bar0) */ Kstar_20 = 315, /**< \f$\mbox{K}^{*0 }_{2}\f$ (K*_20) */ Kstar_2bar0 = -315, /**< \f$\overline{\mbox{K}}^{*0 }_{2}\f$ (K*_2bar0) */ Kplus = 321, /**< \f$\mbox{K}^{+}\f$ (K+) */ Kminus = -321, /**< \f$\mbox{K}^{-}\f$ (K-) */ Kstarplus = 323, /**< \f$\mbox{K}^{*+}\f$ (K*+) */ Kstarminus = -323, /**< \f$\mbox{K}^{*-}\f$ (K*-) */ Kstar_2plus = 325, /**< \f$\mbox{K}^{*+}_{2}\f$ (K*_2+) */ Kstar_2minus = -325, /**< \f$\mbox{K}^{*-}_{2}\f$ (K*_2-) */ etaprime = 331, /**< \f$\eta ^{\prime }\f$ (eta') */ phi = 333, /**< \f$\phi \f$ (phi) */ fprime_2 = 335, /**< \f$\mbox{f}^{\prime }_{2}\f$ (f'_2) */ Dplus = 411, /**< \f$\mbox{D}^{+}\f$ (D+) */ Dminus = -411, /**< \f$\mbox{D}^{-}\f$ (D-) */ Dstarplus = 413, /**< \f$\mbox{D}^{*+}\f$ (D*+) */ Dstarminus = -413, /**< \f$\mbox{D}^{*-}\f$ (D*-) */ Dstar_2plus = 415, /**< \f$\mbox{D}^{*+}_{2}\f$ (D*_2+) */ Dstar_2minus = -415, /**< \f$\mbox{D}^{*-}_{2}\f$ (D*_2-) */ D0 = 421, /**< \f$\mbox{D}^{0 }\f$ (D0) */ Dbar0 = -421, /**< \f$\overline{\mbox{D}}^{0 }\f$ (Dbar0) */ Dstar0 = 423, /**< \f$\mbox{D}^{*0 }\f$ (D*0) */ Dstarbar0 = -423, /**< \f$\overline{\mbox{D}}^{*0 }\f$ (D*bar0) */ Dstar_20 = 425, /**< \f$\mbox{D}^{*0 }_{2}\f$ (D*_20) */ Dstar_2bar0 = -425, /**< \f$\overline{\mbox{D}}^{*0 }_{2}\f$ (D*_2bar0) */ D_splus = 431, /**< \f$\mbox{D}^{+}_{s}\f$ (D_s+) */ D_sminus = -431, /**< \f$\mbox{D}^{-}_{s}\f$ (D_s-) */ Dstar_splus = 433, /**< \f$\mbox{D}^{*+}_{s}\f$ (D*_s+) */ Dstar_sminus = -433, /**< \f$\mbox{D}^{*-}_{s}\f$ (D*_s-) */ Dstar_2splus = 435, /**< \f$\mbox{D}^{*+}_{2s}\f$ (D*_2s+) */ Dstar_2sminus = -435, /**< \f$\mbox{D}^{*-}_{2s}\f$ (D*_2s-) */ eta_c = 441, /**< \f$\eta _{c}\f$ (eta_c) */ Jpsi = 443, /**< \f$J/\psi \f$ (J/psi) */ chi_2c = 445, /**< \f$\chi _{2c}\f$ (chi_2c) */ B0 = 511, /**< \f$\mbox{B}^{0 }\f$ (B0) */ Bbar0 = -511, /**< \f$\overline{\mbox{B}}^{0 }\f$ (Bbar0) */ Bstar0 = 513, /**< \f$\mbox{B}^{*0 }\f$ (B*0) */ Bstarbar0 = -513, /**< \f$\overline{\mbox{B}}^{*0 }\f$ (B*bar0) */ Bstar_20 = 515, /**< \f$\mbox{B}^{*0 }_{2}\f$ (B*_20) */ Bstar_2bar0 = -515, /**< \f$\overline{\mbox{B}}^{*0 }_{2}\f$ (B*_2bar0) */ Bplus = 521, /**< \f$\mbox{B}^{+}\f$ (B+) */ Bminus = -521, /**< \f$\mbox{B}^{-}\f$ (B-) */ Bstarplus = 523, /**< \f$\mbox{B}^{*+}\f$ (B*+) */ Bstarminus = -523, /**< \f$\mbox{B}^{*-}\f$ (B*-) */ Bstar_2plus = 525, /**< \f$\mbox{B}^{*+}_{2}\f$ (B*_2+) */ Bstar_2minus = -525, /**< \f$\mbox{B}^{*-}_{2}\f$ (B*_2-) */ B_s0 = 531, /**< \f$\mbox{B}^{0 }_{s}\f$ (B_s0) */ B_sbar0 = -531, /**< \f$\overline{\mbox{B}}^{0 }_{s}\f$ (B_sbar0) */ Bstar_s0 = 533, /**< \f$\mbox{B}^{*0 }_{s}\f$ (B*_s0) */ Bstar_sbar0 = -533, /**< \f$\overline{\mbox{B}}^{*0 }_{s}\f$ (B*_sbar0) */ Bstar_2s0 = 535, /**< \f$\mbox{B}^{*0 }_{2s}\f$ (B*_2s0) */ Bstar_2sbar0 = -535, /**< \f$\overline{\mbox{B}}^{*0 }_{2s}\f$ (B*_2sbar0) */ B_cplus = 541, /**< \f$\mbox{B}^{+}_{c}\f$ (B_c+) */ B_cminus = -541, /**< \f$\mbox{B}^{-}_{c}\f$ (B_c-) */ Bstar_cplus = 543, /**< \f$\mbox{B}^{*+}_{c}\f$ (B*_c+) */ Bstar_cminus = -543, /**< \f$\mbox{B}^{*-}_{c}\f$ (B*_c-) */ Bstar_2cplus = 545, /**< \f$\mbox{B}^{*+}_{2c}\f$ (B*_2c+) */ Bstar_2cminus = -545, /**< \f$\mbox{B}^{*-}_{2c}\f$ (B*_2c-) */ eta_b = 551, /**< \f$\eta _{b}\f$ (eta_b) */ Upsilon = 553, /**< \f$\Upsilon \f$ (Upsilon) */ chi_2b = 555, /**< \f$\chi _{2b}\f$ (chi_2b) */ pomeron = 990, /**< \f$I\!\!P\f$ (pomeron) */ dd_1 = 1103, /**< \f$\mbox{dd}_{1}\f$ (dd_1) */ dd_1bar = -1103, /**< \f$\overline{\mbox{dd}}_{1}\f$ (dd_1bar) */ Deltaminus = 1114, /**< \f$\Delta ^{-}\f$ (Delta-) */ Deltabarplus = -1114, /**< \f$\overline{\Delta }^{+}\f$ (Deltabar+) */ ud_0 = 2101, /**< \f$\mbox{ud}^{0 }\f$ (ud_0) */ ud_0bar = -2101, /**< \f$\overline{\mbox{ud}}^{0 }\f$ (ud_0bar) */ ud_1 = 2103, /**< \f$\mbox{ud}_{1}\f$ (ud_1) */ ud_1bar = -2103, /**< \f$\overline{\mbox{ud}}_{1}\f$ (ud_1bar) */ n0 = 2112, /**< \f$\mbox{n}^{0 }\f$ (n0) */ nbar0 = -2112, /**< \f$\overline{\mbox{n}}^{0 }\f$ (nbar0) */ Delta0 = 2114, /**< \f$\Delta ^{0 }\f$ (Delta0) */ Deltabar0 = -2114, /**< \f$\overline{\Delta }^{0 }\f$ (Deltabar0) */ uu_1 = 2203, /**< \f$\mbox{uu}_{1}\f$ (uu_1) */ uu_1bar = -2203, /**< \f$\overline{\mbox{uu}}_{1}\f$ (uu_1bar) */ pplus = 2212, /**< \f$\mbox{p}^{+}\f$ (p+) */ pbarminus = -2212, /**< \f$\overline{\mbox{p}}^{-}\f$ (pbar-) */ Deltaplus = 2214, /**< \f$\Delta ^{+}\f$ (Delta+) */ Deltabarminus = -2214, /**< \f$\overline{\Delta }^{-}\f$ (Deltabar-) */ Deltaplus2 = 2224, /**< \f$\Delta ^{++}\f$ (Delta++) */ Deltabarminus2 = -2224, /**< \f$\overline{\Delta }^{--}\f$ (Deltabar--) */ sd_0 = 3101, /**< \f$\mbox{sd}^{0 }\f$ (sd_0) */ sd_0bar = -3101, /**< \f$\overline{\mbox{sd}}^{0 }\f$ (sd_0bar) */ sd_1 = 3103, /**< \f$\mbox{sd}_{1}\f$ (sd_1) */ sd_1bar = -3103, /**< \f$\overline{\mbox{sd}}_{1}\f$ (sd_1bar) */ Sigmaminus = 3112, /**< \f$\Sigma ^{-}\f$ (Sigma-) */ Sigmabarplus = -3112, /**< \f$\overline{\Sigma }^{+}\f$ (Sigmabar+) */ Sigmastarminus = 3114, /**< \f$\Sigma ^{*-}\f$ (Sigma*-) */ Sigmastarbarplus = -3114, /**< \f$\overline{\Sigma }^{*+}\f$ (Sigma*bar+) */ Lambda0 = 3122, /**< \f$\Lambda ^{0 }\f$ (Lambda0) */ Lambdabar0 = -3122, /**< \f$\overline{\Lambda }^{0 }\f$ (Lambdabar0) */ su_0 = 3201, /**< \f$\mbox{su}^{0 }\f$ (su_0) */ su_0bar = -3201, /**< \f$\overline{\mbox{su}}^{0 }\f$ (su_0bar) */ su_1 = 3203, /**< \f$\mbox{su}_{1}\f$ (su_1) */ su_1bar = -3203, /**< \f$\overline{\mbox{su}}_{1}\f$ (su_1bar) */ Sigma0 = 3212, /**< \f$\Sigma ^{0 }\f$ (Sigma0) */ Sigmabar0 = -3212, /**< \f$\overline{\Sigma }^{0 }\f$ (Sigmabar0) */ Sigmastar0 = 3214, /**< \f$\Sigma ^{*0 }\f$ (Sigma*0) */ Sigmastarbar0 = -3214, /**< \f$\overline{\Sigma }^{*0 }\f$ (Sigma*bar0) */ Sigmaplus = 3222, /**< \f$\Sigma ^{+}\f$ (Sigma+) */ Sigmabarminus = -3222, /**< \f$\overline{\Sigma }^{-}\f$ (Sigmabar-) */ Sigmastarplus = 3224, /**< \f$\Sigma ^{*+}\f$ (Sigma*+) */ Sigmastarbarminus = -3224, /**< \f$\overline{\Sigma }^{*-}\f$ (Sigma*bar-) */ ss_1 = 3303, /**< \f$\mbox{ss}_{1}\f$ (ss_1) */ ss_1bar = -3303, /**< \f$\overline{\mbox{ss}}_{1}\f$ (ss_1bar) */ Ximinus = 3312, /**< \f$\Xi ^{-}\f$ (Xi-) */ Xibarplus = -3312, /**< \f$\overline{\Xi }^{+}\f$ (Xibar+) */ Xistarminus = 3314, /**< \f$\Xi ^{*-}\f$ (Xi*-) */ Xistarbarplus = -3314, /**< \f$\overline{\Xi }^{*+}\f$ (Xi*bar+) */ Xi0 = 3322, /**< \f$\Xi ^{0 }\f$ (Xi0) */ Xibar0 = -3322, /**< \f$\overline{\Xi }^{0 }\f$ (Xibar0) */ Xistar0 = 3324, /**< \f$\Xi ^{*0 }\f$ (Xi*0) */ Xistarbar0 = -3324, /**< \f$\overline{\Xi }^{*0 }\f$ (Xi*bar0) */ Omegaminus = 3334, /**< \f$\Omega ^{-}\f$ (Omega-) */ Omegabarplus = -3334, /**< \f$\overline{\Omega }^{+}\f$ (Omegabar+) */ cd_0 = 4101, /**< \f$\mbox{cd}^{0 }\f$ (cd_0) */ cd_0bar = -4101, /**< \f$\overline{\mbox{cd}}^{0 }\f$ (cd_0bar) */ cd_1 = 4103, /**< \f$\mbox{cd}_{1}\f$ (cd_1) */ cd_1bar = -4103, /**< \f$\overline{\mbox{cd}}_{1}\f$ (cd_1bar) */ Sigma_c0 = 4112, /**< \f$\Sigma ^{0 }_{c}\f$ (Sigma_c0) */ Sigma_cbar0 = -4112, /**< \f$\overline{\Sigma }^{0 }_{c}\f$ (Sigma_cbar0) */ Sigmastar_c0 = 4114, /**< \f$\Sigma ^{*0 }_{c}\f$ (Sigma*_c0) */ Sigmastar_cbar0 = -4114, /**< \f$\overline{\Sigma }^{*0 }_{c}\f$ (Sigma*_cbar0) */ Lambda_cplus = 4122, /**< \f$\Lambda ^{+}_{c}\f$ (Lambda_c+) */ Lambda_cbarminus = -4122, /**< \f$\overline{\Lambda }^{-}_{c}\f$ (Lambda_cbar-) */ Xi_c0 = 4132, /**< \f$\Xi ^{0 }_{c}\f$ (Xi_c0) */ Xi_cbar0 = -4132, /**< \f$\overline{\Xi }^{0 }_{c}\f$ (Xi_cbar0) */ cu_0 = 4201, /**< \f$\mbox{cu}^{0 }\f$ (cu_0) */ cu_0bar = -4201, /**< \f$\overline{\mbox{cu}}^{0 }\f$ (cu_0bar) */ cu_1 = 4203, /**< \f$\mbox{cu}_{1}\f$ (cu_1) */ cu_1bar = -4203, /**< \f$\overline{\mbox{cu}}_{1}\f$ (cu_1bar) */ Sigma_cplus = 4212, /**< \f$\Sigma ^{+}_{c}\f$ (Sigma_c+) */ Sigma_cbarminus = -4212, /**< \f$\overline{\Sigma }^{-}_{c}\f$ (Sigma_cbar-) */ Sigmastar_cplus = 4214, /**< \f$\Sigma ^{*+}_{c}\f$ (Sigma*_c+) */ Sigmastar_cbarminus = -4214, /**< \f$\overline{\Sigma }^{*-}_{c}\f$ (Sigma*_cbar-) */ Sigma_cplus2 = 4222, /**< \f$\Sigma ^{++}_{c}\f$ (Sigma_c++) */ Sigma_cbarminus2 = -4222, /**< \f$\overline{\Sigma }^{--}_{c}\f$ (Sigma_cbar--) */ Sigmastar_cplus2 = 4224, /**< \f$\Sigma ^{*++}_{c}\f$ (Sigma*_c++) */ Sigmastar_cbarminus2 = -4224, /**< \f$\overline{\Sigma }^{*--}_{c}\f$ (Sigma*_cbar--) */ Xi_cplus = 4232, /**< \f$\Xi ^{+}_{c}\f$ (Xi_c+) */ Xi_cbarminus = -4232, /**< \f$\overline{\Xi }^{-}_{c}\f$ (Xi_cbar-) */ cs_0 = 4301, /**< \f$\mbox{cs}^{0 }\f$ (cs_0) */ cs_0bar = -4301, /**< \f$\overline{\mbox{cs}}^{0 }\f$ (cs_0bar) */ cs_1 = 4303, /**< \f$\mbox{cs}_{1}\f$ (cs_1) */ cs_1bar = -4303, /**< \f$\overline{\mbox{cs}}_{1}\f$ (cs_1bar) */ Xiprime_c0 = 4312, /**< \f$\Xi ^{\prime 0 }_{c}\f$ (Xi'_c0) */ Xiprime_cbar0 = -4312, /**< \f$\overline{\Xi }^{\prime 0 }_{c}\f$ (Xi'_cbar0) */ Xistar_c0 = 4314, /**< \f$\Xi ^{*0 }_{c}\f$ (Xi*_c0) */ Xistar_cbar0 = -4314, /**< \f$\overline{\Xi }^{*0 }_{c}\f$ (Xi*_cbar0) */ Xiprime_cplus = 4322, /**< \f$\Xi ^{\prime +}_{c}\f$ (Xi'_c+) */ Xiprime_cbarminus = -4322, /**< \f$\overline{\Xi }^{\prime -}_{c}\f$ (Xi'_cbar-) */ Xistar_cplus = 4324, /**< \f$\Xi ^{*+}_{c}\f$ (Xi*_c+) */ Xistar_cbarminus = -4324, /**< \f$\overline{\Xi }^{*-}_{c}\f$ (Xi*_cbar-) */ Omega_c0 = 4332, /**< \f$\Omega ^{0 }_{c}\f$ (Omega_c0) */ Omega_cbar0 = -4332, /**< \f$\overline{\Omega }^{0 }_{c}\f$ (Omega_cbar0) */ Omegastar_c0 = 4334, /**< \f$\Omega ^{*0 }_{c}\f$ (Omega*_c0) */ Omegastar_cbar0 = -4334, /**< \f$\overline{\Omega }^{*0 }_{c}\f$ (Omega*_cbar0) */ cc_1 = 4403, /**< \f$\mbox{cc}_{1}\f$ (cc_1) */ cc_1bar = -4403, /**< \f$\overline{\mbox{cc}}_{1}\f$ (cc_1bar) */ Xi_ccplus = 4412, /**< \f$\Xi ^{+}_{cc}\f$ (Xi_cc+) */ Xi_ccbarminus = -4412, /**< \f$\overline{\Xi }^{-}_{cc}\f$ (Xi_ccbar-) */ Xistar_ccplus = 4414, /**< \f$\Xi ^{*+}_{cc}\f$ (Xi*_cc+) */ Xistar_ccbarminus = -4414, /**< \f$\overline{\Xi }^{*-}_{cc}\f$ (Xi*_ccbar-) */ Xi_ccplus2 = 4422, /**< \f$\Xi ^{++}_{cc}\f$ (Xi_cc++) */ Xi_ccbarminus2 = -4422, /**< \f$\overline{\Xi }^{--}_{cc}\f$ (Xi_ccbar--) */ Xistar_ccplus2 = 4424, /**< \f$\Xi ^{*++}_{cc}\f$ (Xi*_cc++) */ Xistar_ccbarminus2 = -4424, /**< \f$\overline{\Xi }^{*--}_{cc}\f$ (Xi*_ccbar--) */ Omega_ccplus = 4432, /**< \f$\Omega ^{+}_{cc}\f$ (Omega_cc+) */ Omega_ccbarminus = -4432, /**< \f$\overline{\Omega }^{-}_{cc}\f$ (Omega_ccbar-) */ Omegastar_ccplus = 4434, /**< \f$\Omega ^{*+}_{cc}\f$ (Omega*_cc+) */ Omegastar_ccbarminus = -4434, /**< \f$\overline{\Omega }^{*-}_{cc}\f$ (Omega*_ccbar-) */ Omegastar_cccplus2 = 4444, /**< \f$\Omega ^{*++}_{ccc}\f$ (Omega*_ccc++) */ Omegastar_cccbarminus = -4444, /**< \f$\overline{\Omega }^{*-}_{ccc}\f$ (Omega*_cccbar-) */ bd_0 = 5101, /**< \f$\mbox{bd}^{0 }\f$ (bd_0) */ bd_0bar = -5101, /**< \f$\overline{\mbox{bd}}^{0 }\f$ (bd_0bar) */ bd_1 = 5103, /**< \f$\mbox{bd}_{1}\f$ (bd_1) */ bd_1bar = -5103, /**< \f$\overline{\mbox{bd}}_{1}\f$ (bd_1bar) */ Sigma_bminus = 5112, /**< \f$\Sigma ^{-}_{b}\f$ (Sigma_b-) */ Sigma_bbarplus = -5112, /**< \f$\overline{\Sigma }^{+}_{b}\f$ (Sigma_bbar+) */ Sigmastar_bminus = 5114, /**< \f$\Sigma ^{*-}_{b}\f$ (Sigma*_b-) */ Sigmastar_bbarplus = -5114, /**< \f$\overline{\Sigma }^{*+}_{b}\f$ (Sigma*_bbar+) */ Lambda_b0 = 5122, /**< \f$\Lambda ^{0 }_{b}\f$ (Lambda_b0) */ Lambda_bbar0 = -5122, /**< \f$\overline{\Lambda }^{0 }_{b}\f$ (Lambda_bbar0) */ Xi_bminus = 5132, /**< \f$\Xi ^{-}_{b}\f$ (Xi_b-) */ Xi_bbarplus = -5132, /**< \f$\overline{\Xi }^{+}_{b}\f$ (Xi_bbar+) */ Xi_bc0 = 5142, /**< \f$\Xi ^{0 }_{bc}\f$ (Xi_bc0) */ Xi_bcbar0 = -5142, /**< \f$\overline{\Xi }^{0 }_{bc}\f$ (Xi_bcbar0) */ bu_0 = 5201, /**< \f$\mbox{bu}^{0 }\f$ (bu_0) */ bu_0bar = -5201, /**< \f$\overline{\mbox{bu}}^{0 }\f$ (bu_0bar) */ bu_1 = 5203, /**< \f$\mbox{bu}_{1}\f$ (bu_1) */ bu_1bar = -5203, /**< \f$\overline{\mbox{bu}}_{1}\f$ (bu_1bar) */ Sigma_b0 = 5212, /**< \f$\Sigma ^{0 }_{b}\f$ (Sigma_b0) */ Sigma_bbar0 = -5212, /**< \f$\overline{\Sigma }^{0 }_{b}\f$ (Sigma_bbar0) */ Sigmastar_b0 = 5214, /**< \f$\Sigma ^{*0 }_{b}\f$ (Sigma*_b0) */ Sigmastar_bbar0 = -5214, /**< \f$\overline{\Sigma }^{*0 }_{b}\f$ (Sigma*_bbar0) */ Sigma_bplus = 5222, /**< \f$\Sigma ^{+}_{b}\f$ (Sigma_b+) */ Sigma_bbarminus = -5222, /**< \f$\overline{\Sigma }^{-}_{b}\f$ (Sigma_bbar-) */ Sigmastar_bplus = 5224, /**< \f$\Sigma ^{*+}_{b}\f$ (Sigma*_b+) */ Sigmastar_bbarminus = -5224, /**< \f$\overline{\Sigma }^{*-}_{b}\f$ (Sigma*_bbar-) */ Xi_b0 = 5232, /**< \f$\Xi ^{0 }_{b}\f$ (Xi_b0) */ Xi_bbar0 = -5232, /**< \f$\overline{\Xi }^{0 }_{b}\f$ (Xi_bbar0) */ Xi_bcplus = 5242, /**< \f$\Xi ^{+}_{bc}\f$ (Xi_bc+) */ Xi_bcbarminus = -5242, /**< \f$\overline{\Xi }^{-}_{bc}\f$ (Xi_bcbar-) */ bs_0 = 5301, /**< \f$\mbox{bs}^{0 }\f$ (bs_0) */ bs_0bar = -5301, /**< \f$\overline{\mbox{bs}}^{0 }\f$ (bs_0bar) */ bs_1 = 5303, /**< \f$\mbox{bs}_{1}\f$ (bs_1) */ bs_1bar = -5303, /**< \f$\overline{\mbox{bs}}_{1}\f$ (bs_1bar) */ Xiprime_bminus = 5312, /**< \f$\Xi ^{\prime -}_{b}\f$ (Xi'_b-) */ Xiprime_bbarplus = -5312, /**< \f$\overline{\Xi }^{\prime +}_{b}\f$ (Xi'_bbar+) */ Xistar_bminus = 5314, /**< \f$\Xi ^{*-}_{b}\f$ (Xi*_b-) */ Xistar_bbarplus = -5314, /**< \f$\overline{\Xi }^{*+}_{b}\f$ (Xi*_bbar+) */ Xiprime_b0 = 5322, /**< \f$\Xi ^{\prime 0 }_{b}\f$ (Xi'_b0) */ Xiprime_bbar0 = -5322, /**< \f$\overline{\Xi }^{\prime 0 }_{b}\f$ (Xi'_bbar0) */ Xistar_b0 = 5324, /**< \f$\Xi ^{*0 }_{b}\f$ (Xi*_b0) */ Xistar_bbar0 = -5324, /**< \f$\overline{\Xi }^{*0 }_{b}\f$ (Xi*_bbar0) */ Omega_bminus = 5332, /**< \f$\Omega ^{-}_{b}\f$ (Omega_b-) */ Omega_bbarplus = -5332, /**< \f$\overline{\Omega }^{+}_{b}\f$ (Omega_bbar+) */ Omegastar_bminus = 5334, /**< \f$\Omega ^{*-}_{b}\f$ (Omega*_b-) */ Omegastar_bbarplus = -5334, /**< \f$\overline{\Omega }^{*+}_{b}\f$ (Omega*_bbar+) */ Omega_bc0 = 5342, /**< \f$\Omega ^{0 }_{bc}\f$ (Omega_bc0) */ Omega_bcbar0 = -5342, /**< \f$\overline{\Omega }^{0 }_{bc}\f$ (Omega_bcbar0) */ bc_0 = 5401, /**< \f$\mbox{bc}^{0 }\f$ (bc_0) */ bc_0bar = -5401, /**< \f$\overline{\mbox{bc}}^{0 }\f$ (bc_0bar) */ bc_1 = 5403, /**< \f$\mbox{bc}_{1}\f$ (bc_1) */ bc_1bar = -5403, /**< \f$\overline{\mbox{bc}}_{1}\f$ (bc_1bar) */ Xiprime_bc0 = 5412, /**< \f$\Xi ^{\prime 0 }_{bc}\f$ (Xi'_bc0) */ Xiprime_bcbar0 = -5412, /**< \f$\overline{\Xi }^{\prime 0 }_{bc}\f$ (Xi'_bcbar0) */ Xistar_bc0 = 5414, /**< \f$\Xi ^{*0 }_{bc}\f$ (Xi*_bc0) */ Xistar_bcbar0 = -5414, /**< \f$\overline{\Xi }^{*0 }_{bc}\f$ (Xi*_bcbar0) */ Xiprime_bcplus = 5422, /**< \f$\Xi ^{\prime +}_{bc}\f$ (Xi'_bc+) */ Xiprime_bcbarminus = -5422, /**< \f$\overline{\Xi }^{\prime -}_{bc}\f$ (Xi'_bcbar-) */ Xistar_bcplus = 5424, /**< \f$\Xi ^{*+}_{bc}\f$ (Xi*_bc+) */ Xistar_bcbarminus = -5424, /**< \f$\overline{\Xi }^{*-}_{bc}\f$ (Xi*_bcbar-) */ Omegaprime_bc0 = 5432, /**< \f$\Omega ^{\prime 0 }_{bc}\f$ (Omega'_bc0) */ Omegaprime_bcba = -5432, /**< \f$\overline{\Omega }^{\prime }_{bc}\f$ (Omega'_bcba) */ Omegastar_bc0 = 5434, /**< \f$\Omega ^{*0 }_{bc}\f$ (Omega*_bc0) */ Omegastar_bcbar0 = -5434, /**< \f$\overline{\Omega }^{*0 }_{bc}\f$ (Omega*_bcbar0) */ Omega_bccplus = 5442, /**< \f$\Omega ^{+}_{bcc}\f$ (Omega_bcc+) */ Omega_bccbarminus = -5442, /**< \f$\overline{\Omega }^{-}_{bcc}\f$ (Omega_bccbar-) */ Omegastar_bccplus = 5444, /**< \f$\Omega ^{*+}_{bcc}\f$ (Omega*_bcc+) */ Omegastar_bccbarminus = -5444, /**< \f$\overline{\Omega }^{*-}_{bcc}\f$ (Omega*_bccbar-) */ bb_1 = 5503, /**< \f$\mbox{bb}_{1}\f$ (bb_1) */ bb_1bar = -5503, /**< \f$\overline{\mbox{bb}}_{1}\f$ (bb_1bar) */ Xi_bbminus = 5512, /**< \f$\Xi ^{-}_{bb}\f$ (Xi_bb-) */ Xi_bbbarplus = -5512, /**< \f$\overline{\Xi }^{+}_{bb}\f$ (Xi_bbbar+) */ Xistar_bbminus = 5514, /**< \f$\Xi ^{*-}_{bb}\f$ (Xi*_bb-) */ Xistar_bbbarplus = -5514, /**< \f$\overline{\Xi }^{*+}_{bb}\f$ (Xi*_bbbar+) */ Xi_bb0 = 5522, /**< \f$\Xi ^{0 }_{bb}\f$ (Xi_bb0) */ Xi_bbbar0 = -5522, /**< \f$\overline{\Xi }^{0 }_{bb}\f$ (Xi_bbbar0) */ Xistar_bb0 = 5524, /**< \f$\Xi ^{*0 }_{bb}\f$ (Xi*_bb0) */ Xistar_bbbar0 = -5524, /**< \f$\overline{\Xi }^{*0 }_{bb}\f$ (Xi*_bbbar0) */ Omega_bbminus = 5532, /**< \f$\Omega ^{-}_{bb}\f$ (Omega_bb-) */ Omega_bbbarplus = -5532, /**< \f$\overline{\Omega }^{+}_{bb}\f$ (Omega_bbbar+) */ Omegastar_bbminus = 5534, /**< \f$\Omega ^{*-}_{bb}\f$ (Omega*_bb-) */ Omegastar_bbbarplus = -5534, /**< \f$\overline{\Omega }^{*+}_{bb}\f$ (Omega*_bbbar+) */ Omega_bbc0 = 5542, /**< \f$\Omega ^{0 }_{bbc}\f$ (Omega_bbc0) */ Omega_bbcbar0 = -5542, /**< \f$\overline{\Omega }^{0 }_{bbc}\f$ (Omega_bbcbar0) */ Omegastar_bbc0 = 5544, /**< \f$\Omega ^{*0 }_{bbc}\f$ (Omega*_bbc0) */ Omegastar_bbcbar0 = -5544, /**< \f$\overline{\Omega }^{*0 }_{bbc}\f$ (Omega*_bbcbar0) */ Omegastar_bbbminus = 5554, /**< \f$\Omega ^{*-}_{bbb}\f$ (Omega*_bbb-) */ Omegastar_bbbbarplus = -5554, /**< \f$\overline{\Omega }^{*+}_{bbb}\f$ (Omega*_bbbbar+) */ a_00 = 9000111, /**< \f$\mbox{a}^{0 }\f$ (a_00) */ b_10 = 10113, /**< \f$\mbox{b}^{0 }_{1}\f$ (b_10) */ a_0plus = 9000211, /**< \f$\mbox{a}^{0 +}\f$ (a_0+) */ a_0minus = -9000211, /**< \f$\mbox{a}^{0 -}\f$ (a_0-) */ b_1plus = 10213, /**< \f$\mbox{b}^{+}_{1}\f$ (b_1+) */ b_1minus = -10213, /**< \f$\mbox{b}^{-}_{1}\f$ (b_1-) */ f_0 = 9010221, /**< \f$\mbox{f}^{0 }\f$ (f_0) */ h_1 = 10223, /**< \f$\mbox{h}_{1}\f$ (h_1) */ Kstar_00 = 10311, /**< \f$\mbox{K}^{*0 }\f$ (K*_00) */ Kstar_0bar0 = -10311, /**< \f$\overline{\mbox{K}}^{*0 }\f$ (K*_0bar0) */ K_10 = 10313, /**< \f$\mbox{K}^{0 }_{1}\f$ (K_10) */ K_1bar0 = -10313, /**< \f$\overline{\mbox{K}}^{0 }_{1}\f$ (K_1bar0) */ Kstar_0plus = 10321, /**< \f$\mbox{K}^{*0 +}\f$ (K*_0+) */ Kstar_0minus = -10321, /**< \f$\mbox{K}^{*0 -}\f$ (K*_0-) */ K_1plus = 10323, /**< \f$\mbox{K}^{+}_{1}\f$ (K_1+) */ K_1minus = -10323, /**< \f$\mbox{K}^{-}_{1}\f$ (K_1-) */ eta1440 = 100331, /**< \f$\eta ^{0 }_{144}\f$ (eta1440) */ hprime_1 = 10333, /**< \f$\mbox{h}^{\prime }_{1}\f$ (h'_1) */ Dstar_0plus = 10411, /**< \f$\mbox{D}^{*0 +}\f$ (D*_0+) */ Dstar_0minus = -10411, /**< \f$\mbox{D}^{*0 -}\f$ (D*_0-) */ D_1plus = 10413, /**< \f$\mbox{D}^{+}_{1}\f$ (D_1+) */ D_1minus = -10413, /**< \f$\mbox{D}^{-}_{1}\f$ (D_1-) */ Dstar_00 = 10421, /**< \f$\mbox{D}^{*0 }\f$ (D*_00) */ Dstar_0bar0 = -10421, /**< \f$\overline{\mbox{D}}^{*0 }\f$ (D*_0bar0) */ D_10 = 10423, /**< \f$\mbox{D}^{0 }_{1}\f$ (D_10) */ D_1bar0 = -10423, /**< \f$\overline{\mbox{D}}^{0 }_{1}\f$ (D_1bar0) */ Dstar_0splus = 10431, /**< \f$\mbox{D}^{*+}_{0s}\f$ (D*_0s+) */ Dstar_0sminus = -10431, /**< \f$\mbox{D}^{*-}_{0s}\f$ (D*_0s-) */ D_1splus = 10433, /**< \f$\mbox{D}^{+}_{1s}\f$ (D_1s+) */ D_1sminus = -10433, /**< \f$\mbox{D}^{-}_{1s}\f$ (D_1s-) */ chi_0c = 10441, /**< \f$\chi _{0c}\f$ (chi_0c) */ h_1c = 10443, /**< \f$\mbox{h}_{1c}\f$ (h_1c) */ Bstar_00 = 10511, /**< \f$\mbox{B}^{*0 }\f$ (B*_00) */ Bstar_0bar0 = -10511, /**< \f$\overline{\mbox{B}}^{*0 }\f$ (B*_0bar0) */ B_10 = 10513, /**< \f$\mbox{B}^{0 }_{1}\f$ (B_10) */ B_1bar0 = -10513, /**< \f$\overline{\mbox{B}}^{0 }_{1}\f$ (B_1bar0) */ Bstar_0plus = 10521, /**< \f$\mbox{B}^{*0 +}\f$ (B*_0+) */ Bstar_0minus = -10521, /**< \f$\mbox{B}^{*0 -}\f$ (B*_0-) */ B_1plus = 10523, /**< \f$\mbox{B}^{+}_{1}\f$ (B_1+) */ B_1minus = -10523, /**< \f$\mbox{B}^{-}_{1}\f$ (B_1-) */ Bstar_0s0 = 10531, /**< \f$\mbox{B}^{*0 }_{0s}\f$ (B*_0s0) */ Bstar_0sbar0 = -10531, /**< \f$\overline{\mbox{B}}^{*0 }_{0s}\f$ (B*_0sbar0) */ B_1s0 = 10533, /**< \f$\mbox{B}^{0 }_{1s}\f$ (B_1s0) */ B_1sbar0 = -10533, /**< \f$\overline{\mbox{B}}^{0 }_{1s}\f$ (B_1sbar0) */ Bstar_0cplus = 10541, /**< \f$\mbox{B}^{*+}_{0c}\f$ (B*_0c+) */ Bstar_0cminus = -10541, /**< \f$\mbox{B}^{*-}_{0c}\f$ (B*_0c-) */ B_1cplus = 10543, /**< \f$\mbox{B}^{+}_{1c}\f$ (B_1c+) */ B_1cminus = -10543, /**< \f$\mbox{B}^{-}_{1c}\f$ (B_1c-) */ chi_0b = 10551, /**< \f$\chi _{0b}\f$ (chi_0b) */ h_1b = 10553, /**< \f$\mbox{h}_{1b}\f$ (h_1b) */ a_10 = 20113, /**< \f$\mbox{a}^{0 }_{1}\f$ (a_10) */ a_1plus = 20213, /**< \f$\mbox{a}^{+}_{1}\f$ (a_1+) */ a_1minus = -20213, /**< \f$\mbox{a}^{-}_{1}\f$ (a_1-) */ f_1 = 20223, /**< \f$\mbox{f}_{1}\f$ (f_1) */ Kstar_10 = 20313, /**< \f$\mbox{K}^{*0 }_{1}\f$ (K*_10) */ Kstar_1bar0 = -20313, /**< \f$\overline{\mbox{K}}^{*0 }_{1}\f$ (K*_1bar0) */ Kstar_1plus = 20323, /**< \f$\mbox{K}^{*+}_{1}\f$ (K*_1+) */ Kstar_1minus = -20323, /**< \f$\mbox{K}^{*-}_{1}\f$ (K*_1-) */ fprime_1 = 20333, /**< \f$\mbox{f}^{\prime }_{1}\f$ (f'_1) */ Dstar_1plus = 20413, /**< \f$\mbox{D}^{*+}_{1}\f$ (D*_1+) */ Dstar_1minus = -20413, /**< \f$\mbox{D}^{*-}_{1}\f$ (D*_1-) */ Dstar_10 = 20423, /**< \f$\mbox{D}^{*0 }_{1}\f$ (D*_10) */ Dstar_1bar0 = -20423, /**< \f$\overline{\mbox{D}}^{*0 }_{1}\f$ (D*_1bar0) */ Dstar_1splus = 20433, /**< \f$\mbox{D}^{*+}_{1s}\f$ (D*_1s+) */ Dstar_1sminus = -20433, /**< \f$\mbox{D}^{*-}_{1s}\f$ (D*_1s-) */ chi_1c = 20443, /**< \f$\chi _{1c}\f$ (chi_1c) */ Bstar_10 = 20513, /**< \f$\mbox{B}^{*0 }_{1}\f$ (B*_10) */ Bstar_1bar0 = -20513, /**< \f$\overline{\mbox{B}}^{*0 }_{1}\f$ (B*_1bar0) */ Bstar_1plus = 20523, /**< \f$\mbox{B}^{*+}_{1}\f$ (B*_1+) */ Bstar_1minus = -20523, /**< \f$\mbox{B}^{*-}_{1}\f$ (B*_1-) */ Bstar_1s0 = 20533, /**< \f$\mbox{B}^{*0 }_{1s}\f$ (B*_1s0) */ Bstar_1sbar0 = -20533, /**< \f$\overline{\mbox{B}}^{*0 }_{1s}\f$ (B*_1sbar0) */ Bstar_1cplus = 20543, /**< \f$\mbox{B}^{*+}_{1c}\f$ (B*_1c+) */ Bstar_1cminus = -20543, /**< \f$\mbox{B}^{*-}_{1c}\f$ (B*_1c-) */ chi_1b = 20553, /**< \f$\chi _{1b}\f$ (chi_1b) */ psiprime = 100443, /**< \f$\psi ^{\prime }\f$ (psi') */ Upsilonprime = 100553, /**< \f$\Upsilon ^{\prime }\f$ (Upsilon') */ SUSY_d_L = 1000001, /**< \f$\tilde{\mbox{d}}_{L}\f$ (~d_L) */ SUSY_d_Lbar = -1000001, /**< \f$\tilde{\overline{\mbox{d}}}_{L}\f$ (~d_Lbar) */ SUSY_u_L = 1000002, /**< \f$\tilde{\mbox{u}}_{L}\f$ (~u_L) */ SUSY_u_Lbar = -1000002, /**< \f$\tilde{\overline{\mbox{u}}}_{L}\f$ (~u_Lbar) */ SUSY_s_L = 1000003, /**< \f$\tilde{\mbox{s}}_{L}\f$ (~s_L) */ SUSY_s_Lbar = -1000003, /**< \f$\tilde{\overline{\mbox{s}}}_{L}\f$ (~s_Lbar) */ SUSY_c_L = 1000004, /**< \f$\tilde{\mbox{c}}_{L}\f$ (~c_L) */ SUSY_c_Lbar = -1000004, /**< \f$\tilde{\overline{\mbox{c}}}_{L}\f$ (~c_Lbar) */ SUSY_b_1 = 1000005, /**< \f$\tilde{\mbox{b}}_{1}\f$ (~b_1) */ SUSY_b_1bar = -1000005, /**< \f$\tilde{\overline{\mbox{b}}}_{1}\f$ (~b_1bar) */ SUSY_t_1 = 1000006, /**< \f$\tilde{\mbox{t}}_{1}\f$ (~t_1) */ SUSY_t_1bar = -1000006, /**< \f$\tilde{\overline{\mbox{t}}}_{1}\f$ (~t_1bar) */ SUSY_e_Lminus = 1000011, /**< \f$\tilde{\mbox{e}}^{-}_{L}\f$ (~e_L-) */ SUSY_e_Lplus = -1000011, /**< \f$\tilde{\mbox{e}}^{+}_{L}\f$ (~e_L+) */ SUSY_nu_eL = 1000012, /**< \f$\tilde{\nu }_{eL}\f$ (~nu_eL) */ SUSY_nu_eLbar = -1000012, /**< \f$\tilde{\overline{\nu }}_{eL}\f$ (~nu_eLbar) */ SUSY_mu_Lminus = 1000013, /**< \f$\tilde{\mu }^{-}_{L}\f$ (~mu_L-) */ SUSY_mu_Lplus = -1000013, /**< \f$\tilde{\mu }^{+}_{L}\f$ (~mu_L+) */ SUSY_nu_muL = 1000014, /**< \f$\tilde{\nu }_{\mu L}\f$ (~nu_muL) */ SUSY_nu_muLbar = -1000014, /**< \f$\tilde{\overline{\nu }}_{\mu L}\f$ (~nu_muLbar) */ SUSY_tau_1minus = 1000015, /**< \f$\tilde{\tau }^{-}_{1}\f$ (~tau_1-) */ SUSY_tau_1plus = -1000015, /**< \f$\tilde{\tau }^{+}_{1}\f$ (~tau_1+) */ SUSY_nu_tauL = 1000016, /**< \f$\tilde{\nu }_{\tau L}\f$ (~nu_tauL) */ SUSY_nu_tauLbar = -1000016, /**< \f$\tilde{\overline{\nu }}_{\tau L}\f$ (~nu_tauLbar) */ SUSY_g = 1000021, /**< \f$\tilde{\mbox{g}}\f$ (~g) */ SUSY_chi_10 = 1000022, /**< \f$\tilde{\chi }^{0 }_{1}\f$ (~chi_10) */ SUSY_chi_20 = 1000023, /**< \f$\tilde{\chi }^{0 }_{2}\f$ (~chi_20) */ SUSY_chi_1plus = 1000024, /**< \f$\tilde{\chi }^{+}_{1}\f$ (~chi_1+) */ SUSY_chi_1minus = -1000024, /**< \f$\tilde{\chi }^{-}_{1}\f$ (~chi_1-) */ SUSY_chi_30 = 1000025, /**< \f$\tilde{\chi }^{0 }_{3}\f$ (~chi_30) */ SUSY_chi_40 = 1000035, /**< \f$\tilde{\chi }^{0 }_{4}\f$ (~chi_40) */ SUSY_chi_2plus = 1000037, /**< \f$\tilde{\chi }^{+}_{2}\f$ (~chi_2+) */ SUSY_chi_2minus = -1000037, /**< \f$\tilde{\chi }^{-}_{2}\f$ (~chi_2-) */ SUSY_Gravitino = 1000039, /**< \f$\tilde{{\cal G}}\f$ (~Gravitino) */ SUSY_d_R = 2000001, /**< \f$\tilde{\mbox{d}}_{R}\f$ (~d_R) */ SUSY_d_Rbar = -2000001, /**< \f$\tilde{\overline{\mbox{d}}}_{R}\f$ (~d_Rbar) */ SUSY_u_R = 2000002, /**< \f$\tilde{\mbox{u}}_{R}\f$ (~u_R) */ SUSY_u_Rbar = -2000002, /**< \f$\tilde{\overline{\mbox{u}}}_{R}\f$ (~u_Rbar) */ SUSY_s_R = 2000003, /**< \f$\tilde{\mbox{s}}_{R}\f$ (~s_R) */ SUSY_s_Rbar = -2000003, /**< \f$\tilde{\overline{\mbox{s}}}_{R}\f$ (~s_Rbar) */ SUSY_c_R = 2000004, /**< \f$\tilde{\mbox{c}}_{R}\f$ (~c_R) */ SUSY_c_Rbar = -2000004, /**< \f$\tilde{\overline{\mbox{c}}}_{R}\f$ (~c_Rbar) */ SUSY_b_2 = 2000005, /**< \f$\tilde{\mbox{b}}_{2}\f$ (~b_2) */ SUSY_b_2bar = -2000005, /**< \f$\tilde{\overline{\mbox{b}}}_{2}\f$ (~b_2bar) */ SUSY_t_2 = 2000006, /**< \f$\tilde{\mbox{t}}_{2}\f$ (~t_2) */ SUSY_t_2bar = -2000006, /**< \f$\tilde{\overline{\mbox{t}}}_{2}\f$ (~t_2bar) */ SUSY_e_Rminus = 2000011, /**< \f$\tilde{\mbox{e}}^{-}_{R}\f$ (~e_R-) */ SUSY_e_Rplus = -2000011, /**< \f$\tilde{\mbox{e}}^{+}_{R}\f$ (~e_R+) */ SUSY_nu_eR = 2000012, /**< \f$\tilde{\nu }_{eR}\f$ (~nu_eR) */ SUSY_nu_eRbar = -2000012, /**< \f$\tilde{\overline{\nu }}_{eR}\f$ (~nu_eRbar) */ SUSY_mu_Rminus = 2000013, /**< \f$\tilde{\mu }^{-}_{R}\f$ (~mu_R-) */ SUSY_mu_Rplus = -2000013, /**< \f$\tilde{\mu }^{+}_{R}\f$ (~mu_R+) */ SUSY_nu_muR = 2000014, /**< \f$\tilde{\nu }_{\mu R}\f$ (~nu_muR) */ SUSY_nu_muRbar = -2000014, /**< \f$\tilde{\overline{\nu }}_{\mu R}\f$ (~nu_muRbar) */ SUSY_tau_2minus = 2000015, /**< \f$\tilde{\tau }^{-}_{2}\f$ (~tau_2-) */ SUSY_tau_2plus = -2000015, /**< \f$\tilde{\tau }^{+}_{2}\f$ (~tau_2+) */ SUSY_nu_tauR = 2000016, /**< \f$\tilde{\nu }_{\tau R}\f$ (~nu_tauR) */ SUSY_nu_tauRbar = -2000016, /**< \f$\tilde{\overline{\nu }}_{\tau R}\f$ (~nu_tauRbar) */ pi_tc0 = 3000111, /**< \f$\pi ^{0 }_{tc}\f$ (pi_tc0) */ pi_tcplus = 3000211, /**< \f$\pi ^{+}_{tc}\f$ (pi_tc+) */ pi_tcminus = -3000211, /**< \f$\pi ^{-}_{tc}\f$ (pi_tc-) */ piprime_tc0 = 3000221, /**< \f$\pi ^{\prime 0 }_{tc}\f$ (pi'_tc0) */ eta_tc0 = 3000331, /**< \f$\eta ^{0 }_{tc}\f$ (eta_tc0) */ rho_tc0 = 3000113, /**< \f$\rho ^{0 }_{tc}\f$ (rho_tc0) */ rho_tcplus = 3000213, /**< \f$\rho ^{+}_{tc}\f$ (rho_tc+) */ rho_tcminus = -3000213, /**< \f$\rho ^{-}_{tc}\f$ (rho_tc-) */ omega_tc = 3000223, /**< \f$\omega _{tc}\f$ (omega_tc) */ V8_tc = 3100021, /**< \f$\mbox{V}_{8tc}\f$ (V8_tc) */ pi_22_1_tc = 3100111, /**< \f$\pi _{22}\f$ (pi_22_1_tc) */ pi_22_8_tc = 3200111, /**< \f$\pi _{22}\f$ (pi_22_8_tc) */ rho_11_tc = 3100113, /**< \f$\rho _{11}\f$ (rho_11_tc) */ rho_12_tc = 3200113, /**< \f$\rho _{12}\f$ (rho_12_tc) */ rho_21_tc = 3300113, /**< \f$\rho _{21}\f$ (rho_21_tc) */ rho_22_tc = 3400113, /**< \f$\rho _{22}\f$ (rho_22_tc) */ dstar = 4000001, /**< \f$\mbox{d}^{*}\f$ (d*) */ dstarbar = -4000001, /**< \f$\overline{\mbox{d}}^{*}\f$ (d*bar) */ ustar = 4000002, /**< \f$\mbox{u}^{*}\f$ (u*) */ ustarbar = -4000002, /**< \f$\overline{\mbox{u}}^{*}\f$ (u*bar) */ estarminus = 4000011, /**< \f$\mbox{e}^{*-}\f$ (e*-) */ estarbarplus = -4000011, /**< \f$\overline{\mbox{e}}^{*+}\f$ (e*bar+) */ nustar_e0 = 4000012, /**< \f$\nu ^{*0 }_{e}\f$ (nu*_e0) */ nustar_ebar0 = -4000012, /**< \f$\overline{\nu }^{*0 }_{e}\f$ (nu*_ebar0) */ Gravitonstar = 5000039, /**< \f${\cal G}^{*}\f$ (Graviton*) */ nu_Re = 9900012, /**< \f$\nu _{Re}\f$ (nu_Re) */ nu_Rmu = 9900014, /**< \f$\nu _{R\mu }\f$ (nu_Rmu) */ nu_Rtau = 9900016, /**< \f$\nu _{R\tau }\f$ (nu_Rtau) */ Z_R0 = 9900023, /**< \f$\mbox{Z}^{0 }_{R}\f$ (Z_R0) */ W_Rplus = 9900024, /**< \f$\mbox{W}^{+}_{R}\f$ (W_R+) */ W_Rminus = -9900024, /**< \f$\mbox{W}^{-}_{R}\f$ (W_R-) */ H_Lplus2 = 9900041, /**< \f$\mbox{H}^{++}_{L}\f$ (H_L++) */ H_Lminus2 = -9900041, /**< \f$\mbox{H}^{--}_{L}\f$ (H_L--) */ H_Rplus2 = 9900042, /**< \f$\mbox{H}^{++}_{R}\f$ (H_R++) */ H_Rminus2 = -9900042, /**< \f$\mbox{H}^{--}_{R}\f$ (H_R--) */ rho_diff0 = 9900110, /**< \f$\rho ^{0 }_{\mbox{\scriptsize diffr}}\f$ (rho_diff0) */ pi_diffrplus = 9900210, /**< \f$\pi ^{+}_{\mbox{\scriptsize diffr}}\f$ (pi_diffr+) */ pi_diffrminus = -9900210, /**< \f$\pi ^{-}_{\mbox{\scriptsize diffr}}\f$ (pi_diffr-) */ omega_di = 9900220, /**< \f$\omega _{\mbox{\scriptsize diffr}}\f$ (omega_di) */ phi_diff = 9900330, /**< \f$\phi _{\mbox{\scriptsize diffr}}\f$ (phi_diff) */ Jpsi_di = 9900440, /**< \f$J/\psi _{\mbox{\scriptsize diffr}}\f$ (J/psi_di) */ n_diffr0 = 9902110, /**< \f$\mbox{n}^{0 }_{\mbox{\scriptsize diffr}}\f$ (n_diffr0) */ n_diffrbar0 = -9902110, /**< \f$\overline{\mbox{n}}^{0 }_{\mbox{\scriptsize diffr}}\f$ (n_diffrbar0) */ p_diffrplus = 9902210, /**< \f$\mbox{p}^{+}_{\mbox{\scriptsize diffr}}\f$ (p_diffr+) */ p_diffrbarminus = -9902210, /**< \f$\overline{\mbox{p}}^{-}_{\mbox{\scriptsize diffr}}\f$ (p_diffrbar-) */ undefined = 0 /**< Undefined particle. */ }; } } #endif diff --git a/PDT/FlatDecayer.cc b/PDT/FlatDecayer.cc --- a/PDT/FlatDecayer.cc +++ b/PDT/FlatDecayer.cc @@ -1,78 +1,78 @@ // -*- C++ -*- // // FlatDecayer.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the FlatDecayer class. // #include "FlatDecayer.h" #include "ThePEG/PDT/DecayMode.h" #include "ThePEG/Utilities/SimplePhaseSpace.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Vectors/LorentzRotation.h" #include "ThePEG/Interface/ClassDocumentation.h" using namespace ThePEG; IBPtr FlatDecayer::clone() const { return new_ptr(*this); } IBPtr FlatDecayer::fullclone() const { return new_ptr(*this); } bool FlatDecayer::accept(const DecayMode & dm) const { if ( dm.products().size() == 1 && ( dm.parent()->massMax() > (**(dm.products().begin())).massMax() || dm.parent()->massMin() < (**(dm.products().begin())).massMin() ) ) return false; return dm.products().size() > 0 && dm.cascadeProducts().empty() && dm.productMatchers().empty() && !dm.wildProductMatcher(); } ParticleVector FlatDecayer::decay(const DecayMode & dm, const Particle & parent) const { ParticleVector children = getChildren(dm, parent); try { do { if ( children.size() == 1 ) { children[0]->setMomentum(parent.momentum()); children[0]->scale(parent.momentum().mass2()); return children; } else { SimplePhaseSpace::CMSn(children, parent.mass()); } } while ( reweight(dm, parent, children) < UseRandom::rnd() ); } catch ( ImpossibleKinematics & ) { children.clear(); return children; } finalBoost(parent, children); setScales(parent, children); return children; } NoPIOClassDescription FlatDecayer::initFlatDecayer; // Definition of the static class description member. void FlatDecayer::Init() { static ClassDocumentation documentation ("The ThePEG::FlatDecayer class describes the decay of a " "ThePEG::Particle into a set of specified children according " "to a flat distribution in phase space."); } diff --git a/PDT/FlatDecayer.h b/PDT/FlatDecayer.h --- a/PDT/FlatDecayer.h +++ b/PDT/FlatDecayer.h @@ -1,138 +1,138 @@ // -*- C++ -*- // // FlatDecayer.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_FlatDecayer_H #define ThePEG_FlatDecayer_H // This is the declaration of the FlatDecayer class. #include "ThePEG/PDT/Decayer.h" namespace ThePEG { /** * The FlatDecayer class inrerits from the abstract Decayer class and * implements the decay of a given Particle to a given set of children * according to a flat phase space distribution. * * It is possible to implement a more complicated decay distribution * by inheriting from the FlatDecayer class and only override the * virtual function reweight() to return a weight (between zero and * one) of a given phase space point relative to the flat * distribution. * * @see \ref FlatDecayerInterfaces "The interfaces" * defined for FlatDecayer. * @see Decayer * @see Particle */ class FlatDecayer: public Decayer { public: /** @name Virtual functions required by the Decayer class. */ //@{ /** * Check if this decayer can perfom the decay specified by the * given decay mode. * @param dm the DecayMode describing the decay. * @return true if this decayer can handle the given mode, otherwise false. */ virtual bool accept(const DecayMode & dm) const; /** * Perform a decay for a given DecayMode and a given Particle instance. * @param dm the DecayMode describing the decay. * @param p the Particle instance to be decayed. * @return a ParticleVector containing the decay products. */ virtual ParticleVector decay(const DecayMode & dm, const Particle & p) const; /** * Give a weight to a phase space point. To be overridden by * subclasses. For a given decay mode, \a dm, decaying \a parent * particle and decayproducts, \a children, distributed according to * a flat distribution in phase space, return a weight (less or * equal to unity) modifying the flat distribution to the desired * one. Note that the chosen phase space point may be rejected, but * the chosen decay channel will not. This means that the weight * returned by this function does not influence the branching * ratios. For the FlatDecayer class this function simply returns 1. */ virtual double reweight(const DecayMode &, const Particle & , const ParticleVector & ) const { return 1.0; } //@} public: /** * Standard Init function used to initialize the interfaces. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * Describe a concrete class without persistent data. */ static NoPIOClassDescription initFlatDecayer; /** * Private and non-existent assignment operator. */ FlatDecayer & operator=(const FlatDecayer &) = delete; }; } namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the base classes * of FlatDecayer. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of FlatDecayer. */ typedef Decayer NthBase; }; /** This template specialization informs ThePEG about the name of the * FlatDecayer class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "ThePEG::FlatDecayer"; } }; /** @endcond */ } #endif /* ThePEG_FlatDecayer_H */ diff --git a/PDT/MassGenerator.cc b/PDT/MassGenerator.cc --- a/PDT/MassGenerator.cc +++ b/PDT/MassGenerator.cc @@ -1,28 +1,28 @@ // -*- C++ -*- // // MassGenerator.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MassGenerator class. // #include "MassGenerator.h" #include "ThePEG/Interface/ClassDocumentation.h" using namespace ThePEG; AbstractNoPIOClassDescription MassGenerator::initMassGenerator; void MassGenerator::Init() { static ClassDocumentation documentation ("This is the base class for models giving specific masses to particle " "instances."); } diff --git a/PDT/MassGenerator.h b/PDT/MassGenerator.h --- a/PDT/MassGenerator.h +++ b/PDT/MassGenerator.h @@ -1,89 +1,89 @@ // -*- C++ -*- // // MassGenerator.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_MassGenerator_H #define ThePEG_MassGenerator_H // This is the declaration of the MassGenerator class. #include "ThePEG/Config/ThePEG.h" #include "ThePEG/Interface/Interfaced.h" #include "MassGenerator.fh" namespace ThePEG { /** * MassGenerator is an abstract base class used by the ParticleData * class to generate a mass for a Particle instance. * * @see \ref MassGeneratorInterfaces "The interfaces" * defined for MassGenerator. * @see ParticleData */ class MassGenerator: public Interfaced { public: /** @name Virtual functions to be overridden by sub-classes. */ //@{ /** * Return true if this mass generator can handle the given particle * type. */ virtual bool accept(const ParticleData &) const = 0; /** * Generate a mass for an instance of a given particle type. */ virtual Energy mass(const ParticleData &) const = 0; //@} public: /** * Standard Init function used to initialize the interface. */ static void Init(); private: /** * The static object used to initialize the description of this class. * Indicates that this is an abstract class without persistent data. */ static AbstractNoPIOClassDescription initMassGenerator; /** * Private and non-existent assignment operator. */ MassGenerator & operator=(const MassGenerator &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the base classes * of MassGenerator. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of MassGenerator. */ typedef Interfaced NthBase; }; /** This template specialization informs ThePEG about the name of the * MassGenerator class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "ThePEG::MassGenerator"; } }; /** @endcond */ } #endif /* ThePEG_MassGenerator_H */ diff --git a/PDT/Matcher.cc b/PDT/Matcher.cc --- a/PDT/Matcher.cc +++ b/PDT/Matcher.cc @@ -1,66 +1,66 @@ // -*- C++ -*- // // Matcher.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the Matcher class. // #include "Matcher.h" #include "StandardMatchers.h" #ifdef ThePEG_TEMPLATES_IN_CC_FILE #include "Matcher.tcc" #endif #define THEPEG_MATCH_DESC(T) \ /** \ * This template specialization registers the Matcher \ */ \ template <> \ NoPIOClassDescription T::initMatcher \ = NoPIOClassDescription(); \ namespace ThePEG { THEPEG_MATCH_DESC(MatchAny) THEPEG_MATCH_DESC(MatchStandardQCDParton) THEPEG_MATCH_DESC(MatchLightAntiQuark) THEPEG_MATCH_DESC(MatchLightQuark) THEPEG_MATCH_DESC(MatchLepton) THEPEG_MATCH_DESC(MatchDiquark) THEPEG_MATCH_DESC(MatchMeson) THEPEG_MATCH_DESC(MatchBaryon) THEPEG_MATCH_DESC(MatchNegative) THEPEG_MATCH_DESC(MatchNeutral) THEPEG_MATCH_DESC(MatchPositive) THEPEG_MATCH_DESC(MatchCharged) THEPEG_MATCH_DESC(MatchNeutrino) } namespace { using namespace ThePEG; static MatchAny m00; static MatchStandardQCDParton m01; static MatchLightAntiQuark m02; static MatchLightQuark m03; static MatchLepton m04; static MatchDiquark m05; static MatchMeson m06; static MatchBaryon m07; static MatchNegative m08; static MatchNeutral m09; static MatchPositive m11; static MatchCharged m12; static MatchNeutrino m13; } diff --git a/PDT/Matcher.h b/PDT/Matcher.h --- a/PDT/Matcher.h +++ b/PDT/Matcher.h @@ -1,138 +1,138 @@ // -*- C++ -*- // // Matcher.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_Matcher_H #define ThePEG_Matcher_H // This is the declaration of the Matcher class. #include "MatcherBase.h" namespace ThePEG { /** * Matcher is a templated class inheriting from MatcherBase. It is * used to conveniently create interfaced classes inheriting from * MatcherBase giving a class with a static T::Check() method as * template argument. * * @see MatcherBase * */ template class Matcher: public MatcherBase { public: /** @name Standard constructors and destructors. */ //@{ /** * Destructor. */ virtual ~Matcher(); //@} /** @name Special clone and create functions used by the Repository. */ //@{ /** * Create and clone Matcher objects. */ static PMPtr Create(const string & newName, string antiName); /** * Create and clone Matcher objects. */ virtual PMPtr pmclone() const; //@} 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; //@} /** @name Virtual and static versions of the check functions. */ //@{ /** * Virtual function overriding the one in MatcherBase. Simply calls * Check(). */ virtual bool check(const ParticleData & pd) const { return T::Check(pd); } /** * Static check function. Return true if a given particle type, \a * pd, is matched by this Matcher, ie. if the T::Check() function of * the template argument returns true. */ static bool Check(const ParticleData & pd) { return T::Check(pd); } //@} protected: /** * Set antipartner. */ static void setCC(tPMPtr pm, tPMPtr apm) { MatcherBase::setCC(pm,apm); } private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class without persistent data. */ static NoPIOClassDescription< Matcher > initMatcher; }; /** * MatcherType is an empty non-polymorphic base class for all matcher * classes to be used as template argument to Matcher. */ struct MatcherType {}; /** @cond TRAITSPECIALIZATIONS */ /** This partial template specialization informs ThePEG about the base * classes of Matcher. */ template struct BaseClassTrait,1>: public ClassTraitsType { /** Typedef of the first base class of Matcher. */ typedef MatcherBase NthBase; }; /** This partial template specialization informs ThePEG about the name * of the Matcher class. Note that the template argument class is * assumed to have a specialization of ClassTraits of its own.*/ template struct ClassTraits< Matcher >: public ClassTraitsBase< Matcher > { /** Return a platform-independent class name */ static string className() { return "ThePEG::Matcher<" + T::className() + ">"; } }; /** @endcond */ } #ifndef ThePEG_TEMPLATES_IN_CC_FILE #include "Matcher.tcc" #endif #endif /* ThePEG_Matcher_H */ diff --git a/PDT/Matcher.tcc b/PDT/Matcher.tcc --- a/PDT/Matcher.tcc +++ b/PDT/Matcher.tcc @@ -1,60 +1,60 @@ // -*- C++ -*- // // Matcher.tcc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined templated member // functions of the Matcher class. // namespace ThePEG { template Matcher::~Matcher() { if( !initMatcher.check() ) assert(false); } template NoPIOClassDescription< Matcher > Matcher::initMatcher; template PMPtr Matcher::Create(const string & newName, string antiName) { typedef typename Ptr< Matcher >::pointer MatcherPtr; typedef typename Ptr< Matcher >::pointer AMatcherPtr; PMPtr pm = new_ptr(); registerRepository(pm, newName); if ( typeid(T) == typeid(typename T::CC) ) return pm; if ( antiName.empty() ) antiName = newName + "~"; PMPtr apm = new_ptr(); setCC(pm, apm); registerRepository(apm, antiName); return pm; } template PMPtr Matcher::pmclone() const { return new_ptr(*this); } template IBPtr Matcher::clone() const { return pmclone(); } template IBPtr Matcher::fullclone() const { PMPtr pm = pmclone(); registerRepository(pm); if ( !CC() ) return pm; PMPtr apm = CC()->pmclone(); setCC(pm, apm); registerRepository(apm); return pm; } } diff --git a/PDT/MatcherBase.cc b/PDT/MatcherBase.cc --- a/PDT/MatcherBase.cc +++ b/PDT/MatcherBase.cc @@ -1,201 +1,201 @@ // -*- C++ -*- // // MatcherBase.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MatcherBase class. // #include "MatcherBase.h" #include "DecayMode.h" #include "ThePEG/Utilities/Rebinder.h" #include "ThePEG/Repository/Repository.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Utilities/EnumIO.h" #include "ThePEG/Interface/ClassDocumentation.h" using namespace ThePEG; MatcherBase::MatcherBase() : theMaxMass(ZERO), theMinMass(ZERO), commonMass(-1.0*GeV), commonWidth(-1.0*GeV), commonCTau(-1.0*mm), commonCharge(PDT::ChargeUndefined), commonSpin(PDT::SpinUndefined), commonColour(PDT::ColourUndefined), commonStable(-1) {} MatcherBase::MatcherBase(const MatcherBase & m) : Interfaced(m), theMaxMass(m.theMaxMass), theMinMass(m.theMinMass), commonMass(m.commonMass), commonWidth(m.commonWidth), commonCTau(m.commonCTau), commonCharge(m.commonCharge), commonSpin(m.commonSpin), commonColour(m.commonColour), commonStable(m.commonStable), theAntiPartner(m.theAntiPartner) {} MatcherBase::~MatcherBase() {} void MatcherBase::doupdate() { Interfaced::doupdate(); tPDSet oldParticles; tPMSet oldMatchers; Energy oldMass = commonMass; Energy oldWidth = commonWidth; Length oldCTau = commonCTau; PDT::Spin oldSpin = commonSpin; PDT::Charge oldCharge = commonCharge; PDT::Colour oldColour = commonColour; int oldStable = commonStable; matchingParticles.swap(oldParticles); matchingMatchers.swap(oldMatchers); if ( generator() ) { for ( ParticleMap::const_iterator it = generator()->particles().begin(); it != generator()->particles().end(); ++it ) addPIfMatch(it->second); addMIfMatchFrom(generator()->matchers()); } else { addPIfMatchFrom(Repository::allParticles()); addMIfMatchFrom(Repository::allMatchers()); } if ( matchingParticles != oldParticles || matchingMatchers != oldMatchers || oldMass != commonMass || oldWidth != commonWidth || oldCTau != commonCTau || oldSpin != commonSpin || oldCharge != commonCharge || oldColour != commonColour || oldStable != commonStable ) touch(); } void MatcherBase::clear() { matchingParticles.clear(); matchingMatchers.clear(); theMaxMass = ZERO; theMinMass = ZERO; commonMass = -1.0*GeV; commonWidth = -1.0*GeV; commonCTau = -1.0*mm; commonSpin = PDT::SpinUndefined; commonCharge = PDT::ChargeUndefined; commonColour = PDT::ColourUndefined; commonStable = -1; } void MatcherBase::addMIfMatch(tPMPtr pm) { if ( member(matchingMatchers, pm) ) return; pm->update(); tPDSet::const_iterator i = pm->matchingParticles.begin(); while ( i != pm->matchingParticles.end() ) if ( !member(matchingParticles, *i++) ) return; matchingMatchers.insert(pm); } void MatcherBase::addPIfMatch(tPDPtr pd) { if ( !pd || !check(*pd) || member(matchingParticles, pd) ) return; if ( matchingParticles.empty() ) { commonMass = pd->mass(); theMinMass = pd->mass(); theMaxMass = pd->mass(); commonWidth = pd->width(); commonCTau = pd->cTau(); commonCharge = pd->iCharge(); commonSpin = pd->iSpin(); commonColour = pd->iColour(); commonStable = pd->stable(); } else { if ( commonMass != pd->mass() ) commonMass = -1.0*GeV; theMinMass = min(theMinMass, pd->mass()); theMaxMass = min(theMaxMass, pd->mass()); if ( commonWidth != pd->width() ) commonWidth = -1.0*GeV; if ( commonCTau != pd->cTau() ) commonCTau = -1.0*mm; if ( commonCharge != pd->iCharge() ) { switch ( commonCharge ) { case PDT::ChargeUndefined: break; case PDT::Positive: if ( PDT::negative(pd->iCharge()) ) commonCharge = PDT::Charged; else if ( !PDT::positive(pd->iCharge()) ) commonCharge = PDT::ChargeUndefined; break; case PDT::Negative: if ( PDT::positive(pd->iCharge()) ) commonCharge = PDT::Charged; else if ( !PDT::negative(pd->iCharge()) ) commonCharge = PDT::ChargeUndefined; break; case PDT::Charged: if ( !PDT::charged(pd->iCharge()) ) commonCharge = PDT::ChargeUndefined; break; default: if ( PDT::positive(commonCharge) ) { if ( PDT::positive(pd->iCharge()) ) commonCharge = PDT::Positive; else if ( PDT::negative(pd->iCharge()) ) commonCharge = PDT::Charged; else commonCharge = PDT::ChargeUndefined; } else if ( PDT::negative(commonCharge) ) { if ( PDT::negative(pd->iCharge()) ) commonCharge = PDT::Negative; else if ( PDT::positive(pd->iCharge()) ) commonCharge = PDT::Charged; else commonCharge = PDT::ChargeUndefined; } else commonCharge = PDT::ChargeUndefined; } } if ( commonSpin != pd->iSpin() ) commonSpin = PDT::SpinUndefined; if ( commonColour != pd->iColour() ) { if ( PDT::coloured(commonColour) && PDT::coloured(pd->iColour()) ) commonColour = PDT::Coloured; else commonColour = PDT::ColourUndefined; if ( commonStable != pd->stable() ) commonStable = -1; } } matchingParticles.insert(pd); } struct ParticleOrdering { bool operator()(tcPDPtr p1, tcPDPtr p2) const { return abs(p1->id()) > abs(p2->id()) || ( abs(p1->id()) == abs(p2->id()) && p1->id() > p2->id() ) || ( p1->id() == p2->id() && p1->fullName() > p2->fullName() ); } }; struct MatcherOrdering { bool operator()(tcPMPtr m1, tcPMPtr m2) const { return m1->name() < m2->name() || ( m1->name() == m2->name() && m1->fullName() < m2->fullName() ); } }; void MatcherBase::persistentOutput(PersistentOStream & os ) const { multiset parts(particles().begin(), particles().end()); multiset match(matchers().begin(), matchers().end()); os << parts << match << ounit(theMaxMass, GeV) << ounit(theMinMass, GeV) << ounit(commonMass, GeV) << ounit(commonWidth, GeV) << ounit(commonCTau, mm) << oenum(commonCharge) << oenum(commonSpin) << oenum(commonColour) << commonStable << theAntiPartner; } void MatcherBase::persistentInput(PersistentIStream & is, int) { is >> matchingParticles >> matchingMatchers >> iunit(theMaxMass, GeV) >> iunit(theMinMass, GeV) >> iunit(commonMass, GeV) >> iunit(commonWidth, GeV) >> iunit(commonCTau, mm) >> ienum(commonCharge) >> ienum(commonSpin) >> ienum(commonColour) >> commonStable >> theAntiPartner; } AbstractClassDescription MatcherBase::initMatcherBase; void MatcherBase::Init() { static ClassDocumentation documentation ("This is the base class for objects representing groups of particle " "types."); } diff --git a/PDT/MatcherBase.h b/PDT/MatcherBase.h --- a/PDT/MatcherBase.h +++ b/PDT/MatcherBase.h @@ -1,420 +1,420 @@ // -*- C++ -*- // // MatcherBase.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_MatcherBase_H #define ThePEG_MatcherBase_H // This is the declaration of the MatcherBase class. #include "ParticleData.h" #include "ThePEG/EventRecord/Particle.h" namespace ThePEG { /** * MatcherBase is an abstract base class to be used for objects * representing groups of ParticleData objects. Concrete * implementations will typically use the templated Matcher class for * easy building of a full sub-class. * * @see ParticleData * @see Matcher * */ class MatcherBase: public Interfaced { public: /** Repository needs to be a friend. */ friend class Repository; /** * Convenient typedef. */ typedef set tPDSet; /** * Convenient typedef. */ typedef set tPMSet; public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ MatcherBase(); /** * Copy-constructor. */ MatcherBase(const MatcherBase &); /** * Destructor. */ virtual ~MatcherBase(); //@} public: /** @name Virtual functions to be overridden by sub-classes. */ //@{ /** * Check if a particle type meets the criteria. */ virtual bool check(const ParticleData &) const = 0; /** * Specialized clone method for MatcherBase used by the * Repository. A sub class must make sure that also the MatcherBase * object corresponding to the complex conjugate of this is cloned. */ virtual PMPtr pmclone() const = 0; //@} /** @name Check if something is matched. */ //@{ /** * Check if a Particle meets the criteria. */ bool checkp(const Particle & p) const { return check(p.data()); } /** * Check if a given particle type belongs to the set of * matches. This function looks for the same ParticleData object in * the set of all particles matched by this matcher. May be quicker * than to go through the check proceedure. */ bool matches(const ParticleData & pd) const { return member(matchingParticles, PDPtr(const_cast(&pd))); } /** * Check if a given particle belongs to the set of matches. This * function looks for the corresponding ParticleData object in the * set of all particles matched by this matcher. May be quicker than * to go through the check proceedure. */ bool matches(const Particle & p) const { return matches(p.data()); } /** * Check if a given particle matcher belongs to the set of * matches. This function looks for the same MatcherBase object in * the set of all matchers matched by this matcher. */ bool matches(const MatcherBase & pm) const { return member(matchingMatchers, PMPtr(const_cast(&pm))); } //@} /** @name Access the sets of matching particles and matchers. */ //@{ /** * Access to the set of matching particles. */ const tPDSet & particles() const { return matchingParticles; } /** * Access to the set of matching matchers. */ const tPMSet & matchers() const { return matchingMatchers; } //@} /** @name Access common properties of all matched particles. */ //@{ /** * Returns the minimum mass of the matching particles. */ Energy minMass() const { return theMinMass; } /** * Returns the maximum mass of the matching particles. */ Energy maxMass() const { return theMaxMass; } /** * Returns the common mass of the matching particles. If all matching * particles do not have exactly the same mass, -1.0 GeV is returned. */ Energy mass() const { return commonMass; } /** * Returns the common width of the matching particles. If all matching * particles do not have exactly the same width, -1.0 GeV is returned. */ Energy width() const { return commonWidth; } /** * Returns the common decay length of the matching particles. If all * matching particles do not have exactly the same decay length -1.0 * mm is returned. */ Length cTau() const { return commonCTau; } /** * Return common charge. If all matching particles have the same * charge the common charge is returned. Otherwise if all are * positive (negative), PDT::Positive (PDT::Negative) is * returned. Otherwise if all are charged, PDT::Charged is * returned. Otherwise PDT::ChargeUndefined is returned. */ PDT::Charge iCharge() const { return commonCharge; } /** * Are the particles charged? If all matching particles are charged, return * true, otherwise false. */ bool charged() const { return PDT::charged(commonCharge); } /** * Are the particles positively charged? If all matching particles * are positively charged, return true, otherwise false. */ bool positive() const { return PDT::positive(commonCharge); } /** * Are the particles negatively charged? If all matching particles * are negatively charged, return true, otherwise false. */ bool negative() const { return PDT::negative(commonCharge); } /** * Return common spin. If all matching particles have the same spin, * the common spin is returned. Otherwise PDT::SpinUndefined is * returned. */ PDT::Spin iSpin() const { return commonSpin; } /** * If all matching particles have the same colour, the common colour * is returned. Otherwise if all are coloured, PDT::Coloured is * returned. Otherwise PDT::ColourUndefined is returned. */ PDT::Colour iColour() const { return commonColour; } /** * Are the particles coloured? If all matching particles are * coloured, return true, otherwise false. */ bool coloured() const { return PDT::coloured(commonColour); } /** * Are the particles stable? Returns (0)1 if all matching particles * are (un)stable. Otherwise -1 is returned. */ int stable() const { return commonStable; } //@} /** * Get the matcher object matching the antiparticles of this. If * no-one exists null is returned. */ tPMPtr CC() const { return theAntiPartner; } public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interface. */ static void Init(); protected: /** @name Standard Interfaced functions. */ //@{ /** * Check sanity of the object during the setup phase. */ virtual void doupdate(); //@} protected: /** * Add a particle to the set of matching particles if it meets the * criteria. */ void addPIfMatch(tPDPtr); /** * Add a particle matcher to the set of matching matchers if it * meets the criteria. */ void addMIfMatch(tPMPtr); /** * Add a number of particles to the set of matching particles if * they meets the criteria. */ template void addPIfMatch(Iterator first, Iterator last) { for ( ; first != last; ++first ) addPIfMatch(*first); } /** * Add a number of particles to the set of matching particles if * they meets the criteria. */ template void addPIfMatchFrom(const Cont & c) { addPIfMatch(c.begin(), c.end()); } /** * Add a number of particle matchers to the set of matching * matchers if they meets the criteria. */ template void addMIfMatch(Iterator first, Iterator last) { for ( ; first != last; ++first ) addMIfMatch(*first); } /** * Add a number of particle matchers to the set of matching * matchers if they meets the criteria. */ template void addMIfMatchFrom(const Cont & c) { addMIfMatch(c.begin(), c.end()); } /** * Clear information about matching particles and matchers. */ void clear(); /** * Set antipartner. */ static void setCC(tPMPtr pm, tPMPtr apm) { pm->theAntiPartner = apm; apm->theAntiPartner = pm; } private: /** * The set of particle data objects matched by this matcher. */ tPDSet matchingParticles; /** * A set of matchers which matches a subset of this matcher. */ tPMSet matchingMatchers; /** * The maximum mass of all matching particles. */ Energy theMaxMass; /** * The minimum mass of all matching particles. */ Energy theMinMass; /** * The common mass of all matching particles. */ Energy commonMass; /** * The common width of all matching particles. */ Energy commonWidth; /** * The common decay length of all matching particles. */ Length commonCTau; /** * The common charge of all matching particles. */ PDT::Charge commonCharge; /** * The common spin of all matching particles. */ PDT::Spin commonSpin; /** * The common colour of all matching particles. */ PDT::Colour commonColour; /** * The common stability of all matching particles. */ int commonStable; /** * Pointer to a matcher object which matches all anti particles * which are matched by this matcher. */ tPMPtr theAntiPartner; private: /** * The static object used to initialize the description of this class. * Indicates that this is an abstract class with persistent data. */ static AbstractClassDescription initMatcherBase; /** * Private and non-existent assignment operator. */ MatcherBase & operator=(const MatcherBase &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the base classes * of MatcherBase. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of MatcherBase. */ typedef Interfaced NthBase; }; /** This template specialization informs ThePEG about the name of the * MatcherBase class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "ThePEG::MatcherBase"; } }; /** @endcond */ } #endif /* ThePEG_MatcherBase_H */ diff --git a/PDT/OmegaPhi3PiDecayer.cc b/PDT/OmegaPhi3PiDecayer.cc --- a/PDT/OmegaPhi3PiDecayer.cc +++ b/PDT/OmegaPhi3PiDecayer.cc @@ -1,94 +1,94 @@ // -*- C++ -*- // // OmegaPhi3PiDecayer.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the OmegaPhi3PiDecayer class. // #include "OmegaPhi3PiDecayer.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/PDT/DecayMode.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG; IBPtr OmegaPhi3PiDecayer::clone() const { return new_ptr(*this); } IBPtr OmegaPhi3PiDecayer::fullclone() const { return new_ptr(*this); } bool OmegaPhi3PiDecayer::accept(const DecayMode & dm) const { if ( dm.products().size() != 3 || !dm.cascadeProducts().empty() || !dm.productMatchers().empty() || dm.wildProductMatcher() ) return false; bool foundp = false, foundm = false, found0 = false; for ( ParticleMSet::const_iterator pit = dm.products().begin(); pit != dm.products().end(); ++pit ) { if ( (**pit).id() == ParticleID::piplus ) foundp = true; else if ( (**pit).id() == ParticleID::piminus ) foundm = true; else if ( (**pit).id() == ParticleID::pi0 ) found0 = true; } return foundp && foundm && found0; } double OmegaPhi3PiDecayer::reweight(const DecayMode &, const Particle & parent, const ParticleVector & children) const { Energy2 m2 = parent.momentum().mass2(); Lorentz5Momentum pp; Lorentz5Momentum pm; Lorentz5Momentum p0; for ( int i = 0, N = children.size(); i < N; ++i ) { if ( children[i]->id() == ParticleID::piplus ) pp = children[i]->momentum(); else if ( children[i]->id() == ParticleID::piminus ) pm = children[i]->momentum(); else if ( children[i]->id() == ParticleID::pi0 ) p0 = children[i]->momentum(); } return (pp.mass2()*pm.mass2()*p0.mass2() + 2.0*(pp*pm)*(pp*p0)*(pm*p0) - pp.mass2()*sqr(pm*p0) - pm.mass2()*sqr(pp*p0) - p0.mass2()*sqr(pp*pm))*margin/(m2*m2*m2); } void OmegaPhi3PiDecayer::persistentOutput(PersistentOStream & os) const { os << margin; } void OmegaPhi3PiDecayer::persistentInput(PersistentIStream & is, int) { is >> margin; } ClassDescription OmegaPhi3PiDecayer::initOmegaPhi3PiDecayer; // Definition of the static class description member. void OmegaPhi3PiDecayer::Init() { static ClassDocumentation documentation ("This class performs the decay of a phi or an omega into pi+ pi- " "p0. It will in fact decay anything into pi+ pi- p0 assuming the " "same matrix element."); static Parameter interfaceMargin ("Margin", "Used to multiply the bare weight to get something below unity. " "In the Fortran pythia version it was set to 150 for unknown reasons.", &OmegaPhi3PiDecayer::margin, 150.0, 0.0, 1000.0, true, false, true); } diff --git a/PDT/OmegaPhi3PiDecayer.h b/PDT/OmegaPhi3PiDecayer.h --- a/PDT/OmegaPhi3PiDecayer.h +++ b/PDT/OmegaPhi3PiDecayer.h @@ -1,168 +1,168 @@ // -*- C++ -*- // // OmegaPhi3PiDecayer.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_OmegaPhi3PiDecayer_H #define THEPEG_OmegaPhi3PiDecayer_H // This is the declaration of the OmegaPhi3PiDecayer class. #include "ThePEG/PDT/FlatDecayer.h" namespace ThePEG { /** * The OmegaPhi3PiDecayer class inherits from performs FlatDecayer and * will reweight the flat phase space suitable to describe the decay * of a \f$\phi\f$ or an \f$\omega\f$ into \f$\pi^+\pi^-\pi^0\f$. It * will in fact decay anything into \f$\pi^+\pi^-\pi^0\f$ assuming the * same matrix element. * * @see \ref OmegaPhi3PiDecayerInterfaces "The interfaces" * defined for OmegaPhi3PiDecayer. * @see FlatDecayer * @see ParticleData */ class OmegaPhi3PiDecayer: public FlatDecayer { public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ OmegaPhi3PiDecayer() : margin(150.0) {} //@} public: /** @name Virtual functions required by the Decayer class. */ //@{ /** * Check if this decayer can perfom the decay specified by the * given decay mode. * @param dm the DecayMode describing the decay. * @return true if this decayer can handle the given mode, otherwise false. */ virtual bool accept(const DecayMode & dm) const; /** * Give a weight to a phase space point. To be overridden by * subclasses. For a given decay mode, \a dm, decaying \a parent * particle and decayproducts, \a children, distributed according to * a flat distribution in phase space, return a weight (less or * equal to unity) modifying the flat distribution to the desired * one. Note that the chosen phase space point may be rejected, but * the chosen decay channel will not. This means that the weight * returned by this function does not influence the branching * ratios. */ virtual double reweight(const DecayMode & dm, const Particle & parent, const ParticleVector & children) const; //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interfaces. */ static void Init(); protected: protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * Used to multiply the bare weight to get something below unity. In * the Fortran pythia version it was set to 150 for unknown reasons. */ double margin; private: /** * Describe a concrete class with persistent data. */ static ClassDescription initOmegaPhi3PiDecayer; /** * Private and non-existent assignment operator. */ OmegaPhi3PiDecayer & operator=(const OmegaPhi3PiDecayer &) = delete; }; } namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the base classes * of OmegaPhi3PiDecayer. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of OmegaPhi3PiDecayer. */ typedef FlatDecayer NthBase; }; /** This template specialization informs ThePEG about the name of the * OmegaPhi3PiDecayer 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::OmegaPhi3PiDecayer"; } /** Return the name of the shared library be loaded to get access to * the OmegaPhi3PiDecayer class and every other class it uses * (except the base class). */ static string library() { return "OmegaPhi3PiDecayer.so"; } }; /** @endcond */ } #endif /* THEPEG_OmegaPhi3PiDecayer_H */ diff --git a/PDT/Onium3GDecayer.cc b/PDT/Onium3GDecayer.cc --- a/PDT/Onium3GDecayer.cc +++ b/PDT/Onium3GDecayer.cc @@ -1,134 +1,134 @@ // -*- C++ -*- // // Onium3GDecayer.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the Onium3GDecayer class. // #include "Onium3GDecayer.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/PDT/DecayMode.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/PDT/StandardMatchers.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Handlers/HandlerGroup.h" #include "ThePEG/Handlers/Hint.h" #include "ThePEG/Handlers/EventHandler.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG; Onium3GDecayer::~Onium3GDecayer() {} IBPtr Onium3GDecayer::clone() const { return new_ptr(*this); } IBPtr Onium3GDecayer::fullclone() const { return new_ptr(*this); } bool Onium3GDecayer::accept(const DecayMode & dm) const { if ( dm.products().size() != 3 || !dm.cascadeProducts().empty() || !dm.productMatchers().empty() || dm.wildProductMatcher() ) return false; if ( !VectorMesonMatcher::Check(*dm.parent()) ) return false; vector flv = PDT::flavourContent(*dm.parent()); if ( abs(flv[0]) < 4 || flv[0] + flv[1] != 0 ) return false; int ng = 0; int np = 0; for ( int i = 0; i < 3; ++i ) if ( dm.orderedProducts()[i]->id() == ParticleID::g ) ++ng; else if ( dm.orderedProducts()[i]->id() == ParticleID::gamma ) ++np; if ( ng < 2 || ng + np != 3 ) return false; return true; } ParticleVector Onium3GDecayer::decay(const DecayMode & dm, const Particle & parent) const { PVector children = FlatDecayer::decay(dm, parent); PVector gluons; for ( int i = 0, N = children.size(); i < N; ++i ) { children[i]->scale(sqr(parent.mass())); if ( children[i]->id() == ParticleID::g ) gluons.push_back(children[i]); } for ( int i = 0, N = gluons.size(); i < N; ++i ) gluons[i]->colourNeighbour(gluons[(i + 1)%N]); HintPtr h = ptr_new(); h->tag(children.begin(), children.end()); using namespace Group; generator()->currentEventHandler()-> addStep(main, shower()? cascade: hadron, tStepHdlPtr(), h); return children; } double Onium3GDecayer::reweight(const DecayMode &, const Particle & parent, const ParticleVector & ch) const { vector x(3); Energy2 m2 = parent.momentum().mass2(); x[0] = 2.0*ch[1]->momentum()*ch[2]->momentum()/m2; x[1] = 2.0*ch[2]->momentum()*ch[0]->momentum()/m2; x[2] = 2.0*ch[0]->momentum()*ch[1]->momentum()/m2; for ( int i = 0; i < 3; ++i ) if ( ch[i]->id() == ParticleID::gamma && (1.0 - x[i])*m2 < sqr(minGGMass()) ) return 0.0; return 0.5*(sqr((1.0 - x[0])/(x[1]*x[2])) + sqr((1.0 - x[1])/(x[2]*x[0])) + sqr((1.0 - x[2])/(x[0]*x[1]))); } void Onium3GDecayer::persistentOutput(PersistentOStream & os) const { os << doShower << ounit(theMinGGMass,GeV); } void Onium3GDecayer::persistentInput(PersistentIStream & is, int) { is >> doShower >> iunit(theMinGGMass,GeV); } ClassDescription Onium3GDecayer::initOnium3GDecayer; // Definition of the static class description member. void Onium3GDecayer::Init() { static ClassDocumentation documentation ("This class performs the decay of a spin-1 onium resonance into " "three gluons or two gluons and a photon. After the decay the " "collision handler is instructed to restart the generation from the " "hadronization (or optionally the parton cascade) stage."); static Switch interfaceShower ("Shower", "Should the produced gluons be showered or only hadronized?", &Onium3GDecayer::doShower, true, true, false); static SwitchOption interfaceShowerYes (interfaceShower, "Yes", "The produced gluons should be showered before hadronization.", true); static SwitchOption interfaceShowerNo (interfaceShower, "No", "The produced gluons should be hadronized whithout preceeding shower.", false); static Parameter interfaceMinGGMass ("MinGGMass", "The minimum invariant mass of the two gluons allowed in gamma-g-g " "decays.", &Onium3GDecayer::theMinGGMass, GeV, 2.0*GeV, ZERO, 10.0*GeV, true, false, true); interfaceShower.rank(10); } diff --git a/PDT/Onium3GDecayer.h b/PDT/Onium3GDecayer.h --- a/PDT/Onium3GDecayer.h +++ b/PDT/Onium3GDecayer.h @@ -1,195 +1,195 @@ // -*- C++ -*- // // Onium3GDecayer.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_Onium3GDecayer_H #define THEPEG_Onium3GDecayer_H // This is the declaration of the Onium3GDecayer class. #include "ThePEG/PDT/FlatDecayer.h" namespace ThePEG { /** * The Onium3GDecayer class inherits from performs FlatDecayer and * will reweight the flat phase space suitable to describe the decay * of a spin-1 onium resonance into three gluons or two gluons and a * photon. After the decay the collision handler is instructed to * restart the generation from the hadronization (or optionally the * parton cascade) stage. * * @see \ref Onium3GDecayerInterfaces "The interfaces" * defined for Onium3GDecayer. * @see FlatDecayer * @see ParticleData */ class Onium3GDecayer: public FlatDecayer { public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ Onium3GDecayer() : doShower(true), theMinGGMass(2.0*GeV) {} /** * Destructor. */ virtual ~Onium3GDecayer(); //@} public: /** @name Virtual functions required by the Decayer class. */ //@{ /** * Check if this decayer can perfom the decay specified by the * given decay mode. * @param dm the DecayMode describing the decay. * @return true if this decayer can handle the given mode, otherwise false. */ virtual bool accept(const DecayMode & dm) const; /** * Perform a decay for a given DecayMode and a given Particle instance. * @param dm the DecayMode describing the decay. * @param p the Particle instance to be decayed. * @return a ParticleVector containing the decay products. */ virtual ParticleVector decay(const DecayMode & dm, const Particle & p) const; /** * Give a weight to a phase space point. To be overridden by * subclasses. For a given decay mode, \a dm, decaying \a parent * particle and decayproducts, \a children, distributed according to * a flat distribution in phase space, return a weight (less or * equal to unity) modifying the flat distribution to the desired * one. Note that the chosen phase space point may be rejected, but * the chosen decay channel will not. This means that the weight * returned by this function does not influence the branching * ratios. */ virtual double reweight(const DecayMode & dm, const Particle & parent, const ParticleVector & children) const; //@} /** * Return true if the produced gluons should be showered. */ bool shower() const { return doShower; } /** * Return the minimum invariant mass between two gluons in gamma-g-g * decays. */ Energy minGGMass() const { return theMinGGMass; } 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(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * If true the produced gluons should be showered. */ bool doShower; /** * The minimum invariant mass between two gluons in gamma-g-g * decays. */ Energy theMinGGMass; private: /** * Describe a concrete class with persistent data. */ static ClassDescription initOnium3GDecayer; /** * Private and non-existent assignment operator. */ Onium3GDecayer & operator=(const Onium3GDecayer &) = delete; }; } namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the base classes * of Onium3GDecayer. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of Onium3GDecayer. */ typedef FlatDecayer NthBase; }; /** This template specialization informs ThePEG about the name of the * Onium3GDecayer 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::Onium3GDecayer"; } /** Return the name of the shared library be loaded to get access to * the Onium3GDecayer class and every other class it uses * (except the base class). */ static string library() { return "Onium3GDecayer.so"; } }; /** @endcond */ } #endif /* THEPEG_Onium3GDecayer_H */ diff --git a/PDT/PDT.cc b/PDT/PDT.cc --- a/PDT/PDT.cc +++ b/PDT/PDT.cc @@ -1,69 +1,69 @@ // -*- C++ -*- // // PDT.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the PDT class. // #include "PDT.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/PDT/StandardMatchers.h" #include "ThePEG/EventRecord/Particle.h" using namespace ThePEG; vector PDT::flavourContent(long id) { vector ret; if ( id == ParticleID::K_L0 || id == ParticleID::K_S0 ) { ret.push_back(ParticleID::s); ret.push_back(ParticleID::d); } else if ( MesonMatcher::Check(id) ) { ret.push_back((id/100)%10); ret.push_back(-(id/10)%10); } else if ( BaryonMatcher::Check(id) ) { ret.push_back((id/1000)%10); long iqb = (id/100)%10; long iqc = (id/10)%10; if ( abs(iqb) < abs(iqc) ) { ret.push_back(iqc); ret.push_back(iqb); } else { ret.push_back(iqb); ret.push_back(iqc); } } else if ( DiquarkMatcher::Check(id) ) { ret.push_back((id/1000)%10); ret.push_back((id/100)%10); } else if ( abs(id) < 10 ) { ret.push_back(id); } return ret; } vector PDT::flavourContent(tcPDPtr p) { return flavourContent(p->id()); } vector PDT::flavourContent(tcPPtr p) { return flavourContent(p->id()); } vector PDT::flavourContent(const ParticleData & p) { return flavourContent(p.id()); } vector PDT::flavourContent(const Particle & p) { return flavourContent(p.id()); } diff --git a/PDT/PDT.h b/PDT/PDT.h --- a/PDT/PDT.h +++ b/PDT/PDT.h @@ -1,244 +1,244 @@ // -*- C++ -*- // // PDT.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_PDT_H #define ThePEG_PDT_H // This is the declaration of the PDT class. #include "ThePEG/Config/ThePEG.h" namespace ThePEG { /** * PDT is a helper class implementing enumerations for charge, colour * and spin to be used by the ParticleData class. In addition, some * static utility functions are provided. * * @see ParticleData */ class PDT { public: /** * Definition of enumerated values used for spin information. THe * integer values are given according to 2s+1. */ enum Spin { SpinNA = -1, /**< Spin is not applicable. */ SpinUnknown = 0, /**< Unknown spin */ SpinUndefined = 0, /**< Undefined spin */ Spin0 = 1, /**< Spin zero. */ Spin1Half = 2, /**< Spin 1/2. */ Spin1 = 3, /**< Spin 1. */ Spin3Half = 4, /**< Spin 3/2. */ Spin2 = 5, /**< Spin 2. */ Spin5Half = 6, /**< Spin 5/2. */ Spin3 = 7, /**< Spin 4. */ Spin7Half = 8, /**< Spin 7/2. */ Spin4 = 9 /**< Spin 5. */ }; /** * Definition of enumerated values used for charge information. The * integer values are given in units of e/3. */ enum Charge { ChargeUnknown = -999999, /**< Unknown charge. */ ChargeUndefined = -999999, /**< Undefined charge. */ Charged = 999990, /**< Is charged. */ Positive = 900000, /**< Is positively charged. */ Negative = -900000, /**< Is negatively charged. */ ChargeNeutral = 0, /**< Uncharged. */ Charge0 = 0, /**< Uncharged. */ Plus1Third = 1, /**< e/3. */ Plus2Third = 2, /**< 2e/3. */ Plus1 = 3, /**< e. */ Minus1Third = -1, /**< -e/3. */ Minus2Third = -2, /**< -2e/3. */ Minus1 = -3, /**< -e. */ Plus4Third = 4, /**< 4e/3. */ Plus5Third = 5, /**< 5e/3. */ Plus2 = 6, /**< 2e. */ Minus4Third = -4, /**< -4e/3. */ Minus5Third = -5, /**< -5e/3. */ Minus2 = -6, /**< -3e. */ Plus7Third = 7, /**< 7e/3. */ Plus8Third = 8, /**< 8e/3. */ Plus3 = 9, /**< 3e. */ Minus7Third = -7, /**< -7e/3. */ Minus8Third = -8, /**< -8e/3. */ Minus3 = -9, /**< -3e. */ Plus4 = 12, /**< 4e. */ Plus5 = 15, /**< 5e. */ Plus6 = 18, /**< 6e. */ Plus7 = 21, /**< 7e. */ Plus8 = 24, /**< 8e. */ Minus4 = -12, /**< -4e. */ Minus5 = -15, /**< -5e. */ Minus6 = -18, /**< -6e. */ Minus7 = -21, /**< -7e. */ Minus8 = -24 /**< -8e. */ }; /** *Definition of enumerated values used for colour information. */ enum Colour { ColourUnknown = -1, /**< Unknown colour */ ColourUndefined = -1, /**< Undefined colour */ ColourNeutral = 0, /**< Colour-singlet */ Colour0 = 0, /**< Colour-singlet */ Coloured = 1, /**< Coloured */ Colour3 = 3, /**< Colour-triplet */ Colour3bar = -3, /**< Colour-anti-triplet */ Colour6 = 6, /**< Colour-sextet */ Colour6bar = -6, /**< Colour-anti-sextet */ Colour8 = 8 /**< Colour-octet */ }; /** * True if the argument corresponds to a non-zero charge. */ static bool charged(Charge c) { return c != ChargeNeutral && c != ChargeUndefined; } /** * True if the argument corresponds to a positive charge. */ static bool positive(Charge c) { return c > ChargeNeutral && c != Charged; } /** * True if the argument corresponds to a negative charge. */ static bool negative(Charge c) { return c < ChargeNeutral && c != ChargeUndefined; } /** * True if the argument corresponds to a non-zero colour charge. */ static bool coloured(Colour c) { return c != ColourNeutral && c != ColourUnknown; } /** * Return the anti-colour of the specified colour. */ static Colour antiColour(Colour c) { if ( c == Colour3 || c == Colour3bar ) return Colour(-c); if ( c == Colour6 || c == Colour6bar ) return Colour(-c); return c; } /** * Return the flavour content of the given particle. The flavours * will be given in decreasing mass with flavour before * anti-flavour. */ static vector flavourContent(long id); /** * Return the flavour content of the given particle. The flavours * will be given in decreasing mass with flavour before * anti-flavour. */ static vector flavourContent(tcPDPtr); /** * Return the flavour content of the given particle. The flavours * will be given in decreasing mass with flavour before * anti-flavour. */ static vector flavourContent(tcPPtr); /** * Return the flavour content of the given particle. The flavours * will be given in decreasing mass with flavour before * anti-flavour. */ static vector flavourContent(const ParticleData &); /** * Return the flavour content of the given particle. The flavours * will be given in decreasing mass with flavour before * anti-flavour. */ static vector flavourContent(const Particle &); }; /** Input a colour from a stream. */ template IStream & operator>>(IStream & is, PDT::Colour & c) { int ci; is >> ci; c = PDT::Colour(ci); return is; } /** Input a charge from a stream. */ template IStream & operator>>(IStream & is, PDT::Charge & c) { int ci; is >> ci; c = PDT::Charge(ci); return is; } /** Input a spin from a stream. */ template IStream & operator>>(IStream & is, PDT::Spin & s) { int si; is >> si; s = PDT::Spin(si); return is; } /// Type traits for built-in types template <> struct TypeTraits { /** Enum for dimensions*/ enum { hasDimension = false }; /// Type switch set to standard type. typedef EnumT DimType; /// Base unit static constexpr PDT::Spin baseunit() { return PDT::Spin(1); } }; /// Type traits for built-in types template <> struct TypeTraits { /** Enum for dimensions*/ enum { hasDimension = false }; /// Type switch set to standard type. typedef EnumT DimType; /// Base unit static constexpr PDT::Charge baseunit() { return PDT::Charge(1); } }; /// Type traits for built-in types template <> struct TypeTraits { /** Enum for dimensions*/ enum { hasDimension = false }; /// Type switch set to standard type. typedef EnumT DimType; /// Base unit static constexpr PDT::Colour baseunit() { return PDT::Colour(3); } }; } #endif /* ThePEG_PDT_H */ diff --git a/PDT/PID.h b/PDT/PID.h --- a/PDT/PID.h +++ b/PDT/PID.h @@ -1,76 +1,76 @@ // -*- C++ -*- // // PID.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_PID_H #define ThePEG_PID_H #include "EnumParticles.h" namespace ThePEG { /** * PID is a helper class implementing the type of PDG particle ids. At * the moment it just converts to a long, and other conversions are * intercepted. * * @see ParticleData */ class PID { public: /** * Generic construction is disallowed. */ template PID(T t) { t.ERROR_only_use_long_as_Particle_ID_type(); } /** * Casting to generic types is disallowed. */ template operator T() const { T t; t.ERROR_only_use_long_as_Particle_ID_type(); return t; } /** * The negation operator */ PID operator-() const; private: /** * The particle id. */ long id; }; /// Specialized constructor for 'long' template <> inline PID::PID(long t) : id(t) {} /// Specialized constructor for 'int' template <> inline PID::PID(int t) : id(t) {} /// Specialized constructor for Particle Code enum template <> inline PID::PID(ParticleID::ParticleCodes t) : id(t) {} /// Specialized cast for 'long' template <> inline PID::operator long() const { return id; } /** * The negation operator */ inline PID PID::operator-() const { return -id; } } #endif /* ThePEG_PID_H */ diff --git a/PDT/ParticleData.cc b/PDT/ParticleData.cc --- a/PDT/ParticleData.cc +++ b/PDT/ParticleData.cc @@ -1,1038 +1,1038 @@ // -*- C++ -*- // // ParticleData.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the ParticleData class. // #include "ParticleData.h" #include "ParticleData.xh" #include "ThePEG/PDT/DecayMode.h" #include "ThePEG/Utilities/HoldFlag.h" #include "ThePEG/Utilities/Rebinder.h" #include "ThePEG/Utilities/StringUtils.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/Interface/Command.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Repository/Repository.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Config/algorithm.h" #include "ThePEG/Utilities/Exception.h" #include "ThePEG/Utilities/EnumIO.h" #include "ThePEG/Repository/UseRandom.h" namespace ThePEG { ParticleData::ParticleData() : theId(0), thePDGName(""), theMass(-1.0*GeV), theWidth(-1.0*GeV), theHardProcessMass(-1.0*GeV), hardProcessMassSet(false), theHardProcessWidth(-1.0*GeV), hardProcessWidthSet(false), theWidthUpCut(-1.0*GeV), theWidthLoCut(-1.0*GeV), theCTau(-1.0*mm), theCharge(PDT::ChargeUnknown), theSpin(PDT::SpinUnknown), theColour(PDT::ColourUnknown), isStable(true), theVariableRatio(false), syncAnti(false), theDefMass(-1.0*GeV), theDefWidth(-1.0*GeV), theDefCut(-1.0*GeV), theDefCTau(-1.0*mm), theDefCharge(PDT::ChargeUnknown), theDefSpin(PDT::SpinUnknown), theDefColour(PDT::ColourUnknown) {} ParticleData:: ParticleData(PID newId, const string & newPDGName) : theId(newId), thePDGName(newPDGName), theMass(-1.0*GeV), theWidth(-1.0*GeV), theHardProcessMass(-1.0*GeV), hardProcessMassSet(false), theHardProcessWidth(-1.0*GeV), hardProcessWidthSet(false), theWidthUpCut(-1.0*GeV), theWidthLoCut(-1.0*GeV), theCTau(-1.0*mm), theCharge(PDT::ChargeUnknown), theSpin(PDT::SpinUnknown), theColour(PDT::ColourUnknown), isStable(true), theVariableRatio(false), syncAnti(false), theDefMass(-1.0*GeV), theDefWidth(-1.0*GeV), theDefCut(-1.0*GeV), theDefCTau(-1.0*mm), theDefCharge(PDT::ChargeUnknown), theDefSpin(PDT::SpinUnknown), theDefColour(PDT::ColourUnknown) {} ParticleData::~ParticleData() {} PDPtr ParticleData::Create(PID newId, const string & newPDGName) { return new_ptr(ParticleData(newId, newPDGName)); } PDPair ParticleData:: Create(PID newId, const string & newPDGName, const string & newAntiPDGName) { PDPair pap; pap.first = new_ptr(ParticleData(newId, newPDGName)); pap.second = new_ptr(ParticleData(-newId, newAntiPDGName)); antiSetup(pap); return pap; } void ParticleData::readSetup(istream & is) { long id; is >> id >> thePDGName >> iunit(theDefMass, GeV) >> iunit(theDefWidth, GeV) >> iunit(theDefCut, GeV) >> iunit(theDefCTau, mm) >> ienum(theDefCharge) >> ienum(theDefColour) >> ienum(theDefSpin) >> ienum(isStable); theId = id; theMass = theDefMass; theWidth = theDefWidth; theWidthUpCut = theDefCut; theWidthLoCut = theDefCut; theCTau = theDefCTau; theCharge = theDefCharge; theColour = theDefColour; theSpin = theDefSpin; if ( PDGName() == "-" ) thePDGName = name(); return; } void ParticleData::antiSetup(const PDPair & pap) { pap.first->theAntiPartner = pap.second; pap.second->theAntiPartner = pap.first; pap.first->syncAnti = pap.second->syncAnti = true; } PDPtr ParticleData::pdclone() const { return new_ptr(*this); } IBPtr ParticleData::clone() const { return pdclone(); } IBPtr ParticleData::fullclone() const { PDPtr pd = pdclone(); Repository::Register(pd); pd->theDecaySelector.clear(); pd->theDecayModes.clear(); pd->isStable = true; PDPtr apd; if ( CC() ) { apd = CC()->pdclone(); Repository::Register(apd); apd->theDecaySelector.clear(); apd->theDecayModes.clear(); apd->isStable = true; pd->theAntiPartner = apd; apd->theAntiPartner = pd; pd->syncAnti = syncAnti; apd->syncAnti = CC()->syncAnti; } HoldFlag<> dosync(pd->syncAnti, true); for ( DecaySet::const_iterator it = theDecayModes.begin(); it != theDecayModes.end(); ++it ) pd->addDecayMode(*it); return pd; } Energy ParticleData::mass(Energy mi) { theMass = mi; if ( synchronized() && CC() ) CC()->theMass = theMass; return theMass; } Energy ParticleData::width(Energy wi) { theWidth = wi; if ( synchronized() && CC() ) CC()->theWidth = theWidth; return theWidth; } Energy ParticleData::widthUpCut(Energy wci) { theWidthUpCut = wci; if ( synchronized() && CC() ) CC()->theWidthUpCut = theWidthUpCut; return theWidthUpCut; } Energy ParticleData::widthLoCut(Energy wci) { theWidthLoCut = wci; if ( synchronized() && CC() ) CC()->theWidthLoCut = theWidthLoCut; return theWidthLoCut; } Length ParticleData::cTau(Length ti) { theCTau = ti; if ( synchronized() && CC() ) CC()->theCTau = theCTau; return theCTau; } PDT::Charge ParticleData::iCharge(PDT::Charge ci) { theCharge = ci; if ( synchronized() && CC() ) CC()->theCharge = PDT::Charge(-ci); return theCharge; } PDT::Spin ParticleData::iSpin(PDT::Spin si) { theSpin = si; if ( synchronized() && CC() ) CC()->theSpin = si; return si; } PDT::Colour ParticleData::iColour(PDT::Colour ci) { theColour = ci; if ( synchronized() && CC() ) CC()->theColour = PDT::Colour(-ci); return theColour; } void ParticleData::stable(bool s) { isStable = s; if ( synchronized() && CC() ) CC()->isStable = s; } void ParticleData::synchronized(bool h) { syncAnti = h; if ( CC() ) CC()->syncAnti = h; } void ParticleData::variableRatio(bool varRatio) { theVariableRatio=varRatio; } void ParticleData::addDecayMode(tDMPtr dm) { if ( member(theDecayModes, dm) ) return; cPDPtr parent = dm->parent(); if ( !parent ) parent = this; if ( parent != this ) { dm = dm->clone(this); } theDecayModes.insert(dm); theDecaySelector.insert(dm->brat(), dm); if ( CC() ) { if ( !synchronized() ) dm->CC()->switchOff(); CC()->theDecayModes.insert(dm->CC()); CC()->theDecaySelector.insert(dm->CC()->brat(), dm->CC()); } } void ParticleData::removeDecayMode(tDMPtr dm) { theDecayModes.erase(theDecayModes.find(dm)); if(theDecayModes.empty()) isStable = true; theDecaySelector.erase(dm); if ( !CC() ) return; CC()->theDecayModes.erase(dm->CC()); if(CC()->theDecayModes.empty()) CC()->isStable = true; CC()->theDecaySelector.erase(dm->CC()); } void ParticleData::synchronize() { if ( !CC() ) return; isStable = CC()->isStable; theMass = CC()->theMass; theHardProcessMass = CC()->theHardProcessMass; hardProcessMassSet = CC()->hardProcessMassSet; theWidth = CC()->theWidth; theHardProcessWidth = CC()->theHardProcessWidth; hardProcessWidthSet = CC()->hardProcessWidthSet; theWidthUpCut = CC()->theWidthUpCut; theWidthLoCut = CC()->theWidthLoCut; theCTau = CC()->theCTau; theCharge = PDT::Charge(-CC()->theCharge); theSpin = CC()->theSpin; theColour = PDT::antiColour(CC()->theColour); theMassGenerator = CC()->theMassGenerator; theWidthGenerator = CC()->theWidthGenerator; syncAnti = CC()->syncAnti; theDecaySelector.clear(); for ( DecaySet::iterator it = theDecayModes.begin(); it != theDecayModes.end(); ++it ) { (*it)->synchronize(); theDecaySelector.insert((*it)->brat(), *it); } } void ParticleData::doupdate() { Interfaced::doupdate(); bool redo = touched(); for_each(theDecayModes, UpdateChecker(redo)); UpdateChecker::check(theMassGenerator, redo); UpdateChecker::check(theWidthGenerator, redo); if ( !redo ) return; theDecaySelector.clear(); for ( DecaySet::const_iterator dit = theDecayModes.begin(); dit != theDecayModes.end(); ++dit ) { tDMPtr dm = *dit; dm->resetOverlap(); for ( DecaySet::const_iterator dit2 = theDecayModes.begin(); dit2 != theDecayModes.end(); ++dit2 ) if ( dit2 != dit ) dm->addOverlap(dm); if ( dm->brat() > 0.0 ) theDecaySelector.insert(dm->brat(), dm); } if ( theMassGenerator && !theMassGenerator->accept(*this) ) throw UpdateException(); if ( theWidthGenerator && !theWidthGenerator->accept(*this) ) throw UpdateException(); if ( theWidthGenerator ) theDecaySelector = theWidthGenerator->rate(*this); touch(); } tDMPtr ParticleData::selectMode(Particle & p) const { if ( &(p.data()) != this ) return tDMPtr(); try { if ( !theWidthGenerator || !theVariableRatio ) return theDecaySelector.select(UseRandom::current()); DecaySelector local; if ( theWidthGenerator ) local = theWidthGenerator->rate(p); else for ( DecaySet::const_iterator mit = theDecayModes.begin(); mit != theDecayModes.end(); ++mit ) local.insert((*mit)->brat(p), *mit); return local.select(UseRandom::current()); } catch (range_error & e) { return tDMPtr(); } } void ParticleData::rebind(const TranslationMap & trans) { if ( CC() ) theAntiPartner = trans.translate(theAntiPartner); DecaySet newModes; DecaySelector newSelector; for ( DecaySet::iterator it = theDecayModes.begin(); it != theDecayModes.end(); ++it ) { DMPtr dm; dm = trans.translate(*it); if ( !dm ) throw RebindException(); newModes.insert(dm); newSelector.insert(dm->brat(), dm); } theDecayModes.swap(newModes); theDecaySelector.swap(newSelector); } IVector ParticleData::getReferences() { IVector refs = Interfaced::getReferences(); if ( CC() ) refs.push_back(CC()); refs.insert(refs.end(), theDecayModes.begin(), theDecayModes.end()); return refs; } void ParticleData::massGenerator(tMassGenPtr mg) { if ( mg && !mg->accept(*this) ) return; if ( mg && synchronized() && CC() && !mg->accept(*CC()) ) return; theMassGenerator = mg; if ( synchronized() && CC() ) CC()->theMassGenerator = mg; } void ParticleData::widthGenerator(tWidthGeneratorPtr newGen) { if ( newGen && !newGen->accept(*this) ) return; if ( newGen && synchronized() && CC() && !newGen->accept(*CC()) ) return; theWidthGenerator = newGen; if ( synchronized() && CC() ) CC()->theWidthGenerator = newGen; } Energy ParticleData::generateMass() const { return massGenerator()? massGenerator()->mass(*this): mass(); } Energy ParticleData::generateWidth(Energy m) const { return widthGenerator()? widthGenerator()->width(*this, m): width(); } Length ParticleData::generateLifeTime(Energy m, Energy w) const { return widthGenerator() ? widthGenerator()->lifeTime(*this, m, w) : UseRandom::rndExp(cTau()); } PPtr ParticleData::produceParticle(const Lorentz5Momentum & pp) const { PPtr p = new_ptr(Particle(this)); p->set5Momentum(pp); return p; } PPtr ParticleData::produceParticle(const LorentzMomentum & pp) const { PPtr p(produceParticle(Lorentz5Momentum(pp))); return p; } PPtr ParticleData::produceParticle(const LorentzMomentum & pp, Energy m) const { PPtr p(produceParticle(Lorentz5Momentum(pp, m))); return p; } PPtr ParticleData::produceParticle(Energy m, const Momentum3 & pp) const { PPtr p(produceParticle(Lorentz5Momentum(m, pp))); return p; } PPtr ParticleData::produceParticle(const Momentum3 & pp) const { PPtr p(produceParticle(Lorentz5Momentum(generateMass(), pp))); return p; } PPtr ParticleData:: produceParticle(Energy plus, Energy minus, Energy px, Energy py) const { PPtr p(produceParticle(LorentzMomentum(px, py, 0.5*(plus-minus), 0.5*(plus+minus)))); return p; } void ParticleData::setMass(Energy mi) { mass(mi); } void ParticleData::setHardProcessMass(Energy mi) { theHardProcessMass = mi; hardProcessMassSet = true; ParticleData * apd = CC().operator->(); if ( synchronized() && apd ) { apd->theHardProcessMass = theHardProcessMass; apd->hardProcessMassSet = true; } } void ParticleData::setHardProcessWidth(Energy mi) { theHardProcessWidth = mi; hardProcessWidthSet = true; ParticleData * apd = CC().operator->(); if ( synchronized() && apd ) { apd->theHardProcessWidth = theHardProcessWidth; apd->hardProcessWidthSet = true; } } string ParticleData::doUnsetHardProcessMass(string) { hardProcessMassSet = false; theHardProcessMass = -1.*GeV; return ""; } string ParticleData::doAdjustNominalMass(string) { if ( hardProcessMassSet ) setMass(theHardProcessMass); return ""; } string ParticleData::doUnsetHardProcessWidth(string) { hardProcessWidthSet = false; theHardProcessWidth = -1.*GeV; return ""; } Energy ParticleData::defMass() const { return theDefMass; } void ParticleData::setWidth(Energy wi) { width(wi); } Energy ParticleData::getWidth() const { return width(); } Energy ParticleData::defWidth() const { return theDefWidth; } void ParticleData::setCut(Energy ci) { widthCut(ci); } Energy ParticleData::getCut() const { return (theWidthUpCut >= ZERO && theWidthLoCut >= ZERO)? max(theWidthUpCut, theWidthLoCut): min(theWidthUpCut, theWidthLoCut); } Energy ParticleData::defCut() const { return theDefCut; } void ParticleData::setUpCut(Energy ci) { widthUpCut(ci); } Energy ParticleData::getUpCut() const { return theWidthUpCut; } void ParticleData::setLoCut(Energy ci) { widthLoCut(ci); } Energy ParticleData::getLoCut() const { return theWidthLoCut; } void ParticleData::setCTau(Length ti) { cTau(ti); } Length ParticleData::getCTau() const { return cTau(); } Length ParticleData::defCTau() const { return theDefCTau; } void ParticleData::setStable(long is) { stable(is); } long ParticleData::getStable() const { return stable(); } void ParticleData::setSync(long is) { synchronized(is); } long ParticleData::getSync() const { return synchronized(); } void ParticleData::setVariableRatio(long is) { variableRatio(is); } long ParticleData::getVariableRatio() const { return variableRatio(); } string ParticleData::doSync(string) { synchronize(); return ""; } void ParticleData::setMassGenerator(MassGenPtr gi) { massGenerator(gi); } void ParticleData::setWidthGenerator(WidthGeneratorPtr wg) { widthGenerator(wg); } void ParticleData::setColour(long c) { theColour = PDT::Colour(c); } long ParticleData::getColour() const { return theColour; } long ParticleData::defColour() const { return theDefColour; } void ParticleData::setCharge(int c) { theCharge = PDT::Charge(c); } string ParticleData::ssetCharge(string arg) { istringstream is(arg); long i; if ( is >> i ) { theCharge = PDT::Charge(i); return "New charge is " + arg; } if ( arg == "unknown" ) theCharge = PDT::ChargeUnknown; else if ( arg == "charged" ) theCharge = PDT::Charged; else if ( arg == "positive" ) theCharge = PDT::Positive; else if ( arg == "negative" ) theCharge = PDT::Negative; else throw ParticleChargeCommand(*this, arg); return "New charge is " + arg; } int ParticleData::getCharge() const { return theCharge; } int ParticleData::defCharge() const { return theDefCharge; } void ParticleData::setSpin(int s) { theSpin = PDT::Spin(s); } int ParticleData::getSpin() const { return theSpin; } int ParticleData::defSpin() const { return theDefSpin; } ClassDescription ParticleData::initParticleData; struct ParticleOrdering { bool operator()(tcPDPtr p1, tcPDPtr p2) const { return abs(p1->id()) > abs(p2->id()) || ( abs(p1->id()) == abs(p2->id()) && p1->id() > p2->id() ) || ( p1->id() == p2->id() && p1->fullName() > p2->fullName() ); } }; struct ModeOrdering { bool operator()(const tcDMPtr & d1, const tcDMPtr & d2) const { ParticleOrdering ord; return ord(d1->parent(), d2->parent()) || ( !ord(d2->parent(), d1->parent()) && ( d1->tag() < d2->tag() || ( d1->tag() == d2->tag() && d1->fullName() < d2->fullName() ) ) ); } }; void ParticleData::persistentOutput(PersistentOStream & os) const { multiset modes(theDecayModes.begin(), theDecayModes.end()); os << long(theId) << thePDGName << ounit(theMass, GeV) << ounit(theWidth, GeV) << ounit(theHardProcessMass,GeV) << hardProcessMassSet << ounit(theHardProcessWidth,GeV) << hardProcessWidthSet << ounit(theWidthUpCut, GeV) << ounit(theWidthLoCut, GeV) << ounit(theCTau, mm) << oenum(theCharge) << oenum(theSpin) << oenum(theColour); os << theMassGenerator << isStable << modes << theDecaySelector << theWidthGenerator << theVariableRatio << theAntiPartner << syncAnti << ounit(theDefMass, GeV) << ounit(theDefWidth, GeV) << ounit(theDefCut, GeV) << ounit(theDefCTau, mm) << oenum(theDefColour) << oenum(theDefCharge) << oenum(theDefSpin); } void ParticleData::persistentInput(PersistentIStream & is, int) { long id; is >> id >> thePDGName >> iunit(theMass, GeV) >> iunit(theWidth, GeV) >> iunit(theHardProcessMass,GeV) >> hardProcessMassSet >> iunit(theHardProcessWidth,GeV) >> hardProcessWidthSet >> iunit(theWidthUpCut, GeV) >> iunit(theWidthLoCut, GeV) >> iunit(theCTau, mm) >> ienum(theCharge) >> ienum(theSpin) >> ienum(theColour) >> theMassGenerator >> isStable >> theDecayModes >> theDecaySelector >> theWidthGenerator >> theVariableRatio >> theAntiPartner >> syncAnti >> iunit(theDefMass, GeV) >> iunit(theDefWidth, GeV) >> iunit(theDefCut, GeV) >> iunit(theDefCTau, mm) >> ienum(theDefColour) >> ienum(theDefCharge) >> ienum(theDefSpin); theId = id; } void ParticleData::Init() { static ClassDocumentation documentation ("There is no documentation for the ThePEG::ParticleData class"); static Parameter interfaceMass ("NominalMass", "The nominal mass in GeV of the particle. The actual mass " "of a particle instance is generated depending on the " "nominal mass and the width and is generated by the " "Mass_generator object associated with the " "particle.", &ParticleData::theMass, GeV, ZERO, ZERO, Constants::MaxEnergy, false, false, Interface::lowerlim, &ParticleData::setMass, 0, 0, 0, &ParticleData::defMass); static Parameter interfaceHardProcessMass ("HardProcessMass", "The mass in GeV of the particle to be used in calculating hard process cross sections.", &ParticleData::theHardProcessMass, GeV, ZERO, ZERO, Constants::MaxEnergy, false, false, Interface::lowerlim, &ParticleData::setHardProcessMass, 0, 0, 0, 0); static Parameter interfaceDefMass ("DefaultMass", "The default nominal mass in GeV of the particle. The actual mass " "of a particle instance is generated depending on the " "nominal mass and the width and is generated by the " "Mass_generator object associated with the " "particle.", &ParticleData::theDefMass, GeV, ZERO, ZERO, Constants::MaxEnergy, false, true, Interface::lowerlim); interfaceDefMass.setHasDefault(false); static Parameter interfaceWidth ("Width", "The width of the particle in GeV.", 0, GeV, ZERO, ZERO, Constants::MaxEnergy, false, false, Interface::lowerlim, &ParticleData::setWidth, &ParticleData::getWidth, 0, 0, &ParticleData::defWidth); static Parameter interfaceHardProcessWidth ("HardProcessWidth", "The width in GeV of the particle to be used in calculating hard process cross sections.", &ParticleData::theHardProcessWidth, GeV, ZERO, ZERO, Constants::MaxEnergy, false, false, Interface::lowerlim, &ParticleData::setHardProcessWidth, 0, 0, 0, 0); static Parameter interfaceDefWidth ("DefaultWidth", "The default width of the particle in GeV.", &ParticleData::theDefWidth, GeV, ZERO, ZERO, Constants::MaxEnergy, false, true, Interface::lowerlim); interfaceDefWidth.setHasDefault(false); static Parameter interfaceWidthUpCut ("WidthUpCut", "The upper hard cutoff in GeV in generated mass, which is the maximum " "allowed upwards deviation from the nominal mass. A negative value " "corresponds to no limit.", 0, GeV, ZERO, -1.0*GeV, Constants::MaxEnergy, false, false, Interface::lowerlim, &ParticleData::setUpCut, &ParticleData::getUpCut, 0, 0, &ParticleData::defCut); static Parameter interfaceWidthLoCut ("WidthLoCut", "The lower hard cutoff in GeV in generated mass, which is the maximum " "allowed downwards deviation from the nominal mass. A negative value " "corresponds to no limit.", 0, GeV, ZERO, -1.0*GeV, Constants::MaxEnergy, false, false, Interface::lowerlim, &ParticleData::setLoCut, &ParticleData::getLoCut, 0, 0, &ParticleData::defCut); static Parameter interfaceWidthCut ("WidthCut", "The hard cutoff in GeV in generated mass, which is the maximum " "allowed deviation from the nominal mass. Sets both the upper and lower " "cut. (The displayed value is the maximium of the upper and lower cut.) " "A negative value corresponds to no limit.", 0, GeV, ZERO, -1.0*GeV, Constants::MaxEnergy, false, false, Interface::lowerlim, &ParticleData::setCut, &ParticleData::getCut, 0, 0, &ParticleData::defCut); interfaceWidthCut.setHasDefault(false); static Parameter interfaceDefWidthCut ("DefaultWidthCut", "The default hard cutoff in GeV in generated mass, which is the maximum " "allowed deviation from the nominal mass. For the actual cutoff, the " "upper and lower cut can be set separately.", &ParticleData::theDefCut, GeV, ZERO, ZERO, Constants::MaxEnergy, false, true, Interface::lowerlim); interfaceDefWidthCut.setHasDefault(false); static Parameter interfaceCTau ("LifeTime", "c times the average lifetime of the particle measuerd in mm." "The actual lifetime of a particle instance is generated " "from this number by the Mass_generator " "object associated with the particle.", 0, mm, ZERO, ZERO, Constants::MaxLength, false, false, Interface::lowerlim, &ParticleData::setCTau, &ParticleData::getCTau, 0, 0, &ParticleData::defCTau); interfaceCTau.setHasDefault(false); static Parameter interfaceDefCTau ("DefaultLifeTime", "c times the default average lifetime of the particle measuerd in mm." "The actual lifetime of a particle instance is generated " "from this number by the Mass_generator " "object associated with the particle.", &ParticleData::theDefCTau, mm, ZERO, ZERO, Constants::MaxLength, false, true, Interface::lowerlim); interfaceDefCTau.setHasDefault(false); static Switch interfaceColour ("Colour", "The colour quantum number of this particle type.", 0, -1, false, false, &ParticleData::setColour, &ParticleData::getColour, &ParticleData::defColour); static SwitchOption interfaceColourUndefined (interfaceColour, "Undefined", "The coulur is undefined.", -1); static SwitchOption interfaceColourNeutral (interfaceColour, "Neutral", "This particle is colour neutral.", 0); static SwitchOption interfaceColour3 (interfaceColour, "Triplet", "This particle is a colour triplet.", 3); static SwitchOption interfaceColour3bar (interfaceColour, "AntiTriplet", "This particle is a colour anti-triplet.", -3); static SwitchOption interfaceColour6 (interfaceColour, "Sextet", "This particle is a colour sextet.", 6); static SwitchOption interfaceColour6bar (interfaceColour, "AntiSextet", "This particle is a colour anti-sextet.", -6); static SwitchOption interfaceColour8 (interfaceColour, "Octet", "This particle is a colour octet.", 8); static Switch interfaceDefColour ("DefaultColour", "The default colour quantum number of this particle type.", &ParticleData::theDefColour, PDT::Colour(-1), false, true); static SwitchOption interfaceDefColourUndefined (interfaceDefColour, "Undefined", "The coulur is undefined.", -1); static SwitchOption interfaceDefColourNeutral (interfaceDefColour, "Neutral", "This particle is colour neutral.", 0); static SwitchOption interfaceDefColour3 (interfaceDefColour, "Triplet", "This particle is a colour triplet.", 3); static SwitchOption interfaceDefColour3bar (interfaceDefColour, "AntiTriplet", "This particle is a colour anti-triplet.", -3); static SwitchOption interfaceDefColour6 (interfaceDefColour, "Sextet", "This particle is a colour sextet.", 6); static SwitchOption interfaceDefColour6bar (interfaceDefColour, "AntiSextet", "This particle is a colour anti-sextet.", -6); static SwitchOption interfaceDefColour8 (interfaceDefColour, "Octet", "This particle is a colour octet.", 8); interfaceDefColour.setHasDefault(false); static Parameter interfaceCharge ("Charge", "The charge of this particle in units of e/3. " "See also the command interface SetCharge.", 0, 0, -24, 24, false, false, true, &ParticleData::setCharge, &ParticleData::getCharge, 0, 0, &ParticleData::defCharge); static Parameter interfaceDefCharge ("DefaultCharge", "The default charge of this particle in units of e/3. " "See also the command interface SetCharge.", &ParticleData::theDefCharge, PDT::Charge(0), PDT::Charge(-24), PDT::Charge(24), false, true, true); interfaceDefCharge.setHasDefault(false); static Command interfaceSetCharge ("SetCharge", "Set the charge of this particle. The argument should be given as an " "interger giving three times the unit charge, or 'unknown', " "'charged', 'positive' or 'negative'", &ParticleData::ssetCharge); static Parameter interfaceSpin ("Spin", "The spin quantim number of this particle on the form 2j+1.", 0, 0, 0, 9, false, false, true, &ParticleData::setSpin, &ParticleData::getSpin, 0, 0, &ParticleData::defSpin); static Parameter interfaceDefSpin ("DefaultSpin", "The default spin quantim number of this particle on the form 2j+1.", &ParticleData::theDefSpin, PDT::Spin(0), PDT::Spin(0), PDT::Spin(9), false, true, true); interfaceDefSpin.setHasDefault(false); static Switch interfaceStable ("Stable", "Indicates if the particle is stable or not.", 0, 0, false, false, &ParticleData::setStable, &ParticleData::getStable, 0); static SwitchOption interfaceStableYes (interfaceStable, "Stable", "This particle is stable", 1); static SwitchOption interfaceStableNo (interfaceStable, "Unstable", "This particle is not stable", 0); interfaceStable.setHasDefault(false); static Switch interfaceVariableRatio ("VariableRatio", "Indicates if the branching ratios of the particle are allowed" " to vary for given Particle instances depending on the mass of the instance.", 0, 0, false, false, &ParticleData::setVariableRatio, &ParticleData::getVariableRatio, 0); static SwitchOption interfaceVariableRatioYes (interfaceVariableRatio, "Yes", "The branching ratio varies.", 1); static SwitchOption interfaceVariableRatioNo (interfaceVariableRatio, "No", "The branching ratio does not vary.", 0); static Switch interfaceSync ("Synchronized", "Indicates if the changes to this particle is propagated to " "its anti-partner or not. Note that setting this switch does not " "actually synchronize the properties with the anti-partner, " "it only assures that following changes are propagated. " "To sync the particle with its anti-particle, use the " "Synchronize command.", 0, 1, false, false, &ParticleData::setSync, &ParticleData::getSync, 0); static SwitchOption interfaceSyncYes (interfaceSync, "Synchronized", "Changes to this particle will propagate to its " "anti-partner", 1); static SwitchOption interfaceSyncNo (interfaceSync, "Not_synchronized", "Changes to this particle will propagate to its " "anti-partner", 0); interfaceSync.setHasDefault(false); static Command interfaceSynchronize ("Synchronize", "Synchronizes this particle so that all its properties " "correspond to those of its anti-partner", &ParticleData::doSync, false); static Reference interfaceMassGenerator ("Mass_generator", "An object derived from the ThePEG::MassGenerator" "class, which is able to generate a mass for a given " "particle instance", &ParticleData::theMassGenerator, false, false, true, true, &ParticleData::setMassGenerator, 0, 0); static Reference interfaceWidthGenerator ("Width_generator", "An object derived from the ThePEG::WidthGenerator class, " "which is able to calculate the full and partial widths for" "this particle type and for a given instance of this " "particle type.", &ParticleData::theWidthGenerator, false, false, true, true, &ParticleData::setWidthGenerator, 0, 0); static RefVector interfaceDecayModes ("DecayModes", "The list of decay modes defined for this particle type.", 0, -1, false, false, false, false, 0, &ParticleData::insDecayModes, &ParticleData::delDecayModes, &ParticleData::getDecayModes); static Command interfaceSelectDecayModes ("SelectDecayModes", "Only the decay modes which are given as (white-space separated) " "decay tags will be switched on, all others will be switched off. " "If no argument or 'none' is given, all decay modes are switched off. " "If the argument is 'all', all decay modes are switched on.", &ParticleData::doSelectDecayModes, false); static Command interfacePrintDecayModes ("PrintDecayModes", "Print all decay modes of this particle.", &ParticleData::doPrintDecayModes, true); static Command interfaceUnsetHardProcessMass ("UnsetHardProcessMass", "Unset a previously set hard process mass.", &ParticleData::doUnsetHardProcessMass, false); static Command interfaceAdjustNominalMass ("AdjustNominalMass", "Unset a previously set hard process mass.", &ParticleData::doAdjustNominalMass, false); static Command interfaceUnsetHardProcessWidth ("UnsetHardProcessWidth", "Unset a previously set hard process width.", &ParticleData::doUnsetHardProcessWidth, false); interfaceStable.rank(14); interfaceDecayModes.rank(13); interfaceMass.rank(12); interfaceWidth.rank(11); interfaceWidthCut.rank(10); interfaceCTau.rank(9); interfaceMassGenerator.rank(8); interfaceWidthGenerator.rank(7); interfaceWidthUpCut.rank(-0.1); interfaceWidthLoCut.rank(-0.1); } string ParticleData::doPrintDecayModes(string) { multimap > sorted; for ( DecaySet::iterator it = decayModes().begin(); it != decayModes().end(); ++it ) sorted.insert(make_pair((**it).brat(), *it)); ostringstream os; for ( multimap >::iterator it = sorted.begin(); it != sorted.end(); ++it ) os << it->second->tag() << (it->second->on()? " ": " (off) ") << it->first << endl; return os.str(); } string ParticleData::doSelectDecayModes(string args) { DecaySet on; while ( !args.empty() ) { string arg = StringUtils::car(args); if ( arg == "all" ) { on = decayModes(); break; } if ( arg == "none" ) { on.clear(); break; } string name = arg; args = StringUtils::cdr(args); if ( arg.empty() ) continue; if ( arg[0] != '/' ) arg = fullName() + "/" + arg; DMPtr dm = Repository::GetPtr(arg); if ( !dm ) return "Error: No decay mode with tag '" + name + "' exists."; on.insert(dm); } for ( DecaySet::iterator it = decayModes().begin(); it != decayModes().end(); ++it ) { if ( on.find(*it) != on.end() ) { (**it).switchOn(); on.erase(*it); } else { (**it).switchOff(); } } if ( !on.empty() ) return "Error: decay mode '" + (**on.begin()).tag() + "'was not available."; return ""; } void ParticleData::insDecayModes(DMPtr dm, int) { addDecayMode(dm); } void ParticleData::delDecayModes(int i) { vector mv = getDecayModes(); if ( i >= 0 && static_cast(i) < mv.size() ) removeDecayMode(mv[i]); } vector ParticleData::getDecayModes() const { return vector(theDecayModes.begin(), theDecayModes.end()); } ParticleChargeCommand:: ParticleChargeCommand(const ParticleData & pd, string arg) { theMessage << "Cannot set the charge of particle '" << pd.name() << "' to '" << arg << "'."; severity(warning); } void ParticleData::doinit() { Interfaced::doinit(); if( theMassGenerator ) theMassGenerator->init(); if( theWidthGenerator ) theWidthGenerator->init(); } void ParticleData::doinitrun() { Interfaced::doinitrun(); if( theMassGenerator ) theMassGenerator->initrun(); if( theWidthGenerator ) theWidthGenerator->initrun(); } } diff --git a/PDT/ParticleData.h b/PDT/ParticleData.h --- a/PDT/ParticleData.h +++ b/PDT/ParticleData.h @@ -1,968 +1,968 @@ // -*- C++ -*- // // ParticleData.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_ParticleData_H #define ThePEG_ParticleData_H // This is the declaration of the ParticleData class. #include "ThePEG/Config/ThePEG.h" #include "ThePEG/PDT/PDT.h" #include "ThePEG/PDT/PID.h" #include "ThePEG/Vectors/LorentzVector.h" #include "ThePEG/Vectors/ThreeVector.h" #include "ThePEG/Interface/Interfaced.h" #include "ThePEG/Utilities/Selector.h" #include "ThePEG/PDT/WidthGenerator.h" #include "ThePEG/PDT/MassGenerator.h" #include "ThePEG/PDT/DecayMode.fh" #include "ThePEG/Utilities/ClassTraits.h" #include "ThePEG/Utilities/ClassDescription.h" namespace ThePEG { /** * ParticleData inherits from InterfacedBase and represents the * properties of a particle type. It is also able to produce instances * of this Particle type and, among other things, to decay them. * * @see \ref ParticleDataInterfaces "The interfaces" * defined for ParticleData. */ class ParticleData: public Interfaced { public: /** The Repository is a friend. */ friend class Repository; /** The EventGenerator is a friend. */ friend class EventGenerator; /** DecayMode is a friend. */ friend class DecayMode; /** A selector of DecayMode objects. */ typedef Selector DecaySelector; public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ ParticleData(); /** * Destructor. */ virtual ~ParticleData(); //@} /** @name The Create methods are special interfaces for ParticleData classes. */ //@{ /** * Create a Particle which is its own anti-particle. */ static PDPtr Create(PID newId, const string & newPDGName); /** * Create a particle - anti particle pair. */ static PDPair Create(PID newId, const string & newPDGName, const string & newAntiPDGName); //@} public: /** @name Acces to number and name. */ //@{ /** * Return the PDG id number. */ long id() const { return theId; } /** * Return the generic PDG name. Note that this is not really * standardised. */ const string & PDGName() const { return thePDGName; } /** * Return the generic PDG name. Note that this is not really * standardised. */ const string & genericName() const { return thePDGName; } //@} /** @name Functions used for producing Particle instances. */ //@{ /** * Produce a particle specifying momentum. */ PPtr produceParticle(const Lorentz5Momentum &) const; /** * Produce a particle specifying momentum. */ PPtr produceParticle(const LorentzMomentum &) const; /** * Produce a particle specifying 4-momentum and a mass. */ PPtr produceParticle(const LorentzMomentum &, Energy m) const; /** * Produce a particle specifying 3-momentum. */ PPtr produceParticle(const Momentum3 & pp = Momentum3()) const; /** * Produce a particle specifying mass and 3-momentum. */ PPtr produceParticle(Energy m, const Momentum3 & pp = Momentum3()) const; /** * Produce a particle specifying light-cone momentum components and * transverse momentum components. */ PPtr produceParticle(Energy plus, Energy minus, Energy px, Energy py) const; /** * Generate a mass for an instance of this particle type. */ Energy generateMass() const; /** * Generate a width for an instance of this particle type. Given a * \a mass of an instance of this particle type, calculate its width. */ Energy generateWidth(Energy mass) const; /** * Generate a mass for an instance of this particle type. Given a \a * mass and a \a width of an instance of this particle type, * generate a life time. */ Length generateLifeTime(Energy mass, Energy width) const; // Given a mass and a width of an instance of this particle type, // generate a life time. //@} /** @name Access the decay modes. */ //@{ /** * Return the nominal decay selector for this particle. Ie. the * decay modes weighted by their nominal branching ratios. */ const DecaySelector & decaySelector() const { return theDecaySelector; } /** * Selects a decay mode randomly according to the branching * ratios. The nominal branching ratios may be changed for the * particular Particle instance \a p, iether by an assigned * WidthGenerator or the respective Decayers. */ tDMPtr selectMode(Particle & p) const; /** * Access all the decay modes, including those which are * switched off, or have zero branching ratio */ const DecaySet & decayModes() const { return theDecayModes; } //@} /** * Set the nominal mass */ Energy mass(Energy); /** * Return the nominal mass. */ Energy mass() const { return theMass; } /** * Return the mass to be used when evaluating hard process cross sections. */ Energy hardProcessMass() const { return hardProcessMassSet ? theHardProcessMass : mass(); } /** * Return the maximum possible mass of this particle type. */ Energy massMax() const { return mass() + widthUpCut(); } /** * Return the minimum possible mass of this particle type. */ Energy massMin() const { return max(mass() - widthLoCut(), ZERO); } /** * Return the constituent mass of this particle if relevant. This * version simply returns the nominal mass. */ virtual Energy constituentMass() const { return mass(); } /** * Set the width. */ Energy width(Energy); /** * Get the width. If no width is specified, it is calculated from * the lifetime. */ Energy width() const { return theWidth >= ZERO ? theWidth : ( theCTau > Length() ? hbarc/theCTau : ( theCTau == Length() ? Constants::MaxEnergy : ZERO ) ); } /** * Set the width cut. Both upper and lower cut is set. */ Energy widthCut(Energy wci) { widthUpCut(wci); return widthLoCut(wci); } /** * Get the width cut. */ Energy widthCut() const { return max(widthUpCut(), widthLoCut()); } /** * Set the upper width cut. */ Energy widthUpCut(Energy); /** * Get the upper width cut. */ Energy widthUpCut() const { return theWidthUpCut >= ZERO? theWidthUpCut: Constants::MaxEnergy; } /** * Set the lower width cut. */ Energy widthLoCut(Energy); /** * Get the lower width cut. */ Energy widthLoCut() const { return theWidthLoCut >= ZERO? theWidthLoCut: Constants::MaxEnergy; } /** * Set the life time cTau. */ Length cTau(Length); /** * Get the life time cTau cTau. If no life time is specified, it is * calculated from the width. If the width is also not specified, * the lifetime is assumed to be zero for ustable particles and * infinite for stable ones. */ Length cTau() const { return theCTau > Length() ? theCTau : ( theWidth > ZERO ? hbarc/theWidth : ( stable() ? Constants::MaxLength : Length() ) ); } /** * Return the width to be used when evaluating hard process cross sections. */ Energy hardProcessWidth() const { return hardProcessWidthSet ? theHardProcessWidth : width(); } /** * Set the charge. The charge should be given * in units of e/3 using the PDT::Charge enum. */ PDT::Charge iCharge(PDT::Charge); /** * Get the charge. The charge is returned in standard units and in * iCharge the charge is returned in units of e/3. */ Charge charge() const { return eplus*double(theCharge)/3.0; } /** * Get the charge. The charge is returned in units of e/3. */ PDT::Charge iCharge() const { return theCharge; } /** * Return true if charged. */ bool charged() const { return PDT::charged(theCharge); } /** * Return true if positively charged. */ bool positive() const { return PDT::positive(theCharge); } /** * Return true if negatively charged. */ bool negative() const { return PDT::negative(theCharge); } /** * Set the spin. The spin should be given as 2J+1 (in units of * hbar/2) using the PDT::Spin enum. */ PDT::Spin iSpin(PDT::Spin); /** * Get the spin.The spin is returned in standard units. */ AngularMomentum spin() const { return hbar_Planck*double(theSpin-1)*0.5; } /** * Get the spin. The spin is returned as 2J+1 in units of hbar/2. */ PDT::Spin iSpin() const { return theSpin; } /** * Set the colour of the particle in units of PDT::Colour. */ PDT::Colour iColour(PDT::Colour); /** * Get the colour of the particle in units of PDT::Colour. */ PDT::Colour iColour() const { return theColour; } /** * Return true if coloured. */ bool coloured() const { return PDT::coloured(iColour()); } /** * Return true if (\a anti) coloured or colour-octet. */ bool hasColour(bool anti = false) const { return anti? hasAntiColour(): ( iColour() == PDT::Colour3 || iColour() == PDT::Colour6 || iColour() == PDT::Colour8 ); } /** * Return true if anti coloured or colour-octet. */ bool hasAntiColour() const { return iColour() == PDT::Colour3bar || iColour() == PDT::Colour6bar || iColour() == PDT::Colour8; } /** * Specify if particle is to be considered stable according to \a * stab. */ void stable(bool stab); /** * Return true if particle is to be considered stable. If the decay * table is empty the function always returns true, even if the * member variable is false. */ bool stable() const { return isStable; } /** * Get the pointer to the corresponding anti partner. */ tPDPtr CC() const { return theAntiPartner; } /** * Specify if the anti partner chould be changed automatically when * this object is changed according to \a sync. */ void synchronized(bool sync); /** * Return true if the anti partner chould be changed automatically * when this object is changed. */ bool synchronized() const { return syncAnti; } /** * If there is an anti-partner, update this object to have correct * anti-properties. */ void synchronize(); /** * Set the mass generator object. */ void massGenerator(tMassGenPtr); /** * Get the mass generator object. */ tMassGenPtr massGenerator() const { return theMassGenerator; } /** * Set the width generator object. */ void widthGenerator(tWidthGeneratorPtr); /** * Get the width generator object. */ tWidthGeneratorPtr widthGenerator() const { return theWidthGenerator; } /** * Specify if the branching ratio of the Particle instances should vary with their * masses. */ void variableRatio(bool varRatio); /** * Return true if the branching ratio should vary with the mass of the Particle * instance. */ bool variableRatio() const { return theVariableRatio; } public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} /** * Special clone function used by the Repository. Also makes copies * the decay modes and the anti-partner if it exists and if * synchronized() is true. */ virtual PDPtr pdclone() const; /** * Protected constructor only to be used by subclasses or by the * Create method. */ ParticleData(PID newId, const string & newPDGName); /** * Read setup info from a standard stream. The following information * must be supplied in a white-space separated list: PDG number, * generic name, default mass (GeV), default width (GeV), width cut * (GeV), the lifetime ctau (mm), the charge, the colour, the spin, * stable (true) or not (false). Note that if a minus sign is given * instead of a generic name, the name of the object will be used * instead. */ virtual void readSetup(istream & is); /** * Used by subclasses or by the Create method to setup * anti-relationship. */ static void antiSetup(const PDPair & pap); protected: /** @name Standard Interfaced functions. */ //@{ /** * Check sanity of the object during the setup phase. */ virtual void doupdate(); /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Rebind pointer to other Interfaced objects. Called in the setup phase * after all objects used in an EventGenerator has been cloned so that * the pointers will refer to the cloned objects afterwards. * @param trans a TranslationMap relating the original objects to * their respective clones. * @throws RebindException if no cloned object was found for a given * pointer. */ virtual void rebind(const TranslationMap & trans) ; /** * Return a vector of all pointers to Interfaced objects used in this * object. * @return a vector of pointers. */ virtual IVector getReferences(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); //@} protected: /** * Add a decay mode for this particle. */ void addDecayMode(tDMPtr); /** * Remove a decay mode for this particle. */ void removeDecayMode(tDMPtr); private: /** * Id number according to the STDHEP/PDG standard. */ PID theId; /** * Name and Id number according to the STDHEP/PDG standard. */ string thePDGName; /** * Nominal mass. */ Energy theMass; /** * Width. */ Energy theWidth; /** * The mass to be used when evaluating hard process cross sections. */ Energy theHardProcessMass; /** * True, if a hard process mass has been set. */ bool hardProcessMassSet; /** * The width to be used when evaluating hard process cross sections. */ Energy theHardProcessWidth; /** * True, if a hard process width has been set. */ bool hardProcessWidthSet; /** * Upper width cut. */ Energy theWidthUpCut; /** * Lower width cut. */ Energy theWidthLoCut; /** * Lifetime. */ Length theCTau; /** * Three times the charge. */ PDT::Charge theCharge; /** * 2 times the spin plus one. */ PDT::Spin theSpin; /** * The colour for this particle. */ PDT::Colour theColour; /** * A pointer to an object capable to generate a mass for a particle * of this type. */ MassGenPtr theMassGenerator; /** * True if the particle is considered stable. */ bool isStable; /** * A selector of decay modes weighted by the nominal branching * ratios. */ DecaySelector theDecaySelector; /** * The set of all decay modes. */ DecaySet theDecayModes; /** * A pointer to an object capable to generate the branching * fractions for different decay modes for this particle type. The * object will be asked to generate branching fractions every time * the ParticleData object it updated and will modify the branching * fractions for every particle instance if variableRatio is true. */ WidthGeneratorPtr theWidthGenerator; /** * Determine whether the branching fractions are allowed to change * on a particle-by-particle basis. */ bool theVariableRatio; /** * Pointer to the object corresponding to the antiparticle. Set to * null if it is its own antiparticle. */ tPDPtr theAntiPartner; /** * If syncAnti is true all changes to this object will be transfered * to the antiParticle. */ bool syncAnti; /** * Helper variable to keep track of the default mass. */ Energy theDefMass; /** * Helper variable to keep track of the default width. */ Energy theDefWidth; /** * Helper variable to keep track of the default width cut. */ Energy theDefCut; /** * Helper variable to keep track of the default lifetime. */ Length theDefCTau; /** * Helper variable to keep track of the default charge. */ PDT::Charge theDefCharge; /** * Helper variable to keep track of the default spin. */ PDT::Spin theDefSpin; /** * Helper variable to keep track of the default colour. */ PDT::Colour theDefColour; /** * Utility function for the interface. */ void setMass(Energy); /** * Utility function for the interface. */ void setHardProcessMass(Energy); /** * Reset the hard process mass */ string doUnsetHardProcessMass(string); /** * Adjust the nominal mass to the hard process mass if a reshuffling * is not desirable. */ string doAdjustNominalMass(string); /** * Utility function for the interface. */ Energy defMass() const; /** * Utility function for the interface. */ void setWidth(Energy); /** * Utility function for the interface. */ void setHardProcessWidth(Energy); /** * Reset the hard process mass */ string doUnsetHardProcessWidth(string); /** * Utility function for the interface. */ Energy getWidth() const; /** * Utility function for the interface. */ Energy defWidth() const; /** * Utility function for the interface. */ void setCut(Energy); /** * Utility function for the interface. */ Energy getCut() const; /** * Utility function for the interface. */ Energy defCut() const; /** * Utility function for the interface. */ void setUpCut(Energy); /** * Utility function for the interface. */ Energy getUpCut() const; /** * Utility function for the interface. */ void setLoCut(Energy); /** * Utility function for the interface. */ Energy getLoCut() const; /** * Utility function for the interface. */ void setCTau(Length); /** * Utility function for the interface. */ Length getCTau() const; /** * Utility function for the interface. */ Length defCTau() const; /** * Utility function for the interface. */ void setStable(long); /** * Utility function for the interface. */ long getStable() const; /** * Utility function for the interface. */ void setSync(long); /** * Utility function for the interface. */ long getSync() const; /** * Utility function for the interface. */ void setVariableRatio(long); /** * Utility function for the interface. */ long getVariableRatio() const; /** * Utility function for the interface. */ string doSync(string); /** * Utility function for the interface. */ void setMassGenerator(MassGenPtr); /** * Utility function for the interface. */ void setWidthGenerator(WidthGeneratorPtr); /** * Utility function for the interface. */ void setCharge(int); /** * Utility function for the interface. */ string ssetCharge(string); /** * Utility function for the interface. */ int getCharge() const; /** * Utility function for the interface. */ int defCharge() const; /** * Utility function for the interface. */ void setSpin(int); /** * Utility function for the interface. */ int getSpin() const; /** * Utility function for the interface. */ int defSpin() const; /** * Utility function for the interface. */ void setColour(long); /** * Utility function for the interface. */ long getColour() const; /** * Utility function for the interface. */ long defColour() const; /** * Utility function for the interface. */ void insDecayModes(DMPtr dm, int); /** * Utility function for the interface. */ void delDecayModes(int i); /** * Utility function for the interface. */ vector getDecayModes() const; /** * Utility function for the interface. */ string doSelectDecayModes(string); /** * Utility function for the interface. */ string doPrintDecayModes(string); /** * Describe a concrete class with persistent data. */ static ClassDescription initParticleData; }; /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the base classes * of ParticleData. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of ParticleData. */ typedef Interfaced NthBase; }; /** This template specialization informs ThePEG about the name of the * ParticleData class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "ThePEG::ParticleData"; } }; /** @endcond */ } #endif /* ThePEG_ParticleData_H */ diff --git a/PDT/ParticleData.xh b/PDT/ParticleData.xh --- a/PDT/ParticleData.xh +++ b/PDT/ParticleData.xh @@ -1,31 +1,31 @@ // -*- C++ -*- // // ParticleData.xh is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_ParticleData_XH #define ThePEG_ParticleData_XH // // This is the declarations of the exception classes used by the // ParticleData class. // #include "ThePEG/Interface/InterfaceBase.xh" namespace ThePEG { /** @cond EXCEPTIONCLASSES */ /** Exception class used by ParticleData if the setting of the charge fails. */ struct ParticleChargeCommand: public InterfaceException { /** Standard constructor. */ ParticleChargeCommand(const ParticleData &, string); }; /** @endcond */ } #endif /* ThePEG_ParticleData_XH */ diff --git a/PDT/QuarksToHadronsDecayer.cc b/PDT/QuarksToHadronsDecayer.cc --- a/PDT/QuarksToHadronsDecayer.cc +++ b/PDT/QuarksToHadronsDecayer.cc @@ -1,236 +1,236 @@ // -*- C++ -*- // // QuarksToHadronsDecayer.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the QuarksToHadronsDecayer class. // #include "QuarksToHadronsDecayer.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/PDT/DecayMode.h" #include "ThePEG/PDT/StandardMatchers.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/SimplePhaseSpace.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG; QuarksToHadronsDecayer::~QuarksToHadronsDecayer() {} IBPtr QuarksToHadronsDecayer::clone() const { return new_ptr(*this); } IBPtr QuarksToHadronsDecayer::fullclone() const { return new_ptr(*this); } bool QuarksToHadronsDecayer::accept(const DecayMode & dm) const { int col = 0; int acol = 0; if ( !dm.productMatchers().empty() ) { for ( MatcherMSet::const_iterator it = dm.productMatchers().begin(); it != dm.productMatchers().end(); ++it ) { const auto & tmp=**it; if ( typeid(tmp) == typeid(MatchLightQuark) ) ++col; else if ( typeid(tmp) == typeid(MatchLightAntiQuark) ) ++acol; else return false; } if ( col != 1 || col != acol ) return false; } if ( dm.orderedProducts().size() + col + acol < 2 || !dm.cascadeProducts().empty() || dm.wildProductMatcher() ) return false; for ( int i = 0, N = dm.orderedProducts().size(); i < N; ++i ) { if ( DiquarkMatcher::Check(*dm.orderedProducts()[i]) ) { if ( i + 1 != N ) return false; if ( dm.orderedProducts()[i]->id() < 0 ) ++col; else ++acol; } if ( QuarkMatcher::Check(*dm.orderedProducts()[i]) ) { if ( dm.orderedProducts()[i]->id() > 0 ) ++col; else ++acol; } } if ( acol != col || col < 1 || col > 2 ) return false; return true; } PVector QuarksToHadronsDecayer::decay(const DecayMode & dm, const Particle & parent) const { PVector children; tcPDVector quarks; if ( !dm.productMatchers().empty() ) { tcPDPtr pd = getParticleData(flavourGenerator()->selectQuark()); quarks.push_back(pd); quarks.push_back(pd->CC()); } Energy summq = ZERO; Energy summp = ZERO; tPDVector prods = dm.orderedProducts(); for ( int i = 0, N = prods.size(); i < N; ++i ) if ( QuarkMatcher::Check(*prods[i]) || DiquarkMatcher::Check(*prods[i])) { quarks.push_back(prods[i]); summq += quarks.back()->mass(); } else { children.push_back(prods[i]->produceParticle()); summp += children.back()->mass(); } Energy summh = ZERO; PVector hadrons; if ( !quarks.empty() ) do { hadrons = getHadrons(getN(parent.mass(), summq, quarks.size()), quarks); summh = ZERO; for ( int i = 0, N = hadrons.size(); i < N; ++i ) summh += hadrons[i]->mass(); } while ( hadrons.empty() || summp + summh >= parent.mass() ); children.insert(children.end(), hadrons.begin(), hadrons.end()); distribute(parent, children); finalBoost(parent, children); setScales(parent, children); return children; } int QuarksToHadronsDecayer::getN(Energy m0, Energy summq, int Nq) const { int Nh = fixedN(); if ( Nh >= 2 ) return Nh; double c = c1()*log((m0 - summq)/c2()) + c3(); if ( c < 0.0 ) return minN(); while ( true ) { using namespace Constants; Nh = int(0.5 + double(Nq)/4.0 + c + sqrt(-2.0*c*log(max(1.0e-10, rnd())))*sin(2.0*pi*rnd())); if ( Nh >= minN() ) return Nh; } } PVector QuarksToHadronsDecayer:: getHadrons(int Nh, tcPDVector quarks) const { PVector hadrons; Nh -= quarks.size()/2; while ( Nh-- > 0 ) { int i = irnd(quarks.size() - 1); tcPDPair hq = flavourGenerator()->alwaysGenerateHadron(quarks[i]); hadrons.push_back(hq.first->produceParticle()); quarks[i] = hq.second; } if ( DiquarkMatcher::Check(*quarks[0]) && DiquarkMatcher::Check(*quarks[1]) ) return PVector(); tcPDPtr h = flavourGenerator()->alwaysGetHadron(quarks[0], quarks[1]); hadrons.push_back(h->produceParticle()); if ( quarks.size() <= 2 ) return hadrons; if ( DiquarkMatcher::Check(*quarks[2]) && DiquarkMatcher::Check(*quarks[3]) ) return PVector(); h = flavourGenerator()->alwaysGetHadron(quarks[2], quarks[3]); hadrons.push_back(h->produceParticle()); return hadrons; } void QuarksToHadronsDecayer:: distribute(const Particle & parent, PVector & children) const { do { try { SimplePhaseSpace::CMSn(children, parent.mass()); } catch ( ImpossibleKinematics & e) { children.clear(); return; } } while ( reweight(parent, children) < rnd() ); } double QuarksToHadronsDecayer:: reweight(const Particle &, const PVector &) const { return 1.0; } void QuarksToHadronsDecayer::persistentOutput(PersistentOStream & os) const { os << theFixedN << theMinN << theC1 << ounit(theC2,GeV) << theC3 << theFlavourGenerator; } void QuarksToHadronsDecayer::persistentInput(PersistentIStream & is, int) { is >> theFixedN >> theMinN >> theC1 >> iunit(theC2,GeV) >> theC3 >> theFlavourGenerator; } ClassDescription QuarksToHadronsDecayer::initQuarksToHadronsDecayer; // Definition of the static class description member. void QuarksToHadronsDecayer::Init() { static ClassDocumentation documentation ("This class decays particles to nq (2 or 4) quarks which then are " "decayes to hadrons according to phase space. The number of final " "hadrons can either be given by a fixed number or as a Gaussian " "multiplicity distribution centered around c+nq/4+c3 and a width " "sqrt(c), where c = c1 log((m - summ)/c2), m is the mass of the " "decaying particle, summ the sum of the quark masses and ci real " "parameters."); static Parameter interfaceFixedN ("FixedN", "The fixed number of hadrons to be produced. If less than 2, the " "number is instead given by a gaussian multiplicity distribution.", &QuarksToHadronsDecayer::theFixedN, 0, 0, 10, true, false, true); static Parameter interfaceMinN ("MinN", "The minimum hadrons to be produced.", &QuarksToHadronsDecayer::theMinN, 2, 2, 10, true, false, true); static Parameter interfaceC1 ("C1", "The c1 parameter of the gaussian multiplicity distribution centered " "around c1 log((m - summ)/c2) +c3.", &QuarksToHadronsDecayer::theC1, 4.5, 0.0, 10.0, true, false, true); static Parameter interfaceC2 ("C2", "The c2 parameter of the gaussian multiplicity distribution centered " "around c1 log((m - summ)/c2) +c3.", &QuarksToHadronsDecayer::theC2, GeV, 0.7*GeV, ZERO, 10.0*GeV, true, false, true); static Parameter interfaceC3 ("C3", "The c3 parameter of the gaussian multiplicity distribution centered " "around c1 log((m - summ)/c2) +c3.", &QuarksToHadronsDecayer::theC3, 0.0, 0.0, 10.0, true, false, true); static Reference interfaceFlavourGenerator ("FlavourGenerator", "The object in charge of generating hadrons spieces from given quark " "flavours.", &QuarksToHadronsDecayer::theFlavourGenerator, true, false, true, false, true); interfaceFixedN.rank(10); interfaceMinN.rank(9); interfaceFlavourGenerator.rank(8); interfaceMinN.setHasDefault(false);; } diff --git a/PDT/QuarksToHadronsDecayer.h b/PDT/QuarksToHadronsDecayer.h --- a/PDT/QuarksToHadronsDecayer.h +++ b/PDT/QuarksToHadronsDecayer.h @@ -1,264 +1,264 @@ // -*- C++ -*- // // QuarksToHadronsDecayer.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_QuarksToHadronsDecayer_H #define THEPEG_QuarksToHadronsDecayer_H // This is the declaration of the QuarksToHadronsDecayer class. #include "ThePEG/PDT/Decayer.h" #include "ThePEG/Handlers/FlavourGenerator.h" namespace ThePEG { ThePEG_DECLARE_CLASS_POINTERS(FlavourGenerator, FlavGenPtr); /** * The QuarksToHadronsDecayer class inherits from Decayer and is able * to decay particles to \f$n_q\f$ (2 or 4) quarks which then are * decayed to hadrons according to phase space. The number of final * hadrons can either be given by a fixed number or as a Gaussian * multiplicity distribution centered around \f$c+n_q/4+c_3\f$ and a * width \f$\sqrt{c}\f$, where \f$c = c_1 \log((m - \sum m)/c_2)\f$, * \f$m\f$ is the mass of the decaying particle, \f$\sum m\f$ the sum * of the quark masses and \f$c_i\f$ real parameters. * * @see \ref QuarksToHadronsDecayerInterfaces "The interfaces" * defined for QuarksToHadronsDecayer. * @see ParticleData * */ class QuarksToHadronsDecayer: public Decayer { public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ QuarksToHadronsDecayer() : theFixedN(0), theMinN(2), theC1(4.5), theC2(0.7*GeV), theC3(0.0) {} /** * Destructor. */ virtual ~QuarksToHadronsDecayer(); //@} public: /** @name Virtual functions required by the Decayer class. */ //@{ /** * Check if this decayer can perfom the decay specified by the * given decay mode. * @param dm the DecayMode describing the decay. * @return true if this decayer can handle the given mode, otherwise false. */ virtual bool accept(const DecayMode & dm) const; /** * Perform a decay for a given DecayMode and a given Particle instance. * @param dm the DecayMode describing the decay. * @param p the Particle instance to be decayed. * @return a ParticleVector containing the decay products. */ virtual ParticleVector decay(const DecayMode & dm, const Particle & p) const; //@} /** * Get the number of hadrons to be produced, given the mass of the * decaying particle, \a m0, and the number, \a Nq and summed masses * of the quarks, \a summq. */ virtual int getN(Energy m0, Energy summq, int Nq) const; /** * Produce \a Nh hadrons from the specified \a quarks. The last * quark is considered to be a spectator quark. */ virtual PVector getHadrons(int Nh, tcPDVector quarks) const; /** * Distribute the produced children in phase space. This default * version uses a flat phase space which can be reweighted by * overriding the reweight() function. */ virtual void distribute(const Particle & parent, PVector & children) const; /** * Called by distribute() to reweight the default flat phase * spece. Can be overridden by sub-classes and should return a * number between 0 and 1. This version returns 1. */ virtual double reweight(const Particle & parent, const PVector & children) const; public: /** * Return the fixed number of hadrons to be produced. If less than * 2, the number is instead given by a gaussian multiplicity * distribution. */ int fixedN() const { return theFixedN; } /** * Return the minimum number of hadrons to be produced. */ int minN() const { return theMinN; } /** * Return the parameter \f$c_1\f$ used for the multiplicity * distriution. */ double c1() const { return theC1; } /** * Return the parameter \f$c_2\f$ used for the multiplicity * distriution. */ Energy c2() const { return theC2; } /** * Return the parameter \f$c_3\f$ used for the multiplicity * distriution. */ double c3() const { return theC3; } /** * Return a pointer to the flavour generator to be used. */ tcFlavGenPtr flavourGenerator() const { return theFlavourGenerator; } 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(); protected: protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * The fixed number of hadrons to be produced. If less than 2, the * number is instead given by a gaussian multiplicity distribution. */ int theFixedN; /** * The minimum hadrons to be produced. */ int theMinN; /** * The parameter \f$c_1\f$ of the multiplicity distribution. */ double theC1; /** * The parameter \f$c_2\f$ of the multiplicity distribution. */ Energy theC2; /** * The parameter \f$c_3\f$ of the multiplicity distribution. */ double theC3; /** * The object in charge of generating hadrons spieces from given * quark flavours. */ FlavGenPtr theFlavourGenerator; private: /** * Describe a concrete class with persistent data. */ static ClassDescription initQuarksToHadronsDecayer; /** * Private and non-existent assignment operator. */ QuarksToHadronsDecayer & operator=(const QuarksToHadronsDecayer &) = delete; }; } namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the base classes * of QuarksToHadronsDecayer. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of QuarksToHadronsDecayer. */ typedef Decayer NthBase; }; /** This template specialization informs ThePEG about the name of the * QuarksToHadronsDecayer 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::QuarksToHadronsDecayer"; } /** Return the name of the shared library be loaded to get access to * the QuarksToHadronsDecayer class and every other class it uses * (except the base class). */ static string library() { return "QuarksToHadronsDecayer.so"; } }; /** @endcond */ } #endif /* THEPEG_QuarksToHadronsDecayer_H */ diff --git a/PDT/RemnantData.cc b/PDT/RemnantData.cc --- a/PDT/RemnantData.cc +++ b/PDT/RemnantData.cc @@ -1,117 +1,117 @@ // -*- C++ -*- // // RemnantData.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the RemnantData class. // #include "RemnantData.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/PDT/RemnantDecayer.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG; RemnantData:: RemnantData(tcPDPtr particle, RemDecPtr dec) // : ParticleData(particle->id(), "Rem:" + particle->PDGName()), : ParticleData(82, "Rem:" + particle->PDGName()), parentPD(particle), theDecayer(dec) { synchronized(false); width(ZERO); widthCut(ZERO); iCharge(particle->iCharge()); iSpin(particle->iSpin()); iColour(particle->iColour()); stable(true); fixColour(); } IBPtr RemnantData::clone() const { return new_ptr(*this); } IBPtr RemnantData::fullclone() const { return new_ptr(*this); } bool RemnantData::extract(tcPDPtr parton) { if ( !decayMode ) { stable(false); decayMode = new_ptr(DecayMode()); decayMode->parent(this); decayMode->brat(1.0); decayMode->decayer(theDecayer); decayMode->switchOn(); addDecayMode(decayMode); } if ( !parton ) return false; // if ( !extracted.empty() && !decayer->multiCapable() ) return false; if ( !theDecayer->canHandle(parentPD, parton) ) return false; extracted.insert(parton); iCharge(PDT::Charge(iCharge() - parton->iCharge())); return fixColour(); } bool RemnantData:: reextract(tcPDPtr oldp, tcPDPtr newp) { multiset::iterator it = extracted.find(oldp); if ( it == extracted.end() ) return false; if ( !theDecayer->canHandle(parentPD, newp) ) return false; extracted.erase(it); extracted.insert(newp); iCharge(PDT::Charge(iCharge() + oldp->iCharge() - newp->iCharge())); return fixColour(); } bool RemnantData:: remove(tcPDPtr oldp) { multiset::iterator it = extracted.find(oldp); if ( it == extracted.end() ) return false; extracted.erase(it); iCharge(PDT::Charge(iCharge() + oldp->iCharge())); return fixColour(); } bool RemnantData::fixColour() { bool col = parentPD->hasAntiColour(); bool acol = parentPD->hasColour(); for ( multiset::const_iterator it = extracted.begin(); it != extracted.end(); ++it ) { if ( (**it).hasColour() ) col = true; if ( (**it).hasAntiColour() ) acol = true; } if ( col ) iColour(acol? PDT::Colour8: PDT::Colour3bar); else iColour(acol? PDT::Colour3: PDT::Colour0); return true; } void RemnantData::persistentOutput(PersistentOStream & os) const { os << parentPD << theDecayer << decayMode << extracted; } void RemnantData::persistentInput(PersistentIStream & is, int) { is >> parentPD >> theDecayer >> decayMode >> extracted; } ClassDescription RemnantData::initRemnantData; // Definition of the static class description member. void RemnantData::Init() { static ClassDocumentation documentation ("There is no documentation for the RemnantData class"); } diff --git a/PDT/RemnantData.h b/PDT/RemnantData.h --- a/PDT/RemnantData.h +++ b/PDT/RemnantData.h @@ -1,225 +1,225 @@ // -*- C++ -*- // // RemnantData.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_RemnantData_H #define THEPEG_RemnantData_H // // This is the declaration of the RemnantData class. // #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/PDT/RemnantData.fh" #include "ThePEG/PDT/RemnantDecayer.fh" #include "ThePEG/PDT/DecayMode.h" namespace ThePEG { /** * The RemnantData class is not a normal ParticleData class. It should * never be handled directly by the interface but is automatically * created and assigned to an object of the SoftRemnant sub-class of * Particle. The SoftRemnant in turn is not a proper Particle, but * rather a place holder for what is left of a colliding particle * after one or several partons has been extracted. To be able to * retrieve properties of the SoftRemnant through its ParticleData the * RemnantData is used to dynamically keep track of this. * * The RemnantData is initialized by the ParticleData corresponding to * the colliding particle. For each particle which is extracted the * charge charge is changed accordingly. Also the colour charge is * changed, but only such that the coloured(), hasColour() and * hasAntiColour() returns relevant information. The actual colour can * only be singlet, (anti-)triplet or octet. * * When created the RemnantData object must be given a RemnantDecayer * object and a single DecayMode object will be created with this * Decayer. * * @see \ref RemnantDataInterfaces "The interfaces" * defined for RemnantData. */ class RemnantData: public ParticleData { public: /** @name Standard constructors and destructors. */ //@{ /** * The standard constructor takes as argument the \a particle type * for which this is the remnant and a \a decayer capable of * performing the decay. */ RemnantData(tcPDPtr particle, RemDecPtr decayer); //@} public: /** * The Decayer responsible for for the decay of this remnant. */ const RemnantDecayer & decayer() const { return *theDecayer; }; /** * Modify the properties to reflect that the given \a parton was * extracted. */ bool extract(tcPDPtr parton); /** * Modify the properties to reflect that the given \a parton which was * previously extracted is removed. */ bool remove(tcPDPtr parton); /** * Modify the properties to reflect that the previously extracted * parton, \a oldp, was evolved backwards to the the parton \a newp. */ bool reextract(tcPDPtr oldp, tcPDPtr newp); protected: /** * Modify the colour to reflect that the given \a parton was * extracted. */ bool fixColour(); public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The particle type of the parent. */ tcPDPtr parentPD; /** * The Decayer responsible for for the decay of this remnant. */ RemDecPtr theDecayer; /** * The only DecayMode available for this remnant. */ DMPtr decayMode; /** * The set of extracted particle types. */ multiset extracted; protected: /** * The default constructor is protected and must only be used by the * PersistentIStream class via the ClassTraits class. */ RemnantData() {} /** * The ClassTraits class must be a friend to be able to * use the private default constructor. */ friend struct ClassTraits; private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initRemnantData; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ RemnantData & operator=(const RemnantData &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of RemnantData. */ template <> struct BaseClassTrait { /** Typedef of the first base class of RemnantData. */ typedef ParticleData NthBase; }; /** This template specialization informs ThePEG about the name of * the RemnantData 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::RemnantData"; } /** Create a Particle object. */ static TPtr create() { return TPtr::Create(RemnantData()); } }; /** @endcond */ } #endif /* THEPEG_RemnantData_H */ diff --git a/PDT/RemnantDecayer.cc b/PDT/RemnantDecayer.cc --- a/PDT/RemnantDecayer.cc +++ b/PDT/RemnantDecayer.cc @@ -1,272 +1,272 @@ // -*- C++ -*- // // RemnantDecayer.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the RemnantDecayer class. // #include "RemnantDecayer.h" #include "ThePEG/PDT/DecayMode.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/PDT/RemnantData.h" #include "ThePEG/PDT/StandardMatchers.h" #include "ThePEG/Utilities/EnumIO.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Utilities/Throw.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG; RemnantDecayer::~RemnantDecayer() {} bool RemnantDecayer::accept(const DecayMode &) const { return false; } bool RemnantDecayer::needsFullStep() const { return true; } bool RemnantDecayer:: canHandle(tcPDPtr, tcPDPtr) const { return false; } bool RemnantDecayer:: checkExtract(tcPPtr, tcPPtr, const LorentzMomentum & pnew) const { return pnew.e() > ZERO; } bool RemnantDecayer::multiCapable() const { return false; } ParticleVector RemnantDecayer:: decay(const DecayMode &, const Particle &) const { return ParticleVector(); } ParticleVector RemnantDecayer:: decay(const DecayMode & dm, const Particle & p, Step &) const { ParticleVector children; tcRemPPtr remnant = dynamic_ptr_cast(&p); if ( !remnant ) return children; tRemPDPtr rpd = data(remnant); PVector ex = extracted(remnant); tcPPtr par = parent(remnant); if ( !par || ex.empty() || !rpd ) return children; children= dm.produceProducts(); return children; } void RemnantDecayer:: fillSubSystem(tPPtr p, set & sub) const { // If this particle has already been added we're done. if ( member(sub, p) ) return; if ( respectDISKinematics() && !LeptonMatcher::Check(p->data()) && p->momentum().m2() < ZERO ) { // If this particle belongs to an electro-weak scattering vertex // it should be excluded. (more specifically part of a vertex // where the other particles are incoming and outgoing leptons // while this is not a lepton and is space-like) if ( p->children().size() == 1 && p->children()[0]->parents().size() == 2 && LeptonMatcher::Check(p->children()[0]->data()) && ( p->children()[0]->momentum().m2() >= ZERO || p->children()[0]->children().empty() ) && ( LeptonMatcher::Check(p->children()[0]->parents()[0]->data()) || LeptonMatcher::Check(p->children()[0]->parents()[1]->data()) ) ) return; if ( p->parents().size() == 1 && p->parents()[0]->children().size() == 2 && LeptonMatcher::Check(p->parents()[0]->data()) && ( ( LeptonMatcher::Check(p->parents()[0]->children()[0]->data()) && ( p->parents()[0]->children()[0]->momentum().m2() >= ZERO || p->parents()[0]->children()[0]->children().empty() ) ) || ( LeptonMatcher::Check(p->parents()[0]->children()[1]->data()) && ( p->parents()[0]->children()[1]->momentum().m2() >= ZERO || p->parents()[0]->children()[1]->children().empty() ) ) ) ) return; } sub.insert(p); // Fill in children. if ( p->next() ) fillSubSystem(p->next(), sub); for ( int i = 0, N = p->children().size(); i < N; ++i ) fillSubSystem(p->children()[i], sub); // Fill also parents, but only if this is not an incoming parton // coming from a particle with a soft remnant. Also if this is an // incoming particle (with no parents) is is ignored. if ( p->previous() ) fillSubSystem(p->previous(), sub); for ( int i = 0, N = p->parents().size(); i < N; ++i ) { tPPtr parent = p->parents()[i]; if ( member(sub, parent) ) continue; if ( parent->parents().empty() ) continue; for ( int j = 0, M = parent->children().size(); j < M; ++j ) if ( dynamic_ptr_cast(parent->children()[j]) ) { parent = tPPtr(); break; } if ( parent ) fillSubSystem(parent, sub); } } tPVector RemnantDecayer::getSubSystem(tcPPtr parent, tPPtr parton) const { tPVector ret; Axis dir = parent->momentum()/GeV; set sub; fillSubSystem(parton, sub); multimap ordsub; for ( set::iterator it = sub.begin(); it != sub.end(); ++it ) { if ( (**it).children().size() || (**it).next() ) continue; try { ordsub.insert(make_pair(-(**it).momentum().rapidity(dir), *it)); } catch ( ... ) { Throw() << "Could not find subsystem for shuffling momenta in RemnantDecayer." << Exception::eventerror; } } ret.reserve(ordsub.size()); for ( multimap::iterator it = ordsub.begin(); it != ordsub.end(); ++it ) ret.push_back(it->second); return ret; } LorentzRotation RemnantDecayer:: getZBoost(const LorentzMomentum & p0, const LorentzMomentum & p) { LorentzRotation R; if ( p.z() > ZERO ) R.setBoostZ((sqr(p.plus()) - sqr(p0.plus()))/ (sqr(p.plus()) + sqr(p0.plus()))); else R.setBoostZ((sqr(p0.minus()) - sqr(p.minus()))/ (sqr(p0.minus()) + sqr(p.minus()))); return R; } tPVector RemnantDecayer:: decayRemnants(const tPVector & particles, Step & step) { tPVector final; tPVector remnants; for ( int i = 0, N= particles.size(); i < N; ++i ) if ( dynamic_ptr_cast(particles[i]) ) remnants.push_back(particles[i]); else final.push_back(particles[i]); while ( !remnants.empty() ) { int i = UseRandom::irnd(remnants.size()); ParticleVector children = Decayer::DecayParticle(remnants[i], step); final.insert(final.end(), children.begin(), children.end()); remnants.erase(remnants.begin() + i); } // The final particles may have received a pt-kick and would then be // copied. Go through and find the final particles. for ( int i = 0, N = final.size(); i < N; ++ i) final[i] = final[i]->final(); return final; } bool RemnantDecayer::preInitialize() const { return Decayer::preInitialize() || !pTGenerator(); } void RemnantDecayer::doinit() { Decayer::doinit(); if ( pTGenerator() ) return; thePTGenerator = dynamic_ptr_cast (generator()->preinitCreate("ThePEG::GaussianPtGenerator", fullName() + "/PtGen", "GaussianPtGenerator.so")); } void RemnantDecayer::persistentOutput(PersistentOStream & os) const { os << oenum(theRecoilOption) << respectDIS << thePTGenerator; } void RemnantDecayer::persistentInput(PersistentIStream & is, int) { is >> ienum(theRecoilOption) >> respectDIS >> thePTGenerator; } AbstractClassDescription RemnantDecayer::initRemnantDecayer; // Definition of the static class description member. void RemnantDecayer::Init() { static ClassDocumentation documentation ("The RemnantDecayer class is the base class to be used for all " "decayers capable of decaying a RemnantParticle object produced by a " "SoftRemnantHandler object."); static Switch interfaceRecoilOption ("RecoilOption", "Different options for how to distribute recoils in the hard subsystem " "when taking energy to produce remnants.", &RemnantDecayer::theRecoilOption, copyFinal, true, false); static SwitchOption interfaceRecoilOptionCopyFinal (interfaceRecoilOption, "CopyFinal", "Boost copies of final state particles in hard subsystem.", copyFinal); static SwitchOption interfaceRecoilOptionBoostFinal (interfaceRecoilOption, "BoostFinal", "Boost only final state particles in hard subsystem.", boostFinal); static SwitchOption interfaceRecoilOptionBoostAll (interfaceRecoilOption, "BoostAll", "Boost all particles in the hard subsystem.", boostAll); static Switch interfaceRespectDISKinematics ("RespectDISKinematics", "If true, do not boost a scattered lepton (and possible radiated " "photons) in a DIS event, to ensure that \f$x\f$ and \f$Q^2\f$ is " "unmodified.", &RemnantDecayer::respectDIS, 2, true, false); static SwitchOption interfaceRespectDISKinematicsYes (interfaceRespectDISKinematics, "Yes", "Do not boost scattered lepton. If that doesn't work, include " "the scattered lepton and emit a warning message.", 1); static SwitchOption interfaceRespectDISKinematicsNo (interfaceRespectDISKinematics, "No", "Boost scattered lepton together with the rest of the hard subsystem.", 0); static SwitchOption interfaceRespectDISKinematicsTry (interfaceRespectDISKinematics, "Try", "Do not boost scattered lepton. If that doesn't work, silently " "include the scattered lepton.", 2); static Reference interfacePTGenerator ("PTGenerator", "An object capable of generating an intrinsic transverse momentum of " "the created remnants. If not set and the controlling EventGenerator " "has a default PtGenerator object, this will be used. Otherwise a " "GaussianPtGenerator object created with default settings in the " "initialization will be used instead.", &RemnantDecayer::thePTGenerator, true, false, true, true, true); } diff --git a/PDT/RemnantDecayer.h b/PDT/RemnantDecayer.h --- a/PDT/RemnantDecayer.h +++ b/PDT/RemnantDecayer.h @@ -1,325 +1,325 @@ // -*- C++ -*- // // RemnantDecayer.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_RemnantDecayer_H #define THEPEG_RemnantDecayer_H // // This is the declaration of the RemnantDecayer class. // #include "ThePEG/PDT/Decayer.h" #include "RemnantDecayer.fh" #include "ThePEG/PDT/RemnantData.h" #include "ThePEG/EventRecord/RemnantParticle.h" #include "ThePEG/Handlers/PtGenerator.h" namespace ThePEG { /** * The RemnantDecayer class is the base class to be used for all * decayers capable of decaying a RemnantParticle object produced by a * SoftRemnantHandler object. A derived class must implement the * decay(const DecayMode &, const Particle &, Step &) function, while * the decay(const DecayMode &, const Particle &) function should * never be called. * * @see \ref RemnantDecayerInterfaces "The interfaces" * defined for RemnantDecayer. */ class RemnantDecayer: public Decayer { public: /** A pointer to a PtGenerator object. */ typedef Ptr::pointer PtGPtr; public: /** * Enumerate the options for how to distribute recoils in the hard * subsystem when taking energy to produce remnants. */ enum RecoilOption { boostAll, /**< Boost all particles in the hard subsystem. */ boostFinal, /**< Boost only final state particles in hard subsystem. */ copyFinal /**< Boost copies of final state particles in hard subsystem. */ }; public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ RemnantDecayer() : respectDIS(2), theRecoilOption(copyFinal) {} /** * The destructor. */ virtual ~RemnantDecayer(); //@} public: /** @name Virtual functions required by the Decayer class. */ //@{ /** * Check if this decayer can perfom the decay specified by the * given decay mode. * @param dm the DecayMode describing the decay. * @return true if this decayer can handle the given mode, otherwise false. */ virtual bool accept(const DecayMode & dm) const; /** * Return true if this Decayer need to access the full current step * when a particle is decayed. If true is returned the standard * Decay Handler will call the decay(const DecayMode&,const * Particle&,Step&) function rather than the decay(const * DecayMode&,const Particle&) function. */ virtual bool needsFullStep() const; /** * Perform a decay for a given DecayMode and a given Particle * instance. This version allows the decaying particle to borrow * energy/momentum from its sublings in the current step. This will * be called by the standard DecayHandler if the needsFullStep() * function returns true. * * @param dm the DecayMode describing the decay. * @param p the Particle instance to be decayed. * @param step the current step in which to find possible siblings to * shuffle energy with. * @return a ParticleVector containing the decay products. */ virtual ParticleVector decay(const DecayMode & dm, const Particle & p, Step & step) const = 0; /** * Perform a decay for a given DecayMode and a given Particle instance. * @param dm the DecayMode describing the decay. * @param p the Particle instance to be decayed. * @return a ParticleVector containing the decay products. */ virtual ParticleVector decay(const DecayMode & dm, const Particle & p) const; //@} /** * Return true if this decayer can handle the extraction of the \a * extracted parton from the given \a particle. */ virtual bool canHandle(tcPDPtr parent, tcPDPtr extracted) const; /** * Return true if this decayer can handle the extraction of the \a * extracted parton instance from the given \a particle instance. \a * pnew is the momentum of the resulting remnant. The default * version simply checks if the energy is positive. */ virtual bool checkExtract(tcPPtr parent, tcPPtr extracted, const LorentzMomentum & pnew) const; /** * Return true if this decayed can extract more than one parton from * a particle. */ virtual bool multiCapable() const; /** * The option for how to distribute recoils in the hard subsystem * when taking energy to produce remnants. */ RecoilOption recoilOption() const { return theRecoilOption; } /** * If true, do not boost a scattered lepton (and possible radiated * photons) in a DIS event, to ensure that \f$x\f$ and \f$Q^2\f$ is * unmodified. */ int respectDISKinematics() const { return respectDIS; } /** * An object capable of generating an intrinsic transverse momentum * of the created remnants. */ PtGPtr pTGenerator() const { return thePTGenerator; } /** * Static function to decay al remnants among the given \a * particles. The decay products are inserted in the \a step * provided. * @return a vector of the non-remnant particles together with the * remnant decay products. */ static tPVector decayRemnants(const tPVector & particles, Step & step); protected: /** * Access the RemnantData object of a \a remnant. */ tRemPDPtr data(tcRemPPtr remnant) const { return remnant->remData; } /** * Access the parent of a \a remnant. */ tcPPtr parent(tcRemPPtr remnant) const { return remnant->parent; } /** * Access the vector of extracted particles of a \a remnant. */ const PVector & extracted(tcRemPPtr remnant) const { return remnant->extracted(); } /** * Recursively find all particles produced from an extracted parton. */ virtual void fillSubSystem(tPPtr p, set & sub) const; /** * Return the system of particles from the hard subsystem which may * be used to shuffle momenta to get the remnants on-shell. In this * version the particles are ordered in rapidity with the ones * closest to the remnant direction comes first. Other orderings can * be enforced by sub-classes. */ virtual tPVector getSubSystem(tcPPtr parent, tPPtr parton) const; /** * Return a small boost along the z-axis. To cure rounding errors * when making large boosts it is sometimes necessary to correct the * plus (or minus) lightcone component with a small boost along the * z-axis. The resulting boost is constructed so that the momentum * \a p0 would be transformed to have the sam z-value as the * momentum \a p. */ static LorentzRotation getZBoost(const LorentzMomentum & p0, const LorentzMomentum & p); public: /** * Exception used if getSubSystem fails. */ struct SubSystemFail: public Exception {}; 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(); /** * Return true if this object needs to be initialized before all * other objects because it needs to extract cuts from the event file. */ virtual bool preInitialize() const; //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** * If true, do not boost a scattered lepton (and possible radiated * photons) in a DIS event, to ensure that \f$x\f$ and \f$Q^2\f$ is * unmodified. */ mutable int respectDIS; private: /** * The option for how to distribute recoils in the hard subsystem * when taking energy to produce remnants. */ RecoilOption theRecoilOption; /** * An object capable of generating an intrinsic transverse momentum * of the created remnants. */ PtGPtr thePTGenerator; private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static AbstractClassDescription initRemnantDecayer; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ RemnantDecayer & operator=(const RemnantDecayer &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of RemnantDecayer. */ template <> struct BaseClassTrait { /** Typedef of the first base class of RemnantDecayer. */ typedef Decayer NthBase; }; /** This template specialization informs ThePEG about the name of * the RemnantDecayer 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::RemnantDecayer"; } }; /** @endcond */ } #endif /* THEPEG_RemnantDecayer_H */ diff --git a/PDT/SimpleBaryonRemnantDecayer.cc b/PDT/SimpleBaryonRemnantDecayer.cc --- a/PDT/SimpleBaryonRemnantDecayer.cc +++ b/PDT/SimpleBaryonRemnantDecayer.cc @@ -1,397 +1,397 @@ // -*- C++ -*- // // SimpleBaryonRemnantDecayer.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the SimpleBaryonRemnantDecayer class. // #include "SimpleBaryonRemnantDecayer.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/PDT/DecayMode.h" #include "ThePEG/PDT/RemnantData.h" #include "ThePEG/PDT/StandardMatchers.h" #include "ThePEG/Utilities/UtilityBase.h" #include "ThePEG/Utilities/SimplePhaseSpace.h" #include "ThePEG/Utilities/HoldFlag.h" #include "ThePEG/Utilities/Throw.h" #include "ThePEG/PDF/BeamParticleData.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/EventRecord/Step.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG; SimpleBaryonRemnantDecayer::~SimpleBaryonRemnantDecayer() {} IBPtr SimpleBaryonRemnantDecayer::clone() const { return new_ptr(*this); } IBPtr SimpleBaryonRemnantDecayer::fullclone() const { return new_ptr(*this); } bool SimpleBaryonRemnantDecayer::accept(const DecayMode &) const { return true; } bool SimpleBaryonRemnantDecayer:: canHandle(tcPDPtr particle, tcPDPtr parton) const { return BaryonMatcher::Check(*particle) && StandardQCDPartonMatcher::Check(*parton); } bool SimpleBaryonRemnantDecayer:: checkExtract(tcPPtr parent, tcPPtr parton, const LorentzMomentum & pnew) const { return pnew.e() > parent->nominalMass() + parton->data().constituentMass(); } ParticleVector SimpleBaryonRemnantDecayer:: decay(const DecayMode & dm, const Particle & p, Step & step) const { ParticleVector children; tcRemPPtr remnant = dynamic_ptr_cast(&p); if ( !remnant ) return children; tRemPDPtr rpd = data(remnant); PVector ex = extracted(remnant); tcPPtr particle = parent(remnant); if ( !particle || ex.empty() || !rpd ) return children; // We can't handle multiple extractions (yet) if ( ex.size() != 1 ) return children; tPPtr parton = ex[0]; tPVector subsys = getSubSystem(particle, parton); tPVector subpart; LorentzMomentum pitot = Utilities::sumMomentum(subsys) + remnant->momentum(); Energy2 s = ZERO; Energy2 shat = ZERO; LorentzMomentum psub; Energy minmass = particle->nominalMass() + 2.0*parton->nominalMass() + margin(); unsigned int closeskip = 0; while ( closeskip < subsys.size() ) { subpart = tPVector(subsys.begin() + closeskip, subsys.end()); while ( !subpart.empty() ) { psub = Utilities::sumMomentum(subpart); s = max((remnant->momentum() + psub).m2(), ZERO); shat = max(psub.m2(), ZERO); if ( subpart.size() == 1 ) shat = max(subpart[0]->momentum().mass2(), ZERO); if ( sqrt(s) > sqrt(shat) + minmass ) break; subpart.pop_back(); } if ( !subpart.empty() ) break; ++closeskip; } if ( subpart.empty() ) { if ( respectDISKinematics() ) { // If we couldn't find any way of shuffling momentum and this may // have been a DIS event, try to include the scattered lepton as // well. { HoldFlag nodis(respectDIS, 0); children = decay(dm, p, step); } if ( respectDISKinematics() == 1 ) Throw() << "The decay of the remnant '" << p.PDGName() << "' changed the kinematics of a scattered lepton in a DIS event.\n" << *step.collision()->event() << Exception::warning; return children; } else { Throw() << "Could not decay remnant '" << p.PDGName() << "' since not enough energy-momentum was available." << Exception::eventerror; } } const BaryonContent & bi = getBaryonInfo(particle->dataPtr()); // Check if we are extracting a valence quark int iq = parton->id(); vector vflav = bi.flav; vector::iterator v = find(vflav.begin(), vflav.end(), bi.sign*iq); double pval = 0.0; if ( v != vflav.end() ) { vflav.erase(v); tcPDFPtr pdf; const BeamParticleData * beamp = dynamic_cast(&*particle->dataPtr()); if ( beamp ) pdf = beamp->pdf(); if ( pdf && !specialValence() ) { Energy2 scale = abs(parton->scale()); double x = shat/s; pval = pdf->xfvx(particle->dataPtr(), parton->dataPtr(), scale, x)/ pdf->xfx(particle->dataPtr(), parton->dataPtr(), scale, x); } else { pval = 1; } } Energy mr = ZERO; while ( true ) { children.clear(); if ( rndbool(pval) ) { // A simple valence remnant. int idqr = 1000*max(vflav[0], vflav[1]) + 100*min(vflav[0], vflav[1]) + 3; if ( vflav[0] != vflav[1] && rndbool(0.25) ) idqr -= 2; children.push_back(getParticleData(bi.sign*idqr)->produceParticle()); mr = children[0]->mass(); } else { // We haven't extracted a valence so we first divide up the baryon // in a quark and a diquark. pair r = bi.flavsel.select(UseRandom::current()); int iqr = r.first*bi.sign; int idqr = r.second*bi.sign; if ( iq == ParticleID::g ) { children.push_back(getParticleData(iqr)->produceParticle()); children.push_back(getParticleData(idqr)->produceParticle()); } else if ( iq*iqr > 0 ) { children.push_back(getParticleData(idqr)->produceParticle()); children.push_back(flavourGenerator().getHadron (getParticleData(-iq), getParticleData(iqr))->produceParticle()); } else { children.push_back(getParticleData(iqr)->produceParticle()); children.push_back(flavourGenerator().getHadron (getParticleData(-iq), getParticleData(idqr))->produceParticle()); } TransverseMomentum ptr = pTGenerator()->generate(); Energy2 mt02 = children[0]->momentum().mass2() + ptr.pt2(); Energy2 mt12 = children[1]->momentum().mass2() + ptr.pt2(); double z = zGenerator().generate(children[1]->dataPtr(), children[0]->dataPtr(), mt12); mr = sqrt(mt02/(1.0 - z) + mt12/z); if ( sqrt(s) <= sqrt(shat) + mr ) continue; children[0]->set3Momentum(static_cast (lightCone((1.0 - z)*mr, mt02/((1.0 - z)*mr), ptr))); children[1]->set3Momentum(static_cast (lightCone(z*mr, mt12/(z*mr), -ptr))); } break; } // Make copies of all final particles in the hard subsystem which // will take recoil. for ( unsigned int i = 0, N = subsys.size(); i < N; ++i ) { if ( subsys[i]->birthStep() != &step ) subsys[i] = step.copyParticle(subsys[i]); if ( i >= closeskip && i - closeskip < subpart.size() ) subpart[i - closeskip] = subsys[i]; } // Boost part of the hard subsystem to give energy to the new // remnants. LorentzMomentum pr = remnant->momentum(); LorentzRotation R = Utilities::getBoostToCM(make_pair(psub, pr)); Energy pz = SimplePhaseSpace::getMagnitude(s, sqrt(shat), mr); if ( subpart.size() > 1 ) { LorentzRotation Rs(-(R*psub).boostVector()); Rs.boost(0.0, 0.0, pz/sqrt(sqr(pz) + shat)); Rs = Rs*R; R.invert(); Rs = R*Rs; Utilities::transform(subpart, Rs); } else { subpart[0]->set5Momentum( Lorentz5Momentum(ZERO, ZERO, pz, sqrt(sqr(pz) + shat), sqrt(shat))); R.invert(); Utilities::transform(subpart, R); } LorentzRotation Rr(0.0, 0.0, -pz/sqrt(sqr(pz) + sqr(mr))); Rr = R*Rr; Utilities::transform(children, Rr); // Give the remnants and subsystem a transverse momentum by Lorentz // rotations. LorentzMomentum pr0 = ( pr = Utilities::sumMomentum(children) ); LorentzMomentum psub0 = ( psub = Utilities::sumMomentum(subsys) ); LorentzMomentum ksub = pr + psub - particle->momentum(); R = Utilities::boostToCM(make_pair(&psub, &pr)); TransverseMomentum kt; do { kt = pTGenerator()->generate(); } while ( kt.pt() >= psub.z() ); LorentzRotation Rtot = R; Rtot.rotateY(asin(kt.pt()/psub.z())); Rtot.rotateZ(kt.phi()); Rtot = R.inverse()*Rtot; psub = Rtot*psub0; pr = Rtot*pr0; Utilities::transform(children, Rtot); if ( subsys.size() > 1 ) Utilities::transform(subsys, Utilities::getTransformToMomentum(psub0, psub, ksub)); else subsys[0]->setMomentum(psub); // Make small z-boosts to correct Utilities::transform(subsys, getZBoost(Utilities::sumMomentum(subsys), psub)); LorentzMomentum pftot = Utilities::sumMomentum(subsys) + Utilities::sumMomentum(children); R = getZBoost(pftot, pitot); Utilities::transform(subsys, R); Utilities::transform(children, R); return children; } const SimpleBaryonRemnantDecayer::BaryonContent & SimpleBaryonRemnantDecayer::getBaryonInfo(tcPDPtr baryon) const { map::iterator it = baryonmap.find(baryon); if ( it != baryonmap.end() ) return it->second; BaryonContent & bi = baryonmap[baryon]; int pid = baryon->id(); bi.sign = pid < 0? -1: 1; bi.flav = vector(3); bi.flav[0] = (pid = abs(pid)/10)%10; bi.flav[1] = (pid /= 10)%10; bi.flav[2] = (pid /= 10)%10; bi.flavsel = VSelector< pair >(); for ( int iq1 = 0; iq1 < 3; ++iq1 ) { int iq2 = (iq1 + 1)%3; int iq3 = (iq2 + 1)%3; int idq = 1000*max(bi.flav[iq2], bi.flav[iq3]) + 100*min(bi.flav[iq2], bi.flav[iq3]) + 3; bi.flavsel.insert(3.0, make_pair(bi.flav[iq1], idq)); if ( bi.flav[iq2] == bi.flav[iq3] ) continue; bi.flavsel.insert(1.0, make_pair(bi.flav[iq1], idq - 2)); } return bi; } bool SimpleBaryonRemnantDecayer::preInitialize() const { return RemnantDecayer::preInitialize() || !theZGenerator || !theFlavourGenerator; } void SimpleBaryonRemnantDecayer::doinit() { RemnantDecayer::doinit(); if ( !theZGenerator ) { theZGenerator = dynamic_ptr_cast (generator()->preinitCreate("ThePEG::SimpleZGenerator", fullName() + "/ZGen", "SimpleZGenerator.so")); } if ( !theFlavourGenerator ) { theFlavourGenerator = dynamic_ptr_cast (generator()->preinitCreate("ThePEG::SimpleFlavour", fullName() + "/FlavGen", "SimpleFlavour.so")); } } void SimpleBaryonRemnantDecayer:: persistentOutput(PersistentOStream & os) const { os << theZGenerator << theFlavourGenerator << ounit(theMargin,GeV) << useSpecialValence; } void SimpleBaryonRemnantDecayer:: persistentInput(PersistentIStream & is, int) { is >> theZGenerator >> theFlavourGenerator >> iunit(theMargin,GeV) >> useSpecialValence; } ClassDescription SimpleBaryonRemnantDecayer::initSimpleBaryonRemnantDecayer; // Definition of the static class description member. void SimpleBaryonRemnantDecayer::Init() { static ClassDocumentation documentation ("The SimpleBaryonRemnantDecayer class inherits from the RemnantDecayer " "class and is able to decay RemnantParticles produced by the " "SoftRemnantHandler class for the cases when a single parton has been " "extracted from a baryon."); static Reference interfaceZGenerator ("ZGenerator", "The object responsible for generating momentum fractions in case " "of more than one remnant. If not set and the controlling EventGenerator " "has a default ZGenerator object, this will be used. Otherwise a " "SimpleZGenerator object created with default settings in the " "initialization will be used instead.", &SimpleBaryonRemnantDecayer::theZGenerator, true, false, true, true, true); static Reference interfaceFlavourGenerator ("FlavourGenerator", "The object responsible for handling the flavour contents of a baryon. " "If not set and the controlling EventGenerator " "has a default FlavourGenerator object, this will be used. Otherwise a " "SimpleFlavour object created with default settings in the " "initialization will be used instead.", &SimpleBaryonRemnantDecayer::theFlavourGenerator, true, false, true, true, true); static Parameter interfaceMargin ("EnergyMargin", "The energy margin (in GeV) to be added to the sum of the parent and " "parton masses to determine if it is possible to construct the remnants " "with the given (upper limit of the) virtuality of the extracted parton.", &SimpleBaryonRemnantDecayer::theMargin, GeV, 1.0*GeV, ZERO, 10.0*GeV, false, false, true); static Switch interfaceSpecialValence ("SpecialValence", "If true, an extracted valence quark will always give a di-quark remnant.", &SimpleBaryonRemnantDecayer::useSpecialValence, false, true, false); static SwitchOption interfaceSpecialValenceYes (interfaceSpecialValence, "Yes", "An extracted valence quark will always give a di-quark remnant.", true); static SwitchOption interfaceSpecialValenceNo (interfaceSpecialValence, "No", "An extracted valence flavour may be considered to be a sea-quark.", false); interfaceZGenerator.rank(8); interfaceFlavourGenerator.rank(7); } diff --git a/PDT/SimpleBaryonRemnantDecayer.h b/PDT/SimpleBaryonRemnantDecayer.h --- a/PDT/SimpleBaryonRemnantDecayer.h +++ b/PDT/SimpleBaryonRemnantDecayer.h @@ -1,308 +1,308 @@ // -*- C++ -*- // // SimpleBaryonRemnantDecayer.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_SimpleBaryonRemnantDecayer_H #define THEPEG_SimpleBaryonRemnantDecayer_H // // This is the declaration of the SimpleBaryonRemnantDecayer class. // #include "ThePEG/PDT/RemnantDecayer.h" #include "ThePEG/Handlers/ZGenerator.h" #include "ThePEG/Handlers/FlavourGenerator.h" #include "ThePEG/Utilities/VSelector.h" namespace ThePEG { /** * The SimpleBaryonRemnantDecayer class inherits from the * RemnantDecayer class and is able to decay RemnantParticles produced * by the SoftRemnantHandler class for the cases when a single parton * has been extracted from a baryon. * * @see \ref SimpleBaryonRemnantDecayerInterfaces "The interfaces" * defined for SimpleBaryonRemnantDecayer. */ class SimpleBaryonRemnantDecayer: public RemnantDecayer { public: /** A pointer to a ZGenerator object. */ typedef Ptr::pointer ZGPtr; /** A pointer to a FlavourGenerator object. */ typedef Ptr::pointer FlGPtr; public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ SimpleBaryonRemnantDecayer() : theMargin(1.0*GeV), useSpecialValence(false) {} /** * The copy constructor. */ SimpleBaryonRemnantDecayer(const SimpleBaryonRemnantDecayer & x) : RemnantDecayer(x), theZGenerator(x.theZGenerator), theFlavourGenerator(x.theFlavourGenerator), theMargin(x.theMargin), useSpecialValence(x.useSpecialValence) {} /** * The destructor. */ virtual ~SimpleBaryonRemnantDecayer(); //@} public: /** @name Virtual functions required by the RemnantDecayer class. */ //@{ /** * Check if this decayer can perfom the decay specified by the * given decay mode. * @param dm the DecayMode describing the decay. * @return true if this decayer can handle the given mode, otherwise false. */ virtual bool accept(const DecayMode & dm) const; /** * Perform a decay for a given DecayMode and a given Particle * instance. This version allows the decaying particle to borrow * energy/momentum from its sublings in the current step. This will * be called by the standard DecayHandler if the needsFullStep() * function returns true. * * @param dm the DecayMode describing the decay. * @param p the Particle instance to be decayed. * @param step the current step in which to find possible siblings to * shuffle energy with. * @return a ParticleVector containing the decay products. */ virtual ParticleVector decay(const DecayMode & dm, const Particle & p, Step & step) const; /** * Return true if this decayer can handle the extraction of the \a * extracted parton from the given \a particle. */ virtual bool canHandle(tcPDPtr parent, tcPDPtr extracted) const; /** * Return true if this decayer can handle the extraction of the \a * extracted parton instance from the given \a particle instance. \a * pnew is the momentum of the resulting remnant. The default * version simply checks if the energy is positive. */ virtual bool checkExtract(tcPPtr parent, tcPPtr extracted, const LorentzMomentum & pnew) 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(); /** * Return true if this object needs to be initialized before all * other objects because it needs to extract cuts from the event file. */ virtual bool preInitialize() const; //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); public: /** * Warning Exception used when DIS kinematics was not respected. */ struct NoDISRespect: public Exception {}; /** * Exception thrown if the decay of a remnant was impossible. */ struct DecayFailed: public Exception {}; public: /** * Return a reference to the object responsible for generating * momentum fractions in case of more than one remnant. */ ZGenerator & zGenerator() const { return *theZGenerator; } /** * Return a reference to the object responsible for handling the * flavour contents of a baryon. */ FlavourGenerator & flavourGenerator() const { return *theFlavourGenerator; } /** * Return the energy margin to be added to the sum of the parent and * parton masses to determine if it is possible to construct the * remnants with the given (upper limit of the) virtuality of the * extracted parton. */ Energy margin() const { return theMargin; } /** * If true an extracted valens quark will always give a di-quark remnant. */ bool specialValence() const { return useSpecialValence; } 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; //@} public: /** * Simple struct to store info about baryon quark and di-quark * constituents. */ struct BaryonContent { /** The valence flavours of the corresponding baryon. */ vector flav; /** Different divisions into quark-diquark weighted by their respective probabilities. */ VSelector< pair > flavsel; /** -1 if the particle is an anti-particle. +1 otherwise. */ int sign; }; /** * Return info about baryon quark and di-quark constituents. */ const BaryonContent & getBaryonInfo(tcPDPtr baryon) const; private: /** * The object responsible for generating momentum fractions in case * of more than one remnant. */ ZGPtr theZGenerator; /** * The object responsible for handling the flavour contents of a * baryon. */ FlGPtr theFlavourGenerator; /** * The energy margin to be added to the sum of the parent and parton * masses to determine if it is possible to construct the remnants * with the given (upper limit of the) virtuality of the extracted * parton. */ Energy theMargin; /** * If true an extracted valens quark will always give a di-quark remnant. */ bool useSpecialValence; /** * A map of info about baryon quark and di-quark constituents. */ mutable map baryonmap; private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initSimpleBaryonRemnantDecayer; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ SimpleBaryonRemnantDecayer & operator=(const SimpleBaryonRemnantDecayer &) = delete; }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of SimpleBaryonRemnantDecayer. */ template <> struct BaseClassTrait { /** Typedef of the first base class of SimpleBaryonRemnantDecayer. */ typedef RemnantDecayer NthBase; }; /** This template specialization informs ThePEG about the name of the * SimpleBaryonRemnantDecayer 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::SimpleBaryonRemnantDecayer"; } }; /** @endcond */ } #endif /* THEPEG_SimpleBaryonRemnantDecayer_H */ diff --git a/PDT/StandardMatchers.h b/PDT/StandardMatchers.h --- a/PDT/StandardMatchers.h +++ b/PDT/StandardMatchers.h @@ -1,359 +1,359 @@ // -*- C++ -*- // // StandardMatchers.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_StandardMatchers_H #define ThePEG_StandardMatchers_H // This is the declaration of the AnyMatcher, #include "Matcher.h" #include "ThePEG/PDT/EnumParticles.h" namespace ThePEG { /** \file StandardMatchers.h * * This file declare a set of standard matcher classes. The * ChargedMatcher, NegativeMatcher, PositiveMatcher, NeutralMatcher, * BaryonMatcher, MesonMatcher, DiquarkMatcher, LeptonMatcher, * LightAntiQuarkMatcher, LightQuarkMatcher and * StandardQCDPartonMatcher classes can be used by themselves (with * their static functions) or together with the Matcher class to * define Interfaced objects of the MatcherBase type to be used in the * Repository. Suitable typedefs are declared for the latter. * * @see Matcher * @see MatcherBase */ /** * A Matcher class which matches any particle. */ struct AnyMatcher: public MatcherType { /** Typedef the class matching the complex conjugate particles. */ typedef AnyMatcher CC; /** The main static function to check if a given particle type \a pd matches. */ static bool Check(const ParticleData & pd) { return bool(pd.id()); } /** A simplified but unique class name. */ static string className() { return "Any"; } }; /** Gives a MatcherBase class based on AnyMatcher. */ typedef Matcher MatchAny; /** * A Matcher class which matches any charged particle. */ struct ChargedMatcher: public MatcherType { /** Typedef the class matching the complex conjugate particles. */ typedef ChargedMatcher CC; /** The main static function to check if a given particle type \a pd matches. */ static bool Check(const ParticleData & pd) { return PDT::charged(pd.iCharge()); } /** A simplified but unique class name. */ static string className() { return "Charged"; } }; /** Gives a MatcherBase class based on ChargedMatcher. */ typedef Matcher MatchCharged; struct NegativeMatcher; /** * A Matcher class which matches any positively charged particle. */ struct PositiveMatcher: public MatcherType { /** Typedef the class matching the complex conjugate particles. */ typedef NegativeMatcher CC; /** The main static function to check if a given particle type \a pd matches. */ static bool Check(const ParticleData & pd) { return PDT::positive(pd.iCharge()); } /** A simplified but unique class name. */ static string className() { return "Positive"; } }; /** Gives a MatcherBase class based on PositiveMatcher. */ typedef Matcher MatchPositive; /** * A Matcher class which matches any uncharged particle. */ struct NeutralMatcher: public MatcherType { /** Typedef the class matching the complex conjugate particles. */ typedef NeutralMatcher CC; /** The main static function to check if a given particle type \a pd matches. */ static bool Check(const ParticleData & pd) { return pd.iCharge() == PDT::Charge0; } /** A simplified but unique class name. */ static string className() { return "Neutral"; } }; /** Gives a MatcherBase class based on NeutralMatcher. */ typedef Matcher MatchNeutral; /** * A Matcher class which matches any negatively charged particle. */ struct NegativeMatcher: public MatcherType { /** Typedef the class matching the complex conjugate particles. */ typedef PositiveMatcher CC; /** The main static function to check if a given particle type \a pd matches. */ static bool Check(const ParticleData & pd) { return PDT::negative(pd.iCharge()); } /** A simplified but unique class name. */ static string className() { return "Negative"; } }; /** Gives a MatcherBase class based on NegativeMatcher. */ typedef Matcher MatchNegative; /** * A Matcher class which matches any baryon. */ struct BaryonMatcher: public MatcherType { /** Typedef the class matching the complex conjugate particles. */ typedef BaryonMatcher CC; /** The main static function to check if a given particle type \a pd matches. */ static bool Check(const ParticleData & pd) { return Check(pd.id()); } /** The main static function to check if a given particle with type \a id matches. */ static bool Check(long id) { return (id/10)%10 && (id/100)%10 && (id/1000)%10; } /** A simplified but unique class name. */ static string className() { return "Baryon"; } }; /** Gives a MatcherBase class based on BaryonMatcher. */ typedef Matcher MatchBaryon; /** * A Matcher class which matches any meson. */ struct MesonMatcher: public MatcherType { /** Typedef the class matching the complex conjugate particles. */ typedef MesonMatcher CC; /** The main static function to check if a given particle type \a pd matches. */ static bool Check(const ParticleData & pd) { return Check(pd.id()); } /** The main static function to check if a given particle with type \a id matches. */ static bool Check(long id) { return (id/10)%10 && (id/100)%10 && (id/1000)%10 == 0; } /** A simplified but unique class name. */ static string className() { return "Meson"; } }; /** Gives a MatcherBase class based on MesonMatcher. */ typedef Matcher MatchMeson; /** * A Matcher class which matches any (anti-)diquark. */ struct DiquarkMatcher: public MatcherType { /** Typedef the class matching the complex conjugate particles. */ typedef DiquarkMatcher CC; /** The main static function to check if a given particle type \a pd matches. */ static bool Check(const ParticleData & pd) { return Check(pd.id()); } /** The main static function to check if a given particle with type \a id matches. */ static bool Check(long id) { return id/10 && (id/10)%10 == 0 && (id/100)%10 && (id/1000)%10; } /** A simplified but unique class name. */ static string className() { return "Diquark"; } }; /** Gives a MatcherBase class based on DiquarkMatcher. */ typedef Matcher MatchDiquark; /** * A Matcher class which matches any (anti-)quark. */ struct QuarkMatcher: public MatcherType { /** Typedef the class matching the complex conjugate particles. */ typedef QuarkMatcher CC; /** The main static function to check if a given particle type \a pd matches. */ static bool Check(const ParticleData & pd) { return Check(pd.id()); } /** The main static function to check if a given particle with type \a id matches. */ static bool Check(long id) { return id && abs(id) < 10; } /** A simplified but unique class name. */ static string className() { return "Quark"; } }; /** Gives a MatcherBase class based on QuarkMatcher. */ typedef Matcher MatchQuark; /** * A Matcher class which matches any lepton. */ struct LeptonMatcher: public MatcherType { /** Typedef the class matching the complex conjugate particles. */ typedef LeptonMatcher CC; /** The main static function to check if a given particle type \a pd matches. */ static bool Check(const ParticleData & pd) { return Check(pd.id()); } /** The main static function to check if a given particle with type \a id matches. */ static bool Check(long id) { return abs(id) > 10 && abs(id) <= 20; } /** A simplified but unique class name. */ static string className() { return "Lepton"; } }; /** Gives a MatcherBase class based on LeptonMatcher. */ typedef Matcher MatchLepton; /** * A Matcher class which matches any neutrino. */ struct NeutrinoMatcher: public MatcherType { /** Typedef the class matching the complex conjugate particles. */ typedef NeutrinoMatcher CC; /** The main static function to check if a given particle type \a pd matches. */ static bool Check(const ParticleData & pd) { return Check(pd.id()); } /** The main static function to check if a given particle with type \a id matches. */ static bool Check(long id) { return abs(id)-10 >= 2 && abs(id)-10 <= 8 && abs(id)%2 == 0; } /** A simplified but unique class name. */ static string className() { return "Neutrino"; } }; /** Gives a MatcherBase class based on VectorMesonMatcher. */ typedef Matcher MatchNeutrino; struct LightAntiQuarkMatcher; /** * A Matcher class which matches any light quark (d,u or s). */ struct LightQuarkMatcher: public MatcherType { /** Typedef the class matching the complex conjugate particles. */ typedef LightAntiQuarkMatcher CC; /** The main static function to check if a given particle type \a pd matches. */ static bool Check(const ParticleData & pd) { return Check(pd.id()); } /** The main static function to check if a given particle with type \a id matches. */ static bool Check(long id) { return id > 0 && id < 4 ; } /** A simplified but unique class name. */ static string className() { return "LightQuark"; } }; /** Gives a MatcherBase class based on LightQuarkMatcher. */ typedef Matcher MatchLightQuark; /** * A Matcher class which matches any light anti-quark * (\f$\bar{\mbox{d}}\f$,\f$\bar{\mbox{u}}\f$ or * \f$\bar{\mbox{s}}\f$). */ struct LightAntiQuarkMatcher: public MatcherType { /** Typedef the class matching the complex conjugate particles. */ typedef LightQuarkMatcher CC; /** The main static function to check if a given particle type \a pd matches. */ static bool Check(const ParticleData & pd) { return Check(pd.id()); } /** The main static function to check if a given particle with type \a id matches. */ static bool Check(long id) { return id < 0 && id > -4 ; } /** A simplified but unique class name. */ static string className() { return "LightAntiQuark"; } }; /** Gives a MatcherBase class based on LightAntiQuarkMatcher. */ typedef Matcher MatchLightAntiQuark; /** * A Matcher class which matches any standard QCD parton, ie. gluons * and quarks up to bottom. */ struct StandardQCDPartonMatcher: public MatcherType { /** Typedef the class matching the complex conjugate particles. */ typedef StandardQCDPartonMatcher CC; /** The main static function to check if a given particle type \a pd matches. */ static bool Check(const ParticleData & pd) { return Check(pd.id()); } /** The main static function to check if a given particle with type \a id matches. */ static bool Check(long id) { return id && ( abs(id) <= 5 || id == ParticleID::g ); } /** A simplified but unique class name. */ static string className() { return "StandardQCDParton"; } }; /** Gives a MatcherBase class based on StandardQCDPartonMatcher. */ typedef Matcher MatchStandardQCDParton; /** * A Matcher class which matches any pseudo scalar meson. */ struct PseudoScalarMesonMatcher: public MatcherType { /** Typedef the class matching the complex conjugate particles. */ typedef PseudoScalarMesonMatcher CC; /** The main static function to check if a given particle type \a pd matches. */ static bool Check(const ParticleData & pd) { return Check(pd.id()); } /** The main static function to check if a given particle with type \a id matches. */ static bool Check(long id) { return ( (abs(id)/1000)%1 == 0 && abs(id) > 100 && abs(id)%10 == 1 ) || ( id == ParticleID::K_L0 || id == ParticleID::K_S0 ); } /** A simplified but unique class name. */ static string className() { return "PseudoScalarMeson"; } }; /** Gives a MatcherBase class based on PseudoScalarMesonMatcher. */ typedef Matcher MatchPseudoScalarMeson; /** * A Matcher class which matches any vector meson. */ struct VectorMesonMatcher: public MatcherType { /** Typedef the class matching the complex conjugate particles. */ typedef VectorMesonMatcher CC; /** The main static function to check if a given particle type \a pd matches. */ static bool Check(const ParticleData & pd) { return Check(pd.id()); } /** The main static function to check if a given particle with type \a id matches. */ static bool Check(long id) { return (abs(id)/1000)%1 == 0 && abs(id) > 100 && abs(id)%10 == 3; } /** A simplified but unique class name. */ static string className() { return "VectorMeson"; } }; /** Gives a MatcherBase class based on VectorMesonMatcher. */ typedef Matcher MatchVectorMeson; } #endif /* ThePEG_StandardMatchers_H */ diff --git a/PDT/Tau2HadronsDecayer.cc b/PDT/Tau2HadronsDecayer.cc --- a/PDT/Tau2HadronsDecayer.cc +++ b/PDT/Tau2HadronsDecayer.cc @@ -1,73 +1,73 @@ // -*- C++ -*- // // Tau2HadronsDecayer.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the Tau2HadronsDecayer class. // #include "Tau2HadronsDecayer.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/PDT/DecayMode.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/PDT/StandardMatchers.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG; Tau2HadronsDecayer::~Tau2HadronsDecayer() {} IBPtr Tau2HadronsDecayer::clone() const { return new_ptr(*this); } IBPtr Tau2HadronsDecayer::fullclone() const { return new_ptr(*this); } bool Tau2HadronsDecayer::accept(const DecayMode & dm) const { if ( dm.products().size() < 3 || !dm.cascadeProducts().empty() || !dm.productMatchers().empty() || dm.wildProductMatcher() ) return false; if ( abs(dm.parent()->id()) != ParticleID::tauminus ) return false; for ( ParticleMSet::const_iterator pit = dm.products().begin(); pit != dm.products().end(); ++pit ) if ( (**pit).id()*dm.parent()->id() == ParticleID::tauminus*ParticleID::nu_tau ) return true; return false; } double Tau2HadronsDecayer::reweight(const DecayMode &, const Particle & parent, const ParticleVector & children) const { tPPtr nu; for ( int i = 0, N = children.size(); i < N; ++i ) if ( parent.id()*children[i]->id() == ParticleID::tauminus*ParticleID::nu_tau ) { nu = children[i]; break; } double xnu = 2.0*nu->momentum().e()/parent.mass(); return 0.5*xnu*(3.0 - xnu); } void Tau2HadronsDecayer::persistentOutput(PersistentOStream &) const {} void Tau2HadronsDecayer::persistentInput(PersistentIStream &, int) {} ClassDescription Tau2HadronsDecayer::initTau2HadronsDecayer; // Definition of the static class description member. void Tau2HadronsDecayer::Init() { static ClassDocumentation documentation ("This class will perform the decays of tau to neutrimo + hadrons " "according to phase space, with an extra weight xnu(3-nxu)."); } diff --git a/PDT/Tau2HadronsDecayer.h b/PDT/Tau2HadronsDecayer.h --- a/PDT/Tau2HadronsDecayer.h +++ b/PDT/Tau2HadronsDecayer.h @@ -1,156 +1,156 @@ // -*- C++ -*- // // Tau2HadronsDecayer.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_Tau2HadronsDecayer_H #define THEPEG_Tau2HadronsDecayer_H // This is the declaration of the Tau2HadronsDecayer class. #include "ThePEG/PDT/FlatDecayer.h" namespace ThePEG { /** * The Tau2HadronsDecayer class inherits FlatDecayer and can perform * the decays of tau to neutrino + hadrons according to phase space, * with an extra weight \f$x_\nu(3-x_\nu)\f$. * * @see \ref Tau2HadronsDecayerInterfaces "The interfaces" * defined for Tau2HadronsDecayer. */ class Tau2HadronsDecayer: public FlatDecayer { public: /** @name Standard constructors and destructors. */ //@{ /** * Destructor. */ virtual ~Tau2HadronsDecayer(); //@} public: /** @name Virtual functions required by the Decayer class. */ //@{ /** * Check if this decayer can perfom the decay specified by the * given decay mode. * @param dm the DecayMode describing the decay. * @return true if this decayer can handle the given mode, otherwise false. */ virtual bool accept(const DecayMode & dm) const; /** * Give a weight to a phase space point. To be overridden by * subclasses. For a given decay mode, \a dm, decaying \a parent * particle and decayproducts, \a children, distributed according to * a flat distribution in phase space, return a weight (less or * equal to unity) modifying the flat distribution to the desired * one. Note that the chosen phase space point may be rejected, but * the chosen decay channel will not. This means that the weight * returned by this function does not influence the branching * ratios. */ virtual double reweight(const DecayMode & dm, const Particle & parent, const ParticleVector & children) const; //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interfaces. */ static void Init(); protected: protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * Describe a concrete class with persistent data. */ static ClassDescription initTau2HadronsDecayer; /** * Private and non-existent assignment operator. */ Tau2HadronsDecayer & operator=(const Tau2HadronsDecayer &) = delete; }; } namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the base classes * of Tau2HadronsDecayer. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of Tau2HadronsDecayer. */ typedef FlatDecayer NthBase; }; /** This template specialization informs ThePEG about the name of the * Tau2HadronsDecayer 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::Tau2HadronsDecayer"; } /** Return the name of the shared library be loaded to get access to * the Tau2HadronsDecayer class and every other class it uses * (except the base class). */ static string library() { return "Tau2HadronsDecayer.so"; } }; /** @endcond */ } #endif /* THEPEG_Tau2HadronsDecayer_H */ diff --git a/PDT/V2PPDecayer.cc b/PDT/V2PPDecayer.cc --- a/PDT/V2PPDecayer.cc +++ b/PDT/V2PPDecayer.cc @@ -1,102 +1,102 @@ // -*- C++ -*- // // V2PPDecayer.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the V2PPDecayer class. // #include "V2PPDecayer.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/PDT/DecayMode.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/PDT/StandardMatchers.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG; V2PPDecayer::~V2PPDecayer() {} IBPtr V2PPDecayer::clone() const { return new_ptr(*this); } IBPtr V2PPDecayer::fullclone() const { return new_ptr(*this); } bool V2PPDecayer::accept(const DecayMode & dm) const { if ( dm.products().size() != 2 || !dm.cascadeProducts().empty() || !dm.productMatchers().empty() || dm.wildProductMatcher() ) return false; for ( ParticleMSet::const_iterator it = dm.products().begin(); it != dm.products().end(); ++it ) if ( !PseudoScalarMesonMatcher::Check(**it) ) return false; return ( VectorMesonMatcher::Check(*dm.parent()) ); } ParticleVector V2PPDecayer::decay(const DecayMode & dm, const Particle & parent) const { grandParent = tPPtr(); sibling = tPPtr(); if ( parent.parents().size() == 1 && PseudoScalarMesonMatcher::Check(parent.parents()[0]->data()) ) grandParent = parent.parents()[0]; if ( grandParent && grandParent->children().size() == 2 ) { tParticleSet siblings = parent.siblings(); if ( siblings.size() == 1 && (PseudoScalarMesonMatcher::Check((**siblings.begin()).data()) || (**siblings.begin()).id() == ParticleID::gamma ) ) sibling = *siblings.begin(); } return FlatDecayer::decay(dm, parent); } double V2PPDecayer::reweight(const DecayMode &, const Particle & parent, const ParticleVector & children) const { if ( !sibling || !grandParent ) return 1.0; LorentzMomentum gp = grandParent->momentum(); gp.boost(-parent.momentum().boostVector()); LorentzMomentum pp(ZERO, ZERO, ZERO, parent.mass()); Energy2 p10 = pp*gp; Energy2 p12 = pp*children[0]->momentum(); Energy2 p02 = gp*children[0]->momentum(); Energy2 m02 = gp.m2(); Energy2 m12 = pp.m2(); Energy2 m22 = children[0]->momentum().mass2(); if ( grandParent->id() == ParticleID::gamma ) return m12*(2.0*p10*p12*p02 - m12*sqr(p02) - m02*sqr(p12) - m22*sqr(p10) + m12*m02*m22)/((sqr(p10) - m12*m02)*(sqr(p12) - m12*m22)); else return sqr(p10*p12 - m12*p02)/((sqr(p10) - m12*m02)*(sqr(p12) - m12*m22)); } void V2PPDecayer::persistentOutput(PersistentOStream & os) const { os << grandParent << sibling; } void V2PPDecayer::persistentInput(PersistentIStream & is, int) { is >> grandParent >> sibling; } ClassDescription V2PPDecayer::initV2PPDecayer; // Definition of the static class description member. void V2PPDecayer::Init() { static ClassDocumentation documentation ("This class performs the decay of a vector meson into two " "pseudo-scalars according to a flat phase space. If, however the " "decaying particle comes from a pseudo-scalar and has only one " "sibling which is a pseudo-scalar (or a photon) the decay is " "reweighted with cos^2 (sin^2 for photon) of the angle between one " "of the decay products and its grand parent. "); } diff --git a/PDT/V2PPDecayer.h b/PDT/V2PPDecayer.h --- a/PDT/V2PPDecayer.h +++ b/PDT/V2PPDecayer.h @@ -1,181 +1,181 @@ // -*- C++ -*- // // V2PPDecayer.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_V2PPDecayer_H #define THEPEG_V2PPDecayer_H // This is the declaration of the V2PPDecayer class. #include "ThePEG/PDT/FlatDecayer.h" namespace ThePEG { /** * The V2PPDecayer class performs the decay of a vector meson into two * pseudo-scalars according to a flat phase space. If, however the * decaying particle comes from a pseudo-scalar and has only one * sibling which is a pseudo-scalar (or a photon) the decay is * reweighted with \f$\cos^2\f$ (\f$\sin^2\f$ for photon) of the angle * between one of the decay products and its grand parent. * * @see \ref V2PPDecayerInterfaces "The interfaces" * defined for V2PPDecayer. * @see FlatDecayer * @see ParticleData */ class V2PPDecayer: public FlatDecayer { public: /** @name Standard constructors and destructors. */ //@{ /** * Destructor. */ virtual ~V2PPDecayer(); //@} public: /** @name Virtual functions required by the Decayer class. */ //@{ /** * Check if this decayer can perfom the decay specified by the * given decay mode. * @param dm the DecayMode describing the decay. * @return true if this decayer can handle the given mode, otherwise false. */ virtual bool accept(const DecayMode & dm) const; /** * Perform a decay for a given DecayMode and a given Particle instance. * @param dm the DecayMode describing the decay. * @param p the Particle instance to be decayed. * @return a ParticleVector containing the decay products. */ virtual ParticleVector decay(const DecayMode & dm, const Particle & p) const; /** * Give a weight to a phase space point. To be overridden by * subclasses. For a given decay mode, \a dm, decaying \a parent * particle and decayproducts, \a children, distributed according to * a flat distribution in phase space, return a weight (less or * equal to unity) modifying the flat distribution to the desired * one. Note that the chosen phase space point may be rejected, but * the chosen decay channel will not. This means that the weight * returned by this function does not influence the branching * ratios. */ virtual double reweight(const DecayMode & dm, const Particle & parent, const ParticleVector & children) const; //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interfaces. */ static void Init(); protected: protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * The grand parent in case reweighting should be done. */ mutable tPPtr grandParent; /** * The decaying particles sibling in case reweighting should be done. */ mutable tPPtr sibling; private: /** * Describe a concrete class with persistent data. */ static ClassDescription initV2PPDecayer; /** * Private and non-existent assignment operator. */ V2PPDecayer & operator=(const V2PPDecayer &) = delete; }; } namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the base classes * of V2PPDecayer. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of . */ typedef FlatDecayer NthBase; }; /** This template specialization informs ThePEG about the name of the * V2PPDecayer 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::V2PPDecayer"; } /** Return the name of the shared library be loaded to get access to * the V2PPDecayer class and every other class it uses * (except the base class). */ static string library() { return "V2PPDecayer.so"; } }; /** @endcond */ } #endif /* THEPEG_V2PPDecayer_H */ diff --git a/PDT/WeakToHadronsDecayer.cc b/PDT/WeakToHadronsDecayer.cc --- a/PDT/WeakToHadronsDecayer.cc +++ b/PDT/WeakToHadronsDecayer.cc @@ -1,118 +1,118 @@ // -*- C++ -*- // // WeakToHadronsDecayer.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the WeakToHadronsDecayer class. // #include "WeakToHadronsDecayer.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/PDT/DecayMode.h" #include "ThePEG/PDT/StandardMatchers.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG; IBPtr WeakToHadronsDecayer::clone() const { return new_ptr(*this); } IBPtr WeakToHadronsDecayer::fullclone() const { return new_ptr(*this); } bool WeakToHadronsDecayer::accept(const DecayMode & dm) const { if ( dm.orderedProducts().size() < 3 || !dm.productMatchers().empty() || !dm.cascadeProducts().empty() || dm.wildProductMatcher() ) return false; int Nqq = 0; if ( LeptonMatcher::Check(*dm.orderedProducts()[0]) ) { if ( !LeptonMatcher::Check(*dm.orderedProducts()[1]) ) return false; if ( dm.orderedProducts()[0]->iCharge() && dm.orderedProducts()[1]->iCharge() ) return false; if ( !dm.orderedProducts()[0]->iCharge() && !dm.orderedProducts()[1]->iCharge() ) return false; } for ( int i = 0, N = dm.orderedProducts().size(); i < N; ++i ) { if ( !dm.orderedProducts()[i]->coloured() ) continue; ++Nqq; if ( i == N - 1 ) return false; if ( dm.orderedProducts()[i]->iColour() + dm.orderedProducts()[i + 1]->iColour() ) return false; if ( i == N - 2 && DiquarkMatcher::Check(*dm.orderedProducts()[i]) && DiquarkMatcher::Check(*dm.orderedProducts()[i + 1]) ) return false; ++i; } if ( Nqq > 2 ) return false; return true; } PVector WeakToHadronsDecayer:: getHadrons(int Nh, tcPDVector quarks) const { PVector hadrons; int Nq = quarks.size(); tcPDPtr h = flavourGenerator()-> alwaysGetHadron(quarks[Nq - 2], quarks[Nq - 1]); hadrons.push_back(h->produceParticle()); if ( Nq == 2 ) return hadrons; while ( Nh-- > 0 ) { int i = irnd(Nq - 2); tcPDPair hq = flavourGenerator()->alwaysGenerateHadron(quarks[i]); hadrons.push_back(hq.first->produceParticle()); quarks[i] = hq.second; } if ( DiquarkMatcher::Check(*quarks[0]) && DiquarkMatcher::Check(*quarks[1]) ) return PVector(); h = flavourGenerator()->alwaysGetHadron(quarks[0], quarks[1]); hadrons.push_back(h->produceParticle()); return hadrons; } double WeakToHadronsDecayer:: reweight(const Particle & parent, const PVector & children) const { if ( LeptonMatcher::Check(children[0]->data()) ) { LorentzMomentum ph; int il = 1; int in = 0; if ( children[0]->data().iCharge() ) { il = 0; in = 1; } for ( int i = 2, N = children.size(); i < N; ++i ) ph += children[i]->momentum(); double w = (parent.mass()*children[il]->momentum().e())* (children[in]->momentum()*ph)*16.0/sqr(sqr(parent.mass())); return w; } return 1.0; } void WeakToHadronsDecayer::persistentOutput(PersistentOStream &) const {} void WeakToHadronsDecayer::persistentInput(PersistentIStream &, int) {} ClassDescription WeakToHadronsDecayer::initWeakToHadronsDecayer; // Definition of the static class description member. void WeakToHadronsDecayer::Init() { static ClassDocumentation documentation ("This class performs weak decays of taus and charmed and bottom " "hadrons. The intermediate W can either decay leptonically in which " "case standard V-A matrix element is used, or it can decay into " "quarks in which case the conversion into quarks is performed as for " "the QuarkToHadronsDecayer base class. In both cases the W decay " "products should be specified first. The spectator system can either " "be specified in terms of hadrons or in terms of quarks which will " "be collapsed into a single hadron."); } diff --git a/PDT/WeakToHadronsDecayer.h b/PDT/WeakToHadronsDecayer.h --- a/PDT/WeakToHadronsDecayer.h +++ b/PDT/WeakToHadronsDecayer.h @@ -1,150 +1,150 @@ // -*- C++ -*- // // WeakToHadronsDecayer.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_WeakToHadronsDecayer_H #define THEPEG_WeakToHadronsDecayer_H // This is the declaration of the WeakToHadronsDecayer class. #include "ThePEG/PDT/QuarksToHadronsDecayer.h" namespace ThePEG { /** * The WeakToHadronsDecayer class inherits from QuarksToHadronsDecayer * and can performs weak decays of taus and charmed and bottom * hadrons. The intermediate W can either decay leptonically in which * case standard V-A matrix element is used, or it can decay into * quarks in which case the conversion into quarks is performed as for * the QuarkToHadronsDecayer base class. In both cases the W decay * products should be specified first. The spectator system can either * be specified in terms of hadrons or in terms of quarks which will * be collapsed into a single hadron. * * @see \ref WeakToHadronsDecayerInterfaces "The interfaces" * defined for WeakToHadronsDecayer. */ class WeakToHadronsDecayer: public QuarksToHadronsDecayer { public: /** @name Virtual functions required by the Decayer and QuarksToHadronsDecayer classes. */ //@{ /** * Check if this decayer can perfom the decay specified by the * given decay mode. * @param dm the DecayMode describing the decay. * @return true if this decayer can handle the given mode, otherwise false. */ virtual bool accept(const DecayMode & dm) const; /** * Called by QuarksToHadronsDecayer::distribute() to reweight the * default flat phase spece. Can be overridden by sub-classes and * should return a number between 0 and 1. This version returns 1. */ virtual double reweight(const Particle & parent, const PVector & children) const; /** * Produce \a Nh hadrons from the specified \a quarks. The last * quark is considered to be a spectator quark. */ virtual PVector getHadrons(int Nh, tcPDVector quarks) const; //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interfaces. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * Describe a concrete class with persistent data. */ static ClassDescription initWeakToHadronsDecayer; /** * Private and non-existent assignment operator. */ WeakToHadronsDecayer & operator=(const WeakToHadronsDecayer &) = delete; }; } namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the base classes * of WeakToHadronsDecayer. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of WeakToHadronsDecayer. */ typedef QuarksToHadronsDecayer NthBase; }; /** This template specialization informs ThePEG about the name of the * WeakToHadronsDecayer 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::WeakToHadronsDecayer"; } /** Return the name of the shared library be loaded to get access to * the WeakToHadronsDecayer class and every other class it uses * (except the base class). */ static string library() { return "WeakToHadronsDecayer.so"; } }; /** @endcond */ } #endif /* THEPEG_WeakToHadronsDecayer_H */ diff --git a/PDT/WidthGenerator.cc b/PDT/WidthGenerator.cc --- a/PDT/WidthGenerator.cc +++ b/PDT/WidthGenerator.cc @@ -1,45 +1,45 @@ // -*- C++ -*- // // WidthGenerator.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the WidthGenerator class. // #include "WidthGenerator.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Repository/UseRandom.h" using namespace ThePEG; Length WidthGenerator::lifeTime(const ParticleData &, Energy, Energy w) const { return UseRandom::rndExp(hbarc/w); } WidthGenerator::DecayMap WidthGenerator::rate(const Particle & p) { DecayMap dm(p.data().decaySelector()); return dm; } Energy WidthGenerator::width(const Particle & p) const { return width(p.data(), p.mass()); } AbstractNoPIOClassDescription WidthGenerator::initWidthGenerator; void WidthGenerator::Init() { static ClassDocumentation documentation ("Abstract base class to be used to encapsulate models for giving the " "partial decay width of a ParticleData given the specified DecayModes."); } diff --git a/PDT/WidthGenerator.h b/PDT/WidthGenerator.h --- a/PDT/WidthGenerator.h +++ b/PDT/WidthGenerator.h @@ -1,121 +1,121 @@ // -*- C++ -*- // // WidthGenerator.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_WidthGenerator_H #define ThePEG_WidthGenerator_H // This is the declaration of the WidthGenerator class. #include "ThePEG/Config/ThePEG.h" #include "WidthGenerator.fh" #include "ThePEG/Interface/Interfaced.h" #include "ThePEG/Utilities/Selector.h" #include "ThePEG/PDT/DecayMode.fh" namespace ThePEG { /** * WidthGenerator is an abstract base class to be used to encapsulate * models for giving the partial decay width of a ParticleData given * the specified DecayModes. * * @see \ref WidthGeneratorInterfaces "The interfaces" * defined for WidthGenerator. * @see ParticleData * @see DecayMode */ class WidthGenerator: public Interfaced { public: /** A selector of DecayModess weighted by their * branching ratios. */ typedef Selector DecayMap; public: /** @name Virtual functions to be overridden by sub-classes. */ //@{ /** * Return true if this object can be used for the given particle * type with the given decay map. */ virtual bool accept(const ParticleData &) const = 0; /** * Given a Particle, calculate a width. */ Energy width(const Particle &) const; /** * Given a particle type and a mass of an instance of that particle * type, calculate a width. */ virtual Energy width(const ParticleData &, Energy m) const = 0; /** * Given a particle type and a mass and a width of an instance of * that particle type, generate a life time. */ virtual Length lifeTime(const ParticleData &, Energy m, Energy w) const; /** * Return decay map for the given particle type. */ virtual DecayMap rate(const ParticleData &) const = 0; /** * Return a decay map for a given Particle instance. */ virtual DecayMap rate(const Particle &); //@} public: /** * Standard Init function used to initialize the interface. */ static void Init(); private: /** * The static object used to initialize the description of this class. * Indicates that this is an abstract class without persistent data. */ static AbstractNoPIOClassDescription initWidthGenerator; /** * Private and non-existent assignment operator. */ WidthGenerator & operator=(const WidthGenerator &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the base classes * of WidthGenerator. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of WidthGenerator. */ typedef Interfaced NthBase; }; /** This template specialization informs ThePEG about the name of the * WidthGenerator class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "ThePEG::WidthGenerator"; } }; /** @endcond */ } #endif /* ThePEG_WidthGenerator_H */ diff --git a/Persistency/InputDescription.h b/Persistency/InputDescription.h --- a/Persistency/InputDescription.h +++ b/Persistency/InputDescription.h @@ -1,115 +1,115 @@ // -*- C++ -*- // // InputDescription.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_InputDescription_H #define ThePEG_InputDescription_H // This is the declaration of the InputDescription class. #include "ThePEG/Config/ThePEG.h" #include "ThePEG/Utilities/ClassDescription.h" namespace ThePEG { /** @ingroup Persistency * InputDescription objects are used by the PersistentIStream class to * keep track of all classes it has read from a stream. It keeps a * pointer to the corresponding ClassDescription in case the class * read in was actually present in the current program, a version * number of the read class which may be different from the class * present in the current program and a list of base class * InputDescriptions. * * @see PersistentIStream * @see Named * @see ClassDescription */ class InputDescription: public Named { public: /** A vector of pointers to InputDescription objects. */ typedef vector DescriptionVector; ThePEG_DECLARE_POINTERS(PersistentBase,BPtr); public: /** * The standard constructor. * @param newName the name of the class being read. * @param newVersion the version number of the class when written. */ InputDescription(string newName, int newVersion) : Named(newName), theDescription(0), theVersion(newVersion) {} /** * Set the ClassDescriptionBase object of the class being read. */ void setDescription(const ClassDescriptionBase * cd) { theDescription = cd; } /** * Add a base class description. */ void addBaseClass(const InputDescription * newBase) { theBaseClasses.push_back(newBase); } /** * Return the list of base class descriptions. */ const DescriptionVector & descriptions() const { return theBaseClasses; } /** * Create an object of the corresponding class. */ BPtr create() const { if ( theDescription ) return theDescription->create(); DescriptionVector::const_iterator dit = theBaseClasses.begin(); while ( dit != theBaseClasses.end() ) { BPtr obj = (*dit++)->create(); if ( obj ) return obj; } return BPtr(); } /** * Read an object part of the corresponding class from a stream. * Will only read the part of the object corresponding to the * members of the class represented by this object. */ void input(tBPtr b, PersistentIStream & is) const { if ( theDescription ) theDescription->input(b, is, theVersion); } private: /** * The list of base class descriptions. */ DescriptionVector theBaseClasses; /** * The description of the corresponding class in the current * program. */ const ClassDescriptionBase * theDescription; /** * The version of the class to be read. */ int theVersion; }; } #endif /* ThePEG_InputDescription_H */ diff --git a/Persistency/PersistentIStream.cc b/Persistency/PersistentIStream.cc --- a/Persistency/PersistentIStream.cc +++ b/Persistency/PersistentIStream.cc @@ -1,292 +1,292 @@ // -*- C++ -*- // // PersistentIStream.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the PersistentIStream class. // #include "PersistentIStream.h" #include "PersistentOStream.xh" #include "PersistentIStream.xh" #include "ThePEG/Utilities/DynamicLoader.h" #include "ThePEG/Utilities/Debug.h" namespace ThePEG { PersistentIStream::PersistentIStream(string file) : theIStream(0), isPedantic(true), allocStream(true), badState(false) { // if ( file[0] == '|' ) // theIStream = new ipfstream(file.substr(1).c_str()); // else if ( file.substr(file.length()-3, file.length()) == ".gz" ) // theIStream = new ipfstream(string("gzip -d -c " + file).c_str()); // else theIStream = new ifstream(file.c_str()); if ( theIStream ) { init(); } else setBadState(); } void PersistentIStream::init() { string tag; operator>>(tag); if ( tag != "ThePEG version 1 Database" ) setBadState(); operator>>(version); operator>>(subVersion); if ( version > 0 || subVersion > 0 ) { vector paths; *this >> paths; for ( int i = 0, N = paths.size(); i < N; ++i ) DynamicLoader::appendPath(paths[i]); *this >> paths; for ( int i = 0, N = paths.size(); i < N; ++i ) DynamicLoader::prependPath(paths[i]); } if ( version > 0 || subVersion > 1 ) { *this >> theGlobalLibraries; string loaderror; for ( int i = 0, N = theGlobalLibraries.size(); i < N; ++i ) { istringstream is(theGlobalLibraries[i]); string library; while ( is >> library ) { DynamicLoader::load(library); loaderror += DynamicLoader::lastErrorMessage; } } if ( !loaderror.empty() ) loaderror = "\nerror message from dynamic loader:\n" + loaderror; } } PersistentIStream::~PersistentIStream() { if ( allocStream ) delete theIStream; for ( int i = 0, N = readClasses.size(); i < N; ++i ) delete readClasses[i]; } void PersistentIStream::endObject() { // We have just read an object, but we may only have acces to a base class // of the originally written object. Therefore we must skip everything that // the unknown derived class may have written. So we check one field at // the time... while ( good() ) { switch ( is().peek() ) { case tEnd: // OK we found the end of the object, let's quit get(); return; case tBegin: // it seems there is an object next on the stream. We read it in and // add it to the list of orphans getObject(); break; case tSep: case tNext: // This was a field separator, check next char; get(); break; default: // Just an ordinary character, this means we are in a field, // skip to the end of the field. skipField(); } }; } void PersistentIStream::endBase(string classname) { // We have just read an object part, but we may only have acces to a // base class of the originally written object. Therefore we must // skip everything that the unknown derived class may have // written. So we check one field at the time... if ( is().peek() != tNext && pedantic() ) throw ReadFailure() << "PersistentIStream could not read an object of class '" << classname << "'. The file may be corrupted, or the class could not be found. The " << "base class was found, however, and if the PersistentIStream is " << "'setTolerant()' it may still be possible to read the part of the " << "object corresponding to this base class." << Exception::runerror; while ( good() ) { switch ( is().peek() ) { case tNext: // This is what we are looking for. get(); return; case tSep: // This was a field separator, check next char; get(); break; case tBegin: // it seems there is an object next on the stream. We read it in and // add it to the list of orphans getObject(); break; case tEnd: // OOPS we found the end of an object, something went wrong, let's quit throw ReadFailure() << "PersistentIStream could not read an object of class '" << classname << "'. Maybe the file was written with another version " << "of the class." << Exception::runerror; default: // Just an ordinary character, this means we are in a field, // skip to the end of the field. skipField(); } } } PersistentIStream::BPtr PersistentIStream::getObject() { BPtr obj; if ( !good() ) return obj; ObjectVector::size_type oid; const InputDescription * pid = 0; try { if ( !beginObject() ) { *this >> oid; if ( !oid ) return obj; if ( oid <= readObjects.size() ) return readObjects[oid-1]; throw MissingObject() << "PersistentIStream could not find object number " << oid << " which should have already been read." << Exception::runerror; } get(); *this >> oid; if ( oid > readObjects.size() + 1 ) throw MissingObject() << "PersistentIStream could not read in object because its number (" << oid << ") was inconsistent." << Exception::runerror; pid = getClass(); unsigned long uid = ReferenceCounted::objectCounter + 1; if ( version > 0 || subVersion >= 3 ) *this >> uid; unsigned long saveid = ReferenceCounted::objectCounter; ReferenceCounted::objectCounter = uid - 1; obj = pid->create(); ReferenceCounted::objectCounter = max(saveid, uid); readObjects.erase(readObjects.begin() + (oid - 1), readObjects.end()); readObjects.push_back(obj); getObjectPart(obj, pid); endObject(); if ( badState && Debug::level ) throw ReadFailure() << "PersistentIStream failed to read in object number " << oid << " of class " << pid->name() << "." << Exception::runerror; return obj; } catch ( Exception & e ) { if ( pedantic() || Debug::level ) { e.handle(); string classname = ""; if ( pid ) classname = pid->name(); throw ReadFailure() << "While reading object number " << oid << " of class " << classname << ":\n" << e.message() << Exception::runerror; } setBadState(); return obj; } catch (...) { setBadState(); if ( pedantic() ) throw; return obj; } } void PersistentIStream:: getObjectPart(tBPtr obj, const InputDescription * pid) { DescriptionVector::const_iterator bit = pid->descriptions().begin(); while ( bit != pid->descriptions().end() ) { getObjectPart(obj, *bit++); endBase(pid->name()); } pid->input(obj, *this); } const InputDescription * PersistentIStream::getClass() { unsigned int cid; operator>>(cid); if ( cid < readClasses.size() ) return readClasses[cid]; string className; operator>>(className); if ( cid != readClasses.size() ) throw MissingClass() << "PersistentIStream could not read info on class '" << className << "' because its number (" << cid << ") was inconsistent." << Exception::runerror; int version; string libraries; operator>>(version); operator>>(libraries); InputDescription * id = new InputDescription(className, version); readClasses.push_back(id); int nBase; operator>>(nBase); while ( nBase-- ) id->addBaseClass(getClass()); const ClassDescriptionBase * db = DescriptionList::find(className); string loaderror; if ( !db && libraries.length() ) { istringstream is(libraries); string library; while ( is >> library ) { DynamicLoader::load(library); loaderror += DynamicLoader::lastErrorMessage; } if ( !loaderror.empty() ) loaderror = "\nerror message from dynamic loader:\n" + loaderror; } db = DescriptionList::find(className); if ( pedantic() && !db ) throw MissingClass() << "PersistentIStream could not find the class '" << className << "'." << loaderror << Exception::runerror; id->setDescription(db); return id; } PersistentIStream & PersistentIStream::operator>>(string & s) { s.erase(); char c = 0; while ( good() && (c = get()) != tSep ) { if ( c == tNull ) s += escaped(); else s += c; } return *this; } PersistentIStream & PersistentIStream::operator>>(char & c) { if ( (c = get()) == tNull ) c = escaped(); getSep(); return *this; } PersistentIStream & PersistentIStream::operator>>(unsigned char & c) { char cc; *this >> cc; c = static_cast(cc); return *this; } PersistentIStream & PersistentIStream::operator>>(signed char & c) { char cc; *this >> cc; c = static_cast(cc); return *this; } PersistentIStream & PersistentIStream::operator>>(bool & t) { char c = get(); t = ( c == tYes ); if ( !t && c != tNo ) setBadState(); getSep(); return *this; } PersistentIStream & PersistentIStream::operator>>(Complex & z) { double re = 0.0; double im = 0.0; *this >> re >> im; z = Complex(re, im); return *this; } } diff --git a/Persistency/PersistentIStream.h b/Persistency/PersistentIStream.h --- a/Persistency/PersistentIStream.h +++ b/Persistency/PersistentIStream.h @@ -1,667 +1,667 @@ // -*- C++ -*- // // PersistentIStream.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_PersistentIStream_H #define ThePEG_PersistentIStream_H // This is the declaration of the PersistentIStream class. #include "ThePEG/Config/ThePEG.h" #include "InputDescription.h" #include "PersistentIStream.fh" #include "ThePEG/Utilities/Exception.h" #include #include namespace ThePEG { /** @ingroup Persistency * PersistentIStream is used to read persistent objects from a stream * where they were previously written using PersistentOStream. Basic * types and pointers to objects derived from * PersistentBase should be read in the same order they * were written out. If pedantic() is true the same * classes that were written out must be present in the current * program. If pedantic() is false and if an object is * read for which only a base class is present in the current program, * only the parts corresponding to the base class will be read, and * the rest will be gracefully skipped. * * Each base class of a given object will be asked to read its * members from the stream starting from the least derived class going to * the most derived one. Members may be pointers to other persistent * objects or basic types or containers of these. The output for each * object part should be implemented by specializing the * ClassTraits::input method, which otherwise * will call the non-virtual persistentInput function of * the class. Note that for diamond-shaped multiple inheritance * structures, the virtual base classes will be written out several * times for the same object. * * @see PersistentOStream * @see ClassTraits */ class PersistentIStream { public: ThePEG_DECLARE_POINTERS(PersistentBase,BPtr); /** A vector of pointers to persistent objects */ typedef vector ObjectVector; /** A vector of bare pointers to InputDescription objects. */ typedef InputDescription::DescriptionVector DescriptionVector; public: /** * Constuctor giving an input stream to be used as an underlying * istream. */ PersistentIStream(istream & is) : theIStream(&is), isPedantic(true), allocStream(false), badState(false) { init(); } /** * Constuctor giving a file name to read from. If the first * character in the string is a '|', the corresponding program is * run and its standard output is used instead. If the filename ends * in ".gz" the file is uncompressed with gzip. */ PersistentIStream(string); /** * The destructor. */ ~PersistentIStream(); /** * Operator for extracting persistent objects from the stream. * @param ptr this pointer will refer to the extracted object. * @return a reference to the stream. */ template PersistentIStream & operator>>(RCPtr & ptr) { BPtr b = getObject(); ptr = dynamic_ptr_cast< RCPtr >(b); if ( b && !ptr ) setBadState(); return *this; } /** * Operator for extracting persistent objects from the stream. * @param ptr this pointer will refer to the extracted object. * @return a reference to the stream. */ template PersistentIStream & operator>>(ConstRCPtr & ptr) { BPtr b = getObject(); ptr = dynamic_ptr_cast< ConstRCPtr >(b); if ( b && !ptr ) setBadState(); return *this; } /** * Operator for extracting persistent objects from the stream. * @param ptr this pointer will refer to the extracted object. * @return a reference to the stream. */ template PersistentIStream & operator>>(TransientRCPtr & ptr) { BPtr b = getObject(); ptr = dynamic_ptr_cast< TransientRCPtr >(b); if ( b && !ptr ) setBadState(); return *this; } /** * Operator for extracting persistent objects from the stream. * @param ptr this pointer will refer to the extracted object. * @return a reference to the stream. */ template PersistentIStream & operator>>(TransientConstRCPtr & ptr) { BPtr b = getObject(); ptr = dynamic_ptr_cast< TransientConstRCPtr >(b); if ( b && !ptr ) setBadState(); return *this; } /** @name Operators for extracting built-in types from the stream. */ //@{ /** * Read a character string. */ PersistentIStream & operator>>(string &); /** * Read a character. */ PersistentIStream & operator>>(char &); /** * Read a signed character. */ PersistentIStream & operator>>(signed char &); /** * Read an unsigned character. */ PersistentIStream & operator>>(unsigned char &); /** * Read an integer. */ PersistentIStream & operator>>(int & i) { is() >> i; getSep(); return *this; } /** * Read an unsigned integer. */ PersistentIStream & operator>>(unsigned int & i) { is() >> i; getSep(); return *this; } /** * Read a long integer. */ PersistentIStream & operator>>(long & i) { is() >> i; getSep(); return *this; } /** * Read an unsigned long integer. */ PersistentIStream & operator>>(unsigned long & i) { is() >> i; getSep(); return *this; } /** * Read a short integer. */ PersistentIStream & operator>>(short & i) { is() >> i; getSep(); return *this; } /** * Read an unsigned short integer. */ PersistentIStream & operator>>(unsigned short & i) { is() >> i; getSep(); return *this; } /** * Read a double. */ PersistentIStream & operator>>(double & d) { is() >> d; getSep(); return *this; } /** * Read a float. */ PersistentIStream & operator>>(float & f) { is() >> f; getSep(); return *this; } /** * Read a bool. */ PersistentIStream & operator>>(bool &); /** * Read a Complex. */ PersistentIStream & operator>>(Complex &); //@} /** * Intput of containers streamable objects. * @param c the container into which objects are added. */ template void getContainer(Container & c) { long size; typename Container::value_type val; c.clear(); *this >> size; while ( size-- && good() ) { *this >> val; c.insert(c.end(), val); } } /** * Read in an object. Create an object and read its data from the * stream. * @return a pointer to the read object. */ BPtr getObject(); /** * For a given object, read the member variables corresponding to a * given InputDescription object. * @param obj the object to be read into. * @param pid a pointer to an InputDescription describing the * (sub)class to be read. */ void getObjectPart(tBPtr obj, const InputDescription * pid); /** * Read a class description from the underlying stream and return a * corresponding InputDescription object */ const InputDescription * getClass(); /** * Set pedantic mode. If the stream is set to be tolerant it is * allowed to read an object from the stream even if the * corresponding class is not known to the running executable, under * the condition that a public base class of the unknown class is * known. If the stream is set to be pedantic this is not allowed. * By default, the stream is pedantic. */ PersistentIStream & setPedantic() { isPedantic = true; return *this; } /** * Set tolerant mode. If the stream is set to be tolerant it is * allowed to read an object from the stream even if the * corresponding class is not known to the running executable, under * the condition that a public base class of the unknown class is * known. If the stream is set to be pedantic this is not allowed. * By default, the stream is pedantic. */ PersistentIStream & setTolerant() { isPedantic = false; return *this; } /** * Check the state of the stream. */ bool good() const { return !badState && is(); } /** * Check the state of the stream. */ bool operator!() const { return !good(); } /** * Check the state of the stream. */ operator bool() const { return good(); } /** * Check the tolerance. Returns true if setPedantic() has been * called or if not setTolerant() has been called. */ bool pedantic() const { return isPedantic; } /** * The global libraries loaded on initialization. */ const vector & globalLibraries() const { return theGlobalLibraries; } private: /** @cond EXCEPTIONCLASSES */ /** @ingroup Persistency Thrown if a class is missing */ struct MissingClass: public Exception {}; /** @ingroup Persistency Thrown if an object which should have been read in is missing. */ struct MissingObject: public Exception {}; /** @ingroup Persistency Thrown if reading from the stream failed for some reason. */ struct ReadFailure: public Exception {}; /** @endcond */ /** * Internal initialization. */ void init(); /** * Get the next character from the associated istream. */ char get() { return is().get(); } /** * Get the next character from the associated istream and decode it * if it is escaped. */ char escaped() { char c = get(); return c == tNoSep? tSep: c; } /** * Set the stream in a bad state */ void setBadState() { breakThePEG(); badState = true; } /** * Read a field separator from the stream. */ void getSep() { if ( !pedantic() ) skipField(); else if ( get() != tSep ) setBadState(); } /** * Scan the stream for the next field separator. */ void skipField() { is().ignore(INT_MAX, tSep); if ( !is() ) setBadState(); } /** * Check if the next char to be read is a tBegin marker. */ bool beginObject() { return is().peek() == tBegin; } /** * Scan the stream to the end of the current object. If any new object are * found these are read prom the stream to ensure that the pointer structure * is preserved. */ void endObject(); /** * Scan stream for "end base class" marker. The \a classname is the * name of the class currently being read and is only used for * documenting exceptions. */ void endBase(string classname); /** * Return a reference to the associated stream. */ istream & is() { return *theIStream; } /** * Return a const reference to the associated stream. */ const istream & is() const { return *theIStream; } /** * Lists of objects that have been read. */ ObjectVector readObjects; /** * Lists of classes and corresponding version strings that have been read. */ DescriptionVector readClasses; /** * A pointer to the associated istream. */ istream * theIStream; /** * Pedantic or tolerant. See description of the setPedantic() and * setTolerant() methods. */ bool isPedantic; /** * True if the associated istream should be deleted when the PersistentIStream * is destroyed. */ bool allocStream; /** * False if no errors has occurred. */ bool badState; /** Version number of the PersistentOStream which has written the * file being read. */ int version; /** Subversion number of the PersistentOStream which has written the * file being read. */ int subVersion; /** * Global libraries loaded in the initialization. */ vector theGlobalLibraries; /** @name Special marker characters */ //@{ /** * The special marker character indicating the beginning of an object. */ static const char tBegin = '{'; /** * The special marker character indicating the end of an object. */ static const char tEnd = '}'; /** * The marker character indicating the beginning of the next base * class in case of multiple inheritance. */ static const char tNext = '|'; /** * The special marker character indicating an escaped marker character. */ static const char tNull = '\\'; /** * The special marker character indicating the end of a value. */ static const char tSep = '\n'; /** * The special marker character used to avoid confusion with escaped * tSep markers. */ static const char tNoSep = 'n'; /** * The special marker character indicating a true boolean value. */ static const char tYes = 'y'; /** * The special marker character indicating a false boolean value. */ static const char tNo = 'n'; //@} private: /** * Standard ctors and assignment are private and not implemented. */ PersistentIStream(); /** * Standard ctors and assignment are private and not implemented. */ PersistentIStream(const PersistentIStream &); /** * Standard ctors and assignment are private and not implemented. */ PersistentIStream & operator=(const PersistentIStream &) = delete; }; /** * Operator for applying manipulators to the stream. */ inline PersistentIStream & operator>>(PersistentIStream & is, PersistentIManip func) { return (*func)(is); } /** * The manipulator for setting pedantic mode. */ inline PersistentIStream & pedantic(PersistentIStream & is) { return is.setPedantic(); } /** * The manipulator for setting tolerant mode. */ inline PersistentIStream & tolerant(PersistentIStream & is) { return is.setTolerant(); } /** * @name Partial specializations of operator>> for input of * std::containers. */ //@{ /** Input a pair of objects. */ template inline PersistentIStream & operator>>(PersistentIStream & is, pair & p) { return is >> p.first >> p.second; } /** Input a map of key/objects pairs. */ template inline PersistentIStream & operator>>(PersistentIStream & is, map & m) { m.clear(); long size; Key k; is >> size; while ( size-- && is ) { is >> k; is >> m[k]; } return is; } /** Input a multimap of key/objects pairs. */ template inline PersistentIStream & operator>>(PersistentIStream & is, multimap & m) { m.clear(); long size; Key k; T t; is >> size; while ( size-- && is ) { is >> k; is >> t; m.insert(make_pair(k, t)); } return is; } /** Input a set of objects. */ template inline PersistentIStream & operator>>(PersistentIStream & is, set & s) { is.getContainer(s); return is; } /** Input a multoset of objects. */ template inline PersistentIStream & operator>>(PersistentIStream & is, multiset & s) { is.getContainer(s); return is; } /** Input a list of objects. */ template inline PersistentIStream & operator>>(PersistentIStream & is, list & l) { is.getContainer(l); return is; } /** Input a vector of objects. */ template inline PersistentIStream & operator>>(PersistentIStream & is, vector & v) { is.getContainer(v); return is; } /** Input an array of objects. */ template inline PersistentIStream & operator>>(PersistentIStream & is, array & a) { for ( size_t i = 0; i < N && is.good(); ++i ) is >> a[i]; return is; } /** Input a deque of objects. */ template inline PersistentIStream & operator>>(PersistentIStream & is, deque & d) { is.getContainer(d); return is; } /** Input a valarray. */ template inline PersistentIStream & operator>>(PersistentIStream & is, std::valarray & v) { long size; is >> size; v = std::valarray(size); for ( int i = 0; i < size && is.good(); ++i ) is >> v[i]; return is; } } #endif /* ThePEG_PersistentIStream_H */ diff --git a/Persistency/PersistentIStream.xh b/Persistency/PersistentIStream.xh --- a/Persistency/PersistentIStream.xh +++ b/Persistency/PersistentIStream.xh @@ -1,23 +1,23 @@ // -*- C++ -*- // // PersistentIStream.xh is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_PersistentIStream_XH #define ThePEG_PersistentIStream_XH // // This is the declarations of the exception classes used by the // PersistentIStream class. // #include "PersistentIStream.fh" namespace ThePEG { } #endif /* ThePEG_PersistentIStream_XH */ diff --git a/Persistency/PersistentOStream.cc b/Persistency/PersistentOStream.cc --- a/Persistency/PersistentOStream.cc +++ b/Persistency/PersistentOStream.cc @@ -1,170 +1,170 @@ // -*- C++ -*- // // PersistentOStream.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the PersistentOStream class. // #include "PersistentOStream.h" #include "ThePEG/Utilities/DynamicLoader.h" #include namespace ThePEG { PersistentOStream::PersistentOStream(ostream & os, const vector & libs) : theOStream(&os), badState(false), allocStream(false) { init(libs); } PersistentOStream::PersistentOStream(string file, const vector & libs) : badState(false), allocStream(true) { // if ( file[0] == '|' ) // theOStream = new opfstream(file.substr(1).c_str()); // else if ( file.substr(file.length()-3, file.length()) == ".gz" ) // theOStream = new opfstream(string("gzip > " + file).c_str()); // else theOStream = new ofstream(file.c_str()); if ( theOStream ) init(libs); else setBadState(); } void PersistentOStream::init(const vector & libs) { operator<<(string("ThePEG version 1 Database")); operator<<(version); operator<<(subVersion); *this << DynamicLoader::appendedPaths(); *this << DynamicLoader::prependedPaths(); vector libraries; for ( int i = 0, N = libs.size(); i < N; ++i ) libraries.push_back(DynamicLoader::dlnameversion(libs[i])); *this << libraries; } PersistentOStream::~PersistentOStream() { if ( allocStream ) delete theOStream; } void PersistentOStream:: putObjectPart(tcBPtr obj, const ClassDescriptionBase * db) { ClassDescriptionBase::DescriptionVector::const_iterator bit = db->descriptions().begin(); while ( bit != db->descriptions().end() ) { putObjectPart(obj, *bit++); endBase(); } db->output(obj, *this); } PersistentOStream & PersistentOStream::outputPointer(tcBPtr obj) { if ( !good() ) return *this; if ( !obj ) return operator<<(0); // It it's the null pointer, just print a zero. int oid = 0; const ClassDescriptionBase * desc = 0; try { // Check if the object has been written before. In that case just write // out it's number ObjectMap::const_iterator oit = writtenObjects.find(obj); if ( oit != writtenObjects.end() ) { *this << oit->second; return *this; } // This object hasn't been written before so we write it out, beginning // with a number, then the class information, and finally let it write // itself on the stream. beginObject(); oid = writtenObjects.size()+1; writtenObjects[obj] = oid; *this << oid; desc = writeClassId(obj); *this << obj->uniqueId; putObjectPart(obj, desc); endObject(); } catch (Exception & e) { e.handle(); string classname = ""; if ( desc ) classname = desc->name(); throw WriteError() << "While writing object number " << oid << " of class " << classname << ":\n" << e.message() << Exception::runerror; setBadState(); } catch (...) { setBadState(); } checkState(); return *this; } const ClassDescriptionBase * PersistentOStream::writeClassId(tcBPtr obj) { const auto & tmp=*obj; const ClassDescriptionBase * db = DescriptionList::find(typeid(tmp)); if ( !db ) { throw MissingClass() << "PersistentOStream could not find the ClassDescription object " << "corresponding to the class " << typeid(tmp).name() << ". Please check that the class has a properly instantiated " << "ClassDescription object." << Exception::runerror; } writeClassDescription(db); return db; } void PersistentOStream:: writeClassDescription(const ClassDescriptionBase * db) { // If objects of this class has been written out before, just write // the corresponding number ClassMap::iterator cit = writtenClasses.find(db); if ( cit != writtenClasses.end() ) { operator<<(cit->second); return; } // This class hasn't been written before, so append it to the list of // written classes and assign a number to it, before writing the string // containing the information int cid = writtenClasses.size(); writtenClasses[db] = cid; operator<<(cid); operator<<(db->name()); operator<<(db->version()); operator<<(DynamicLoader::dlnameversion(db->library())); // Now write its base classes or a zero if the base class is PersistentBase. operator<<(db->descriptions().size()); DescriptionVector::const_iterator bit = db->descriptions().begin(); while ( bit != db->descriptions().end() ) writeClassDescription(*bit++); } PersistentOStream & PersistentOStream::flush() { #ifdef _LIBCPP_VERSION typedef ObjectMap::const_iterator Iterator; #else typedef ObjectMap::iterator Iterator; #endif Iterator it = writtenObjects.begin(); while ( it != writtenObjects.end() ) { Iterator it2 = it++; if ( (*it2).second > lastSavedObject.top() ) writtenObjects.erase(it2); } os().flush(); return *this; } } diff --git a/Persistency/PersistentOStream.h b/Persistency/PersistentOStream.h --- a/Persistency/PersistentOStream.h +++ b/Persistency/PersistentOStream.h @@ -1,671 +1,671 @@ // -*- C++ -*- // // PersistentOStream.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_PersistentOStream_H #define ThePEG_PersistentOStream_H // This is the declaration of the PersistentOStream class. #include "ThePEG/Config/ThePEG.h" #include "ThePEG/Utilities/ClassDescription.h" #include "ThePEG/Utilities/Exception.h" #include "ThePEG/Utilities/Debug.h" #include "PersistentOStream.fh" #include "PersistentOStream.xh" #include namespace ThePEG { /** @ingroup Persistency * PersistentOStream is used to write objects persistently * to a stream from which they can be read in again with a * PersistentIStream. Pointers to objects of classes * derived from PersistentBase may be written out if a * static ClassDescription object is present for the * class. Also basic types may be written to the stream, as well as * containers of pointers to persistent objects and basic types. * * The PersistentOStream keeps a list of all pointers to * written persistent objects, so that if several pointers to the * smame object is written, the object will only be written once. * * Each base class of a given object will be asked to write its * members to the stream starting from the least derived class going to * the most derived one. Members may be pointers to other persistent * objects or basic types or containers of these. The output for each * object part should be implemented by specializing the * ClassTraits::output method, which otherwise * will call the non-virtual persistentOutput function of * the class. Note that for diamond-shaped multiple inheritance * structures, the virtual base classes will be written out several * times for the same object. * * @see PersistentIStream * @see ClassDescription * @see ClassTraits */ class PersistentOStream { public: ThePEG_DECLARE_POINTERS(PersistentBase,BPtr); /** A map of objects indexed by integers */ ThePEG_DECLARE_MAP(cBPtr, int, ObjectMap); /** A map relating class descriptions to integers. */ ThePEG_DECLARE_MAP(const ClassDescriptionBase *, int, ClassMap); /** A vector of bare pointers to InputDescription objects. */ typedef ClassDescriptionBase::DescriptionVector DescriptionVector; public: /** * Constuctor giving an output stream. Optionally a vector of * libraries to be loaded before the resulting file can be read in * again can be given in \a libs. */ PersistentOStream(ostream &, const vector & libs = vector()); /** * Constuctor giving a file name to read. If the first * character in the string is a '|', the corresponding program is * run and its standard input is used instead. If the filename ends * in ".gz" the file is compressed with gzip. Optionally a vector of * libraries to be loaded before the resulting file can be read in * again can be given in \a libs. */ PersistentOStream(string, const vector & libs = vector()); /** * The destructor */ ~PersistentOStream(); /** * Operator for writing persistent objects to the stream. * @param p a pointer to the object to be written. * @return a reference to the stream. */ template PersistentOStream & operator<<(const RCPtr & p) { return outputPointer(p); } /** * Operator for writing persistent objects to the stream. * @param p a pointer to the object to be written. * @return a reference to the stream. */ template PersistentOStream & operator<<(const ConstRCPtr & p) { return outputPointer(p); } /** * Operator for writing persistent objects to the stream. * @param p a pointer to the object to be written. * @return a reference to the stream. */ template PersistentOStream & operator<<(const TransientRCPtr & p) { return outputPointer(p); } /** * Operator for writing persistent objects to the stream. * @param p a pointer to the object to be written. * @return a reference to the stream. */ template PersistentOStream & operator<<(const TransientConstRCPtr & p) { return outputPointer(p); } /** @name Operators for extracting built-in types from the stream. */ //@{ /** * Write a character string. */ PersistentOStream & operator<<(string s) { for ( string::const_iterator i = s.begin(); i < s.end(); ++i ) escape(*i); put(tSep); return *this; } /** * Write a character. */ PersistentOStream & operator<<(char c) { escape(c); put(tSep); return *this; } /** * Write a signed character. */ PersistentOStream & operator<<(signed char c) { return (*this) << static_cast(c); } /** * Write an unsigned character. */ PersistentOStream & operator<<(unsigned char c) { return (*this) << static_cast(c); } /** * Write an integer. */ PersistentOStream & operator<<(int i) { os() << i; put(tSep); return *this; } /** * Write an unsigned integer. */ PersistentOStream & operator<<(unsigned int i) { os() << i; put(tSep); return *this; } /** * Write a long integer. */ PersistentOStream & operator<<(long i) { os() << i; put(tSep); return *this; } /** * Write an unsigned long integer. */ PersistentOStream & operator<<(unsigned long i) { os() << i; put(tSep); return *this; } /** * Write a short integer. */ PersistentOStream & operator<<(short i) { os() << i; put(tSep); return *this; } /** * Write an unsigned short integer. */ PersistentOStream & operator<<(unsigned short i) { os() << i; put(tSep); return *this; } /** * Write a double. */ PersistentOStream & operator<<(double d) { if ( ! isfinite(d) ) throw WriteError() << "Tried to write a NaN or Inf double to a persistent stream." << Exception::runerror; os() << setprecision(18) << d; put(tSep); return *this; } /** * Write a float. */ PersistentOStream & operator<<(float f) { if ( ! isfinite(f) ) throw WriteError() << "Tried to write a NaN or Inf float to a persistent stream." << Exception::runerror; os() << setprecision(9) << f; put(tSep); return *this; } /** * Write a boolean. */ PersistentOStream & operator<<(bool t) { if (t) put(tYes); else put(tNo); // This is a workaround for a possible bug in gcc 4.0.0 // which inserts tYes and tNo as global symbols although // they are private // put(t? tYes: tNo); put(tSep); return *this; } /** * Write a c-style character string (to be read in as a std::string). */ PersistentOStream & operator<<(const char * s) { *this << string(s); return *this; } /** * Write a Complex. */ PersistentOStream & operator<<(Complex z) { *this << z.real() << z.imag(); return *this; } //@} /** * Output of containers of streamable objects. */ template void putContainer(const Container & c) { *this << c.size(); for ( typename Container::const_iterator it = c.begin(); it != c.end() && good() ; ++it ) *this << *it; } /** * Write out a persistent object given a pointer to it. */ PersistentOStream & outputPointer(tcBPtr); /** * For a given object, write the member variables corresponding to a * given ClassDescriptionBase object. * @param obj the object to be written. * @param cd a pointer to a ClassDescriptionBase describing the * (sub)class to written. */ void putObjectPart(tcBPtr obj, const ClassDescriptionBase * cd); /** * Remove all objects that have been written, except those which are * to be saved, from the list of written objects. */ PersistentOStream & flush(); /** * Instuct the stream to save the following objects (protecting them from * being flushed). */ PersistentOStream & push() { lastSavedObject.push(writtenObjects.size() - 1); return *this; } /** * Instuct the stream not to save the following objects. */ PersistentOStream & pop() { lastSavedObject.pop(); return *this; } /** * Check the state of the stream. */ bool good() const { return !badState && os(); } /** * Check the state of the stream. */ operator bool() const { return good(); } /** * Check the state of the stream. */ bool operator!() const { return !good(); } private: /** @cond EXCEPTIONCLASSES */ /** @ingroup Persistency * Internal exception class. */ struct MissingClass: public Exception {}; /** @ingroup Persistency * Internal exception class. */ struct WriteError: public Exception {}; /** @endcond */ /** * The version of this PersistentOStream implementation. */ static const int version = 0; /** * The subversion of this PersistentOStream implementation. */ static const int subVersion = 3; /** @name Special marker characters */ //@{ /** * The special marker character indicating the beginning of an object. */ static const char tBegin = '{'; /** * The special marker character indicating the end of an object. */ static const char tEnd = '}'; /** * The marker character indicating the beginning of the next base * class in case of multiple inheritance. */ /** * The special marker character indicating an escaped marker character. */ static const char tNext = '|'; /** * The special marker character indicating an escaped marker character. */ static const char tNull = '\\'; /** * The special marker character indicating the end of a value. */ static const char tSep = '\n'; /** * The special marker character used to avoid confusion with escaped * tSep markers. */ static const char tNoSep = 'n'; /** * The special marker character indicating a true boolean value. */ static const char tYes = 'y'; /** * The special marker character indicating a false boolean value. */ static const char tNo = 'n'; //@} /** * Return true if the given character is aspecial marker character. */ bool isToken(char c) const { return c == tBegin || c == tEnd || c == tNext || c == tSep || c == tNull; } /** * Set the stream in a bad state. */ void setBadState() { breakThePEG(); badState = true; } /** * Check if the state is ok. */ void checkState() { if ( ! os() ) badState = true; } /** * Write out class information to the associated ostream. */ const ClassDescriptionBase * writeClassId(tcBPtr); /** * write out class information to the associated ostream. */ void writeClassDescription(const ClassDescriptionBase *); /** * Put a "begin object" marker on the associated ostream */ void beginObject() { put(tBegin); } /** * Put a "end of object" marker on the associated ostream */ void endObject() { put(tEnd); } /** * Put an "next base class" marker on the associated ostream */ void endBase() { put(tNext); } /** * Put a character on the associated ostream */ void put(char c) { os().put(c); } /** * Put a character on the associated ostream but escape it if it is * a token. */ void escape(char c) { if ( isToken(c) ) { put(tNull); put( c == tSep? tNoSep: c ); } else put(c); } /** * Return a reference to the associated ostream. */ ostream & os() { return *theOStream; } /** * Return a const reference to the associated ostream. */ const ostream & os() const { return *theOStream; } /** * Write out initial metainfo on the stream. */ void init(const vector & libs); /** * List of written objects. */ ObjectMap writtenObjects; /** * List of written objects that are to be saved. */ stack lastSavedObject; /** * List of written classes. */ ClassMap writtenClasses; /** * A pointer to the associated ostream. */ ostream * theOStream; /** * True if no errors has occurred. */ bool badState; /** * True if the associated ostream should be deleted in the destructor. */ bool allocStream; private: /** * Standard ctors and assignment are private and not implemented. */ PersistentOStream(); /** * Standard ctors and assignment are private and not implemented. */ PersistentOStream(const PersistentOStream &); /** * Standard ctors and assignment are private and not implemented. */ PersistentOStream & operator=(const PersistentOStream &) = delete; }; /** * Operator for applying manipulators to the stream. */ inline PersistentOStream & operator<<(PersistentOStream & os, PersistentOManip func) { return (*func)(os); } /** * The manipulator for calling PersistentOStream::flush(). */ inline PersistentOStream & flush(PersistentOStream & os) { return os.flush(); } /** * The manipulator for calling PersistentOStream::push(). */ inline PersistentOStream & push(PersistentOStream & os) { return os.push(); } /** * The manipulator for calling PersistentOStream::pop(). */ inline PersistentOStream & pop(PersistentOStream & os) { return os.pop(); } /** * @name Partial specializations of operator<< for output of * std::containers. */ //@{ /** Output a pair of objects. */ template inline PersistentOStream & operator<<(PersistentOStream & os, const pair & p) { return os << p.first << p.second; } /** * Output a multimap of key/object pairs. */ template inline PersistentOStream & operator<<(PersistentOStream & os, const multimap & m) { os.putContainer(m); return os; } /** * Output a map of key/object pairs. */ template inline PersistentOStream & operator<<(PersistentOStream & os, const map & m) { os.putContainer(m); return os; } /** * Output a set of objects. */ template inline PersistentOStream & operator<<(PersistentOStream & os, const set & s) { os.putContainer(s); return os; } /** * Output a multiset of objects. */ template inline PersistentOStream & operator<<(PersistentOStream & os, const multiset & s) { os.putContainer(s); return os; } /** * Output a list of objects. */ template inline PersistentOStream & operator<<(PersistentOStream & os, const list & l) { os.putContainer(l); return os; } /** * Output a vector of objects. */ template inline PersistentOStream & operator<<(PersistentOStream & os, const vector & v) { os.putContainer(v); return os; } /** * Output an array of objects. */ template inline PersistentOStream & operator<<(PersistentOStream & os, const array & a) { for ( auto it = a.cbegin(); it != a.cend() && os.good() ; ++it ) os << *it; return os; } /** * Output a deque of objects. */ template inline PersistentOStream & operator<<(PersistentOStream & os, const deque & d) { os.putContainer(d); return os; } /** * Output a valarray. */ template inline PersistentOStream & operator<<(PersistentOStream & os, const std::valarray & v) { os << v.size(); for ( int i = 0, N = v.size(); i < N; ++i ) os << v[i]; return os; } //@} } #endif /* ThePEG_PersistentOStream_H */ diff --git a/Persistency/PersistentOStream.xh b/Persistency/PersistentOStream.xh --- a/Persistency/PersistentOStream.xh +++ b/Persistency/PersistentOStream.xh @@ -1,23 +1,23 @@ // -*- C++ -*- // // PersistentOStream.xh is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_PersistentOStream_XH #define ThePEG_PersistentOStream_XH // // This is the declarations of the exception classes used by the // PersistentOStream class. // #include "PersistentOStream.fh" namespace ThePEG { } #endif /* ThePEG_PersistentOStream_XH */ diff --git a/Pointer/Ptr.h b/Pointer/Ptr.h --- a/Pointer/Ptr.h +++ b/Pointer/Ptr.h @@ -1,67 +1,67 @@ // -*- C++ -*- // // Ptr.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_Ptr_H #define ThePEG_Ptr_H // This is the declaration of the Ptr class. #include "RCPtr.fh" namespace ThePEG { /** The namespace for the reference counted pointer classes */ namespace Pointer { /** * Ptr is a templated class to provide typedefs for pointers types * ThePEG should use for a given type. If you want to use ThePEG with * another kind of (smart) pointers than those provided you have to * provide an alternative ThePEG.h file which includes an alternative * Ptr class. It may also be possible to specialize this Ptr class for * using different pointer classes for different classes. * * @see RCPtr * @see ConstRCPtr * @see TransientRCPtr * @see TransientConstRCPtr * */ template struct Ptr { /** Template argument typedef. */ typedef RCPtr pointer; /** Template argument typedef. */ typedef ConstRCPtr const_pointer; /** Template argument typedef. */ typedef TransientRCPtr transient_pointer; /** Template argument typedef. */ typedef TransientConstRCPtr transient_const_pointer; /** Template argument typedef. */ typedef pointer ptr; /** Template argument typedef. */ typedef const_pointer cptr; /** Template argument typedef. */ typedef transient_pointer tptr; /** Template argument typedef. */ typedef transient_const_pointer tcptr; /** Template argument typedef. */ typedef pointer p; /** Template argument typedef. */ typedef const_pointer cp; /** Template argument typedef. */ typedef transient_pointer tp; /** Template argument typedef. */ typedef transient_const_pointer tcp; }; } } #endif /* ThePEG_Ptr_H */ diff --git a/Pointer/PtrTraits.h b/Pointer/PtrTraits.h --- a/Pointer/PtrTraits.h +++ b/Pointer/PtrTraits.h @@ -1,227 +1,227 @@ // -*- C++ -*- // // PtrTraits.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_PtrTraits_H #define ThePEG_PtrTraits_H // This is the declaration of the PtrTraits class. namespace ThePEG { namespace Pointer { /** * PtrTraitsType is an empty non-polymorphic base class for all * PtrTraits classes. */ struct PtrTraitsType {}; /** * The PtrTraits class is used everywhere in ThePEG to * interface to the pointers which are handled. In particular, ThePEG * never uses new or delete but always * PtrTraits

::create and * PtrTraits

::destroy (to be precise the destroy method * is never used since all pointers are assumed to be reference * counted or in another way garbage collected). Also ThePEG * always uses dynamic_ptr_cast (rather than the standard * dynamic_cast) which in turn calls the * PtrTraits

::DynamicCast. * * In this file is also defined the specialized std::iterator_traits * for the reference counted pointers. * */ template struct PtrTraits: public PtrTraitsType {}; /** * Specialization of the PtrTraits class for standard bare pointers. */ template struct PtrTraits: public PtrTraitsType { /** Template argument typedef. */ typedef T value_type; /** Template argument typedef. */ typedef T & reference; /** Template argument typedef. */ typedef const T & const_reference; /** Template argument typedef. */ typedef T * pointer; /** Template argument typedef. */ typedef T * const_pointer; /** * Return the bare pointer of the given pointer object. */ static T * barePointer(T * p) { return p; } /** * Create an object and return a pointer to it. */ static pointer create() { return new T; } /** * Create an copy of an object and return a pointer to it. */ static pointer create(const_reference t) { return new T(t); } /** * Destroy the object pointed to. */ static void destroy(pointer tp) { delete tp; } /** * Cast dynamically. */ template static pointer DynamicCast(R * r) { return dynamic_cast(r); } /** * Cast away constness. */ static pointer ConstCast(const T * t) { return const_cast(t); } /** * Cast from a basic pointer. */ static pointer PtrCast(T * t) { return t; } /** * The bare pointer is not reference counted. */ static const bool reference_counted = false; }; /** * Specialization of the PtrTraits class for standard bare * const pointers. */ template struct PtrTraits: public PtrTraitsType { /** Template argument typedef. */ typedef T value_type; /** Template argument typedef. */ typedef T & reference; /** Template argument typedef. */ typedef const T & const_reference; /** Template argument typedef. */ typedef T * pointer; /** Template argument typedef. */ typedef T * const_pointer; /** * Return the bare pointer of the given pointer object. */ static const T * barePointer(const T * p) { return p; } /** * Create an object and return a pointer to it. */ static pointer create() { return new T; } /** * Create an copy of an object and return a pointer to it. */ static pointer create(const_reference t) { return new T(t); } /** * Destroy the object pointed to. */ static void destroy(pointer tp) { delete tp; } /** * Cast dynamically. */ template static const_pointer DynamicCast(const R * r) { return dynamic_cast(r); } /** * Do not cast away constness. */ static const_pointer ConstCast(const T * r) { return r; } /** * Cast from a basic pointer. */ static const_pointer PtrCast(const T * t) { return t; } /** * The bare pointer is not reference counted. */ static const bool reference_counted = false; }; /** * Replacement for the standard dynamic_cast */ template T1 dynamic_ptr_cast(const T2 & t2) { return PtrTraits::DynamicCast(t2); } /** * Replacement for the standard const_cast */ template T1 const_ptr_cast(const T2 & t2) { return PtrTraits::ConstCast(t2); } /** * Simple interface to the PtrTraits::create() */ template inline Ptr ptr_new() { return PtrTraits::create(); } /** * Simple interface to the PtrTraits::create() */ template inline Ptr ptr_new(typename PtrTraits::const_reference t) { return PtrTraits::create(t); } /** * Simple interface to the PtrTraits::create() */ template inline typename Ptr::pointer new_ptr() { return PtrTraits< typename Ptr::pointer >::create(); } /** * Simple interface to the PtrTraits::create() */ template inline typename Ptr::pointer new_ptr(const T & t) { return PtrTraits< typename Ptr::pointer >::create(t); } /** * Simple interface to the PtrTraits::PtrCast() */ template inline TPtr ptr_cast(T * t) { return PtrTraits::PtrCast(t); } /** * Simple interface to the PtrTraits::PtrCast() */ template inline TPtr ptr_cast_const(const T * t) { return PtrTraits::PtrCast(const_cast(t)); } } } #endif /* ThePEG_PtrTraitsH */ diff --git a/Pointer/RCPtr.h b/Pointer/RCPtr.h --- a/Pointer/RCPtr.h +++ b/Pointer/RCPtr.h @@ -1,1171 +1,1171 @@ // -*- C++ -*- // // RCPtr.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_RCPtr_H #define ThePEG_RCPtr_H // This is the declaration of the RCPtrBase, #include "ReferenceCounted.h" #include "RCPtr.fh" #include "PtrTraits.h" namespace ThePEG { namespace Pointer { /** * RCPtrBase is the base class of RCPtr and ConstRCPtr which are * reference counted (smart) pointers. The RCPtrBase class communicates with the * ReferenceCounted object which must be the base class of * all objects pointed to and which keeps count of the pointers * pointing to an object. * * @see ReferenceCounted */ class RCPtrBase { /** Get counter type from ReferenceCounted class. */ typedef ReferenceCounted::CounterType CounterType; protected: /** * Increment the counter of a reference counted object. */ void increment(const ReferenceCounted * rcp) { if ( rcp ) rcp->incrementReferenceCount(); } /** * Decrement the counter of a reference counted object. */ bool release(const ReferenceCounted * rcp) { return rcp && rcp->decrementReferenceCount(); } }; /** * RCPtr is a reference counted (smart) pointer. Objects created using * the RCPtr::create() methods will continue living until no RCPtr or * ConstRCPtr are pointing to it, at which point it will be deleted. * * @see ReferenceCounted */ template class RCPtr: public RCPtrBase { public: /** Template argument typedef. */ typedef void iterator_category; /** Template argument typedef. */ typedef void difference_type; /** Template argument typedef. */ typedef T * pointer; /** Template argument typedef. */ typedef const T * const_pointer; /** Template argument typedef. */ typedef T & reference; /** Template argument typedef. */ typedef const T & const_reference; /** Template argument typedef. */ typedef T value_type; public: /** */ /** * Constructor for null pointer. */ RCPtr() : ptr(nullptr) {} /** * Constructor for nullptr. */ RCPtr( decltype(nullptr) ) : ptr(nullptr) {} /** * Copy constructor. */ RCPtr(const RCPtr & p) : ptr(p.ptr) { increment(); } /** * Copy constructor for class UPtr which has operator-> defined * resulting in a value implicitly convertible to T *. */ template RCPtr(const UPtr & u) : ptr(PtrTraits::barePointer(u)) { increment(); } /** * Construction from real pointer. */ explicit RCPtr(pointer p) : ptr(p) { increment(); } /** * Destructor. Deletes the object pointed to if this is the last * pointer to it. */ ~RCPtr() { release(); } /** * Allocate and construct an object of class T and return a RCPtr to * it. */ static RCPtr Create() { RCPtr p; return p.create(); } /** * Allocate and copy-construct an object of class T and return a * RCPtr to it. */ static RCPtr Create(const_reference t) { RCPtr p; return p.create(t); } /** * Allocate and construct an object of class T and point to it, * possibly deleting the object pointed to before. */ RCPtr & create() { release(); ptr = new T; // increment(); // ReferenceCounted() constructor starts at 1 return *this; } /** * Allocate and copy-construct an object of class T and point to it, * possibly deleting the object pointed to before. */ RCPtr & create(const_reference t) { release(); ptr = new T(t); // increment(); // ReferenceCounted() constructor starts at 1 return *this; } /** * Assignment. */ RCPtr & operator=(const RCPtr & p) { if ( ptr == p.ptr ) return *this; release(); ptr = p.ptr; increment(); return *this; } /** * Assignment from class UPtr which has operator-> defined resulting * in a value implicitly convertible to T *. */ template RCPtr & operator=(const UPtr & u) { if ( ptr == PtrTraits::barePointer(u) ) return *this; release(); ptr = PtrTraits::barePointer(u); increment(); return *this; } /** * Assignment from class UPtr which has operator-> defined resulting * in a value which can be cast dynamically to T *. */ template RCPtr & assignDynamic(const UPtr & u) { pointer up = dynamic_cast(PtrTraits::barePointer(u)); if ( ptr == up ) return *this; release(); ptr = up; increment(); return *this; } /** * Assignment from class UPtr which has operator-> defined resulting * in a value which can be const_cast'ed to T *. */ template RCPtr & assignConst(const UPtr & u) { pointer up = const_cast(PtrTraits::barePointer(u)); if ( ptr == up ) return *this; release(); ptr = up; increment(); return *this; } /** * Make p point to the object pointed to by this and vice versa. */ void swap(RCPtr & p) { const pointer tmp = ptr; ptr = p.ptr; p.ptr = tmp; // std::swap(ptr, p.ptr); } /** * Test for equality of the underlying pointers. */ bool operator==(const RCPtr & p) const { return ptr == p.ptr; } /** * Test for inequality of the underlying pointers. */ bool operator!=(const RCPtr & p) const { return ptr != p.ptr; } /** * Test for equality of the underlying pointers. */ bool operator==(const_pointer p) const { return ptr == p; } /** * Test for inequality of the underlying pointers. */ bool operator!=(const_pointer p) const { return ptr != p; } /** * Test for equality of the underlying pointers. */ template bool operator==(const UPtr & u) const { return ptr == PtrTraits::barePointer(u); } /** * Test for inequality of the underlying pointers. */ template bool operator!=(const UPtr & u) const { return ptr != PtrTraits::barePointer(u); } /** * Test for ordering. */ bool operator<(const RCPtr & p) const { return ( ptr && p.ptr && ptr->uniqueId != p.ptr->uniqueId ) ? ptr->uniqueId < p.ptr->uniqueId : ptr < p.ptr; } /** * Test for ordering. */ bool operator<(const_pointer p) const { return ( ptr && p && ptr->uniqueId != p->uniqueId ) ? ptr->uniqueId < p->uniqueId : ptr < p; } /** * Returns true if the underlying pointer is null. */ bool operator!() const { return !ptr; } /** * Returns the underlying pointer. */ operator T * () const { return ptr; } /** * Member access. */ pointer operator->() const { return ptr; } /** * Dereferencing. */ reference operator*() const { return *ptr; } private: /** * Increment the counter of the object pointed to. */ void increment() { RCPtrBase::increment(ptr); } /** * Stop pointing to the current object and delete it if this was the * last pointer to it. */ void release() { if ( RCPtrBase::release(ptr) ) delete ptr; } /** * The actual pointer. */ pointer ptr; }; /** * ConstRCPtr is a reference counted (smart) const pointer. Objects * created using the RCPtr::create() methods will continue living * until no RCPtr or ConstRCPtr are pointing to it, at which point it * will be deleted. * * @see ReferenceCounted */ template class ConstRCPtr : public RCPtrBase { public: /** Template argument typedef. */ typedef void iterator_category; /** Template argument typedef. */ typedef void difference_type; /** Template argument typedef. */ typedef T * pointer; /** Template argument typedef. */ typedef const T * const_pointer; /** Template argument typedef. */ typedef T & reference; /** Template argument typedef. */ typedef const T & const_reference; /** Template argument typedef. */ typedef T value_type; public: /** * Constructor for null pointer. */ ConstRCPtr() : ptr(nullptr) {} /** * Constructor for nullptr. */ ConstRCPtr( decltype(nullptr) ) : ptr(nullptr) {} /** * Copy constructor. */ ConstRCPtr(const ConstRCPtr & p) : ptr(p.ptr) { increment(); } /** * Copyconstructor for class UPtr which has operator-> defined * resulting in a value implicitly convertible to const T *. */ template ConstRCPtr(const UPtr & u) : ptr(PtrTraits::barePointer(u)) { increment(); } /** * Construction from real pointer. */ explicit ConstRCPtr(const_pointer p) : ptr(p) { increment(); } /** * Destructor. Deletes the object pointed to if this is the last * pointer to it. */ ~ConstRCPtr() { release(); } /** * Assignment. */ ConstRCPtr & operator=(const ConstRCPtr & p) { if ( ptr == p.ptr ) return *this; release(); ptr = p.ptr; increment(); return *this; } /** * Assignment from class UPtr which has operator-> defined resulting * in a value implicitly convertible to const T *. */ template ConstRCPtr & operator=(const UPtr & u) { if ( ptr == PtrTraits::barePointer(u) ) return *this; release(); ptr = PtrTraits::barePointer(u); increment(); return *this; } /** * Assignment from class UPtr which has operator-> defined resulting * in a value which can be cast dynamically to const T *. */ template ConstRCPtr & assignDynamic(const UPtr & u) { const_pointer up = dynamic_cast(PtrTraits::barePointer(u)); if ( ptr == up ) return *this; release(); ptr = up; increment(); return *this; } /** * Make p point to the object pointed to by this and vice versa. */ void swap(ConstRCPtr & p) { const const_pointer tmp = ptr; ptr = p.ptr; p.ptr = tmp; // std::swap(ptr, p.ptr); } /** * Test for equality of the underlying pointers. */ bool operator==(const ConstRCPtr & p) const { return ptr == p.ptr; } /** * Test for inequality of the underlying pointers. */ bool operator!=(const ConstRCPtr & p) const { return ptr != p.ptr; } /** * Test for equality of the underlying pointers. */ bool operator==(const_pointer p) const { return ptr == p; } /** * Test for inequality of the underlying pointers. */ bool operator!=(const_pointer p) const { return ptr != p; } /** * Test for equality of the underlying pointers. */ template bool operator==(const UPtr & u) const { return ptr == PtrTraits::barePointer(u); } /** * Test for inequality of the underlying pointers. */ template bool operator!=(const UPtr & u) const { return ptr != PtrTraits::barePointer(u); } /** * Test for ordering. */ bool operator<(const ConstRCPtr & p) const { return ( ptr && p.ptr && ptr->uniqueId != p.ptr->uniqueId ) ? ptr->uniqueId < p.ptr->uniqueId : ptr < p.ptr; } /** * Test for ordering. */ bool operator<(const_pointer p) const { return ( ptr && p && ptr->uniqueId != p->uniqueId ) ? ptr->uniqueId < p->uniqueId : ptr < p; } /** * Returns true if the underlying pointer is null. */ bool operator!() const { return !ptr; } /** * Returns the underlying pointer. */ operator const T * () const { return ptr; } /** * Member access. */ const_pointer operator->() const { return ptr; } /** * Dereferencing. */ const_reference operator*() const { return *ptr; } private: /** * Increment the counter of the object pointed to. */ void increment() { RCPtrBase::increment(ptr); } /** * Stop pointing to the current object and delete it if this was the * last pointer to it. */ void release() { if ( RCPtrBase::release(ptr) ) delete ptr; } /** * The actual pointer. */ const_pointer ptr; }; /** * TransientRCPtr is a simple wrapper around a bare pointer which can * be assigned to and from an RCPtr and ConstRCPtr without problem. * * @see RCPtr * @see ConstRCPtr */ template class TransientRCPtr { public: /** Template argument typedef. */ typedef void iterator_category; /** Template argument typedef. */ typedef void difference_type; /** Template argument typedef. */ typedef T * pointer; /** Template argument typedef. */ typedef const T * const_pointer; /** Template argument typedef. */ typedef T & reference; /** Template argument typedef. */ typedef const T & const_reference; /** Template argument typedef. */ typedef T value_type; public: /** * Constructor for null pointer. */ TransientRCPtr() : ptr(nullptr) {} /** * Constructor for nullptr. */ TransientRCPtr( decltype(nullptr) ) : ptr(nullptr) {} /** * Copy constructor. */ TransientRCPtr(const TransientRCPtr & p) : ptr(p.ptr) {} /** * Copyconstructor for class UPtr which has operator-> defined * resulting in a value implicitly convertible to T *. */ template TransientRCPtr(const UPtr & u) : ptr(PtrTraits::barePointer(u)) {} /** * Construction from real pointer. */ explicit TransientRCPtr(pointer p) : ptr(p) {} /** * Destructor. Does not delete the object pointed to. */ ~TransientRCPtr() {} /** * Assignment. */ TransientRCPtr & operator=(const TransientRCPtr & p) { ptr = p.ptr; return *this; } /** * Assignment from class UPtr which has operator-> defined resulting * in a value implicitly convertible to T *. */ template TransientRCPtr & operator=(const UPtr & u) { ptr = PtrTraits::barePointer(u); return *this; } /** * Assignment from class UPtr which has operator-> defined resulting * in a value which can be cast dynamically to T *. */ template TransientRCPtr & assignDynamic(const UPtr & u) { ptr = dynamic_cast(PtrTraits::barePointer(u)); return *this; } /** * Assignment from class UPtr which has operator-> defined resulting * in a value whcih can be const_cast'ed to T *. */ template TransientRCPtr & assignConst(const UPtr & u) { ptr = const_cast(PtrTraits::barePointer(u)); return *this; } /** * Test for equality of the underlying pointers. */ bool operator==(const TransientRCPtr & p) const { return ptr == p.ptr; } /** * Test for inequality of the underlying pointers. */ bool operator!=(const TransientRCPtr & p) const { return ptr != p.ptr; } /** * Test for equality of the underlying pointers. */ bool operator==(const_pointer p) const { return ptr == p; } /** * Test for inequality of the underlying pointers. */ bool operator!=(const_pointer p) const { return ptr != p; } /** * Test for equality of the underlying pointers. */ template bool operator==(const UPtr & u) const { return ptr == PtrTraits::barePointer(u); } /** * Test for inequality of the underlying pointers. */ template bool operator!=(const UPtr & u) const { return ptr != PtrTraits::barePointer(u); } /** * Test for ordering. */ bool operator<(const TransientRCPtr & p) const { return ( ptr && p.ptr && ptr->uniqueId != p.ptr->uniqueId ) ? ptr->uniqueId < p.ptr->uniqueId : ptr < p.ptr; } /** * Test for ordering. */ bool operator<(const_pointer p) const { return ( ptr && p && ptr->uniqueId != p->uniqueId ) ? ptr->uniqueId < p->uniqueId : ptr < p; } /** * Returns true if the underlying pointer is null. */ bool operator!() const { return !ptr; } /** * Returns the underlying pointer. */ operator T * () const { return ptr; } /** * Member access. */ pointer operator->() const { return ptr; } /** * Dereferencing. */ reference operator*() const { return *ptr; } private: /** * The actual pointer. */ pointer ptr; }; /** * TransientConstRCPtr is a simple wrapper around a bare const pointer * which can be assigned to and from an RCPtr and ConstRCPtr without * problem. * * @see RCPtr * @see ConstRCPtr */ template class TransientConstRCPtr { public: /** Template argument typedef. */ typedef void iterator_category; /** Template argument typedef. */ typedef void difference_type; /** Template argument typedef. */ typedef T * pointer; /** Template argument typedef. */ typedef const T * const_pointer; /** Template argument typedef. */ typedef T & reference; /** Template argument typedef. */ typedef const T & const_reference; /** Template argument typedef. */ typedef T value_type; public: /** * Constructor for null pointer. */ TransientConstRCPtr() : ptr(nullptr) {} /** * Constructor for nullptr. */ TransientConstRCPtr( decltype(nullptr) ) : ptr(nullptr) {} /** * Copy constructor. */ TransientConstRCPtr(const TransientConstRCPtr & p) : ptr(p.ptr) {} /** * Copyconstructor for class UPtr which has operator-> defined * resulting in a value implicitly convertible to const T *. */ template TransientConstRCPtr(const UPtr & u) : ptr(PtrTraits::barePointer(u)) {} /** * Construction from real pointer. */ explicit TransientConstRCPtr(const_pointer p) : ptr(p) {} /** * Destructor. Does not delete the object pointed to. */ ~TransientConstRCPtr() {} /** * Assignment. */ TransientConstRCPtr & operator=(const TransientConstRCPtr & p) { ptr = p.ptr; return *this; } /** * Assignment from class UPtr which has operator-> defined resulting * in a value implicitly convertible to const T *. */ template TransientConstRCPtr & operator=(const UPtr & u) { ptr = PtrTraits::barePointer(u); return *this; } /** * Assignment from class UPtr which has operator-> defined resulting * in a value which can be cast dynamically to const T *. */ template TransientConstRCPtr & assignDynamic(const UPtr & u) { ptr = dynamic_cast(PtrTraits::barePointer(u)); return *this; } /** * Test for equality of the underlying pointers. */ bool operator==(const TransientConstRCPtr & p) const { return ptr == p.ptr; } /** * Test for inequality of the underlying pointers. */ bool operator!=(const TransientConstRCPtr & p) const { return ptr != p.ptr; } /** * Test for equality of the underlying pointers. */ bool operator==(const_pointer p) const { return ptr == p; } /** * Test for inequality of the underlying pointers. */ bool operator!=(const_pointer p) const { return ptr != p; } /** * Test for equality of the underlying pointers. */ template bool operator==(const UPtr & u) const { return ptr == PtrTraits::barePointer(u); } /** * Test for inequality of the underlying pointers. */ template bool operator!=(const UPtr & u) const { return ptr != PtrTraits::barePointer(u); } /** * Test for ordering. */ bool operator<(const TransientConstRCPtr & p) const { return ( ptr && p.ptr && ptr->uniqueId != p.ptr->uniqueId ) ? ptr->uniqueId < p.ptr->uniqueId : ptr < p.ptr; } /** * Test for ordering. */ bool operator<(const_pointer p) const { return ( ptr && p && ptr->uniqueId != p->uniqueId ) ? ptr->uniqueId < p->uniqueId : ptr < p; } /** * Returns true if the underlying pointer is null. */ bool operator!() const { return !ptr; } /** * Returns (not) the underlying pointer. */ operator const T * () const { return ptr; } /** * Member access. */ const_pointer operator->() const { return ptr; } /** * Dereferencing. */ const_reference operator*() const { return *ptr; } private: /** * The actual pointer. */ const_pointer ptr; }; /** * Specialization of the PtrTraits class for RCPtr. */ template struct PtrTraits< RCPtr >: public PtrTraitsType { /** Template argument typedef. */ typedef typename RCPtr::value_type value_type; /** Template argument typedef. */ typedef typename RCPtr::reference reference; /** Template argument typedef. */ typedef typename RCPtr::const_reference const_reference; /** Template argument typedef. */ typedef RCPtr pointer; /** Template argument typedef. */ typedef ConstRCPtr const_pointer; /** Template argument typedef. */ typedef TransientRCPtr transient_pointer; /** Template argument typedef. */ typedef TransientConstRCPtr transient_const_pointer; /** * Return the bare pointer of the given pointer object. */ static T * barePointer(const RCPtr & p) { return p.operator->(); } /** * Create an object and return a pointer to it. */ static pointer create() { return RCPtr::Create(); } /** * Create an copy of an object and return a pointer to it. */ static pointer create(const_reference t) { return RCPtr::Create(t); } /** * Destroy the object pointed to. */ static void destroy(pointer) {} /** * Cast dynamically. */ template static pointer DynamicCast(const UPtr & u) { pointer t; t.assignDynamic(u); return t; } /** * Cast away constness. */ template static pointer ConstCast(const UPtr & u) { pointer t; t.assignConst(u); return t; } /** * Cast from a basic pointer. */ static pointer PtrCast(T * t) { return pointer(t); } /** * RCPtr is reference counted. */ static const bool reference_counted = true; }; /** * Specialization of the PtrTraits class for ConstRCPtr. */ template struct PtrTraits< ConstRCPtr >: public PtrTraitsType { /** Template argument typedef. */ typedef typename ConstRCPtr::value_type value_type; /** Template argument typedef. */ typedef typename ConstRCPtr::reference reference; /** Template argument typedef. */ typedef typename ConstRCPtr::const_reference const_reference; /** Template argument typedef. */ typedef RCPtr pointer; /** Template argument typedef. */ typedef ConstRCPtr const_pointer; /** Template argument typedef. */ typedef TransientRCPtr transient_pointer; /** Template argument typedef. */ typedef TransientConstRCPtr transient_const_pointer; /** * Return the bare pointer of the given pointer object. */ static const T * barePointer(const ConstRCPtr & p) { return p.operator->(); } /** * Create an object and return a pointer to it. */ static const_pointer create() { return RCPtr::Create(); } /** * Create an copy of an object and return a pointer to it. */ static const_pointer create(const_reference t) { return RCPtr::Create(t); } /** * Destroy the object pointed to. */ static void destroy(const_pointer) {} /** * Cast dynamically. */ template static const_pointer DynamicCast(const UPtr & u) { const_pointer t; t.assignDynamic(u); return t; } /** * Cast away constness. */ template static const_pointer ConstCast(const UPtr & u) { const_pointer t; t.assignDynamic(u); return t; } /** * Cast from a basic pointer. */ static const_pointer PtrCast(const T * t) { return const_pointer(t); } /** * ConstRCPtr is reference counted. */ static const bool reference_counted = true; }; /** * Specialization of the PtrTraits class for TransientRCPtr. */ template struct PtrTraits< TransientRCPtr >: public PtrTraitsType { /** Template argument typedef. */ typedef typename TransientRCPtr::value_type value_type; /** Template argument typedef. */ typedef typename TransientRCPtr::reference reference; /** Template argument typedef. */ typedef typename TransientRCPtr::const_reference const_reference; /** Template argument typedef. */ typedef RCPtr pointer; /** Template argument typedef. */ typedef ConstRCPtr const_pointer; /** Template argument typedef. */ typedef TransientRCPtr transient_pointer; /** Template argument typedef. */ typedef TransientConstRCPtr transient_const_pointer; /** * Return the bare pointer of the given pointer object. */ static T * barePointer(const TransientRCPtr & p) { return p.operator->(); } /** * Destroy the object pointed to. */ static void destroy(transient_pointer) {} /** * Cast dynamically. */ template static transient_pointer DynamicCast(const UPtr & u) { transient_pointer t; t.assignDynamic(u); return t; } /** * Cast away constness. */ static transient_pointer ConstCast(transient_const_pointer c) { transient_pointer t; t.assignConst(c); return t; } /** * Cast from a basic pointer. */ static transient_pointer PtrCast(T * t) { return transient_pointer(t); } /** * TransientRCPtr is not reference counted. */ static const bool reference_counted = false; }; /** * Specialization of the PtrTraits class for TransientConstRCPtr. */ template struct PtrTraits< TransientConstRCPtr >: public PtrTraitsType { /** Template argument typedef. */ typedef typename TransientConstRCPtr::value_type value_type; /** Template argument typedef. */ typedef typename TransientConstRCPtr::reference reference; /** Template argument typedef. */ typedef typename TransientConstRCPtr::const_reference const_reference; /** Template argument typedef. */ typedef RCPtr pointer; /** Template argument typedef. */ typedef ConstRCPtr const_pointer; /** Template argument typedef. */ typedef TransientRCPtr transient_pointer; /** Template argument typedef. */ typedef TransientConstRCPtr transient_const_pointer; /** * Return the bare pointer of the given pointer object. */ static const T * barePointer(const TransientConstRCPtr & p) { return p.operator->(); } /** * Destroy the object pointed to. */ static void destroy(transient_const_pointer) {} /** * Cast dynamically. */ template static transient_const_pointer DynamicCast(const UPtr & u) { transient_const_pointer t; t.assignDynamic(u); return t; } /** * Cast away constness. */ template static transient_const_pointer ConstCast(const UPtr & u) { transient_const_pointer t; t.assignConst(u); return t; } /** * Cast from a basic pointer. */ static transient_const_pointer PtrCast(const T * t) { return transient_const_pointer(t); } /** * TransientConstRCPtr is not reference counted. */ static const bool reference_counted = false; }; } } namespace std { /** * Specialization of std::swap to avoid unnecessary (in/de)crements of * the reference count. */ template inline void swap(ThePEG::Pointer::RCPtr & t1, ThePEG::Pointer::RCPtr & t2) { t1.swap(t2); } /** * Specialization of std::swap to avoid unnecessary (in/de)crements of * the reference count. */ template inline void swap(ThePEG::Pointer::ConstRCPtr & t1, ThePEG::Pointer::ConstRCPtr & t2) { t1.swap(t2); } } #endif /* ThePEG_RCPtr_H */ diff --git a/Pointer/ReferenceCounted.h b/Pointer/ReferenceCounted.h --- a/Pointer/ReferenceCounted.h +++ b/Pointer/ReferenceCounted.h @@ -1,126 +1,126 @@ // -*- C++ -*- // // ReferenceCounted.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_ReferenceCounted_H #define ThePEG_ReferenceCounted_H // This is the declaration of the ReferenceCounted class. #include "RCPtr.fh" #include "ThePEG/Persistency/PersistentIStream.fh" namespace ThePEG { namespace Pointer { /** * ReferenceCounted must be the (virtual) base class of all * classes which may be pointed to by the RCPtr smart * pointer class. It keeps track of all RCPtr and * ConstRCPtr pointers which are currently pointing to an * object. * * @see RCPtr * @see ConstRCPtr */ class ReferenceCounted { /** The RCPtrBase class needs to acces the private parts of ReferenceCounted. */ friend class RCPtrBase; friend class ThePEG::PersistentIStream; public: /** * The integer type used for counting. */ typedef unsigned int CounterType; protected: /** @name Standard constructors and assignment. */ //@{ /** * Default constructor. */ ReferenceCounted() : uniqueId(++objectCounter), theReferenceCounter(CounterType(1)) {} /** * Copy-constructor. */ ReferenceCounted(const ReferenceCounted &) : uniqueId(++objectCounter), theReferenceCounter(CounterType(1)) {} /** * Assignment. */ ReferenceCounted & operator=(const ReferenceCounted &) { return *this; } //@} public: /** * Return the reference count. */ CounterType referenceCount() const { return theReferenceCounter; } private: /** * Increment the reference count. */ void incrementReferenceCount() const { ++theReferenceCounter; } /** * Decrement with the reference count. */ bool decrementReferenceCount() const { return !--theReferenceCounter; } public: /** * The unique ID. Can be used as sorting criterion, e.g. for set<> and map<>. */ const unsigned long uniqueId; private: /** * A counter for issuing unique IDs. It will overflow back to 0 eventually, * but it is very unlikely that two identical IDs show up in the same event. */ static unsigned long objectCounter; /** * The reference count. */ mutable CounterType theReferenceCounter; }; } } #endif /* ThePEG_ReferenceCounted_H */ diff --git a/Repository/BaseRepository.cc b/Repository/BaseRepository.cc --- a/Repository/BaseRepository.cc +++ b/Repository/BaseRepository.cc @@ -1,986 +1,986 @@ // -*- C++ -*- // // BaseRepository.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the BaseRepository class. // // macro is passed in from -D compile flag #ifndef THEPEG_PKGDATADIR #error Makefile.am needs to define THEPEG_PKGDATADIR #endif #include "BaseRepository.h" #include "ThePEG/Config/algorithm.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/InterfaceBase.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/Interface/Command.h" #include "ThePEG/Utilities/ClassDescription.h" #include "ThePEG/Utilities/DescriptionList.h" #include "ThePEG/Utilities/HoldFlag.h" #include "ThePEG/Utilities/TypeInfo.h" #include "ThePEG/Utilities/DynamicLoader.h" #include "ThePEG/Utilities/StringUtils.h" #include "ThePEG/Utilities/Throw.h" #include "ThePEG/PDT/DecayMode.h" #ifdef ThePEG_TEMPLATES_IN_CC_FILE #include "BaseRepository.tcc" #endif using namespace ThePEG; ostream *& BaseRepository::coutp() { static ostream * theCout = &std::cout; return theCout; } ostream *& BaseRepository::cerrp() { static ostream * theCerr = &std::cerr; return theCerr; } ostream *& BaseRepository::clogp() { static ostream * theClog = &std::clog; return theClog; } bool & BaseRepository::updating() { static bool theBool = false; return theBool; } ObjectMap & BaseRepository::objects() { static ObjectMap theObjectMap; return theObjectMap; } ObjectSet & BaseRepository::allObjects() { static ObjectSet theObjectSet; return theObjectSet; } BaseRepository::TypeInterfaceMap & BaseRepository::interfaces() { static TypeInterfaceMap theInterfaceMap; return theInterfaceMap; } BaseRepository::TypeDocumentationMap & BaseRepository::documentations() { static TypeDocumentationMap theDocumentationMap; return theDocumentationMap; } BaseRepository::DirectorySet & BaseRepository::directories() { static DirectorySet theDirectories = {"/"}; return theDirectories; } vector & BaseRepository::globalLibraries() { static vector theGlobalLibraries; return theGlobalLibraries; } stack & BaseRepository::currentReadDirStack() { static stack theCurrentReadDirStack; if ( theCurrentReadDirStack.empty() ) theCurrentReadDirStack.push(""); return theCurrentReadDirStack; } vector & BaseRepository::readDirs() { // macro is passed in from -D compile flag static vector theReadDirs(1, THEPEG_PKGDATADIR); return theReadDirs; } const vector & BaseRepository::listReadDirs() { return BaseRepository::readDirs(); } void BaseRepository::prependReadDir(string dir) { readDirs().insert(readDirs().begin(), dir); } void BaseRepository::prependReadDir(const std::vector& dirs) { readDirs().insert(readDirs().begin(), dirs.begin(), dirs.end()); } void BaseRepository::appendReadDir(string dir) { readDirs().push_back(dir); } void BaseRepository::appendReadDir(const std::vector& dirs) { readDirs().insert(readDirs().end(), dirs.begin(), dirs.end()); } BaseRepository::StringVector & BaseRepository::directoryStack() { static StringVector theDirectoryStack(1, "/"); return theDirectoryStack; } void BaseRepository::Register(const InterfaceBase & ib, const type_info & i) { const ClassDescriptionBase * db = DescriptionList::find(i); if ( db ) interfaces()[db].insert(&ib); } void BaseRepository:: Register(const ClassDocumentationBase & cd, const type_info & i) { const ClassDescriptionBase * db = DescriptionList::find(i); if ( db ) documentations()[db] = &cd; } void BaseRepository::Register(IBPtr ip, string newName) { DirectoryAppend(newName); ip->name(newName); Register(ip); } void BaseRepository::Register(IBPtr ip) { if ( !ip || member(allObjects(), ip) ) return; if ( member(objects(), ip->fullName()) ) throw RepoNameExistsException(ip->fullName()); objects()[ip->fullName()] = ip; allObjects().insert(ip); ip->clear(); ip->update(); ip->touch(); } void BaseRepository::DirectoryAppend(string & name) { if ( name == "." ) name = directoryStack().back(); if ( name[0] != '/' ) name = directoryStack().back() + name; } void BaseRepository::CreateDirectory(string name) { DirectoryAppend(name); if ( name[name.size()-1] != '/' ) name += "/"; if ( member(directories(), name) ) return; directories().insert(name); name = name.substr(0, name.size() - 1); name = name.substr(0, name.rfind('/')); if ( name.size() ) CreateDirectory(name); } void BaseRepository::CheckObjectDirectory(string name) { if ( name[name.size() - 1] != '/' ) name = name.substr(0, name.rfind('/') + 1); CheckDirectory(name); } void BaseRepository::CheckDirectory(string name) { DirectoryAppend(name); if ( name[name.size()-1] != '/' ) name += "/"; if ( member(directories(), name) ) return; throw RepositoryNoDirectory(name); } void BaseRepository::ChangeDirectory(string name) { DirectoryAppend(name); if ( name[name.size()-1] != '/' ) name += "/"; if ( member(directories(), name) ) { directoryStack().back() = name; return; } throw RepositoryNoDirectory(name); } void BaseRepository::PushDirectory(string name) { DirectoryAppend(name); if ( name[name.size()-1] != '/' ) name += "/"; if ( member(directories(), name) ) { directoryStack().push_back(name); return; } throw RepositoryNoDirectory(name); } void BaseRepository::PopDirectory() { if ( directoryStack().size() > 1 ) directoryStack().pop_back(); } IBPtr BaseRepository::GetPointer(string name) { ObjectMap::iterator it = objects().find(name); return it == objects().end()? IBPtr(): it->second; } IVector BaseRepository::SearchDirectory(string name, string className) { IVector ret; DirectoryAppend(name); const ClassDescriptionBase * cdb = 0; if ( className.size() ) { cdb = DescriptionList::find(className); if ( !cdb ) return ret; } if ( name[name.size()-1] != '/' ) name += "/"; string::size_type size = name.size(); for ( ObjectMap::const_iterator i = objects().begin(); i != objects().end(); ++i ) { const auto & tmp=(*(i->second)); if ( cdb && !DescriptionList::find(typeid(tmp))->isA(*cdb) ) continue; if ( i->first.substr(0, size) == name ) ret.push_back(i->second); } return ret; } IVector BaseRepository::GetObjectsReferringTo(IBPtr obj) { IVector ret; for ( ObjectMap::const_iterator i = objects().begin(); i != objects().end(); ++i ) { if ( obj == i->second ) continue; IVector ov = DirectReferences(i->second); if ( member(ov, obj) ) ret.push_back(i->second); } return ret; } IVector BaseRepository::DirectReferences(IBPtr obj) { IVector ov = obj->getReferences(); const auto & tmp=*obj; InterfaceMap interfaceMap = getInterfaces(typeid(tmp)); for ( InterfaceMap::iterator iit = interfaceMap.begin(); iit != interfaceMap.end(); ++iit ) { IVector ovi = iit->second->getReferences(*obj); ov.insert(ov.end(), ovi.begin(), ovi.end()); } return ov; } void BaseRepository:: addReferences(tIBPtr obj, ObjectSet & refs) { if ( !obj ) return; refs.insert(obj); IVector ov = obj->getReferences(); for ( IVector::const_iterator it = ov.begin(); it != ov.end(); ++it ) if ( !member(refs, *it) ) addReferences(*it, refs); const auto & tmp=*obj; InterfaceMap interfaceMap = getInterfaces(typeid(tmp)); for ( InterfaceMap::iterator iit = interfaceMap.begin(); iit != interfaceMap.end(); ++iit ) { IVector ov = iit->second->getReferences(*obj); for ( IVector::const_iterator it = ov.begin(); it != ov.end(); ++it ) if ( !member(refs, *it) ) addReferences(*it, refs); } } void BaseRepository:: addInterfaces(const ClassDescriptionBase & db, InterfaceMap & interfaceMap, bool all) { for ( ClassDescriptionBase::DescriptionVector::const_iterator it = db.descriptions().begin(); it != db.descriptions().end(); ++it ) if ( *it ) addInterfaces(**it, interfaceMap, all); TypeInterfaceMap::const_iterator cit = interfaces().find(&db); if ( cit == interfaces().end() ) return; for ( InterfaceSet::const_iterator iit = (cit->second).begin(); iit != (cit->second).end(); ++iit ) { string n = (**iit).name(); while ( all && member(interfaceMap, n) ) n = "+" + n; interfaceMap[n] = *iit; } } InterfaceMap BaseRepository::getInterfaces(const type_info & ti, bool all) { InterfaceMap interfaceMap; const ClassDescriptionBase * db = DescriptionList::find(ti); if ( !db ) return interfaceMap; addInterfaces(*db, interfaceMap, all); return interfaceMap; } void BaseRepository:: rebind(InterfacedBase & i, const TranslationMap & trans, const IVector & defaults) { InterfaceMap interfaceMap = getInterfaces(typeid(i), true); for ( InterfaceMap::iterator iit = interfaceMap.begin(); iit != interfaceMap.end(); ++iit ) iit->second->rebind(i, trans, defaults); i.rebind(trans); } void BaseRepository::update() { for_each(allObjects(), std::mem_fn(&InterfacedBase::update)); clearAll(allObjects()); } template bool overlap(const Set1 & s1, const Set2 & s2) { typename Set1::const_iterator i1 = s1.begin(); typename Set2::const_iterator i2 = s2.begin(); while ( i1 != s1.end() && i2 != s2.end() ) { if ( *i1 == *i2 ) return true; if ( *i1 < *i2 ) { i1 = s1.lower_bound(*i2); if ( *i1 == *i2 ) return true; ++i1; } else { i2 = s2.lower_bound(*i1); if ( *i1 == *i2 ) return true; ++i2; } } return false; } void BaseRepository::remove(tIBPtr ip) { ObjectMap::iterator it = objects().find(ip->fullName()); if ( it == objects().end() || ip != it->second ) return; objects().erase(it); allObjects().erase(ip); } string BaseRepository::remove(const ObjectSet & rmset) { ObjectSet refset; for ( ObjectSet::const_iterator oi = rmset.begin(); oi != rmset.end(); ++oi ) { IVector ov = GetObjectsReferringTo(*oi); refset.insert(ov.begin(), ov.end()); } for ( ObjectSet::iterator oi = rmset.begin(); oi != rmset.end(); ++oi ) refset.erase(*oi); if ( refset.empty() ) { for ( ObjectSet::iterator oi = rmset.begin(); oi != rmset.end(); ++oi ) remove(*oi); return ""; } string ret = "Error: cannot remove the objects because the following " "objects refers to some of them:\n"; for ( ObjectSet::iterator oi = refset.begin(); oi != refset.end(); ++oi ) ret += (**oi).fullName() + "\n"; return ret; } void BaseRepository::rename(tIBPtr ip, string newName) { ObjectSet::iterator it = allObjects().find(ip); if ( it == allObjects().end() ) { Register(ip, newName); return; } ObjectMap::iterator mit = objects().find(ip->fullName()); if ( mit == objects().end() || mit->second != ip ) throw RepoNameException(ip->fullName()); objects().erase(mit); ip->name(newName); while ( member(objects(), ip->fullName()) ) ip->name(ip->fullName() + "#"); objects()[ip->fullName()] = ip; } const InterfaceBase * BaseRepository::FindInterface(IBPtr ip, string name) { const auto & tmp=*ip; InterfaceMap imap = getInterfaces(typeid(tmp), false); InterfaceMap::iterator it = imap.find(name); return it == imap.end()? 0: it->second; } const ClassDocumentationBase * BaseRepository::getDocumentation(tcIBPtr ip) { const auto & tmp=*ip; TypeDocumentationMap::const_iterator cdoc = documentations().find(DescriptionList::find(typeid(tmp))); return cdoc != documentations().end()? cdoc->second: 0; } string BaseRepository::getModelDescription(tcIBPtr ip) { const ClassDocumentationBase * cd = getDocumentation(ip); return cd? cd->modelDescription(): string(""); } string BaseRepository::getModelReferences(tcIBPtr ip) { const ClassDocumentationBase * cd = getDocumentation(ip); return cd? cd->modelReferences(): string(""); } IBPtr BaseRepository::TraceObject(string path) { DirectoryAppend(path); string::size_type colon = path.find(':'); IBPtr ip = GetPointer(path.substr(0, colon)); if ( !ip ) { // Do special check if this is a decay mode. string name = path.substr(0, colon); string::size_type slash = name.rfind('/'); if ( slash != string::npos ) name = name.substr(slash + 1); if ( name.find("->") != string::npos && name[name.length() - 1] == ';' ) { vector save; DMPtr dm = DecayMode::constructDecayMode(name, &save); if ( dm ) ip = dynamic_ptr_cast(GetPointer(path.substr(0, slash + 1) + dm->tag())); if ( ip ) Throw() << "Warning: rewriting DecayMode name '" << path.substr(0, colon).substr(slash + 1) << "' to '" << ip->name() << Exception::warning; } } while ( colon != string::npos ) { if ( !ip ) throw RepositoryNotFound(path); path = path.substr(colon+1); colon = path.find(':'); string::size_type bra = path.find('['); const InterfaceBase * ifb = FindInterface(ip, path.substr(0, min(colon, bra))); const ReferenceBase * rb = dynamic_cast(ifb); if ( rb ) { ip = rb->get(*ip); continue; } const RefVectorBase * rvb = dynamic_cast(ifb); if ( rvb ) { unsigned int place = 0; if ( bra < colon ) { string::size_type ket = path.find(']'); place = atoi(path.substr(bra + 1,ket - bra - 1).c_str()); } IVector iv = rvb->get(*ip); if ( place >= iv.size() ) throw RepositoryNotFound(path); ip = iv[place]; continue; } const CommandBase * cb = dynamic_cast(ifb); if ( cb ) { string::size_type ket = path.find(']'); string newobj = cb->cmd(*ip, path.substr(bra + 1,ket - bra - 1)); ip = GetPointer(newobj); continue; } throw RepositoryNotFound(path); } if ( !ip ) throw RepositoryNotFound(path); return ip; } IBPtr BaseRepository::getObjectFromNoun(string noun) { string::size_type colon = noun.rfind(':'); return TraceObject(noun.substr(0, colon)); } string BaseRepository::getInterfaceFromNoun(string noun) { string::size_type colon = noun.rfind(':'); string interface = noun.substr(colon+1); string::size_type bra = interface.find('['); if ( bra != string::npos ) return interface.substr(0, bra); else return interface; } string BaseRepository::getPosArgFromNoun(string noun) { string::size_type colon = noun.rfind(':'); string interface = noun.substr(colon+1); string::size_type bra = interface.find('['); if ( bra != string::npos ) { string::size_type ket = interface.find(']'); return interface.substr(bra + 1,ket - bra - 1); } return ""; } string BaseRepository:: GetInterfacedBaseClasses(const ClassDescriptionBase * cdb) { if ( !cdb || cdb->name() == "ThePEG::Interfaced" || cdb->name() == "ThePEG::InterfacedBase" ) return ""; string ret = cdb->name() + "\n"; for ( int i = 0, N = cdb->descriptions().size(); i < N; ++i ) ret += GetInterfacedBaseClasses(cdb->descriptions()[i]); return ret; } struct InterfaceOrder { bool operator()(const InterfaceBase * x, const InterfaceBase * y) const { return x->rank() > y->rank() || ( x->rank() == y->rank() && x->name() < y->name() ); } }; void BaseRepository::readSetup(tIBPtr ip, istream & is) { ip->setup(is); } string BaseRepository::exec(string command, ostream &) { string verb = StringUtils::car(command); command = StringUtils::cdr(command); if ( verb.empty() || verb[0] == '#' ) return ""; try { if ( verb == "DISABLEREADONLY" ) { InterfaceBase::NoReadOnly = true; return ""; } if ( verb == "ENABLEREADONLY" ) { InterfaceBase::NoReadOnly = false; return ""; } if ( verb == "cd" || verb == "pushd" || verb == "mkdir") { string dir = StringUtils::car(command); if ( verb == "cd" ) ChangeDirectory(dir); else if ( verb == "pushd" ) PushDirectory(dir); else CreateDirectory(dir); return ""; } if ( verb == "popd" ) { PopDirectory(); return ""; } if ( verb == "pwd" ) return directoryStack().back(); if ( verb == "dirs" ) { string ret; for ( StringVector::reverse_iterator it = directoryStack().rbegin(); it != directoryStack().rend(); ++it ) ret += *it; return ret; } if ( verb == "cp" || verb == "mv" ) { string oldname = StringUtils::car(command); DirectoryAppend(oldname); IBPtr obj = GetPointer(oldname); if ( !obj ) return "Error: No object named '" + oldname + "' available."; command = StringUtils::cdr(command); string newname = StringUtils::car(command); DirectoryAppend(newname); if ( newname[newname.size() - 1] == '/' ) newname += obj->name(); if ( verb == "cp" ) obj = obj->fullclone(); rename(obj, newname); return ""; } if ( verb == "check" ) { string name = StringUtils::car(command); if ( directories().find(name) != directories().end() ) return name; if ( objects().find(name) != objects().end() ) return name; return "Not found"; } if ( verb == "ls" ) { string className; string dir = StringUtils::car(command); if ( dir.size() ) { PushDirectory(dir); command = StringUtils::cdr(command); className = StringUtils::car(command); } string ret; string thisdir = directoryStack().back(); for ( DirectorySet::iterator it = directories().begin(); it != directories().end(); ++it ) { string d = *it; if ( d.size() <= thisdir.size() ) continue; string d0 = d.substr(0, thisdir.size()); string d1 = d.substr(thisdir.size()); if ( d0 == thisdir && d1.find('/') == d1.size() - 1 ) { if ( className.size() && SearchDirectory(d, className).empty() ) continue; ret += (dir.size()? d: d1) + "\n"; } } for ( ObjectMap::iterator it = objects().begin(); it != objects().end(); ++it ) { if ( className.size() ) { const ClassDescriptionBase * cdb = DescriptionList::find(className); const auto & tmp=*(it->second); if ( cdb && !DescriptionList::find(typeid(tmp))->isA(*cdb) ) continue; } if ( thisdir + it->second->name() == it->first ) ret += (dir.size()? it->first: it->second->name()) + '\n'; } if ( dir.size() ) PopDirectory(); return ret; } if ( verb == "library" ) { string library = StringUtils::car(command); if ( library.empty() ) return "Error: No library specified."; if ( !DynamicLoader::load(library) ) return "Error: Could not load library " + library + "\n - " + DynamicLoader::lastErrorMessage; return ""; } if ( verb == "globallibrary" ) { string library = StringUtils::car(command); if ( library.empty() ) return "Error: No library specified."; if ( !DynamicLoader::load(library) ) return "Error: Could not load library " + library + "\n - " + DynamicLoader::lastErrorMessage; globalLibraries().push_back(library); return ""; } if ( verb == "rmgloballibrary" ) { string library = StringUtils::car(command); if ( library.empty() ) return "Error: No library specified."; vector::iterator it; while ( (it = find(globalLibraries(), library)) != globalLibraries().end() ) globalLibraries().erase(it); return ""; } if ( verb == "appendpath" ) { string path = StringUtils::car(command); if ( !path.empty() ) DynamicLoader::appendPath(path); return ""; } if ( verb == "lspaths" ) { string paths; for ( int i = 0, N = DynamicLoader::allPaths().size(); i < N; ++i ) paths += DynamicLoader::allPaths()[i] + "\n"; return paths; } if ( verb == "prependpath" ) { string path = StringUtils::car(command); if ( !path.empty() ) DynamicLoader::prependPath(path); return ""; } if ( verb == "create" ) { string className = StringUtils::car(command); command = StringUtils::cdr(command); string name = StringUtils::car(command); const ClassDescriptionBase * db = DescriptionList::find(className); command = StringUtils::cdr(command); while ( !db && command.length() ) { string library = StringUtils::car(command); command = StringUtils::cdr(command); DynamicLoader::load(library); db = DescriptionList::find(className); } if ( !db ) { string msg = "Error: " + className + ": No such class found."; if ( !DynamicLoader::lastErrorMessage.empty() ) msg += "\nerror message from dynamic loader:\n" + DynamicLoader::lastErrorMessage; return msg; } IBPtr obj = dynamic_ptr_cast(db->create()); if ( !obj ) return "Error: Could not create object of class "+className; if ( name.empty() ) return "Error: No name specified."; Register(obj, name); return ""; } if ( verb == "setup" ) { string name = StringUtils::car(command); DirectoryAppend(name); IBPtr obj = GetPointer(name); if ( !obj ) return "Error: Could not find object named " + name; istringstream is(StringUtils::cdr(command)); readSetup(obj, is); return ""; } if ( verb == "rm" ) { ObjectSet rmset; while ( !command.empty() ) { string name = StringUtils::car(command); DirectoryAppend(name); IBPtr obj = GetPointer(name); if ( !obj ) return "Error: Could not find object named " + name; rmset.insert(obj); command = StringUtils::cdr(command); } return remove(rmset); } if ( verb == "rmdir" || verb == "rrmdir" ) { string dir = StringUtils::car(command); DirectoryAppend(dir); if ( dir[dir.size() - 1] != '/' ) dir += '/'; if ( !member(directories(), dir) ) return verb == "rmdir"? "Error: No such directory.": ""; IVector ov = SearchDirectory(dir); if ( ov.size() && verb == "rmdir" ) return "Error: Cannot remove a non-empty directory. " "(Use rrmdir do remove all object and subdirectories.)"; ObjectSet rmset(ov.begin(), ov.end()); string ret = remove(rmset); if ( !ret.empty() ) return ret; StringVector dirs(directories().begin(), directories().end()); for ( int i = 0, N = dirs.size(); i < N; ++ i ) if ( dirs[i].substr(0, dir.size()) == dir ) directories().erase(dirs[i]); for ( int i = 0, N = directoryStack().size(); i < N; ++i ) if ( directoryStack()[i].substr(0, dir.size()) == dir ) directoryStack()[i] = '/'; return ""; } if ( verb == "rcp" ) { string name = StringUtils::car(command); DirectoryAppend(name); string newName = StringUtils::car(StringUtils::cdr(command)); if ( newName.empty() ) return "Error: No destination directory specified."; DirectoryAppend(newName); CreateDirectory(newName); if ( newName[newName.size() - 1] != '/' ) newName += '/'; IBPtr obj = GetPointer(name); if ( name[name.size() - 1] != '/' ) name += '/'; IVector ov = SearchDirectory(name); ov.push_back(obj); if ( ov.empty() ) return "Error: No such object or directory."; ObjectSet toclone; for ( IVector::iterator i = ov.begin(); i != ov.end(); ++i ) { toclone.insert(*i); addReferences(*i, toclone); } for ( ObjectSet::iterator i = toclone.begin(); i != toclone.end(); ++i ) Register((**i).clone(), newName + (**i).name()); return ""; } if ( verb == "rebind" ) { // For all objects in the repository, replace any references to // the first object given with references to the second // object. The two objects will change names IBPtr ip1 = TraceObject(StringUtils::car(command)); string newname = StringUtils::car(StringUtils::cdr(command)); DirectoryAppend(newname); IBPtr ip2 = GetPointer(newname); if ( !ip2 ) { ip2 = ip1->fullclone(); rename(ip2, newname); } TranslationMap trans; trans[ip1] = ip2; IVector objs = GetObjectsReferringTo(ip1); for ( int i = 0, N = objs.size(); i < N; ++i ) rebind(*objs[i], trans, IVector()); } if ( verb == "doxygendump" ) { string spacename = StringUtils::car(command); command = StringUtils::cdr(command); string filename = StringUtils::car(command); ofstream os(filename.c_str()); for ( TypeDocumentationMap::const_iterator it = documentations().begin(); it != documentations().end(); ++it ) { const ClassDescriptionBase & db = *(it->first); string classname = db.name(); if ( classname.substr(0, spacename.length()) != spacename ) continue; string briefname = classname.substr(spacename.length()); os << "/** \\page " << briefname << "Interfaces " << "Interfaces defined for the " << classname << " class.\n\n" << "\\par Brief class description:\n"; string doc = it->second->documentation(); if ( doc.substr(0,25) == "There is no documentation" ) os << "See " << classname << "\n\n"; else os << doc << "
See also " << classname << "\n\n"; TypeInterfaceMap::const_iterator isit = interfaces().find(it->first); if ( isit == interfaces().end() || isit->second.empty() ) { os << "There are no interfaces declared for this class.\n\n"; } else { const InterfaceSet & ints = isit->second; for ( InterfaceSet::const_iterator iit = ints.begin(); iit != ints.end(); ++iit ) (**iit).doxygenDescription(os); } string baserefs = ""; int nbases = 0; for ( int ib = 0, N = db.descriptions().size(); ib < N; ++ib ) { if ( documentations().find(db.descriptions()[ib]) == documentations().end() ) continue; const ClassDescriptionBase & bdb = *db.descriptions()[ib]; if ( nbases ) baserefs += " and "; string briefname = bdb.name().substr(bdb.name().rfind("::") + 2); baserefs += "\\ref " + briefname + "Interfaces \"" + bdb.name() + "\""; ++nbases; } if ( nbases == 1 ) os << "


There may be interfaces inherited from the " << baserefs << " class."; else if ( nbases > 1 ) os << "
There may be interfaces inherited from the " << "following classes: " << baserefs << "."; os << "\n\n*/\n\n"; } return ""; } if ( verb == "mset" || verb == "msetdef" || verb == "minsert" || verb == "mdo" || verb == "mget" || verb == "mdef" || verb == "mmin" || verb == "mmax" || verb == "merase" || verb == "msend" ) { if ( verb == "msend" ) verb = "mdo"; string dir = StringUtils::car(command); command = StringUtils::cdr(command); string className = StringUtils::car(command); command = StringUtils::cdr(command); string interface = StringUtils::car(command); string arguments = StringUtils::cdr(command); string::size_type bra = interface.find('['); if ( bra != string::npos ) { string::size_type ket = interface.find(']'); arguments = interface.substr(bra + 1,ket - bra - 1) + " " + arguments; interface = interface.substr(0, bra); } IVector ov = SearchDirectory(dir, className); if ( ov.empty() ) return "Error: no matching objects found."; string ret; verb = verb.substr(1); for ( IVector::size_type i = 0; i < ov.size(); ++i ) { const InterfaceBase * ifb = FindInterface(ov[i], interface); if ( !ifb ) continue; string mess = ifb->exec(*ov[i], verb, arguments); if ( !mess.empty() ) ret += ov[i]->fullName() + ": " + mess + "\n"; } return ret.substr(0, ret.size() - 1); } if ( verb == "set" || verb == "setdef" || verb == "insert" || verb == "do" || verb == "get" || verb == "def" || verb == "min" || verb == "max" || verb == "describe" || verb == "fulldescribe" || verb == "erase" || verb == "clear" || verb == "send" || verb == "newdef" ) { if ( verb == "send" ) verb = "do"; if ( verb == "newdef" && !InterfaceBase::NoReadOnly ) return "Error: The default value of an interface is a read-only " "entity. Use the command 'DISABLEREADONLY' to override."; string noun = StringUtils::car(command); string arguments = getPosArgFromNoun(noun) + " " + StringUtils::cdr(command); IBPtr ip = getObjectFromNoun(noun); const InterfaceBase * ifb = FindInterface(ip, getInterfaceFromNoun(noun)); if ( !ifb && verb != "describe" && verb != "fulldescribe" ) { string ret = "Error: The interface '" + noun + "' was not found.\n"; ret += "Valid interfaces:\n"; const auto & tmp=*ip; InterfaceMap imap = getInterfaces(typeid(tmp)); for ( InterfaceMap::iterator it = imap.begin(); it != imap.end(); ++it ) ret += "* " + it->second->name() + "\n"; return ret; } if ( verb == "describe" ) { if ( ifb ) return ifb->description(); const auto & tmp=*ip; const ClassDescriptionBase * cd = DescriptionList::find(typeid(tmp)); string ret = "Object '" + ip->name() + "' of class '" + cd->name() + "':\n"; TypeDocumentationMap::const_iterator cdoc = documentations().find(cd); if ( cdoc != documentations().end() ) ret += cdoc->second->documentation() + "\n"; ret +="Interfaces:\n"; InterfaceMap imap = getInterfaces(typeid(tmp)); for ( InterfaceMap::iterator it = imap.begin(); it != imap.end(); ++it ) ret += "* " + it->second->name() + "\n"; return ret; } else if ( verb == "fulldescribe" ) { if ( ifb ) return ifb->fullDescription(*ip); ostringstream ret; const auto & tmp=*ip; const ClassDescriptionBase * cd = DescriptionList::find(typeid(tmp)); TypeDocumentationMap::const_iterator cdoc = documentations().find(cd); ret << ip->fullName() << endl << cd->name() << endl; if ( cdoc != documentations().end() ) ret << cdoc->second->documentation() << endl; ret << "Interfaces:" << endl; InterfaceMap imap = getInterfaces(typeid(tmp)); typedef set InterfaceSet; InterfaceSet iset; for ( InterfaceMap::iterator it = imap.begin(); it != imap.end(); ++it ) iset.insert(it->second); double rank = 1.0; for ( InterfaceSet::iterator it = iset.begin(); it != iset.end(); ++it ) { if ( rank >= 0.0 && (**it).rank() < 0.0 ) ret << "0" << endl; rank = (**it).rank(); ret << (**it).type() << " " << (**it).name() << endl; } return ret.str(); } else return ifb->exec(*ip, verb, arguments); } if ( verb == "baseclasses" ) { string className = StringUtils::car(command); const ClassDescriptionBase * cdb = 0; if ( className.size() ) { cdb = DescriptionList::find(className); if ( !cdb ) return "Error: no class '" + className + "' found."; } return GetInterfacedBaseClasses(cdb); } if ( verb == "describeclass" ) { string className = StringUtils::car(command); const ClassDescriptionBase * cdb = 0; if ( className.size() ) { cdb = DescriptionList::find(className); if ( !cdb ) return "Error: no class '" + className + "' found."; } TypeDocumentationMap::const_iterator cdoc = documentations().find(cdb); if ( cdoc != documentations().end() ) return cdoc->second->documentation() + "\n"; else return ""; } if ( verb == "lsclass" ) { string className = StringUtils::car(command); const ClassDescriptionBase * cdb = 0; if ( className.size() ) { cdb = DescriptionList::find(className); if ( !cdb ) return "Error: no class '" + className + "' found."; } vector classes; if ( cdb && !cdb->abstract() ) classes.push_back(cdb); for ( DescriptionList::DescriptionMap::const_iterator it = DescriptionList::all().begin(); it != DescriptionList::all().end(); ++it ) { if ( it->second == cdb || it->second->abstract() ) continue; if ( cdb && !it->second->isA(*cdb) ) continue; classes.push_back(it->second); } if ( classes.empty() ) return "Error: no classes found."; string ret; for ( int i = 0, N = classes.size(); i < N; ++i ) ret += classes[i]->name() + "\n"; return ret; } } catch (const Exception & e) { e.handle(); return "Error: " + e.message(); } return "Error: Unrecognized command '" + verb + "'."; } BadClassClone::BadClassClone(const InterfacedBase & o) { theMessage << "Could not clone the object '" << o.name() << "' of class '" << TypeInfo::name(o) << "' because the class does not" << " implement a working 'clone' method."; severity(abortnow); } BadClone::BadClone(const InterfacedBase & o) { theMessage << "Could not clone the object '" << o.name() << "' of class '" << TypeInfo::name(o) << "' because the clone method threw an unknown exception."; severity(abortnow); } RepoNameException::RepoNameException(string name) { theMessage << "The object '" << name << "' is present in the Repository but " << "under a different name. This means that the name of the " << "object has been illegally changed outside of the Repository."; severity(abortnow); } RepoNameExistsException::RepoNameExistsException(string name) { theMessage << "The object '" << name << "' was not created as another object with that name already exists."; severity(warning); } RepositoryNoDirectory::RepositoryNoDirectory(string name) { theMessage << "The directory '" << name << "' does not exist."; severity(warning); } RepositoryNotFound::RepositoryNotFound(string name) { theMessage << "There was no object named '" << name << "' in the repository."; severity(warning); } RepositoryClassMisMatch:: RepositoryClassMisMatch(const InterfacedBase & o, string name) { theMessage << "The requested object '" << o.fullName() << "' was not of the " << "specified type (" << name << ")."; severity(warning); } diff --git a/Repository/BaseRepository.h b/Repository/BaseRepository.h --- a/Repository/BaseRepository.h +++ b/Repository/BaseRepository.h @@ -1,583 +1,583 @@ // -*- C++ -*- // // BaseRepository.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_BaseRepository_H #define ThePEG_BaseRepository_H // This is the declaration of the BaseRepository class. #include "ThePEG/Config/ThePEG.h" #include "BaseRepository.xh" #include "ThePEG/Interface/InterfaceBase.fh" #include "ThePEG/Interface/ClassDocumentation.fh" #include "ThePEG/Interface/InterfacedBase.h" #include "ThePEG/Utilities/ClassDescription.fh" namespace ThePEG { /** * BaseRepository is a purely static class which keeps a set of * InterfacedBase objects indexed by their name. The objects and their * names are divided up in a tree-like structure inspired by the Unix * file system. * * The InterfacedBase objects may be manipulated using InterfaceBase * objects. This may be done directly or via a simple command * interface using the exec() method. * * RepositoryBase is closely related to the Repository sub-class. The * division may seem unnecessary, but the idea is that BaseRepository * is a general repository for administrating and manipulating a set * of InterfacedBase objects, while the Repository adds on utilites * which are special to ThePEG where the objects are Interfaced (a * sub-class of InterfacedBase). * * @see Repository * @see InterfacedBase * @see InterfaceBase * @see Interfaced * */ class BaseRepository { public: /** A set of strings. */ typedef StringSet DirectorySet; /** A vector of character strings. */ typedef vector StringVector; /** A set of pointers to InterfaceBase objects. */ typedef set InterfaceSet; /** A map of sets of IterfaceBase objects indexed by pointers to ClassDescriptionBase objects. */ typedef map TypeInterfaceMap; /** A map of ClassDocumentationBase objects indexed by pointers to ClassDescriptionBase objects. */ typedef map TypeDocumentationMap; public: /** * Interpret the command in \a cmd and return possible * messages. This is the main function for the command-line * interface. The syntax is described elsewhere. The ostream * argument is currently unused. */ static string exec(string cmd, ostream &); /** @name Functions for adding and deleting objects and interfaces. */ //@{ /** * Register an interface. This is called automatically in the * InterfaceBase constructor and should never be called explicitly. */ static void Register(const InterfaceBase &, const type_info &); /** * Register a class documentation. This is called automatically in * the ClassDocumentationBase constructor and should never be called * explicitly. */ static void Register(const ClassDocumentationBase &, const type_info &); /** * Register a new object using the its current name. If the object * is already in the repository, nothing happens. If another object * already exists with the same name, the new object will have * #'s appended to its name to make it unique. */ static void Register(IBPtr); /** * Register a new object giving it a new \a name. If the object is * already in the repository, nothing happens. If another object * already exists with the same name, the new object will have * #'s appended to its name to make it unique. */ static void Register(IBPtr, string name); /** * Remove the given object from the repository. If the object was * not present nothing will happen. */ static void remove(tIBPtr); /** * Remove objects. Remove the objects in \a rmset if there are no * other objects in the repository referring to them, otherwise * return an error message and the names of the objects refering to * them separated by new-line characters. */ static string remove(const ObjectSet & rmset); /** * Rename a given \a object. Syntacticly the same as * remove(object); Register(object, newName);. */ static void rename(tIBPtr object, string newName); //@} /** @name Access the directory stack. */ //@{ /** * Create a new directory with the given name. If the given name * starts with a / the name is assumed to be an absolute * path, otherwise it is assumed to be a path relative to the * current directory. */ static void CreateDirectory(string); /** * Check if directory exixts. Check if the name given as argument * corresponds to an existing directory. If the argument string does * not end in a / it is assumed to be the name of an * object in a directory, and only the directory part of the name is * checked. If the given name starts with a / the name * is assumed to be an absolute path, otherwise it is assumed to be * a path relative to the current directory. * * @throws RepositoryNoDirectory if the correspinding directory is * non-existent. */ static void CheckObjectDirectory(string); /** * Check if directory exixts. Check if the name given as argument * corresponds to an existing directory. If the given name starts * with a / the name is assumed to be an absolute path, * otherwise it is assumed to be a path relative to the current * directory. * * @throws RepositoryNoDirectory if the correspinding directory is * non-existent. */ static void CheckDirectory(string); /** * Return the absolute path. If the given name starts with a * / the name is assumed to be an absolute path already, * otherwise it is assumed to be a path relative to the current * directory, and the absolute path is constructed. */ static void DirectoryAppend(string &); /** * Set the current directory to \a name. \a name can be aither a * relative or absolute path. The new directory replaces the * previous current directory on the directory stack. * * @throws RepositoryNoDirectory if the directory is non-existent. */ static void ChangeDirectory(string name); /** * Set the current directory to \a name. \a name can be aither a * relative or absolute path. The new directory is pushed onto the * directory stack. * * @throws RepositoryNoDirectory if the directory is non-existent. */ static void PushDirectory(string name); /** * Pop the directory stack. Leave the current directory and set the * directory which is on top of the popped directory stack. */ static void PopDirectory(); /** * A list of all globally loaded libraries. */ static vector & globalLibraries(); //@} /** @name Information on where to read input files. */ //@{ protected: /** * The stack of directories used by the "read" command. */ static stack & currentReadDirStack(); /** * List of directories to search for files for the "read" command. */ static vector & readDirs(); public: /** * Access to list of directories to search for files for the "read" command. */ static const vector & listReadDirs(); /** * Add a directory to readDirs(). */ static void prependReadDir(string); /** * Add a string vector with directories to readDirs(). */ static void prependReadDir(const std::vector& dirs); /** * Add a directory to readDirs(). */ static void appendReadDir(string); /** * Add a string vector with directories to readDirs(). */ static void appendReadDir(const std::vector& dirs); //@} /** @name Access objects in the repository. */ //@{ /** * Return a reference counted pointer to the given object. This * currently not needed when ThePEG is used with the * ThePEG::Pointer::RCPtr class of pointers. */ template static typename Ptr::pointer GetPtr(const T &); /** * Return a pointer of the specified type to an object with the * given name. If such an object does not exist, GetPtr will return * a null pointer. */ template static PtrType GetPtr(string); /** * Return a pointer of the specified type to an object with the * given name. If such an object does not exist an exception will be * thrown. * @throws RepositoryNotFound if the object was not found. * @throws RepositoryClassMisMatch if the object exists but is of * the wrong class. */ template static PtrType GetObject(string); /** * Return a pointer to an object with the given name or null if no * such object exists. */ static IBPtr GetPointer(string); /** * Return all objects in the directory \a name. Optionally only return * objects of class \a className or of a sub-class thereof. */ static IVector SearchDirectory(string name, string className = ""); /** * Find an object. If the \a name does not begin with '/', the * current directory is prepended. If the string is on the form * object:interface (or * object:interface[i]) and interface * corresponds to an Reference (or RefVector) interface, the * corresponding referenced object is returned. (also * object:interface:interface is allowed etc.) */ static IBPtr TraceObject(string name); /** * Return a string containing the name of the given class * description and its base classes, one on each line. */ static string GetInterfacedBaseClasses(const ClassDescriptionBase * cdb); /** * Get an object. Decompose a string of the form * object:interface or * object:vector-interface[pos]. Retrun a pointer to * the corresponding object. */ static IBPtr getObjectFromNoun(string noun); //@} /** @name Access references between object in the repository. */ //@{ /** * Get referring objects. Return all object which refers to the * given object through a Reference of RefVector interface. */ static IVector GetObjectsReferringTo(IBPtr); /** * Get direct references. Return all objects the given object refers * to directly through a Reference of RefVector interface. */ static IVector DirectReferences(IBPtr); /** * Get all references. If \a obj contains references to other objects, * either through a Reference or RefVector interface or through the * virtual getReferences member function, add these to refs. Do the * same to the references recursively. */ static void addReferences(tIBPtr obj, ObjectSet & refs); //@} /** @name Access the interfaces of the objects in the repository. */ //@{ /** * Get interfaces. Return the interfaces defined for the * InterfacedBase class with the given type_info, \a ti, mapped to * their name. If several interfaces with the same name exists only * the one which correspond to the most derived class will be given, * except if \a all is true in which case all interfaces are given * (prefixed by '+'s to become unique). */ static InterfaceMap getInterfaces(const type_info & ti, bool all = true); /** * Return an interface with the given \a name to the given \a object. */ static const InterfaceBase * FindInterface(IBPtr object, string name); /** * Get an interface name. Decompose a string of the form * object:interface or * object:vector-interface[pos]. Return the interface * name (without the [pos]). */ static string getInterfaceFromNoun(string noun); /** * Get interface index. Decompose a string of the form * object:interface or * object:vector-interface[pos]. Return the * pos part or empty string if not present. */ static string getPosArgFromNoun(string noun); /** * Return a list of the interfaces which do not have their default * values for the given objects. */ template static vector< pair > getNonDefaultInterfaces(const Cont &); //@} /** @name Manipulate objects in the repository. */ //@{ /** * Call the InterfacedBase::update() function of all objects. */ static void update(); /** * Clear the InterfacedBase::touched() flag in all objects in the * given container. */ template static void clearAll(const Cont & c) { for_each(c, mem_fn(&InterfacedBase::clear)); } /** * Set the status of all objects in the given container to * InterfacedBase::uninitialized. */ template static void resetAll(const Cont & c) { for_each(c, mem_fn(&InterfacedBase::reset)); } /** * Setup an object. Execute the InterfacedBase::readSetup() method * of \a ip with the stream \a is as argument. */ static void readSetup(tIBPtr ip, istream & is); /** * Lock the given object. Locked objects cannot be * changed through an interface. */ static void lock(tIBPtr ip) { ip->lock(); } /** * Unlock the given object. Locked objects cannot be changed through * an interface. */ static void unlock(tIBPtr ip) { ip->unlock(); } //@} /** @name Access the documentation of objects. */ //@{ /** * Return the class documentation of a given object */ static const ClassDocumentationBase * getDocumentation(tcIBPtr ip); /** * Get the description for the model implemented in the class of the * given object. */ static string getModelDescription(tcIBPtr ip); /** * Get the references for the model implemented in the class of the * given object. */ static string getModelReferences(tcIBPtr ip); //@} /** @name Manipulate the output streams of the repository. */ //@{ /** * Set the standard output stream */ static void cout(ostream & os) { coutp() = &os; } /** * Get the standard output stream */ static ostream & cout() { return *coutp(); } /** * Set the standard error stream */ static void cerr(ostream & os) { cerrp() = &os; } /** * Get the standard error stream */ static ostream & cerr() { return *cerrp(); } /** * Set the standard log stream */ static void clog(ostream & os) { clogp() = &os; } /** * Get the standard log stream */ static ostream & clog() { return *clogp(); } //@} protected: /** @name Access standard InterfacedBase functions. */ //@{ /** * Return a clone of the given object. Calls the * InterfacedBase::clone() function of \a t and casts the resulting * pointer to the correct type. */ template static typename Ptr::pointer clone(const T & t); /** * Return a clone of the given object. Calls the * InterfacedBase::fullclone() function of \a t and casts the * resulting pointer to the correct type. */ template static typename Ptr::pointer fullclone(const T & t); /** * Rebind references. For all objects directly referenced by \a obj, * replace them with the translation found in \a trans. If \a obj has a * Reference or a member of a RefVector interface which is null, and * the corresponding interface has the RefInterfaceBase::defaultIfNull() flag set, * translate the null pointer to the first acceptable object in * defaults. */ static void rebind(InterfacedBase & obj, const TranslationMap & trans, const IVector & defaults); //@} /** * Add interfaces to the given map for the class with the given * class description. Recursively do the same with the base classes. */ static void addInterfaces(const ClassDescriptionBase &, InterfaceMap &, bool all = true); /** @name Functions containing the static instances of objects used by the repository. */ //@{ /** * All InterfacedBase objects mapped to their name. */ static ObjectMap & objects(); /** * All InterfacedBase objects. */ static ObjectSet & allObjects(); /** * Sets of InterfaceBase objects mapped to the class description of * the class for which they are defined. */ static TypeInterfaceMap & interfaces(); /** * Sets of ClassDocumentationBase objects mapped to the class * description of the class for which they are defined. */ static TypeDocumentationMap & documentations(); /** * All defined directories. */ static DirectorySet & directories(); /** * The current directory stack. */ static StringVector & directoryStack(); /** * Flag to say if we are in the middle of an update procedure. */ static bool & updating(); /** * The current current standard output stream. */ static ostream *& coutp(); /** * The current current standard error stream. */ static ostream *& cerrp(); /** * The current current standard log stream. */ static ostream *& clogp(); //@} }; } #ifndef ThePEG_TEMPLATES_IN_CC_FILE #include "BaseRepository.tcc" #endif #endif /* ThePEG_BaseRepository_H */ diff --git a/Repository/BaseRepository.tcc b/Repository/BaseRepository.tcc --- a/Repository/BaseRepository.tcc +++ b/Repository/BaseRepository.tcc @@ -1,82 +1,82 @@ // -*- C++ -*- // // BaseRepository.tcc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined templated member // functions of the BaseRepository class. // namespace ThePEG { template typename Ptr::pointer BaseRepository::GetPtr(const T & t) { typedef typename Ptr::pointer ptr; ObjectSet::iterator it = allObjects().find (IBPtr(const_cast(dynamic_cast(&t)))); return it == allObjects().end()? ptr(): dynamic_ptr_cast(*it); } template PtrType BaseRepository::GetPtr(string name) { return dynamic_ptr_cast(GetPointer(name)); } template PtrType BaseRepository::GetObject(string name) { typedef ClassTraits::value_type> Traits; IBPtr ip = GetPointer(name); if ( !ip ) throw RepositoryNotFound(name); PtrType p = dynamic_ptr_cast(ip); if ( !p ) throw RepositoryClassMisMatch(*ip, Traits::className()); return p; } template typename Ptr::pointer BaseRepository::clone(const T & t) { typedef typename Ptr::pointer ptr; const InterfacedBase & ib = t; ptr ret; try { ret = dynamic_ptr_cast(ib.clone()); } catch ( ... ) { throw BadClone(t); } if ( !ret ) throw BadClassClone(t); return ret; } template typename Ptr::pointer BaseRepository::fullclone(const T & t) { typedef typename Ptr::pointer ptr; ptr ret; try { ret = dynamic_ptr_cast(t.fullclone()); } catch ( ... ) { throw BadClone(t); } if ( !ret ) throw BadClassClone(t); return ret; } template vector< pair > BaseRepository::getNonDefaultInterfaces(const Cont & c) { vector< pair > ret; for ( typename Cont::const_iterator it = c.begin(); it != c.end(); ++it ) { InterfaceMap im = getInterfaces(typeid(**it)); for ( InterfaceMap::iterator iit = im.begin(); iit != im.end(); ++iit ) if ( iit->second->notDefault(**it) ) ret.push_back(make_pair(*it, iit->second)); } return ret; } } diff --git a/Repository/BaseRepository.xh b/Repository/BaseRepository.xh --- a/Repository/BaseRepository.xh +++ b/Repository/BaseRepository.xh @@ -1,74 +1,74 @@ // -*- C++ -*- // // BaseRepository.xh is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_BaseRepository_XH #define ThePEG_BaseRepository_XH // // This is the declarations of the exception classes used by the // BaseRepository class. // #include "ThePEG/Interface/InterfaceBase.xh" namespace ThePEG { /** @cond EXCEPTIONCLASSES */ /** Exception class used by BaseRepository if an object does not implement the InterfacedBase::clone() function properly. */ struct BadClassClone: public InterfaceException { /** Standard constructor. */ BadClassClone(const InterfacedBase &); }; /** Exception class used by BaseRepository if an objects InterfacedBase::clone() function throws an exception. */ struct BadClone: public InterfaceException { /** Standard constructor. */ BadClone(const InterfacedBase &); }; /** Exception class used by BaseRepository if the name of an object in the repository has been changed outside the repository. */ struct RepoNameException: public InterfaceException { /** Standard constructor. */ RepoNameException(string); }; /** Exception class used by BaseRepository if creating an object with a name that already exists in the repository.. */ struct RepoNameExistsException: public InterfaceException { /** Standard constructor. */ RepoNameExistsException(string); }; /** Exception class used by BaseRepository when trying to access a non-existing directory. */ struct RepositoryNoDirectory: public InterfaceException { /** Standard constructor. */ RepositoryNoDirectory(string); }; /** Exception class used by BaseRepository when trying to access a non-existent object. */ struct RepositoryNotFound: public InterfaceException { /** Standard constructor. */ RepositoryNotFound(string name); }; /** Exception class used by BaseRepository if a specified object was not of the expected class. */ struct RepositoryClassMisMatch: public InterfaceException { /** Standard constructor. */ RepositoryClassMisMatch(const InterfacedBase & o, string name); }; /** @endcond */ } #endif /* ThePEG_BaseRepository_XH */ diff --git a/Repository/CurrentGenerator.cc b/Repository/CurrentGenerator.cc --- a/Repository/CurrentGenerator.cc +++ b/Repository/CurrentGenerator.cc @@ -1,20 +1,20 @@ // -*- C++ -*- // // CurrentGenerator.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the CurrentGenerator class. // #include "CurrentGenerator.h" using namespace ThePEG; vector CurrentGenerator::theGeneratorStack; diff --git a/Repository/CurrentGenerator.h b/Repository/CurrentGenerator.h --- a/Repository/CurrentGenerator.h +++ b/Repository/CurrentGenerator.h @@ -1,278 +1,278 @@ // -*- C++ -*- // // CurrentGenerator.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_CurrentGenerator_H #define ThePEG_CurrentGenerator_H // This is the declaration of the CurrentGenerator class. #include "ThePEG/Repository/EventGenerator.h" #include "CurrentGenerator.fh" namespace ThePEG { /** * This CurrentGenerator class keeps a static stack of EventGenerators * which can be used anywhere by any class. When an EventGenerator is * initialized or run it adds itself to the stack which can be used by * any other object being initialized or run through the static * functions of the CurrentGenerator class. If someone * needs to use an alternative EventGenerator object a new * CurrentGenerator object can be constructed with a * pointer to the desired EventGenerator object as argument and that * object will the be used by the static CurrentGenerator * functions until the CurrentGenerator object is destructed. * * @see EventGenerator * */ class CurrentGenerator { public: /** * Default constructor does nothing. */ CurrentGenerator() : generatorPushed(false) {} /** * Copy-constructor does nothing. */ CurrentGenerator(const CurrentGenerator &) : generatorPushed(false) {} /** * Construct a new object specifying a new EventGenerator, \a eg, to * be used during this objects lifetime. */ CurrentGenerator(const EGPtr & eg) : generatorPushed(false) { if ( eg ) { theGeneratorStack.push_back(eg); generatorPushed = true; } } /** * The destructor removing the EventGenerator specified in the * constructor from the stack. */ ~CurrentGenerator() { if ( generatorPushed ) theGeneratorStack.pop_back(); } public: /** * Returns true if there is no currently chosen EventGenerator * object. */ static bool isVoid() { return theGeneratorStack.empty() || !(theGeneratorStack.back()); } /** * Return a reference to the currently chosen EventGenerator object. */ static EventGenerator & current() { return *theGeneratorStack.back(); } /** * Return a reference to the currently chosen object. */ EventGenerator & operator*() const { return *theGeneratorStack.back(); } /** * Return a pointer to the currently chosen object. */ EventGenerator * operator->() const { return theGeneratorStack.back(); } /** * Pointer to the stack */ static EventGenerator * ptr() { return theGeneratorStack.back(); } /** * Test for existance */ operator bool() const { return ptr(); } /** * Test for existance */ bool operator!() const { return !ptr(); } /** * Return a pointer to the standard model parameters used by the * current generator. */ static tSMPtr standardModel() { return current().standardModel(); } /** * Return a pointer to the strategy object containing eg. a set of * non-default particles to be used by the current generator. */ static tStrategyPtr strategy() { return current().strategy(); } /** * Get the current standard output stream. Return a reference to the * stream connected to the file for general output of the current * generator. If no file is connected, the BaseRepository::cout() * will be used instead. */ static ostream & out() { return current().out(); } /** * Get the current standard log stream. Return a reference to the * stream connected to the file for logging information of the * current generator. If no file is connected, the * BaseRepository::clog() will be used instead. */ static ostream & log() { return current().log(); } /** * Get the current standard ref stream. Return a reference to the * stream connected to the file for references from used objects of * the current generator. If no file is connected, the * BaseRepository::cout() will be used instead. */ static ostream & ref() { return current().ref(); } /** * Get object. Return a garbage collected pointer to a given object * in the current EventGenerator. If the object is not found, a null * pointer will be returned. */ template static typename Ptr::pointer getPtr(const T & t) { return current().getPtr(t); } /** * Get object. Return a pointer to an object present in the current * EventGenerator given its full name. Return the null pointer if * non-existent. */ static IBPtr getPointer(string name) { return current().getPointer(name); } /** * Get object. Return a pointer to an object of type T present in * the current EventGenerator given its full name. Return the null * pointer if non-existent. */ template static typename Ptr::pointer getObject(string name) { return current().getObject(name); } /** * Get default object. Return the default object for class T in the * current EventGenerator. Returns the null pointer if non-existent. */ template static typename Ptr::pointer getDefault() { return current().getDefault(); } public: /** * Class used to temporarily redirect a given ostream to the misc() * stream of the current EventGenerator. */ class Redirect { public: /** * Constructor taking the stream to be redirected as input. If the * \a internal flag false the output will be stored in the Event * Generator and written to the log file in the end of the run. If * \internal is true the output is instead stored internally in * this object and is accessible through the str() function until * the object is destroyed. */ Redirect(ostream & os, bool internal = false) : theStream(&os), theBuffer(os.rdbuf()) { if ( internal ) theStream->rdbuf(intStream.rdbuf()); else if ( !current().useStdOut() ) theStream->rdbuf(current().misc().rdbuf()); } /** * The destructor which restores the original destination of the * stream. */ ~Redirect() { theStream->rdbuf(theBuffer); } /** * If output is stored internally, acces what has been written so * far. */ string str() const { return intStream.str(); } /** * The stream which is redirected. */ ostream * theStream; /** * The original buffer of the redirected stream. */ std::streambuf * theBuffer; /** * An internal buffer, the content of which will be discarded when * the this object is destructed. */ ostringstream intStream; }; private: /** * The stack of EventGenerators requested. */ static vector theGeneratorStack; /** * True if this object is responsible for pushing a EventGenerator * onto the stack. */ bool generatorPushed; private: /** * Private and non-existent assignment operator. */ CurrentGenerator & operator=(const CurrentGenerator &) = delete; }; } #endif /* ThePEG_CurrentGenerator_H */ diff --git a/Repository/EventGenerator.cc b/Repository/EventGenerator.cc --- a/Repository/EventGenerator.cc +++ b/Repository/EventGenerator.cc @@ -1,1415 +1,1415 @@ // -*- C++ -*- // // EventGenerator.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the EventGenerator class. // #include "EventGenerator.h" #include "EventGenerator.xh" #include "ThePEG/Handlers/EventHandler.h" #include "Repository.h" #include "ThePEG/Utilities/HoldFlag.h" #include "ThePEG/Utilities/Debug.h" #include "ThePEG/Utilities/DebugItem.h" #include "ThePEG/Interface/Interfaced.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Command.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/PDT/MatcherBase.h" #include "ThePEG/PDT/DecayMode.h" #include "ThePEG/StandardModel/StandardModelBase.h" #include "ThePEG/Repository/Strategy.h" #include "ThePEG/Repository/CurrentGenerator.h" #include "ThePEG/Handlers/AnalysisHandler.h" #include "ThePEG/Analysis/FactoryBase.h" #include "ThePEG/Handlers/EventManipulator.h" #include "ThePEG/Handlers/LuminosityFunction.h" #include "ThePEG/MatrixElement/MEBase.h" #include "ThePEG/EventRecord/Event.h" #include "ThePEG/Handlers/SubProcessHandler.h" #include "ThePEG/Handlers/CascadeHandler.h" #include "ThePEG/Handlers/HadronizationHandler.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Config/algorithm.h" #include "ThePEG/Utilities/DynamicLoader.h" #include #include "ThePEG/Repository/Main.h" #include #ifdef ThePEG_TEMPLATES_IN_CC_FILE #include "EventGenerator.tcc" #endif using namespace ThePEG; namespace { volatile sig_atomic_t THEPEG_SIGNAL_STATE = 0; } // signal handler function // very restricted in what it is allowed do // without causing undefined behaviour extern "C" { void thepegSignalHandler(int id) { THEPEG_SIGNAL_STATE=id; signal(id,SIG_DFL); } } void EventGenerator::checkSignalState() { if (THEPEG_SIGNAL_STATE) { log() << "Caught signal " << THEPEG_SIGNAL_STATE << ". Exiting ..." << std::endl; finalize(); exit(0); } } EventGenerator::EventGenerator() : thePath("."), theNumberOfEvents(1000), theQuickSize(7000), preinitializing(false), ieve(0), weightSum(0.0), theDebugLevel(0), logNonDefault(-1), printEvent(0), dumpPeriod(0), keepAllDumps(false), debugEvent(0), maxWarnings(10), maxErrors(10), theCurrentRandom(0), theCurrentGenerator(0), useStdout(false), theIntermediateOutput(false) {} EventGenerator::EventGenerator(const EventGenerator & eg) : Interfaced(eg), theDefaultObjects(eg.theDefaultObjects), theLocalParticles(eg.theLocalParticles), theStandardModel(eg.theStandardModel), theStrategy(eg.theStrategy), theRandom(eg.theRandom), theEventHandler(eg.theEventHandler), theAnalysisHandlers(eg.theAnalysisHandlers), theHistogramFactory(eg.theHistogramFactory), theEventManipulator(eg.theEventManipulator), thePath(eg.thePath), theRunName(eg.theRunName), theNumberOfEvents(eg.theNumberOfEvents), theObjects(eg.theObjects), theObjectMap(eg.theObjectMap), theParticles(eg.theParticles), theQuickParticles(eg.theQuickParticles), theQuickSize(eg.theQuickSize), preinitializing(false), theMatchers(eg.theMatchers), usedObjects(eg.usedObjects), ieve(eg.ieve), weightSum(eg.weightSum), theDebugLevel(eg.theDebugLevel), logNonDefault(eg.logNonDefault), printEvent(eg.printEvent), dumpPeriod(eg.dumpPeriod), keepAllDumps(eg.keepAllDumps), debugEvent(eg.debugEvent), maxWarnings(eg.maxWarnings), maxErrors(eg.maxErrors), theCurrentRandom(0), theCurrentGenerator(0), theCurrentEventHandler(eg.theCurrentEventHandler), theCurrentStepHandler(eg.theCurrentStepHandler), useStdout(eg.useStdout), theIntermediateOutput(eg.theIntermediateOutput) {} EventGenerator::~EventGenerator() { if ( theCurrentRandom ) delete theCurrentRandom; if ( theCurrentGenerator ) delete theCurrentGenerator; } IBPtr EventGenerator::clone() const { return new_ptr(*this); } IBPtr EventGenerator::fullclone() const { return new_ptr(*this); } tcEventPtr EventGenerator::currentEvent() const { return eventHandler()->currentEvent(); } CrossSection EventGenerator::histogramScale() const { return eventHandler()->histogramScale(); } CrossSection EventGenerator::integratedXSec() const { return eventHandler()->integratedXSec(); } CrossSection EventGenerator::integratedXSecErr() const { return eventHandler()->integratedXSecErr(); } void EventGenerator::setSeed(long seed) { random().setSeed(seed); ostringstream s; s << seed; const InterfaceBase * ifb = BaseRepository::FindInterface(theRandom, "Seed"); ifb->exec(*theRandom, "set", s.str()); } void EventGenerator::setup(string newRunName, ObjectSet & newObjects, ParticleMap & newParticles, MatcherSet & newMatchers) { HoldFlag debug(Debug::level, Debug::isset? Debug::level: theDebugLevel); theRunName = newRunName; theObjects.swap(newObjects); theParticles.swap(newParticles); theMatchers.swap(newMatchers); theObjectMap.clear(); for ( ObjectSet::const_iterator it = objects().begin(); it != objects().end(); ++it ) theObjectMap[(**it).fullName()] = *it; UseRandom currentRandom(theRandom); CurrentGenerator currentGenerator(this); // Force update of all objects and then reset. touch(); for_each(theObjects, mem_fn(&InterfacedBase::touch)); update(); for_each(theObjects, mem_fn(&InterfacedBase::update)); clear(); BaseRepository::clearAll(theObjects); init(); } IBPtr EventGenerator::getPointer(string name) const { ObjectMap::const_iterator it = objectMap().find(name); if ( it == objectMap().end() ) return IBPtr(); else return it->second; } void EventGenerator::openOutputFiles() { if ( !useStdout ) { logfile().open((filename() + ".log").c_str()); theOutFileName = filename() + ".out"; outfile().open(theOutFileName.c_str()); outfile().close(); theOutStream.str(""); } out() << Repository::banner() << endl; log() << Repository::banner() << endl; } void EventGenerator::closeOutputFiles() { flushOutputFile(); if ( !useStdout ) logfile().close(); } void EventGenerator::flushOutputFile() { if ( !useStdout ) { outfile().open(theOutFileName.c_str(), ios::out|ios::app); outfile() << theOutStream.str(); outfile().close(); } else BaseRepository::cout() << theOutStream.str(); theOutStream.str(""); } void EventGenerator::doinit() { HoldFlag debug(Debug::level, Debug::isset? Debug::level: theDebugLevel); // First initialize base class and random number generator. Interfaced::doinit(); random().init(); // Make random generator and this available in standard static // classes. UseRandom useRandom(theRandom); CurrentGenerator currentGenerator(this); // First initialize all objects which have requested this by // implementing a InterfacedBase::preInitialize() function which // returns true. while ( true ) { HoldFlag hold(preinitializing, true); ObjectSet preinits; for ( ObjectSet::iterator it = objects().begin(); it != objects().end(); ++it ) if ( (**it).preInitialize() && (**it).state() == InterfacedBase::uninitialized ) preinits.insert(*it); if ( preinits.empty() ) break; for_each(preinits, std::mem_fn(&InterfacedBase::init)); } // Initialize the quick access to particles. theQuickParticles.clear(); theQuickParticles.resize(2*theQuickSize); for ( ParticleMap::const_iterator pit = theParticles.begin(); pit != theParticles.end(); ++pit ) if ( abs(pit->second->id()) < theQuickSize ) theQuickParticles[pit->second->id()+theQuickSize] = pit->second; // Then call the init method for all objects. Start with the // standard model and the strategy. standardModel()->init(); if ( strategy() ) strategy()->init(); eventHandler()->init(); // initialize particles first for(ParticleMap::const_iterator pit = particles().begin(); pit != particles().end(); ++pit) pit->second->init(); for_each(objects(), std::mem_fn(&InterfacedBase::init)); // Then initialize the Event Handler calculating initial cross // sections and stuff. eventHandler()->initialize(); } void EventGenerator::doinitrun() { HoldFlag debug(Debug::level, Debug::isset? Debug::level: theDebugLevel); signal(SIGHUP, thepegSignalHandler); signal(SIGINT, thepegSignalHandler); signal(SIGTERM,thepegSignalHandler); currentEventHandler(eventHandler()); Interfaced::doinitrun(); random().initrun(); // Then call the init method for all objects. Start with the // standard model and the strategy. standardModel()->initrun(); if ( strategy() ) { strategy()->initrun(); if ( ! strategy()->versionstring().empty() ) { out() << ">> " << strategy()->versionstring() << '\n' << endl; log() << ">> " << strategy()->versionstring() << '\n' << endl; } } // initialize particles first for(ParticleMap::const_iterator pit = particles().begin(); pit != particles().end(); ++pit) { pit->second->initrun(); } eventHandler()->initrun(); for_each(objects(), std::mem_fn(&InterfacedBase::initrun)); if ( logNonDefault > 0 || ( ThePEG_DEBUG_LEVEL && logNonDefault == 0 ) ) { vector< pair > changed = Repository::getNonDefaultInterfaces(objects()); if ( changed.size() ) { log() << string(78, '=') << endl << "The following interfaces have non-default values (default):" << endl << string(78, '-') << endl; for ( int i = 0, N = changed.size(); i < N; ++i ) { log() << changed[i].first->fullName() << ":" << changed[i].second->name() << " = " << changed[i].second->exec(*changed[i].first, "notdef", "") << endl; } log() << string(78,'=') << endl; } } weightSum = 0.0; } PDPtr EventGenerator::getParticleData(PID id) const { long newId = id; if ( abs(newId) < theQuickSize && theQuickParticles.size() ) return theQuickParticles[newId+theQuickSize]; ParticleMap::const_iterator it = theParticles.find(newId); if ( it == theParticles.end() ) return PDPtr(); return it->second; } PPtr EventGenerator::getParticle(PID newId) const { tcPDPtr pd = getParticleData(newId); if ( !pd ) return PPtr(); return pd->produceParticle(); } void EventGenerator::finalize() { UseRandom currentRandom(theRandom); CurrentGenerator currentGenerator(this); finish(); finally(); } void EventGenerator::dofinish() { HoldFlag debug(Debug::level, Debug::isset? Debug::level: theDebugLevel); // first write out statistics from the event handler. eventHandler()->statistics(out()); // Call the finish method for all other objects. for_each(objects(), std::mem_fn(&InterfacedBase::finish)); if ( theExceptions.empty() ) { log() << "No exceptions reported in this run.\n"; } else { log() << "\nThe following exception classes were reported in this run:\n"; for ( ExceptionMap::iterator it = theExceptions.begin(); it != theExceptions.end(); ++it ) { string severity; switch ( it->first.second ) { case Exception::info : severity="info"; break; case Exception::warning : severity="warning"; break; case Exception::setuperror : severity="setuperror"; break; case Exception::eventerror : severity="eventerror"; break; case Exception::runerror : severity="runerror"; break; case Exception::maybeabort : severity="maybeabort"; break; case Exception::abortnow : severity="abortnow"; break; default : severity="unknown"; } log() << it->first.first << ' ' << severity << " (" << it->second << " times)\n"; } } theExceptions.clear(); const string & msg = theMiscStream.str(); if ( ! msg.empty() ) { log() << endl << "Miscellaneous output from modules to the standard output:\n\n" << msg; theMiscStream.str(""); } flushOutputFile(); } void EventGenerator::finally() { generateReferences(); closeOutputFiles(); if ( theCurrentRandom ) delete theCurrentRandom; if ( theCurrentGenerator ) delete theCurrentGenerator; theCurrentRandom = 0; theCurrentGenerator = 0; } void EventGenerator::initialize(bool initOnly) { UseRandom currentRandom(theRandom); CurrentGenerator currentGenerator(this); doInitialize(initOnly); } bool EventGenerator::loadMain(string file) { initialize(); UseRandom currentRandom(theRandom); CurrentGenerator currentGenerator(this); Main::eventGenerator(this); bool ok = DynamicLoader::load(file); finish(); finally(); return ok; } void EventGenerator::go(long next, long maxevent, bool tics) { UseRandom currentRandom(theRandom); CurrentGenerator currentGenerator(this); doGo(next, maxevent, tics); } EventPtr EventGenerator::shoot() { static DebugItem debugfpu("ThePEG::FPU", 1); if ( debugfpu ) Debug::unmaskFpuErrors(); UseRandom currentRandom(theRandom); CurrentGenerator currentGenerator(this); checkSignalState(); EventPtr event = doShoot(); if ( event ) weightSum += event->weight(); DebugItem::tic(); return event; } EventPtr EventGenerator::doShoot() { EventPtr event; if ( N() >= 0 && ++ieve > N() ) return event; HoldFlag debug(Debug::level, Debug::isset? Debug::level: theDebugLevel); do { int state = 0; int loop = 1; eventHandler()->clearEvent(); try { do { // Generate a full event or part of an event if ( eventHandler()->empty() ) event = eventHandler()->generateEvent(); else event = eventHandler()->continueEvent(); if ( eventHandler()->empty() ) loop = -loop; // Analyze the possibly uncomplete event for ( AnalysisVector::iterator it = analysisHandlers().begin(); it != analysisHandlers().end(); ++it ) (**it).analyze(event, ieve, loop, state); // Manipulate the current event, possibly deleting some steps // and telling the event handler to redo them. if ( manipulator() ) state = manipulator()->manipulate(eventHandler(), event); // If the event was not completed, continue generation and continue. loop = abs(loop) + 1; } while ( !eventHandler()->empty() ); } catch (Exception & ex) { if ( logException(ex, eventHandler()->currentEvent()) ) throw; } catch (...) { event = eventHandler()->currentEvent(); if ( event ) log() << *event; else log() << "An exception occurred before any event object was created!"; log() << endl; if ( ThePEG_DEBUG_LEVEL ) dump(); throw; } if ( ThePEG_DEBUG_LEVEL ) { if ( ( ThePEG_DEBUG_LEVEL == Debug::printEveryEvent || ieve < printEvent ) && event ) log() << *event; if ( debugEvent > 0 && ieve + 1 >= debugEvent ) Debug::level = Debug::full; } } while ( !event ); // If scheduled, dump a clean state between events if ( ThePEG_DEBUG_LEVEL && dumpPeriod > 0 && ieve%dumpPeriod == 0 ) { eventHandler()->clearEvent(); eventHandler()->clean(); dump(); } return event; } EventPtr EventGenerator::doGenerateEvent(tEventPtr e) { if ( N() >= 0 && ++ieve > N() ) return EventPtr(); EventPtr event = e; try { event = eventHandler()->generateEvent(e); } catch (Exception & ex) { if ( logException(ex, eventHandler()->currentEvent()) ) throw; } catch (...) { event = eventHandler()->currentEvent(); if ( !event ) event = e; log() << *event << endl; dump(); throw; } return event; } EventPtr EventGenerator::doGenerateEvent(tStepPtr s) { if ( N() >= 0 && ++ieve > N() ) return EventPtr(); EventPtr event; try { event = eventHandler()->generateEvent(s); } catch (Exception & ex) { if ( logException(ex, eventHandler()->currentEvent()) ) throw; } catch (...) { event = eventHandler()->currentEvent(); if ( event ) log() << *event << endl; dump(); throw; } return event; } EventPtr EventGenerator::generateEvent(Event & e) { UseRandom currentRandom(theRandom); CurrentGenerator currentGenerator(this); EventPtr event = doGenerateEvent(tEventPtr(&e)); if ( event ) weightSum += event->weight(); return event; } EventPtr EventGenerator::generateEvent(Step & s) { UseRandom currentRandom(theRandom); CurrentGenerator currentGenerator(this); EventPtr event = doGenerateEvent(tStepPtr(&s)); if ( event ) weightSum += event->weight(); return event; } Energy EventGenerator::maximumCMEnergy() const { tcEHPtr eh = eventHandler(); return eh->lumiFnPtr()? eh->lumiFn().maximumCMEnergy(): ZERO; } void EventGenerator::doInitialize(bool initOnly) { if ( !initOnly ) openOutputFiles(); init(); if ( !initOnly ) initrun(); if ( !ThePEG_DEBUG_LEVEL ) Exception::noabort = true; } void EventGenerator::doGo(long next, long maxevent, bool tics) { if ( maxevent >= 0 ) N(maxevent); if ( next >= 0 ) { if ( tics ) cerr << "event> " << setw(9) << "init\r" << flush; initialize(); ieve = next-1; } else { openOutputFiles(); } if ( tics ) tic(); try { while ( shoot() ) { if ( tics ) tic(); } } catch ( ... ) { finish(); throw; } finish(); finally(); } void EventGenerator::tic(long currev, long totev) const { if ( !currev ) currev = ieve; if ( !totev ) totev = N(); long i = currev; long n = totev; bool skip = currev%(max(totev/100, 1L)); if ( i > n/2 ) i = n-i; while ( skip && i >= 10 && !(i%10) ) i /= 10; if ( i == 1 || i == 2 || i == 5 ) skip = false; if (!theIntermediateOutput) { //default if ( skip ) return; cerr << "event> " << setw(8) << currev << " " << setw(8) << totev << "\r"; } else if (theIntermediateOutput) { if ( skip && currev%10000!=0) return; cerr << "event> " << setw(9) << right << currev << "/" << totev << "; xs = " << integratedXSec()/picobarn << " pb +- " << integratedXSecErr()/picobarn << " pb" << endl; } cerr.flush(); if ( currev == totev ) cerr << endl; } void EventGenerator::dump() const { if ( dumpPeriod > -1 ) { string dumpfile; if ( keepAllDumps ) { ostringstream number; number << ieve; dumpfile = filename() + "-" + number.str() + ".dump"; } else dumpfile = filename() + ".dump"; PersistentOStream file(dumpfile, globalLibraries()); file << tcEGPtr(this); } } void EventGenerator::use(const Interfaced & i) { IBPtr ip = getPtr(i); if ( ip ) usedObjects.insert(ip); } void EventGenerator::generateReferences() { typedef map StringMap; StringMap references; // First get all model descriptions and model references from the // used objects. Put them in a map indexed by the description to // avoid duplicates. for ( ObjectSet::iterator it = usedObjects.begin(); it != usedObjects.end(); ++it ) { if ( *it == strategy() ) continue; string desc = Repository::getModelDescription(*it); if ( desc.empty() ) continue; if ( dynamic_ptr_cast(*it) ) desc = "A " + desc; else if ( dynamic_ptr_cast(*it) ) desc = "B " + desc; else if ( dynamic_ptr_cast(*it) ) desc = "C " + desc; else if ( dynamic_ptr_cast(*it) ) desc = "D " + desc; else if ( dynamic_ptr_cast(*it) ) desc = "E " + desc; else if ( dynamic_ptr_cast(*it) ) desc = "F " + desc; else if ( dynamic_ptr_cast(*it) ) desc = "Y " + desc; else if ( dynamic_ptr_cast(*it) ) desc = "Z " + desc; else if ( dynamic_ptr_cast::const_pointer>(*it) ) desc = "G " + desc; else desc = "H " + desc; references[desc] = Repository::getModelReferences(*it); } // Now get the main strategy description which should put first and // remove it from the map. string stratdesc; string stratref; if ( strategy() ) { stratdesc = Repository::getModelDescription(strategy()); stratref = Repository::getModelReferences(strategy()); references.erase(stratdesc); } // Open the file and write out an appendix header if ( !useStdout ) reffile().open((filename() + ".tex").c_str()); ref() << "\\documentclass{article}\n" << "\\usepackage{graphics}\n" << "\\begin{document}\n" << "\\appendix\n" << "\\section[xxx]{\\textsc{ThePEG} version " << Repository::version() << " \\cite{ThePEG} Run Information}\n" << "Run name: \\textbf{" << runName() << "}:\\\\\n"; if ( !stratdesc.empty() ) ref() << "This run was generated using " << stratdesc << " and the following models:\n"; else ref() << "The following models were used:\n"; ref() << "\\begin{itemize}\n"; // Write out all descriptions. for ( StringMap::iterator it = references.begin(); it != references.end(); ++it ) ref() << "\\item " << it->first.substr(2) << endl; // Write out thebibliography header and all references. ref() << "\\end{itemize}\n\n" << "\\begin{thebibliography}{99}\n" << "\\bibitem{ThePEG} L.~L\\\"onnblad, " << "Comput.~Phys.~Commun.\\ {\\bf 118} (1999) 213.\n"; if ( !stratref.empty() ) ref() << stratref << '\n'; for ( StringMap::iterator it = references.begin(); it != references.end(); ++it ) ref() << it->second << '\n'; ref() << "\\end{thebibliography}\n" << "\\end{document}" << endl; if ( !useStdout ) reffile().close(); } void EventGenerator::strategy(StrategyPtr s) { theStrategy = s; } int EventGenerator::count(const Exception & ex) { return ++theExceptions[make_pair(StringUtils::typeName(typeid(ex)), ex.severity())]; } void EventGenerator::printException(const Exception & ex) { switch ( ex.severity() ) { case Exception::info: log() << "* An information"; break; case Exception::warning: log() << "* A warning"; break; case Exception::setuperror: log() << "** A setup"; break; case Exception::eventerror: log() << "** An event"; break; case Exception::runerror: log() << "*** An run"; break; case Exception::maybeabort: case Exception::abortnow: log() << "**** A serious"; break; default: log() << "**** An unknown"; break; } if ( ieve > 0 ) log() << " exception of type " << StringUtils::typeName(typeid(ex)) << " occurred while generating event number " << ieve << ": \n" << ex.message() << endl; else log() << " exception occurred in the initialization of " << name() << ": \n" << ex.message() << endl; if ( ex.severity() == Exception::eventerror ) log() << "The event will be discarded." << endl; } void EventGenerator::logWarning(const Exception & ex) { if ( ex.severity() != Exception::info && ex.severity() != Exception::warning ) throw ex; ex.handle(); int c = count(ex); if ( c > maxWarnings ) return; printException(ex); if ( c == maxWarnings ) log() << "No more warnings of this kind will be reported." << endl; } bool EventGenerator:: logException(const Exception & ex, tcEventPtr event) { bool noEvent = !event; ex.handle(); int c = count(ex); if ( c <= maxWarnings ) { printException(ex); if ( c == maxWarnings ) log() << "No more warnings of this kind will be reported." << endl; } if ( ex.severity() == Exception::info || ex.severity() == Exception::warning ) { ex.handle(); return false; } if ( ex.severity() == Exception::eventerror ) { if ( c < maxErrors || maxErrors <= 0 ) { ex.handle(); if ( ThePEG_DEBUG_LEVEL > 0 && !noEvent ) log() << *event; return false; } if ( c > maxErrors ) printException(ex); log() << "Too many (" << c << ") exceptions of this kind has occurred. " "Execution will be stopped.\n"; } else { log() << "This exception is too serious. Execution will be stopped.\n"; } if ( !noEvent ) log() << *event; else log() << "An exception occurred before any event object was created!\n"; dump(); return true; } struct MatcherOrdering { bool operator()(tcPMPtr m1, tcPMPtr m2) const { return m1->name() < m2->name() || ( m1->name() == m2->name() && m1->fullName() < m2->fullName() ); } }; struct ObjectOrdering { bool operator()(tcIBPtr i1, tcIBPtr i2) const { return i1->fullName() < i2->fullName(); } }; void EventGenerator::persistentOutput(PersistentOStream & os) const { set match(theMatchers.begin(), theMatchers.end()); set usedset(usedObjects.begin(), usedObjects.end()); os << theDefaultObjects << theLocalParticles << theStandardModel << theStrategy << theRandom << theEventHandler << theAnalysisHandlers << theHistogramFactory << theEventManipulator << thePath << theRunName << theNumberOfEvents << theObjectMap << theParticles << theQuickParticles << theQuickSize << match << usedset << ieve << weightSum << theDebugLevel << logNonDefault << printEvent << dumpPeriod << keepAllDumps << debugEvent << maxWarnings << maxErrors << theCurrentEventHandler << theCurrentStepHandler << useStdout << theIntermediateOutput << theMiscStream.str() << Repository::listReadDirs(); } void EventGenerator::persistentInput(PersistentIStream & is, int) { string dummy; vector readdirs; theGlobalLibraries = is.globalLibraries(); is >> theDefaultObjects >> theLocalParticles >> theStandardModel >> theStrategy >> theRandom >> theEventHandler >> theAnalysisHandlers >> theHistogramFactory >> theEventManipulator >> thePath >> theRunName >> theNumberOfEvents >> theObjectMap >> theParticles >> theQuickParticles >> theQuickSize >> theMatchers >> usedObjects >> ieve >> weightSum >> theDebugLevel >> logNonDefault >> printEvent >> dumpPeriod >> keepAllDumps >> debugEvent >> maxWarnings >> maxErrors >> theCurrentEventHandler >> theCurrentStepHandler >> useStdout >> theIntermediateOutput >> dummy >> readdirs; theMiscStream.str(dummy); theMiscStream.seekp(0, std::ios::end); theObjects.clear(); for ( ObjectMap::iterator it = theObjectMap.begin(); it != theObjectMap.end(); ++it ) theObjects.insert(it->second); Repository::appendReadDir(readdirs); } void EventGenerator::setLocalParticles(PDPtr pd, int) { localParticles()[pd->id()] = pd; } void EventGenerator::insLocalParticles(PDPtr pd, int) { localParticles()[pd->id()] = pd; } void EventGenerator::delLocalParticles(int place) { ParticleMap::iterator it = localParticles().begin(); while ( place-- && it != localParticles().end() ) ++it; if ( it != localParticles().end() ) localParticles().erase(it); } vector EventGenerator::getLocalParticles() const { vector ret; for ( ParticleMap::const_iterator it = localParticles().begin(); it != localParticles().end(); ++it ) ret.push_back(it->second); return ret; } void EventGenerator::setPath(string newPath) { if ( std::system(("mkdir -p " + newPath).c_str()) ) throw EGNoPath(newPath); if ( std::system(("touch " + newPath + "/.ThePEG").c_str()) ) throw EGNoPath(newPath); if ( std::system(("rm -f " + newPath + "/.ThePEG").c_str()) ) throw EGNoPath(newPath); thePath = newPath; } string EventGenerator::defPath() const { char * env = std::getenv("ThePEG_RUN_DIR"); if ( env ) return string(env); return string("."); } ostream & EventGenerator::out() { return theOutStream; } ostream & EventGenerator::log() { return logfile().is_open()? logfile(): BaseRepository::cout(); } ostream & EventGenerator::ref() { return reffile().is_open()? reffile(): BaseRepository::cout(); } string EventGenerator::doSaveRun(string runname) { runname = StringUtils::car(runname); if ( runname.empty() ) runname = theRunName; if ( runname.empty() ) runname = name(); EGPtr eg = Repository::makeRun(this, runname); string file = eg->filename() + ".run"; PersistentOStream os(file); os << eg; if ( !os ) return "Error: Save failed! (I/O error)"; return ""; } string EventGenerator::doMakeRun(string runname) { runname = StringUtils::car(runname); if ( runname.empty() ) runname = theRunName; if ( runname.empty() ) runname = name(); Repository::makeRun(this, runname); return ""; } bool EventGenerator::preinitRegister(IPtr obj, string fullname) { if ( !preinitializing ) throw InitException() << "Tried to register a new object in the initialization of an " << "EventGenerator outside of the pre-initialization face. " << "The preinitRegister() can only be called from a doinit() function " << "in an object for which preInitialize() returns true."; if ( objectMap().find(fullname) != objectMap().end() ) return false; obj->name(fullname); objectMap()[fullname] = obj; objects().insert(obj); obj->theGenerator = this; PDPtr pd = dynamic_ptr_cast(obj); if ( pd ) theParticles[pd->id()] = pd; PMPtr pm = dynamic_ptr_cast(obj); if ( pm ) theMatchers.insert(pm); return true; } bool EventGenerator::preinitRemove(IPtr obj) { bool deleted=true; if(theObjects.find(obj)!=theObjects.end()) { theObjects.erase(obj); } else deleted = false; if(theObjectMap.find(obj->fullName())!=theObjectMap.end()) theObjectMap.erase(obj->fullName()); else deleted = false; return deleted; } IPtr EventGenerator:: preinitCreate(string classname, string fullname, string libraries) { if ( !preinitializing ) throw InitException() << "Tried to create a new object in the initialization of an " << "EventGenerator outside of the pre-initialization face. " << "The preinitCreate() can only be called from a doinit() function " << "in an object for which preInitialize() returns true."; if ( objectMap().find(fullname) != objectMap().end() ) return IPtr(); const ClassDescriptionBase * db = DescriptionList::find(classname); while ( !db && libraries.length() ) { string library = StringUtils::car(libraries); libraries = StringUtils::cdr(libraries); DynamicLoader::load(library); db = DescriptionList::find(classname); } if ( !db ) return IPtr(); IPtr obj = dynamic_ptr_cast(db->create()); if ( !obj ) return IPtr(); if ( !preinitRegister(obj, fullname) ) return IPtr(); return obj; } string EventGenerator:: preinitInterface(IPtr obj, string ifcname, string cmd, string value) { if ( !preinitializing ) throw InitException() << "Tried to manipulate an external object in the initialization of an " << "EventGenerator outside of the pre-initialization face. " << "The preinitSet() can only be called from a doinit() function " << "in an object for which preInitialize() returns true."; if ( !obj ) return "Error: No object found."; const InterfaceBase * ifc = Repository::FindInterface(obj, ifcname); if ( !ifc ) return "Error: No such interface found."; try { return ifc->exec(*obj, cmd, value); } catch ( const InterfaceException & ex) { ex.handle(); return "Error: " + ex.message(); } } string EventGenerator:: preinitInterface(IPtr obj, string ifcname, int index, string cmd, string value) { ostringstream os; os << index; return preinitInterface(obj, ifcname, cmd, os.str() + " " + value); } string EventGenerator:: preinitInterface(string fullname, string ifcname, string cmd, string value) { return preinitInterface(getObject(fullname), ifcname, cmd, value); } string EventGenerator:: preinitInterface(string fullname, string ifcname, int index, string cmd, string value) { return preinitInterface(getObject(fullname), ifcname, index, cmd, value); } tDMPtr EventGenerator::findDecayMode(string tag) const { for ( ObjectSet::const_iterator it = objects().begin(); it != objects().end(); ++it ) { tDMPtr dm = dynamic_ptr_cast(*it); if ( dm && dm->tag() == tag ) return dm; } return tDMPtr(); } tDMPtr EventGenerator::preinitCreateDecayMode(string tag) { return constructDecayMode(tag); } DMPtr EventGenerator::constructDecayMode(string & tag) { DMPtr rdm; DMPtr adm; int level = 0; string::size_type end = 0; while ( end < tag.size() && ( tag[end] != ']' || level ) ) { switch ( tag[end++] ) { case '[': ++level; break; case ']': --level; break; } } rdm = findDecayMode(tag.substr(0,end)); if ( rdm ) return rdm; string::size_type next = tag.find("->"); if ( next == string::npos ) return rdm; if ( tag.find(';') == string::npos ) return rdm; tPDPtr pd = getObject(tag.substr(0,next)); if ( !pd ) pd = findParticle(tag.substr(0,next)); if ( !pd ) return rdm; rdm = ptr_new(); rdm->parent(pd); if ( pd->CC() ) { adm = ptr_new(); adm->parent(pd->CC()); rdm->theAntiPartner = adm; adm->theAntiPartner = rdm; } bool error = false; tag = tag.substr(next+2); tPDPtr lastprod; bool dolink = false; do { switch ( tag[0] ) { case '[': { tag = tag.substr(1); tDMPtr cdm = constructDecayMode(tag); if ( cdm ) rdm->addCascadeProduct(cdm); else error = true; } break; case '=': dolink = true; [[fallthrough]]; case ',': case ']': tag = tag.substr(1); break; case '?': { next = min(tag.find(','), tag.find(';')); tPMPtr pm = findMatcher(tag.substr(1,next-1)); if ( pm ) rdm->addProductMatcher(pm); else error = true; tag = tag.substr(next); } break; case '!': { next = min(tag.find(','), tag.find(';')); tPDPtr pd = findParticle(tag.substr(1,next-1)); if ( pd ) rdm->addExcluded(pd); else error = true; tag = tag.substr(next); } break; case '*': { next = min(tag.find(','), tag.find(';')); tPMPtr pm = findMatcher(tag.substr(1,next-1)); if ( pm ) rdm->setWildMatcher(pm); else error = true; tag = tag.substr(next); } break; default: { next = min(tag.find('='), min(tag.find(','), tag.find(';'))); tPDPtr pdp = findParticle(tag.substr(0,next)); if ( pdp ) rdm->addProduct(pdp); else error = true; tag = tag.substr(next); if ( dolink && lastprod ) { rdm->addLink(lastprod, pdp); dolink = false; } lastprod = pdp; } break; } } while ( tag[0] != ';' && tag.size() ); if ( tag[0] != ';' || error ) { return DMPtr(); } tag = tag.substr(1); DMPtr ndm = findDecayMode(rdm->tag()); if ( ndm ) return ndm; pd->addDecayMode(rdm); if ( !preinitRegister(rdm, pd->fullName() + "/" + rdm->tag()) ) return DMPtr(); if ( adm ) { preinitRegister(adm, pd->CC()->fullName() + "/" + adm->tag()); rdm->CC(adm); adm->CC(rdm); } return rdm; } tPDPtr EventGenerator::findParticle(string pdgname) const { for ( ParticleMap::const_iterator it = particles().begin(); it != particles().end(); ++it ) if ( it->second->PDGName() == pdgname ) return it->second; return tPDPtr(); } tPMPtr EventGenerator::findMatcher(string name) const { for ( MatcherSet::const_iterator it = matchers().begin(); it != matchers().end(); ++it ) if ( (**it).name() == name ) return *it; return tPMPtr(); } ClassDescription EventGenerator::initEventGenerator; void EventGenerator::Init() { static ClassDocumentation documentation ("This is the main class used to administer an event generation run. " "The actual generation of each event is handled by the assigned " "EventHandler object. When the event generator" "is properly set up it can be initialized with the command " "MakeRun and/or saved to a file with the command " "SaveRun. If saved to a file, the event generator " "can be read into another program to produce events. The file can also " "be read into the runThePEG program where a number of events " "determined by the parameter NumberOfEvents is " "generated with each event analysed by the list of assigned " "AnalysisHandlers."); static Reference interfaceStandardModel ("StandardModelParameters", "The ThePEG::StandardModelBase object to be used to access standard " "model parameters in this run.", &EventGenerator::theStandardModel, false, false, true, false); static Reference interfaceEventHandler ("EventHandler", "The ThePEG::EventHandler object to be used to generate the " "individual events in this run.", &EventGenerator::theEventHandler, false, false, true, false); static RefVector interfaceAnalysisHandlers ("AnalysisHandlers", "ThePEG::AnalysisHandler objects to be used to analyze the produced " "events in this run.", &EventGenerator::theAnalysisHandlers, 0, true, false, true, false); static Reference interfaceHistogramFactory ("HistogramFactory", "An associated factory object for handling histograms to be used by " "AnalysisHandlers.", &EventGenerator::theHistogramFactory, true, false, true, true, true); static Reference interfaceEventManip ("EventManipulator", "An ThePEG::EventManipulator called each time the generation of an " "event is stopped. The ThePEG::EventManipulator object is able to " "manipulate the generated event, as opposed to an " "ThePEG::AnalysisHandler which may only look at the event.", &EventGenerator::theEventManipulator, true, false, true, true); static RefVector interfaceLocalParticles ("LocalParticles", "Special versions of ThePEG::ParticleData objects to be used " "in this run. Note that to delete an object, its number in the list " "should be given, rather than its id number.", 0, 0, false, false, true, false, &EventGenerator::setLocalParticles, &EventGenerator::insLocalParticles, &EventGenerator::delLocalParticles, &EventGenerator::getLocalParticles); static RefVector interfaceDefaultObjects ("DefaultObjects", "A vector of pointers to default objects. In a ThePEG::Reference or " "ThePEG::RefVector interface with the defaultIfNull() flag set, if a " "null pointer is encountered this vector is gone through until an " "acceptable object is found in which case the null pointer is replaced " "by a pointer to this object.", &EventGenerator::theDefaultObjects, 0, true, false, true, false, false); static Reference interfaceStrategy ("Strategy", "An ThePEG::Strategy with additional ThePEG::ParticleData objects to " "be used in this run.", &EventGenerator::theStrategy, false, false, true, true); static Reference interfaceRandomGenerator ("RandomNumberGenerator", "An ThePEG::RandomGenerator object which should typically interaface to " "a CLHEP Random object. This will be the default random number generator " "for the run, but individual objects may use their own random generator " "if they wish.", &EventGenerator::theRandom, true, false, true, false); static Parameter interfacePath ("Path", "The directory where the output files are put.", &EventGenerator::thePath, ".", true, false, &EventGenerator::setPath, 0, &EventGenerator::defPath); interfacePath.directoryType(); static Parameter interfaceRunName ("RunName", "The name of this run. This name will be used in the output filenames. " "The files wil be placed in the directory specified by the " "Path parameter" "If empty the name of the event generator will be used instead.", &EventGenerator::theRunName, "", true, false, 0, 0, &EventGenerator::name); static Parameter interfaceNumberOfEvents ("NumberOfEvents", "The number of events to be generated in this run. If less than zero, " "the number of events is unlimited", &EventGenerator::theNumberOfEvents, 1000, -1, Constants::MaxInt, true, false, Interface::lowerlim); static Parameter interfaceDebugLevel ("DebugLevel", "The level of debug information sent out to the log file in the run. " "Level 0 only gives a limited ammount of warnings and error messages. " "Level 1 will print the first few events. " "Level 5 will print every event. " "Level 9 will print every step in every event.", &EventGenerator::theDebugLevel, 0, 0, 9, true, false, true); static Parameter interfacePrintEvent ("PrintEvent", "If the debug level is above zero, print the first 'PrintEvent' events.", &EventGenerator::printEvent, 0, 0, 1000, true, false, Interface::lowerlim); static Parameter interfaceDumpPeriod ("DumpPeriod", "If the debug level is above zero, dump the full state of the run every " "'DumpPeriod' events. Set it to -1 to disable dumping even in the case of errors.", &EventGenerator::dumpPeriod, 0, -1, Constants::MaxInt, true, false, Interface::lowerlim); static Switch interfaceKeepAllDumps ("KeepAllDumps", "Whether all dump files should be kept, labelled by event number.", &EventGenerator::keepAllDumps, false, true, false); static SwitchOption interfaceKeepAllDumpsYes (interfaceKeepAllDumps, "Yes", "Keep all dump files, labelled by event number.", true); static SwitchOption interfaceKeepAllDumpsNo (interfaceKeepAllDumps, "No", "Keep only the latest dump file.", false); static Parameter interfaceDebugEvent ("DebugEvent", "If the debug level is above zero, step up to the highest debug level " "befor event number 'DebugEvent'.", &EventGenerator::debugEvent, 0, 0, Constants::MaxInt, true, false, Interface::lowerlim); static Parameter interfaceMaxWarnings ("MaxWarnings", "The maximum number of warnings of each type which will be printed.", &EventGenerator::maxWarnings, 10, 1, 100, true, false, Interface::lowerlim); static Parameter interfaceMaxErrors ("MaxErrors", "The maximum number of errors of each type which will be tolerated. " "If more errors are reported, the run will be aborted.", &EventGenerator::maxErrors, 10, -1, 100000, true, false, Interface::lowerlim); static Parameter interfaceQuickSize ("QuickSize", "The max absolute id number of particle data objects which are accessed " "quickly through a vector indexed by the id number.", &EventGenerator::theQuickSize, 7000, 0, 50000, true, false, Interface::lowerlim); static Command interfaceSaveRun ("SaveRun", "Isolate, initialize and save this event generator to a file, from which " "it can be read in and run in another program. If an agument is given " "this is used as the run name, otherwise the run name is taken from the " "RunName parameter.", &EventGenerator::doSaveRun, true); static Command interfaceMakeRun ("MakeRun", "Isolate and initialize this event generator and give it a run name. " "If no argument is given, the run name is taken from the " "RunName parameter.", &EventGenerator::doMakeRun, true); interfaceEventHandler.rank(11.0); interfaceSaveRun.rank(10.0); interfaceMakeRun.rank(9.0); interfaceRunName.rank(8.0); interfaceNumberOfEvents.rank(7.0); interfaceAnalysisHandlers.rank(6.0); static Switch interfaceUseStdout ("UseStdout", "Redirect the logging and output to stdout instead of files.", &EventGenerator::useStdout, false, true, false); static SwitchOption interfaceUseStdoutYes (interfaceUseStdout, "Yes", "Use stdout instead of log files.", true); static SwitchOption interfaceUseStdoutNo (interfaceUseStdout, "No", "Use log files.", false); static Switch interfaceLogNonDefault ("LogNonDefault", "Controls the printout of important interfaces which has been changed from their default values.", &EventGenerator::logNonDefault, -1, true, false); static SwitchOption interfaceLogNonDefaultYes (interfaceLogNonDefault, "Yes", "Always print changed interfaces.", 1); static SwitchOption interfaceLogNonDefaultOnDebug (interfaceLogNonDefault, "OnDebug", "Only print changed interfaces if debugging is turned on.", 0); static SwitchOption interfaceLogNonDefaultNo (interfaceLogNonDefault, "No", "Don't print changed interfaces.", -1); interfaceLogNonDefault.setHasDefault(false); static Switch interfaceIntermediateOutput ("IntermediateOutput", "Modified event number count with the number of events processed so far, " "which updates at least every 10000 events, together with the corresponding " "intermediate estimate for the cross section plus the integration error.", &EventGenerator::theIntermediateOutput, false, true, false); static SwitchOption interfaceIntermediateOutputYes (interfaceIntermediateOutput, "Yes", "Show the modified event number count with the number of events processed so far, " "plus further information on the intermediate cross section estimate.", true); static SwitchOption interfaceIntermediateOutputNo (interfaceIntermediateOutput, "No", "Show the usual event number count with the number of events processed so far, " "but no further information on the intermediate cross section estimate.", false); } EGNoPath::EGNoPath(string path) { theMessage << "Cannot set the directory path for output files to '" << path << "' because the directory did not exist and could not be " << "created."; severity(warning); } diff --git a/Repository/EventGenerator.h b/Repository/EventGenerator.h --- a/Repository/EventGenerator.h +++ b/Repository/EventGenerator.h @@ -1,1189 +1,1189 @@ // -*- C++ -*- // // EventGenerator.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_EventGenerator_H #define ThePEG_EventGenerator_H // This is the declaration of the EventGenerator class. #include "ThePEG/Config/ThePEG.h" #include "ThePEG/Utilities/Named.h" #include "EventGenerator.fh" #include "RandomGenerator.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/Strategy.h" #include "ThePEG/Repository/CurrentGenerator.fh" #include "ThePEG/Utilities/ClassDescription.h" #include "ThePEG/Handlers/EventHandler.fh" #include "ThePEG/Analysis/FactoryBase.fh" #include #include "EventGenerator.xh" namespace ThePEG { /** * The EventGenerator class manages a whole event generator run. It * keeps a list of all Interfaced objects which are needed for a * particular run (these objects each have a pointer back to the * EventGenerator). Some objects are special, such as a default * RandomGenerator object, a StandardModelBase object and a Strategy * object and lists of ParticleData and MatcherBase objects used in * the run. * * The EventGenerator also manages information about the * run such as the exceptions being thrown, files to write output and * error messages to, etc. * * There are three main external member functions:
* go() generates a specified number of events and exits.
* * shoot() generates one Event and returns it.
* * generateEvent() takes an initial Step or a partially generated * Event as argument and generates subsequent steps defined in the * generator.
* * doShoot() is a virtual function called by shoot() and may be * overridden in sub-classes.
* * doGenrateEvent() is a virtual function called by generateEvent() and * may to be overridden in sub-classes. * * @see \ref EventGeneratorInterfaces "The interfaces" * defined for EventGenerator. * @see Interfaced * @see RandomGenerator * @see StandardModelBase * @see Strategy * @see ParticleData * @see Event * @see Step * @see FullEventGenerator * */ class EventGenerator: public Interfaced { /** The Repository is a friend. */ friend class Repository; public: /** A map of integers giving the number of times an exception of the * key type has been thrown. */ //typedef map ExceptionMap; //typedef map ExceptionMap; typedef map, int> ExceptionMap; public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ EventGenerator(); /** * Copy-constructor. */ EventGenerator(const EventGenerator &); /** * Destructor. */ virtual ~EventGenerator(); //@} public: /** @name Access special objects in the run. */ //@{ /** * Return a pointer to the standard model parameters. */ tSMPtr standardModel() const { return theStandardModel; } /** * Return a pointer to the strategy object containing a set of * non-default particles to use. */ tStrategyPtr strategy() const { return theStrategy; } /** * Get the currently active EventHandler. */ tEHPtr currentEventHandler() const { return theCurrentEventHandler; } /** * Set the currently active EventHandler. */ void currentEventHandler(tEHPtr eh) { theCurrentEventHandler = eh; } /** * Get the currently active step handler. */ tStepHdlPtr currentStepHandler() const { return theCurrentStepHandler; } /** * Set the currently active step handler. */ void currentStepHandler(tStepHdlPtr sh) { theCurrentStepHandler = sh; } /** * Return a pointer to the EventHandler. */ tEHPtr eventHandler() const { return theEventHandler; } /** * Return the vector of analysis objects to be used in the run. */ AnalysisVector & analysisHandlers() { return theAnalysisHandlers; } /** * Return a pointer to an associated factory objects for handling * histograms to be used by AnalysisHandlers. */ tHistFacPtr histogramFactory() const { return theHistogramFactory; } /** * Return the EventManipulator used in the run. */ tEvtManipPtr manipulator() const { return theEventManipulator; } //@} public: /** @name Main functions to controll the run. */ //@{ /** * Initialize this generator. This is done automatically if 'go()' * is used. Calls the virtual method doInitialize(). */ void initialize(bool initOnly = false); /** * Run this EventGenerator session. Calls the virtual method doGo(). * * @param next the number of the firts event to be generated. If * negative it is assumed that this generator was previously * interrupted (or dumped to a file) and the execution will resume * from where it started. Default is 1. * @param maxevent the maximum number of events to be generated. If negative * the N() is used instead. Default is -1. * @param tics if true information the number of events generated * and elapsed time will be written to std::cerr after each event. */ void go(long next = 1, long maxevent = -1, bool tics = false); /** * Generate one event. Calls the virtual method doShoot(); */ EventPtr shoot(); /** * Finish generating an \a event which has already been partially * constructed from the outside. Calls the virtual method do * doGenerateEvent(). */ EventPtr generateEvent(Event & event); /** * Finish generating an event starting from a \a step which has * already been partially constructed from the outside. Calls the * virtual method do doGenerateEvent(). */ EventPtr generateEvent(Step & step); /** * Indicate that the run has ended and call finish() for all objects * including this one. Note that finish() should not be called * directly. */ void finalize(); /** * Dynamically load the Main class in the given \a file, making it * run its Init() method where it may use this EventGenerator. Also * call the initialize function before and the finish() function * afterwards. */ bool loadMain(string file); /** * Return the maximum center of mass energy possible for an * event. Return zero if the assigned EventHander is not able to * generatr full events. */ virtual Energy maximumCMEnergy() const; /** * The number of the event currently being generated. */ long currentEventNumber() const { return ieve; } /** * Return the event being generated. */ tcEventPtr currentEvent() const; /** * Dump the full state of the current run - including the number of * generated events, so that it can be fully continued from this point. */ virtual void dump() const; /** * Register a given object as used. Only objects registered in this * way will be included in the file with model references. */ void use(const Interfaced & i); /** * Set the random seed for the global random number generator. Also * set the interfaced member variable. */ void setSeed(long seed); /** * Log a given exception. */ void logWarning(const Exception &); /** * The number of events to be generated in this run. */ long N() const { return theNumberOfEvents; } /** * 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. */ CrossSection histogramScale() const; /** * The total integrated cross section of the processes generated in * this run. */ CrossSection integratedXSec() const; /** * The error estimate for the total integrated cross section of the * processes generated in this run. */ CrossSection integratedXSecErr() const; /** * The sum of all weight of the events generated so far. */ double sumWeights() const { return weightSum; } //@} /** @name Functions for accessing output files. */ //@{ /** * The base filename used in this run. The actual files are called * filename.run, filename.dump, * filename.out, filename.log and * filename.tex for the input configuration file, * output dump file, output file, log file, and reference * file respectively. The filename is constructed from the path() * and runName(). */ string filename() const { return path() + "/" + runName(); } /** * Return the name assigned to this run. If no name is given, the * name of the EventGenerator object is returned. */ string runName() const { return theRunName.size()? theRunName: name(); } /** * The directory in which the filename() is located */ string path() const { return thePath; } /** * Has the generator been asked to redirect everything to standard * output? */ bool useStdOut() const { return useStdout; } /** * Open all ouput files. */ void openOutputFiles(); /** * Flush the content of the internal output string stream to the .out file. */ void flushOutputFile(); /** * Close all ouput files. */ void closeOutputFiles(); /** * Return a reference to the output file stream. */ ofstream & outfile() { return theOutfile; } /** * Return a reference to the log file stream. */ ofstream & logfile() { return theLogfile; } /** * Return a reference to the reference file stream. This file is * used to output LaTeX text with information about the models used * in the run. */ ofstream & reffile() { return theReffile; } /** * This stream should be used for output of information and * statistics of an EventGenerator run in the finish() phase, after * the actual generation has finished. When used at other times, the * output will be cashed internally before written out in the * finish() phase. This is then written to the .out file, or if * useStdOut() is true, to BaseRepository::cout(). */ ostream & out(); /** * Return a reference to the stream connected to the file for logging * information. If no file is connected, BaseRepository::cout() will * be used instead. */ ostream & log(); /** * Return a reference to a stream to be used to redirect cout for * external modules which prints out messages there. The output will * instead be appended to the log() stream at the end of the run. */ ostream & misc() { return theMiscStream; } /** * Return a reference to the stream connected to the filea for * references from used objects. If no file is connected, * BaseRepository::cout() will be used instead. */ ostream & ref(); //@} /** @name Access objects included in this run. */ //@{ /** * Return the set of objects used in this run. */ const ObjectSet & objects() const { return theObjects; } /** * Return the map of objects used in this run indexed by their name. */ const ObjectMap & objectMap() const { return theObjectMap; } /** * Return a garbage collected pointer to a given object. If the * object is not included in the run, a null pointer will be * returned. */ template typename Ptr::pointer getPtr(const T &) const; /** * Return a pointer to an object present in this run given its full * name. Return the null pointer if non-existent. */ IBPtr getPointer(string name) const; /** * Return a pointer to an object of type T present in this run given * its full name. Return the null pointer if non-existent. Calls * getPointer(string) and dynamically casts the result to the * requested pointer type. */ template typename Ptr::pointer getObject(string name) const { return dynamic_ptr_cast::pointer>(getPointer(name)); } /** * Return the default object for class T. Returns the null pointer * if non-existent. */ template typename Ptr::pointer getDefault() const; /** * Create a particle instance corresponding to the given \a id * number. */ PPtr getParticle(PID id) const; /** * Return a pointer to the ParticleData object corresponding to the * given \a id number. */ PDPtr getParticleData(PID id) const; /** * Return a reference to the complete list of matchers in this * generator. */ const MatcherSet & matchers() const { return theMatchers; } /** * Return a reference to the complete map of particle data objects * in this generator, indexed by their id numbers. */ const ParticleMap & particles() const { return theParticles; } /** * Return a reference to the set of objects which have been * registered as used during the current run. */ const ObjectSet & used() const { return usedObjects; } //@} protected: /** * Check if there has been an interrupt signal from the OS. * If that's the case, finalize() is called */ void checkSignalState(); /** * Return a reference to the default RandomGenerator object in this * run. */ RandomGenerator & random() const { return *theRandom; } /** * Finish the setup of an event generator run. Set run name, all * particles, matchers and other objects to be used. Is used by the * Repository when isolating an EventGenerator. */ void setup(string newRunName, ObjectSet & newObjects, ParticleMap & newParticles, MatcherSet & newMatchers); /** @name Main virtual functions to be overridden by sub-classes. */ //@{ /** * Run this EventGenerator session. Is called from go(long,long,bool). */ virtual void doGo(long next, long maxevent, bool tics); /** * Initialize this generator. Is called from initialize(). */ virtual void doInitialize(bool initOnly = false); /** * Generate one event. Is called from shoot(). */ virtual EventPtr doShoot(); /** * Write out the number of events generated and the elapsed time in * suitable periods. */ void tic(long currev = 0, long totev = 0) const; /** * Finish generating an event constructed from the outside. Is * called by generateEvent(tEventPtr). */ virtual EventPtr doGenerateEvent(tEventPtr); /** * Finish generating an event starting from a Step constructed from * the outside. Is called by generateEvent(tStepPtr). */ virtual EventPtr doGenerateEvent(tStepPtr); //@} /** * Print the message of an exception to the log file. */ void printException(const Exception &); /** * Log a given exception. */ bool logException(const Exception &, tcEventPtr); /** * Set number of events to be generated. */ void N(long n) { theNumberOfEvents = n; } /** * Set the name of this run */ void runName(string f) { theRunName = f; } public: /** * Append a tag to the run name. Derived classes may put special * meaning to the tags. */ virtual void addTag(string tag) { runName(runName() + tag); } private: /** * Return the vector of default objects. */ const vector & defaultObjects() const { return theDefaultObjects; } /** * Access the special particles used in this generator. Not relevant * in the run phase. */ ParticleMap & localParticles() { return theLocalParticles; } /** * Access the special particles used in this generator. Not relevant * in the run phase. */ const ParticleMap & localParticles() const { return theLocalParticles; } /** * Set the directory where the output files will be stored. */ void path(string f) { thePath = f; } /** * Set a pointer to the strategy object containing a set of * non-default particles to use. */ void strategy(StrategyPtr); /** * Isolate, initialize and save this generator to a file. */ string doSaveRun(string); /** * Isolate and initialize this generator. */ string doMakeRun(string); public: /** @name The following functions may be called by objects belonging to this event generator during the initialization phase (in the doinit() function). It is typically used by objects which need to introduce other Interfaced objects depending the parameters of the StandardModel object used. Note that objects which use these functions MUST override the preInitialize() function to return true, otherwize the whole initialization procedure may be corrupted. */ //@{ /** * Register a new object to be included in the run currently being * initialized. * * @param obj (pointer to) the object being registered. * * @param fullname the full name including the directory path. Note * that although the full path is given the object will not be * inserted in the Repository, but only in this current * EventGenerator. * * @return false if another object of that name already exists. */ bool preinitRegister(IPtr obj, string fullname); /** * Create a new Interfaced object to be used in the run being * initialized. * * @param classname the class name of the object being created. * * @param fullname the full name including the directory path. Note * that although the full path is given the object will not be * inserted in the Repository, but only in this current * EventGenerator. * * @param libraries an optional list of shared libraries to be * loaded to be able to create an object of the specified class. * * @return the created object if the it was successfully * created. Return null if the object could not be created or if * another object of that name already exists. */ IPtr preinitCreate(string classname, string fullname, string libraries = ""); /** * Manipulate an interface of an Interfaced object. * * @param fullname the name including the full path of an object to * be manipulated. * * @param ifcname the name of the interface to be used. * * @param cmd the operation to be performed on the interface (set or * get). * * @param value Optional value to be passed to the interface. * * @return a string containing the result of the operation. If this * string starts with "Error: " then something went wrong. */ string preinitInterface(string fullname, string ifcname, string cmd, string value); /** * Manipulate an interface of vector type (RefVector or ParVector) * of an Interfaced object. * * @param fullname the name including the full path of an object to * be manipulated. * * @param ifcname the name of the interface to be used. * * @param index the vector index corresponding to the element to be * manipulated. * * @param cmd the operation to be performed on the interface (set, * get, insert or erase). * * @param value Optional value to be passed to the interface. * * @return a string containing the result of the operation. If this * string starts with "Error: " then something went wrong. */ string preinitInterface(string fullname, string ifcname, int index, string cmd, string value); /** * Manipulate an interface of an Interfaced object. * * @param obj the object to be manipulated. * * @param ifcname the name of the interface to be used. * * @param cmd the operation to be performed on the interface (set or * get). * * @param value Optional value to be passed to the interface. * * @return a string containing the result of the operation. If this * string starts with "Error: " then something went wrong. */ string preinitInterface(IPtr obj, string ifcname, string cmd, string value); /** * Manipulate an interface of vector type (RefVector or ParVector) * of an Interfaced object. * * @param obj the object to be manipulated. * * @param ifcname the name of the interface to be used. * * @param index the vector index corresponding to the element to be * manipulated. * * @param cmd the operation to be performed on the interface (set, * get, insert or erase). * * @param value Optional value to be passed to the interface. * * @return a string containing the result of the operation. If this * string starts with "Error: " then something went wrong. */ string preinitInterface(IPtr obj, string ifcname, int index, string cmd, string value); /** * Remove the object */ bool preinitRemove(IPtr obj); /** * Find a decaymode given a decay \a tag. * @return null if no decay mode was found. */ tDMPtr findDecayMode(string tag) const; /** * Create a decay mode according to the given tag. * @return null if no decay mode could be created. */ tDMPtr preinitCreateDecayMode(string tag); /** * Find a particle in this run, using its PDG name. * @return null if no particle is found. */ tPDPtr findParticle(string pdgname) const; /** * Find a matcher in this run given its \a name. * @return null if no mather is found. */ tPMPtr findMatcher(string name) const; private: /** * Used internally by preinitCreateDecayMode(); */ DMPtr constructDecayMode(string & tag); //@} 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 global libraries needed for objects used in this EventGenerator. */ const vector & globalLibraries() const { return theGlobalLibraries; } //@} /** * Standard Init function used to initialize the interface. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} 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(); /** * Additional things to do at the very end after the (do)finish(), * such as closing output files etc. */ void finally(); //@} /** * Return the set of all objects to be used in this run. */ ObjectSet & objects() { return theObjects; } /** * Return the map of all objects to be used in this run indexed by * their name. */ ObjectMap & objectMap() { return theObjectMap; } /** * Print out the .tex file with descriptions of and references to * all models used in the run. */ void generateReferences(); /** * Increase and return the count for the given exception. */ int count(const Exception &); private: /** * A vector of default objects. */ vector theDefaultObjects; /** * Map of non-default particles used in this EventGenerator. */ ParticleMap theLocalParticles; /** * Pointer to an object containing standard model parameters. */ SMPtr theStandardModel; /** * Pointer to a strategy object with other non-default particles to * be used in this EventGenerator. */ StrategyPtr theStrategy; /** * Pointer to the default RandomGenerator to be used in this run. */ RanGenPtr theRandom; /** * Pointer to the event handler used to generate the indivudual * events. */ EHPtr theEventHandler; /** * A vector of all analysis handlers to be called after each event. */ AnalysisVector theAnalysisHandlers; /** * A pointer to an associated factory objects for handling * histograms to be used by AnalysisHandlers. */ HistFacPtr theHistogramFactory; /** * A pointer to an optional event manipulator object. */ EvtManipPtr theEventManipulator; /** * The directory where the input and output files resides. */ string thePath; /** * The name of this run. */ string theRunName; /** * A reference to the output file stream. */ ofstream theOutfile; /** * A reference to the log file stream. */ ofstream theLogfile; /** * A reference to the reference file stream. */ ofstream theReffile; /** * A stream to be used to redirect cout for external modules which * prints out messages there. The output will instead be appended to * the log() stream at the end of the run. */ ostringstream theMiscStream; /** * A string stream used as a buffer for messages written to the .out * file. The .out file should in rinciple only be written to in the * end of a run, during the finish() phase, but if anything is * written before that, it will be cashed in this string stream * before written out properly in the end of the run. */ ostringstream theOutStream; /** * Remember the name of the file where the output should be * sent. This is set int openOutputFiles(). */ string theOutFileName; /** * Number of events to be generated in this run. */ long theNumberOfEvents; /** * The set of all objects to be used in this run. */ ObjectSet theObjects; /** * All objects to be used in this run mapped to their name. */ ObjectMap theObjectMap; /** * The map of all particles to be used in this run, indexed by the * id number. */ ParticleMap theParticles; /** * A vector of particles indexed by the id number for quick access. * Only particles with id number less than theQuickSize are * available. */ PDVector theQuickParticles; /** * Only particles with id number less than theQuickSize are * available in theQuickParticles. */ long theQuickSize; /** * A flag to tell if we are in the pre-initialization phase where * objects with preInitialize() functions returning true are * initialized before others. */ bool preinitializing; /** * The set of all matchers to be used in this run. */ MatcherSet theMatchers; /** * The set of objects which have actually been used in this run. */ ObjectSet usedObjects; protected: /** * The current event number; */ long ieve; /** * The sum of the weights of the events produced so far. */ double weightSum; /** * The debug level. */ int theDebugLevel; private: /** * List all modified interfaces in the log file. If positive always * do this, if negative never do it. If zero, only do it if * debugging is turned on. */ int logNonDefault; /** * If the debug level is higher than 0, print the first 'printEvent' * events to the logfile. */ int printEvent; /** * If the debug level is higher than 0, dump the complete state of * this run to the default dump file every 'dumpPeriod' events. * If 'dumpPeriod' is -1, dumping is disabled completely, * even when runs are aborted. */ long dumpPeriod; /** * If this flag is true, keep all dump files of the run, * labelled by event number. */ bool keepAllDumps; /** * If the debug level is higher than 0, step up to the highest debug * level just before the event with number debugEvent is performed. */ long debugEvent; /** * The maximum number of warnings reported of each type. If more * than maxWarnings warnings of one type is issued, the generation * will continue without reporting this warning. */ int maxWarnings; /** * The maximum number of warnings and errors reported of each * type. If more than maxErrors errors is reported for one type the * run will be aborted. Disable the check by setting to -1. */ int maxErrors; /** * A map of all Exceptions which have been caught by the event * generator and the number of time each exception type has been * caught. */ ExceptionMap theExceptions; private: /** * Utility function for the interface. */ void setLocalParticles(PDPtr pd, int); /** * Utility function for the interface. */ void insLocalParticles(PDPtr pd, int); /** * Utility function for the interface. */ void delLocalParticles(int place); /** * Utility function for the interface. */ vector getLocalParticles() const; /** * Utility function for the interface. */ void setPath(string newPath); /** * Utility function for the interface. */ string defPath() const; /** * The UseRandom object constructed for the duration of an * EventGenerator run so that the default random number generator * always can be accessed through the static methods of the * UseRandom class. */ UseRandom * theCurrentRandom; /** * The CurrentGenerator object constructed for the duration of an * EventGenerator run so that the default event generator always can * be accessed through the static methods of the CurrentGenerator * class. */ CurrentGenerator * theCurrentGenerator; /** * The currently active EventHandler. */ tEHPtr theCurrentEventHandler; /** * The currently active step handler. */ tStepHdlPtr theCurrentStepHandler; /** * Whether to use files or stdout for logging and output. */ bool useStdout; /** * Whether to use a modified event number count. */ bool theIntermediateOutput; /** * The global libraries needed for objects used in this EventGenerator. */ vector theGlobalLibraries; private: /** * Describe an abstract class with persistent data. */ static ClassDescription initEventGenerator; /** * Private and non-existent assignment operator. */ EventGenerator & operator=(const EventGenerator &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the base classes * of EventGenerator. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of EventGenerator. */ typedef Interfaced NthBase; }; /** This template specialization informs ThePEG about the name of the * EventGenerator class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "ThePEG::EventGenerator"; } }; /** @endcond */ } #ifndef ThePEG_TEMPLATES_IN_CC_FILE #include "EventGenerator.tcc" #endif #endif /* ThePEG_EventGenerator_H */ diff --git a/Repository/EventGenerator.tcc b/Repository/EventGenerator.tcc --- a/Repository/EventGenerator.tcc +++ b/Repository/EventGenerator.tcc @@ -1,43 +1,43 @@ // -*- C++ -*- // // EventGenerator.tcc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined templated member // functions of the EventGenerator class. // namespace ThePEG { template typename Ptr::pointer EventGenerator::getPtr(const T & t) const { typedef typename Ptr::pointer ptr; ObjectSet::const_iterator it = objects().find(ptr_cast_const(&t)); return it == objects().end()? ptr(): dynamic_ptr_cast(*it); } template typename Ptr::pointer EventGenerator::getDefault() const { typedef typename Ptr::pointer ptr; ptr ret; for ( vector::const_iterator it = defaultObjects().begin(); it != defaultObjects().end(); ++it ) { ret = dynamic_ptr_cast(*it); if ( ret ) return ret; } if ( strategy() ) { for ( vector::const_iterator it = strategy()->defaultObjects().begin(); it != strategy()->defaultObjects().end(); ++it ) { ret = dynamic_ptr_cast(*it); if ( ret ) return ret; } } return ret; } } diff --git a/Repository/EventGenerator.xh b/Repository/EventGenerator.xh --- a/Repository/EventGenerator.xh +++ b/Repository/EventGenerator.xh @@ -1,32 +1,32 @@ // -*- C++ -*- // // EventGenerator.xh is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_EventGenerator_XH #define ThePEG_EventGenerator_XH // // This is the declarations of the exception classes used by the // EventGenerator class. // #include "ThePEG/Utilities/Exception.h" namespace ThePEG { /** @cond EXCEPTIONCLASSES */ /** Exception class used by EventGenerator if a directory could not be found/created. */ struct EGNoPath: public Exception { /** Standard constructor. */ EGNoPath(string); }; /** @endcond */ } #endif /* ThePEG_EventGenerator_XH */ diff --git a/Repository/Main.cc b/Repository/Main.cc --- a/Repository/Main.cc +++ b/Repository/Main.cc @@ -1,26 +1,26 @@ // -*- C++ -*- // // Main.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the Main class. // #include "Main.h" using namespace ThePEG; AbstractNoPIOClassDescription
Main::initMain; // Definition of the static class description member. EGPtr Main::theEventGenerator; long Main::theN = 0; vector Main::theArguments; diff --git a/Repository/Main.h b/Repository/Main.h --- a/Repository/Main.h +++ b/Repository/Main.h @@ -1,139 +1,139 @@ // -*- C++ -*- // // Main.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_Main_H #define THEPEG_Main_H // This is the declaration of the Main class. #include "ThePEG/Config/ThePEG.h" #include "ThePEG/Repository/EventGenerator.h" namespace ThePEG { /** * This is a base class for classes implementing a main steering * routine for running an EventGenerator, in case the standard * 'go()' function in the EventGenerator is not enough. An example * is a EventGenerator where the class deriving from Main specifies an * initial set of partons which should be cascaded and hadronized etc. * * The derived class will be dynamically loaded by the standard * runThePEG program and the static Init() function will * be run. The loaded EventGenerator will then be available in the * static eventGenerator() function. In addition the number of events * requested from the command line will be available from the N() * function. All other command-line arguments will be available from * the arguments() function. * * @see EventGenerator */ class Main: public Base { public: /** * Set the global event generator. */ static void eventGenerator(tEGPtr eg) { theEventGenerator = eg; } /** * Get the global event generator. */ static tEGPtr eventGenerator() { return theEventGenerator; } /** * Set the number of events requested. */ static void N(long n) { theN = n; } /** * Get the number of events requested. */ static long N() { return theN; } /** * Set the command-line arguments. */ static void arguments(const vector & args) { theArguments = args; } /** * Get the command-line arguments. */ static const vector & arguments() { return theArguments; } public: /** * Standard Init function used to initialize the interfaces. */ static void Init() {} private: /** * The global event generator. */ static EGPtr theEventGenerator; /** * The number of events requested. */ static long theN; /** * The command-line arguments. */ static vector theArguments; private: /** * Describe an abstract base class without persistent data. */ static AbstractNoPIOClassDescription
initMain; /** * Private and non-existent assignment operator. */ Main & operator=(const Main &) = delete; }; } namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the base classes * of Main. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of Main. */ typedef int NthBase; }; /** This template specialization informs ThePEG about the name of the * Main class. */ template <> struct ClassTraits
: public ClassTraitsBase
{ /** Return a platform-independent class name */ static string className() { return "ThePEG::Main"; } }; /** @endcond */ } #endif /* THEPEG_Main_H */ diff --git a/Repository/MultiEventGenerator.cc b/Repository/MultiEventGenerator.cc --- a/Repository/MultiEventGenerator.cc +++ b/Repository/MultiEventGenerator.cc @@ -1,347 +1,347 @@ // -*- C++ -*- // // MultiEventGenerator.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MultiEventGenerator class. // #include "MultiEventGenerator.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Command.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Repository/BaseRepository.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Utilities/Rebinder.h" #include "ThePEG/EventRecord/Event.h" #include "ThePEG/Config/algorithm.h" #include "ThePEG/Utilities/StringUtils.h" #include "ThePEG/Handlers/EventHandler.h" #include "ThePEG/Repository/CurrentGenerator.h" #include using namespace ThePEG; MultiEventGenerator::~MultiEventGenerator() {} IBPtr MultiEventGenerator::clone() const { return new_ptr(*this); } IBPtr MultiEventGenerator::fullclone() const { return new_ptr(*this); } string MultiEventGenerator::removeInterface(string cmd) { string noun = StringUtils::car(cmd); IBPtr ip = BaseRepository::getObjectFromNoun(noun); const InterfaceBase * ifb = BaseRepository:: FindInterface(ip, BaseRepository::getInterfaceFromNoun(noun)); string posarg = BaseRepository::getPosArgFromNoun(noun); for ( string::size_type i = 0; i < theObjects.size(); ++i ) { if ( theObjects[i] == ip && theInterfaces[i] == ifb->name() && thePosArgs[i] == posarg ) { theObjects.erase(theObjects.begin() + i); theInterfaces.erase(theInterfaces.begin() + i); thePosArgs.erase(thePosArgs.begin() + i); theValues.erase(theValues.begin() + i); return ""; } } return "No such object/interface defined for this MultiEventGenerator."; } string MultiEventGenerator::addInterface(string cmd) { return addInterface(cmd, false); } string MultiEventGenerator::addRndInterface(string cmd) { return addInterface(cmd, true); } string MultiEventGenerator::addInterface(string cmd, bool rnd) { breakThePEG(); string noun = StringUtils::car(cmd); IBPtr ip = BaseRepository::getObjectFromNoun(noun); const InterfaceBase * ifb = BaseRepository:: FindInterface(ip, BaseRepository::getInterfaceFromNoun(noun)); string posarg = BaseRepository::getPosArgFromNoun(noun); cmd = StringUtils::cdr(cmd); if ( cmd.empty() ) return "Error: empty argument list."; string ret; string oldvalue = ifb->exec(*ip, "get", posarg); StringVector args; try { if ( rnd ) { do { args.push_back(StringUtils::car(cmd)); cmd = StringUtils::cdr(cmd); } while ( !cmd.empty() ); if ( args.size() < 3 ) return "Error: Argument list should be 'N min max mean width'."; int N = atoi(args[0].c_str()); string vmin = args[1]; string vmax = args[2]; string vmean = "0"; if ( args.size() > 3 ) vmean = args[3]; string vwidth = "0"; if ( args.size() > 4 ) vwidth = args[4]; string arg = "RND " + vmin + " " + vmax + " " + vmean + " " + vwidth; args = vector(N, arg); ifb->exec(*ip, "set", vmin); ifb->exec(*ip, "set", vmax); ifb->exec(*ip, "set", posarg + " " + oldvalue); } else { do { args.push_back(StringUtils::car(cmd, ",")); cmd = StringUtils::cdr(cmd, ","); } while ( !cmd.empty() ); for ( string::size_type i = 0; i < args.size(); ++i ) ifb->exec(*ip, "set", args[i]); } } catch (const Exception & e) { e.handle(); ret = "Error: " + e.message(); } ifb->exec(*ip, "set", posarg + " " + oldvalue); if ( !ret.empty() ) return ret; for ( string::size_type i = 0; i < theObjects.size(); ++i ) { if ( theObjects[i] == ip && theInterfaces[i] == ifb->name() && thePosArgs[i] == posarg ) { if ( rnd || theValues[i][0].substr(0,3) == "RND" ) theValues[i] = args; else theValues[i].insert(theValues[i].end(), args.begin(), args.end()); return ""; } } theObjects.push_back(ip); theInterfaces.push_back(ifb->name()); thePosArgs.push_back(posarg); theValues.push_back(args); return ""; } void MultiEventGenerator::addTag(string tag) { if ( tag[0] == '#' ) { string::size_type dash = tag.find('-'); if ( dash == string::npos ) firstSubrun = lastSubrun = atoi(tag.substr(1).c_str()); else { firstSubrun = atoi(tag.substr(1, dash - 1).c_str()); lastSubrun = atoi(tag.substr(dash + 1).c_str()); } } EventGenerator::addTag(tag); } void MultiEventGenerator::doGo(long next, long maxevent, bool tics) { if ( theObjects.empty() || next < 0 ) { EventGenerator::doGo(next, maxevent, tics); return; } if ( maxevent >= 0 ) N(maxevent); vector interfaces; long nargs = 1; for ( string::size_type i = 0; i < theObjects.size(); ++i ) { nargs *= theValues[i].size(); interfaces.push_back(BaseRepository::FindInterface(theObjects[i], theInterfaces[i])); } if ( theSeparateRandom ) { theSeparateRandom->init(); theSeparateRandom->initrun(); const InterfaceBase * ifb = BaseRepository::FindInterface(theSeparateRandom, "Seed"); ifb->exec(*theSeparateRandom, "set", "0"); } openOutputFiles(); string baseName = runName(); if ( tics ) tic(next - 1, nargs*N()); for ( long iargs = 0; iargs < nargs; ++iargs ) { ostringstream subname; subname << baseName << ":" << iargs + 1; runName(subname.str()); string head = heading(iargs, interfaces, baseName); if ( ( firstSubrun > 0 && iargs + 1 < firstSubrun ) || ( lastSubrun > 0 && iargs + 1 > lastSubrun ) ) { if ( theSeparateRandom ) { // This is needed to ensure the same random settings for a // given sub-run irrespectively if previous sub-runs have been // included or not. theSeparateRandom->reset(); theSeparateRandom->init(); theSeparateRandom->initrun(); } continue; } log() << head; out() << head; reset(); for_each(objects(), mem_fn(&InterfacedBase::reset)); init(); initrun(); ieve = next-1; try { while ( shoot() ) { if ( tics ) tic(ieve + iargs*N(), nargs*N()); } } catch ( ... ) { finish(); throw; } finish(); } runName(baseName); finally(); } string MultiEventGenerator:: heading(long iargs, const vector & interfaces, string baseName) const { ostringstream os; long div = 1; if ( iargs > 0 ) os << endl; os << ">> " << baseName << " sub-run number " << iargs + 1 << " using the following interface values:" << endl; for ( string::size_type i = 0; i < theObjects.size(); ++i ) { long iarg = (iargs/div)%theValues[i].size(); string sval = theValues[i][iarg]; if ( theValues[i][iarg].substr(0,3) == "RND" ) { double vmin, vmax, vmean, vwidth; istringstream is(theValues[i][iarg].substr(3)); is >> vmin >> vmax >> vmean >> vwidth; double val = randomArg().rnd(vmin, vmax); if ( vwidth > 0.0 ) do { val = randomArg().rndGauss(vwidth, vmean); } while ( val < vmin || val > vmax ); ostringstream ssv; ssv << val; sval = ssv.str(); } interfaces[i]->exec(*theObjects[i], "set", thePosArgs[i] + " " + sval); os << " set " << theObjects[i]->name() << ":" << theInterfaces[i]; if ( !thePosArgs[i].empty() ) os << "[" << thePosArgs[i] << "]"; os << " " << sval << endl; div *= theValues[i].size(); } os << endl; return os.str(); } void MultiEventGenerator::persistentOutput(PersistentOStream & os) const { os << theObjects << theInterfaces << thePosArgs << theValues << firstSubrun << lastSubrun << theSeparateRandom; } void MultiEventGenerator::persistentInput(PersistentIStream & is, int) { is >> theObjects >> theInterfaces >> thePosArgs >> theValues >> firstSubrun >> lastSubrun >> theSeparateRandom; } IVector MultiEventGenerator::getReferences() { IVector ret = EventGenerator::getReferences(); ret.insert(ret.end(), theObjects.begin(), theObjects.end()); return ret; } void MultiEventGenerator::rebind(const TranslationMap & trans) { for ( string::size_type i = 0; i < theObjects.size(); ++i ) theObjects[i] = trans.translate(theObjects[i]); EventGenerator::rebind(trans); } ClassDescription MultiEventGenerator::initMultiEventGenerator; // Definition of the static class description member. void MultiEventGenerator::Init() { static ClassDocumentation documentation ("The ThePEG::MultiEventGenerator class is derived from the " "ThePEG::EventGenerator and is capable of making " "several runs with a pre-defined set of parameter and switch values."); static Command interfaceAddInterface ("AddInterface", "If arguments are given on the form 'object-name:interface-name arg1, " "arg2, arg3' or 'object-name:vectorinterface-name[pos] arg1, arg2, arg3' " "the generator will be run three times with the corresonding interface of " "the given object set to arg1, arg2, arg3 in each run respectively. If " "another interface with e.g. 4 different arguments, the generator will " "be run 12 times once for each combination of arguments. If called with " "an object and interface wich has already been given in a previous call, " "the new arguments will be added to the previously specified list without " "checking if any argument is doubled.", &MultiEventGenerator::addInterface); static Command interfaceAddRndInterface ("AddRndInterface", "If arguments are given on the form 'object-name:interface-name N min max " "mean width'"" or 'object-name:vectorinterface-name[pos] N min max mean width' " "the generator will be run N times with the corresonding interface of " "the given object set to a random value between min and max according to a " "Gaussian distribution with the given mean and width (if the width is absent " "or zero a flat distribution between min and max will be used instead) . If " "another interface with e.g. 4 different arguments, the generator will " "be run N*4 times once for each combination of arguments and the specified " "interface will get a new random value each time.. If called with " "an object and interface wich has already been given in a previous call to " "AddInterface or AddRndInterface " "the previous call will be ignored.", &MultiEventGenerator::addRndInterface); static Command interfaceRemoveInterface ("RemoveInterface", "If arguments are given on the form 'object-name:interface-name' and " "the same interface and object was previously with an " "AddInterface}, the corresponding arguments are " "removed and the interfaced will be left unchanged during the generation.", &MultiEventGenerator::removeInterface); static Reference interfaceSeparateRandom ("SeparateRandom", "A separate random number generator used for AddRndInterface" " to ensure reproducible sequences of interface values. If null, the standard " "random generator will be used instead.", &MultiEventGenerator::theSeparateRandom, true, false, true, true, false); interfaceAddInterface.rank(10.7); interfaceRemoveInterface.rank(10.5); } diff --git a/Repository/MultiEventGenerator.h b/Repository/MultiEventGenerator.h --- a/Repository/MultiEventGenerator.h +++ b/Repository/MultiEventGenerator.h @@ -1,265 +1,265 @@ // -*- C++ -*- // // MultiEventGenerator.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_MultiEventGenerator_H #define ThePEG_MultiEventGenerator_H // This is the declaration of the MultiEventGenerator class. #include "EventGenerator.h" namespace ThePEG { /** * The MultiEventGenerator class is derived from the * EventGenerator class and is capable of making several runs with * a pre-defined set of parameter and switch values. * * With the Command interface AddInterface set of * parameters for an included object can be specified as eg. * object:interface arg1, arg2, arg3 .... The event * generator will then be run once with the specified objects * interface set to arg1, then once with * arg2 etc. If several AddInterface commands are given * the event generator will be run once for each possible combination * arguments to object interfaces. * * @see EventGenerator * */ class MultiEventGenerator: public EventGenerator { public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ MultiEventGenerator(): firstSubrun(0), lastSubrun(0) {} /** * Destructor. */ virtual ~MultiEventGenerator(); //@} /** * Append a tag to the run name. Derived classes may put special * meaning to the tags. In this case a tag on the form #n will * select only subrun number n, while #n-m will select subruns n * through m. */ virtual void addTag(string tag); protected: /** @name Public virtual functions required by the base class. */ //@{ /** * Run this EventGenerator session. Is called from * EventGenerator::go(long,long,bool). */ virtual void doGo(long next, long maxevent, bool tics); //@} /** @name Functions used by the Command interfaces to set up the different parameters of the runs. */ //@{ /** * Used to add an interface of an object which should be used with a * set of different values. The argument should be given as * "object:interface arg1, arg2, ..." */ string addInterface(string); /** * Used to add an interface of an object a random value each * run. The argument should be given as "object:interface N min max * mean width" */ string addRndInterface(string); /** * Helper function for addInterface(string) and addRndInterface(string). */ string addInterface(string, bool rnd); /** * Used to remove an interface of an object which should be used * with a set of different values. The argument should be given as * "object:interface arg1, arg2, ..." */ string removeInterface(string); //@} /** * return a header for this sub-run. */ string heading(long, const vector &, string) const; /** * A separate random number generator to be used for generating * random parameter values (to ensure reproducable sequences). */ RandomGenerator & randomArg() const { return theSeparateRandom? *theSeparateRandom: random(); } 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(); 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. */ //@{ /** * 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(); //@} private: /** A vector of character strings. */ typedef vector StringVector; /** * The objects for which there are different interface settings. */ IVector theObjects; /** * The interfaces to be modified for the corresponding objects in * theObjects. */ StringVector theInterfaces; /** * If the there are positional arguments to theInterfaces these are * specified here. */ StringVector thePosArgs; /** * The arguments to be used for each of theInterfaces. */ vector theValues; /** * If non zero, the first subrun to be considered. */ int firstSubrun; /** * If non zero, the last subrun to be considered. */ int lastSubrun; /** * A separate random number generator to be used for generating * random parameter values (to ensure reproducable sequences). */ RanGenPtr theSeparateRandom; private: /** * Describe a concrete class with persistent data. */ static ClassDescription initMultiEventGenerator; /** * Private and non-existent assignment operator. */ MultiEventGenerator & operator=(const MultiEventGenerator &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the base classes * of MultiEventGenerator. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of MultiEventGenerator. */ typedef EventGenerator NthBase; }; /** This template specialization informs ThePEG about the name of the * MultiEventGenerator 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::MultiEventGenerator"; } /** Return the name of the shared library be loaded to get access to * the MultiEventGenerator class and every other class it uses * (except the base class). */ static string library() { return "MultiEventGenerator.so"; } }; /** @endcond */ } #endif /* ThePEG_MultiEventGenerator_H */ diff --git a/Repository/RandomGenerator.cc b/Repository/RandomGenerator.cc --- a/Repository/RandomGenerator.cc +++ b/Repository/RandomGenerator.cc @@ -1,184 +1,184 @@ // -*- C++ -*- // // RandomGenerator.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the RandomGenerator class. // #include "RandomGenerator.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "gsl/gsl_randist.h" extern "C" { typedef struct { ThePEG::RandomGenerator * r; } thepeg_random_state_t; void thepeg_random_set(void *, unsigned long int) {} double thepeg_random_get_double(void * s) { return static_cast(s)->r->rnd(); } unsigned long int thepeg_random_get(void * s) { return static_cast(std::numeric_limits::max()*thepeg_random_get_double(s)); } static const gsl_rng_type thepeg_random_type = {"thepeg_random", (unsigned long int)std::numeric_limits::max(), 0, sizeof(thepeg_random_state_t), &thepeg_random_set, &thepeg_random_get, &thepeg_random_get_double}; const gsl_rng_type *gsl_rng_thepeg_random = &thepeg_random_type; } using namespace ThePEG; RandomGenerator::RandomGenerator() : theNumbers(1000), theSize(1000), theSeed(-1), savedGauss(0.0), gaussSaved(false) { nextNumber = theNumbers.end(); gsl = gsl_rng_alloc(gsl_rng_thepeg_random); static_cast(gsl->state)->r = this; } RandomGenerator::RandomGenerator(const RandomGenerator & rg) : Interfaced(rg), theNumbers(rg.theNumbers), theSize(rg.theSize), theSeed(rg.theSeed), savedGauss(rg.savedGauss), gaussSaved(rg.gaussSaved) { nextNumber = theNumbers.begin() + ( RndVector::const_iterator(rg.nextNumber) - rg.theNumbers.begin() ); gsl = gsl_rng_alloc(gsl_rng_thepeg_random); static_cast(gsl->state)->r = this; } RandomGenerator::~RandomGenerator() { gsl_rng_free(gsl); } void RandomGenerator::doinit() { if ( theSeed != 0 ) setSeed(theSeed); flush(); } void RandomGenerator::setSize(size_type newSize) { RndVector newNumbers(newSize); RndVector::iterator nextNew = newNumbers.end() - min( int(theNumbers.end() - nextNumber), int(newSize) ); for ( RndVector::iterator i = nextNew; i != newNumbers.end(); ++i ) *i = *nextNumber++; RndVector::difference_type pos = nextNew - newNumbers.begin(); theNumbers.swap(newNumbers); nextNumber = theNumbers.begin() + pos; } bool RandomGenerator::prndbool(double p) { if ( p >= 1.0 ) return true; if ( p <= 0.0 ) return false; double r = rnd(); if ( r < p ) { push_back(r/p); return true; } else { push_back((r - p)/(1.0 - p)); return false; } } int RandomGenerator::rndsign(double p1, double p2, double p3) { double sum = p1 + p2 + p3; double r = rnd()*sum; if ( r < p1 ) return -1; else if ( r < p1 + p2 ) return 0; else return 1; } int RandomGenerator::prndsign(double p1, double p2, double p3) { double sum = p1 + p2 + p3; double r = rnd()*sum; if ( r < p1 ) { push_back(r/p1); return -1; } else if ( r < p1 + p2 ) { push_back((r - p1)/p2); return 0; } else { push_back((r - p1 - p2)/p3); return 1; } } int RandomGenerator::rnd4(double p0, double p1, double p2, double p3) { double sum = p0 + p1 + p2 + p3; double r = rnd()*sum; if ( r < p0 ) return 0; else if ( r < p0 + p1 ) return 1; else if ( r < p0 + p1 + p2 ) return 2; else return 3; } int RandomGenerator::rnd5(double p0, double p1, double p2, double p3, double p4) { double sum = p0 + p1 + p2 + p3 + p4; double r = rnd()*sum; if ( r < p0 ) return 0; else if ( r < p0 + p1 ) return 1; else if ( r < p0 + p1 + p2 ) return 2; else if ( r < p0 + p1 + p2 + p3 ) return 3; else return 4; } long RandomGenerator::rndPoisson(double mean) { return gsl_ran_poisson(gsl, mean); } void RandomGenerator::persistentOutput(PersistentOStream & os) const { os << theNumbers << RndVector::const_iterator(nextNumber) - theNumbers.begin() << theSize << theSeed << savedGauss << gaussSaved; } void RandomGenerator::persistentInput(PersistentIStream & is, int) { RndVector::difference_type pos; is >> theNumbers >> pos >> theSize >> theSeed >> savedGauss >> gaussSaved; nextNumber = theNumbers.begin() + pos; } ClassDescription RandomGenerator::initRandomGenerator; void RandomGenerator::Init() { static ClassDocumentation documentation ("There is no documentation for the ThePEG::RandomGenerator class"); static Parameter interfaceSize ("CacheSize", "The Random numbers are generated in chunks of this size.", &RandomGenerator::theSize, 1000, 10, 100000, true, false, true, &RandomGenerator::setSize); static Parameter interfaceSeed ("Seed", "The seed with which this random generator is initialized. " "If set to -1, the default build-in seed will be used. If set to zero, no seed will " "be set.", &RandomGenerator::theSeed, -1, -1, 100000000, true, false, false); interfaceSeed.setHasDefault(false); interfaceSize.rank(10); interfaceSeed.rank(9); } diff --git a/Repository/RandomGenerator.h b/Repository/RandomGenerator.h --- a/Repository/RandomGenerator.h +++ b/Repository/RandomGenerator.h @@ -1,497 +1,497 @@ // -*- C++ -*- // // RandomGenerator.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_RandomGenerator_H #define ThePEG_RandomGenerator_H // This is the declaration of the RandomGenerator class. #include "ThePEG/Config/ThePEG.h" #include "ThePEG/Interface/Interfaced.h" #include "gsl/gsl_rng.h" namespace ThePEG { /** * RandomGenerator is an interface to the CLHEP::RandomEngine * classes. To avoid excessive virtual function calls, the * RandomGenerator caches random numbers generated by the engine which * are then retrieved by the non-virtual inlined rnd() method. * * Sub-classes of RandomGenerator should be used to * implement a particular random engine. * * RandomGenerator only provides a flat distribution between 0 and * 1. Any other distribution can be achieved using the CLHEP random * classes using the engine returned from the randomGenerator() * method. * * @see \ref RandomGeneratorInterfaces "The interfaces" * defined for RandomGenerator. * @see UseRandom */ class RandomGenerator: public Interfaced { public: /** A vector of doubles. */ typedef vector RndVector; /** The size_type of RndVector. */ typedef RndVector::size_type size_type; public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ RandomGenerator(); /** * Copy-constructor. */ RandomGenerator(const RandomGenerator &); /** * Destructor. */ virtual ~RandomGenerator(); //@} /** * Reset the underlying random engine with the given \a seed. If the * \a seed is set to -1 a standard seed will be used. */ virtual void setSeed(long seed) = 0; /** @name Functions to return random numbers. */ //@{ /** * Return a (possibly cached) flat random number in the interval * \f$]0,1[\f$. */ double rnd() { if ( nextNumber == theNumbers.end() ) fill(); return *nextNumber++; } /** * Return a flat random number in the interval * \f$]0,b[\f$. */ template Unit rnd(Unit b) { return b*rnd(); } /** * Return a flat random number in the interval * \f$]a,b[\f$. */ template Unit rnd(Unit a, Unit b) { return a + rnd(b - a); } /** * Return \a n flat random number in the interval * \f$]0,1[\f$. */ RndVector rndvec(int n) { RndVector ret(n); for ( int i = 0; i < n; ++i ) ret[i] = rnd(); return ret; } /** * Return a (possibly cached) flat random number in the interval * \f$]0,1[\f$. */ double operator()() { return rnd(); } /** * Return a (possibly cached) flat integer random number in the * interval \f$[0,N[\f$. * Function was introduced since otherwise operator()() is used if a double is given * resulting in a \f$]0,1[\f$ distribution. */ double operator()(double N) { return double(rnd() * N); } /** * Return a (possibly cached) flat integer random number in the * interval \f$[0,N[\f$. */ long operator()(long N) { return long(rnd() * N); } /** * Return a true with probability \a p. Uses rnd(). */ bool rndbool(double p = 0.5) { return rnd() < p; } /** * Return a true with probability \a p. Uses rnd(). Also uses * push_back(double). */ bool prndbool(double p = 0.5); /** * Return a true with probability \a p1/(\a p1+\a p2). Uses * rnd(). */ bool rndbool(double p1, double p2) { return rndbool(p1/(p1 + p2)); } /** * Return a true with probability \a p1/(\a p1+\a p2). Uses * rnd(). Also uses push_back(double). */ bool prndbool(double p1, double p2) { return prndbool(p1/(p1 + p2)); } /** * Return -1, 0, or 1 with relative probabilities \a p1, \a p2, \a * p3. Uses rnd(). */ int rndsign(double p1, double p2, double p3); /** * Return -1, 0, or 1 with relative probabilities \a p1, \a p2, \a * p3. Uses rnd(). Also uses push_back(double). */ int prndsign(double p1, double p2, double p3); /** * Return an integer \f$i\f$ with probability p\f$i\f$/(\a p0+\a * p1). Uses rnd(). */ int rnd2(double p0, double p1) { return rndbool(p0, p1)? 0: 1; } /** * Return an integer \f$i\f$ with probability p\f$i\f$/(\a p0+\a * p1+\a p2). Uses rnd(). */ int rnd3(double p0, double p1, double p2) { return 1 + rndsign(p0, p1, p2); } /** * Return an integer/ \f$i\f$ with probability p\f$i\f$(\a p0+\a * p1+\a p2+\a p3). Uses rnd(). */ int rnd4(double p0, double p1, double p2, double p3); /** * Return an integer/ \f$i\f$ with probability p\f$i\f$(\a p0+\a * p1+\a p2+\a p3+\a p4). Uses rnd(). */ int rnd5(double p0, double p1, double p2, double p3, double p4); /** * Return a number between zero and infinity, distributed according * to \f$e^-x\f$. */ double rndExp() { return -log(rnd()); } /** * Return a number between zero and infinity, distributed according * to \f$e^-{x/\mu}\f$ where \f$\mu\f$ is the \a mean value. */ template Unit rndExp(Unit mean) { return mean*rndExp(); } /** * Return two numbers distributed according to a Gaussian distribution * with zero mean and unit variance. * * @param[out] First random number * @param[out] Second random number */ void rndGaussTwoNumbers(double & randomNumberOne, double & randomNumberTwo) { double r = sqrt(-2.0*log(rnd())); double phi = rnd()*2.0*Constants::pi; randomNumberOne = r*sin(phi); randomNumberTwo = r*cos(phi); } /** * Return a number distributed according to a Gaussian distribution * with zero mean and unit variance. * A second number is cached and returned the next time. * This function calls the rndGaussTwoNumbers function which returns two numbers at once. */ double rndGauss() { if ( gaussSaved ) { gaussSaved = false; return savedGauss; } double randomNumberOne, randomNumberTwo; rndGaussTwoNumbers(randomNumberOne, randomNumberTwo); savedGauss = randomNumberTwo; gaussSaved = true; return randomNumberOne; } /** * Return a number distributed according to a Gaussian distribution * with a given standard deviation, \a sigma, and a given \a mean. */ template Unit rndGauss(Unit sigma, Unit mean = Unit()) { return mean + sigma*rndGauss(); } /** * Return two numbers distributed according to a Gaussian distribution * with a given standard deviation, \a sigma, and a given \a mean. */ template void rndGaussTwoNumbers(Unit & randomNumberOne, Unit & randomNumberTwo, Unit sigma, Unit mean = Unit()) { double r1,r2; rndGaussTwoNumbers(r1,r2); randomNumberOne = mean + sigma * r1; randomNumberTwo = mean + sigma * r2; } /** * Return a positive number distributed according to a * non-relativistic Breit-Wigner with a given width, \a gamma, and a * given \a mean. */ template Unit rndBW(Unit mean, Unit gamma) { if ( gamma <= Unit() ) return mean; return mean + 0.5*gamma*tan(rnd(atan(-2.0*mean/gamma), Constants::pi/2)); } /** * Return a positive number distributed according to a * non-relativistic Breit-Wigner with a given width, \a gamma, and a * given \a mean. The distribution is cut-off so that the number is * between \a mean - \a cut and \a mean + \a cut */ template Unit rndBW(Unit mean, Unit gamma, Unit cut) { if ( gamma <= Unit() || cut <= Unit() ) return mean; return mean + 0.5*gamma*tan(rnd(atan(-2.0*min(mean,cut)/gamma), atan(2.0*cut/gamma))); } /** * Return a positive number distributed according to a relativistic * Breit-Wigner with a given width, \a gamma, and a given \a mean. */ template Unit rndRelBW(Unit mean, Unit gamma) { if ( gamma <= Unit() ) return mean; return sqrt(sqr(mean) + mean*gamma*tan(rnd(atan(-mean/gamma), Constants::pi/2))); } /** * Return a positive number distributed according to a relativistic * Breit-Wigner with a given width, \a gamma, and a given \a * mean. The distribution is cut-off so that the number is between * \a mean - \a cut and \a mean + \a cut */ template Unit rndRelBW(Unit mean, Unit gamma, Unit cut) { if ( gamma <= Unit() || cut <= Unit() ) return mean; double minarg = cut > mean? -mean/gamma: (sqr(mean - cut) - sqr(mean))/(gamma*mean); double maxarg = (sqr(mean + cut) - sqr(mean))/(mean*gamma); return sqrt(sqr(mean) + mean*gamma*tan(rnd(atan(minarg), atan(maxarg)))); } /** * Return a non-negative number generated according to a Poissonian * distribution with a given \a mean. Warning: the method * implemented is very slow for large mean and large return * values. For this reason the maximum return value is given by \a * nmax. */ long rndPoisson(double mean); //@} /** @name Access the cached random numbers from the underlying engine. */ //@{ /** * Give back a partly unused random number. This is typically used * when generating integral random numbers. In eg. rndbool(double p) * a random number r is drawn and if it is less than * p true is returned, but r is still a * good random number in the interval ]0,p[. Hence * r/p is still a good random number in the interval * ]0,1[ and this is then pushed back into the cache * and is used by the next call to rnd(). Note that the resulting * random number is of lesser quality, and successive calls to * push_back() should be avoided. To ensure a highest quality random * number random number in the next call to rnd(), pop_back() should * be used. */ void push_back(double r) { if ( r > 0.0 && r < 1.0 && nextNumber != theNumbers.begin() ) *--nextNumber = r; } /** * Discard the next random number in the cache. */ void pop_back() { if ( nextNumber != theNumbers.end() ) ++nextNumber; } /** * Discard all random numbers in the cache. Typically used after the * internal random engine has been reinitialized for some reason. */ void flush() { nextNumber = theNumbers.end(); gaussSaved = false; } /** * Generate n random numbers between 0 and 1 and put them in the * output iterator. */ template void rnd(OutputIterator o, size_type n) { while ( n-- ) *o++ = rnd(); } //@} protected: /** * Initializes this random generator. This should be done first of * all before the initialization of any other object associated with * an event generator. */ virtual void doinit(); public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interface. */ static void Init(); /** * Return a gsl_rng interface to this random generator. */ gsl_rng * getGslInterface() { return gsl; } protected: /** * Utility function for the interface. */ void setSize(size_type newSize); /** * Fill the cache with random numbers. */ virtual void fill() = 0; /** * A vector of cached numbers. */ RndVector theNumbers; /** * Iterator pointing to the next number to be extracted */ RndVector::iterator nextNumber; /** * The size of the cache. */ size_type theSize; /** * The seed to initialize the random generator with. */ long theSeed; /** * A saved Gaussian random number. */ mutable double savedGauss; /** * Indicate the precense of a saved Gaussian random number. */ mutable bool gaussSaved; /** * A pinter to a gsl_rng interface to this generator. */ gsl_rng * gsl; private: /** * Describe a concrete class with persistent data. Note that the * class should in principle be abstract. */ static ClassDescription initRandomGenerator; /** * Private and non-existent assignment operator. */ RandomGenerator & operator=(const RandomGenerator &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the base classes * of RandomGenerator. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of RandomGenerator. */ typedef Interfaced NthBase; }; /** This template specialization informs ThePEG about the name of the * RandomGenerator class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "ThePEG::RandomGenerator"; } /** This class should in principle be abstract, therefore the create() method will throw a std::logic_error if called. */ static TPtr create() { throw std::logic_error("Tried to instantiate abstract class" "'Pythis7::RandomGenerator'"); } }; /** @endcond */ } #endif /* ThePEG_RandomGenerator_H */ diff --git a/Repository/Repository.cc b/Repository/Repository.cc --- a/Repository/Repository.cc +++ b/Repository/Repository.cc @@ -1,1131 +1,1131 @@ // -*- C++ -*- // // Repository.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the Repository class. // // macro is passed in from -D compile flag #ifndef THEPEG_PKGLIBDIR #error Makefile.am needs to define THEPEG_PKGLIBDIR #endif #include "Repository.h" #include "ThePEG/Utilities/Rebinder.h" #include "ThePEG/Handlers/EventHandler.h" #include "ThePEG/PDT/DecayMode.h" #include "ThePEG/Repository/Strategy.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Utilities/Debug.h" #include "ThePEG/Config/algorithm.h" #include "ThePEG/Utilities/DynamicLoader.h" #include "ThePEG/Utilities/StringUtils.h" #include #include #include // readline options taken from // http://autoconf-archive.cryp.to/vl_lib_readline.html // Copyright © 2008 Ville Laurikari // Copying and distribution of this file, with or without // modification, are permitted in any medium without royalty provided // the copyright notice and this notice are preserved. #ifdef HAVE_LIBREADLINE # if defined(HAVE_READLINE_READLINE_H) # include # elif defined(HAVE_READLINE_H) # include # else extern "C" char *readline (const char *); # endif #endif #ifdef HAVE_READLINE_HISTORY # if defined(HAVE_READLINE_HISTORY_H) # include # elif defined(HAVE_HISTORY_H) # include # else extern "C" void add_history (const char *); # endif #endif using namespace ThePEG; ParticleMap & Repository::defaultParticles() { static ParticleMap theMap; return theMap; } ParticleDataSet & Repository::particles() { static ParticleDataSet theSet; return theSet; } MatcherSet & Repository::matchers() { static MatcherSet theSet; return theSet; } Repository::GeneratorMap & Repository::generators() { static GeneratorMap theMap;; return theMap; } string & Repository::currentFileName() { static string theCurrentFileName; return theCurrentFileName; } int & Repository::exitOnError() { static int exitonerror = 0; return exitonerror; } void Repository::cleanup() { generators().clear(); } void Repository::Register(IBPtr ip) { BaseRepository::Register(ip); registerParticle(dynamic_ptr_cast(ip)); registerMatcher(dynamic_ptr_cast(ip)); } void Repository::Register(IBPtr ip, string newName) { DirectoryAppend(newName); BaseRepository::Register(ip, newName); registerParticle(dynamic_ptr_cast(ip)); registerMatcher(dynamic_ptr_cast(ip)); } void Repository::registerParticle(tPDPtr pd) { if ( !pd ) return; if ( !member(particles(), pd) ) { particles().insert(pd); CreateDirectory(pd->fullName()); } if ( pd->id() == 0 ) return; if ( !member(defaultParticles(), pd->id()) ) defaultParticles()[pd->id()] = pd; for ( MatcherSet::iterator it = matchers().begin(); it != matchers().end(); ++it) (*it)->addPIfMatch(pd); } void Repository::registerMatcher(tPMPtr pm) { if ( !pm || member(matchers(), pm) ) return; pm->addPIfMatchFrom(particles()); for ( MatcherSet::iterator it = matchers().begin(); it != matchers().end(); ++it) { (*it)->addMIfMatch(pm); pm->addMIfMatch(*it); } matchers().insert(pm); } tPDPtr Repository::findParticle(string name) { tPDPtr pd; string path = name; DirectoryAppend(path); pd = dynamic_ptr_cast(GetPointer(path)); if ( pd ) return pd; for ( ParticleMap::iterator pit = defaultParticles().begin(); pit != defaultParticles().end(); ++pit ) if ( pit->second->PDGName() == name ) return pit->second; for ( ParticleDataSet::iterator pit = particles().begin(); pit != particles().end(); ++pit ) if ( (**pit).PDGName() == name ) return *pit; return pd; } tPMPtr Repository::findMatcher(string name) { for ( MatcherSet::iterator mit = matchers().begin(); mit != matchers().end(); ++mit ) if ( name == (**mit).name() ) return *mit; return tPMPtr(); } void Repository::saveRun(string EGname, string name, string filename) { EGPtr eg = BaseRepository::GetObject(EGname); EGPtr run = makeRun(eg, name); PersistentOStream os(filename, globalLibraries()); if ( ThePEG_DEBUG_ITEM(3) ) clog() << "Saving event generator '" << name << "'... " << flush; os << run; if ( ThePEG_DEBUG_ITEM(3) ) clog() << "done" << endl; } EGPtr Repository::makeRun(tEGPtr eg, string name) { // Clone all objects relevant for the EventGenerator. This is // the EventGenerator itself, all particles and all particle // matchers. 'localObject' is the set of all object refered to by // the generator particles and matcher and in the end these are // cloned as well. // Clone all Particle matchers if ( ThePEG_DEBUG_ITEM(3) ) clog() << "Making event generator '" << name << "':" << endl << "Updating all objects... " << flush; if ( ThePEG_DEBUG_ITEM(3) ) clog() << "done\nCloning matchers and particles... " << flush; MatcherSet localMatchers; ObjectSet localObjects; ObjectSet clonedObjects; TranslationMap trans; for ( MatcherSet::iterator mit = matchers().begin(); mit != matchers().end(); ++mit ) { PMPtr pm = clone(**mit); pm->clear(); trans[*mit] = pm; localMatchers.insert(pm); clonedObjects.insert(pm); localObjects.insert(*mit); addReferences(*mit, localObjects); } // Clone the particles. But only the ones which should be // used. First select the localParticles of the EventGenerator, then // add particles from the strategy of the EventGenerator which have // not already been selected. Finally add particles from the global // default if no default directories has been specified in the // strategy which have not already been selected. PDVector allParticles; for ( ParticleMap::const_iterator pit = eg->localParticles().begin(); pit != eg->localParticles().end(); ++pit ) allParticles.push_back(pit->second); if ( eg->strategy() ) { tcStrategyPtr strat = eg->strategy(); for ( ParticleMap::const_iterator pit = strat->particles().begin(); pit != strat->particles().end(); ++pit ) allParticles.push_back(pit->second); vector pdirs; if ( eg->strategy()->localParticlesDir().length() ) pdirs.push_back(eg->strategy()->localParticlesDir()); pdirs.insert(pdirs.end(), eg->strategy()->defaultParticlesDirs().begin(), eg->strategy()->defaultParticlesDirs().end()); for ( int i = 0, N = pdirs.size(); i < N; ++i ) { string dir = pdirs[i]; for ( ParticleDataSet::iterator pit = particles().begin(); pit != particles().end(); ++pit ) if ( (**pit).fullName().substr(0, dir.length()) == dir ) allParticles.push_back(*pit); } } if ( !eg->strategy() || eg->strategy()->defaultParticlesDirs().empty() ) for ( ParticleMap::iterator pit = defaultParticles().begin(); pit != defaultParticles().end(); ++pit ) allParticles.push_back(pit->second); for ( ParticleDataSet::iterator pit = particles().begin(); pit != particles().end(); ++pit ) allParticles.push_back(*pit); ParticleMap localParticles; set pdgnames; for ( PDVector::iterator pit = allParticles.begin(); pit != allParticles.end(); ++pit ) { ParticleMap::iterator it = localParticles.find((**pit).id()); if ( it == localParticles.end() ) { PDPtr pd = clone(**pit); trans[*pit] = pd; localParticles[pd->id()] = pd; clonedObjects.insert(pd); localObjects.insert(*pit); addReferences(*pit, localObjects); if ( pdgnames.find(pd->PDGName()) != pdgnames.end() ) std::cerr << "Using duplicate PDGName " << pd->PDGName() << " for a new particle.\n This can cause problems and is not " << "recommended.\n If this second particle is a new particle " << "in a BSM Model we recommend you change the name of the particle.\n"; else pdgnames.insert(pd->PDGName()); } else { trans[*pit] = it->second; } } if ( ThePEG_DEBUG_ITEM(3) ) clog() << "done\nCloning other objects... " << flush; // Clone the OldEventGenerator object to be used: localObjects.insert(eg); addReferences(eg, localObjects); EGPtr egrun = clone(*eg); clonedObjects.insert(egrun); trans[eg] = egrun; for ( ObjectSet::iterator it = localObjects.begin(); it != localObjects.end(); ++it ) { if ( member(trans.map(), *it) ) continue; IBPtr ip = clone(**it); trans[*it] = ip; clonedObjects.insert(ip); } if ( ThePEG_DEBUG_ITEM(3) ) clog() << "done\nRebind references... " << flush; IVector defaults; trans.translate(inserter(defaults), eg->defaultObjects().begin(), eg->defaultObjects().end()); if ( eg->strategy() ) trans.translate(inserter(defaults), eg->strategy()->defaultObjects().begin(), eg->strategy()->defaultObjects().end()); for ( ObjectSet::iterator it = clonedObjects.begin(); it != clonedObjects.end(); ++it ) { dynamic_cast(**it).theGenerator = egrun; rebind(**it, trans, defaults); } // Now, dependencies may have changed, so we do a final round of // updates. if ( ThePEG_DEBUG_ITEM(3) ) clog() << "done\nUpdating cloned objects... " << flush; if ( ThePEG_DEBUG_ITEM(3) ) clog() << "done\nInitializing... " << flush; clonedObjects.erase(egrun); egrun->setup(name, clonedObjects, localParticles, localMatchers); if ( ThePEG_DEBUG_ITEM(3) ) clog() << "done" << endl; generators()[name] = egrun; return egrun; } PDPtr Repository::defaultParticle(PID id) { ParticleMap::iterator pit = defaultParticles().find(id); return pit == defaultParticles().end()? PDPtr(): pit->second; } void Repository::defaultParticle(tPDPtr pdp) { if ( pdp ) defaultParticles()[pdp->id()] = pdp; } struct ParticleOrdering { bool operator()(tcPDPtr p1, tcPDPtr p2) const { return abs(p1->id()) > abs(p2->id()) || ( abs(p1->id()) == abs(p2->id()) && p1->id() > p2->id() ) || ( p1->id() == p2->id() && p1->fullName() > p2->fullName() ); } }; struct MatcherOrdering { bool operator()(tcPMPtr m1, tcPMPtr m2) const { return m1->name() < m2->name() || ( m1->name() == m2->name() && m1->fullName() < m2->fullName() ); } }; struct InterfaceOrdering { bool operator()(tcIBPtr i1, tcIBPtr i2) const { return i1->fullName() < i2->fullName(); } }; void Repository::save(string filename) { if ( ThePEG_DEBUG_ITEM(3) ) clog() << "saving '" << filename << "'... " << flush; PersistentOStream os(filename, globalLibraries()); set part(particles().begin(), particles().end()); set match(matchers().begin(), matchers().end()); os << objects().size(); for ( ObjectMap::iterator it = objects().begin(); it != objects().end(); ++it ) os << it->second; os << defaultParticles() << part << match << generators() << directories() << directoryStack() << globalLibraries() << readDirs(); if ( ThePEG_DEBUG_ITEM(3) ) clog() << "(" << objects().size() << " objects in " << directories().size() << " directories) done" << endl; } string Repository::load(string filename) { if ( ThePEG_DEBUG_ITEM(3) ) clog() << "loading '" << filename << "'... " << flush; currentFileName() = filename; PersistentIStream * is = new PersistentIStream(filename); if ( !*is ) { delete is; // macro is passed in from -D compile flag string fullpath = string(THEPEG_PKGLIBDIR) + '/' + filename; is = new PersistentIStream(fullpath); if ( !*is ) { delete is; return "Error: Could not find repository '" + filename + "'."; } } *is >> allObjects() >> defaultParticles() >> particles() >> matchers() >> generators() >> directories() >> directoryStack() >> globalLibraries() >> readDirs(); delete is; objects().clear(); for ( ObjectSet::iterator it = allObjects().begin(); it != allObjects().end(); ++it ) objects()[(**it).fullName()] = *it; if ( ThePEG_DEBUG_ITEM(3) ) clog() << "(" << objects().size() << " objects in " << directories().size() << " directories) done\nUpdating... " << flush; BaseRepository::resetAll(allObjects()); BaseRepository::update(); if ( ThePEG_DEBUG_ITEM(3) ) clog() << "done" << endl; return ""; } void Repository::stats(ostream & os) { os << "number of objects: " << setw(6) << objects().size() << endl; os << "number of objects (all): " << setw(6) << allObjects().size() << endl; os << "number of particles: " << setw(6) << particles().size() << endl; os << "number of matchers: " << setw(6) << matchers().size() << endl; } string Repository::read(string filename, ostream & os) { ifstream is; string file = filename; if ( file[0] == '/' ) { if ( ThePEG_DEBUG_LEVEL > 1 ) os << "(= trying to open " << file << " =)" << endl; is.open(file.c_str()); } else { vector dirs(readDirs().rbegin(), readDirs().rend()); dirs.push_back(currentReadDirStack().top()); if ( ThePEG_DEBUG_LEVEL > 1 ) { os << "(= search path order =)\n(== "; std::copy(dirs.rbegin(), dirs.rend(), std::ostream_iterator(os, " ==)\n(== ")); os << ")" << endl; } while ( dirs.size() ) { string dir = dirs.back(); if ( dir != "" && dir[dir.length() -1] != '/' ) dir += '/'; file = dir + filename; is.clear(); if ( ThePEG_DEBUG_LEVEL > 1 ) os << "(= trying to open " << file << " =)" << endl; is.open(file.c_str()); if ( is ) break; if ( ThePEG_DEBUG_LEVEL > 1 ) os << "(= no, try next search path =)" << endl; dirs.pop_back(); } } if ( !is ) { return "Error: Could not find input file '" + filename + "'"; } if ( ThePEG_DEBUG_LEVEL > 1 ) os << "(= yes =)" << endl; const string dir = StringUtils::dirname(file); if ( ThePEG_DEBUG_LEVEL > 1 ) os << "(= pushing <" << dir << "> to stack =)" << endl; currentReadDirStack().push(dir); try { Repository::read(is, os); if ( ThePEG_DEBUG_LEVEL > 1 ) os << "(= popping <" << currentReadDirStack().top() << "> from stack =)" << endl; currentReadDirStack().pop(); } catch ( ... ) { if ( ThePEG_DEBUG_LEVEL > 1 ) os << "(= popping <" << currentReadDirStack().top() << "> from stack =)" << endl; currentReadDirStack().pop(); throw; } return ""; } string Repository:: modifyEventGenerator(EventGenerator & eg, string filename, ostream & os, bool initOnly) { ObjectSet objs = eg.objects(); objs.insert(&eg); for ( ObjectSet::iterator it = objs.begin(); it != objs.end(); ++it ) { string name = (**it).fullName(); if ( name.rfind('/') != string::npos ) CreateDirectory(name.substr(0, name.rfind('/') + 1)); objects()[name] = *it; allObjects().insert(*it); } string msg = read(filename, os); if ( !msg.empty() ) return msg; for_each(objs, mem_fn(&InterfacedBase::reset)); eg.initialize(initOnly); if ( !generators().empty() ) msg += "Warning: new generators were initialized while modifying " + eg.fullName() + ".\n"; return msg; } void Repository::resetEventGenerator(EventGenerator & eg) { ObjectSet objs = eg.objects(); objs.insert(&eg); for ( ObjectSet::iterator it = objs.begin(); it != objs.end(); ++it ) { string name = (**it).fullName(); if ( name.rfind('/') != string::npos ) CreateDirectory(name.substr(0, name.rfind('/') + 1)); objects()[name] = *it; allObjects().insert(*it); } for_each(objs, mem_fn(&InterfacedBase::reset)); eg.initialize(true); } void Repository::execAndCheckReply(string line, ostream & os) { string reply = exec(line, os); if ( reply.size() ) os << reply; if ( reply.size() && reply[reply.size()-1] != '\n' ) os << endl; if ( exitOnError() && reply.size() >= 7 && reply.substr(0, 7) == "Error: " ) exit(exitOnError()); } void Repository::read(istream & is, ostream & os, string prompt) { #ifdef HAVE_LIBREADLINE if ( &is == &std::cin ) { char * line_read = 0; do { if ( line_read ) { free(line_read); line_read = 0; } line_read = readline(prompt.c_str()); if ( line_read && *line_read ) { string line = line_read; while ( !line.empty() && line[line.size() - 1] == '\\' ) { line[line.size() - 1] = ' '; char * cont_read = readline("... "); if ( cont_read ) { line += cont_read; free(cont_read); } } if ( prompt.empty() && ThePEG_DEBUG_LEVEL > 0 ) os << "(" << line << ")" << endl; #ifdef HAVE_READLINE_HISTORY add_history(line.c_str()); #endif // HAVE_READLINE_HISTORY execAndCheckReply(line, os); } } while ( line_read ); } else { #endif // HAVE_LIBREADLINE string line; if ( prompt.size() ) os << prompt; while ( getline(is, line) ) { while ( !line.empty() && line[line.size() - 1] == '\\' ) { line[line.size() - 1] = ' '; string cont; if ( prompt.size() ) os << "... "; getline(is, cont); line += cont; } if ( prompt.empty() && ThePEG_DEBUG_LEVEL > 0 ) os << "(" << line << ")" << endl; execAndCheckReply(line, os); if ( prompt.size() ) os << prompt; } #ifdef HAVE_LIBREADLINE } #endif if ( prompt.size() ) os << endl; } string Repository::copyParticle(tPDPtr p, string newname) { DirectoryAppend(newname); string newdir = newname.substr(0, newname.rfind('/')+1); newname =newname.substr(newname.rfind('/')+1); if ( newname.empty() ) newname = p->name(); if ( GetPointer(newdir + newname) ) return "Error: Cannot create particle " + newdir + newname + ". Object already exists."; if ( p->CC() && GetPointer(newdir + p->CC()->name()) ) return "Error: Cannot create anti-particle " + newdir + newname + ". Object already exists."; PDPtr pd = p->pdclone(); Register(pd, newdir + newname); pd->theDecaySelector.clear(); pd->theDecayModes.clear(); pd->isStable = true; if ( p->CC() ) { PDPtr apd = p->CC()->pdclone(); Register(apd, newdir + apd->name()); apd->theDecaySelector.clear(); apd->theDecayModes.clear(); apd->isStable = true; pd->theAntiPartner = apd; apd->theAntiPartner = pd; pd->syncAnti = p->syncAnti; apd->syncAnti = p->CC()->syncAnti; } HoldFlag<> dosync(pd->syncAnti, true); for ( DecaySet::const_iterator it = p->theDecayModes.begin(); it != p->theDecayModes.end(); ++it ) pd->addDecayMode(*it); return ""; } void Repository::remove(tIBPtr ip) { ObjectMap::iterator it = objects().find(ip->fullName()); if ( it == objects().end() || ip != it->second ) return; objects().erase(it); allObjects().erase(ip); if ( dynamic_ptr_cast(ip) ) { particles().erase(dynamic_ptr_cast(ip)); defaultParticles().erase(dynamic_ptr_cast(ip)->id()); } if ( dynamic_ptr_cast(ip) ) matchers().erase(dynamic_ptr_cast(ip)); } string Repository::remove(const ObjectSet & rmset) { ObjectSet refset; for ( ObjectMap::const_iterator i = objects().begin(); i != objects().end(); ++i ) { if ( member(rmset, i->second) ) continue; IVector ov = DirectReferences(i->second); for ( int j = 0, M = ov.size(); j < M; ++j ) if ( member(rmset, ov[j]) ) { refset.insert(i->second); break; } } if ( refset.empty() ) { for ( ObjectSet::iterator oi = rmset.begin(); oi != rmset.end(); ++oi ) remove(*oi); return ""; } string ret = "Error: cannot remove the objects because the following " "objects refers to some of them:\n"; for ( ObjectSet::iterator oi = refset.begin(); oi != refset.end(); ++oi ) ret += (**oi).fullName() + "\n"; return ret; } string Repository::exec(string command, ostream & os) { string cpcmd = command; try { string verb = StringUtils::car(command); command = StringUtils::cdr(command); if ( verb == "help" ) { help(command, os); return ""; } if ( verb == "rm" ) { ObjectSet rmset; while ( !command.empty() ) { string name = StringUtils::car(command); DirectoryAppend(name); IBPtr obj = GetPointer(name); if ( !obj ) return "Error: Could not find object named " + name; rmset.insert(obj); command = StringUtils::cdr(command); } return remove(rmset); } if ( verb == "rmdir" || verb == "rrmdir" ) { string dir = StringUtils::car(command); DirectoryAppend(dir); if ( dir[dir.size() - 1] != '/' ) dir += '/'; if ( !member(directories(), dir) ) return verb == "rmdir"? "Error: No such directory.": ""; IVector ov = SearchDirectory(dir); if ( ov.size() && verb == "rmdir" ) return "Error: Cannot remove a non-empty directory. " "(Use rrmdir do remove all object and subdirectories.)"; ObjectSet rmset(ov.begin(), ov.end()); string ret = remove(rmset); if ( !ret.empty() ) return ret; StringVector dirs(directories().begin(), directories().end()); for ( int i = 0, N = dirs.size(); i < N; ++ i ) if ( dirs[i].substr(0, dir.size()) == dir ) directories().erase(dirs[i]); for ( int i = 0, N = directoryStack().size(); i < N; ++i ) if ( directoryStack()[i].substr(0, dir.size()) == dir ) directoryStack()[i] = '/'; return ""; } if ( verb == "cp" ) { string name = StringUtils::car(command); DirectoryAppend(name); tPDPtr p = dynamic_ptr_cast(GetPointer(name)); if ( p ) return copyParticle(p, StringUtils::cdr(command)); return BaseRepository::exec(cpcmd, os); } if ( verb == "setup" ) { string name = StringUtils::car(command); DirectoryAppend(name); IBPtr obj = GetPointer(name); if ( !obj ) return "Error: Could not find object named " + name; istringstream is(StringUtils::cdr(command)); readSetup(obj, is); // A particle may have been registered before but under the wrong id(). PDPtr pd = dynamic_ptr_cast(obj); if(pd) registerParticle(pd); return ""; } if ( verb == "decaymode" ) { string tag = StringUtils::car(command); DMPtr dm = DecayMode::constructDecayMode(tag); if ( !dm ) return "Error: Could not create decay mode from the tag " + StringUtils::car(command); istringstream is(StringUtils::cdr(command)); readSetup(dm, is); if ( !dm->CC() ) return ""; if ( dm->CC()->parent()->synchronized() ) { dm->CC()->synchronize(); return ""; } if ( !dm->CC()->decayer() ) return FindInterface(dm, "Decayer")-> exec(*dm->CC(), "set", dm->decayer()->fullName()); return ""; } if ( verb == "makeanti" ) { string name = StringUtils::car(command); DirectoryAppend(name); tPDPtr p = dynamic_ptr_cast(GetPointer(name)); if ( !p ) return "Error: No particle named " + name; name = StringUtils::car(StringUtils::cdr(command)); DirectoryAppend(name); tPDPtr ap = dynamic_ptr_cast(GetPointer(name)); if ( !ap ) return "Error: No particle named " + name; ParticleData::antiSetup(PDPair(p, ap)); return ""; } if ( verb == "read" ) { // remember directory we're in string cwd = directoryStack().back(); string filename = StringUtils::car(command); string msg = read(filename, os); // Return to the original directory, so that // calling 'read' in an input file will not change the // repository directory you're in ChangeDirectory(cwd); return msg; } if ( verb == "load" ) { return load(StringUtils::car(command)); } if ( verb == "save" ) { save(StringUtils::car(command)); return ""; } if ( verb == "lsruns" ) { string ret; for ( GeneratorMap::iterator ieg = generators().begin(); ieg != generators().end(); ++ieg ) ret += ieg->first + "\n"; return ret; } if ( verb == "makerun" ) { string runname = StringUtils::car(command); string generator = StringUtils::car(StringUtils::cdr(command)); DirectoryAppend(generator); EGPtr eg = BaseRepository::GetObject(generator); makeRun(eg, runname); return ""; } if ( verb == "rmrun" ) { string runname = StringUtils::car(command); generators().erase(runname); return ""; } if ( verb == "saverun" || verb == "saverunfile" || verb == "run" ) { string runname = StringUtils::car(command); string generator = StringUtils::car(StringUtils::cdr(command)); DirectoryAppend(generator); GeneratorMap::iterator ieg = generators().find(runname); EGPtr eg; if ( ieg == generators().end() ) { eg = BaseRepository::GetObject(generator); eg = makeRun(eg, runname); } else eg = ieg->second; if ( !eg ) return "Error: Could not create/find run named'" + runname + "'."; if ( verb == "run" ) eg->go(); else if ( verb == "saverunfile" ) { string file = generator; PersistentOStream os(file, globalLibraries()); os << eg; if ( !os ) return "Save failed! (I/O error)"; } else { string file = eg->filename() + ".run"; PersistentOStream os(file, globalLibraries()); os << eg; if ( !os ) return "Save failed! (I/O error)"; } return ""; } if ( verb == "removerun" ) { string runname = StringUtils::car(command); GeneratorMap::iterator ieg = generators().find(runname); if ( ieg != generators().end() ) { generators().erase(ieg); return ""; } else return "Error: No run named '" + runname + "' available."; } if ( verb == "create" ) { string className = StringUtils::car(command); command = StringUtils::cdr(command); string name = StringUtils::car(command); const ClassDescriptionBase * db = DescriptionList::find(className); command = StringUtils::cdr(command); while ( !db && command.length() ) { string library = StringUtils::car(command); command = StringUtils::cdr(command); DynamicLoader::load(library); db = DescriptionList::find(className); } if ( !db ) { string msg = "Error: " + className + ": No such class found."; if ( !DynamicLoader::lastErrorMessage.empty() ) msg += "\nerror message from dynamic loader:\n" + DynamicLoader::lastErrorMessage; return msg; } IBPtr obj = dynamic_ptr_cast(db->create()); if ( !obj ) return "Error: Could not create object of this class class."; if ( name.empty() ) return "Error: No name specified."; Register(obj, name); return ""; } if ( verb == "defaultparticle" ) { while ( !command.empty() ) { string name = StringUtils::car(command); DirectoryAppend(name); tPDPtr p = dynamic_ptr_cast(GetPointer(name)); if ( !p ) return "Error: No particle named " + name; defaultParticle(p); command = StringUtils::cdr(command); } return ""; } if ( verb == "EXITONERROR" ) { exitOnError() = 1; return ""; } } catch (const Exception & e) { e.handle(); return "Error: " + e.message(); } return BaseRepository::exec(cpcmd, os); } void Repository::help(string cmd, ostream & os) { cmd = StringUtils::car(cmd); if ( cmd == "cd" ) os << "Usage: cd " << endl << "Set the current directory to ." << endl; else if ( cmd == "mkdir" ) os << "Usage: mkdir " << endl << "Create a new directory called with the given path name." << endl; else if ( cmd == "rmdir" ) os << "Usage: rmdir " << endl << "Remove an empty directory." << endl; else if ( cmd == "rrmdir" ) os << "Usage: rrmdir " << endl << "Remove a directory and everything that is in it recursively." << endl << "Will only succeed if no other objects refers to the ones to " << "be deleted." << endl; else if ( cmd == "cp" ) os << "Usage: cp " << endl << "Copy the given object to a new object with the given name." << endl; else if ( cmd == "setup" ) os << "Usage: setup ..." << endl << "Tell a given object to read information given by the arguments." << endl; else if ( cmd == "decaymode" ) os << "Usage: decaymode " << endl << "Construct a decay mode from the given decay tag. The resulting " << "object will be inserted in the directory with the same path as " << "the decaying particle object. The given brancing fraction will " << "be set as well as the given decayer object. If the mode should " << "be switched on by default 1(on) should be specified (otherwise " << "0(off))." << endl; else if ( cmd == "makeanti" ) os << "Usage: makeanti " << endl << "Indicate that the two given particle objects are eachothers " << "anti-partnets." << endl; else if ( cmd == "read" ) os << "Usage: read " << endl << "Read more commands from the given file. The file name can be " << "given relative to the current directory in the shell, or " << "relative to standard directories, or as an absolute path." << endl; else if ( cmd == "load" ) os << "Usage: load " << endl << "Discard everything in the reopsitory and read in a completely " << "new repository from the given file." << endl; else if ( cmd == "save" ) os << "Usage: save " << endl << "Save the complete repository to the given file." << endl; else if ( cmd == "lsruns" ) os << "Usage: lsruns" << endl << "List the run names of all initialized event generators." << endl; else if ( cmd == "makerun" ) os << "Usage: makerun " << endl << "Initialize the given event generator and assign a run name." << endl; else if ( cmd == "rmrun" ) os << "Usage: rmrun " << endl << "Remove the initialized event generator given by the run name." << endl; else if ( cmd == "saverun" ) os << "Usage: saverun " << endl << "Initialize the given event generator and assign a run name " << "and save it to a file named .run" << endl; else if ( cmd == "run" ) os << "Usage: run " << endl << "Run the initialized event generator given b the run name." << endl; else if ( cmd == "create" ) os << "Usage: create {}" << endl << "Create an object of the given class and assign the given name. " << "Optionally supply a dynamically loaded library where the class " << "is included." << endl; else if ( cmd == "pushd" ) os << "Usage: pushd " << endl << "Set the current directory to , but keep the previous " << "working directory on the directory stack." << endl; else if ( cmd == "popd" ) os << "Usage: popd" << endl << "Leave the current working directory and set the current " << "directory to the previous one on the directory stack." << endl; else if ( cmd == "pwd" ) os << "Usage: pwd" << endl << "Print the current working directory." << endl; else if ( cmd == "dirs" ) os << "Usage: dirs" << endl << " Print the contents of the directory stack." << endl; else if ( cmd == "mv" ) os << "Usage: mv " << endl << "Rename the given object to a new path name." << endl; else if ( cmd == "ls" ) os << "Usage: ls {}" << endl << "List the objects and subdirectories in the current or given " << "directory." << endl; else if ( cmd == "library" ) os << "Usage: library " << endl << "Make new classes available to the repository by dynamically " << "linking the given library." << endl; else if ( cmd == "globallibrary" ) os << "Usage: globallibrary " << endl << "Make new classes available to the repository by dynamically " << "linking the given library. If this repository is saved and read " << "in again, this library will be linked in from the beginning." << endl; else if ( cmd == "rmgloballibrary" ) os << "Usage: rmgloballibrary " << endl << "Remove a dynamic library previously added with globallibrary." << endl; else if ( cmd == "appendpath" ) os << "Usage: appendpath " << endl << "Add a search path for dynamic libraries to the end of the " << "search list." << endl; else if ( cmd == "lspaths" ) os << "Usage: lspaths" << endl << "List search paths for dynamic libraries." << endl; else if ( cmd == "prependpath" ) os << "Usage: prependpath " << endl << "Add a search path for dynamic libraries to the beginning of the " << "search list." << endl; else if ( cmd == "doxygendump" ) os << "Usage: doxygendump " << endl << "Extract doxygen documentation of all loaded classes in the " << "given name space and weite it to a file.." << endl; else if ( cmd == "mset" || cmd == "minsert" || cmd == "mdo" ) os << "Usage: " << cmd << " " << endl << "Recursively find in the given directory all objects of the " << "given class and call '" << cmd.substr(1) << "' with the given value for the given interface." << endl; else if ( cmd == "msetdef" || cmd == "mget" || cmd == "mdef" || cmd == "mmin" || cmd == "mmax" || cmd == "merase" ) os << "Usage: " << cmd << " " << endl << "Recursively find in the given directory all objects of the given " << "class and call '" << cmd.substr(1) << "' for the given interface." << endl; else if ( cmd == "set" ) os << "Usage: set : " << endl << "Set the interface for the given object to the given value." << endl; else if ( cmd == "setdef" ) os << "Usage: setdef :" << endl << "Set the interface for the given object to its default value." << endl; else if ( cmd == "insert" ) os << "Usage: insert : " << endl << "Insert a value in the vector interface of the given object." << endl; else if ( cmd == "erase" ) os << "Usage: erase :" << endl << "Erase a value from the vector interface of the given object." << endl; else if ( cmd == "do" ) os << "Usage: do : " << endl << "Call the command interface of the given object with the " << "given arguments." << endl; else if ( cmd == "get" ) os << "Usage: get :" << endl << "Print the value of the interface of the given object." << endl; else if ( cmd == "def" ) os << "Usage: def :" << endl << "Print the default value of the interface of the given object." << endl; else if ( cmd == "min" ) os << "Usage: min :" << endl << "Print the minimum value of the interface of the given object." << endl; else if ( cmd == "max" ) os << "Usage: max :" << endl << "Print the maximum value of the interface of the given object." << endl; else if ( cmd == "describe" ) os << "Usage: describe {:}" << endl << "Describe the given object or an interface of the object." << endl; else if ( cmd == "lsclass" ) os << "Usage: lsclass" << endl << "List all classes available in the repository." << endl; else if ( cmd == "all" ) { os << "Available commands:" << endl << "* cd, mkdir, rmdir, rrmdir, pwd, cp, mv, rm, pushd, popd, dirs, ls:\n" << " Manipulate the repository structure. Analogous to unix " << "shell commands." << endl << "* create, setup, decaymode makeanti:\n" << " Create or setup an object." << endl << "* set, get, insert, erase, do, detdef, def, min, max, describe\n" << " mset, minsert, mdo, msetdef, mdef, mmin, mmax, merase:\n" << " Manipulate interfaces to objects." << endl << "* makerun, saverun, run, lsruns, rmrun:\n" << " Create and handle initialized event genrators which can be run." << endl << "* read, load, library globallibrary, rmgloballibrary,\n" << " appendpath, prependpath, lspaths, doxygendump:\n" << " Handle files external files and libraries." << endl; os << "Do 'help syntax' for help on syntax." << endl << "Do 'help ' for help on a particular command." << endl; } else if ( cmd == "syntax" ) os << "* = '/' | | /" << endl << " = | / | :\n" << " Analogous to a unix file structure, an object can be " << "specified with an\n absolute path or a path relative to " << "the current directory." << endl << "* = |[]" << endl << " An interface can be a parameter (floating point, integer or " << "string),\n a switch (integer, possibly named), a reference to " << "another object in the\n repository or a command which takes " << "an arbitrary string as argument.\n There are also vector interfaces " << "of parameters and references for which\n an index must be supplied." << endl; else { if ( !cmd.empty() ) os << "No command '" << cmd << "' found." << endl; os << "Common commands:" << endl << "* cd, mkdir, rmdir, pwd, cp, mv, rm:\n" << " Manipulate the repository structure. Analogous to unix " << "shell commands." << endl << "* create, setup:\n" << " Create an object." << endl << "set, get, insert, erase, do:\n" << " Manipulate interfaces to objects." << endl << "* makerun, saverun, run, lsruns:\n" << " Create and handle initialized event genrators which can be run." << endl; os << "Do 'help all' for a complete list of commands." << endl << "Do 'help syntax' for help on syntax." << endl << "Do 'help ' for help on a particular command." << endl; } } Repository::Repository() { ++ninstances; } Repository::~Repository() { --ninstances; if ( ninstances <= 0 ) { generators().clear(); } } int Repository::ninstances = 0; namespace { static string version_ = #include "versionstamp.inc" ""; } string Repository::version() { return ::version_; } string Repository::banner() { const auto now = std::chrono::system_clock::now(); const auto now_c = std::chrono::system_clock::to_time_t(now); string time = ">>>> " ; time += StringUtils::stripws(string(std::ctime(&now_c))) + ' '; time += string(max(0,74 - int(time.size())), ' '); time += "<<<<"; string line = ">>>> Toolkit for HEP Event Generation - " + Repository::version() + ' '; line += string(max(0,78 - int(line.size())), '<'); string block = string(78, '>') + '\n' + line + '\n' + time + '\n' + string(78, '<') + '\n'; return block; } diff --git a/Repository/Repository.h b/Repository/Repository.h --- a/Repository/Repository.h +++ b/Repository/Repository.h @@ -1,343 +1,343 @@ // -*- C++ -*- // // Repository.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_Repository_H #define ThePEG_Repository_H // This is the declaration of the Repository class. #include "ThePEG/Config/ThePEG.h" #include "BaseRepository.h" #include "EventGenerator.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/PDT/MatcherBase.h" namespace ThePEG { /** * Repository inherits from the BaseRepository class. While * BaseRepository is fairly general and could in principle be used for * any program where sets of InterfacedBase objects are managed, the * Repository is ThePEG specific in that it deals with ParticleData, * ParticleMatchers and EventGenerators. * * One main function is to write an EventGenerator to disk using * saveRun(). Here all objects needed for the run, including the * EventGenerator is cloned and isolated from the other objects in the * Repository (and are hence not handled by the Repository anymore) * before they are all persistently written out to disk. * * The Register() function simply pass the objects to the corresonding * method in BaseRepository, but if the object is a ParticleData or a * ParticleMatcher, they are stored separately. * * @see BaseRepository * @see InterfacedBase * @see ParticleData * @see ParticleMatcher * @see EventGenerator * */ class Repository: public BaseRepository { public: /** A map of EventGenerator objects indexed by their run name. */ typedef map GeneratorMap; public: /** @name Standsrd constructors and destructors */ //@{ /** * The default constructor is the only one that should be used. */ Repository(); /** * The destructor will do some clean-up when the last Repository is * deleted. */ ~Repository(); public: /** @name Functions for register objects in the Repository. */ //@{ /** * Register an object with BaseRepository::Register() and add it to * the list of particles or matchers if of any of those * types. */ static void Register(IBPtr); /** * Register an object with BaseRepository::Register() and add it to * the list of particles or matchers if of any of those * types. */ static void Register(IBPtr, string newName); //@} /** @name Access ParticleData and MatcherBase objects in the Repository. */ //@{ /** * Add a particle to the list of default ones. If one of the same * type alredy existed, it is removed from the list (but not from * the repository). */ static void defaultParticle(tPDPtr); /** * Get a pointer to the default particle of the given type or * generic name. */ static PDPtr defaultParticle(PID id); /** * Get a pointer to a particle based on the given path or name. The * argument is first treated as a path to an object. If no such * particle object is found, the argument is treated as a generic * particle PDGName and is searched for among the default set of * particles. */ static tPDPtr findParticle(string name); /** * Return the set of all particles in the repository. */ static const ParticleDataSet & allParticles() { return particles(); } /** * Return the set of all matchers in the repository. */ static const MatcherSet & allMatchers() { return matchers(); } /** * Find a matcher with a given generic name */ static tPMPtr findMatcher(string name); /** * Special function for copying particles. Also corresponding * anti-particle is copied to the same directory. In addition, their * decay modes are copied. */ static string copyParticle(tPDPtr, string); //@} /** @name Functions to isolate Eventgenerator objects. */ //@{ /** * Isolate an event generator, \a eg, and save it to disk in a file * named \a name (with .run appended. */ static EGPtr makeRun(tEGPtr eg, string name); /** * Isolate an event generatorn, named \a EGname, set its run \a name * and save it to a file named \a filename. */ static void saveRun(string EGname, string name, string filename); //@} /** @name I/O functions for the Repository. */ //@{ /** * Load a whole repository from the given file. All objects * previously in the Repository are discarded. Any errors will be * reported in the returned string. */ static string load(string filename); /** * Save the repository to the given file. */ static void save(string filename); /** * Save the repository to the default file. */ static void save() { save(currentFileName()); } /** * Write some statistics about the repository to the standard output. */ static void stats(ostream &); //@} /** @name Command-line interface functions. */ //@{ /** * Print out a help message. Extended text for a specific command if given. */ static void help(string command, ostream & os); /** * Remove the given object from the repository. If the object was * not present nothing will happen. */ static void remove(tIBPtr); /** * Remove objects. Remove the objects in \a rmset if there are no * other objects in the repository referring to them, otherwise * return an error message and the names of the objects refering to * them separated by new-line characters. */ static string remove(const ObjectSet & rmset); /** * Read commands from a stream and send them one by one to exec(). * * @param is the stream from which to read commands. * @param os the stream where output is written. * @param prompt before reading a command from \a is, this string is * written to \a os. */ static void read(istream & is, ostream & os, string prompt = ""); /** * Read commands from a file and send them one by one to exec(). * * Passes the call through to read(istream, ostream), but also sets * currentReadDirStack() correctly. * * Returns possible messages. * * @param filename the file from which to read commands. * @param os the stream where output is written. */ static string read(string filename, ostream & os); /** * Interpret the command in \a cmd and return possible * messages. This is the main function for the command-line * interface. The syntax is described elsewhere. The ostream * argument is currently unused. */ static string exec(string cmd, ostream &); /** * Insert the given EventGenerator and its dependent Interfaced * objects into the repository and read commands to modify its * interfaces. Any line accepted by the command-line interface will * be executed, but the main purpose of this function is to modify * an already saved and initialized EventGenerator before running * without re-initializing. If an interface which does not have the * dependencySafe() flag set, a warning will be emitted. */ static string modifyEventGenerator(EventGenerator & eg, string filename, ostream & os, bool initOnly = false); /** * Reset the given EventGenerator; equivalent to * modifyEventGenerator without reading an input file. */ static void resetEventGenerator(EventGenerator & eg); //@} /** * Return the version number of ThePEG. */ static string version(); /** * Return a string with a ThePEG banner. */ static string banner(); private: /** * Used by Register. */ static void registerParticle(tPDPtr); /** * Used by Register. */ static void registerMatcher(tPMPtr); /** * Used by read() */ static void execAndCheckReply(string, ostream &); protected: /** @name Functions containing the static instances of objects used by the repository. */ //@{ /** * The set of default particles. */ static ParticleMap & defaultParticles(); /** * The set of all particles. */ static ParticleDataSet & particles(); /** * The set of all matchers. */ static MatcherSet & matchers(); /** * All isolated generators mapped to their run name. */ static GeneratorMap & generators(); /** * The default file name used by save(). */ static string & currentFileName(); public: /** * If non-zero the setup program will exit with this error code as * soon as an error is encountered. */ static int & exitOnError(); /** * Call this function to clean up the repository at the end of your * program if you are using the static functions directly without * going through a Repository object. There, the destructor would do * the job. */ static void cleanup(); //@} private: /** * It makes no sense to copy a Repository, so this constructor is * not implemented */ Repository(const Repository &); /** * It makes no sense to copy a Repository, so this assignment is * not implemented */ Repository & operator=(const Repository &) = delete; /** * Count the number of repositorys instantiated. */ static int ninstances; }; } #endif /* ThePEG_Repository_H */ diff --git a/Repository/StandardRandom.cc b/Repository/StandardRandom.cc --- a/Repository/StandardRandom.cc +++ b/Repository/StandardRandom.cc @@ -1,102 +1,102 @@ // -*- C++ -*- // // StandardRandom.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the StandardRandom class. // #include "StandardRandom.h" #include "ThePEG/Interface/ClassDocumentation.h" using namespace ThePEG; IBPtr StandardRandom::clone() const { return new_ptr(*this); } IBPtr StandardRandom::fullclone() const { return new_ptr(*this); } void StandardRandom::setSeed(long seed) { if ( seed == -1 ) seed = 19940801; long ij = seed/30082; long kl = seed - 30082*ij; long i = (ij/177) % 177 + 2; long j = ij % 177 + 2; long k = (kl/169) % 178 + 1; long l = kl % 169; for ( int n = 1 ; n < 98 ; n++ ) { double s = 0.0; double t = 0.5; for ( int m = 1 ; m < 25 ; m++) { int mm = ( ( (i*j) % 179 ) * k ) % 179; i = j; j = k; k = mm; l = ( 53 * l + 1 ) % 169; if ( (l*mm % 64 ) >= 32 ) s += t; t *= 0.5; } u[n-1] = s; } c = 362436.0 / 16777216.0; cd = 7654321.0 / 16777216.0; cm = 16777213.0 / 16777216.0; i97 = 96; j97 = 32; flush(); } void StandardRandom::fill() { for ( int i = 0, N = theNumbers.size(); i < N; ++i ) { double & uni = theNumbers[i]; do { uni = u[i97] - u[j97]; if ( uni < 0.0 ) uni++; u[i97] = uni; if (i97 == 0) i97 = 96; else i97--; if (j97 == 0) j97 = 96; else j97--; c -= cd; if (c < 0.0) c += cm; uni -= c; if (uni < 0.0) uni += 1.0; } while ( uni <= 0.0 || uni >= 1.0 ); } nextNumber = theNumbers.begin(); } void StandardRandom::persistentOutput(PersistentOStream & os) const { os << u << c << cd << cm << i97 << j97; } void StandardRandom::persistentInput(PersistentIStream & is, int) { is >> u >> c >> cd >> cm >> i97 >> j97; } ClassDescription StandardRandom::initStandardRandom; void StandardRandom::Init() { static ClassDocumentation documentation ("Interface to the CLHEP::JamesRandom engine class."); } diff --git a/Repository/StandardRandom.h b/Repository/StandardRandom.h --- a/Repository/StandardRandom.h +++ b/Repository/StandardRandom.h @@ -1,162 +1,162 @@ // -*- C++ -*- // // StandardRandom.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_StandardRandom_H #define ThePEG_StandardRandom_H // This is the declaration of the StandardRandom class. #include "RandomGenerator.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" namespace ThePEG { /** * StandardRandom inherits from the RandomGenerator class and is an * interface to the CLHEP::JamesRandom engine class. * * @see \ref StandardRandomInterfaces "The interfaces" * defined for StandardRandom. */ class StandardRandom: public RandomGenerator { public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ StandardRandom() : u() { if ( theSeed != 0 ) setSeed(theSeed); } //@} public: /** * Reset the underlying random algorithm with the given seed. If the * \a seed is set to -1 a standard seed will be used. */ virtual void setSeed(long seed); protected: /** * Fill the cache with random numbers. */ virtual void fill(); public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interface. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * The internal state vector. */ array u; /** * Parameter for the internal state. */ double c; /** * Parameter for the internal state. */ double cd; /** * Parameter for the internal state. */ double cm; /** * Index for the internal state. */ int i97; /** * Index for the internal state. */ int j97; private: /** * Describe a concrete class with persistent data. */ static ClassDescription initStandardRandom; /** * Private and non-existent assignment operator. */ StandardRandom & operator=(const StandardRandom &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the base classes * of StandardRandom. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of StandardRandom. */ typedef RandomGenerator NthBase; }; /** This template specialization informs ThePEG about the name of the * StandardRandom class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "ThePEG::StandardRandom"; } }; /** @endcond */ } #endif /* ThePEG_StandardRandom_H */ diff --git a/Repository/Strategy.cc b/Repository/Strategy.cc --- a/Repository/Strategy.cc +++ b/Repository/Strategy.cc @@ -1,181 +1,181 @@ // -*- C++ -*- // // Strategy.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the Strategy class. // #include "Strategy.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/ParVector.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Repository/Repository.h" #include "ThePEG/Utilities/Throw.h" using namespace ThePEG; string Strategy::localParticlesDir() const { return theLocalParticlesDir; } bool Strategy::checkDir(string x) { if ( x == "" ) return false; if ( x[0] != '/' ) Throw() << "Directory name must start with a '/'." << Exception::setuperror; if ( x[x.length() - 1] != '/' ) x += '/'; try { Repository::CheckObjectDirectory(x); } catch ( Exception & e ) { e.handle(); Throw() << "No directory named " << x << " in the repository." << Exception::setuperror; } return true; } void Strategy::setDefaultParticlesDirs(string dir, int i) { if ( i < 0 || unsigned(i) >= theDefaultParticlesDirs.size() ) Throw() << "Index out of range in DefaultParticlesDirs" << Exception::setuperror; if ( !checkDir(dir) ) Throw() << "Empty directory name not allowd in DefaultParticlesDirs" << Exception::setuperror; theDefaultParticlesDirs[i] = dir; } void Strategy::insDefaultParticlesDirs(string dir, int i) { if ( i < 0 || unsigned(i) > theDefaultParticlesDirs.size() ) Throw() << "Index out of range in DefaultParticlesDirs" << Exception::setuperror; if ( !checkDir(dir) ) Throw() << "Empty directory name not allowd in DefaultParticlesDirs" << Exception::setuperror; theDefaultParticlesDirs.insert(theDefaultParticlesDirs.begin() + i, dir); } void Strategy::setLocalParticlesDir(string x) { if ( checkDir(x) ) theLocalParticlesDir = x; } IBPtr Strategy::clone() const { return new_ptr(*this); } IBPtr Strategy::fullclone() const { return new_ptr(*this); } void Strategy::persistentOutput(PersistentOStream & os) const { os << theParticles << theLocalParticlesDir << theDefaultObjects << theDefaultParticlesDirs; } void Strategy::persistentInput(PersistentIStream & is, int) { is >> theParticles >> theLocalParticlesDir >> theDefaultObjects >> theDefaultParticlesDirs; } ClassDescription Strategy::initStrategy; void Strategy::setLocalParticles(PDPtr pd, int) { particles()[pd->id()] = pd; } void Strategy::insLocalParticles(PDPtr pd, int) { particles()[pd->id()] = pd; } void Strategy::delLocalParticles(int place) { ParticleMap::iterator it = particles().begin(); while ( place-- && it != particles().end() ) ++it; if ( it != particles().end() ) particles().erase(it); } vector Strategy::getLocalParticles() const { vector ret; for ( ParticleMap::const_iterator it = particles().begin(); it != particles().end(); ++it ) ret.push_back(it->second); return ret; } void Strategy::Init() { static ClassDocumentation documentation ("Represents a general strategy to be assigned to an EventGenerator. " "It contains a set of default ParticleData objects which takes " "presedence over the ones in the Repository (although not over " "the ones in the EventGenerator). It also contains a set of other " "default objects which are automatically assigned to all Reference " "and RefVector interfaces which have the " "InterfaceBase::defaultIfNull() flag set."); static RefVector interfaceLocalParticles ("LocalParticles", "Special versions of ThePEG::ParticleData objects to be used. Note " "that to delete an object, its number in the list " "should be given, rather than its id number.", 0, 0, false, false, true, false, &Strategy::setLocalParticles, &Strategy::insLocalParticles, &Strategy::delLocalParticles, &Strategy::getLocalParticles); static RefVector interfaceDefaultObjects ("DefaultObjects", "A vector of pointers to default objects. In a ThePEG::Reference or " "ThePEG::RefVector interface with the defaultIfNull() flag set, if a " "null pointer is encountered this vector is gone through until an " "acceptable object is found in which case the null pointer is replaced " "by a pointer to this object. Note that the default objects given in the " "ThePEG::EventGenerator are gone through first and are given precedence.", &Strategy::theDefaultObjects, 0, true, false, true, false, false); static Parameter interfaceLocalParticlesDir ("LocalParticlesDir", "A directory in the repository which will be scanned for particles " "which will be included as default particles in a run. These particles " "will be overridden by particles specified in " "LocalParticles and default particles " "specified directly in the EventGenerator.", &Strategy::theLocalParticlesDir, "", true, false, &Strategy::setLocalParticlesDir, (string(Strategy::*)()const)(0), (string(Strategy::*)()const)(0)); static ParVector interfaceDefaultParticlesDirs ("DefaultParticlesDirs", "By default all particles in the Repository are included in a run, " "although only one particle object per PDG id number. If directories are " "listed in DefaultParticlesDirs, only particles in these will be " "considered for default inclusion in a run. Only particles which have " "a PDG id which is not given by particles in " "LocalParticlesDir, " "LocalParticles, or in " "EventGenerator::LocalParticles will be " "considered.", &Strategy::theDefaultParticlesDirs, -1, "", "", "", true, false, Interface::nolimits, &Strategy::setDefaultParticlesDirs, &Strategy::insDefaultParticlesDirs); interfaceLocalParticles.rank(10); interfaceLocalParticlesDir.rank(11); interfaceDefaultObjects.rank(9); interfaceDefaultParticlesDirs.rank(8); } diff --git a/Repository/Strategy.h b/Repository/Strategy.h --- a/Repository/Strategy.h +++ b/Repository/Strategy.h @@ -1,242 +1,242 @@ // -*- C++ -*- // // Strategy.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_Strategy_H #define ThePEG_Strategy_H // This is the declaration of the Strategy class. #include "ThePEG/Config/ThePEG.h" #include "Strategy.fh" #include "ThePEG/Interface/Interfaced.h" namespace ThePEG { /** * The Strategy class represents a general strategy to be assigned to * an EventGenerator. It contains a set of default ParticleData * objects which takes presedence over the ones in the Repository * (although not over the ones in the EventGenerator). It also * contains a set of other default objects which are automatically * assigned to all Reference and RefVector interfaces which have the * InterfaceBase::defaultIfNull() flag set. In this case each of the * objects in defaultObjects() are tested in turn, and the first * object which has the correct class and can be set will be used. * * Sub-classes may implement other behaviors by overriding the * doinit() function. * * @see \ref StrategyInterfaces "The interfaces" * defined for Strategy. * @see EventGenerator * @see ParticleData * @see Repository * @see Reference * */ class Strategy: public Interfaced { public: /** @name Access the special objects in this Strategy. */ //@{ /** * Return the map of local particles indexed by their PDG id number. */ const ParticleMap & particles() const { return theParticles; } /** * A directory in the repository which will be scanned for particles * which will be included as default particles in a run. These * particles will be overridden by particles specified in * LocalParticles and default particles * specified directly in the EventGenerator. */ string localParticlesDir() const; /** * By default all particles in the Repository are included in a run, * although only one particle per PDG id number. If directories are * listed here, only particles in these will be considered for * inclusion in a run. Only particles which have a PDG id which is * not given by particles in localParticlesDir(), particles(), or in * EventGenerator::localParticles() will be considered. */ const vector & defaultParticlesDirs() const { return theDefaultParticlesDirs; } /** * Return the vector of default objects. */ const vector & defaultObjects() const { return theDefaultObjects; } //@} /** * Return a freeform version string. Client code should not rely on the * string's format. It can be used e.g. to annotate plots. */ virtual const string versionstring() const { return ""; } public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interface. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * Return the map of local particles. */ ParticleMap & particles() { return theParticles; } private: /** * the map of default particles. */ ParticleMap theParticles; /** * A directory in the repository which will be scanned for particles * which will be included as default particles in a run. These * particles will be overridden by particles specified in * LocalParticles and default particles * specified directly in the EventGenerator. */ string theLocalParticlesDir; /** * A vector of default objects. */ vector theDefaultObjects; /** * By default all particles in the Repository are included in a run, * although only one particle per PDG id number. If directories are * listed in theDefaultParticlesDirs, only particles in these will * be considered for inclusion in a run. Only particles which have a * PDG id which is not given by particles in localParticlesDir(), * particles(), or in EventGenerator::localParticles() will be * considered. */ vector theDefaultParticlesDirs; private: /** * Utility function used by the interface. */ void setLocalParticles(PDPtr pd, int); /** * Utility function used by the interface. */ void insLocalParticles(PDPtr pd, int); /** * Utility function used by the interface. */ void delLocalParticles(int place); /** * Utility function used by the interface. */ vector getLocalParticles() const; /** * Utility function used by the interface. */ void setLocalParticlesDir(string); /** * Utility function used by the interface. */ void setDefaultParticlesDirs(string,int); /** * Utility function used by the interface. */ void insDefaultParticlesDirs(string,int); /** * Utility function used by the interface. */ static bool checkDir(string); private: /** * Describe a concrete class with persistent data. */ static ClassDescription initStrategy; /** * Private and non-existent assignment operator. */ Strategy & operator=(const Strategy &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the base classes * of Strategy. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of Strategy. */ typedef Interfaced NthBase; }; /** This template specialization informs ThePEG about the name of the * Strategy class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "ThePEG::Strategy"; } }; /** @endcond */ } #endif /* ThePEG_Strategy_H */ diff --git a/Repository/ThePEGStrategy.cc b/Repository/ThePEGStrategy.cc --- a/Repository/ThePEGStrategy.cc +++ b/Repository/ThePEGStrategy.cc @@ -1,41 +1,41 @@ // -*- C++ -*- // // ThePEGStrategy.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the ThePEGStrategy class. // #include "ThePEGStrategy.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/PDT/ParticleData.h" #include "Repository.h" using namespace ThePEG; const std::string ThePEGStrategy::versionstring() const { return Repository::version(); } IBPtr ThePEGStrategy::clone() const { return new_ptr(*this); } IBPtr ThePEGStrategy::fullclone() const { return new_ptr(*this); } NoPIOClassDescription ThePEGStrategy::initThePEGStrategy; void ThePEGStrategy::Init() { static ClassDocumentation interfaceDescription ("This class represents the default ThePEG strategy", "", ""); } diff --git a/Repository/ThePEGStrategy.h b/Repository/ThePEGStrategy.h --- a/Repository/ThePEGStrategy.h +++ b/Repository/ThePEGStrategy.h @@ -1,99 +1,99 @@ // -*- C++ -*- // // ThePEGStrategy.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_ThePEGStrategy_H #define ThePEG_ThePEGStrategy_H // This is the declaration of the ThePEGStrategy class. #include "ThePEG/Repository/Strategy.h" #include namespace ThePEG { /** * The ThePEGStrategy class is a sub-class of the Strategy class, * simply implementing the correct citation for ThePEG in the * ClassDocumentation interface. * * @see Strategy * */ class ThePEGStrategy: public Strategy { public: /** * Standard Init function used to initialize the interface. */ static void Init(); /** * Version string */ virtual const std::string versionstring() const; protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * Describe concrete class without persistent data. */ static NoPIOClassDescription initThePEGStrategy; /** * Private and non-existent assignment operator. */ ThePEGStrategy & operator=(const ThePEGStrategy &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the base classes * of ThePEGStrategy. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of ThePEGStrategy. */ typedef Strategy NthBase; }; /** This template specialization informs ThePEG about the name of the * ThePEGStrategy 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::ThePEGStrategy"; } /** Return the name of the shared library be loaded to get access to * the ThePEGStrategy class and every other class it uses * (except the base class). */ static string library() { return "ThePEGStrategy.so"; } }; /** @endcond */ } #endif /* ThePEG_ThePEGStrategy_H */ diff --git a/Repository/UseRandom.cc b/Repository/UseRandom.cc --- a/Repository/UseRandom.cc +++ b/Repository/UseRandom.cc @@ -1,20 +1,20 @@ // -*- C++ -*- // // UseRandom.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the UseRandom class. // #include "UseRandom.h" using namespace ThePEG; vector UseRandom::theRandomStack; diff --git a/Repository/UseRandom.h b/Repository/UseRandom.h --- a/Repository/UseRandom.h +++ b/Repository/UseRandom.h @@ -1,297 +1,297 @@ // -*- C++ -*- // // UseRandom.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_UseRandom_H #define ThePEG_UseRandom_H // This is the declaration of the UseRandom class. #include "ThePEG/Repository/RandomGenerator.h" namespace ThePEG { /** * This UseRandom class keeps a static stack of RandomGenerator * objects which can be used anywhere by any class. When an * EventGenerator is initialized or run it adds a RandomGenerator * object to the stack which can be used by any other object being * initialized or run through the static functions of the UseRandom * class. If someone needs to use an alternative RandomGenerator * object a new UseRandom object can be constructed with a pointer to * the desired RandomGenerator object as argument and that object will * the be used by the static UseRandom functions until the UseRandom * object is destructed. * * @see RandomGenerator * @see EventGenerator * */ class UseRandom { public: /** * Default constructor does nothing. */ UseRandom() : randomPushed(false) {} /** * Copy-constructor does nothing. */ UseRandom(const UseRandom &) : randomPushed(false) {} /** * Construct a new object specifying a new RandomGenerator, \a r, to * be used during this objects lifetime */ UseRandom(const RanGenPtr & r) : randomPushed(false) { if ( r ) { theRandomStack.push_back(r); randomPushed = true; } } /** * The destructor removing the RandomGenerator specified in the * constructor from the stack. */ ~UseRandom() { if ( randomPushed ) theRandomStack.pop_back(); } public: /** * Return a reference to the currently chosen RandomGenerator object. */ static RandomGenerator & current() { return *theRandomStack.back(); } /** * Return a pointer to the currently chosen RandomGenerator object. */ // static RandomEngine * currentEngine() { // return &(current().randomGenerator()); // } /** * Return a simple flat random number (from the current * RandomGenerator object) in the range ]0,1[. */ static double rnd() { return current().rnd(); } /** * Return \a n simple flat random number (from the current * RandomGenerator object) in the range ]0,1[. */ static RandomGenerator::RndVector rndvec(int n) { return current().rndvec(n); } /** * Return a simple flat random number (from the current * RandomGenerator object) in the range ]0,\a xu[. */ template static Unit rnd(Unit xu) { return current().rnd(xu); } /** * Return a simple flat random number (from the current * RandomGenerator object) in the range ]\a xl,\a xu[. */ template static Unit rnd(Unit xl, Unit xu) { return current().rnd(xl, xu); } /** * Return a true with probability \a p (default 0.5). */ static bool rndbool(double p = 0.5) { return current().rndbool(p); } /** * Return a true with probability \a p (default 0.5). Uses push_back * to reuse random number. */ static bool prndbool(double p = 0.5) { return current().rndbool(p); } /** * Return a true with probability \a p1/(\a p1+\a p2). */ static bool rndbool(double p1, double p2) { return current().rndbool(p1, p2); } /** * Return a true with probability \a p1/(\a p1+\a p2). Uses * push_back to reuse random number. */ static bool prndbool(double p1, double p2) { return current().rndbool(p1, p2); } /** * Return -1, 0, or 1 with relative probabilities \a p1, \a p2, \a * p3. */ static int rndsign(double p1, double p2, double p3) { return current().rndsign(p1, p2, p3); } /** * Return -1, 0, or 1 with relative probabilities \a p1, \a p2, \a * p3. Uses push_back to reuse random number. */ static int prndsign(double p1, double p2, double p3) { return current().rndsign(p1, p2, p3); } /** * Return an integer \f$i\f$ with probability p\f$i\f$/(\a p0+\a * p1). */ static int rnd2(double p0, double p1) { return current().rnd2(p0, p1); } /** * Return an integer \f$i\f$ with probability p\f$i\f$/(\a p0+\a * p1+\a p2). */ static int rnd3(double p0, double p1, double p2) { return current().rnd3(p0, p1, p2); } /** * Return an integer/ \f$i\f$ with probability p\f$i\f$(\a p0+\a * p1+\a p2+\a p3). */ static int rnd4(double p0, double p1, double p2, double p3) { return current().rnd4(p0, p1, p2, p3); } /** * Return an integer/ \f$i\f$ with probability p\f$i\f$(\a p0+\a * p1+\a p2+\a p3+\a p4). */ static int rnd5(double p0, double p1, double p2, double p3, double p4) { return current().rnd5(p0, p1, p2, p3, p4); } /** * Return a simple flat random integrer number in the range [0,\a xu[. */ static long irnd(long xu = 2) { return long(rnd() * xu); } /** * Return a simple flat random integrer number in the range [\a xl,\a xu[. */ static long irnd(long xl, long xu) { return xl + irnd(xu-xl); } /** * Return a number between zero and infinity, distributed according * to \f$e^-x\f$. */ static double rndExp() { return current().rndExp(); } /** * Return a number between zero and infinity, distributed according * to \f$e^-{x/\mu}\f$ where \f$\mu\f$ is the \a mean value. */ template static Unit rndExp(Unit mean) { return current().rndExp(mean); } /** * Return a number distributed according to a Gaussian distribution * with zero mean and unit variance. */ static double rndGauss() { return current().rndGauss(); } /** * Return a number distributed according to a Gaussian distribution * with a given standard deviation, \a sigma, and a given \a mean. */ template static Unit rndGauss(Unit sigma, Unit mean = Unit()) { return current().rndGauss(sigma, mean); } /** * Return a positive number distributed according to a * non-relativistic Breit-Wigner with a given width, \a gamma, and a * given \a mean. */ template static Unit rndBW(Unit mean, Unit gamma) { return current().rndBW(mean, gamma); } /** * Return a positive number distributed according to a * non-relativistic Breit-Wigner with a given width, \a gamma, and a * given \a mean. The distribution is cut-off so that the number is * between \a mean - \a cut and \a mean + \a cut */ template static Unit rndBW(Unit mean, Unit gamma, Unit cut) { return current().rndBW(mean, gamma, cut); } /** * Return a positive number distributed according to a relativistic * Breit-Wigner with a given width, \a gamma, and a given \a mean. */ template static Unit rndRelBW(Unit mean, Unit gamma) { return current().rndRelBW(mean, gamma); } /** * Return a positive number distributed according to a relativistic * Breit-Wigner with a given width, \a gamma, and a given \a * mean. The distribution is cut-off so that the number is between * \a mean - \a cut and \a mean + \a cut */ template static Unit rndRelBW(Unit mean, Unit gamma, Unit cut) { return current().rndRelBW(mean, gamma, cut); } /** * Return a non-negative number generated according to a Poissonian * distribution with a given \a mean. */ static long rndPoisson(double mean) { return current().rndPoisson(mean); } private: /** * The stack of RandomGenerators requested. */ static vector theRandomStack; /** * True if this object is responsible for pushing a RandomGenerator * onto the stack. */ bool randomPushed; private: /** * Private and non-existent assignment operator. */ UseRandom & operator=(const UseRandom &) = delete; }; } #endif /* ThePEG_UseRandom_H */ diff --git a/Repository/tests/repositoryTestRandomGenerator.h b/Repository/tests/repositoryTestRandomGenerator.h --- a/Repository/tests/repositoryTestRandomGenerator.h +++ b/Repository/tests/repositoryTestRandomGenerator.h @@ -1,1305 +1,1305 @@ // -*- C++ -*- // // utilitiesTestSmearing.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad, 2015 Marco A. Harrendorf +// Copyright (C) 1999-2019 Leif Lonnblad, 2015 Marco A. Harrendorf // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_Repository_Test_RandomGenerator_H #define ThePEG_Repository_Test_RandomGenerator_H #include #include #include "ThePEG/Repository/RandomGenerator.h" #include /* * Helper class to test generated random numbers * * The class checks how many random numbers are inside a pre-defined interval and how many outside * This class is e.g. useful to check random numbers produced by a gaussian distribution */ template class BinningCheck { private: // Do not accept missing interval limits BinningCheck() {} public: // Define interval limits BinningCheck(Unit lo, Unit hi) : m_lo(lo), m_hi(hi), m_in(0), m_out(0) {} ~BinningCheck() {} int in() {return m_in;} int out() {return m_out;} int tot() {return m_out + m_in;} // Check if random number is inside / outside interval and increase corresponding counter void add(Unit randomNumber) { if(randomNumber >= m_lo && randomNumber <= m_hi) { m_in++; } else { m_out++; } } // Reset counters void reset() {m_in = 0; m_out = 0;} private: Unit m_lo, m_hi; int m_in, m_out; }; typedef BinningCheck DoubleBinCheck; typedef BinningCheck LongBinCheck; /* * Start of BOOST unit tests for Helper class * */ BOOST_AUTO_TEST_SUITE(HelperRandomNumberBinning) BOOST_AUTO_TEST_CASE(HelperDoubleBinning) { DoubleBinCheck a(0, 1); a.add(-1.1); a.add(-0.1); a.add(0.1); a.add(0.5); a.add(0.8); a.add(1.1); a.add(100); BOOST_CHECK_EQUAL(a.tot(), 7); BOOST_CHECK_EQUAL(a.in(), 3); BOOST_CHECK_EQUAL(a.out(), 4); a.reset(); BOOST_CHECK_EQUAL(a.tot(), 0); BOOST_CHECK_EQUAL(a.in(), 0); BOOST_CHECK_EQUAL(a.out(), 0); DoubleBinCheck b(-1.5, 0.5); b.add(-1.1); b.add(-0.1); b.add(0.1); b.add(0.5); b.add(0.8); b.add(1.1); b.add(100); BOOST_CHECK_EQUAL(b.tot(), 7); BOOST_CHECK_EQUAL(b.in(), 4); BOOST_CHECK_EQUAL(b.out(), 3); } /* * End of BOOST unit tests for Helper class * */ BOOST_AUTO_TEST_SUITE_END() /* * Local fix to provide randomGenerator object * */ struct FixLocal1 { FixLocal1() : rng() { BOOST_TEST_MESSAGE( "setup local fixture for repositoryTestRandomGenerator" ); } ~FixLocal1() { BOOST_TEST_MESSAGE( "teardown local fixture for repositoryTestRandomGenerator" ); } ThePEG::StandardRandom rng; }; /* * Start of boost unit tests for RandomGenerator.h * */ BOOST_FIXTURE_TEST_SUITE(repositoryRandomGenerator, FixLocal1) /* * Boost unit tests * */ BOOST_AUTO_TEST_CASE(rndZeroToOne) { int N = 1000; // Check for whole interval DoubleBinCheck posRange(0, 1); // Check for flat distribution DoubleBinCheck quarter1(0, 0.25); DoubleBinCheck quarter3(0.5, 0.75); // rnd function for(int i = 0; i < N; ++i) { posRange.add(rng.rnd()); quarter1.add(rng.rnd()); quarter3.add(rng.rnd()); } // Prob laying inside of interval should be 1 BOOST_CHECK_EQUAL(posRange.tot(), N); BOOST_CHECK_EQUAL(posRange.in(), N); BOOST_CHECK_EQUAL(posRange.out(), 0); // Prob laying inside of interval should be 0.25 BOOST_CHECK_EQUAL(quarter1.tot(), N); BOOST_CHECK_CLOSE(quarter1.in(), 0.25 * N, 10); BOOST_CHECK_CLOSE(quarter1.out(), 0.75 * N, 5); // Prob laying inside of interval should be 0.25 BOOST_CHECK_EQUAL(quarter3.tot(), N); BOOST_CHECK_CLOSE(quarter3.in(), 0.25 * N, 10); BOOST_CHECK_CLOSE(quarter3.out(), 0.75 * N, 5); // repeat for operator() posRange.reset(); quarter1.reset(); quarter3.reset(); for(int i = 0; i < N; ++i) { posRange.add(rng()); quarter1.add(rng()); quarter3.add(rng()); } BOOST_CHECK_EQUAL(posRange.tot(), N); BOOST_CHECK_EQUAL(posRange.in(), N); BOOST_CHECK_EQUAL(posRange.out(), 0); // Prob laying inside of interval should be 0.25 BOOST_CHECK_EQUAL(quarter1.tot(), N); BOOST_CHECK_CLOSE(quarter1.in(), 0.25 * N, 10); BOOST_CHECK_CLOSE(quarter1.out(), 0.75 * N, 5); // Prob laying inside of interval should be 0.25 BOOST_CHECK_EQUAL(quarter3.tot(), N); BOOST_CHECK_CLOSE(quarter3.in(), 0.25 * N, 10); BOOST_CHECK_CLOSE(quarter3.out(), 0.75 * N, 5); } BOOST_AUTO_TEST_CASE(rndZeroTohi) { int N = 1000; double hi = 2.5; // Check for whole interval DoubleBinCheck zero2hi(0, 2.5); // Check for flat distribution DoubleBinCheck quarter1(0, 0.5); DoubleBinCheck quarter3(1.5, 2.0); // rnd function for(int i = 0; i < N; ++i) { zero2hi.add(rng.rnd(hi)); quarter1.add(rng.rnd(hi)); quarter3.add(rng.rnd(hi)); } // Prob laying inside of interval should be 1 BOOST_CHECK_EQUAL(zero2hi.tot(), N); BOOST_CHECK_EQUAL(zero2hi.in(), N); BOOST_CHECK_EQUAL(zero2hi.out(), 0); // Prob laying inside of interval should be 0.2 BOOST_CHECK_EQUAL(quarter1.tot(), N); BOOST_CHECK_CLOSE(quarter1.in(), 0.2 * N, 10); BOOST_CHECK_CLOSE(quarter1.out(), 0.8 * N, 5); // Prob laying inside of interval should be 0.2 BOOST_CHECK_EQUAL(quarter3.tot(), N); BOOST_CHECK_CLOSE(quarter3.in(), 0.2 * N, 10); BOOST_CHECK_CLOSE(quarter3.out(), 0.8 * N, 5); // repeat for operator(), note it is generally requiring a long! zero2hi.reset(); quarter1.reset(); quarter3.reset(); for(int i = 0; i < N; ++i) { zero2hi.add(rng(hi)); quarter1.add(rng(hi)); quarter3.add(rng(hi)); } BOOST_CHECK_EQUAL(zero2hi.tot(), N); BOOST_CHECK_EQUAL(zero2hi.in(), N); BOOST_CHECK_EQUAL(zero2hi.out(), 0); // Prob laying inside of interval should be 0.2 BOOST_CHECK_EQUAL(quarter1.tot(), N); BOOST_CHECK_CLOSE(quarter1.in(), 0.2 * N, 10); BOOST_CHECK_CLOSE(quarter1.out(), 0.8 * N, 5); // Prob laying inside of interval should be 0.2 BOOST_CHECK_EQUAL(quarter3.tot(), N); BOOST_CHECK_CLOSE(quarter3.in(), 0.2 * N, 10); BOOST_CHECK_CLOSE(quarter3.out(), 0.8 * N, 5); // repeat for operator(), note it is requiring a long! long hiTwo = 3; // Check for whole interval LongBinCheck zero2hiTwo(0, hiTwo); // Check for flat distribution LongBinCheck quarter1Two(1, 1); LongBinCheck quarter3Two(2, 2); // operator()(long N) for(int i = 0; i < N; ++i) { zero2hiTwo.add(rng(hiTwo)); quarter1Two.add(rng(hiTwo)); quarter3Two.add(rng(hiTwo)); } // Prob laying inside of interval should be 1 BOOST_CHECK_EQUAL(zero2hiTwo.tot(), N); BOOST_CHECK_EQUAL(zero2hiTwo.in(), N); BOOST_CHECK_EQUAL(zero2hiTwo.out(), 0); // Prob laying inside of interval should be 0.333 BOOST_CHECK_EQUAL(quarter1Two.tot(), N); BOOST_CHECK_CLOSE(quarter1Two.in(), 0.333 * N, 10); BOOST_CHECK_CLOSE(quarter1Two.out(), 0.666 * N, 5); // Prob laying inside of interval should be 0.333 BOOST_CHECK_EQUAL(quarter3Two.tot(), N); BOOST_CHECK_CLOSE(quarter3Two.in(), 0.333 * N, 10); BOOST_CHECK_CLOSE(quarter3Two.out(), 0.666 * N, 5); } BOOST_AUTO_TEST_CASE(rndIntervallLowerLimitTohi) { int N = 1000; double lo = -1.5; double hi = 2.5; // Check for whole interval DoubleBinCheck zero2hi(lo, hi); // Check for flat distribution DoubleBinCheck quarter1(-0.5, 0.5); DoubleBinCheck quarter3(1.5, 2.5); // rnd function for(int i = 0; i < N; ++i) { zero2hi.add(rng.rnd(lo, hi)); quarter1.add(rng.rnd(lo, hi)); quarter3.add(rng.rnd(lo, hi)); } // Prob laying inside of interval should be 1 BOOST_CHECK_EQUAL(zero2hi.tot(), N); BOOST_CHECK_EQUAL(zero2hi.in(), N); BOOST_CHECK_EQUAL(zero2hi.out(), 0); // Prob laying inside of interval should be 0.25 BOOST_CHECK_EQUAL(quarter1.tot(), N); BOOST_CHECK_CLOSE(quarter1.in(), 0.25 * N, 10); BOOST_CHECK_CLOSE(quarter1.out(), 0.75 * N, 5); // Prob laying inside of interval should be 0.25 BOOST_CHECK_EQUAL(quarter3.tot(), N); BOOST_CHECK_CLOSE(quarter3.in(), 0.25 * N, 10); BOOST_CHECK_CLOSE(quarter3.out(), 0.75 * N, 5); } BOOST_AUTO_TEST_CASE(rndZeroToOneVector) { int N = 10; int L = 10; // Check for whole interval DoubleBinCheck posRange(0, 1); // Check for flat distribution DoubleBinCheck quarter1(0, 0.25); DoubleBinCheck quarter3(0.5, 0.75); for(int i = 0; i < N; ++i) { posRange.reset(); quarter1.reset(); quarter3.reset(); std::vector rndvec = rng.rndvec(L); BOOST_CHECK_EQUAL(static_cast(rndvec.size()), L); for(int j = 0; j < static_cast(rndvec.size()); ++j) { posRange.add(rndvec[j]); quarter1.add(rndvec[j]); quarter3.add(rndvec[j]); } // Prob laying inside of interval should be 1 BOOST_CHECK_EQUAL(posRange.tot(), N); BOOST_CHECK_EQUAL(posRange.in(), N); BOOST_CHECK_EQUAL(posRange.out(), 0); // Prob laying inside of interval should be 0.25 BOOST_CHECK_EQUAL(quarter1.tot(), N); BOOST_CHECK_CLOSE(quarter1.in(), 0.25 * L, 300); BOOST_CHECK_CLOSE(quarter1.out(), 0.75 * L, 300); // Prob laying inside of interval should be 0.25 BOOST_CHECK_EQUAL(quarter3.tot(), N); BOOST_CHECK_CLOSE(quarter3.in(), 0.25 * L, 300); BOOST_CHECK_CLOSE(quarter3.out(), 0.75 * L, 300); } } BOOST_AUTO_TEST_CASE(rndBoolSingleProbability) { int N = 1000; // Check for whole interval LongBinCheck posRange(0, 1); // Check for flat distribution LongBinCheck zero(0, 0); LongBinCheck one(1, 1); // rndbool function, prob should be 0.5 for(int i = 0; i < N; ++i) { posRange.add(rng.rndbool()); zero.add(rng.rndbool()); one.add(rng.rndbool()); } // Prob laying inside of interval should be 1 BOOST_CHECK_EQUAL(posRange.tot(), N); BOOST_CHECK_EQUAL(posRange.in(), N); BOOST_CHECK_EQUAL(posRange.out(), 0); // Prob laying inside of interval should be 0.5 BOOST_CHECK_EQUAL(zero.tot(), N); BOOST_CHECK_CLOSE(zero.in(), 0.5 * N, 10); BOOST_CHECK_CLOSE(zero.out(), 0.5 * N, 10); // Prob laying inside of interval should be 0.5 BOOST_CHECK_EQUAL(one.tot(), N); BOOST_CHECK_CLOSE(one.in(), 0.5 * N, 10); BOOST_CHECK_CLOSE(one.out(), 0.5 * N, 10); // Check for whole interval LongBinCheck posRangeTwo(0, 1); // Check for flat distribution LongBinCheck midPoint(0, 0); LongBinCheck hiEdge(1, 1); // rndbool function, prob should be now 0.4 for(int i = 0; i < N; ++i) { posRangeTwo.add(rng.rndbool(0.4)); midPoint.add(rng.rndbool(0.4)); hiEdge.add(rng.rndbool(0.4)); } // Prob laying inside of interval should be 1 BOOST_CHECK_EQUAL(posRangeTwo.tot(), N); BOOST_CHECK_EQUAL(posRangeTwo.in(), N); BOOST_CHECK_EQUAL(posRangeTwo.out(), 0); // Prob laying inside of interval should be 0.6 BOOST_CHECK_EQUAL(midPoint.tot(), N); BOOST_CHECK_CLOSE(midPoint.in(), 0.6 * N, 10); BOOST_CHECK_CLOSE(midPoint.out(), 0.4 * N, 10); // Prob laying inside of interval should be 0.4 BOOST_CHECK_EQUAL(hiEdge.tot(), N); BOOST_CHECK_CLOSE(hiEdge.in(), 0.4 * N, 10); BOOST_CHECK_CLOSE(hiEdge.out(), 0.6 * N, 10); } BOOST_AUTO_TEST_CASE(prndBoolSingleProbability) { int N = 1000; // Check for whole interval LongBinCheck posRange(0, 1); // Check for flat distribution LongBinCheck zero(0, 0); LongBinCheck one(1, 1); // rndbool function, prob should be 0.5 for(int i = 0; i < N; ++i) { posRange.add(rng.prndbool()); zero.add(rng.prndbool()); one.add(rng.prndbool()); } // Prob laying inside of interval should be 1 BOOST_CHECK_EQUAL(posRange.tot(), N); BOOST_CHECK_EQUAL(posRange.in(), N); BOOST_CHECK_EQUAL(posRange.out(), 0); // Prob laying inside of interval should be 0.5 BOOST_CHECK_EQUAL(zero.tot(), N); BOOST_CHECK_CLOSE(zero.in(), 0.5 * N, 15); BOOST_CHECK_CLOSE(zero.out(), 0.5 * N, 15); // Prob laying inside of interval should be 0.5 BOOST_CHECK_EQUAL(one.tot(), N); BOOST_CHECK_CLOSE(one.in(), 0.5 * N, 15); BOOST_CHECK_CLOSE(one.out(), 0.5 * N, 15); // Check for whole interval LongBinCheck posRangeTwo(0, 1); // Check for flat distribution LongBinCheck midPoint(0, 0); LongBinCheck hiEdge(1, 1); // rndbool function, prob should be now 0.4 for(int i = 0; i < N; ++i) { posRangeTwo.add(rng.prndbool(0.4)); midPoint.add(rng.prndbool(0.4)); hiEdge.add(rng.prndbool(0.4)); } // Prob laying inside of interval should be 1 BOOST_CHECK_EQUAL(posRangeTwo.tot(), N); BOOST_CHECK_EQUAL(posRangeTwo.in(), N); BOOST_CHECK_EQUAL(posRangeTwo.out(), 0); // Prob laying inside of interval should be 0.6 BOOST_CHECK_EQUAL(midPoint.tot(), N); BOOST_CHECK_CLOSE(midPoint.in(), 0.6 * N, 10); BOOST_CHECK_CLOSE(midPoint.out(), 0.4 * N, 10); // Prob laying inside of interval should be 0.4 BOOST_CHECK_EQUAL(hiEdge.tot(), N); BOOST_CHECK_CLOSE(hiEdge.in(), 0.4 * N, 10); BOOST_CHECK_CLOSE(hiEdge.out(), 0.6 * N, 10); } BOOST_AUTO_TEST_CASE(rndBoolTwoProbabilities) { int N = 1000; double p1 = 0.2; double p2 = 0.3; // Check for whole interval LongBinCheck posRange(0, 1); // Check for flat distribution LongBinCheck zero(0, 0); LongBinCheck one(1, 1); for(int i = 0; i < N; ++i) { posRange.add(rng.rndbool(p1, p2)); zero.add(rng.rndbool(p1, p2)); one.add(rng.rndbool(p1, p2)); } // Prob laying inside of interval should be 1 BOOST_CHECK_EQUAL(posRange.tot(), N); BOOST_CHECK_EQUAL(posRange.in(), N); BOOST_CHECK_EQUAL(posRange.out(), 0); // Prob laying inside of interval should be 0.6 BOOST_CHECK_EQUAL(zero.tot(), N); BOOST_CHECK_CLOSE(zero.in(), 0.6 * N, 10); BOOST_CHECK_CLOSE(zero.out(), 0.4 * N, 10); // Prob laying inside of interval should be 0.2/0.5 = 0.4 BOOST_CHECK_EQUAL(one.tot(), N); BOOST_CHECK_CLOSE(one.in(), 0.4 * N, 10); BOOST_CHECK_CLOSE(one.out(), 0.6 * N, 10); } BOOST_AUTO_TEST_CASE(prndBoolTwoProbabilities) { int N = 1000; double p1 = 0.2; double p2 = 0.3; // Check for whole interval LongBinCheck posRange(0, 1); // Check for flat distribution LongBinCheck zero(0, 0); LongBinCheck one(1, 1); for(int i = 0; i < N; ++i) { posRange.add(rng.prndbool(p1, p2)); zero.add(rng.prndbool(p1, p2)); one.add(rng.prndbool(p1, p2)); } // Prob laying inside of interval should be 1 BOOST_CHECK_EQUAL(posRange.tot(), N); BOOST_CHECK_EQUAL(posRange.in(), N); BOOST_CHECK_EQUAL(posRange.out(), 0); // Prob laying inside of interval should be 0.6 BOOST_CHECK_EQUAL(zero.tot(), N); BOOST_CHECK_CLOSE(zero.in(), 0.6 * N, 10); BOOST_CHECK_CLOSE(zero.out(), 0.4 * N, 10); // Prob laying inside of interval should be 0.2/0.5 = 0.4 BOOST_CHECK_EQUAL(one.tot(), N); BOOST_CHECK_CLOSE(one.in(), 0.4 * N, 10); BOOST_CHECK_CLOSE(one.out(), 0.6 * N, 10); } BOOST_AUTO_TEST_CASE(rndSign) { int N = 1000; double p1 = 0.4; double p2 = 0.2; double p3 = 0.3; // Check for whole interval LongBinCheck range(-1, 1); // Check for flat distribution LongBinCheck lowEdge(-1, -1); LongBinCheck midPoint(0, 0); LongBinCheck hiEdge(1, 1); for(int i = 0; i < N; ++i) { range.add(rng.rndsign(p1, p2, p3)); lowEdge.add(rng.rndsign(p1, p2, p3)); midPoint.add(rng.rndsign(p1, p2, p3)); hiEdge.add(rng.rndsign(p1, p2, p3)); } // Prob laying inside of interval should be 1 BOOST_CHECK_EQUAL(range.tot(), N); BOOST_CHECK_EQUAL(range.in(), N); BOOST_CHECK_EQUAL(range.out(), 0); // Prob laying inside of interval should be 0.4 BOOST_CHECK_EQUAL(lowEdge.tot(), N); BOOST_CHECK_CLOSE(lowEdge.in(), 0.4/0.9 * N, 10); BOOST_CHECK_CLOSE(lowEdge.out(), 0.5/0.9 * N, 10); // Prob laying inside of interval should be 0.2 BOOST_CHECK_EQUAL(midPoint.tot(), N); BOOST_CHECK_CLOSE(midPoint.in(), 0.2/0.9 * N, 10); BOOST_CHECK_CLOSE(midPoint.out(), 0.7/0.9 * N, 10); // Prob laying inside of interval should be 0.2 BOOST_CHECK_EQUAL(hiEdge.tot(), N); BOOST_CHECK_CLOSE(hiEdge.in(), 0.3/0.9 * N, 10); BOOST_CHECK_CLOSE(hiEdge.out(), 0.6/0.9 * N, 10); } BOOST_AUTO_TEST_CASE(prndSign) { int N = 1000; double p1 = 0.4; double p2 = 0.2; double p3 = 0.3; // Check for whole interval LongBinCheck range(-1, 1); // Check for flat distribution LongBinCheck lowEdge(-1, -1); LongBinCheck midPoint(0, 0); LongBinCheck hiEdge(1, 1); for(int i = 0; i < N; ++i) { range.add(rng.prndsign(p1, p2, p3)); lowEdge.add(rng.prndsign(p1, p2, p3)); midPoint.add(rng.prndsign(p1, p2, p3)); hiEdge.add(rng.prndsign(p1, p2, p3)); } // Prob laying inside of interval should be 1 BOOST_CHECK_EQUAL(range.tot(), N); BOOST_CHECK_EQUAL(range.in(), N); BOOST_CHECK_EQUAL(range.out(), 0); // Prob laying inside of interval should be 0.4 BOOST_CHECK_EQUAL(lowEdge.tot(), N); BOOST_CHECK_CLOSE(lowEdge.in(), 0.4/0.9 * N, 10); BOOST_CHECK_CLOSE(lowEdge.out(), 0.5/0.9 * N, 10); // Prob laying inside of interval should be 0.2 BOOST_CHECK_EQUAL(midPoint.tot(), N); BOOST_CHECK_CLOSE(midPoint.in(), 0.2/0.9 * N, 10); BOOST_CHECK_CLOSE(midPoint.out(), 0.7/0.9 * N, 10); // Prob laying inside of interval should be 0.2 BOOST_CHECK_EQUAL(hiEdge.tot(), N); BOOST_CHECK_CLOSE(hiEdge.in(), 0.3/0.9 * N, 10); BOOST_CHECK_CLOSE(hiEdge.out(), 0.6/0.9 * N, 10); } BOOST_AUTO_TEST_CASE(rnd2) { int N = 1000; double p1 = 0.4; double p2 = 0.2; // Check for whole interval LongBinCheck posRange(0, 1); // Check for flat distribution LongBinCheck midPoint(0, 0); LongBinCheck hiEdge(1, 1); for(int i = 0; i < N; ++i) { posRange.add(rng.rnd2(p1, p2)); midPoint.add(rng.rnd2(p1, p2)); hiEdge.add(rng.rnd2(p1, p2)); } // Prob laying inside of interval should be 1 BOOST_CHECK_EQUAL(posRange.tot(), N); BOOST_CHECK_EQUAL(posRange.in(), N); BOOST_CHECK_EQUAL(posRange.out(), 0); // Prob laying inside of interval should be 0.666 BOOST_CHECK_EQUAL(midPoint.tot(), N); BOOST_CHECK_CLOSE(midPoint.in(), 0.666 * N, 10); BOOST_CHECK_CLOSE(midPoint.out(), 0.333 * N, 10); // Prob laying inside of interval should be 0.333 BOOST_CHECK_EQUAL(hiEdge.tot(), N); BOOST_CHECK_CLOSE(hiEdge.in(), 0.333 * N, 10); BOOST_CHECK_CLOSE(hiEdge.out(), 0.666 * N, 10); } BOOST_AUTO_TEST_CASE(rnd3) { int N = 1000; double p1 = 0.4; double p2 = 0.2; double p3 = 0.3; // Check for whole interval LongBinCheck zero2two(0, 2); // Check for flat distribution LongBinCheck midPoint(0, 0); LongBinCheck hiEdge(1, 1); LongBinCheck two(2, 2); for(int i = 0; i < N; ++i) { zero2two.add(rng.rnd3(p1, p2, p3)); midPoint.add(rng.rnd3(p1, p2, p3)); hiEdge.add(rng.rnd3(p1, p2, p3)); two.add(rng.rnd3(p1, p2, p3)); } // Prob laying inside of interval should be 1 BOOST_CHECK_EQUAL(zero2two.tot(), N); BOOST_CHECK_EQUAL(zero2two.in(), N); BOOST_CHECK_EQUAL(zero2two.out(), 0); // Prob laying inside of interval should be 0.4 / 0.9 BOOST_CHECK_EQUAL(midPoint.tot(), N); BOOST_CHECK_CLOSE(midPoint.in(), 0.4/0.9 * N, 10); BOOST_CHECK_CLOSE(midPoint.out(), 0.5/0.9 * N, 10); // Prob laying inside of interval should be 0.2 / 0.9 BOOST_CHECK_EQUAL(hiEdge.tot(), N); BOOST_CHECK_CLOSE(hiEdge.in(), 0.2/0.9 * N, 10); BOOST_CHECK_CLOSE(hiEdge.out(), 0.7/0.9 * N, 10); // Prob laying inside of interval should be 0.3 / 0.9 BOOST_CHECK_EQUAL(two.tot(), N); BOOST_CHECK_CLOSE(two.in(), 0.3/0.9 * N, 10); BOOST_CHECK_CLOSE(two.out(), 0.6/0.9 * N, 10); } BOOST_AUTO_TEST_CASE(rnd4) { int N = 1000; double p1 = 0.4; double p2 = 0.2; double p3 = 0.3; double p4 = 0.5; // Check for whole interval LongBinCheck bin_03(0, 3); // Check for flat distribution LongBinCheck bin0(0, 0); LongBinCheck bin1(1, 1); LongBinCheck bin2(2, 2); LongBinCheck bin3(3, 3); for(int i = 0; i < N; ++i) { bin_03.add(rng.rnd4(p1, p2, p3, p4)); bin0.add(rng.rnd4(p1, p2, p3, p4)); bin1.add(rng.rnd4(p1, p2, p3, p4)); bin2.add(rng.rnd4(p1, p2, p3, p4)); bin3.add(rng.rnd4(p1, p2, p3, p4)); } // Prob laying inside of interval should be 1 BOOST_CHECK_EQUAL(bin_03.tot(), N); BOOST_CHECK_EQUAL(bin_03.in(), N); BOOST_CHECK_EQUAL(bin_03.out(), 0); // Prob laying inside of interval should be 0.4 / 1.4 BOOST_CHECK_EQUAL(bin0.tot(), N); BOOST_CHECK_CLOSE(bin0.in(), 0.4/1.4 * N, 10); BOOST_CHECK_CLOSE(bin0.out(), 1.0/1.4 * N, 10); // Prob laying inside of interval should be 0.2 / 1.4 BOOST_CHECK_EQUAL(bin1.tot(), N); BOOST_CHECK_CLOSE(bin1.in(), 0.2/1.4 * N, 10); BOOST_CHECK_CLOSE(bin1.out(), 1.2/1.4 * N, 10); // Prob laying inside of interval should be 0.3 / 1.4 BOOST_CHECK_EQUAL(bin2.tot(), N); BOOST_CHECK_CLOSE(bin2.in(), 0.3/1.4 * N, 10); BOOST_CHECK_CLOSE(bin2.out(), 1.1/1.4 * N, 10); // Prob laying inside of interval should be 0.5 / 1.4 BOOST_CHECK_EQUAL(bin3.tot(), N); BOOST_CHECK_CLOSE(bin3.in(), 0.5/1.4 * N, 10); BOOST_CHECK_CLOSE(bin3.out(), 0.9/1.4 * N, 10); } BOOST_AUTO_TEST_CASE(rndExp) { int N = 1000; // Check for whole interval DoubleBinCheck allnums(-DBL_MAX, DBL_MAX); // Check for median DoubleBinCheck firstHalf(-DBL_MAX, log(2)); DoubleBinCheck secondHalf(log(2), DBL_MAX); // Check for increasing probability DoubleBinCheck neg1000(-1000, 0); DoubleBinCheck pos1000(0, 1000); for(int i = 0; i < N; ++i) { allnums.add(rng.rndExp()); firstHalf.add(rng.rndExp()); secondHalf.add(rng.rndExp()); neg1000.add(rng.rndExp()); pos1000.add(rng.rndExp()); } // Prob laying inside of interval should be 1 BOOST_CHECK_EQUAL(allnums.tot(), N); BOOST_CHECK_EQUAL(allnums.in(), N); BOOST_CHECK_EQUAL(allnums.out(), 0); // Prob laying inside of interval should be 0.5 BOOST_CHECK_EQUAL(firstHalf.tot(), N); BOOST_CHECK_CLOSE(firstHalf.in(), 0.5 * N, 15); BOOST_CHECK_CLOSE(firstHalf.out(), 0.5 * N, 15); // Prob laying inside of interval should be 0.5 BOOST_CHECK_EQUAL(secondHalf.tot(), N); BOOST_CHECK_CLOSE(secondHalf.in(), 0.5 * N, 15); BOOST_CHECK_CLOSE(secondHalf.out(), 0.5 * N, 15); // Increasing probability BOOST_CHECK(neg1000.in() <= pos1000.in()); } BOOST_AUTO_TEST_CASE(rndExpMean) { int N = 1000; double meanValue = 5; // Check for whole interval DoubleBinCheck allnums(-DBL_MAX, DBL_MAX); // Check for median DoubleBinCheck firstHalf(-DBL_MAX, log(2) * meanValue); DoubleBinCheck secondHalf(log(2) * meanValue, DBL_MAX); // Check for increasing probability DoubleBinCheck neg1000(-1000, 0); DoubleBinCheck pos1000(0, 1000); for(int i = 0; i < N; ++i) { allnums.add(rng.rndExp(meanValue)); firstHalf.add(rng.rndExp(meanValue)); secondHalf.add(rng.rndExp(meanValue)); neg1000.add(rng.rndExp(meanValue)); pos1000.add(rng.rndExp(meanValue)); } // Prob laying inside of interval should be 1 BOOST_CHECK_EQUAL(allnums.tot(), N); BOOST_CHECK_EQUAL(allnums.in(), N); BOOST_CHECK_EQUAL(allnums.out(), 0); // Prob laying inside of interval should be 0.5 BOOST_CHECK_EQUAL(firstHalf.tot(), N); BOOST_CHECK_CLOSE(firstHalf.in(), 0.5 * N, 15); BOOST_CHECK_CLOSE(firstHalf.out(), 0.5 * N, 15); // Prob laying inside of interval should be 0.5 BOOST_CHECK_EQUAL(secondHalf.tot(), N); BOOST_CHECK_CLOSE(secondHalf.in(), 0.5 * N, 15); BOOST_CHECK_CLOSE(secondHalf.out(), 0.5 * N, 15); // Increasing probability BOOST_CHECK(neg1000.in() <= pos1000.in()); } BOOST_AUTO_TEST_CASE(rndGauss) { int N = 1000; // Check for whole interval DoubleBinCheck allnums(-DBL_MAX, DBL_MAX); // Check for median DoubleBinCheck firstHalf(-DBL_MAX, 0); DoubleBinCheck secondHalf(0, DBL_MAX); // Check for increasing probability DoubleBinCheck oneSigma(-1, 1); DoubleBinCheck threeSigma(-3, 3); DoubleBinCheck eightSigma(-8, 8); for(int i = 0; i < N; ++i) { allnums.add(rng.rndGauss()); firstHalf.add(rng.rndGauss()); secondHalf.add(rng.rndGauss()); oneSigma.add(rng.rndGauss()); threeSigma.add(rng.rndGauss()); eightSigma.add(rng.rndGauss()); } // Prob laying inside of interval should be 1 BOOST_CHECK_EQUAL(allnums.tot(), N); BOOST_CHECK_EQUAL(allnums.in(), N); BOOST_CHECK_EQUAL(allnums.out(), 0); // Prob laying inside of interval should be 0.5 BOOST_CHECK_EQUAL(firstHalf.tot(), N); BOOST_CHECK_CLOSE(firstHalf.in(), 0.5 * N, 15); BOOST_CHECK_CLOSE(firstHalf.out(), 0.5 * N, 15); // Prob laying inside of interval should be 0.5 BOOST_CHECK_EQUAL(secondHalf.tot(), N); BOOST_CHECK_CLOSE(secondHalf.in(), 0.5 * N, 15); BOOST_CHECK_CLOSE(secondHalf.out(), 0.5 * N, 15); // Prob laying inside of interval should be 0.68 BOOST_CHECK_EQUAL(oneSigma.tot(), N); BOOST_CHECK_CLOSE(oneSigma.in(), 0.68 * N, 15); BOOST_CHECK_CLOSE(oneSigma.out(), 0.32 * N, 15); // Prob laying inside of interval should be 99,730 0204% BOOST_CHECK_EQUAL(threeSigma.tot(), N); BOOST_CHECK_CLOSE(threeSigma.in(), 0.99730 * N, 15); // Prob laying inside of interval should be 99,999 999 999 % BOOST_CHECK_EQUAL(eightSigma.tot(), N); BOOST_CHECK_CLOSE(eightSigma.in(), 0.9999 * N, 15); } BOOST_AUTO_TEST_CASE(rndGaussMeanSigma) { int N = 1000; for(double mean = 1; mean < 5; mean += 1) { for(double sigma = 0.25; sigma < 0.65; sigma += 0.1) { // Check for whole interval DoubleBinCheck allnums(-DBL_MAX, DBL_MAX); // Check for median DoubleBinCheck firstHalf(-DBL_MAX, mean); DoubleBinCheck secondHalf(mean, DBL_MAX); // Check for increasing probability DoubleBinCheck oneSigma(mean - sigma, mean + sigma); DoubleBinCheck threeSigma(mean - 3 * sigma, mean + 3 * sigma); DoubleBinCheck eightSigma(mean - 8 * sigma, mean + 8 * sigma); for(int i = 0; i < N; ++i) { allnums.add(rng.rndGauss(sigma, mean)); firstHalf.add(rng.rndGauss(sigma, mean)); secondHalf.add(rng.rndGauss(sigma, mean)); oneSigma.add(rng.rndGauss(sigma, mean)); threeSigma.add(rng.rndGauss(sigma, mean)); eightSigma.add(rng.rndGauss(sigma, mean)); } // Prob laying inside of interval should be 1 BOOST_CHECK_EQUAL(allnums.tot(), N); BOOST_CHECK_EQUAL(allnums.in(), N); BOOST_CHECK_EQUAL(allnums.out(), 0); // Prob laying inside of interval should be 0.5 BOOST_CHECK_EQUAL(firstHalf.tot(), N); BOOST_CHECK_CLOSE(firstHalf.in(), 0.5 * N, 15); BOOST_CHECK_CLOSE(firstHalf.out(), 0.5 * N, 15); // Prob laying inside of interval should be 0.5 BOOST_CHECK_EQUAL(secondHalf.tot(), N); BOOST_CHECK_CLOSE(secondHalf.in(), 0.5 * N, 15); BOOST_CHECK_CLOSE(secondHalf.out(), 0.5 * N, 15); // Prob laying inside of interval should be 0.68 BOOST_CHECK_EQUAL(oneSigma.tot(), N); BOOST_CHECK_CLOSE(oneSigma.in(), 0.68 * N, 15); BOOST_CHECK_CLOSE(oneSigma.out(), 0.32 * N, 15); // Prob laying inside of interval should be 99,730 0204% BOOST_CHECK_EQUAL(threeSigma.tot(), N); BOOST_CHECK_CLOSE(threeSigma.in(), 0.99730 * N, 15); // Prob laying inside of interval should be 99,999 999 999 % BOOST_CHECK_EQUAL(eightSigma.tot(), N); BOOST_CHECK_CLOSE(eightSigma.in(), 0.9999 * N, 15); } } } BOOST_AUTO_TEST_CASE(rndGaussTwoNumbers) { int N = 1000; // Check for whole interval DoubleBinCheck allnums(-DBL_MAX, DBL_MAX); // Check for median DoubleBinCheck firstHalf(-DBL_MAX, 0); DoubleBinCheck secondHalf(0, DBL_MAX); // Check for increasing probability DoubleBinCheck oneSigma(-1, 1); DoubleBinCheck threeSigma(-3, 3); DoubleBinCheck eightSigma(-8, 8); double r1, r2; for(int i = 0; i < N; ++i) { rng.rndGaussTwoNumbers(r1, r2); allnums.add(r1); firstHalf.add(r1); secondHalf.add(r1); oneSigma.add(r1); threeSigma.add(r1); eightSigma.add(r1); allnums.add(r2); firstHalf.add(r2); secondHalf.add(r2); oneSigma.add(r2); threeSigma.add(r2); eightSigma.add(r2); } // Two random numbers were added in each round N *= 2; // Prob laying inside of interval should be 1 BOOST_CHECK_EQUAL(allnums.tot(), N); BOOST_CHECK_EQUAL(allnums.in(), N); BOOST_CHECK_EQUAL(allnums.out(), 0); // Prob laying inside of interval should be 0.5 BOOST_CHECK_EQUAL(firstHalf.tot(), N); BOOST_CHECK_CLOSE(firstHalf.in(), 0.5 * N, 15); BOOST_CHECK_CLOSE(firstHalf.out(), 0.5 * N, 15); // Prob laying inside of interval should be 0.5 BOOST_CHECK_EQUAL(secondHalf.tot(), N); BOOST_CHECK_CLOSE(secondHalf.in(), 0.5 * N, 15); BOOST_CHECK_CLOSE(secondHalf.out(), 0.5 * N, 15); // Prob laying inside of interval should be 0.68 BOOST_CHECK_EQUAL(oneSigma.tot(), N); BOOST_CHECK_CLOSE(oneSigma.in(), 0.68 * N, 15); BOOST_CHECK_CLOSE(oneSigma.out(), 0.32 * N, 15); // Prob laying inside of interval should be 99,730 0204% BOOST_CHECK_EQUAL(threeSigma.tot(), N); BOOST_CHECK_CLOSE(threeSigma.in(), 0.99730 * N, 15); // Prob laying inside of interval should be 99,999 999 999 % BOOST_CHECK_EQUAL(eightSigma.tot(), N); BOOST_CHECK_CLOSE(eightSigma.in(), 0.9999 * N, 15); } BOOST_AUTO_TEST_CASE(rndGaussTwoNumbersMeanSigma) { int N = 1000; // Two random numbers will be added in each round int NTwo = 2 * N; double r1, r2; for(double mean = 1; mean < 5; mean += 1) { for(double sigma = 0.25; sigma < 0.65; sigma += 0.1) { // Check for whole interval DoubleBinCheck allnums(-DBL_MAX, DBL_MAX); // Check for median DoubleBinCheck firstHalf(-DBL_MAX, mean); DoubleBinCheck secondHalf(mean, DBL_MAX); // Check for increasing probability DoubleBinCheck oneSigma(mean - sigma, mean + sigma); DoubleBinCheck threeSigma(mean - 3 * sigma, mean + 3 * sigma); DoubleBinCheck eightSigma(mean - 8 * sigma, mean + 8 * sigma); for(int i = 0; i < N; ++i) { rng.rndGaussTwoNumbers(r1, r2, sigma, mean); allnums.add(r1); firstHalf.add(r1); secondHalf.add(r1); oneSigma.add(r1); threeSigma.add(r1); eightSigma.add(r1); allnums.add(r2); firstHalf.add(r2); secondHalf.add(r2); oneSigma.add(r2); threeSigma.add(r2); eightSigma.add(r2); } // Prob laying inside of interval should be 1 BOOST_CHECK_EQUAL(allnums.tot(), NTwo); BOOST_CHECK_EQUAL(allnums.in(), NTwo); BOOST_CHECK_EQUAL(allnums.out(), 0); // Prob laying inside of interval should be 0.5 BOOST_CHECK_EQUAL(firstHalf.tot(), NTwo); BOOST_CHECK_CLOSE(firstHalf.in(), 0.5 * NTwo, 15); BOOST_CHECK_CLOSE(firstHalf.out(), 0.5 * NTwo, 15); // Prob laying inside of interval should be 0.5 BOOST_CHECK_EQUAL(secondHalf.tot(), NTwo); BOOST_CHECK_CLOSE(secondHalf.in(), 0.5 * NTwo, 15); BOOST_CHECK_CLOSE(secondHalf.out(), 0.5 * NTwo, 15); // Prob laying inside of interval should be 0.68 BOOST_CHECK_EQUAL(oneSigma.tot(), NTwo); BOOST_CHECK_CLOSE(oneSigma.in(), 0.68 * NTwo, 15); BOOST_CHECK_CLOSE(oneSigma.out(), 0.32 * NTwo, 15); // Prob laying inside of interval should be 99,730 0204% BOOST_CHECK_EQUAL(threeSigma.tot(), NTwo); BOOST_CHECK_CLOSE(threeSigma.in(), 0.99730 * NTwo, 15); // Prob laying inside of interval should be 99,999 999 999 % BOOST_CHECK_EQUAL(eightSigma.tot(), NTwo); BOOST_CHECK_CLOSE(eightSigma.in(), 0.9999 * NTwo, 15); } } } BOOST_AUTO_TEST_CASE(rndPoisson) { int N = 1000; for(double mean = 5; mean < 21; mean += 5) { // Check for whole interval LongBinCheck zero2max(0, LONG_MAX); // Check for median LongBinCheck zero(0, mean); LongBinCheck secondHalf(mean, LONG_MAX); // Check for decreasing probability away from mean LongBinCheck nearMean(mean - std::sqrt(mean), mean + std::sqrt(mean)); LongBinCheck awayMean(mean + std::sqrt(mean), mean + 3 * std::sqrt(mean)); for(int i = 0; i < N; ++i) { zero2max.add(rng.rndPoisson(mean)); zero.add(rng.rndPoisson(mean)); secondHalf.add(rng.rndPoisson(mean)); nearMean.add(rng.rndPoisson(mean)); awayMean.add(rng.rndPoisson(mean)); } // Prob laying inside of interval should be 1 BOOST_CHECK_EQUAL(zero2max.tot(), N); BOOST_CHECK_EQUAL(zero2max.in(), N); BOOST_CHECK_EQUAL(zero2max.out(), 0); // Prob laying inside of interval should be 0.5 BOOST_CHECK_EQUAL(zero.tot(), N); BOOST_CHECK_CLOSE(zero.in(), 0.5 * N, 30); BOOST_CHECK_CLOSE(zero.out(), 0.5 * N, 30); // Prob laying inside of interval should be 0.5 BOOST_CHECK_EQUAL(secondHalf.tot(), N); BOOST_CHECK_CLOSE(secondHalf.in(), 0.5 * N, 30); BOOST_CHECK_CLOSE(secondHalf.out(), 0.5 * N, 30); // Prob should decrease away from mean BOOST_CHECK(nearMean.in() > awayMean.in()); } } BOOST_AUTO_TEST_CASE(rndBW) { int N = 1000; for(double mean = 5; mean < 21; mean += 5) { for (double gamma = 1; gamma < 5; gamma += 1) { // Check for whole interval DoubleBinCheck allnums(-DBL_MAX, DBL_MAX); // Check for median DoubleBinCheck firstHalf(-DBL_MAX, mean); DoubleBinCheck secondHalf(mean, DBL_MAX); // Check for decreasing probability away from mean DoubleBinCheck nearMean(mean - std::sqrt(gamma), mean + std::sqrt(gamma)); DoubleBinCheck awayMeanOne(mean + std::sqrt(gamma), mean + 3 * std::sqrt(gamma)); // Additional check for symmetry DoubleBinCheck awayMeanTwo(mean - 3 * std::sqrt(gamma), mean - std::sqrt(gamma)); for(int i = 0; i < N; ++i) { allnums.add(rng.rndBW(mean, gamma)); firstHalf.add(rng.rndBW(mean, gamma)); secondHalf.add(rng.rndBW(mean, gamma)); nearMean.add(rng.rndBW(mean, gamma)); awayMeanOne.add(rng.rndBW(mean, gamma)); awayMeanTwo.add(rng.rndBW(mean, gamma)); } // Prob laying inside of interval should be 1 BOOST_CHECK_EQUAL(allnums.tot(), N); BOOST_CHECK_EQUAL(allnums.in(), N); BOOST_CHECK_EQUAL(allnums.out(), 0); // Prob laying inside of interval should be 0.5 BOOST_CHECK_EQUAL(firstHalf.tot(), N); BOOST_CHECK_CLOSE(firstHalf.in(), 0.5 * N, 30); BOOST_CHECK_CLOSE(firstHalf.out(), 0.5 * N, 30); // Prob laying inside of interval should be 0.5 BOOST_CHECK_EQUAL(secondHalf.tot(), N); BOOST_CHECK_CLOSE(secondHalf.in(), 0.5 * N, 30); BOOST_CHECK_CLOSE(secondHalf.out(), 0.5 * N, 30); // Prob should decrease away from mean BOOST_CHECK(nearMean.in() > awayMeanOne.in()); // Prob should be roughly symmetric with a shift to the left or right BOOST_CHECK_CLOSE(1.0 * awayMeanTwo.in(), 1.0 * awayMeanOne.in(), 60); } } } BOOST_AUTO_TEST_CASE(rndBWCut) { int N = 1000; double cutValue = 2; for(double mean = 5; mean < 10; mean += 2) { for (double gamma = 1; gamma < 5; gamma += 1) { // Check for whole interval DoubleBinCheck allnums(-DBL_MAX, DBL_MAX); // Check for cut interval DoubleBinCheck inCut(mean - cutValue, mean + cutValue); // Check for median DoubleBinCheck firstHalf(-DBL_MAX, mean); DoubleBinCheck secondHalf(mean, DBL_MAX); // Check for decreasing probability away from mean DoubleBinCheck nearMean(mean - std::sqrt(gamma), mean + std::sqrt(gamma)); DoubleBinCheck awayMeanOne(mean + std::sqrt(gamma), mean + 3 * std::sqrt(gamma)); // Additional check for symmetry DoubleBinCheck awayMeanTwo(mean - 3 * std::sqrt(gamma), mean - std::sqrt(gamma)); for(int i = 0; i < N; ++i) { allnums.add(rng.rndBW(mean, gamma, cutValue)); inCut.add(rng.rndBW(mean, gamma, cutValue)); firstHalf.add(rng.rndBW(mean, gamma, cutValue)); secondHalf.add(rng.rndBW(mean, gamma, cutValue)); nearMean.add(rng.rndBW(mean, gamma, cutValue)); awayMeanOne.add(rng.rndBW(mean, gamma, cutValue)); awayMeanTwo.add(rng.rndBW(mean, gamma, cutValue)); } // Prob laying inside of interval should be 1 BOOST_CHECK_EQUAL(allnums.tot(), N); BOOST_CHECK_EQUAL(allnums.in(), N); BOOST_CHECK_EQUAL(allnums.out(), 0); // Prob laying inside of interval should be 1 BOOST_CHECK_EQUAL(inCut.tot(), N); BOOST_CHECK_EQUAL(inCut.in(), N); BOOST_CHECK_EQUAL(inCut.out(), 0); // Prob laying inside of interval should be 0.5 BOOST_CHECK_EQUAL(firstHalf.tot(), N); BOOST_CHECK_CLOSE(firstHalf.in(), 0.5 * N, 30); BOOST_CHECK_CLOSE(firstHalf.out(), 0.5 * N, 30); // Prob laying inside of interval should be 0.5 BOOST_CHECK_EQUAL(secondHalf.tot(), N); BOOST_CHECK_CLOSE(secondHalf.in(), 0.5 * N, 30); BOOST_CHECK_CLOSE(secondHalf.out(), 0.5 * N, 30); // Prob should decrease away from mean BOOST_CHECK(nearMean.in() > awayMeanOne.in()); // Prob should be roughly symmetric with a shift to the left or right BOOST_CHECK_CLOSE(1.0 * awayMeanTwo.in(), 1.0 * awayMeanOne.in(), 60); } } } BOOST_AUTO_TEST_CASE(rndRelBW) { int N = 1000; for(double mean = 5; mean < 21; mean += 5) { for (double gamma = 1; gamma < 5; gamma += 1) { // Check for whole interval DoubleBinCheck allnums(-DBL_MAX, DBL_MAX); // Check for median DoubleBinCheck firstHalf(-DBL_MAX, mean); DoubleBinCheck secondHalf(mean, DBL_MAX); // Check for decreasing probability away from mean DoubleBinCheck nearMean(mean - std::sqrt(gamma), mean + std::sqrt(gamma)); DoubleBinCheck awayMeanOne(mean + std::sqrt(gamma), mean + 3 * std::sqrt(gamma)); // Additional check for symmetry DoubleBinCheck awayMeanTwo(mean - 3 * std::sqrt(gamma), mean - std::sqrt(gamma)); for(int i = 0; i < N; ++i) { allnums.add(rng.rndRelBW(mean, gamma)); firstHalf.add(rng.rndRelBW(mean, gamma)); secondHalf.add(rng.rndRelBW(mean, gamma)); nearMean.add(rng.rndRelBW(mean, gamma)); awayMeanOne.add(rng.rndRelBW(mean, gamma)); awayMeanTwo.add(rng.rndRelBW(mean, gamma)); } // Prob laying inside of interval should be 1 BOOST_CHECK_EQUAL(allnums.tot(), N); BOOST_CHECK_EQUAL(allnums.in(), N); BOOST_CHECK_EQUAL(allnums.out(), 0); // Prob laying inside of interval should be 0.5 BOOST_CHECK_EQUAL(firstHalf.tot(), N); BOOST_CHECK_CLOSE(firstHalf.in(), 0.5 * N, 50); BOOST_CHECK_CLOSE(firstHalf.out(), 0.5 * N, 50); // Prob laying inside of interval should be 0.5 BOOST_CHECK_EQUAL(secondHalf.tot(), N); BOOST_CHECK_CLOSE(secondHalf.in(), 0.5 * N, 50); BOOST_CHECK_CLOSE(secondHalf.out(), 0.5 * N, 50); // Prob should decrease away from mean BOOST_CHECK(nearMean.in() > awayMeanOne.in()); // Prob should be roughly symmetric with a shift to the left or right BOOST_CHECK_CLOSE(1.0 * awayMeanTwo.in(), 1.0 * awayMeanOne.in(), 200); } } } BOOST_AUTO_TEST_CASE(rndRelBWCut) { int N = 1000; double cutValue = 2; for(double mean = 5; mean < 10; mean += 2) { for (double gamma = 1; gamma < 5; gamma += 1) { // Check for whole interval DoubleBinCheck allnums(-DBL_MAX, DBL_MAX); // Check for cut interval DoubleBinCheck inCut(mean - cutValue, mean + cutValue); // Check for median DoubleBinCheck firstHalf(-DBL_MAX, mean); DoubleBinCheck secondHalf(mean, DBL_MAX); // Check for decreasing probability away from mean DoubleBinCheck nearMean(mean - std::sqrt(gamma), mean + std::sqrt(gamma)); DoubleBinCheck awayMeanOne(mean + std::sqrt(gamma), mean + 3 * std::sqrt(gamma)); // Additional check for symmetry DoubleBinCheck awayMeanTwo(mean - 3 * std::sqrt(gamma), mean - std::sqrt(gamma)); for(int i = 0; i < N; ++i) { allnums.add(rng.rndRelBW(mean, gamma, cutValue)); inCut.add(rng.rndRelBW(mean, gamma, cutValue)); firstHalf.add(rng.rndRelBW(mean, gamma, cutValue)); secondHalf.add(rng.rndRelBW(mean, gamma, cutValue)); nearMean.add(rng.rndRelBW(mean, gamma, cutValue)); awayMeanOne.add(rng.rndRelBW(mean, gamma, cutValue)); awayMeanTwo.add(rng.rndRelBW(mean, gamma, cutValue)); } // Prob laying inside of interval should be 1 BOOST_CHECK_EQUAL(allnums.tot(), N); BOOST_CHECK_EQUAL(allnums.in(), N); BOOST_CHECK_EQUAL(allnums.out(), 0); // Prob laying inside of interval should be 1 BOOST_CHECK_EQUAL(inCut.tot(), N); BOOST_CHECK_EQUAL(inCut.in(), N); BOOST_CHECK_EQUAL(inCut.out(), 0); // Prob laying inside of interval should be 0.5 BOOST_CHECK_EQUAL(firstHalf.tot(), N); BOOST_CHECK_CLOSE(firstHalf.in(), 0.5 * N, 30); BOOST_CHECK_CLOSE(firstHalf.out(), 0.5 * N, 30); // Prob laying inside of interval should be 0.5 BOOST_CHECK_EQUAL(secondHalf.tot(), N); BOOST_CHECK_CLOSE(secondHalf.in(), 0.5 * N, 30); BOOST_CHECK_CLOSE(secondHalf.out(), 0.5 * N, 30); // Prob should decrease away from mean BOOST_CHECK(nearMean.in() > awayMeanOne.in()); // Prob should be roughly symmetric with a shift to the left or right BOOST_CHECK_CLOSE(1.0 * awayMeanTwo.in(), 1.0 * awayMeanOne.in(), 120); } } } BOOST_AUTO_TEST_SUITE_END() #endif /* ThePEG_Repository_Test_RandomGenerator_H */ diff --git a/Repository/tests/repositoryTestsGlobalFixture.h b/Repository/tests/repositoryTestsGlobalFixture.h --- a/Repository/tests/repositoryTestsGlobalFixture.h +++ b/Repository/tests/repositoryTestsGlobalFixture.h @@ -1,33 +1,33 @@ // -*- C++ -*- // // repositoryTestGlobalFixture.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad, 2015 Marco A. Harrendorf +// Copyright (C) 1999-2019 Leif Lonnblad, 2015 Marco A. Harrendorf // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_Repository_Tests_GlobalFixture_H #define ThePEG_Repository_Tests_GlobalFixture_H #include #include "ThePEG/Repository/StandardRandom.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Config/Unitsystem.h" struct FixGlobal1 { ThePEG::StandardRandom srng; ThePEG::UseRandom urng; FixGlobal1() : srng(), urng(&srng) { BOOST_TEST_MESSAGE( "setup global fixture for repositoryTest" ); } ~FixGlobal1() { BOOST_TEST_MESSAGE( "teardown global fixture for repositoryTest" ); } }; BOOST_GLOBAL_FIXTURE(FixGlobal1); #endif diff --git a/Repository/tests/repositoryTestsMain.cc b/Repository/tests/repositoryTestsMain.cc --- a/Repository/tests/repositoryTestsMain.cc +++ b/Repository/tests/repositoryTestsMain.cc @@ -1,37 +1,37 @@ // -*- C++ -*- // // repositoryTestMain.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad, 2015 Marco A. Harrendorf +// Copyright (C) 1999-2019 Leif Lonnblad, 2015 Marco A. Harrendorf // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // /** * The following part should be included only once. */ #define BOOST_TEST_DYN_LINK #define BOOST_TEST_MAIN #include #define BOOST_TEST_MODULE repositoryTest /** * Include global fixture * * Global fixture initializes the randomNumber generator */ #include "ThePEG/Repository/tests/repositoryTestsGlobalFixture.h" /** * Include here the sub tests */ #include "ThePEG/Repository/tests/repositoryTestRandomGenerator.h" /** * Debug and development part */ BOOST_AUTO_TEST_CASE(fail) { //BOOST_FAIL("Ende"); } diff --git a/StandardModel/AlphaEMBase.cc b/StandardModel/AlphaEMBase.cc --- a/StandardModel/AlphaEMBase.cc +++ b/StandardModel/AlphaEMBase.cc @@ -1,28 +1,28 @@ // -*- C++ -*- // // AlphaEMBase.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the AlphaEMBase class. // #include "AlphaEMBase.h" #include "ThePEG/Interface/ClassDocumentation.h" using namespace ThePEG; AbstractNoPIOClassDescription AlphaEMBase::initAlphaEMBase; void AlphaEMBase::Init() { static ClassDocumentation documentation ("An abstract base class used by the StandardModelBase class to " "implement the electro-magnetic coupling."); } diff --git a/StandardModel/AlphaEMBase.h b/StandardModel/AlphaEMBase.h --- a/StandardModel/AlphaEMBase.h +++ b/StandardModel/AlphaEMBase.h @@ -1,72 +1,72 @@ // -*- C++ -*- // // AlphaEMBase.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_AlphaEMBase_H #define ThePEG_AlphaEMBase_H // This is the declaration of the AlphaEMBase class. #include "RunningCoupling.h" namespace ThePEG { /** * AlphaEMBase an abstract base class used by the StandardModelBase * class to implement the electro-magnetic coupling. Concrete * sub-classes must implement the value(Energy2, const * StandardModelBase &) function. * * @see \ref AlphaEMBaseInterfaces "The interfaces" * defined for AlphaEMBase. * @see StandardModelBase */ class AlphaEMBase: public RunningCoupling { public: /** * Standard Init function used to initialize the interface. */ static void Init(); private: /** * Describe an abstract class without persistent data. */ static AbstractNoPIOClassDescription initAlphaEMBase; /** * Private and non-existent assignment operator. */ AlphaEMBase & operator=(const AlphaEMBase &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the base classes * of AlphaEMBase. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of AlphaEMBase. */ typedef RunningCoupling NthBase; }; /** This template specialization informs ThePEG about the name of the * AlphaEMBase class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "ThePEG::AlphaEMBase"; } }; /** @endcond */ } #endif /* ThePEG_AlphaEMBase_H */ diff --git a/StandardModel/AlphaSBase.cc b/StandardModel/AlphaSBase.cc --- a/StandardModel/AlphaSBase.cc +++ b/StandardModel/AlphaSBase.cc @@ -1,54 +1,54 @@ // -*- C++ -*- // // AlphaSBase.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the AlphaSBase class. // #include "AlphaSBase.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/ParVector.h" using namespace ThePEG; void AlphaSBase::doinit() { theFlavourThresholds = flavourThresholds(); theLambdaQCDs = LambdaQCDs(); RunningCoupling::doinit(); } void AlphaSBase::persistentOutput(PersistentOStream & os) const { os << ounit(theQuarkMasses,GeV) << ounit(theFlavourThresholds, GeV2) << ounit(theLambdaQCDs, GeV); } void AlphaSBase::persistentInput(PersistentIStream & is, int) { is >> iunit(theQuarkMasses,GeV) >> iunit(theFlavourThresholds, GeV2) >> iunit(theLambdaQCDs, GeV); } AbstractClassDescription AlphaSBase::initAlphaSBase; void AlphaSBase::Init() { static ClassDocumentation documentation ("An abstract base class used by the StandardModelBase to implement the " "QCD coupling."); static ParVector interfaceQuarkMasses ("QuarkMasses", "The quark masses to be used instead of the masses set in the particle data.", &AlphaSBase::theQuarkMasses, GeV, -1, 0.0*GeV, 0.0*GeV, 0*GeV, false, false, Interface::lowerlim); } diff --git a/StandardModel/AlphaSBase.h b/StandardModel/AlphaSBase.h --- a/StandardModel/AlphaSBase.h +++ b/StandardModel/AlphaSBase.h @@ -1,174 +1,174 @@ // -*- C++ -*- // // AlphaSBase.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_AlphaSBase_H #define ThePEG_AlphaSBase_H // This is the declaration of the AlphaSBase class. #include "RunningCoupling.h" namespace ThePEG { /** * AlphaSBase is an abstract base class used by the StandardModelBase * to implement the QCD coupling, \f$\alpha_S\f$. The AlphaSBase also * encodes the number of active flavours at a given scale and the * \f$\Lambda_{QCD}\f$ for a given number of active flavours or for a * given scale. * * @see \ref AlphaSBaseInterfaces "The interfaces" * defined for AlphaSBase. * @see StandardModelBase */ class AlphaSBase: public RunningCoupling { public: /** @name Virtual functions to be overridden by sub-classes. */ //@{ /** * Return the flavour thresholds used. The returned vector contains * (in position i) the scales when the active number of * flavours changes from i to i+1. */ virtual vector flavourThresholds() const = 0; /** * Return the \f$\Lambda_{QCD}\f$ used for different numbers of * active flavours. */ virtual vector LambdaQCDs() const = 0; //@} /** @name Access information about number of flavours and \f$\Lambda_{QCD}\f$. */ //@{ /** * Return the number of avtive quark flavours. */ unsigned int Nf(Energy2 scale) const { unsigned int i = 0; while ( i < theFlavourThresholds.size() && theFlavourThresholds[i] < scale ) ++i; return i; } /** * Return the \f$\Lambda_{QCD}\f$ used for \a nflav active flavours. */ Energy LambdaQCD(unsigned int nflav) const { return theLambdaQCDs[nflav]; } /** * Return the \f$\Lambda_{QCD}\f$ used for corresponding given \a scale. */ Energy LambdaQCD(Energy2 scale) const { return theLambdaQCDs[Nf(scale)]; } //@} /** * Return the quark masses to be used; if not empty these masses * should be considered instead of the ones set in the particle data * objects. */ const vector& quarkMasses() const { return theQuarkMasses; } public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interface. */ static void Init(); protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); //@} private: /** * The quark masses to be used; if not empty these masses * should be considered instead of the ones set in the particle data * objects. */ vector theQuarkMasses; /** * Flavour thresholds, set from the virtual functions in the * initialization. */ vector theFlavourThresholds; /** * The values of \f$\Lambda_{QCD}\f$ corresponding to * theFlavourThresholds, set from the virtual functions in the * initialization. */ vector theLambdaQCDs; private: /** * Describe an abstract class with persistent data. */ static AbstractClassDescription initAlphaSBase; /** * Private and non-existent assignment operator. */ AlphaSBase & operator=(const AlphaSBase &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the base classes * of AlphaSBase. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of AlphaSBase. */ typedef RunningCoupling NthBase; }; /** This template specialization informs ThePEG about the name of the * AlphaSBase class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "ThePEG::AlphaSBase"; } }; /** @endcond */ } #endif /* ThePEG_AlphaSBase_H */ diff --git a/StandardModel/CKMBase.cc b/StandardModel/CKMBase.cc --- a/StandardModel/CKMBase.cc +++ b/StandardModel/CKMBase.cc @@ -1,30 +1,30 @@ // -*- C++ -*- // // CKMBase.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the CKMBase class. // #include "CKMBase.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Interface/ClassDocumentation.h" using namespace ThePEG; AbstractNoPIOClassDescription CKMBase::initCKMBase; void CKMBase::Init() { static ClassDocumentation documentation ("An abstract base classused by the StandardModelBase to implement " "the Cabibbo-Kobayashi-Mascawa mixing matrix."); } diff --git a/StandardModel/CKMBase.h b/StandardModel/CKMBase.h --- a/StandardModel/CKMBase.h +++ b/StandardModel/CKMBase.h @@ -1,81 +1,81 @@ // -*- C++ -*- // // CKMBase.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_CKMBase_H #define ThePEG_CKMBase_H // This is the declaration of the CKMBase class. #include "ThePEG/Interface/Interfaced.h" #include "StandardModelBase.fh" namespace ThePEG { /** * CKMBase is an abstract base classused by the StandardModelBase to * implement the Cabibbo-Kobayashi-Mascawa mixing matrix. Concrete * sub-classes must implement the getMatrix(unsigned int) function. * * @see \ref CKMBaseInterfaces "The interfaces" * defined for CKMBase. * @see StandardModelBase */ class CKMBase: public Interfaced { public: /** * Return the matrix of squared CKM matrix elements. The returned * matrix should be for \a nf families. This function must be * overridden by sub-classes. */ virtual vector< vector > getMatrix(unsigned int nf) const = 0; public: /** * Standard Init function used to initialize the interface. */ static void Init(); private: /** * Describe an abstract class without persistent data. */ static AbstractNoPIOClassDescription initCKMBase; /** * Private and non-existent assignment operator. */ CKMBase & operator=(const CKMBase &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the base classes * of CKMBase. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of CKMBase. */ typedef Interfaced NthBase; }; /** This template specialization informs ThePEG about the name of the * CKMBase class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "ThePEG::CKMBase"; } }; /** @endcond */ } #endif /* ThePEG_CKMBase_H */ diff --git a/StandardModel/O1AlphaS.cc b/StandardModel/O1AlphaS.cc --- a/StandardModel/O1AlphaS.cc +++ b/StandardModel/O1AlphaS.cc @@ -1,141 +1,141 @@ // -*- C++ -*- // // O1AlphaS.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the O1AlphaS class. // #include "O1AlphaS.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/ClassDocumentation.h" using namespace ThePEG; IBPtr O1AlphaS::clone() const { return new_ptr(*this); } IBPtr O1AlphaS::fullclone() const { return new_ptr(*this); } double O1AlphaS::value(Energy2 scale, const StandardModelBase &) const { Energy2 theScale = scaleFactor()*scale; return 12.0*Constants::pi/((33.0-2.0*Nf(theScale))* log(max(theScale, sqr(Q0))/sqr(LambdaQCD(Nf(theScale))))); } vector O1AlphaS::flavourThresholds() const { if ( !quarkMasses().empty() ) { int nMasses = quarkMasses().size(); if ( nMasses != theMaxFlav ) throw InitException() << "External masses set in O1AlphaS but not for all flavours."; } vector thresholds; for ( long f = 1; f <= theMaxFlav; ++f ) { if ( quarkMasses().empty() ) { PDPtr p = getParticleData(f); if ( p ) thresholds.push_back(sqr((p->mass() + p->CC()->mass())/2.)); } else { thresholds.push_back(sqr(quarkMasses()[f-1])); } } std::sort(thresholds.begin(), thresholds.end()); return thresholds; } vector O1AlphaS::LambdaQCDs() const { vector lambdas(theMaxFlav + 1); vector thresholds = flavourThresholds(); lambdas[theLambdaFlavour] = theLambdaQCD; for ( int f = theLambdaFlavour - 1; f >= 0; --f ) { if ( thresholds[f] > ZERO ) { lambdas[f] = sqrt(thresholds[f]* exp(-log(thresholds[f]/sqr(lambdas[f + 1]))* (33.0-2.0*(f+1))/(33.0-2.0*f))); } else { lambdas[f] = lambdas[f + 1]; } } for ( int f = theLambdaFlavour; f < theMaxFlav; ++f ) { if ( thresholds[f] > ZERO ) { lambdas[f + 1] = sqrt(thresholds[f]* exp(-log(thresholds[f]/sqr(lambdas[f]))* (33.0-2.0*f)/(33.0-2.0*(f+1)))); } else { lambdas[f + 1] = lambdas[f]; } } return lambdas; } void O1AlphaS::persistentOutput(PersistentOStream & os) const { os << ounit(theLambdaQCD, GeV) << theLambdaFlavour << theMaxFlav << ounit(Q0, GeV); } void O1AlphaS::persistentInput(PersistentIStream & is, int) { is >> iunit(theLambdaQCD, GeV) >> theLambdaFlavour >> theMaxFlav >> iunit(Q0, GeV); } ClassDescription O1AlphaS::initO1AlphaS; void O1AlphaS::Init() { static ClassDocumentation documentation ("O1AlphaS inherits from AlphaSBase and implements the leading order " "running QCD coupling. The value is determined by the " "LambdaQCD parameter at a given number of " "flavours, LambdaFlav. Optionally the coupling " "can be frozen under some minimum scale, " "FreezeScale to avoid divergencies or negative " "couplings."); static Parameter interfaceLambdaQCD ("LambdaQCD", "The \\f$\\Lambda_{QCD}\\f$ in GeV for " "LambdaFlav active " "flavours. The value for other numbers of active flavours is derived by " "assuming that \\f$\\alpha_S\\f$ is continuous.", &O1AlphaS::theLambdaQCD, GeV, 0.25*GeV, ZERO, ZERO, false, false, Interface::lowerlim); static Parameter interfaceMaxFlav ("MaxFlav", "The maximum number of flavours used to calculate \\f$\\alpha_S\\f$.", &O1AlphaS::theMaxFlav, 6, 3, 8, false, false, true); typedef void (ThePEG::O1AlphaS::*IFN)(int); static Parameter interfaceLambdaFlavour ("LambdaFlav", "The number of active flavours for which LambdaQCD is specified.", &O1AlphaS::theLambdaFlavour, 4, 3, 8, false, false, true, (IFN)0, 0, 0, &O1AlphaS::getMaxFlav, 0); static Parameter interfaceFreezeScale ("FreezeScale", "The scale in units of GeV below which \\f$\\alpha_S\\f$ is frozen.", &O1AlphaS::Q0, GeV, ZERO, ZERO, ZERO, true, false, Interface::lowerlim); interfaceLambdaQCD.rank(10); interfaceLambdaFlavour.rank(9); interfaceFreezeScale.rank(8); } diff --git a/StandardModel/O1AlphaS.h b/StandardModel/O1AlphaS.h --- a/StandardModel/O1AlphaS.h +++ b/StandardModel/O1AlphaS.h @@ -1,183 +1,183 @@ // -*- C++ -*- // // O1AlphaS.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_O1AlphaS_H #define ThePEG_O1AlphaS_H // This is the declaration of the O1AlphaS class. #include "AlphaSBase.h" namespace ThePEG { /** * O1AlphaS inherits from AlphaSBase and implements the leading order * running QCD coupling. The value is determined by a * \f$\Lambda_{QCD}\f$ parameter at a given number of * flavours. Optionally the coupling can be frozen under some minimum * scale to avoid divergencies or negative couplings. * * @see \ref O1AlphaSInterfaces "The interfaces" * defined for O1AlphaS. */ class O1AlphaS: public AlphaSBase { public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ O1AlphaS() : theLambdaQCD(0.25*GeV), theLambdaFlavour(4), theMaxFlav(6), Q0(ZERO) {} //@} public: /** @name Virtual functions mandated by the sub-class. */ //@{ /** * The \f$\alpha_S\f$. Return the QCD coupling for a given \a scale * using the given standard model object \a sm. */ virtual double value(Energy2 scale, const StandardModelBase &) const; /** * Return the number of loops contributing to * the running this coupling. */ virtual unsigned int nloops () const { return 1; } /** * Return the flavour thresholds used. The returned vector contains * (in position i) the scales when the active number of * flavours changes from i to i+1. */ virtual vector flavourThresholds() const; /** * Return the \f$\Lambda_{QCD}\f$ used for different numbers of * active flavours. */ virtual vector LambdaQCDs() const; //@} /** * Return the maximum number of active flavours. */ int getMaxFlav() const { return theMaxFlav; } public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interface. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * The \f$\Lambda_{QCD}\f$ for the number of flavours specified by * theLambdaFlavour. Other \f$\Lambda_{QCD}\f$ values for other * numbers of active flavours are calculated from * flavourThresholds() using a continuity requirement. */ Energy theLambdaQCD; /** * The number of flavours for which theLambdaQCD is given. */ int theLambdaFlavour; /** * The maximum number of active flavours. */ int theMaxFlav; /** * The scale below which \f$\alpha_S\f$ is frozen. */ Energy Q0; private: /** * Describe a concrete class with persistent data. */ static ClassDescription initO1AlphaS; /** * Private and non-existent assignment operator. */ O1AlphaS & operator=(const O1AlphaS &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the base classes * of O1AlphaS. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of O1AlphaS. */ typedef AlphaSBase NthBase; }; /** This template specialization informs ThePEG about the name of the * O1AlphaS 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::O1AlphaS"; } /** Return the name of the shared library be loaded to get access to * the O1AlphaS class and every other class it uses * (except the base class). */ static string library() { return "O1AlphaS.so"; } }; /** @endcond */ } #endif /* ThePEG_O1AlphaS_H */ diff --git a/StandardModel/RunningCoupling.cc b/StandardModel/RunningCoupling.cc --- a/StandardModel/RunningCoupling.cc +++ b/StandardModel/RunningCoupling.cc @@ -1,47 +1,47 @@ // -*- C++ -*- // // RunningCoupling.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the RunningCoupling class. // #include "RunningCoupling.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace ThePEG; AbstractClassDescription RunningCoupling::initRunningCoupling; void RunningCoupling::persistentOutput(PersistentOStream & os) const { os << theScaleFactor; } void RunningCoupling::persistentInput(PersistentIStream & is, int) { is >> theScaleFactor; } void RunningCoupling::Init() { static ClassDocumentation documentation ("An abstract base class used to implement running couplings."); static Parameter interfaceScaleFactor ("ScaleFactor", "The scale factor used to globally rescale the argument of the running coupling", &RunningCoupling::theScaleFactor, 1.0, 0.0, 0, false, false, Interface::lowerlim); interfaceScaleFactor.rank(-1); } diff --git a/StandardModel/RunningCoupling.h b/StandardModel/RunningCoupling.h --- a/StandardModel/RunningCoupling.h +++ b/StandardModel/RunningCoupling.h @@ -1,153 +1,153 @@ // -*- C++ -*- // // RunningCoupling.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad, (C) 2009 Simon Platzer +// Copyright (C) 1999-2019 Leif Lonnblad, (C) 2009 Simon Platzer // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_RunningCoupling_H #define ThePEG_RunningCoupling_H // This is the declaration of the RunningCoupling class. #include "ThePEG/Interface/Interfaced.h" #include "ThePEG/Repository/EventGenerator.h" #include "StandardModelBase.fh" namespace ThePEG { /** * RunningCoupling an abstract base class unifying the treatment * of running couplings in ThePEG. * * @see \ref RunningCouplingInterfaces "The interfaces" * defined for RunningCoupling. * @see StandardModelBase */ class RunningCoupling: public Interfaced { public: /** * The default constructor. */ RunningCoupling () : theScaleFactor(1.) {} /**@name Methods to be implemented by a derived class */ //@{ /** * Return the value of the coupling at a given \a scale using the * given standard model object, \a sm. */ virtual double value (Energy2 scale, const StandardModelBase & sm) const = 0; /** * Return the number of loops contributing to * the running this coupling. The default returns * zero to ensure backward compatibility. */ virtual unsigned int nloops () const { return 0; } //@} /** * Return the value of the coupling at a given \a scale using the * StandardModelBase object used by the EventGenerator. */ double value(Energy2 scale) const { return value(scale,*(generator()->standardModel())); } /** * Return an overestimate to the running coupling at the * given scale. This is defined to aid veto algorithms * and by default returns the coupling itself, using the EventGenerators's * StandardModelBase object. */ virtual double overestimateValue (Energy2 scale) const { return value(scale); } /** * Return the ratio of the exact to the overestimated value * of the running coupling. The default implementation returns * one in accordance with the default implementation of * overestimateValue */ virtual double ratioToOverestimate (Energy2) const { return 1.; } /** * Return the scale factor, which may be used to globally * rescale the argument of the running coupling. */ double scaleFactor () const { return theScaleFactor; } public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interface. */ static void Init(); private: /** * Describe an abstract class without persistent data. */ static AbstractClassDescription initRunningCoupling; /** * Private and non-existent assignment operator. */ RunningCoupling & operator=(const RunningCoupling &) = delete; /** * The scale factor used to rescale the argument of * the running coupling. */ double theScaleFactor; }; /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the base classes * of RunningCoupling. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of RunningCoupling. */ typedef Interfaced NthBase; }; /** This template specialization informs ThePEG about the name of the * RunningCoupling class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "ThePEG::RunningCoupling"; } }; /** @endcond */ } #endif /* ThePEG_RunningCoupling_H */ diff --git a/StandardModel/SimpleAlphaEM.cc b/StandardModel/SimpleAlphaEM.cc --- a/StandardModel/SimpleAlphaEM.cc +++ b/StandardModel/SimpleAlphaEM.cc @@ -1,58 +1,58 @@ // -*- C++ -*- // // SimpleAlphaEM.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the SimpleAlphaEM class. // #include "SimpleAlphaEM.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/StandardModel/StandardModelBase.h" using namespace ThePEG; IBPtr SimpleAlphaEM::clone() const { return new_ptr(*this); } IBPtr SimpleAlphaEM::fullclone() const { return new_ptr(*this); } double SimpleAlphaEM::value(Energy2 scale, const StandardModelBase & sm) const { useMe(); double alem = sm.alphaEM(); double alem3pi = alem/(3.0*Constants::pi); double rpigg; double Q2 = scaleFactor()*scale/GeV2; if(Q2<=2e-6) rpigg=0.; else if ( Q2 < 0.09 ) rpigg = alem3pi*(13.4916 + log(Q2)) + 0.00835*log(1.0 + Q2); else if ( Q2 < 9.0 ) rpigg=alem3pi*(16.3200 + 2.0*log(Q2)) + 0.00238*log(1.0 + 3.927*Q2); else if ( Q2 < 10000.0 ) rpigg=alem3pi*(13.4955 + 3.0*log(Q2)) + 0.00165 + 0.00299*log(1.0 + Q2); else rpigg=alem3pi*(13.4955 + 3.0*log(Q2)) + 0.00221 + 0.00293*log(1.0 + Q2); return alem/(1.0-rpigg); } NoPIOClassDescription SimpleAlphaEM::initSimpleAlphaEM; void SimpleAlphaEM::Init() { static ClassDocumentation interfaceDocumentation ("This class implements a running \\f$\\alpha_{\\mbox{EM}}\\f$ according " "to Buckhardt et al.", "In the running of $\\alpha_{EM}$, the parametrization of " "H.~Buckhardt et al. was used. See \\cite{KLEISSCERN9808v3pp129}.", "\\bibitem{KLEISSCERN9808v3pp129} R.~Kleiss et al, " "CERN 89-08, vol.~3, pp 129-131."); } diff --git a/StandardModel/SimpleAlphaEM.h b/StandardModel/SimpleAlphaEM.h --- a/StandardModel/SimpleAlphaEM.h +++ b/StandardModel/SimpleAlphaEM.h @@ -1,106 +1,106 @@ // -*- C++ -*- // // SimpleAlphaEM.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_SimpleAlphaEM_H #define ThePEG_SimpleAlphaEM_H // This is the declaration of the SimpleAlphaEM class. #include "AlphaEMBase.h" namespace ThePEG { /** * SimpleAlphaEM inherits from AlphaEMBase and implements a simple * running of the electromagnetic coupling as parameterized by * H.~Buckhardt et al. * * @see \ref SimpleAlphaEMInterfaces "The interfaces" * defined for SimpleAlphaEM. */ class SimpleAlphaEM: public AlphaEMBase { public: /** * The \f$\alpha_{EM}\f$. Return the value of the coupling at a * given \a scale using the given standard model object, \a sm. */ virtual double value(Energy2 scale, const StandardModelBase &) const; /** * Return the number of loops contributing to * the running this coupling. */ virtual unsigned int nloops () const { return 1; } public: /** * Standard Init function used to initialize the interface. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * Describe a concrete class without persistent data. */ static NoPIOClassDescription initSimpleAlphaEM; /** * Private and non-existent assignment operator. */ SimpleAlphaEM & operator=(const SimpleAlphaEM &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the base classes * of SimpleAlphaEM. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of SimpleAlphaEM. */ typedef AlphaEMBase NthBase; }; /** This template specialization informs ThePEG about the name of the * SimpleAlphaEM 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::SimpleAlphaEM"; } /** Return the name of the shared library be loaded to get access to * the SimpleAlphaEM class and every other class it uses * (except the base class). */ static string library() { return "SimpleAlphaEM.so"; } }; /** @endcond */ } #endif /* ThePEG_SimpleAlphaEM_H */ diff --git a/StandardModel/StandardCKM.cc b/StandardModel/StandardCKM.cc --- a/StandardModel/StandardCKM.cc +++ b/StandardModel/StandardCKM.cc @@ -1,106 +1,106 @@ // -*- C++ -*- // // StandardCKM.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the StandardCKM class. // #include "StandardCKM.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/ClassDocumentation.h" using namespace ThePEG; IBPtr StandardCKM::clone() const { return new_ptr(*this); } IBPtr StandardCKM::fullclone() const { return new_ptr(*this); } vector< vector > StandardCKM::getMatrix(unsigned int nFamilies) const { vector< vector > ckm(nFamilies, vector(nFamilies, 0.0)); for ( unsigned int i = 0; i < nFamilies; ++i ) ckm[i][i] = 1.0; if ( nFamilies <= 1 ) return ckm; double s12 = sin(theta12); double c12 = cos(theta12); if ( nFamilies == 2 ) { ckm[0][0] = sqr(c12); ckm[0][1] = sqr(s12); ckm[1][0] = sqr(s12); ckm[1][1] = sqr(c12); return ckm; } double s13 = sin(theta13); double c13 = cos(theta13); double s23 = sin(theta23); double c23 = cos(theta23); double cd = cos(delta); ckm[0][0] = sqr(c12*c13); ckm[0][1] = sqr(s12*c13); ckm[0][2] = sqr(s13); ckm[1][0] = sqr(s12*c23)+sqr(c12*s23*s13)+2.0*s12*c23*c12*s23*s13*cd; ckm[1][1] = sqr(c12*c23)+sqr(s12*s23*s13)-2.0*c12*c23*s12*s23*s13*cd; ckm[1][2] = sqr(s23*c13); ckm[2][0] = sqr(s12*s23)+sqr(c12*c23*s13)-2.0*s12*s23*c12*c23*s13*cd; ckm[2][1] = sqr(c12*s23)+sqr(s12*c23*s13)+2.0*c12*s23*s12*c23*s13*cd; ckm[2][2] = sqr(c23*c13); return ckm; } void StandardCKM::persistentOutput(PersistentOStream & os) const { os << theta12 << theta13 << theta23 << delta; } void StandardCKM::persistentInput(PersistentIStream & is, int) { is >> theta12 >> theta13 >> theta23 >> delta; } ClassDescription StandardCKM::initStandardCKM; void StandardCKM::Init() { static ClassDocumentation documentation ("Implements the standard parameterization of the CKM matrix in terms " "of three angles and a phase."); static Parameter interfaceTheta12 ("theta_12", "The mixing angle between the first and second generation in the standard " "parameterization of the CKM matrix", &StandardCKM::theta12, 0.222357, 0.0, Constants::twopi, false, false, true); static Parameter interfaceTheta13 ("theta_13", "The mixing angle between the first and third generation in the standard " "parameterization of the CKM matrix", &StandardCKM::theta13, 0.0003150, 0.0, Constants::twopi, false, false, true); static Parameter interfaceTheta23 ("theta_23", "The mixing angle between the second and third generation in the standard " "parameterization of the CKM matrix", &StandardCKM::theta23, 0.039009, 0.0, Constants::twopi, false, false, true); static Parameter interfaceDelta ("delta", "The phase angle in the standard " "parameterization of the CKM matrix", &StandardCKM::delta, 1.35819, 0.0, Constants::twopi, false, false, true); interfaceTheta12.rank(10); interfaceTheta13.rank(9); interfaceTheta23.rank(8); interfaceDelta.rank(7); } diff --git a/StandardModel/StandardCKM.h b/StandardModel/StandardCKM.h --- a/StandardModel/StandardCKM.h +++ b/StandardModel/StandardCKM.h @@ -1,151 +1,151 @@ // -*- C++ -*- // // StandardCKM.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_StandardCKM_H #define ThePEG_StandardCKM_H // This is the declaration of the StandardCKM class. #include "CKMBase.h" namespace ThePEG { /** * StandardCKM inherits from CKMBase and implements the standard * parameterization of the CKM matrix in terms of three angles and a * phase. * * @see \ref StandardCKMInterfaces "The interfaces" * defined for StandardCKM. */ class StandardCKM: public CKMBase { public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ StandardCKM() : theta12(0.222357), theta13(0.0003150), theta23(0.039009), delta(1.35819) {} //@} public: /** * Return the matrix of squared CKM matrix elements. The returned * matrix should be for \a nf families. */ virtual vector< vector > getMatrix(unsigned int nFamilies) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interface. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * The \f$\theta_{12}\f$ angle. */ double theta12; /** * The \f$\theta_{13}\f$ angle. */ double theta13; /** * The \f$\theta_{23}\f$ angle. */ double theta23; /** * The \f$\delta\f$ angle describing the phase. */ double delta; private: /** * Describe a concrete class with persistent data. */ static ClassDescription initStandardCKM; /** * Private and non-existent assignment operator. */ StandardCKM & operator=(const StandardCKM &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the base classes * of StandardCKM. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of StandardCKM. */ typedef CKMBase NthBase; }; /** This template specialization informs ThePEG about the name of the * StandardCKM 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::StandardCKM"; } /** Return the name of the shared library be loaded to get access to * the StandardCKM class and every other class it uses * (except the base class). */ static string library() { return "StandardCKM.so"; } }; /** @endcond */ } #endif /* ThePEG_StandardCKM_H */ diff --git a/StandardModel/StandardModelBase.cc b/StandardModel/StandardModelBase.cc --- a/StandardModel/StandardModelBase.cc +++ b/StandardModel/StandardModelBase.cc @@ -1,381 +1,381 @@ // -*- C++ -*- // // StandardModelBase.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the StandardModelBase class. // #include "StandardModelBase.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/PDT/ParticleData.h" using namespace ThePEG; StandardModelBase::StandardModelBase() : theFamilies(3), theAlphaEM(1.0/137.04), theAlphaEMMZ(1.0/128.91), theSin2ThetaW(0.232), theGF(1.16637e-5/GeV2), theEnu(0.0), theEe(-1.0), theEu(2.0/3.0), theEd(-1.0/3.0), theVnu(1.0), theVe(-0.072), theVu(0.381333333), theVd(-0.690666666), theAnu(1.0), theAe(-1.0), theAu(1.0), theAd(-1.0), recalculateEW(1), theNc(3), theAlphaS(0.2), theElectroWeakScheme(0), theBosonWidthOption(0) {} StandardModelBase::~StandardModelBase() {} IBPtr StandardModelBase::clone() const { return new_ptr(*this); } IBPtr StandardModelBase::fullclone() const { return new_ptr(*this); } void StandardModelBase::doinit() { // calculation of the electroweak parameters // get the default values PDPtr Wplus = getParticleData(ParticleID::Wplus); PDPtr Z0 = getParticleData(ParticleID::Z0 ); Energy mw = Wplus->mass(), mz = Z0->mass(); double sw2 = sin2ThetaW(); double alpha = theAlphaEMMZ; InvEnergy2 GF = theGF; // recalculate if needed if(theElectroWeakScheme==1) { sw2 = 1.-sqr(mw/mz); alpha = sqrt(2.)*fermiConstant()*sqr(mw)*sw2/Constants::pi; } else if(theElectroWeakScheme==2) { sw2 = 1.-sqr(mw/mz); GF = Constants::pi*alpha/sqrt(2.)/sqr(mw)/sw2; } else if(theElectroWeakScheme==3) { mw = sqrt(4.*Constants::pi*alpha/4./sqrt(2.)/fermiConstant()/sw2); mz = mw/sqrt(1.-sw2); } else if(theElectroWeakScheme==4) { mz = mw/sqrt(1.-sw2); alpha = 4.*sqrt(2.)*fermiConstant()*sqr(mw)*sw2/4./Constants::pi; } else if(theElectroWeakScheme==5) { mw = mz*sqrt(1.-sw2); GF = Constants::pi*alpha/sqrt(2.)/sqr(mw)/sw2; } else if(theElectroWeakScheme==7) { mw = sqrt(sqr(mz)/2.+sqrt(sqr(mz)*sqr(mz)/4. -Constants::pi*alpha*sqr(mz)/sqrt(2.)/fermiConstant())); sw2 = 1.-sqr(mw/mz); } // reset if needed if(theElectroWeakScheme!=0) { recalculateEW = true; theSin2ThetaW = sw2; theAlphaEMMZ = alpha; theGF=GF; ostringstream os; os << setprecision(12) << mw/GeV; generator()->preinitInterface(Wplus, "NominalMass", "set", os .str()); ostringstream os2; os2 << setprecision(12) << mz/GeV; generator()->preinitInterface(Z0 , "NominalMass", "set", os2.str()); } if ( recalculateEW ) { theAnu = theEnu < 0? -1.0: 1.0; theAe = theEe < 0? -1.0: 1.0; theAd = theEd < 0? -1.0: 1.0; theAu = theEu < 0? -1.0: 1.0; theVnu = theAnu - 4.0*theEnu*sin2ThetaW(); theVe = theAe - 4.0*theEe*sin2ThetaW(); theVd = theAd - 4.0*theEd*sin2ThetaW(); theVu = theAu - 4.0*theEu*sin2ThetaW(); } theRunningAlphaEM->init(); theCKM->init(); theRunningAlphaS->init(); theCKM2Matrix = theCKM->getMatrix(families()); // calculate W/Z widths if needed if(theBosonWidthOption!=0) { //@TODO: Do we want theGF here? InvEnergy2 GF = Constants::pi*alpha/sqrt(2.)/sqr(mw)/sw2; double aSpi = theBosonWidthOption > 1 ? .1184/Constants::pi : 0.; double C = 1.+aSpi + sqr(aSpi)*(1.409-12.77*aSpi-80.0*sqr(aSpi)); Energy widthW = GF*pow<3,1>(mw)/(6.*sqrt(2.)*Constants::pi)* 3.*(1.+C*(CKM(1,1)+CKM(1,2)+CKM(1,3)+CKM(2,1)+CKM(2,2)+CKM(2,3))); Energy widthZ = 0.25*GF*pow<3,1>(mz)/(6.*sqrt(2.)*Constants::pi)* (3. *(sqr(theVnu)+sqr(theAnu)) + 3. *(sqr(theVe )+sqr(theAe )) + 9.*C*(sqr(theVd )+sqr(theAd )) + 6.*C*(sqr(theVu )+sqr(theAu ))); ostringstream os; os << widthW/GeV; generator()->preinitInterface(Wplus, "Width" , "set", os .str()); ostringstream os2; os2 << widthZ/GeV; generator()->preinitInterface(Z0 , "Width" , "set", os2.str()); } Interfaced::doinit(); } double StandardModelBase::CKM(unsigned int uFamily, unsigned int dFamily) const { if ( theCKM2Matrix.empty() ) theCKM2Matrix = theCKM->getMatrix(families()); if ( uFamily >= theCKM2Matrix.size() ) return 0.0; const vector & row = theCKM2Matrix[uFamily]; if ( dFamily >= row.size() ) return 0.0; return row[dFamily]; } double StandardModelBase::CKM(const ParticleData & uType, const ParticleData & dType) const { int uFamily = abs(uType.id() - 1)/2; int dFamily = abs(dType.id())/2; return CKM(uFamily, dFamily); } void StandardModelBase::persistentOutput(PersistentOStream & os) const { os << theFamilies << theAlphaEM << theAlphaEMMZ << theRunningAlphaEM << theSin2ThetaW << theEnu << theEe << theEu << theEd << theVnu << theVe << theVu << theVd << theAnu << theAe << theAu << theAd << recalculateEW << theCKM << theNc << theAlphaS << theRunningAlphaS << ounit(theGF,1./GeV2) << theElectroWeakScheme << theBosonWidthOption; } void StandardModelBase::persistentInput(PersistentIStream & is, int) { is >> theFamilies >> theAlphaEM >> theAlphaEMMZ >> theRunningAlphaEM >> theSin2ThetaW >> theEnu >> theEe >> theEu >> theEd >> theVnu >> theVe >> theVu >> theVd >> theAnu >> theAe >> theAu >> theAd >> recalculateEW >> theCKM >> theNc >> theAlphaS >> theRunningAlphaS >> iunit(theGF,1./GeV2) >> theElectroWeakScheme >> theBosonWidthOption; } ClassDescription StandardModelBase::initStandardModelBase; void StandardModelBase::Init() { static ClassDocumentation documentation ("The ThePEG::StandardModelBase class provides the base class" " for all models and an implementation of the couplings and parameters" " of the Standard Model."); static Parameter interfaceFamilies ("NumberOfFamilies", "The number of families assumed in the Standard model.", &StandardModelBase::theFamilies, 3, 0, 5, false, false, true); static Parameter interfaceAlphaEM ("EW/AlphaEM", "The electro-magnetic coupling constant at zero momentum transfer.", &StandardModelBase::theAlphaEM, 1.0/137.04, 0.0, 1.0, false, false, true); static Parameter interfaceAlphaEMMZ ("EW/AlphaEMMZ", "The electro-magnetic coupling constant at the Z mass.", &StandardModelBase::theAlphaEMMZ, 1.0/128.91, 0.0, 1.0, false, false, true); static Reference interfaceRunningAlphaEM ("EW/RunningAlphaEM", "Reference to an object capable of calculating the running " "electro-magnetic coupling at a given scale", &StandardModelBase::theRunningAlphaEM, false, false, true, false); static Parameter interfaceSin2ThetaW ("EW/Sin2ThetaW", "The square of the sine of the weak mixing angel", &StandardModelBase::theSin2ThetaW, 0.232, 0.0, 1.0, false, false, true); static Parameter interfaceFermiConstant ("EW/FermiConstant", "The Fermi constants G_F", &StandardModelBase::theGF, 1./GeV2, 1.16637e-5/GeV2, 1.e-5/GeV2, 2.e-5/GeV2, false, false, Interface::limited); static Parameter interfaceEnu ("EW/e_nu", "The coupling between a neutrino and a photon.", &StandardModelBase::theEnu, 0.0, 0.0, 0.0, false, false, false); static Parameter interfaceEe ("EW/e_e", "The coupling between a charged lepton and a photon.", &StandardModelBase::theEe, -1.0, 0.0, 0.0, false, false, false); static Parameter interfaceEu ("EW/e_u", "The coupling between an up-type quark and a photon.", &StandardModelBase::theEu, 2.0/3.0, 0.0, 0.0, false, false, false); static Parameter interfaceEd ("EW/e_d", "The coupling between a down-type quark and a photon.", &StandardModelBase::theEd, -1.0/3.0, 0.0, 0.0, false, false, false); static Parameter interfaceVnu ("EW/v_nu", "The vector coupling between a neutrino and a Z^0. " "See also command interface EW/RecalculateEW", &StandardModelBase::theVnu, 1.0, 0.0, 0.0, false, false, false); static Parameter interfaceVe ("EW/v_e", "The vector coupling between a charged lepton and a Z^0. " "See also command interface EW/RecalculateEW", &StandardModelBase::theVe, -0.072, 0.0, 0.0, false, false, false); static Parameter interfaceVu ("EW/v_u", "The vector coupling between an up-type quark and a Z^0. " "See also command interface EW/RecalculateEW", &StandardModelBase::theVu, 0.381333333, 0.0, 0.0, false, false, false); static Parameter interfaceVd ("EW/v_d", "The vector coupling between a down-type quark and a Z^0. " "See also command interface EW/RecalculateEW", &StandardModelBase::theVd, -0.690666666, 0.0, 0.0, false, false, false); static Parameter interfaceAnu ("EW/a_nu", "The axial coupling between a neutrino and a Z^0. " "See also command interface EW/RecalculateEW", &StandardModelBase::theAnu, 1.0, 0.0, 0.0, false, false, false); static Parameter interfaceAe ("EW/a_e", "The axial coupling between a charged lepton and a Z^0. " "See also command interface EW/RecalculateEW", &StandardModelBase::theAe, -1.0, 0.0, 0.0, false, false, false); static Parameter interfaceAu ("EW/a_u", "The axial coupling between an up-type quark and a Z^0. " "See also command interface EW/RecalculateEW", &StandardModelBase::theAu, 1.0, 0.0, 0.0, false, false, false); static Parameter interfaceAd ("EW/a_d", "The axial coupling between a down-type quark and a Z^0. " "See also command interface EW/RecalculateEW", &StandardModelBase::theAd, -1.0, 0.0, 0.0, false, false, false); static Switch interfaceRecalculateEW ("EW/RecalculateEW", "Recalculate all parameters which depend directly on " "\\f$\\sin^2\\theta_W\\f$ " "in the initialization disregarding the values previously set. " "This affects only " "EW/v_nu, " "EW/v_e, " "EW/v_u, " "EW/v_d, " "EW/a_nu, " "EW/a_e, " "EW/a_u and " "EW/a_d.", &StandardModelBase::recalculateEW, 1, false, false); static SwitchOption interfaceRecalculateEWOn (interfaceRecalculateEW, "On", "On", 1); static SwitchOption interfaceRecalculateEWOff (interfaceRecalculateEW, "Off", "Off", 0); static SwitchOption interfaceRecalculateEWYes (interfaceRecalculateEW, "Yes", "Yes", 1); static SwitchOption interfaceRecalculateEWNo (interfaceRecalculateEW, "No", "No", 0); static Reference interfaceCKM ("EW/CKM", "Reference to an object capable of calculating the square of the " "elements of the Cabibbo-Kobayashi-Maskawa flavour mixing matrix", &StandardModelBase::theCKM, false, false, true, false); static Switch interfaceElectroWeakScheme ("EW/Scheme", "Option for the definition of the electroweak parameters", &StandardModelBase::theElectroWeakScheme, 0, false, false); static SwitchOption interfaceElectroWeakSchemeDefault (interfaceElectroWeakScheme, "Default", "Use the best values for all the electroweak parameters, which can be inconsistent.", 0); static SwitchOption interfaceElectroWeakSchemeGMuScheme (interfaceElectroWeakScheme, "GMuScheme", "Use the G_mu scheme, input parameters mW,mZ and GF", 1); static SwitchOption interfaceElectroWeakSchemealphaMZScheme (interfaceElectroWeakScheme, "alphaMZScheme", "Use the alpha_MZ scheme, input parameters mW, mZ and alpha(mZ)", 2); static SwitchOption interfaceElectroWeakSchemeNoMass (interfaceElectroWeakScheme, "NoMass", "Input parameters alpha(mZ),GF,sin2thetaW", 3); static SwitchOption interfaceElectroWeakSchememW (interfaceElectroWeakScheme, "mW", "Input parameters mW, GF and sin2thetaW", 4); static SwitchOption interfaceElectroWeakSchememZ (interfaceElectroWeakScheme, "mZ", "Input parameters mZ, alphaEM and sin2thetaW", 5); static SwitchOption interfaceElectroWeakIndependent (interfaceElectroWeakScheme, "Independent", "All values input but fixed scale in ME calculations", 6); static SwitchOption interfaceElectroWeakSchemeFeynRulesUFO (interfaceElectroWeakScheme, "FeynRulesUFO", "Input parameters mZ, GF and alpha(mZ). Frequently used by FeynRules/UFO models.", 7); static Switch interfaceEWBosonWidth ("EW/BosonWidth", "Option for the calculation of the W and Z boson widths", &StandardModelBase::theBosonWidthOption, 0, false, false); static SwitchOption interfaceEWBosonWidthExperiment (interfaceEWBosonWidth, "Experiment", "Use the values from the ParticleData objects", 0); static SwitchOption interfaceEWBosonWidthLeadingOrder (interfaceEWBosonWidth, "LeadingOrder", "Calculate them using leading-order formulae", 1); static SwitchOption interfaceEWBosonWidthHigherOrder (interfaceEWBosonWidth, "HigherOrder", "Calculate them including higher order QCD corrections", 2); static Parameter interfaceNc ("QCD/Nc", "The number of colours assumed in the Standard model.", &StandardModelBase::theNc, 3, 0, 10, false, false, true); static Parameter interfaceAlphaS ("QCD/AlphaS", "The (fixed) strong coupling constant.", &StandardModelBase::theAlphaS, 0.2, 0.0, 100.0, false, false, true); static Reference interfaceRunningAlphaS ("QCD/RunningAlphaS", "Reference to an object capable of calculating the running " "stron coupling at a given scale", &StandardModelBase::theRunningAlphaS, false, false, true, false); interfaceRunningAlphaEM.rank(10); interfaceRunningAlphaS.rank(9); interfaceSin2ThetaW.rank(8); interfaceCKM.rank(7); } diff --git a/StandardModel/StandardModelBase.h b/StandardModel/StandardModelBase.h --- a/StandardModel/StandardModelBase.h +++ b/StandardModel/StandardModelBase.h @@ -1,498 +1,498 @@ // -*- C++ -*- // // StandardModelBase.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_StandardModelBase_H #define ThePEG_StandardModelBase_H // This is the declaration of the StandardModelBase class. #include "ThePEG/Config/ThePEG.h" #include "AlphaEMBase.h" #include "CKMBase.h" #include "AlphaSBase.h" // #include "StandardModelBase.fh" // #include "StandardModelBase.xh" namespace ThePEG { /** * StandardModelBase is used to handle standard model parameters in an * EventGenerator. It uses AlphaEMBase, AlphaSBase and CKMBase to help * with the implementation of the electro-magnetic and QCD couplings * and the flavour mixing matrix. This means that StandardModelBase * does not need to be inherited from when it comes to standard model * parameters. Beyond the standard model parameters should be * implemented as sub-classes. * * @see \ref StandardModelBaseInterfaces "The interfaces" * defined for StandardModelBase. * @see EventGenerator * @see AlphaEMBase * @see AlphaSBase * @see CKMBase */ class StandardModelBase: public Interfaced { /** Declare a pointer to an AlphaEMBase object. */ typedef Ptr::pointer AEMPtr; /** Declare a pointer to an AlphaSBase object. */ typedef Ptr::pointer ASPtr; /** Declare a pointer to n CKMBase object. */ typedef Ptr::pointer CKMPtr; /** Declare a transient pointer to an AlphaEMBase object. */ typedef Ptr::transient_pointer tAEMPtr; /** Declare a transient pointer to an AlphaSBase object. */ typedef Ptr::transient_pointer tASPtr; /** Declare a transient pointer to a CKMBase object. */ typedef Ptr::transient_pointer tCKMPtr; public: /** @name Standard constructors and destructors. */ //@{ /** * Default constructor. */ StandardModelBase(); /** * Destructor. */ virtual ~StandardModelBase(); //@} public: /** * Return the number of families assumed in the standard model. */ unsigned int families() const { return theFamilies; } public: /** @name Functions accessing electro-weak parameters. */ /** * Return the electroweak scheme used */ unsigned int ewScheme() const { return theElectroWeakScheme; } /** * Set the electroweak scheme used */ void ewScheme(unsigned int s) { theElectroWeakScheme = s; } //@{ /** * Constant \f$\alpha_{EM}(q^2=0)\f$. */ double alphaEM() const { return theAlphaEM; } /** * Constant \f$\alpha_{EM}(q^2=m_Z^2)\f$. */ double alphaEMMZ() const { return theAlphaEMMZ; } /** * The electromagnetic coupling for vertex classes * in a well defined self-consistent EW scheme if requested */ double alphaEMME(Energy2 scale) const { if(theElectroWeakScheme==0) return alphaEM(scale); else if(scale>1e-6*GeV2) return theAlphaEMMZ; else return theAlphaEM; } /** * Running \f$\alpha_{EM}\f$. */ double alphaEM(Energy2 scale) const { return theRunningAlphaEM->value(scale, *this); } /** * Return a pointer to the object handling \f$\alpha_{EM}\f$. */ tAEMPtr alphaEMPtr() const { return theRunningAlphaEM; } /** * Return \f$\sin^2(\theta_W)\f$. */ double sin2ThetaW() const { return theSin2ThetaW; } /** * The Fermi constant */ InvEnergy2 fermiConstant() const {return theGF;} /** * The neutrino-photon coupling. */ double enu() const { return theEnu; } /** * The charged lepton-photon coupling. */ double ee() const { return theEe; } /** * The up-type-photon coupling. */ double eu() const { return theEu; } /** * The down-type-photon coupling. */ double ed() const { return theEd; } /** * The vector neutrino-\f$Z^0\f$ coupling. */ double vnu() const { return theVnu; } /** * The vector charged lepton-\f$Z^0\f$ coupling. */ double ve() const { return theVe; } /** * The vector up-type-\f$Z^0\f$ coupling. */ double vu() const { return theVu; } /** * The vector down-type-\f$Z^0\f$ coupling. */ double vd() const { return theVd; } /** * The axial neutrino-\f$Z^0\f$ coupling. */ double anu() const { return theAnu; } /** * The axial charged lepton-\f$Z^0\f$ coupling. */ double ae() const { return theAe; } /** * The axial up-type-\f$Z^0\f$ coupling. */ double au() const { return theAu; } /** * The axial down-type-\f$Z^0\f$ coupling. */ double ad() const { return theAd; } /** * Return a pointer to the CKMBase object used. */ tCKMPtr CKM() const { return theCKM; } /** * Return a square of the element of the Cabibbo-Kobayashi-Maskawa * Matrix. The fatrix element for the \a uf up-type family and \a df * down-type family. */ double CKM(unsigned int uf, unsigned int df) const; /** * Return the square of the elements of the Cabibbo-Kobayashi-Maskawa * Matrix. */ double CKM(const ParticleData & uType, const ParticleData & dType) const; //@} public: /** @name Functions accessing QCD parameters. */ //@{ /** * Return the number of colours. */ unsigned int Nc() const { return theNc; } /** * Return the number of avtive quark flavours for a given \a scale. */ unsigned int Nf(Energy2 scale) const { return theRunningAlphaS->Nf(scale); } /** * Return the constant strong coupling constant. */ double alphaS() const { return theAlphaS; } /** * Return the running strong coupling for a given \a scale */ double alphaS(Energy2 scale) const { return theRunningAlphaS->value(scale, *this); } /** * Return a pointer to the object handling \f$\alpha_S\f$. */ tASPtr alphaSPtr() const { return theRunningAlphaS; } /** * Return the \f$\Lambda_{QCD}\f$ for \a nflav active flavours. */ Energy LambdaQCD(unsigned int nflav) const { return theRunningAlphaS->LambdaQCD(nflav); } /** * Return the \f$\Lambda_{QCD}\f$ for the given \a scale. */ Energy LambdaQCD(Energy2 scale) const { return LambdaQCD(Nf(scale)); } //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interface. */ static void Init(); /** * Overloaded function from Interfaced */ virtual bool preInitialize() const { return true; } 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(); //@} private: /** * The number of families. */ unsigned int theFamilies; /** * The constant \f$\alpha_{EM}\f$. */ double theAlphaEM; /** * The constant \f$\alpha_{EM}\f$. */ double theAlphaEMMZ; /** * Pointer to an object capable of calculating the running * \f$\alpha_{EM}\f$. */ AEMPtr theRunningAlphaEM; /** * The \f$\sin^2(\theta_W)\f$ */ double theSin2ThetaW; /** * The Fermi contants \f$G_F\f$ */ InvEnergy2 theGF; /** * Coupling between a fundamental fermion and the photon. */ double theEnu; /** * Coupling between a fundamental fermion and the photon. */ double theEe; /** * Coupling between a fundamental fermion and the photon. */ double theEu; /** * Coupling between a fundamental fermion and the photon. */ double theEd; /** * Vector coupling between a fundamental fermion and Z^0. */ double theVnu; /** * Vector coupling between a fundamental fermion and Z^0. */ double theVe; /** * Vector coupling between a fundamental fermion and Z^0. */ double theVu; /** * Vector coupling between a fundamental fermion and Z^0. */ double theVd; /** * Axial coupling between a fundamental fermions and Z^0. */ double theAnu; /** * Axial coupling between a fundamental fermions and Z^0. */ double theAe; /** * Axial coupling between a fundamental fermions and Z^0. */ double theAu; /** * Axial coupling between a fundamental fermions and Z^0. */ double theAd; /** * If true, the electro-weak couplings are derived from * \f$\theta_W\f$ in the initialization. */ long recalculateEW; /** * A pointer to an object representing the Cabibbo-Kobayashi-Maskawa * matrix. */ CKMPtr theCKM; /** * The matrix of squared CKM elements set from theCKM at initialization. */ mutable vector< vector > theCKM2Matrix; /** * The number of colours; */ unsigned int theNc; /** * The fixed strong coupling. */ double theAlphaS; /** * Pointer to an object capable of calculating the running * \f$\alpha_{S}\f$. */ ASPtr theRunningAlphaS; /** * Electroweak scheme */ unsigned int theElectroWeakScheme; /** * Option for the calculation of the W/Z widths */ unsigned int theBosonWidthOption; private: /** * Describe a concrete class with persistent data. */ static ClassDescription initStandardModelBase; /** * Private and non-existent assignment operator. */ StandardModelBase & operator=(const StandardModelBase &) = delete; }; /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the base classes * of StandardModelBase. */ template <> struct BaseClassTrait: public ClassTraitsType { /** Typedef of the first base class of StandardModelBase. */ typedef Interfaced NthBase; }; /** This template specialization informs ThePEG about the name of the * StandardModelBase class. */ template <> struct ClassTraits: public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "ThePEG::StandardModelBase"; } }; /** @endcond */ } #endif /* ThePEG_StandardModelBase_H */ diff --git a/Utilities/AnyReference.h b/Utilities/AnyReference.h --- a/Utilities/AnyReference.h +++ b/Utilities/AnyReference.h @@ -1,183 +1,183 @@ // -*- C++ -*- // // AnyReference.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad -// Copyright (C) 2010-2017 Simon Platzer +// Copyright (C) 1999-2019 Leif Lonnblad +// Copyright (C) 2010-2019 Simon Platzer // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_AnyReference_H #define ThePEG_AnyReference_H #include "ThePEG/Config/ThePEG.h" #include "Exception.h" namespace ThePEG { /** * AnyReference is inspired by boost::any to hold a reference to an * object of arbitrary type. */ class AnyReference { struct ReferenceHolderBase { /** * The destructor. */ virtual ~ReferenceHolderBase() {} /** * Return the type held. */ virtual const std::type_info& type() const = 0; /** * Clone this reference holder. */ virtual ReferenceHolderBase* clone() const = 0; }; template struct ReferenceHolder : public ReferenceHolderBase { /** * The reference held. */ T& value; /** * Static member to initialize the reference. */ static T& init() { static T v; return v; } /** * The default constructor */ ReferenceHolder() : value(init()) {} /** * Construct from given reference. */ explicit ReferenceHolder(T& v) : value(v) {} /** * Return the type held. */ virtual const std::type_info& type() const { return typeid(T); } /** * Clone this reference holder. */ virtual ReferenceHolderBase* clone() const { return new ReferenceHolder(*this); } }; /** * The reference holder used. */ ReferenceHolderBase* holder; public: /** * The default constructor */ AnyReference() : holder(0) {} /** * The standard constructor */ template AnyReference(T& v) : holder(new ReferenceHolder(v)) {} /** * The copy constructor */ AnyReference(const AnyReference& other) : holder(other.holder ? other.holder->clone() : 0) {} /** * The destructor. */ ~AnyReference() { delete holder; holder = 0; } public: /** * Return the type held. */ const std::type_info& type() const { return holder ? holder->type() : typeid(void); } /** * Return true, if no reference is held. */ bool empty() const { return !holder; } public: /** * Swap the references held. */ AnyReference& swap(AnyReference& other) { std::swap(holder,other.holder); return *this; } /** * Assign from definite type */ template AnyReference& operator=(T& v) { AnyReference(v).swap(*this); return *this; } /** * Assign from AnyReference */ AnyReference& operator=(AnyReference other) { other.swap(*this); return *this; } /** * Reset to not keep track of any reference. */ void reset() { delete holder; holder = 0; } public: /** * Extract the held reference. */ template T& cast() const { if ( !empty() && type() == typeid(T) ) { return static_cast*>(holder)->value; } throw Exception() << "Bad cast in AnyReference" << Exception::abortnow; return ReferenceHolder::init(); } }; } #endif // ThePEG_AnyReference_H diff --git a/Utilities/CFile.cc b/Utilities/CFile.cc --- a/Utilities/CFile.cc +++ b/Utilities/CFile.cc @@ -1,234 +1,234 @@ // -*- C++ -*- // // CFileLineReader.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the CFileLineReader class. // #include "CFile.h" #include "config.h" #include #include #include "Throw.h" #include #ifdef HAVE_LIBZ #include #else typedef void * gzFile; #endif #ifdef HAVE_LIBBZ2_NEVER #include #else typedef void BZFILE; #endif using namespace ThePEG; void CFile::open(string filename, string mode) { close(); if ( filename[filename.length()-1] == '|' && mode.find("r") != string::npos ) { filename = filename.substr(0, filename.length() - 1); file = popen(filename.c_str(), mode.c_str()); fileType = pipe; } else if ( filename[0] == '|' && mode.find("w") != string::npos ) { filename = filename.substr(1); file = popen(filename.c_str(), mode.c_str()); fileType = pipe; } else if ( filename.substr(filename.length()-3,3) == ".gz" ) { #ifdef HAVE_LIBZ file = gzopen(filename.c_str(), mode.c_str()); fileType = gzip; #else #ifdef ThePEG_GZREAD_FILE #ifdef ThePEG_GZWRITE_FILE if ( mode.find("r") != string::npos ) filename = ThePEG_GZREAD_FILE " " + filename + " 2>/dev/null"; else filename = ThePEG_GZWRITE_FILE " " + filename + " 2>/dev/null"; file = popen(filename.c_str(), mode.c_str()); fileType = pipe; #else file = fopen(filename.c_str(), mode.c_str()); fileType = plain; #endif #endif #endif } else if ( filename.substr(filename.length()-4,4) == ".bz2" ) { #ifdef HAVE_LIBBZ2_NEVER file = BZ2_bzopen(filename.c_str(), mode.c_str()); fileType = bzip2; #else #ifdef ThePEG_BZ2READ_FILE #ifdef ThePEG_BZ2WRITE_FILE if ( mode.find("r") != string::npos ) filename = ThePEG_BZ2READ_FILE " " + filename + " 2>/dev/null"; else filename = ThePEG_BZ2WRITE_FILE " " + filename + " 2>/dev/null"; file = popen(filename.c_str(), mode.c_str()); fileType = pipe; #else file = fopen(filename.c_str(), mode.c_str()); fileType = plain; #endif #endif #endif } else { file = fopen(filename.c_str(), mode.c_str()); fileType = plain; } if ( !file ) { Throw() << std::strerror(errno) << ": " << filename << Exception::runerror; } } void CFile::close() { if ( !file ) { fileType = undefined; return; } switch ( fileType ) { case plain: fclose((FILE*)file); break; case pipe: pclose((FILE*)file); break; #ifdef HAVE_LIBZ case gzip: gzclose((gzFile)file); break; #endif #ifdef HAVE_LIBBZ2_NEVER case bzip2: BZ2_bzclose(file); break; #endif default: break; } file = 0; fileType = undefined; } char * CFile::gets(char * s, int size) { switch ( fileType ) { case plain: case pipe: return fgets(s, size, (FILE*)file); #ifdef HAVE_LIBZ case gzip: return gzgets((gzFile)file, s, size); #endif #ifdef HAVE_LIBBZ2_NEVER case bzip2: // don't know what to do here #endif default: return 0; } } int CFile::puts(const char * s) { switch ( fileType ) { case plain: case pipe: return fputs(s, (FILE*)file); #ifdef HAVE_LIBZ case gzip: return gzputs((gzFile)file, s); #endif #ifdef HAVE_LIBBZ2_NEVER case bzip2: // don't know what to do here #endif default: return 0; } } int CFile::getc() { switch ( fileType ) { case plain: case pipe: return fgetc((FILE*)file); #ifdef HAVE_LIBZ case gzip: return gzgetc((gzFile)file); #endif #ifdef HAVE_LIBBZ2_NEVER case bzip2:// don't know what to do here #endif default: return 0; } } int CFile::putc(int c) { switch ( fileType ) { case plain: case pipe: return fputc(c, (FILE*)file); #ifdef HAVE_LIBZ case gzip: return gzputc((gzFile)file, c); #endif #ifdef HAVE_LIBBZ2_NEVER case bzip2: // don't know what to do here #endif default: return 0; } } int CFile::ungetc(int c) { switch ( fileType ) { case plain: case pipe: return std::ungetc(c, (FILE*)file); #ifdef HAVE_LIBZ case gzip: return gzungetc(c, (gzFile)file); #endif #ifdef HAVE_LIBBZ2_NEVER case bzip2: // don't know what to do here #endif default: return 0; } } size_t CFile::read(void *ptr, size_t size, size_t nmemb) { switch ( fileType ) { case plain: case pipe: return fread(ptr, size, nmemb, (FILE*)file); #ifdef HAVE_LIBZ case gzip: return gzread((gzFile)file, ptr, size); #endif #ifdef HAVE_LIBBZ2_NEVER case bzip2: return BZ2_bzread(file, ptr, size); #endif default: return 0; } } size_t CFile::write(const void *ptr, size_t size, size_t nmemb) { switch ( fileType ) { case plain: case pipe: return fwrite(ptr, size, nmemb, (FILE*)file); #ifdef HAVE_LIBZ case gzip: return gzwrite((gzFile)file, ptr, size); #endif #ifdef HAVE_LIBBZ2_NEVER case bzip2: return BZ2_bzwrite(file, ptr, size); #endif default: return 0; } } diff --git a/Utilities/CFileLineReader.cc b/Utilities/CFileLineReader.cc --- a/Utilities/CFileLineReader.cc +++ b/Utilities/CFileLineReader.cc @@ -1,159 +1,159 @@ // -*- C++ -*- // // CFileLineReader.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the CFileLineReader class. // #include "CFileLineReader.h" #include "config.h" #include using namespace ThePEG; CFileLineReader::CFileLineReader() : bufflen(defsize), buff(new char[defsize]), pos(buff), bad(false) {} CFileLineReader::CFileLineReader(string filename, int len) : bufflen(len), buff(new char[len]), pos(buff), bad(false) { open(filename); } CFileLineReader::~CFileLineReader() { close(); } void CFileLineReader::open(string filename) { close(); file = CFile(filename, "r"); pos = buff; bad = !file; } void CFileLineReader::close() { file.close(); bad = true; } bool CFileLineReader::readline() { bad = ( file.gets(buff, bufflen) == 0 ); pos = buff; return !bad; } CFileLineReader::operator void *() { // the returned address is not meant to be dereferenced, // it only indicates success. return bad ? 0 : &bad; } bool CFileLineReader::operator!() { return bad; } char CFileLineReader::getc() { char c = *pos++; bad = ( *pos == 0 ); return c; } bool CFileLineReader::skip(char c) { while ( *pos != 0 && *pos++ != c ) {} bad = ( *pos == 0 ); return !bad; } bool CFileLineReader::find(string str) const { return ( string(pos).find(str) != string::npos ); } std::string CFileLineReader::getline() const { return std::string(pos); } CFileLineReader & CFileLineReader::operator>>(long & l) { char * next; l = std::strtol(pos, &next, 0); bad = ( next == pos ); pos = next; return *this; } CFileLineReader & CFileLineReader::operator>>(int & i) { char * next; i = int(std::strtol(pos, &next, 0)); bad = ( next == pos ); pos = next; return *this; } CFileLineReader & CFileLineReader::operator>>(unsigned long & l) { char * next; l = std::strtoul(pos, &next, 0); bad = ( next == pos ); pos = next; return *this; } CFileLineReader & CFileLineReader::operator>>(unsigned int & i) { char * next; i = static_cast(std::strtoul(pos, &next, 0)); bad = ( next == pos ); pos = next; return *this; } CFileLineReader & CFileLineReader::operator>>(double & d) { char * next; d = std::strtod(pos, &next); bad = ( next == pos ); pos = next; // fortran formatted doubles if(!bad && ( *pos == 'd' || *pos == 'D')) { ++pos; int exp; *this >> exp; d *= pow(10.,exp); } return *this; } CFileLineReader & CFileLineReader::operator>>(float & f) { char * next; f = float(std::strtod(pos, &next)); bad = ( next == pos ); pos = next; // fortran formatted doubles if(!bad && ( *pos == 'd' || *pos == 'D')) { ++pos; int exp; *this >> exp; f *= pow(10.,exp); } return *this; } CFileLineReader & CFileLineReader::operator>>(std::string & s) { while ( *pos != 0 && std::isspace(*pos) ) ++pos; bad = ( *pos == 0 ); char * first = pos; while ( *pos != 0 && !std::isspace(*pos) ) ++pos; s.assign(first, pos); return *this; } CFile CFileLineReader::cFile() const { return file; } void CFileLineReader::resetline() { bad = false; pos = buff; } diff --git a/Utilities/CFileLineReader.h b/Utilities/CFileLineReader.h --- a/Utilities/CFileLineReader.h +++ b/Utilities/CFileLineReader.h @@ -1,222 +1,222 @@ // -*- C++ -*- // // CFileLineReader.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_CFileLineReader_H #define THEPEG_CFileLineReader_H // // This is the declaration of the CFileLineReader class. // #include "ThePEG/Config/ThePEG.h" #include "CFileLineReader.fh" #include "CFile.h" #include #include namespace ThePEG { /** * CFileLineReader is a wrapper around a standard C FILE stream. With * it one reads one line at the time (with readline()) into an * internal buffer from which one can then read as from a standard * std::istream with a limited set of operator>> functions. It can be * thought of as an std::ifstream where the internal buffer must be * filled by hand one line at the time. * * Contrary to std::ifstream the CFileLineReader can also handle * gipped files and pipes. Gzipped files are automatically handles by * a pipe using the zcat command if the file name ends * with .gz. Also if a file name ends with a * | sign, the preceding string is interpreted as a * command defining a pipe from which to read. * * Since CFileLineReader is very close to the standard C FILE stream * it is in many cases much faster than eg. reading from lines via * std::istringstream. */ class CFileLineReader { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ CFileLineReader(); /** * Constructor taking a \a filename as argument. Optionally the size * \a len of the line buffer can be specified. If \a filename ends * with .gz a pipe is opened where the file is read by * zcat. If \a filename ends with a | * sign, the preceding string is interpreted as a command defining a * pipe from which to read. */ CFileLineReader(string filename, int len = defsize); /** * The destructor. */ ~CFileLineReader(); //@} /** @name Initialization functions. */ //@{ /** * Initialize with a \a filename. If \a filename ends with * .gz a pipe is opened where the file is read by * zcat. If \a filename ends with a | * sign, the preceding string is interpreted as a command defining a * pipe from which to read. */ void open(string filename); /** * If the file was opened from within this object, close it. */ void close(); //@} /** * Read a line from the underlying c-file into the line buffer. */ bool readline(); /** * Undo reading from the current line, ie. the next read will be * from the beginning of the current line. Afterwards the state will * be not bad. */ void resetline(); /** * Return a string containing what is left of the line buffer. */ string getline() const; /** * Return the underlying c-file. */ CFile cFile() const; /** * Return null if a previous read failed. */ operator void *(); /** * Return true if a previous read failed. */ bool operator!(); /** * Scan forward up and until the first occurrence of the given * character. * @return true if the given character was found. */ bool skip(char c); /** * Check if a given string is present in the current line buffer. */ bool find(string str) const; /** @name Operators to read from the line buffer. */ //@{ /** * Return the next character of the line-buffer. */ char getc(); /** * Read a long from the line buffer. */ CFileLineReader & operator>>(long & l); /** * Read an int from the line buffer. */ CFileLineReader & operator>>(int & i); /** * Read an unsigned long from the line buffer. */ CFileLineReader & operator>>(unsigned long & l); /** * Read an unsigned int from the line buffer. */ CFileLineReader & operator>>(unsigned int & i); /** * Read a double from the line buffer. */ CFileLineReader & operator>>(double & d); /** * Read a float from the line buffer. */ CFileLineReader & operator>>(float & f); /** * Read a (whitespace delimited) string from the line buffer. */ CFileLineReader & operator>>(std::string & s); //@} private: /** * The c-file to be read from. */ CFile file; /** * The length of the line buffer. */ int bufflen; /** * The line buffer. */ char * buff; /** * The current position in the line buffer. */ char * pos; /** * The current state is bad if a read has failed. */ bool bad; /** * The default size of the buffer. */ static const int defsize = 1024; private: /** * The copy constructor is private and not implemented. */ CFileLineReader(const CFileLineReader &); /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ CFileLineReader & operator=(const CFileLineReader &) = delete; }; } #endif /* THEPEG_CFileLineReader_H */ diff --git a/Utilities/ClassDescription.cc b/Utilities/ClassDescription.cc --- a/Utilities/ClassDescription.cc +++ b/Utilities/ClassDescription.cc @@ -1,27 +1,27 @@ // -*- C++ -*- // // ClassDescription.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the ClassDescription class. // #include "ClassDescription.h" using namespace ThePEG; ClassDescriptionBase::~ClassDescriptionBase() {} bool ClassDescriptionBase::isA(const ClassDescriptionBase & base) const { if ( base.info() == info() ) return true; for ( DescriptionVector::const_iterator i = descriptions().begin(); i != descriptions().end(); ++i ) if ( (**i).isA(base) ) return true; return false; } diff --git a/Utilities/ClassDescription.h b/Utilities/ClassDescription.h --- a/Utilities/ClassDescription.h +++ b/Utilities/ClassDescription.h @@ -1,487 +1,487 @@ // -*- C++ -*- // // ClassDescription.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_ClassDescription_H #define ThePEG_ClassDescription_H #include "ThePEG/Config/ThePEG.h" #include "ClassDescription.fh" #include "ThePEG/Utilities/Named.h" #include "ThePEG/Persistency/PersistentOStream.fh" #include "ThePEG/Persistency/PersistentIStream.fh" #include "ClassTraits.h" #include "DescriptionList.h" namespace ThePEG { /** * ClassDescriptionBase is the base class for all class description * classes. ClassDescriptionBase is the non-templated base class for * the templated ClassDescriptionTBase, ClassDescription, * AbstractClassDescription, NoPIOClassDescription and * AbstractNoPIOClassDescription classes. An instantiation of one of * these classes represents a meta class encapsulating information * about the template argument class. This information is obtained * from the templated ClassTraits class which can be specialized for * any given class should the default information not be * satisfactory. Information is also obtained from the templated * BaseClassTraits class which must be specialized for each class * declaring a typedef for each of its base classes. * * The information about a class stored in a * ClassDescriptionBase objects is the following:
a * platform-independent class name,
a reference to the * type_info
an integer version number,
a vector * of ClassDescriptionBase* corresponding to the base * classes,
methods for reading/writing members of a class from/to * a PersistentIStream/PersistentOStream and
a method for creating * an object of a class. * * The ClassDescriptionBase objects should be created before main() is * executed, and shouold therfore be instantiated as static member * variables. Only one ClassDescriptionBase object shall be * instantiated for each class to be described. The * ClassDescriptionBase objects are automatically stored in a purely * static DescriptionList class. * * AbstractClassDescription and AbstractNoPIOClassDescription should * be used for abstract base classes, while NoPIOClassDescription and * AbstractNoPIOClassDescription should be used for classes which do * not have any members which need to be read and written * persistently. * * @see ClassTraits * @see PersistentIStream * @see PersistentOStream * @see DescriptionList */ class ClassDescriptionBase: public Named { public: /** A vector of class descriptions. */ typedef vector DescriptionVector; protected: /** * The constructor used by sub-classes. * @param newName the platform independent name of the class. * @param newInfo the type_info object corresponding to the class. * @param newVersion the implementation version of the class. * @param newLibrary the name of a file containing the dynamic * @param abst true if the class is abstract. * library where the class is implemented. */ ClassDescriptionBase(string newName, const type_info & newInfo, int newVersion, string newLibrary, bool abst) : Named(newName), theVersion(newVersion), theLibrary(newLibrary), theInfo(newInfo), isAbstract(abst), done(false) {} public: /** * Empty destructor. */ virtual ~ClassDescriptionBase(); /** * The standart RTTI type_info object for the described class. */ const type_info & info() const { return theInfo; } /** * The version of the described class. */ int version() const { return theVersion; } /** * The name of a file containing the dynamic * library where the class is implemented. */ string library() const { return theLibrary; } /** * Return true if this object was set up properly. */ bool check() const { return done; } /** * Return the descriptions of the base classes of the described * class. */ const DescriptionVector & descriptions() const { return theBaseClasses; } /** * Set up the base class information for this object. */ virtual void setup() = 0; /** * Create an object of the described class. */ virtual BPtr create() const = 0; /** * Output the members of an object of the described class to a * persistent stream. * @param b the object to be written. * @param os the persistent stream. */ virtual void output(tcBPtr b, PersistentOStream & os) const = 0; /** * Read the members of an object of the described class from a * persistent stream. * @param b the object to be read. * @param is the persistent stream. * @param oldVersion the version number of the object when it was written. */ virtual void input(tBPtr b, PersistentIStream & is, int oldVersion) const = 0; /** * Return true if the class described by the argument is a base * class of the class described by this. */ bool isA(const ClassDescriptionBase & base) const; /** * Return true if the corresponding class is abstract. */ bool abstract() const { return isAbstract; } protected: /** * Set the base classes. * @param first an iterator refering to the first base class * @param last an iterator giving the end of the range of base class * descriptions. */ void baseClasses(DescriptionVector::iterator first, DescriptionVector::iterator last) { theBaseClasses = DescriptionVector(first, last); done = true; } private: /** * The version of the described class. */ int theVersion; /** * The library file where this class may be found. */ string theLibrary; /** * The type_info object for the described class */ const type_info & theInfo; /** * The vector of base classes. */ DescriptionVector theBaseClasses; /** * True if this class is abstract. */ bool isAbstract; /** * True if this object was set up properly. */ bool done; }; /** * A helper class for tracing the base classes of a class to be * described */ template ::NthBase> struct ClassDescriptionHelper { /** Add base classes */ static void addBases(vector & c){ const ClassDescriptionBase * b = DescriptionList::find(typeid(B)); if ( !b ) return; c.push_back(b); ClassDescriptionHelper::addBases(c); } }; /** @cond TRAITSPECIALIZATIONS */ /** * A helper class for tracing the base classes of a class to be * described */ template struct ClassDescriptionHelper { /** Add base classes */ static void addBases(vector & ) {} }; /** @endcond */ /** * An intermediate templated base class derived from * ClassDescriptionBase. */ template class ClassDescriptionTBase: public ClassDescriptionBase { public: /** The traits class for the template argument class. */ typedef ClassTraits Traits; public: /** * Default constructor. If \a abst is true then the corresponding * class is abstract. */ ClassDescriptionTBase(bool abst) : ClassDescriptionBase(Traits::className(), typeid(T), Traits::version(), Traits::library(), abst) { DescriptionList::Register(*this); T::Init(); } /** * The descructor. */ virtual ~ClassDescriptionTBase() {} /** * Set up the base class information for this object. */ virtual void setup() { DescriptionVector bases; ClassDescriptionHelper::addBases(bases); baseClasses(bases.begin(), bases.end()); } }; /** * A concreate implementation of ClassDescriptionBase describing an * abstract class with persistent data. */ template class AbstractClassDescription: public ClassDescriptionTBase { public: /** The traits class for the template argument class. */ typedef ClassTraits Traits; public: /** * Default constructor. */ AbstractClassDescription() : ClassDescriptionTBase(true) {} /** * Do not create an object of the described class (which is * abstract). Just return the null pointer. */ virtual BPtr create() const { throw std::logic_error("Tried to instantiate virtual class " + Named::name()); } /** * Output the members of an object of the described class to a * persistent stream. * @param b the object to be written. * @param os the persistent stream. */ virtual void output(tcBPtr b, PersistentOStream & os) const { Traits::output(Traits::cast(b), os); } /** * Read the members of an object of the described class from a * persistent stream. * @param b the object to be read. * @param is the persistent stream. * @param oldVersion the version number of the object when it was written. */ virtual void input(tBPtr b, PersistentIStream & is, int oldVersion) const { Traits::input(Traits::cast(b), is, oldVersion); } }; /** * A concreate implementation of ClassDescriptionBase describing a * concrete class with persistent data. */ template class ClassDescription: public ClassDescriptionTBase { public: /** The traits class for the template argument class. */ typedef ClassTraits Traits; public: /** * Default constructor. */ ClassDescription() : ClassDescriptionTBase(false) {} /** * Create an object of the described class. */ virtual BPtr create() const { return Traits::create(); } /** * Output the members of an object of the described class to a * persistent stream. * @param b the object to be written. * @param os the persistent stream. */ virtual void output(tcBPtr b, PersistentOStream & os) const { Traits::output(Traits::cast(b), os); } /** * Read the members of an object of the described class from a * persistent stream. * @param b the object to be read. * @param is the persistent stream. * @param oldVersion the version number of the object when it was written. */ virtual void input(tBPtr b, PersistentIStream & is, int oldVersion) const { Traits::input(Traits::cast(b), is, oldVersion); } }; /** * A concreate implementation of ClassDescriptionBase describing a * concrete class without persistent data. */ template class NoPIOClassDescription: public ClassDescriptionTBase { public: /** The traits class for the template argument class. */ typedef ClassTraits Traits; public: /** * Default constructor. */ NoPIOClassDescription() : ClassDescriptionTBase(false) {} /** * Create an object of the described class. */ virtual BPtr create() const { return Traits::create(); } /** * Do nothing since the described class has no persistent data. */ virtual void output(tcBPtr, PersistentOStream &) const {} /** * Do nothing since the described class has no persistent data. */ virtual void input(tBPtr, PersistentIStream &, int) const {} }; /** * A concreate implementation of ClassDescriptionBase describing an * abstract class without persistent data. */ template class AbstractNoPIOClassDescription: public ClassDescriptionTBase { public: /** The traits class for the template argument class. */ typedef ClassTraits Traits; public: /** * Default constructor. */ AbstractNoPIOClassDescription() : ClassDescriptionTBase(true) {} /** * Do not create an object of the described class (which is * abstract). Just return the null pointer. */ virtual BPtr create() const { throw std::logic_error("Tried to instantiate virtual class " + Named::name()); } /** * Do nothing since the described class has no persistent data. */ virtual void output(tcBPtr, PersistentOStream & ) const {} /** * Do nothing since the described class has no persistent data. */ virtual void input(tBPtr, PersistentIStream &, int) const {} }; } #define ThePEG_DECLARE_CLASS_DESCRIPTION(Class) \ /** Describe a concrete class with persistent data. */ \ static ClassDescription init ## Class \ #define ThePEG_DECLARE_ABSTRACT_CLASS_DESCRIPTION(Class) \ /** Describe an abstract class with persistent data. */ \ static AbstractClassDescription init ## Class \ #define ThePEG_DECLARE_NOPIO_CLASS_DESCRIPTION(Class) \ /** Describe a concrete class without persistent data. */ \ static NoPIOClassDescription init ## Class \ #define ThePEG_DECLARE_ABSTRACT_NOPIO_CLASS_DESCRIPTION(Class) \ /** Describe an abstract class without persistent data. */ \ static AbstractNoPIOClassDescription init ## Class \ #define ThePEG_IMPLEMENT_CLASS_DESCRIPTION(Class) \ ClassDescription Class::init ## Class \ #define ThePEG_IMPLEMENT_ABSTRACT_CLASS_DESCRIPTION(Class) \ AbstractClassDescription Class::init ## Class \ #define ThePEG_IMPLEMENT_NOPIO_CLASS_DESCRIPTION(Class) \ NoPIOClassDescription Class::init ## Class \ #define ThePEG_IMPLEMENT_ABSTRACT_NOPIO_CLASS_DESCRIPTION(Class) \ AbstractNoPIOClassDescription Class::init ## Class \ #endif /* ThePEG_ClassDescription_H */ diff --git a/Utilities/ClassTraits.h b/Utilities/ClassTraits.h --- a/Utilities/ClassTraits.h +++ b/Utilities/ClassTraits.h @@ -1,239 +1,239 @@ // -*- C++ -*- // // ClassTraits.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_ClassTraits_H #define ThePEG_ClassTraits_H // This is the declaration of the ClassTraitsBase, ClassTraits and // BaseClassTraits classes. #include "ThePEG/Config/ThePEG.h" // #include "ClassTraits.fh" // #include "ClassTraits.xh" #include "ThePEG/Persistency/PersistentOStream.fh" #include "ThePEG/Persistency/PersistentIStream.fh" #include "DescriptionList.h" namespace ThePEG { /** * ClassTraitsType is an empty, non-polymorphic, base class. It is * used as a base class of all class traits classes in order to group * them together in the documentation. It currently serves no other * purpose. */ struct ClassTraitsType: public TraitsType {}; /** * The templated ClassTraitsBase class defines a set of default * information about classes used by ThePEG. By default, the * ClassTraits simply inherits from ClassTraitsBase, but it can be * specialized to override the static member functions. * * The information that should be made available is:
* create() creates an object of the described class,
* className() returns the platform-independent name of * the class,
version() return the version * number,
output() output the members of the class * to a PersistentOStream,
input() reads the members * of the class from a PersistentIStream and
cast() * dynamically cast a pointer to a public base class to a pointer to * the class. * * @see PersistentOStream * @see PersistentIStream */ template struct ClassTraitsBase: public ClassTraitsType { ThePEG_DECLARE_TEMPLATE_POINTERS(T,TPtr); ThePEG_DECLARE_POINTERS(Base,BPtr); /** * Create a T object and return a smart pointer to it. */ static TPtr create() { return TPtr::Create(); } /** * Return the name of class T. */ // static string className() { return T::className(); } static string className() { return DescriptionList::className(typeid(T)); } /** * Return the version of class T */ static int version() { return DescriptionList::version(typeid(T)); } /** * The name of a file containing the dynamic library where the class * T is implemented. It may also include several, space separated, * libraries if the class T depends on other classes (base classes * excepted). In this case the listed libraries will be dynamically * linked in the order they are specified. */ static string library() { return DescriptionList::library(typeid(T)); } /** * Write the T part of an object to a persistent stream. */ static void output(tcTPtr t, PersistentOStream & os) { t->persistentOutput(os); } /** * Read the T part of an object from a persistent stream. */ static void input(tTPtr t, PersistentIStream & is, int oldVersion) { t->persistentInput(is, oldVersion); } /** * Perform a dynamic cast from the given pointer to a pointer to T. */ static TPtr cast(BPtr b) { return dynamic_ptr_cast(b); } /** * Perform a dynamic cast from the given const pointer to a pointer * to const T. */ static cTPtr cast(cBPtr b) { return dynamic_ptr_cast(b); } /** * Perform a dynamic cast from the given transient pointer to a * transient pointer to T. */ static tTPtr cast(tBPtr b) { return dynamic_ptr_cast(b); } /** * Perform a dynamic cast from the given transient const pointer to * a transient pointer to const T. */ static tcTPtr cast(tcBPtr b) { return dynamic_ptr_cast(b); } }; /** * The default concrete implementation of ClassTraitsBase. This * templated class may be specialized for any class if the default * implementation is not sufficient. */ template struct ClassTraits: public ClassTraitsBase {}; /** * ClassTraits specialization for double */ template<> struct ClassTraits : public ClassTraitsBase { static string className() { return "double"; } }; /** * BaseClassTraits describes the base classes of the templated class. * BaseClassTraits should be specialized once for each * base class of a class to be described. The specializations should * contain a typedef so that * BaseClassTraits::NthBase is made an alias for * the first base class of T, * BaseClassTraits::NthBase the second base * class and so on. The typedef defaults to int which means * no base class. */ template struct BaseClassTrait: public ClassTraitsType { /** * The type of the BaseN'th base class (int means there * are no further base classes). */ typedef int NthBase; }; } #define ThePEG_DECLARE_BASE_CLASS_TRAITS_1(Class,Base) \ /** This template specialization informs ThePEG about the \ * base classes of Class. */ \ template <> \ struct BaseClassTrait: public ClassTraitsType { \ /** Typedef of the first base class of Class. */ \ typedef Base NthBase; \ }; \ #define ThePEG_DECLARE_BASE_CLASS_TRAITS_2(Class,Base1,Base2) \ /** This template specialization informs ThePEG about the \ * base classes of Class. */ \ template <> \ struct BaseClassTrait: public ClassTraitsType { \ /** Typedef of the first base class of Class. */ \ typedef Base1 NthBase; \ }; \ /** This template specialization informs ThePEG about the \ * base classes of Class. */ \ template <> \ struct BaseClassTrait: public ClassTraitsType { \ /** Typedef of the second base class of Class. */ \ typedef Base2 NthBase; \ }; \ #define ThePEG_DECLARE_NAMED_DYNAMIC_CLASS_TRAITS_(Class,Name,Lib) \ /** This template specialization informs ThePEG about the name of \ * the Class class and the shared object where it is defined. */ \ template <> \ struct ClassTraits: \ public ClassTraitsBase { \ /** Return a platform-independent class name */ \ static string className() { return Name; } \ /** \ * The name of a file containing the dynamic library where the class \ * T is implemented. It may also include several, space separated, \ * libraries if the class T depends on other classes (base classes \ * excepted). In this case the listed libraries will be dynamically \ * linked in the order they are specified. \ */ \ static string library() { return Lib; } \ } \ #define ThePEG_DECLARE_CLASS_TRAITS(Class,Base) \ ThePEG_DECLARE_BASE_CLASS_TRAITS_1(Class,Base) \ ThePEG_DECLARE_NAMED_DYNAMIC_CLASS_TRAITS_(Class,"ThePEG::" #Class,"") \ #define ThePEG_DECLARE_DYNAMIC_CLASS_TRAITS(Class,Base,Lib) \ ThePEG_DECLARE_BASE_CLASS_TRAITS_1(Class,Base) \ ThePEG_DECLARE_NAMED_DYNAMIC_CLASS_TRAITS_(Class,"ThePEG::" #Class,Lib) \ #define ThePEG_DECLARE_CLASS_TRAITS_2(Class,Base1,Base2) \ ThePEG_DECLARE_BASE_CLASS_TRAITS_2(Class,Base1,Base2) \ ThePEG_DECLARE_NAMED_DYNAMIC_CLASS_TRAITS_(Class,"ThePEG/::" #Class,"") \ #define ThePEG_DECLARE_DYNAMIC_CLASS_TRAITS_2(Class,Base1,Base2,Lib) \ ThePEG_DECLARE_BASE_CLASS_TRAITS_2(Class,Base1,Base2) \ ThePEG_DECLARE_NAMED_DYNAMIC_CLASS_TRAITS_(Class,"ThePEG::" #Class,Lib) \ #define ThePEG_DECLARE_NAMED_CLASS_TRAITS(Class,Base,Name) \ ThePEG_DECLARE_BASE_CLASS_TRAITS_1(Class,Base) \ ThePEG_DECLARE_NAMED_DYNAMIC_CLASS_TRAITS_(Class,Name,"") \ #define ThePEG_DECLARE_NAMED_DYNAMIC_CLASS_TRAITS(Class,Base,Name,Lib) \ ThePEG_DECLARE_BASE_CLASS_TRAITS_1(Class,Base) \ ThePEG_DECLARE_NAMED_DYNAMIC_CLASS_TRAITS_(Class,Name,Lib) \ #define ThePEG_DECLARE_NAMED_CLASS_TRAITS_2(Class,Base1,Base2,Name) \ ThePEG_DECLARE_BASE_CLASS_TRAITS_2(Class,Base1,Base2) \ ThePEG_DECLARE_NAMED_DYNAMIC_CLASS_TRAITS_(Class,Name,"") \ #endif /* ThePEG_ClassTraits_H */ diff --git a/Utilities/ColourOutput.cc b/Utilities/ColourOutput.cc --- a/Utilities/ColourOutput.cc +++ b/Utilities/ColourOutput.cc @@ -1,47 +1,47 @@ // -*- C++ -*- // // ColourOutput.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the 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 --- a/Utilities/ColourOutput.h +++ b/Utilities/ColourOutput.h @@ -1,47 +1,47 @@ // -*- C++ -*- // // ColourOutput.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_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/CompSelector.h b/Utilities/CompSelector.h --- a/Utilities/CompSelector.h +++ b/Utilities/CompSelector.h @@ -1,310 +1,310 @@ // -*- C++ -*- // // CompSelector.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_CompSelector_H #define THEPEG_CompSelector_H // // This is the declaration of the CompSelector class. // #include "ThePEG/Utilities/Selector.h" namespace ThePEG { /** * The CompSelector class works like the Selector class in that it can * be used to randomly select objects according to associated * probabilities. In addition, the CompSelector class is able to * handle the case where the associated probabilities are * overestimates and the selected object will be discarded according * to some weight. If then a weight above one is encountered, this * means that the overestimated probability for the selected object * was wrong and it should in fact have been higher. If this happens, * the CompSelecteor will go into compensation mode, which means that * the selected object will be oversampled a period after the * violation to compensate for having been undersampled before. Also * the associated probability is adjusted to reflect the new * overestimate. * * The available functions are not as many as in Selector, and some of * the works somewhat differently. Before starting sampling the * objects should be added to a CompSelector object with the insert() * function. To selct an object the select() function should be * used. After that the weight with which the object should be * accepted should be presented with the reweight() function which * normally returns zero. If, however, the weight is larger than unity * the new overestimated probability is returned and the CompSelector * enters the compensating mode. Note that the weight is passed as a * reference and may be changed in by the reweight function if in the * compensating mode. */ template class CompSelector { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. The optional argument gives the margin * used to get a new overestimated probability for an object when * entering compensation mode. */ CompSelector(double newMargin = 1.1, double newTolerance = 1.0e-6) : N(0), last(), theMargin(newMargin), theTolerance(newTolerance) {} //@} public: /** @name The main function controlling the selection and compensation. */ //@{ /** * Insert an object given a probability for this object. If the * probability is zero or negative, the object will not be inserted * and the probability itself is returned. Otherwise the sum of * probabilities so far is returned. Note that if selection has * already started and this CompSelector is in compensating mode, it * will immediately leave this mode and the selection procedure will * start from scratch. */ WeightType insert(WeightType d, const T & t) { reset(); return selector.insert(d, t); } /** * Selct an object randomly. Given a random number generator which * generates flat random numbers in the interval ]0,1[ with the * operator()() function, select an object according to * the individual probabilities specified when they were * inserted. If the generated number is outside the allowed range or * the Selector is empty, a range_error will be thrown. The * generator should have a push_back function which will be used * push back a uniform random number in the interval ]0,1[ * calculated from the fraction of rnd which was in the range of the * selected object. */ template T & select(RNDGEN & rnd) { ++N; if ( !compensating() ) last = selector.select(rnd); return last; } /** * Report the weight associated with the last selected * object. Returns the zero if weight was below unity, otherwise the * compensation mode will be entered and the new overestimated * probabilty for the last selected object will be returned. */ WeightType reweight(double & weight) { if ( abs(weight) > 1.0 + tolerance() ) { // Retrieve the old overestimate of the object by seing how much // the summed weights are decreased when removing the object. WeightType oldtot = selector.sum(); WeightType oldmax = oldtot - selector.erase(last); WeightType newmax = oldmax*abs(weight)*margin(); WeightType newtot = selector.insert(newmax, last); double rat = newmax/oldmax; // Setup the new compensation level. Level level; level.weight = 1.0/rat; level.lastN = long(N*newtot/oldtot); // If we are already compensating, reweight the previous // compensation levels. for ( int i = 0, M = levels.size(); i < M; ++i ) { levels[i].lastN = long(levels[i].lastN*newtot/oldtot); levels[i].weight /= rat; } levels.push_back(level); weight /= rat; return newmax; } // If we are compensating we should only accept the selection if the // weight is above the previous overestimate. if ( compensating() ) if ( abs(weight) < levels.back().weight ) weight = 0.0; return WeightType(); } /** * Exit compensation mode and start selection procedure from * scratch. */ void reset() { N = 0; levels.clear(); last = T(); } /** * Erases all objects. */ void clear() { selector.clear(); reset(); } /** * Set the margin used to get a new overestimated probability for an * object when entering compensation mode. */ void margin(double m) { theMargin = m; } /** * Set the tolerance for how much a weight is allowed to be * larger than unity before starting the compensation. */ void tolerance(double t) { theTolerance = t; } //@} /** @name Simple access functions. */ //@{ /** * Return true if this CompSelector is in a compensating state. */ bool compensating() { // Leave all levels which has reached there 'expiry date'. while ( levels.size() && levels.back().lastN < N ) levels.pop_back(); return !levels.empty(); } /** * If in a compensating mode, return the number of selection needed * before exiting this mode. */ long compleft() const { return levels.empty()? 0: levels.back().lastN - N; } /** * Return the sum of probabilities of the objects inserted. Note * that probabilities specified when objects are inserted are * rescaled with this number to give unit probability for * 'select()'. */ WeightType sum() const { return selector.sum(); } /** * Return the margin used to get a new overestimated probability for an * object when entering compensation mode. */ double margin() const { return theMargin; } /** * Return the tolerance for how much a weight is allowed to be * larger than unity before starting the compensation. */ double tolerance() const { return theTolerance; } //@} /** @name I/O functions. */ //@{ /** * Output to a stream. */ template void output(OStream & os) const { os << selector << N << last << theMargin << theTolerance << levels.size(); for ( int i = 0, M = levels.size(); i < M; ++i ) os << levels[i].lastN << levels[i].weight; } /** * Input from a stream. */ template void input(IStream & is) { long M; is >> selector >> N >> last >> theMargin >> theTolerance >> M; levels.resize(M); for ( int i = 0; i < M; ++i ) is >> levels[i].lastN >> levels[i].weight; } //@} private: /** * Internal struct used for bookkeeping when compensating. */ struct Level { /** * The selection number at which point this level of compensation * is ended. */ long lastN; /** * The minimum weight allowed when compensating on this level. */ double weight; }; private: /** * The underlying selector */ Selector selector; /** * The number of selections so far. */ long N; /** * The last selected object. */ T last; /** * The margin used to get a new overestimated probability for an * object when entering compensation mode. */ double theMargin; /** * Set the tolerance for how much a weight is allowed to be * larger than unity before starting the compensation. */ double theTolerance; /** * The currently active compensation levels. */ vector levels; }; /** * Output a Selector to a stream. */ template inline OStream & operator<<(OStream & os, const CompSelector & s) { s.output(os); return os; } /** * Input a Selector from a stream. */ template inline IStream & operator>>(IStream & is, CompSelector & s) { s.input(is); return is; } } #endif /* THEPEG_CompSelector_H */ diff --git a/Utilities/Current.h b/Utilities/Current.h --- a/Utilities/Current.h +++ b/Utilities/Current.h @@ -1,152 +1,152 @@ // -*- C++ -*- // // Current.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_Current_H #define ThePEG_Current_H // This is the declaration of the Current class. namespace ThePEG { /** * The Current class keeps a static stack of objects of the templated * class, which can be used anywhere by any class. When an object is * active it adds itself to the stack which can be used by any other * object through the static functions of the Current class. If * someone needs to use an alternative object a new Current object can * be constructed with a pointer to the desired object * as argument and that object will the be used by the static Current * functions until the Current object is destructed. * * Default-contructed objects of the Current class can be used as a * pointer to the currently chosen object on the stack. * * The typical use case for this class is a handler class which uses a * number of objects which do not have a reference back to the * handler, but still need to acces some member functions. In a member * function the handler class will construct a Current object: * Current<Handler> current(this); in any following * function called in this member function, any object can then access * the handlers methods as * Current<Handler>()->memfun();. * */ template class Current { public: /** * Default constructor does nothing. */ Current() : pushed(false) {} /** * Copy-constructor does nothing. */ Current(const Current &) : pushed(false) {} /** * Construct a new object specifying a new object, \a o, to be used * during this objects lifetime. The object must not be deleted * until the Current object us destroyed. */ Current(T * t) : pushed(false) { if ( t ) { theStack.push_back(t); pushed = true; } } /** * The destructor removing the object specified in the constructor * from the stack. */ ~Current() { if ( pushed ) theStack.pop_back(); } public: /** * Returns true if there is no currently chosen object. */ static bool isVoid() { return theStack.empty() || !(theStack.back()); } /** * Return a reference to the currently chosen object. */ static T & current() { return *theStack.back(); } /** * Return a reference to the currently chosen object. */ T & operator*() const { return *theStack.back(); } /** * Return a pointer to the currently chosen object. */ T * operator->() const { return theStack.back(); } /** * Pointer to the stack */ static T * ptr() { return theStack.back(); } /** * Test for existance */ operator bool() const { return ptr(); } /** * Test for existance */ bool operator!() const { return !ptr(); } private: /** * The stack of objects requested. */ static vector theStack; /** * True if this object is responsible for pushing an object * onto the stack. */ bool pushed; private: /** * Private and non-existent assignment operator. */ Current & operator=(const Current &) = delete; }; template std::vector ThePEG::Current::theStack; } #endif /* ThePEG_Current_H */ diff --git a/Utilities/Debug.cc b/Utilities/Debug.cc --- a/Utilities/Debug.cc +++ b/Utilities/Debug.cc @@ -1,188 +1,188 @@ // -*- C++ -*- // // Debug.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the Debug class. // #include "Debug.h" #include "config.h" #ifdef ThePEG_HAS_FPU_CONTROL #include #endif #ifdef ThePEG_HAS_FENV #include #endif using namespace ThePEG; int Debug::level = 0; bool Debug::isset = false; std::vector Debug::debugItems; void Debug::debugItem(int item, bool on) { if ( item < 0 ) return; debugItems.resize(item + 1, false); debugItems[item] = on; } void Debug::setDebug(int ilev) { if ( ilev < 0 ) debugItem(-ilev, true); else { level = ilev; isset = true; } } void Debug::unmaskFpuErrors() { unmaskFpuOverflow(); unmaskFpuDivZero(); // unmaskFpuDenorm(); unmaskFpuInvalid(); } void Debug::unmaskFpuOverflow() { #ifdef ThePEG_HAS_FENV feenableexcept(FE_OVERFLOW); #else #ifdef ThePEG_HAS_FPU_CONTROL fpu_control_t cw; _FPU_GETCW(cw); cw &= ~(_FPU_MASK_OM); _FPU_SETCW(cw); #endif #endif } void Debug::unmaskFpuUnderflow() { #ifdef ThePEG_HAS_FENV feenableexcept(FE_UNDERFLOW); #else #ifdef ThePEG_HAS_FPU_CONTROL fpu_control_t cw; _FPU_GETCW(cw); cw &= ~(_FPU_MASK_UM); _FPU_SETCW(cw); #endif #endif } void Debug::unmaskFpuDivZero() { #ifdef ThePEG_HAS_FENV feenableexcept(FE_DIVBYZERO); #else #ifdef ThePEG_HAS_FPU_CONTROL fpu_control_t cw; _FPU_GETCW(cw); cw &= ~(_FPU_MASK_ZM); _FPU_SETCW(cw); #endif #endif } void Debug::unmaskFpuDenorm() { #ifdef ThePEG_HAS_FENV feenableexcept(FE_INEXACT); #else #ifdef ThePEG_HAS_FPU_CONTROL fpu_control_t cw; _FPU_GETCW(cw); cw &= ~(_FPU_MASK_DM); _FPU_SETCW(cw); #endif #endif } void Debug::unmaskFpuInvalid() { #ifdef ThePEG_HAS_FENV feenableexcept(FE_INVALID); #else #ifdef ThePEG_HAS_FPU_CONTROL fpu_control_t cw; _FPU_GETCW(cw); cw &= ~(_FPU_MASK_IM); _FPU_SETCW(cw); #endif #endif } void Debug::maskFpuErrors() { maskFpuOverflow(); maskFpuDivZero(); maskFpuDenorm(); maskFpuInvalid(); } void Debug::maskFpuOverflow() { #ifdef ThePEG_HAS_FENV fedisableexcept(FE_OVERFLOW); #else #ifdef ThePEG_HAS_FPU_CONTROL fpu_control_t cw; _FPU_GETCW(cw); cw |= (_FPU_MASK_OM); _FPU_SETCW(cw); #endif #endif } void Debug::maskFpuUnderflow() { #ifdef ThePEG_HAS_FENV fedisableexcept(FE_UNDERFLOW); #else #ifdef ThePEG_HAS_FPU_CONTROL fpu_control_t cw; _FPU_GETCW(cw); cw |= (_FPU_MASK_UM); _FPU_SETCW(cw); #endif #endif } void Debug::maskFpuDivZero() { #ifdef ThePEG_HAS_FENV fedisableexcept(FE_DIVBYZERO); #else #ifdef ThePEG_HAS_FPU_CONTROL fpu_control_t cw; _FPU_GETCW(cw); cw |= (_FPU_MASK_ZM); _FPU_SETCW(cw); #endif #endif } void Debug::maskFpuDenorm() { #ifdef ThePEG_HAS_FENV fedisableexcept(FE_INEXACT); #else #ifdef ThePEG_HAS_FPU_CONTROL fpu_control_t cw; _FPU_GETCW(cw); cw |= (_FPU_MASK_DM); _FPU_SETCW(cw); #endif #endif } void Debug::maskFpuInvalid() { #ifdef ThePEG_HAS_FENV fedisableexcept(FE_INVALID); #else #ifdef ThePEG_HAS_FPU_CONTROL fpu_control_t cw; _FPU_GETCW(cw); cw |= (_FPU_MASK_IM); _FPU_SETCW(cw); #endif #endif } diff --git a/Utilities/Debug.h b/Utilities/Debug.h --- a/Utilities/Debug.h +++ b/Utilities/Debug.h @@ -1,137 +1,137 @@ // -*- C++ -*- // // Debug.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_Debug_H #define ThePEG_Debug_H // This is the declaration of the Debug class. #include namespace ThePEG { /** * The Debug class defines a number of debug levels and a * static public member giving the current debug level in a run. */ class Debug { public: /** * The different debug levels. */ enum Levels { noDebug = 0, /**< No debugging. */ printSomeEvents = 1, /**< Lowest debug level. Some events are printed out. */ printEveryEvent = 5, /**< Higher debug level. All events are printed out. */ full = 9 /**< Highest possible debug level */ }; /** * The current level. */ static int level; /** * If true, the debug level has been set from the outside from the * calling program. This would then override any debug settings in * the event generator. */ static bool isset; /** * A vector of switches indicating whether a given debug item * is switched on or not. The index of a debug item has no special * meaning. An implementor may assume that a given number * corresponds to a certain request for debug output, but cannot be * sure that someone else uses that number for some other purpose. */ static std::vector debugItems; /** * Switch on or off a given debug item. If no such item exists, one * will be created. */ static void debugItem(int item, bool on); /** * Set the debug level. */ static void setDebug(int ilev); /** * Check if a given item should be debugged. If no such item is * present false is returned. */ static bool debugItem(int item) { if ( level == noDebug ) return false; if ( level == full ) return true; return ( item < 0 || std::size_t(item) >= debugItems.size() )? false: debugItems[item]; } /** @name Functions for manipulating floating point (FPU) signals * (requires the existence of fpu_controll.h on the * platform). */ //@{ /** * Switch on signalling all FPU exceptions. */ static void unmaskFpuErrors(); /** * Switch on signalling overflow FPU exceptions. */ static void unmaskFpuOverflow(); /** * Switch on signalling underflow FPU exceptions. */ static void unmaskFpuUnderflow(); /** * Switch on signalling division by zero FPU exceptions. */ static void unmaskFpuDivZero(); /** * Switch on signalling denormalized argument FPU exceptions. */ static void unmaskFpuDenorm(); /** * Switch on signalling invalid operation FPU exceptions. */ static void unmaskFpuInvalid(); /** * Switch off signalling all FPU exceptions. */ static void maskFpuErrors(); /** * Switch off signalling overflow FPU exceptions. */ static void maskFpuOverflow(); /** * Switch off signalling underflow FPU exceptions. */ static void maskFpuUnderflow(); /** * Switch off signalling division by zero FPU exceptions. */ static void maskFpuDivZero(); /** * Switch off signalling denormalized argument FPU exceptions. */ static void maskFpuDenorm(); /** * Switch off signalling invalid operation FPU exceptions. */ static void maskFpuInvalid(); //@} }; } #endif /* ThePEG_Debug_H */ diff --git a/Utilities/DescribeClass.h b/Utilities/DescribeClass.h --- a/Utilities/DescribeClass.h +++ b/Utilities/DescribeClass.h @@ -1,357 +1,357 @@ // -*- C++ -*- // // DescribeClass.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_DescribeClass_H #define ThePEG_DescribeClass_H #include "ThePEG/Utilities/ClassDescription.h" namespace ThePEG { /** * Helper class for multiple base classes. If a class to be described * by DescribeClass has multiple base classes, B1 and B2, they should * be encoded by BaseClasses. This can be done for up to four * base classes. */ template struct BaseClasses {}; /** * Traits class used by DescribeCLassT for transparent handling of one * base class or a several base classes encoded by BaseClasses. */ template struct BaseClassesTraits { /** The first base class */ typedef T Base1; /** The second base class */ typedef int Base2; /** The third base class */ typedef int Base3; /** The fourth base class */ typedef int Base4; }; /** * Traits class used by DescribeCLassT for transparent handling of one * base class or a several base classes encoded by BaseClasses. */ template struct BaseClassesTraits< BaseClasses > { /** The first base class */ typedef BaseT1 Base1; /** The second base class */ typedef BaseT2 Base2; /** The third base class */ typedef BaseT3 Base3; /** The fourth base class */ typedef BaseT4 Base4; }; /** * Helper class used by DescribeClassT for transparent handling of * classes with and without persistent I/O functions. */ template struct DescribeClassPIOHelper { /** * Call standard output function. */ static void output(const T & t, PersistentOStream & os) { t.persistentOutput(os); } /** * Call standard input function. */ static void input(T & t, PersistentIStream & is, int oldVersion) { t.persistentInput(is, oldVersion); } }; /** * Helper class used by DescribeClassT for transparent handling of * classes with and without persistent I/O functions. */ template struct DescribeClassPIOHelper { /** * Do nothing as T has no persistent I/O functions. */ static void output(const T &, PersistentOStream &) {} /** * Do nothing as T has no persistent I/O functions. */ static void input(T &, PersistentIStream &, int) {} }; /** * Helper class used by DescribeClassT for transparent handling of * abstract and concrete classes. */ template struct DescribeClassAbstractHelper { /** * Default-creat an object. */ static typename ThePEG::Ptr::pointer create() { return new_ptr(T()); } }; /** * Helper class used y DescribeClassT for transparent handling of * abstract and concrete classes. */ template struct DescribeClassAbstractHelper { /** * Throw an exception as the class is bastract. */ static typename ThePEG::Ptr::pointer create() { throw std::logic_error("Tried to instantiate abstract class " + ClassTraits::className()); } }; /** * DescribeClassT and its derived companion classes DescribeClass * DescribeAbstractClass, DescribeNoPIOClass and * DescribeAbstractNoPIOClass, is a simplified interface to the type * information system in ThePEG. For simple classes there is no need * to specialize the ClassTraits and BaseClassTrait classes and to * have a static member variable of ClassDescription in the class (as * in the full ThePEG type info system). Instead it is enough to have * one statically initialized variable of one of the DescraibeClass * classes for each class. The Abstract and NoPIO versions of this * class should be used for abstract classes and classes without * persistent I/O functions respectively. */ template class DescribeClassT: public ClassDescriptionBase { public: ThePEG_DECLARE_TEMPLATE_POINTERS(T,TPtr); ThePEG_DECLARE_POINTERS(Base,BPtr); /** * Constructor taking the name of the class, the dynamic library * where it is located and an optional version number as argument. */ DescribeClassT(string cname, string lib, int vers = 0) : ClassDescriptionBase(cname, typeid(T), vers, lib, Abstract) { DescriptionList::Register(*this); T::Init(); } /** * The descructor. */ virtual ~DescribeClassT() {} /** * Set up the base class information for this object. */ virtual void setup() { DescriptionVector bases; const ClassDescriptionBase * b = DescriptionList::find(typeid(typename BaseClassesTraits::Base1)); if ( b ) bases.push_back(b); b = DescriptionList::find(typeid(typename BaseClassesTraits::Base2)); if ( b ) bases.push_back(b); b = DescriptionList::find(typeid(typename BaseClassesTraits::Base3)); if ( b ) bases.push_back(b); b = DescriptionList::find(typeid(typename BaseClassesTraits::Base4)); if ( b ) bases.push_back(b); baseClasses(bases.begin(), bases.end()); } /** * Default-create an object. */ virtual BPtr create() const { return DescribeClassAbstractHelper::create(); } /** * Call standard output function. */ virtual void output(tcBPtr o, PersistentOStream & os) const { tcTPtr t = dynamic_ptr_cast(o); DescribeClassPIOHelper::output(*t, os); } /** * Call standard input function. */ virtual void input(tBPtr o, PersistentIStream & is, int oldVersion) const { tTPtr t = dynamic_ptr_cast(o); DescribeClassPIOHelper::input(*t, is, oldVersion); } }; /** * DescribeClass and its companion classes DescribeAbstractClass, * DescribeNoPIOClass and DescribeAbstractNoPIOClass, is a simplified * interface to type information system in ThePEG. For simple classes * there is no need to specialize the ClassTraits and BaseClassTrait * classes and to have a static member variable of ClassDescription in * the class (as in the full ThePEG type info system). Instead it is * enough to have one statically initialized variable of one of the * DescraibeClass classes for each class. The Abstract and NoPIO * versions of this class may be used for abstract classes and * classes without persistent I/O functions respectively. * * The template arguments are as follows: * T : the class being described. * BaseT : The base class of T. If several base classes these should be * encoded s template arguments to the BaseClasses class * (at most four base classes can be encoded). * Abstract: shoule be set to true if class T is abstract. * NoPIO : shoule be set to true if class T does not persistent I/O functions. */ template class DescribeClass: public DescribeClassT { public: /** * Constructor taking the name of the class, the dynamic library * where it is located and an optional version number as argument. */ DescribeClass(string cname, string lib, int vers = 0) : DescribeClassT(cname, lib, vers) {} }; /** * DescribeClass and its companion classes DescribeAbstractClass, * DescribeNoPIOClass and DescribeAbstractNoPIOClass, is a simplified * interface to type information system in ThePEG. For simple classes * there is no need to specialize the ClassTraits and BaseClassTrait * classes and to have a static member variable of ClassDescription in * the class (as in the full ThePEG type info system). Instead it is * enough to have one statically initialized variable of one of the * DescraibeClass classes for each class. The Abstract and NoPIO * versions of this class may be used for abstract classes and * classes without persistent I/O functions respectively. * * The template arguments are as follows: * T : the class being described. * BaseT : The base class of T. If several base classes these should be * encoded s template arguments to the BaseClasses class * (at most four base classes can be encoded). */ template class DescribeNoPIOClass: public DescribeClassT { public: /** * Constructor taking the name of the class, the dynamic library * where it is located and an optional version number as argument. */ DescribeNoPIOClass(string cname, string lib, int vers = 0) : DescribeClassT(cname, lib, vers) {} }; /** * DescribeClass and its companion classes DescribeAbstractClass, * DescribeNoPIOClass and DescribeAbstractNoPIOClass, is a simplified * interface to type information system in ThePEG. For simple classes * there is no need to specialize the ClassTraits and BaseClassTrait * classes and to have a static member variable of ClassDescription in * the class (as in the full ThePEG type info system). Instead it is * enough to have one statically initialized variable of one of the * DescraibeClass classes for each class. The Abstract and NoPIO * versions of this class may be used for abstract classes and * classes without persistent I/O functions respectively. * * The template arguments are as follows: * T : the class being described. * BaseT : The base class of T. If several base classes these should be * encoded s template arguments to the BaseClasses class * (at most four base classes can be encoded). */ template class DescribeAbstractClass: public DescribeClassT { public: /** * Constructor taking the name of the class, the dynamic library * where it is located and an optional version number as argument. */ DescribeAbstractClass(string cname, string lib, int vers = 0) :DescribeClassT(cname, lib, vers) {} }; /** * DescribeClass and its companion classes DescribeAbstractClass, * DescribeNoPIOClass and DescribeAbstractNoPIOClass, is a simplified * interface to type information system in ThePEG. For simple classes * there is no need to specialize the ClassTraits and BaseClassTrait * classes and to have a static member variable of ClassDescription in * the class (as in the full ThePEG type info system). Instead it is * enough to have one statically initialized variable of one of the * DescraibeClass classes for each class. The Abstract and NoPIO * versions of this class may be used for abstract classes and * classes without persistent I/O functions respectively. * * The template arguments are as follows: * T : the class being described. * BaseT : The base class of T. If several base classes these should be * encoded s template arguments to the BaseClasses class * (at most four base classes can be encoded). */ template class DescribeAbstractNoPIOClass: public DescribeClassT { public: /** * Constructor taking the name of the class, the dynamic library * where it is located and an optional version number as argument. */ DescribeAbstractNoPIOClass(string cname, string lib, int vers = 0) :DescribeClassT(cname, lib, vers) {} }; } #endif /* ThePEG_DescribeClass_H */ diff --git a/Utilities/DescriptionList.cc b/Utilities/DescriptionList.cc --- a/Utilities/DescriptionList.cc +++ b/Utilities/DescriptionList.cc @@ -1,95 +1,95 @@ // -*- C++ -*- // // DescriptionList.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the DescriptionList class. // #include "DescriptionList.h" #include "ClassDescription.h" using namespace ThePEG; void DescriptionList::hookup() { for ( DescriptionMap::iterator it = descriptionMap().begin(); it != descriptionMap().end(); ++it ) it->second->setup(); } void DescriptionList::Register(ClassDescriptionBase & pd) { if ( find(pd.info()) ) return; insert(pd); hookup(); } DescriptionList::DescriptionMap & DescriptionList::descriptionMap() { static DescriptionMap theDescriptionMap; return theDescriptionMap; } DescriptionList::StringMap & DescriptionList::stringMap() { static StringMap theStringMap; return theStringMap; } string DescriptionList::className(const type_info & ti) { const ClassDescriptionBase * d = find(ti); return d? d->name(): string(); } int DescriptionList::version(const type_info & ti) { const ClassDescriptionBase * d = find(ti); return d? d->version(): 0; } string DescriptionList::library(const type_info & ti) { const ClassDescriptionBase * d = find(ti); return d? d->library(): string(); } void DescriptionList::insert(ClassDescriptionBase & pb) { #ifndef THEPEG_DYNAMIC_TYPE_INFO_BUG descriptionMap()[&(pb.info())] = &pb; #else descriptionMap()[pb.info().name()] = &pb; #endif stringMap()[pb.name()] = &pb; // The following is for backward compatibility and will eventually // be removed. string name = pb.name(); if ( name.find('/') == string::npos ) { if ( name.substr(0, 2) == "::" ) name = name.substr(2); if ( name.find("::") == string::npos ) return; while ( name.find("::") != string::npos ) name.replace(name.find("::"), 2, "/"); name = "/" + name; stringMap()[name] = &pb; } else { if ( name[0] == '/' ) name = name.substr(1); while ( name.find('/') != string::npos ) name.replace(name.find('/'), 1, "::"); stringMap()[name] = &pb; } } void DescriptionList::printHierarchies(ostream & os) { for ( DescriptionMap::iterator it = descriptionMap().begin(); it != descriptionMap().end(); ++it ) { os << "Class Name '" << it->second->name() << "'\n (" #ifndef THEPEG_DYNAMIC_TYPE_INFO_BUG << it->first->name() #else << it->first #endif << "," << it->second << ") version " << it->second->version() << endl << " Base classes:" << endl; for ( unsigned int i = 0; i < it->second->descriptions().size(); ++i ) os << " " << i << " '" << it->second->descriptions()[i]->name() << "' (" << it->second->descriptions()[i] << ")" << endl; } } diff --git a/Utilities/DescriptionList.h b/Utilities/DescriptionList.h --- a/Utilities/DescriptionList.h +++ b/Utilities/DescriptionList.h @@ -1,125 +1,125 @@ // -*- C++ -*- // // DescriptionList.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_DescriptionList_H #define ThePEG_DescriptionList_H // This is the declaration of the DescriptionList class. #include "ThePEG/Config/ThePEG.h" #include "ClassDescription.fh" namespace ThePEG { /** * The DescriptionList keeps a static list of descriptions * of classes included in the current run. */ class DescriptionList { public: #ifndef THEPEG_DYNAMIC_TYPE_INFO_BUG /** Map of class descriptions indexed by type_info objects. */ typedef map DescriptionMap; #else /** Map of class descriptions indexed by type_info objects. */ typedef map DescriptionMap; #endif /** Map of class descriptions indexed by platform-independent class * names. */ typedef map StringMap; public: /** * Insert a description in the list. */ static void Register(ClassDescriptionBase &); /** * Get the description of a class giving its type_info object. */ static inline const ClassDescriptionBase * find(const type_info & ti) { #ifndef THEPEG_DYNAMIC_TYPE_INFO_BUG DescriptionMap::const_iterator it = descriptionMap().find(&ti); #else DescriptionMap::const_iterator it = descriptionMap().find(ti.name()); #endif if ( it == descriptionMap().end() ) return 0; return (*it).second; } /** * Return the name of the class corresponding to the given type_info object. */ static string className(const type_info & ti); /** * Return the version of the class corresponding to the given type_info object. */ static int version(const type_info & ti); /** * Return the dynamic library of the class corresponding to the * given type_info object. */ static string library(const type_info & ti); /** * Get the description of a class giving its name. */ static inline const ClassDescriptionBase * find(const string & name) { StringMap::const_iterator it = stringMap().find(name); if ( it == stringMap().end() ) return 0; return it->second; } /** * Return the static set of descriptions mapped to the relevant * type_info objects. */ static inline const DescriptionMap & all() { return descriptionMap(); } /** * Print the classes in the list and their base classes to a * stream. Mainly intended for debugging purposes. */ static void printHierarchies(ostream & os); protected: /** * Hookup the base class descriptions in the list. */ static void hookup(); /** * Insert a class description. */ static void insert(ClassDescriptionBase & pb); /** * Return the static set of descriptions mapped to the relevant * type_info objects. This function has a static DescriptionMap * variable which is initialized the first time it is called. */ static DescriptionMap & descriptionMap(); /** * Return the static set of descriptions mapped to the corresponding * class names. This function has a static StringMap variable which * is initialized the first time it is called. */ static StringMap & stringMap(); }; } #endif /* ThePEG_DescriptionList_H */ diff --git a/Utilities/Direction.cc b/Utilities/Direction.cc --- a/Utilities/Direction.cc +++ b/Utilities/Direction.cc @@ -1,28 +1,28 @@ // -*- C++ -*- // // Direction.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the Direction class. // #include "Direction.h" using namespace ThePEG; MultipleDirectionException::MultipleDirectionException(int i) { theMessage << "Attempted to instantiate a second object of the Direction<" << i << ">. This is intolerable!"; severity(abortnow); } UndefinedDirectionException::UndefinedDirectionException(int i) { theMessage << "Attempted to use/create a Direction<" << i << "> object with undefined direction. This is intolerable!"; severity(abortnow); } diff --git a/Utilities/Direction.h b/Utilities/Direction.h --- a/Utilities/Direction.h +++ b/Utilities/Direction.h @@ -1,161 +1,161 @@ // -*- C++ -*- // // Direction.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_Direction_H #define ThePEG_Direction_H // This is the declaration of the Direction class. #include "ThePEG/Config/ThePEG.h" #include "Direction.xh" namespace ThePEG { template /** * A Direction object can be used to specify that some * following operations should be assumed to be performed with the * z-direction of the momenta reversed. As an example, if * Direction<0>::pos() is true, the method * Lorentz5Momentum::dirPlus() will return the positive, * light-cone component, and Lorentz5Momentum::dirMinus() * the negative, while if Direction<0>::pos() is false * the behavior of the methods are reversed. * * Direction is templated with an integer template argument * (default = 0), and only one object per class can be instatiated at * the time. Attempts to instatiate a second object of a * Direction class will result in an exception being * thrown. To have several different directions classes with different * template arguments must be instantiated. Direction<0> is * reserved for Lorentz5Momentum. Attempts to use the * static methods of a Direction class when no object has * been instatiated will result in an exception being thrown. * * @see Lorentz5Momentum */ class Direction { public: /** The enum defining the directions. */ enum Dir { Neg = -1, /**< Reversed direction. */ Negative = -1, /**< Reversed direction. */ Undefined = 0, /**< No direction has been defined. */ Pos = 1, /**< Standard (positive) direction. */ Positive = 1 /**< Standard (positive) direction. */ }; public: /** * Create an object with a given direction. */ Direction(Dir newDirection) { if ( theDirection != Undefined ) throw MultipleDirectionException(I); if ( newDirection == Positive ) theDirection = Positive; else if ( newDirection == Negative ) theDirection = Negative; else throw UndefinedDirectionException(I); } /** * Create an object with a positive direction if rnd > 0.5, * otherwise set the negative direction. */ Direction(double rnd) { if ( theDirection != Undefined ) throw MultipleDirectionException(I); theDirection = rnd > 0 ? Positive : Negative; } /** * Create an object with a positive direction if p is true, * otherwise set the negative direction. */ Direction(bool p) { if ( theDirection != Undefined ) throw MultipleDirectionException(I); theDirection = p ? Positive : Negative; } /** * Destructure makeing the static variable undefined. */ ~Direction() { theDirection = Undefined; } public: /** * Set the direction. */ static void set(Dir newDirection) { if ( newDirection == Positive ) theDirection = Positive; else if ( newDirection == Negative ) theDirection = Negative; else throw UndefinedDirectionException(I); } /** * Reverse the direction. */ static void reverse() { theDirection = pos() ? Negative : Positive; } /** * Return true if the direction is positive. */ static bool pos() { return dir() == Positive; } /** * Return true if the direction is negative (reversed). */ static bool neg() { return dir() == Negative; } /** * Return the direction. */ static Dir dir() { if ( theDirection == Undefined ) throw UndefinedDirectionException(I); return theDirection; } private: /** * The direction. */ static Dir theDirection; private: /** * Default ctors and assignment is private and not implemented. */ Direction(); /** * Default ctors and assignment is private and not implemented. */ Direction(const Direction &); /** * Default ctors and assignment is private and not implemented. */ Direction & operator=(const Direction &) = delete; }; template typename Direction::Dir Direction::theDirection = Direction::Undefined; } #endif /* ThePEG_Direction_H */ diff --git a/Utilities/Direction.xh b/Utilities/Direction.xh --- a/Utilities/Direction.xh +++ b/Utilities/Direction.xh @@ -1,39 +1,39 @@ // -*- C++ -*- // // Direction.xh is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_Direction_XH #define ThePEG_Direction_XH // // This is the declarations of the exception classes used by the // Direction class. // #include "ThePEG/Utilities/Exception.h" namespace ThePEG { /** @cond EXCEPTIONCLASSES */ /** Exception class used by Direction when multiple objects of the * same direction class is requested. */ struct MultipleDirectionException: public Exception { /** Constructor */ MultipleDirectionException(int); }; /** Exception class used by Direction when an undefined direction is * used. */ struct UndefinedDirectionException: public Exception { /** Constructor */ UndefinedDirectionException(int); }; /** @endcond */ } #endif /* ThePEG_Direction_XH */ diff --git a/Utilities/DynamicLoader.cc b/Utilities/DynamicLoader.cc --- a/Utilities/DynamicLoader.cc +++ b/Utilities/DynamicLoader.cc @@ -1,159 +1,161 @@ // -*- C++ -*- // // DynamicLoader.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the DynamicLoader class. // // macro is passed in from -D compile flag #ifndef THEPEG_PKGLIBDIR #error Makefile.am needs to define THEPEG_PKGLIBDIR #endif #include "DynamicLoader.h" #include "ThePEG/Utilities/StringUtils.h" #include "ThePEG/Config/algorithm.h" #include "config.h" #ifdef ThePEG_HAS_DLOPEN #include #endif #include #ifdef ThePEG_HAS_FENV #include #endif using namespace ThePEG; void DynamicLoader::dlname(string sofile) { if ( StringUtils::suffix(sofile) == "so" ) { string lafile = StringUtils::remsuf(sofile) + ".la"; ifstream is(lafile.c_str()); string line; while ( getline(is, line) ) { if ( line.find("dlname='") != string::npos ) { int pos = line.find('\'') + 1; int l = line.rfind('\'') - pos; sofile = StringUtils::basename(sofile); versionMap[sofile] = line.substr(pos, l); } } } else if ( StringUtils::suffix(StringUtils::remsuf(sofile)) == "so" ) { versionMap[StringUtils::basename(StringUtils::remsuf(sofile))] = StringUtils::basename(sofile); } } string DynamicLoader::dlnameversion(string libs) { string ret; do { string soname = StringUtils::car(libs); string dir = StringUtils::dirname(soname); if ( dir.length() ) dir += '/'; libs = StringUtils::cdr(libs); if ( versionMap.find(StringUtils::basename(soname)) != versionMap.end() ) ret += dir + versionMap[StringUtils::basename(soname)] + " "; else ret += soname + " "; } while ( libs.length() ); return StringUtils::stripws(ret); } bool DynamicLoader::loadcmd(string file) { #ifdef ThePEG_HAS_DLOPEN dlname(file); #ifdef ThePEG_HAS_FENV int oldfpe = fegetexcept(); #endif bool ret = dlopen(file.c_str(), RTLD_LAZY|RTLD_GLOBAL) != 0; #ifdef ThePEG_HAS_FENV feenableexcept(oldfpe); #endif if ( !ret ) lastErrorMessage += string(dlerror()) + string("\n"); return ret; #else #error ThePEG can only be run on platforms which support #error dynamic loading. return false; #endif } void DynamicLoader::appendPath(string path) { + if (path.size()==0) return; if ( path[path.size()-1] != '/' ) path += '/'; paths.push_back(path); apppaths.push_back(path); } void DynamicLoader::prependPath(string path) { + if (path.size()==0) return; if ( path[path.size()-1] != '/' ) path += '/'; paths.insert(paths.begin(), path); prepaths.push_back(path); } bool DynamicLoader::load(string name) { lastErrorMessage = ""; static set loaded; if ( loaded.find(name) != loaded.end() ) return true; loaded.insert(name); bool success = false; const string name_dylib = StringUtils::remsuf(name) + ".dylib"; if ( name[0] == '/' ) { success = loadcmd(name) || loadcmd(name_dylib); } else { for ( unsigned i = 0; i < paths.size(); ++i ) { string path = paths[i]; if ( path[path.size() - 1] != '/' ) path += '/'; if ( loadcmd(path + name) || loadcmd(path + name_dylib) ) { success = true; break; } } } if ( success || loadcmd(name) || loadcmd(name_dylib) ) { lastErrorMessage = ""; return true; } loaded.erase(name); return false; } const vector & DynamicLoader::appendedPaths() { return apppaths; } const vector & DynamicLoader::prependedPaths() { return prepaths; } const vector & DynamicLoader::allPaths() { return paths; } vector DynamicLoader::paths = DynamicLoader::defaultPaths(); vector DynamicLoader::prepaths = vector(); vector DynamicLoader::apppaths = vector(); string DynamicLoader::lastErrorMessage; map DynamicLoader::versionMap; vector DynamicLoader::defaultPaths() { vector vpaths; // macro is passed in from -D compile flag string instpath = THEPEG_PKGLIBDIR; vpaths.push_back(instpath); vpaths.push_back("."); return vpaths; } diff --git a/Utilities/DynamicLoader.h b/Utilities/DynamicLoader.h --- a/Utilities/DynamicLoader.h +++ b/Utilities/DynamicLoader.h @@ -1,127 +1,127 @@ // -*- C++ -*- // // DynamicLoader.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_DynamicLoader_H #define ThePEG_DynamicLoader_H // This is the declaration of the DynamicLoader class. #include "ThePEG/Config/ThePEG.h" namespace ThePEG { /** * DynamicLoader is the general interface to the dynamic * loader functions of the underlying operating system. Currently it * only works on Linux. * * @see ClassTraits * @see ClassDescription * @see DescriptionList * @see PersistentIStream */ class DynamicLoader { public: /** * The actual load command used on the current platform. */ static bool loadcmd(string); /** * Try to load the file given as argument. If the filename does not * begin with a '/', try to prepend the paths one at the time until * success. If all fail try without prepending a path. * @return true if the loading succeeded, false otherwise. */ static bool load(string file); /** * Add a path to the bottom of the list of directories to seach for * dynaically linkable libraries. */ static void appendPath(string); /** * Add a path to the top of the list of directories to seach for * dynaically linkable libraries. */ static void prependPath(string); /** * Return the last error message issued from the platforms loader. */ static string lastErrorMessage; /** * Insert the name of the given library with correct version numbers * appended, in the corresponding map. */ static void dlname(string); /** * Given a list of generic library names, return the same list with * appended version numbers where available. */ static string dlnameversion(string libs); /** * Return the full list of directories to seach for dynaically * linkable libraries. */ static const vector & allPaths(); /** * Return the list of appended directories to seach for dynaically * linkable libraries. */ static const vector & appendedPaths(); /** * Return the list of prepended directories to seach for dynaically * linkable libraries. */ static const vector & prependedPaths(); private: /** * The list of directories to seach for dynaically linkable * libraries. */ static vector paths; /** * The list of prepended directories to seach for dynaically linkable * libraries. */ static vector prepaths; /** * The list of appended directories to seach for dynaically linkable * libraries. */ static vector apppaths; /** * Used to initialize the paths vector from the ThePEG_PATH * environment. */ static vector defaultPaths(); /** * Map of names of dynamic libraries with correct version numbers * indexed by their generic names. */ static map versionMap; }; } #endif /* ThePEG_DynamicLoader_H */ diff --git a/Utilities/EnumIO.h b/Utilities/EnumIO.h --- a/Utilities/EnumIO.h +++ b/Utilities/EnumIO.h @@ -1,96 +1,96 @@ // -*- C++ -*- // // EnumIO.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_EnumIO_H #define ThePEG_EnumIO_H // This is the declaration of the IEnum and OEnum classes and // associated templated functions. // #include "ThePEG/Config/ThePEG.h" // #include "EnumIO.fh" // #include "EnumIO.xh" namespace ThePEG { template /** * The OEnum helper class is used to facilitate output of enums * to persistent streams. An enum can hence be written like this:
* os >> oenum(x);
* * @see PersistentOStream * @see PersistentIStream * */ struct OEnum { /** Constructor. */ OEnum(const T & t): theT(t) {} /** Copy constructor. */ OEnum(const OEnum & oe): theT(oe.theT) {} /** The variable to be written */ const T & theT; }; /** * The IEnum helper class is used to facilitate input of enums * from persistent streams. An enum can hence be read like this:
* is >> ienum(x); * * @see PersistentOStream * @see PersistentIStream * */ template struct IEnum { /** Constructor. */ IEnum(T & t): theT(t) {} /** Copy constructor. */ IEnum(const IEnum & ie): theT(ie.theT) {} /** The variable to be read */ T & theT; }; /** Helper function to create an OEnum object for a given variable. */ template inline OEnum oenum(const T & t) { return OEnum(t); } /** Helper function to create an IEnum object for a given variable. */ template inline IEnum ienum(T & t) { return IEnum(t); } /** Overloading of operator<< for OEnum. */ template OStream & operator<<(OStream & os, const OEnum & e) { os << long(e.theT); return os; } /** Overloading of operator<< for IEnum. */ template IStream & operator>>(IStream & is, const IEnum & e) { long l = 0; is >> l; e.theT = T(l); return is; } } #endif /* ThePEG_EnumIO_H */ diff --git a/Utilities/Exception.cc b/Utilities/Exception.cc --- a/Utilities/Exception.cc +++ b/Utilities/Exception.cc @@ -1,144 +1,144 @@ // -*- C++ -*- // // Exception.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the Exception class. // #include "Exception.h" #include #include #include "ThePEG/Interface/Interfaced.h" #include "ThePEG/Repository/CurrentGenerator.h" #include "ThePEG/EventRecord/Event.h" #include "ThePEG/Utilities/Debug.h" void breakThePEG() { return; } extern "C" { void debugThePEG(const ThePEG::Interfaced * i) { i->debug(); } void debugEvent() { using namespace ThePEG; if ( !CurrentGenerator::isVoid() && CurrentGenerator::current().currentEvent() ) cerr << *CurrentGenerator::current().currentEvent(); } long debugEventNumber() { using namespace ThePEG; if ( !CurrentGenerator::isVoid() ) return CurrentGenerator::current().currentEventNumber(); return 0; } void debugDump() { using namespace ThePEG; if ( !CurrentGenerator::isVoid() ) CurrentGenerator::current().dump(); } void debugParticle(const ThePEG::Particle * p) { using namespace ThePEG; cerr << *p; } void debugParticles(int n, const ThePEG::Particle ** p) { using namespace ThePEG; LorentzMomentum sum; for ( int i = 0; i < n; i++ ) { cerr << **p; sum += (**p).momentum(); ++p; } cerr << ounit(sum,GeV) << "GeV \t" << ounit(sum.m(),GeV) << " GeV\n"; } } namespace ThePEG { Veto::Veto() { if ( ThePEG_DEBUG_LEVEL ) breakThePEG(); } Exception::Exception(const string & newMessage, Severity newSeverity) : theMessage(newMessage), handled(false), theSeverity(newSeverity) { breakThePEG(); if ( noabort && ( theSeverity == abortnow || theSeverity == maybeabort ) ) theSeverity = runerror; if ( theSeverity == abortnow ) { writeMessage(); abort(); } } Exception::~Exception() noexcept { if ( !handled ) { writeMessage(); if ( theSeverity == maybeabort ) abort(); } } void Exception::severity(Severity newSeverity) { theSeverity = newSeverity; if ( noabort && ( theSeverity == abortnow || theSeverity == maybeabort ) ) theSeverity = runerror; if ( theSeverity == abortnow ) { writeMessage(cerr); abort(); } } void Exception::writeMessage(ostream & os) const { switch ( severity() ) { case unknown: os << "unknown error type: "; break; case info: os << "Informational exception: "; break; case warning: os << "Warning: "; break; case setuperror: case eventerror: case runerror: case maybeabort: case abortnow: os << "Error: "; break; } os << message() << endl; switch ( severity() ) { case eventerror: os << "The generated event will be discarded." << endl; break; case runerror: os << "This run will be aborted." << endl; break; case maybeabort: case abortnow: os << "The program will now abort and dump core." << endl; break; case unknown: case info: case warning: case setuperror: break; } } ostream * Exception::errstream = &cerr; bool Exception::noabort = false; } diff --git a/Utilities/Exception.h b/Utilities/Exception.h --- a/Utilities/Exception.h +++ b/Utilities/Exception.h @@ -1,221 +1,221 @@ // -*- C++ -*- // // Exception.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_Exception_H #define ThePEG_Exception_H // This is the declaration of the Exception class. #include #include "ThePEG/Config/ThePEG.h" #include "Exception.fh" #include #include extern "C" { void breakThePEG(); } namespace ThePEG { /** * Exception is the base class for all exceptions to be * used in ThePEG. It is derived from std::exception and * adds information about the severity of the exception to indicate to * the Repository and EventGenrator how to act on it. * * To throw an exception one should inherit from * Exception and add information in the constructor of * the base class. Alternatively one can use the operator<< * operator on a default constructed Exception to * add information as for a standard ostream object, in * which case one should always end with adding an enum of the type * Exception::Severity to indicate the severity of the * exception e.g.
Exception() << "Something went wrong." << * Exception::eventerror. * * @see Repository * @see EventGenrator */ class Exception: public exception { public: /** * The levels of severity. */ enum Severity { unknown, /**< Unknown severity */ info, /**< Not severe (but the user should be * informed). */ warning, /**< Possibly severe, (the user should be * warned). */ setuperror, /**< Command failed during setup phase, * execution is continued. */ eventerror, /**< Possibly severe, (the event being * generated should be discarded). */ runerror, /**< Severe error, (the run should be * terminated). */ maybeabort, /**< Severe error, (the run should be * terminated, possibly dumping core). */ abortnow /**< Severe error, (the run is aborted * immediately, before the exception is * thrown). */ }; public: /** * Standard constructor. * @param str an error message. * @param sev the severity. */ Exception(const string & str, Severity sev); /** * Default constructor. */ Exception() : handled(false), theSeverity(unknown) { breakThePEG(); } /** * The copy constructor. */ Exception(const Exception & ex) : std::exception(ex), theMessage(ex.message()), handled(ex.handled), theSeverity(ex.severity()) { ex.handle(); } /** * The destructor */ virtual ~Exception() noexcept; public: /** * Assignment. */ const Exception & operator=(const Exception & ex) { handled = ex.handled; theMessage << ex.message(); theSeverity = ex.severity(); ex.handle(); return *this; } /** * Comparison */ bool operator==(const Exception & ex) const { return ( message() == ex.message() && severity() == ex.severity() ); } /** * Compare severity. If equal compare error message * lexicographically. */ bool operator<(const Exception & ex) const { return ( severity() == ex.severity() ? ( message() < ex.message() ) : ( severity() < ex.severity() ) ); } public: /** * Return the error message. */ virtual const char* what() const noexcept { static string str; str = message(); return str.c_str(); } /** * Return the error message. */ string message() const { string mess = theMessage.str(); return mess.empty() ? string("Error message not provided.") : mess; } /** * Write the error message to a stream. */ void writeMessage(ostream & os = *errstream) const; /** * Return the severity. */ Severity severity() const { return theSeverity; } /** * Indicate that this exception has been taken care of. */ void handle() const { handled = true; } /** * Add info to the exception message. */ template Exception & operator<<(const T & t) { theMessage << t; return *this; } /** * Set the severity for the exception. */ Exception & operator<<(Severity sev) { severity(sev); return *this; } protected: /** * set the severity. */ void severity(Severity); /** * Stream to write the error message to. */ mutable ostringstream theMessage; private: /** * True if this exception has been taken care of. */ mutable bool handled; /** * The severity. */ Severity theSeverity; /** * The default stream to write the error message if unhandled. */ static ostream * errstream; public: /** * If this flag is set, all abortnow and maybeabort severities will * be treated as runerror. */ static bool noabort; }; } #endif /* ThePEG_Exception_H */ diff --git a/Utilities/HoldFlag.h b/Utilities/HoldFlag.h --- a/Utilities/HoldFlag.h +++ b/Utilities/HoldFlag.h @@ -1,147 +1,147 @@ // -*- C++ -*- // // HoldFlag.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_HoldFlag_H #define ThePEG_HoldFlag_H // This is the declaration of the HoldFlag class. namespace ThePEG { template /** * HoldFlag objects are used to temporarily change the value * of an object, restoring the original value when the * HoldFlag object is destructed. * * @see Level */ class HoldFlag { public: /** * Constructor setting a temporary value for the given object. * @param newFlag the object which value is temporarily changed. * @param holdFlag the temporary value for the newFlag object. */ HoldFlag(T & newFlag, const T & holdFlag) : theFlag(newFlag), oldFlag(holdFlag) { std::swap(theFlag, oldFlag); } /** * Constructor setting the a temporary value for the given object. * @param newFlag the object which value is temporarily changed. * @param holdFlag the temporary value for the newFlag object. * @param finalFlag the newFlag object will be given the value * finalFlag when the HoldFlag object is destroyed. */ HoldFlag(T & newFlag, const T & holdFlag, const T & finalFlag) : theFlag(newFlag), oldFlag(holdFlag) { std::swap(theFlag, oldFlag); oldFlag = finalFlag; } /** * Destructor. Restores the corresponding object to its original * value. */ ~HoldFlag() { std::swap(theFlag, oldFlag); } private: /** * The object to be changed. */ T & theFlag; /** * The value which will be restored when this is destroyed. */ T oldFlag; /** * Default constructor is private and not implemented. */ HoldFlag(); /** * Copy constructor is private and not implemented. */ HoldFlag(const HoldFlag &); /** * Assignment is private and not implemented. */ HoldFlag & operator=(const HoldFlag &) = delete; }; /** * Specialization of HoldFlag for boolean variables. */ template <> class HoldFlag { public: /** * Constructor setting the a temporary value for the bool variable. * @param newFlag the boolean variable which value is temporarily changed. * @param holdFlag the temporary value for the newFlag variable. */ HoldFlag(bool & newFlag, bool holdFlag = true) : theFlag(newFlag), oldFlag(newFlag) { theFlag = holdFlag; } /** * Constructor setting the a temporary value for the bool variable. * @param newFlag the boolean variable which value is temporarily changed. * @param holdFlag the temporary value for the newFlag variable. * @param finalFlag the newFlag variable will be given the value * finalFlag when the HoldFlag object is destroyed. */ HoldFlag(bool & newFlag, bool holdFlag, bool finalFlag) : theFlag(newFlag), oldFlag(finalFlag) { theFlag = holdFlag; } /** * Destructor. Restores the corresponding variable to its original * value. */ ~HoldFlag() { theFlag = oldFlag; } private: /** * The variable to be changed. */ bool & theFlag; /** * The value which will be restored when this is destroyed. */ bool oldFlag; /** * Default constructor is private and not implemented. */ HoldFlag(); /** * Copy constructor is private and not implemented. */ HoldFlag(const HoldFlag &); /** * Assignment is private and not implemented. */ HoldFlag & operator=(const HoldFlag &) = delete; }; } #endif /* ThePEG_HoldFlag_H */ diff --git a/Utilities/Interval.h b/Utilities/Interval.h --- a/Utilities/Interval.h +++ b/Utilities/Interval.h @@ -1,244 +1,244 @@ // -*- C++ -*- // // Interval.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_Interval_H #define ThePEG_Interval_H // This is the declaration of the Interval class. #include #include #include "Interval.fh" #include "ThePEG/Utilities/UnitIO.h" namespace ThePEG { template /** * An Interval object is used to represent an interval * [ lower(), upper() ) where the ordering is defined by * the bool operator()(const T &, const T &) const member * of the CMP class (by defaut less). */ class Interval { public: /** * Construct an empty interval. */ Interval() : theLimits(pair()) {} /** * Construct interval [dn,up). */ Interval(T dn, T up) : theLimits(pair(dn, up)) {} /** * Test for equality. */ bool operator==(const Interval & i) const { return lower() == i.lower() && upper() == i.upper(); } /** * Test for ordering. * @return true if lower() < i.lower() or lower() * == i.lower() and upper() < i.upper(). */ bool operator<(const Interval & i) const { return cmp(lower(), i.lower()) || ( lower() == i.lower() && cmp(upper(), i.upper()) ); } /** * Check consistency ie. that lower() < upper(). */ bool check() const { return cmp(lower(), upper()); } /** * Returns true if x is within the interval. */ bool operator()(T x) const { return includes(x); } /** * Returns true if x is within the interval. */ bool includes(T x) const { return !cmp(x, lower()) && cmp(x, upper()); } /** * Returns true if the whole of i is within the interval. */ bool includes(const Interval & i) const { return includes(i.lower()) && !cmp(upper(), i.upper()); } /** * If x is in the interval return the interval [x,upper()) and * change this interval to [lower(),x). If x is not within the * interval, return [0,0) and leave this interval as it is. */ Interval chopUpper(T x) { Interval r; if ( includes(x) ) { r.lower(x); r.upper(upper()); upper(x); } return r; } /** * If x is in the interval return the interval [lower(),x) and * change this interval to [x,upper()). If x is not within the * interval, return [0,0) and leave this interval as it is. */ Interval chopLower(T x) { Interval r; if ( includes(x) ) { r.lower(lower()); r.upper(x); lower(x); } return r; } /** * If this interval operlaps with i return the overlapping interval. */ Interval overlap(const Interval & i) const { Interval res; if ( operator==(i) ) res = i; if ( includes(i.upper()) || includes(i.lower()) ) res = Interval(max(lower(),i.lower()), min(upper(), i.upper())); return res; } /** * If this interval operlaps with i return the union of the two * intervals. */ Interval sum(const Interval & i) const { Interval res; if ( operator==(i) ) res = i; if ( includes(i.upper()) || includes(i.lower()) ) res = Interval(min(lower(),i.lower()), max(upper(), i.upper())); return res; } /** * Return the upper limit of the interval. */ T upper() const { return theLimits.second; } /** * Return the lower limit of the interval. */ T lower() const { return theLimits.first; } /** * Set the upper limit of the interval. */ void upper(T up) { theLimits.second = up; } /** * Set the lower limit of the interval. */ void lower(T dn) { theLimits.first = dn; } /** * Check if any of the values in the iterator given range is * included in this interval. */ template bool check(Iterator first, Iterator last); /** * Check if all of the values in the given iterator range is * included in this interval. */ template bool checkAll(Iterator first, Iterator last); /** * If x is in the given interval, split the given interval in two, * otherwise return an empty list. */ std::vector< Interval > split(Interval, T x); /** * For each value in the given range is in the given interval, split * the interval in two, otherwise return an empty list. */ template std::vector< Interval > split(Interval, Iterator first, Iterator last); private: /** The lower and upper limit of this interval */ std::pair theLimits; /** The object used for comparisons. */ static CMP cmp; }; /** An interval of doubles. */ typedef Interval DInterval; /** Helper function to create an interval of a type determined by the * parameters. */ template inline Interval makeInterval(T dn, T up) { return Interval(dn, up); } /** Ouptut an interval to a stream. */ template inline OStream & operator<<(OStream & os, const Interval & i) { os << i.lower() << i.upper(); return os; } /** Input an interval from a stream. */ template inline IStream & operator>>(IStream & is, Interval & i) { T up, dn; is >> dn >> up; i.lower(dn); i.upper(up); return is; } /** Output an interval of a diminsionful type to a stream using the * given unit. * @param os the output stream. * @param i the interval. * @param u the unit. */ template void ounitstream(OStream & os, const Interval & i, UT & u) { os << ounit(i.lower(), u) << ounit(i.upper(), u); } /** Input an interval of a diminsionful type from a stream using the * given unit. * @param is the input stream. * @param i the interval. * @param u the unit. */ template void iunitstream(IStream & is, Interval & i, UT & u) { T low, upp; is >> iunit(low, u) >> iunit(upp, u); i = Interval(low, upp); } } #ifndef ThePEG_TEMPLATES_IN_CC_FILE #include "Interval.tcc" #endif #endif /* ThePEG_Interval_H */ diff --git a/Utilities/Interval.tcc b/Utilities/Interval.tcc --- a/Utilities/Interval.tcc +++ b/Utilities/Interval.tcc @@ -1,61 +1,61 @@ // -*- C++ -*- // // Interval.tcc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // namespace ThePEG { template template bool Interval::check(Iterator first, Iterator last) { while ( first != last ) if ( includes(*first++) ) return true; return false; } template template bool Interval::checkAll(Iterator first, Iterator last) { while ( first != last ) if ( !includes(*first++) ) return false; return true; } template std::vector< Interval > Interval::split(Interval i, T x) { std::vector< Interval > intervals; Interval low = i.chopLower(x); if ( low.check() ) intervals.push_back(low); intervals.push_back(x); return intervals; } template template std::vector< Interval > Interval::split(Interval i, Iterator first, Iterator last) { typedef std::vector< Interval > IVec; IVec intervals; if ( first != last ) { Interval low = i.chopLower(*first++); IVec loints; if ( low.check() ) loints = split(low, first, last); IVec hiints = split(i, first, last); intervals.insert(intervals.end(), loints.begin(), loints.end()); intervals.insert(intervals.end(), hiints.begin(), hiints.end()); } else intervals = IVec(1, i); return intervals; } template CMP Interval::cmp; } diff --git a/Utilities/Level.h b/Utilities/Level.h --- a/Utilities/Level.h +++ b/Utilities/Level.h @@ -1,63 +1,63 @@ // -*- C++ -*- // // Level.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_Level_H #define ThePEG_Level_H // This is the declaration of the Level class. #include "ThePEG/Config/ThePEG.h" namespace ThePEG { /** * Level is used to increment temporarily a given integer * variable. Everytime a Level object is created with a given integer * variable as argument, the variable will be incremented. When the * corresponding Level object is destroyed, the associated integer * variable is decremented again. * * @see HoldFlag */ template class Level { public: /** Constructor taking an integer variable which is incremented. A * reference to the variable will be stored. */ Level(T & newLevel) : theLevel(++newLevel) {} /** Destructor decrementing the associated integer variable. */ ~Level() { --theLevel; } private: /** A reference to the integer variable to be decremmmented when * this object is destroyed. */ T & theLevel; /** * Default constructor is private and not implemented. */ Level(); /** * Copy constructor is private and not implemented. */ Level(const Level &); /** * Assignment is private and not implemented. */ Level & operator=(const Level &) = delete; }; } #endif /* ThePEG_Level_H */ diff --git a/Utilities/LoopGuard.h b/Utilities/LoopGuard.h --- a/Utilities/LoopGuard.h +++ b/Utilities/LoopGuard.h @@ -1,144 +1,144 @@ // -*- C++ -*- // // LoopGuard.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_LoopGuard_H #define ThePEG_LoopGuard_H // This is the declaration of the LoopGuard class. namespace ThePEG { /** * A LoopGuard object can be used to throw an exception if a loop is * iterated too many times. It is used by constructing an object * before the loop giving the maximum number of iterations allowed and * a message to be used as argument to the constructor of the * exception to be thrown. Inside the loop the parenthesis is called * without argument, which will increment and check an internal counter. * * * @see Level */ template class LoopGuard { public: /** * Create a loop guard object which will throw an exception of type * ExceptionT, constructed with 'mess' as argument, if the maximum * number of iterations is exceeded. */ LoopGuard(const MessageT & mess, long maxc = 1000000 ) : count(0), maxCount(maxc), message(mess) {} /** * Increase the iteration count and throw an ExceptionT if the * maximum number of iterations is exceeded. */ void operator()() { if ( ++count > maxCount ) throw ExceptionT(message); } private: /** * The number of counts so far. */ long count; /** * The maximum number of counts allowed. */ long maxCount; /** * The message with which the thrown ExceptionT object will be * initialized. */ const MessageT & message; private: /** * Default constructor is private and not implemented. */ LoopGuard(); /** * Copy constructor is private and not implemented. */ LoopGuard(const LoopGuard &); }; /** * A LoopGuard object can be used to throw an exception if a loop is * iterated too many times. It is used by constructing an object * before the loop giving the maximum number of iterations allowed and * a message to be used as argument to the constructor of the * exception to be thrown. Inside the loop the parenthesis is called * without argument, which will increment and check an internal * counter. This specialization is for the case where the exception * class cannot be created with a message. * * * @see Level */ template class LoopGuard { public: /** * Create a loop guard object which will throw an exception of type * ExceptionT, constructed with 'mess' as argument, if the maximum * number of iterations is exceeded. */ LoopGuard(long maxc = 1000000 ) : count(0), maxCount(maxc) {} /** * Increase the iteration count and throw an ExceptionT if the * maximum number of iterations is exceeded. */ void operator()() { if ( ++count > maxCount ) throw ExceptionT(); } private: /** * The number of counts so far. */ long count; /** * The maximum number of counts allowed. */ long maxCount; private: /** * Default constructor is private and not implemented. */ LoopGuard(); /** * Copy constructor is private and not implemented. */ LoopGuard(const LoopGuard &); }; } #endif /* ThePEG_LoopGuard_H */ diff --git a/Utilities/Maths.cc b/Utilities/Maths.cc --- a/Utilities/Maths.cc +++ b/Utilities/Maths.cc @@ -1,48 +1,48 @@ // -*- C++ -*- // // Maths.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #include #include "Maths.h" #include double ThePEG::Math::exp1m(double x) { using namespace std; #ifndef ThePEG_HAS_EXPM1 return 2.0*std::exp(x/2.0)*std::sinh(-x/2.0); #else return -expm1(x); #endif } double ThePEG::Math::log1m(double x) { using namespace std; #ifndef ThePEG_HAS_LOG1P #ifndef ThePEG_HAS_ATANH volatile double y = 1.0 - x; return log(y) - ((y - 1.0) + x)/y ; /* cancels errors with IEEE arithmetic */ #else return 2.0*atanh(x/(x-2.0)); #endif #else return log1p(-x); #endif } double ThePEG::Math::powi(double x, int i) { switch ( i ) { case 0: return 1.0; case -1: return 1/x; case -2: return 1/x/x; case -3: return 1/x/x/x; case 1: return x; case 2: return x*x; case 3: return x*x*x; default: return i > 0? powi(x, i - 1)*x: powi(x, i + 1)/x; } } diff --git a/Utilities/Maths.h b/Utilities/Maths.h --- a/Utilities/Maths.h +++ b/Utilities/Maths.h @@ -1,340 +1,340 @@ // -*- C++ -*- // // Maths.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_Math_H #define ThePEG_Math_H #include namespace ThePEG { /** The Math namespace includes the declaration of some useful * mathematical functions. */ namespace Math { /** * MathType is an empty non-polymorphic base class for all * mathematical function types. */ struct MathType {}; /** Return \f$1-e^x\f$, with highest possible precision for * \f$x\rightarrow 0\f$. */ double exp1m(double x); /** Return \f$1\log(1-x)\f$, with highest possible precision for * \f$x\rightarrow 0\f$. */ double log1m(double); /** Return x rased to the integer power p, using recursion. */ double powi(double x, int p); /** Return the integral of \f$x^p dx\f$ between xl and xu. */ inline double pIntegrate(double p, double xl, double xu) { return p == -1.0? log(xu/xl): (pow(xu, p + 1.0) - pow(xl, p + 1.0))/(p + 1.0); } /** Return the integral of \f$x^p dx\f$ between xl and xu. */ inline double pIntegrate(int p, double xl, double xu) { return p == -1? log(xu/xl): (powi(xu, p + 1) - powi(xl, p + 1))/double(p + 1); } /** Return the integral of \f$x^{e-1} dx\f$ between xl and xl+dx with * highest possible precision for \f$dx\rightarrow 0\f$ and/or * \f$e\rightarrow 0\f$. */ inline double pXIntegrate(double e, double xl, double dx) { return e == 0.0? log1m(-dx/xl): -pow(xl, e)*exp1m(e*log1m(-dx/xl))/e; } /** Generate an x between xl and xu distributed as \f$x^p\f$. */ inline double pGenerate(double p, double xl, double xu, double rnd) { return p == -1.0? xl*pow(xu/xl, rnd): pow((1.0 - rnd)*pow(xl, p + 1.0) + rnd*pow(xu, p + 1.0), 1.0/(1.0 + p)); } /** Generate an x between xl and xu distributed as \f$x^p\f$. */ inline double pGenerate(int p, double xl, double xu, double rnd) { return p == -1? xl*pow(xu/xl, rnd): pow((1.0 - rnd)*powi(xl, p + 1) + rnd*powi(xu, p + 1), 1.0/double(1 + p)); } /** Generate an x between xl and xl + dx distributed as \f$x^{e-1}\f$ * with highest possible precision for\f$dx\rightarrow 0\f$ and/or * * \f$e\rightarrow 0\f$. * @param e the parameter defining the power in \f$x^{e-1}\f$. * @param xl the lower bound of the generation interval. * @param dx the interval. * @param rnd a flat random number in the interval ]0,1[. */ inline double pXGenerate(double e, double xl, double dx, double rnd) { return e == 0.0? -xl*exp1m(rnd*log1m(-dx/xl)): -exp1m(log1m(rnd*exp1m(e*log1m(-dx/xl)))/e)*xl; } /** Returns (x - y)/(|x| + |y|). */ template inline double relativeError(FloatType x, FloatType y) { return ( x == y ? 0.0 : double((x - y)/(abs(x) + abs(y))) ); } /** Return x if |x|<|y|, else return y. */ template inline T absmin(const T & x, const T & y) { return abs(x) < abs(y)? x: y; } /** Return x if |x|>|y|, else return y. */ template inline T absmax(const T & x, const T & y) { return abs(x) > abs(y)? x: y; } /** Transfer the sign of the second argument to the first. * @return \f$|x|\f$ if \f$y>0\f$ otherwise return \f$-|x|\f$. */ template inline T sign(T x, U y) { return y > U()? abs(x): -abs(x); } /** Templated class for calculating integer powers. */ //@{ /** * Struct for powers */ template struct Power: public MathType {}; /** * Struct for powers */ template struct Power { /** Member for the power*/ static double pow(double x) { return x*Power::pow(x); } }; /** * Struct for powers */ template struct Power { /** Member for the power*/ static double pow(double x) { return Power::pow(x)/x; } }; /** * Struct for powers */ template <> struct Power<0,true> { /** Member for the power*/ static double pow(double) { return 1.0; } }; /** * Struct for powers */ template <> struct Power<0,false> { /** Member for the power*/ static double pow(double) { return 1.0; } }; //@} /** Templated function to calculate integer powers known at * compile-time. */ template inline double Pow(double x) { return Power::pow(x); } /** This namespace introduces some useful function classes with known * primitive and inverse primitive functions. Useful to sample * corresponding distributions.*/ namespace Functions { /** Class corresponding to functions of the form \f$x^N\f$ with integer N. */ template struct PowX: public MathType { /** The primitive function. */ static double primitive(double x) { return Pow(x)/double(N+1); } /** Integrate function in a given interval. */ static double integrate(double x0, double x1) { return primitive(x1) - primitive(x0); } /** Sample a distribution in a given interval given a flat random * number R in the interval ]0,1[. */ static double generate(double x0, double x1, double R) { return pow(primitive(x0) + R*integrate(x0, x1), 1.0/double(N+1)); } }; /** @cond TRAITSPECIALIZATIONS */ /** * Template for generating according to a specific power */ template <> inline double PowX<1>::generate(double x0, double x1, double R) { return std::sqrt(x0*x0 + R*(x1*x1 - x0*x0)); } /** * Template for generating according to a specific power */ template <> inline double PowX<0>::generate(double x0, double x1, double R) { return x0 + R*(x1 - x0); } /** * Template for generating according to a specific power */ template<> inline double PowX<-1>::primitive(double x) { return log(x); } /** * Template for generating according to a specific power */ template <> inline double PowX<-1>::integrate(double x0, double x1) { return log(x1/x0); } /** * Template for generating according to a specific power */ template <> inline double PowX<-1>::generate(double x0, double x1, double R) { return x0*pow(x1/x0, R); } /** * Template for generating according to a specific power */ template <> inline double PowX<-2>::generate(double x0, double x1, double R) { return x0*x1/(x1 - R*(x1 - x0)); } /** * Template for generating according to a specific power */ template <> inline double PowX<-3>::generate(double x0, double x1, double R) { return x0*x1/std::sqrt(x1*x1 - R*(x1*x1 - x0*x0)); } /** @endcond */ /** Class corresponding to functions of the form \f$(1-x)^N\f$ * with integer N. */ template struct Pow1mX: public MathType { /** The primitive function. */ static double primitive(double x) { return -PowX::primitive(1.0 - x); } /** Integrate function in a given interval. */ static double integrate(double x0, double x1) { return PowX::integrate(1.0 - x1, 1.0 - x0); } /** Sample a distribution in a given interval given a flat random * number R in the interval ]0,1[. */ static double generate(double x0, double x1, double R) { return 1.0 - PowX::generate(1.0 - x1, 1.0 - x0, R); } }; /** Class corresponding to functions of the form \f$1/(x(1-x))\f$ */ struct InvX1mX: public MathType { /** The primitive function. */ static double primitive(double x) { return log(x/(1.0 - x)); } /** Integrate function in a given interval. */ static double integrate(double x0, double x1) { return log(x1*(1.0 - x0)/(x0*(1.0 - x1))); } /** Sample a distribution in a given interval given a flat random * number R in the interval ]0,1[. */ static double generate(double x0, double x1, double R) { double r = pow(x1*(1.0 - x0)/(x0*(1.0 - x1)), R)*x0/(1.0 - x0); return r/(1.0 + r); } }; /** Class corresponding to functions of the form \f$e^x\f$ */ struct ExpX: public MathType { /** The primitive function. */ static double primitive(double x) { return exp(x); } /** Integrate function in a given interval. */ static double integrate(double x0, double x1) { return exp(x1) - exp(x0); } /** Sample a distribution in a given interval given a flat random * number R in the interval ]0,1[. */ static double generate(double x0, double x1, double R) { return log(exp(x0) + R*(exp(x1) - exp(x0))); } }; /** Class corresponding to functions of the form \f$x^{N/D}\f$ * with integer N and D. */ template struct FracPowX: public MathType { /** The primitive function. */ static double primitive(double x) { double r = double(N)/double(D) + 1.0; return pow(x, r)/r; } /** Integrate function in a given interval. */ static double integrate(double x0, double x1) { return primitive(x1) - primitive(x0); } /** Sample a distribution in a given interval given a flat random * number R in the interval ]0,1[. */ static double generate(double x0, double x1, double R) { double r = double(N)/double(D) + 1.0; return pow(primitive(x0) + R*integrate(x0, x1), 1.0/r); } }; } } } #endif /* ThePEG_Math_H */ diff --git a/Utilities/MaxCmp.h b/Utilities/MaxCmp.h --- a/Utilities/MaxCmp.h +++ b/Utilities/MaxCmp.h @@ -1,132 +1,132 @@ // -*- C++ -*- // // MaxCmp.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_MaxCmp_H #define THEPEG_MaxCmp_H // // This is the declaration of the MaxCmp class. // #include namespace ThePEG { /** * MaxCmp is a helper class to be used in a loop where one would like * to keep track of the largest value so far of a certain * expression. The class simply checks if the given value to the * operator() is the largest so far (in which case true is returned, * and the value is saved together with the optional index * argument. The Cmp template argument is by default greater, but * can be set to any comparison class to change the meaning of * maximum: MaxCmp > will keep track of the * smallest value. */ template > class MaxCmp { public: /** * The default constructor. */ MaxCmp() : init(false), max(T()), indx(Indx()) {} /** * Constructor specifying an initial maximum value, \a t. */ MaxCmp(const T & t, Indx in = Indx()) : init(true), max(t), indx(in) {} public: /** * If \a t is the largest value seen so far return true. Otherwise * return false. \a i is an optional index for the value \a t. */ bool operator()(const T & t, Indx i = Indx()) { if ( !init || cmp(t, max) ) { max = t; init = true; indx = i; return true; } return false; } /** * Return the largest value so far. */ operator const T & () const { return value(); } /** * Return the largest value so far. */ const T & value() const { return max; } /** * Return the index of the largest object seen so far. */ Indx index() const { return indx; } /** * Return true if no index has been chosen. */ bool operator!() const { return !init; } private: /** * True if a first value has been given; */ bool init; /** * The largest value seen so far. */ T max; /** * The index for the largest value seen so far. */ Indx indx; /** * The comparison object to be used. */ Cmp cmp; }; /** * Special calss for Minimum comparisons. */ template class MinCmp: public MaxCmp > { public: /** * Constructors are not inherited. */ MinCmp() {} /** * Constructors are not inherited. */ MinCmp(const T & t, Indx in = Indx()) : MaxCmp >(t, in) {} }; } #endif /* THEPEG_MaxCmp_H */ diff --git a/Utilities/Named.h b/Utilities/Named.h --- a/Utilities/Named.h +++ b/Utilities/Named.h @@ -1,87 +1,87 @@ // -*- C++ -*- // // Named.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_Named_H #define ThePEG_Named_H // This is the declaration of the Named class. #include namespace ThePEG { /** * The Named class is a simple concrete base class to * used by classes of objects with a name. It just defines a string * member variable with corresponding (protected) set and get * functions. */ class Named { public: /** * Constructor with name. */ Named(const string & newName = string()) : theName(newName) {} /** * Explicit default copy-constructor (too avoid compiler warnings) */ Named(const Named & ) = default; /** * Return name. */ const string & name() const { return theName; } /** * Test for equality. */ bool operator == (const Named & other) const { return theName == other.name(); } /** * Lexicographical comparison. */ bool operator < (const Named & other) const { return theName < other.name(); } protected: /** * Assignment. */ const Named & operator = (const Named & other) { if (this != &other) theName = other.name(); return *this; } /** * Set new name. */ const string & name(const string & newName) { return theName = newName; } private: /** * The string containing the name. */ string theName; }; } #endif /* ThePEG_Named_H */ diff --git a/Utilities/ObjectIndexer.h b/Utilities/ObjectIndexer.h --- a/Utilities/ObjectIndexer.h +++ b/Utilities/ObjectIndexer.h @@ -1,184 +1,184 @@ // -*- C++ -*- // // ObjectIndexer.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_ObjectIndexer_H #define THEPEG_ObjectIndexer_H // This is the declaration of the ObjectIndexer class. #include "ThePEG/Config/ThePEG.h" #include namespace ThePEG { /** * This is a templated class which dynamically associates (reference * counted) objects to integer indices. By default, all indices will * be non-negative, but explicit usage of negative indices is * allowed as long as they do not include NoIndex. */ template (-1)> class ObjectIndexer { public: ThePEG_DECLARE_TEMPLATE_POINTERS(ObjT,TPtr); /** Map of objects to indices */ typedef map IndexObjectMap; /** Map of indices to objects. */ typedef map ObjectIndexMap; public: /** * Empty constructor. */ ObjectIndexer(): next(0) {} /** * Return the index for the given object. If the object is not known, * a new index will be created. */ IntT operator()(tTPtr o) { typename ObjectIndexMap::iterator it = objectIndex.find(o); if ( it == objectIndex.end() ) { IntT i = next++; objectIndex[o] = i; indexObject[i] = o; return i; } else return it->second; } /** * Return the index for the given object. If the object is not known, * NoIndex will be returned. */ IntT operator()(tTPtr o) const { return find(o); } /** * Return the index for the given object. If the object is not known, * NoIndex will be returned. */ IntT find(tTPtr o) const { typename ObjectIndexMap::const_iterator it = objectIndex.find(o); return it == objectIndex.end()? NoIndex: it->second; } /** * Return the object for the given index. If the index is not known, * a new object will be (default) created. */ tTPtr operator()(IntT i) { if ( i == NoIndex ) return tTPtr(); typename IndexObjectMap::iterator it = indexObject.find(i); if ( it == indexObject.end() ) { TPtr o = new_ptr(); objectIndex[o] = i; indexObject[i] = o; next = max(next, i + 1); return o; } else return it->second; } /** * Return the object for the given index. If the index is not known, * a null pointer will be returned. */ tTPtr operator()(IntT i) const { return find(i); } /** * Return the object for the given index. If the index is not known, * a null pointer will be returned. */ tTPtr find(IntT i) const { typename IndexObjectMap::const_iterator it = indexObject.find(i); return it == indexObject.end()? tTPtr(): it->second; } /** * Associate the given object with the given index. Possible other * associations involving the index or the object is removed. If the * given index is NoIndex, this function does nothing. */ void operator()(IntT i, tTPtr o) { if ( i == NoIndex ) return; typename IndexObjectMap::iterator iit = indexObject.find(i); if ( iit != indexObject.end() ) objectIndex.erase(iit->second); typename ObjectIndexMap::iterator oit = objectIndex.find(o); if ( oit != objectIndex.end() ) indexObject.erase(oit->second); objectIndex[o] = i; indexObject[i] = o; next = max(next, i + 1); } /** * Return true if the given object is known. */ bool included(tTPtr o) const { return objectIndex.find(o) != objectIndex.end(); } /** * Return true if the given index is known. */ bool included(IntT i) const { return indexObject.find(i) != indexObject.end(); } /** * Remove all associations. */ void clear() { indexObject.clear(); objectIndex.clear(); } /** * Return true if no associations has been made. */ bool empty() const { return indexObject.empty() && objectIndex.empty(); } private: /** * All known objects keyed by their indices. */ IndexObjectMap indexObject; /** * All known indices keyed by the corresponding objects. */ ObjectIndexMap objectIndex; /** * The next index to be used. */ IntT next; private: /** * Private and non-existent assignment operator. */ ObjectIndexer & operator=(const ObjectIndexer &) = delete; }; } #endif /* THEPEG_ObjectIndexer_H */ diff --git a/Utilities/Rebinder.h b/Utilities/Rebinder.h --- a/Utilities/Rebinder.h +++ b/Utilities/Rebinder.h @@ -1,128 +1,128 @@ // -*- C++ -*- // // Rebinder.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_Rebinder_H #define ThePEG_Rebinder_H #include "ThePEG/Config/ThePEG.h" #include "Rebinder.fh" #include namespace ThePEG { /** * Rebinder is a class associating pairs of pointers to objects. It is * typically used when cloning a set of objects which have pointers to * eachother. The Rebinder is then set up so that a cloned object can * easily be retrieved given a pointer to the original one. The cloned * objects can then use the Rebinder to change their pointers so that * they henceforth points to the cloned copies. */ template class Rebinder { public: /** Default constructor. */ Rebinder() {} public: ThePEG_DECLARE_TEMPLATE_POINTERS(T,TPtr); /** Map associating pairs of objects. */ typedef std::map MapType; /** The iterator of the underlying map. */ typedef typename MapType::const_iterator const_iterator; public: /** * Return a pointer to the object associated with the argument. */ TPtr & operator[](tcTPtr t) { return theMap[t]; } /** * Return a pointer to the object associated with the argument. If * no corresponding object is found a null pointer given by R() is * returned. * @param r a pointer to an object of a type which is derived from T. */ template R translate(const R & r) const { const_iterator it = theMap.find(r); return it == theMap.end()? R(): dynamic_ptr_cast(it->second); } /** * Insert pointers to objects into the output iterator, pointers to * objects corresponding to the ones given by the range of input * iterators. If a given object in the input iterator range does not * exists, a null pointer will be inserted in the output iterator. */ template void translate(OutputIterator r, InputIterator first, InputIterator last) const { while ( first != last ) *r++ = translate(*first++); } /** * Return a pointer to the object associated with the argument. If * no corresponding object is found an exception is thrown. * @param r a pointer to an object of a type which is derived from T. */ template R alwaysTranslate(const R & r) const { R ret; if ( !r ) return ret; const_iterator it = theMap.find(r); ret = (it == theMap.end()? R(): dynamic_ptr_cast(it->second)); if ( !ret ) throw std::runtime_error("Rebinder exception"); return ret; } /** * Insert pointers to objects into the output iterator, pointers to * objects corresponding to the ones given by the range of input * iterators. If a given object in the input iterator range does not * exists, an exception will be thrown. */ template void alwaysTranslate(OutputIterator r, InputIterator first, InputIterator last) const { while ( first != last ) *r++ = alwaysTranslate(*first++); } /** * Acces the underlying map representation. */ const MapType & map() const { return theMap; } private: /** * The underlying map representation. */ MapType theMap; private: /** The copy constructor is private and not implemented */ Rebinder(const Rebinder &); /** The assignment operator is private and not implemented */ Rebinder & operator=(const Rebinder &) = delete; }; } #endif /* ThePEG_Rebinder_H */ diff --git a/Utilities/Selector.h b/Utilities/Selector.h --- a/Utilities/Selector.h +++ b/Utilities/Selector.h @@ -1,306 +1,306 @@ // -*- C++ -*- // // Selector.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_Selector_H #define ThePEG_Selector_H // This is the declaration of the Selector class. #include "ThePEG/Config/ThePEG.h" #include #include #include namespace ThePEG { /** * Selector is a templated class for storing objects associated with * probabilities in a way such that, given a flat random number * between 0 and 1, an object can be selected according to its * relative probability. Internally, the objects of class * T are stored in a map where the key is the * probability of the corresponding object plus the accumulated sum of * probabilities of all objects before the current one in the * map. This allows for fast retreival of an object according to its * probability. Where fast means that the time increases as a * logarithm of the number of objects in the selector. * * Here is an example on how to use the class:
* double random(); // A random generator returning a * number between 0 and 1.
* class foo; // Any class.
* Selector bar; // A selector.
* foo f1, f2;
* bar.insert(0.5,&f1) // assign probability 0.5
* bar.insert(0.5,&f2) // to each of f1 and f2
* foo * f = bar.select(random()) // randomly returns * a pointer to f1 or f2
* * @see VSelector */ template class Selector { public: /** Map doubles to objects. */ typedef map > MapType; /** Iterator corresponding to the underlying map. */ typedef typename MapType::const_iterator const_iterator; /** Iterator corresponding to the underlying map. */ typedef typename MapType::iterator iterator; /** Size type of the underlying map. */ typedef typename MapType::size_type size_type; public: /** * Default constructor. */ Selector() : theSum(WeightType()) {} /** * Swap the underlying representation with the argument. */ void swap(Selector & s) { theMap.swap(s.theMap); std::swap(theSum, s.theSum); } /** * Insert an object given a probability for this object. If the * probability is zero or negative, the object will not be inserted * and the probability itself is returned. Otherwise the sum of * probabilities so far is returned. */ WeightType insert(WeightType d, const T & t) { typedef typename MapType::value_type value_type; WeightType newSum = theSum + d; if ( newSum <= theSum ) return d; theMap.insert(theMap.end(), value_type((theSum = newSum), t)); return theSum; } /** * Reweight an object previously inserted giving it a new * weight. Semantically reweight(w,o); is equivalent to * erase(o); insert(w,o); */ WeightType reweight(WeightType d, const T & t) { erase(t); return insert(d, t); } /** * Erase an object, previously inserted. If the object had not been * inserted, nothing will happen. If several copies of the object * has been inserted, all will be removed removed. In all cases the * sum of the remaining probabilities is returned. */ WeightType erase(const T &); /** * Replace all occurencies of oldObject with newObject without * changing the probability for the entry. */ void replace(const T & oldObject, const T & newObject) { for ( iterator it = theMap.begin(); it != theMap.end(); ++it ) if ( it->second == oldObject ) it->second = newObject; } /** * Select an object randomly. Given a random number flatly * distributed in the interval ]0,1[ Select an object according to * the individual probabilities specified when they were * inserted. If rnd <= 0 or if rnd >= 1 or the Selector is empty, a * range_error will be thrown. * @param rnd a flat random number in the interval ]0,1[ * @param remainder if non-zero the double pointed to will be set to * a uniform random number in the interval ]0,1[ calculated from the * fraction of rnd which was in the range of the selected object. */ T & select(double rnd, double * remainder = 0); /** * Selct an object randomly. Given a random number flatly * distributed in the interval ]0,1[ Select an object according to * the individual probabilities specified when they were * inserted. If rnd <= 0 or if rnd >= 1 or the Selector is empty, a * range_error will be thrown. */ T & operator[](double rnd) { return select(rnd); } /** * Selct an object randomly. Given a random number flatly * distributed in the interval ]0,1[ Select an object according to * the individual probabilities specified when they were * inserted. If rnd <= 0 or if rnd >= 1 or the Selector is empty, a * range_error will be thrown. * @param rnd a flat random number in the interval ]0,1[ * @param remainder if non-zero the double pointed to will be set to * a uniform random number in the interval ]0,1[ calculated from the * fraction of rnd which was in the range of the selected object. */ const T & select(double rnd, double * remainder = 0) const; /** * Selct an object randomly. Given a random number flatly * distributed in the interval ]0,1[ select an object according to * the individual probabilities specified when they were * inserted. If rnd <= 0 or if rnd >= 1 or the Selector is empty, a * range_error will be thrown. */ const T & operator[](double rnd) const { return select(rnd); } /** * Selct an object randomly. Given a random number generator which * generates flat random numbers in the interval ]0,1[ with the * operator()() function, select an object according to * the individual probabilities specified when they were * inserted. If the generated number is outside the allowed range or * the Selector is empty, a range_error will be thrown. The * generator should have a push_back function which will be used * push back a uniform random number in the interval ]0,1[ * calculated from the fraction of rnd which was in the range of the * selected object. */ template T & select(RNDGEN & rnd) { double rem = 0.0; T & t = select(rnd(), &rem); rnd.push_back(rem); return t; } /** * Selct an object randomly. Given a random number generator which * generates flat random numbers in the interval ]0,1[ with the * operator()() function, select an object according to * the individual probabilities specified when they were * inserted. If the generated number is outside the allowed range or * the Selector is empty, a range_error will be thrown. The * generator should have a push_back function which will be used * push back a uniform random number in the interval ]0,1[ * calculated from the fraction of rnd which was in the range of the * selected object. */ template const T & select(RNDGEN & rnd) const { double rem = 0.0; const T & t = select(rnd(), &rem); rnd.push_back(rem); return t; } /** * Return the sum of probabilities of the objects inserted. Note * that probabilities specified when objects are inserted are * rescaled with this number to give unit probability for * 'select()'. */ WeightType sum() const { return theSum; } /** * Access to the begin() iterator of the underlying * map. Dereferenced, it will give a std::pair, where * 'first' is the sum of all probabilities up to this one, and * 'second' is the object inserted. */ const_iterator begin() const { return theMap.begin(); } /** * Access to the end() iterator in the underlying * map. */ const_iterator end() const { return theMap.end(); } /** * Returns true if the Selector is empty. */ bool empty() const { return theMap.empty(); } /** * Returns the number of objects in the selector. */ size_type size() const { return theMap.size(); } /** * Erases all objects. */ void clear() { theMap.clear(); theSum = WeightType(); } /** * Output to a stream for dimensionful units. */ template void output(OStream &, DimensionT) const; /** * Input from a stream for dimensionful units. */ template void input(IStream &, DimensionT); /** * Output to a stream. */ template void output(OStream &, StandardT) const; /** * Input from a stream. */ template void input(IStream &, StandardT); private: /** * The underlying map relating sums of probabilities to inserted objects. */ MapType theMap; /** * The sum of all probabilities assicialted with inserted objects. */ WeightType theSum; }; /** * Output a Selector to a stream. */ template OStream & operator<<(OStream & os, const Selector & s) { s.output(os, typename TypeTraits::DimType()); return os; } /** * Input a Selector from a stream. */ template IStream & operator>>(IStream & is, Selector & s) { s.input(is, typename TypeTraits::DimType()); return is; } } #ifndef ThePEG_TEMPLATES_IN_CC_FILE #include "Selector.tcc" #endif #endif /* ThePEG_Selector_H */ diff --git a/Utilities/Selector.tcc b/Utilities/Selector.tcc --- a/Utilities/Selector.tcc +++ b/Utilities/Selector.tcc @@ -1,114 +1,114 @@ // -*- C++ -*- // // Selector.tcc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // namespace ThePEG { template WeightType Selector::erase(const T & t) { Selector newSelector; WeightType oldsum = WeightType(); for ( iterator it = theMap.begin(); it != theMap.end(); ++it ) { WeightType r = it->first - oldsum; oldsum = it->first; if ( it->second != t ) newSelector.insert(r, it->second); } theMap.swap(newSelector.theMap); return theSum = newSelector.theSum; } template const T & Selector:: select(double rnd, double * remainder) const { if ( rnd <= 0 ) throw range_error("Random number out of range in Selector::select."); const_iterator it = theMap.upper_bound(rnd*theSum); if ( it == theMap.end() ) throw range_error("Empty Selector, or random number out of range " "in Selector::select"); if ( remainder ) { if ( it == theMap.begin() ) *remainder = rnd*theSum/(it->first); else { const_iterator prit = it; --prit; *remainder = (rnd*theSum - prit->first)/(it->first - prit->first); } } return it->second; } template T & Selector:: select(double rnd, double * remainder) { if ( rnd <= 0 ) throw range_error("Random number out of range in Selector::select."); iterator it = theMap.upper_bound(rnd*theSum); if ( it == theMap.end() ) throw range_error("Empty Selector, or random number out of range " "in Selector::select"); if ( remainder ) { if ( it == theMap.begin() ) *remainder = rnd*theSum/(it->first); else { const_iterator prit = it; --prit; *remainder = (rnd*theSum - prit->first)/(it->first - prit->first); } } return it->second; } template template void Selector::output(OStream & os, DimensionT) const { os << ounit(theSum,WeightType::baseunit()) << size(); for ( const_iterator it = theMap.begin(); it != theMap.end(); ++it ) os << ounit(it->first,WeightType::baseunit()) << it->second; } template template void Selector::input(IStream & is, DimensionT) { typedef typename MapType::value_type value_type; clear(); T t; WeightType weightsum; long n; is >> iunit(theSum,WeightType::baseunit()) >> n; while ( n-- ) { is >> iunit(weightsum,WeightType::baseunit()) >> t; theMap.insert(theMap.end(), value_type(weightsum, t)); } } template template void Selector::output(OStream & os, StandardT) const { os << theSum << size(); for ( const_iterator it = theMap.begin(); it != theMap.end(); ++it ) os << it->first << it->second; } template template void Selector::input(IStream & is, StandardT) { typedef typename MapType::value_type value_type; clear(); T t; WeightType weightsum; long n; is >> theSum >> n; while ( n-- ) { is >> weightsum >> t; theMap.insert(theMap.end(), value_type(weightsum, t)); } } } diff --git a/Utilities/SimplePhaseSpace.cc b/Utilities/SimplePhaseSpace.cc --- a/Utilities/SimplePhaseSpace.cc +++ b/Utilities/SimplePhaseSpace.cc @@ -1,116 +1,116 @@ // -*- C++ -*- // // SimplePhaseSpace.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #include "SimplePhaseSpace.h" #ifdef ThePEG_TEMPLATES_IN_CC_FILE #include "SimplePhaseSpace.tcc" #endif using namespace ThePEG; Energy SimplePhaseSpace::getMagnitude(Energy2 s, Energy m1, Energy m2) { const Energy2 eps = 10.0*s*Constants::epsilon; if ( m1 < ZERO && sqr(m1) < eps ) m1 = ZERO; if ( m2 < ZERO && sqr(m2) < eps ) m2 = ZERO; if ( m1 >= ZERO && m2 >= ZERO ) { Energy2 aa = s - sqr(m1+m2); if ( aa < ZERO && aa > -eps ) return ZERO; if ( aa < ZERO ) throw ImpossibleKinematics(); return 0.5*sqrt(aa*(s-sqr(m1-m2))/s); } if ( m1 >= ZERO && m2 < ZERO ) { return sqrt(sqr(m2)+sqr(s-sqr(m1)-sqr(m2))/(4.*s)); } if ( m1 < ZERO && m2 >= ZERO ) { return sqrt(sqr(m1)+sqr(s-sqr(m1)-sqr(m2))/(4.*s)); } if ( m1 < ZERO && m2 < ZERO ) { return sqrt(sqr(m1)+sqr(s-sqr(m1)+sqr(m2))/(4.*s)); } return ZERO; } // Energy SimplePhaseSpace::checkMagnitude(Energy2 s, Energy m1, Energy m2) // { // if ( s < ZERO ) return -1.0*GeV; // const Energy2 eps = 10.0*s*Constants::epsilon; // if ( m1 < ZERO && sqr(m1) < eps ) m1 = ZERO; // if ( m2 < ZERO && sqr(m2) < eps ) m2 = ZERO; // if ( m1 >= ZERO && m2 >= ZERO ) { // Energy2 aa = s - sqr(m1+m2); // if ( aa < ZERO && aa > -eps ) return ZERO; // if ( aa < ZERO ) return -1.0*GeV; // return 0.5*sqrt(aa*(s-sqr(m1-m2))/s); // } // Energy2 m12 = m1 < ZERO? -sqr(m1): sqr(m1); // Energy2 m22 = m2 < ZERO? -sqr(m2): sqr(m2); // Energy2 r2 = 0.25*(sqr(m12) + sqr(m22 - s) -2.0*m12*(m22 + s))/s; // if ( r2 < ZERO || r2 + m12 < ZERO || r2 + m22 < ZERO ) // return -1.0*GeV; // return sqrt(r2); // } vector SimplePhaseSpace:: CMSn(Energy m0, const vector & m) { using Constants::pi; // Setup constants. int Np = m.size(); vector ret(Np); Energy summ = std::accumulate(m.begin(), m.end(), Energy()); if ( summ >= m0 ) throw ImpossibleKinematics(); while ( true ) { // First get an ordered list of random numbers. vector rndv(Np); rndv[0] = 1.0; rndv.back() = 0.0; for ( int i = 1; i < Np - 1; ++i ) rndv[i] = UseRandom::rnd(); std::sort(rndv.begin() + 1, rndv.end() - 1, std::greater()); // Now setup masses of subsystems. vector sm(Np); Energy tmass = m0 - summ; Energy tmp = summ; for ( int i = 0; i < Np; ++i ) { sm[i] = rndv[i]*tmass + tmp; tmp -= m[i]; } // Now the magnitude of all the momenta can be calculated. This // gives the weight. double weight = 1.0; vector p(Np); p[Np - 1] = getMagnitude(sqr(sm[Np - 2]), m[Np -2], sm[Np - 1]); for ( int i = Np - 2; i >= 0; --i ) weight *= (p[i] = getMagnitude(sqr(sm[i]), m[i], sm[i + 1]))/sm[i]; if ( weight > UseRandom::rnd() ) continue; // Now we just have to generate the angles. ret[Np - 1] = LorentzMomentum(ZERO, ZERO, ZERO, m[Np - 1]); for ( int i = Np - 2; i >= 0; --i ) { Momentum3 p3 = polar3Vector(p[i], 2.0*UseRandom::rnd() - 1.0, 2.0*pi*UseRandom::rnd()); ret[i] = LorentzMomentum(-p3, sqrt(sqr(p[i]) + sqr(m[i]))); if ( i == Np -2 ) { ret[Np - 1] = LorentzMomentum(p3, sqrt(sqr(m[Np - 1]) + p3.mag2())); } else { Boost bv = p3*(1.0/sqrt(sqr(p[i]) + sqr(sm[i + 1]))); if ( bv.mag2() >= 1.0 ) throw ImpossibleKinematics(); LorentzRotation r(bv); for ( int j = i + 1; j < Np; ++j ) ret[j]*=r.one(); } } return ret; } } diff --git a/Utilities/SimplePhaseSpace.h b/Utilities/SimplePhaseSpace.h --- a/Utilities/SimplePhaseSpace.h +++ b/Utilities/SimplePhaseSpace.h @@ -1,244 +1,244 @@ // -*- C++ -*- // // SimplePhaseSpace.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_SimplePhaseSpace_H #define ThePEG_SimplePhaseSpace_H #include "ThePEG/Config/ThePEG.h" #include "ThePEG/Vectors/LorentzRotation.h" #include "ThePEG/Vectors/LorentzRotation.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/EventRecord/ParticleTraits.h" #include "ThePEG/Repository/UseRandom.h" #include "SimplePhaseSpace.xh" #include namespace ThePEG { /** * SimplePhaseSpace defines a set of static functions to be used for * distributing momenta evenly in phase space. In most cases pointers * and references to both particle and momentum objects can be used as * arguments as long as the ParticleTraits class is specialized * properly. When needed, random numbers are generated with the * generator given by the static UseRandom class. */ namespace SimplePhaseSpace { /** * Set two momenta in their center of mass system. Their total * invariant mass squared is given by s, and their direction is * distributed isotropically. * @param s the total invariant mass squared. * @param p1 pointer or reference to the first momentum. Its * invariant mass will be preserved. * @param p2 pointer or reference to the second momentum. Its * invariant mass will be preserved. * @throw ImpossibleKinematics if the sum of the invariant masses was * larger than the given invariant mass (\f$\sqrt{s}\f$). */ template void CMS(Energy2 s, PType & p1, PType & p2); /** * Set two momenta in their center of mass system. Their total * invariant mass squared is given by s, and their direction is * given in terms of the polar and azimuth angle of the first * momenta. * @param s the total invariant mass squared. * @param p1 pointer or reference to the first momentum. Its * invariant mass will be preserved. * @param p2 pointer or reference to the second momentum. Its * invariant mass will be preserved. * @param cosTheta cosine of the azimuth angle of the first momentum. * @param phi azimuth angle of the first momentum. * @throw ImpossibleKinematics if the sum of the invariant masses was * larger than the given invariant mass (\f$\sqrt{s}\f$). */ template void CMS(PType & p1, PType & p2, Energy2 s, double cosTheta, double phi); /** * Set two momenta in their center of mass system. Their total * invariant mass squared is given by s. The helper momentum p0 is * used so that afterwards \f$t=(p0-p1)^2\f$ and p1 has the azimuth * angle phi around p0. * @param p1 pointer or reference to the first momentum. Its * invariant mass will be preserved. * @param p2 pointer or reference to the second momentum. Its * invariant mass will be preserved. * @param s the total invariant mass squared. * @param t \f$=(p0-p1)^2\f$. * @param phi azimuth angle of the first momentum around p0. * @param p0 pointer or reference to an auxiliary momentum. * @throw ImpossibleKinematics if the sum of the invariant masses was * larger than the given invariant mass (\f$\sqrt{s}\f$). */ template void CMS(PType & p1, PType & p2, Energy2 s, Energy2 t, double phi, const PType & p0); /** * Set two momenta in their center of mass system. Their total * invariant mass squared is given by s. p1 will be along the z-axis. * @param p1 pointer or reference to the first momentum. Its * invariant mass will be preserved. * @param p2 pointer or reference to the second momentum. Its * invariant mass will be preserved. * @param s the total invariant mass squared. * @throw ImpossibleKinematics if the sum of the invariant masses was * larger than the given invariant mass (\f$\sqrt{s}\f$). */ template void CMS(PType & p1, PType & p2, Energy2 s); /** * Set two momenta in their center of mass system. Their total * invariant mass squared is given by s. The first will be along the * z-axis. * @param p a pair of pointers or references to the two momenta. Their * invariant masses will be preserved. * @param s the total invariant mass squared. * @throw ImpossibleKinematics if the sum of the invariant masses was * larger than the given invariant mass (\f$\sqrt{s}\f$). */ template void CMS(const PPairType & p, Energy2 s) { CMS(*p.first, *p.second, s); } /** * Set three momenta in their center of mass system. Their total * invariant mass squared is given by s. The energy fraction of * particle p1(3) is x1(3) of the total energy and the angles of the * system is distributed isotropically. * @param p1 pointer or reference to the first momentum. Its * invariant mass will be preserved. * @param p2 pointer or reference to the second momentum. Its * invariant mass will be preserved. * @param p3 pointer or reference to the second momentum. Its * invariant mass will be preserved. * @param s the total invariant mass squared. * @param x1 the energy fraction \f$2e_1/\sqrt{s}\f$. * @param x3 the energy fraction \f$2e_3/\sqrt{s}\f$. * @throw ImpossibleKinematics if the sum of the invariant masses was * larger than the given invariant mass (\f$\sqrt{s}\f$). */ template void CMS(PType & p1, PType & p2, PType & p3, Energy2 s, double x1, double x3); /** * Set three momenta in their center of mass system. Their total * invariant mass squared is given by s. The energy fraction of * particle p1(3) is x1(3) of the total energy. Particle p1 is * initially placed along the z-axis and particle p2 is given * azimuth angle phii. Then the system is then rotated with * theta and phi respectively. * @param p1 pointer or reference to the first momentum. Its * invariant mass will be preserved. * @param p2 pointer or reference to the second momentum. Its * invariant mass will be preserved. * @param p3 pointer or reference to the second momentum. Its * invariant mass will be preserved. * @param s the total invariant mass squared. * @param x1 the energy fraction \f$2e_1/\sqrt{s}\f$. * @param x3 the energy fraction \f$2e_3/\sqrt{s}\f$. * @param phii the azimuth angle of p2 around p1. * @param theta the polar angle of p1. * @param phi the azimuth angle of p1. * @throw ImpossibleKinematics if the sum of the invariant masses was * larger than the given invariant mass (\f$\sqrt{s}\f$). */ template void CMS(PType & p1, PType & p2, PType & p3, Energy2 s, double x1, double x3, double phii = 0.0, double theta = 0.0, double phi = 0.0); /** * Calculate the absolute magnitude of the momenta of two particles * with masses m1 and m2 when put in their CMS of total invariant * mass squared s. * @param s the total invariant mass squared. * @param m1 the mass of particle 1. * @param m2 the mass of particle 2. * @throw ImpossibleKinematics if the sum of the masses was * larger than the given invariant mass (\f$\sqrt{s}\f$). */ Energy getMagnitude(Energy2 s, Energy m1, Energy m2); /** * Calculate the absolute magnitude of the momenta of two particles * with masses m1 and m2 when put in their CMS of total invariant * mass squared s. * @param s the total invariant mass squared. * @param m1 the mass of particle 1. * @param m2 the mass of particle 2. * @return a negative value if the sum of the masses was * larger than the given invariant mass (\f$\sqrt{s}\f$). */ // static Energy checkMagnitude(Energy2 s, Energy m1, Energy m2); /** * Return a three-vector given the absolute momentum, cos(theta) and * phi. * @param p the magnitude of the momentum. * @param costheta the cosine of the polar angle. * @param phi the azimuth angle. */ inline Momentum3 polar3Vector(Energy p, double costheta, double phi) { return Momentum3(p*sqrt(1.0 - sqr(costheta))*sin(phi), p*sqrt(1.0 - sqr(costheta))*cos(phi), p*costheta); } /** * Get a number of randomly distributed momenta. * Given a number specified invariant masses and a * total invariant mass m0, return corresponding four-momenta * randomly distributed according to phase space. * @param m0 the * total invariant mass of the resulting momenta. * @param m a vector * of invariant masses of the resulting momenta. * @return a vector * of momenta with the given masses randomly distributed. * @throw ImpossibleKinematics if the sum of the masses was * larger than the given invariant mass (\f$\sqrt{s}\f$). */ vector CMSn(Energy m0, const vector & m); /** * Set the momentum of a number of particles. Given a number of * particles and a total invariant mass m0, distribute their * four-momenta randomly according to phase space. * @param particles a container of particles or pointers to * particles. The invariant mass of these particles will not be * chaned. * @param m0 the * total invariant mass of the resulting momenta. * @throw ImpossibleKinematics if the sum of the masses was * larger than the given invariant mass (\f$\sqrt{s}\f$). */ template void CMSn(Container & particles, Energy m0); } } #ifndef ThePEG_TEMPLATES_IN_CC_FILE #include "SimplePhaseSpace.tcc" #endif #endif /* ThePEG_SimplePhaseSpace_H */ diff --git a/Utilities/SimplePhaseSpace.tcc b/Utilities/SimplePhaseSpace.tcc --- a/Utilities/SimplePhaseSpace.tcc +++ b/Utilities/SimplePhaseSpace.tcc @@ -1,141 +1,141 @@ // -*- C++ -*- // // SimplePhaseSpace.tcc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined templated member // functions of the SimplePhaseSpace class. // namespace ThePEG { template void SimplePhaseSpace::CMS(PType & p1, PType & p2, Energy2 s) { typedef ParticleTraits Traits; Energy m1 = Traits::mass(p1); Energy m2 = Traits::mass(p2); Energy z = getMagnitude(s, m1, m2); Energy2 m12 = m1 >= ZERO ? sqr(m1) : -sqr(m1); Energy2 m22 = m2 >= ZERO ? sqr(m2) : -sqr(m2); Energy2 c1 = (s+m12-m22); Energy2 c2 = (s-m12+m22); Traits::set5Momentum(p1, Lorentz5Momentum(ZERO, ZERO, z, (c1 > ZERO ? 1. : -1.) * 0.5*sqrt(sqr(c1)/s), m1)); Traits::set5Momentum(p2, Lorentz5Momentum(ZERO, ZERO, -z, (c2 > ZERO ? 1. : -1.) * 0.5*sqrt(sqr(c2)/s), m2)); } template void SimplePhaseSpace::CMS(Energy2 s, PType & p1, PType & p2) { CMS(p1, p2, s, 2.0*UseRandom::rnd() - 1.0, Constants::twopi*UseRandom::rnd()); } template void SimplePhaseSpace::CMS(PType & p1, PType & p2, Energy2 s, double cthe, double phi) { typedef ParticleTraits Traits; Energy r = getMagnitude(s, Traits::mass(p1), Traits::mass(p2)); double sthe = sqrt(1.0-sqr(cthe)); Momentum3 p(r*sthe*cos(phi), r*sthe*sin(phi), r*cthe); Traits::set3Momentum(p1, p); Traits::set3Momentum(p2, -p); } template void SimplePhaseSpace:: CMS(PType & p1, PType & p2, PType & p3, Energy2 s, double x1, double x3) { CMS(p1, p2, p3, s, x1, x3, Constants::twopi*UseRandom::rnd(), acos(2.0*UseRandom::rnd() - 1.0), Constants::twopi*UseRandom::rnd()); } template void SimplePhaseSpace:: CMS(PType & p1, PType & p2, PType & p3, Energy2 s, double x1, double x3, double phii, double the, double phi) { typedef ParticleTraits Traits; Energy Etot = sqrt(s); Energy m1 = Traits::mass(p1); Energy m2 = Traits::mass(p2); Energy m3 = Traits::mass(p3); Energy e1 = 0.5*x1*Etot; Energy e3 = 0.5*x3*Etot; Energy e2 = Etot - e1 - e3; if ( e1 < m1 || e2 < m2 || e3 < m3 ) throw ImpossibleKinematics(); Energy r1 = sqrt(sqr(e1)-sqr(m1)); Energy r2 = sqrt(sqr(e2)-sqr(m2)); Energy r3 = sqrt(sqr(e3)-sqr(m3)); Traits::set3Momentum(p1, Momentum3(ZERO, ZERO, r1)); double cthe2 = (sqr(r3)-sqr(r2)-sqr(r1))/(2.0*r2*r1); double cthe3 = (sqr(r2)-sqr(r3)-sqr(r1))/(2.0*r3*r1); if ( abs(cthe2) > 1.0 || abs(cthe3) > 1.0 ) throw ImpossibleKinematics(); double sthe2 = sqrt(1.0-sqr(cthe2)); Energy px = r2*sthe2*cos(phii); Energy py = r2*sthe2*sin(phii); Traits::set3Momentum(p2, Momentum3(px, py, r2*cthe2)); Traits::set3Momentum(p3, Momentum3(-px, -py, r3*cthe3)); if ( the == 0.0 && phi == 0.0 ) return; LorentzRotation r; r.rotateZ(phi); r.rotateX(the); Traits::transform(p1, r); Traits::transform(p2, r); Traits::transform(p3, r); } template void SimplePhaseSpace:: CMS(PType & p1, PType & p2, Energy2 s, Energy2 t, double phi, const PType & p0) { typedef ParticleTraits Traits; Energy r = getMagnitude(s, Traits::mass(p1), Traits::mass(p2)); Energy e = sqrt(sqr(r) + sqr(Traits::mass(p1))); Energy r0 = Traits::momentum(p0).rho(); Energy e0 = Traits::momentum(p0).e(); double cthe = (t + sqr(e - e0) + sqr(r) + sqr(r0))/(2.0*r*r0); if ( abs(cthe) > 1.0 ) throw ImpossibleKinematics(); double sthe = sqrt(1.0-sqr(cthe)); Momentum3 p(r*sthe*cos(phi), r*sthe*sin(phi), r*cthe); Traits::set3Momentum(p1, p); Traits::set3Momentum(p2, -p); if ( Traits::momentum(p0).perp2() > ZERO ) { LorentzRotation r; r.rotateX(Traits::momentum(p0).theta()); r.rotateZ(Traits::momentum(p0).phi()); Traits::transform(p1, r); Traits::transform(p2, r); } } template void SimplePhaseSpace::CMSn(Container & particles, Energy m0) { typedef typename Container::value_type PType; typedef typename Container::iterator Iterator; if ( particles.size() == 2 ) { Iterator it = particles.begin(); PType & p1 = *it++; PType & p2 = *it; CMS(sqr(m0), p1, p2); return; } typedef ParticleTraits Traits; vector masses(particles.size()); int j = 0; for ( Iterator i = particles.begin();i != particles.end(); ++i, ++j ) masses[j] = Traits::mass(*i); vector p = CMSn(m0, masses); j = 0; for ( Iterator i = particles.begin();i != particles.end(); ++i, ++j ) Traits::set5Momentum(*i, p[j]); } } diff --git a/Utilities/SimplePhaseSpace.xh b/Utilities/SimplePhaseSpace.xh --- a/Utilities/SimplePhaseSpace.xh +++ b/Utilities/SimplePhaseSpace.xh @@ -1,30 +1,30 @@ // -*- C++ -*- // // SimplePhaseSpace.xh is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_SimplePhaseSpace_XH #define ThePEG_SimplePhaseSpace_XH // #include "SimplePhaseSpace.fh" namespace ThePEG { /** @cond EXCEPTIONCLASSES */ /** Exception class used by SimplePhaseSpace. */ struct ImpossibleKinematics: public std::runtime_error { /** Constructor. */ ImpossibleKinematics() : runtime_error("Impossible kinematics in SimplePhaseSpace.") { breakThePEG(); } }; /** @endcond */ } #endif /* ThePEG_SimplePhaseSpace_XH */ diff --git a/Utilities/StringUtils.cc b/Utilities/StringUtils.cc --- a/Utilities/StringUtils.cc +++ b/Utilities/StringUtils.cc @@ -1,162 +1,162 @@ // -*- C++ -*- // // StringUtils.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the StringUtils class. // #include "StringUtils.h" #include "ThePEG/Interface/ClassDocumentation.h" using namespace ThePEG; StringUtils::StringVector StringUtils::split(string s, string ws) { StringVector r; string::size_type i = s.find_first_not_of(ws); while ( i != string::npos ) { s = s.substr(i); i = s.find_first_of(ws); r.push_back(s.substr(0, i)); if ( i == string::npos ) return r; s = s.substr(i); i = s.find_first_not_of(ws); } return r; } string StringUtils::car(string s, string ws) { string::size_type p = s.find_first_not_of(ws); if ( p == string::npos ) return ""; s = s.substr(p); return s.substr(0, s.find_first_of(ws)); } string StringUtils::cdr(string s, string ws) { string::size_type p = s.find_first_not_of(ws); if ( p == string::npos ) return ""; s = s.substr(p); p = s.find_first_of(ws); if ( p == string::npos ) return ""; s = s.substr(p); p = s.find_first_not_of(ws); if ( p == string::npos ) return ""; return s.substr(p); } string StringUtils::stripws(string str) { string::size_type i = str.find_first_not_of(" \t\r\n"); if ( i != string::npos ) str = str.substr(i); i = str.find_last_not_of(" \t\r\n"); return str.substr(0, i + 1); } map StringUtils:: xmlAttributes(string tag, string line, string::size_type curr) { map ret; // First find the beginning and end of the tag pos_t begin = line.find("<" + tag, curr); if ( begin == end ) return ret; curr = begin + tag.length() + 2; while ( true ) { pos_t close = line.find(">", curr); // Now skip some white space to see if we can find an attribute. curr = line.find_first_not_of(" \t\r\n", curr); if ( curr == end || curr >= close ) return ret; pos_t tend = line.find_first_of("= \t\r\n", curr); if ( tend == end || tend >= close ) return ret; string name = line.substr(curr, tend - curr); curr = line.find("=", curr) + 1; // OK now find the beginning and end of the atribute. curr = line.find("\"", curr); if ( curr == end || curr >= close ) return ret; pos_t bega = ++curr; curr = line.find("\"", curr); while ( curr != end && line[curr - 1] == '\\' ) curr = line.find("\"", curr + 1); string value = line.substr(bega, curr == end? end: curr - bega); ret[name] = value; ++curr; } } string StringUtils::dirname(string file) { string::size_type pos = file.rfind('/'); if ( pos == string::npos ) return ""; return file.substr(0,pos); } string StringUtils::basename(string file) { string::size_type pos = file.rfind('/'); if ( pos == string::npos ) return file; return file.substr(pos + 1); } string StringUtils::remsuf(string file) { string::size_type pos = file.rfind('.'); if ( pos == string::npos ) return ""; return file.substr(0,pos); } string StringUtils::suffix(string file) { string::size_type pos = file.rfind('.'); if ( pos == string::npos ) return file; return file.substr(pos + 1); } string StringUtils::typeName(const type_info & t) { string ret; string name = t.name(); if ( name[0] != 'N' ) return name; string::size_type pos = 1; while ( pos < name.length() && name[pos] != 'E' ) { int size = 0; while ( pos < name.length() && isdigit(name[pos]) ) size = size*10 + int(name[pos++] - '0'); if ( size == 0 ) return name; if ( !ret.empty() ) ret += "::"; ret += name.substr(pos, size); pos += size; } return ret; } string StringUtils::replace(string original, string from, string to){ if (from == "" || from == to) return(original); string result = original; size_t n = result.length(); size_t f; for (size_t i=0; i StringVector; /** * Return a vector of string containing the substrings of s, defined * by the separating characters in ws (the ws characters are not * included in the substrings. */ static StringVector split(string s, string ws = " \t\r\n"); /** * Return the first substring of s, defined by the separating * characters in ws (the ws characters are not included in the * substrings. */ static string car(string s, string ws = " \t\r\n"); /** * Return s after removing the first substring, defined by the * separating characters in ws (the ws characters are not included * in the substrings. */ static string cdr(string s, string ws = " \t\r\n"); /** * Return the string \a str stripped from leading and trailing white * space. */ static string stripws(string str); /** * Return the directory path part (excluding the trailing slash) of * the given filename, or an empty string if no directory path is * included */ static string dirname(string file); /** * Return the base name of the given filename, removing the * directory path if present. */ static string basename(string file); /** * Remove the trailing suffix from the given filename. */ static string remsuf(string file); /** * Return the trailing suffix (without the dot) of the given * filename. */ static string suffix(string file); /** * Assuming the \a line contains a valid XML \a tag, scan the \a * line for attributes belonging to this \a tag and return a map of * name-value pairs. Oprionally only look from position \a curr in * the \a line. */ static map xmlAttributes(string tag, string line, string::size_type curr = 0); /** * Try to return a human-readable class name given a type_info * object. Currently only works for simple classes compiled by g++. */ static string typeName(const type_info & t); /** * Replace all occurences of the substring 'from' with the substring * 'to' in the string 'original' and return the new string */ static string replace(string original, string from, string to); /** * Convenient typdef. */ typedef string::size_type pos_t; /** * Convenient alias for npos. */ static const pos_t end = string::npos; }; } #endif /* ThePEG_StringUtils_H */ diff --git a/Utilities/Throw.h b/Utilities/Throw.h --- a/Utilities/Throw.h +++ b/Utilities/Throw.h @@ -1,116 +1,116 @@ // -*- C++ -*- // // Throw.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_Throw_H #define ThePEG_Throw_H // This is the declaration of the Throw class. #include "ThePEG/Config/ThePEG.h" #include "ThePEG/Utilities/Exception.h" #include "ThePEG/Repository/CurrentGenerator.h" #include "ThePEG/Repository/Repository.h" namespace ThePEG { /** * Helper function to make it easier to throw exceptions. The template * argument should be a class inheriting from Exception. In the * constructor, an object of this Exception class is created and * afterwards a message may be added using ostream-like output * (<<). If a Exception::Severity value is output with << * the Exception object is assumed to be complete and the exception is * actually thrown, except if the Exception::Severity value * Exception::warning was specified, in which case the Exception * object is treated as a warning which is logged with the current * EventGenerator. If no current EventGenerator is present the warning * message is instead written to std::cerr. If no Exception::Severity * is specified, the Exception object is treated as a warning * when the Throw object is destroyed. * * Assuming you have an Exception class called MyEx the Throw class is * used as follows:
Throw<MyEx>>() << "My error * message" << Exception::eventerror;
This will throw * an exception and the current event will be discarded. Changing * Exception::eventerror to * Exception::warning will write out a warning, but no * proper exception is thrown. */ template struct Throw { public: /** * Standard constructor creating an internal Exception object. */ Throw(): ex(Ex()), handled(false) {} /** * Add information to the current Exception object. */ template Throw & operator<<(const T & t) { ex << t; return *this; } private: /** * Write warning messages to the current EventGenerator. If no * current EventGenerator is present, the warning message is instead * written to std::cerr. */ void writeWarning() { if ( CurrentGenerator::isVoid() ) { Repository::clog() << ex.message() << endl; ex.handle(); } else { CurrentGenerator::current().logWarning(ex); } } public: /** * Specify the Exception::Severity of the exception. If this is * Exception::warning, the exception will not be thown, instead it * will be logged with writeWarning(). All other seveities will cause * the exception to be thrown immediately. */ void operator<<(Exception::Severity sev) { handled = true; ex << sev; if ( sev != Exception::warning && sev != Exception::info ) { throw ex; } else { writeWarning(); } } /** * The destructor will throw the exception if it has not been handled. */ ~Throw() { if ( !handled ) { ex << Exception::warning; writeWarning(); } } /** * The ExceptionObject to be thrown. */ Ex ex; /** * If true, the exception has been handled and should not be thrown * in the destructor. */ bool handled; }; } #endif /* ThePEG_Throw_H */ diff --git a/Utilities/Triplet.h b/Utilities/Triplet.h --- a/Utilities/Triplet.h +++ b/Utilities/Triplet.h @@ -1,93 +1,93 @@ // -*- C++ -*- // // Triplet.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_Triplet_H #define ThePEG_Triplet_H #include "ThePEG/Config/ThePEG.h" namespace ThePEG { /** * The Triplet class represents a general triplet of objects * completely analogous to std::pair. */ template struct Triplet { /** The type of the first member. */ typedef T1 first_type; /** The type of the second member. */ typedef T2 second_type; /** The type of the third member. */ typedef T3 third_type; /** The first member. */ T1 first; /** The second member. */ T2 second; /** The third member. */ T3 third; /** Default construcotr. */ Triplet() : first(T1()), second(T2()), third(T3()) {} /** Constructor specifying the three members. */ Triplet(const T1 & t1, const T2 & t2, const T3 & t3) : first(t1), second(t2), third(t3) {} /** Copy constructor. */ Triplet(const Triplet & t) : first(t.first), second(t.second), third(t.third) {} /** Copy constructor from other Triplet type. */ template Triplet(const Triplet & u) : first(u.first), second(u.second), third(u.third) {} /** Test for equality. */ bool operator==(const Triplet & t) const { return first == t.first && second == t.second && third == t.third; } /** Test for ordering. * @return first < t.first || ( * !(t.first < first) && ( * second < t.second || ( !(t.second < second) && third < t.third * ))) */ bool operator<(const Triplet & t) const { return first < t.first || ( !(t.first < first) && ( second < t.second || ( !(t.second < second) && third < t.third ))); } }; /** Helper function returning a Triplet with template parameters * determined by the arguments. */ template inline Triplet makeTriplet (const T1 & t1, const T2 & t2, const T3 & t3) { return Triplet(t1, t2, t3); } /** Output a Triplet to a stream. */ template OStream & operator<<(OStream & os, const Triplet & t) { return os << t.first << t.second << t.third; } /** Input a Triplet from a stream. */ template IStream & operator>>(IStream & is, Triplet & t) { return is >> t.first >> t.second >> t.third; } } #endif /* ThePEG_Triplet_H */ diff --git a/Utilities/TypeInfo.h b/Utilities/TypeInfo.h --- a/Utilities/TypeInfo.h +++ b/Utilities/TypeInfo.h @@ -1,43 +1,43 @@ // -*- C++ -*- // // TypeInfo.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_TypeInfo_H #define ThePEG_TypeInfo_H #include "DescriptionList.h" namespace ThePEG { /** TypeInfo is a simple wrapper around the ClassDescription system in * ThePEG. Defines a few static functions for returning the mane and * version of the class given objects of that class. */ struct TypeInfo { /** Return the name of the class of the given object. */ template static string name(const T &) { const ClassDescriptionBase * cd = DescriptionList::find(typeid(T)); if ( cd ) return cd->name(); return "**** CLASS NOT REGISTERED ****"; } /** Return the version number of the class of the given object. */ template static int version(const T &) { const ClassDescriptionBase * cd = DescriptionList::find(typeid(T)); if ( cd ) return cd->version(); return -1; } }; } #endif /* ThePEG_TypeInfo_H */ diff --git a/Utilities/UnitIO.h b/Utilities/UnitIO.h --- a/Utilities/UnitIO.h +++ b/Utilities/UnitIO.h @@ -1,299 +1,299 @@ // -*- C++ -*- // // UnitIO.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_UnitIO_H #define ThePEG_UnitIO_H // This is the declaration of the IUnit and OUnit classes and // associated templated functions. #include #include #include #include #include namespace ThePEG { /** * The OUnit< class is used to * facilitate output of unitful numbers to a * persistent stream. An Energy can hence be written like * this:
os * << ounit(x, GeV);
Also containers of unitful * numbers may be written like this, as well as LorentzVector and * ThreeVector. * * @see PersistentOStream * @see PersistentIStream * */ template struct OUnit { /** Constructor given an object to be written assuming the given * unit. */ OUnit(const T & t, const UT & u): theX(t), theUnit(u) {} /** Copy constructor */ OUnit(const OUnit & iu): theX(iu.theX), theUnit(iu.theUnit) {} /** Reference to the object to be written. */ const T & theX; /** The unit assumed when writing the object. */ const UT & theUnit; }; /** * The IUnit class is used to facilitate input of unitful numbers from * and to a persistent stream. An Energy can hence be read like * this:
is >> iunit(x, GeV);
Also containers of * unitful numbers may be read like this, as well as LorentzVector and * ThreeVector. * * @see PersistentOStream * @see PersistentIStream * */ template struct IUnit { /** Constructor given an object to be read assuming the given * unit. */ IUnit(T & t, const UT & u): theX(t), theUnit(u) {} /** Copy constructor */ IUnit(const IUnit & iu): theX(iu.theX), theUnit(iu.theUnit) {} /** Reference to the object to be read. */ T & theX; /** The unit assumed when reading the object. */ const UT & theUnit; }; /** Helper function creating a OUnit object given an object and a * unit. */ template inline OUnit ounit(const T & t, const UT & ut) { return OUnit(t, ut); } /** Helper function creating a IUnit object given an object and a * unit. */ template inline IUnit iunit(T & t, const UT & ut) { return IUnit(t, ut); } /** Helper function writing out an object with a given unit to an * output stream. */ template void ounitstream(OStream & os, const T & t, UT & u) { os << t/u; } /** Helper function reading an object with a given unit from an * input stream. */ template void iunitstream(IStream & is, T & t, UT & u) { double d; is >> d; t = d*u;; } /** Helper function reading a complex object with a given unit from an * input stream. */ template void iunitstream(IStream & is, std::complex & t, UT & u) { std::complex d; is >> d; t = d*u;; } /** Output an OUnit object to a stream. */ template OStream & operator<<(OStream & os, const OUnit & u) { ounitstream(os, u.theX, u.theUnit); return os; } /** Input an IUnit object from a stream. */ template IStream & operator>>(IStream & is, const IUnit & u) { iunitstream(is, u.theX, u.theUnit); return is; } /** * OUnitErr is used to write out unitful numbers with an error * estimate on a standard ostream. using the helper function ouniterr * an energy e with an error estimate de can * be written out as eg. cout << ouniterr(e, de, * GeV);. The result will be presented in scientific format * (with the exponent divisible by three) with the relevant number of * significant digits with a single digit in parenthesis indicating * the error in the least significant digit, * eg. 1.23(2)e+03. */ template struct OUnitErr { /** Constructor given an object to be written assuming the given * unit. */ OUnitErr(const T & t, const T & dt, const UT & u): x(t/u), dx(dt/u) {} /** The number to be written. */ double x; /** The estimated error of the number to be written. */ double dx; }; /** Helper function creating a OUnitErr object. */ template inline OUnitErr ouniterr(const T & t, const T & dt, const UT & ut) { return OUnitErr(t, dt, ut); } /** Helper function creating a OUnitErr object. */ inline OUnitErr ouniterr(double t, double dt) { return OUnitErr(t, dt, 1.0); } /** Output an OUnitErr object to a stream. */ template OStream & operator<<(OStream & os, const OUnitErr & u) { if ( ! isfinite(u.x) ) return os << u.x; if ( ! isfinite(u.dx) ) { ostringstream out; out << u.x << '(' << u.dx << ')'; return os << out.str(); } double dx = min(u.dx, abs(u.x)); if ( dx <= 0.0 ) return os << u.x; double x = abs(u.x); ostringstream osse; osse << std::scientific << setprecision(0) << dx; string sse = osse.str(); string::size_type ee = sse.find('e'); long m = static_cast(round(abs(x)/std::pow(10.0,std::atoi(sse.substr(ee + 1).c_str())))); int powx = m <= 0? os.precision(): int(log10(double(m))); if ( m <= 0 || powx > os.precision() ) sse[0]='0'; ostringstream oss; oss << std::scientific << setprecision(powx) << x; string ss = oss.str(); string::size_type e = ss.find('e'); ostringstream out; int pp = std::atoi(ss.substr(e + 1).c_str()); if ( pp%3 == 0 ) out << ss.substr(0, e) << "(" << sse[0] << ")" << ss.substr(e); else if ( (pp - 1)%3 == 0 ) { ostringstream oss; oss << std::scientific << setprecision(powx) << x/10.0; string ss = oss.str(); string::size_type e = ss.find('e'); if ( powx == 0 ) out << ss.substr(0, e) << "0(" << sse[0] << "0)" << ss.substr(e); else if ( powx == 1 ) out << ss.substr(0, ss.find('.')) << ss.substr(ss.find('.') + 1, e - ss.find('.') - 1) << "(" << sse[0] << ")" << ss.substr(e); else { swap(ss[ss.find('.')], ss[ss.find('.') + 1]); out << ss.substr(0, e) << "(" << sse[0] << ")" << ss.substr(e); } } else { ostringstream oss; oss << std::scientific << setprecision(powx) << x*10.0; string ss = oss.str(); string::size_type e = ss.find('e'); if ( powx == 0 ) out << "0." << ss.substr(0, e) << "(" << sse[0] << ")" << ss.substr(e); else { swap(ss[ss.find('.')], ss[ss.find('.') - 1]); out << ss.substr(0, ss.find('.')) << "0" << ss.substr(ss.find('.'), e) << "(" << sse[0] << ")" << ss.substr(e); } } string res = out.str(); if ( u.x < 0.0 ) res = "-" + res; return os << res; } /** * The IUnitErr class is used to facilitate input of unitful numbers * with error estimates written out using the OUnitErr class. * */ template struct IUnitErr { /** Constructor given an object to be read assuming the given * unit. */ IUnitErr(T & t, T & dt, const UT & u): x(t), dx(dt), ut(u) {} /** Reference to the object to be read. */ T & x; /** The estimated error of the number to be read. */ T & dx; /** The unit assumed when reading the object. */ UT ut; }; /** Helper function creating a IUnitErr object. */ template inline IUnitErr iuniterr(T & t, T & dt, const UT & ut) { return IUnitErr(t, dt, ut); } /** Helper function creating a OUnitErr object. */ inline IUnitErr iuniterr(double & t, double & dt) { return IUnitErr(t, dt, 1.0); } /** Input an IUnit object from a stream. */ template IStream & operator>>(IStream & is, const IUnitErr & u) { string s; double x = 0.0; double dx = 0.0; double ex = 1.0; is >> s; string::size_type open = s.find('('); string::size_type close = s.find(')'); string se = "0"; string sp = "1"; double pe = 1.0; if ( open != string::npos && close != string::npos ) { se = s.substr(open + 1); sp += s.substr(close + 1); string::size_type dot = s.find('.'); if ( dot != string::npos && dot < open ) pe = std::pow(10.0, 1.0 - (open - dot)); } istringstream(s) >> x; istringstream(se) >> dx; istringstream(sp) >> ex; u.x = x*ex*u.ut; u.dx = dx*ex*pe*u.ut; return is; } } #endif /* ThePEG_UnitIO_H */ diff --git a/Utilities/UtilityBase.cc b/Utilities/UtilityBase.cc --- a/Utilities/UtilityBase.cc +++ b/Utilities/UtilityBase.cc @@ -1,15 +1,15 @@ // -*- C++ -*- // // UtilityBase.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #include "UtilityBase.h" #ifdef ThePEG_TEMPLATES_IN_CC_FILE #include "UtilityBase.tcc" #endif diff --git a/Utilities/UtilityBase.h b/Utilities/UtilityBase.h --- a/Utilities/UtilityBase.h +++ b/Utilities/UtilityBase.h @@ -1,382 +1,382 @@ // -*- C++ -*- // // UtilityBase.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_UtilityBase_H #define ThePEG_UtilityBase_H #include "ThePEG/Config/ThePEG.h" #include "ThePEG/EventRecord/ParticleTraits.h" #include "ThePEG/Utilities/Triplet.h" namespace ThePEG { /** * UtilityBase is a base class implementing a number of static utility * functions. It should be used as a base class to give acces to these * functions to a class. A class can safely multiply inherit from this * class as it only contains static functions. */ struct UtilityBase { /** * Sums the four-momentum of given container. The class * Cont::value_type must be of a type T * for which ParticleTraits::momentum(const T&) is * implemented correctly. */ template static LorentzMomentum sumMomentum(const Cont & c) { return sumMomentum(c.begin(), c.end()); } /** * Sums the four-momentum of the entries between first and last. The * class Iterator::value_type must be of a type * T for which ParticleTraits::momentum(const * T&) is implemented correctly. */ template static LorentzMomentum sumMomentum(Iterator first, Iterator last) { LorentzMomentum sum; typedef typename std::iterator_traits::value_type PType; typedef ParticleTraits Traits; while ( first != last ) sum += Traits::momentum(*first++); return sum; } /** * Transform the entries between \a first and \a last. The class * Iterator::value_type must be of a type * T for which ParticleTraits::momentum(const * T&) is implemented correctly. */ template static void transform(Iterator first, Iterator last, const LorentzRotation & boost) { typedef typename std::iterator_traits::value_type PType; typedef ParticleTraits Traits; while ( first != last ) Traits::transform(*first++, boost); } /** * Transform the entries in a container \a cont. The class * Cont::value_type must be of a type T * for which ParticleTraits::momentum(const T&) is * implemented correctly. */ template static void transform(Cont & cont, const LorentzRotation & boost) { transform(cont.begin(), cont.end(), boost); } /** * Boost the two objects in the pair to their CM system. Also rotate * so that the first is along the z-axis. The class * PType must have * ParticleTraits::momentum(const PType&) and * ParticleTraits::transform(PType&, const * LorentzRotation&) implemented correctly. */ template static LorentzRotation boostToCM(const pair & pp); /** * Boost the three objects in the Triplet to their CM system. Also * rotate so that the first is along the z-axis and the second is in * the x-z plane with positive x. The class PType must * have ParticleTraits::momentum(const PType&) * and ParticleTraits::transform(PType&, const * LorentzRotation&) implemented correctly. */ template static LorentzRotation boostToCM(const Triplet & pt); /** * Obtain the LorentzRotation needed to boost the two objects in the * pair to their CM system. Also rotate the LorentzRotation so that * the first is along the z-axis. The class PType must * have ParticleTraits::momentum(const PType&) * implemented correctly. */ template static LorentzRotation getBoostToCM(const pair & pp); /** * Obtain the LorentzRotation needed to boost the three objects in * the Triplet to their CM system. Also rotate the LorentzRotation * so that the first is along the z-axis and the secons i in the x-z * plane with positive x. The class PType * must have ParticleTraits::momentum(const * PType&) implemented correctly. */ template static LorentzRotation getBoostToCM(const Triplet & pt); /** * Get the inverse boost as compared to getBoostToCM. */ template static LorentzRotation getBoostFromCM(const pair & pp); /** * Get the inverse boost as compared to getBoostToCM. */ template static LorentzRotation getBoostFromCM(const Triplet & pt); /** * Boost the entries between fisrt and last into their CM system. * The class Iterator::value_type must be of a type * T for which ParticleTraits::momentum(const * T&) and ParticleTraits::transform(T&, const * LorentzRotation&) are implemented correctly. */ template static LorentzRotation boostToCM(Iterator first, Iterator last) { return boostToCM(first, last, last, last); } /** * Boost the entries between fisrt and last into their CM system. If * zAxis != last, also rotate the entries so that zAxis becomes * paralell to the z-axis. The class * Iterator::value_type must be of a type * T for which ParticleTraits::momentum(const * T&) and ParticleTraits::transform(T&, const * LorentzRotation&) are implemented correctly. */ template static LorentzRotation boostToCM(Iterator first, Iterator last, Iterator zAxis) { return boostToCM(first, last, zAxis, last); } /** * Boost the entries between fisrt and last into their CM system. If * zAxis != last, also rotate the entries so that zAxis becomes * paralell to the z-axis. Also, if xzPlane != last, rotate the * entries so that xzPlane is placed in the xz-plane. The class * Iterator::value_type must be of a type * T for which ParticleTraits::momentum(const * T&) and ParticleTraits::transform(T&, const * LorentzRotation&) are implemented correctly. */ template static LorentzRotation boostToCM(Iterator first, Iterator last, Iterator zAxis, Iterator xzPlane); /** * Rotate p to the z-axis and boost it to its CMS, then boost it * along the z-axis and rotate it so that it ends up with momentum * q. If p is massless - simply set its momentum. The class * PType must have * ParticleTraits::momentum(const PType&) * implemented correctly. */ template static void setMomentum(PType & p, const Momentum3 & q); /** * Boost p along the z-axis and rotate it so that, if it was * previously at rest, it ends up with momentum q. If p is massless * - simply set its momentum to q. The class * PType must have * ParticleTraits::momentum(const PType&) * implemented correctly. */ template static void setMomentumFromCMS(PType & p, const Momentum3 & q); /** * Rotate the range of particles so their sum is along z-axis and * boost them to their CMS, then boost them along the z-axis and * rotate them so that they end up with total momentum q. The class * Iter::value_type must be of a type T * for which ParticleTraits::momentum(const T&) and * ParticleTraits::transform(T&, const * LorentzRotation&) are implemented correctly. */ template static void setMomentum(Iter first, Iter last, const Momentum3 & q); /** * Rotate the range of particles so their sum is along z-axis then * boost them along the z-axis and rotate them so that they end up * with total momentum q. If a single boost does not succeed to * obtain the required precision within eps times the total energy, * the boost is redone. The class Iter::value_type must * be of a type T for which * ParticleTraits::momentum(const T&) and * ParticleTraits::transform(T&, const * LorentzRotation&) are implemented correctly. */ template static void setMomentum(Iter first, Iter last, const Momentum3 & q, double eps); /** * Boost the range of particles along the z-axis and rotate them so * that, if they were previously in their rest frame, they end up * with total momentum q. The class Iter::value_type must * be of a type T for which * ParticleTraits::momentum(const T&) and * ParticleTraits::transform(T&, const * LorentzRotation&) are implemented correctly. * @param first iterator pointing to the first particle in the range. * @param last iterator indicating the end of the range. * @param m2 the invariant mass squared of the particles. * @param q final summed momentum of the particles. */ template static void setMomentumFromCMS(Iter first, Iter last, Energy2 m2, const Momentum3 & q); /** * Return the transformation needed to rotate \a p to the z-axis and * boost it to its CMS, then boost it along the z-axis and rotate it * so that it ends up with momentum \a q. The class * PType must have * ParticleTraits::momentum(const PType&) * implemented correctly. Warning This function only works * properly if \a p has a well defined direction in both polar and * azimuth angles. * \deprecated{Use getTransformToMomentum() instead.} */ template static LorentzRotation transformToMomentum(const PType & p, const Momentum3 & q) { typedef ParticleTraits Traits; LorentzMomentum q4(q, sqrt(q.mag2() + Traits::momentum(p).m2())); return transformToMomentum(p, q4); } /** * Return the transformation needed to rotate \a p to the z-axis and * boost it to its CMS, then boost it along the z-axis and rotate it * so that it ends up with momentum \a q. The class PType * must have ParticleTraits::momentum(const * PType&) implemented correctly. Warning This * function only works properly if \a p has a well defined direction * in both polar and azimuth angles. * \deprecated{Use getTransformToMomentum() instead.} */ template static LorentzRotation transformToMomentum(const PType & p, const LorentzMomentum & q) { return transformFromCMS(q)*transformToCMS(p); } /** * Return a transformation appropriate for transforming \a p to have * the momentum \a q. The transformation is done so that the * auxiliary vector \a k is left unchanged. */ template static LorentzRotation getTransformToMomentum(const PType & p, const LorentzMomentum & q, const LorentzMomentum & k) { typedef ParticleTraits Traits; LorentzMomentum k0 = Traits::momentum(p) - k; LorentzMomentum k1 = Traits::momentum(q) - k; return getBoostFromCM(make_pair(k1, k))*getBoostToCM(make_pair(k0, k)); } /** * Return a transformation appropriate for transforming \a p to have * the momentum \a q. The transformation is done so that the * auxiliary vector \a k is left unchanged. */ template static LorentzRotation getTransformToMomentum(const PType & p, const Momentum3 & q, const LorentzMomentum & k) { typedef ParticleTraits Traits; LorentzMomentum q4(q, sqrt(q.mag2() + Traits::momentum(p).m2())); return getTransformToMomentum(p, q4, k); } /** * Create a rotation corresponding to transforming p to its current * value from its CMS by first boosting along the z-axis and then * rotating. The class LV must have methods * rho() and e(). */ template static LorentzRotation transformFromCMS(const LV & p); /** * Create a rotation corresponding to transforming sum to its * current value from its CMS, with zAxis along the z-axis in that * CMS frame. The class LV must have methods * rho(), phi() theta() and * e(). */ template static LorentzRotation transformFromCMS(const LV & sum, LV zAxis); /** * Create a rotation corresponding to transforming sum to its * current value from its CMS, with zAxis along the z-axis and * xyPlane in the x-y plane in that CMS frame. The class * LV must have methods rho(), * phi() theta() and e(). */ template static LorentzRotation transformFromCMS(const LV & sum, const LV & zAxis, LV xyPlane); /** * Create a rotation which would transform sum to its CMS frame with * zAxis along the z-axis in that frame. The class LV * must have methods rho(), phi() * theta() and e(). */ template static LorentzRotation transformToCMS(const LV & sum, LV zAxis); /** * Create a rotation which would transform sum to its CMS frame * first rotating it to the z-axis and then boost it along the * z-axis. The class LV must have methods * rho(), phi() theta() and * e(). */ template static LorentzRotation transformToCMS(const LV & p); /** * Create a rotation which would transform sum to its CMS frame with * zAxis along the z-axis and xyPlane in the x-y plane in that * frame. The class LV must have methods * rho(), phi() theta() and * e(). */ template static LorentzRotation transformToCMS(const LV & sum, const LV & zAxis, LV xyPlane); /** * Add the elements in Cont2 to Cont1, appending them to the end if * possible. */ template static void add(Cont1 & c1, const Cont2 & c2); }; /** Concrete class with UtilityBase as base class. */ struct Utilities: public UtilityBase {}; } #ifndef ThePEG_TEMPLATES_IN_CC_FILE #include "UtilityBase.tcc" #endif #endif /* ThePEG_UtilityBase_H */ diff --git a/Utilities/UtilityBase.tcc b/Utilities/UtilityBase.tcc --- a/Utilities/UtilityBase.tcc +++ b/Utilities/UtilityBase.tcc @@ -1,268 +1,268 @@ // -*- C++ -*- // // UtilityBase.tcc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // namespace ThePEG { template LorentzRotation UtilityBase::boostToCM(const pair & pp) { typedef ParticleTraits Traits; LorentzRotation boost(-(Traits::momentum(pp.first) + Traits::momentum(pp.second)).boostVector()); Traits::transform(pp.first, boost); Traits::transform(pp.second, boost); LorentzRotation rot; rot.rotateZ(-Traits::momentum(pp.first).phi()); rot.rotateY(-Traits::momentum(pp.first).theta()); rot.rotateZ(Traits::momentum(pp.first).phi()); Traits::transform(pp.first, rot); Traits::transform(pp.second, rot); return rot*boost; } template LorentzRotation UtilityBase::boostToCM(const Triplet & pt) { typedef ParticleTraits Traits; LorentzRotation rot = getBoostToCM(pt); Traits::transform(pt.first, rot); Traits::transform(pt.second, rot); Traits::transform(pt.third, rot); return rot; } template LorentzRotation UtilityBase::getBoostToCM(const pair & pp) { typedef ParticleTraits Traits; LorentzMomentum p1 = Traits::momentum(pp.first); Boost b = (p1 + Traits::momentum(pp.second)).boostVector(); p1.boost(-b); LorentzRotation rot(-b); rot.rotateZ(-p1.phi()); rot.rotateY(-p1.theta()); rot.rotateZ(p1.phi()); return rot; } template LorentzRotation UtilityBase:: getBoostToCM(const Triplet & pt) { typedef ParticleTraits Traits; LorentzMomentum p1 = Traits::momentum(pt.first); LorentzMomentum p2 = Traits::momentum(pt.second); Boost b = (p1 + p2 + Traits::momentum(pt.third)).boostVector(); p1.boost(-b); LorentzRotation rot(-b); rot.rotateZ(-p1.phi()); rot.rotateY(-p1.theta()); p2.transform(rot); rot.rotateZ(-p2.phi()); return rot; } template LorentzRotation UtilityBase:: getBoostFromCM(const Triplet & pt) { return getBoostToCM(pt).inverse(); } template LorentzRotation UtilityBase::getBoostFromCM(const pair & pp) { typedef ParticleTraits Traits; LorentzMomentum p1 = Traits::momentum(pp.first); Boost b = (p1 + Traits::momentum(pp.second)).boostVector(); p1.boost(-b); LorentzRotation rot; rot.rotateZ(-p1.phi()); rot.rotateY(p1.theta()); rot.rotateZ(p1.phi()); rot.boost(b); return rot; } template LorentzRotation UtilityBase::boostToCM(Iterator first, Iterator last, Iterator zAxis, Iterator xzPlane) { if ( first == last ) return LorentzRotation(); LorentzRotation boost(-sumMomentum(first, last).boostVector()); typedef typename std::iterator_traits::value_type PType; typedef ParticleTraits Traits; transform(first, last, boost); if ( zAxis != last ) { LorentzRotation rot; rot.rotateZ(-Traits::momentum(*zAxis).phi()); rot.rotateY(-Traits::momentum(*zAxis).theta()); if ( xzPlane == last ) rot.rotateZ(Traits::momentum(*zAxis).phi()); transform(first, last, rot); boost = rot*boost; } if ( xzPlane != last ) { LorentzRotation rot; rot.rotateZ(-Traits::momentum(*xzPlane).phi()); transform(first, last, rot); boost = rot*boost; } return boost; } template LorentzRotation UtilityBase:: transformFromCMS(const LV & p) { if(p.rho()/p.e()>=1.) throw Exception() << "Boost >=1. in " << "UtilityBase::transformFromCMS()" << Exception::eventerror; LorentzRotation r(0.0, 0.0, p.rho()/p.e()); r.rotateZ(-p.phi()); r.rotateY(p.theta()); r.rotateZ(p.phi()); return r; } template LorentzRotation UtilityBase:: transformFromCMS(const LV & sum, LV zAxis) { LorentzRotation r; Boost bz(sum.boostVector()); zAxis.boost(-bz); r.rotateZ(-zAxis.phi()); r.rotateY(zAxis.theta()); r.rotateZ(zAxis.phi()); r.boost(bz); return r; } template LorentzRotation UtilityBase:: transformFromCMS(const LV & sum, const LV & zAxis, LV xyPlane) { LorentzRotation r; LorentzRotation r1 = transformFromCMS(sum, zAxis); xyPlane.transform(r1.inverse()); r.rotateZ(xyPlane.phi()); r.transform(r1); return r; } template LorentzRotation UtilityBase:: transformToCMS(const LV & p) { LorentzRotation r; r.rotateZ(-p.phi()); r.rotateY(-p.theta()); r.rotateZ(p.phi()); if(p.rho()/p.e()>1.) throw Exception() << "Boost >=1. in " << "UtilityBase::transformToCMS " << Exception::eventerror; r.boostZ(-p.rho()/p.e()); return r; } template LorentzRotation UtilityBase:: transformToCMS(const LV & sum, LV zAxis) { LorentzRotation r(-sum.boostVector()); zAxis.transform(r); r.rotateZ(-zAxis.phi()); r.rotateY(-zAxis.theta()); r.rotateZ(zAxis.phi()); return r; } template LorentzRotation UtilityBase:: transformToCMS(const LV & sum, const LV & zAxis, LV xyPlane) { LorentzRotation r(transformToCMS(sum, zAxis)); xyPlane.transform(r); r.rotateZ(-xyPlane.phi()); return r; } template void UtilityBase::setMomentum(PType & p, const Momentum3 & q) { typedef ParticleTraits Traits; if ( Traits::momentum(p).m2() <= ZERO || Traits::mass(p) <= ZERO ) { Traits::set3Momentum(p, q); } else { Traits::transform(p, transformToCMS(Traits::momentum(p))); setMomentumFromCMS(p, q); } } template void UtilityBase::setMomentumFromCMS(PType & p, const Momentum3 & q) { typedef ParticleTraits Traits; LorentzMomentum q4(q, sqrt(q.mag2() + sqr(Traits::mass(p)))); if ( Traits::momentum(p) == LorentzMomentum() ) Traits::set5Momentum(p, q4); else Traits::transform(p, transformFromCMS(q4)); return; } template void UtilityBase::setMomentum(Iter first, Iter last, const Momentum3 & q) { if ( first == last ) return; typedef typename std::iterator_traits::value_type PType; typedef ParticleTraits Traits; Iter second = first; if ( ++second == last ) return setMomentum(Traits::ref(*first), q); LorentzMomentum sum = sumMomentum(first, last); transform(first, last, transformToCMS(sum)); setMomentumFromCMS(first, last, sum.m2(), q); } template void UtilityBase:: setMomentum(Iter first, Iter last, const Momentum3 & q, double eps) { if ( first == last ) return; typedef typename std::iterator_traits::value_type PType; typedef ParticleTraits Traits; Iter second = first; if ( ++second == last ) return setMomentum(Traits::ref(*first), q); LorentzRotation r; LorentzMomentum sum = sumMomentum(first, last); if ( sum.rho2() > 1.0e-12*MeV2 ) { r.rotateZ(-sum.phi()); r.rotateY(-sum.theta()); r.rotateZ(sum.phi()); } if((sum.vect()-q).mag2()< 1.0e-12*MeV2) return; Energy2 ppo = sqr(sum.rho() + sum.e()); Energy2 ppn = sqr(q.mag() + sqrt(q.mag2() + sum.m2())); r.boost(0.0, 0.0, (ppn - ppo)/(ppn + ppo)); r.rotateZ(-q.phi()); r.rotateY(q.theta()); r.rotateZ(q.phi()); transform(first, last, r); sum = sumMomentum(first, last); if ( abs(sum.x() - q.x()) > eps*sum.e() || abs(sum.y() - q.y()) > eps*sum.e() || abs(sum.z() - q.z()) > eps*sum.e() ) setMomentum(first, last, q, eps); } template void UtilityBase:: setMomentumFromCMS(Iter first, Iter last, Energy2 m2, const Momentum3 & q) { if ( first == last ) return; typedef typename std::iterator_traits::value_type PType; typedef ParticleTraits Traits; Iter second = first; if ( ++second == last ) return setMomentumFromCMS(Traits::ref(*first), q); transform(first, last, transformFromCMS(LorentzMomentum(q, sqrt(q.mag2() + m2)))); } template void UtilityBase::add(Cont1 & c1, const Cont2 & c2) { typename Cont2::const_iterator i = c2.begin(); while ( i != c2.end() ) c1.insert(c1.end(), *i++); } } diff --git a/Utilities/UtilityBase.xh b/Utilities/UtilityBase.xh --- a/Utilities/UtilityBase.xh +++ b/Utilities/UtilityBase.xh @@ -1,19 +1,19 @@ // -*- C++ -*- // // UtilityBase.xh is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_UtilityBase_XH #define ThePEG_UtilityBase_XH #include "UtilityBase.fh" namespace ThePEG { } #endif /* ThePEG_UtilityBase_XH */ diff --git a/Utilities/VSelector.h b/Utilities/VSelector.h --- a/Utilities/VSelector.h +++ b/Utilities/VSelector.h @@ -1,336 +1,336 @@ // -*- C++ -*- // // VSelector.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_VSelector_H #define ThePEG_VSelector_H // This is the definition of the ThePEG::VSelector class. #include "ThePEG/Config/ThePEG.h" #include #include #include namespace ThePEG { template /** * VSelector is a templated class for storing objects associated with * probabilities in a way such that, given a flat random number * between 0 and 1, an object can be selected according to its * relative probability. Internally, the objects of class * T are stored in a vector parallel to a vector of the * probability of the corresponding object plus the accumulated sum of * probabilities of all objects before the current one in the * vector. This allows for fast retreival of an object according to * its probability. Where fast means that the time increases as a * logarithm of the number of objects in the selector. * * Here is an example on how to use the class:
* double random(); // A random generator returning a * number between 0 and 1.
* class foo; // Any class.
* VSelector bar; // A selector.
* foo f1, f2;
* bar.insert(0.5,&f1) // assign probability 0.5
* bar.insert(0.5,&f2) // to each of f1 and f2
* foo * f = bar.select(random()) // randomly returns * a pointer to f1 or f2
* * @see Selector */ class VSelector { public: /** A vector of weights. */ typedef vector WeightVector; /** The weight vector iterator type. */ typedef typename WeightVector::const_iterator WIterator; /** A vector ob objects. */ typedef vector ObjectVector; /** The object vector iterator type. */ typedef typename ObjectVector::iterator iterator; /** The object vector const iterator type. */ typedef typename ObjectVector::const_iterator const_iterator; /** Size type of the underlying vector. */ typedef typename ObjectVector::size_type size_type; public: /** * Default constructor. */ VSelector(size_type reserved = 0) : theSum() { reserve(reserved); } /** * Swap the underlying representation with the argument. */ void swap(VSelector & s) { theSums.swap(s.theSums); theWeights.swap(s.theWeights); theObjects.swap(s.theObjects); std::swap(theSum, s.theSum); } /** * Insert an object given a probability for this object. If the * probability is zero or negative, the object will not be inserted * and the probability itself is returned. Otherwise the sum of * probabilities is returned. */ WeightType insert(WeightType d, const T & t) { WeightType newSum = theSum + d; if ( newSum <= theSum ) return d; theSums.push_back(theSum = newSum); theWeights.push_back(d); theObjects.push_back(t); return theSum; } /** * Reweight an object previously inserted giving it a new weight. If * several equivalent objects exists, all of them will be * reweighted. */ WeightType reweight(WeightType, const T &); /** * Erase an object, previously inserted. If the object had not been * inserted, nothing will happen. If several copies of the object * has been inserted, all will be removed removed. In all cases the * sum of probabilities is returned. */ WeightType erase(const T &); /** * Replace all occurencies of told with tnew without changing the * probability for the entry. */ void replace(const T & told, const T & tnew) { for ( iterator it = theObjects.begin(); it != theObjects.end(); ++it ) if ( *it == told ) *it = tnew; } /** * Select an object randomly. Given a random number flatly * distributed in the interval ]0,1[ Select an object according to * the individual probabilities specified when they were * inserted. If rnd <= 0 or if rnd >= 1 or the Selector is empty, a * range_error will be thrown. * @param rnd a flat random number in the interval ]0,1[ * @param remainder if non-zero the double pointed to will be set to * a uniform random number in the interval ]0,1[ calculated from the * fraction of rnd which was in the range of the selected object. */ T & select(double rnd, double * remainder = 0) { return theObjects[iselect(rnd, remainder)]; } /** * Selct an object randomly. Given a random number flatly * distributed in the interval ]0,1[ Select an object according to * the individual probabilities specified when they were * inserted. If rnd <= 0 or if rnd >= 1 or the Selector is empty, a * range_error will be thrown. */ T & operator[](double rnd) { return select(rnd, 0); } /** * Selct an object randomly. Given a random number flatly * distributed in the interval ]0,1[ Select an object according to * the individual probabilities specified when they were * inserted. If rnd <= 0 or if rnd >= 1 or the Selector is empty, a * range_error will be thrown. * @param rnd a flat random number in the interval ]0,1[ * @param remainder if non-zero the double pointed to will be set to * a uniform random number in the interval ]0,1[ calculated from the * fraction of rnd which was in the range of the selected object. */ const T & select(double rnd, double * remainder = 0) const { return theObjects[iselect(rnd, remainder)]; } /** * Selct an object randomly. Given a random number flatly * distributed in the interval ]0,1[ select an object according to * the individual probabilities specified when they were * inserted. If rnd <= 0 or if rnd >= 1 or the Selector is empty, a * range_error will be thrown. */ const T & operator[](double rnd) const { return select(rnd, 0); } /** * Selct an object randomly. Given a random number generator which * generates flat random numbers in the interval ]0,1[ with the * operator()() function, select an object according to * the individual probabilities specified when they were * inserted. If the generated number is outside the allowed range or * the Selector is empty, a range_error will be thrown. The * generator should have a push_back function which will be used * push back a uniform random number in the interval ]0,1[ * calculated from the fraction of rnd which was in the range of the * selected object. */ template T & select(RNDGEN & rnd) { double rem = 0.0; T & t = select(rnd(), &rem); rnd.push_back(rem); return t; } /** * Selct an object randomly. Given a random number generator which * generates flat random numbers in the interval ]0,1[ with the * operator()() function, select an object according to * the individual probabilities specified when they were * inserted. If the generated number is outside the allowed range or * the Selector is empty, a range_error will be thrown. The * generator should have a push_back function which will be used * push back a uniform random number in the interval ]0,1[ * calculated from the fraction of rnd which was in the range of the * selected object. */ template const T & select(RNDGEN & rnd) const { double rem = 0.0; const T & t = select(rnd(), &rem); rnd.push_back(rem); return t; } /** * Return the sum of probabilities of the objects inserted. Note * that probabilities specified when objects are inserted are * rescaled with this number to give unit probability for * 'select()'. */ WeightType sum() const { return theSum; } /** * Access to the begin() iterator of the underlying * vector of objects. */ const_iterator begin() const { return theObjects.begin(); } /** * Access to the end() iterator in the underlying * vector of objects. */ const_iterator end() const { return theObjects.end(); } /** * Returns true if the VSelector is empty. */ bool empty() const { return theObjects.empty(); } /** * Returns the number of objects in the selector. */ size_type size() const { return theObjects.size(); } /** * Allocate space for a number of objects in the underlying vectors. */ void reserve(size_type reserved) { theSums.reserve(reserved); theWeights.reserve(reserved); theObjects.reserve(reserved); } /** * Erases all objects. */ void clear() { theSums.clear(); theWeights.clear(); theObjects.clear(); theSum = WeightType(); } /** * Output to a stream. */ template void output(OStream &) const; /** * Input from a stream. */ template void input(IStream &); protected: /** * Internal selection engine. */ size_type iselect(double rnd, double * remainder) const; private: /** * The vector of accumulated weights for the objects in the selector */ WeightVector theSums; /** * The vector of weights for the objects in the selector */ WeightVector theWeights; /** * The vector of objects in the selector. */ ObjectVector theObjects; /** * The sum of all weights. */ WeightType theSum; }; /** * Output a VSelector to a stream. */ template inline OStream & operator<<(OStream & os, const VSelector & s) { s.output(os); return os; } /** * Input a VSelector from a stream. */ template inline IStream & operator>>(IStream & is, VSelector & s) { s.input(is); return is; } } #include "VSelector.tcc" #endif /* ThePEG_VSelector_H */ diff --git a/Utilities/VSelector.tcc b/Utilities/VSelector.tcc --- a/Utilities/VSelector.tcc +++ b/Utilities/VSelector.tcc @@ -1,70 +1,70 @@ // -*- C++ -*- // // VSelector.tcc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // namespace ThePEG { template WeightType VSelector::erase(const T & t) { theSum = WeightType(); int j = 0; for ( int i = 0, N = theWeights.size(); i < N; ++i ) { if ( theObjects[i] == t ) continue; theSums[j] = (theSum += theWeights[i]); if ( i != j ) { theWeights[j] = theWeights[i]; theObjects[j] = theObjects[i]; } ++j; } theSums.erase(theSums.begin() + j, theSums.end()); theWeights.erase(theWeights.begin() + j, theWeights.end()); theObjects.erase(theObjects.begin() + j, theObjects.end()); return theSum; } template WeightType VSelector::reweight(WeightType d, const T & t) { d = max(d, WeightType()); theSum = WeightType(); for ( int i = 0, N = theWeights.size(); i < N; ++i ) { if ( theObjects[i] == t ) theWeights[i] = d; theSums[i] = ( theSum += theWeights[i] ); } return theSum; } template typename VSelector::size_type VSelector:: iselect(double rnd, double * remainder) const { if ( rnd <= 0 ) throw range_error("Random number out of range in VSelector::select."); WeightType sum = rnd*theSum; WIterator it = upper_bound(theSums.begin(), theSums.end(), sum); if ( it == theSums.end() ) throw range_error("Empty Selector, or random number out of range " "in Selector::select"); size_type i = it - theSums.begin(); if ( remainder ) *remainder = 1.0 - (theSums[i] - sum)/theWeights[i]; return i; } template template void VSelector::output(OStream & os) const { os << theSum << theSums << theWeights << theObjects; } template template void VSelector::input(IStream & is) { clear(); is >> theSum >> theSums >> theWeights >> theObjects; } } diff --git a/Utilities/XSecStat.cc b/Utilities/XSecStat.cc --- a/Utilities/XSecStat.cc +++ b/Utilities/XSecStat.cc @@ -1,43 +1,43 @@ // -*- C++ -*- // // XSecStat.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the XSecStat class. // #include "XSecStat.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" namespace ThePEG { PersistentOStream & operator<<(PersistentOStream & os, const XSecStat & x) { x.output(os); return os; } PersistentIStream & operator>>(PersistentIStream & is, XSecStat & x) { x.input(is); return is; } } using namespace ThePEG; void XSecStat::output(PersistentOStream & os) const { os << ounit(theMaxXSec,picobarn) << theAttempts << theAccepted << theSumWeights << theSumWeights2 << theLastWeight; } void XSecStat::input(PersistentIStream & is) { is >> iunit(theMaxXSec,picobarn) >> theAttempts >> theAccepted >> theSumWeights >> theSumWeights2 >> theLastWeight; } diff --git a/Utilities/XSecStat.h b/Utilities/XSecStat.h --- a/Utilities/XSecStat.h +++ b/Utilities/XSecStat.h @@ -1,321 +1,321 @@ // -*- C++ -*- // // XSecStat.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_XSecStat_H #define THEPEG_XSecStat_H // // This is the declaration of the XSecStat class. // #include "ThePEG/Config/ThePEG.h" namespace ThePEG { /** * XSecStat is a concrete helper class used to collect statistics * about the cross section for a specific process or group of * processes. It contains an overestimated cross section and * information about the number of times the process has been used to * generate an event and how many times this event has been accepted. * * An object of this class must initially be given an overestimated * cross section in the constructor or with the maxXSec(CrossSection) * function. Each time the corresponding process is selected * (according to maxXSec()), the select(double) function should be * called giving the weight with which the event will be accepted as * argument. If the event is then accepted, the accept() function * should be called. If an event is later vetoed, the reject() * function should be called. * */ class XSecStat { public: /** * Enumerate the different weight classes */ enum { plainWeights = 0, plainVetoedWeights, reweightedWeights, reweightedVetoedWeights }; /** @name Standard constructors, destructor and assignment operator. */ //@{ /** * The default constructor. */ XSecStat() : theMaxXSec(ZERO), theAttempts(0), theAccepted(0), theVetoed(0), theSumWeights (), theSumWeights2(), theLastWeight(0.0) {} /** * Constructor taking the overestimated cross section, \a xsecmax, * as argument. */ explicit XSecStat(CrossSection xsecmax) : theMaxXSec(xsecmax), theAttempts(0), theAccepted(0), theVetoed(0), theSumWeights (), theSumWeights2(), theLastWeight(0.0) {} /** * The assignment operator. */ XSecStat & operator=(const XSecStat & x) = default; /** * Add the contents of another XSecStat. */ XSecStat & operator+=(const XSecStat & x) { theAttempts += x.theAttempts; theAccepted += x.theAccepted; theVetoed += x.theVetoed; for( unsigned int ix = 0; ix < 4; ++ix ) { theSumWeights [ix] += x.theSumWeights [ix]; theSumWeights2[ix] += x.theSumWeights2[ix]; } theLastWeight = 0.0; return *this; } /** * Reset the statistics. */ void reset() { theAttempts = theAccepted = theVetoed = 0; theSumWeights = theSumWeights2 = {}; theLastWeight = 0.0; } //@} public: /** @name Simple access functions */ //@{ /** * An event of the corresponding class has been accepted. The * select() method must have been called before. */ void accept() { theAccepted += 1; } /** * An event of the corresponding class has been attempted. It will * subsequently be accepted with the given \a weight. */ void select(double weight) { theAttempts += 1; theSumWeights [reweightedWeights] += weight ; theSumWeights2[reweightedWeights] += sqr(weight); theSumWeights [plainWeights] += weight ; theSumWeights2[plainWeights] += sqr(weight); theLastWeight = weight; } /** * Reweight a selected and accepted event. */ void reweight(double oldWeight, double newWeight) { theSumWeights [reweightedWeights] += newWeight - oldWeight ; theSumWeights2[reweightedWeights] += sqr(newWeight) - sqr(oldWeight); } /** * Reject the event which was last accepted with accept() or * selected with select(double). The \a weight should be set to the * value, \f$w\f$, used in the previous call to select(double), * except if the event has been accepted with the probability * \f$w\f$, in which case \a weight should be set to \f$sign(1, * w)\f$. */ void reject(double weight = 1.0) { theSumWeights [reweightedVetoedWeights] += weight ; theSumWeights2[reweightedVetoedWeights] += sqr(weight); theSumWeights [plainVetoedWeights] += theLastWeight ; theSumWeights2[plainVetoedWeights] += sqr(theLastWeight); theVetoed += 1; } /** * The overestimated cross section. */ CrossSection maxXSec() const { return theMaxXSec; } /** * The sum of the weights so far. */ double sumWeights() const { return theSumWeights[reweightedWeights] - theSumWeights[reweightedVetoedWeights]; } /** * The sum of the squared weights so far. */ double sumWeights2() const { return theSumWeights2[reweightedWeights] + theSumWeights2[reweightedVetoedWeights]; } /** * The sum of the weights so far, excluding reweighting. */ double sumWeightsNoReweight() const { return theSumWeights[plainWeights] - theSumWeights[plainVetoedWeights]; } /** * The sum of the squared weights so far, excluding reweighting. */ double sumWeights2NoReweight() const { return theSumWeights2[plainWeights] + theSumWeights2[plainVetoedWeights]; } /** * The current estimate of the cross section for the corresponding * class of events. If no events have been generated, maxXSec() will * be returned. */ CrossSection xSec(double att = 0) const { double n = (att == 0.0 ? attempts() : att); return n ? maxXSec()*sumWeights()/n : maxXSec(); } /** * The current estimate of the error in the cross section for the * corresponding class of events. If no events have been generated, * maxXSec() will be returned. */ CrossSection xSecErr(double att = 0) const { double n = (att == 0.0 ? attempts() : att); if ( n < 2 ) return maxXSec(); double sw = sumWeights(); double sw2 = sumWeights2(); return maxXSec()*sqrt(abs(sw2/n-sqr(sw/n))/(n-1)); } /** * The current estimate of the cross section for the corresponding * class of events, excluding reweighting. If no events have been * generated, maxXSec() will be returned. */ CrossSection xSecNoReweight(double att = 0) const { double n = (att == 0.0 ? attempts() : att); return n ? maxXSec()*sumWeightsNoReweight()/n : maxXSec(); } /** * The current estimate of the error in the cross section for the * corresponding class of events, excluding reweighting. If no * events have been generated, maxXSec() will be returned. */ CrossSection xSecErrNoReweight(double att = 0) const { double n = (att == 0.0 ? attempts() : att); if ( n < 2 ) return maxXSec(); double sw = sumWeightsNoReweight(); double sw2 = sumWeights2NoReweight(); return maxXSec()*sqrt(abs(sw2/n-sqr(sw/n))/(n-1)); } /** * Number of attempts so far. */ double attempts() const { return theAttempts; } /** * Number of accepts so far. */ double accepted() const { return theAccepted-theVetoed; } /** * Number of vetoes so far. */ double vetoed() const { return theVetoed; } /** * Set the overestimated cross section. */ void maxXSec(CrossSection x) { theMaxXSec = x; } //@} public: /** @name I/O functions */ //@{ /** * Output to a persistent stream. */ void output(PersistentOStream & os) const; /** * Input from a persistent stream. */ void input(PersistentIStream & is); //@} private: /** * The overestimated cross section. */ CrossSection theMaxXSec; /** * Number of attempts so far. */ double theAttempts; /** * Number of accepted events so far. */ double theAccepted; /** * Number of events vetoed after being accepted */ double theVetoed; /** * The sum of the weights so far. */ array theSumWeights; /** * The sum of the squared weights so far. */ array theSumWeights2; /** * The last selected weight, ignoring reweighting. */ double theLastWeight; }; /** Ouptut an XSecStat to a persistent stream. */ PersistentOStream & operator<<(PersistentOStream &, const XSecStat &); /** Input an XSecStat from a persistent stream. */ PersistentIStream & operator>>(PersistentIStream &, XSecStat &); /** Add the contents of two XSecStat objects. */ inline XSecStat operator+(const XSecStat & x1, const XSecStat & x2) { XSecStat x = x1; return x += x2; } } #endif /* THEPEG_XSecStat_H */ diff --git a/Vectors/HepMCConverter.h b/Vectors/HepMCConverter.h --- a/Vectors/HepMCConverter.h +++ b/Vectors/HepMCConverter.h @@ -1,226 +1,226 @@ // -*- C++ -*- // // HepMCConverter.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_HepMCConverter_H #define ThePEG_HepMCConverter_H // This is the declaration of the HepMCConverter class. #include "ThePEG/Config/ThePEG.h" #include "ThePEG/EventRecord/Event.h" #include "HepMCTraits.h" namespace ThePEG { /** * The HepMCConverter defines only one public static function which * converts a ThePEG::Event object to a * HepMC::GenEvent. All mother-daughter relationships and * colour information is preserved. * * @see Event * @see Particle * * @author Leif Lönnblad */ template > class HepMCConverter { public: /** @cond EXCEPTIONCLASSES */ /** Exception class for HepMCConverter. */ struct HepMCConverterException: public Exception {}; /** @endcond */ /** * Help class to represent a temporary vertex which can be * converted to a GenVertex. */ struct Vertex { /** Particles going in to the vertex. */ tcParticleSet in; /** Particles going out of the vertex. */ tcParticleSet out; }; /** Forward typedefs from Traits class. */ typedef typename Traits::ParticleT GenParticle; /** Forward typedefs from Traits class. */ typedef typename Traits::ParticlePtrT GenParticlePtrT; /** Forward typedefs from Traits class. */ typedef typename Traits::EventT GenEvent; /** Forward typedefs from Traits class. */ typedef typename Traits::VertexT GenVertex; /** Forward typedefs from Traits class. */ typedef typename Traits::VertexPtrT GenVertexPtrT; /** Forward typedefs from Traits class. */ typedef typename Traits::PdfInfoT PdfInfo; /** Map ThePEG particles to HepMC particles. */ typedef map ParticleMap; /** Map ThePEG colour lines to HepMC colour indices. */ typedef map FlowMap; /** Map ThePEG particles to vertices. */ typedef map VertexMap; /** Map vertices to GenVertex */ typedef map GenVertexMap; public: /** * Convert a ThePEG::Event to a HepMC::GenEvent. The caller is * responsible for deleting the constructed GenEvent object. If \a * nocopies is true, only final copies of particles connected with * Particle::previous() and Particle::next() will be entered in the * HepMC::GenEvent. In the GenEvent object, the energy/momentum * variables will be in units of \a eunit and lengths variables in * units of \a lunit. */ static GenEvent * convert(const Event & ev, bool nocopies = false, Energy eunit = Traits::defaultEnergyUnit(), Length lunit = Traits::defaultLengthUnit()); /** * Convert a ThePEG::Event to a HepMC::GenEvent. The caller supplies * a GenEvent object, \a gev, which will be filled. If \a nocopies * is true, only final copies of particles connected with * Particle::previous() and Particle::next() will be entered in the * HepMC::GenEvent. In the GenEvent object, the energy/momentum * variables will be in units of \a eunit and lengths variables in * units of \a lunit. */ static void convert(const Event & ev, GenEvent & gev, bool nocopies, Energy eunit, Length lunit); /** * Convert a ThePEG::Event to a HepMC::GenEvent. The caller supplies * a GenEvent object, \a gev, which will be filled. If \a nocopies * is true, only final copies of particles connected with * Particle::previous() and Particle::next() will be entered in the * HepMC::GenEvent. In the GenEvent object, the energy/momentum * variables will be in units of \a eunit and lengths variables in * units of \a lunit. */ static void convert(const Event & ev, GenEvent & gev, bool nocopies = false); private: /** * The proper constructors are private. The class is only * instantiated within the convert method. */ HepMCConverter(const Event & ev, bool nocopies, Energy eunit, Length lunit); /** * The proper constructors are private. The class is only * instantiated within the convert method. */ HepMCConverter(const Event & ev, GenEvent & gev, bool nocopies, Energy eunit, Length lunit); /** * Common init function used by the constructors. */ void init(const Event & ev, bool nocopies); /** * Default constructor is unimplemented and private and should never be used. */ HepMCConverter(); /** * Copy constructor is unimplemented and private and should never be used. */ HepMCConverter(const HepMCConverter &); /** * Assignment is unimplemented and private and should never be used. */ HepMCConverter & operator=(const HepMCConverter &) = delete; private: /** * Create a GenParticle from a ThePEG Particle. */ GenParticlePtrT createParticle(tcPPtr p) const; /** * Join the decay vertex of the parent with the decay vertex of the * child. */ void join(tcPPtr parent, tcPPtr child); /** * Create a GenVertex from a temporary Vertex. */ GenVertexPtrT createVertex(Vertex * v); /** * Create and set a PdfInfo object for the event */ void setPdfInfo(const Event & e); private: /** * The constructed GenEvent. */ GenEvent * geneve; /** * The translation table between the ThePEG particles and the * GenParticles. */ ParticleMap pmap; /** * The translation table between ThePEG ColourLine objects and HepMC * Flow indices. */ FlowMap flowmap; /** * All temporary vertices created. */ vector vertices; /** * The mapping of particles to their production vertices. */ VertexMap prov; /** * The mapping of particles to their decy vertices. */ VertexMap decv; /** * The mapping between temporary vertices and the created GenVertex Objects. */ GenVertexMap vmap; /** * The energy unit to be used in the GenEvent. */ Energy energyUnit; /** * The length unit to be used in the GenEvent. */ Length lengthUnit; }; } #include "HepMCConverter.tcc" #endif /* ThePEG_HepMCConverter_H */ diff --git a/Vectors/HepMCConverter.tcc b/Vectors/HepMCConverter.tcc --- a/Vectors/HepMCConverter.tcc +++ b/Vectors/HepMCConverter.tcc @@ -1,337 +1,337 @@ // -*- C++ -*- // // HepMCConverter.tcc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the HepMCConverter class. // #include "ThePEG/StandardModel/StandardModelBase.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/EventRecord/StandardSelectors.h" #include "ThePEG/EventRecord/Collision.h" #include "ThePEG/EventRecord/Step.h" #include "ThePEG/EventRecord/SubProcess.h" #include "ThePEG/Handlers/XComb.h" #include "ThePEG/Handlers/EventHandler.h" #include "ThePEG/PDF/PartonExtractor.h" #include "ThePEG/PDF/PDF.h" #include "ThePEG/PDT/StandardMatchers.h" #include "ThePEG/Utilities/Throw.h" namespace ThePEG { template typename HepMCConverter::GenEvent * HepMCConverter:: convert(const Event & ev, bool nocopies, Energy eunit, Length lunit) { HepMCConverter converter(ev, nocopies, eunit, lunit); return converter.geneve; } template void HepMCConverter:: convert(const Event & ev, GenEvent & gev, bool nocopies) { HepMCConverter converter(ev, gev, nocopies, Traits::momentumUnit(gev), Traits::lengthUnit(gev)); } template void HepMCConverter:: convert(const Event & ev, GenEvent & gev, bool nocopies, Energy eunit, Length lunit) { HepMCConverter converter(ev, gev, nocopies, eunit, lunit); } template HepMCConverter:: HepMCConverter(const Event & ev, bool nocopies, Energy eunit, Length lunit) : energyUnit(eunit), lengthUnit(lunit) { geneve = Traits::newEvent(ev.number(), ev.weight(), ev.optionalWeights()); init(ev, nocopies); } template HepMCConverter:: HepMCConverter(const Event & ev, GenEvent & gev, bool nocopies, Energy eunit, Length lunit) : energyUnit(eunit), lengthUnit(lunit) { geneve = &gev; Traits::resetEvent(geneve, ev.number(), ev.weight(), ev.optionalWeights()); init(ev, nocopies); } struct ParticleOrderNumberCmp { bool operator()(tcPPtr a, tcPPtr b) const { return a->number() < b->number(); } }; template void HepMCConverter::init(const Event & ev, bool nocopies) { if ( lengthUnit != millimeter && lengthUnit != centimeter ) Throw() << "Length unit used for HepMC::GenEvent was not MM nor CM." << Exception::runerror; if ( energyUnit != GeV && energyUnit != MeV ) Throw() << "Momentum unit used for HepMC::GenEvent was not GEV nor MEV." << Exception::runerror; Traits::setUnits(*geneve, energyUnit, lengthUnit); tcEHPtr eh; if ( ev.primaryCollision() && ( eh = dynamic_ptr_cast(ev.primaryCollision()->handler()) ) ) { // Get general event info if present. Traits::setScaleAndAlphas(*geneve, eh->lastScale(), eh->lastAlphaS(),eh->lastAlphaEM(), energyUnit); } // Extract all particles and order them. tcPVector all; ev.select(back_inserter(all), SelectAll()); stable_sort(all.begin(), all.end(), ParticleOrderNumberCmp()); vertices.reserve(all.size()*2); // Create GenParticle's and map them to the ThePEG particles. for ( int i = 0, N = all.size(); i < N; ++i ) { tcPPtr p = all[i]; if ( nocopies && p->next() ) continue; if ( pmap.find(p) != pmap.end() ) continue; pmap[p] = createParticle(p); if ( !p->children().empty() || p->next() ) { // If the particle has children it should have a decay vertex: vertices.push_back(Vertex()); decv[p] = &vertices.back(); vertices.back().in.insert(p); } if ( !p->parents().empty() || p->previous() || (p->children().empty() && !p->next()) ) { // If the particle has parents it should have a production // vertex. If neither parents or children it should still have a // dummy production vertex. vertices.push_back(Vertex()); prov[p] = &vertices.back(); vertices.back().out.insert(p); } } // Now go through the the particles again, and join the vertices. for ( int i = 0, N = all.size(); i < N; ++i ) { tcPPtr p = all[i]; if ( nocopies ) { if ( p->next() ) continue; for ( int i = 0, N = p->children().size(); i < N; ++i ) join(p, p->children()[i]->final()); tcPPtr pp = p; while ( pp->parents().empty() && pp->previous() ) pp = pp->previous(); for ( int i = 0, N = pp->parents().size(); i < N; ++i ) join(pp->parents()[i]->final(), p); } else { for ( int i = 0, N = p->children().size(); i < N; ++i ) join(p, p->children()[i]); if ( p->next() ) join(p, p->next()); for ( int i = 0, N = p->parents().size(); i < N; ++i ) join(p->parents()[i], p); if ( p->previous() ) join(p->previous(), p); } } // Time to create the GenVertex's for ( typename VertexMap::iterator it = prov.begin(); it != prov.end(); ++it ) if ( !member(vmap, it->second) ) vmap[it->second] = createVertex(it->second); for ( typename VertexMap::iterator it = decv.begin(); it != decv.end(); ++it ) if ( !member(vmap, it->second) ) vmap[it->second] = createVertex(it->second); // Now find the primary signal process vertex defined to be the // decay vertex of the first parton coming into the primary hard // sub-collision. tSubProPtr sub = ev.primarySubProcess(); if ( sub && sub->incoming().first ) { const Vertex * prim = decv[sub->incoming().first]; Traits::setSignalProcessVertex(*geneve, vmap[prim]); vmap.erase(prim); } // Then add the rest of the vertices. for ( typename GenVertexMap::iterator it = vmap.begin(); it != vmap.end(); ++it ) Traits::addVertex(*geneve, it->second); // and the incoming beam particles Traits::setBeamParticles(*geneve,pmap[ev.incoming().first], pmap[ev.incoming().second]); // and the PDF info setPdfInfo(ev); // and the cross section info Traits::setCrossSection(*geneve, eh->integratedXSec()/picobarn, eh->integratedXSecErr()/picobarn); for ( int i = 0, N = all.size(); i < N; ++i ) { tcPPtr p = all[i]; if ( pmap.find(p) == pmap.end() ) continue; GenParticlePtrT gp = pmap[p]; if ( p->hasColourInfo() ) { // Check if the particle is connected to colour lines, in which // case the lines are mapped to an integer and set in the // GenParticle's Flow info. tcColinePtr l; if ( (l = p->colourLine()) ) { if ( !member(flowmap, l) ) flowmap[l] = flowmap.size() + 500; Traits::setColourLine(*gp, 1, flowmap[l]); } if ( (l = p->antiColourLine()) ) { if ( !member(flowmap, l) ) flowmap[l] = flowmap.size() + 500; Traits::setColourLine(*gp, 2, flowmap[l]); } } if ( p->spinInfo() && p->spinInfo()->hasPolarization() ) { DPair pol = p->spinInfo()->polarization(); Traits::setPolarization(*gp, pol.first, pol.second); } } } template typename HepMCConverter::GenParticlePtrT HepMCConverter::createParticle(tcPPtr p) const { int status = 1; size_t nChildren = p->children().size(); if ( nChildren > 0 || p->next() ) status = 11; if ( nChildren > 1 ) { long id = p->data().id(); if ( BaryonMatcher::Check(id) || MesonMatcher::Check(id) || id == ParticleID::muminus || id == ParticleID::muplus || id == ParticleID::tauminus || id == ParticleID::tauplus ) { bool child = false; for(unsigned int ix=0;ixchildren()[ix]->id()==id) { child = true; break; } } if ( !child ) { if(p->data().widthCut()!=ZERO) { if(p->mass() <= p->data().massMax() && p->mass() >= p->data().massMin() ) status = 2; } else { status = 2; } } } } GenParticlePtrT gp = Traits::newParticle(p->momentum(), p->id(), p->status() ? p->status() : status, energyUnit); if ( p->spinInfo() && p->spinInfo()->hasPolarization() ) { DPair pol = p->spinInfo()->polarization(); Traits::setPolarization(*gp, pol.first, pol.second); } return gp; } template void HepMCConverter::join(tcPPtr parent, tcPPtr child) { Vertex * dec = decv[parent]; Vertex * pro = prov[child]; if ( !pro || !dec ) Throw() << "Found a reference to a ThePEG::Particle which was not in the Event." << Exception::eventerror; if ( pro == dec ) return; while ( !pro->in.empty() ) { dec->in.insert(*(pro->in.begin())); decv[*(pro->in.begin())] = dec; pro->in.erase(pro->in.begin()); } while ( !pro->out.empty() ) { dec->out.insert(*(pro->out.begin())); prov[*(pro->out.begin())] = dec; pro->out.erase(pro->out.begin()); } } template typename HepMCConverter::GenVertexPtrT HepMCConverter::createVertex(Vertex * v) { if ( !v ) Throw() << "Found internal null Vertex." << Exception::abortnow; GenVertexPtrT gv = Traits::newVertex(); // We assume that the vertex position is the average of the decay // vertices of all incoming and the creation vertices of all // outgoing particles in the lab. Note that this will probably not // be useful information for very small distances. LorentzPoint p; for ( tcParticleSet::iterator it = v->in.begin(); it != v->in.end(); ++it ) { p += (**it).labDecayVertex(); Traits::addIncoming(*gv, pmap[*it]); } for ( tcParticleSet::iterator it = v->out.begin(); it != v->out.end(); ++it ) { p += (**it).labVertex(); Traits::addOutgoing(*gv, pmap[*it]); } p /= double(v->in.size() + v->out.size()); Traits::setPosition(*gv, p, lengthUnit); return gv; } template void HepMCConverter::setPdfInfo(const Event & e) { // ids of the partons going into the primary sub process tSubProPtr sub = e.primarySubProcess(); int id1 = sub->incoming().first ->id(); int id2 = sub->incoming().second->id(); // get the event handler tcEHPtr eh = dynamic_ptr_cast(e.handler()); // get the values of x double x1 = eh->lastX1(); double x2 = eh->lastX2(); // get the pdfs pair pdfs; pdfs.first = eh->pdf(sub->incoming().first ); pdfs.second = eh->pdf(sub->incoming().second); // get the scale Energy2 scale = eh->lastScale(); // get the values of the pdfs double xf1 = pdfs.first.xfx(sub->incoming().first->dataPtr(), scale, x1); double xf2 = pdfs.second.xfx(sub->incoming().second->dataPtr(), scale, x2); Traits::setPdfInfo(*geneve, id1, id2, x1, x2, sqrt(scale/GeV2), xf1, xf2); } } diff --git a/Vectors/HepMCTraits.h b/Vectors/HepMCTraits.h --- a/Vectors/HepMCTraits.h +++ b/Vectors/HepMCTraits.h @@ -1,354 +1,354 @@ // -*- C++ -*- // // HepMCTraits.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_HepMCTraits_H #define ThePEG_HepMCTraits_H #ifdef HAVE_HEPMC3 #include "HepMC3/GenEvent.h" namespace HepMC3 { class GenEvent; class GenParticle; class GenVertex; class GenPdfInfo; } namespace HepMC3 { using PdfInfo=GenPdfInfo; using Polarization=std::pair; } namespace HepMC=HepMC3; #else #include "HepMC/GenEvent.h" namespace HepMC { class GenEvent; class GenParticle; class GenVertex; class Polarization; #ifndef HEPMC_GENPDFINFO_H class PdfInfo; #endif } #endif 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; /** Typedef of a particle pointer */ typedef HepMCParticlePtrT ParticlePtrT; /** Typedef of a vertex pointer */ typedef HepMCVertexPtrT VertexPtrT; /** 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); std::vector wnames; std::vector wvalues; wnames.push_back("Default"); wvalues.push_back(weight); for ( map::const_iterator w = optionalWeights.begin(); w != optionalWeights.end(); ++w ) { wnames.push_back(w->first); wvalues.push_back(w->second); } #ifdef HAVE_HEPMC3 e->run_info()->set_weight_names(wnames); e->weights()=wvalues; #else #ifdef HEPMC_HAS_NAMED_WEIGHTS for (size_t i=0;iweights()[wnames[i]] = wvalues[i]; #else e->weights()=wvalues; #endif #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(); std::vector wnames; std::vector wvalues; wnames.push_back("Default"); wvalues.push_back(weight); for ( map::const_iterator w = optionalWeights.begin(); w != optionalWeights.end(); ++w ) { wnames.push_back(w->first); wvalues.push_back(w->second); } #ifdef HAVE_HEPMC3 e->run_info()->set_weight_names(wnames); e->weights()=wvalues; #else #ifdef HEPMC_HAS_NAMED_WEIGHTS for (size_t i=0;iweights()[wnames[i]] = wvalues[i]; #else e->weights()=wvalues; #endif #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, VertexPtrT v) { e.set_signal_process_vertex(v); } /** Set a vertex, \a v, for the event \a e. */ static void addVertex(EventT & e, VertexPtrT 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 ParticlePtrT 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; ParticlePtrT 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 VertexPtrT newVertex() { return new VertexT(); } /** Add an incoming particle, \a p, to the vertex, \a v. */ static void addIncoming(VertexT & v, ParticlePtrT p) { v.add_particle_in(p); } /** Add an outgoing particle, \a p, to the vertex, \a v. */ static void addOutgoing(VertexT & v, ParticlePtrT 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, ParticlePtrT p1, ParticlePtrT 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) { #ifdef HAVE_HEPMC3 HepMC::GenPdfInfoPtr pdfinfo = std::make_shared(); pdfinfo->set(id1, id2, x1, x2, scale, xf1, xf2); e.set_pdf_info(pdfinfo); #else e.set_pdf_info(PdfInfoT(id1, id2, x1, x2, scale, xf1, xf2)); #endif } #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) { #ifdef HAVE_HEPMC3 std::shared_ptr x =std::make_shared(); x->set_cross_section(xs,xserr); ev.set_cross_section(x); #else HepMC::GenCrossSection x; x.set_cross_section(xs, xserr); ev.set_cross_section(x); #endif } #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/Vectors/Lorentz5Vector.h b/Vectors/Lorentz5Vector.h --- a/Vectors/Lorentz5Vector.h +++ b/Vectors/Lorentz5Vector.h @@ -1,325 +1,325 @@ // -*- C++ -*- // // Lorentz5Vector.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_Lorentz5Vector_H #define ThePEG_Lorentz5Vector_H // This is the declaration of the Lorentz5vector class. #include "LorentzVector.h" #include "Lorentz5Vector.fh" #include "ThePEG/Utilities/Maths.h" #include "ThePEG/Utilities/Direction.h" #include "ThePEG/Utilities/UnitIO.h" #include "LorentzRotation.h" namespace ThePEG { template /** * The Lorentz5Vector inherits from the * LorentzVector class. It is templated on the * type of the member variables. The Lorentz5Vector class is a * LorentzVector with an extra member for the invariant * length/mass of the vector. Note that an object of the * Lorentz5Vector class may be internally inconsistent in * that the invariant length/mass of the LorentzVector * class need not be the same as the member variable representing the * invariant length/mass. The degree of inconsistency can be accessed * with the massError(), energyError() and * rhoError() methods and an object can be made consistent * using the rescaleMass(), rescaleEnergy() or * rescaleRho() methods. * * @see Math * */ class Lorentz5Vector: public LorentzVector { public: /** Template argument typedef. */ using Value2 = decltype(sqr(std::declval())); public: /// Component access. //@{ Value x() const { return LorentzVector::x(); } Value y() const { return LorentzVector::y(); } Value z() const { return LorentzVector::z(); } Value t() const { return LorentzVector::t(); } //@} public: /** @name Constructors and destructor. */ //@{ /** * Constructor giving the null vector. */ Lorentz5Vector() : mm() {} /** * Constructor giving the invariant length. */ Lorentz5Vector(Value m) : LorentzVector(Value(), Value(), Value(), m), mm(m) {} /** * Constructor giving the components x, y, z, t. The invariant * length is set to LorentzVector::mag(). */ Lorentz5Vector(Value x, Value y, Value z, Value t = Value()) : LorentzVector(x, y, z, t) { rescaleMass(); } /** * Constructor giving the components x, y, z, t and invariant length. * May result in an inconsistent Lorentz5Vector. */ Lorentz5Vector(Value x, Value y, Value z, Value t, Value tau) : LorentzVector(x, y, z, t), mm(tau) {} /** * Constructor giving a 3-Vector and a time component. The invariant * length is set to LorentzVector::mag(). */ Lorentz5Vector(const ThreeVector & p, Value e) : LorentzVector(p, e) { rescaleMass(); } /** * Constructor giving an invariant length and a 3-Vector * component. The time component is set to the corresponding value. */ Lorentz5Vector(Value m, const ThreeVector & p) : LorentzVector(p, sqrt(p.mag2() + m*m)), mm(m) {} /** * Constructor giving a 3-Vector, a time component and an invariant * length. May result in an inconsistent Lorentz5Vector. */ Lorentz5Vector(const ThreeVector & p, Value t, Value tau) : LorentzVector(p, t), mm(tau) {} /** * Constructor giving a LorentzVector and an invariant length. * May result in an inconsistent Lorentz5Vector. */ Lorentz5Vector(const LorentzVector & p, Value m) : LorentzVector(p), mm(m) {} /** * Copy from HepLorentzVector constructor. The invariant * length is set to LorentzVector::mag(). */ Lorentz5Vector(const LorentzVector & p) : LorentzVector(p) { rescaleMass(); } /** * Construct from value type U convertible to Value. */ template Lorentz5Vector(const Lorentz5Vector & p) : LorentzVector(p), mm(p.m) {} //@} /** @name Assignment and set functions. */ //@{ /** * Set invariant length/mass. */ void setTau(Value a) { mm = a; } /** * Set invariant length/mass. */ void setMass(Value a) { mm = a; } /** * Assignment. The invariant length is kept fixed. May result in an * inconsistent Lorentz5Vector. */ Lorentz5Vector & operator=(const LorentzVector & q) { LorentzVector::operator=(q); return *this; } //@} /** @name Rescale functions to make consistent. */ //@{ /** * Rescale energy, so that the invariant length/mass of the * LorentzVector agrees with the current one. */ void rescaleEnergy() { LorentzVector::setT(sqrt(LorentzVector::vect().mag2() + mass2())); } /** * Rescale spatial component, so that the invariant length/mass of * the LorentzVector agrees with the current one. */ void rescaleRho() { LorentzVector::setRho(sqrt(t()*t() - mass2())); } /** * Set the invariant length/mass member, so that it agrees with the * invariant length/mass of the LorentzVector. */ void rescaleMass() { mm = LorentzVector::m(); } //@} /** @name Check consistency. */ //@{ /** * Return the relative inconsistency in the mass component. */ double massError() const { return sqrt(abs(Math::relativeError(mass2(), LorentzVector::m2()))); } /** * Return the relative inconsistency in the energy component. */ double energyError() const { return sqrt(abs(Math::relativeError(t()*t(), mass2() + LorentzVector::vect().mag2()))); } /** * Return the relative inconsistency in the spatial components. */ double rhoError() const { return sqrt(abs(Math::relativeError(LorentzVector::vect().mag2(), t()*t() - mass2()))); } //@} /** @name Access components. */ //@{ /** * Mass/invariant length component squared. m2() gives * the same calculated from the LorentzVector */ Value2 mass2() const { return mm > Value() ? mm*mm: -mm*mm; } /** * Mass/invariant length component squared. m2() gives * the same calculated from the LorentzVector */ Value2 tau2() const { return mass2(); } /** * Mass/invariant length component. m() gives the same * calculated from the LorentzVector */ Value mass() const { return mm; } /** * Mass/invariant length component. m() gives the same * calculated from the LorentzVector */ Value tau() const { return mass(); } /** * Return the positive negative light-cone components (depending on * the value of Direction<0>. */ Value dirPlus() const { return Direction<0>::pos() ? LorentzVector::plus() : LorentzVector::minus(); } /** * Return the positive negative light-cone components (depending on * the value of Direction<0>. */ Value dirMinus() const { return Direction<0>::neg() ? LorentzVector::plus() : LorentzVector::minus(); } //@} /** * Perform a Lorentz transformation */ Lorentz5Vector & transform(const LorentzRotation & r) { LorentzVector::transform(r.one()); return *this; } private: /** The invariant mass/length member. */ Value mm; }; /** Output a Lorentz5Vector to a stream. */ template void ounitstream(OStream & os, const Lorentz5Vector & p, UT & u) { os << ounit(p.x(), u) << ounit(p.y(), u) << ounit(p.z(), u) << ounit(p.e(), u) << ounit(p.mass(), u); } /** Input a Lorentz5Vector from a stream. */ template void iunitstream(IStream & is, Lorentz5Vector & p, UT & u) { T x, y, z, e, mass; is >> iunit(x, u) >> iunit(y, u) >> iunit(z, u) >> iunit(e, u) >> iunit(mass, u); p = Lorentz5Vector(x, y, z, e, mass); } /// @name Dot product overloads. //@{ template inline auto operator*(const Lorentz5Vector & a, const Lorentz5Vector & b) -> decltype(a.dot(b)) { return a.dot(b); } template inline auto operator*(const LorentzVector & a, const Lorentz5Vector & b) -> decltype(a.dot(b)) { return a.dot(b); } template inline auto operator*(const Lorentz5Vector & a, const LorentzVector & b) -> decltype(a.dot(b)) { return a.dot(b); } template inline auto operator*(const Lorentz5Vector & a, const Lorentz5Vector & b) -> decltype(a.dot(b)) { return a.dot(b); } //@} } #endif /* ThePEG_Particle_H */ diff --git a/Vectors/LorentzRotation.cc b/Vectors/LorentzRotation.cc --- a/Vectors/LorentzRotation.cc +++ b/Vectors/LorentzRotation.cc @@ -1,24 +1,24 @@ // -*- C++ -*- // // LorentzRotation.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the LorentzRotation class. // #include "LorentzRotation.h" using namespace ThePEG; // output operator std::ostream & LorentzRotation::print( std::ostream & os ) const { os << "Spin 1 Transform: \n " << _one << "\n Spin 1/2 Transform: \n " << _half << "\n"; return os; } diff --git a/Vectors/LorentzRotation.h b/Vectors/LorentzRotation.h --- a/Vectors/LorentzRotation.h +++ b/Vectors/LorentzRotation.h @@ -1,544 +1,544 @@ // -*- C++ -*- // // LorentzRotation.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_LorentzRotation_H #define THEPEG_LorentzRotation_H // // This is the declaration of the LorentzRotation class. // #include "SpinOneLorentzRotation.h" #include "SpinHalfLorentzRotation.h" #include "LorentzRotation.fh" namespace ThePEG { /** * The LorentzRotation class combine a SpinOneLorentzRotation and a * spin SpinHalfLorentzRotation to provide members which can perform the * Lorentz transformation of any object. The class ensures that the * two transformations are consistent by only allowing transformations * to be made to both the spin-1 and spin-\f$\frac12\f$ members. */ class LorentzRotation { /** * The external inverseOf needs to be a friend */ friend LorentzRotation inverseOf ( const LorentzRotation & lt ); public: /** @name Constructors and destructor. */ //@{ /** * Default constructor. Gives a unit matrix. */ LorentzRotation() : _half(), _one() {} /** * Constructor giving the components of a Lorentz boost. * @param bx The x-component of the boost * @param by The y-component of the boost * @param bz The z-component of the boost * @param gamma The \f$\gamma\f$ factor (optional) */ LorentzRotation (double bx, double by, double bz, double gamma=-1.) : _half(bx,by,bz,gamma), _one(bx,by,bz,gamma) {} /** * Constructor giving the vector for a Lorentz boost. * @param b The boost vector * @param gamma The \f$\gamma\f$ factor (optional) */ LorentzRotation (const Boost & b, double gamma=-1.) : _half(b,gamma), _one(b,gamma) {} //@} /** * Returns true if the Identity matrix. */ bool isIdentity() const { return _half.isIdentity() && _one.isIdentity(); } /** * Return the inverse. */ LorentzRotation inverse() const { LorentzRotation output; output._half = _half.inverse(); output._one = _one.inverse(); return output; } /** * Inverts the LorentzRotation matrix. */ LorentzRotation & invert() { return *this=inverse(); } /** * output operator */ std::ostream & print( std::ostream & os ) const; /** @name Set methods for speical cases of simple rotations and boosts */ //@{ /** * Specify the components of a Lorentz Boost * @param bx The x-component of the boost * @param by The y-component of the boost * @param bz The z-component of the boost * @param gamma The \f$\gamma\f$ factor (optional) */ LorentzRotation & setBoost (double bx, double by, double bz, double gamma=-1.) { _half.setBoost(bx,by,bz,gamma); _one.setBoost(bx,by,bz,gamma); return *this; } /** * Specify a Lorentz Boost as a vector * @param b The boost vector * @param gamma The \f$\gamma\f$ factor (optional) */ LorentzRotation & setBoost (const Boost & b, double gamma=-1.) { _half.setBoost(b,gamma); _one.setBoost(b,gamma); return *this; } /** * Specify a boost by the given factor along the x-axis * @param boost The Lorentz boost */ LorentzRotation & setBoostX (double boost) { _half.setBoostX(boost); _one.setBoost(boost,0,0); return *this; } /** * Specify a boost by the given factor along the y-axis * @param boost The Lorentz boost */ LorentzRotation & setBoostY (double boost) { _half.setBoostY(boost); _one.setBoost(0,boost,0); return *this; } /** * Specify a boost by the given factor along the z-axis * @param boost The Lorentz boost */ LorentzRotation & setBoostZ (double boost) { _half.setBoostZ(boost); _one.setBoost(0,0,boost); return *this; } /** * Specify a rotation about a general axis by the angle given. * @param delta The angle * @param axis The axis */ LorentzRotation & setRotate(double delta, const Axis & axis) { _half.setRotate(delta,axis); _one.setRotate(delta,axis); return *this; } /** * Specify a rotation by the given angle about the x-axis * @param angle The rotation angle */ LorentzRotation & setRotateX (double angle) { _half.setRotateX(angle); _one.setRotateX(angle); return *this; } /** * Specify a rotation by the given angle about the y-axis * @param angle The rotation angle */ LorentzRotation & setRotateY (double angle) { _half.setRotateZ(angle); _one.setRotateZ(angle); return *this; } /** * Specify a rotation by the given angle about the z-axis * @param angle The rotation angle */ LorentzRotation & setRotateZ (double angle) { _half.setRotateZ(angle); _one.setRotateZ(angle); return *this; } //@} /** @name Methods to return the spin-\f$\frac12\f$ and spin-1 transformations */ //@{ /** * The spin-\f$\frac12\f$ transformation */ const SpinHalfLorentzRotation & half() const { return _half; } /** * The spin-1 transformation */ const SpinOneLorentzRotation & one() const { return _one; } /** * Automatically cast to the spin-1 transformation */ operator const SpinOneLorentzRotation & () const { return _one; } //@} /** @name Access methods for the components of the spin-1 rotation */ //@{ /** * The xx component */ double xx() const { return _one.xx(); } /** * The xy component */ double xy() const { return _one.xy(); } /** * The xz component */ double xz() const { return _one.xz(); } /** * The xt component */ double xt() const { return _one.xt(); } /** * The yx component */ double yx() const { return _one.yx(); } /** * The yy component */ double yy() const { return _one.yy(); } /** * The yz component */ double yz() const { return _one.yz(); } /** * The yt component */ double yt() const { return _one.yt(); } /** * The zx component */ double zx() const { return _one.zx(); } /** * The zy component */ double zy() const { return _one.zy(); } /** * The zz component */ double zz() const { return _one.zz(); } /** * The zt component */ double zt() const { return _one.zt(); } /** * The tx component */ double tx() const { return _one.tx(); } /** * The ty component */ double ty() const { return _one.ty(); } /** * The tz component */ double tz() const { return _one.tz(); } /** * The tt component */ double tt() const { return _one.tt(); } //@} /** @name Access methods for the components of the spin-\f$\frac12\f$ rotation */ //@{ /** * The \f$(1,1)\f$ component */ Complex s1s1() const { return _half.s1s1(); } /** * The \f$(1,2)\f$ component */ Complex s1s2() const { return _half.s1s2(); } /** * The \f$(1,3)\f$ component */ Complex s1s3() const { return _half.s1s3(); } /** * The \f$(1,4)\f$ component */ Complex s1s4() const { return _half.s1s4(); } /** * The \f$(1,1)\f$ component */ Complex s2s1() const { return _half.s2s1(); } /** * The \f$(1,1)\f$ component */ Complex s2s2() const { return _half.s2s2(); } /** * The \f$(1,1)\f$ component */ Complex s2s3() const { return _half.s2s3(); } /** * The \f$(1,1)\f$ component */ Complex s2s4() const { return _half.s2s4(); } /** * The \f$(1,1)\f$ component */ Complex s3s1() const { return _half.s3s1(); } /** * The \f$(1,1)\f$ component */ Complex s3s2() const { return _half.s3s2(); } /** * The \f$(1,1)\f$ component */ Complex s3s3() const { return _half.s3s3(); } /** * The \f$(1,1)\f$ component */ Complex s3s4() const { return _half.s3s4(); } /** * The \f$(1,1)\f$ component */ Complex s4s1() const { return _half.s4s1(); } /** * The \f$(1,1)\f$ component */ Complex s4s2() const { return _half.s4s2(); } /** * The \f$(1,1)\f$ component */ Complex s4s3() const { return _half.s4s3(); } /** * The \f$(1,1)\f$ component */ Complex s4s4() const { return _half.s4s4(); } //@} /** @name Transformation and product members */ //@{ /** * Product with a LorentzVector simply returns the rotated vector. */ template LorentzVector operator*(const LorentzVector & lv) const { return one()*lv; } /** * Product with a Lorentz5Vector simply returns the rotated vector. */ template Lorentz5Vector operator*(const Lorentz5Vector & lv) const { return one()*lv; } /** * Product of two LorentzRotations (this) * lt - matrix multiplication * @param lt The LorentzRotation we are multiplying */ LorentzRotation operator * (const LorentzRotation & lt) const { LorentzRotation output; output._half = _half * lt._half; output._one = _one * lt._one; return output; } /** * Multiply by and assign a*=b becomes a= a*b */ LorentzRotation & operator *= (const LorentzRotation & lt) { _one *=lt._one; _half*=lt._half; return *this; } /** * Transform (similar to *= but a.transform(b) becomes a = b*a */ LorentzRotation & transform(const LorentzRotation & lt) { _half.transform(lt._half); _one.transform(lt._one); return *this; } /** * Rotation around the x-axis; equivalent to LT = RotationX(delta) * LT */ LorentzRotation & rotateX(double delta) { _half.rotateX(delta); _one.rotateX(delta); return *this; } /** * Rotation around the y-axis; equivalent to LT = RotationY(delta) * LT */ LorentzRotation & rotateY(double delta) { _half.rotateY(delta); _one.rotateY(delta); return *this; } /** * Rotation around the z-axis; equivalent to LT = RotationZ(delta) * LT */ LorentzRotation & rotateZ(double delta) { _half.rotateZ(delta); _one.rotateZ(delta); return *this; } /** * Rotation around specified vector - LT = Rotation(delta,axis)*LT */ LorentzRotation & rotate(double delta, const Axis & axis) { _half.rotate(delta,axis); _one.rotate(delta,axis); return *this; } /** * Pure boost along the x-axis; equivalent to LT = BoostX(beta) * LT */ LorentzRotation & boostX(double beta) { _half.boostX(beta); _one.boostX(beta); return *this; } /** * Pure boost along the y-axis; equivalent to LT = BoostX(beta) * LT */ LorentzRotation & boostY(double beta) { _half.boostY(beta); _one.boostY(beta); return *this; } /** * Pure boost along the z-axis; equivalent to LT = BoostX(beta) * LT */ LorentzRotation & boostZ(double beta) { _half.boostZ(beta); _one.boostZ(beta); return *this; } /** * boost equivalent to LT = Boost(bx,by,bz) * LT * @param bx The x-component of the boost * @param by The y-component of the boost * @param bz The z-component of the boost * @param gamma The \f$\gamma\f$ factor (optional) */ LorentzRotation & boost(double bx, double by, double bz, double gamma=-1.) { _half.boost(bx,by,bz,gamma); _one.boost(bx,by,bz,gamma); return *this; } /** * boost equivalent to LT = Boost(bv) * LT * @param bv The boost * @param gamma The \f$\gamma\f$ factor (optional) */ LorentzRotation & boost(const Boost & bv, double gamma=-1.) { _half.boost(bv,gamma); _one.boost(bv,gamma); return *this; } //@} private: /** * The spin-\f$\frac12\f$ rotation */ SpinHalfLorentzRotation _half; /** * The spin-1 rotation */ SpinOneLorentzRotation _one; }; /** * Global method to get the inverse */ inline LorentzRotation inverseOf ( const LorentzRotation & lt ) { return lt.inverse(); } /** * output operator */ inline std::ostream & operator<< ( std::ostream & os, const LorentzRotation& lt ) { return lt.print(os); } } #endif /* THEPEG_LorentzRotation_H */ diff --git a/Vectors/LorentzVector.h b/Vectors/LorentzVector.h --- a/Vectors/LorentzVector.h +++ b/Vectors/LorentzVector.h @@ -1,765 +1,765 @@ // -*- C++ -*- // // LorentzVector.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2006-2017 David Grellscheid, Leif Lonnblad +// Copyright (C) 2006-2019 David Grellscheid, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_LorentzVector_H #define ThePEG_LorentzVector_H /** * @file LorentzVector.h contains the LorentzVector class. Lorentz * vectors can be created with any unit type as template parameter. * All basic mathematical operations are supported, as well as a * subset of the CLHEP LorentzVector functionality. */ #include "LorentzVector.fh" #include "ThePEG/Utilities/Direction.h" #include "ThePEG/Utilities/UnitIO.h" #include "LorentzRotation.h" #include "ThreeVector.h" /// Debug helper function #ifdef NDEBUG #define ERROR_IF(condition,message) if (false) {} #else #define ERROR_IF(condition,message) \ if ( condition ) throw ThePEG::Exception( (message) , ThePEG::Exception::eventerror) #endif namespace ThePEG { template class LorentzVector; /** * A 4-component Lorentz vector. It can be created with any unit type * as template parameter. All basic mathematical operations are * supported, as well as a subset of the CLHEP LorentzVector * functionality. */ template class LorentzVector { private: /// Value squared using Value2 = decltype(sqr(std::declval())); public: /** @name Constructors. */ //@{ LorentzVector() : theX(), theY(), theZ(), theT() {} LorentzVector(Value x, Value y, Value z, Value t) : theX(x), theY(y), theZ(z), theT(t) {} LorentzVector(const ThreeVector & v, Value t) : theX(v.x()), theY(v.y()), theZ(v.z()), theT(t) {} template LorentzVector(const LorentzVector & v) : theX(v.x()), theY(v.y()), theZ(v.z()), theT(v.t()) {} //@} /// Assignment operator template LorentzVector & operator=(const LorentzVector & b) { setX(b.x()); setY(b.y()); setZ(b.z()); setT(b.t()); return *this; } public: /// @name Component access methods. //@{ Value x() const { return theX; } Value y() const { return theY; } Value z() const { return theZ; } Value t() const { return theT; } Value e() const { return t(); } //@} /// @name Component set methods. //@{ void setX(Value x) { theX = x; } void setY(Value y) { theY = y; } void setZ(Value z) { theZ = z; } void setT(Value t) { theT = t; } void setE(Value e) { setT(e); } //@} public: /// Access to the 3-component part. ThreeVector vect() const { return ThreeVector(x(),y(),z()); } /// Cast to the 3-component part. operator ThreeVector() const { return vect(); } /// Set the 3-component part. void setVect(const ThreeVector & p) { theX = p.x(); theY = p.y(); theZ = p.z(); } public: /// The complex conjugate vector. LorentzVector conjugate() const { return LorentzVector(conj(x()),conj(y()),conj(z()),conj(t())); } /// Squared magnitude \f$x^\mu\,x_\mu=t^2 - \vec{x}^2\f$. Value2 m2() const { return (t()-z())*(t()+z()) - sqr(x()) - sqr(y()); } /// Squared magnitude with another vector Value2 m2(const LorentzVector & a) const { Value tt(a.t()+t()),zz(a.z()+z()); return (tt-zz)*(tt+zz)-sqr(a.x()+x())-sqr(a.y()+y()); } /// Magnitude (signed) \f$\pm\sqrt{|t^2 - \vec{x}^2|}\f$. Value m() const { Value2 tmp = m2(); return tmp < Value2() ? -Value(sqrt(-tmp)) : Value(sqrt(tmp)); } /// Transverse mass squared \f$t^2-z^2\f$. Value2 mt2() const { return (t()-z())*(t()+z()); } /// Transverse mass (signed) \f$\pm\sqrt{|t^2 - z^2|}\f$. Value mt() const { Value2 tmp = mt2(); return tmp < Value2() ? -Value(sqrt(-tmp)) : Value(sqrt(tmp)); } /// Squared transverse component of the spatial vector \f$x^2+y^2\f$. Value2 perp2() const { return sqr(x()) + sqr(y()); } /// Transverse component of the spatial vector \f$\pm\sqrt{x^2 + y^2}\f$. Value perp() const { return sqrt(perp2()); } /** * Squared transverse component of the spatial vector with respect to the * given axis. */ template Value2 perp2(const ThreeVector & p) const { return vect().perp2(p); } /** * Transverse component of the spatial vector with respect to the * given axis. */ template Value perp(const ThreeVector & p) const { return vect().perp(p); } /// Transverse energy squared. Value2 et2() const { Value2 pt2 = vect().perp2(); return pt2 == Value2() ? Value2() : e()*e() * pt2/(pt2+z()*z()); } /// Transverse energy (signed). Value et() const { Value2 etet = et2(); return e() < Value() ? -sqrt(etet) : sqrt(etet); } /// Transverse energy squared with respect to the given axis. Value2 et2(const ThreeVector & v) const { Value2 pt2 = vect().perp2(v); Value pv = vect().dot(v.unit()); return pt2 == Value2() ? Value2() : e()*e() * pt2/(pt2+pv*pv); } /// Transverse energy with respect to the given axis (signed). Value et(const ThreeVector & v) const { Value2 etet = et2(v); return e() < Value() ? -sqrt(etet) : sqrt(etet); } /// @name Spherical coordinates for the spatial part. //@{ /// Radius squared. Value2 rho2() const { return sqr(x()) + sqr(y()) + sqr(z()); } /// Radius. Value rho() const { return sqrt(rho2()); } /// Set new radius. void setRho(Value newRho) { Value oldRho = rho(); if (oldRho == Value()) return; double factor = newRho / oldRho; setX(x()*factor); setY(y()*factor); setZ(z()*factor); } /// Polar angle. double theta() const { assert(!(x() == Value() && y() == Value() && z() == Value())); return atan2(perp(),z()); } /// Cosine of the polar angle. double cosTheta() const { Value ptot = rho(); assert( ptot > Value() ); return z() / ptot; } /// Azimuthal angle. double phi() const { return atan2(y(),x()) ; } //@} /// Pseudorapidity of spatial part. double eta() const { Value m = rho(); if ( m == Value() ) return 0.0; Value pt = max(Constants::epsilon*m, perp()); double rap = log((m + abs(z()))/pt); return z() > ZERO? rap: -rap; } /// Spatial angle with another vector. double angle(const LorentzVector & w) const { return vect().angle(w.vect()); } /// Rapidity \f$\frac{1}{2}\ln\frac{t+z}{t-z} \f$ double rapidity() const { if ( z() == ZERO ) return 0.0; ERROR_IF(t() <= ZERO, "Tried to take rapidity of negative-energy Lorentz vector"); Value pt = sqrt(max(sqr(t()*Constants::epsilon), perp2() + m2())); double rap = log((t() + abs(z()))/pt); return z() > ZERO? rap: -rap; } /// Rapidity with respect to another vector double rapidity(const Axis & ref) const { double r = ref.mag2(); ERROR_IF(r == 0,"A zero vector used as reference to LorentzVector rapidity"); Value vdotu = vect().dot(ref)/sqrt(r); if ( vdotu == ZERO ) return 0.0; ERROR_IF(t() <= ZERO, "Tried to take rapidity of negative-energy Lorentz vector"); Value pt = sqrt(max(sqr(t()*Constants::epsilon), perp2(ref) + m2())); double rap = log((t() + abs(z()))/pt); return z() > ZERO? rap: -rap; } /** * Boost from reference frame into this vector's rest * frame: \f$\frac{\vec{x}}{t}\f$. */ Boost boostVector() const { if (t() == Value()) { if (rho2() == Value2()) return Boost(); else ERROR_IF(true,"boostVector computed for LorentzVector with t=0 -- infinite result"); } // result will make analytic sense but is physically meaningless ERROR_IF(m2() <= Value2(),"boostVector computed for a non-timelike LorentzVector"); return vect() * (1./t()); } /** * Boost from reference frame into this vector's rest * frame: \f$-\frac{\vec{x}}{t}\f$. */ Boost findBoostToCM() const { return -boostVector(); } /// Returns the positive light-cone component \f$t + z\f$. Value plus() const { return t() + z(); } /// Returns the negative light-cone component \f$t - z\f$. Value minus() const { return t() - z(); } /// Are two vectors nearby, using Euclidean measure \f$t^2 + |\vec{x}|^2\f$? bool isNear(const LorentzVector & w, double epsilon) const { Value2 limit = abs(vect().dot(w.vect())); limit += 0.25 * sqr( t() + w.t() ); limit *= sqr(epsilon); Value2 delta = (vect() - w.vect()).mag2(); delta += sqr( t() - w.t() ); return (delta <= limit); } /// Rotate the vector. Resets \f$x^\mu\rightarrow\mathsf{M}^\mu_\nu x^\nu\f$. LorentzVector & transform(const SpinOneLorentzRotation & m) { return *this = m.operator*(*this); } /// Rotate the vector. Resets \f$x^\mu\rightarrow\mathsf{M}^\mu_\nu x^\nu\f$. LorentzVector & operator*=(const SpinOneLorentzRotation & m) { return transform(m); } /// Dot product with metric \f$(+,-,-,-)\f$ template auto dot(const LorentzVector & a) const -> decltype(this->t() * a.t()) { return t() * a.t() - ( x() * a.x() + y() * a.y() + z() * a.z() ); } public: /** * Apply boost. * * @param bx Component x of the boost. * @param by Component y of the boost. * @param bz Component z of the boost. * @param gamma Optional gamma parameter for higher numerical * accuracy. The user has to ensure consistency. If not given, it * will be calculated as \f$\gamma=1/\sqrt{1-\beta^2}\f$. * */ LorentzVector & boost(double bx, double by, double bz, double gamma=-1.) { const double b2 = bx*bx + by*by + bz*bz; if ( b2 == 0.0 ) return *this; if ( gamma < 0.0 ) { gamma = 1.0 / sqrt(1.0 - b2); } const Value bp = bx*x() + by*y() + bz*z(); const double gamma2 = (gamma - 1.0)/b2; setX(x() + gamma2*bp*bx + gamma*bx*t()); setY(y() + gamma2*bp*by + gamma*by*t()); setZ(z() + gamma2*bp*bz + gamma*bz*t()); setT(gamma*(t() + bp)); return *this; } /** * Apply boost. * * @param b Three-vector giving the boost. * * @param gamma Optional gamma parameter for higher numerical * accuracy. The user has to ensure consistency. If not given, it * will be calculated as \f$\gamma=1/\sqrt{1-\beta^2}\f$. * */ LorentzVector & boost(Boost b, double gamma=-1.) { return boost(b.x(), b.y(), b.z(),gamma); } /** * Apply rotation around the x-axis. * * @param phi Angle in radians. */ LorentzVector & rotateX (double phi) { double sinphi = sin(phi); double cosphi = cos(phi); Value ty = y() * cosphi - z() * sinphi; theZ = z() * cosphi + y() * sinphi; theY = ty; return *this; } /** * Apply rotation around the y-axis. * * @param phi Angle in radians. */ LorentzVector & rotateY (double phi) { double sinphi = sin(phi); double cosphi = cos(phi); Value tz = z() * cosphi - x() * sinphi; theX = x() * cosphi + z() * sinphi; theZ = tz; return *this; } /** * Apply rotation around the z-axis. * * @param phi Angle in radians. */ LorentzVector & rotateZ (double phi) { double sinphi = sin(phi); double cosphi = cos(phi); Value tx = x() * cosphi - y() * sinphi; theY = y() * cosphi + x() * sinphi; theX = tx; return *this; } /** * Rotate the reference frame to a new z-axis. */ LorentzVector & rotateUz (const Axis & axis) { Axis ax = axis.unit(); double u1 = ax.x(); double u2 = ax.y(); double u3 = ax.z(); double up = u1*u1 + u2*u2; if (up>0) { up = sqrt(up); Value px = x(), py = y(), pz = z(); setX( (u1*u3*px - u2*py)/up + u1*pz ); setY( (u2*u3*px + u1*py)/up + u2*pz ); setZ( -up*px + u3*pz ); } else if (u3 < 0.) { setX(-x()); setZ(-z()); } return *this; } /** * Apply a rotation. * @param angle Rotation angle in radians. * @param axis Rotation axis. */ template LorentzVector & rotate(double angle, const ThreeVector & axis) { if (angle == 0.0) return *this; const U ll = axis.mag(); assert( ll > U() ); const double sa = sin(angle), ca = cos(angle); const double dx = axis.x()/ll, dy = axis.y()/ll, dz = axis.z()/ll; const Value xx = x(), yy = y(), zz = z(); setX((ca+(1-ca)*dx*dx) * xx +((1-ca)*dx*dy-sa*dz) * yy +((1-ca)*dx*dz+sa*dy) * zz ); setY(((1-ca)*dy*dx+sa*dz) * xx +(ca+(1-ca)*dy*dy) * yy +((1-ca)*dy*dz-sa*dx) * zz ); setZ(((1-ca)*dz*dx-sa*dy) * xx +((1-ca)*dz*dy+sa*dx) * yy +(ca+(1-ca)*dz*dz) * zz ); return *this; } public: /// @name Mathematical assignment operators. //@{ LorentzVector & operator+=(const LorentzVector > & a) { theX += a.x(); theY += a.y(); theZ += a.z(); theT += a.t(); return *this; } template LorentzVector & operator+=(const LorentzVector & a) { theX += a.x(); theY += a.y(); theZ += a.z(); theT += a.t(); return *this; } LorentzVector & operator-=(const LorentzVector > & a) { theX -= Complex(a.x()); theY -= Complex(a.y()); theZ -= Complex(a.z()); theT -= Complex(a.t()); return *this; } template LorentzVector & operator-=(const LorentzVector & a) { theX -= a.x(); theY -= a.y(); theZ -= a.z(); theT -= a.t(); return *this; } LorentzVector & operator*=(double a) { theX *= a; theY *= a; theZ *= a; theT *= a; return *this; } LorentzVector & operator/=(double a) { theX /= a; theY /= a; theZ /= a; theT /= a; return *this; } //@} private: /// @name Vector components //@{ Value theX; Value theY; Value theZ; Value theT; //@} }; /// @name Basic mathematical operations //@{ template inline LorentzVector operator/(const LorentzVector & v, Value a) { return LorentzVector(v.x()/a, v.y()/a, v.z()/a, v.t()/a); } inline LorentzVector operator/(const LorentzVector & v, Complex a) { return LorentzVector(v.x()/a, v.y()/a, v.z()/a, v.t()/a); } template inline LorentzVector operator-(const LorentzVector & v) { return LorentzVector(-v.x(),-v.y(),-v.z(),-v.t()); } template inline LorentzVector operator+(LorentzVector a, const LorentzVector & b) { return a += b; } template inline LorentzVector operator-(LorentzVector a, const LorentzVector & b) { return a -= b; } template inline LorentzVector operator*(const LorentzVector & a, double b) { return LorentzVector(a.x()*b, a.y()*b, a.z()*b, a.t()*b); } template inline LorentzVector operator*(double b, LorentzVector a) { return a *= b; } template inline auto operator*(ValueB a, const LorentzVector & v) -> LorentzVector { return {a*v.x(), a*v.y(), a*v.z(), a*v.t()}; } template inline auto operator*(const LorentzVector & v, ValueB b) -> LorentzVector { return b*v; } template inline auto operator/(const LorentzVector & v, ValueB b) -> LorentzVector { return {v.x()/b, v.y()/b, v.z()/b, v.t()/b}; } //@} /// @name Scalar product with metric \f$(+,-,-,-)\f$ //@{ template inline auto operator*(const LorentzVector & a, const LorentzVector & b) -> decltype(a.dot(b)) { return a.dot(b); } //@} /// Equality template inline bool operator==(const LorentzVector & a, const LorentzVector & b) { return a.x() == b.x() && a.y() == b.y() && a.z() == b.z() && a.t() == b.t(); } /// Stream output. Format \f$(x,y,z;t)\f$. inline ostream & operator<< (ostream & os, const LorentzVector & v) { return os << "(" << v.x() << "," << v.y() << "," << v.z() << ";" << v.t() << ")"; } /** Return the positive light-cone component. Or negative if the * current Direction<0> is reversed. */ template inline Value dirPlus(const LorentzVector & p) { return Direction<0>::pos()? p.plus(): p.minus(); } /** Return the negative light-cone component. Or positive if the * current Direction<0> is reversed. */ template inline Value dirMinus(const LorentzVector & p) { return Direction<0>::neg()? p.plus(): p.minus(); } /** Return the component along the positive z-axis. Or the negative * z-axis if the current Direction<0> is reversed. */ template inline Value dirZ(const LorentzVector & p) { return Direction<0>::dir()*p.z(); } /** Return the polar angle wrt. the positive z-axis. Or the negative * z-axis if the current Direction<0> is reversed. */ template inline double dirTheta(const LorentzVector & p) { return Direction<0>::pos()? p.theta(): Constants::pi - p.theta(); } /** Return the cosine of the polar angle wrt. the positive z-axis. Or * the negative z-axis if the current Direction<0> is reversed. */ template inline double dirCosTheta(const LorentzVector & p) { return Direction<0>::pos()? p.cosTheta(): -p.cosTheta(); } /** Get the boost vector for the LorentzVector. If the current * Direction<0> is reversed, so is the z-component. */ template inline ThreeVector dirBoostVector(const LorentzVector & p) { ThreeVector b(p.boostVector()); if ( Direction<0>::neg() ) b.setZ(-b.z()); return b; } /** Create a LorentzVector giving its light-cone and transverse * components. */ template inline LorentzVector lightCone(Value plus, Value minus, Value x, Value y) { LorentzVector r(x, y, 0.5*(plus-minus), 0.5*(plus+minus)); return r; } /** Create a LorentzVector giving its light-cone components. */ template inline LorentzVector lightCone(Value plus, Value minus) { // g++-3.3 has a problem with using Value() directly // gcc-bug c++/3650, fixed in 3.4 static const Value zero = Value(); LorentzVector r(zero, zero, 0.5*(plus-minus), 0.5*(plus+minus)); return r; } } // delayed header inclusion to break inclusion loop: // LorentzVec -> Transverse -> Lorentz5Vec -> LorentzVec #include "Transverse.h" namespace ThePEG { /** Create a LorentzVector giving its light-cone and transverse * components. */ template inline LorentzVector lightCone(Value plus, Value minus, Transverse pt) { LorentzVector r(pt.x(), pt.y(), 0.5*(plus-minus), 0.5*(plus+minus)); return r; } /** Create a LorentzVector giving its light-cone and transverse * components. If the current Direction<0> is reversed, so is the * z-component. */ template inline LorentzVector lightConeDir(Value plus, Value minus, Value x = Value(), Value y = Value()) { LorentzVector r(x, y, Direction<0>::dir()*0.5*(plus - minus), 0.5*(plus + minus)); return r; } /** Create a LorentzVector giving its light-cone and transverse * components. If the current Direction<0> is reversed, so is the * z-component. */ template inline LorentzVector lightConeDir(Value plus, Value minus, Transverse pt) { LorentzVector r(pt.x(), pt.y(), Direction<0>::dir()*0.5*(plus - minus), 0.5*(plus + minus)); return r; } /** Output a LorentzVector with units to a stream. */ template void ounitstream(OStream & os, const LorentzVector & p, UnitT & u) { os << ounit(p.x(), u) << ounit(p.y(), u) << ounit(p.z(), u) << ounit(p.e(), u); } /** Input a LorentzVector with units from a stream. */ template void iunitstream(IStream & is, LorentzVector & p, UnitT & u) { Value x, y, z, e; is >> iunit(x, u) >> iunit(y, u) >> iunit(z, u) >> iunit(e, u); p = LorentzVector(x, y, z, e); } } #undef ERROR_IF #endif /* ThePEG_LorentzVector_H */ diff --git a/Vectors/SpinHalfLorentzRotation.cc b/Vectors/SpinHalfLorentzRotation.cc --- a/Vectors/SpinHalfLorentzRotation.cc +++ b/Vectors/SpinHalfLorentzRotation.cc @@ -1,415 +1,415 @@ // -*- C++ -*- // // SpinHalfLorentzRotation.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the SpinHalfLorentzRotation class. // #include "SpinHalfLorentzRotation.h" using namespace ThePEG; // default constructor SpinHalfLorentzRotation::SpinHalfLorentzRotation() : _mx{{ {{1., 0., 0., 0.}}, {{0., 1., 0., 0.}}, {{0., 0., 1., 0.}}, {{0., 0., 0., 1.}} }} {} // constructor giving the components of a Lorentz boost SpinHalfLorentzRotation:: SpinHalfLorentzRotation(double bx, double by, double bz, double gamma) : _mx{} { setBoost(bx,by,bz,gamma); } // constructor with boost vector SpinHalfLorentzRotation:: SpinHalfLorentzRotation (const Boost & b, double gamma) : _mx{} { setBoost(b,gamma); } // protected set all elements constructor SpinHalfLorentzRotation:: SpinHalfLorentzRotation(Complex c1c1,Complex c1c2,Complex c1c3,Complex c1c4, Complex c2c1,Complex c2c2,Complex c2c3,Complex c2c4, Complex c3c1,Complex c3c2,Complex c3c3,Complex c3c4, Complex c4c1,Complex c4c2,Complex c4c3,Complex c4c4) : _mx{{ {{c1c1, c1c2, c1c3, c1c4}}, {{c2c1, c2c2, c2c3, c2c4}}, {{c3c1, c3c2, c3c3, c3c4}}, {{c4c1, c4c2, c4c3, c4c4}} }} {} // check for identity matrix bool SpinHalfLorentzRotation::isIdentity() const { return _mx == MatrixT{{ {{1., 0., 0., 0.}}, {{0., 1., 0., 0.}}, {{0., 0., 1., 0.}}, {{0., 0., 0., 1.}} }}; } // inverse ( inverse is gamma0 S dagger gamma 0) SpinHalfLorentzRotation SpinHalfLorentzRotation::inverse() const { return SpinHalfLorentzRotation {conj(_mx[2][2]),conj(_mx[3][2]),conj(_mx[0][2]),conj(_mx[1][2]), conj(_mx[2][3]),conj(_mx[3][3]),conj(_mx[0][3]),conj(_mx[1][3]), conj(_mx[2][0]),conj(_mx[3][0]),conj(_mx[0][0]),conj(_mx[1][0]), conj(_mx[2][1]),conj(_mx[3][1]),conj(_mx[0][1]),conj(_mx[1][1])}; } // specify the components of a lorentz boost SpinHalfLorentzRotation & SpinHalfLorentzRotation:: setBoost (double bx, double by, double bz, double) { // work out beta and chi const double eps=1e-10; double beta(sqrt(bx*bx+by*by+bz*bz)); double chi(atanh(beta)), chc(cosh(0.5*chi)), shc(0.5); if ( beta > eps ) shc=sinh(0.5*chi)/beta; Complex ii(0.,1.),nxminy(bx-ii*by),nxplny(bx+ii*by); _mx[0][0]= chc-shc*bz; _mx[0][1]=-shc*nxminy; _mx[0][2]= 0. ; _mx[0][3]= 0. ; _mx[1][0]=-shc*nxplny; _mx[1][1]= chc+shc*bz; _mx[1][2]= 0. ; _mx[1][3]= 0. ; _mx[2][0]= 0. ; _mx[2][1]= 0. ; _mx[2][2]= chc+shc*bz; _mx[2][3]=+shc*nxminy; _mx[3][0]= 0. ; _mx[3][1]= 0. ; _mx[3][2]=+shc*nxplny; _mx[3][3]= chc-shc*bz; return *this; } // specify a boost vector SpinHalfLorentzRotation & SpinHalfLorentzRotation::setBoost (const Boost & b,double) { // work out beta and chi const double eps=1e-10; double bx(b.x()),by(b.y()),bz(b.z()),beta(b.mag()),chi(atanh(beta)), chc(cosh(0.5*chi)),shc(0.5); if(beta>eps){shc=sinh(0.5*chi)/beta;} Complex ii(0.,1.),nxminy(bx-ii*by),nxplny(bx+ii*by); _mx[0][0]= chc-shc*bz;_mx[0][1]=-shc*nxminy;_mx[0][2]= 0. ;_mx[0][3]= 0. ; _mx[1][0]=-shc*nxplny;_mx[1][1]= chc+shc*bz;_mx[1][2]= 0. ;_mx[1][3]= 0. ; _mx[2][0]= 0. ;_mx[2][1]= 0. ;_mx[2][2]= chc+shc*bz;_mx[2][3]=+shc*nxminy; _mx[3][0]= 0. ;_mx[3][1]= 0. ;_mx[3][2]=+shc*nxplny;_mx[3][3]= chc-shc*bz; return *this; } // lorentz boost in x direction SpinHalfLorentzRotation & SpinHalfLorentzRotation::setBoostX (double & bx) { // work out beta and chi double chi(atanh(bx)),shc(sinh(0.5*chi)),chc(cosh(0.5*chi)); _mx[0][0]= chc;_mx[0][1]=-shc;_mx[0][2]= 0. ;_mx[0][3]= 0. ; _mx[1][0]=-shc;_mx[1][1]= chc;_mx[1][2]= 0. ;_mx[1][3]= 0. ; _mx[2][0]= 0 ;_mx[2][1]= 0. ;_mx[2][2]= chc;_mx[2][3]=+shc; _mx[3][0]= 0 ;_mx[3][1]= 0. ;_mx[3][2]=+shc;_mx[3][3]= chc; return *this; } // lorentz boost in y direction SpinHalfLorentzRotation & SpinHalfLorentzRotation::setBoostY (double & by) { // work out beta and chi double chi(atanh(by)),chc(cosh(0.5*chi)); Complex shc(0.,sinh(0.5*chi)); _mx[0][0]= chc;_mx[0][1]= shc;_mx[0][2]= 0. ;_mx[0][3]= 0. ; _mx[1][0]=-shc;_mx[1][1]= chc;_mx[1][2]= 0. ;_mx[1][3]= 0 ; _mx[2][0]= 0. ;_mx[2][1]= 0. ;_mx[2][2]= chc;_mx[2][3]=-shc; _mx[3][0]= 0. ;_mx[3][1]= 0. ;_mx[3][2]=+shc;_mx[3][3]= chc; return *this; } // lorentz boost in z direction SpinHalfLorentzRotation & SpinHalfLorentzRotation::setBoostZ (double & bz) { // work out beta and chi double chi(atanh(bz)),shc(sinh(0.5*chi)),chc(cosh(0.5*chi)); _mx[0][0]= chc-shc;_mx[0][1]= 0. ;_mx[0][2]= 0. ;_mx[0][3]= 0. ; _mx[1][0]= 0. ;_mx[1][1]= chc+shc;_mx[1][2]= 0. ;_mx[1][3]= 0. ; _mx[2][0]= 0. ;_mx[2][1]= 0. ;_mx[2][2]= chc+shc ;_mx[2][3]= 0. ; _mx[3][0]= 0. ;_mx[3][1]= 0. ;_mx[3][2]=+0. ;_mx[3][3]= chc-shc; return *this; } // Pure boost along the x-axis; equivalent to LT = BoostX(beta) * LT SpinHalfLorentzRotation & SpinHalfLorentzRotation::boostX(double bx) { double chi(atanh(bx)),shc(sinh(0.5*chi)),chc(cosh(0.5*chi)); MatrixT temp; for(size_t ix=0;ix<4;++ix) { temp[0][ix]= chc*_mx[0][ix]-shc*_mx[1][ix]; temp[1][ix]= chc*_mx[1][ix]-shc*_mx[0][ix]; temp[2][ix]= chc*_mx[2][ix]+shc*_mx[3][ix]; temp[3][ix]= chc*_mx[3][ix]+shc*_mx[2][ix]; } _mx = temp; return *this; } // Pure boost along the y-axis; equivalent to LT = BoostY(beta) * LT SpinHalfLorentzRotation & SpinHalfLorentzRotation::boostY(double by) { double chi(atanh(by)),chc(cosh(0.5*chi)); Complex shc(0.,sinh(0.5*chi)); MatrixT temp; for(size_t ix=0;ix<4;++ix) { temp[0][ix]= chc*_mx[0][ix]+shc*_mx[1][ix]; temp[1][ix]= chc*_mx[1][ix]-shc*_mx[0][ix]; temp[2][ix]= chc*_mx[2][ix]-shc*_mx[3][ix]; temp[3][ix]= chc*_mx[3][ix]+shc*_mx[2][ix]; } _mx = temp; return *this; } // Pure boost along the z-axis; equivalent to LT = BoostX(beta) * LT SpinHalfLorentzRotation & SpinHalfLorentzRotation::boostZ(double bz) { double chi(atanh(bz)),shc(sinh(0.5*chi)),chc(cosh(0.5*chi)); MatrixT temp; for(size_t ix=0;ix<4;++ix) { temp[0][ix]=(chc-shc)*_mx[0][ix]; temp[1][ix]=(chc+shc)*_mx[1][ix]; temp[2][ix]=(chc+shc)*_mx[2][ix]; temp[3][ix]=( chc-shc)*_mx[3][ix]; } _mx = temp; return *this; } // General boost equivalent to LT = Boost(bx,by,bz) * LT SpinHalfLorentzRotation & SpinHalfLorentzRotation::boost(double bx, double by, double bz, double gamma) { // calculation of gamma and beta double b2(bx*bx+by*by+bz*bz); if(gamma<1.) gamma = 1./sqrt(1.-b2); double beta = sqrt(b2); // work out beta and chi const double eps=1e-8; double chc = sqrt(0.5*(1+gamma)); double shc = beta>eps ? sqrt(0.5*(gamma-1))/beta : 0.5+b2*(0.1875+0.12109375*b2); Complex ii(0.,1.),nxminy(bx-ii*by),nxplny(bx+ii*by); MatrixT temp; for(size_t ix=0;ix<4;++ix) { temp[0][ix]= (chc-shc*bz)*_mx[0][ix]-shc*nxminy *_mx[1][ix]; temp[1][ix]=-shc*nxplny *_mx[0][ix]+(chc+shc*bz)*_mx[1][ix]; temp[2][ix]= (chc+shc*bz)*_mx[2][ix]+shc*nxminy *_mx[3][ix]; temp[3][ix]= shc*nxplny *_mx[2][ix]+(chc-shc*bz)*_mx[3][ix]; } _mx = temp; return *this; } // General boost equivalent to LT = Boost(bv) * LT SpinHalfLorentzRotation & SpinHalfLorentzRotation::boost(const Boost & b, double gamma) { // calculation of gamma and beta double b2(b.mag2()); if(gamma<1.) gamma = 1./sqrt(1.-b2); double beta = sqrt(b2); // work out chi const double eps=1e-8; double bx(b.x()),by(b.y()),bz(b.z()); double chc = sqrt(0.5*(1+gamma)); double shc = beta>eps ? sqrt(0.5*(gamma-1))/beta : 0.5+b2*(0.1875+0.12109375*b2); Complex ii(0.,1.),nxminy(bx-ii*by),nxplny(bx+ii*by); MatrixT temp; for(size_t ix=0;ix<4;++ix) { temp[0][ix]= (chc-shc*bz)*_mx[0][ix]-shc*nxminy *_mx[1][ix]; temp[1][ix]=-shc*nxplny *_mx[0][ix]+(chc+shc*bz)*_mx[1][ix]; temp[2][ix]= (chc+shc*bz)*_mx[2][ix]+shc*nxminy *_mx[3][ix]; temp[3][ix]= shc*nxplny *_mx[2][ix]+(chc-shc*bz)*_mx[3][ix]; } _mx = temp; return *this; } std::ostream & SpinHalfLorentzRotation::print( std::ostream & os ) const { os << "\n [ ( " << std::setw(14) << std::setprecision(6) << s1s1() << " " << std::setw(14) << std::setprecision(6) << s1s2() << " " << std::setw(14) << std::setprecision(6) << s1s3() << " " << std::setw(14) << std::setprecision(6) << s1s4() << ")\n" << " ( " << std::setw(14) << std::setprecision(6) << s2s1() << " " << std::setw(14) << std::setprecision(6) << s2s2() << " " << std::setw(14) << std::setprecision(6) << s2s3() << " " << std::setw(14) << std::setprecision(6) << s2s4() << ")\n" << " ( " << std::setw(14) << std::setprecision(6) << s3s1() << " " << std::setw(14) << std::setprecision(6) << s3s2() << " " << std::setw(14) << std::setprecision(6) << s3s3() << " " << std::setw(14) << std::setprecision(6) << s3s4() << ")\n" << " ( " << std::setw(14) << std::setprecision(6) << s4s1() << " " << std::setw(14) << std::setprecision(6) << s4s2() << " " << std::setw(14) << std::setprecision(6) << s4s3() << " " << std::setw(14) << std::setprecision(6) << s4s4() << ") ]\n"; return os; } // general rotation SpinHalfLorentzRotation & SpinHalfLorentzRotation::setRotate(double phi, const Axis & axis) { double cp(cos(0.5*phi)); // get the normalised components of the vector double amag(axis.mag()),ax(axis.x()/amag),ay(axis.y()/amag),az(axis.z()/amag); Complex ii(0.,1.),nxminy(ax-ii*ay),nxplny(ax+ii*ay),isp(0.,sin(0.5*phi)); // rotatation matrix is the same in both conventions _mx[0][0]= cp-isp*az ;_mx[0][1]=-isp*nxminy;_mx[0][2]= 0. ;_mx[0][3]= 0. ; _mx[1][0]=-isp*nxplny;_mx[1][1]= cp+isp*az ;_mx[1][2]= 0. ;_mx[1][3]= 0. ; _mx[2][0]= 0. ;_mx[2][1]= 0. ;_mx[2][2]= cp-isp*az ;_mx[2][3]=-isp*nxminy; _mx[3][0]= 0. ;_mx[3][1]= 0. ;_mx[3][2]=-isp*nxplny;_mx[3][3]= cp+isp*az ; return *this; } // rotation about x SpinHalfLorentzRotation & SpinHalfLorentzRotation::setRotateX(double& phi) { double cp(cos(0.5*phi)); Complex isp(0.,sin(0.5*phi)); // rotatation matrix is the same in both conventions _mx[0][0]= cp ;_mx[0][1]=-isp;_mx[0][2]= 0. ;_mx[0][3]= 0. ; _mx[1][0]=-isp;_mx[1][1]= cp ;_mx[1][2]= 0. ;_mx[1][3]= 0. ; _mx[2][0]= 0. ;_mx[2][1]= 0. ;_mx[2][2]= cp ;_mx[2][3]=-isp; _mx[3][0]= 0. ;_mx[3][1]= 0. ;_mx[3][2]=-isp;_mx[3][3]= cp ; return *this; } // rotation about y SpinHalfLorentzRotation & SpinHalfLorentzRotation::setRotateY(double& phi) { double cp(cos(0.5*phi)),sp(sin(0.5*phi)); // rotatation matrix is the same in both conventions _mx[0][0]= cp;_mx[0][1]=-sp;_mx[0][2]= 0.;_mx[0][3]= 0.; _mx[1][0]= sp;_mx[1][1]= cp;_mx[1][2]= 0.;_mx[1][3]= 0.; _mx[2][0]= 0.;_mx[2][1]= 0.;_mx[2][2]= cp;_mx[2][3]=-sp; _mx[3][0]= 0.;_mx[3][1]= 0.;_mx[3][2]= sp;_mx[3][3]= cp; return *this; } // rotation about z SpinHalfLorentzRotation & SpinHalfLorentzRotation::setRotateZ(double& phi) { double cp(cos(0.5*phi)); Complex isp(0.,sin(0.5*phi)); // rotatation matrix is the same in both conventions _mx[0][0]= cp-isp ;_mx[0][1]= 0. ;_mx[0][2]= 0. ;_mx[0][3]= 0. ; _mx[1][0]= 0. ;_mx[1][1]= cp+isp;_mx[1][2]= 0. ;_mx[1][3]= 0. ; _mx[2][0]= 0. ;_mx[2][1]= 0. ;_mx[2][2]= cp-isp;_mx[2][3]= 0. ; _mx[3][0]= 0. ;_mx[3][1]= 0. ;_mx[3][2]= 0. ;_mx[3][3]= cp+isp; return *this; } // product SpinHalfLorentzRotation SpinHalfLorentzRotation::operator * (const SpinHalfLorentzRotation & lt) const { SpinHalfLorentzRotation temp{_mx}; temp *= lt; return temp; } // multiply and assign SpinHalfLorentzRotation & SpinHalfLorentzRotation::operator *= (const SpinHalfLorentzRotation & lt) { MatrixT temp; for(size_t ix=0;ix<4;++ix) { for(size_t iy=0;iy<4;++iy) { temp[ix][iy] = 0.0; for(size_t iz=0;iz<4;++iz) temp[ix][iy] += _mx[ix][iz] * lt._mx[iz][iy]; } } _mx = temp; return *this; } // transform method SpinHalfLorentzRotation & SpinHalfLorentzRotation::transform(const SpinHalfLorentzRotation & lt) { SpinHalfLorentzRotation temp{lt._mx}; temp *= (*this); _mx = temp._mx; return *this; } // Rotation around the x-axis; equivalent to LT = RotationX(delta) * LT SpinHalfLorentzRotation & SpinHalfLorentzRotation::rotateX(double phi) { double cp(cos(0.5*phi)); Complex isp(0.,sin(0.5*phi)); MatrixT temp; for(size_t ix=0;ix<4;++ix) { temp[0][ix]= cp*_mx[0][ix]-isp*_mx[1][ix]; temp[1][ix]=-isp*_mx[0][ix]+ cp*_mx[1][ix]; temp[2][ix]= cp*_mx[2][ix]-isp*_mx[3][ix]; temp[3][ix]=-isp*_mx[2][ix]+ cp*_mx[3][ix]; } _mx = temp; return *this; } // Rotation around the y-axis; equivalent to LT = RotationY(delta) * LT SpinHalfLorentzRotation & SpinHalfLorentzRotation::rotateY(double phi) { double cp(cos(0.5*phi)),sp(sin(0.5*phi)); MatrixT temp; for(size_t ix=0;ix<4;++ix) { temp[0][ix]= cp*_mx[0][ix]-sp*_mx[1][ix]; temp[1][ix]= sp*_mx[0][ix]+cp*_mx[1][ix]; temp[2][ix]= cp*_mx[2][ix]-sp*_mx[3][ix]; temp[3][ix]= sp*_mx[2][ix]+cp*_mx[3][ix]; } _mx = temp; return *this; } // Rotation around the z-axis; equivalent to LT = RotationZ(delta) * LT SpinHalfLorentzRotation & SpinHalfLorentzRotation::rotateZ(double phi) { double cp(cos(0.5*phi)); Complex isp(0.,sin(0.5*phi)); MatrixT temp; for(size_t ix=0;ix<4;++ix) { temp[0][ix]= (cp-isp)*_mx[0][ix]; temp[1][ix]= (cp+isp)*_mx[1][ix]; temp[2][ix]= (cp-isp)*_mx[2][ix]; temp[3][ix]= (cp+isp)*_mx[3][ix]; } _mx = temp; return *this; } // Rotation around specified vector - LT = Rotation(delta,axis)*LT SpinHalfLorentzRotation & SpinHalfLorentzRotation::rotate(double phi, const Axis & axis) { double cp(cos(0.5*phi)),amag(axis.mag()), ax(axis.x()/amag),ay(axis.y()/amag),az(axis.z()/amag); Complex ii(0.,1.),nxminy(ax-ii*ay),nxplny(ax+ii*ay),isp(0.,sin(0.5*phi)); MatrixT temp; for(size_t ix=0;ix<4;++ix) { temp[0][ix]= (cp-isp*az)*_mx[0][ix]-isp*nxminy *_mx[1][ix]; temp[1][ix]=-isp*nxplny *_mx[0][ix]+(cp+isp*az)*_mx[1][ix]; temp[2][ix]= (cp-isp*az)*_mx[2][ix]-isp*nxminy *_mx[3][ix]; temp[3][ix]=-isp*nxplny *_mx[2][ix]+(cp+isp*az)*_mx[3][ix]; } _mx = temp; return *this; } diff --git a/Vectors/SpinHalfLorentzRotation.h b/Vectors/SpinHalfLorentzRotation.h --- a/Vectors/SpinHalfLorentzRotation.h +++ b/Vectors/SpinHalfLorentzRotation.h @@ -1,353 +1,353 @@ // -*- C++ -*- // // SpinHalfLorentzRotation.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef THEPEG_SpinHalfLorentzRotation_H #define THEPEG_SpinHalfLorentzRotation_H // // This is the declaration of the SpinHalfLorentzRotation class. // #include "ThePEG/Helicity/HelicityDefinitions.h" #include "ThreeVector.h" namespace ThePEG { /** * The SpinHalfLorentzRotation class is designed to offer the same * features as the HepLorentzRotation class of CLHEP but for the spin-\f$\frac12\f$ * Lorentz transformation. This is then combined into the general LorentzRotation * class of ThePEG to provide the Lorentz transformation for any object as the * transformations for higher spin objects can be built from the spin-\f$\frac12\f$ * and spin-1 transformations. * * The boost matrix is calculated using the default Dirac matrix representation. * Any conversion to other Dirac matrix representations must be handled when the * transformation is used. */ class SpinHalfLorentzRotation { /** * The external inverseOf needs to be a friend */ friend SpinHalfLorentzRotation inverseOf ( const SpinHalfLorentzRotation & lt ); public: /** @name Constructors and destructor. */ //@{ /** * Default constructor. Gives a unit matrix. */ SpinHalfLorentzRotation(); /** * Constructor giving the components of a Lorentz boost. * @param bx The x-component of the boost * @param by The y-component of the boost * @param bz The z-component of the boost * @param gamma The \f$\gamma\f$ factor (optional) */ SpinHalfLorentzRotation (double bx, double by, double bz, double gamma=-1.); /** * Constructor giving the vector for a Lorentz boost. * @param b The boost vector * @param gamma The \f$\gamma\f$ factor (optional) */ SpinHalfLorentzRotation (const Boost & b,double gamma=-1.); //@} /** * Returns true if the Identity matrix. */ bool isIdentity() const; /** * Return the inverse. */ SpinHalfLorentzRotation inverse() const; /** * Inverts the SpinHalfLorentzRotation matrix. */ SpinHalfLorentzRotation & invert() { return *this = inverse(); } /** * output operator */ std::ostream & print( std::ostream & os ) const; /** @name Set methods for speical cases of simple rotations and boosts */ //@{ /** * Specify the components of a Lorentz Boost * @param bx The x-component of the boost * @param by The y-component of the boost * @param bz The z-component of the boost * @param gamma The \f$\gamma\f$ factor (optional) */ SpinHalfLorentzRotation & setBoost (double bx, double by, double bz,double gamma=-1.); /** * Specify a Lorentz Boost as a vector * @param b The boost vector * @param gamma The \f$\gamma\f$ factor (optional) */ SpinHalfLorentzRotation & setBoost (const Boost & b,double gamma=-1.); /** * Specify a boost by the given factor along the x-axis * @param boost The Lorentz boost */ SpinHalfLorentzRotation & setBoostX (double & boost); /** * Specify a boost by the given factor along the y-axis * @param boost The Lorentz boost */ SpinHalfLorentzRotation & setBoostY (double & boost); /** * Specify a boost by the given factor along the z-axis * @param boost The Lorentz boost */ SpinHalfLorentzRotation & setBoostZ (double & boost); /** * Specify a rotation about a general axis by the angle given. * @param delta The angle * @param axis The axis */ SpinHalfLorentzRotation & setRotate(double delta, const Axis & axis); /** * Specify a rotation by the given angle about the x-axis * @param angle The rotation angle */ SpinHalfLorentzRotation & setRotateX (double & angle); /** * Specify a rotation by the given angle about the y-axis * @param angle The rotation angle */ SpinHalfLorentzRotation & setRotateY (double & angle); /** * Specify a rotation by the given angle about the z-axis * @param angle The rotation angle */ SpinHalfLorentzRotation & setRotateZ (double & angle); //@} /** @name Access methods for the components */ //@{ /** * The \f$(1,1)\f$ component */ Complex s1s1() const { return _mx[0][0]; } /** * The \f$(1,2)\f$ component */ Complex s1s2() const { return _mx[0][1]; } /** * The \f$(1,3)\f$ component */ Complex s1s3() const { return _mx[0][2]; } /** * The \f$(1,4)\f$ component */ Complex s1s4() const { return _mx[0][3]; } /** * The \f$(1,1)\f$ component */ Complex s2s1() const { return _mx[1][0]; } /** * The \f$(1,1)\f$ component */ Complex s2s2() const { return _mx[1][1]; } /** * The \f$(1,1)\f$ component */ Complex s2s3() const { return _mx[1][2]; } /** * The \f$(1,1)\f$ component */ Complex s2s4() const { return _mx[1][3]; } /** * The \f$(1,1)\f$ component */ Complex s3s1() const { return _mx[2][0]; } /** * The \f$(1,1)\f$ component */ Complex s3s2() const { return _mx[2][1]; } /** * The \f$(1,1)\f$ component */ Complex s3s3() const { return _mx[2][2]; } /** * The \f$(1,1)\f$ component */ Complex s3s4() const { return _mx[2][3]; } /** * The \f$(1,1)\f$ component */ Complex s4s1() const { return _mx[3][0]; } /** * The \f$(1,1)\f$ component */ Complex s4s2() const { return _mx[3][1]; } /** * The \f$(1,1)\f$ component */ Complex s4s3() const { return _mx[3][2]; } /** * The \f$(1,1)\f$ component */ Complex s4s4() const { return _mx[3][3]; } /** * Fortran style subscript operator */ Complex operator()(unsigned int i, unsigned int j) const { assert(i<=3 && j<=3); return _mx[i][j]; } //@} /** @name Transformation and product members */ //@{ /** * Product of two SpinHalfLorentzRotations (this) * lt - matrix multiplication * @param lt The SpinHalfLorentzRotation we are multiplying */ SpinHalfLorentzRotation operator * (const SpinHalfLorentzRotation & lt) const; /** * Multiply by and assign a*=b becomes a= a*b */ SpinHalfLorentzRotation & operator *= (const SpinHalfLorentzRotation & ); /** * Transform (similar to *= but a.transform(b) becomes a = b*a */ SpinHalfLorentzRotation & transform (const SpinHalfLorentzRotation & ); /** * Rotation around the x-axis; equivalent to LT = RotationX(delta) * LT */ SpinHalfLorentzRotation & rotateX(double delta); /** * Rotation around the y-axis; equivalent to LT = RotationY(delta) * LT */ SpinHalfLorentzRotation & rotateY(double delta); /** * Rotation around the z-axis; equivalent to LT = RotationZ(delta) * LT */ SpinHalfLorentzRotation & rotateZ(double delta); /** * Rotation around specified vector - LT = Rotation(delta,axis)*LT */ SpinHalfLorentzRotation & rotate(double delta, const Axis & axis); /** * Pure boost along the x-axis; equivalent to LT = BoostX(beta) * LT */ SpinHalfLorentzRotation & boostX(double beta); /** * Pure boost along the y-axis; equivalent to LT = BoostX(beta) * LT */ SpinHalfLorentzRotation & boostY(double beta); /** * Pure boost along the z-axis; equivalent to LT = BoostX(beta) * LT */ SpinHalfLorentzRotation & boostZ(double beta); /** * General boost equivalent to LT = Boost(bx,by,bz) * LT * @param bx The x-component of the boost * @param by The y-component of the boost * @param bz The z-component of the boost * @param gamma The \f$\gamma\f$ factor (optional) */ SpinHalfLorentzRotation & boost(double bx, double by, double bz, double gamma=-1.); /** * General boost equivalent to LT = Boost(bv) * LT * @param bv The boost vector * @param gamma The \f$\gamma\f$ factor (optional) */ SpinHalfLorentzRotation & boost(const Boost & bv, double gamma=-1.); //@} protected: /** * Protected constructor giving all the members, no check it is a valid * transformation */ SpinHalfLorentzRotation(Complex s1s1,Complex s1s2,Complex s1s3,Complex s1s4, Complex s2s1,Complex s2s2,Complex s2s3,Complex s2s4, Complex s3s1,Complex s3s2,Complex s3s3,Complex s3s4, Complex s4s1,Complex s4s2,Complex s4s3,Complex s4s4); private: using MatrixT = array,4>; SpinHalfLorentzRotation(const MatrixT & m) : _mx(m) {} /** * The members of the transformation matrix. */ MatrixT _mx; }; /** * Global method to get the inverse */ inline SpinHalfLorentzRotation inverseOf ( const SpinHalfLorentzRotation & lt ) { return lt.inverse(); } /** * output operator */ inline std::ostream & operator<< ( std::ostream & os, const SpinHalfLorentzRotation& lt ) { return lt.print(os); } } #endif /* THEPEG_SpinHalfLorentzRotation_H */ diff --git a/Vectors/SpinOneLorentzRotation.cc b/Vectors/SpinOneLorentzRotation.cc --- a/Vectors/SpinOneLorentzRotation.cc +++ b/Vectors/SpinOneLorentzRotation.cc @@ -1,188 +1,188 @@ // -*- C++ -*- // // SpinOneLorentzRotation.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the LorentzRotation class. // #include "SpinOneLorentzRotation.h" using namespace ThePEG; SpinOneLorentzRotation:: SpinOneLorentzRotation(double xx, double xy, double xz, double xt, double yx, double yy, double yz, double yt, double zx, double zy, double zz, double zt, double tx, double ty, double tz, double tt) { xx_() = xx; xy_() = xy; xz_() = xz; xt_() = xt; yx_() = yx; yy_() = yy; yz_() = yz; yt_() = yt; zx_() = zx; zy_() = zy; zz_() = zz; zt_() = zt; tx_() = tx; ty_() = ty; tz_() = tz; tt_() = tt; } bool SpinOneLorentzRotation::isIdentity() const { return 1.0 == xx() && 0.0 == xy() && 0.0 == xz() && 0.0 == xt() && 0.0 == yx() && 1.0 == yy() && 0.0 == yz() && 0.0 == yt() && 0.0 == zx() && 0.0 == zy() && 1.0 == zz() && 0.0 == zt() && 0.0 == tx() && 0.0 == ty() && 0.0 == tz() && 1.0 == tt(); } SpinOneLorentzRotation SpinOneLorentzRotation::inverse() const { return SpinOneLorentzRotation( xx(), yx(), zx(),-tx(), xy(), yy(), zy(),-ty(), xz(), yz(), zz(),-tz(), -xt(),-yt(),-zt(), tt()); } // output operator std::ostream & SpinOneLorentzRotation::print( std::ostream & os) const { os << "\n [ ( " << std::setw(14) << std::setprecision(6) << xx() << " " << std::setw(14) << std::setprecision(6) << xy() << " " << std::setw(14) << std::setprecision(6) << xz() << " " << std::setw(14) << std::setprecision(6) << xt() << ")\n" << " ( " << std::setw(14) << std::setprecision(6) << yx() << " " << std::setw(14) << std::setprecision(6) << yy() << " " << std::setw(14) << std::setprecision(6) << yz() << " " << std::setw(14) << std::setprecision(6) << yt() << ")\n" << " ( " << std::setw(14) << std::setprecision(6) << zx() << " " << std::setw(14) << std::setprecision(6) << zy() << " " << std::setw(14) << std::setprecision(6) << zz() << " " << std::setw(14) << std::setprecision(6) << zt() << ")\n" << " ( " << std::setw(14) << std::setprecision(6) << tx() << " " << std::setw(14) << std::setprecision(6) << ty() << " " << std::setw(14) << std::setprecision(6) << tz() << " " << std::setw(14) << std::setprecision(6) << tt() << ") ]\n"; return os; } SpinOneLorentzRotation & SpinOneLorentzRotation:: setBoost (double bx, double by, double bz, double gamma) { double beta2 = sqr(bx) + sqr(by) + sqr(bz); if (beta2 >= 1.0) { throw Exception() << "Invalid boost (" << bx << ',' << by << ',' << bz << ") in SpinOneLorentzRotatio::setBoost" << Exception::eventerror; } if(gamma<0.) gamma = 1.0 / sqrt((1.-bz)*(1.+bz)-sqr(bx)-sqr(by)); double bgamma = sqr(gamma) / (1.0 + gamma); xx_() = 1.0 + bgamma * bx * bx; yy_() = 1.0 + bgamma * by * by; zz_() = 1.0 + bgamma * bz * bz; xy_() = yx_() = bgamma * bx * by; xz_() = zx_() = bgamma * bx * bz; yz_() = zy_() = bgamma * by * bz; xt_() = tx_() = gamma * bx; yt_() = ty_() = gamma * by; zt_() = tz_() = gamma * bz; tt_() = gamma; return *this; } SpinOneLorentzRotation & SpinOneLorentzRotation::setRotate(double delta, const Axis & axis) { double sinDelta = sin(delta), cosDelta = cos(delta); double oneMinusCosDelta = 1.0 - cosDelta; Axis u = unitVector(axis); double uX = u.x(); double uY = u.y(); double uZ = u.z(); double rxx = oneMinusCosDelta * uX * uX + cosDelta; double rxy = oneMinusCosDelta * uX * uY - sinDelta * uZ; double rxz = oneMinusCosDelta * uX * uZ + sinDelta * uY; double ryx = oneMinusCosDelta * uY * uX + sinDelta * uZ; double ryy = oneMinusCosDelta * uY * uY + cosDelta; double ryz = oneMinusCosDelta * uY * uZ - sinDelta * uX; double rzx = oneMinusCosDelta * uZ * uX - sinDelta * uY; double rzy = oneMinusCosDelta * uZ * uY + sinDelta * uX; double rzz = oneMinusCosDelta * uZ * uZ + cosDelta; xx_() = rxx; xy_() = rxy; xz_() = rxz; xt_() = 0.0; yx_() = ryx; yy_() = ryy; yz_() = ryz; yt_() = 0.0; zx_() = rzx; zy_() = rzy; zz_() = rzz; zt_() = 0.0; tx_() = 0.0; ty_() = 0.0; tz_() = 0.0; tt_() = 1.0; return *this; } SpinOneLorentzRotation & SpinOneLorentzRotation::setRotateX(double delta) { double sinDelta = sin(delta), cosDelta = cos(delta); double ryy = cosDelta, ryz = -sinDelta; double rzy = sinDelta, rzz = cosDelta; xx_() = 1.0; xy_() = 0.0; xz_() = 0.0; xt_() = 0.0; yx_() = 0.0; yy_() = ryy; yz_() = ryz; yt_() = 0.0; zx_() = 0.0; zy_() = rzy; zz_() = rzz; zt_() = 0.0; tx_() = 0.0; ty_() = 0.0; tz_() = 0.0; tt_() = 1.0; return *this; } SpinOneLorentzRotation & SpinOneLorentzRotation::setRotateY(double delta) { double sinDelta = sin(delta), cosDelta = cos(delta); double rxx = cosDelta, rxz = sinDelta; double rzx = -sinDelta, rzz = cosDelta; xx_() = rxx; xy_() = 0.0; xz_() = rxz; xt_() = 0.0; yx_() = 0.0; yy_() = 1.0; yz_() = 0.0; yt_() = 0.0; zx_() = rzx; zy_() = 0.0; zz_() = rzz; zt_() = 0.0; tx_() = 0.0; ty_() = 0.0; tz_() = 0.0; tt_() = 1.0; return *this; } SpinOneLorentzRotation & SpinOneLorentzRotation::setRotateZ(double delta) { double sinDelta = sin(delta), cosDelta = cos(delta); double rxx = cosDelta, rxy = -sinDelta; double ryx = sinDelta, ryy = cosDelta; xx_() = rxx; xy_() = rxy; xz_() = 0.0; xt_() = 0.0; yx_() = ryx; yy_() = ryy; yz_() = 0.0; yt_() = 0.0; zx_() = 0.0; zy_() = 0.0; zz_() = 1.0; zt_() = 0.0; tx_() = 0.0; ty_() = 0.0; tz_() = 0.0; tt_() = 1.0; return *this; } SpinOneLorentzRotation SpinOneLorentzRotation::operator*(const SpinOneLorentzRotation & b) const { return SpinOneLorentzRotation (xx()*b.xx() + xy()*b.yx() + xz()*b.zx() + xt()*b.tx(), xx()*b.xy() + xy()*b.yy() + xz()*b.zy() + xt()*b.ty(), xx()*b.xz() + xy()*b.yz() + xz()*b.zz() + xt()*b.tz(), xx()*b.xt() + xy()*b.yt() + xz()*b.zt() + xt()*b.tt(), yx()*b.xx() + yy()*b.yx() + yz()*b.zx() + yt()*b.tx(), yx()*b.xy() + yy()*b.yy() + yz()*b.zy() + yt()*b.ty(), yx()*b.xz() + yy()*b.yz() + yz()*b.zz() + yt()*b.tz(), yx()*b.xt() + yy()*b.yt() + yz()*b.zt() + yt()*b.tt(), zx()*b.xx() + zy()*b.yx() + zz()*b.zx() + zt()*b.tx(), zx()*b.xy() + zy()*b.yy() + zz()*b.zy() + zt()*b.ty(), zx()*b.xz() + zy()*b.yz() + zz()*b.zz() + zt()*b.tz(), zx()*b.xt() + zy()*b.yt() + zz()*b.zt() + zt()*b.tt(), tx()*b.xx() + ty()*b.yx() + tz()*b.zx() + tt()*b.tx(), tx()*b.xy() + ty()*b.yy() + tz()*b.zy() + tt()*b.ty(), tx()*b.xz() + ty()*b.yz() + tz()*b.zz() + tt()*b.tz(), tx()*b.xt() + ty()*b.yt() + tz()*b.zt() + tt()*b.tt()); } diff --git a/Vectors/SpinOneLorentzRotation.h b/Vectors/SpinOneLorentzRotation.h --- a/Vectors/SpinOneLorentzRotation.h +++ b/Vectors/SpinOneLorentzRotation.h @@ -1,394 +1,394 @@ // -*- C++ -*- // // SpinOneLorentzRotation.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_SpinOneLorentzRotation_H #define ThePEG_SpinOneLorentzRotation_H #include "ThePEG/Helicity/HelicityDefinitions.h" #include "ThePEG/Helicity/LorentzTensor.fh" #include "ThePEG/Helicity/LorentzRSSpinor.fh" #include "ThePEG/Helicity/LorentzRSSpinorBar.fh" #include "ThreeVector.h" #include namespace ThePEG { /** * The SpinOneLorentzRotation class is ... */ class SpinOneLorentzRotation { public: /** @name Constructors and destructor. */ //@{ /** * Default constructor. Gives a unit matrix. */ SpinOneLorentzRotation() { xx_() = yy_() = zz_() = tt_() = 1.0; } /** * Constructor giving the components of a Lorentz boost. * @param bx The x-component of the boost * @param by The y-component of the boost * @param bz The z-component of the boost * @param gamma The \f$\gamma\f$ factor (optional) */ SpinOneLorentzRotation (double bx, double by, double bz, double gamma=-1.) { setBoost(bx,by,bz,gamma); } /** * Constructor giving the vector for a Lorentz boost. * @param b The boost vector * @param gamma The \f$\gamma\f$ factor (optional) */ explicit SpinOneLorentzRotation (const Boost & b, double gamma=-1.) { setBoost(b.x(), b.y(), b.z(),gamma); } //@} /** * Returns true if the Identity matrix. */ bool isIdentity() const; /** * Return the inverse. */ SpinOneLorentzRotation inverse() const; /** * Inverts the SpinOneLorentzRotation matrix. */ SpinOneLorentzRotation & invert() { return *this = inverse(); } /** * output operator */ std::ostream & print( std::ostream & os ) const; /** @name Set methods for speical cases of simple rotations and boosts */ //@{ /** * Specify the components of a Lorentz Boost * @param bx The x-component of the boost * @param by The y-component of the boost * @param bz The z-component of the boost * @param gamma The \f$\gamma\f$ factor (optional) */ SpinOneLorentzRotation & setBoost (double bx, double by, double bz, double gamma=-1.); /** * Specify a Lorentz Boost as a vector * @param b The boost vector * @param gamma The \f$\gamma\f$ factor (optional) */ SpinOneLorentzRotation & setBoost (const Boost & b, double gamma=-1.) { return setBoost(b.x(), b.y(), b.z(),gamma); } /** * Specify a rotation about a general axis by the angle given. * @param delta The angle * @param axis The axis */ SpinOneLorentzRotation & setRotate(double delta, const Axis & axis); /** * Specify a rotation by the given angle about the x-axis * @param angle The rotation angle */ SpinOneLorentzRotation & setRotateX (double angle); /** * Specify a rotation by the given angle about the y-axis * @param angle The rotation angle */ SpinOneLorentzRotation & setRotateY (double angle); /** * Specify a rotation by the given angle about the z-axis * @param angle The rotation angle */ SpinOneLorentzRotation & setRotateZ (double angle); //@} /** @name Access methods for the components of the spin-1 rotation */ //@{ /** * The xx component */ double xx() const { return matrix_[ 0]; } /** * The xy component */ double xy() const { return matrix_[ 1]; } /** * The xz component */ double xz() const { return matrix_[ 2]; } /** * The xt component */ double xt() const { return matrix_[ 3]; } /** * The yx component */ double yx() const { return matrix_[ 4]; } /** * The yy component */ double yy() const { return matrix_[ 5]; } /** * The yz component */ double yz() const { return matrix_[ 6]; } /** * The yt component */ double yt() const { return matrix_[ 7]; } /** * The zx component */ double zx() const { return matrix_[ 8]; } /** * The zy component */ double zy() const { return matrix_[ 9]; } /** * The zz component */ double zz() const { return matrix_[10]; } /** * The zt component */ double zt() const { return matrix_[11]; } /** * The tx component */ double tx() const { return matrix_[12]; } /** * The ty component */ double ty() const { return matrix_[13]; } /** * The tz component */ double tz() const { return matrix_[14]; } /** * The tt component */ double tt() const { return matrix_[15]; } //@} /** @name Transformation and product members */ //@{ /** * Product with a LorentzVector simply returns the rotated vector. */ template LorentzVector operator*(const LorentzVector & v) const { return LorentzVector (xx()*v.x() + xy()*v.y() + xz()*v.z() + xt()*v.t(), yx()*v.x() + yy()*v.y() + yz()*v.z() + yt()*v.t(), zx()*v.x() + zy()*v.y() + zz()*v.z() + zt()*v.t(), tx()*v.x() + ty()*v.y() + tz()*v.z() + tt()*v.t()); } /** * Product with a Lorentz5Vector simply returns the rotated vector. */ template Lorentz5Vector operator*(const Lorentz5Vector & v) const { return Lorentz5Vector (xx()*v.x() + xy()*v.y() + xz()*v.z() + xt()*v.t(), yx()*v.x() + yy()*v.y() + yz()*v.z() + yt()*v.t(), zx()*v.x() + zy()*v.y() + zz()*v.z() + zt()*v.t(), tx()*v.x() + ty()*v.y() + tz()*v.z() + tt()*v.t()); } /** * Product of two LorentzRotations (this) * lt - matrix multiplication * @param lt The LorentzRotation we are multiplying */ SpinOneLorentzRotation operator * (const SpinOneLorentzRotation & lt) const; /** * Multiply by and assign a*=b becomes a= a*b */ SpinOneLorentzRotation & operator *= (const SpinOneLorentzRotation & lt) { return *this = *this * lt; } /** * Transform (similar to *= but a.transform(b) becomes a = b*a */ SpinOneLorentzRotation & transform (const SpinOneLorentzRotation & lt) { return *this = lt * *this; } /** * Rotation around the x-axis; equivalent to LT = RotationX(delta) * LT */ SpinOneLorentzRotation & rotateX(double delta) { SpinOneLorentzRotation tmp; tmp.setRotateX(delta); return *this = tmp * *this; } /** * Rotation around the y-axis; equivalent to LT = RotationY(delta) * LT */ SpinOneLorentzRotation & rotateY(double delta) { SpinOneLorentzRotation tmp; tmp.setRotateY(delta); return *this = tmp * *this; } /** * Rotation around the z-axis; equivalent to LT = RotationZ(delta) * LT */ SpinOneLorentzRotation & rotateZ(double delta) { SpinOneLorentzRotation tmp; tmp.setRotateZ(delta); return *this = tmp * *this; } /** * Rotation around specified vector - LT = Rotation(delta,axis)*LT */ SpinOneLorentzRotation & rotate(double delta, const Axis & axis) { SpinOneLorentzRotation tmp; tmp.setRotate(delta, axis); return *this = tmp * *this; } /** * Pure boost along the x-axis; equivalent to LT = BoostX(beta) * LT */ SpinOneLorentzRotation & boostX(double beta) { return *this = SpinOneLorentzRotation(beta,0,0) * *this; } /** * Pure boost along the y-axis; equivalent to LT = BoostX(beta) * LT */ SpinOneLorentzRotation & boostY(double beta) { return *this = SpinOneLorentzRotation(0,beta,0) * *this; } /** * Pure boost along the z-axis; equivalent to LT = BoostX(beta) * LT */ SpinOneLorentzRotation & boostZ(double beta) { return *this = SpinOneLorentzRotation(0,0,beta) * *this; } /** * boost equivalent to LT = Boost(bx,by,bz) * LT * @param bx The x-component of the boost * @param by The y-component of the boost * @param bz The z-component of the boost * @param gamma The \f$\gamma\f$ factor (optional) */ SpinOneLorentzRotation & boost(double bx, double by, double bz, double gamma=-1.) { return *this = SpinOneLorentzRotation(bx,by,bz,gamma) * *this; } /** * boost equivalent to LT = Boost(bv) * LT * @param b The boost vector * @param gamma The \f$\gamma\f$ factor (optional) */ SpinOneLorentzRotation & boost(const Boost & b, double gamma=-1.) { return *this = SpinOneLorentzRotation(b.x(),b.y(),b.z(),gamma) * *this; } //@} private: template friend class Helicity::LorentzTensor; template friend class Helicity::LorentzRSSpinor; template friend class Helicity::LorentzRSSpinorBar; /// Matrix components, order: \f$(xx, xy, \ldots, tz, tt)\f$. array matrix_ = {}; /// Constructor from doubles. SpinOneLorentzRotation (double xx, double xy, double xz, double xt, double yx, double yy, double yz, double yt, double zx, double zy, double zz, double zt, double tx, double ty, double tz, double tt); /// Component access by index: x=0, t=3. double operator()(unsigned int i, unsigned int j) const { return matrix_[4*i + j]; } /// @name Component access. //@{ double & xx_() { return matrix_[ 0]; } double & xy_() { return matrix_[ 1]; } double & xz_() { return matrix_[ 2]; } double & xt_() { return matrix_[ 3]; } double & yx_() { return matrix_[ 4]; } double & yy_() { return matrix_[ 5]; } double & yz_() { return matrix_[ 6]; } double & yt_() { return matrix_[ 7]; } double & zx_() { return matrix_[ 8]; } double & zy_() { return matrix_[ 9]; } double & zz_() { return matrix_[10]; } double & zt_() { return matrix_[11]; } double & tx_() { return matrix_[12]; } double & ty_() { return matrix_[13]; } double & tz_() { return matrix_[14]; } double & tt_() { return matrix_[15]; } //@} }; /** * output operator */ inline std::ostream & operator<< ( std::ostream & os, const SpinOneLorentzRotation& lt ) { return lt.print(os); } } #endif /* ThePEG_SpinOneLorentzRotation_H */ diff --git a/Vectors/ThreeVector.h b/Vectors/ThreeVector.h --- a/Vectors/ThreeVector.h +++ b/Vectors/ThreeVector.h @@ -1,421 +1,421 @@ // -*- C++ -*- // // ThreeVector.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 2006-2017 David Grellscheid, Leif Lonnblad +// Copyright (C) 2006-2019 David Grellscheid, Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_ThreeVector_H #define ThePEG_ThreeVector_H /** * @file ThreeVector.h contains the ThreeVector class. ThreeVector can be * created with any unit type as template parameter. All basic * mathematical operations are supported, as well as a subset of the * CLHEP Vector3 functionality. */ #include "ThreeVector.fh" #include "ThePEG/Config/ThePEG.h" #include "ThePEG/Utilities/UnitIO.h" #include #include namespace ThePEG { /** * A 3-component vector. It can be created with any unit type * as template parameter. All basic mathematical operations are * supported, as well as a subset of the CLHEP Vector3 * functionality. */ template class ThreeVector { private: /// Value squared using Value2 = decltype(sqr(std::declval())); public: /** @name Constructors. */ //@{ ThreeVector() : theX(), theY(), theZ() {} ThreeVector(Value x, Value y, Value z) : theX(x), theY(y), theZ(z) {} template ThreeVector(const ThreeVector & v) : theX(v.x()), theY(v.y()), theZ(v.z()) {} //@} public: /// @name Component access methods. //@{ Value x() const { return theX; } Value y() const { return theY; } Value z() const { return theZ; } //@} /// @name Component set methods. //@{ void setX(Value x) { theX = x; } void setY(Value y) { theY = y; } void setZ(Value z) { theZ = z; } //@} public: /// Squared magnitude \f$x^2+y^2+z^2\f$. Value2 mag2() const { return sqr(x()) + sqr(y()) + sqr(z()); } /// Magnitude \f$\sqrt{x^2+y^2+z^2}\f$. Value mag() const { return sqrt(mag2()); } /// Squared transverse component \f$x^2+y^2\f$. Value2 perp2() const { return sqr(x()) + sqr(y()); } /// Transverse component \f$\sqrt{x^2+y^2}\f$. Value perp() const { return sqrt(perp2()); } /// Dot product. template auto dot(const ThreeVector & a) const -> decltype(this->x()*a.x()) { return x()*a.x() + y()*a.y() + z()*a.z(); } /// Squared transverse component with respect to the given axis. template Value2 perp2(const ThreeVector & p) const { const auto pMag2 = p.mag2(); assert( pMag2 > ZERO ); auto ss = this->dot(p); Value2 ret = mag2() - sqr(ss)/pMag2; if ( ret <= ZERO ) ret = ZERO; return ret; } /// Transverse component with respect to the given axis. template Value perp(const ThreeVector & p) const { return sqrt(perp2(p)); } /// @name Spherical coordinates. //@{ /// Polar angle. double theta() const { assert(!(x() == ZERO && y() == ZERO && z() == ZERO)); return atan2(perp(),z()); } /// Azimuthal angle. double phi() const { return atan2(y(),x()); } /// Set the polar angle. void setTheta(double th) { double ma = mag(); double ph = phi(); setX(ma*sin(th)*cos(ph)); setY(ma*sin(th)*sin(ph)); setZ(ma*cos(th)); } /// Set the azimuthal angle. void setPhi(double ph) { double xy = perp(); setX(xy*cos(ph)); setY(xy*sin(ph)); } //@} /// Parallel vector with unit length. ThreeVector unit() const { Value2 mg2 = mag2(); assert(mg2 > ZERO); Value mg = sqrt(mg2); return {x()/mg, y()/mg, z()/mg}; } /// Orthogonal vector. ThreeVector orthogonal() const { Value xx = abs(x()); Value yy = abs(y()); Value zz = abs(z()); using TVec = ThreeVector; if (xx < yy) { return xx < zz ? TVec{ZERO,z(),-y()} : TVec{y(),-x(),ZERO}; } else { return yy < zz ? TVec{-z(),ZERO,x()} : TVec{y(),-x(),ZERO}; } } /// Azimuthal angle difference, brought into the range \f$(-\pi,\pi]\f$. template double deltaPhi (const ThreeVector & v2) const { double dphi = v2.phi() - phi(); if ( dphi > Constants::pi ) { dphi -= Constants::twopi; } else if ( dphi <= -Constants::pi ) { dphi += Constants::twopi; } return dphi; } /** * Apply a rotation. * @param angle Rotation angle in radians. * @param axis Rotation axis. */ template ThreeVector & rotate(double angle, const ThreeVector & axis) { if (angle == 0.0) return *this; const U ll = axis.mag(); assert( ll > ZERO ); const double sa = sin(angle), ca = cos(angle); const double dx = axis.x()/ll, dy = axis.y()/ll, dz = axis.z()/ll; const Value xx = x(), yy = y(), zz = z(); setX((ca+(1-ca)*dx*dx) * xx +((1-ca)*dx*dy-sa*dz) * yy +((1-ca)*dx*dz+sa*dy) * zz ); setY(((1-ca)*dy*dx+sa*dz) * xx +(ca+(1-ca)*dy*dy) * yy +((1-ca)*dy*dz-sa*dx) * zz ); setZ(((1-ca)*dz*dx-sa*dy) * xx +((1-ca)*dz*dy+sa*dx) * yy +(ca+(1-ca)*dz*dz) * zz ); return *this; } /** * Rotate the reference frame to a new z-axis. */ ThreeVector & rotateUz (const Axis & axis) { Axis ax = axis.unit(); double u1 = ax.x(); double u2 = ax.y(); double u3 = ax.z(); double up = u1*u1 + u2*u2; if (up>0) { up = sqrt(up); Value px = x(), py = y(), pz = z(); setX( (u1*u3*px - u2*py)/up + u1*pz ); setY( (u2*u3*px + u1*py)/up + u2*pz ); setZ( -up*px + u3*pz ); } else if (u3 < 0.) { setX(-x()); setZ(-z()); } return *this; } /** * Rotate from a reference frame to the z-axis. */ ThreeVector & rotateUzBack (const Axis & axis) { Axis ax = axis.unit(); double u1 = ax.x(); double u2 = ax.y(); double u3 = ax.z(); double up = u1*u1 + u2*u2; if (up>0) { up = sqrt(up); Value px = x(), py = y(), pz = z(); setX( ( u1*u3*px + u2*u3*py)/up - up*pz ); setY( (-u2*px + u1*py)/up ); setZ( u1*px + u2*py + u3*pz ); } else if (u3 < 0.) { setX(-x()); setZ(-z()); } return *this; } /// Vector cross-product template auto cross(const ThreeVector & a) const -> ThreeVectory()*a.z())> { return { y()*a.z()-z()*a.y(), -x()*a.z()+z()*a.x(), x()*a.y()-y()*a.x() }; } public: /// @name Comparison operators. //@{ bool operator==(const ThreeVector & a) const { return (theX == a.x() && theY == a.y() && theZ == a.z()); } bool operator!=(const ThreeVector & a) const { return !(*this == a); } bool almostEqual(const ThreeVector & a, double threshold = 1e-04) const { return ((std::abs(theX - a.x()) < threshold) && (std::abs(theY - a.y()) < threshold) && (std::abs(theZ - a.z()) < threshold)); } bool almostUnequal(const ThreeVector & a, double threshold = 1e-04) const { return ! this->almostEqual(a, threshold); } //@} public: /// @name Mathematical assignment operators. //@{ ThreeVector & operator+=(const ThreeVector & a) { theX += a.x(); theY += a.y(); theZ += a.z(); return *this; } ThreeVector & operator-=(const ThreeVector & a) { theX -= a.x(); theY -= a.y(); theZ -= a.z(); return *this; } ThreeVector & operator*=(double a) { theX *= a; theY *= a; theZ *= a; return *this; } ThreeVector & operator/=(double a) { theX /= a; theY /= a; theZ /= a; return *this; } //@} /// Cosine of the azimuthal angle between two vectors. template double cosTheta(const ThreeVector & q) const { auto ptot = mag()*q.mag(); assert( ptot > ZERO ); double arg = dot(q)/ptot; if (arg > 1.0) arg = 1.0; else if(arg < -1.0) arg = -1.0; return arg; } /// Angle between two vectors. template double angle(const ThreeVector & v) const { return acos(cosTheta(v)); } private: /// @name Vector components //@{ Value theX; Value theY; Value theZ; //@} }; /// Stream output. Format \f$(x,y,z)\f$. inline ostream & operator<< (ostream & os, const ThreeVector & v) { return os << '(' << v.x() << ',' << v.y() << ',' << v.z() << ')'; } /// @name Basic mathematical operations //@{ template inline ThreeVector operator+(ThreeVector a, const ThreeVector & b) { return a += b; } template inline ThreeVector operator-(ThreeVector a, const ThreeVector & b) { return a -= b; } template inline ThreeVector operator-(const ThreeVector & v) { return {-v.x(),-v.y(),-v.z()}; } template inline ThreeVector operator*(ThreeVector v, double a) { return v *= a; } template inline ThreeVector operator*(double a, ThreeVector v) { return v *= a; } template inline auto operator*(ValueB a, ThreeVector v) -> ThreeVector { return {a*v.x(), a*v.y(), a*v.z()}; } template inline auto operator*(ThreeVector v, ValueB a) -> ThreeVector { return {v.x()*a, v.y()*a, v.z()*a}; } //@} /// Vector dot product. template inline auto operator*(const ThreeVector & a, const ThreeVector & b) -> decltype(a.x()*b.x()) { return a.dot(b); } /// A parallel vector with unit length. template ThreeVector unitVector(const ThreeVector & v) { return v.unit(); } /** Output a ThreeVector with units to a stream. */ template void ounitstream(OStream & os, const ThreeVector & p, UT & u) { os << ounit(p.x(), u) << ounit(p.y(), u) << ounit(p.z(), u); } /** Input a ThreeVector with units from a stream. */ template void iunitstream(IStream & is, ThreeVector & p, UT & u) { Value x, y, z; is >> iunit(x, u) >> iunit(y, u) >> iunit(z, u); p = ThreeVector(x, y, z); } } #endif /* ThePEG_ThreeVector_H */ diff --git a/Vectors/Transverse.h b/Vectors/Transverse.h --- a/Vectors/Transverse.h +++ b/Vectors/Transverse.h @@ -1,260 +1,260 @@ // -*- C++ -*- // // Transverse.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_Transverse_H #define ThePEG_Transverse_H // This is the declaration of the Transverse class. #include "ThePEG/Config/ThePEG.h" #include "ThePEG/Vectors/Lorentz5Vector.h" #include "Transverse.fh" namespace ThePEG { /** * Transverse represents the transverse components of a * LorentzVector. It inherits from * std::pair and can be used * anywhere such a pair is called for. It can also be created directly * from a ThreeVector, LorentzVector and * Lorentz5Momentum. * * @see Lorentz5Vector */ template class Transverse: public pair { public: /** Template argument typedef. */ using Value2 = decltype(sqr(std::declval())); /** Template argument typedef. */ using BasePair = pair; public: /** @name Constructors. */ //@{ /** * Default constructor. */ Transverse() : BasePair(Value(), Value()) {} /** * Constructor from underlying representation. */ Transverse(const BasePair & p) : BasePair(p) {} /** * Constructor from x and y components. */ Transverse(Value x, Value y) : BasePair(x, y) {} /** * Constructor taking the transverse parts of a ThreeVector. */ Transverse(const ThreeVector & p) : BasePair(p.x(), p.y()) {} /** * Constructor taking the transverse parts of a LorentzVector. */ Transverse(const LorentzVector & p) : BasePair(p.x(), p.y()) {} /** * Constructor taking the transverse parts of a Lorentz5Vector. */ Transverse(const Lorentz5Vector & p) : BasePair(p.x(), p.y()) {} //@} /** @name Assignment operators. */ //@{ /** * Assignment from underlying representation. */ const Transverse & operator=(const BasePair & p) { BasePair::operator=(p); return *this; } /** * Assignment taking the transverse parts of a ThreeVector. */ const Transverse & operator=(const ThreeVector & p) { BasePair::operator=(BasePair(p.x(), p.y())); return *this; } /** * Assignment taking the transverse parts of a LorentzVector. */ const Transverse & operator=(const LorentzVector & p) { BasePair::operator=(BasePair(p.x(), p.y())); return *this; } /** * Assignment taking the transverse parts of a Lorentz5Vector. */ const Transverse & operator=(const Lorentz5Vector & p) { BasePair::operator=(BasePair(p.x(), p.y())); return *this; } //@} /** @name Arithmetric operations */ //@{ /** * Unary minus. */ Transverse operator-() const { return Transverse(-x(), -y()); } /** * Binary minus. */ Transverse operator-(const Transverse & pt) const { return Transverse(x() - pt.x(), y() - pt.y()); } /** * Assign-subtract. */ Transverse & operator-=(const Transverse & pt) { BasePair::first -= pt.x(); BasePair::second -= pt.y(); return *this; } /** * Addition. */ Transverse operator+(const Transverse & pt) const { return Transverse(x() + pt.x(), y() + pt.y()); } /** * Assign-add. */ Transverse & operator+=(const Transverse & pt) { BasePair::first += pt.x(); BasePair::second += pt.y(); return *this; } /** * Multiply-assign with a scalar. */ inline Transverse & operator*=(double a) { BasePair::first *= a; BasePair::second *= a; return *this; } /** * Divide-assign with a scalar. */ inline Transverse & operator/=(double a) { BasePair::first /= a; BasePair::second /= a; return *this; } //@} /** @name Access coordinates. */ //@{ /** * The x-component. */ Value x() const { return BasePair::first; } /** * The y-component. */ Value y() const { return BasePair::second; } /** * The magnitude squared. */ Value2 pt2() const { return sqr(x()) + sqr(y()); } /** * The magnitude. */ Value pt() const { return sqrt(pt2()); } /** * The azimuth angle. */ double phi() const { return atan2(y(), x()); } //@} }; /** Output a Transverse with units to a stream. */ template void ounitstream(OStream & os, const Transverse & p, UT & u) { os << ounit(p.x(), u) << ounit(p.y(), u); } /** Input a Transverse with units from a stream. */ template void iunitstream(IStream & is, Transverse & p, UT & u) { T x, y; is >> iunit(x, u) >> iunit(y, u); p = Transverse(x, y); } /** Multiply a Transverse with a number. */ template inline Transverse operator*(Transverse a, double b) { return a *= b; } /** Multiply a number with a Transverse. */ template inline Transverse operator*(double b, Transverse a) { return a *= b; } /** Multiply a (unitful) number with a Transverse. */ template inline auto operator*(ValueB a, const Transverse & v) -> Transverse { return {a*v.x(), a*v.y()}; } /** Multiply a Transverse with a (unitful) number. */ template inline auto operator*(const Transverse & v, ValueB a) -> Transverse { return {a*v.x(), a*v.y()}; } /** Divide a Transverse by a number. */ template inline Transverse operator/(const Transverse & v, Value a) { return {v.x()/a, v.y()/a}; } /** Divide a Transverse by a (unitful) number. */ template inline auto operator/(const Transverse & v, ValueB b) -> Transverse { return {v.x()/b, v.y()/b}; } } #endif /* ThePEG_Transverse_H */ diff --git a/configure.ac b/configure.ac --- a/configure.ac +++ b/configure.ac @@ -1,175 +1,175 @@ dnl Process this file with autoconf to produce a configure script. AC_PREREQ([2.69]) AC_INIT([ThePEG],[devel],[http://www.thep.lu.se/ThePEG/],[ThePEG]) AC_CONFIG_AUX_DIR([Config]) AC_CONFIG_MACRO_DIR([m4]) -THEPEG_LIBTOOL_VERSION_INFO(29,0,0) +THEPEG_LIBTOOL_VERSION_INFO(30,0,0) AC_CONFIG_SRCDIR([EventRecord/SubProcess.h]) AC_CONFIG_HEADERS([Config/config.h]) AC_CANONICAL_HOST case "${host}" in *-darwin[[0156]].*) AC_MSG_ERROR([ThePEG requires OS X 10.3 or later]) ;; *-darwin7.*) if test "x$MACOSX_DEPLOYMENT_TARGET" != "x10.3"; then AC_MSG_ERROR( [Please export the MACOSX_DEPLOYMENT_TARGET variable, set to 10.3]) fi ;; esac AC_LANG(C++) AM_INIT_AUTOMAKE([1.9 gnu dist-bzip2 subdir-objects -Wall]) dnl also include std-options once --version and --help exist m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) dnl Checks for C++ compiler. Handle C++11 flags. AC_PROG_CXX AX_CXX_COMPILE_STDCXX([11],[noext],[mandatory]) dnl check for unistd AC_CHECK_HEADER([unistd.h],[], [AC_MSG_ERROR([ThePEG needs "unistd.h". Check your system is POSIX-compliant.])]) dnl Checks for programs. AC_PROG_INSTALL AC_PROG_MAKE_SET AC_PROG_LN_S LT_PREREQ([2.2]) LT_INIT([disable-static dlopen pic-only]) VL_LIB_READLINE THEPEG_CHECK_GSL THEPEG_SEARCH_LHAPDF THEPEG_CHECK_HEPMC THEPEG_CHECK_RIVET FASTJET_CHECK_FASTJET AX_CHECK_ZLIB dnl AX_CHECK_BZ2LIB THEPEG_DEFINE_ENVDEFAULT(ThePEG_GZREAD_FILE,GZREAD_FILE,gunzip -c,[The command which, taking the name of a gzipped file as argument, unzips it and prints it to stdout. Default is "gunzip -c"]) THEPEG_DEFINE_ENVDEFAULT(ThePEG_GZWRITE_FILE,GZWRITE_FILE,[gzip -c > ],[The command which, taking the name of a gzipped file as argument, reads stdin, zips it and writes it to the file. Default is "gzip -c > ".]) THEPEG_DEFINE_ENVDEFAULT(ThePEG_BZ2READ_FILE,BZ2READ_FILE,bunzip2 -c,[The command which, taking the name of a bzipped file as argument, unzips it and prints it to stdout. Default is "bunzip2 -c".]) THEPEG_DEFINE_ENVDEFAULT(ThePEG_BZ2WRITE_FILE,BZ2WRITE_FILE,[bzip2 -c > ],[The command which, taking the name of a bzipped file as argument, reads stdin, zips it and writes it to the file. Default is "bzip2 -c > ".]) THEPEG_CHECK_EXPM1 THEPEG_CHECK_LOG1P THEPEG_CHECK_DLOPEN AX_COMPILER_VENDOR case "${ax_cv_cxx_compiler_vendor}" in clang) case "${host}" in *linux*) AC_MSG_WARN([ ***************************************************************************** clang/LLVM ignores the CPU floating-point environment. All floating point exception trapping will be disabled. *****************************************************************************]) ;; esac esac THEPEG_CHECK_FPUCONTROL THEPEG_CHECK_FENV AM_CPPFLAGS="-I\$(top_builddir)/include \$(GSLINCLUDE)" case "${ax_cv_cxx_compiler_vendor}" in gnu) AM_CXXFLAGS="-pedantic -Wall -W" ;; clang) AM_CXXFLAGS="-pedantic -Wall -Wno-overloaded-virtual -Wno-unused-function" dnl -Wno-unneeded-internal-declaration ;; intel) AM_CXXFLAGS="-strict-ansi -Wall -wd13000,1418,981,444,383,1599,1572,2259,980" ;; esac AC_SUBST(AM_CPPFLAGS) AC_SUBST(AM_CXXFLAGS) dnl do an actual capability check on ld instead of this workaround case "${host}" in *-darwin*) ;; *) AM_LDFLAGS="-Wl,--enable-new-dtags" ;; esac AC_SUBST(AM_LDFLAGS) THEPEG_EMPTY_SUBST AC_PATH_PROG(PERL, perl) AC_ARG_WITH(javagui, [ --with-javagui Compile and install the java-based GUI.]) if test "x$with_javagui" != "xno"; then THEPEG_HAS_JAVA([1.4], [], [with_javagui=no; AC_MSG_NOTICE([Java GUI disabled])]) fi AM_CONDITIONAL([JAVAGUI], [test "x$with_javagui" != "xno"]) AC_CONFIG_FILES([Helicity/Makefile Helicity/WaveFunction/Makefile Helicity/Vertex/Makefile Helicity/Vertex/Scalar/Makefile Helicity/Vertex/Vector/Makefile Helicity/Vertex/Tensor/Makefile Utilities/Makefile include/Makefile Interface/Makefile LesHouches/Makefile Vectors/Makefile PDT/Makefile PDF/Makefile Persistency/Makefile Config/Makefile Handlers/Makefile MatrixElement/Makefile Pointer/Makefile lib/Makefile lib/Makefile.common.install src/Makefile src/thepeg-config ACDC/Makefile Repository/Makefile EventRecord/Makefile StandardModel/Makefile Cuts/Makefile Analysis/Makefile Doc/Makefile Doc/MakeDocs.in Doc/refman.h Doc/refman.conf java/Makefile Makefile]) AC_CONFIG_FILES([Doc/fixinterfaces.pl],[chmod +x Doc/fixinterfaces.pl]) BOOST_REQUIRE([1.41],[AC_SUBST([BOOST_NOT_FOUND],[true])]) BOOST_TEST() THEPEG_BOOST_UNIT_TEST THEPEG_OVERVIEW AC_CONFIG_COMMANDS([summary],[cat config.thepeg]) AC_OUTPUT diff --git a/src/TestLHAPDF.cc b/src/TestLHAPDF.cc --- a/src/TestLHAPDF.cc +++ b/src/TestLHAPDF.cc @@ -1,149 +1,149 @@ // -*- C++ -*- // // TestLHAPDF.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the TestLHAPDF class. // #include "TestLHAPDF.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/PDF/PDFBase.h" using namespace ThePEG; NoPIOClassDescription TestLHAPDF::initTestLHAPDF; // Definition of the static class description member. bool approx(double x1, double x2, double eps = 1.0e-3) { eps *= abs(x1) + abs(x2); if ( eps == 0.0 ) return true; return abs(x1 - x2) < eps; } void TestLHAPDF::Init() { double PDF1P[] = { 0.000000000, 0.254411259, 0.551724644, 0.679716202, 0.871195736, 0.872211343, 23.791350673, 0.919026004, 0.947097315, 0.679716202, 0.551724644, 0.254411259, 0.000000000 }; double PDF1PB[] = { 0.000000000, 0.254411259, 0.551724644, 0.679716202, 0.947097315, 0.919026004, 23.791350673, 0.872211343, 0.871195736, 0.679716202, 0.551724644, 0.254411259, 0.000000000 }; double PDF1N[] = { 0.000000000, 0.254411259, 0.551724644, 0.679716202, 0.872211343, 0.871195736, 23.791350673, 0.947097315, 0.919026004, 0.679716202, 0.551724644, 0.254411259, 0.000000000 }; double PDF1NB[] = { 0.000000000, 0.254411259, 0.551724644, 0.679716202, 0.919026004, 0.947097315, 23.791350673, 0.871195736, 0.872211343, 0.679716202, 0.551724644, 0.254411259, 0.000000000 }; double PDFVP[] = { 0.000000000, 0.000000000, 0.000000000, 0.000000000, 0.000000000, 0.000000000, 0.000000000, 0.919026004 - 0.872211343, 0.947097315 - 0.871195736, 0.000000000, 0.000000000, 0.000000000, 0.000000000 }; double PDFVPB[] = { 0.000000000, 0.000000000, 0.000000000, 0.000000000, 0.947097315 - 0.871195736, 0.919026004 - 0.872211343, 0.000000000, 0.000000000, 0.000000000, 0.000000000, 0.000000000, 0.000000000, 0.000000000 }; double PDFVN[] = { 0.000000000, 0.000000000, 0.000000000, 0.000000000, 0.000000000, 0.000000000, 0.000000000, 0.947097315 - 0.871195736, 0.919026004 - 0.87221134, 0.000000000, 0.000000000, 0.000000000, 0.000000000 }; double PDFVNB[] = { 0.000000000, 0.000000000, 0.000000000, 0.000000000, 0.919026004 - 0.872211343, 0.947097315 - 0.871195736, 0.000000000, 0.000000000, 0.000000000, 0.000000000, 0.000000000, 0.000000000, 0.00000000 }; double PDF2N[] = { 0.000000000, 0.277690000, 0.563260000, 0.756930000, 0.894200000, 0.893470000, 26.288140000, 0.963870000, 0.945850000, 0.756930000, 0.563260000, 0.277690000, 0.000000000 }; double PDF3NB[] = { 0.000000000, 0.257616025, 0.551677676, 0.551677676, 1.142526340, 1.092702640, 24.771891800, 1.031855390, 1.105400690, 0.551677676, 0.551677676, 0.257616025, 0.000000000 }; double PDF4PB[] = { 0.000000000, 0.000000000, 0.551300347, 0.679214040, 0.946471989, 0.918402827, 23.770542200, 0.871592366, 0.870576794, 0.679214040, 0.551300347, 0.000000000, 0.000000000 }; PDPtr proton = eventGenerator()->getParticleData(ParticleID::pplus); PDPtr neutron = eventGenerator()->getParticleData(ParticleID::n0); PDPtr pbar = eventGenerator()->getParticleData(ParticleID::pbarminus); PDPtr nbar = eventGenerator()->getParticleData(ParticleID::nbar0); PDPtr pi0 = eventGenerator()->getParticleData(ParticleID::pi0); PDVector partons; partons.push_back(eventGenerator()->getParticleData(ParticleID::tbar)); partons.push_back(eventGenerator()->getParticleData(ParticleID::bbar)); partons.push_back(eventGenerator()->getParticleData(ParticleID::cbar)); partons.push_back(eventGenerator()->getParticleData(ParticleID::sbar)); partons.push_back(eventGenerator()->getParticleData(ParticleID::ubar)); partons.push_back(eventGenerator()->getParticleData(ParticleID::dbar)); partons.push_back(eventGenerator()->getParticleData(ParticleID::g)); partons.push_back(eventGenerator()->getParticleData(ParticleID::d)); partons.push_back(eventGenerator()->getParticleData(ParticleID::u)); partons.push_back(eventGenerator()->getParticleData(ParticleID::s)); partons.push_back(eventGenerator()->getParticleData(ParticleID::c)); partons.push_back(eventGenerator()->getParticleData(ParticleID::b)); partons.push_back(eventGenerator()->getParticleData(ParticleID::t)); PDFPtr pdf1 = eventGenerator()->getObject("/LHAPDF/CTEQ6ll"); assert(pdf1); for ( int i = 0; i < 13; ++i ) if ( !approx(pdf1->xfx(proton, partons[i], 100.0*GeV2, 0.001), PDF1P[i]) ) exit(1); for ( int i = 0; i < 13; ++i ) if ( !approx(pdf1->xfx(pbar, partons[i], 100.0*GeV2, 0.001), PDF1PB[i]) ) exit(1); for ( int i = 0; i < 13; ++i ) if ( !approx(pdf1->xfx(neutron, partons[i], 100.0*GeV2, 0.001), PDF1N[i]) ) exit(1); for ( int i = 0; i < 13; ++i ) if ( !approx(pdf1->xfx(nbar, partons[i], 100.0*GeV2, 0.001), PDF1NB[i]) ) exit(1); for ( int i = 0; i < 13; ++i ) if ( !approx(pdf1->xfvx(proton, partons[i], 100.0*GeV2, 0.001), PDFVP[i]) ) exit(1); for ( int i = 0; i < 13; ++i ) if ( !approx(pdf1->xfvx(pbar, partons[i], 100.0*GeV2, 0.001), PDFVPB[i]) ) exit(1); for ( int i = 0; i < 13; ++i ) if ( !approx(pdf1->xfvx(neutron, partons[i], 100.0*GeV2, 0.001), PDFVN[i]) ) exit(1); for ( int i = 0; i < 13; ++i ) if ( !approx(pdf1->xfvx(nbar, partons[i], 100.0*GeV2, 0.001), PDFVNB[i]) ) exit(1); PDFPtr pdf2 = eventGenerator()->getObject("/LHAPDF/MRST2007"); assert(pdf2); for ( int i = 0; i < 13; ++i ) if ( !approx(pdf2->xfx(neutron, partons[i], 100.0*GeV2, 0.001), PDF2N[i]) ) exit(1); PDFPtr pdf3 = eventGenerator()->getObject("/LHAPDF/CT09MC1"); assert(pdf3); for ( int i = 0; i < 13; ++i ) if ( !approx(pdf3->xfx(nbar, partons[i], 100.0*GeV2, 0.001), PDF3NB[i]) ) exit(1); PDFPtr pdf4 = eventGenerator()->getObject("/LHAPDF/CTEQ6ll4"); assert(pdf4); for ( int i = 0; i < 13; ++i ) if ( !approx(pdf4->xfx(pbar, partons[i], 100.0*GeV2, 0.001), PDF4PB[i]) ) exit(1); } diff --git a/src/TestLHAPDF.h b/src/TestLHAPDF.h --- a/src/TestLHAPDF.h +++ b/src/TestLHAPDF.h @@ -1,89 +1,89 @@ // -*- C++ -*- // // TestLHAPDF.h is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #ifndef ThePEG_TestLHAPDF_H #define ThePEG_TestLHAPDF_H // // This is the declaration of the TestLHAPDF class. // // CLASSDOC SUBSECTION Description: // // // // CLASSDOC SUBSECTION See also: // // .h, // .h. // #include "ThePEG/Repository/Main.h" namespace ThePEG { /** * Class derived from Main to do simple tests of the LHAPDF class. */ class TestLHAPDF: public Main { public: /** * Standard Init function used to initialize the interfaces. This is * where all the tests are done. */ static void Init(); private: /** * Describe a concrete class without persistent data. */ static NoPIOClassDescription initTestLHAPDF; /** * Private and non-existent assignment operator. */ TestLHAPDF & operator=(const TestLHAPDF &) = delete; }; } // CLASSDOC OFF #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ // The following template specialization informs ThePEG about the // base class of TestLHAPDF. template <> struct BaseClassTrait: public ClassTraitsType { typedef Main 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 { static string className() { return "ThePEG::TestLHAPDF"; } // Return the class name. static string library() { return "TestLHAPDF.so"; } // Return the name of the shared library to be loaded to get // access to this class and every other class it uses // (except the base class). }; /** @endcond */ } #endif /* ThePEG_TestLHAPDF_H */ diff --git a/src/runEventLoop.cc b/src/runEventLoop.cc --- a/src/runEventLoop.cc +++ b/src/runEventLoop.cc @@ -1,133 +1,133 @@ // -*- C++ -*- // // runEventLoop.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/StandardMatchers.h" #include "ThePEG/Utilities/Debug.h" #include "ThePEG/Utilities/DynamicLoader.h" #include "ThePEG/Utilities/Exception.h" #include "ThePEG/Vectors/HepMCConverter.h" #include "HepMC/GenEvent.h" namespace ThePEG { template<> struct HepMCTraits: public HepMCTraitsBase {}; } int main(int argc, char * argv[]) { using namespace ThePEG; // First we get some command-line arguments string run; long N = -1; long seed = 0; for ( int iarg = 1; iarg < argc; ++iarg ) { string arg = argv[iarg]; // Specifying a run file if ( arg == "-r" ) run = argv[++iarg]; // Append a path for the dynamic loader else if ( arg == "-l" ) DynamicLoader::appendPath(argv[++iarg]); else if ( arg.substr(0,2) == "-l" ) DynamicLoader::appendPath(arg.substr(2)); // Prepend a path for the dynamic loader else if ( arg == "-L" ) DynamicLoader::prependPath(argv[++iarg]); else if ( arg.substr(0,2) == "-L" ) DynamicLoader::prependPath(arg.substr(2)); // Set debug level else if ( arg == "-d" ) Debug::setDebug(atoi(argv[++iarg])); else if ( arg.substr(0,2) == "-d" ) Debug::setDebug(atoi(arg.substr(2).c_str())); // Set number of events else if ( arg == "-N" ) N = atoi(argv[++iarg]); else if ( arg.substr(0,2) == "-N" ) N = atoi(arg.substr(2).c_str()); // Set random seed else if ( arg == "-seed" ) seed = atoi(argv[++iarg]); // Print (out of date) help message else if ( arg == "-h" ) { cerr << "Usage: " << argv[0] << " [-d {debuglevel|-debugitem}] " << "[-l load-path] [-L first-load-path] run-file" << endl; return 3; } else // Any other argument is treated as a run file run = arg; } if ( Debug::level ) Debug::unmaskFpuErrors(); if ( run.empty() ) { cerr << "No run-file specified." << endl; return 1; } try { // Create a persistent stream and read in an OldEventGenerator from // the run file PersistentIStream is(run); EGPtr eg; is >> eg; breakThePEG(); if ( eg ) { if ( seed > 0 ) eg->setSeed(seed); // Initialize the Event generator eg->initialize(); // Get number of events if ( N < 0 ) N = eg->N(); // HERE IS THE MAIN EVENT LOOP for ( int ieve = 0; ieve < N; ++ieve ) { // Generate an event EventPtr event = eg->shoot(); // Convert to a HepMC::GenEvent HepMC::GenEvent * geneve = HepMCConverter::convert(*event); // Do whatever you want with the event here if ( ieve < 10 ) geneve->print(cout); // Don't forget to delete the HepMC::GenEvent (The // ThePEG::Event is automatically garbage collected) delete geneve; } // End the run eg->finalize(); } else std::cout << "eg = nil" << endl; } catch ( std::exception & e ) { cerr << e.what() << endl; return 1; } catch ( ... ) { breakThePEG(); cerr << "Unknown Exception\n"; return 2; } return 0; } diff --git a/src/runPartial.cc b/src/runPartial.cc --- a/src/runPartial.cc +++ b/src/runPartial.cc @@ -1,136 +1,136 @@ // -*- C++ -*- // // runPartial.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/ParticleData.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/EventRecord/Event.h" #include "ThePEG/Utilities/DynamicLoader.h" #include "ThePEG/Vectors/GenEventConverter.h" int main(int argc, char * argv[]) { using namespace ThePEG; string run; for ( int iarg = 1; iarg < argc; ++iarg ) { string arg = argv[iarg]; if ( arg == "-r" ) run = argv[++iarg]; else if ( arg == "-l" ) DynamicLoader::appendPath(argv[++iarg]); else if ( arg.substr(0,2) == "-l" ) DynamicLoader::appendPath(arg.substr(2)); else if ( arg == "-L" ) DynamicLoader::prependPath(argv[++iarg]); else if ( arg.substr(0,2) == "-L" ) DynamicLoader::prependPath(arg.substr(2)); else if ( arg == "-h" ) { cerr << "Usage: " << argv[0] << " [-l load-path] [-L first-load-path] run-file" << endl; return 3; } else run = arg; } if ( run.empty() ) { cerr << "No run-file specified." << endl; return 1; } try { PersistentIStream is(run); EGPtr eg; is >> eg; if ( !eg ) throw std::runtime_error("No generator found."); eg->initialize(); // Open a persistent stream and read an OldEventGenerator object // from it and initialize the Event generator. for ( int i = 0; i < 10; ++i ) { EventPtr event = new_ptr(Event(PPair())); StepPtr firstStep = event->newStep(); // Create an empty step. PPtr u = eg->getParticle(ParticleID::u); PPtr d = eg->getParticle(ParticleID::ubar); // Create a quark and an anti-quark. u->set3Momentum(Momentum3(ZERO, ZERO, 400.0*MeV)); d->set3Momentum(Momentum3(ZERO, ZERO, -400.0*MeV)); // Set the momentum of the quarks. u->antiColourNeighbour(d); d->colourNeighbour(u); // Setup their colour connections firstStep->addParticle(u); firstStep->addParticle(d); // Add the quarks to the first step PPtr p = eg->getParticle(ParticleID::pplus); p->set3Momentum(Momentum3(100.0*GeV, ZERO, ZERO)); firstStep->addParticle(p); // Sometimes, the string fragmentation routine needs to shuffle some // energy around, so we add an extra proton for this purpose. event = eg->partialEvent(event); // Generate the event starting from the first step. // event->removeParticle(p); // Remove the proton used for energy-momentum conservation. // vector products; // event->selectFinalState(inserter(products)); // Extract the final state particles. cout << *event; // Do something interesting with the event. CLHEPMC::GenEvent * geneve = GenEventConverter::convert(*event); geneve->print(cout); delete geneve; } for ( int i = 0; i < 10; ++i ) { EventPtr event = eg->shoot(); cout << *event; // Do something interesting with the event. using namespace CLHEPMC; CLHEPMC::GenEvent * geneve = GenEventConverter::convert(*event); geneve->print(cout); for ( GenEvent::particle_const_iterator it = geneve->particles_begin(); it != geneve->particles_end(); ++it ) { (**it).print(); } delete geneve; } eg->finalize(); // Tell the generator to write out statistics and stuff. } catch ( std::exception & e ) { cerr << e.what() << endl; return 1; } catch ( ... ) { cerr << "Unknown Exception\n"; return 2; } return 0; } diff --git a/src/runThePEG.cc b/src/runThePEG.cc --- a/src/runThePEG.cc +++ b/src/runThePEG.cc @@ -1,128 +1,128 @@ // -*- C++ -*- // // runThePEG.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/StandardMatchers.h" #include "ThePEG/Utilities/Debug.h" #include "ThePEG/Utilities/DebugItem.h" #include "ThePEG/Utilities/DynamicLoader.h" #include "ThePEG/Utilities/Exception.h" #include "ThePEG/Repository/Main.h" #include "ThePEG/Repository/Repository.h" int main(int argc, char * argv[]) { using namespace ThePEG; string run; long N = -1; long seed = 0; string mainclass; bool tics = false; bool resume = false; string tag = ""; string setupfile = ""; for ( int iarg = 1; iarg < argc; ++iarg ) { string arg = argv[iarg]; if ( arg == "-r" ) run = argv[++iarg]; else if ( arg == "-x" ) mainclass = argv[++iarg]; else if ( arg == "-m" ) setupfile = argv[++iarg]; else if ( arg == "-s" ) DynamicLoader::load(argv[++iarg]); else if ( arg.substr(0,2) == "-s" ) DynamicLoader::load(arg.substr(2)); else if ( arg == "-l" ) DynamicLoader::appendPath(argv[++iarg]); else if ( arg.substr(0,2) == "-l" ) DynamicLoader::appendPath(arg.substr(2)); else if ( arg == "-L" ) DynamicLoader::prependPath(argv[++iarg]); else if ( arg.substr(0,2) == "-L" ) DynamicLoader::prependPath(arg.substr(2)); else if ( arg == "-d" ) Debug::setDebug(atoi(argv[++iarg])); else if ( arg.substr(0,2) == "-d" ) Debug::setDebug(atoi(arg.substr(2).c_str())); else if ( arg.substr(0,2) == "-D" ) DebugItem::setDebugItem(arg.substr(2)); else if ( arg == "-N" ) N = atoi(argv[++iarg]); else if ( arg.substr(0,2) == "-N" ) N = atoi(arg.substr(2).c_str()); else if ( arg == "--seed" || arg == "-seed" ) seed = atol(argv[++iarg]); else if ( arg == "--tics" || arg == "-tics" ) tics = true; else if ( arg == "--resume" ) resume = true; else if ( arg == "-t" ) tag = argv[++iarg]; else if ( arg.substr(0,2) == "-t" ) tag = arg.substr(2); else if ( arg.substr(0,6) == "--tag=" ) tag = arg.substr(6); else if ( arg == "--help" || arg == "-h" ) { cerr << "Usage: " << argv[0] << " [-d {debuglevel|-debugitem}] " << "[-l load-path] [-L first-load-path] [-m setup-file] run-file" << endl; return 3; } else if ( arg == "-v" || arg == "--version" ) { cout << Repository::version() << endl; return 0; } else run = arg; } if ( Debug::level ) Debug::unmaskFpuErrors(); if ( run.empty() ) { cerr << "No run-file specified." << endl; return 1; } try { EGPtr eg; if ( run == "-" ) { PersistentIStream is(cin); is >> eg; } else { PersistentIStream is(run); is >> eg; } breakThePEG(); if ( !eg ) { cout << "Could not find or read the requested EventGenerator." << endl; return 1; } if ( setupfile.size() ) { string msg = Repository::modifyEventGenerator(*eg, setupfile, cout); if ( ! msg.empty() ) cerr << msg << '\n'; } if ( seed > 0 ) eg->setSeed(seed); if ( !tag.empty() ) eg->addTag(tag); if ( !mainclass.empty() ) { Main::arguments(vector(argv + 1, argv + argc)); Main::N(N); if ( !eg->loadMain(mainclass) ) std::cout << "Main class file '" << mainclass << "' not found." << endl; } else { eg->go(resume? -1: 1, N, tics); } } catch ( Exception & e ) { cerr << "Unexpected exception caught: " << e.what() << endl; e.handle(); return 1; } catch ( std::exception & e ) { cerr << "Unexpected exception caught: " << e.what() << endl; return 1; } catch ( ... ) { breakThePEG(); cerr << "Unknown Exception\n"; return 2; } return 0; } diff --git a/src/setupThePEG.cc b/src/setupThePEG.cc --- a/src/setupThePEG.cc +++ b/src/setupThePEG.cc @@ -1,159 +1,159 @@ // -*- C++ -*- // // setupThePEG.cc is a part of ThePEG - Toolkit for HEP Event Generation -// Copyright (C) 1999-2017 Leif Lonnblad +// Copyright (C) 1999-2019 Leif Lonnblad // // ThePEG is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // macro is passed in from -D compile flag #ifndef THEPEG_PKGLIBDIR #error Makefile.am needs to define THEPEG_PKGLIBDIR #endif #include "ThePEG/Repository/Repository.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/Utilities/Debug.h" #include "ThePEG/Utilities/Exception.h" #include "ThePEG/Utilities/DynamicLoader.h" int main(int argc, char * argv[]) { using namespace ThePEG; Debug::level = 1; // macro is passed in from -D compile flag string repo = string(THEPEG_PKGLIBDIR) + "/ThePEGDefaults.rpo"; string repout; string file; bool init = false; vector globlib; vector preread; vector appread; Repository repository; for ( int iarg = 1; iarg < argc; ++iarg ) { string arg = argv[iarg]; if ( arg == "-d" ) Debug::setDebug(atoi(argv[++iarg])); else if ( arg.substr(0,2) == "-d" ) Debug::setDebug(atoi(arg.substr(2).c_str())); else if ( arg == "-r" ) repo = argv[++iarg]; else if ( arg == "-o" ) repout = argv[++iarg]; else if ( arg == "--init" || arg == "-init" ) { init = true; Debug::level = 0; } else if ( arg == "--exitonerror" ) repository.exitOnError() = 1; else if ( arg == "-s" ) { DynamicLoader::load(argv[++iarg]); repository.globalLibraries().push_back(argv[iarg]); globlib.push_back(argv[iarg]); } else if ( arg.substr(0,2) == "-s" ) { DynamicLoader::load(arg.substr(2)); repository.globalLibraries().push_back(arg.substr(2)); globlib.push_back(arg.substr(2)); } else if ( arg == "-l" ) DynamicLoader::appendPath(argv[++iarg]); else if ( arg.substr(0,2) == "-l" ) DynamicLoader::appendPath(arg.substr(2)); else if ( arg == "-L" ) DynamicLoader::prependPath(argv[++iarg]); else if ( arg.substr(0,2) == "-L" ) DynamicLoader::prependPath(arg.substr(2)); else if ( arg == "-i" ) { Repository::appendReadDir(argv[++iarg]); appread.push_back(argv[iarg]); } else if ( arg.substr(0,2) == "-i" ) { Repository::appendReadDir(arg.substr(2)); appread.push_back(arg.substr(2)); } else if ( arg == "-I" ) { Repository::prependReadDir(argv[++iarg]); preread.push_back(argv[iarg]); } else if ( arg.substr(0,2) == "-I" ) { Repository::prependReadDir(arg.substr(2)); preread.push_back(arg.substr(2)); } else if ( arg == "-h" || arg == "--help" ) { cerr << "Usage: " << argv[0] << " {cmdfile} [-d {debuglevel|-debugitem}] [-r input-repository-file]" << " [-l load-path] [-L first-load-path]" << endl; return 3; } else if ( arg == "-v" || arg == "--version" ) { cout << Repository::version() << endl; return 0; } else file = arg; } if ( Debug::level ) Debug::unmaskFpuErrors(); try { if ( init ) { breakThePEG(); if ( repout.empty() ) repout = repo; else { string msg = repository.load(repo); if ( ! msg.empty() ) cerr << msg << '\n'; for ( unsigned int i = 0; i < globlib.size(); ++i ) repository.globalLibraries().push_back(globlib[i]); for ( unsigned int i = 0; i < appread.size(); ++i ) Repository::appendReadDir(appread[i]); for ( unsigned int i = 0; i < preread.size(); ++i ) Repository::prependReadDir(preread[i]); } { HoldFlag<> setup(InterfaceBase::NoReadOnly); if ( file.empty() ) file = "ThePEGDefaults.in"; string msg = repository.read(file, cout); if ( ! msg.empty() ) cerr << msg << '\n'; repository.update(); } repository.save(repout); } else { string msg = repository.load(repo); if ( ! msg.empty() ) cerr << msg << '\n'; for ( unsigned int i = 0; i < globlib.size(); ++i ) repository.globalLibraries().push_back(globlib[i]); for ( unsigned int i = 0; i < appread.size(); ++i ) Repository::appendReadDir(appread[i]); for ( unsigned int i = 0; i < preread.size(); ++i ) Repository::prependReadDir(preread[i]); breakThePEG(); if ( file.size() && file != "-" ) { if ( file == "--java" || file == "-java" ) repository.read(cin, cout, "-*-ready-*-\n"); else { string msg = repository.read(file, cout); if ( ! msg.empty() ) cerr << msg << '\n'; } } else { repository.read(cin, cout, "ThePEG> "); } } } catch ( Exception & e ) { cerr << "Unexpected exception caught: " << e.what() << endl; e.handle(); return 1; } catch ( std::exception & e ) { cerr << "Unexpected exception caught: " << e.what() << endl; return 1; } catch ( ... ) { cerr << "Unknown Exception\n"; return 2; } return 0; }