00001 // -*- C++ -*- 00002 #ifndef RIVET_Thrust_HH 00003 #define RIVET_Thrust_HH 00004 00005 #include "Rivet/Projection.hh" 00006 #include "Rivet/Projections/AxesDefinition.hh" 00007 #include "Rivet/Projections/FinalState.hh" 00008 #include "Rivet/Event.hh" 00009 00010 namespace Rivet { 00011 00012 00013 /** 00014 @brief Obtain the e+ e- thrust event shape, consisting of the thrust basis and the 00015 thrust scalar values in each direction (the thrust, thrust major and thrust 00016 minor). 00017 00018 @author Andy Buckley 00019 00020 The scalar (maximum) thrust is defined as 00021 \f[ 00022 T = \mathrm{max}_{\vec{n}} \frac{\sum_i \left|\vec{p}_i \cdot \vec{n} \right|}{\sum_i |\vec{p}_i|} 00023 \f], 00024 with the direction of the unit vector \f$ \vec{n} \f$ which maximises \f$ T \f$ 00025 being identified as the thrust axis. The unit vector which maximises the thrust 00026 scalar in the plane perpendicular to \f$ \vec{n} \f$ is the "thrust major" 00027 direction, and the vector perpendicular to both the thrust and thrust major directions 00028 is the thrust minor. Both the major and minor directions have associated thrust 00029 scalars. 00030 00031 Thrust calculations have particularly simple forms for less than 4 particles, and 00032 in those cases this projection is computationally minimal. For 4 or more particles, 00033 a more general calculation must be carried out, based on the Brandt/Dahmen method 00034 from Z. Phys. C1 (1978). While a polynomial improvement on the exponential scaling 00035 of the naive method, this algorithm scales asymptotically as 00036 \f$ \mathcal{O}\left( n^3 \right) \f$. Be aware that the thrust may easily be the 00037 most computationally demanding projection in Rivet for large events! 00038 00039 The Rivet implementation of thrust is based heavily on Stefan Gieseke's Herwig++ 00040 re-coding of the 'tasso' code from HERWIG. 00041 00042 NB. special case with >= 4 coplanar particles will still fail. 00043 NB. Thrust assumes all momenta are in the CoM system: no explicit boost is performed. 00044 This can be dealt with by appropriate choice of the supplied FinalState. 00045 */ 00046 class Thrust : public AxesDefinition { 00047 public: 00048 00049 /// Constructor. 00050 Thrust(const FinalState& fsp) 00051 : _calculatedThrust(false) 00052 { 00053 setName("Thrust"); 00054 addProjection(fsp, "FS"); 00055 } 00056 00057 /// Clone on the heap. 00058 virtual const Projection* clone() const { 00059 return new Thrust(*this); 00060 } 00061 00062 protected: 00063 00064 /// Perform the projection on the Event 00065 void project(const Event& e) { 00066 const vector<Particle> ps 00067 = applyProjection<FinalState>(e, "FS").particles(); 00068 calc(ps); 00069 } 00070 00071 /// Compare projections 00072 int compare(const Projection& p) const { 00073 return mkNamedPCmp(p, "FS"); 00074 } 00075 00076 00077 public: 00078 00079 ///@{ Thrust scalar accessors 00080 /// The thrust scalar, \f$ T \f$, (maximum thrust). 00081 double thrust() const { return _thrusts[0]; } 00082 /// The thrust major scalar, \f$ M \f$, (thrust along thrust major axis). 00083 double thrustMajor() const { return _thrusts[1]; } 00084 /// The thrust minor scalar, \f$ m \f$, (thrust along thrust minor axis). 00085 double thrustMinor() const { return _thrusts[2]; } 00086 /// The oblateness, \f$ O = M - m \f$ . 00087 double oblateness() const { return _thrusts[1] - _thrusts[2]; } 00088 ///@} 00089 00090 ///@{ Thrust axis accessors 00091 /// The thrust axis. 00092 const Vector3& thrustAxis() const { return _thrustAxes[0]; } 00093 /// The thrust major axis (axis of max thrust perpendicular to thrust axis). 00094 const Vector3& thrustMajorAxis() const { return _thrustAxes[1]; } 00095 /// The thrust minor axis (axis perpendicular to thrust and thrust major). 00096 const Vector3& thrustMinorAxis() const { return _thrustAxes[2]; } 00097 ///@} 00098 00099 ///@{ AxesDefinition axis accessors. 00100 const Vector3& axis1() const { return thrustAxis(); } 00101 const Vector3& axis2() const { return thrustMajorAxis(); } 00102 const Vector3& axis3() const { return thrustMinorAxis(); } 00103 ///@} 00104 00105 00106 public: 00107 00108 /// @name Direct methods 00109 /// Ways to do the calculation directly, without engaging the caching system 00110 //@{ 00111 00112 /// Manually calculate the thrust, without engaging the caching system 00113 void calc(const FinalState& fs); 00114 00115 /// Manually calculate the thrust, without engaging the caching system 00116 void calc(const vector<Particle>& fsparticles); 00117 00118 /// Manually calculate the thrust, without engaging the caching system 00119 void calc(const vector<FourMomentum>& fsmomenta); 00120 00121 /// Manually calculate the thrust, without engaging the caching system 00122 void calc(const vector<Vector3>& threeMomenta); 00123 00124 //@} 00125 00126 00127 private: 00128 00129 /// The thrust scalars. 00130 vector<double> _thrusts; 00131 00132 /// The thrust axes. 00133 vector<Vector3> _thrustAxes; 00134 00135 /// Caching flag to avoid costly recalculations. 00136 bool _calculatedThrust; 00137 00138 private: 00139 00140 /// Explicitly calculate the thrust values. 00141 void _calcThrust(const vector<Vector3>& fsmomenta); 00142 00143 }; 00144 00145 } 00146 00147 #endif