#include "AHADIC++/Formation/Gluon_Splitter.H" #include "AHADIC++/Tools/Hadronisation_Parameters.H" #include "ATOOLS/Org/Message.H" #include "ATOOLS/Math/Random.H" using namespace AHADIC; using namespace ATOOLS; Gluon_Splitter::~Gluon_Splitter() { msg_Info()<Switch("GluonDecayForm"); m_alpha = hadpars->Get("alphaG"); } bool Gluon_Splitter::MakeLongitudinalMomenta() { m_arg = (sqr(m_Q2-m_minQ2[0]-m_popped_mass2)- 4.*(m_Q2*m_kt2 + m_minQ2[0]*m_popped_mass2)); if (m_arg<0.) return false; CalculateLimits(); do { m_z[1] = m_zselector(m_zmin[1],m_zmax[1]); } while (!CalculateXY()); return true; } void Gluon_Splitter::CalculateLimits() { double mean1 = (m_Q2+m_minQ2[0]-m_popped_mass2)/(2.*m_Q2); double delta = sqrt(m_arg)/(2.*m_Q2); m_zmin[0] = Max(0.0,mean1-delta); m_zmax[0] = Min(1.0,mean1+delta); double mean2 = (m_Q2-m_minQ2[0]+m_popped_mass2)/(2.*m_Q2); m_zmin[1] = Max(0.0,mean2-delta/2.); m_zmax[1] = Min(1.0,mean2+delta); } bool Gluon_Splitter::CalculateXY() { m_z[0] = 1.-(m_popped_mass2+m_kt2)/(m_z[1]*m_Q2); double M2 = m_z[0]*(1.-m_z[1])*m_Q2; //This is a new addition w.r.t. original master double R2 = M2 - m_kt2; if (R2 < m_mdec[0]) { M2 = m_mdec2[0]; m_z[0] = M2/((1.-m_z[1])*m_Q2); } if (M2/m_m2[0] > 1e6 && M2/m_kt2 > 1e6) { // Use Taylor expansion to first order in m12/M2 and kt2/M2 to avoid // numerical instability for x, y -> 1.0 m_x = 1.0 - m_kt2/M2; m_y = 1.0; } else { double arg = sqr(M2-m_kt2-m_m2[0])-4*m_m2[0]*m_kt2; if (arg<0.) return false; m_x = ((M2-m_kt2+m_m2[0])+sqrt(arg))/(2.*M2); m_y = m_kt2/M2/(1.-m_x); } return (!(m_x>1.) && !(m_x<0.) && !(m_y>1.) && !(m_y<0.)); } double Gluon_Splitter:: WeightFunction(const double & z,const double & zmin,const double & zmax, const unsigned int & cnt) { double norm = 1.; switch (m_mode) { case 1: norm = pow(0.5,2*m_alpha); return pow(z*(1.-z),m_alpha)/norm; case 0: default: break; } if (m_alpha<=0.) norm = pow(zmin,m_alpha) + pow(1.-zmax,m_alpha); return (pow(z,m_alpha)+pow(1.-z,m_alpha))/norm; } bool Gluon_Splitter::CheckKinematics() { // check if: // 1. new cluster mass larger than minimal mass // 2. spectator still on its mass shell // 3. new cluster particle with mass 0 // 4. new particle after gluon splitting on its mass-shell. double M2 = m_z[0]*(1.-m_z[1])*m_Q2; if (M2-m_kt2-m_minQ2[0] < 1.e-6*m_Q2 || dabs(m_x*(1.-m_y)*M2-m_m2[0]) > 1.e-6*m_Q2 || dabs((1.-m_x)*m_y*M2-m_kt2) > 1.e-6*m_Q2 || dabs((1.-m_z[0])*m_z[1]*m_Q2-m_kt2-m_popped_mass2) > 1.e-6*m_Q2) { msg_Tracking()<<"Error in "< " <Flavour()<<"),\n" <<" new in-quark:"<<((1.-m_x)*m_y*m_z[0]*(1.-m_z[1])*m_Q2-m_kt2) <<" should be 0 for ("<Momentum()).Abs2()>sqr(m_minQ[1])); } bool Gluon_Splitter::FillParticlesInLists() { Cluster * cluster = MakeCluster(); switch (p_softclusters->Treat(cluster)) { case 1: delete cluster; break; case -1: delete cluster; return false; default: p_cluster_list->push_back(cluster); break; } UpdateSpectator(); return true; } void Gluon_Splitter::UpdateSpectator() { // Replace splitted gluon with (anti-)(di-)quark and correct momentum Vec4D newmom2 = m_E*((1.-m_z[0])*s_AxisP+m_z[1]*s_AxisM)-m_ktvec; m_rotat.RotateBack(newmom2); m_boost.BoostBack(newmom2); p_part[1]->SetFlavour(m_newflav[1]); p_part[1]->SetMomentum(newmom2); p_part[1]->SetKT2_Max(m_kt2); } Cluster * Gluon_Splitter::MakeCluster() { // If kinematically allowed, i.e. if the emerging cluster is heavy enough, // we calculate the split of cluster momentum into momenta for its // constituents; otherwise we just use some ad-hoc kinematics with one of // the light cluster constituents being off-shell. // This is the overall cluster momentum - we do not need it - and its // individual components, i.e. the momenta of the Proto_Particles // it is made of --- transverse momentum goes to new particle Vec4D newmom11 = (m_E*(m_z[0]* m_x*s_AxisP + (1.-m_z[1])*(1.-m_y)*s_AxisM)); Vec4D newmom12 = (m_E*(m_z[0]*(1.-m_x)*s_AxisP + (1.-m_z[1])* m_y*s_AxisM) + m_ktvec); // back into lab system m_rotat.RotateBack(newmom11); m_boost.BoostBack(newmom11); m_rotat.RotateBack(newmom12); m_boost.BoostBack(newmom12); if (dabs(newmom11.Abs2()-m_m2[0]) > 1.e-3*m_Q2 || dabs(newmom12.Abs2()) > 1.e-3*m_Q2) { Vec4D newmom2 = m_E*((1.-m_z[0])*s_AxisP+m_z[1]*s_AxisM) - m_ktvec; m_rotat.RotateBack(newmom2); m_boost.BoostBack(newmom2); msg_Error()<<"Error in "< "< "< "<Flavour()<<") and " <Momentum()<<"("<Flavour()<<").\n"; m_kin_fails++; return NULL; } // Update momentum of original (anti-)(di-) quark after gluon splitting p_part[0]->SetMomentum(newmom11); // Make new particle Proto_Particle * newp12 = new Proto_Particle(m_newflav[0],newmom12,false, p_part[0]->IsBeam() || p_part[1]->IsBeam()); newp12->SetKT2_Max(m_kt2); // Take care of sequence in cluster = triplet + anti-triplet Cluster * cluster(m_barrd?new Cluster(newp12,p_part[0]):new Cluster(p_part[0],newp12)); return cluster; }