#ifndef METOOLS_Main_Spin_Structure_H #define METOOLS_Main_Spin_Structure_H #include "METOOLS/Main/Polarization_Index.H" #include "ATOOLS/Math/MyComplex.H" #include "ATOOLS/Phys/Particle.H" #include "ATOOLS/Math/Matrix.H" #include "ATOOLS/Org/Message.H" #include <algorithm> #include <iomanip> #include "ATOOLS/Org/Exception.H" namespace METOOLS { bool SortByFirst(const std::pair<int,int> p1, const std::pair<int,int> p2); template<class Value> class Spin_Structure : public std::vector<Value>, public Polarization_Index { protected: size_t GetNumber(std::vector<std::pair<int,int> >& spins) const { sort(spins.begin(),spins.end(),SortByFirst); if(spins.size()!=m_spins.size()) { msg_Error()<<METHOD<<" Error: wrong size of spin std::vector."<<std::endl; abort(); } int mult(1); size_t num(0); for(size_t i=0; i<spins.size(); i++) { num += mult * spins[i].second; mult *= m_spins[i]; } if(num>this->size()) { msg_Error()<<METHOD<<" Error: tried to access value out of bounce. " <<"num="<<num<<" > "<<this->size()<<std::endl; abort(); } return num; } public: Spin_Structure() {} Spin_Structure(const std::vector<int>& spins, const Value& value): Polarization_Index(spins) { this->resize(m_n, value); } Spin_Structure(const ATOOLS::Flavour_Vector& flavs, const Value& value) { m_spins = std::vector<int>(flavs.size()); m_n=1; for(size_t i=0;i<flavs.size();i++) { if(flavs[i].IsVector() && flavs[i].IsMassive()==0) m_spins[i] = 2; else m_spins[i] = flavs[i].IntSpin()+1; m_n*=m_spins[i]; } this->resize(m_n,value); } Spin_Structure(const ATOOLS::Flavour_Vector& flavs, const std::vector<int>& indices) { m_spins = std::vector<int>(indices.size()); m_n=1; for(size_t i=0;i<indices.size();i++) { if(flavs[indices[i]].IsVector() && flavs[indices[i]].IsMassive()==0) m_spins[i] = 2; else m_spins[i] = flavs[indices[i]].IntSpin()+1; m_n*=m_spins[i]; } this->resize(m_n); } Spin_Structure(const ATOOLS::Particle_Vector& particles) { m_spins = std::vector<int>(particles.size()); m_n=1; for(size_t i=0;i<particles.size();i++) { if(particles[i]->Flav().IsVector() && particles[i]->Flav().IsMassive()==0) m_spins[i] = 2; else m_spins[i] = particles[i]->Flav().IntSpin()+1; m_n*=m_spins[i]; } this->resize(m_n); } ~Spin_Structure() {} inline size_t GetNumber(const std::vector<int> &spins) const { return (*this)(spins); } inline std::vector<int> GetSpinCombination(size_t number) const { return (*this)(number); } void Insert(Value value, std::vector<std::pair<int,int> >& spins) { (*this)[GetNumber(spins)]=value; } void Insert(Value value, const std::vector<int>& spins) { (*this)[GetNumber(spins)]=value; } void Add(Value value, std::vector<std::pair<int,int> >& spins) { (*this)[GetNumber(spins)]=value; } void Insert(Value value, size_t index) { (*this)[index]=value; } Value Get(const std::vector<int>& spins) const { return (*this)[GetNumber(spins)]; } Value Get(size_t index) const { return (*this)[index]; } void CreateTrivial(Value value) { size_t n = this->size(); this->clear(); this->resize(n,value); } Spin_Structure<Value>& operator+= (const Spin_Structure<Value>& addend) { for(size_t i=0;i<this->size();i++) { (*this)[i]+=addend[i]; } return *this; } }; template<class Value> std::ostream& operator<<(std::ostream& ostr, const Spin_Structure<Value>& s) { ostr<<" Spin_Structure with "<<s.size()<<" spin combinations:"<<std::endl; for(size_t i=0;i<s.size();i++) { ostr<<std::setw(3)<<i; std::vector<int> spins = s.GetSpinCombination(i); for(size_t j=0;j<spins.size();j++) { ostr<<std::setw(8)<<spins[j]<<" | "; } ostr<<s[i]<<std::endl; } return ostr; } class Spin_Amplitudes : public Spin_Structure<Complex> { public: Spin_Amplitudes(const std::vector<int>& spins, const Complex& value); Spin_Amplitudes(const ATOOLS::Flavour_Vector& flavs, const Complex& value); Spin_Amplitudes(const ATOOLS::Flavour_Vector& flavs, const std::vector<int>& indices); Spin_Amplitudes(const ATOOLS::Particle_Vector& particles); virtual ~Spin_Amplitudes(); double SumSquare() const; virtual void Calculate(const ATOOLS::Vec4D_Vector& momenta,bool anti=false); }; /*! \class Spin_Structure \brief Storing objects by spin combination. This class provides methods to access and manipulate arbitrary objects, by specifying the corresponding spin combination. It inherits from STL vector which contains one 'object' for each spin combination. */ /*! \var std::vector<int> Spin_Structure::m_spins \brief vector containing the number of spin combinations for each particle "node". */ /*! \var std::vector<Value> \brief storage of objects Objects are ordered as in this example (where the node part1 has 2 spin combinations, part2 has 1, part3 has 3, part4 has 2): | part1 | part2 | part3 | part4 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 2 | 0 | 0 | 1 | 0 | 3 | 1 | 0 | 1 | 0 | 4 | 0 | 0 | 2 | 0 | 5 | 1 | 0 | 2 | 0 | 6 | 0 | 0 | 0 | 1 | 7 | 1 | 0 | 0 | 1 | 8 | 0 | 0 | 1 | 1 | 9 | 1 | 0 | 1 | 1 | 10 | 0 | 0 | 2 | 1 | 11 | 1 | 0 | 2 | 1 | The polarisation index for each particle corresponds to: - <var>lambda</var> - \f$0 \to \epsilon^+\f$ - \f$1 \to \epsilon^-\f$ - \f$2 \to \epsilon^0\f$ . */ /*! \fn size_t Spin_Structure::GetNumber(const vector<int>& spins) const \brief Determine number of given combination in the STL vector. Here, the spins have to be specified in the same order as in m_spins (i.e. as the flavours or particles in the constructor where specified). */ /*! \fn size_t Spin_Structure::GetNumber(vector<pair<int,int> >& spins) const \brief Determine number of given combination in the STL vector. Here, the spins (second int in pair) can be in arbitrary order, as long as the first int in the pair specifies the number in m_spins it belongs to. */ /*! \fn std::vector<int> Spin_Structure::GetSpinCombination(size_t number) const \brief Determine spin combination from number of combination in the vector. The other way around from the GetNumber methods. Useful to traverse through all spin combinations. */ /*! \fn Spin_Structure::Spin_Structure(ATOOLS::Flavour* flavs, size_t size) \brief Constructor */ /*! \fn Spin_Structure::Spin_Structure(ATOOLS::Particle_Vector particles) \brief Constructor ATOOLS::Particles' flavours determine the number of spin combinations of each node. */ /*! \fn Spin_Structure::~Spin_Structure() \brief Destructor Doesn't do anything, because there are no pointer members. */ /*! \fn void Spin_Structure::Insert(Value value, vector<pair<int,int> >& spins) \brief Inserts value at the right position determined by GetNumber. */ /*! \fn void Spin_Structure::Insert(Complex amp, size_t index) \brief Inserts value at the given position. */ /*! \fn Value Spin_Structure::Get(const vector<int>& spins) const \brief Retrieves the value from the right position determined by GetNumber. */ /*! \fn vector<Complex> Spin_Structure::Get(size_t index) const; \brief Retrieves the value from the given position. */ /*! \fn void Spin_Structure::CreateTrivial(Value value) \brief Inserts the given object for all spin combinations. */ } #endif