#include "REMNANTS/Tools/Beam_Decorrelator.H" #include "REMNANTS/Main/Remnant_Handler.H" #include "ATOOLS/Math/Random.H" #include "ATOOLS/Org/Run_Parameter.H" #include "ATOOLS/Org/Message.H" #include "ATOOLS/Org/Scoped_Settings.H" using namespace REMNANTS; using namespace ATOOLS; using namespace std; Beam_Decorrelator::Beam_Decorrelator() : m_on(false) {} Beam_Decorrelator::~Beam_Decorrelator() {} void Beam_Decorrelator:: Initialize(Remnant_Handler * const rhandler) { p_rhandler = rhandler; if (p_rhandler->Type()==strat::DIS1 || p_rhandler->Type()==strat::DIS2 || p_rhandler->Type()==strat::hh) { p_kperpGenerator = p_rhandler->GetKPerp(); auto s = Settings::GetMainSettings()["REMNANTS"]; m_expo = s["SOFT_X_EXPONENT"].SetDefault(-2.0).Get(); m_xiP = m_expo+1; m_invxiP = 1./m_xiP; m_maxeta = dabs(s["SOFT_ETA_RANGE"].SetDefault(7.5).Get()); m_mass2 = sqr(s["SOFT_MASS"].SetDefault(5.0).Get()); m_deltaM = s["DELTA_MASS"].SetDefault(1.5).Get(); m_on = (m_maxeta>0. && m_mass2>0.); } } bool Beam_Decorrelator::operator()(Blob * softblob) { if (!m_on) return true; p_softblob = softblob; // Check for pairs of partons; if they are colour-correlated and involve either // * one beam parton and one "proper" shower parton with |eta| < maxeta, or // * two beam partons from different beams // and if their mass is larger than the minimal mass m_mass2, they will emit a soft // gluon to be decorrelated in colour. for (size_t i=0;iNOutP()-1;i++) { for (size_t j=i+1;jNOutP();j++) { if (MustEmit(p_softblob->OutParticle(i),p_softblob->OutParticle(j))) SoftEmission(); } } // Add the produced soft gluons to the blob. while (!m_softgluons.empty()) { p_softblob->AddToOutParticles(m_softgluons.back()); m_softgluons.pop_back(); } return true; } bool Beam_Decorrelator::MustEmit(Particle * pi, Particle * pj) { //return false; // Checks if the partons must emit a soft gluon, for conditions see above. // Ignore parton pairs from shower or from the same beam breakup if ((pi->Beam()<=0 && pj->Beam()<=0) || (pi->Beam()==pj->Beam() && pi->Beam()!=0)) return false; // Ignore parton pairs that are not colour-correlated if (!((pi->GetFlow(1)==pj->GetFlow(2) && pi->GetFlow(1)!=0) || (pi->GetFlow(2)==pj->GetFlow(1) && pi->GetFlow(2)!=0))) return false; if (pi->Beam()>0 && ((pj->Beam()>0 && pi->Momentum()[0]>pj->Momentum()[0]) || pj->Beam()<=0)) { p_beam = pi; p_spect = pj; } else {p_beam = pj; p_spect = pi; } m_pbeam = p_beam->Momentum(); m_pspect = p_spect->Momentum(); m_Q2 = (m_pspect+m_pbeam).Abs2(); // Spectator parton must be from final state and inside eta-range or from other beam, // and invariant mass of pair must be above threshold return ((p_spect->Beam()<0 || dabs(m_pspect.Eta()) m_mass2); } bool Beam_Decorrelator::SoftEmission() { InitSoftEmission(); return DefineKinematics(); } void Beam_Decorrelator::InitSoftEmission() { // Construct invariants and c.m. system of emitter-spectator pair m_Q = sqrt(m_Q2); m_mbeam = p_beam->Flav().HadMass(); m_mbeam2 = sqr(m_mbeam); m_mspect = p_spect->Flav().HadMass(); m_mspect2 = sqr(m_mspect); m_boost = Poincare(m_pbeam+m_pspect); m_boost.Boost(m_pbeam); m_boost.Boost(m_pspect); m_rotat = Poincare(m_pspect, m_Q*s_AxisM); m_rotat.Rotate(m_pbeam); m_rotat.Rotate(m_pspect); } bool Beam_Decorrelator::DefineKinematics() { // 1000 trials to produce a kinematics that works, with x from a simple monomial x^(m_xiP-1) // and the transverse momentum vector from the Primordial_KPerp m_minMbeam = m_mbeam+m_deltaM; m_minMbeam2 = sqr(m_minMbeam); m_minMspect = m_mspect+m_deltaM; m_minMspect2 = sqr(m_minMspect); double eps = m_minMbeam2/m_Q2; double poweps = pow(eps,m_xiP); int trials = 1000; do { m_x = pow(ran->Get()*(1-poweps)+poweps,m_invxiP); m_ktvec = p_kperpGenerator->KT(2.); } while (!MakeKinematics() && (trials--)>0); //if (trials<=0) msg_Out()<<" ---> couldn't construct kinematics.\n"; //else msg_Out()<<" ---> ok with kinematics.\n"; return (trials>0); } bool Beam_Decorrelator::MakeKinematics() { // Constructing a kinematics in the c.m. frame double m_kt2 = dabs(m_ktvec.Abs2()), x = m_x; double y = m_kt2/(m_Q2*x); double alpha, beta; if (m_mspect2<1.e-12) { beta = 1.-y-(m_mbeam2+m_kt2)/((1.-x)*m_Q2); alpha = 1.; } else { double h1 = 1.-y+(m_mbeam2-m_mspect2+m_kt2)/((1.-x)*m_Q2); double h2 = m_mspect2/m_Q2*(1.-y); double disc = h1*h1-4.*h2; if (disc<0.) return false; beta = (h1+sqrt(disc))/2.; alpha = 1.-m_mspect2/(m_Q2*beta); } // Simple kinematics checks on parameters if (y>x || y<0 || beta>(1.-y) || alpha<0. || alpha>1.) { return false; } double E = m_Q/2.; Vec4D pi = E * (( alpha-x) * s_AxisP + (1.-beta-y) * s_AxisM) + m_ktvec; Vec4D pj = E * ( x * s_AxisP + y * s_AxisM) - m_ktvec; Vec4D pk = E * ((1.-alpha) * s_AxisP + beta * s_AxisM); // Simple kinematics checks on momenta: right mass shells, enogh mass in the beam-gluon pair // positive energies for all particles if (!IsZero(dabs(pi.Abs2()) - m_mbeam2) || !IsZero(dabs(pj.Abs2()) - 0.) || !IsZero(dabs(pk.Abs2()) - m_mspect2) || !IsZero(dabs((pi+pj+pk).Abs2()) - m_Q2) || !(pi[0]>0.) || !(pj[0]>0.) || !(pk[0]>0.) || (pi+pj).Abs2()SetMomentum(pi); p_spect->SetMomentum(pk); Particle * gluon = new Particle(-1,Flavour(kf_gluon),pj,'B'); m_softgluons.push_back(gluon); return true; } void Beam_Decorrelator::Reset() { m_softgluons.clear(); }