Vector4.hh

Go to the documentation of this file.
00001 #ifndef RIVET_MATH_VECTOR4
00002 #define RIVET_MATH_VECTOR4
00003 
00004 #include "Rivet/Math/MathHeader.hh"
00005 #include "Rivet/Math/MathUtils.hh"
00006 #include "Rivet/Math/VectorN.hh"
00007 #include "Rivet/Math/Vector3.hh"
00008 
00009 namespace Rivet {
00010 
00011 
00012   class FourVector;
00013   class FourMomentum;
00014   class LorentzTransform;
00015   typedef FourVector Vector4;
00016   FourVector transform(const LorentzTransform& lt, const FourVector& v4);
00017 
00018 
00019   /// @brief Specialisation of VectorN to a general (non-momentum) Lorentz 4-vector.
00020   class FourVector : public Vector<4> {
00021     friend FourVector multiply(const double a, const FourVector& v);
00022     friend FourVector multiply(const FourVector& v, const double a);
00023     friend FourVector add(const FourVector& a, const FourVector& b);
00024     friend FourVector transform(const LorentzTransform& lt, const FourVector& v4);
00025 
00026   public:
00027     FourVector() : Vector<4>() { }
00028 
00029     template<typename V4>
00030     FourVector(const V4& other) {
00031       this->setT(other.t());
00032       this->setX(other.x());
00033       this->setY(other.y());
00034       this->setZ(other.z());
00035     }
00036 
00037     FourVector(const Vector<4>& other)
00038     : Vector<4>(other) { }
00039 
00040     FourVector(const double t, const double x, const double y, const double z) {
00041       this->setT(t);
00042       this->setX(x);
00043       this->setY(y);
00044       this->setZ(z);
00045     }
00046 
00047     virtual ~FourVector() { }
00048 
00049   public:
00050     double t() const { return get(0); }
00051     double x() const { return get(1); }
00052     double y() const { return get(2); }
00053     double z() const { return get(3); }
00054     FourVector& setT(const double t) { set(0, t); return *this; }
00055     FourVector& setX(const double x) { set(1, x); return *this; }
00056     FourVector& setY(const double y) { set(2, y); return *this; }
00057     FourVector& setZ(const double z) { set(3, z); return *this; }
00058 
00059     double invariant() const {
00060       // Done this way for numerical precision
00061       return (t() + z())*(t() - z()) - x()*x() - y()*y();
00062     }
00063 
00064     double angle(const FourVector& v) const {
00065       return vector3().angle( v.vector3() );
00066     }
00067 
00068     double angle(const Vector3& v3) const {
00069       return vector3().angle(v3);
00070     }
00071 
00072     double polarRadius2() const {
00073       return vector3().polarRadius2();
00074     }
00075 
00076     /// Synonym for polarRadius2
00077     double perp2() const {
00078       return vector3().perp2();
00079     }
00080 
00081     /// Synonym for polarRadius2
00082     double rho2() const {
00083       return vector3().rho2();
00084     }
00085 
00086     double polarRadius() const {
00087       return vector3().polarRadius();
00088     }
00089 
00090     /// Synonym for polarRadius
00091     double perp() const {
00092       return vector3().perp();
00093     }
00094 
00095     /// Synonym for polarRadius
00096     double rho() const {
00097       return vector3().rho();
00098     }
00099 
00100     /// Angle subtended by the 3-vector's projection in x-y and the x-axis.
00101     double azimuthalAngle(const PhiMapping mapping = ZERO_2PI) const {
00102       return vector3().azimuthalAngle(mapping);
00103     }
00104 
00105     /// Synonym for azimuthalAngle.
00106     double phi(const PhiMapping mapping = ZERO_2PI) const {
00107       return vector3().phi(mapping);
00108     }
00109 
00110     /// Angle subtended by the 3-vector and the z-axis.
00111     double polarAngle() const {
00112       return vector3().polarAngle();
00113     }
00114 
00115     /// Synonym for polarAngle.
00116     double theta() const {
00117       return vector3().theta();
00118     }
00119 
00120     double pseudorapidity() const {
00121       return vector3().pseudorapidity();
00122     }
00123 
00124     /// Synonym for pseudorapidity.
00125     double eta() const {
00126       return vector3().eta();
00127     }
00128 
00129     /// Get the spatial part of the 4-vector as a 3-vector.
00130     Vector3 vector3() const {
00131       return Vector3(get(1), get(2), get(3));
00132     }
00133 
00134   public:
00135     /// Contract two 4-vectors, with metric signature (+ - - -).
00136     double contract(const FourVector& v) const {
00137       const double result = t()*v.t() - x()*v.x() - y()*v.y() - z()*v.z();
00138       return result;
00139     }
00140 
00141     /// Contract two 4-vectors, with metric signature (+ - - -).
00142     double dot(const FourVector& v) const {
00143       return contract(v);
00144     }
00145 
00146     /// Contract two 4-vectors, with metric signature (+ - - -).
00147     double operator*(const FourVector& v) const {
00148       return contract(v);
00149     }
00150 
00151     /// Multiply by a scalar
00152     FourVector& operator*=(double a) {
00153       _vec = multiply(a, *this)._vec;
00154       return *this;
00155     }
00156 
00157     /// Divide by a scalar
00158     FourVector& operator/=(double a) {
00159       _vec = multiply(1.0/a, *this)._vec;
00160       return *this;
00161     }
00162 
00163     FourVector& operator+=(const FourVector& v) {
00164       _vec = add(*this, v)._vec;
00165       return *this;
00166     }
00167 
00168     FourVector& operator-=(const FourVector& v) {
00169       _vec = add(*this, -v)._vec;
00170       return *this;
00171     }
00172 
00173     FourVector operator-() const {
00174       FourVector result;
00175       result._vec = -_vec;
00176       return result;
00177     }
00178 
00179   };
00180 
00181 
00182   /// Contract two 4-vectors, with metric signature (+ - - -).
00183   inline double contract(const FourVector& a, const FourVector& b) {
00184     return a.contract(b);
00185   }
00186 
00187   /// Contract two 4-vectors, with metric signature (+ - - -).
00188   inline double dot(const FourVector& a, const FourVector& b) {
00189     return contract(a, b);
00190   }
00191 
00192   inline FourVector multiply(const double a, const FourVector& v) {
00193     FourVector result;
00194     result._vec = a * v._vec;
00195     return result;
00196   }
00197 
00198   inline FourVector multiply(const FourVector& v, const double a) {
00199     return multiply(a, v);
00200   }
00201 
00202   inline FourVector operator*(const double a, const FourVector& v) {
00203     return multiply(a, v);
00204   }
00205 
00206   inline FourVector operator*(const FourVector& v, const double a) {
00207     return multiply(a, v);
00208   }
00209 
00210   inline FourVector operator/(const FourVector& v, const double a) {
00211     return multiply(1.0/a, v);
00212   }
00213 
00214   inline FourVector add(const FourVector& a, const FourVector& b) {
00215     FourVector result;
00216     result._vec = a._vec + b._vec;
00217     return result;
00218   }
00219 
00220   inline FourVector operator+(const FourVector& a, const FourVector& b) {
00221     return add(a, b);
00222   }
00223 
00224   inline FourVector operator-(const FourVector& a, const FourVector& b) {
00225     return add(a, -b);
00226   }
00227 
00228   /// Calculate the Lorentz self-invariant of a 4-vector.
00229   /// \f$ v_\mu v^\mu = g_{\mu\nu} x^\mu x^\nu \f$.
00230   inline double invariant(const FourVector& lv) {
00231     return lv.invariant();
00232   }
00233 
00234   /// Angle (in radians) between spatial parts of two Lorentz vectors.
00235   inline double angle(const FourVector& a, const FourVector& b) {
00236     return a.angle(b);
00237   }
00238 
00239   /// Angle (in radians) between spatial parts of two Lorentz vectors.
00240   inline double angle(const Vector3& a, const FourVector& b) {
00241     return angle( a, b.vector3() );
00242   }
00243 
00244   /// Angle (in radians) between spatial parts of two Lorentz vectors.
00245   inline double angle(const FourVector& a, const Vector3& b) {
00246     return a.angle(b);
00247   }
00248 
00249   /// Calculate transverse length sq. \f$ \rho^2 \f$ of a Lorentz vector.
00250   inline double polarRadius2(const FourVector& v) {
00251     return v.polarRadius2();
00252   }
00253   /// Synonym for polarRadius2.
00254   inline double perp2(const FourVector& v) {
00255     return v.perp2();
00256   }
00257   /// Synonym for polarRadius2.
00258   inline double rho2(const FourVector& v) {
00259     return v.rho2();
00260   }
00261 
00262   /// Calculate transverse length \f$ \rho \f$ of a Lorentz vector.
00263   inline double polarRadius(const FourVector& v) {
00264     return v.polarRadius();
00265   }
00266   /// Synonym for polarRadius.
00267   inline double perp(const FourVector& v) {
00268     return v.perp();
00269   }
00270   /// Synonym for polarRadius.
00271   inline double rho(const FourVector& v) {
00272     return v.rho();
00273   }
00274 
00275   /// Calculate azimuthal angle of a Lorentz vector.
00276   inline double azimuthalAngle(const FourVector& v, const PhiMapping mapping = ZERO_2PI) {
00277     return v.azimuthalAngle(mapping);
00278   }
00279   /// Synonym for azimuthalAngle.
00280   inline double phi(const FourVector& v, const PhiMapping mapping = ZERO_2PI) {
00281     return v.phi(mapping);
00282   }
00283 
00284 
00285   /// Calculate polar angle of a Lorentz vector.
00286   inline double polarAngle(const FourVector& v) {
00287     return v.polarAngle();
00288   }
00289   /// Synonym for polarAngle.
00290   inline double theta(const FourVector& v) {
00291     return v.theta();
00292   }
00293 
00294   /// Calculate pseudorapidity of a Lorentz vector.
00295   inline double pseudorapidity(const FourVector& v) {
00296     return v.pseudorapidity();
00297   }
00298   /// Synonym for pseudorapidity.
00299   inline double eta(const FourVector& v) {
00300     return v.eta();
00301   }
00302 
00303 
00304 
00305   ////////////////////////////////////////////////
00306 
00307 
00308 
00309   /// Specialized version of the FourVector with momentum/energy functionality.
00310   class FourMomentum : public FourVector {
00311   public:
00312     FourMomentum() { }
00313 
00314     template<typename V4>
00315     FourMomentum(const V4& other) {
00316       this->setE(other.t());
00317       this->setPx(other.x());
00318       this->setPy(other.y());
00319       this->setPz(other.z());
00320     }
00321 
00322     FourMomentum(const Vector<4>& other)
00323       : FourVector(other) { }
00324 
00325     FourMomentum(const double E, const double px, const double py, const double pz) {
00326       this->setE(E);
00327       this->setPx(px);
00328       this->setPy(py);
00329       this->setPz(pz);
00330     }
00331 
00332     ~FourMomentum() {}
00333 
00334   public:
00335     /// Get energy \f$ E \f$ (time component of momentum).
00336     double E() const { return t(); }
00337 
00338     /// Get 3-momentum part, \f$ p \f$.
00339     Vector3 p() const { return vector3(); }
00340 
00341     /// Get x-component of momentum \f$ p_x \f$.
00342     double px() const { return x(); }
00343 
00344     /// Get y-component of momentum \f$ p_y \f$.
00345     double py() const { return y(); }
00346 
00347     /// Get z-component of momentum \f$ p_z \f$.
00348     double pz() const { return z(); }
00349 
00350     /// Set energy \f$ E \f$ (time component of momentum).
00351     FourMomentum& setE(double E)   { setT(E); return *this; }
00352 
00353     /// Set x-component of momentum \f$ p_x \f$.
00354     FourMomentum& setPx(double px) { setX(px); return *this; }
00355 
00356     /// Set y-component of momentum \f$ p_y \f$.
00357     FourMomentum& setPy(double py) { setY(py); return *this; }
00358 
00359     /// Set z-component of momentum \f$ p_z \f$.
00360     FourMomentum& setPz(double pz) { setZ(pz); return *this; }
00361 
00362     /// Get squared mass \f$ m^2 = E^2 - p^2 \f$ (the Lorentz self-invariant).
00363     double mass2() const {
00364       return invariant();
00365     }
00366 
00367     /// Get mass \f$ m = \sqrt{E^2 - p^2} \f$ (the Lorentz self-invariant).
00368     double mass() const {
00369       assert(Rivet::isZero(mass2()) || mass2() > 0);
00370       if (Rivet::isZero(mass2())) {
00371         return 0.0;
00372       } else {
00373         return sqrt(mass2());
00374       }
00375     }
00376 
00377     /// Calculate rapidity.
00378     double rapidity() const {
00379       return 0.5 * std::log( (E() + pz()) / (E() - pz()) );
00380     }
00381 
00382     /// Calculate squared transverse momentum \f$ p_T^2 \f$.
00383     double pT2() const {
00384       return vector3().polarRadius2();
00385     }
00386 
00387     /// Calculate transverse momentum \f$ p_T \f$.
00388     double pT() const {
00389       return sqrt(pT2());
00390     }
00391 
00392     /// Calculate transverse energy \f$ E_T^2 = E^2 \sin^2{\theta} \f$.
00393     double Et2() const {
00394       return Et() * Et();
00395     }
00396 
00397     /// Calculate transverse energy \f$ E_T = E \sin{\theta} \f$.
00398     double Et() const {
00399       return E() * sin(polarAngle());
00400     }
00401 
00402     /// Calculate boost vector (in units of \f$ \beta \f$).
00403     Vector3 boostVector() const {
00404       // const Vector3 p3 = vector3();
00405       // const double m2 = mass2();
00406       // if (Rivet::isZero(m2)) return p3.unit();
00407       // else {
00408       //   // Could also do this via beta = tanh(rapidity), but that's
00409       //   // probably more messy from a numerical hygiene point of view.
00410       //   const double p2 = p3.mod2();
00411       //   const double beta = sqrt( p2 / (m2 + p2) );
00412       //   return beta * p3.unit();
00413       // }
00414       /// @todo Be careful about c=1 convention...
00415       return Vector3(px()/E(), py()/E(), pz()/E());
00416     }
00417 
00418     /// struct for sorting by increasing energy
00419 
00420     struct byEAscending{
00421       bool operator()(const FourMomentum &left, const FourMomentum &right) const{
00422         double pt2left = left.E();
00423         double pt2right = right.E();
00424         return pt2left < pt2right;
00425       }
00426 
00427       bool operator()(const FourMomentum *left, const FourMomentum *right) const{
00428         return (*this)(left, right);
00429       }
00430     };
00431 
00432     /// struct for sorting by decreasing energy
00433 
00434     struct byEDescending{
00435       bool operator()(const FourMomentum &left, const FourMomentum &right) const{
00436         return byEAscending()(right, left);
00437       }
00438 
00439       bool operator()(const FourMomentum *left, const FourVector *right) const{
00440         return (*this)(left, right);
00441       }
00442     };
00443 
00444   };
00445 
00446 
00447   /// Get squared mass \f$ m^2 = E^2 - p^2 \f$ (the Lorentz self-invariant) of a momentum 4-vector.
00448   inline double mass2(const FourMomentum& v) {
00449     return v.mass2();
00450   }
00451 
00452   /// Get mass \f$ m = \sqrt{E^2 - p^2} \f$ (the Lorentz self-invariant) of a momentum 4-vector.
00453   inline double mass(const FourMomentum& v) {
00454     return v.mass();
00455   }
00456 
00457   /// Calculate rapidity of a momentum 4-vector.
00458   inline double rapidity(const FourMomentum& v) {
00459     return v.rapidity();
00460   }
00461 
00462   /// Calculate squared transverse momentum \f$ p_T^2 \f$ of a momentum 4-vector.
00463   inline double pT2(const FourMomentum& v) {
00464     return v.pT2();
00465   }
00466 
00467   /// Calculate transverse momentum \f$ p_T \f$ of a momentum 4-vector.
00468   inline double pT(const FourMomentum& v) {
00469     return v.pT();
00470   }
00471 
00472   /// Calculate transverse energy squared, \f$ E_T^2 = E^2 \sin^2{\theta} \f$ of a momentum 4-vector.
00473   inline double Et2(const FourMomentum& v) {
00474     return v.Et2();}
00475 
00476   /// Calculate transverse energy \f$ E_T = E \sin{\theta} \f$ of a momentum 4-vector.
00477   inline double Et(const FourMomentum& v) {
00478     return v.Et();
00479   }
00480 
00481   /// Calculate velocity boost vector of a momentum 4-vector.
00482   inline Vector3 boostVector(const FourMomentum& v) {
00483     return v.boostVector();
00484   }
00485 
00486 
00487   //////////////////////////////////////////////////////
00488 
00489 
00490   /// Calculate the 2D rapidity-azimuthal ("eta-phi") distance between two
00491   /// four-vectors. There is a scheme ambiguity for momentum-type four vectors
00492   /// as to whether the pseudorapidity (a purely geometric concept) or the
00493   /// rapidity (a relativistic energy-momentum quantity) is to be used: this can
00494   /// be chosen via the optional scheme parameter, which is discouraged in this
00495   /// case since @c RAPIDITY is only a valid option for vectors whose type is
00496   /// really the FourMomentum derived class.
00497   inline double deltaR(const FourVector& a, const FourVector& b,
00498                        RapScheme scheme = PSEUDORAPIDITY) {
00499     switch (scheme) {
00500     case PSEUDORAPIDITY :
00501       return deltaR(a.vector3(), b.vector3());
00502     case RAPIDITY:
00503       {
00504         const FourMomentum* ma = dynamic_cast<const FourMomentum*>(&a);
00505         const FourMomentum* mb = dynamic_cast<const FourMomentum*>(&b);
00506         if (!ma || !mb) {
00507           string err = "deltaR with scheme RAPIDITY, can be called with FourMomenta only";
00508           throw std::runtime_error(err);
00509         }
00510         return deltaR(*ma, *mb, scheme);
00511       }
00512     default:
00513       throw std::runtime_error("The specified deltaR scheme is not yet implemented");
00514     }
00515   }
00516 
00517 
00518   inline double deltaR(const FourVector& v,
00519                        double eta2, double phi2,
00520                        RapScheme scheme = PSEUDORAPIDITY) {
00521     switch (scheme) {
00522     case PSEUDORAPIDITY :
00523       return deltaR(v.vector3(), eta2, phi2);
00524     case RAPIDITY:
00525       {
00526         const FourMomentum* mv = dynamic_cast<const FourMomentum*>(&v);
00527         if (!mv) {
00528           string err = "deltaR with scheme RAPIDITY, can be called with FourMomenta only";
00529           throw std::runtime_error(err);
00530         }
00531         return deltaR(*mv, eta2, phi2, scheme);
00532       }
00533     default:
00534       throw std::runtime_error("The specified deltaR scheme is not yet implemented");
00535     }
00536   }
00537 
00538 
00539   inline double deltaR(double eta1, double phi1,
00540                        const FourVector& v,
00541                        RapScheme scheme = PSEUDORAPIDITY) {
00542     switch (scheme) {
00543     case PSEUDORAPIDITY :
00544       return deltaR(eta1, phi1, v.vector3());
00545     case RAPIDITY:
00546       {
00547         const FourMomentum* mv = dynamic_cast<const FourMomentum*>(&v);
00548         if (!mv) {
00549           string err = "deltaR with scheme RAPIDITY, can be called with FourMomenta only";
00550           throw std::runtime_error(err);
00551         }
00552         return deltaR(eta1, phi1, *mv, scheme);
00553       }
00554     default:
00555       throw std::runtime_error("The specified deltaR scheme is not yet implemented");
00556     }
00557   }
00558 
00559 
00560   /// Calculate the 2D rapidity-azimuthal ("eta-phi") distance between two
00561   /// four-vectors. There is a scheme ambiguity for momentum-type four vectors
00562   /// as to whether the pseudorapidity (a purely geometric concept) or the
00563   /// rapidity (a relativistic energy-momentum quantity) is to be used: this can
00564   /// be chosen via the optional scheme parameter.
00565   inline double deltaR(const FourMomentum& a, const FourMomentum& b,
00566                        RapScheme scheme = PSEUDORAPIDITY) {
00567     switch (scheme) {
00568     case PSEUDORAPIDITY:
00569       return deltaR(a.vector3(), b.vector3());
00570     case RAPIDITY:
00571       return deltaR(a.rapidity(), a.azimuthalAngle(), b.rapidity(), b.azimuthalAngle());
00572     default:
00573       throw std::runtime_error("The specified deltaR scheme is not yet implemented");
00574     }
00575   }
00576 
00577   inline double deltaR(const FourMomentum& v,
00578                        double eta2, double phi2,
00579                        RapScheme scheme = PSEUDORAPIDITY) {
00580     switch (scheme) {
00581     case PSEUDORAPIDITY:
00582       return deltaR(v.vector3(), eta2, phi2);
00583     case RAPIDITY:
00584       return deltaR(v.rapidity(), v.azimuthalAngle(), eta2, phi2);
00585     default:
00586       throw std::runtime_error("The specified deltaR scheme is not yet implemented");
00587     }
00588   }
00589 
00590 
00591   inline double deltaR(double eta1, double phi1,
00592                        const FourMomentum& v,
00593                        RapScheme scheme = PSEUDORAPIDITY) {
00594     switch (scheme) {
00595     case PSEUDORAPIDITY:
00596       return deltaR(eta1, phi1, v.vector3());
00597     case RAPIDITY:
00598       return deltaR(eta1, phi1, v.rapidity(), v.azimuthalAngle());
00599     default:
00600       throw std::runtime_error("The specified deltaR scheme is not yet implemented");
00601     }
00602   }
00603 
00604 
00605   //////////////////////////////////////////////////////
00606 
00607 
00608   /// Render a 4-vector as a string.
00609   inline const string toString(const FourVector& lv) {
00610     ostringstream out;
00611     out << "("  << (fabs(lv.t()) < 1E-30 ? 0.0 : lv.t())
00612         << "; " << (fabs(lv.x()) < 1E-30 ? 0.0 : lv.x())
00613         << ", " << (fabs(lv.y()) < 1E-30 ? 0.0 : lv.y())
00614         << ", " << (fabs(lv.z()) < 1E-30 ? 0.0 : lv.z())
00615         << ")";
00616     return out.str();
00617   }
00618 
00619   /// Write a 4-vector to an ostream.
00620   inline std::ostream& operator<<(std::ostream& out, const FourVector& lv) {
00621     out << toString(lv);
00622     return out;
00623   }
00624 
00625 
00626 }
00627 
00628 #endif