Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-08-06 09:24:15

0001 // -*- C++ -*-
0002 //
0003 // SpinorHelicity.h is a part of Herwig - A multi-purpose Monte Carlo event generator
0004 // Copyright (C) 2002-2019 The Herwig Collaboration
0005 //
0006 // Herwig is licenced under version 3 of the GPL, see COPYING for details.
0007 // Please respect the MCnet academic guidelines, see GUIDELINES for details.
0008 //
0009 #ifndef HERWIG_SpinorHelicity_H
0010 #define HERWIG_SpinorHelicity_H
0011 
0012 #include "ThePEG/Config/Complex.h"
0013 #include "ThePEG/Vectors/LorentzVector.h"
0014 
0015 #include <boost/operators.hpp>
0016 
0017 namespace Herwig {
0018 
0019 using namespace ThePEG;
0020 
0021 namespace SpinorHelicity {
0022 
0023   /**
0024    * \ingroup Matchbox
0025    * \author Simon Platzer
0026    *
0027    * \brief Tag for |p>
0028    *
0029    */
0030   struct PlusSpinorTag {};
0031 
0032   /**
0033    * \ingroup Matchbox
0034    * \author Simon Platzer
0035    *
0036    * \brief Tag for |p]
0037    *
0038    */
0039   struct MinusSpinorTag {};
0040 
0041   /**
0042    * \ingroup Matchbox
0043    * \author Simon Platzer
0044    *
0045    * \brief Tag for <p|
0046    *
0047    */
0048   struct PlusConjugateSpinorTag {};
0049 
0050   /**
0051    * \ingroup Matchbox
0052    * \author Simon Platzer
0053    *
0054    * \brief Tag for [p|
0055    *
0056    */
0057   struct MinusConjugateSpinorTag {};
0058 
0059   /**
0060    * \ingroup Matchbox
0061    * \author Simon Platzer
0062    *
0063    * \brief Helpers for commonly encountered types.
0064    *
0065    */
0066   template<class Value>
0067   struct SpinorMultiplicationTraits {
0068 
0069     typedef decltype(sqr(std::declval<Value>())) ResultType;
0070     typedef complex<ResultType> ComplexResultType;
0071     typedef LorentzVector<ComplexResultType> ComplexVectorResultType;
0072 
0073   };
0074 
0075   /**
0076    * \ingroup Matchbox
0077    * \author Simon Platzer
0078    *
0079    * \brief Helpers for Weyl spinors
0080    *
0081    */
0082   template<class Type>
0083   struct WeylSpinorTraits;
0084 
0085   // specialize for |p>
0086   template<>
0087   struct WeylSpinorTraits<PlusSpinorTag> {
0088 
0089     template<class Value, class MValue>
0090     static pair<complex<Value>,complex<Value> > 
0091     components(const LorentzVector<MValue>& p) {
0092       if ( p.t() < ZERO ) {
0093     pair<complex<Value>,complex<Value> > res = 
0094       components<Value,MValue>(-p);
0095   // do not revert to *=, breaks with XCode 5.1
0096     res.first = res.first * Complex(0.,1.);
0097     res.second = res.second * Complex(0.,1.);
0098     return res;
0099       }
0100       Energy pPlus = p.t() + p.x();
0101       if ( abs(pPlus) < 1.e-10 * GeV ) {
0102     return make_pair(complex<Value>(ZERO),
0103              complex<Value>(sqrt(2.*p.t())));
0104       }
0105       return make_pair(complex<Value>(sqrt(pPlus)),
0106                complex<Value>(p.z()/sqrt(pPlus),p.y()/sqrt(pPlus)));
0107     }
0108 
0109   };
0110 
0111   // specialize for |p]
0112   template<>
0113   struct WeylSpinorTraits<MinusSpinorTag> {
0114 
0115     template<class Value, class MValue>
0116     static pair<complex<Value>,complex<Value> > 
0117     components(const LorentzVector<MValue>& p) {
0118       if ( p.t() < ZERO ) {
0119     pair<complex<Value>,complex<Value> > res = 
0120       components<Value,MValue>(-p);
0121   // do not revert to *=, breaks with XCode 5.1  
0122     res.first = res.first * Complex(0.,1.);
0123     res.second = res.second * Complex(0.,1.);
0124     return res;
0125       }
0126       Energy pPlus = p.t() + p.x();
0127       if ( abs(pPlus) < 1.e-10 * GeV ) {
0128     return make_pair(complex<Value>(sqrt(2.*p.t())),
0129              complex<Value>(ZERO));
0130       }
0131       return make_pair(complex<Value>(p.z()/sqrt(pPlus),-p.y()/sqrt(pPlus)),
0132                -complex<Value>(sqrt(pPlus)));
0133     }
0134 
0135   };
0136 
0137   // specialize for <p|
0138   template<>
0139   struct WeylSpinorTraits<PlusConjugateSpinorTag> {
0140 
0141     typedef PlusSpinorTag ConjugateSpinorTag;
0142     typedef MinusSpinorTag BarSpinorTag;
0143 
0144     template<class Value, class MValue>
0145     static pair<complex<Value>,complex<Value> > 
0146     components(const LorentzVector<MValue>& p) {
0147       pair<complex<Value>,complex<Value> > res =
0148     WeylSpinorTraits<PlusSpinorTag>::template components<Value>(p);
0149       res.first = -res.first;
0150       swap(res.first,res.second);
0151       return res;
0152     }
0153 
0154   };
0155 
0156   // specialize for [p|
0157   template<>
0158   struct WeylSpinorTraits<MinusConjugateSpinorTag> {
0159 
0160     typedef MinusSpinorTag ConjugateSpinorTag;
0161     typedef PlusSpinorTag BarSpinorTag;
0162 
0163     template<class Value, class MValue>
0164     static pair<complex<Value>,complex<Value> > 
0165     components(const LorentzVector<MValue>& p) {
0166       pair<complex<Value>,complex<Value> > res =
0167     WeylSpinorTraits<MinusSpinorTag>::template components<Value>(p);
0168       res.second = -res.second;
0169       swap(res.first,res.second);
0170       return res;
0171     }
0172 
0173   };
0174 
0175   /**
0176    * \ingroup Matchbox
0177    * \author Simon Platzer
0178    *
0179    * \brief Base class for Weyl spinors
0180    *
0181    */
0182   template<class Type, class Value>
0183   class WeylSpinor {
0184 
0185   public:
0186 
0187     typedef complex<Value> ComplexType;
0188     typedef pair<ComplexType,ComplexType> ComponentsType;
0189     typedef Type Tag;
0190     typedef WeylSpinorTraits<Tag> Traits;
0191     typedef Value ValueType;
0192 
0193   private:
0194 
0195     /**
0196      * The components
0197      */
0198     ComponentsType theComponents;
0199 
0200   public:
0201 
0202     /**
0203      * Construct from components
0204      */
0205     explicit WeylSpinor(const ComponentsType& c = ComponentsType())
0206       : theComponents(c) {}
0207 
0208     /**
0209      * Construct from momentum
0210      */
0211     template<class MValue>
0212     explicit WeylSpinor(const LorentzVector<MValue>& p)
0213       : theComponents(Traits::template components<Value>(p)) {}
0214 
0215     /**
0216      * Return the components.
0217      */
0218     const ComponentsType& components() const { return theComponents; }
0219 
0220     /**
0221      * Return the first component
0222      */
0223     const ComplexType& s1() const { return theComponents.first; }
0224 
0225     /**
0226      * Return the second component
0227      */
0228     const ComplexType& s2() const { return theComponents.second; }
0229 
0230   };
0231 
0232   /** Define |p> */
0233   typedef WeylSpinor<PlusSpinorTag,SqrtEnergy> PlusSpinor;
0234 
0235   /** Define |p] */
0236   typedef WeylSpinor<MinusSpinorTag,SqrtEnergy> MinusSpinor;
0237 
0238   /** Define <p| */
0239   typedef WeylSpinor<PlusConjugateSpinorTag,SqrtEnergy> PlusConjugateSpinor;
0240 
0241   /** Define [p| */
0242   typedef WeylSpinor<MinusConjugateSpinorTag,SqrtEnergy> MinusConjugateSpinor;
0243 
0244   /**
0245    * \ingroup Matchbox
0246    * \author Simon Platzer
0247    *
0248    * \brief Weyl spinor product
0249    *
0250    */
0251   template<class Type, class Value>
0252   class SpinorProduct 
0253     : public boost::addable<SpinorProduct<Type,Value> >,
0254       public boost::subtractable<SpinorProduct<Type,Value> >,
0255       public boost::multipliable<SpinorProduct<Type,Value>, double>,
0256       public boost::multipliable<SpinorProduct<Type,Value>, complex<double> > {
0257 
0258   public:
0259 
0260     typedef typename SpinorMultiplicationTraits<Value>::ComplexResultType ResultType;
0261     typedef WeylSpinor<Type,Value> LeftSpinorType;
0262     typedef typename WeylSpinorTraits<Type>::ConjugateSpinorTag RightSpinorTag;
0263     typedef WeylSpinor<RightSpinorTag,Value> RightSpinorType;
0264 
0265   private:
0266 
0267     /**
0268      * The result.
0269      */
0270     ResultType theResult;
0271 
0272   public:
0273 
0274     /**
0275      * Construct from two spinors; note that the
0276      * spinor metric is included, when constructing spinors.
0277      * Typedefs break zero products like <p|q]
0278      */
0279     explicit SpinorProduct(const LeftSpinorType& left,
0280                const RightSpinorType& right)
0281       : theResult(left.s1()*right.s1()+left.s2()*right.s2()) {}
0282 
0283     /**
0284      * Implicitly convert to complex value
0285      */
0286     operator ResultType() const { return theResult; }
0287 
0288     /**
0289      * Return result
0290      */
0291     ResultType eval() const { return theResult; }
0292 
0293   public:
0294 
0295     SpinorProduct& operator+= (const SpinorProduct& other) {
0296       theResult += other.theResult;
0297       return *this;
0298     }
0299 
0300     SpinorProduct& operator-= (const SpinorProduct& other) {
0301       theResult -= other.theResult;
0302       return *this;
0303     }
0304 
0305     SpinorProduct& operator*= (double x) {
0306       theResult *= x;
0307       return *this;
0308     }
0309 
0310     SpinorProduct& operator*= (complex<double> x) {
0311       theResult *= x;
0312       return *this;
0313     }
0314 
0315   };
0316 
0317   /** Define <pq> */
0318   typedef SpinorProduct<PlusConjugateSpinorTag,SqrtEnergy> PlusSpinorProduct;
0319 
0320   /** Define [pq] */
0321   typedef SpinorProduct<MinusConjugateSpinorTag,SqrtEnergy> MinusSpinorProduct;
0322 
0323   /**
0324    * \ingroup Matchbox
0325    * \author Simon Platzer
0326    *
0327    * \brief Weyl spinor current.
0328    *
0329    */
0330   template<class Type, class Value>
0331   class SpinorCurrent 
0332     : public boost::addable<SpinorCurrent<Type,Value> >,
0333       public boost::subtractable<SpinorCurrent<Type,Value> >,
0334       public boost::multipliable<SpinorCurrent<Type,Value>, double>,
0335       public boost::multipliable<SpinorCurrent<Type,Value>, complex<double> > {
0336 
0337   public:
0338 
0339     typedef typename SpinorMultiplicationTraits<Value>::ComplexVectorResultType ResultType;
0340     typedef WeylSpinor<Type,Value> LeftSpinorType;
0341     typedef typename WeylSpinorTraits<Type>::BarSpinorTag RightSpinorTag;
0342     typedef WeylSpinor<RightSpinorTag,Value> RightSpinorType;
0343 
0344   private:
0345 
0346     ResultType theResult;
0347 
0348     /**
0349      * Calculate [p|\gamma^\mu|q>
0350      */
0351     ResultType evaluate(const WeylSpinor<MinusConjugateSpinorTag,Value>& left,
0352             const WeylSpinor<PlusSpinorTag,Value>& right) {
0353       return 
0354     ResultType(right.s1()*left.s1()-right.s2()*left.s2(),
0355            complex<double>(0.,1.)*(right.s1()*left.s2()-right.s2()*left.s1()),
0356            right.s1()*left.s2()+right.s2()*left.s1(),
0357            right.s1()*left.s1()+right.s2()*left.s2());
0358     }
0359 
0360     /**
0361      * Calculate <p|\gamma^\mu|q]
0362      */
0363     ResultType evaluate(const WeylSpinor<PlusConjugateSpinorTag,Value>& left,
0364             const WeylSpinor<MinusSpinorTag,Value>& right) {
0365       return 
0366     ResultType(-right.s1()*left.s1()+right.s2()*left.s2(),
0367            -complex<double>(0.,1.)*(right.s1()*left.s2()-right.s2()*left.s1()),
0368            -right.s1()*left.s2()-right.s2()*left.s1(),
0369            right.s1()*left.s1()+right.s2()*left.s2());
0370     }
0371 
0372   public:
0373 
0374     /**
0375      * Construct from two spinors.
0376      * Typedefs break zero products like <p|\gamma^\mu|q>
0377      */
0378     explicit SpinorCurrent(const LeftSpinorType& left,
0379                const RightSpinorType& right)
0380       : theResult(evaluate(left,right)) {}
0381 
0382     /**
0383      * Implicitly convert to complex Lorentz vector
0384      */
0385     operator ResultType() const { return theResult; }
0386 
0387     /**
0388      * Return result
0389      */
0390     ResultType eval() const { return theResult; }
0391 
0392   public:
0393 
0394     SpinorCurrent& operator+= (const SpinorCurrent& other) {
0395       theResult += other.theResult;
0396       return *this;
0397     }
0398 
0399     SpinorCurrent& operator-= (const SpinorCurrent& other) {
0400       theResult -= other.theResult;
0401       return *this;
0402     }
0403 
0404     SpinorCurrent& operator*= (double x) {
0405       theResult *= x;
0406       return *this;
0407     }
0408 
0409     SpinorCurrent& operator*= (complex<double> x) {
0410       theResult *= x;
0411       return *this;
0412     }
0413 
0414   };
0415 
0416   /** Define <p|\gamma^\mu|q] */
0417   typedef SpinorCurrent<PlusConjugateSpinorTag,SqrtEnergy> PlusSpinorCurrent;
0418 
0419   /** Define [p|\gamma^\mu|q> */
0420   typedef SpinorCurrent<MinusConjugateSpinorTag,SqrtEnergy> MinusSpinorCurrent;
0421 
0422   /**
0423    * Return |c|^2
0424    */
0425   template<class T>
0426   auto abs2(const complex<T>& x) -> decltype((x*conj(x)).real())
0427   {
0428     return (x*conj(x)).real();
0429   }
0430 
0431 }
0432 
0433 }
0434 
0435 #endif // HERWIG_SpinorHelicity_H