diff --git a/MatrixElement/Lepton/MEee2gZ2ll.cc b/MatrixElement/Lepton/MEee2gZ2ll.cc --- a/MatrixElement/Lepton/MEee2gZ2ll.cc +++ b/MatrixElement/Lepton/MEee2gZ2ll.cc @@ -1,718 +1,718 @@ // -*- C++ -*- // // MEee2gZ2ll.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2019 The Herwig Collaboration // // Herwig is licenced under version 3 of the GPL, see COPYING for details. // Please respect the MCnet academic guidelines, see GUIDELINES for details. // // // This is the implementation of the non-inlined, non-templated member // functions of the MEee2gZ2ll class. // #include "MEee2gZ2ll.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h" #include "ThePEG/Handlers/StandardXComb.h" #include "Herwig/MatrixElement/HardVertex.h" #include "ThePEG/PDF/PolarizedBeamParticleData.h" #include "ThePEG/Utilities/DescribeClass.h" #include <numeric> #include "Herwig/Shower/RealEmissionProcess.h" using namespace Herwig; void MEee2gZ2ll::getDiagrams() const { // specific the diagrams tcPDPtr ep = getParticleData(ParticleID::eplus); tcPDPtr em = getParticleData(ParticleID::eminus); // setup the processes for( int i =11;i<=16;++i) { if(allowed_==0 || (allowed_==1 && i%2==1) || (allowed_==2&&i==11) || (allowed_==3&&i==13) || (allowed_==4&&i==15)) { tcPDPtr lm = getParticleData(i); tcPDPtr lp = lm->CC(); add(new_ptr((Tree2toNDiagram(2), em, ep, 1, gamma_, 3, lm, 3, lp, -1))); add(new_ptr((Tree2toNDiagram(2), em, ep, 1, Z0_, 3, lm, 3, lp, -2))); } } } Energy2 MEee2gZ2ll::scale() const { return sHat(); } unsigned int MEee2gZ2ll::orderInAlphaS() const { return 0; } unsigned int MEee2gZ2ll::orderInAlphaEW() const { return 2; } Selector<MEBase::DiagramIndex> MEee2gZ2ll::diagrams(const DiagramVector & diags) const { double lastCont(0.5),lastBW(0.5); if ( lastXCombPtr() ) { lastCont = meInfo()[0]; lastBW = meInfo()[1]; } Selector<DiagramIndex> sel; for ( DiagramIndex i = 0; i < diags.size(); ++i ) { if ( diags[i]->id() == -1 ) sel.insert(lastCont, i); else if ( diags[i]->id() == -2 ) sel.insert(lastBW, i); } return sel; } Selector<const ColourLines *> MEee2gZ2ll::colourGeometries(tcDiagPtr) const { static ColourLines ctST(" "); Selector<const ColourLines *> sel; sel.insert(1.0, &ctST); return sel; } void MEee2gZ2ll::persistentOutput(PersistentOStream & os) const { os << allowed_ << FFZVertex_ << FFPVertex_ << gamma_ << Z0_ << alphaQED_ << ounit(pTmin_,GeV) << preFactor_; } void MEee2gZ2ll::persistentInput(PersistentIStream & is, int) { is >> allowed_ >> FFZVertex_ >> FFPVertex_ >> gamma_ >> Z0_ >> alphaQED_ >> iunit(pTmin_,GeV) >> preFactor_; } // *** Attention *** The following static variable is needed for the type // description system in ThePEG. Please check that the template arguments // are correct (the class and its base class), and that the constructor // arguments are correct (the class name and the name of the dynamically // loadable library where the class implementation can be found). DescribeClass<MEee2gZ2ll,HwMEBase> describeMEee2gZ2ll("Herwig::MEee2gZ2ll", "HwMELepton.so"); void MEee2gZ2ll::Init() { static ClassDocumentation<MEee2gZ2ll> documentation ("The MEee2gZ2ll class implements the matrix element for" "e+e- to leptons via Z and photon exchange using helicity amplitude" "techniques"); static Switch<MEee2gZ2ll,int> interfaceallowed ("Allowed", "Allowed outgoing leptons", &MEee2gZ2ll::allowed_, 0, false, false); static SwitchOption interfaceallowedAll (interfaceallowed, "All", "Allow all leptons as outgoing particles", 0); static SwitchOption interfaceallowedCharged (interfaceallowed, "Charged", "Only charged leptons as outgoing particles", 1); static SwitchOption interfaceallowedElectron (interfaceallowed, "Electron", "Only the electron and positron as outgoing leptons", 2); static SwitchOption interfaceallowedMuon (interfaceallowed, "Muon", "Only muons as outgoing particles", 3); static SwitchOption interfaceallowedTau (interfaceallowed, "Tau", "Only taus as outgoing particles", 4); static Parameter<MEee2gZ2ll,Energy> interfacepTMin ("pTMin", "Minimum pT for hard radiation", &MEee2gZ2ll::pTmin_, GeV, 1.0*GeV, 0.001*GeV, 10.0*GeV, false, false, Interface::limited); static Parameter<MEee2gZ2ll,double> interfacePrefactor ("Prefactor", "Prefactor for the overestimate of the emission probability", &MEee2gZ2ll::preFactor_, 6.0, 1.0, 100.0, false, false, Interface::limited); static Reference<MEee2gZ2ll,ShowerAlpha> interfaceEMCoupling ("AlphaQED", "Pointer to the object to calculate the EM coupling for the correction", &MEee2gZ2ll::alphaQED_, false, false, true, false, false); } double MEee2gZ2ll::me2() const { return loME(mePartonData(),rescaledMomenta(),true); } double MEee2gZ2ll::loME(const vector<cPDPtr> & partons, const vector<Lorentz5Momentum> & momenta, bool first) const { vector<SpinorWaveFunction> fin,aout; vector<SpinorBarWaveFunction> ain,fout; SpinorWaveFunction ein (momenta[0],partons[0],incoming); SpinorBarWaveFunction pin (momenta[1],partons[1],incoming); SpinorBarWaveFunction ilmout(momenta[2],partons[2],outgoing); SpinorWaveFunction ilpout(momenta[3],partons[3],outgoing); for(unsigned int ix=0;ix<2;++ix) { ein.reset(ix) ;fin.push_back( ein ); pin.reset(ix) ;ain.push_back( pin ); ilmout.reset(ix);fout.push_back(ilmout); ilpout.reset(ix);aout.push_back(ilpout); } // compute the matrix element double me,lastCont,lastBW; HelicityME(fin,ain,fout,aout,me,lastCont,lastBW); // save the components if(first) { DVector save; save.push_back(lastCont); save.push_back(lastBW); meInfo(save); } // return the answer return me; } ProductionMatrixElement MEee2gZ2ll::HelicityME(vector<SpinorWaveFunction> & fin, vector<SpinorBarWaveFunction> & ain, vector<SpinorBarWaveFunction> & fout, vector<SpinorWaveFunction> & aout, double & me,double & cont, double & BW ) const { // the particles should be in the order // for the incoming // 0 incoming fermion (u spinor) // 1 incoming antifermion (vbar spinor) // for the outgoing // 0 outgoing fermion (ubar spinor) // 1 outgoing antifermion (v spinor) // me to be returned ProductionMatrixElement output(PDT::Spin1Half,PDT::Spin1Half, PDT::Spin1Half,PDT::Spin1Half); ProductionMatrixElement gamma (PDT::Spin1Half,PDT::Spin1Half, PDT::Spin1Half,PDT::Spin1Half); ProductionMatrixElement Zboson(PDT::Spin1Half,PDT::Spin1Half, PDT::Spin1Half,PDT::Spin1Half); // // wavefunctions for the intermediate particles VectorWaveFunction interZ,interG; // temporary storage of the different diagrams Complex diag1,diag2; // sum over helicities to get the matrix element unsigned int inhel1,inhel2,outhel1,outhel2; double total[3]={0.,0.,0.}; for(inhel1=0;inhel1<2;++inhel1) { for(inhel2=0;inhel2<2;++inhel2) { // intermediate Z interZ = FFZVertex_->evaluate(sHat(),1,Z0_,fin[inhel1],ain[inhel2]); // intermediate photon interG = FFPVertex_->evaluate(sHat(),1,gamma_,fin[inhel1],ain[inhel2]); for(outhel1=0;outhel1<2;++outhel1) { for(outhel2=0;outhel2<2;++outhel2) { // first the Z exchange diagram diag1 = FFZVertex_->evaluate(sHat(),aout[outhel2],fout[outhel1], interZ); // then the photon exchange diagram diag2 = FFPVertex_->evaluate(sHat(),aout[outhel2],fout[outhel1], interG); // add up squares of individual terms total[1] += norm(diag1); Zboson(inhel1,inhel2,outhel1,outhel2) = diag1; total[2] += norm(diag2); gamma (inhel1,inhel2,outhel1,outhel2) = diag2; // the full thing including interference diag1 += diag2; total[0] += norm(diag1); output(inhel1,inhel2,outhel1,outhel2) = diag1; } } } } // results for(int ix=0;ix<3;++ix) total[ix] *= 0.25; tcPolarizedBeamPDPtr beam[2] = {dynamic_ptr_cast<tcPolarizedBeamPDPtr>(mePartonData()[0]), dynamic_ptr_cast<tcPolarizedBeamPDPtr>(mePartonData()[1])}; if( beam[0] || beam[1] ) { RhoDMatrix rho[2] = {beam[0] ? beam[0]->rhoMatrix() : RhoDMatrix(mePartonData()[0]->iSpin()), beam[1] ? beam[1]->rhoMatrix() : RhoDMatrix(mePartonData()[1]->iSpin())}; total[0] = output.average(rho[0],rho[1]); total[1] = Zboson.average(rho[0],rho[1]); total[2] = gamma .average(rho[0],rho[1]); } cont = total[2]; BW = total[1]; me = total[0]; return output; } void MEee2gZ2ll::constructVertex(tSubProPtr sub) { // extract the particles in the hard process ParticleVector hard; hard.push_back(sub->incoming().first);hard.push_back(sub->incoming().second); hard.push_back(sub->outgoing()[0]);hard.push_back(sub->outgoing()[1]); if(hard[0]->id()<hard[1]->id()) swap(hard[0],hard[1]); if(hard[2]->id()<hard[3]->id()) swap(hard[2],hard[3]); vector<SpinorWaveFunction> fin,aout; vector<SpinorBarWaveFunction> ain,fout; SpinorWaveFunction( fin ,hard[0],incoming,false,true); SpinorBarWaveFunction(ain ,hard[1],incoming,false,true); SpinorBarWaveFunction(fout,hard[2],outgoing,true ,true); SpinorWaveFunction( aout,hard[3],outgoing,true ,true); // calculate the matrix element double me,cont,BW; ProductionMatrixElement prodme=HelicityME(fin,ain,fout,aout,me,cont,BW); // construct the vertex HardVertexPtr hardvertex=new_ptr(HardVertex()); // set the matrix element for the vertex hardvertex->ME(prodme); // set the pointers and to and from the vertex for(unsigned int ix=0;ix<4;++ix) { tSpinPtr spin = hard[ix]->spinInfo(); if(ix<2) { tcPolarizedBeamPDPtr beam = dynamic_ptr_cast<tcPolarizedBeamPDPtr>(hard[ix]->dataPtr()); if(beam) spin->rhoMatrix() = beam->rhoMatrix(); } spin->productionVertex(hardvertex); } } void MEee2gZ2ll::doinit() { HwMEBase::doinit(); // set the particle data objects Z0_=getParticleData(ThePEG::ParticleID::Z0); gamma_=getParticleData(ThePEG::ParticleID::gamma); // cast the SM pointer to the Herwig SM pointer tcHwSMPtr hwsm= dynamic_ptr_cast<tcHwSMPtr>(standardModel()); // do the initialisation if(!hwsm) throw InitException() << "Wrong type of StandardModel object in " << "MEee2gZ2ll::doinit() the Herwig" << " version must be used" << Exception::runerror; FFZVertex_ = hwsm->vertexFFZ(); FFPVertex_ = hwsm->vertexFFP(); } void MEee2gZ2ll::rebind(const TranslationMap & trans) { FFZVertex_ = trans.translate(FFZVertex_); FFPVertex_ = trans.translate(FFPVertex_); Z0_ = trans.translate(Z0_); gamma_ = trans.translate(gamma_); HwMEBase::rebind(trans); } IVector MEee2gZ2ll::getReferences() { IVector ret = HwMEBase::getReferences(); ret.push_back(FFZVertex_); ret.push_back(FFPVertex_); ret.push_back(Z0_ ); ret.push_back(gamma_ ); return ret; } RealEmissionProcessPtr MEee2gZ2ll::generateHardest(RealEmissionProcessPtr born, ShowerInteraction inter) { // check if generating QCD radiation if(inter!=ShowerInteraction::QED && inter!=ShowerInteraction::QEDQCD && inter!=ShowerInteraction::ALL) return RealEmissionProcessPtr(); // generate the momenta for the hard emission vector<Lorentz5Momentum> emission; unsigned int iemit,ispect; Energy pTveto = generateHard(born,emission,iemit,ispect,false); // check if charged if(!partons_[2]->charged()) return RealEmissionProcessPtr(); // maximum pT of emission if(pTveto<=ZERO) { born->pT()[ShowerInteraction::QED] = pTmin_; return born; } else { born->pT()[ShowerInteraction::QED] = pTveto; } born->interaction(ShowerInteraction::QED); // get the quark and antiquark ParticleVector qq; for(unsigned int ix=0;ix<2;++ix) qq.push_back(born->bornOutgoing()[ix]); bool order = qq[0]->id()>0; if(!order) swap(qq[0],qq[1]); // create the new quark, antiquark and gluon PPtr newq = qq[0]->dataPtr()->produceParticle(emission[2]); PPtr newa = qq[1]->dataPtr()->produceParticle(emission[3]); PPtr newg = gamma_->produceParticle(emission[4]); // create the output real emission process for(unsigned int ix=0;ix<born->bornIncoming().size();++ix) { born->incoming().push_back(born->bornIncoming()[ix]->dataPtr()-> produceParticle(born->bornIncoming()[ix]->momentum())); } if(order) { born->outgoing().push_back(newq); born->outgoing().push_back(newa); } else { born->outgoing().push_back(newa); born->outgoing().push_back(newq); swap(iemit,ispect); } born->outgoing().push_back(newg); // set emitter and spectator born->emitter (iemit); born->spectator(ispect); born->emitted(4); return born; } double MEee2gZ2ll::meRatio(vector<cPDPtr> partons, vector<Lorentz5Momentum> momenta, unsigned int iemitter, bool subtract) const { Lorentz5Momentum q = momenta[2]+momenta[3]+momenta[4]; Energy2 Q2=q.m2(); Energy2 lambda = sqrt((Q2-sqr(momenta[2].mass()+momenta[3].mass()))* (Q2-sqr(momenta[2].mass()-momenta[3].mass()))); InvEnergy2 D[2]; double lome[2]; for(unsigned int iemit=0;iemit<2;++iemit) { unsigned int ispect = iemit==0 ? 1 : 0; Energy2 pipj = momenta[4 ] * momenta[2+iemit ]; Energy2 pipk = momenta[4 ] * momenta[2+ispect]; Energy2 pjpk = momenta[2+iemit] * momenta[2+ispect]; double y = pipj/(pipj+pipk+pjpk); double z = pipk/( pipk+pjpk); Energy mij = sqrt(2.*pipj+sqr(momenta[2+iemit].mass())); Energy2 lamB = sqrt((Q2-sqr(mij+momenta[2+ispect].mass()))* (Q2-sqr(mij-momenta[2+ispect].mass()))); Energy2 Qpk = q*momenta[2+ispect]; Lorentz5Momentum pkt = lambda/lamB*(momenta[2+ispect]-Qpk/Q2*q) +0.5/Q2*(Q2+sqr(momenta[2+ispect].mass())-sqr(momenta[2+ispect].mass()))*q; Lorentz5Momentum pijt = q-pkt; double muj = momenta[2+iemit ].mass()/sqrt(Q2); double muk = momenta[2+ispect].mass()/sqrt(Q2); double vt = sqrt((1.-sqr(muj+muk))*(1.-sqr(muj-muk)))/(1.-sqr(muj)-sqr(muk)); double v = sqrt(sqr(2.*sqr(muk)+(1.-sqr(muj)-sqr(muk))*(1.-y))-4.*sqr(muk)) /(1.-y)/(1.-sqr(muj)-sqr(muk)); // dipole term D[iemit] = 0.5/pipj*(2./(1.-(1.-z)*(1.-y)) -vt/v*(2.-z+sqr(momenta[2+iemit].mass())/pipj)); // matrix element vector<Lorentz5Momentum> lomom(4); lomom[0] = momenta[0]; lomom[1] = momenta[1]; if(iemit==0) { lomom[2] = pijt; lomom[3] = pkt ; } else { lomom[3] = pijt; lomom[2] = pkt ; } lome[iemit] = loME(partons,lomom,false); } InvEnergy2 ratio = realME(partons,momenta) *abs(D[iemitter])/(abs(D[0]*lome[0])+abs(D[1]*lome[1])); double output = Q2*ratio; if(subtract) output -= 2.*Q2*D[iemitter]; return output; } InvEnergy2 MEee2gZ2ll::realME(const vector<cPDPtr> & partons, const vector<Lorentz5Momentum> & momenta) const { // compute the spinors vector<SpinorWaveFunction> fin,aout; vector<SpinorBarWaveFunction> ain,fout; vector<VectorWaveFunction> gout; SpinorWaveFunction ein (momenta[0],partons[0],incoming); SpinorBarWaveFunction pin (momenta[1],partons[1],incoming); SpinorBarWaveFunction qkout(momenta[2],partons[2],outgoing); SpinorWaveFunction qbout(momenta[3],partons[3],outgoing); VectorWaveFunction photon(momenta[4],partons[4],outgoing); for(unsigned int ix=0;ix<2;++ix) { ein.reset(ix) ; fin.push_back( ein ); pin.reset(ix) ; ain.push_back( pin ); qkout.reset(ix); fout.push_back(qkout); qbout.reset(ix); aout.push_back(qbout); photon.reset(2*ix); gout.push_back(photon); } vector<Complex> diag(4,0.); ProductionMatrixElement output(PDT::Spin1Half,PDT::Spin1Half, PDT::Spin1Half,PDT::Spin1Half, PDT::Spin1); double total(0.); for(unsigned int inhel1=0;inhel1<2;++inhel1) { for(unsigned int inhel2=0;inhel2<2;++inhel2) { // intermediate Z VectorWaveFunction interZ = FFZVertex_->evaluate(scale(),1,Z0_,fin[inhel1],ain[inhel2]); // intermediate photon VectorWaveFunction interG = FFPVertex_->evaluate(scale(),1,gamma_,fin[inhel1],ain[inhel2]); for(unsigned int outhel1=0;outhel1<2;++outhel1) { for(unsigned int outhel2=0;outhel2<2;++outhel2) { for(unsigned int outhel3=0;outhel3<2;++outhel3) { SpinorBarWaveFunction off1 = - FFPVertex_->evaluate(scale(),3,partons[2],fout[outhel1],gout[outhel3]); + FFPVertex_->evaluate(scale(),3,partons[2]->CC(),fout[outhel1],gout[outhel3]); diag[0] = FFZVertex_->evaluate(scale(),aout[outhel2],off1,interZ); diag[1] = FFPVertex_->evaluate(scale(),aout[outhel2],off1,interG); SpinorWaveFunction off2 = - FFPVertex_->evaluate(scale(),3,partons[3],aout[outhel2],gout[outhel3]); + FFPVertex_->evaluate(scale(),3,partons[3]->CC(),aout[outhel2],gout[outhel3]); diag[2] = FFZVertex_->evaluate(scale(),off2,fout[outhel1],interZ); diag[3] = FFPVertex_->evaluate(scale(),off2,fout[outhel1],interG); // sum of diagrams Complex sum = std::accumulate(diag.begin(),diag.end(),Complex(0.)); // matrix element output(inhel1,inhel2,outhel1,outhel2,outhel3)=sum; // me2 total += norm(sum); } } } } } // spin average total *= 0.25; tcPolarizedBeamPDPtr beam[2] = {dynamic_ptr_cast<tcPolarizedBeamPDPtr>(partons[0]), dynamic_ptr_cast<tcPolarizedBeamPDPtr>(partons[1])}; if( beam[0] || beam[1] ) { RhoDMatrix rho[2] = {beam[0] ? beam[0]->rhoMatrix() : RhoDMatrix(mePartonData()[0]->iSpin()), beam[1] ? beam[1]->rhoMatrix() : RhoDMatrix(mePartonData()[1]->iSpin())}; total = output.average(rho[0],rho[1]); } // divide out the coupling and charge total /= norm(FFPVertex_->norm())* sqr(double(mePartonData()[2]->iCharge())/3.); // return the total return total*UnitRemoval::InvE2; } Energy MEee2gZ2ll::generateHard(RealEmissionProcessPtr born, vector<Lorentz5Momentum> & emmision, unsigned int & iemit, unsigned int & ispect, bool applyVeto) { // get the momenta of the incoming and outgoing particles // incoming tPPtr em = born->bornIncoming()[0]; tPPtr ep = born->bornIncoming()[1]; if(em->id()<0) swap(em,ep); // outgoing tPPtr qk = born->bornOutgoing()[0]; tPPtr qb = born->bornOutgoing()[1]; if(qk->id()<0) swap(qk,qb); // extract the momenta loMomenta_.clear(); loMomenta_.push_back(em->momentum()); loMomenta_.push_back(ep->momentum()); loMomenta_.push_back(qk->momentum()); loMomenta_.push_back(qb->momentum()); // and ParticleData objects partons_.resize(5); partons_[0]=em->dataPtr(); partons_[1]=ep->dataPtr(); partons_[2]=qk->dataPtr(); partons_[3]=qb->dataPtr(); partons_[4]=gamma_; // boost from lab to CMS frame with outgoing particles // along the z axis LorentzRotation eventFrame( ( loMomenta_[2] + loMomenta_[3] ).findBoostToCM() ); Lorentz5Momentum spectator = eventFrame*loMomenta_[2]; eventFrame.rotateZ( -spectator.phi() ); eventFrame.rotateY( -spectator.theta() ); eventFrame.invert(); // mass of the final-state system Energy2 M2 = (loMomenta_[2]+loMomenta_[3]).m2(); Energy M = sqrt(M2); double mu1 = loMomenta_[2].mass()/M; double mu2 = loMomenta_[3].mass()/M; double mu12 = sqr(mu1), mu22 = sqr(mu2); double lambda = sqrt(1.+sqr(mu12)+sqr(mu22)-2.*mu12-2.*mu22-2.*mu12*mu22); // max pT Energy pTmax = 0.5*sqrt(M2)* (1.-sqr(loMomenta_[2].mass()+loMomenta_[3].mass())/M2); // max y double ymax = acosh(pTmax/pTmin_); double a = alphaQED_->overestimateValue()/Constants::twopi* 2.*ymax*preFactor_*sqr(double(mePartonData()[2]->iCharge())/3.); // variables for the emission Energy pT[2]; double y[2],phi[2],x3[2],x1[2][2],x2[2][2]; double contrib[2][2]; // storage of the real emission momenta vector<Lorentz5Momentum> realMomenta[2][2]= {{vector<Lorentz5Momentum>(5),vector<Lorentz5Momentum>(5)}, {vector<Lorentz5Momentum>(5),vector<Lorentz5Momentum>(5)}}; for(unsigned int ix=0;ix<2;++ix) for(unsigned int iy=0;iy<2;++iy) for(unsigned int iz=0;iz<2;++iz) realMomenta[ix][iy][iz] = loMomenta_[iz]; // generate the emission for(unsigned int ix=0;ix<2;++ix) { if(ix==1) { swap(mu1 ,mu2 ); swap(mu12,mu22); } pT[ix] = pTmax; y [ix] = 0.; bool reject = true; do { // generate pT pT[ix] *= pow(UseRandom::rnd(),1./a); if(pT[ix]<pTmin_) { pT[ix] = -GeV; break; } // generate y y[ix] = -ymax+2.*UseRandom::rnd()*ymax; // generate phi phi[ix] = UseRandom::rnd()*Constants::twopi; // calculate x3 and check in allowed region x3[ix] = 2.*pT[ix]*cosh(y[ix])/M; if(x3[ix] < 0. || x3[ix] > 1. -sqr( mu1 + mu2 ) ) continue; // find the possible solutions for x1 double xT2 = sqr(2./M*pT[ix]); double root = (-sqr(x3[ix])+xT2)* (xT2*mu22+2.*x3[ix]-sqr(mu12)+2.*mu22+2.*mu12-sqr(x3[ix])-1. +2.*mu12*mu22-sqr(mu22)-2.*mu22*x3[ix]-2.*mu12*x3[ix]); double c1=2.*sqr(x3[ix])-4.*mu22-6.*x3[ix]+4.*mu12-xT2*x3[ix] +2.*xT2-2.*mu12*x3[ix]+2.*mu22*x3[ix]+4.; if(root<0.) continue; x1[ix][0] = 1./(4.-4.*x3[ix]+xT2)*(c1-2.*sqrt(root)); x1[ix][1] = 1./(4.-4.*x3[ix]+xT2)*(c1+2.*sqrt(root)); // change sign of y if 2nd particle emits if(ix==1) y[ix] *=-1.; // loop over the solutions for(unsigned int iy=0;iy<2;++iy) { contrib[ix][iy]=0.; // check x1 value allowed if(x1[ix][iy]<2.*mu1||x1[ix][iy]>1.+mu12-mu22) continue; // calculate x2 value and check allowed x2[ix][iy] = 2.-x3[ix]-x1[ix][iy]; double root = max(0.,sqr(x1[ix][iy])-4.*mu12); root = sqrt(root); double x2min = 1.+mu22-mu12 -0.5*(1.-x1[ix][iy]+mu12-mu22)/(1.-x1[ix][iy]+mu12)*(x1[ix][iy]-2.*mu12+root); double x2max = 1.+mu22-mu12 -0.5*(1.-x1[ix][iy]+mu12-mu22)/(1.-x1[ix][iy]+mu12)*(x1[ix][iy]-2.*mu12-root); if(x2[ix][iy]<x2min||x2[ix][iy]>x2max) continue; // check the z components double z1 = sqrt(sqr(x1[ix][iy])-4.*mu12-xT2); double z2 = -sqrt(sqr(x2[ix][iy])-4.*mu22); double z3 = pT[ix]*sinh(y[ix])*2./M; if(ix==1) z3 *=-1.; if(abs(-z1+z2+z3)<1e-9) z1 *= -1.; if(abs(z1+z2+z3)>1e-5) continue; // if using as an ME correction the veto if(applyVeto) { // double xb = x1[ix][iy], xc = x2[ix][iy]; // double b = mu12, c = mu22; // double r = 0.5*(1.+b/(1.+c-xc)); // double z1 = r + (xb-(2.-xc)*r)/sqrt(sqr(xc)-4.*c); // double kt1 = (1.-b+c-xc)/z1/(1.-z1); // r = 0.5*(1.+c/(1.+b-xb)); // double z2 = r + (xc-(2.-xb)*r)/sqrt(sqr(xb)-4.*b); // double kt2 = (1.-c+b-xb)/z2/(1.-z2); // if(ix==1) { // swap(z1 ,z2); // swap(kt1,kt2); // } // // veto the shower region // if( kt1 < d_kt1_ || kt2 < d_kt2_ ) continue; } // construct the momenta realMomenta[ix][iy][4] = Lorentz5Momentum(pT[ix]*cos(phi[ix]),pT[ix]*sin(phi[ix]), pT[ix]*sinh(y[ix]) ,pT[ix]*cosh(y[ix]),ZERO); if(ix==0) { realMomenta[ix][iy][2] = Lorentz5Momentum(-pT[ix]*cos(phi[ix]),-pT[ix]*sin(phi[ix]), z1*0.5*M,x1[ix][iy]*0.5*M,M*mu1); realMomenta[ix][iy][3] = Lorentz5Momentum(ZERO,ZERO, z2*0.5*M,x2[ix][iy]*0.5*M,M*mu2); } else { realMomenta[ix][iy][2] = Lorentz5Momentum(ZERO,ZERO,-z2*0.5*M,x2[ix][iy]*0.5*M,M*mu2); realMomenta[ix][iy][3] = Lorentz5Momentum(-pT[ix]*cos(phi[ix]),-pT[ix]*sin(phi[ix]), -z1*0.5*M,x1[ix][iy]*0.5*M,M*mu1); } // boost the momenta back to the lab for(unsigned int iz=2;iz<5;++iz) realMomenta[ix][iy][iz] *= eventFrame; // jacobian and prefactors for the weight Energy J = M/sqrt(xT2)*abs(-x1[ix][iy]*x2[ix][iy]+2.*mu22*x1[ix][iy] +x2[ix][iy]+x2[ix][iy]*mu12+mu22*x2[ix][iy] -sqr(x2[ix][iy])) /pow(sqr(x2[ix][iy])-4.*mu22,1.5); // prefactors etc contrib[ix][iy] = 0.5*pT[ix]/J/preFactor_/lambda; // matrix element piece contrib[ix][iy] *= meRatio(partons_,realMomenta[ix][iy],ix,false); // coupling piece contrib[ix][iy] *= alphaQED_->ratio(sqr(pT[ix])); } if(contrib[ix][0]+contrib[ix][1]>1.) { ostringstream s; s << "MEee2gZ2qq::generateHardest weight for channel " << ix << "is " << contrib[ix][0]+contrib[ix][1] << " which is greater than 1"; generator()->logWarning( Exception(s.str(), Exception::warning) ); } reject = UseRandom::rnd() > contrib[ix][0] + contrib[ix][1]; } while (reject); if(pT[ix]<pTmin_) pT[ix] = -GeV; } // now pick the emmision with highest pT Energy pTemit(ZERO); // no emission if(pT[0]<ZERO&&pT[1]<ZERO) return -GeV; // which one emitted if(pT[0]>pT[1]) { iemit = 2; ispect = 3; pTemit = pT[0]; if(UseRandom::rnd()<contrib[0][0]/(contrib[0][0]+contrib[0][1])) emmision = realMomenta[0][0]; else emmision = realMomenta[0][1]; } else { iemit = 3; ispect = 2; pTemit = pT[1]; if(UseRandom::rnd()<contrib[1][0]/(contrib[1][0]+contrib[1][1])) emmision = realMomenta[1][0]; else emmision = realMomenta[1][1]; } // return pT of emmision return pTemit; }