diff --git a/Decay/Baryon/Baryon1MesonDecayerBase.cc b/Decay/Baryon/Baryon1MesonDecayerBase.cc --- a/Decay/Baryon/Baryon1MesonDecayerBase.cc +++ b/Decay/Baryon/Baryon1MesonDecayerBase.cc @@ -1,978 +1,978 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the Baryon1MesonDecayerBase class. // #include "Baryon1MesonDecayerBase.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/PDT/DecayMode.h" #include "Herwig/Utilities/Kinematics.h" #include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/RSSpinorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/RSSpinorBarWaveFunction.h" #include "ThePEG/Helicity/LorentzPolarizationVector.h" #include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h" #include "Herwig/Decay/TwoBodyDecayMatrixElement.h" using namespace Herwig; using namespace ThePEG::Helicity; // The following static variable is needed for the type // description system in ThePEG. DescribeAbstractNoPIOClass describeHerwigBaryon1MesonDecayerBase("Herwig::Baryon1MesonDecayerBase", "HwBaryonDecay.so"); void Baryon1MesonDecayerBase::Init() { static ClassDocumentation documentation ("The Baryon1MesonDecayerBase class is the base class for" " the decays of the baryons to a baryon and a pseudoscalar or vector meson."); } // return the matrix element squared for a given mode and phase-space channel // (inherited from DecayIntegrator and implemented here) double Baryon1MesonDecayerBase::me2(const int ichan, const Particle & inpart, const ParticleVector & decay, MEOption meopt) const { double me(0.); // decide which matrix element we are doing // incoming spin-1/2 particle if(inpart.dataPtr()->iSpin()==2) { // decay to spin-1/2 particle if(decay[0]->dataPtr()->iSpin()==2) { // scalar meson if(decay[1]->dataPtr()->iSpin()==1) me=halfHalfScalar(ichan,inpart,decay,meopt); // vector meson else if(decay[1]->dataPtr()->iSpin()==3) me=halfHalfVector(ichan,inpart,decay,meopt); else throw DecayIntegratorError() << "Unknown outgoing meson spin in " << "Baryon1MesonDecayerBase::me2()" << Exception::abortnow; } // decay to spin-3/2 particle else if(decay[0]->dataPtr()->iSpin()==4) { // scalar meson if(decay[1]->dataPtr()->iSpin()==1) me=halfThreeHalfScalar(ichan,inpart,decay,meopt); // vector meson else if(decay[1]->dataPtr()->iSpin()==3) me=halfThreeHalfVector(ichan,inpart,decay,meopt); else throw DecayIntegratorError() << "Unknown outgoing meson spin in " << "Baryon1MesonDecayerBase::me2()" << Exception::abortnow; } // unknown else throw DecayIntegratorError() << "Unknown outgoing baryon spin in " << "Baryon1MesonDecayerBase::me2()" << Exception::abortnow; } // incoming spin-3/2 particle else if(inpart.dataPtr()->iSpin()==4) { // decay to spin-1/2 particle if(decay[0]->dataPtr()->iSpin()==2) { // scalar meson if(decay[1]->dataPtr()->iSpin()==1) me=threeHalfHalfScalar(ichan,inpart,decay,meopt); // vector meson else if(decay[1]->dataPtr()->iSpin()==3) me=threeHalfHalfVector(ichan,inpart,decay,meopt); else throw DecayIntegratorError() << "Unknown outgoing meson spin in " << "Baryon1MesonDecayerBase::me2()" << Exception::abortnow; } // decay to spin-3/2 particle else if(decay[0]->dataPtr()->iSpin()==4) { // scalar meson if(decay[1]->dataPtr()->iSpin()==1) me=threeHalfThreeHalfScalar(ichan,inpart,decay,meopt); else throw DecayIntegratorError() << "Unknown outgoing meson spin in " << "Baryon1MesonDecayerBase::me2()" << Exception::abortnow; } // unknown else throw DecayIntegratorError() << "Unknown outgoing baryon spin in " << "Baryon1MesonDecayerBase::me2()" << Exception::abortnow; } // unknown else throw DecayIntegratorError() << "Unknown incoming spin in " << "Baryon1MesonDecayerBase::me2()" << Exception::abortnow; return me; } // matrix element for the decay of a spin-1/2 fermion to a spin-1/2 fermion and // a pseudoscalar meson double Baryon1MesonDecayerBase:: halfHalfScalar(const int,const Particle & inpart, const ParticleVector & decay,MEOption meopt) const { if(!ME()) ME(new_ptr(TwoBodyDecayMatrixElement(PDT::Spin1Half,PDT::Spin1Half,PDT::Spin0))); // spinors etc for the decaying particle if(meopt==Initialize) { // spinors and rho if(inpart.id()>0) SpinorWaveFunction ::calculateWaveFunctions(_inHalf,_rho, const_ptr_cast(&inpart), incoming); else SpinorBarWaveFunction::calculateWaveFunctions(_inHalfBar,_rho, const_ptr_cast(&inpart), incoming); // matrix element } // setup spin info when needed if(meopt==Terminate) { // for the decaying particle if(inpart.id()>0) { SpinorWaveFunction:: constructSpinInfo(_inHalf,const_ptr_cast(&inpart),incoming,true); SpinorBarWaveFunction::constructSpinInfo(_inHalfBar,decay[0],outgoing,true); } else { SpinorBarWaveFunction:: constructSpinInfo(_inHalfBar,const_ptr_cast(&inpart),incoming,true); SpinorWaveFunction::constructSpinInfo(_inHalf,decay[0],outgoing,true); } ScalarWaveFunction::constructSpinInfo(decay[1],outgoing,true); return 0.; } // spinors for the decay product if(inpart.id()>0) { SpinorBarWaveFunction::calculateWaveFunctions(_inHalfBar,decay[0],outgoing); } else { SpinorWaveFunction ::calculateWaveFunctions(_inHalf,decay[0],outgoing); } // get the couplings Complex A,B; halfHalfScalarCoupling(imode(),inpart.mass(),decay[0]->mass(),decay[1]->mass(),A,B); - Complex left,right,meout; + Complex left,right; // coupling for an incoming particle if(inpart.id()>0) { left = (A-B); right = (A+B); } // coupling for an incoming antiparticle else { left = conj(A+B); right = conj(A-B); } // calculate the matrix element vector ispin(3,0); unsigned int ix,iy; // Complex output(0.); for(ix=0;ix<2;++ix) { for(iy=0;iy<2;++iy) { if(decay[0]->id()>0){ispin[0]=iy;ispin[1]=ix;} else{ispin[0]=ix;ispin[1]=iy;} (*ME())(ispin)=Complex(_inHalf[iy].generalScalar(_inHalfBar[ix],left,right)/inpart.mass()); // output += norm(ME()(ispin)); } } // test of the matrix elemen// t // Energy m1(inpart.mass()),m2(decay[0]->mass()),m3(decay[1]->mass()); // Energy Qp(sqrt(sqr(m1+m2)-sqr(m3))),Qm(sqrt(sqr(m1-m2)-sqr(m3))); // Complex h1(2.*Qp*A/inpart.mass()),h2(-2.*Qm*B/inpart.mass()); // generator()->log() << "testing 1/2->1/2 0 " // << 0.5*output << " " // << 0.25*(h1*conj(h1)+h2*conj(h2)) << " " // << 0.5*(h1*conj(h1)+h2*conj(h2))/output << endl; // generator()->log() << "testing alpha " << // (norm(0.5*(h1+h2))-norm(0.5*(h1-h2)))/ // (norm(0.5*(h1+h2))+norm(0.5*(h1-h2))) << "\n"; // Energy pcm(Kinematics::pstarTwoBodyDecay(m1,m2,m3)); // generator()->log() << "testing masses " << m1/GeV << " " << m2/GeV << " " << m3/GeV // << "\n"; // generator()->log() << "testing partial " << pcm*0.5*output/8./Constants::pi/MeV // << "\n"; // store the matrix element return (ME()->contract(_rho)).real(); } // matrix element for the decay of a spin-1/2 fermion to a spin-1/2 fermion and // a vector meson double Baryon1MesonDecayerBase:: halfHalfVector(const int,const Particle & inpart, const ParticleVector & decay,MEOption meopt) const { if(!ME()) ME(new_ptr(TwoBodyDecayMatrixElement(PDT::Spin1Half,PDT::Spin1Half,PDT::Spin1))); // check if the outgoing meson is really a photon bool photon=decay[1]->id()==ParticleID::gamma; // spinors etc for the decaying particle if(meopt==Initialize) { // spinors and rho if(inpart.id()>0) SpinorWaveFunction ::calculateWaveFunctions(_inHalf,_rho, const_ptr_cast(&inpart), incoming); else SpinorBarWaveFunction::calculateWaveFunctions(_inHalfBar,_rho, const_ptr_cast(&inpart), incoming); // matrix element } // setup spin info when needed if(meopt==Terminate) { // for the decaying particle if(inpart.id()>0) { SpinorWaveFunction:: constructSpinInfo(_inHalf,const_ptr_cast(&inpart),incoming,true); SpinorBarWaveFunction::constructSpinInfo(_inHalfBar,decay[0],outgoing,true); } else { SpinorBarWaveFunction:: constructSpinInfo(_inHalfBar,const_ptr_cast(&inpart),incoming,true); SpinorWaveFunction::constructSpinInfo(_inHalf,decay[0],outgoing,true); } VectorWaveFunction::constructSpinInfo(_inVec,decay[1],outgoing,true,photon); return 0.; } // spinors for the decay product if(inpart.id()>0) { SpinorBarWaveFunction::calculateWaveFunctions(_inHalfBar,decay[0],outgoing); } else { SpinorWaveFunction ::calculateWaveFunctions(_inHalf,decay[0],outgoing); } VectorWaveFunction::calculateWaveFunctions(_inVec,decay[1],outgoing,photon); // get the couplings Complex A1,A2,B1,B2; halfHalfVectorCoupling(imode(),inpart.mass(),decay[0]->mass(),decay[1]->mass(), A1,A2,B1,B2); Complex lS,rS,lV,rV; complex scalar; // couplings for an incoming particle if(inpart.id()>0) { lS = (A2-B2); rS = (A2+B2); lV = (A1-B1); rV = (A1+B1); } else { lS = -conj(A2+B2); rS = -conj(A2-B2); lV = conj(A1-B1); rV = conj(A1+B1); } // calculate the matrix element // decide which type of mode to do Energy msum(inpart.mass()+decay[0]->mass()); vector ispin(3); LorentzVector > svec; Complex prod; // Complex output(0.); unsigned int ix,iy; for(ix=0;ix<2;++ix) { for(iy=0;iy<2;++iy) { // scalar like piece scalar = _inHalf[iy].generalScalar(_inHalfBar[ix],lS,rS); // vector like piece svec = _inHalf[iy].generalCurrent(_inHalfBar[ix],lV,rV); if(decay[0]->id()>0) { ispin[0] = iy; ispin[1] = ix; } else { ispin[0] = ix; ispin[1] = iy; } for(ispin[2]=0;ispin[2]<3;++ispin[2]) { ispin[2]=ispin[2]; prod=_inVec[ispin[2]].dot(inpart.momentum())/msum; (*ME())(ispin)=(svec.dot(_inVec[ispin[2]])+prod*scalar)/inpart.mass(); // output += norm(ME()(ispin)); } } } // test of the matrix element // Energy m1(inpart.mass()),m2(decay[0]->mass()),m3(decay[1]->mass()); // Energy Qp(sqrt(sqr(m1+m2)-sqr(m3))),Qm(sqrt(sqr(m1-m2)-sqr(m3))); // double r2(sqrt(2.)); // Energy pcm(Kinematics::pstarTwoBodyDecay(m1,m2,m3)); // Complex h1(2.*r2*Qp*B1/inpart.mass()),h2(-2.*r2*Qm*A1/inpart.mass()), // h3(2./m3*(Qp*(m1-m2)*B1-Qm*m1*B2*pcm/(m1+m2))/inpart.mass()), // h4(2./m3*(Qm*(m1+m2)*A1+Qp*m1*A2*pcm/(m1+m2))/inpart.mass()); // generator()->log() << "testing 1/2->1/2 1 " // << 0.5*output << " " // << 0.25*(h1*conj(h1)+h2*conj(h2)+h3*conj(h3)+h4*conj(h4)) << " " // << 0.50*(h1*conj(h1)+h2*conj(h2)+h3*conj(h3)+h4*conj(h4))/output // << "\n"; // generator()->log() << "alpha = " << 2.*(norm(h3)+norm(h4))/(norm(h1)+norm(h2))-1. // << "\n"; // return the answer return (ME()->contract(_rho)).real(); } // matrix element for the decay of a spin-1/2 fermion to a spin-3/2 fermion and // a scalar meson double Baryon1MesonDecayerBase::halfThreeHalfScalar(const int, const Particle & inpart, const ParticleVector & decay, MEOption meopt) const { if(!ME()) ME(new_ptr(TwoBodyDecayMatrixElement(PDT::Spin1Half,PDT::Spin3Half,PDT::Spin0))); // spinors etc for the decaying particle if(meopt==Initialize) { // spinors and rho if(inpart.id()>0) SpinorWaveFunction ::calculateWaveFunctions(_inHalf,_rho, const_ptr_cast(&inpart), incoming); else SpinorBarWaveFunction::calculateWaveFunctions(_inHalfBar,_rho, const_ptr_cast(&inpart), incoming); // matrix element } // setup spin info when needed if(meopt==Terminate) { // for the decaying particle if(inpart.id()>0) { SpinorWaveFunction:: constructSpinInfo(_inHalf,const_ptr_cast(&inpart),incoming,true); RSSpinorBarWaveFunction::constructSpinInfo(_inThreeHalfBar, decay[0],outgoing,true); } else { SpinorBarWaveFunction:: constructSpinInfo(_inHalfBar,const_ptr_cast(&inpart),incoming,true); RSSpinorWaveFunction::constructSpinInfo(_inThreeHalf, decay[0],outgoing,true); } ScalarWaveFunction::constructSpinInfo(decay[1],outgoing,true); return 0.; } // spinors for the decay product LorentzPolarizationVector in=UnitRemoval::InvE*inpart.momentum(); if(inpart.id()>0) { RSSpinorBarWaveFunction:: calculateWaveFunctions(_inThreeHalfBar,decay[0],outgoing); _inHalfBar.resize(_inThreeHalfBar.size()); for(unsigned int ix=0;ix<_inThreeHalfBar.size();++ix) _inHalfBar[ix] = _inThreeHalfBar[ix].dot(in); } else { RSSpinorWaveFunction:: calculateWaveFunctions(_inThreeHalf,decay[0],outgoing); _inHalf.resize(_inThreeHalf.size()); for(unsigned int ix=0;ix<_inThreeHalf.size();++ix) _inHalf[ix] = _inThreeHalf[ix].dot(in); } // get the couplings Complex A,B,left,right; Energy msum(inpart.mass()+decay[0]->mass()); halfThreeHalfScalarCoupling(imode(),inpart.mass(),decay[0]->mass(),decay[1]->mass(), A,B); // incoming particle if(inpart.id()>0) { left=(A-B); right=(A+B); } // incoming anti-particle else { left=conj(A+B); right=conj(A-B); } vector ispin(3,0); //Complex output(0.); for(unsigned ixa=0;ixa<2;++ixa) { for(unsigned int iya=0;iya<4;++iya) { unsigned int ix(iya),iy(ixa); if(decay[0]->id()<0) swap(ix,iy); ispin[0]=ixa; ispin[1]=iya; complex value = _inHalf[iy].generalScalar(_inHalfBar[ix],left,right) *UnitRemoval::E/inpart.mass()/msum; (*ME())(ispin) = value; //output+= norm(ME()(ispin)); } } double output = (ME()->contract(_rho)).real(); // test of the matrix element // Energy m1(inpart.mass()),m2(decay[0]->mass()),m3(decay[1]->mass()); // Energy Qp(sqrt(sqr(m1+m2)-sqr(m3))),Qm(sqrt(sqr(m1-m2)-sqr(m3))); // double r23(sqrt(2./3.)); // Energy pcm(Kinematics::pstarTwoBodyDecay(m1,m2,m3)); // complex h1(-2.*r23*pcm*m1/m2*Qm*B/(m1+m2)),h2( 2.*r23*pcm*m1/m2*Qp*A/(m1+m2)); // cout << "testing 1/2->3/2 0 " << inpart.id() << " " // << output << " " // << 0.25*(h1*conj(h1)+h2*conj(h2))/sqr(inpart.mass()) << " " // << 0.25*(h1*conj(h1)+h2*conj(h2))/sqr(inpart.mass())/output << endl; // return the answer return output; } // matrix element for the decay of a spin-1/2 fermion to a spin-3/2 fermion and // a vector meson double Baryon1MesonDecayerBase:: halfThreeHalfVector(const int,const Particle & inpart, const ParticleVector & decay, MEOption meopt) const { if(!ME()) ME(new_ptr(TwoBodyDecayMatrixElement(PDT::Spin1Half,PDT::Spin3Half,PDT::Spin1))); // check if the outgoing meson is really a photon bool photon=decay[1]->id()==ParticleID::gamma; // spinors etc for the decaying particle if(meopt==Initialize) { // spinors and rho if(inpart.id()>0) SpinorWaveFunction ::calculateWaveFunctions(_inHalf,_rho, const_ptr_cast(&inpart), incoming); else SpinorBarWaveFunction::calculateWaveFunctions(_inHalfBar,_rho, const_ptr_cast(&inpart), incoming); // matrix element } // setup spin info when needed if(meopt==Terminate) { // for the decaying particle if(inpart.id()>0) { SpinorWaveFunction:: constructSpinInfo(_inHalf,const_ptr_cast(&inpart),incoming,true); RSSpinorBarWaveFunction::constructSpinInfo(_inThreeHalfBar, decay[0],outgoing,true); } else { SpinorBarWaveFunction:: constructSpinInfo(_inHalfBar,const_ptr_cast(&inpart),incoming,true); RSSpinorWaveFunction::constructSpinInfo(_inThreeHalf, decay[0],outgoing,true); } VectorWaveFunction::constructSpinInfo(_inVec,decay[1],outgoing,true,photon); return 0.; } LorentzPolarizationVector in=UnitRemoval::InvE*inpart.momentum(); if(inpart.id()>0) { RSSpinorBarWaveFunction:: calculateWaveFunctions(_inThreeHalfBar,decay[0],outgoing); _inHalfBar.resize(_inThreeHalfBar.size()); for(unsigned int ix=0;ix<_inThreeHalfBar.size();++ix) _inHalfBar[ix] = _inThreeHalfBar[ix].dot(in); } else { RSSpinorWaveFunction:: calculateWaveFunctions(_inThreeHalf,decay[0],outgoing); _inHalf.resize(_inThreeHalf.size()); for(unsigned int ix=0;ix<_inThreeHalf.size();++ix) _inHalf[ix] = _inThreeHalf[ix].dot(in); } ME()->zero(); VectorWaveFunction::calculateWaveFunctions(_inVec,decay[1],outgoing,photon); // get the couplings Complex A1,A2,A3,B1,B2,B3; halfThreeHalfVectorCoupling(imode(),inpart.mass(),decay[0]->mass(),decay[1]->mass(), A1,A2,A3,B1,B2,B3); Energy msum(inpart.mass()+decay[0]->mass()); Complex lS,rS,lV,rV,left,right; // incoming particle if(inpart.id()>0) { lS=(A3-B3);rS=(A3+B3); lV=(A2-B2);rV=(A2+B2); left=(A1-B1);right=(A1+B1); } // incoming anti-particle else { lS=conj(A3+B3);rS=conj(A3-B3); lV=-conj(A2-B2);rV=-conj(A2+B2); left=conj(A1+B1);right=conj(A1-B1); } // compute the matrix element vector ispin(3); LorentzVector > svec; Complex prod; complex scalar; LorentzSpinor stemp; LorentzSpinorBar sbtemp; for(unsigned iya=0;iya<4;++iya) { ispin[1]=iya; // piece where the vector-spinor is dotted with the momentum of the // incoming fermion for(unsigned ixa=0;ixa<2;++ixa) { unsigned int ix(iya),iy(ixa); if(decay[0]->id()<0) swap(ix,iy); scalar = _inHalf[iy].generalScalar (_inHalfBar[ix],lS,rS); svec = _inHalf[iy].generalCurrent(_inHalfBar[ix],lV,rV); ispin[0]=ixa; for(unsigned int iz=0;iz<3;++iz) { ispin[2]=iz; prod=_inVec[iz].dot(inpart.momentum())/msum; (*ME())(ispin) += (svec.dot(_inVec[iz])+prod*scalar)* UnitRemoval::E/msum/inpart.mass(); } } // the piece where the vector spinor is dotted with the polarization vector for(unsigned int iz=0;iz<3;++iz) { ispin[2]=iz; if(decay[0]->id()>0) sbtemp = _inThreeHalfBar[iya].dot(_inVec[iz]); else stemp = _inThreeHalf[iya].dot(_inVec[iz]); for(unsigned int ixa=0;ixa<2;++ixa) { ispin[0]=ixa; if(decay[0]->id()>0) stemp = _inHalf[ixa]; else sbtemp = _inHalfBar[ixa]; (*ME())(ispin) += Complex(stemp.generalScalar(sbtemp,left,right)/inpart.mass()); } } } double output = (ME()->contract(_rho)).real(); // test of the matrix element // Energy m1(inpart.mass()),m2(decay[0]->mass()),m3(decay[1]->mass()); // Energy2 m12(m1*m1),m22(m2*m2),m32(m3*m3); // Energy Qp(sqrt(sqr(m1+m2)-sqr(m3))),Qm(sqrt(sqr(m1-m2)-sqr(m3))); // double r2(sqrt(2.)),r3(sqrt(3.)); // Energy pcm(Kinematics::pstarTwoBodyDecay(m1,m2,m3)); // complex h1(-2.*Qp*A1),h2(2.*Qm*B1); // complex h3(-2./r3*Qp*(A1-Qm*Qm/m2*A2/msum)); // complex h4( 2./r3*Qm*(B1-Qp*Qp/m2*B2/msum)); // complex h5(-2.*r2/r3/m2/m3*Qp*(0.5*(m12-m22-m32)*A1+0.5*Qm*Qm*(m1+m2)*A2/msum // +m12*pcm*pcm*A3/msum/msum)); // complex h6( 2.*r2/r3/m2/m3*Qm*(0.5*(m12-m22-m32)*B1-0.5*Qp*Qp*(m1-m2)*B2/msum // +m12*pcm*pcm*B3/msum/msum)); // cout << "testing 1/2->3/2 1 " << inpart.id() << " " // << output << " " // << 0.25*(h1*conj(h1)+h2*conj(h2)+h3*conj(h3)+ // h4*conj(h4)+h5*conj(h5)+h6*conj(h6))/sqr(inpart.mass()) << " " // << 0.25*(h1*conj(h1)+h2*conj(h2)+h3*conj(h3)+ // h4*conj(h4)+h5*conj(h5)+h6*conj(h6))/sqr(inpart.mass())/output << endl; // return the answer return output; } // matrix element for the decay of a spin-3/2 fermion to a spin-1/2 fermion and // a scalar meson double Baryon1MesonDecayerBase:: threeHalfHalfScalar(const int,const Particle & inpart, const ParticleVector & decay, MEOption meopt) const { if(!ME()) ME(new_ptr(TwoBodyDecayMatrixElement(PDT::Spin3Half,PDT::Spin1Half,PDT::Spin0))); // spinors etc for the decaying particle if(meopt==Initialize) { // spinors and rho if(inpart.id()>0) { RSSpinorWaveFunction ::calculateWaveFunctions(_inThreeHalf,_rho, const_ptr_cast(&inpart), incoming); } else { RSSpinorBarWaveFunction::calculateWaveFunctions(_inThreeHalfBar,_rho, const_ptr_cast(&inpart), incoming); } // matrix element } // setup spin info when needed if(meopt==Terminate) { // for the decaying particle if(inpart.id()>0) { RSSpinorWaveFunction:: constructSpinInfo(_inThreeHalf,const_ptr_cast(&inpart),incoming,true); SpinorBarWaveFunction::constructSpinInfo(_inHalfBar,decay[0],outgoing,true); } else { RSSpinorBarWaveFunction:: constructSpinInfo(_inThreeHalfBar,const_ptr_cast(&inpart),incoming,true); SpinorWaveFunction::constructSpinInfo(_inHalf,decay[0],outgoing,true); } ScalarWaveFunction::constructSpinInfo(decay[1],outgoing,true); return 0.; } // spinors for the decay product if(inpart.id()>0) { SpinorBarWaveFunction::calculateWaveFunctions(_inHalfBar,decay[0],outgoing); } else { SpinorWaveFunction ::calculateWaveFunctions(_inHalf,decay[0],outgoing); } LorentzPolarizationVector out=UnitRemoval::InvE*decay[0]->momentum(); if(inpart.id()>0) { _inHalf.resize(_inThreeHalf.size()); for(unsigned int ix=0;ix<_inThreeHalf.size();++ix) _inHalf[ix] = _inThreeHalf[ix].dot(out); } else { _inHalfBar.resize(_inThreeHalfBar.size()); for(unsigned int ix=0;ix<_inThreeHalfBar.size();++ix) _inHalfBar[ix] = _inThreeHalfBar[ix].dot(out); } // get the couplings Complex A,B; Energy msum=inpart.mass()+decay[0]->mass(); threeHalfHalfScalarCoupling(imode(),inpart.mass(),decay[0]->mass(),decay[1]->mass(), A,B); Complex left,right; // incoming particle if(inpart.id()>0) { left=(A-B); right=(A+B); } // incoming anti-particle else { left=conj(A+B); right=conj(A-B); } // compute the matrix element vector ispin(3,0); for(unsigned ixa=0;ixa<2;++ixa) { for(unsigned iya=0;iya<4;++iya) { unsigned int iy=iya,ix=ixa; if(decay[0]->id()<0) swap(ix,iy); ispin[0]=iya; ispin[1]=ixa; (*ME())(ispin) = Complex(_inHalf[iy].generalScalar(_inHalfBar[ix],left,right)* UnitRemoval::E/msum/inpart.mass()); } } double output = (ME()->contract(_rho)).real(); // test of the matrix element // Energy m1(inpart.mass()),m2(decay[0]->mass()),m3(decay[1]->mass()); // Energy Qp(sqrt(sqr(m1+m2)-sqr(m3))),Qm(sqrt(sqr(m1-m2)-sqr(m3))); // double r23(sqrt(2./3.)); // Energy pcm(Kinematics::pstarTwoBodyDecay(m1,m2,m3)); // complex h1(-2.*r23*pcm*Qm*B/(m1+m2)),h2( 2.*r23*pcm*Qp*A/(m1+m2)); // cout << "testing 3/2->1/2 0 " << inpart.id() << " " // << output << " " // << 0.125*(h1*conj(h1)+h2*conj(h2))/sqr(inpart.mass()) << " " // << 0.125*(h1*conj(h1)+h2*conj(h2))/sqr(inpart.mass())/output << endl; // return the answer return output; } // matrix element for the decay of a spin-3/2 fermion to a spin-3/2 fermion and // a scalar meson double Baryon1MesonDecayerBase::threeHalfThreeHalfScalar(const int, const Particle & inpart, const ParticleVector & decay, MEOption meopt) const { if(!ME()) ME(new_ptr(TwoBodyDecayMatrixElement(PDT::Spin3Half,PDT::Spin3Half,PDT::Spin0))); // spinors etc for the decaying particle if(meopt==Initialize) { // spinors and rho if(inpart.id()>0) { RSSpinorWaveFunction ::calculateWaveFunctions(_inThreeHalf,_rho, const_ptr_cast(&inpart), incoming); } else { RSSpinorBarWaveFunction::calculateWaveFunctions(_inThreeHalfBar,_rho, const_ptr_cast(&inpart), incoming); } // matrix element } // setup spin info when needed if(meopt==Terminate) { // for the decaying particle if(inpart.id()>0) { RSSpinorWaveFunction:: constructSpinInfo(_inThreeHalf,const_ptr_cast(&inpart),incoming,true); RSSpinorBarWaveFunction::constructSpinInfo(_inThreeHalfBar, decay[0],outgoing,true); } else { RSSpinorBarWaveFunction:: constructSpinInfo(_inThreeHalfBar,const_ptr_cast(&inpart),incoming,true); RSSpinorWaveFunction::constructSpinInfo(_inThreeHalf, decay[0],outgoing,true); } ScalarWaveFunction::constructSpinInfo(decay[1],outgoing,true); return 0.; } // spinors for the decay product LorentzPolarizationVector in=UnitRemoval::InvE*inpart.momentum(); if(inpart.id()>0) { RSSpinorBarWaveFunction:: calculateWaveFunctions(_inThreeHalfBar,decay[0],outgoing); } else { RSSpinorWaveFunction:: calculateWaveFunctions(_inThreeHalf,decay[0],outgoing); } _inHalf.resize(_inThreeHalf.size()); _inHalfBar.resize(_inThreeHalfBar.size()); for(unsigned int ix=0;ix<_inThreeHalf.size();++ix) { _inHalf[ix] = _inThreeHalf[ix].dot(in); _inHalfBar[ix] = _inThreeHalfBar[ix].dot(in); } // get the couplings Complex A1,B1,A2,B2; Energy msum(inpart.mass()+decay[0]->mass()); threeHalfThreeHalfScalarCoupling(imode(),inpart.mass(),decay[0]->mass(), decay[1]->mass(),A1,A2,B1,B2); Complex left1,right1,left2,right2; // incoming particle if(inpart.id()>0) { left1=(A1-B1); right1=(A1+B1); left2=(A2-B2); right2=(A2+B2); } // incoming anti-particle else { left1=(A1+B1); right1=(A1-B1); left2=(A2+B2); right2=(A2-B2); } // compute the matrix element vector ispin(3,0); for(unsigned ixa=0;ixa<4;++ixa) { for(unsigned iya=0;iya<4;++iya) { unsigned int iy=iya,ix=ixa; if(decay[0]->id()<0) swap(ix,iy); ispin[0]=iya; ispin[1]=ixa; (*ME())(ispin)=Complex((_inThreeHalf[iy].generalScalar(_inThreeHalfBar[ix],left1,right1) +_inHalf[iy].generalScalar( _inHalfBar[ix],left2,right2) *UnitRemoval::E2/sqr(msum))/inpart.mass()); } } // return the answer return (ME()->contract(_rho)).real(); } // matrix element for the decay of a spin-3/2 fermion to a spin-1/2 fermion and // a vector meson double Baryon1MesonDecayerBase:: threeHalfHalfVector(const int,const Particle & inpart, const ParticleVector & decay,MEOption meopt) const { if(!ME()) ME(new_ptr(TwoBodyDecayMatrixElement(PDT::Spin3Half,PDT::Spin1Half,PDT::Spin1))); // check if the outgoing meson is really a photon bool photon=decay[1]->id()==ParticleID::gamma; // spinors etc for the decaying particle if(meopt==Initialize) { // spinors and rho if(inpart.id()>0) { RSSpinorWaveFunction ::calculateWaveFunctions(_inThreeHalf,_rho, const_ptr_cast(&inpart), incoming); } else { RSSpinorBarWaveFunction::calculateWaveFunctions(_inThreeHalfBar,_rho, const_ptr_cast(&inpart), incoming); } // matrix element } // setup spin info when needed if(meopt==Terminate) { // for the decaying particle if(inpart.id()>0) { RSSpinorWaveFunction:: constructSpinInfo(_inThreeHalf,const_ptr_cast(&inpart),incoming,true); SpinorBarWaveFunction::constructSpinInfo(_inHalfBar,decay[0],outgoing,true); } else { RSSpinorBarWaveFunction:: constructSpinInfo(_inThreeHalfBar,const_ptr_cast(&inpart),incoming,true); SpinorWaveFunction::constructSpinInfo(_inHalf,decay[0],outgoing,true); } VectorWaveFunction::constructSpinInfo(_inVec,decay[1],outgoing,true,photon); return 0.; } // spinors for the decay product if(inpart.id()>0) { SpinorBarWaveFunction::calculateWaveFunctions(_inHalfBar,decay[0],outgoing); } else { SpinorWaveFunction ::calculateWaveFunctions(_inHalf,decay[0],outgoing); } LorentzPolarizationVector out=UnitRemoval::InvE*decay[0]->momentum(); if(inpart.id()>0) { _inHalf.resize(_inThreeHalf.size()); for(unsigned int ix=0;ix<_inThreeHalf.size();++ix) _inHalf[ix] = _inThreeHalf[ix].dot(out); } else { _inHalfBar.resize(_inThreeHalfBar.size()); for(unsigned int ix=0;ix<_inThreeHalfBar.size();++ix) _inHalfBar[ix] = _inThreeHalfBar[ix].dot(out); } ME()->zero(); VectorWaveFunction::calculateWaveFunctions(_inVec,decay[1],outgoing,photon); // get the couplings - Complex A1,A2,A3,B1,B2,B3,prod,meout; + Complex A1,A2,A3,B1,B2,B3,prod; threeHalfHalfVectorCoupling(imode(),inpart.mass(),decay[0]->mass(),decay[1]->mass(), A1,A2,A3,B1,B2,B3); Energy msum(inpart.mass()+decay[0]->mass()); Complex lS,rS,lV,rV,left,right; // incoming particle if(inpart.id()>0) { lS=(A3-B3);rS=(A3+B3); lV=(A2-B2);rV=(A2+B2); left=(A1-B1);right=(A1+B1); } // incoming anti-particle else { lS=conj(A3+B3);rS=conj(A3-B3); lV=-conj(A2-B2);rV=-conj(A2+B2); left=conj(A1+B1);right=conj(A1-B1); } // compute the matrix element vector ispin(3); LorentzVector > svec; LorentzSpinor stemp; LorentzSpinorBar sbtemp; complex scalar; for(unsigned iya=0;iya<4;++iya) { ispin[0]=iya; for(unsigned ixa=0;ixa<2;++ixa) { unsigned int iy=iya,ix=ixa; if(decay[0]->id()<0) swap(ix,iy); scalar = _inHalf[iy].generalScalar( _inHalfBar[ix],lS,rS); svec = _inHalf[iy].generalCurrent(_inHalfBar[ix],lV,rV); ispin[1]=ixa; for(unsigned int iz=0;iz<3;++iz) { ispin[2]=iz; prod=_inVec[iz].dot(decay[0]->momentum())/msum; (*ME())(ispin) += (svec.dot(_inVec[iz])+prod*scalar)* UnitRemoval::E/msum/inpart.mass(); } } // the piece where the vector spinor is dotted with the polarization vector for(unsigned iz=0;iz<3;++iz) { ispin[2]=iz; if(decay[0]->id()>0) stemp = _inThreeHalf[iya].dot(_inVec[iz]); else sbtemp = _inThreeHalfBar[iya].dot(_inVec[iz]); for(unsigned int ixa=0;ixa<2;++ixa) { ispin[1]=ixa; if(decay[0]->id()>0) sbtemp = _inHalfBar[ixa]; else stemp = _inHalf[ixa]; (*ME())(ispin) += Complex(stemp.generalScalar(sbtemp,left,right)/inpart.mass()); } } } double output = (ME()->contract(_rho)).real(); // testing code // Energy m1(inpart.mass()),m2(decay[0]->mass()),m3(decay[1]->mass()); // Energy2 m12(m1*m1),m22(m2*m2),m32(m3*m3); // Energy Qp(sqrt(sqr(m1+m2)-sqr(m3))),Qm(sqrt(sqr(m1-m2)-sqr(m3))); // double r2(sqrt(2.)),r3(sqrt(3.)); // Energy pcm(Kinematics::pstarTwoBodyDecay(m1,m2,m3)); // complex h1(-2.*Qp*A1),h2(2.*Qm*B1); // complex h3(-2./r3*Qp*(A1-Qm*Qm/m1*A2/msum)); // complex h4( 2./r3*Qm*(B1-Qp*Qp/m1*B2/msum)); // complex h5(-2.*r2/r3/m1/m3*Qp*(0.5*(m22-m12-m32)*A1+0.5*Qm*Qm*(m1+m2)*A2/msum // +m12*pcm*pcm*A3/msum/msum)); // complex h6( 2.*r2/r3/m1/m3*Qm*(0.5*(m22-m12-m32)*B1-0.5*Qp*Qp*(m2-m1)*B2/msum // +m22*pcm*pcm*B3/msum/msum)); // cout << "testing 3/2->1/2 1 " << inpart.id() << " " // << output << " " // << 0.25*(h1*conj(h1)+h2*conj(h2)+h3*conj(h3)+ // h4*conj(h4)+h5*conj(h5)+h6*conj(h6))/sqr(inpart.mass()) << " " // << 0.25*(h1*conj(h1)+h2*conj(h2)+h3*conj(h3)+ // h4*conj(h4)+h5*conj(h5)+h6*conj(h6))/sqr(inpart.mass())/output << endl; // return the answer return output; } void Baryon1MesonDecayerBase::halfHalfScalarCoupling(int,Energy,Energy,Energy, Complex&,Complex&) const { throw DecayIntegratorError() << "Baryon1MesonDecayerBase::halfHalfScalarCoupling()" << " called from base class this must be implemented" << " in the inheriting class" << Exception::abortnow; } void Baryon1MesonDecayerBase::halfHalfVectorCoupling(int,Energy,Energy,Energy, Complex&,Complex&, Complex&,Complex&) const { throw DecayIntegratorError() << "Baryon1MesonDecayerBase::halfHalfVectorCoupling()" << " called from base class this must be implemented " << "in the inheriting class" << Exception::abortnow; } void Baryon1MesonDecayerBase::halfThreeHalfScalarCoupling(int,Energy,Energy,Energy, Complex&,Complex&) const { throw DecayIntegratorError() << "Baryon1MesonDecayerBase::halfThreeHalfScalarCoupling" << "() called from base class this must be implemented" << " in the inheriting class" << Exception::abortnow; } void Baryon1MesonDecayerBase::halfThreeHalfVectorCoupling(int,Energy,Energy,Energy, Complex&,Complex&, Complex&,Complex&, Complex&,Complex&) const { throw DecayIntegratorError() << "Baryon1MesonDecayerBase::halfThreeHalfVectorCoupling" << "() called from base class this must be implemented " << "in the inheriting class" << Exception::abortnow; } void Baryon1MesonDecayerBase::threeHalfHalfScalarCoupling(int,Energy,Energy,Energy, Complex&,Complex&) const { throw DecayIntegratorError() << "Baryon1MesonDecayerBase::threeHalfHalfScalarCoupling" << "() called from base class this must be implemented" << " in the inheriting class" << Exception::abortnow; } void Baryon1MesonDecayerBase::threeHalfHalfVectorCoupling(int,Energy,Energy,Energy, Complex&,Complex&, Complex&,Complex&, Complex&,Complex&) const { throw DecayIntegratorError() << "Baryon1MesonDecayerBase::threeHalfHalfVectorCoupling" << "() called from base class this must be implemented " << "in the inheriting class" << Exception::abortnow; } void Baryon1MesonDecayerBase::threeHalfThreeHalfScalarCoupling(int,Energy,Energy, Energy,Complex&, Complex&,Complex&, Complex&) const { throw DecayIntegratorError() << "Baryon1MesonDecayerBase::threeHalfThreeHalfScalar" << "Coupling() called from base class this must be " << "implemented in the inheriting class" << Exception::abortnow; } bool Baryon1MesonDecayerBase::twoBodyMEcode(const DecayMode & dm,int & mecode, double & coupling) const { coupling=1.; unsigned int inspin(dm.parent()->iSpin()),outspin,outmes; ParticleMSet::const_iterator pit(dm.products().begin()); bool order; if((**pit).iSpin()%2==0) { order=true; outspin=(**pit).iSpin(); ++pit;outmes=(**pit).iSpin(); } else { order=false; outmes=(**pit).iSpin();++pit; outspin=(**pit).iSpin(); } mecode=-1; if(inspin==2) { if(outspin==2){if(outmes==1){mecode=101;}else{mecode=102;}} else if(outspin==4){if(outmes==1){mecode=103;}else{mecode=104;}} } else if(inspin==4) { if(outspin==2){if(outmes==1){mecode=105;}else{mecode=106;}} else if(outspin==4){if(outmes==1){mecode=107;}else{mecode=108;}} } return order; } void Baryon1MesonDecayerBase::dataBaseOutput(ofstream & os,bool header) const { DecayIntegrator::dataBaseOutput(os,header); } diff --git a/Decay/FormFactors/ChengHeavyBaryonFormFactor.cc b/Decay/FormFactors/ChengHeavyBaryonFormFactor.cc --- a/Decay/FormFactors/ChengHeavyBaryonFormFactor.cc +++ b/Decay/FormFactors/ChengHeavyBaryonFormFactor.cc @@ -1,440 +1,440 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the ChengHeavyBaryonFormFactor class. // #include "ChengHeavyBaryonFormFactor.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/ParVector.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; using namespace ThePEG; ChengHeavyBaryonFormFactor::ChengHeavyBaryonFormFactor() { // consituent quark masses _mu = 338*MeV; _md = 322*MeV; _ms = 510*MeV; _mc = 1.6*GeV; _mb = 5.0*GeV; // masses for the q^2 dependence _mVbc = 6.34*GeV; _mVbs = 5.42*GeV; _mVcs = 2.11*GeV; _mVbd = 5.32*GeV; _mVcu = 2.01*GeV; _mAbc = 6.73*GeV; _mAbs = 5.86*GeV; _mAcs = 2.54*GeV; _mAbd = 5.71*GeV; _mAcu = 2.42*GeV; double one3(1./sqrt(3.)),one2(1./sqrt(2.)); // lambda_b to lambda_c addFormFactor(5122,4122,2,2,1,2,5,4);_Nfi.push_back(1. );_eta.push_back(1.); // lambda_b to lambda addFormFactor(5122,3122,2,2,1,2,5,3);_Nfi.push_back(one3 );_eta.push_back(1.); // lambda_b to n addFormFactor(5122,2112,2,2,1,2,5,1);_Nfi.push_back(one2 );_eta.push_back(1.); // xi_b to xi_c addFormFactor(5232,4232,2,2,2,3,5,4);_Nfi.push_back(1. );_eta.push_back(1.); addFormFactor(5132,4132,2,2,1,3,5,4);_Nfi.push_back(1. );_eta.push_back(1.); // xi_b to xi addFormFactor(5232,3322,2,2,2,3,5,3);_Nfi.push_back(one2 );_eta.push_back(1.); addFormFactor(5132,3312,2,2,1,3,5,3);_Nfi.push_back(one2 );_eta.push_back(1.); // xi_b to sigma addFormFactor(5232,3212,2,2,2,3,5,1);_Nfi.push_back(0.5 );_eta.push_back(1.); addFormFactor(5132,3112,2,2,1,3,5,1);_Nfi.push_back(0.5 );_eta.push_back(1.); // xi_b to lambda addFormFactor(5232,3122,2,2,2,3,5,1);_Nfi.push_back(one3/2.);_eta.push_back(1.); // omega_b to omega_c addFormFactor(5332,4332,2,2,3,3,5,4);_Nfi.push_back(1. );_eta.push_back(-1./3.); // omega_b to xi addFormFactor(5332,3312,2,2,3,3,5,1);_Nfi.push_back(one3 );_eta.push_back(-1./3.); // omega_b to omega_c* addFormFactor(5332,4334,2,4,3,3,5,4);_Nfi.push_back(1. );_eta.push_back(0.); // omega_b to omega addFormFactor(5332,3334,2,4,3,3,5,3);_Nfi.push_back(1. );_eta.push_back(0.); // omega_b to xi* addFormFactor(5332,3314,2,4,3,3,5,1);_Nfi.push_back(one3 );_eta.push_back(0.); // omega_c to omega addFormFactor(4332,3334,2,4,3,3,4,3);_Nfi.push_back(1. );_eta.push_back(0.); // omega_c to xi* addFormFactor(4332,3324,2,4,3,3,4,2);_Nfi.push_back(one3 );_eta.push_back(0.); // lambda_c to lambda_0 addFormFactor(4122,3122,2,2,1,2,4,3);_Nfi.push_back(1./sqrt(3.));_eta.push_back(1.); // xi_c to xi addFormFactor(4232,3322,2,2,2,3,4,3);_Nfi.push_back(1./sqrt(3.));_eta.push_back(1.); addFormFactor(4132,3312,2,2,1,3,4,3);_Nfi.push_back(1./sqrt(3.));_eta.push_back(1.); // initial number of form factors initialModes(numberOfFactors()); } void ChengHeavyBaryonFormFactor::doinit() { BaryonFormFactor::doinit(); // check the parameters are consistent unsigned int isize(numberOfFactors()); if(isize!=_eta.size()||isize!=_Nfi.size()) {throw InitException() << "Inconsistent paramters in ChengHeavyBaryon" << "FormFactor::doinit() " << Exception::abortnow;} Energy mi,mf,mq,mQ,lambda,delta,msum; int id0,id1,inspin,outspin,isp1,isp2,inq,outq; for(unsigned int ix=0;ixmass(); mf=getParticleData(id1)->mass(); msum=mi+mf; // masses of the incoming and outgoing quarks if((id0==4122&&id1==3122)||(id0==4232&&id1==3322)||(id0==4132&&id1==3312)|| (id0==4332&&id1==3334)) {mq=_ms;mQ=_mc;} else if((id0==4332&&id1==3322)||(id0==4332&&id1==3324)) {mq=_mu;mQ=_mc;} else if((id0==5122&&id1==4122)||(id0==5232&&id1==4232)||(id0==5132&&id1==4132)|| (id0==5332&&id1==4332)||(id0==5332&&id1==4334)) {mq=_mc;mQ=_mb;} else if((id0==5122&&id1==3122)||(id0==5132&&id1==3312)||(id0==5232&&id1==3322)|| (id0==5332&&id1==3334)) {mq=_ms;mQ=_mb;} else if((id0==5122&&id1==2112)||(id0==5132&&id1==3112)||(id0==5232&&id1==3212)|| (id0==5332&&id1==3312)||(id0==5232&&id1==3122)||(id0==5332&&id1==3314)) {mq=_md;mQ=_mb;} else {throw InitException() << "Unknown decay in ChengHeavyBaryon" << "FormFactor::doinit() " << Exception::abortnow;} // parameters lambda = mf-mq; delta = mi-mf; // compute the form-factors if(inspin==2&&outspin==2) { _f1.push_back(_Nfi[ix]*(1.-0.5*delta/mi +0.25*delta/mi/mq*(1.-0.5*lambda/mf)* (mi+mf-_eta[ix]*delta) -0.125*delta/mi/mf/mQ*lambda*(mi+mf+_eta[ix]*delta))); _f2.push_back(_Nfi[ix]*msum*(0.5/mi+0.25/mi/mq*(1.-0.5*lambda/mf)* (delta-(mi+mf)*_eta[ix]) -0.125*lambda/mi/mf/mQ*(delta+(mi+mf)*_eta[ix]))); _f3.push_back(_Nfi[ix]*msum*(0.5/mi-0.25/mi/mq*(1.-0.5*lambda/mf)* (mi+mf-_eta[ix]*delta) +0.125*lambda/mi/mf/mQ*(mi+mf+_eta[ix]*delta))); _g1.push_back(_Nfi[ix]*_eta[ix]*(1.+0.25*delta*lambda*(1./mi/mq-1./mf/mQ))); _g2.push_back(-0.25*msum*_Nfi[ix]*_eta[ix]*lambda*(1./mi/mq-1./mf/mQ)); _g3.push_back(-0.25*msum*_Nfi[ix]*_eta[ix]*lambda*(1./mi/mq+1./mf/mQ)); } else if(inspin==2&&outspin==4) { _f1.push_back(2.*_Nfi[ix]/sqrt(3.)*(1.+0.5*lambda*(1./mq+1./mQ))); _f2.push_back(_Nfi[ix]*msum/sqrt(3.)/mi*(1.+0.5*lambda*(1./mq+1./mQ))); _f3.push_back(-_Nfi[ix]*msum*msum/mi/mf/sqrt(3.)* (1.+0.5*lambda*(1./mq+1./mQ))); _g1.push_back(-2./sqrt(3.)*_Nfi[ix]); _g2.push_back(-_Nfi[ix]*msum/sqrt(3.)*lambda/mq/mi); _g3.push_back(-_f3.back()); } else {throw InitException() << "Unknown spin combination in ChengHeavyBaryon" << "FormFactor::doinit() " << Exception::abortnow;} } for(unsigned int ix=0;ixmass(); tcPDPtr part1=getParticleData(id1); Energy m1=part1->mass(); if ( part1->iSpin() == 2 ) { - Complex f1v,f2v,f3v,f4v,f1a,f2a,f3a,f4a; // dummy variables + Complex f1v,f2v,f3v,f1a,f2a,f3a; // dummy variables SpinHalfSpinHalfFormFactor(ZERO,ix,id0,id1,m0,m1,f1v,f2v,f3v,f1a,f2a,f3a); } else { Complex f1v,f2v,f3v,f4v,f1a,f2a,f3a,f4a; // dummy variables SpinHalfSpinThreeHalfFormFactor(ZERO,ix,id0,id1,m0,m1,f1v,f2v,f3v, f4v,f1a,f2a,f3a,f4a); } } } void ChengHeavyBaryonFormFactor::persistentOutput(PersistentOStream & os) const { os << ounit(_mu,MeV) << ounit(_md,MeV) << ounit(_ms,MeV) << ounit(_mc,MeV) << ounit(_mb,MeV) << _Nfi << _eta << _f1 << _f2 << _f3 << _g1 << _g2 << _g3 << ounit(_mVbc,MeV) << ounit(_mVbs,MeV) << ounit(_mVcs,MeV) << ounit(_mVbd,MeV) << ounit(_mVcu,MeV) << ounit(_mAbc,MeV) << ounit(_mAbs,MeV) << ounit(_mAcs,MeV) << ounit(_mAbd,MeV) << ounit(_mAcu,MeV); } void ChengHeavyBaryonFormFactor::persistentInput(PersistentIStream & is, int) { is >> iunit(_mu,MeV) >> iunit(_md,MeV) >> iunit(_ms,MeV) >> iunit(_mc,MeV) >> iunit(_mb,MeV) >> _Nfi >> _eta >> _f1 >> _f2 >> _f3 >> _g1 >> _g2 >> _g3 >> iunit(_mVbc,MeV) >> iunit(_mVbs,MeV) >> iunit(_mVcs,MeV) >> iunit(_mVbd,MeV) >> iunit(_mVcu,MeV) >> iunit(_mAbc,MeV) >> iunit(_mAbs,MeV) >> iunit(_mAcs,MeV) >> iunit(_mAbd,MeV) >> iunit(_mAcu,MeV); } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigChengHeavyBaryonFormFactor("Herwig::ChengHeavyBaryonFormFactor", "HwFormFactors.so"); void ChengHeavyBaryonFormFactor::Init() { static ClassDocumentation documentation ("The ChengHeavyBaryonFormFactor class is the implementation" " of the form-factors of PRD53, 1457 and PRD56, 2799 for the weak decay of" "baryons containing a heavy quark. This model can be used for either" "semi-leptonic decays, or with the factorization approximation for" " non-leptonic weak decays", "The weak decay of baryons containing a heavy quark used form factors from " "\\cite{Cheng:1995fe,Cheng:1996cs}.", "%\\cite{Cheng:1995fe}\n" "\\bibitem{Cheng:1995fe}\n" " H.~Y.~Cheng and B.~Tseng,\n" " %``1/M corrections to baryonic form-factors in the quark model,''\n" " Phys.\\ Rev.\\ D {\\bf 53} (1996) 1457\n" " [Erratum-ibid.\\ D {\\bf 55} (1997) 1697]\n" " [arXiv:hep-ph/9502391].\n" " %%CITATION = PHRVA,D53,1457;%%\n" "%\\cite{Cheng:1996cs}\n" "\\bibitem{Cheng:1996cs}\n" " H.~Y.~Cheng,\n" " %``Nonleptonic weak decays of bottom baryons,''\n" " Phys.\\ Rev.\\ D {\\bf 56} (1997) 2799\n" " [arXiv:hep-ph/9612223].\n" " %%CITATION = PHRVA,D56,2799;%%\n" ); static Parameter interfaceUpMass ("DownMass", "The consituent mass of the down quark", &ChengHeavyBaryonFormFactor::_md, GeV, 0.322*GeV, ZERO, 10.0*GeV, false, false, true); static Parameter interfaceDownMass ("UpMass", "The consituent mass of the up quark", &ChengHeavyBaryonFormFactor::_mu, GeV, 0.338*GeV, ZERO, 10.0*GeV, false, false, true); static Parameter interfacStrangeMass ("StrangeMass", "The consituent mass of the strange quark", &ChengHeavyBaryonFormFactor::_ms, GeV, 0.510*GeV, ZERO, 10.0*GeV, false, false, true); static Parameter interfaceCharmMass ("CharmMass", "The consituent mass of the charm quark", &ChengHeavyBaryonFormFactor::_mc, GeV, 1.6*GeV, ZERO, 10.0*GeV, false, false, true); static Parameter interfaceBottomMass ("BottomMass", "The consituent mass of the bottom quark", &ChengHeavyBaryonFormFactor::_mb, GeV, 5.0*GeV, ZERO, 10.0*GeV, false, false, true); static Parameter interfaceVectorMassbc ("VectorMassbc", "The vector mass for the b->c transitions.", &ChengHeavyBaryonFormFactor::_mVbc, GeV, 6.34*GeV, ZERO, 10.0*GeV, false, false, true); static Parameter interfaceAxialMassbc ("AxialMassbc", "The axial-vector mass for the b->c transitions.", &ChengHeavyBaryonFormFactor::_mAbc, GeV, 6.73*GeV, ZERO, 10.0*GeV, false, false, true); static Parameter interfaceVectorMassbs ("VectorMassbs", "The vector mass for the b->s transitions.", &ChengHeavyBaryonFormFactor::_mVbs, GeV, 5.42*GeV, ZERO, 10.0*GeV, false, false, true); static Parameter interfaceAxialMassbs ("AxialMassbs", "The axial-vector mass for the b->s transitions.", &ChengHeavyBaryonFormFactor::_mAbs, GeV, 5.86*GeV, ZERO, 10.0*GeV, false, false, true); static Parameter interfaceVectorMassbd ("VectorMassbd", "The vector mass for the b->d transitions.", &ChengHeavyBaryonFormFactor::_mVbd, GeV, 5.32*GeV, ZERO, 10.0*GeV, false, false, true); static Parameter interfaceAxialMassbd ("AxialMassbd", "The axial-vector mass for the b->d transitions.", &ChengHeavyBaryonFormFactor::_mAbd, GeV, 5.71*GeV, ZERO, 10.0*GeV, false, false, true); static Parameter interfaceVectorMasscs ("VectorMasscs", "The vector mass for the c->s transitions.", &ChengHeavyBaryonFormFactor::_mVcs, GeV, 2.11*GeV, ZERO, 10.0*GeV, false, false, true); static Parameter interfaceAxialMasscs ("AxialMasscs", "The axial-vector mass for the c->s transitions.", &ChengHeavyBaryonFormFactor::_mAcs, GeV, 2.54*GeV, ZERO, 10.0*GeV, false, false, true); static Parameter interfaceVectorMasscu ("VectorMasscu", "The vector mass for the c->u transitions.", &ChengHeavyBaryonFormFactor::_mVcu, GeV, 2.01*GeV, ZERO, 10.0*GeV, false, false, true); static Parameter interfaceAxialMasscu ("AxialMasscu", "The axial-vector mass for the c->u transitions.", &ChengHeavyBaryonFormFactor::_mAcu, GeV, 2.42*GeV, ZERO, 10.0*GeV, false, false, true); static ParVector interfaceNfi ("Nfi", "The prefactor for a given form factor", &ChengHeavyBaryonFormFactor::_Nfi, -1, 1.0, -10.0, 10.0, false, false, true); static ParVector interfaceEta ("Eta", "The eta parameter for the form factor", &ChengHeavyBaryonFormFactor::_eta, -1, 0.0, -10.0, 10.0, false, false, true); } // form factor for spin-1/2 to spin-1/2 void ChengHeavyBaryonFormFactor:: SpinHalfSpinHalfFormFactor(Energy2 q2,int iloc,int id0,int id1, Energy m0,Energy m1, Complex & f1v,Complex & f2v,Complex & f3v, Complex & f1a,Complex & f2a,Complex & f3a) { useMe(); id0=abs(id0); id1=abs(id1); // masses for the energy dependence of the form-factors Energy mV(ZERO),mA(ZERO); if((id0==4122&&id1==3122)||(id0==4232&&id1==3322)||(id0==4132&&id1==3312)|| (id0==4332&&id1==3334)) {mA=_mAcs;mV=_mVcs;} else if((id0==4332&&id1==3322)||(id0==4332&&id1==3324)) {mA=_mAcu;mV=_mVcu;} else if((id0==5122&&id1==4122)||(id0==5232&&id1==4232)||(id0==5132&&id1==4132)|| (id0==5332&&id1==4332)||(id0==5332&&id1==4334)) {mA=_mAbc;mV=_mVbc;} else if((id0==5122&&id1==3122)||(id0==5132&&id1==3312)||(id0==5232&&id1==3322)|| (id0==5332&&id1==3334)) {mA=_mAbs;mV=_mVbs;} else if((id0==5122&&id1==2112)||(id0==5132&&id1==3112)||(id0==5232&&id1==3212)|| (id0==5332&&id1==3312)||(id0==5232&&id1==3122)||(id0==5332&&id1==3314)) {mA=_mAbd;mV=_mVbd;} Energy delta=m0-m1; double Vfact = (1.-delta*delta/mV/mV)/(1.-q2/mV/mV); Vfact *=Vfact; double Afact = (1.-delta*delta/mA/mA)/(1.-q2/mA/mA); Afact *=Afact; f1v = _f1[iloc]*Vfact; f2v = _f2[iloc]*Vfact; f3v = _f3[iloc]*Vfact; f1a =-_g1[iloc]*Afact; f2a =-_g2[iloc]*Afact; f3a =-_g3[iloc]*Afact; } // form factor for spin-1/2 to spin-3/2 void ChengHeavyBaryonFormFactor:: SpinHalfSpinThreeHalfFormFactor(Energy2 q2,int iloc, int id0, int id1, Energy m0, Energy m1, Complex & g1v,Complex & g2v,Complex & g3v, Complex & g4v,Complex & g1a,Complex & g2a, Complex & g3a,Complex & g4a) { useMe(); id0=abs(id0); id1=abs(id1); // masses for the energy dependence of the form-factors Energy mV(ZERO),mA(ZERO); if((id0==4122&&id1==3122)||(id0==4232&&id1==3322)||(id0==4132&&id1==3312)|| (id0==4332&&id1==3334)) {mA=_mAcs;mV=_mVcs;} else if((id0==4332&&id1==3322)||(id0==4332&&id1==3324)) {mA=_mAcu;mV=_mVcu;} else if((id0==5122&&id1==4122)||(id0==5232&&id1==4232)||(id0==5132&&id1==4132)|| (id0==5332&&id1==4332)||(id0==5332&&id1==4334)) {mA=_mAbc;mV=_mVbc;} else if((id0==5122&&id1==3122)||(id0==5132&&id1==3312)||(id0==5232&&id1==3322)|| (id0==5332&&id1==3334)) {mA=_mAbs;mV=_mVbs;} else if((id0==5122&&id1==2112)||(id0==5132&&id1==3112)||(id0==5232&&id1==3212)|| (id0==5332&&id1==3312)||(id0==5232&&id1==3122)||(id0==5332&&id1==3314)) {mA=_mAbd;mV=_mVbd;} Energy delta=m0-m1; double Vfact = (1.-delta*delta/mV/mV)/(1.-q2/mV/mV); Vfact *=Vfact; double Afact = (1.-delta*delta/mA/mA)/(1.-q2/mA/mA); Afact *=Afact; g1v = _f1[iloc]*Vfact; g2v = _f2[iloc]*Vfact; g3v = _f3[iloc]*Vfact; g4v = 0.; g1a =-_g1[iloc]*Afact; g2a =-_g2[iloc]*Afact; g3a =-_g3[iloc]*Afact; g4a = 0.; } // output the information for the database void ChengHeavyBaryonFormFactor::dataBaseOutput(ofstream& output,bool header, bool create) const { if(header){output << "update decayers set parameters=\"";} if(create) {output << "create Herwig::ChengHeavyBaryonFormFactor " << name() << " \n";} output << "newdef " << name() << ":DownMass " << _md/GeV << " \n"; output << "newdef " << name() << ":UpMass " << _mu/GeV << " \n"; output << "newdef " << name() << ":StrangeMass " << _ms/GeV << " \n"; output << "newdef " << name() << ":CharmMass " << _mc/GeV << " \n"; output << "newdef " << name() << ":BottomMass " << _mb/GeV << " \n"; output << "newdef " << name() << ":VectorMassbc " << _mVbc/GeV << " \n"; output << "newdef " << name() << ":AxialMassbc " << _mAbc/GeV << " \n"; output << "newdef " << name() << ":VectorMassbs " << _mVbs/GeV << " \n"; output << "newdef " << name() << ":AxialMassbs " << _mAbs/GeV << " \n"; output << "newdef " << name() << ":VectorMassbd " << _mVbd/GeV << " \n"; output << "newdef " << name() << ":AxialMassbd " << _mAbd/GeV << " \n"; output << "newdef " << name() << ":VectorMasscs " << _mVcs/GeV << " \n"; output << "newdef " << name() << ":AxialMasscs " << _mAcs/GeV << " \n"; output << "newdef " << name() << ":VectorMasscu " << _mVcu/GeV << " \n"; output << "newdef " << name() << ":AxialMasscu " << _mAcu/GeV << " \n"; for(unsigned int ix=0;ix & ids, const double & z, const Energy & scale, const Energy & pT); /** * Has a POWHEG style correction */ virtual POWHEGType hasPOWHEGCorrection() {return FSR;} //@} public: /** * Which of the possible decays is required */ virtual int modeNumber(bool & , tcPDPtr , const tPDVector & ) const {return -1;} /** * Check if this decayer can perfom the decay for a particular mode. * Uses the modeNumber member but can be overridden * @param parent The decaying particle * @param children The decay products */ virtual bool accept(tcPDPtr parent, const tPDVector & children) const; /** * For a given decay mode and a given particle instance, perform the * decay and return the decay products. As this is the base class this * is not implemented. * @return The vector of particles produced in the decay. */ virtual ParticleVector decay(const Particle & parent, const tPDVector & children) const; /** * Return the matrix element squared for a given mode and phase-space channel. * @param ichan The channel we are calculating the matrix element for. * @param part The decaying Particle. * @param decay The particles produced in the decay. * @param meopt Option for the calculation of the matrix element * @return The matrix element squared for the phase-space configuration. */ virtual double me2(const int ichan, const Particle & part, const ParticleVector & decay, MEOption meopt) const; /** * Method to return an object to calculate the 3 (or higher body) partial width * @param dm The DecayMode * @return A pointer to a WidthCalculatorBase object capable of calculating the width */ virtual WidthCalculatorBasePtr threeBodyMEIntegrator(const DecayMode & dm) const; /** * The differential three body decay rate with one integral performed. * @param imode The mode for which the matrix element is needed. * @param q2 The scale, \e i.e. the mass squared of the decaying particle. * @param s The invariant mass which still needs to be integrate over. * @param m1 The mass of the first outgoing particle. * @param m2 The mass of the second outgoing particle. * @param m3 The mass of the third outgoing particle. * @return The differential rate \f$\frac{d\Gamma}{ds}\f$ */ virtual InvEnergy threeBodydGammads(const int imode, const Energy2 q2, const Energy2 s, const Energy m1, const Energy m2, const Energy m3) const; /** * Output the setup information for the particle database * @param os The stream to output the information to * @param header Whether or not to output the information for MySQL */ virtual void dataBaseOutput(ofstream & os,bool header) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** * The integrand for the integrate partial width */ Energy6 dGammaIntegrand(Energy2 mffb2, Energy2 mbf2, Energy mt, Energy mb, Energy mf, Energy mfb, Energy mw) const; protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const {return new_ptr(*this);} /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const {return new_ptr(*this);} //@} protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving and * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); //@} protected: /** * This function determines the point (\f$x_{g}\f$) where the condition that * \f$x_{a}\f$ be real supersedes that due to the external input * \f$\tilde{\kappa}\f$ where, again, \f$\kappa\f$ pertains to emissions from the * b. */ double xgbcut(double); /** * Full matrix element with a factor of \f$\frac{\alpha_SC_F}{x_g^2\pi}\f$ removed. * @param xw The momentum fraction of the W boson * @param xg The momentum fraction of the gluon. */ double me(double xw, double xg); protected: /** * Calculate matrix element ratio R/B */ virtual double matrixElementRatio(const Particle & inpart, const ParticleVector & decay2, const ParticleVector & decay3, MEOption meopt, ShowerInteraction inter); /** * LO matrix element for \f$t\to b W^\pm\f$ */ double loME(const Particle & inpart, const ParticleVector & decay); /** * LO matrix element for \f$t\to b W^\pm\f$ */ double realME(const Particle & inpart, const ParticleVector & decay, ShowerInteraction inter); private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ SMTopDecayer & operator=(const SMTopDecayer &) = delete; /** * Pointer to the W vertex */ AbstractFFVVertexPtr FFWVertex_; /** * Pointer to the gluon vertex */ AbstractFFVVertexPtr FFGVertex_; /** * Pointer to the photon vertex */ AbstractFFVVertexPtr FFPVertex_; /** * Pointer to the photon vertex */ AbstractVVVVertexPtr WWWVertex_; /** * Max weight for integration */ //@{ /** * Weight \f$W\to q\bar{q}'\f$ */ vector _wquarkwgt; /** * Weight \f$W\to \ell \nu\f$ */ vector _wleptonwgt; //@} /** * Pointer to the \f$W^\pm\f$ */ PDPtr _wplus; /** * Spin density matrix for the decay */ mutable RhoDMatrix _rho; /** * 1st spinor for the decay */ mutable vector _inHalf; /** * 2nd spinor for the decay */ mutable vector _outHalf; /** * 1st barred spinor for the decay */ mutable vector _inHalfBar; /** * 2nd barred spinor for the decay */ mutable vector _outHalfBar; /** * The mass of the W boson */ Energy _ma; /** * The mass of the bottom quark */ Energy _mc; /** * The top mass */ Energy _mt; /** * The gluon mass. */ Energy _mg; /** * The mass ratio for the W. */ double _a; /** * The mass ratio for the bottom. */ double _c; /** * The mass ratio for the gluon. */ double _g; /** * Two times the energy fraction of a. */ double _ktb; /** * Two times the energy fraction of the gluon. */ double _ktc; - /** - * Two times the energy fraction of the gluon. - */ - double _xg; - - /** - * Two times the energy fraction of a. - */ - double _xa; - - /** - * Two times the energy fraction of c. - */ - double _xc; /** * This determines the hard matrix element importance * sampling in _xg. _xg_sampling=2.0 samples as 1/xg^2. */ double _xg_sampling; /** * The enhancement factor for initial-state radiation */ double _initialenhance; /** * The enhancement factor for final-state radiation */ double _finalenhance; }; } #endif /* HERWIG_SMTopDecayer_H */ diff --git a/Decay/Perturbative/SMWDecayer.h b/Decay/Perturbative/SMWDecayer.h --- a/Decay/Perturbative/SMWDecayer.h +++ b/Decay/Perturbative/SMWDecayer.h @@ -1,502 +1,479 @@ // -*- C++ -*- // // SMWDecayer.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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. // #ifndef HERWIG_SMWDecayer_H #define HERWIG_SMWDecayer_H // // This is the declaration of the SMWDecayer class. // #include "Herwig/Decay/PerturbativeDecayer.h" #include "ThePEG/Helicity/Vertex/Vector/FFVVertex.h" #include "ThePEG/Helicity/Vertex/AbstractVVVVertex.h" #include "Herwig/Decay/DecayPhaseSpaceMode.h" namespace Herwig { using namespace ThePEG; using namespace ThePEG::Helicity; /** \ingroup Decay * * The SMWDecayer is designed to perform the decay of the * W boson to the Standard Model fermions, including the first order * electroweak corrections. * * @see PerturbativeDecayer * */ class SMWDecayer: public PerturbativeDecayer { public: /** * Default constructor. */ SMWDecayer(); public: /** * Virtual members to be overridden by inheriting classes * which implement hard corrections */ //@{ /** * Has an old fashioned ME correction */ virtual bool hasMECorrection() {return true;} /** * Initialize the ME correction */ virtual void initializeMECorrection(RealEmissionProcessPtr , double & , double & ); /** * Apply the soft matrix element correction * @param parent The initial particle in the current branching * @param progenitor The progenitor particle of the jet * @param fs Whether the emission is initial or final-state * @param highestpT The highest pT so far in the shower * @param ids ids of the particles produced in the branching * @param z The momentum fraction of the branching * @param scale the evolution scale of the branching * @param pT The transverse momentum of the branching * @return If true the emission should be vetoed */ virtual bool softMatrixElementVeto(PPtr parent, PPtr progenitor, const bool & fs, const Energy & highestpT, const vector & ids, const double & z, const Energy & scale, const Energy & pT); /** * Has a POWHEG style correction */ virtual POWHEGType hasPOWHEGCorrection() {return FSR;} public: /** * Which of the possible decays is required * @param cc Is this mode the charge conjugate * @param parent The decaying particle * @param children The decay products */ virtual int modeNumber(bool & cc, tcPDPtr parent, const tPDVector & children) const; /** * Return the matrix element squared for a given mode and phase-space channel. * @param ichan The channel we are calculating the matrix element for. * @param part The decaying Particle. * @param decay The particles produced in the decay. * @param meopt Option for the calculation of the matrix element * @return The matrix element squared for the phase-space configuration. */ virtual double me2(const int ichan, const Particle & part, const ParticleVector & decay,MEOption meopt) const; /** * Output the setup information for the particle database * @param os The stream to output the information to * @param header Whether or not to output the information for MySQL */ virtual void dataBaseOutput(ofstream & os,bool header) const; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * Standard Init function used to initialize the interfaces. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const {return new_ptr(*this);} /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const {return new_ptr(*this);} //@} protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving and * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); //@} protected: /** * Set the \f$\rho\f$ parameter */ void setRho(double); /** * Set the \f$\tilde{\kappa}\f$ parameters symmetrically */ void setKtildeSymm(); /** * Set second \f$\tilde{\kappa}\f$, given the first. */ void setKtilde2(); /** * Translate the variables from \f$x_q,x_{\bar{q}}\f$ to \f$\tilde{\kappa},z\f$ */ //@{ /** * Calculate \f$z\f$. */ double getZfromX(double, double); /** * Calculate \f$\tilde{\kappa}\f$. */ double getKfromX(double, double); //@} /** * Calculate \f$x_{q},x_{\bar{q}}\f$ from \f$\tilde{\kappa},z\f$. * @param kt \f$\tilde{\kappa}\f$ * @param z \f$z\f$ * @param x \f$x_{q}\f$ * @param xbar \f$x_{\bar{q}}\f$ */ void getXXbar(double kt, double z, double & x, double & xbar); /** * Soft weight */ //@{ /** * Soft quark weight calculated from \f$x_{q},x_{\bar{q}}\f$ * @param x \f$x_{q}\f$ * @param xbar \f$x_{\bar{q}}\f$ */ double qWeight(double x, double xbar); /** * Soft antiquark weight calculated from \f$x_{q},x_{\bar{q}}\f$ * @param x \f$x_{q}\f$ * @param xbar \f$x_{\bar{q}}\f$ */ double qbarWeight(double x, double xbar); /** * Soft quark weight calculated from \f$\tilde{q},z\f$ * @param qtilde \f$\tilde{q}\f$ * @param z \f$z\f$ */ double qWeightX(Energy qtilde, double z); /** * Soft antiquark weight calculated from \f$\tilde{q},z\f$ * @param qtilde \f$\tilde{q}\f$ * @param z \f$z\f$ */ double qbarWeightX(Energy qtilde, double z); //@} /** * ???? */ double u(double); /** * Vector and axial vector parts of the matrix element */ //@{ /** * Vector part of the matrix element */ double MEV(double, double); /** * Axial vector part of the matrix element */ double MEA(double, double); /** * The matrix element, given \f$x_1\f$, \f$x_2\f$. * @param x1 \f$x_1\f$ * @param x2 \f$x_2\f$ */ double PS(double x1, double x2); //@} protected: /** * Real emission term, for use in generating the hardest emission */ double calculateRealEmission(double x1, double x2, vector hardProcess, double phi, double muj, double muk, int iemit, bool subtract) const; /** * Calculate the ratio between NLO & LO ME */ double meRatio(vector partons, vector momenta, unsigned int iemitter,bool subtract) const; /** * Calculate matrix element ratio R/B */ virtual double matrixElementRatio(const Particle & inpart, const ParticleVector & decay2, const ParticleVector & decay3, MEOption meopt, ShowerInteraction inter); /** * Calculate the LO ME */ double loME(const vector & partons, const vector & momenta) const; /** * Calculate the NLO real emission piece of ME */ InvEnergy2 realME(const vector & partons, const vector & momenta, ShowerInteraction inter) const; private: /** * Private and non-existent assignment operator. */ SMWDecayer & operator=(const SMWDecayer &) = delete; private: /** * Pointer to the fermion-antifermion W vertex */ AbstractFFVVertexPtr FFWVertex_; /** * Pointer to the fermion-antifermion G vertex */ AbstractFFVVertexPtr FFGVertex_; /** * Pointer to the fermion-antifermion G vertex */ AbstractFFVVertexPtr FFPVertex_; /** * Pointer to the fermion-antifermion G vertex */ AbstractVVVVertexPtr WWWVertex_; /** * maximum weights for the different integrations */ //@{ /** * Weights for the W to quarks decays. */ vector quarkWeight_; /** * Weights for the W to leptons decays. */ vector leptonWeight_; //@} /** * Spin density matrix for the decay */ mutable RhoDMatrix rho_; /** * Polarization vectors for the decay */ mutable vector vectors_; /** * Spinors for the decay */ mutable vector wave_; /** * Barred spinors for the decay */ mutable vector wavebar_; private: /** * CM energy */ Energy d_Q_; /** * Quark mass */ Energy d_m_; /** * The rho parameter */ double d_rho_; /** * The v parameter */ double d_v_; /** * The initial kappa-tilde values for radiation from the quark */ double d_kt1_; /** * The initial kappa-tilde values for radiation from the antiquark */ double d_kt2_; /** * Cut-off parameter */ static const double EPS_; private: /** * The colour factor */ double CF_; /** * The W mass */ mutable Energy mW_; - // TODO: delete this - mutable double mu_; - - /** - * The reduced mass of particle 1 - */ - mutable double mu1_; - /** - * The reduced mass of particle 1 squared - */ - mutable double mu12_; - - /** - * The reduceed mass of particle 2 - */ - mutable double mu2_; - - /** - * The reduceed mass of particle 2 squared - */ - mutable double mu22_; - - /** * The strong coupling */ mutable double aS_; /** * The scale */ mutable Energy2 scale_; /** * Stuff for the POWHEG correction */ //@{ /** * ParticleData object for the gluon */ tcPDPtr gluon_; /** * The ParticleData objects for the fermions */ vector partons_; /** * The fermion momenta */ vector quark_; /** * The momentum of the radiated gauge boson */ Lorentz5Momentum gauge_; /** * The W boson */ PPtr wboson_; /** * W mass squared */ Energy2 mw2_; //@} /** * Whether ro return the LO or NLO result */ bool NLO_; }; } #endif /* HERWIG_SMWDecayer_H */ diff --git a/Decay/Radiation/IFDipole.h b/Decay/Radiation/IFDipole.h --- a/Decay/Radiation/IFDipole.h +++ b/Decay/Radiation/IFDipole.h @@ -1,385 +1,381 @@ // -*- C++ -*- // // IFDipole.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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. // #ifndef HERWIG_IFDipole_H #define HERWIG_IFDipole_H // // This is the declaration of the IFDipole class. // #include "ThePEG/Repository/EventGenerator.h" #include "Herwig/Utilities/Kinematics.h" #include "Herwig/Utilities/Maths.h" #include "ThePEG/StandardModel/StandardModelBase.h" #include "ThePEG/Vectors/Lorentz5Vector.h" #include "ThePEG/Interface/Interfaced.h" #include "IFDipole.fh" namespace Herwig { using namespace ThePEG; using ThePEG::Constants::pi; /** \ingroup Decay * * The IFDipole class generates radiation from a final-final dipole for * the generation of photons in decay by the SOPTHY algorithm. * * @see SOPTHY * @see \ref IFDipoleInterfaces "The interfaces" * defined for IFDipole. */ class IFDipole: public Interfaced { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ IFDipole() : _alpha(), _emin(1.0*MeV), _emax(), _multiplicity(), _map(2,0), _m(3), _chrg1(), _chrg2(), _qprf(2), _qnewprf(2), _lprf(), _bigLprf(), _qlab(2), _qnewlab(2), _llab(), _bigLlab(), _dipolewgt(), _yfswgt(), _jacobianwgt(), _mewgt(), _maxwgt(2.0), - _mode(1), _maxtry(500), _energyopt(1), _betaopt(1), _dipoleopt() + _mode(1), _maxtry(500), _energyopt(1), _betaopt(1) {} //@} public: /** * Member to generate the photons from the dipole * @param p The decaying particle * @param children The decay products * @return The decay products with additional radiation */ virtual ParticleVector generatePhotons(const Particle & p,ParticleVector children); public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const {return new_ptr(*this);} /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const {return new_ptr(*this);} //@} protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); //@} protected: /** * Average crude photon multiplicity * @param beta1 Velocity of the first charged particle, \f$\beta_1\f$. * @param ombeta1 One minus the velocity of the first particle, \f$1-\beta_1\f$. * @return The average photon multiplicity */ double nbar(double beta1,double ombeta1) { return _alpha/pi*_chrg1*_chrg2/beta1* log((1.+beta1)/ombeta1)*log(_emax/_emin); } /** * Generate the momentum of a photon * @param beta1 The velocity, \f$\beta_1\f$, of the first charged particle * @param ombeta1 One minus the velocity, \f$1-\beta_1\f$, of the first * charged particle which is supplied for numerical stability * @return The contribution to the dipole weight */ double photon(double beta1,double ombeta1); /** * Calculate the exact weight for the dipole. * @param beta1 Velocity of the first charged particle, \f$\beta_1\f$ * @param ombeta1 One minus the velocity of the first particle, \f$1-\beta_1\f$ * @param iphot The number of the photon for which the weight is required * @return The weight */ double exactDipoleWeight(double beta1,double ombeta1, unsigned int iphot) { double ombc; // if cos is greater than zero use result accurate as cos->1 if(_cosphot[iphot]>0.0) ombc=ombeta1+beta1*sqr(_sinphot[iphot])/(1.+_cosphot[iphot]); // if cos is less than zero use result accurate as cos->-1 else ombc=1.-beta1*_cosphot[iphot]; return 1.0*sqr(beta1*_sinphot[iphot]/ombc); } /** * The crude YFS form factor for calculating the weight * @param b Velocity of the first charged particle, \f$\beta_1\f$ * @param omb One minus the velocity of the first particle, \f$1-\beta_1\f$ * @return The YFS form factor */ double crudeYFSFormFactor(double b,double omb) { double Y =-_alpha/pi*_chrg1*_chrg2 / b * log((1.+b)/omb) * log(_m[0]/(2.*_emin)); return exp(Y); } /** * The exact YFS form factor for calculating the weight * @param beta1 Velocity of the first charged particle, \f$\beta_1\f$ * @param beta2 Velocity of the second charged particle, \f$\beta_2\f$. * @param ombeta1 One minus the velocity of the first particle, \f$1-\beta_1\f$ * @param ombeta2 One minus the velocity of the second particle, \f$1-\beta_2\f$ * @return The YFS form factor */ double exactYFSFormFactor(double beta1,double ombeta1, double beta2,double ombeta2); /** * Jacobian factor for the weight */ double jacobianWeight(); /** * Matrix element weight */ double meWeight(ParticleVector children); /** * Member which generates the photons * @param boost Boost vector to take the particles produced back from * the decaying particle's rest frame to the lab * @param children The decay products */ double makePhotons(Boost boost,ParticleVector children); /** * Compute a Lorentz transform from p to q * @param p Original momentum * @param q Final momentum */ LorentzRotation solveBoost(const Lorentz5Momentum & q, const Lorentz5Momentum & p ) const; private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ IFDipole & operator=(const IFDipole &) = delete; private: /** * the fine structure constant at $q^2=0$ */ double _alpha; /** * The minimum photon energy */ Energy _emin; /** * The maximum photon energy */ Energy _emax; /** * Photon multiplicity being generated */ unsigned int _multiplicity; /** * Map from arguments of lists such that * _q???[_map[0]] is the charged child and * _q???[_map[1]] is the neutral child. */ vector _map; /** * Masses of the particles involved */ vector _m; /** * charge of the parent particle */ double _chrg1; /** * charge of the (charged) child particle */ double _chrg2; /** * Momentum of the particles in the parent's rest frame */ //@{ /** * Momenta of the charged particles in the parent's rest frame before radiation */ vector _qprf; /** * Momenta of the charged particles in the parent's rest frame after radiation */ vector _qnewprf; /** * Momenta of the photons in the parent rest frame */ vector _lprf; /** * Total momentum of the photons in the parent rest frame */ Lorentz5Momentum _bigLprf; //@} /** * Momentum of the particles in the lab frame */ //@{ /** * Momenta of the charged particles in the lab frame before radiation */ vector _qlab; /** * Momenta of the charged particles in the lab frame after radiation */ vector _qnewlab; /** * Momenta of the photons in the lab frame */ vector _llab; /** * Total momentum of the photons in the lab frame */ Lorentz5Momentum _bigLlab; //@} /** * Reweighting factors due to differences between the true and crude * distributions */ //@{ /** * Reweighting factor for the real emission */ double _dipolewgt; /** * Reweighting factor for the YFS form-factor */ double _yfswgt; /** * Reweighting factor due to phase space */ double _jacobianwgt; /** * Reweighting factor due to matrix element corrections */ double _mewgt; /** * Maximum weight */ double _maxwgt; //@} /** * Angles of the photons with respect to the first charged particle * which are stored for numerical accuracy */ //@{ /** * Cosine of the photon angles */ vector _cosphot; /** * Sine of the photon angles */ vector _sinphot; //@} /** * Type of unweighting to perform */ unsigned int _mode; /** * Maximum number of attempts to generate a result */ unsigned int _maxtry; /** * Option for the energy cut-off */ unsigned int _energyopt; /** * Option for the inclusion of higher order corrections */ unsigned int _betaopt; - /** - * Option for the form of the primary distribution - */ - unsigned int _dipoleopt; }; } #endif /* HERWIG_IFDipole_H */ diff --git a/Hadronization/ClusterFissioner.cc b/Hadronization/ClusterFissioner.cc --- a/Hadronization/ClusterFissioner.cc +++ b/Hadronization/ClusterFissioner.cc @@ -1,1121 +1,1121 @@ // -*- C++ -*- // // ClusterFissioner.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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. // // // Thisk is the implementation of the non-inlined, non-templated member // functions of the ClusterFissioner class. // #include "ClusterFissioner.h" #include #include #include #include #include #include #include #include "Herwig/Utilities/Kinematics.h" #include "CheckId.h" #include "Cluster.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include using namespace Herwig; DescribeClass describeClusterFissioner("Herwig::ClusterFissioner",""); ClusterFissioner::ClusterFissioner() : _clMaxLight(3.35*GeV), _clMaxBottom(3.35*GeV), _clMaxCharm(3.35*GeV), _clMaxExotic(3.35*GeV), _clPowLight(2.0), _clPowBottom(2.0), _clPowCharm(2.0), _clPowExotic(2.0), _pSplitLight(1.0), _pSplitBottom(1.0), _pSplitCharm(1.0), _pSplitExotic(1.0), - _fissionCluster(0), _fissionPwtUquark(1), _fissionPwtDquark(1), _fissionPwtSquark(0.5), + _fissionCluster(0), _btClM(1.0*GeV), _iopRem(1), _kappa(1.0e15*GeV/meter), _enhanceSProb(0), _m0Fission(2.*GeV), _massMeasure(0) {} IBPtr ClusterFissioner::clone() const { return new_ptr(*this); } IBPtr ClusterFissioner::fullclone() const { return new_ptr(*this); } void ClusterFissioner::persistentOutput(PersistentOStream & os) const { os << _hadronsSelector << ounit(_clMaxLight,GeV) << ounit(_clMaxBottom,GeV) << ounit(_clMaxCharm,GeV) << ounit(_clMaxExotic,GeV) << _clPowLight << _clPowBottom << _clPowCharm << _clPowExotic << _pSplitLight << _pSplitBottom << _pSplitCharm << _pSplitExotic << _fissionCluster << _fissionPwtUquark << _fissionPwtDquark << _fissionPwtSquark << ounit(_btClM,GeV) << _iopRem << ounit(_kappa, GeV/meter) << _enhanceSProb << ounit(_m0Fission,GeV) << _massMeasure; } void ClusterFissioner::persistentInput(PersistentIStream & is, int) { is >> _hadronsSelector >> iunit(_clMaxLight,GeV) >> iunit(_clMaxBottom,GeV) >> iunit(_clMaxCharm,GeV) >> iunit(_clMaxExotic,GeV) >> _clPowLight >> _clPowBottom >> _clPowCharm >> _clPowExotic >> _pSplitLight >> _pSplitBottom >> _pSplitCharm >> _pSplitExotic >> _fissionCluster >> _fissionPwtUquark >> _fissionPwtDquark >> _fissionPwtSquark >> iunit(_btClM,GeV) >> _iopRem >> iunit(_kappa, GeV/meter) >> _enhanceSProb >> iunit(_m0Fission,GeV) >> _massMeasure; } void ClusterFissioner::Init() { static ClassDocumentation documentation ("Class responsibles for chopping up the clusters"); static Reference interfaceHadronSelector("HadronSelector", "A reference to the HadronSelector object", &Herwig::ClusterFissioner::_hadronsSelector, false, false, true, false); // ClMax for light, Bottom, Charm and exotic (e.g. Susy) quarks static Parameter interfaceClMaxLight ("ClMaxLight","cluster max mass for light quarks (unit [GeV])", &ClusterFissioner::_clMaxLight, GeV, 3.35*GeV, ZERO, 10.0*GeV, false,false,false); static Parameter interfaceClMaxBottom ("ClMaxBottom","cluster max mass for b quarks (unit [GeV])", &ClusterFissioner::_clMaxBottom, GeV, 3.35*GeV, ZERO, 10.0*GeV, false,false,false); static Parameter interfaceClMaxCharm ("ClMaxCharm","cluster max mass for c quarks (unit [GeV])", &ClusterFissioner::_clMaxCharm, GeV, 3.35*GeV, ZERO, 10.0*GeV, false,false,false); static Parameter interfaceClMaxExotic ("ClMaxExotic","cluster max mass for exotic quarks (unit [GeV])", &ClusterFissioner::_clMaxExotic, GeV, 3.35*GeV, ZERO, 10.0*GeV, false,false,false); // ClPow for light, Bottom, Charm and exotic (e.g. Susy) quarks static Parameter interfaceClPowLight ("ClPowLight","cluster mass exponent for light quarks", &ClusterFissioner::_clPowLight, 0, 2.0, 0.0, 10.0,false,false,false); static Parameter interfaceClPowBottom ("ClPowBottom","cluster mass exponent for b quarks", &ClusterFissioner::_clPowBottom, 0, 2.0, 0.0, 10.0,false,false,false); static Parameter interfaceClPowCharm ("ClPowCharm","cluster mass exponent for c quarks", &ClusterFissioner::_clPowCharm, 0, 2.0, 0.0, 10.0,false,false,false); static Parameter interfaceClPowExotic ("ClPowExotic","cluster mass exponent for exotic quarks", &ClusterFissioner::_clPowExotic, 0, 2.0, 0.0, 10.0,false,false,false); // PSplit for light, Bottom, Charm and exotic (e.g. Susy) quarks static Parameter interfacePSplitLight ("PSplitLight","cluster mass splitting param for light quarks", &ClusterFissioner::_pSplitLight, 0, 1.0, 0.0, 10.0,false,false,false); static Parameter interfacePSplitBottom ("PSplitBottom","cluster mass splitting param for b quarks", &ClusterFissioner::_pSplitBottom, 0, 1.0, 0.0, 10.0,false,false,false); static Parameter interfacePSplitCharm ("PSplitCharm","cluster mass splitting param for c quarks", &ClusterFissioner::_pSplitCharm, 0, 1.0, 0.0, 10.0,false,false,false); static Parameter interfacePSplitExotic ("PSplitExotic","cluster mass splitting param for exotic quarks", &ClusterFissioner::_pSplitExotic, 0, 1.0, 0.0, 10.0,false,false,false); static Switch interfaceFission ("Fission", "Option for different Fission options", &ClusterFissioner::_fissionCluster, 1, false, false); static SwitchOption interfaceFissionDefault (interfaceFission, "default", "Normal cluster fission which depends on the hadron selector class.", 0); static SwitchOption interfaceFissionNew (interfaceFission, "new", "Alternative cluster fission which does not depend on the hadron selector class", 1); static Parameter interfaceFissionPwtUquark ("FissionPwtUquark", "Weight for fission in U quarks", &ClusterFissioner::_fissionPwtUquark, 1, 0.0, 1.0, false, false, Interface::limited); static Parameter interfaceFissionPwtDquark ("FissionPwtDquark", "Weight for fission in D quarks", &ClusterFissioner::_fissionPwtDquark, 1, 0.0, 1.0, false, false, Interface::limited); static Parameter interfaceFissionPwtSquark ("FissionPwtSquark", "Weight for fission in S quarks", &ClusterFissioner::_fissionPwtSquark, 0.5, 0.0, 1.0, false, false, Interface::limited); static Switch interfaceRemnantOption ("RemnantOption", "Option for the treatment of remnant clusters", &ClusterFissioner::_iopRem, 1, false, false); static SwitchOption interfaceRemnantOptionSoft (interfaceRemnantOption, "Soft", "Both clusters produced in the fission of the beam cluster" " are treated as soft clusters.", 0); static SwitchOption interfaceRemnantOptionHard (interfaceRemnantOption, "Hard", "Only the cluster containing the remnant is treated as a soft cluster.", 1); static SwitchOption interfaceRemnantOptionVeryHard (interfaceRemnantOption, "VeryHard", "Even remnant clusters are treated as hard, i.e. all clusters the same", 2); static Parameter interfaceBTCLM ("SoftClusterFactor", "Parameter for the mass spectrum of remnant clusters", &ClusterFissioner::_btClM, GeV, 1.*GeV, 0.1*GeV, 10.0*GeV, false, false, Interface::limited); static Parameter interfaceStringTension ("StringTension", "String tension used in vertex displacement calculation", &ClusterFissioner::_kappa, GeV/meter, 1.0e15*GeV/meter, ZERO, ZERO, false, false, Interface::lowerlim); static Switch interfaceEnhanceSProb ("EnhanceSProb", "Option for enhancing strangeness", &ClusterFissioner::_enhanceSProb, 0, false, false); static SwitchOption interfaceEnhanceSProbNo (interfaceEnhanceSProb, "No", "No strangeness enhancement.", 0); static SwitchOption interfaceEnhanceSProbScaled (interfaceEnhanceSProb, "Scaled", "Scaled strangeness enhancement", 1); static SwitchOption interfaceEnhanceSProbExponential (interfaceEnhanceSProb, "Exponential", "Exponential strangeness enhancement", 2); static Switch interfaceMassMeasure ("MassMeasure", "Option to use different mass measures", &ClusterFissioner::_massMeasure,0,false,false); static SwitchOption interfaceMassMeasureMass (interfaceMassMeasure, "Mass", "Mass Measure", 0); static SwitchOption interfaceMassMeasureLambda (interfaceMassMeasure, "Lambda", "Lambda Measure", 1); static Parameter interfaceFissionMassScale ("FissionMassScale", "Cluster fission mass scale", &ClusterFissioner::_m0Fission, GeV, 2.0*GeV, 0.1*GeV, 50.*GeV, false, false, Interface::limited); } tPVector ClusterFissioner::fission(ClusterVector & clusters, bool softUEisOn) { // return if no clusters if (clusters.empty()) return tPVector(); /***************** * Loop over the (input) collection of cluster pointers, and store in * the vector splitClusters all the clusters that need to be split * (these are beam clusters, if soft underlying event is off, and * heavy non-beam clusters). ********************/ stack splitClusters; for(ClusterVector::iterator it = clusters.begin() ; it != clusters.end() ; ++it) { /************** * Skip 3-component clusters that have been redefined (as 2-component * clusters) or not available clusters. The latter check is indeed * redundant now, but it is used for possible future extensions in which, * for some reasons, some of the clusters found by ClusterFinder are tagged * straight away as not available. **************/ if((*it)->isRedefined() || !(*it)->isAvailable()) continue; // if the cluster is a beam cluster add it to the vector of clusters // to be split or if it is heavy if((*it)->isBeamCluster() || isHeavy(*it)) splitClusters.push(*it); } tPVector finalhadrons; cut(splitClusters, clusters, finalhadrons, softUEisOn); return finalhadrons; } void ClusterFissioner::cut(stack & clusterStack, ClusterVector &clusters, tPVector & finalhadrons, bool softUEisOn) { /************************************************** * This method does the splitting of the cluster pointed by cluPtr * and "recursively" by all of its cluster children, if heavy. All of these * new children clusters are added (indeed the pointers to them) to the * collection of cluster pointers collecCluPtr. The method works as follows. * Initially the vector vecCluPtr contains just the input pointer to the * cluster to be split. Then it will be filled "recursively" by all * of the cluster's children that are heavy enough to require, in their turn, * to be split. In each loop, the last element of the vector vecCluPtr is * considered (only once because it is then removed from the vector). * This approach is conceptually recursive, but avoid the overhead of * a concrete recursive function. Furthermore it requires minimal changes * in the case that the fission of an heavy cluster could produce more * than two cluster children as assumed now. * * Draw the masses: for normal, non-beam clusters a power-like mass dist * is used, whereas for beam clusters a fast-decreasing exponential mass * dist is used instead (to avoid many iterative splitting which could * produce an unphysical large transverse energy from a supposed soft beam * remnant process). ****************************************/ // Here we recursively loop over clusters in the stack and cut them while (!clusterStack.empty()) { // take the last element of the vector ClusterPtr iCluster = clusterStack.top(); clusterStack.pop(); // split it cutType ct = iCluster->numComponents() == 2 ? cutTwo(iCluster, finalhadrons, softUEisOn) : cutThree(iCluster, finalhadrons, softUEisOn); // There are cases when we don't want to split, even if it fails mass test if(!ct.first.first || !ct.second.first) { // if an unsplit beam cluster leave if for the underlying event if(iCluster->isBeamCluster() && softUEisOn) iCluster->isAvailable(false); continue; } // check if clusters ClusterPtr one = dynamic_ptr_cast(ct.first.first); ClusterPtr two = dynamic_ptr_cast(ct.second.first); // is a beam cluster must be split into two clusters if(iCluster->isBeamCluster() && (!one||!two) && softUEisOn) { iCluster->isAvailable(false); continue; } // There should always be a intermediate quark(s) from the splitting assert(ct.first.second && ct.second.second); /// \todo sort out motherless quark pairs here. Watch out for 'quark in final state' errors iCluster->addChild(ct.first.first); // iCluster->addChild(ct.first.second); // ct.first.second->addChild(ct.first.first); iCluster->addChild(ct.second.first); // iCluster->addChild(ct.second.second); // ct.second.second->addChild(ct.second.first); // Sometimes the clusters decay C -> H + C' rather then C -> C' + C'' if(one) { clusters.push_back(one); if(one->isBeamCluster() && softUEisOn) one->isAvailable(false); if(isHeavy(one) && one->isAvailable()) clusterStack.push(one); } if(two) { clusters.push_back(two); if(two->isBeamCluster() && softUEisOn) two->isAvailable(false); if(isHeavy(two) && two->isAvailable()) clusterStack.push(two); } } } namespace { /** * Check if can't make a hadron from the partons */ bool cantMakeHadron(tcPPtr p1, tcPPtr p2) { return ! CheckId::canBeHadron(p1->dataPtr(), p2->dataPtr()); } /** * Check if can't make a diquark from the partons */ bool cantMakeDiQuark(tcPPtr p1, tcPPtr p2) { long id1 = p1->id(), id2 = p2->id(); return ! (QuarkMatcher::Check(id1) && QuarkMatcher::Check(id2) && id1*id2>0); } } ClusterFissioner::cutType ClusterFissioner::cutTwo(ClusterPtr & cluster, tPVector & finalhadrons, bool softUEisOn) { // need to make sure only 2-cpt clusters get here assert(cluster->numComponents() == 2); tPPtr ptrQ1 = cluster->particle(0); tPPtr ptrQ2 = cluster->particle(1); Energy Mc = cluster->mass(); assert(ptrQ1); assert(ptrQ2); // And check if those particles are from a beam remnant bool rem1 = cluster->isBeamRemnant(0); bool rem2 = cluster->isBeamRemnant(1); // workout which distribution to use bool soft1(false),soft2(false); switch (_iopRem) { case 0: soft1 = rem1 || rem2; soft2 = rem2 || rem1; break; case 1: soft1 = rem1; soft2 = rem2; break; } // Initialization for the exponential ("soft") mass distribution. static const int max_loop = 1000; int counter = 0; Energy Mc1 = ZERO, Mc2 = ZERO,m1=ZERO,m2=ZERO,m=ZERO; tcPDPtr toHadron1, toHadron2; PPtr newPtr1 = PPtr (); PPtr newPtr2 = PPtr (); bool succeeded = false; do { succeeded = false; ++counter; if (_enhanceSProb == 0){ drawNewFlavour(newPtr1,newPtr2); } else { Energy2 mass2 = clustermass(cluster); drawNewFlavourEnhanced(newPtr1,newPtr2,mass2); } // check for right ordering assert (ptrQ2); assert (newPtr2); assert (ptrQ2->dataPtr()); assert (newPtr2->dataPtr()); if(cantMakeHadron(ptrQ1, newPtr1) || cantMakeHadron(ptrQ2, newPtr2)) { swap(newPtr1, newPtr2); // check again if(cantMakeHadron(ptrQ1, newPtr1) || cantMakeHadron(ptrQ2, newPtr2)) { throw Exception() << "ClusterFissioner cannot split the cluster (" << ptrQ1->PDGName() << ' ' << ptrQ2->PDGName() << ") into hadrons.\n" << Exception::runerror; } } // Check that new clusters can produce particles and there is enough // phase space to choose the drawn flavour m1 = ptrQ1->data().constituentMass(); m2 = ptrQ2->data().constituentMass(); m = newPtr1->data().constituentMass(); // Do not split in the case there is no phase space available if(Mc < m1+m + m2+m) continue; // power for splitting double exp1=_pSplitLight; double exp2=_pSplitLight; if (CheckId::isExotic(ptrQ1->dataPtr())) exp1 = _pSplitExotic; else if(CheckId::hasBottom(ptrQ1->dataPtr()))exp1 = _pSplitBottom; else if(CheckId::hasCharm(ptrQ1->dataPtr())) exp1 = _pSplitCharm; if (CheckId::isExotic(ptrQ2->dataPtr())) exp2 = _pSplitExotic; else if(CheckId::hasBottom(ptrQ2->dataPtr())) exp2 = _pSplitBottom; else if(CheckId::hasCharm(ptrQ2->dataPtr())) exp2 = _pSplitCharm; // If, during the drawing of candidate masses, too many attempts fail // (because the phase space available is tiny) /// \todo run separate loop here? Mc1 = drawChildMass(Mc,m1,m2,m,exp1,soft1); Mc2 = drawChildMass(Mc,m2,m1,m,exp2,soft2); if(Mc1 < m1+m || Mc2 < m+m2 || Mc1+Mc2 > Mc) continue; /************************** * New (not present in Fortran Herwig): * check whether the fragment masses Mc1 and Mc2 are above the * threshold for the production of the lightest pair of hadrons with the * right flavours. If not, then set by hand the mass to the lightest * single hadron with the right flavours, in order to solve correctly * the kinematics, and (later in this method) create directly such hadron * and add it to the children hadrons of the cluster that undergoes the * fission (i.e. the one pointed by iCluPtr). Notice that in this special * case, the heavy cluster that undergoes the fission has one single * cluster child and one single hadron child. We prefer this approach, * rather than to create a light cluster, with the mass set equal to * the lightest hadron, and let then the class LightClusterDecayer to do * the job to decay it to that single hadron, for two reasons: * First, because the sum of the masses of the two constituents can be, * in this case, greater than the mass of that hadron, hence it would * be impossible to solve the kinematics for such two components, and * therefore we would have a cluster whose components are undefined. * Second, the algorithm is faster, because it avoids the reshuffling * procedure that would be necessary if we used LightClusterDecayer * to decay the light cluster to the lightest hadron. ****************************/ toHadron1 = _hadronsSelector->chooseSingleHadron(ptrQ1->dataPtr(), newPtr1->dataPtr(),Mc1); if(toHadron1) Mc1 = toHadron1->mass(); toHadron2 = _hadronsSelector->chooseSingleHadron(ptrQ2->dataPtr(), newPtr2->dataPtr(),Mc2); if(toHadron2) Mc2 = toHadron2->mass(); // if a beam cluster not allowed to decay to hadrons if(cluster->isBeamCluster() && (toHadron1||toHadron2) && softUEisOn) continue; // Check if the decay kinematics is still possible: if not then // force the one-hadron decay for the other cluster as well. if(Mc1 + Mc2 > Mc) { if(!toHadron1) { toHadron1 = _hadronsSelector->chooseSingleHadron(ptrQ1->dataPtr(), newPtr1->dataPtr(),Mc-Mc2); if(toHadron1) Mc1 = toHadron1->mass(); } else if(!toHadron2) { toHadron2 = _hadronsSelector->chooseSingleHadron(ptrQ2->dataPtr(), newPtr2->dataPtr(),Mc-Mc1); if(toHadron2) Mc2 = toHadron2->mass(); } } succeeded = (Mc >= Mc1+Mc2); } while (!succeeded && counter < max_loop); if(counter >= max_loop) { static const PPtr null = PPtr(); return cutType(PPair(null,null),PPair(null,null)); } // Determined the (5-components) momenta (all in the LAB frame) Lorentz5Momentum pClu = cluster->momentum(); // known Lorentz5Momentum p0Q1 = ptrQ1->momentum(); // known (mom Q1 before fission) Lorentz5Momentum pClu1, pClu2, pQ1, pQone, pQtwo, pQ2; //unknown pClu1.setMass(Mc1); pClu2.setMass(Mc2); pQ1.setMass(m1); pQ2.setMass(m2); pQone.setMass(m); pQtwo.setMass(m); calculateKinematics(pClu,p0Q1,toHadron1,toHadron2, pClu1,pClu2,pQ1,pQone,pQtwo,pQ2); // out /****************** * The previous methods have determined the kinematics and positions * of C -> C1 + C2. * In the case that one of the two product is light, that means either * decayOneHadronClu1 or decayOneHadronClu2 is true, then the momenta * of the components of that light product have not been determined, * and a (light) cluster will not be created: the heavy father cluster * decays, in this case, into a single (not-light) cluster and a * single hadron. In the other, "normal", cases the father cluster * decays into two clusters, each of which has well defined components. * Notice that, in the case of components which point to particles, the * momenta of the components is properly set to the new values, whereas * we do not change the momenta of the pointed particles, because we * want to keep all of the information (that is the new momentum of a * component after the splitting, which is contained in the _momentum * member of the Component class, and the (old) momentum of that component * before the splitting, which is contained in the momentum of the * pointed particle). Please not make confusion of this only apparent * inconsistency! ********************/ LorentzPoint posC,pos1,pos2; posC = cluster->vertex(); calculatePositions(pClu, posC, pClu1, pClu2, pos1, pos2); cutType rval; if(toHadron1) { rval.first = produceHadron(toHadron1, newPtr1, pClu1, pos1); finalhadrons.push_back(rval.first.first); } else { rval.first = produceCluster(ptrQ1, newPtr1, pClu1, pos1, pQ1, pQone, rem1); } if(toHadron2) { rval.second = produceHadron(toHadron2, newPtr2, pClu2, pos2); finalhadrons.push_back(rval.second.first); } else { rval.second = produceCluster(ptrQ2, newPtr2, pClu2, pos2, pQ2, pQtwo, rem2); } return rval; } ClusterFissioner::cutType ClusterFissioner::cutThree(ClusterPtr & cluster, tPVector & finalhadrons, bool softUEisOn) { // need to make sure only 3-cpt clusters get here assert(cluster->numComponents() == 3); // extract quarks tPPtr ptrQ[3] = {cluster->particle(0),cluster->particle(1),cluster->particle(2)}; assert( ptrQ[0] && ptrQ[1] && ptrQ[2] ); // find maximum mass pair Energy mmax(ZERO); Lorentz5Momentum pDiQuark; int iq1(-1),iq2(-1); Lorentz5Momentum psum; for(int q1=0;q1<3;++q1) { psum+= ptrQ[q1]->momentum(); for(int q2=q1+1;q2<3;++q2) { Lorentz5Momentum ptest = ptrQ[q1]->momentum()+ptrQ[q2]->momentum(); ptest.rescaleMass(); Energy mass = ptest.m(); if(mass>mmax) { mmax = mass; pDiQuark = ptest; iq1 = q1; iq2 = q2; } } } // and the spectators int iother(-1); for(int ix=0;ix<3;++ix) if(ix!=iq1&&ix!=iq2) iother=ix; assert(iq1>=0&&iq2>=0&&iother>=0); // And check if those particles are from a beam remnant bool rem1 = cluster->isBeamRemnant(iq1); bool rem2 = cluster->isBeamRemnant(iq2); // workout which distribution to use bool soft1(false),soft2(false); switch (_iopRem) { case 0: soft1 = rem1 || rem2; soft2 = rem2 || rem1; break; case 1: soft1 = rem1; soft2 = rem2; break; } // Initialization for the exponential ("soft") mass distribution. static const int max_loop = 1000; int counter = 0; Energy Mc1 = ZERO, Mc2 = ZERO, m1=ZERO, m2=ZERO, m=ZERO; tcPDPtr toHadron; bool toDiQuark(false); PPtr newPtr1 = PPtr(),newPtr2 = PPtr(); PDPtr diquark; bool succeeded = false; do { succeeded = false; ++counter; if (_enhanceSProb == 0) { drawNewFlavour(newPtr1,newPtr2); } else { Energy2 mass2 = clustermass(cluster); drawNewFlavourEnhanced(newPtr1,newPtr2, mass2); } // randomly pick which will be (anti)diquark and which a mesonic cluster if(UseRandom::rndbool()) { swap(iq1,iq2); swap(rem1,rem2); } // check first order if(cantMakeHadron(ptrQ[iq1], newPtr1) || cantMakeDiQuark(ptrQ[iq2], newPtr2)) { swap(newPtr1,newPtr2); } // check again if(cantMakeHadron(ptrQ[iq1], newPtr1) || cantMakeDiQuark(ptrQ[iq2], newPtr2)) { throw Exception() << "ClusterFissioner cannot split the cluster (" << ptrQ[iq1]->PDGName() << ' ' << ptrQ[iq2]->PDGName() << ") into a hadron and diquark.\n" << Exception::runerror; } // Check that new clusters can produce particles and there is enough // phase space to choose the drawn flavour m1 = ptrQ[iq1]->data().constituentMass(); m2 = ptrQ[iq2]->data().constituentMass(); m = newPtr1->data().constituentMass(); // Do not split in the case there is no phase space available if(mmax < m1+m + m2+m) continue; // power for splitting double exp1(_pSplitLight),exp2(_pSplitLight); if (CheckId::isExotic (ptrQ[iq1]->dataPtr())) exp1 = _pSplitExotic; else if(CheckId::hasBottom(ptrQ[iq1]->dataPtr())) exp1 = _pSplitBottom; else if(CheckId::hasCharm (ptrQ[iq1]->dataPtr())) exp1 = _pSplitCharm; if (CheckId::isExotic (ptrQ[iq2]->dataPtr())) exp2 = _pSplitExotic; else if(CheckId::hasBottom(ptrQ[iq2]->dataPtr())) exp2 = _pSplitBottom; else if(CheckId::hasCharm (ptrQ[iq2]->dataPtr())) exp2 = _pSplitCharm; // If, during the drawing of candidate masses, too many attempts fail // (because the phase space available is tiny) /// \todo run separate loop here? Mc1 = drawChildMass(mmax,m1,m2,m,exp1,soft1); Mc2 = drawChildMass(mmax,m2,m1,m,exp2,soft2); if(Mc1 < m1+m || Mc2 < m+m2 || Mc1+Mc2 > mmax) continue; // check if need to force meson clster to hadron toHadron = _hadronsSelector->chooseSingleHadron(ptrQ[iq1]->dataPtr(), newPtr1->dataPtr(),Mc1); if(toHadron) Mc1 = toHadron->mass(); // check if need to force diquark cluster to be on-shell toDiQuark = false; diquark = CheckId::makeDiquark(ptrQ[iq2]->dataPtr(), newPtr2->dataPtr()); if(Mc2 < diquark->constituentMass()) { Mc2 = diquark->constituentMass(); toDiQuark = true; } // if a beam cluster not allowed to decay to hadrons if(cluster->isBeamCluster() && toHadron && softUEisOn) continue; // Check if the decay kinematics is still possible: if not then // force the one-hadron decay for the other cluster as well. if(Mc1 + Mc2 > mmax) { if(!toHadron) { toHadron = _hadronsSelector->chooseSingleHadron(ptrQ[iq1]->dataPtr(), newPtr1->dataPtr(),mmax-Mc2); if(toHadron) Mc1 = toHadron->mass(); } else if(!toDiQuark) { Mc2 = _hadronsSelector->massLightestHadron(ptrQ[iq2]->dataPtr(), newPtr2->dataPtr()); toDiQuark = true; } } succeeded = (mmax >= Mc1+Mc2); } while (!succeeded && counter < max_loop); // check no of tries if(counter >= max_loop) return cutType(); // Determine the (5-components) momenta (all in the LAB frame) Lorentz5Momentum p0Q1 = ptrQ[iq1]->momentum(); // to be determined Lorentz5Momentum pClu1(Mc1), pClu2(Mc2), pQ1(m1), pQone(m), pQtwo(m), pQ2(m2); calculateKinematics(pDiQuark,p0Q1,toHadron,toDiQuark, pClu1,pClu2,pQ1,pQone,pQtwo,pQ2); // positions of the new clusters LorentzPoint pos1,pos2; Lorentz5Momentum pBaryon = pClu2+ptrQ[iother]->momentum(); calculatePositions(cluster->momentum(), cluster->vertex(), pClu1, pBaryon, pos1, pos2); // first the mesonic cluster/meson cutType rval; if(toHadron) { rval.first = produceHadron(toHadron, newPtr1, pClu1, pos1); finalhadrons.push_back(rval.first.first); } else { rval.first = produceCluster(ptrQ[iq1], newPtr1, pClu1, pos1, pQ1, pQone, rem1); } if(toDiQuark) { rem2 |= cluster->isBeamRemnant(iother); PPtr newDiQuark = diquark->produceParticle(pClu2); rval.second = produceCluster(newDiQuark, ptrQ[iother], pBaryon, pos2, pClu2, ptrQ[iother]->momentum(), rem2); } else { rval.second = produceCluster(ptrQ[iq2], newPtr2, pBaryon, pos2, pQ2, pQtwo, rem2, ptrQ[iother],cluster->isBeamRemnant(iother)); } cluster->isAvailable(false); return rval; } ClusterFissioner::PPair ClusterFissioner::produceHadron(tcPDPtr hadron, tPPtr newPtr, const Lorentz5Momentum &a, const LorentzPoint &b) const { PPair rval; if(hadron->coloured()) { rval.first = (_hadronsSelector->lightestHadron(hadron,newPtr->dataPtr()))->produceParticle(); } else rval.first = hadron->produceParticle(); rval.second = newPtr; rval.first->set5Momentum(a); rval.first->setVertex(b); return rval; } ClusterFissioner::PPair ClusterFissioner::produceCluster(tPPtr ptrQ, tPPtr newPtr, const Lorentz5Momentum & a, const LorentzPoint & b, const Lorentz5Momentum & c, const Lorentz5Momentum & d, bool isRem, tPPtr spect, bool remSpect) const { PPair rval; rval.second = newPtr; ClusterPtr cluster = !spect ? new_ptr(Cluster(ptrQ,rval.second)) : new_ptr(Cluster(ptrQ,rval.second,spect)); rval.first = cluster; cluster->set5Momentum(a); cluster->setVertex(b); assert(cluster->particle(0)->id() == ptrQ->id()); cluster->particle(0)->set5Momentum(c); cluster->particle(1)->set5Momentum(d); cluster->setBeamRemnant(0,isRem); if(remSpect) cluster->setBeamRemnant(2,remSpect); return rval; } void ClusterFissioner::drawNewFlavour(PPtr& newPtrPos,PPtr& newPtrNeg) const { // Flavour is assumed to be only u, d, s, with weights // (which are not normalized probabilities) given // by the same weights as used in HadronsSelector for // the decay of clusters into two hadrons. double prob_d; double prob_u; double prob_s; switch(_fissionCluster){ case 0: prob_d = _hadronsSelector->pwtDquark(); prob_u = _hadronsSelector->pwtUquark(); prob_s = _hadronsSelector->pwtSquark(); break; case 1: prob_d = _fissionPwtDquark; prob_u = _fissionPwtUquark; prob_s = _fissionPwtSquark; break; default : assert(false); } int choice = UseRandom::rnd3(prob_u, prob_d, prob_s); long idNew = 0; switch (choice) { case 0: idNew = ThePEG::ParticleID::u; break; case 1: idNew = ThePEG::ParticleID::d; break; case 2: idNew = ThePEG::ParticleID::s; break; } newPtrPos = getParticle(idNew); newPtrNeg = getParticle(-idNew); assert (newPtrPos); assert(newPtrNeg); assert (newPtrPos->dataPtr()); assert(newPtrNeg->dataPtr()); } void ClusterFissioner::drawNewFlavourEnhanced(PPtr& newPtrPos,PPtr& newPtrNeg, Energy2 mass2) const { // Flavour is assumed to be only u, d, s, with weights // (which are not normalized probabilities) given // by the same weights as used in HadronsSelector for // the decay of clusters into two hadrons. double prob_d; double prob_u; double prob_s = 0.; double scale = abs(double(sqr(_m0Fission)/mass2)); // Choose which splitting weights you wish to use switch(_fissionCluster){ // 0: ClusterFissioner and ClusterDecayer use the same weights case 0: prob_d = _hadronsSelector->pwtDquark(); prob_u = _hadronsSelector->pwtUquark(); /* Strangeness enhancement: Case 1: probability scaling Case 2: Exponential scaling */ if (_enhanceSProb == 1) prob_s = (_maxScale < scale) ? 0. : pow(_hadronsSelector->pwtSquark(),scale); else if (_enhanceSProb == 2) prob_s = (_maxScale < scale) ? 0. : exp(-scale); break; /* 1: ClusterFissioner uses its own unique set of weights, i.e. decoupled from ClusterDecayer */ case 1: prob_d = _fissionPwtDquark; prob_u = _fissionPwtUquark; if (_enhanceSProb == 1) prob_s = (_maxScale < scale) ? 0. : pow(_fissionPwtSquark,scale); else if (_enhanceSProb == 2) prob_s = (_maxScale < scale) ? 0. : exp(-scale); break; } int choice = UseRandom::rnd3(prob_u, prob_d, prob_s); long idNew = 0; switch (choice) { case 0: idNew = ThePEG::ParticleID::u; break; case 1: idNew = ThePEG::ParticleID::d; break; case 2: idNew = ThePEG::ParticleID::s; break; } newPtrPos = getParticle(idNew); newPtrNeg = getParticle(-idNew); assert (newPtrPos); assert(newPtrNeg); assert (newPtrPos->dataPtr()); assert(newPtrNeg->dataPtr()); } Energy2 ClusterFissioner::clustermass(const ClusterPtr & cluster){ Lorentz5Momentum pIn = cluster->momentum(); Energy2 endpointmass2 = sqr(cluster->particle(0)->mass() + cluster->particle(1)->mass()); Energy2 singletm2 = pIn.m2(); // Return either the cluster mass, or the lambda measure return (_massMeasure == 0) ? singletm2 : singletm2 - endpointmass2; } Energy ClusterFissioner::drawChildMass(const Energy M, const Energy m1, const Energy m2, const Energy m, const double expt, const bool soft) const { /*************************** * This method, given in input the cluster mass Mclu of an heavy cluster C, * made of consituents of masses m1 and m2, draws the masses Mclu1 and Mclu2 * of, respectively, the children cluster C1, made of constituent masses m1 * and m, and cluster C2, of mass Mclu2 and made of constituent masses m2 * and m. The mass is extracted from one of the two following mass * distributions: * --- power-like ("normal" distribution) * d(Prob) / d(M^exponent) = const * where the exponent can be different from the two children C1 (exp1) * and C2 (exponent2). * --- exponential ("soft" distribution) * d(Prob) / d(M^2) = exp(-b*M) * where b = 2.0 / average. * Such distributions are limited below by the masses of * the constituents quarks, and above from the mass of decaying cluster C. * The choice of which of the two mass distributions to use for each of the * two cluster children is dictated by iRemnant (see below). * If the number of attempts to extract a pair of mass values that are * kinematically acceptable is above some fixed number (max_loop, see below) * the method gives up and returns false; otherwise, when it succeeds, it * returns true. * * These distributions have been modified from HERWIG: * Before these were: * Mclu1 = m1 + (Mclu - m1 - m2)*pow( rnd(), 1.0/exponent1 ); * The new one coded here is a more efficient version, same density * but taking into account 'in phase space from' beforehand ***************************/ // hard cluster if(!soft) { return pow(UseRandom::rnd(pow((M-m1-m2-m)*UnitRemoval::InvE, expt), pow(m*UnitRemoval::InvE, expt)), 1./expt )*UnitRemoval::E + m1; } // Otherwise it uses a soft mass distribution else { static const InvEnergy b = 2.0 / _btClM; Energy max = M-m1-m2-2.0*m; double rmin = b*max; rmin = ( rmin < 50 ) ? exp(-rmin) : 0.; double r1; do { r1 = UseRandom::rnd(rmin, 1.0) * UseRandom::rnd(rmin, 1.0); } while (r1 < rmin); return m1 + m - log(r1)/b; } } void ClusterFissioner::calculateKinematics(const Lorentz5Momentum & pClu, const Lorentz5Momentum & p0Q1, const bool toHadron1, const bool toHadron2, Lorentz5Momentum & pClu1, Lorentz5Momentum & pClu2, Lorentz5Momentum & pQ1, Lorentz5Momentum & pQbar, Lorentz5Momentum & pQ, Lorentz5Momentum & pQ2bar) const { /****************** * This method solves the kinematics of the two body cluster decay: * C (Q1 Q2bar) ---> C1 (Q1 Qbar) + C2 (Q Q2bar) * In input we receive the momentum of C, pClu, and the momentum * of the quark Q1 (constituent of C), p0Q1, both in the LAB frame. * Furthermore, two boolean variables inform whether the two fission * products (C1, C2) decay immediately into a single hadron (in which * case the cluster itself is identify with that hadron) and we do * not have to solve the kinematics of the components (Q1,Qbar) for * C1 and (Q,Q2bar) for C2. * The output is given by the following momenta (all 5-components, * and all in the LAB frame): * pClu1 , pClu2 respectively of C1 , C2 * pQ1 , pQbar respectively of Q1 , Qbar in C1 * pQ , pQ2bar respectively of Q , Q2 in C2 * The assumption, suggested from the string model, is that, in C frame, * C1 and its constituents Q1 and Qbar are collinear, and collinear to * the direction of Q1 in C (that is before cluster decay); similarly, * (always in the C frame) C2 and its constituents Q and Q2bar are * collinear (and therefore anti-collinear with C1,Q1,Qbar). * The solution is then obtained by using Lorentz boosts, as follows. * The kinematics of C1 and C2 is solved in their parent C frame, * and then boosted back in the LAB. The kinematics of Q1 and Qbar * is solved in their parent C1 frame and then boosted back in the LAB; * similarly, the kinematics of Q and Q2bar is solved in their parent * C2 frame and then boosted back in the LAB. In each of the three * "two-body decay"-like cases, we use the fact that the direction * of the motion of the decay products is known in the rest frame of * their parent. This is obvious for the first case in which the * parent rest frame is C; but it is also true in the other two cases * where the rest frames are C1 and C2. This is because C1 and C2 * are boosted w.r.t. C in the same direction where their components, * respectively (Q1,Qbar) and (Q,Q2bar) move in C1 and C2 rest frame * respectively. * Of course, although the notation used assumed that C = (Q1 Q2bar) * where Q1 is a quark and Q2bar an antiquark, indeed everything remain * unchanged also in all following cases: * Q1 quark, Q2bar antiquark; --> Q quark; * Q1 antiquark , Q2bar quark; --> Q antiquark; * Q1 quark, Q2bar diquark; --> Q quark * Q1 antiquark, Q2bar anti-diquark; --> Q antiquark * Q1 diquark, Q2bar quark --> Q antiquark * Q1 anti-diquark, Q2bar antiquark; --> Q quark **************************/ // Calculate the unit three-vector, in the C frame, along which // all of the constituents and children clusters move. Lorentz5Momentum u(p0Q1); u.boost( -pClu.boostVector() ); // boost from LAB to C // the unit three-vector is then u.vect().unit() // Calculate the momenta of C1 and C2 in the (parent) C frame first, // where the direction of C1 is u.vect().unit(), and then boost back in the // LAB frame. if (pClu.m() < pClu1.mass() + pClu2.mass() ) { throw Exception() << "Impossible Kinematics in ClusterFissioner::calculateKinematics() (A)" << Exception::eventerror; } Kinematics::twoBodyDecay(pClu, pClu1.mass(), pClu2.mass(), u.vect().unit(), pClu1, pClu2); // In the case that cluster1 does not decay immediately into a single hadron, // calculate the momenta of Q1 (as constituent of C1) and Qbar in the // (parent) C1 frame first, where the direction of Q1 is u.vect().unit(), // and then boost back in the LAB frame. if(!toHadron1) { if (pClu1.m() < pQ1.mass() + pQbar.mass() ) { throw Exception() << "Impossible Kinematics in ClusterFissioner::calculateKinematics() (B)" << Exception::eventerror; } Kinematics::twoBodyDecay(pClu1, pQ1.mass(), pQbar.mass(), u.vect().unit(), pQ1, pQbar); } // In the case that cluster2 does not decay immediately into a single hadron, // Calculate the momenta of Q and Q2bar (as constituent of C2) in the // (parent) C2 frame first, where the direction of Q is u.vect().unit(), // and then boost back in the LAB frame. if(!toHadron2) { if (pClu2.m() < pQ.mass() + pQ2bar.mass() ) { throw Exception() << "Impossible Kinematics in ClusterFissioner::calculateKinematics() (C)" << Exception::eventerror; } Kinematics::twoBodyDecay(pClu2, pQ.mass(), pQ2bar.mass(), u.vect().unit(), pQ, pQ2bar); } } void ClusterFissioner::calculatePositions(const Lorentz5Momentum & pClu, const LorentzPoint & positionClu, const Lorentz5Momentum & pClu1, const Lorentz5Momentum & pClu2, LorentzPoint & positionClu1, LorentzPoint & positionClu2) const { // Determine positions of cluster children. // See Marc Smith's thesis, page 127, formulas (4.122) and (4.123). Energy Mclu = pClu.m(); Energy Mclu1 = pClu1.m(); Energy Mclu2 = pClu2.m(); // Calculate the unit three-vector, in the C frame, along which // children clusters move. Lorentz5Momentum u(pClu1); u.boost( -pClu.boostVector() ); // boost from LAB to C frame // the unit three-vector is then u.vect().unit() Energy pstarChild = Kinematics::pstarTwoBodyDecay(Mclu,Mclu1,Mclu2); // First, determine the relative positions of the children clusters // in the parent cluster reference frame. Length x1 = ( 0.25*Mclu + 0.5*( pstarChild + (sqr(Mclu2) - sqr(Mclu1))/(2.0*Mclu)))/_kappa; Length t1 = Mclu/_kappa - x1; LorentzDistance distanceClu1( x1 * u.vect().unit(), t1 ); Length x2 = (-0.25*Mclu + 0.5*(-pstarChild + (sqr(Mclu2) - sqr(Mclu1))/(2.0*Mclu)))/_kappa; Length t2 = Mclu/_kappa + x2; LorentzDistance distanceClu2( x2 * u.vect().unit(), t2 ); // Then, transform such relative positions from the parent cluster // reference frame to the Lab frame. distanceClu1.boost( pClu.boostVector() ); distanceClu2.boost( pClu.boostVector() ); // Finally, determine the absolute positions in the Lab frame. positionClu1 = positionClu + distanceClu1; positionClu2 = positionClu + distanceClu2; } bool ClusterFissioner::isHeavy(tcClusterPtr clu) { // default double clpow = _clPowLight; Energy clmax = _clMaxLight; // particle data for constituents tcPDPtr cptr[3]={tcPDPtr(),tcPDPtr(),tcPDPtr()}; for(int ix=0;ixnumComponents(),3);++ix) { cptr[ix]=clu->particle(ix)->dataPtr(); } // different parameters for exotic, bottom and charm clusters if(CheckId::isExotic(cptr[0],cptr[1],cptr[1])) { clpow = _clPowExotic; clmax = _clMaxExotic; } else if(CheckId::hasBottom(cptr[0],cptr[1],cptr[1])) { clpow = _clPowBottom; clmax = _clMaxBottom; } else if(CheckId::hasCharm(cptr[0],cptr[1],cptr[1])) { clpow = _clPowCharm; clmax = _clMaxCharm; } bool aboveCutoff = ( pow(clu->mass()*UnitRemoval::InvE , clpow) > pow(clmax*UnitRemoval::InvE, clpow) + pow(clu->sumConstituentMasses()*UnitRemoval::InvE, clpow) ); // required test for SUSY clusters, since aboveCutoff alone // cannot guarantee (Mc > m1 + m2 + 2*m) in cut() static const Energy minmass = getParticleData(ParticleID::d)->constituentMass(); bool canSplitMinimally = clu->mass() > clu->sumConstituentMasses() + 2.0 * minmass; return aboveCutoff && canSplitMinimally; } diff --git a/Hadronization/ClusterHadronizationHandler.cc b/Hadronization/ClusterHadronizationHandler.cc --- a/Hadronization/ClusterHadronizationHandler.cc +++ b/Hadronization/ClusterHadronizationHandler.cc @@ -1,307 +1,307 @@ // -*- C++ -*- // // ClusterHadronizationHandler.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 ClusterHadronizationHandler class. // #include "ClusterHadronizationHandler.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "Herwig/Utilities/EnumParticles.h" #include "CluHadConfig.h" #include "Cluster.h" #include using namespace Herwig; ClusterHadronizationHandler * ClusterHadronizationHandler::currentHandler_ = 0; DescribeClass describeClusterHadronizationHandler("Herwig::ClusterHadronizationHandler",""); IBPtr ClusterHadronizationHandler::clone() const { return new_ptr(*this); } IBPtr ClusterHadronizationHandler::fullclone() const { return new_ptr(*this); } void ClusterHadronizationHandler::persistentOutput(PersistentOStream & os) const { os << _partonSplitter << _clusterFinder << _colourReconnector << _clusterFissioner << _lightClusterDecayer << _clusterDecayer << ounit(_minVirtuality2,GeV2) << ounit(_maxDisplacement,mm) << _underlyingEventHandler << _reduceToTwoComponents; } void ClusterHadronizationHandler::persistentInput(PersistentIStream & is, int) { is >> _partonSplitter >> _clusterFinder >> _colourReconnector >> _clusterFissioner >> _lightClusterDecayer >> _clusterDecayer >> iunit(_minVirtuality2,GeV2) >> iunit(_maxDisplacement,mm) >> _underlyingEventHandler >> _reduceToTwoComponents; } void ClusterHadronizationHandler::Init() { static ClassDocumentation documentation ("This is the main handler class for the Cluster Hadronization", "The hadronization was performed using the cluster model of \\cite{Webber:1983if}.", "%\\cite{Webber:1983if}\n" "\\bibitem{Webber:1983if}\n" " B.~R.~Webber,\n" " ``A QCD Model For Jet Fragmentation Including Soft Gluon Interference,''\n" " Nucl.\\ Phys.\\ B {\\bf 238}, 492 (1984).\n" " %%CITATION = NUPHA,B238,492;%%\n" // main manual ); static Reference interfacePartonSplitter("PartonSplitter", "A reference to the PartonSplitter object", &Herwig::ClusterHadronizationHandler::_partonSplitter, false, false, true, false); static Reference interfaceClusterFinder("ClusterFinder", "A reference to the ClusterFinder object", &Herwig::ClusterHadronizationHandler::_clusterFinder, false, false, true, false); static Reference interfaceColourReconnector("ColourReconnector", "A reference to the ColourReconnector object", &Herwig::ClusterHadronizationHandler::_colourReconnector, false, false, true, false); static Reference interfaceClusterFissioner("ClusterFissioner", "A reference to the ClusterFissioner object", &Herwig::ClusterHadronizationHandler::_clusterFissioner, false, false, true, false); static Reference interfaceLightClusterDecayer("LightClusterDecayer", "A reference to the LightClusterDecayer object", &Herwig::ClusterHadronizationHandler::_lightClusterDecayer, false, false, true, false); static Reference interfaceClusterDecayer("ClusterDecayer", "A reference to the ClusterDecayer object", &Herwig::ClusterHadronizationHandler::_clusterDecayer, false, false, true, false); static Parameter interfaceMinVirtuality2 ("MinVirtuality2", "Minimum virtuality^2 of partons to use in calculating distances (unit [GeV2]).", &ClusterHadronizationHandler::_minVirtuality2, GeV2, 0.1*GeV2, ZERO, 10.0*GeV2,false,false,false); static Parameter interfaceMaxDisplacement ("MaxDisplacement", "Maximum displacement that is allowed for a particle (unit [millimeter]).", &ClusterHadronizationHandler::_maxDisplacement, mm, 1.0e-10*mm, 0.0*mm, 1.0e-9*mm,false,false,false); static Reference interfaceUnderlyingEventHandler ("UnderlyingEventHandler", "Pointer to the handler for the Underlying Event. " "Set to NULL to disable.", &ClusterHadronizationHandler::_underlyingEventHandler, false, false, true, true, false); static Switch interfaceReduceToTwoComponents ("ReduceToTwoComponents", "Whether or not to reduce three component baryon-number violating clusters to two components before cluster splitting or leave" " this till after the cluster splitting", &ClusterHadronizationHandler::_reduceToTwoComponents, true, false, false); static SwitchOption interfaceReduceToTwoComponentsYes (interfaceReduceToTwoComponents, "BeforeSplitting", "Reduce to two components", true); static SwitchOption interfaceReduceToTwoComponentsNo (interfaceReduceToTwoComponents, "AfterSplitting", "Treat as three components", false); } namespace { void extractChildren(tPPtr p, set & all) { if (p->children().empty()) return; for (PVector::const_iterator child = p->children().begin(); child != p->children().end(); ++child) { all.insert(*child); extractChildren(*child, all); } } } void ClusterHadronizationHandler:: handle(EventHandler & ch, const tPVector & tagged, const Hint &) { useMe(); currentHandler_ = this; PVector currentlist(tagged.begin(),tagged.end()); // set the scale for coloured particles to just above the gluon mass squared // if less than this so they are classed as perturbative Energy2 Q02 = 1.01*sqr(getParticleData(ParticleID::g)->constituentMass()); for(unsigned int ix=0;ixscale()scale(Q02); } // split the gluons _partonSplitter->split(currentlist); // form the clusters ClusterVector clusters = _clusterFinder->formClusters(currentlist); // reduce BV clusters to two components now if needed if(_reduceToTwoComponents) _clusterFinder->reduceToTwoComponents(clusters); // perform colour reconnection if needed and then // decay the clusters into one hadron bool lightOK = false; short tried = 0; const ClusterVector savedclusters = clusters; tPVector finalHadrons; // only needed for partonic decayer while (!lightOK && tried++ < 10) { // no colour reconnection with baryon-number-violating (BV) clusters ClusterVector CRclusters, BVclusters; CRclusters.reserve( clusters.size() ); BVclusters.reserve( clusters.size() ); for (size_t ic = 0; ic < clusters.size(); ++ic) { ClusterPtr cl = clusters.at(ic); bool hasClusterParent = false; for (unsigned int ix=0; ix < cl->parents().size(); ++ix) { if (cl->parents()[ix]->id() == ParticleID::Cluster) { hasClusterParent = true; break; } } if (cl->numComponents() > 2 || hasClusterParent) BVclusters.push_back(cl); else CRclusters.push_back(cl); } // colour reconnection _colourReconnector->rearrange(CRclusters); // tag new clusters as children of the partons to hadronize _setChildren(CRclusters); // forms diquarks _clusterFinder->reduceToTwoComponents(CRclusters); // recombine vectors of (possibly) reconnected and BV clusters clusters.clear(); clusters.insert( clusters.end(), CRclusters.begin(), CRclusters.end() ); clusters.insert( clusters.end(), BVclusters.begin(), BVclusters.end() ); // fission of heavy clusters // NB: during cluster fission, light hadrons might be produced straight away finalHadrons = _clusterFissioner->fission(clusters,isSoftUnderlyingEventON()); // if clusters not previously reduced to two components do it now if(!_reduceToTwoComponents) _clusterFinder->reduceToTwoComponents(clusters); lightOK = _lightClusterDecayer->decay(clusters,finalHadrons); // if the decay of the light clusters was not successful, undo the cluster // fission and decay steps and revert to the original state of the event // record if (!lightOK) { clusters = savedclusters; for_each(clusters.begin(), clusters.end(), - mem_fun(&Particle::undecay)); + std::mem_fn(&Particle::undecay)); } } if (!lightOK) { throw Exception("CluHad::handle(): tried LightClusterDecayer 10 times!", Exception::eventerror); } // decay the remaining clusters _clusterDecayer->decay(clusters,finalHadrons); // ***************************************** // ***************************************** // ***************************************** StepPtr pstep = newStep(); set allDecendants; for (tPVector::const_iterator it = tagged.begin(); it != tagged.end(); ++it) { extractChildren(*it, allDecendants); } for(set::const_iterator it = allDecendants.begin(); it != allDecendants.end(); ++it) { // this is a workaround because the set sometimes // re-orders parents after their children if ((*it)->children().empty()) pstep->addDecayProduct(*it); else { pstep->addDecayProduct(*it); pstep->addIntermediate(*it); } } // ***************************************** // ***************************************** // ***************************************** // soft underlying event if needed if (isSoftUnderlyingEventON()) { assert(_underlyingEventHandler); ch.performStep(_underlyingEventHandler,Hint::Default()); } } // Sets parent child relationship of all clusters with two components // Relationships for clusters with more than two components are set elsewhere in the Colour Reconnector void ClusterHadronizationHandler::_setChildren(const ClusterVector & clusters) const { // erase existing information about the partons' children tPVector partons; for ( const auto & cl : clusters ) { if ( cl->numComponents() > 2 ) continue; partons.push_back( cl->colParticle() ); partons.push_back( cl->antiColParticle() ); } // erase all previous information about parent child relationship - for_each(partons.begin(), partons.end(), mem_fun(&Particle::undecay)); + for_each(partons.begin(), partons.end(), std::mem_fn(&Particle::undecay)); // give new parents to the clusters: their constituents for ( const auto & cl : clusters ) { if ( cl->numComponents() > 2 ) continue; cl->colParticle()->addChild(cl); cl->antiColParticle()->addChild(cl); } } diff --git a/Hadronization/HwppSelector.cc b/Hadronization/HwppSelector.cc --- a/Hadronization/HwppSelector.cc +++ b/Hadronization/HwppSelector.cc @@ -1,251 +1,245 @@ // -*- C++ -*- // // HwppSelector.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 HwppSelector class. // #include "HwppSelector.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/Utilities/Kinematics.h" #include "ThePEG/Utilities/Selector.h" #include "ThePEG/Repository/UseRandom.h" #include "CheckId.h" #include #include using namespace Herwig; DescribeClass describeHwppSelector("Herwig::HwppSelector",""); IBPtr HwppSelector::clone() const { return new_ptr(*this); } IBPtr HwppSelector::fullclone() const { return new_ptr(*this); } void HwppSelector::doinit() { HadronSelector::doinit(); } void HwppSelector::persistentOutput(PersistentOStream & os) const { os << _mode << _enhanceSProb << ounit(_m0Decay,GeV) << _massMeasure; } void HwppSelector::persistentInput(PersistentIStream & is, int) { is >> _mode >> _enhanceSProb >> iunit(_m0Decay,GeV) >> _massMeasure; } void HwppSelector::Init() { static ClassDocumentation documentation ("The HwppSelector class implements the Herwig algorithm for selecting" " the hadrons", "The hadronization used the selection algorithm described in \\cite{Kupco:1998fx}.", "%\\cite{Kupco:1998fx}\n" "\\bibitem{Kupco:1998fx}\n" " A.~Kupco,\n" " ``Cluster hadronization in HERWIG 5.9,''\n" " arXiv:hep-ph/9906412.\n" " %%CITATION = HEP-PH/9906412;%%\n" ); // put useMe() only in correct place! static Switch interfaceMode ("Mode", "Which algorithm to use", &HwppSelector::_mode, 1, false, false); static SwitchOption interfaceModeKupco (interfaceMode, "Kupco", "Use the Kupco approach", 0); static SwitchOption interfaceModeHwpp (interfaceMode, "Hwpp", "Use the Herwig approach", 1); static Switch interfaceEnhanceSProb ("EnhanceSProb", "Option for enhancing strangeness", &HwppSelector::_enhanceSProb, 0, false, false); static SwitchOption interfaceEnhanceSProbNo (interfaceEnhanceSProb, "No", "No strangeness enhancement.", 0); static SwitchOption interfaceEnhanceSProbScaled (interfaceEnhanceSProb, "Scaled", "Scaled strangeness enhancement", 1); static SwitchOption interfaceEnhanceSProbExponential (interfaceEnhanceSProb, "Exponential", "Exponential strangeness enhancement", 2); static Switch interfaceMassMeasure ("MassMeasure", "Option to use different mass measures", &HwppSelector::_massMeasure,0,false,false); static SwitchOption interfaceMassMeasureMass (interfaceMassMeasure, "Mass", "Mass Measure", 0); static SwitchOption interfaceMassMeasureLambda (interfaceMassMeasure, "Lambda", "Lambda Measure", 1); static Parameter interfaceDecayMassScale ("DecayMassScale", "Cluster decay mass scale", &HwppSelector::_m0Decay, GeV, 1.0*GeV, 0.1*GeV, 50.*GeV, false, false, Interface::limited); } pair HwppSelector::chooseHadronPair(const Energy cluMass,tcPDPtr par1, tcPDPtr par2,tcPDPtr ) const { // if either of the input partons is a diquark don't allow diquarks to be // produced bool diquark = !(DiquarkMatcher::Check(par1->id()) || DiquarkMatcher::Check(par2->id())); bool quark = true; // if the Herwig algorithm if(_mode ==1) { if(UseRandom::rnd() > 1./(1.+pwtDIquark()) &&cluMass > massLightestBaryonPair(par1,par2)) { diquark = true; quark = false; } else { useMe(); diquark = false; quark = true; } } // weights for the different possibilities Energy weight, wgtsum(ZERO); // loop over all hadron pairs with the allowed flavours static vector hadrons; hadrons.clear(); for(unsigned int ix=0;ixiColour())) == 3 && !DiquarkMatcher::Check(quarktopick->id())) continue; if(!diquark && abs(int(quarktopick->iColour())) == 3 && DiquarkMatcher::Check(quarktopick->id())) continue; HadronTable::const_iterator tit1 = table().find(make_pair(abs(par1->id()),quarktopick->id())); HadronTable::const_iterator tit2 = table().find(make_pair(quarktopick->id(),abs(par2->id()))); // If not in table skip if(tit1 == table().end()||tit2==table().end()) continue; // tables empty skip const KupcoData & T1 = tit1->second; const KupcoData & T2 = tit2->second; if(T1.empty()||T2.empty()) continue; // if too massive skip if(cluMass <= T1.begin()->mass + T2.begin()->mass) continue; + // quark weight + double quarkWeight = pwt(quarktopick->id()); + if (quarktopick->id() == 3) { + // Scaling strangeness enhancement + if (_enhanceSProb == 1){ + double scale = double(sqr(_m0Decay/cluMass)); + quarkWeight = (_maxScale < scale) ? 0. : pow(quarkWeight,scale); + } + // Exponential strangeness enhancement + else if (_enhanceSProb == 2) { + Energy2 mass2; + Energy endpointmass = par1->mass() + par2->mass(); + // Choose to use either the cluster mass + // or to use the lambda measure + mass2 = (_massMeasure == 0) ? sqr(cluMass) : + sqr(cluMass) - sqr(endpointmass); + double scale = double(sqr(_m0Decay)/mass2); + quarkWeight = (_maxScale < scale) ? 0. : exp(-scale); + } + } // loop over the hadrons KupcoData::const_iterator H1,H2; for(H1 = T1.begin();H1 != T1.end(); ++H1) { for(H2 = T2.begin();H2 != T2.end(); ++H2) { // break if cluster too light if(cluMass < H1->mass + H2->mass) break; - // calculate the weight - double pwtstrange; - if (quarktopick->id() == 3) { - // Strangeness weight takes the automatic flat weight - pwtstrange = pwt(3); - // Scaling strangeness enhancement - if (_enhanceSProb == 1){ - double scale = double(sqr(_m0Decay/cluMass)); - pwtstrange = (_maxScale < scale) ? 0. : pow(pwtstrange,scale); - } - // Exponential strangeness enhancement - else if (_enhanceSProb == 2){ - Energy2 mass2; - Energy endpointmass = par1->mass() + par2->mass(); - // Choose to use either the cluster mass - // or to use the lambda measure - mass2 = (_massMeasure == 0) ? sqr(cluMass) : - sqr(cluMass) - sqr(endpointmass); - double scale = double(sqr(_m0Decay)/mass2); - pwtstrange = (_maxScale < scale) ? 0. : exp(-scale); - } - weight = pwtstrange * H1->overallWeight * H2->overallWeight * - Kinematics::pstarTwoBodyDecay(cluMass, H1->mass, H2->mass ); - } - else { - weight = pwt(quarktopick->id()) * H1->overallWeight * H2->overallWeight * - Kinematics::pstarTwoBodyDecay(cluMass, H1->mass, H2->mass ); - } + weight = quarkWeight * H1->overallWeight * H2->overallWeight * + Kinematics::pstarTwoBodyDecay(cluMass, H1->mass, H2->mass ); int signQ = 0; assert (par1 && quarktopick); assert (par2); assert(quarktopick->CC()); if(CheckId::canBeHadron(par1, quarktopick->CC()) && CheckId::canBeHadron(quarktopick, par2)) signQ = +1; else if(CheckId::canBeHadron(par1, quarktopick) && CheckId::canBeHadron(quarktopick->CC(), par2)) signQ = -1; else { cerr << "Could not make sign for" << par1->id()<< " " << quarktopick->id() << " " << par2->id() << "\n"; assert(false); } if (signQ == -1) quarktopick = quarktopick->CC(); // construct the object with the info Kupco a(quarktopick, H1->ptrData, H2->ptrData, weight); hadrons.push_back(a); wgtsum += weight; } } } if (hadrons.empty()) return make_pair(tcPDPtr(),tcPDPtr()); // select the hadron wgtsum *= UseRandom::rnd(); unsigned int ix=0; do { wgtsum-= hadrons[ix].weight; ++ix; } while(wgtsum > ZERO && ix < hadrons.size()); if(ix == hadrons.size() && wgtsum > ZERO) return make_pair(tcPDPtr(),tcPDPtr()); --ix; assert(hadrons[ix].idQ); int signHad1 = signHadron(par1, hadrons[ix].idQ->CC(), hadrons[ix].hadron1); int signHad2 = signHadron(par2, hadrons[ix].idQ, hadrons[ix].hadron2); assert( signHad1 != 0 && signHad2 != 0 ); return make_pair ( signHad1 > 0 ? hadrons[ix].hadron1 : tcPDPtr(hadrons[ix].hadron1->CC()), signHad2 > 0 ? hadrons[ix].hadron2 : tcPDPtr(hadrons[ix].hadron2->CC())); } diff --git a/MatrixElement/Hadron/MEMinBias.cc b/MatrixElement/Hadron/MEMinBias.cc --- a/MatrixElement/Hadron/MEMinBias.cc +++ b/MatrixElement/Hadron/MEMinBias.cc @@ -1,279 +1,280 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the MEMinBias class. // #include "MEMinBias.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Utilities/SimplePhaseSpace.h" //#include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Handlers/StandardXComb.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Handlers/SamplerBase.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" inline bool checkValence(int i,int side,Ptr::tptr eh){ // Inline function to check for valence quarks of the beam. // i: pdgid of quark // side: beam side // eh: pointer to the eventhandler int beam= ( side == 0 ) ? eh->incoming().first->id() : eh->incoming().second->id(); vector val; if( beam == ParticleID::pplus || beam == ParticleID::n0 ) val = {1,2}; if( beam == ParticleID::pbarminus || beam == ParticleID::nbar0 ) val = { -1 , -2 }; - if( val.size() == 0 ) assert(false && ("MEMinBias: Valence Quarks not defined for pid "+beam)); + if( val.size() == 0 ) + {cerr<<"\n\n MEMinBias: Valence Quarks not defined for pid "<::tptr eh = dynamic_ptr_cast::tptr>(generator()->eventHandler()); for ( int i = 1; i <= maxflav; ++i ) { for( int j=1; j <= i; ++j){ tcPDPtr q1 = getParticleData(i); tcPDPtr q1b = q1->CC(); tcPDPtr q2 = getParticleData(j); tcPDPtr q2b = q2->CC(); // For each flavour we add: //qq -> qq if(!onlyValQuarks_) add(new_ptr((Tree2toNDiagram(3), q1, pom, q2, 1, q1, 2, q2, -1))); else if(checkValence(i,0,eh) && checkValence(j,1,eh) ) add(new_ptr((Tree2toNDiagram(3), q1, pom, q2, 1, q1, 2, q2, -1))); //qqb -> qqb if(!onlyValQuarks_) add(new_ptr((Tree2toNDiagram(3), q1, pom, q2b, 1, q1, 2, q2b, -2))); else if(checkValence(i,0,eh) && checkValence(-j,1,eh) ) add(new_ptr((Tree2toNDiagram(3), q1, pom, q2b, 1, q1, 2, q2b, -2))); //qbqb -> qbqb if(!onlyValQuarks_) add(new_ptr((Tree2toNDiagram(3), q1b, pom, q2b, 1, q1b, 2, q2b, -3))); else if(checkValence(-i,0,eh) && checkValence(-j,1,eh) ) add(new_ptr((Tree2toNDiagram(3), q1b, pom, q2b, 1, q1b, 2, q2b, -3))); } } } Energy2 MEMinBias::scale() const { return sqr(Scale_); } int MEMinBias::nDim() const { return 0; } void MEMinBias::setKinematics() { HwMEBase::setKinematics(); // Always call the base class method first. } bool MEMinBias::generateKinematics(const double *) { // generate the masses of the particles for ( int i = 2, N = meMomenta().size(); i < N; ++i ) { meMomenta()[i] = Lorentz5Momentum(mePartonData()[i]->generateMass()); } Energy q = ZERO; try { q = SimplePhaseSpace:: getMagnitude(sHat(), meMomenta()[2].mass(), meMomenta()[3].mass()); } catch ( ImpossibleKinematics & e ) { return false; } Energy pt = ZERO; meMomenta()[2].setVect(Momentum3( pt, pt, q)); meMomenta()[3].setVect(Momentum3(-pt, -pt, -q)); meMomenta()[2].rescaleEnergy(); meMomenta()[3].rescaleEnergy(); jacobian(1.0); return true; } double MEMinBias::correctionweight() const { // Here we calculate the weight to restore the inelastic-diffractiveXSec // given by the MPIHandler. // First get the eventhandler to get the current cross sections. static Ptr::tptr eh = dynamic_ptr_cast::tptr>(generator()->eventHandler()); // All diffractive processes make use of this ME. // The static map can be used to collect all the sumOfWeights. static map weightsmap; weightsmap[lastXCombPtr()]=lastXComb().stats().sumWeights(); // Define static variable to keep trac of reweighting static double rew_=1.; static int countUpdateWeight=50; static double sumRew=0.; static double countN=0; // if we produce events we count if(eh->integratedXSec()>ZERO)sumRew+=rew_; if(eh->integratedXSec()>ZERO)countN+=1.; if(countUpdateWeightsampler()->maxXSec()/eh->sampler()->attempts()*sum; - CrossSection XS_wanted=MPIHandler_->inelasticXSec()-MPIHandler_->diffractiveXSec(); + CrossSection XS_wanted=MPIHandler_->nonDiffractiveXSec(); double deltaN=50; // Cross section without reweighting: XS_norew // XS_have = avcsNorm2*XS_norew (for large N) // We want to determine the rew that allows to get the wanted XS. // In deltaN points we want (left) and we get (right): // XS_wanted*(countN+deltaN) = XS_have*countN + rew*deltaN*XS_norew // Solve for rew: rew_=avRew*(XS_wanted*(countN+deltaN)-XS_have*countN)/(XS_have*deltaN); countUpdateWeight+=deltaN; } //Make sure we dont produce negative weights. // TODO: write finalize method that checks if reweighting was performed correctly. rew_=max(rew_,0.000001); rew_=min(rew_,10000.0); return rew_; } double MEMinBias::me2() const { //tuned so it gives the correct normalization for xmin = 0.11 return csNorm_*(sqr(generator()->maximumCMEnergy())/GeV2); } CrossSection MEMinBias::dSigHatDR() const { return me2()*jacobian()/sHat()*sqr(hbarc)*correctionweight(); } unsigned int MEMinBias::orderInAlphaS() const { return 2; } unsigned int MEMinBias::orderInAlphaEW() const { return 0; } Selector MEMinBias::diagrams(const DiagramVector & diags) const { Selector sel; for ( DiagramIndex i = 0; i < diags.size(); ++i ) sel.insert(1.0, i); return sel; } Selector MEMinBias::colourGeometries(tcDiagPtr diag) const { static ColourLines qq("1 4, 3 5"); static ColourLines qqb("1 4, -3 -5"); static ColourLines qbqb("-1 -4, -3 -5"); Selector sel; switch(diag->id()){ case -1: sel.insert(1.0, &qq); break; case -2: sel.insert(1.0, &qqb); break; case -3: sel.insert(1.0, &qbqb); break; } return sel; } IBPtr MEMinBias::clone() const { return new_ptr(*this); } IBPtr MEMinBias::fullclone() const { return new_ptr(*this); } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigMEMinBias("Herwig::MEMinBias", "HwMEHadron.so"); void MEMinBias::persistentOutput(PersistentOStream & os) const { os << csNorm_ << ounit(Scale_,GeV) << MPIHandler_; } void MEMinBias::persistentInput(PersistentIStream & is, int) { is >> csNorm_ >> iunit(Scale_,GeV) >> MPIHandler_; } void MEMinBias::Init() { static ClassDocumentation documentation ("There is no documentation for the MEMinBias class"); static Parameter interfacecsNorm ("csNorm", "Normalization of the min-bias cross section.", &MEMinBias::csNorm_, 1.0, 0.0, 100.0, false, false, Interface::limited); static Parameter interfaceScale ("Scale", "Scale for the Min Bias matrix element.", &MEMinBias::Scale_,GeV, 2.0*GeV, 0.0*GeV, 100.0*GeV, false, false, Interface::limited); static Reference interfaceMPIHandler ("MPIHandler", "The object that administers all additional scatterings.", &MEMinBias::MPIHandler_, false, false, true, true); static Switch interfaceOnlyVal ("OnlyValence" , "Allow the dummy process to only extract valence quarks." , &MEMinBias::onlyValQuarks_ , false , false , false ); static SwitchOption interfaceOnlyValYes ( interfaceOnlyVal , "Yes" , "" , true ); static SwitchOption interfaceOnlyValNo ( interfaceOnlyVal , "No" , "" , false ); } diff --git a/MatrixElement/Hadron/MEMinBias.h b/MatrixElement/Hadron/MEMinBias.h --- a/MatrixElement/Hadron/MEMinBias.h +++ b/MatrixElement/Hadron/MEMinBias.h @@ -1,217 +1,217 @@ // -*- C++ -*- #ifndef HERWIG_MEMinBias_H #define HERWIG_MEMinBias_H // // This is the declaration of the MEMinBias class. // #include "Herwig/MatrixElement/HwMEBase.h" #include "Herwig/Shower/UEBase.h" namespace Herwig { using namespace ThePEG; /** * The MEMinBias class provides a simple colour singlet exchange matrix element * to be used in the soft component of the multiple scattering model of the * underlying event * * @see \ref MEMinBiasInterfaces "The interfaces" * defined for MEMinBias. */ class MEMinBias: public HwMEBase { public: /** * The default constructor. */ MEMinBias() : csNorm_(1.), Scale_(2.*GeV) {} public: /** @name Virtual functions required by the MEBase class. */ //@{ /** * Return the order in \f$\alpha_S\f$ in which this matrix * element is given. */ virtual unsigned int orderInAlphaS() const; /** * Return the order in \f$\alpha_{EW}\f$ in which this matrix * element is given. */ virtual unsigned int orderInAlphaEW() const; /** * The matrix element for the kinematical configuration * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. * @return the matrix element scaled with sHat() to give a * dimensionless number. */ virtual double me2() const; /** * Correction weight to reweight the cross section to the inelastic cross * section subtracted by the diffractive cross section. */ double correctionweight() const; /** * Return the scale associated with the last set phase space point. */ virtual Energy2 scale() const; /** * Set the typed and momenta of the incoming and outgoing partons to * be used in subsequent calls to me() and colourGeometries() * according to the associated XComb object. If the function is * overridden in a sub class the new function must call the base * class one first. */ virtual void setKinematics(); /** * The number of internal degrees of freedom used in the matrix * element. */ virtual int nDim() const; /** * Generate internal degrees of freedom given nDim() uniform * random numbers in the interval \f$ ]0,1[ \f$. To help the phase space * generator, the dSigHatDR should be a smooth function of these * numbers, although this is not strictly necessary. * @param r a pointer to the first of nDim() consecutive random numbers. * @return true if the generation succeeded, otherwise false. */ virtual bool generateKinematics(const double * r); /** * Return the matrix element squared differential in the variables * given by the last call to generateKinematics(). */ virtual CrossSection dSigHatDR() const; /** * Add all possible diagrams with the add() function. */ virtual void getDiagrams() const; /** * Get diagram selector. With the information previously supplied with the * setKinematics method, a derived class may optionally * override this method to weight the given diagrams with their * (although certainly not physical) relative probabilities. * @param dv the diagrams to be weighted. * @return a Selector relating the given diagrams to their weights. */ virtual Selector diagrams(const DiagramVector & dv) const; /** * Return a Selector with possible colour geometries for the selected * diagram weighted by their relative probabilities. * @param diag the diagram chosen. * @return the possible colour geometries weighted by their * relative probabilities. */ virtual Selector colourGeometries(tcDiagPtr diag) const; //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * Normalization of the min-bias cross section. * Note that the cross section is reweighted in addition to produce the * non-diffractive cross section given by the MPIHandler * csNorm can be modified to improve the unweighting effiency. */ double csNorm_; /** * Scale for the Min Bias matrix element */ Energy Scale_; /** * Allow only valence quark extraction. */ - bool onlyValQuarks_=false; + bool onlyValQuarks_=true; /** * a MPIHandler to administer the creation of several (semihard) * partonic interactions. * Needed to comunicate the non-diffractive cross section. */ UEBasePtr MPIHandler_; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MEMinBias & operator=(const MEMinBias &) = delete; }; } #endif /* HERWIG_MEMinBias_H */ diff --git a/MatrixElement/Hadron/MEPP2Higgs.cc b/MatrixElement/Hadron/MEPP2Higgs.cc --- a/MatrixElement/Hadron/MEPP2Higgs.cc +++ b/MatrixElement/Hadron/MEPP2Higgs.cc @@ -1,1441 +1,1442 @@ // -*- C++ -*- // // MEPP2Higgs.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 MEPP2Higgs class. // #include "MEPP2Higgs.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.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/Handlers/StandardXComb.h" #include "ThePEG/Cuts/Cuts.h" #include "Herwig/MatrixElement/HardVertex.h" #include "Herwig/Models/StandardModel/StandardModel.h" #include "Herwig/Utilities/Maths.h" #include "Herwig/Shower/RealEmissionProcess.h" using namespace Herwig; const complex MEPP2Higgs::epsi_ = complex(ZERO,-1.e-10*GeV2); MEPP2Higgs::MEPP2Higgs() : scaleopt_(1), mu_F_(100.*GeV), shapeOption_(2), processOption_(1), minFlavour_(4), maxFlavour_(5), mh_(ZERO), wh_(ZERO), minLoop_(6),maxLoop_(6),massOption_(0), mu_R_opt_(1),mu_F_opt_(1), channelwgtA_(0.45),channelwgtB_(0.15), ggPow_(1.6), qgPow_(1.6), enhance_(1.1), nover_(0), ntry_(0), ngen_(0), maxwgt_(0.), power_(2.0), pregg_(7.), preqg_(3.), pregqbar_(3.), minpT_(2.*GeV), spinCorrelations_(true) {} // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigMEPP2Higgs("Herwig::MEPP2Higgs", "HwMEHadron.so"); void MEPP2Higgs::persistentOutput(PersistentOStream & os) const { os << HGGVertex_ << HFFVertex_ << shapeOption_ << processOption_ << minFlavour_ << maxFlavour_ << hmass_ << ounit(mh_,GeV) << ounit(wh_,GeV) << minLoop_ << maxLoop_ << massOption_ << alpha_ << prefactor_ << power_ << pregg_ << preqg_ << pregqbar_ << ounit( minpT_, GeV ) << ggPow_ << qgPow_ << enhance_ << channelwgtA_ << channelwgtB_ << channelWeights_ << mu_R_opt_ << mu_F_opt_ << spinCorrelations_; } void MEPP2Higgs::persistentInput(PersistentIStream & is, int) { is >> HGGVertex_ >> HFFVertex_ >> shapeOption_ >> processOption_ >> minFlavour_ >> maxFlavour_ >> hmass_ >> iunit(mh_,GeV) >> iunit(wh_,GeV) >> minLoop_ >> maxLoop_ >> massOption_ >> alpha_ >> prefactor_ >> power_ >> pregg_ >> preqg_ >> pregqbar_ >> iunit( minpT_, GeV ) >> ggPow_ >> qgPow_ >> enhance_ >> channelwgtA_ >> channelwgtB_ >> channelWeights_ >> mu_R_opt_ >> mu_F_opt_ >> spinCorrelations_; } void MEPP2Higgs::Init() { static ClassDocumentation documentation ("The MEPP2Higgs class implements the matrix elements for" " Higgs production (with decay H->W-W+) in hadron-hadron collisions" " including the generation of additional hard QCD radiation in " "gg to h0 processes in the POWHEG scheme", "Hard QCD radiation for $gg\\to h^0$ processes in the" " POWHEG scheme \\cite{Hamilton:2009za}.", "%\\cite{Hamilton:2009za}\n" "\\bibitem{Hamilton:2009za}\n" " K.~Hamilton, P.~Richardson and J.~Tully,\n" " ``A Positive-Weight Next-to-Leading Order Monte Carlo Simulation for Higgs\n" " Boson Production,''\n" " JHEP {\\bf 0904}, 116 (2009)\n" " [arXiv:0903.4345 [hep-ph]].\n" " %%CITATION = JHEPA,0904,116;%%\n"); static Switch interfaceFactorizationScaleOption ("FactorizationScaleOption", "Option for the choice of factorization scale", &MEPP2Higgs::scaleopt_, 1, false, false); static SwitchOption interfaceDynamic (interfaceFactorizationScaleOption, "Dynamic", "Dynamic factorization scale equal to the current sqrt(sHat())", 1); static SwitchOption interfaceFixed (interfaceFactorizationScaleOption, "Fixed", "Use a fixed factorization scale set with FactorizationScaleValue", 2); static Parameter interfaceFactorizationScaleValue ("FactorizationScaleValue", "Value to use in the event of a fixed factorization scale", &MEPP2Higgs::mu_F_, GeV, 100.0*GeV, 50.0*GeV, 500.0*GeV, true, false, Interface::limited); static Reference interfaceCoupling ("Coupling", "Pointer to the object to calculate the coupling for the correction", &MEPP2Higgs::alpha_, false, false, true, false, false); static Switch interfaceShapeOption ("ShapeScheme", "Option for the treatment of the Higgs resonance shape", &MEPP2Higgs::shapeOption_, 1, false, false); static SwitchOption interfaceStandardShapeFixed (interfaceShapeOption, "FixedBreitWigner", "Breit-Wigner s-channel resonanse", 1); static SwitchOption interfaceStandardShapeRunning (interfaceShapeOption, "MassGenerator", "Use the mass generator to give the shape", 2); static Switch interfaceProcess ("Process", "Which subprocesses to include", &MEPP2Higgs::processOption_, 1, false, false); static SwitchOption interfaceProcessAll (interfaceProcess, "All", "Include all subprocesses", 1); static SwitchOption interfaceProcess1 (interfaceProcess, "qqbar", "Only include the incoming q qbar subprocess", 2); static SwitchOption interfaceProcessgg (interfaceProcess, "gg", "Only include the incoming gg subprocess", 3); static Parameter interfaceMinimumInLoop ("MinimumInLoop", "The minimum flavour of the quarks to include in the loops", &MEPP2Higgs::minLoop_, 6, 5, 6, false, false, Interface::limited); static Parameter interfaceMaximumInLoop ("MaximumInLoop", "The maximum flavour of the quarks to include in the loops", &MEPP2Higgs::maxLoop_, 6, 5, 6, false, false, Interface::limited); static Switch interfaceMassOption ("MassOption", "Option for the treatment of the masses in the loop diagrams", &MEPP2Higgs::massOption_, 0, false, false); static SwitchOption interfaceMassOptionFull (interfaceMassOption, "Full", "Include the full mass dependence", 0); static SwitchOption interfaceMassOptionLarge (interfaceMassOption, "Large", "Use the heavy mass limit", 1); static Parameter interfaceMinimumFlavour ("MinimumFlavour", "The minimum flavour of the incoming quarks in the hard process", &MEPP2Higgs::minFlavour_, 4, 3, 5, false, false, Interface::limited); static Parameter interfaceMaximumFlavour ("MaximumFlavour", "The maximum flavour of the incoming quarks in the hard process", &MEPP2Higgs::maxFlavour_, 5, 3, 5, false, false, Interface::limited); static Parameter interfaceQGChannelWeight ("QGChannelWeight", "The relative weights of the g g and q g channels for selection." " This is a technical parameter for the phase-space generation and " "should not affect the results only the efficiency and fraction" " of events with weight > 1.", &MEPP2Higgs::channelwgtA_, 0.45, 0., 1.e10, false, false, Interface::limited); static Parameter interfaceQbarGChannelWeight ("QbarGChannelWeight", "The relative weights of the g g abd qbar g channels for selection." " This is a technical parameter for the phase-space generation and " "should not affect the results only the efficiency and fraction", &MEPP2Higgs::channelwgtB_, 0.15, 0., 1.e10, false, false, Interface::limited); static Parameter interfaceGGPower ("GGPower", "Power for the phase-space sampling of the gg channel", &MEPP2Higgs::ggPow_, 1.6, 1.0, 3.0, false, false, Interface::limited); static Parameter interfaceQGPower ("QGPower", "Power for the phase-space sampling of the qg and qbarg channels", &MEPP2Higgs::qgPow_, 1.6, 1.0, 3.0, false, false, Interface::limited); static Parameter interfaceEnhancementFactor ("InitialEnhancementFactor", "The enhancement factor for initial-state radiation in the shower to ensure" " the weight for the matrix element correction is less than one.", &MEPP2Higgs::enhance_, 1.1, 1.0, 10.0, false, false, Interface::limited); static Parameter interfacePower ("Power", "The power for the sampling of the matrix elements", &MEPP2Higgs::power_, 2.0, 1.0, 10.0, false, false, Interface::limited); static Parameter interfacePrefactorgg ("Prefactorgg", "The prefactor for the sampling of the q qbar channel", &MEPP2Higgs::pregg_, 7.0, 0.0, 1000.0, false, false, Interface::limited); static Parameter interfacePrefactorqg ("Prefactorqg", "The prefactor for the sampling of the q g channel", &MEPP2Higgs::preqg_, 3.0, 0.0, 1000.0, false, false, Interface::limited); static Parameter interfacePrefactorgqbar ("Prefactorgqbar", "The prefactor for the sampling of the g qbar channel", &MEPP2Higgs::pregqbar_, 3.0, 0.0, 1000.0, false, false, Interface::limited); static Parameter interfacePtMin ("minPt", "The pt cut on hardest emision generation" "2*(1-Beta)*exp(-sqr(intrinsicpT/RMS))/sqr(RMS)", &MEPP2Higgs::minpT_, GeV, 2.*GeV, ZERO, 100000.0*GeV, false, false, Interface::limited); static Switch interface_mu_R_Option ("mu_R_Option", "Option to use pT or mT as the scale in alphaS", &MEPP2Higgs::mu_R_opt_, 1, false, false); static SwitchOption interface_mu_R_Option_mT (interface_mu_R_Option, "mT", "Use mT as the scale in alpha_S", 0); static SwitchOption interface_mu_R_Option_pT (interface_mu_R_Option, "pT", "Use pT as the scale in alpha_S", 1); static Switch interface_mu_F_Option ("mu_F_Option", "Option to use pT or mT as the factorization scale in the PDFs", &MEPP2Higgs::mu_F_opt_, 1, false, false); static SwitchOption interface_mu_F_Option_mT (interface_mu_F_Option, "mT", "Use mT as the scale in the PDFs", 0); static SwitchOption interface_mu_F_Option_pT (interface_mu_F_Option, "pT", "Use pT as the scale in the PDFs", 1); static Switch interfaceSpinCorrelations ("SpinCorrelations", "Which on/off spin correlations in the hard process", &MEPP2Higgs::spinCorrelations_, true, false, false); static SwitchOption interfaceSpinCorrelationsYes (interfaceSpinCorrelations, "Yes", "Switch correlations on", true); static SwitchOption interfaceSpinCorrelationsNo (interfaceSpinCorrelations, "No", "Switch correlations off", false); } void MEPP2Higgs::doinit() { HwMEBase::doinit(); // get the vertex pointers from the SM object tcHwSMPtr theSM = dynamic_ptr_cast(standardModel()); // do the initialisation if(!theSM) { throw InitException() << "Wrong type of StandardModel object in MEPP2Higgs::doinit()," << " the Herwig version must be used" << Exception::runerror; } HGGVertex_ = theSM->vertexHGG(); HFFVertex_ = theSM->vertexFFH(); // get the mass generator for the higgs PDPtr h0 = getParticleData(ParticleID::h0); mh_ = h0->mass(); wh_ = h0->generateWidth(mh_); if(h0->massGenerator()) { hmass_=dynamic_ptr_cast(h0->massGenerator()); } if(shapeOption_==2&&!hmass_) throw InitException() << "If using the mass generator for the line shape in MEPP2Higgs::doinit()" << "the mass generator must be an instance of the GenericMassGenerator class" << Exception::runerror; // stuff for the ME correction double total = 1.+channelwgtA_+channelwgtB_; channelWeights_.push_back(1./total); channelWeights_.push_back(channelWeights_.back()+channelwgtA_/total); channelWeights_.push_back(channelWeights_.back()+channelwgtB_/total); // insert the different prefactors in the vector for easy look up prefactor_.push_back(pregg_); prefactor_.push_back(preqg_); prefactor_.push_back(preqg_); prefactor_.push_back(pregqbar_); prefactor_.push_back(pregqbar_); } void MEPP2Higgs::dofinish() { HwMEBase::dofinish(); if(ntry_==0) return; generator()->log() << "MEPP2Higgs when applying the hard correction " << "generated " << ntry_ << " trial emissions of which " << ngen_ << " were accepted\n"; if(nover_==0) return; generator()->log() << "MEPP2Higgs when applying the hard correction " << nover_ << " weights larger than one were generated of which" << " the largest was " << maxwgt_ << "\n"; } unsigned int MEPP2Higgs::orderInAlphaS() const { return 2; } unsigned int MEPP2Higgs::orderInAlphaEW() const { return 1; } Energy2 MEPP2Higgs::scale() const { return scaleopt_ == 1 ? sHat() : sqr(mu_F_); } int MEPP2Higgs::nDim() const { return 0; } bool MEPP2Higgs::generateKinematics(const double *) { Lorentz5Momentum pout = meMomenta()[0] + meMomenta()[1]; pout.rescaleMass(); meMomenta()[2].setMass(pout.mass()); meMomenta()[2] = LorentzMomentum(pout.x(),pout.y(),pout.z(),pout.t()); jacobian(1.0); // check whether it passes all the cuts: returns true if it does vector out(1,meMomenta()[2]); tcPDVector tout(1,mePartonData()[2]); return lastCuts().passCuts(tout, out, mePartonData()[0], mePartonData()[1]); } void MEPP2Higgs::getDiagrams() const { tcPDPtr h0=getParticleData(ParticleID::h0); // gg -> H process if(processOption_==1||processOption_==3) { tcPDPtr g=getParticleData(ParticleID::g); add(new_ptr((Tree2toNDiagram(2), g, g, 1, h0, -1))); } // q qbar -> H processes if(processOption_==1||processOption_==2) { for ( int i = minFlavour_; i <= maxFlavour_; ++i ) { tcPDPtr q = getParticleData(i); tcPDPtr qb = q->CC(); add(new_ptr((Tree2toNDiagram(2), q, qb, 1, h0, -2))); } } } CrossSection MEPP2Higgs::dSigHatDR() const { using Constants::pi; InvEnergy2 bwfact; if(shapeOption_==1) { bwfact = mePartonData()[2]->generateWidth(sqrt(sHat()))*sqrt(sHat())/pi/ (sqr(sHat()-sqr(mh_))+sqr(mh_*wh_)); } else { bwfact = hmass_->BreitWignerWeight(sqrt(sHat())); } double cs = me2() * jacobian() * pi * double(UnitRemoval::E4 * bwfact/sHat()); return UnitRemoval::InvE2 * sqr(hbarc) * cs; } double MEPP2Higgs::me2() const { double output(0.0); ScalarWaveFunction hout(meMomenta()[2],mePartonData()[2],outgoing); // Safety code to garantee the reliable behaviour of Higgs shape limits // (important for heavy and broad Higgs resonance). Energy hmass = meMomenta()[2].m(); tcPDPtr h0 = mePartonData()[2]; Energy mass = h0->mass(); Energy halfmass = .5*mass; if (.0*GeV > hmass) return 0.0; // stricly speaking the condition is applicable if // h0->widthUpCut() == h0->widthLoCut()... if (h0->widthLoCut() > halfmass) { if ( mass + h0->widthUpCut() < hmass || mass - h0->widthLoCut() > hmass ) return 0.0; } else { if (mass + halfmass < hmass || halfmass > hmass) return 0.0; } if (mePartonData()[0]->id() == ParticleID::g && mePartonData()[1]->id() == ParticleID::g) { VectorWaveFunction gin1(meMomenta()[0],mePartonData()[0],incoming); VectorWaveFunction gin2(meMomenta()[1],mePartonData()[1],incoming); vector g1,g2; for(unsigned int i = 0; i < 2; ++i) { gin1.reset(2*i); g1.push_back(gin1); gin2.reset(2*i); g2.push_back(gin2); } output = ggME(g1,g2,hout,false); } else { if (mePartonData()[0]->id() == -mePartonData()[1]->id()) { SpinorWaveFunction qin (meMomenta()[0],mePartonData()[0],incoming); SpinorBarWaveFunction qbin(meMomenta()[1],mePartonData()[1],incoming); vector fin; vector ain; for (unsigned int i = 0; i < 2; ++i) { qin.reset(i); fin.push_back(qin); qbin.reset(i); ain.push_back(qbin); } output = qqME(fin,ain,hout,false); } else assert(false); } return output; } Selector MEPP2Higgs::diagrams(const DiagramVector & diags) const { Selector sel; for (DiagramIndex i = 0; i < diags.size(); ++i) sel.insert(1.0, i); return sel; } Selector MEPP2Higgs::colourGeometries(tcDiagPtr diag) const { // colour lines static const ColourLines line1("1 -2,2 -1"); static const ColourLines line2("1 -2"); // select the colour flow Selector sel; if (diag->id() == -1) { sel.insert(1.0, &line1); } else { sel.insert(1.0, &line2); } // return the answer return sel; } void MEPP2Higgs::constructVertex(tSubProPtr sub) { if(!spinCorrelations_) return; // 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]); if(hard[0]->id() < hard[1]->id()) { swap(hard[0],hard[1]); } // identify the process and calculate the matrix element if(hard[0]->id() == ParticleID::g && hard[1]->id() == ParticleID::g) { vector g1,g2; vector q; vector qbar; VectorWaveFunction (g1,hard[0],incoming,false,true,true); VectorWaveFunction (g2,hard[1],incoming,false,true,true); ScalarWaveFunction hout(hard[2],outgoing,true); g1[1] = g1[2]; g2[1] = g2[2]; ggME(g1,g2,hout,true); } else { vector q1; vector q2; SpinorWaveFunction (q1,hard[0],incoming,false,true); SpinorBarWaveFunction (q2,hard[1],incoming,false,true); ScalarWaveFunction hout(hard[2],outgoing,true); qqME(q1,q2,hout,true); } // construct the vertex HardVertexPtr hardvertex = new_ptr(HardVertex()); // set the matrix element for the vertex hardvertex->ME(me_); // set the pointers and to and from the vertex for(unsigned int i = 0; i < 3; ++i) hard[i]->spinInfo()->productionVertex(hardvertex); } double MEPP2Higgs::ggME(vector g1, vector g2, ScalarWaveFunction & in, bool calc) const { ProductionMatrixElement newme(PDT::Spin1,PDT::Spin1,PDT::Spin0); Energy2 s(sHat()); double me2(0.0); for(int i = 0; i < 2; ++i) { for(int j = 0; j < 2; ++j) { Complex diag = HGGVertex_->evaluate(s,g1[i],g2[j],in); me2 += norm(diag); if(calc) newme(2*i, 2*j, 0) = diag; } } if(calc) me_.reset(newme); // initial colour and spin factors: colour -> (8/64) and spin -> (1/4) return me2/32.; } double MEPP2Higgs::qqME(vector & fin, vector & ain, ScalarWaveFunction & in, bool calc) const { ProductionMatrixElement newme(PDT::Spin1Half,PDT::Spin1Half,PDT::Spin0); Energy2 s(scale()); double me2(0.0); for(int i = 0; i < 2; ++i) { for(int j = 0; j < 2; ++j) { Complex diag = HFFVertex_->evaluate(s,fin[i],ain[j],in); me2+=norm(diag); if(calc) newme(i, j, 0) = diag; } } if(calc) me_.reset(newme); // final colour/spin factors return me2/12.; } RealEmissionProcessPtr MEPP2Higgs::applyHardMatrixElementCorrection(RealEmissionProcessPtr born) { useMe(); assert(born->bornOutgoing().size()==1); if(born->bornIncoming()[0]->id()!=ParticleID::g) return RealEmissionProcessPtr(); // get gluons and Higgs // get the gluons ParticleVector incoming; vector beams; for(unsigned int ix=0;ixbornIncoming().size();++ix) { incoming.push_back(born->bornIncoming()[ix]); beams.push_back(dynamic_ptr_cast(born->hadrons()[ix]->dataPtr())); } pair xnew=born->x(); if(incoming[0]->momentum().z()bornOutgoing()[0]; // calculate the momenta unsigned int iemit,itype; vector pnew; // if not accepted return tPDPtr out; if(!applyHard(incoming,beams,higgs,iemit,itype,pnew,xnew,out)) return RealEmissionProcessPtr(); // fix the momentum of the higgs Boost boostv=born->bornOutgoing()[0]->momentum().findBoostToCM(); LorentzRotation trans(pnew[3].boostVector()); trans *=LorentzRotation(boostv); born->transformation(trans); born->outgoing().push_back(born->bornOutgoing()[0]->dataPtr()->produceParticle(pnew[3])); born->emitted(3); // if applying ME correction create the new particles if(itype==0) { // ensure gluon can be put on shell Lorentz5Momentum ptest(pnew[2]); if(ptest.boost(-(pnew[0]+pnew[1]).boostVector()).e() < getParticleData(ParticleID::g)->constituentMass()) return RealEmissionProcessPtr(); // create the new gluon PPtr newg= getParticleData(ParticleID::g)->produceParticle(pnew[2]); PPtr newg1 = incoming[0]->dataPtr()->produceParticle(pnew[0]); PPtr newg2 = incoming[1]->dataPtr()->produceParticle(pnew[1]); // set emitter and spectator if(born->bornIncoming()[0]->momentum().z()>ZERO) { born->incoming().push_back(newg1); born->incoming().push_back(newg2); if(iemit==0) { born->emitter(0); born->spectator(1); } else { born->emitter(1); born->spectator(0); } } else { born->incoming().push_back(newg2); born->incoming().push_back(newg1); if(iemit==0) { born->emitter(1); born->spectator(0); } else { born->emitter(0); born->spectator(1); } } bool colour = UseRandom::rndbool(); newg ->incomingColour(newg1,!colour); newg ->incomingColour(newg2, colour); newg1->colourConnect(newg2,!colour); born->outgoing().push_back(newg); } else if(itype==1) { // ensure outgoing quark can be put on-shell Lorentz5Momentum ptest(pnew[2]); if(ptest.boost(-(pnew[0]+pnew[1]).boostVector()).e() < out->constituentMass()) return RealEmissionProcessPtr(); // create the new particles PPtr newqout = out->produceParticle(pnew[2]); PPtr newqin,newg; if(iemit==0) { newqin = out ->produceParticle(pnew[0]); newg = incoming[1]->dataPtr()->produceParticle(pnew[1]); } else { newg = incoming[0]->dataPtr()->produceParticle(pnew[0]); newqin = out ->produceParticle(pnew[1]); } newqout->incomingColour(newg); newg->colourConnect(newqin); if((born->bornIncoming()[0]->momentum().z()>ZERO && iemit==0) || (born->bornIncoming()[0]->momentum().z()incoming().push_back(newqin); born->incoming().push_back(newg ); born->emitter(0); born->spectator(1); } else { born->incoming().push_back(newg ); born->incoming().push_back(newqin); born->emitter(1); born->spectator(0); } born->outgoing().push_back(newqout); } else if(itype==2) { // ensure outgoing antiquark can be put on-shell Lorentz5Momentum ptest(pnew[2]); if(ptest.boost(-(pnew[0]+pnew[1]).boostVector()).e() < incoming[0]->dataPtr()->constituentMass()) return RealEmissionProcessPtr(); // create the new particles PPtr newqout = out->produceParticle(pnew[2]); PPtr newqin,newg; if(iemit==0) { newqin = out ->produceParticle(pnew[0]); newg = incoming[1]->dataPtr()->produceParticle(pnew[1]); } else { newg = incoming[0]->dataPtr()->produceParticle(pnew[0]); newqin = out ->produceParticle(pnew[1]); } newqout->incomingAntiColour(newg); newg->colourConnect(newqin,true); if((born->bornIncoming()[0]->momentum().z()>ZERO && iemit==0) || (born->bornIncoming()[0]->momentum().z()incoming().push_back(newqin); born->incoming().push_back(newg ); born->emitter(0); born->spectator(1); } else { born->incoming().push_back(newg ); born->incoming().push_back(newqin); born->emitter(1); born->spectator(0); } born->outgoing().push_back(newqout); } if(born->bornIncoming()[0]->momentum().z()x(xnew); born->interaction(ShowerInteraction::QCD); return born; } bool MEPP2Higgs::softMatrixElementVeto(PPtr parent, PPtr progenitor, const bool & fs, const Energy & highestpT, const vector & ids, const double & z, const Energy & scale, const Energy & pT) { if(fs) return false; // check if me correction should be applied long id[2]={progenitor->id(),parent->id()}; // must have started as a gluon if(id[0]!=ParticleID::g) return false; // must be a gluon going into the hard process if(ids[1]->id()!=ParticleID::g) return false; // check if hardest so far if(pTid()==ParticleID::g&&ids[2]->id()==ParticleID::g) { double split = 6.*(z/(1.-z)+(1.-z)/z+z*(1.-z)); me = ggME(shat,that,uhat)/split; } // q g else if(ids[0]->id() >= 1 && ids[0]->id() <= 5 && ids[2]->id()==ids[0]->id()) { double split = 4./3./z*(1.+sqr(1.-z)); me = qgME(shat,uhat,that)/split; } // qbar g else if(ids[0]->id() <= -1 && ids[0]->id() >= -5 && ids[2]->id()==ids[0]->id()) { double split = 4./3./z*(1.+sqr(1.-z)); me = qbargME(shat,uhat,that)/split; } else { return false; } InvEnergy2 pre = 0.125/Constants::pi/loME()*sqr(mh2_)*that/shat/(shat+uhat); double wgt = -pre*me/enhance_; if(wgt<.0||wgt>1.) generator()->log() << "Soft ME correction weight too large or " << "negative in MEPP2Higgs::" << "softMatrixElementVeto()\n soft weight " << " sbar = " << shat/mh2_ << " tbar = " << that/mh2_ << "weight = " << wgt << " for " << ids[0]->id() << " " << ids[1]->id() << " " << ids[2]->id() << "\n"; // return whether or not vetoed return !UseRandom::rndbool(wgt); } RealEmissionProcessPtr MEPP2Higgs::generateHardest(RealEmissionProcessPtr born, ShowerInteraction inter) { if(inter==ShowerInteraction::QED) return RealEmissionProcessPtr(); useMe(); // get the particles to be showered beams_.clear(); partons_.clear(); // find the incoming particles ParticleVector incoming; ParticleVector particlesToShower; for(unsigned int ix=0;ixbornIncoming().size();++ix) { incoming.push_back( born->bornIncoming()[ix] ); beams_.push_back( dynamic_ptr_cast(born->hadrons()[ix]->dataPtr())); partons_.push_back( born->bornIncoming()[ix]->dataPtr() ); particlesToShower.push_back( born->bornIncoming()[ix] ); } // find the higgs boson assert(born->bornOutgoing().size()==1); PPtr higgs = born->bornOutgoing()[0]; // calculate the rapidity of the higgs yh_ = 0.5 * log((higgs->momentum().e()+higgs->momentum().z())/ (higgs->momentum().e()-higgs->momentum().z())); mass_=higgs->mass(); mh2_ = sqr(mass_); vector pnew; int emission_type(-1); // generate the hard emission and return if no emission if(!getEvent(pnew,emission_type)) { born->pT()[ShowerInteraction::QCD] = minpT_; return born; } // construct the HardTree object needed to perform the showers ParticleVector newparticles(4); // create the partons int iemit=-1; // create the jet newparticles[3] = out_->produceParticle(pnew[3]); // g g -> h g if(emission_type==0) { newparticles[0] = partons_[0]->produceParticle(pnew[0]); newparticles[1] = partons_[1]->produceParticle(pnew[1]); iemit = pnew[0].z()/pnew[3].z()>0. ? 0 : 1; bool colour = UseRandom::rndbool(); newparticles[3]->incomingColour(newparticles[0],!colour); newparticles[3]->incomingColour(newparticles[1], colour); newparticles[0]-> colourConnect(newparticles[1],!colour); } // g q -> H q else if(emission_type==1) { newparticles[0] = partons_[0]->produceParticle(pnew[0]); newparticles[1] = out_ ->produceParticle(pnew[1]); iemit = 1; newparticles[3]->incomingColour(newparticles[0]); newparticles[0]->colourConnect (newparticles[1]); } // q g -> H q else if(emission_type==2) { newparticles[0] = out_ ->produceParticle(pnew[0]); newparticles[1] = partons_[1]->produceParticle(pnew[1]); iemit = 0; newparticles[3]->incomingColour(newparticles[1]); newparticles[1]->colourConnect (newparticles[0]); } // g qbar -> H qbar else if(emission_type==3) { newparticles[0] = partons_[0]->produceParticle(pnew[0]); newparticles[1] = out_ ->produceParticle(pnew[1]); iemit = 1; newparticles[3]->incomingAntiColour(newparticles[0]); newparticles[0]->colourConnect(newparticles[1],true); } // qbar g -> H qbar else if(emission_type==4) { newparticles[0] = out_ ->produceParticle(pnew[0]); newparticles[1] = partons_[1]->produceParticle(pnew[1]); iemit = 0; newparticles[3]->incomingAntiColour(newparticles[1]); newparticles[1]->colourConnect(newparticles[0],true); } unsigned int ispect = iemit==0 ? 1 : 0; // create the boson newparticles[2] = higgs->dataPtr()->produceParticle(pnew[2]); born->emitter (iemit); born->spectator(ispect); born->emitted(3); born->pT()[ShowerInteraction::QCD] = pt_; pair xnew; for(unsigned int ix=0;ix<2;++ix) { born->incoming().push_back(newparticles[ix]); if(ix==0) xnew.first = newparticles[ix]->momentum().rho()/born->hadrons()[ix]->momentum().rho(); else xnew.second = newparticles[ix]->momentum().rho()/born->hadrons()[ix]->momentum().rho(); } born->x(xnew); for(unsigned int ix=0;ix<2;++ix) born->outgoing().push_back(newparticles[ix+2]); // return the answer born->interaction(ShowerInteraction::QCD); return born; } bool MEPP2Higgs::applyHard(ParticleVector gluons, vector beams,PPtr higgs, unsigned int & iemit, unsigned int & itype, vector & pnew, pair & xout, tPDPtr & out) { ++ntry_; // calculate the limits on s Energy mh(higgs->mass()); mh2_=sqr(mh); Energy2 smin=mh2_; Energy2 s= (generator()->currentEvent()->incoming().first->momentum()+ generator()->currentEvent()->incoming().second->momentum()).m2(); Energy2 smax(s); // calculate the rapidity of the higgs double yH = 0.5*log((higgs->momentum().e()+higgs->momentum().z())/ (higgs->momentum().e()-higgs->momentum().z())); // if no phase-space return if(smaxpdf(); assert(pdf[ix]); fx[ix]=pdf[ix]->xfx(beams[ix],gluons[ix]->dataPtr(),mh2_,x[ix]); } // leading order ME Energy4 lome = loME(); // select the type of process and generate the kinematics double rn(UseRandom::rnd()); Energy2 shat(ZERO),uhat(ZERO),that(ZERO); double weight(0.),xnew[2]={1.,1.}; // gg -> H g if(rn=1.||xnew[1]<=0.||xnew[1]>=1.) return false; for(unsigned int ix=0;ix<2;++ix) fxnew[ix]=pdf[ix]->xfx(beams[ix],gluons[ix]->dataPtr(),scale,xnew[ix]); // jacobian and me parts of the weight weight = jacobian2*ggME(shat,uhat,that)/lome*mh2_/sqr(shat); // pdf part of the weight weight *=fxnew[0]*fxnew[1]*x[0]*x[1]/(fx[0]*fx[1]*xnew[0]*xnew[1]); // finally coupling and different channel pieces weight *= 1./16./sqr(Constants::pi)*alpha_->value(scale)/channelWeights_[0]; itype=0; iemit = that>uhat ? 0 : 1; out = getParticleData(ParticleID::g); } // incoming quark or antiquark else { // generate the value of s according to 1/s^n double rhomax(pow(smin/mh2_,1.-qgPow_)),rhomin(pow(smax/mh2_,1.-qgPow_)); double rho = rhomin+UseRandom::rnd()*(rhomax-rhomin); shat = mh2_*pow(rho,1./(1.-qgPow_)); Energy2 jacobian = mh2_/(qgPow_-1.)*(rhomax-rhomin)*pow(shat/mh2_,qgPow_); double sbar=shat/mh2_; // calculate limits on that Energy2 tmax=mh2_*kappa[0]*(1.-sbar)/(kappa[0]+sbar); Energy2 tmin=shat*(1.-sbar)/(kappa[1]+sbar); // calculate the limits on uhat Energy2 umax(mh2_-shat-tmin),umin(mh2_-shat-tmax); // check inside phase space if(tmax=1.||xnew[1]<=0.||xnew[1]>=1.) return false; if(rn H q if(!order) { out = quarkFlavour(pdf[0],scale,xnew[0],beams[0],fxnew[0],false); fxnew[1]=pdf[1]->xfx(beams[1],gluons[1]->dataPtr(),scale,xnew[1]); iemit = 0; mewgt = out ? qgME(shat,uhat,that)/lome*mh2_/sqr(shat) : ZERO; } // g q -> H q else { fxnew[0]=pdf[0]->xfx(beams[0],gluons[0]->dataPtr(),scale,xnew[0]); out = quarkFlavour(pdf[1],scale,xnew[1],beams[1],fxnew[1],false); iemit = 1; mewgt = out ? qgME(shat,that,uhat)/lome*mh2_/sqr(shat) : ZERO; } jacobian2 /= (channelWeights_[1]-channelWeights_[0]); } else { itype=2; // qbar g -> H qbar if(!order) { out = quarkFlavour(pdf[0],scale,xnew[0],beams[0],fxnew[0],true); fxnew[1]=pdf[1]->xfx(beams[1],gluons[1]->dataPtr(),scale,xnew[1]); iemit = 0; mewgt = out ? qbargME(shat,uhat,that)/lome*mh2_/sqr(shat) : ZERO; } // g qbar -> H qbar else { fxnew[0]=pdf[0]->xfx(beams[0],gluons[0]->dataPtr(),scale,xnew[0]); out = quarkFlavour(pdf[1],scale,xnew[1],beams[1],fxnew[1],true); iemit = 1; mewgt = out ? qbargME(shat,that,uhat)/lome*mh2_/sqr(shat) : ZERO; } jacobian2/=(channelWeights_[2]-channelWeights_[1]); } // weight (factor of 2 as pick q(bar)g or gq(bar) weight = 2.*jacobian2*mewgt; // pdf part of the weight weight *=fxnew[0]*fxnew[1]*x[0]*x[1]/(fx[0]*fx[1]*xnew[0]*xnew[1]); // finally coupling and different channel pieces weight *= 1./16./sqr(Constants::pi)*alpha_->value(scale); } // if me correction should be applied if(weight>1.) { ++nover_; maxwgt_ = max( maxwgt_ , weight); weight=1.; } if(UseRandom::rnd()>weight) return false; ++ngen_; // construct the momenta Energy roots = 0.5*sqrt(s); Energy pt = sqrt(uhat*that/shat); Energy mt = sqrt(uhat*that/shat+mh2_); Lorentz5Momentum pin[2]={Lorentz5Momentum(ZERO,ZERO, xnew[0]*roots,xnew[0]*roots), Lorentz5Momentum(ZERO,ZERO,-xnew[1]*roots,xnew[1]*roots)}; double phi = Constants::twopi*UseRandom::rnd(); Lorentz5Momentum pH(pt*cos(phi),pt*sin(phi),mt*sinh(yH),mt*cosh(yH)); Lorentz5Momentum pJ(pin[0]+pin[1]-pH); // momenta to be returned pnew.push_back(pin[0]); pnew.push_back(pin[1]); pnew.push_back(pJ); pnew.push_back(pH); xout.first = xnew[0]; xout.second = xnew[1]; return true; } Energy2 MEPP2Higgs::ggME(Energy2 s, Energy2 t, Energy2 u) { Energy2 output; if(massOption_==0) { complex me[2][2][2]; me[1][1][1] = ZERO; me[1][1][0] = ZERO; me[0][1][0] = ZERO; me[0][1][1] = ZERO; for(unsigned int ix=minLoop_; ix<=maxLoop_; ++ix ) { Energy2 mf2=sqr(getParticleData(long(ix))->mass()); bi_[1]=B(s,mf2); bi_[2]=B(u,mf2); bi_[3]=B(t,mf2); bi_[4]=B(mh2_,mf2); bi_[1]=bi_[1]-bi_[4]; bi_[2]=bi_[2]-bi_[4]; bi_[3]=bi_[3]-bi_[4]; ci_[1]=C(s,mf2); ci_[2]=C(u,mf2); ci_[3]=C(t,mf2); ci_[7]=C(mh2_,mf2); ci_[4]=(s*ci_[1]-mh2_*ci_[7])/(s-mh2_); ci_[5]=(u*ci_[2]-mh2_*ci_[7])/(u-mh2_); ci_[6]=(t*ci_[3]-mh2_*ci_[7])/(t-mh2_); di_[1]=D(t,u,s,mf2); di_[2]=D(s,t,u,mf2); di_[3]=D(s,u,t,mf2); me[1][1][1]+=me1(s,u,t,mf2,1,2,3,4,5,6); me[1][1][0]+=me2(s,u,t,mf2); me[0][1][0]+=me1(u,s,t,mf2,2,1,3,5,4,6); me[0][1][1]+=me1(t,u,s,mf2,3,2,1,6,5,4); } me[0][0][0]=-me[1][1][1]; me[0][0][1]=-me[1][1][0]; me[1][0][1]=-me[0][1][0]; me[1][0][0]=-me[0][1][1]; output = real(me[0][0][0]*conj(me[0][0][0])+ me[0][0][1]*conj(me[0][0][1])+ me[0][1][0]*conj(me[0][1][0])+ me[0][1][1]*conj(me[0][1][1])+ me[1][0][0]*conj(me[1][0][0])+ me[1][0][1]*conj(me[1][0][1])+ me[1][1][0]*conj(me[1][1][0])+ me[1][1][1]*conj(me[1][1][1])); output *= 3./8.; } else { output=32./3.* (pow<4,1>(s)+pow<4,1>(t)+pow<4,1>(u)+pow<4,1>(mh2_))/s/t/u; } // spin and colour factors return output/4./64.; } Energy2 MEPP2Higgs::qgME(Energy2 s, Energy2 t, Energy2 u) { Energy2 output; if(massOption_==0) { complex A(ZERO); Energy2 si(u-mh2_); for(unsigned int ix=minLoop_;ix<=maxLoop_;++ix) { Energy2 mf2=sqr(getParticleData(long(ix))->mass()); A += mf2*(2.+2.*double(u/si)*(B(u,mf2)-B(mh2_,mf2)) +double((4.*mf2-s-t)/si)*Complex(u*C(u,mf2)-mh2_*C(mh2_,mf2))); } output =-4.*(sqr(s)+sqr(t))/sqr(si)/u*real(A*conj(A)); } else{ output =-4.*(sqr(s)+sqr(t))/u/9.; } // final colour/spin factors return output/24.; } Energy2 MEPP2Higgs::qbargME(Energy2 s, Energy2 t, Energy2 u) { Energy2 output; if(massOption_==0) { complex A(ZERO); Energy2 si(u-mh2_); for(unsigned int ix=minLoop_;ix<=maxLoop_;++ix) { Energy2 mf2=sqr(getParticleData(long(ix))->mass()); A+=mf2*(2.+2.*double(u/si)*(B(u,mf2)-B(mh2_,mf2)) +double((4.*mf2-s-t)/si)*Complex(u*C(u,mf2)-mh2_*C(mh2_,mf2))); } output =-4.*(sqr(s)+sqr(t))/sqr(si)/u*real(A*conj(A)); } else { output =-4.*(sqr(s)+sqr(t))/u/9.; } // final colour/spin factors return output/24.; } Energy4 MEPP2Higgs::loME() const { Complex I(0); if(massOption_==0) { for(unsigned int ix=minLoop_;ix<=maxLoop_;++ix) { double x = sqr(getParticleData(long(ix))->mass())/mh2_; I += 3.*x*(2.+(4.*x-1.)*F(x)); } } else { I = 1.; } return sqr(mh2_)/576./Constants::pi*norm(I); } tPDPtr MEPP2Higgs::quarkFlavour(tcPDFPtr pdf, Energy2 scale, double x, tcBeamPtr beam, double & pdfweight, bool anti) { vector weights; vector partons; pdfweight = 0.; if(!anti) { for(unsigned int ix=1;ix<=5;++ix) { partons.push_back(getParticleData(long(ix))); weights.push_back(max(0.,pdf->xfx(beam,partons.back(),scale,x))); pdfweight += weights.back(); } } else { for(unsigned int ix=1;ix<=5;++ix) { partons.push_back(getParticleData(-long(ix))); weights.push_back(max(0.,pdf->xfx(beam,partons.back(),scale,x))); pdfweight += weights.back(); } } if(pdfweight==0.) return tPDPtr(); double wgt=UseRandom::rnd()*pdfweight; for(unsigned int ix=0;ix=ZERO&&rat<1.) output=2.-2.*sqrt(1./rat-1.)*asin(sqrt(rat)); else output=2.-sqrt(1.-1./rat)*(2.*log(sqrt(rat)+sqrt(rat-1.))-pii); return output; } complex MEPP2Higgs::C(Energy2 s,Energy2 mf2) const { complex output; - Complex pii(0.,Constants::pi); + const Complex pii(0.,Constants::pi); double rat=s/(4.*mf2); if(s=ZERO&&rat<1.) output=-2.*sqr(asin(sqrt(rat)))/s; else { double cosh=log(sqrt(rat)+sqrt(rat-1.)); output=2.*(sqr(cosh)-sqr(Constants::pi)/4.-pii*cosh)/s; } return output; } Complex MEPP2Higgs::dIntegral(Energy2 a, Energy2 b, double y0) const { Complex output; if(b==ZERO) output=0.; else { Complex y1=0.5*(1.+sqrt(1.-4.*(a+epsi_)/b)); Complex y2=1.-y1; Complex z1=y0/(y0-y1); Complex z2=(y0-1.)/(y0-y1); Complex z3=y0/(y0-y2); Complex z4=(y0-1.)/(y0-y2); output=Math::Li2(z1)-Math::Li2(z2)+Math::Li2(z3)-Math::Li2(z4); } return output; } complex MEPP2Higgs::D(Energy2 s,Energy2 t, Energy2, Energy2 mf2) const { - Complex output,pii(0.,Constants::pi); + Complex output; Energy4 st=s*t; Energy4 root=sqrt(sqr(st)-4.*st*mf2*(s+t-mh2_)); double xp=0.5*(st+root)/st,xm=1-xp; output = 2.*(-dIntegral(mf2,s,xp)-dIntegral(mf2,t,xp) +dIntegral(mf2,mh2_,xp)+log(-xm/xp) *(log((mf2+epsi_)/GeV2)-log((mf2+epsi_-s*xp*xm)/GeV2) +log((mf2+epsi_-mh2_*xp*xm)/GeV2)-log((mf2+epsi_-t*xp*xm)/GeV2))); return output/root; } complex MEPP2Higgs::me1(Energy2 s,Energy2 t,Energy2 u, Energy2 mf2, unsigned int i ,unsigned int j ,unsigned int k , unsigned int i1,unsigned int j1,unsigned int k1) const { Energy2 s1(s-mh2_),t1(t-mh2_),u1(u-mh2_); return mf2*4.*sqrt(2.*s*t*u)* (-4.*(1./(u*t)+1./(u*u1)+1./(t*t1)) -4.*((2.*s+t)*bi_[k]/sqr(u1)+(2.*s+u)*bi_[j]/sqr(t1))/s -(s-4.*mf2)*(s1*ci_[i1]+(u-s)*ci_[j1]+(t-s)*ci_[k1])/(s*t*u) -8.*mf2*(ci_[j1]/(t*t1)+ci_[k1]/(u*u1)) +0.5*(s-4.*mf2)*(s*t*di_[k]+u*s*di_[j]-u*t*di_[i])/(s*t*u) +4.*mf2*di_[i]/s -2.*Complex(u*ci_[k]+t*ci_[j]+u1*ci_[k1]+t1*ci_[j1]-u*t*di_[i])/sqr(s)); } complex MEPP2Higgs::me2(Energy2 s,Energy2 t,Energy2 u, Energy2 mf2) const { Energy2 s1(s-mh2_),t1(t-mh2_),u1(u-mh2_); return mf2*4.*sqrt(2.*s*t*u)*(4.*mh2_+(mh2_-4.*mf2)*(s1*ci_[4]+t1*ci_[5]+u1*ci_[6]) -0.5*(mh2_-4.*mf2)*(s*t*di_[3]+u*s*di_[2]+u*t*di_[1]) )/ (s*t*u); } Complex MEPP2Higgs::F(double x) const { if(x<.25) { double root = sqrt(1.-4.*x); - Complex pii(0.,Constants::pi); + const Complex pii(0.,Constants::pi); return 0.5*sqr(log((1.+root)/(1.-root))-pii); } else { return -2.*sqr(asin(0.5/sqrt(x))); } } bool MEPP2Higgs::getEvent(vector & pnew, int & emis_type){ // maximum pt (half of centre-of-mass energy) Energy maxp = 0.5*generator()->maximumCMEnergy(); // set pt of emission to zero pt_=ZERO; //Working Variables Energy pt; double yj; // limits on the rapidity of the jet double minyj = -8.0,maxyj = 8.0; bool reject; double wgt; emis_type=-1; tcPDPtr outParton; for(int j=0;j<5;++j) { pt = maxp; do { double a = alpha_->overestimateValue()*prefactor_[j]*(maxyj-minyj)/(power_-1.); // generate next pt pt=GeV/pow(pow(GeV/pt,power_-1)-log(UseRandom::rnd())/a,1./(power_-1.)); // generate rapidity of the jet yj=UseRandom::rnd()*(maxyj-minyj)+ minyj; // calculate rejection weight wgt=getResult(j,pt,yj,outParton); wgt/= prefactor_[j]*pow(GeV/pt,power_); reject = UseRandom::rnd()>wgt; //no emission event if p goes past p min - basically set to outside //of the histogram bounds (hopefully hist object just ignores it) if(pt1.0) { ostringstream s; s << "MEPP2Higgs::getEvent weight for channel " << j << "is " << wgt << " which is greater than 1"; generator()->logWarning( Exception(s.str(), Exception::warning) ); } } while(reject); // set pt of emission etc if(pt>pt_){ emis_type = j; pt_=pt; yj_=yj; out_ = outParton; } } //was this an (overall) no emission event? if(pt_maximumCMEnergy()); // transverse energy Energy et=sqrt(mh2_+sqr(pt_)); // first calculate all the kinematic variables // longitudinal real correction fractions double x = pt_*exp( yj_)/sqrt(s)+et*exp( yh_)/sqrt(s); double y = pt_*exp(-yj_)/sqrt(s)+et*exp(-yh_)/sqrt(s); // that and uhat // Energy2 th = -sqrt(s)*x*pt_*exp(-yj_); // Energy2 uh = -sqrt(s)*y*pt_*exp( yj_); // Energy2 sh = x*y*s; // reconstruct the momenta // incoming momenta pnew.push_back(Lorentz5Momentum(ZERO,ZERO, x*0.5*sqrt(s), x*0.5*sqrt(s),ZERO)); pnew.push_back(Lorentz5Momentum(ZERO,ZERO, -y*0.5*sqrt(s), y*0.5*sqrt(s),ZERO)); // outgoing momenta double phi(Constants::twopi*UseRandom::rnd()); double sphi(sin(phi)),cphi(cos(phi)); pnew.push_back(Lorentz5Momentum( cphi*pt_, sphi*pt_, et*sinh(yh_), et*cosh(yh_), mass_)); pnew.push_back(Lorentz5Momentum(-cphi*pt_,-sphi*pt_,pt_*sinh(yj_), pt_*cosh(yj_),ZERO)); return true; } double MEPP2Higgs::getResult(int emis_type, Energy pt, double yj, tcPDPtr & outParton) { Energy2 s=sqr(generator()->maximumCMEnergy()); Energy2 scale = mh2_+sqr(pt); Energy et=sqrt(scale); scale = mu_F_opt_==0 ? mh2_+sqr(pt) : sqr(pt) ; // longitudinal real correction fractions double x = pt*exp( yj)/sqrt(s)+et*exp( yh_)/sqrt(s); double y = pt*exp(-yj)/sqrt(s)+et*exp(-yh_)/sqrt(s); // reject if outside region if(x<0.||x>1.||y<0.||y>1.||x*ypdf()->xfx(beams_[0],partons_[0],mh2_,x1); pdf[1]=beams_[1]->pdf()->xfx(beams_[1],partons_[1],mh2_,y1); } else { // As in Nason and Ridolfi paper ... pdf[0]=beams_[0]->pdf()->xfx(beams_[0],partons_[0],scale,x1); pdf[1]=beams_[1]->pdf()->xfx(beams_[1],partons_[1],scale,y1); } // g g -> H g if(emis_type==0) { outParton = partons_[1]; pdf[2]=beams_[0]->pdf()->xfx(beams_[0],partons_[0],scale,x); pdf[3]=beams_[1]->pdf()->xfx(beams_[1],partons_[1],scale,y); res = ggME(sh,uh,th)/loME(); } // q g -> H q else if(emis_type==1) { outParton = quarkFlavour(beams_[0]->pdf(),scale,x,beams_[0],pdf[2],false); pdf[3]=beams_[1]->pdf()->xfx(beams_[1],partons_[1],scale,y); res = outParton ? qgME(sh,uh,th)/loME() : ZERO; } // g q -> H q else if(emis_type==2) { pdf[2]=beams_[0]->pdf()->xfx(beams_[0],partons_[0],scale,x); outParton = quarkFlavour(beams_[1]->pdf(),scale,y,beams_[1],pdf[3],false); res = outParton ? qgME(sh,th,uh)/loME() : ZERO; } // qbar g -> H qbar else if(emis_type==3) { outParton = quarkFlavour(beams_[0]->pdf(),scale,x,beams_[0],pdf[2],true); pdf[3]=beams_[1]->pdf()->xfx(beams_[1],partons_[1],scale,y); res = outParton ? qbargME(sh,uh,th)/loME() : ZERO; } // g qbar -> H qbar else if(emis_type==4) { pdf[2]=beams_[0]->pdf()->xfx(beams_[0],partons_[0],scale,x); outParton = quarkFlavour(beams_[1]->pdf(),scale,y,beams_[1],pdf[3],true); res = outParton ? qbargME(sh,th,uh)/loME() : ZERO; } //deals with pdf zero issue at large x if(pdf[0]<=0.||pdf[1]<=0.||pdf[2]<=0.||pdf[3]<=0.) { res = ZERO; } else { res *= pdf[2]*pdf[3]/pdf[0]/pdf[1]*mh2_/sh; } scale = mu_R_opt_==0 ? mh2_+sqr(pt) : sqr(pt) ; return alpha_->ratio(scale)/8./sqr(Constants::pi)*mh2_/sh*GeV*pt*res; } void MEPP2Higgs::initializeMECorrection(RealEmissionProcessPtr born, double & initial, double & final) { final = 1.; initial = born->bornIncoming()[0]->id()==ParticleID::g ? enhance_ : 1.; } diff --git a/MatrixElement/Hadron/MEPP2ZH.h b/MatrixElement/Hadron/MEPP2ZH.h --- a/MatrixElement/Hadron/MEPP2ZH.h +++ b/MatrixElement/Hadron/MEPP2ZH.h @@ -1,111 +1,105 @@ // -*- C++ -*- #ifndef HERWIG_MEPP2ZH_H #define HERWIG_MEPP2ZH_H // // This is the declaration of the MEPP2ZH class. // #include "Herwig/MatrixElement/MEfftoVH.h" namespace Herwig { using namespace ThePEG; /** * The MEPP2ZH class implements the matrix element * for \f$q\bar{q}\to Z^0h^0\f$. * * @see \ref MEPP2ZHInterfaces "The interfaces" * defined for MEPP2ZH. */ class MEPP2ZH: public MEfftoVH { public: /** * The default constructor. */ MEPP2ZH(); /** @name Virtual functions required by the MEBase class. */ //@{ /** * Add all possible diagrams with the add() function. */ virtual void getDiagrams() const; //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const { return new_ptr(*this); } /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const { return new_ptr(*this); } //@} protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MEPP2ZH & operator=(const MEPP2ZH &) = delete; -private: - - /** - * The allowed flavours of the incoming quarks - */ - int _maxflavour; }; } #endif /* HERWIG_MEPP2ZH_H */ diff --git a/MatrixElement/Lepton/MEee2VectorMeson.cc b/MatrixElement/Lepton/MEee2VectorMeson.cc --- a/MatrixElement/Lepton/MEee2VectorMeson.cc +++ b/MatrixElement/Lepton/MEee2VectorMeson.cc @@ -1,228 +1,227 @@ // -*- C++ -*- // // MEee2VectorMeson.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 MEee2VectorMeson class. // #include "MEee2VectorMeson.h" #include "ThePEG/Utilities/DescribeClass.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/Cuts/Cuts.h" #include "Herwig/PDT/GenericMassGenerator.h" #include "ThePEG/Handlers/StandardXComb.h" #include "Herwig/Models/StandardModel/StandardModel.h" #include "Herwig/MatrixElement/HardVertex.h" using namespace Herwig; using namespace ThePEG; using namespace ThePEG::Helicity; void MEee2VectorMeson::getDiagrams() const { tcPDPtr em = getParticleData(ParticleID::eminus); tcPDPtr ep = getParticleData(ParticleID::eplus); add(new_ptr((Tree2toNDiagram(2), em, ep, 1, vector_,-1))); } Energy2 MEee2VectorMeson::scale() const { return sHat(); } int MEee2VectorMeson::nDim() const { return 0; } void MEee2VectorMeson::setKinematics() { MEBase::setKinematics(); } bool MEee2VectorMeson::generateKinematics(const double *) { Lorentz5Momentum pout=meMomenta()[0]+meMomenta()[1]; pout.rescaleMass(); meMomenta()[2] = pout; jacobian(1.0); // check passes all the cuts vector out(1,meMomenta()[2]); tcPDVector tout(1,mePartonData()[2]); return lastCuts().passCuts(tout, out, mePartonData()[0], mePartonData()[1]); } unsigned int MEee2VectorMeson::orderInAlphaS() const { return 0; } unsigned int MEee2VectorMeson::orderInAlphaEW() const { return 2; } Selector MEee2VectorMeson::colourGeometries(tcDiagPtr) const { static ColourLines neutral ( " " ); Selector sel;sel.insert(1.,&neutral); return sel; } void MEee2VectorMeson::persistentOutput(PersistentOStream & os) const { os << coupling_ << vector_ << massGen_ << lineShape_; } void MEee2VectorMeson::persistentInput(PersistentIStream & is, int) { is >> coupling_ >> vector_ >> massGen_ >> lineShape_; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigMEee2VectorMeson("Herwig::MEee2VectorMeson", "HwMELepton.so"); void MEee2VectorMeson::Init() { static ClassDocumentation documentation ("The MEee2VectorMeson class implements the production of a vector meson" " in e+e- collisions and is primilarly intended to test the hadron decay package"); static Switch interfaceLineShape ("LineShape", "Option for the vector meson lineshape", &MEee2VectorMeson::lineShape_, false, false, false); static SwitchOption interfaceLineShapeMassGenerator (interfaceLineShape, "MassGenerator", "Use the mass generator if available", true); static SwitchOption interfaceLineShapeBreitWigner (interfaceLineShape, "BreitWigner", "Use a Breit-Wigner with the naive running width", false); static Reference interfaceVectorMeson ("VectorMeson", "The vector meson produced", &MEee2VectorMeson::vector_, false, false, true, false, false); static Parameter interfaceCoupling ("Coupling", "The leptonic coupling of the vector meson", &MEee2VectorMeson::coupling_, 0., 0.0, 100.0, false, false, Interface::limited); } Selector MEee2VectorMeson::diagrams(const DiagramVector &) const { Selector sel;sel.insert(1.0, 0); return sel; } CrossSection MEee2VectorMeson::dSigHatDR() const { InvEnergy2 wgt; Energy M(vector_->mass()),G(vector_->width()); - Energy2 M2(sqr(M)),GM(G*M); + Energy2 M2(sqr(M)); if(massGen_&&lineShape_) wgt = Constants::pi*massGen_->BreitWignerWeight(sqrt(sHat())); else wgt = sHat()*G/M/(sqr(sHat()-M2)+sqr(sHat()*G/M)); return sqr(4.*Constants::pi*SM().alphaEM(sHat()))*me2()*jacobian()*wgt*sqr(hbarc)*sqr(M2/sHat()); } void MEee2VectorMeson::doinit() { MEBase::doinit(); // mass generator tMassGenPtr mass=vector_->massGenerator(); if(mass) { massGen_=dynamic_ptr_cast(mass); } } double MEee2VectorMeson::me2() const { double aver=0.; // get the order right int ielectron(0),ipositron(1); if(mePartonData()[0]->id()!=11) swap(ielectron,ipositron); // the vectors for the wavefunction to be passed to the matrix element vector fin; vector ain; vector vout; for(unsigned int ihel=0;ihel<2;++ihel) { fin.push_back(SpinorWaveFunction(meMomenta()[ielectron], mePartonData()[ielectron],ihel,incoming)); ain.push_back(SpinorBarWaveFunction(meMomenta()[ipositron], mePartonData()[ipositron],ihel,incoming)); } for(unsigned int ihel=0;ihel<3;++ihel) { vout.push_back(VectorWaveFunction(meMomenta()[2],mePartonData()[2],ihel,outgoing)); } ProductionMatrixElement temp=HelicityME(fin,ain,vout,aver); return aver; } // the helicity amplitude matrix element ProductionMatrixElement MEee2VectorMeson::HelicityME(vector fin, vector ain, vector vout, double & aver) const { ProductionMatrixElement output(PDT::Spin1Half,PDT::Spin1Half,PDT::Spin1); Complex product; // sum over helicities to get the matrix element unsigned int inhel1,inhel2,outhel1; aver = 0.; LorentzPolarizationVectorE vec; - Complex ii(0.,1.); Energy ecms = sqrt(sHat()); for(inhel1=0;inhel1<2;++inhel1) { for(inhel2=0;inhel2<2;++inhel2) { vec = fin[inhel1].dimensionedWave().vectorCurrent(ain[inhel2].dimensionedWave()); vec /= coupling_; for(outhel1=0;outhel1<3;++outhel1) { product = vec.dot(vout[outhel1].wave())/ecms; output(inhel1,inhel2,outhel1)=product; aver += norm(product); } } } aver *= 0.25; return output; } void MEee2VectorMeson::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]); if(hard[0]->id()id()) swap(hard[0],hard[1]); vector fin; vector ain; vector vout; SpinorWaveFunction( fin ,hard[0],incoming,false,true); SpinorBarWaveFunction(ain ,hard[1],incoming,false,true); VectorWaveFunction(vout ,hard[2],outgoing,true,false,true); double dummy; ProductionMatrixElement prodme=HelicityME(fin,ain,vout,dummy); // 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<3;++ix) { (hard[ix]->spinInfo())->productionVertex(hardvertex); } } diff --git a/MatrixElement/Lepton/MEee2gZ2ll.h b/MatrixElement/Lepton/MEee2gZ2ll.h --- a/MatrixElement/Lepton/MEee2gZ2ll.h +++ b/MatrixElement/Lepton/MEee2gZ2ll.h @@ -1,366 +1,363 @@ // -*- C++ -*- // // MEee2gZ2ll.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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. // #ifndef HERWIG_MEee2gZ2ll_H #define HERWIG_MEee2gZ2ll_H // // This is the declaration of the MEee2gZ2ll class. // #include "Herwig/MatrixElement/HwMEBase.h" #include "Herwig/Models/StandardModel/StandardModel.h" #include "ThePEG/PDT/EnumParticles.h" #include "Herwig/MatrixElement/ProductionMatrixElement.h" #include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h" #include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h" #include "Herwig/Shower/ShowerAlpha.h" namespace Herwig { using namespace ThePEG; /** * The MEee2gZ2ll class provides the matrix element for * \f$e^+e^-\to\ell^+\ell^-\f$. N.B. for the production of \f$e^+e^-\f$ * only the \f$s\f$-channel Z and photon diagrams are included. * * @see \ref MEee2gZ2llInterfaces "The interfaces" * defined for MEee2gZ2ll. */ class MEee2gZ2ll: public HwMEBase { public: /** * The default constructor. */ MEee2gZ2ll() : allowed_(0), pTmin_(GeV), preFactor_(6.) { massOption(vector(2,1)); } /** * Members for hard corrections to the emission of QCD radiation */ //@{ /** * Has a POWHEG style correction */ virtual POWHEGType hasPOWHEGCorrection() {return FSR;} /** * Has an old fashioned ME correction */ virtual bool hasMECorrection() {return false;} /** * Apply the POWHEG style correction */ virtual RealEmissionProcessPtr generateHardest(RealEmissionProcessPtr, ShowerInteraction); //@} public: /** @name Virtual functions required by the MEBase class. */ //@{ /** * Return the order in \f$\alpha_S\f$ in which this matrix * element is given. */ virtual unsigned int orderInAlphaS() const; /** * Return the order in \f$\alpha_{EW}\f$ in which this matrix * element is given. */ virtual unsigned int orderInAlphaEW() const; /** * The matrix element for the kinematical configuration * previously provided by the last call to setKinematics(), suitably * scaled by sHat() to give a dimension-less number. * @return the matrix element scaled with sHat() to give a * dimensionless number. */ virtual double me2() const; /** * Return the scale associated with the last set phase space point. */ virtual Energy2 scale() const; /** * Add all possible diagrams with the add() function. */ virtual void getDiagrams() const; /** * Get diagram selector. With the information previously supplied with the * setKinematics method, a derived class may optionally * override this method to weight the given diagrams with their * (although certainly not physical) relative probabilities. * @param dv the diagrams to be weighted. * @return a Selector relating the given diagrams to their weights. */ virtual Selector diagrams(const DiagramVector & dv) const; /** * Return a Selector with possible colour geometries for the selected * diagram weighted by their relative probabilities. * @param diag the diagram chosen. * @return the possible colour geometries weighted by their * relative probabilities. */ virtual Selector colourGeometries(tcDiagPtr diag) const; /** * Construct the vertex of spin correlations. */ virtual void constructVertex(tSubProPtr); //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const {return new_ptr(*this);} /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const {return new_ptr(*this);} //@} protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Rebind pointer to other Interfaced objects. Called in the setup phase * after all objects used in an EventGenerator has been cloned so that * the pointers will refer to the cloned objects afterwards. * @param trans a TranslationMap relating the original objects to * their respective clones. * @throws RebindException if no cloned object was found for a given * pointer. */ virtual void rebind(const TranslationMap & trans) ; /** * Return a vector of all pointers to Interfaced objects used in this * object. * @return a vector of pointers. */ virtual IVector getReferences(); //@} protected: /** * Calculate the matrix element for \f$e^+e^-\to \ell^+ \ell^-\f$. * @param partons The incoming and outgoing particles * @param momenta The momenta of the incoming and outgoing particles */ double loME(const vector & partons, const vector & momenta, bool first) const; /** * Member to calculate the matrix element * @param fin Spinors for incoming fermion * @param ain Spinors for incoming antifermion * @param fout Spinors for outgoing fermion * @param aout Spinors for outgong antifermion * @param me Spin summed Matrix element * @param cont The continuum piece of the matrix element * @param BW The Z piece of the matrix element */ ProductionMatrixElement HelicityME(vector & fin, vector & ain, vector & fout, vector & aout, double & me, double & cont, double & BW ) const; /** * The ratio of the matrix element for one additional jet over the * leading order result. In practice * \[\frac{\hat{s}|\overline{\mathcal{M}}|^2_2|D_{\rm emit}|}{4\pi C_F\alpha_S|\overline{\mathcal{M}}|^2_3\left(|D_{\rm emit}|+|D_{\rm spect}\right)}}\] * is returned where \f$\|\overline{\mathcal{M}}|^2\f$ is * the spin and colour summed/averaged matrix element. * @param partons The incoming and outgoing particles * @param momenta The momenta of the incoming and outgoing particles * @param iemitter Whether the quark or antiquark is regardede as the emitter * @param inter The type of interaction */ double meRatio(vector partons, vector momenta, unsigned int iemittor, bool subtract=false) const; /** * Calculate the matrix element for \f$e^-e^-\to q \bar q g$. * @param partons The incoming and outgoing particles * @param momenta The momenta of the incoming and outgoing particles * @param inter The type of interaction */ InvEnergy2 realME(const vector & partons, const vector & momenta) const; /** * Generate the momenta for a hard configuration */ Energy generateHard(RealEmissionProcessPtr tree, vector & emission, unsigned int & iemit, unsigned int & ispect, bool applyVeto); protected: /** * Pointer to the fermion-antifermion Z vertex */ AbstractFFVVertexPtr FFZVertex() const {return FFZVertex_;} /** * Pointer to the fermion-antifermion photon vertex */ AbstractFFVVertexPtr FFPVertex() const {return FFPVertex_;} /** * Pointer to the particle data object for the Z */ PDPtr Z0() const {return Z0_;} /** * Pointer to the particle data object for the photon */ PDPtr gamma() const {return gamma_;} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MEee2gZ2ll & operator=(const MEee2gZ2ll &) = delete; private: /** * Pointers to the vertices */ //@{ /** * Pointer to the fermion-antifermion Z vertex */ AbstractFFVVertexPtr FFZVertex_; /** * Pointer to the fermion-antifermion photon vertex */ AbstractFFVVertexPtr FFPVertex_; //@} /** * Pointer to the particle data object for the Z */ PDPtr Z0_; /** * Pointer to the particle data object for the photon */ PDPtr gamma_; /** * The allowed outgoing */ int allowed_; - /** - * The initial kappa-tilde values for radiation from the quark - */ - double d_kt1_; + /** * Pointer to the EM coupling */ ShowerAlphaPtr alphaQED_; /** * Variables for the POWHEG style corrections */ //@{ /** * The cut off on pt, assuming massless quarks. */ Energy pTmin_; /** * Overestimate for the prefactor */ double preFactor_; /** * ParticleData objects for the partons */ vector partons_; /** * Momenta of the leading-order partons */ vector loMomenta_; //@} }; } #endif /* HERWIG_MEee2gZ2ll_H */ diff --git a/MatrixElement/Matchbox/Phasespace/FFMassiveInvertedTildeKinematics.h b/MatrixElement/Matchbox/Phasespace/FFMassiveInvertedTildeKinematics.h --- a/MatrixElement/Matchbox/Phasespace/FFMassiveInvertedTildeKinematics.h +++ b/MatrixElement/Matchbox/Phasespace/FFMassiveInvertedTildeKinematics.h @@ -1,183 +1,179 @@ // -*- C++ -*- // // FFMassiveInvertedTildeKinematics.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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. // #ifndef HERWIG_FFMassiveInvertedTildeKinematics_H #define HERWIG_FFMassiveInvertedTildeKinematics_H // // This is the declaration of the FFMassiveInvertedTildeKinematics class. // #include "Herwig/MatrixElement/Matchbox/Phasespace/InvertedTildeKinematics.h" namespace Herwig { using namespace ThePEG; /** * \ingroup Matchbox * \author Simon Platzer, Stephen Webster * * \brief FFMassiveInvertedTildeKinematics inverts the final-final tilde * kinematics. * */ class FFMassiveInvertedTildeKinematics: public Herwig::InvertedTildeKinematics { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ FFMassiveInvertedTildeKinematics(); /** * The destructor. */ virtual ~FFMassiveInvertedTildeKinematics(); //@} public: /** * Perform the mapping of the tilde kinematics for the * last selected process and store all dimensionless * variables in the subtractionParameters() vector. * Return false, if the calculation of the real * kinematics was impossible for the selected configuration * and true on success. */ virtual bool doMap(const double *); /** * Return the pt associated to the last generated splitting. */ virtual Energy lastPt() const; /** * Return the momentum fraction associated to the last splitting. */ virtual double lastZ() const; /** * Return the upper bound on pt */ virtual Energy ptMax() const; /** * Given a pt, return the boundaries on z * Note that allowing parton masses these bounds may be too loose */ virtual pair zBounds(Energy pt, Energy hardPt = ZERO) const; /** * For generated pt and z, check if this point is * kinematically allowed */ /*virtual*/ bool ptzAllowed(pair ptz, vector* values ) const; /** * Generate pt and z */ virtual pair generatePtZ(double& jac, const double * r, vector* values) const; public: /** * Triangular / Kallen function */ template inline T rootOfKallen (T a, T b, T c) const { return sqrt( a*a + b*b + c*c - 2.*( a*b+a*c+b*c ) ); } // TODO: remove in both /** * stolen from FFMassiveKinematics.h * Perform a rotation on both momenta such that the first one will * point along the (positive) z axis. Rotate back to the original * reference frame by applying rotateUz(returnedVector) to each momentum. */ ThreeVector rotateToZ (Lorentz5Momentum& pTarget, Lorentz5Momentum& p1) { ThreeVector oldAxis = pTarget.vect().unit(); double ct = oldAxis.z(); double st = sqrt( 1.-sqr(ct) ); // cos,sin(theta) double cp = oldAxis.x()/st; double sp = oldAxis.y()/st; // cos,sin(phi) pTarget.setZ( pTarget.vect().mag() ); pTarget.setX( 0.*GeV ); pTarget.setY( 0.*GeV ); Lorentz5Momentum p1old = p1; p1.setX( sp*p1old.x() - cp*p1old.y() ); p1.setY( ct*cp*p1old.x() + ct*sp*p1old.y() - st*p1old.z() ); p1.setZ( st*cp*p1old.x() + st*sp*p1old.y() + ct*p1old.z() ); return oldAxis; } public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FFMassiveInvertedTildeKinematics & operator=(const FFMassiveInvertedTildeKinematics &) = delete; - /** - * Option to use the full jacobian, including the z->zprime jacobian. - **/ - bool theFullJacobian; }; } #endif /* HERWIG_FFMassiveInvertedTildeKinematics_H */ diff --git a/MatrixElement/Matchbox/Utility/DensityOperator.cc b/MatrixElement/Matchbox/Utility/DensityOperator.cc --- a/MatrixElement/Matchbox/Utility/DensityOperator.cc +++ b/MatrixElement/Matchbox/Utility/DensityOperator.cc @@ -1,479 +1,479 @@ // -*- C++ -*- // // DensityOperator.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2007 The Herwig Collaboration // // Herwig is licenced under version 2 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 DensityOperator class. // #include "DensityOperator.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "Herwig/MatrixElement/Matchbox/Utility/MatchboxXCombData.h" #include "Herwig/MatrixElement/Matchbox/Base/MatchboxMEBase.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; DensityOperator::DensityOperator() : Nc(3.0), TR(0.5) { } DensityOperator::~DensityOperator() {} void DensityOperator::clear() { theCorrelatorMap.clear(); } // Prepare density operator if not done before void DensityOperator::prepare(const cPDVector& mePartonData) { // Take parton data and create key of type 33bar888 to use as key for basis vector mePartonDataColoured = theColourBasis->normalOrderMap(mePartonData); if( theDensityOperatorMap.count( mePartonDataColoured ) == 0 ){ // Get basis dimension size_t dim = theColourBasis->prepare( mePartonData, false ); // Allocate space for density matrix theDensityOperatorMap.insert(make_pair(mePartonDataColoured,matrix (dim,dim))); } } // Fill the density matrix for the first time void DensityOperator::fill(const Ptr::ptr MBXCombPtr, const cPDVector& partons, const vector& momenta){ // Map from helicity structure to amplitude vector in the color basis const map,CVector>& amplitudeMap = MBXCombPtr->lastAmplitudes(); const cPDVector& mePartonData = MBXCombPtr->mePartonData(); // Get the dimension of the basis for the indexChange method size_t dim = theColourBasis->prepare(mePartonData,false); // Normal order partons according to ColourBasis const vector mePartonDataColoured = theColourBasis->normalOrderMap(mePartonData); // Get the colour basis to colour basis map for this hard subprocess map >::iterator cb2cbit = theColourBasisToColourBasisMap.find(mePartonData); // Fill the map with this hard subprocess if it doesn't have it yet if ( cb2cbit == theColourBasisToColourBasisMap.end() ) { // Get the index map for the partons as they are ordered in the MatchboxXComb // object const map& mbIndexMap = theColourBasis->indexMap().at(mePartonData); // Get the index map for the partons as they are ordered // in the shower. // Use prepare, as it might not have been done for this order of the partons theColourBasis->prepare(partons,false); const map& showerIndexMap = theColourBasis->indexMap().at(partons); // ensure the maps are of the same size assert( mbIndexMap.size() == showerIndexMap.size() ); // Loop over both sets of partons to determine how the order between them // differs, then translate the index to the colour basis and put the // key-value pair into the map map cb2cbMap; // Get the momenta for comparison const vector& meMomenta = MBXCombPtr->matchboxME()->lastMEMomenta(); // Make sure there's the same number of momenta in both vectors assert( momenta.size() == meMomenta.size() ); bool done; // Boost the momenta to the same frame const vector momentaCM = boostToRestFrame(momenta); for ( size_t i = 0; i < momentaCM.size(); i++ ) { // The cb2cb map is intended to translate how the indices // are different in the colour basis due to the different // orderings of the partons, so it should only bother // with coloured particles. if ( partons[i]->coloured() ) { done = false; for ( size_t j = 0; j < meMomenta.size(); j++ ) { if ( !done ) { if ( compareMomentum(momentaCM[i],meMomenta[j]) ) { cb2cbMap[mbIndexMap.at(i)] = showerIndexMap.at(j); done = true; } } } } } // Make sure all momenta have been identified assert( cb2cbMap.size() == mePartonDataColoured.size() ); // Add the map to the cache theColourBasisToColourBasisMap[mePartonData] = cb2cbMap; // Get the iterator cb2cbit = theColourBasisToColourBasisMap.find(mePartonData); } // With the cb2cb index map we can create the basis vector index map const map vectorMap = theColourBasis->indexChange(mePartonDataColoured, dim,cb2cbit->second); // Prepare density operator (allocate) for set of particles prepare(mePartonData); // Check that density operator (place holder for) exist in density operator map map,matrix >::iterator dOit = theDensityOperatorMap.find(mePartonDataColoured); assert(dOit != theDensityOperatorMap.end()); // Initialize the density operator matrix& densOp = dOit->second; for(unsigned int i = 0; i < (amplitudeMap.begin()->second).size(); i++){ for(unsigned int j = 0; j < (amplitudeMap.begin()->second).size(); j++){ densOp (i,j) = 0; } } // Fill the density operator, ok to sum over helicities since the density operator // exist at the probability level CVector amplitude; for ( map,CVector>::const_iterator itHel = amplitudeMap.begin(); itHel != amplitudeMap.end(); itHel++ ) { amplitude = itHel->second; for ( unsigned int i = 0; i < amplitude.size(); i++ ) { for ( unsigned int j = 0; j < amplitude.size(); j++ ) { // vectorMap is used such that densOp is filled according to the // basis order defined by the input cPDVector partons. densOp (vectorMap.at(i),vectorMap.at(j)) += amplitude(i)*std::conj(amplitude(j)); } } } // Colour conservation check colourConservation(mePartonData); } // Update density matrix after emitting or splitting a gluon // The emissionsMap argument contains the relation of the indices in the smaller (before) // and larger basis (after). the first 3-tuple contains the indices // (emitter before, emitter after, emitted parton) // The map contains the old and new indices of all other partons (not involved) void DensityOperator::evolve(const map,Complex>& Vijk, const cPDVector& before, const cPDVector& after, const map,map >& emissionsMap, const bool splitAGluon, const bool initialGluonSplitting) { size_t dimBefore = theColourBasis->prepare( before, false ); size_t dimAfter = theColourBasis->prepare( after, false ); vector beforeColoured = theColourBasis->normalOrderMap(before); vector afterColoured = theColourBasis->normalOrderMap(after); const map,matrix >::iterator dOit = theDensityOperatorMap.find(beforeColoured); assert(dOit != theDensityOperatorMap.end()); const matrix& densOpBefore = dOit->second; prepare(after); matrix& densOpAfter = theDensityOperatorMap[afterColoured]; for(size_t i = 0; i < densOpAfter.size1(); i++){ for(size_t j = 0; j < densOpAfter.size2(); j++){ densOpAfter(i,j) = 0; } } compressed_matrix Tij; matrix TijMn (dimAfter,dimBefore); compressed_matrix Tk; matrix TijMnTkdagger (dimAfter,dimAfter); Complex V; // Compensate for sign from updated density matrix // TODO Check signs again double sign = -1.0; if ( splitAGluon ) sign = 1.0; // Loop over emitter legs ij and recoil legs k and add the contribution, // for Vijk is assumed to contain the factor 4*pi*\alpha_s/pi.pj typedef map,map > dictMap; int ij,k; // Loop over emitters for(dictMap::const_iterator ijit = emissionsMap.begin(); ijit != emissionsMap.end(); ijit++) { // get first element in 3-tuple, i.e., emitter before ij = std::get<0>(ijit->first); assert(before[ij]->coloured()); // Get rectangular matrices T_{ij} or S_{ij} taking us from the // smaller to the larger basis depending on // the involved particles before and after, the emitter index before ij, // the emitter after and the emitted parton index int i=std::get<1>(ijit->first); // emitter after int j=std::get<2>(ijit->first);// emitted parton Tij = theColourBasis->charge(before,after, ij,i,j,ijit->second).first; TijMn = prodSparseDense(Tij,densOpBefore); // Loop over spectators for(dictMap::const_iterator kit = emissionsMap.begin(); kit != emissionsMap.end(); kit++) { k = std::get<0>(kit->first); assert(before[k]->coloured()); // Standard case of gluon radiation if ( ijit != kit || splitAGluon || initialGluonSplitting ) { int k_after=std::get<1>(kit->first); // For color structure k now has role of emitter int k_emission= std::get<2>(kit->first); // Emitted parton index Tk = theColourBasis->charge(before,after, k, k_after, k_emission, kit->second).first; TijMnTkdagger = prodDenseSparse(TijMn,Tk); // sign == -1.0 if it isn't a gluon splitting into a qqbar pair V = sign*(1.0/colourNorm(before[ij]))* Vijk.at(make_pair(ij,k)); densOpAfter += V*TijMnTkdagger; } } } // Check that the density operator does not vanish assert( theColourBasis->me2(after,densOpAfter) != 0.0 ); colourConservation(after); } // The 3-tuple contains (emitter index, spectator index, emission pid) double DensityOperator::colourMatrixElementCorrection(const std::tuple& ikemission, const cPDVector& particles) { const int i = std::get<0>(ikemission); const int k = std::get<1>(ikemission); - const long emissionID = std::get<2>(ikemission); + //const long emissionID = std::get<2>(ikemission); // Get the density operator // normal order particles as in ColourBasis vector particlesColoured = theColourBasis->normalOrderMap(particles); // ... and find corresponding density operator const map,matrix >::iterator particlesit = theDensityOperatorMap.find(particlesColoured); assert(particlesit != theDensityOperatorMap.end()); const matrix& densOp = particlesit->second; double Ti2 = colourNorm(particles[i]); // Emitter-spectator pair const pair ik = make_pair(i,k); // Create key for color matrix element correction map pair,pair > particlesAndLegs = make_pair(particlesColoured,ik); // Result double res = 0; // Check if it has already been calculated // TODO: move this check earlier (we only need particlesColoured to check if it has been // calculated). // Check for color matrix element associated with key, and calculate if not done const map,pair >,double >::const_iterator corrit = theCorrelatorMap.find(particlesAndLegs); if ( corrit == theCorrelatorMap.end() ) { double corrME2 = theColourBasis->colourCorrelatedME2(ik,particles,densOp); double me2 = theColourBasis->me2(particles,densOp); res = -(1/Ti2)*corrME2/me2; if ( particles[i]->id() == ParticleID::g ) res *= 2.; theCorrelatorMap.insert(make_pair(particlesAndLegs,res)); } else { res = corrit->second; } return res; } double DensityOperator::colourNorm(const cPDPtr particle) { if ( particle->id() == ParticleID::g ) { return Nc; //is 3.0 for Nc = 3, TR = 1/2 } else if ( particle->iColour() == PDT::Colour3 || particle->iColour() == PDT::Colour3bar ) { return TR*(Nc*Nc-1.)/Nc; // is 4.0/3.0 for Nc = 3, TR = 1/2 } else { throw Exception() << "Colour matrix element corrections only work " << "on quark and gluon legs. " << Exception::runerror; } } void DensityOperator::colourConservation(const cPDVector& particles) { // To contain (emitter, spectator, emission pid) std::tuple ikemission; // Normal order particles as defined in ColourBasis const vector particlesColoured = theColourBasis->normalOrderMap(particles); vector sum(particlesColoured.size(),0.0); size_t iterm = 0; // To compensate for the CMEC having a 1/(1+\delta(i is gluon)) factor // in the splitting kernel double gluonFactor = 1.0; // Loop over "emitters" to check color conservation for for ( size_t i = 0; i < particles.size(); i++ ) { if ( particles[i]->coloured() ) { for ( size_t k = 0; k < particles.size(); k++ ) { if ( particles[k]->coloured() && i != k ) { ikemission = std::make_tuple(i,k,ParticleID::g); if ( particles[i]->id() != ParticleID::g ) { gluonFactor = 1.0; } else { gluonFactor = 1./2.; } sum[iterm] += gluonFactor*colourMatrixElementCorrection(ikemission,particles); } } iterm++; } } for ( size_t i = 0; i < sum.size(); i++ ) assert( std::abs(sum[i]-1.0) < pow(10.0,-10.0)); } matrix DensityOperator::prodSparseDense(const compressed_matrix& Tij, const matrix& Mn){ // Dimension before emission size_t dimBefore = Tij.size2(); // Dimension after emission size_t dimAfter = Tij.size1(); //Check matrix dimensions assert( dimBefore == Mn.size1() ); // Allocate memory for the matrix matrix TijMn (dimAfter,dimBefore,0); // Use iterators for the compressed matrix to iterate only over the non-zero // elements. size_t ii; size_t jj; for ( compressed_matrix::const_iterator1 it1 = Tij.begin1(); it1 != Tij.end1(); it1++ ) { for ( compressed_matrix::const_iterator2 it2 = it1.begin(); it2 != it1.end(); it2++ ) { ii = it2.index1(); jj = it2.index2(); for ( size_t kk = 0; kk < dimBefore; kk++ ) { // *it2 is Tij(ii,jj) TijMn(ii,kk) += (*it2)*Mn(jj,kk); } } } return TijMn; } matrix DensityOperator::prodDenseSparse(const matrix& TijMn, const compressed_matrix& Tk){ // The compressed matrix comes from the charge method, do not transpose yet // Dimension after emission size_t dimAfter = Tk.size1();//Since this method returns TijMn*Tk^\dagger //Check matrix dimensions assert( TijMn.size2() == Tk.size2() ); // Allocate memory for the matrix matrix TijMnTkdagger (dimAfter,dimAfter,0); size_t jj; size_t kk; for ( compressed_matrix::const_iterator1 it1 = Tk.begin1(); it1 != Tk.end1(); it1++ ) { for ( compressed_matrix::const_iterator2 it2 = it1.begin(); it2 != it1.end(); it2++ ) { jj = it2.index2();//transposing Tk jj is index2(), not index1() kk = it2.index1();//transposing Tk for ( size_t ii = 0; ii < dimAfter; ii++ ) { // *it2 is Tk(kk,jj) = trans(Tk)(jj,kk) TijMnTkdagger(ii,kk) += TijMn(ii,jj)*(*it2); } } } return TijMnTkdagger; } vector DensityOperator::boostToRestFrame(const vector& momenta) { // We need 2 initial particles assert(momenta.size() >= 2); // The boosted vectors vector vboosted = momenta; // The boost should be to the rest frame of the initial particles Boost b = (momenta[0] + momenta[1]).findBoostToCM(); // Boost all of the vectors for ( size_t i = 0; i < momenta.size(); i++ ) { vboosted[i].boost(b); } return vboosted; } bool DensityOperator::compareMomentum(const Lorentz5Momentum& p, const Lorentz5Momentum& q) { bool equal = true; // Compares two momentum vectors p and q, if they are close enough (defined by the // double eps below) it returns true. This is sufficient to distinguish particles // in the matrix element as we are not interested in the matrix element for extremely // collinear radiation (better described by the parton shower). // Create the difference of the two vectors const Lorentz5Momentum l = p - q; // A relevant size that is guaranteed to be larger than 0 const Energy2 e2 = p.t()*p.t(); // Size of the difference that would be considered equal const double eps = pow(10.,-15.); if ( l.x()*l.x()/e2 > eps ) equal = false; if ( l.y()*l.y()/e2 > eps ) equal = false; if ( l.z()*l.z()/e2 > eps ) equal = false; if ( l.t()*l.t()/e2 > eps ) equal = false; return equal; } IBPtr DensityOperator::clone() const { return new_ptr(*this); } IBPtr DensityOperator::fullclone() const { return new_ptr(*this); } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void DensityOperator::persistentOutput(PersistentOStream &) const { // *** ATTENTION *** os << ; // Add all member variable which should be written persistently here. } void DensityOperator::persistentInput(PersistentIStream &, int) { // *** ATTENTION *** is >> ; // Add all member variable which should be read persistently here. } // *** 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 describeHerwigDensityOperator("Herwig::DensityOperator", "DensityOperator.so"); void DensityOperator::Init() { static ClassDocumentation documentation ("There is no documentation for the DensityOperator class"); } diff --git a/MatrixElement/Matchbox/Utility/Tree2toNGenerator.cc b/MatrixElement/Matchbox/Utility/Tree2toNGenerator.cc --- a/MatrixElement/Matchbox/Utility/Tree2toNGenerator.cc +++ b/MatrixElement/Matchbox/Utility/Tree2toNGenerator.cc @@ -1,490 +1,490 @@ // -*- C++ -*- // // Tree2toNGenerator.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 Tree2toNGenerator class. // #include "Tree2toNGenerator.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/Command.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Repository/UseRandom.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Utilities/StringUtils.h" using namespace Herwig; Tree2toNGenerator::Tree2toNGenerator() : maxOrderGs(0), maxOrderGem(0), prepared(false) {} Tree2toNGenerator::~Tree2toNGenerator() {} IBPtr Tree2toNGenerator::clone() const { return new_ptr(*this); } IBPtr Tree2toNGenerator::fullclone() const { return new_ptr(*this); } vector::ptr> Tree2toNGenerator:: generate(const PDVector& legs, unsigned int orderInGs, unsigned int orderInGem) { vector::ptr> res; list > prog = clusterAll(legs,orderInGs,orderInGem); int count = 1; for ( auto & d : prog ) { assert(d.size() == 1); Tree2toNDiagram diag = d.front().generate(count); if ( !spaceLikeAllowed.empty() ) { map counts; for ( int k = 1; k < diag.nSpace()-1; ++k ) counts[diag.allPartons()[k]] += 1; for ( auto & m : spaceLikeAllowed ) { m.reset(); for ( auto const & c : counts ) m.add(c.first,c.second); } bool failed = false; for ( auto const & m : spaceLikeAllowed) { if ( !m.check() ) { failed = true; break; } } if ( failed ) continue; } if ( !timeLikeAllowed.empty() ) { map counts; int all = diag.allPartons().size(); for ( int k = diag.nSpace(); k < all; ++k ) { if ( diag.children(k).first < 0 ) continue; counts[diag.allPartons()[k]] += 1; } for ( auto & m : timeLikeAllowed ) { m.reset(); for ( auto const & c : counts ) m.add(c.first,c.second); } bool failed = false; for ( auto const & m : timeLikeAllowed ) { if ( !m.check() ) { failed = true; break; } } if ( failed ) continue; } bool internalVeto = false; set external; int nex = diag.partons().size(); for ( int i = 0; i < nex; ++i ) { external.insert(diag.diagramId(i)); } int n = diag.allPartons().size(); for ( int i = 0; i < n; ++i ) { if ( external.find(i) != external.end() ) continue; if ( find(excludeInternal().begin(), excludeInternal().end(), diag.allPartons()[i]) != excludeInternal().end() ) { internalVeto = true; break; } } if ( internalVeto ) continue; bool gotit = false; for ( auto const & d : res) { map checkPermutation; if ( diag.isSame(d,checkPermutation) ) { gotit = true; for ( auto const & p : checkPermutation ) if ( p.first != p.second ) gotit = false; if ( gotit ) break; } } if ( !gotit ) { res.push_back(new_ptr(diag)); ++count; } } return res; } list > Tree2toNGenerator:: cluster(const vector& children, unsigned int orderInGs, unsigned int orderInGem) const { list > res; bool externalCluster = children[1].externalId != -1; if ( children.size() == 3 ) { for ( auto const & v : theVertices ) { if ( v->getNpoint() != 3 ) continue; if ( find(theExcludeVertices.begin(), theExcludeVertices.end(), v) != theExcludeVertices.end() ) continue; bool noMatch = - v->orderInGs() != orderInGs || - v->orderInGem() != orderInGem || + v->orderInGs() != int(orderInGs) || + v->orderInGem() != int(orderInGem) || !v->isIncoming(children[0].parent); long idij = children[0].parent->id(); long idi = children[2].parent->id(); long idj = children[1].parent->id(); if ( externalCluster && children[1].parent->CC() ) idj = -idj; if ( children[0].parent->CC() ) idij = -idij; if ( !externalCluster ) noMatch |= !v->isOutgoing(children[1].parent) || !v->isOutgoing(children[2].parent); else noMatch |= !v->isIncoming(children[1].parent) || !v->isOutgoing(children[2].parent); noMatch |= !( v->allowed(idij,idi,idj) || v->allowed(idj,idij,idi) || v->allowed(idi,idj,idij) || v->allowed(idij,idj,idi) || v->allowed(idi,idij,idj) || v->allowed(idj,idi,idij) ); if ( noMatch ) continue; Vertex last; last.spacelike = true; last.parent = children[0].parent; last.externalId = 0; last.children.push_back(children[1]); last.children.push_back(children[2]); res.push_back(vector(1,last)); // only one possible break; } return res; } // spacelike clusterings (cluster on second one) for ( size_t i = 2; i < children.size(); ++i ) { for ( auto const & v : theVertices ) { if ( v->getNpoint() != 3 ) continue; if ( find(theExcludeVertices.begin(), theExcludeVertices.end(), v) != theExcludeVertices.end() ) continue; bool noMatch = false; noMatch |= - v->orderInGs() != orderInGs || - v->orderInGem() != orderInGem; + v->orderInGs() != int(orderInGs) || + v->orderInGem() != int(orderInGem); if ( !externalCluster ) noMatch |= !v->isOutgoing(children[1].parent) || !v->isOutgoing(children[i].parent); else noMatch |= !v->isIncoming(children[1].parent) || !v->isOutgoing(children[i].parent); if ( noMatch ) continue; long idi = children[i].parent->id(); long idj = children[1].parent->id(); if ( externalCluster && children[1].parent->CC() ) idj = -idj; for ( set::const_iterator pij = v->outgoing().begin(); pij != v->outgoing().end() ; ++pij ) { long idij = (**pij).id(); if ( v->allowed(idij,idi,idj) || v->allowed(idj,idij,idi) || v->allowed(idi,idj,idij) || v->allowed(idij,idj,idi) || v->allowed(idi,idij,idj) || v->allowed(idj,idi,idij) ) { PDPtr dij = (**pij).CC() ? (**pij).CC() : *pij; vector cled; for ( size_t k = 0; k < children.size(); ++k ) { if ( k != 1 && k != i ) cled.push_back(children[k]); if ( k == 1 ) { Vertex merge; merge.children.push_back(children[1]); merge.children.push_back(children[i]); merge.parent = dij; merge.spacelike = true; cled.push_back(merge); } if ( k == i ) continue; } res.push_back(cled); } } } } // timelike clusterings for ( size_t i = 2; i < children.size(); ++i ) { for ( size_t j = i+1; j < children.size(); ++j ) { for ( auto const & v : theVertices ) { if ( v->getNpoint() != 3 ) continue; if ( find(theExcludeVertices.begin(), theExcludeVertices.end(), v) != theExcludeVertices.end() ) continue; - if ( v->orderInGs() != orderInGs || - v->orderInGem() != orderInGem || + if ( v->orderInGs() != int(orderInGs) || + v->orderInGem() != int(orderInGem) || !v->isOutgoing(children[i].parent) || !v->isOutgoing(children[j].parent) ) continue; long idi = children[i].parent->id(); long idj = children[j].parent->id(); for ( set::const_iterator pij = v->outgoing().begin(); pij != v->outgoing().end() ; ++pij ) { long idij = (**pij).id(); if ( v->allowed(idij,idi,idj) || v->allowed(idj,idij,idi) || v->allowed(idi,idj,idij) || v->allowed(idij,idj,idi) || v->allowed(idi,idij,idj) || v->allowed(idj,idi,idij) ) { PDPtr dij = (**pij).CC() ? (**pij).CC() : *pij; vector cled; for ( size_t k = 0; k < children.size(); ++k ) { if ( k != i && k != j ) cled.push_back(children[k]); if ( k == i ) { Vertex merge; merge.children.push_back(children[i]); merge.children.push_back(children[j]); merge.parent = dij; merge.spacelike = false; cled.push_back(merge); } if ( k == j ) continue; } res.push_back(cled); } } } } } return res; } list > Tree2toNGenerator:: clusterAll(const list >& current, unsigned int orderInGs, unsigned int orderInGem) const { list > res; for ( list >::const_iterator c = current.begin(); c != current.end(); ++c ) { if ( c->size() == 1 ) { if ( orderInGs == 0 && orderInGem == 0 ) res.push_back(*c); continue; } for ( unsigned int gs = 0; gs <= maxOrderGs; ++gs ) for ( unsigned int gem = 0; gem <= maxOrderGem; ++gem ) { if ( gs == 0 && gem == 0 ) continue; if ( gs > orderInGs || gem > orderInGem ) continue; list > next = cluster(*c,gs,gem); if ( next.empty() ) continue; list > cled = clusterAll(next,orderInGs-gs,orderInGem-gem); copy(cled.begin(),cled.end(),back_inserter(res)); } } return res; } list > Tree2toNGenerator:: clusterAll(const PDVector& external, unsigned int orderInGs, unsigned int orderInGem) { if ( !prepared ) { for ( auto & v : theVertices ) { if ( find(theExcludeVertices.begin(), theExcludeVertices.end(), v) != theExcludeVertices.end() ) continue; v->init(); maxOrderGs = max(maxOrderGs,v->orderInGs()); maxOrderGem = max(maxOrderGem,v->orderInGem()); } for ( auto & m : spaceLikeAllowed) m.rebind(this); for ( auto & m : timeLikeAllowed ) m.rebind(this); prepared = true; } vector legs; for ( unsigned int k = 0; k < external.size(); ++k ) { Vertex v; v.parent = external[k]; v.externalId = k; v.spacelike = k < 2; legs.push_back(v); } list > firstlegs; firstlegs.push_back(legs); return clusterAll(firstlegs,orderInGs,orderInGem); } string Tree2toNGenerator::doSpaceLikeRange(string range) { if ( theRestrictLines.empty() ) return "No particle data specified to restrict internal lines."; vector bounds = StringUtils::split(range); if ( bounds.empty() || bounds.size() > 2 ) return "Need to specify a minimum, or a minimum and maximum number of internal lines."; pair irange(0,-1); istringstream in1(bounds[0]); in1 >> irange.first; if ( bounds.size() == 2 ) { istringstream in2(bounds[1]); in2 >> irange.second; } else { irange.second = irange.first; } if ( irange.second >= 0 && irange.first > irange.second ) return "invalid range specified"; spaceLikeAllowed.push_back(LineMatcher(theRestrictLines,irange)); return ""; } string Tree2toNGenerator::doTimeLikeRange(string range) { if ( theRestrictLines.empty() ) return "No particle data specified to restrict internal lines."; vector bounds = StringUtils::split(range); if ( bounds.empty() || bounds.size() > 2 ) return "Need to specify a minimum, or a minimum and maximum number of internal lines."; pair irange(0,-1); istringstream in1(bounds[0]); in1 >> irange.first; if ( bounds.size() == 2 ) { istringstream in2(bounds[1]); in2 >> irange.second; } else { irange.second = irange.first; } if ( irange.second >= 0 && irange.first > irange.second ) return "invalid range specified"; timeLikeAllowed.push_back(LineMatcher(theRestrictLines,irange)); return ""; } string Tree2toNGenerator::doClearRestrictLines(string) { theRestrictLines.clear(); return ""; } // If needed, insert default implementations of virtual function defined // in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs). void Tree2toNGenerator::persistentOutput(PersistentOStream & os) const { os << theVertices << theExcludeInternal << maxOrderGs << maxOrderGem << prepared << theExcludeVertices << spaceLikeAllowed << timeLikeAllowed; } void Tree2toNGenerator::persistentInput(PersistentIStream & is, int) { is >> theVertices >> theExcludeInternal >> maxOrderGs >> maxOrderGem >> prepared >> theExcludeVertices >> spaceLikeAllowed >> timeLikeAllowed; } // *** 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 describeHerwigTree2toNGenerator("Herwig::Tree2toNGenerator", "Herwig.so"); void Tree2toNGenerator::Init() { static ClassDocumentation documentation ("Generate Tree2toNDiagrams for a given process."); static RefVector interfaceVertices ("Vertices", "All vertices to consider.", &Tree2toNGenerator::theVertices, -1, false, false, true, false, false); static RefVector interfaceExcludeVertices ("ExcludeVertices", "The vertices to exclude.", &Tree2toNGenerator::theExcludeVertices, -1, false, false, true, false, false); static RefVector interfaceExcludeInternal ("ExcludeInternal", "Particles to be exluded from becoming internal lines.", &Tree2toNGenerator::theExcludeInternal, -1, false, false, true, false, false); static RefVector interfaceRestrictLines ("RestrictLines", "Particles to be exluded from becoming internal lines.", &Tree2toNGenerator::theRestrictLines, -1, false, false, true, false, false); static Command interfaceSpaceLikeRange ("SpaceLikeRange", "Limit the number of spacelike occurences of the specified particle.", &Tree2toNGenerator::doSpaceLikeRange, false); static Command interfaceTimeLikeRange ("TimeLikeRange", "Limit the number of timelike occurences of the specified particle.", &Tree2toNGenerator::doTimeLikeRange, false); static Command interfaceClearRestrictLines ("ClearRestrictLines", "Clear the container of lines to be considered for restrictions.", &Tree2toNGenerator::doClearRestrictLines, false); } diff --git a/MatrixElement/Powheg/MEPP2WHPowheg.cc b/MatrixElement/Powheg/MEPP2WHPowheg.cc --- a/MatrixElement/Powheg/MEPP2WHPowheg.cc +++ b/MatrixElement/Powheg/MEPP2WHPowheg.cc @@ -1,392 +1,392 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the MEPP2WHPowheg class. // #include "MEPP2WHPowheg.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/PDT/DecayMode.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Handlers/StandardXComb.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "ThePEG/Repository/EventGenerator.h" using namespace Herwig; MEPP2WHPowheg::MEPP2WHPowheg() : _gluon(), TR_(0.5), CF_(4./3.), _contrib(1) ,_nlo_alphaS_opt(0), _fixed_alphaS(0.115895), - _a(0.5) ,_p(0.7) , _eps(1.0e-8), _scaleopt(1), + _a(0.5) ,_p(0.7) , _scaleopt(1), _fixedScale(100.*GeV), _scaleFact(1.) {} // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigMEPP2WHPowheg("Herwig::MEPP2WHPowheg", "HwMEHadron.so HwPowhegMEHadron.so"); void MEPP2WHPowheg::persistentOutput(PersistentOStream & os) const { os << _contrib << _nlo_alphaS_opt << _fixed_alphaS << _a << _p << _gluon << _scaleopt << ounit(_fixedScale,GeV) << _scaleFact; } void MEPP2WHPowheg::persistentInput(PersistentIStream & is, int) { is >> _contrib >> _nlo_alphaS_opt >> _fixed_alphaS >> _a >> _p >> _gluon >> _scaleopt >> iunit(_fixedScale,GeV) >> _scaleFact; } void MEPP2WHPowheg::Init() { static ClassDocumentation documentation ("The MEPP2WHPowheg class implements the matrix element for the Bjorken" " process q qbar -> WH", "The PP$\\to$W Higgs POWHEG matrix element is described in \\cite{Hamilton:2009za}.", "%\\cite{Hamilton:2009za}\n" "\\bibitem{Hamilton:2009za}\n" " K.~Hamilton, P.~Richardson and J.~Tully,\n" " ``A Positive-Weight Next-to-Leading Order Monte Carlo Simulation for Higgs\n" " Boson Production,''\n" " JHEP {\\bf 0904} (2009) 116\n" " [arXiv:0903.4345 [hep-ph]].\n" " %%CITATION = JHEPA,0904,116;%%\n" ); static Switch interfaceContribution ("Contribution", "Which contributions to the cross section to include", &MEPP2WHPowheg::_contrib, 1, false, false); static SwitchOption interfaceContributionLeadingOrder (interfaceContribution, "LeadingOrder", "Just generate the leading order cross section", 0); static SwitchOption interfaceContributionPositiveNLO (interfaceContribution, "PositiveNLO", "Generate the positive contribution to the full NLO cross section", 1); static SwitchOption interfaceContributionNegativeNLO (interfaceContribution, "NegativeNLO", "Generate the negative contribution to the full NLO cross section", 2); static Switch interfaceNLOalphaSopt ("NLOalphaSopt", "Whether to use a fixed or a running QCD coupling for the NLO weight", &MEPP2WHPowheg::_nlo_alphaS_opt, 0, false, false); static SwitchOption interfaceNLOalphaSoptRunningAlphaS (interfaceNLOalphaSopt, "RunningAlphaS", "Use the usual running QCD coupling evaluated at scale scale()", 0); static SwitchOption interfaceNLOalphaSoptFixedAlphaS (interfaceNLOalphaSopt, "FixedAlphaS", "Use a constant QCD coupling for comparison/debugging purposes", 1); static Parameter interfaceFixedNLOalphaS ("FixedNLOalphaS", "The value of alphaS to use for the nlo weight if _nlo_alphaS_opt=1", &MEPP2WHPowheg::_fixed_alphaS, 0.115895, 0., 1.0, false, false, Interface::limited); static Parameter interfaceCorrectionCoefficient ("CorrectionCoefficient", "The magnitude of the correction term to reduce the negative contribution", &MEPP2WHPowheg::_a, 0.5, -10., 10.0, false, false, Interface::limited); static Parameter interfaceCorrectionPower ("CorrectionPower", "The power of the correction term to reduce the negative contribution", &MEPP2WHPowheg::_p, 0.7, 0.0, 1.0, false, false, Interface::limited); static Switch interfaceFactorizationScaleOption ("FactorizationScaleOption", "Option for the scale to be used", &MEPP2WHPowheg::_scaleopt, 1, false, false); static SwitchOption interfaceScaleOptionFixed (interfaceFactorizationScaleOption, "Fixed", "Use a fixed scale", 0); static SwitchOption interfaceScaleOptionsHat (interfaceFactorizationScaleOption, "Dynamic", "Use the mass of the vector boson-Higgs boson system", 1); static Parameter interfaceFactorizationScaleValue ("FactorizationScaleValue", "The fixed scale to use if required", &MEPP2WHPowheg::_fixedScale, GeV, 100.0*GeV, 10.0*GeV, 1000.0*GeV, false, false, Interface::limited); static Parameter interfaceScaleFactor ("ScaleFactor", "The factor used before sHat if using a running scale", &MEPP2WHPowheg::_scaleFact, 1.0, 0.0, 10.0, false, false, Interface::limited); } void MEPP2WHPowheg::doinit() { // gluon ParticleData object _gluon = getParticleData(ParticleID::g); MEPP2WH::doinit(); } Energy2 MEPP2WHPowheg::scale() const { return _scaleopt == 0 ? sqr(_fixedScale) : _scaleFact*sHat(); } int MEPP2WHPowheg::nDim() const { return 7; } bool MEPP2WHPowheg::generateKinematics(const double * r) { _xt=*(r+5); _v =*(r+6); return MEPP2WH::generateKinematics(r); } CrossSection MEPP2WHPowheg::dSigHatDR() const { // Get Born momentum fractions xbar_a and xbar_b: _xb_a = lastX1(); _xb_b = lastX2(); return MEPP2WH::dSigHatDR()*NLOweight(); } double MEPP2WHPowheg::NLOweight() const { // If only leading order is required return 1: if(_contrib==0) return 1.; useMe(); // Get particle data for QCD particles: _parton_a=mePartonData()[0]; _parton_b=mePartonData()[1]; // get BeamParticleData objects for PDF's _hadron_A=dynamic_ptr_cast::transient_const_pointer> (lastParticles().first->dataPtr()); _hadron_B=dynamic_ptr_cast::transient_const_pointer> (lastParticles().second->dataPtr()); // If necessary swap the particle data vectors so that _xb_a, // mePartonData[0], beam[0] relate to the inbound quark: if(!(lastPartons().first ->dataPtr()==_parton_a&& lastPartons().second->dataPtr()==_parton_b)) { swap(_xb_a ,_xb_b); swap(_hadron_A,_hadron_B); } // calculate the PDF's for the Born process _oldq = _hadron_A->pdf()->xfx(_hadron_A,_parton_a,scale(),_xb_a)/_xb_a; _oldqbar = _hadron_B->pdf()->xfx(_hadron_B,_parton_b,scale(),_xb_b)/_xb_b; // Calculate alpha_S _alphaS2Pi = _nlo_alphaS_opt==1 ? _fixed_alphaS : SM().alphaS(scale()); _alphaS2Pi /= 2.*Constants::pi; // Calculate the invariant mass of the dilepton pair _mll2 = sHat(); _mu2 = scale(); // Calculate the integrand // q qbar contribution double wqqvirt = Vtilde_qq(); double wqqcollin = Ctilde_qq(x(_xt,1.),1.) + Ctilde_qq(x(_xt,0.),0.); double wqqreal = Ftilde_qq(_xt,_v); double wqq = wqqvirt+wqqcollin+wqqreal; // q g contribution double wqgcollin = Ctilde_qg(x(_xt,0.),0.); double wqgreal = Ftilde_qg(_xt,_v); double wqg = wqgreal+wqgcollin; // g qbar contribution double wgqbarcollin = Ctilde_gq(x(_xt,1.),1.); double wgqbarreal = Ftilde_gq(_xt,_v); double wgqbar = wgqbarreal+wgqbarcollin; // total double wgt = 1.+(wqq+wqg+wgqbar); // KMH - 06/08 - This seems to give wrong NLO results for // associated Higgs so I'm omitting it. // //trick to try and reduce neg wgt contribution // if(_xt<1.-_eps) // wgt += _a*(1./pow(1.-_xt,_p)-(1.-pow(_eps,1.-_p))/(1.-_p)/(1.-_eps)); // return the answer assert(isfinite(wgt)); return _contrib==1 ? max(0.,wgt) : max(0.,-wgt); } double MEPP2WHPowheg::x(double xt, double v) const { double x0(xbar(v)); return x0+(1.-x0)*xt; } double MEPP2WHPowheg::x_a(double x, double v) const { if(x==1.) return _xb_a; if(v==0.) return _xb_a; if(v==1.) return _xb_a/x; return (_xb_a/sqrt(x))*sqrt((1.-(1.-x)*(1.-v))/(1.-(1.-x)*v)); } double MEPP2WHPowheg::x_b(double x, double v) const { if(x==1.) return _xb_b; if(v==0.) return _xb_b/x; if(v==1.) return _xb_b; return (_xb_b/sqrt(x))*sqrt((1.-(1.-x)*v)/(1.-(1.-x)*(1.-v))); } double MEPP2WHPowheg::xbar(double v) const { double xba2(sqr(_xb_a)), xbb2(sqr(_xb_b)), omv(-999.); double xbar1(-999.), xbar2(-999.); if(v==1.) return _xb_a; if(v==0.) return _xb_b; omv = 1.-v; xbar1=4.* v*xba2/ (sqrt(sqr(1.+xba2)*4.*sqr(omv)+16.*(1.-2.*omv)*xba2)+2.*omv*(1.-_xb_a)*(1.+_xb_a)); xbar2=4.*omv*xbb2/ (sqrt(sqr(1.+xbb2)*4.*sqr( v)+16.*(1.-2.* v)*xbb2)+2.* v*(1.-_xb_b)*(1.+_xb_b)); return max(xbar1,xbar2); } double MEPP2WHPowheg::Ltilde_qq(double x, double v) const { if(x==1.) return 1.; double xa(x_a(x,v)),xb(x_b(x,v)); double newq = (_hadron_A->pdf()->xfx(_hadron_A,_parton_a,scale(), xa)/ xa); double newqbar = (_hadron_B->pdf()->xfx(_hadron_B,_parton_b,scale(), xb)/ xb); return( newq * newqbar / _oldq / _oldqbar ); } double MEPP2WHPowheg::Ltilde_qg(double x, double v) const { double xa(x_a(x,v)),xb(x_b(x,v)); double newq = (_hadron_A->pdf()->xfx(_hadron_A,_parton_a,scale(), xa)/ xa); double newg2 = (_hadron_B->pdf()->xfx(_hadron_B,_gluon ,scale(), xb)/ xb); return( newq * newg2 / _oldq / _oldqbar ); } double MEPP2WHPowheg::Ltilde_gq(double x, double v) const { double xa(x_a(x,v)),xb(x_b(x,v)); double newg1 = (_hadron_A->pdf()->xfx(_hadron_A,_gluon ,scale(), xa)/ xa); double newqbar = (_hadron_B->pdf()->xfx(_hadron_B,_parton_b,scale(), xb)/ xb); return( newg1 * newqbar / _oldq / _oldqbar ); } double MEPP2WHPowheg::Vtilde_qq() const { return _alphaS2Pi*CF_*(-3.*log(_mu2/_mll2)+(2.*sqr(Constants::pi)/3.)-8.); } double MEPP2WHPowheg::Ccalbar_qg(double x) const { return (sqr(x)+sqr(1.-x))*(log(_mll2/(_mu2*x))+2.*log(1.-x))+2.*x*(1.-x); } double MEPP2WHPowheg::Ctilde_qg(double x, double v) const { return _alphaS2Pi*TR_ * ((1.-xbar(v))/x) * Ccalbar_qg(x)*Ltilde_qg(x,v); } double MEPP2WHPowheg::Ctilde_gq(double x, double v) const { return _alphaS2Pi*TR_ * ((1.-xbar(v))/x) * Ccalbar_qg(x)*Ltilde_gq(x,v); } double MEPP2WHPowheg::Ctilde_qq(double x, double v) const { double wgt = ((1.-x)/x+(1.+x*x)/(1.-x)/x*(2.*log(1.-x)-log(x)))*Ltilde_qq(x,v) - 4.*log(1.-x)/(1.-x) + 2./(1.-xbar(v))*log(1.-xbar(v))*log(1.-xbar(v)) + (2./(1.-xbar(v))*log(1.-xbar(v))-2./(1.-x)+(1.+x*x)/x/(1.-x)*Ltilde_qq(x,v)) *log(_mll2/_mu2); return _alphaS2Pi*CF_*(1.-xbar(v))*wgt; } double MEPP2WHPowheg::Fcal_qq(double x, double v) const { return (sqr(1.-x)*(1.-2.*v*(1.-v))+2.*x)/x*Ltilde_qq(x,v); } double MEPP2WHPowheg::Fcal_qg(double x, double v) const { return ((1.-xbar(v))/x)* (2.*x*(1.-x)*v+sqr((1.-x)*v)+sqr(x)+sqr(1.-x))*Ltilde_qg(x,v); } double MEPP2WHPowheg::Fcal_gq(double x, double v) const { return ((1.-xbar(v))/x)* (2.*x*(1.-x)*(1.-v)+sqr((1.-x)*(1.-v))+sqr(x)+sqr(1.-x))*Ltilde_gq(x,v); } double MEPP2WHPowheg::Ftilde_qg(double xt, double v) const { return _alphaS2Pi*TR_* ( Fcal_qg(x(xt,v),v) - Fcal_qg(x(xt,0.),0.) )/v; } double MEPP2WHPowheg::Ftilde_gq(double xt, double v) const { return _alphaS2Pi*TR_* ( Fcal_gq(x(xt,v),v) - Fcal_gq(x(xt,1.),1.) )/(1.-v); } double MEPP2WHPowheg::Ftilde_qq(double xt, double v) const { double eps(1e-10); // is emission into regular or singular region? if(xt>=0. && xt<1.-eps && v>eps && v<1.-eps) { // x<1, v>0, v<1 (regular emission, neither soft or collinear): return _alphaS2Pi*CF_* (( ( Fcal_qq(x(xt, v), v) - Fcal_qq(x(xt,1.),1.) ) / (1.-v)+ ( Fcal_qq(x(xt, v), v) - Fcal_qq(x(xt,0.),0.) ) / v )/(1.-xt) + ( log(1.-xbar(v)) - log(1.-_xb_a))*2./(1.-v) + ( log(1.-xbar(v)) - log(1.-_xb_b))*2./v); } else { // make sure emission is actually in the allowed phase space: if(!(v>=0. && v<=1. && xt>=0. && xt<=1.)) { ostringstream s; s << "MEPP2WHPowheg::Ftilde_qq : \n" << "xt(" << xt << ") and / or v(" << v << ") not in the phase space."; generator()->logWarning(Exception(s.str(),Exception::warning)); return 0.; } // is emission soft singular? if(xt>=1.-eps) { // x=1: if(v<=eps) { // x==1, v=0 (soft and collinear with particle b): return _alphaS2Pi*CF_* ( ( log(1.-xbar(v)) - log(1.-_xb_a))*2./(1.-v) ); } else if(v>=1.-eps) { // x==1, v=1 (soft and collinear with particle a): return _alphaS2Pi*CF_* ( ( log(1.-xbar(v)) - log(1.-_xb_b))*2./v ); } else { // x==1, 0=1.-eps) { // x<1 but v=1 (collinear with particle a, but not soft): return _alphaS2Pi*CF_* ( ( ( Fcal_qq(x(xt, v), v) - Fcal_qq(x(xt,0.),0.) ) / v )/(1.-xt) + ( log(1.-xbar(v)) - log(1.-_xb_b))*2./v ); } } } return 0.; } diff --git a/MatrixElement/Powheg/MEPP2WHPowheg.h b/MatrixElement/Powheg/MEPP2WHPowheg.h --- a/MatrixElement/Powheg/MEPP2WHPowheg.h +++ b/MatrixElement/Powheg/MEPP2WHPowheg.h @@ -1,386 +1,382 @@ // -*- C++ -*- #ifndef HERWIG_MEPP2WHPowheg_H #define HERWIG_MEPP2WHPowheg_H // // This is the declaration of the MEPP2WHPowheg class. // #include "Herwig/MatrixElement/Hadron/MEPP2WH.h" #include "ThePEG/PDF/BeamParticleData.h" namespace Herwig { using namespace ThePEG; /** * The MEPP2WHPowheg class provides the next-to-leading order * matrix elements for \f$W^\pm\f$ in assoication with a Higgs boson * in the PoOWHEG scheme. * * @see \ref MEPP2WHPowhegInterfaces "The interfaces" * defined for MEPP2WHPowheg. */ class MEPP2WHPowheg: public MEPP2WH { public: /** * Default constructor */ MEPP2WHPowheg(); /** @name Virtual functions required by the MEBase class. */ //@{ /** * Return the scale associated with the last set phase space point. */ virtual Energy2 scale() const; /** * The number of internal degreed of freedom used in the matrix * element. */ virtual int nDim() const; /** * Generate internal degrees of freedom given 'nDim()' uniform * random numbers in the interval ]0,1[. To help the phase space * generator, the 'dSigHatDR()' should be a smooth function of these * numbers, although this is not strictly necessary. Return * false if the chosen points failed the kinematical cuts. */ virtual bool generateKinematics(const double * r); /** * Return the matrix element for the kinematical configuation * previously provided by the last call to setKinematics(). Uses * me(). */ virtual CrossSection dSigHatDR() const; //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** * Calculate the correction weight with which leading-order * configurations are re-weighted. */ double NLOweight() const; /** * Calculate the variable \f$x=M_{B}^2/s\f$ from the integration variables. */ double x(double xt, double v) const; /** * Calculate the momentum fraction of the first parton. */ double x_a(double x, double v) const; /** * Calculate the momentum fraction of second parton. */ double x_b(double x, double v) const; /** * Calculate the minimum of \f$x\f$. */ double xbar(double v) const; /** * Calculate the ratio of the radiative luminosity funcion to the * Born luminosity function for the \f$qg\f$ initiated channel. */ double Ltilde_qg(double x, double v) const; /** * Calculate the ratio of the radiative luminosity funcion to the * Born luminosity function for the \f$g\bar{q}\f$ initiated channel. */ double Ltilde_gq(double x, double v) const; /** * Calculate the ratio of the radiative luminosity funcion to the * Born luminosity function for the \f$q\bar{q}\f$ initiated channel. */ double Ltilde_qq(double x, double v) const; /** * Calculate the soft-virtual contribution to the NLO weight. */ double Vtilde_qq() const; /** * Function for calculation of the \f$g\bar{q}\f$ and \f$g\bar{q}\f$ * initiated real contribution. */ double Ccalbar_qg(double x) const; /** * Function for calculation of the \f$qg\f$ * initiated real contribution. */ double Fcal_qg(double x, double v) const; /** * Function for calculation of the \f$g\bar{q}\f$ initiated real * contribution. */ double Fcal_gq(double x, double v) const; /** * Function for calculation of the \f$q\bar{q}\f$ initiated real * contribution. */ double Fcal_qq(double x, double v) const; /** * Function for calculation of the \f$qg\f$ initiated real * contribution. */ double Ftilde_qg(double xt, double v) const; /** * Function for calculation of the \f$g\bar{q}\f$ initiated real * contribution. */ double Ftilde_gq(double xt, double v) const; /** * Function for calculation of the \f$q\bar{q}\f$ initiated real * contribution. */ double Ftilde_qq(double xt, double v) const; /** * Function for calculation of the \f$qg\f$ initiated real * contribution. */ double Ctilde_qg(double x, double v) const; /** * Function for calculation of the \f$g\bar{q}\f$ initiated real * contribution. */ double Ctilde_gq(double x, double v) const; /** * Function for calculation of the \f$q\bar{q}\f$ initiated real * contribution. */ double Ctilde_qq(double x, double v) const; protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const { return new_ptr(*this); } /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const { return new_ptr(*this); } //@} protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MEPP2WHPowheg & operator=(const MEPP2WHPowheg &) = delete; private: /** * The momentum fraction of the first parton in the Born process */ mutable double _xb_a; /** * The momentum fraction of the second parton in the Born process */ mutable double _xb_b; /** * The ParticleData object for the first parton in the Born process */ mutable tcPDPtr _parton_a; /** * The ParticleData object for the second parton in the Born process */ mutable tcPDPtr _parton_b; /** * The BeamParticleData object for the first hadron */ mutable Ptr::transient_const_pointer _hadron_A; /** * The BeamParticleData object for the second hadron */ mutable Ptr::transient_const_pointer _hadron_B; /** * the ParticleData object for the gluon */ tcPDPtr _gluon; /** * The \f$T_R\f$ colour factor */ const double TR_; /** * The \f$C_F\f$ colour factor */ const double CF_; /** * The value of \f$\frac{\alpha_S}{2\pi}\f$ used for the calculation */ mutable double _alphaS2Pi; /** * The mass squared of the lepton pair */ mutable Energy2 _mll2; /** * The renormalization/factorization scale */ mutable Energy2 _mu2; /** * Parameters for the NLO weight */ //@{ /** * Whether to generate the positive, negative or leading order contribution */ unsigned int _contrib; /** * Whether to use a fixed or a running QCD coupling for the NLO weight */ unsigned int _nlo_alphaS_opt; /** * The value of alphaS to use for the nlo weight if _nloalphaSopt=1 */ double _fixed_alphaS; /** * The magnitude of the correction term to reduce the negative contribution */ double _a; /** * The power of the correction term to reduce the negative contribution */ double _p; - /** - * Cut-off for the correction function - */ - double _eps; //@} /** * Choice of the scale */ //@{ /** * Type of scale */ unsigned int _scaleopt; /** * Fixed scale if used */ Energy _fixedScale; /** * Prefactor if variable scale used */ double _scaleFact; //@} /** * Radiation variables */ //@{ /** * The \f$\tilde{x}\f$ variable */ double _xt; /** * The \f$v\f$ angular variable */ double _v; //@} /** * Values of the PDF's before radiation */ //@{ /** * For the quark */ mutable double _oldq; /** * For the antiquark */ mutable double _oldqbar; //@} }; } #endif /* HERWIG_MEPP2WHPowheg_H */ diff --git a/MatrixElement/Powheg/MEPP2ZHPowheg.cc b/MatrixElement/Powheg/MEPP2ZHPowheg.cc --- a/MatrixElement/Powheg/MEPP2ZHPowheg.cc +++ b/MatrixElement/Powheg/MEPP2ZHPowheg.cc @@ -1,391 +1,391 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the MEPP2ZHPowheg class. // #include "MEPP2ZHPowheg.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Handlers/StandardXComb.h" #include "ThePEG/PDT/EnumParticles.h" #include "ThePEG/MatrixElement/Tree2toNDiagram.h" #include "ThePEG/PDT/DecayMode.h" using namespace Herwig; MEPP2ZHPowheg::MEPP2ZHPowheg() : _gluon(), TR_(0.5), CF_(4./3.), _contrib(1) ,_nlo_alphaS_opt(0), _fixed_alphaS(0.115895), - _a(0.5) ,_p(0.7) , _eps(1.0e-8), _scaleopt(1), + _a(0.5) ,_p(0.7) , _scaleopt(1), _fixedScale(100.*GeV), _scaleFact(1.) {} void MEPP2ZHPowheg::persistentOutput(PersistentOStream & os) const { os << _contrib << _nlo_alphaS_opt << _fixed_alphaS << _a << _p << _gluon << _scaleopt << ounit(_fixedScale,GeV) << _scaleFact; } void MEPP2ZHPowheg::persistentInput(PersistentIStream & is, int) { is >> _contrib >> _nlo_alphaS_opt >> _fixed_alphaS >> _a >> _p >> _gluon >> _scaleopt >> iunit(_fixedScale,GeV) >> _scaleFact; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigMEPP2ZHPowheg("Herwig::MEPP2ZHPowheg", "HwMEHadron.so HwPowhegMEHadron.so"); void MEPP2ZHPowheg::Init() { static ClassDocumentation documentation ("The MEPP2ZHPowheg class implements the matrix element for q qbar -> Z H", "The PP$\\to$Z Higgs POWHEG matrix element is described in \\cite{Hamilton:2009za}.", "\\bibitem{Hamilton:2009za}\n" " K.~Hamilton, P.~Richardson and J.~Tully,\n" " %``A Positive-Weight Next-to-Leading Order Monte Carlo Simulation for Higgs\n" " %Boson Production,''\n" " JHEP {\\bf 0904} (2009) 116\n" " [arXiv:0903.4345 [hep-ph]].\n" " %%CITATION = JHEPA,0904,116;%%\n" ); static Switch interfaceContribution ("Contribution", "Which contributions to the cross section to include", &MEPP2ZHPowheg::_contrib, 1, false, false); static SwitchOption interfaceContributionLeadingOrder (interfaceContribution, "LeadingOrder", "Just generate the leading order cross section", 0); static SwitchOption interfaceContributionPositiveNLO (interfaceContribution, "PositiveNLO", "Generate the positive contribution to the full NLO cross section", 1); static SwitchOption interfaceContributionNegativeNLO (interfaceContribution, "NegativeNLO", "Generate the negative contribution to the full NLO cross section", 2); static Switch interfaceNLOalphaSopt ("NLOalphaSopt", "Whether to use a fixed or a running QCD coupling for the NLO weight", &MEPP2ZHPowheg::_nlo_alphaS_opt, 0, false, false); static SwitchOption interfaceNLOalphaSoptRunningAlphaS (interfaceNLOalphaSopt, "RunningAlphaS", "Use the usual running QCD coupling evaluated at scale scale()", 0); static SwitchOption interfaceNLOalphaSoptFixedAlphaS (interfaceNLOalphaSopt, "FixedAlphaS", "Use a constant QCD coupling for comparison/debugging purposes", 1); static Parameter interfaceFixedNLOalphaS ("FixedNLOalphaS", "The value of alphaS to use for the nlo weight if _nlo_alphaS_opt=1", &MEPP2ZHPowheg::_fixed_alphaS, 0.115895, 0., 1.0, false, false, Interface::limited); static Parameter interfaceCorrectionCoefficient ("CorrectionCoefficient", "The magnitude of the correction term to reduce the negative contribution", &MEPP2ZHPowheg::_a, 0.5, -10., 10.0, false, false, Interface::limited); static Parameter interfaceCorrectionPower ("CorrectionPower", "The power of the correction term to reduce the negative contribution", &MEPP2ZHPowheg::_p, 0.7, 0.0, 1.0, false, false, Interface::limited); static Switch interfaceFactorizationScaleOption ("FactorizationScaleOption", "Option for the scale to be used", &MEPP2ZHPowheg::_scaleopt, 1, false, false); static SwitchOption interfaceScaleOptionFixed (interfaceFactorizationScaleOption, "Fixed", "Use a fixed scale", 0); static SwitchOption interfaceScaleOptionsHat (interfaceFactorizationScaleOption, "Dynamic", "Use the mass of the vector boson-Higgs boson system", 1); static Parameter interfaceFactorizationScaleValue ("FactorizationScaleValue", "The fixed scale to use if required", &MEPP2ZHPowheg::_fixedScale, GeV, 100.0*GeV, 10.0*GeV, 1000.0*GeV, false, false, Interface::limited); static Parameter interfaceScaleFactor ("ScaleFactor", "The factor used before sHat if using a running scale", &MEPP2ZHPowheg::_scaleFact, 1.0, 0.0, 10.0, false, false, Interface::limited); } void MEPP2ZHPowheg::doinit() { // gluon ParticleData object _gluon = getParticleData(ParticleID::g); MEPP2ZH::doinit(); } Energy2 MEPP2ZHPowheg::scale() const { return _scaleopt == 0 ? sqr(_fixedScale) : _scaleFact*sHat(); } int MEPP2ZHPowheg::nDim() const { return 7; } bool MEPP2ZHPowheg::generateKinematics(const double * r) { _xt=*(r+5); _v =*(r+6); return MEPP2ZH::generateKinematics(r); } CrossSection MEPP2ZHPowheg::dSigHatDR() const { // Get Born momentum fractions xbar_a and xbar_b: _xb_a = lastX1(); _xb_b = lastX2(); return MEPP2ZH::dSigHatDR()*NLOweight(); } double MEPP2ZHPowheg::NLOweight() const { // If only leading order is required return 1: if(_contrib==0) return 1.; useMe(); // Get particle data for QCD particles: _parton_a=mePartonData()[0]; _parton_b=mePartonData()[1]; // get BeamParticleData objects for PDF's _hadron_A=dynamic_ptr_cast::transient_const_pointer> (lastParticles().first->dataPtr()); _hadron_B=dynamic_ptr_cast::transient_const_pointer> (lastParticles().second->dataPtr()); // If necessary swap the particle data vectors so that _xb_a, // mePartonData[0], beam[0] relate to the inbound quark: if(!(lastPartons().first ->dataPtr()==_parton_a&& lastPartons().second->dataPtr()==_parton_b)) { swap(_xb_a ,_xb_b); swap(_hadron_A,_hadron_B); } // calculate the PDF's for the Born process _oldq = _hadron_A->pdf()->xfx(_hadron_A,_parton_a,scale(),_xb_a)/_xb_a; _oldqbar = _hadron_B->pdf()->xfx(_hadron_B,_parton_b,scale(),_xb_b)/_xb_b; // Calculate alpha_S _alphaS2Pi = _nlo_alphaS_opt==1 ? _fixed_alphaS : SM().alphaS(scale()); _alphaS2Pi /= 2.*Constants::pi; // Calculate the invariant mass of the dilepton pair _mll2 = sHat(); _mu2 = scale(); // Calculate the integrand // q qbar contribution double wqqvirt = Vtilde_qq(); double wqqcollin = Ctilde_qq(x(_xt,1.),1.) + Ctilde_qq(x(_xt,0.),0.); double wqqreal = Ftilde_qq(_xt,_v); double wqq = wqqvirt+wqqcollin+wqqreal; // q g contribution double wqgcollin = Ctilde_qg(x(_xt,0.),0.); double wqgreal = Ftilde_qg(_xt,_v); double wqg = wqgreal+wqgcollin; // g qbar contribution double wgqbarcollin = Ctilde_gq(x(_xt,1.),1.); double wgqbarreal = Ftilde_gq(_xt,_v); double wgqbar = wgqbarreal+wgqbarcollin; // total double wgt = 1.+(wqq+wqg+wgqbar); // KMH - 06/08 - This seems to give wrong NLO results for // associated Higgs so I'm omitting it. // //trick to try and reduce neg wgt contribution // if(_xt<1.-_eps) // wgt += _a*(1./pow(1.-_xt,_p)-(1.-pow(_eps,1.-_p))/(1.-_p)/(1.-_eps)); // return the answer assert(isfinite(wgt)); return _contrib==1 ? max(0.,wgt) : max(0.,-wgt); } double MEPP2ZHPowheg::x(double xt, double v) const { double x0(xbar(v)); return x0+(1.-x0)*xt; } double MEPP2ZHPowheg::x_a(double x, double v) const { if(x==1.) return _xb_a; if(v==0.) return _xb_a; if(v==1.) return _xb_a/x; return (_xb_a/sqrt(x))*sqrt((1.-(1.-x)*(1.-v))/(1.-(1.-x)*v)); } double MEPP2ZHPowheg::x_b(double x, double v) const { if(x==1.) return _xb_b; if(v==0.) return _xb_b/x; if(v==1.) return _xb_b; return (_xb_b/sqrt(x))*sqrt((1.-(1.-x)*v)/(1.-(1.-x)*(1.-v))); } double MEPP2ZHPowheg::xbar(double v) const { double xba2(sqr(_xb_a)), xbb2(sqr(_xb_b)), omv(-999.); double xbar1(-999.), xbar2(-999.); if(v==1.) return _xb_a; if(v==0.) return _xb_b; omv = 1.-v; xbar1=4.* v*xba2/ (sqrt(sqr(1.+xba2)*4.*sqr(omv)+16.*(1.-2.*omv)*xba2)+2.*omv*(1.-_xb_a)*(1.+_xb_a)); xbar2=4.*omv*xbb2/ (sqrt(sqr(1.+xbb2)*4.*sqr( v)+16.*(1.-2.* v)*xbb2)+2.* v*(1.-_xb_b)*(1.+_xb_b)); return max(xbar1,xbar2); } double MEPP2ZHPowheg::Ltilde_qq(double x, double v) const { if(x==1.) return 1.; double xa(x_a(x,v)),xb(x_b(x,v)); double newq = (_hadron_A->pdf()->xfx(_hadron_A,_parton_a,scale(), xa)/ xa); double newqbar = (_hadron_B->pdf()->xfx(_hadron_B,_parton_b,scale(), xb)/ xb); return( newq * newqbar / _oldq / _oldqbar ); } double MEPP2ZHPowheg::Ltilde_qg(double x, double v) const { double xa(x_a(x,v)),xb(x_b(x,v)); double newq = (_hadron_A->pdf()->xfx(_hadron_A,_parton_a,scale(), xa)/ xa); double newg2 = (_hadron_B->pdf()->xfx(_hadron_B,_gluon ,scale(), xb)/ xb); return( newq * newg2 / _oldq / _oldqbar ); } double MEPP2ZHPowheg::Ltilde_gq(double x, double v) const { double xa(x_a(x,v)),xb(x_b(x,v)); double newg1 = (_hadron_A->pdf()->xfx(_hadron_A,_gluon ,scale(), xa)/ xa); double newqbar = (_hadron_B->pdf()->xfx(_hadron_B,_parton_b,scale(), xb)/ xb); return( newg1 * newqbar / _oldq / _oldqbar ); } double MEPP2ZHPowheg::Vtilde_qq() const { return _alphaS2Pi*CF_*(-3.*log(_mu2/_mll2)+(2.*sqr(Constants::pi)/3.)-8.); } double MEPP2ZHPowheg::Ccalbar_qg(double x) const { return (sqr(x)+sqr(1.-x))*(log(_mll2/(_mu2*x))+2.*log(1.-x))+2.*x*(1.-x); } double MEPP2ZHPowheg::Ctilde_qg(double x, double v) const { return _alphaS2Pi*TR_ * ((1.-xbar(v))/x) * Ccalbar_qg(x)*Ltilde_qg(x,v); } double MEPP2ZHPowheg::Ctilde_gq(double x, double v) const { return _alphaS2Pi*TR_ * ((1.-xbar(v))/x) * Ccalbar_qg(x)*Ltilde_gq(x,v); } double MEPP2ZHPowheg::Ctilde_qq(double x, double v) const { double wgt = ((1.-x)/x+(1.+x*x)/(1.-x)/x*(2.*log(1.-x)-log(x)))*Ltilde_qq(x,v) - 4.*log(1.-x)/(1.-x) + 2./(1.-xbar(v))*log(1.-xbar(v))*log(1.-xbar(v)) + (2./(1.-xbar(v))*log(1.-xbar(v))-2./(1.-x)+(1.+x*x)/x/(1.-x)*Ltilde_qq(x,v)) *log(_mll2/_mu2); return _alphaS2Pi*CF_*(1.-xbar(v))*wgt; } double MEPP2ZHPowheg::Fcal_qq(double x, double v) const { return (sqr(1.-x)*(1.-2.*v*(1.-v))+2.*x)/x*Ltilde_qq(x,v); } double MEPP2ZHPowheg::Fcal_qg(double x, double v) const { return ((1.-xbar(v))/x)* (2.*x*(1.-x)*v+sqr((1.-x)*v)+sqr(x)+sqr(1.-x))*Ltilde_qg(x,v); } double MEPP2ZHPowheg::Fcal_gq(double x, double v) const { return ((1.-xbar(v))/x)* (2.*x*(1.-x)*(1.-v)+sqr((1.-x)*(1.-v))+sqr(x)+sqr(1.-x))*Ltilde_gq(x,v); } double MEPP2ZHPowheg::Ftilde_qg(double xt, double v) const { return _alphaS2Pi*TR_* ( Fcal_qg(x(xt,v),v) - Fcal_qg(x(xt,0.),0.) )/v; } double MEPP2ZHPowheg::Ftilde_gq(double xt, double v) const { return _alphaS2Pi*TR_* ( Fcal_gq(x(xt,v),v) - Fcal_gq(x(xt,1.),1.) )/(1.-v); } double MEPP2ZHPowheg::Ftilde_qq(double xt, double v) const { double eps(1e-10); // is emission into regular or singular region? if(xt>=0. && xt<1.-eps && v>eps && v<1.-eps) { // x<1, v>0, v<1 (regular emission, neither soft or collinear): return _alphaS2Pi*CF_* (( ( Fcal_qq(x(xt, v), v) - Fcal_qq(x(xt,1.),1.) ) / (1.-v)+ ( Fcal_qq(x(xt, v), v) - Fcal_qq(x(xt,0.),0.) ) / v )/(1.-xt) + ( log(1.-xbar(v)) - log(1.-_xb_a))*2./(1.-v) + ( log(1.-xbar(v)) - log(1.-_xb_b))*2./v); } else { // make sure emission is actually in the allowed phase space: if(!(v>=0. && v<=1. && xt>=0. && xt<=1.)) { ostringstream s; s << "MEPP2ZHPowheg::Ftilde_qq : \n" << "xt(" << xt << ") and / or v(" << v << ") not in the phase space."; generator()->logWarning(Exception(s.str(),Exception::warning)); return 0.; } // is emission soft singular? if(xt>=1.-eps) { // x=1: if(v<=eps) { // x==1, v=0 (soft and collinear with particle b): return _alphaS2Pi*CF_* ( ( log(1.-xbar(v)) - log(1.-_xb_a))*2./(1.-v) ); } else if(v>=1.-eps) { // x==1, v=1 (soft and collinear with particle a): return _alphaS2Pi*CF_* ( ( log(1.-xbar(v)) - log(1.-_xb_b))*2./v ); } else { // x==1, 0=1.-eps) { // x<1 but v=1 (collinear with particle a, but not soft): return _alphaS2Pi*CF_* ( ( ( Fcal_qq(x(xt, v), v) - Fcal_qq(x(xt,0.),0.) ) / v )/(1.-xt) + ( log(1.-xbar(v)) - log(1.-_xb_b))*2./v ); } } } return 0.; } diff --git a/MatrixElement/Powheg/MEPP2ZHPowheg.h b/MatrixElement/Powheg/MEPP2ZHPowheg.h --- a/MatrixElement/Powheg/MEPP2ZHPowheg.h +++ b/MatrixElement/Powheg/MEPP2ZHPowheg.h @@ -1,384 +1,380 @@ // -*- C++ -*- #ifndef HERWIG_MEPP2ZHPowheg_H #define HERWIG_MEPP2ZHPowheg_H // // This is the declaration of the MEPP2ZHPowheg class. // #include "Herwig/MatrixElement/Hadron/MEPP2ZH.h" #include "ThePEG/PDF/BeamParticleData.h" namespace Herwig { using namespace ThePEG; /** * The MEPP2ZHPowheg class implements the matrix element * for \f$q\bar{q}\to Z^0h^0\f$. * * @see \ref MEPP2ZHPowhegInterfaces "The interfaces" * defined for MEPP2ZHPowheg. */ class MEPP2ZHPowheg: public MEPP2ZH { public: /** * The default constructor. */ MEPP2ZHPowheg(); /** @name Virtual functions required by the MEBase class. */ //@{ /** * Return the scale associated with the last set phase space point. */ virtual Energy2 scale() const; /** * The number of internal degreed of freedom used in the matrix * element. */ virtual int nDim() const; /** * Generate internal degrees of freedom given 'nDim()' uniform * random numbers in the interval ]0,1[. To help the phase space * generator, the 'dSigHatDR()' should be a smooth function of these * numbers, although this is not strictly necessary. Return * false if the chosen points failed the kinematical cuts. */ virtual bool generateKinematics(const double * r); /** * Return the matrix element for the kinematical configuation * previously provided by the last call to setKinematics(). Uses * me(). */ virtual CrossSection dSigHatDR() const; //@} public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** * Calculate the correction weight with which leading-order * configurations are re-weighted. */ double NLOweight() const; /** * Calculate the variable \f$x=M_{B}^2/s\f$ from the integration variables. */ double x(double xt, double v) const; /** * Calculate the momentum fraction of the first parton. */ double x_a(double x, double v) const; /** * Calculate the momentum fraction of second parton. */ double x_b(double x, double v) const; /** * Calculate the minimum of \f$x\f$. */ double xbar(double v) const; /** * Calculate the ratio of the radiative luminosity funcion to the * Born luminosity function for the \f$qg\f$ initiated channel. */ double Ltilde_qg(double x, double v) const; /** * Calculate the ratio of the radiative luminosity funcion to the * Born luminosity function for the \f$g\bar{q}\f$ initiated channel. */ double Ltilde_gq(double x, double v) const; /** * Calculate the ratio of the radiative luminosity funcion to the * Born luminosity function for the \f$q\bar{q}\f$ initiated channel. */ double Ltilde_qq(double x, double v) const; /** * Calculate the soft-virtual contribution to the NLO weight. */ double Vtilde_qq() const; /** * Function for calculation of the \f$g\bar{q}\f$ and \f$g\bar{q}\f$ * initiated real contribution. */ double Ccalbar_qg(double x) const; /** * Function for calculation of the \f$qg\f$ * initiated real contribution. */ double Fcal_qg(double x, double v) const; /** * Function for calculation of the \f$g\bar{q}\f$ initiated real * contribution. */ double Fcal_gq(double x, double v) const; /** * Function for calculation of the \f$q\bar{q}\f$ initiated real * contribution. */ double Fcal_qq(double x, double v) const; /** * Function for calculation of the \f$qg\f$ initiated real * contribution. */ double Ftilde_qg(double xt, double v) const; /** * Function for calculation of the \f$g\bar{q}\f$ initiated real * contribution. */ double Ftilde_gq(double xt, double v) const; /** * Function for calculation of the \f$q\bar{q}\f$ initiated real * contribution. */ double Ftilde_qq(double xt, double v) const; /** * Function for calculation of the \f$qg\f$ initiated real * contribution. */ double Ctilde_qg(double x, double v) const; /** * Function for calculation of the \f$g\bar{q}\f$ initiated real * contribution. */ double Ctilde_gq(double x, double v) const; /** * Function for calculation of the \f$q\bar{q}\f$ initiated real * contribution. */ double Ctilde_qq(double x, double v) const; protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const { return new_ptr(*this); } /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const { return new_ptr(*this); } //@} protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MEPP2ZHPowheg & operator=(const MEPP2ZHPowheg &) = delete; private: /** * The momentum fraction of the first parton in the Born process */ mutable double _xb_a; /** * The momentum fraction of the second parton in the Born process */ mutable double _xb_b; /** * The ParticleData object for the first parton in the Born process */ mutable tcPDPtr _parton_a; /** * The ParticleData object for the second parton in the Born process */ mutable tcPDPtr _parton_b; /** * The BeamParticleData object for the first hadron */ mutable Ptr::transient_const_pointer _hadron_A; /** * The BeamParticleData object for the second hadron */ mutable Ptr::transient_const_pointer _hadron_B; /** * the ParticleData object for the gluon */ tcPDPtr _gluon; /** * The \f$T_R\f$ colour factor */ const double TR_; /** * The \f$C_F\f$ colour factor */ const double CF_; /** * The value of \f$\frac{\alpha_S}{2\pi}\f$ used for the calculation */ mutable double _alphaS2Pi; /** * The mass squared of the lepton pair */ mutable Energy2 _mll2; /** * The renormalization/factorization scale */ mutable Energy2 _mu2; /** * Parameters for the NLO weight */ //@{ /** * Whether to generate the positive, negative or leading order contribution */ unsigned int _contrib; /** * Whether to use a fixed or a running QCD coupling for the NLO weight */ unsigned int _nlo_alphaS_opt; /** * The value of alphaS to use for the nlo weight if _nloalphaSopt=1 */ double _fixed_alphaS; /** * The magnitude of the correction term to reduce the negative contribution */ double _a; /** * The power of the correction term to reduce the negative contribution */ double _p; - /** - * Cut-off for the correction function - */ - double _eps; //@} /** * Choice of the scale */ //@{ /** * Type of scale */ unsigned int _scaleopt; /** * Fixed scale if used */ Energy _fixedScale; /** * Prefactor if variable scale used */ double _scaleFact; //@} /** * Radiation variables */ //@{ /** * The \f$\tilde{x}\f$ variable */ double _xt; /** * The \f$v\f$ angular variable */ double _v; //@} /** * Values of the PDF's before radiation */ //@{ /** * For the quark */ mutable double _oldq; /** * For the antiquark */ mutable double _oldqbar; //@} }; } #endif /* HERWIG_MEPP2ZHPowheg_H */ diff --git a/Models/ADD/ADDModelFFGGRVertex.cc b/Models/ADD/ADDModelFFGGRVertex.cc --- a/Models/ADD/ADDModelFFGGRVertex.cc +++ b/Models/ADD/ADDModelFFGGRVertex.cc @@ -1,92 +1,91 @@ // -*- C++ -*- // // ADDModelFFGGRVertex.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 ADDModelFFGGRVertex class. // #include "ADDModelFFGGRVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; using namespace ThePEG; ADDModelFFGGRVertex::ADDModelFFGGRVertex() : couplast_(0.), q2last_(ZERO), kappa_(ZERO), r_(ZERO) { orderInGem(1); orderInGs (1); colourStructure(ColourStructure::SU3TFUND); } void ADDModelFFGGRVertex::doinit() { for(int ix=1;ix<7;++ix) { addToList(-ix,ix,21,39); } FFVTVertex::doinit(); tcHwADDPtr hwADD=dynamic_ptr_cast(generator()->standardModel()); if(!hwADD) throw Exception() << "Must have ADDModel in ADDModelFFGGRVertex::doinit()" << Exception::runerror; kappa_ = 2./hwADD->MPlanckBar(); r_ = sqr(hwADD->LambdaT())/hwADD->MPlanckBar(); } void ADDModelFFGGRVertex::persistentOutput(PersistentOStream & os) const { os << ounit(kappa_,InvGeV) << ounit(r_,GeV); } void ADDModelFFGGRVertex::persistentInput(PersistentIStream & is, int) { is >> iunit(kappa_,InvGeV) >> iunit(r_,GeV); } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigADDModelFFGGRVertex("Herwig::ADDModelFFGGRVertex", "HwADDModel.so"); void ADDModelFFGGRVertex::Init() { static ClassDocumentation documentation ("The ADDModelFFGGRVertexxs class is the implementation" " of the two fermion vector coupling for the ADD model."); } #ifndef NDEBUG void ADDModelFFGGRVertex::setCoupling(Energy2 q2,tcPDPtr aa,tcPDPtr, tcPDPtr cc, tcPDPtr) { #else void ADDModelFFGGRVertex::setCoupling(Energy2 q2,tcPDPtr,tcPDPtr, tcPDPtr, tcPDPtr) { #endif // work out the particles assert(cc->id()==ParticleID::g && abs(aa->id()) <= 6); - Complex coup; // overall factor if(q2last_!=q2||couplast_==0.) { couplast_ = strongCoupling(q2); q2last_=q2; } left (1.); right(1.); // set the coupling norm(UnitRemoval::E * kappa_ * couplast_); } Complex ADDModelFFGGRVertex::propagator(int iopt, Energy2 q2,tcPDPtr part, Energy mass, Energy width) { if(part->id()!=ParticleID::Graviton) return VertexBase::propagator(iopt,q2,part,mass,width); else return Complex(4.*Constants::pi*UnitRemoval::E2/sqr(r_)); } diff --git a/Models/General/VVSLoopVertex.cc b/Models/General/VVSLoopVertex.cc --- a/Models/General/VVSLoopVertex.cc +++ b/Models/General/VVSLoopVertex.cc @@ -1,134 +1,134 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the VVSLoopVertex class. // #include "VVSLoopVertex.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "Herwig/Looptools/clooptools.h" using namespace Herwig; using namespace ThePEG; namespace LT = Looptools; IBPtr VVSLoopVertex::clone() const { return new_ptr(*this); } IBPtr VVSLoopVertex::fullclone() const { return new_ptr(*this); } void VVSLoopVertex::persistentOutput(PersistentOStream & os) const { os << ounit(masses,GeV) << type << couplings << Npart_; } void VVSLoopVertex::persistentInput(PersistentIStream & is, int) { is >> iunit(masses,GeV) >> type >> couplings >> Npart_; } void VVSLoopVertex::dofinish() { if(loopToolsInit_) Looptools::ltexi(); GeneralVVSVertex::dofinish(); } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigVVSLoopVertex("Herwig::VVSLoopVertex", "Herwig.so"); void VVSLoopVertex::Init() { static ClassDocumentation documentation ("The VVSLoopVertex class calculates the tensor integral" " coefficients using Looptools."); } void VVSLoopVertex::setCoupling(Energy2, tcPDPtr p1, tcPDPtr,tcPDPtr) { if(!loopToolsInit_) { Looptools::ltini(); loopToolsInit_ = true; } //Kinematic invariants double ps2 = invariant(0,0) / MeV2; double pv1s = invariant(1,1) / MeV2; double pv2s = invariant(2,2) / MeV2; Complex a(0.),b(0.),c(0.),d(0.),e(0.),f(0.); for(unsigned int i = 0; i< Npart_;++i) { double lmass = masses[i] / MeV; double mls = sqr(lmass); // left coupling for fermions or the total coupling // for scalars or vectors Complex lc = couplings[i].first; // double p1p2 = 0.5*(ps2-pv1s-pv2s); Complex C0A = LT::C0i(LT::cc0,pv2s,ps2,pv1s,mls,mls,mls); long theC = LT::Cget(pv2s,ps2,pv1s, mls,mls,mls); // Complex C1A = LT::Cval(LT::cc1,theC); // Complex C2A = LT::Cval(LT::cc2,theC); // Complex C11A = LT::Cval(LT::cc11,theC); Complex C12A = LT::Cval(LT::cc12,theC); // Complex C22A = LT::Cval(LT::cc22,theC); // Complex C00A = LT::Cval(LT::cc00,theC); Complex C0B = LT::C0i(LT::cc0,pv1s,ps2,pv2s,mls,mls,mls); theC = LT::Cget(pv1s,ps2,pv2s, mls,mls,mls); // Complex C1B = LT::Cval(LT::cc1,theC); // Complex C2B = LT::Cval(LT::cc2,theC); // Complex C11B = LT::Cval(LT::cc11,theC); Complex C12B = LT::Cval(LT::cc12,theC); // Complex C22B = LT::Cval(LT::cc22,theC); // Complex C00B = LT::Cval(LT::cc00,theC); if(type[i] == PDT::Spin1Half) { Complex lpr = lc + couplings[i].second; Complex loop = 2.*lpr*lmass*( - 4.*(C12A + C12B) + C0A + C0B ); a -= loop; d += loop; f += 2.*(lc - couplings[i].second)*lmass*(C0A+C0B); // a += 2.*lpr*lmass*(2.*C12A-C0A+2.*C12B-C0B+ // (1. - pv1s*(C22A+C11B)- pv2s*(C11A+C22B) + mls*(C0A+C0B) )/p1p2); // b += 8.*lpr*lmass*(2.*C22A + C2A +2.*C11B + C1B); // c += 2.*lpr*lmass*(- 4.*(C12A + C12B) - 2.*(C2A + C1A + C2B + C1B) - C0A - C0B); // d += 2.*lpr*lmass*( - 4.*(C12A + C12B) + C0A + C0B ); // e += 4.*lpr*lmass*( 2.*(C11A + C22B) + C1A + C2B); } else if(type[i] == PDT::Spin1) { - Complex B0W(LT::B0(ps2 ,mls,mls)); + //Complex B0W(LT::B0(ps2 ,mls,mls)); double mr(sqr(p1->mass()/masses[i])); Complex loop = 2.*lc*( -(6.+mr)*(C12A+C12B) + 4.*(C0A +C0B)); a -= loop; d += loop; // a += lc*(-8.*(C0A+C0B) +(6.+mr)*(2.*(C00A+C00B)-B0W)/p1p2); // b += lc*(6.+mr)*(2.*(C22A+C11B)+C2A+C1B); // c += 0.5*lc*(6.+mr)*( - 4.*(C12A+C12B) - 2.*(C1A+C2A+C1B+C2B) - C0A - C0B ); // d += 2.*lc*( -(6.+mr)*(C12A+C12B) + 4.*(C0A +C0B)); // e += lc*(6.+mr)*( 2.*(C11A+C22B) + C1A + C2B ); } else if(type[i] == PDT::Spin0) { Complex loop = 4.*lc*(C12A+C12B); a -= loop; d += loop; // a += -2.*lc*( 2.*(C00A+C00B) - LT::B0(ps2,mls,mls))/p1p2; // b += -2.*lc* ( 2.*(C22A + C11B) + C2A + C1B); // c += -lc*( - 4.*(C12A + C12B) - 2.*(C2A + C1A + C2B + C1B) - C0A - C0B); // d += 4.*lc*(C12A+C12B); // e += -lc*( 2.*(C11A + C22B) + C1A + C2B ); } else { throw Helicity::HelicityConsistencyError() << "SVVLoopVertex::setCoupling - Incorrect particle in SVV loop. " << "Spin: " << type[i] << Exception::runerror; } } //Looptools defines integrals differently double fact = 1./16./sqr(Constants::pi); a00(fact*a); a11(fact*b); a12(fact*c); a21(fact*d); a22(fact*e); aEp(fact*f); } diff --git a/Models/Susy/SSFFHVertex.h b/Models/Susy/SSFFHVertex.h --- a/Models/Susy/SSFFHVertex.h +++ b/Models/Susy/SSFFHVertex.h @@ -1,171 +1,166 @@ // -*- C++ -*- // // SSFFHVertex.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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. // #ifndef HERWIG_SSFFHVertex_H #define HERWIG_SSFFHVertex_H // // This is the declaration of the SSFFHVertex class. // #include "ThePEG/Helicity/Vertex/Scalar/FFSVertex.h" #include "MSSM.h" namespace Herwig { /** * The is the coupling of higgs bosons in the MSSM to a pair * of SM fermions. * * @see \ref SSFFHVertexInterfaces "The interfaces" * defined for SSFFHVertex. */ class SSFFHVertex: public FFSVertex { public: /** * The default constructor. */ SSFFHVertex(); /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); /** * Calculate the coupling for the vertex * @param q2 The scale to at which evaluate the coupling. * @param particle1 The first particle in the vertex. * @param particle2 The second particle in the vertex. * @param particle3 The third particle in the vertex. */ virtual void setCoupling(Energy2 q2, tcPDPtr particle1, tcPDPtr particle2, tcPDPtr particle3); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const {return new_ptr(*this);} /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const {return new_ptr(*this);} //@} protected: /** @name Standard Interfaced functions. */ //@{ /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ SSFFHVertex & operator=(const SSFFHVertex &) = delete; private: /** * Pointer to the SM object. */ tcMSSMPtr theMSSM; /** * The value of \f$\tan\beta\f$. */ double thetanb; /** * The mass of the \f$W\f$. */ Energy theMw; /** - * The value of \f$\sin\theta_W\f$ - */ - double theSw; - - /** * The value of \f$\sin\alpha\f$ */ double theSa; /** * The value of \f$\sin\beta\f$ */ double theSb; /** * The value of \f$\cos\alpha\f$ */ double theCa; /** * The value of \f$\cos\beta\f$ */ double theCb; /** * The ID of the last fermion for which the vertex was evaluated */ pair theFLast; /** * The value of \f$ \frac{e}{\sin\theta_W} \f$ when it was last evaluated. */ double theGlast; /** * The scale at which then coupling was last evaluated. */ Energy2 theq2last; /** * Values of the masses */ pair theMassLast; }; } #endif /* HERWIG_SSFFHVertex_H */ diff --git a/PDF/HwRemDecayer.cc b/PDF/HwRemDecayer.cc --- a/PDF/HwRemDecayer.cc +++ b/PDF/HwRemDecayer.cc @@ -1,1973 +1,1973 @@ // -*- C++ -*- // // HwRemDecayer.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 HwRemDecayer class. // #include "HwRemDecayer.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Utilities/UtilityBase.h" #include "ThePEG/Utilities/SimplePhaseSpace.h" #include "ThePEG/Utilities/Throw.h" #include "Herwig/Shower/ShowerHandler.h" using namespace Herwig; namespace{ const bool dbg = false; void reShuffle(Lorentz5Momentum &p1, Lorentz5Momentum &p2, Energy m1, Energy m2){ Lorentz5Momentum ptotal(p1+p2); ptotal.rescaleMass(); if( ptotal.m() < m1+m2 ) { if(dbg) cerr << "Not enough energy to perform reshuffling \n"; throw HwRemDecayer::ExtraSoftScatterVeto(); } Boost boostv = -ptotal.boostVector(); ptotal.boost(boostv); p1.boost(boostv); // set the masses and energies, p1.setMass(m1); p1.setE(0.5/ptotal.m()*(ptotal.m2()+sqr(m1)-sqr(m2))); p1.rescaleRho(); // boost back to the lab p1.boost(-boostv); p2.boost(boostv); // set the masses and energies, p2.setMass(m2); p2.setE(0.5/ptotal.m()*(ptotal.m2()+sqr(m2)-sqr(m1))); p2.rescaleRho(); // boost back to the lab p2.boost(-boostv); } } void HwRemDecayer::initialize(pair rems, tPPair beam, Step & step, Energy forcedSplitScale) { // the step thestep = &step; // valence content of the hadrons theContent.first = getHadronContent(beam.first); theContent.second = getHadronContent(beam.second); // momentum extracted from the hadrons theUsed.first = Lorentz5Momentum(); theUsed.second = Lorentz5Momentum(); theMaps.first.clear(); theMaps.second.clear(); theX.first = 0.0; theX.second = 0.0; theRems = rems; _forcedSplitScale = forcedSplitScale; // check remnants attached to the right hadrons if( (theRems.first && parent(theRems.first ) != beam.first ) || (theRems.second && parent(theRems.second) != beam.second) ) throw Exception() << "Remnant order wrong in " << "HwRemDecayer::initialize(...)" << Exception::runerror; return; } void HwRemDecayer::split(tPPtr parton, HadronContent & content, tRemPPtr rem, Lorentz5Momentum & used, PartnerMap &partners, tcPDFPtr pdf, bool first) { theBeam = parent(rem); theBeamData = dynamic_ptr_cast::const_pointer> (theBeam->dataPtr()); double currentx = parton->momentum().rho()/theBeam->momentum().rho(); double check = rem==theRems.first ? theX.first : theX.second; check += currentx; if(1.0-check < 1e-3) throw ShowerHandler::ExtraScatterVeto(); bool anti; Lorentz5Momentum lastp(parton->momentum()); int lastID(parton->id()); Energy oldQ(_forcedSplitScale); _pdf = pdf; //do nothing if already valence quark if(first && content.isValenceQuark(parton)) { //set the extracted value, because otherwise no RemID could be generated. content.extract(lastID); // add the particle to the colour partners partners.push_back(make_pair(parton, tPPtr())); //set the sign anti = parton->hasAntiColour() && parton->id()!=ParticleID::g; if(rem==theRems.first) theanti.first = anti; else theanti.second = anti; // add the x and return if(rem==theRems.first) theX.first += currentx; else theX.second += currentx; return; } //or gluon for secondaries else if(!first && lastID == ParticleID::g) { partners.push_back(make_pair(parton, tPPtr())); // add the x and return if(rem==theRems.first) theX.first += currentx; else theX.second += currentx; return; } // if a sea quark.antiquark forced splitting to a gluon // Create the new parton with its momentum and parent/child relationship set PPtr newSea; if( !(lastID == ParticleID::g || lastID == ParticleID::gamma) ) { newSea = forceSplit(rem, -lastID, oldQ, currentx, lastp, used,content); ColinePtr cl = new_ptr(ColourLine()); if(newSea->id() > 0) cl-> addColoured(newSea); else cl->addAntiColoured(newSea); // if a secondard scatter finished so return if(!first || content.isValenceQuark(ParticleID::g) ){ partners.push_back(make_pair(parton, newSea)); // add the x and return if(rem==theRems.first) theX.first += currentx; else theX.second += currentx; if(first) content.extract(ParticleID::g); return; } } // otherwise evolve back to valence // final valence splitting PPtr newValence = forceSplit(rem, lastID!=ParticleID::gamma ? ParticleID::g : ParticleID::gamma, oldQ, currentx , lastp, used, content); // extract from the hadron to allow remnant to be determined content.extract(newValence->id()); // case of a gluon going into the hard subprocess if( lastID == ParticleID::g ) { partners.push_back(make_pair(parton, tPPtr())); anti = newValence->hasAntiColour(); if(rem==theRems.first) theanti.first = anti; else theanti.second = anti; parton->colourLine(!anti)->addColoured(newValence, anti); return; } else if( lastID == ParticleID::gamma) { partners.push_back(make_pair(parton, newValence)); anti = newValence->hasAntiColour(); ColinePtr newLine(new_ptr(ColourLine())); newLine->addColoured(newValence, anti); if(rem==theRems.first) theanti.first = anti; else theanti.second = anti; // add the x and return if(rem==theRems.first) theX.first += currentx; else theX.second += currentx; return; } //The valence quark will always be connected to the sea quark with opposite sign tcPPtr particle; if(lastID*newValence->id() < 0){ particle = parton; partners.push_back(make_pair(newSea, tPPtr())); } else { particle = newSea; partners.push_back(make_pair(parton, tPPtr())); } anti = newValence->hasAntiColour(); if(rem==theRems.first) theanti.first = anti; else theanti.second = anti; if(particle->colourLine()) particle->colourLine()->addAntiColoured(newValence); if(particle->antiColourLine()) particle->antiColourLine()->addColoured(newValence); // add the x and return if(rem==theRems.first) theX.first += currentx; else theX.second += currentx; return; } void HwRemDecayer::doSplit(pair partons, pair pdfs, bool first) { if(theRems.first) { ParticleVector children=theRems.first->children(); for(unsigned int ix=0;ixdataPtr()==theRems.first->dataPtr()) theRems.first = dynamic_ptr_cast(children[ix]); } } if(theRems.second) { ParticleVector children=theRems.second->children(); for(unsigned int ix=0;ixdataPtr()==theRems.second->dataPtr()) theRems.second = dynamic_ptr_cast(children[ix]); } } // forced splitting for first parton if(isPartonic(partons.first )) { try { split(partons.first, theContent.first, theRems.first, theUsed.first, theMaps.first, pdfs.first, first); } catch(ShowerHandler::ExtraScatterVeto) { throw ShowerHandler::ExtraScatterVeto(); } } // forced splitting for second parton if(isPartonic(partons.second)) { try { split(partons.second, theContent.second, theRems.second, theUsed.second, theMaps.second, pdfs.second, first); // additional check for the remnants // if can't do the rescale veto the emission if(!first&&partons.first->data().coloured()&& partons.second->data().coloured()) { Lorentz5Momentum pnew[2]= {theRems.first->momentum() - theUsed.first - partons.first->momentum(), theRems.second->momentum() - theUsed.second - partons.second->momentum()}; pnew[0].setMass(getParticleData(theContent.first.RemID())->constituentMass()); pnew[0].rescaleEnergy(); pnew[1].setMass(getParticleData(theContent.second.RemID())->constituentMass()); pnew[1].rescaleEnergy(); for(unsigned int iy=0; iychildren().size(); ++iy) pnew[0] += theRems.first->children()[iy]->momentum(); for(unsigned int iy=0; iychildren().size(); ++iy) pnew[1] += theRems.second->children()[iy]->momentum(); Lorentz5Momentum ptotal= theRems.first ->momentum()-partons.first ->momentum()+ theRems.second->momentum()-partons.second->momentum(); // add x limits if(ptotal.m() < (pnew[0].m() + pnew[1].m()) ) { if(partons.second->id() != ParticleID::g){ if(partons.second==theMaps.second.back().first) theUsed.second -= theMaps.second.back().second->momentum(); else theUsed.second -= theMaps.second.back().first->momentum(); thestep->removeParticle(theMaps.second.back().first); thestep->removeParticle(theMaps.second.back().second); } theMaps.second.pop_back(); theX.second -= partons.second->momentum().rho()/ parent(theRems.second)->momentum().rho(); throw ShowerHandler::ExtraScatterVeto(); } } } catch(ShowerHandler::ExtraScatterVeto){ if(!partons.first||!partons.second|| !theRems.first||!theRems.second) throw ShowerHandler::ExtraScatterVeto(); //case of the first forcedSplitting worked fine theX.first -= partons.first->momentum().rho()/ parent(theRems.first)->momentum().rho(); //case of the first interaction //throw veto immediately, because event get rejected anyway. if(first) throw ShowerHandler::ExtraScatterVeto(); //secondary interactions have to end on a gluon, if parton //was NOT a gluon, the forced splitting particles must be removed if(partons.first->id() != ParticleID::g) { if(partons.first==theMaps.first.back().first) theUsed.first -= theMaps.first.back().second->momentum(); else theUsed.first -= theMaps.first.back().first->momentum(); thestep->removeParticle(theMaps.first.back().first); thestep->removeParticle(theMaps.first.back().second); } theMaps.first.pop_back(); throw ShowerHandler::ExtraScatterVeto(); } } // veto if not enough energy for extraction if( !first &&(theRems.first ->momentum().e() - partons.first ->momentum().e() < 1.0e-3*MeV || theRems.second->momentum().e() - partons.second->momentum().e() < 1.0e-3*MeV )) { if(partons.first->id() != ParticleID::g) { if(partons.first==theMaps.first.back().first) theUsed.first -= theMaps.first.back().second->momentum(); else theUsed.first -= theMaps.first.back().first->momentum(); thestep->removeParticle(theMaps.first.back().first); thestep->removeParticle(theMaps.first.back().second); } theMaps.first.pop_back(); if(partons.second->id() != ParticleID::g) { if(partons.second==theMaps.second.back().first) theUsed.second -= theMaps.second.back().second->momentum(); else theUsed.second -= theMaps.second.back().first->momentum(); thestep->removeParticle(theMaps.second.back().first); thestep->removeParticle(theMaps.second.back().second); } theMaps.second.pop_back(); throw ShowerHandler::ExtraScatterVeto(); } } void HwRemDecayer::mergeColour(tPPtr pold, tPPtr pnew, bool anti) const { ColinePtr clnew, clold; //save the corresponding colour lines clold = pold->colourLine(anti); clnew = pnew->colourLine(!anti); assert(clold); // There is already a colour line (not the final diquark) if(clnew){ if( (clnew->coloured().size() + clnew->antiColoured().size()) > 1 ){ if( (clold->coloured().size() + clold->antiColoured().size()) > 1 ){ //join the colour lines //I don't use the join method, because potentially only (anti)coloured //particles belong to one colour line if(clold!=clnew){//procs are not already connected while ( !clnew->coloured().empty() ) { tPPtr p = clnew->coloured()[0]; clnew->removeColoured(p); clold->addColoured(p); } while ( !clnew->antiColoured().empty() ) { tPPtr p = clnew->antiColoured()[0]; clnew->removeAntiColoured(p); clold->addAntiColoured(p); } } }else{ //if pold is the only member on it's //colour line, remove it. clold->removeColoured(pold, anti); //and add it to clnew clnew->addColoured(pold, anti); } } else{//pnnew is the only member on it's colour line. clnew->removeColoured(pnew, !anti); clold->addColoured(pnew, !anti); } } else {//there is no coline at all for pnew clold->addColoured(pnew, !anti); } } void HwRemDecayer::fixColours(PartnerMap partners, bool anti, double colourDisrupt) const { PartnerMap::iterator prev; tPPtr pnew, pold; assert(partners.size()>=2); PartnerMap::iterator it=partners.begin(); while(it != partners.end()) { //skip the first one to have a partner if(it==partners.begin()){ it++; continue; } prev = it - 1; //determine the particles to work with pold = prev->first; if(prev->second) { if(!pold->coloured()) pold = prev->second; else if(pold->hasAntiColour() != anti) pold = prev->second; } assert(pold); pnew = it->first; if(it->second) { if(it->second->colourLine(!anti)) //look for the opposite colour pnew = it->second; } assert(pnew); // Implement the disruption of colour connections if( it != partners.end()-1 ) {//last one is diquark-has to be connected //has to be inside the if statement, so that the probability is //correctly counted: if( UseRandom::rnd() < colourDisrupt ){ if(!it->second){//check, whether we have a gluon mergeColour(pnew, pnew, anti); }else{ if(pnew==it->first)//be careful about the order mergeColour(it->second, it->first, anti); else mergeColour(it->first, it->second, anti); } it = partners.erase(it); continue; } } // regular merging mergeColour(pold, pnew, anti); //end of loop it++; } return; } PPtr HwRemDecayer::forceSplit(const tRemPPtr rem, long child, Energy &lastQ, double &lastx, Lorentz5Momentum &pf, Lorentz5Momentum &p, HadronContent & content) const { static const double eps=1e-6; // beam momentum Lorentz5Momentum beam = theBeam->momentum(); // the last scale is minimum of last value and upper limit Energy minQ=_range*_kinCutoff*sqrt(lastx)/(1-lastx); if(minQ>lastQ) lastQ=minQ; // generate the new value of qtilde // weighted towards the lower value: dP/dQ = 1/Q -> Q(R) = // Q0 (Qmax/Q0)^R Energy q; unsigned int ntry=0,maxtry=100; double xExtracted = rem==theRems.first ? theX.first : theX.second; double zmin= lastx/(1.-xExtracted) ,zmax,yy; if(1-lastx ids; if(child==21||child==22) { ids=content.flav; for(unsigned int ix=0;ix > > partonprob; double ptotal(0.); for(unsigned int iflav=0;iflav prob; for(unsigned int iz=0;izvalue(sqr(max(wz*q,_kinCutoff))) : _alphaEM->value(sqr(max(wz*q,_kinCutoff))); double az=wz*zz*coup; // g -> q qbar if(ids[iflav]==ParticleID::g) { // calculate splitting function // SP as q is always less than forcedSplitScale, the pdf scale is fixed // pdfval = _pdf->xfx(theBeamData,in,sqr(q),lastx*zr); double pdfval=_pdf->xfx(theBeamData,in,sqr(_forcedSplitScale),lastx*zr); if(pdfval>0.) psum += pdfval*az*0.5*(sqr(zz)+sqr(wz)); } // q -> q g else { // calculate splitting function // SP as q is always less than forcedSplitScale, the pdf scale is fixed // pdfval = _pdf->xfx(theBeamData,in,sqr(q),lastx*zr); double pdfval=_pdf->xfx(theBeamData,in,sqr(_forcedSplitScale),lastx*zr); if(pdfval>0.) psum += pdfval*az*4./3.*(1.+sqr(wz))*zr; } if(psum>0.) prob.push_back(psum); yy+=dely; } if(psum>0.) partonprob[ids[iflav]] = make_pair(psum,prob); ptotal+=psum; } // select the flavour if(ptotal==0.) throw ShowerHandler::ExtraScatterVeto(); ptotal *= UseRandom::rnd(); map > >::const_iterator pit; for(pit=partonprob.begin();pit!=partonprob.end();++pit) { if(pit->second.first>=ptotal) break; else ptotal -= pit->second.first; } if(pit==partonprob.end()) throw Exception() << "Can't select parton for forced backward evolution in " << "HwRemDecayer::forceSplit" << Exception::eventerror; // select z unsigned int iz=0; for(;izsecond.second.size();++iz) { if(pit->second.second[iz]>ptotal) break; } if(iz==pit->second.second.size()) --iz; double ey=exp(ymin+dely*(float(iz+1)-UseRandom::rnd())); double z=ey/(1.+ey); Energy2 pt2=sqr((1.-z)*q)- z*sqr(_kinCutoff); // create the particle if(pit->first!=ParticleID::g) child=pit->first; PPtr parton = getParticleData(child)->produceParticle(); Energy2 emittedm2 = sqr(parton->dataPtr()->constituentMass()); // Now boost pcm and pf to z only frame Lorentz5Momentum p_ref = Lorentz5Momentum(ZERO, beam.vect()); Lorentz5Momentum n_ref = Lorentz5Momentum(ZERO, -beam.vect()); // generate phi and compute pt of branching double phi = Constants::twopi*UseRandom::rnd(); Energy pt=sqrt(pt2); Lorentz5Momentum qt = LorentzMomentum(pt*cos(phi), pt*sin(phi), ZERO, ZERO); Axis axis(p_ref.vect().unit()); if(axis.perp2()>0.) { LorentzRotation rot; double sinth(sqrt(sqr(axis.x())+sqr(axis.y()))); rot.setRotate(acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.)); qt.transform(rot); } // compute alpha for previous particle Energy2 p_dot_n = p_ref*n_ref; double lastalpha = pf*n_ref/p_dot_n; Lorentz5Momentum qtout=qt; Energy2 qtout2=-qt*qt; double alphaout=(1.-z)/z*lastalpha; double betaout=0.5*(emittedm2+qtout2)/alphaout/p_dot_n; Lorentz5Momentum k=alphaout*p_ref+betaout*n_ref+qtout; k.rescaleMass(); parton->set5Momentum(k); pf+=k; lastQ=q; lastx/=z; p += parton->momentum(); thestep->addDecayProduct(rem,parton,false); return parton; } void HwRemDecayer::setRemMasses() const { // get the masses of the remnants Energy mrem[2]; Lorentz5Momentum ptotal,pnew[2]; vector theprocessed; theprocessed.push_back(theRems.first); theprocessed.push_back(theRems.second); // one remnant in e.g. DIS if(!theprocessed[0]||!theprocessed[1]) { tRemPPtr rem = theprocessed[0] ? theprocessed[0] : theprocessed[1]; Lorentz5Momentum deltap(rem->momentum()); // find the diquark and momentum we still need in the energy tPPtr diquark; vector progenitors; for(unsigned int ix=0;ixchildren().size();++ix) { if(!DiquarkMatcher::Check(rem->children()[ix]->data())) { progenitors.push_back(rem->children()[ix]); deltap -= rem->children()[ix]->momentum(); } else diquark = rem->children()[ix]; } // now find the total momentum of the hadronic final-state to // reshuffle against // find the hadron for this remnant tPPtr hadron=rem; do hadron=hadron->parents()[0]; while(!hadron->parents().empty()); // find incoming parton to hard process from this hadron tPPtr hardin = generator()->currentEvent()->primaryCollision()->incoming().first==hadron ? generator()->currentEvent()->primarySubProcess()->incoming().first : generator()->currentEvent()->primarySubProcess()->incoming().second; tPPtr parent=hardin; vector tempprog; // find the outgoing particles emitted from the backward shower do { assert(!parent->parents().empty()); tPPtr newparent=parent->parents()[0]; if(newparent==hadron) break; for(unsigned int ix=0;ixchildren().size();++ix) { if(newparent->children()[ix]!=parent) findChildren(newparent->children()[ix],tempprog); } parent=newparent; } while(parent!=hadron); // add to list of potential particles to reshuffle against in right order for(unsigned int ix=tempprog.size();ix>0;--ix) progenitors.push_back(tempprog[ix-1]); // final-state particles which are colour connected tColinePair lines = make_pair(hardin->colourLine(),hardin->antiColourLine()); vector others; for(ParticleVector::const_iterator cit = generator()->currentEvent()->primarySubProcess()->outgoing().begin(); cit!= generator()->currentEvent()->primarySubProcess()->outgoing().end();++cit) { // colour connected if(lines.first&&lines.first==(**cit).colourLine()) { findChildren(*cit,progenitors); continue; } // anticolour connected if(lines.second&&lines.second==(**cit).antiColourLine()) { findChildren(*cit,progenitors); continue; } // not connected for(unsigned int ix=0;ix<(**cit).children().size();++ix) others.push_back((**cit).children()[ix]); } // work out how much of the system needed for rescaling unsigned int iloc=0; Lorentz5Momentum psystem,ptotal; do { psystem+=progenitors[iloc]->momentum(); ptotal = psystem + deltap; ptotal.rescaleMass(); psystem.rescaleMass(); ++iloc; if(ptotal.mass() > psystem.mass() + diquark->mass() && psystem.mass()>1*MeV && DISRemnantOpt_<2 && ptotal.e() > 0.*GeV ) break; } while(iloc psystem.mass() + diquark->mass()) --iloc; if(iloc==progenitors.size()) { // try touching the lepton in dis as a last restort for(unsigned int ix=0;ixmomentum(); ptotal = psystem + deltap; ptotal.rescaleMass(); psystem.rescaleMass(); ++iloc; } --iloc; if(ptotal.mass() > psystem.mass() + diquark->mass()) { if(DISRemnantOpt_==0||DISRemnantOpt_==2) Throw() << "Warning had to adjust the momentum of the" << " non-colour connected" << " final-state, e.g. the scattered lepton in DIS" << Exception::warning; else throw Exception() << "Can't set remnant momentum without adjusting " << "the momentum of the" << " non-colour connected" << " final-state, e.g. the scattered lepton in DIS" << " vetoing event" << Exception::eventerror; } else { throw Exception() << "Can't put the remnant on-shell in HwRemDecayer::setRemMasses()" << Exception::eventerror; } } psystem.rescaleMass(); LorentzRotation R = Utilities::getBoostToCM(make_pair(psystem, deltap)); Energy pz = SimplePhaseSpace::getMagnitude(sqr(ptotal.mass()), psystem.mass(), diquark->mass()); LorentzRotation Rs(-(R*psystem).boostVector()); Rs.boost(0.0, 0.0, pz/sqrt(sqr(pz) + sqr(psystem.mass()))); Rs = Rs*R; // put remnant on shell deltap.transform(R); deltap.setMass(diquark->mass()); deltap.setE(sqrt(sqr(diquark->mass())+sqr(pz))); deltap.rescaleRho(); R.invert(); deltap.transform(R); Rs = R*Rs; // apply transformation to required particles to absorb recoil for(unsigned int ix=0;ix<=iloc;++ix) { progenitors[ix]->deepTransform(Rs); } diquark->set5Momentum(deltap); } // two remnants else { for(unsigned int ix=0;ix<2;++ix) { if(!theprocessed[ix]) continue; pnew[ix]=Lorentz5Momentum(); for(unsigned int iy=0;iychildren().size();++iy) { pnew[ix]+=theprocessed[ix]->children()[iy]->momentum(); } mrem[ix]=sqrt(pnew[ix].m2()); } // now find the remnant remnant cmf frame Lorentz5Momentum prem[2]={theprocessed[0]->momentum(), theprocessed[1]->momentum()}; ptotal=prem[0]+prem[1]; ptotal.rescaleMass(); // boost momenta to this frame if(ptotal.m()< (pnew[0].m()+pnew[1].m())) throw Exception() << "Not enough energy in both remnants in " << "HwRemDecayer::setRemMasses() " << Exception::eventerror; Boost boostv(-ptotal.boostVector()); ptotal.boost(boostv); for(unsigned int ix=0;ix<2;++ix) { prem[ix].boost(boostv); // set the masses and energies, prem[ix].setMass(mrem[ix]); prem[ix].setE(0.5/ptotal.m()*(sqr(ptotal.m())+sqr(mrem[ix])-sqr(mrem[1-ix]))); prem[ix].rescaleRho(); // boost back to the lab prem[ix].boost(-boostv); // set the momenta of the remnants theprocessed[ix]->set5Momentum(prem[ix]); } // boost the decay products Lorentz5Momentum ptemp; for(unsigned int ix=0;ix<2;++ix) { Boost btorest(-pnew[ix].boostVector()); Boost bfmrest( prem[ix].boostVector()); for(unsigned int iy=0;iychildren().size();++iy) { ptemp=theprocessed[ix]->children()[iy]->momentum(); ptemp.boost(btorest); ptemp.boost(bfmrest); theprocessed[ix]->children()[iy]->set5Momentum(ptemp); } } } } void HwRemDecayer::initSoftInteractions(Energy ptmin, InvEnergy2 beta){ ptmin_ = ptmin; beta_ = beta; } Energy HwRemDecayer::softPt() const { Energy2 pt2(ZERO); double xmin(0.0), xmax(1.0), x(0); if(beta_ == ZERO){ return UseRandom::rnd(0.0,(double)(ptmin_/GeV))*GeV; } if(beta_ < ZERO){ xmin = 1.0; xmax = exp( -beta_*sqr(ptmin_) ); }else{ xmin = exp( -beta_*sqr(ptmin_) ); xmax = 1.0; } x = UseRandom::rnd(xmin, xmax); pt2 = 1.0/beta_ * log(1/x); if( pt2 < ZERO || pt2 > sqr(ptmin_) ) throw Exception() << "HwRemDecayer::softPt generation of pt " << "outside allowed range [0," << ptmin_/GeV << "]." << Exception::runerror; //ofstream myfile2("softPt.txt", ios::app ); //myfile2 << pt2/GeV2 <<" "<currentEventHandler()->currentCollision()->incoming()); Lorentz5Momentum P1(beam.first->momentum()), P2(beam.second->momentum()); if(dbg){ cerr << "new event --------------------\n" << *(beam.first) << *(softRems_.first) << "-------------------\n" << *(beam.second) << *(softRems_.second) << endl; } //parton mass Energy mp; if(quarkPair_){ mp = getParticleData(ParticleID::u)->constituentMass(); }else{ mp = mg_; } //Get x_g1 and x_g2 //first limits double xmin = sqr(ptmin_)/4.0/(P1+P2).m2(); double x1max = (r1.e()+abs(r1.z()))/(P1.e() + abs(P1.z())); double x2max = (r2.e()+abs(r2.z()))/(P2.e() + abs(P2.z())); double x1; if(!multiPeriph_){ //now generate according to 1/x x_g1 = xmin * exp(UseRandom::rnd(log(x1max/xmin))); x_g2 = xmin * exp(UseRandom::rnd(log(x2max/xmin))); }else{ if(valOfN_==0) return; double param = (1/(2*valOfN_+1))*initTotRap_; do{ // need 1-x instead of x to get the proper final momenta x1 = UseRandom::rndGauss(gaussWidth_, 1 - (exp(param)-1)/exp(param)); }while(x1 < 0 || x1>=1.0); x_g1 = x1max*x1; x_g2 = x2max*x1; } if(dbg) cerr << x1max << " " << x_g1 << endl << x2max << " " << x_g2 << endl; Lorentz5Momentum ig1, ig2, cmf; ig1 = x_g1*P1; ig2 = x_g2*P2; ig1.setMass(mp); ig2.setMass(mp); ig1.rescaleEnergy(); ig2.rescaleEnergy(); cmf = ig1 + ig2; //boost vector from cmf to lab Boost boostv(cmf.boostVector()); //outgoing gluons in cmf g1.setMass(mp); g2.setMass(mp); g1.setX(pt*cos(phi)); g2.setX(-pt*cos(phi)); g1.setY(pt*sin(phi)); g2.setY(-pt*sin(phi)); pz2 = cmf.m2()/4 - sqr(mp) - (pt*pt); if( pz2/GeV2 < 0.0 ){ if(dbg) cerr << "EXCEPTION not enough energy...." << endl; throw ExtraSoftScatterVeto(); } if(!multiPeriph_){ if(UseRandom::rndbool()){ pz = sqrt(pz2); }else pz = -sqrt(pz2); }else{ pz = pz2 > ZERO ? sqrt(pz2) : ZERO; } if(dbg) cerr << "pz1 has been calculated to: " << pz/GeV << endl; g1.setZ(pz); g2.setZ(-pz); g1.rescaleEnergy(); g2.rescaleEnergy(); if(dbg){ cerr << "check inv mass in cmf frame: " << (g1+g2).m()/GeV << " vs. lab frame: " << (ig1+ig2).m()/GeV << endl; } g1.boost(boostv); g2.boost(boostv); //recalc the remnant momenta Lorentz5Momentum r1old(r1), r2old(r2); r1 -= g1; r2 -= g2; try{ reShuffle(r1, r2, r1old.m(), r2old.m()); }catch(ExtraSoftScatterVeto){ r1 = r1old; r2 = r2old; throw ExtraSoftScatterVeto(); } if(dbg){ cerr << "remnant 1,2 momenta: " << r1/GeV << "--" << r2/GeV << endl; cerr << "remnant 1,2 masses: " << r1.m()/GeV << " " << r2.m()/GeV << endl; cerr << "check momenta in the lab..." << (-r1old-r2old+r1+r2+g1+g2)/GeV << endl; } } void HwRemDecayer::doSoftInteractions_old(unsigned int N) { if(N == 0) return; if(!softRems_.first || !softRems_.second) throw Exception() << "HwRemDecayer::doSoftInteractions: no " << "Remnants available." << Exception::runerror; if( ptmin_ == -1.*GeV ) throw Exception() << "HwRemDecayer::doSoftInteractions: init " << "code has not been called! call initSoftInteractions." << Exception::runerror; Lorentz5Momentum g1, g2; Lorentz5Momentum r1(softRems_.first->momentum()), r2(softRems_.second->momentum()); unsigned int tries(1), i(0); for(i=0; i maxtrySoft_) break; if(dbg){ cerr << "new try \n" << *softRems_.first << *softRems_.second << endl; } try{ softKinematics(r1, r2, g1, g2); }catch(ExtraSoftScatterVeto){ tries++; i--; continue; } PPair oldrems = softRems_; PPair gluons = make_pair(addParticle(softRems_.first, ParticleID::g, g1), addParticle(softRems_.second, ParticleID::g, g2)); //now reset the remnants with the new ones softRems_.first = addParticle(softRems_.first, softRems_.first->id(), r1); softRems_.second = addParticle(softRems_.second, softRems_.second->id(), r2); //do the colour connections pair anti = make_pair(oldrems.first->hasAntiColour(), oldrems.second->hasAntiColour()); ColinePtr cl1 = new_ptr(ColourLine()); ColinePtr cl2 = new_ptr(ColourLine()); // case 2: oldrems.first->colourLine(anti.first) ->addColoured(gluons.second,anti.second); cl2->addColoured(softRems_.first, anti.second); cl2->addColoured(gluons.second, !anti.second); oldrems.first->colourLine(anti.first) ->addColoured(gluons.second,anti.second); oldrems.second->colourLine(anti.second) ->addColoured(gluons.first,anti.first); cl1->addColoured(softRems_.second, anti.first); cl1->addColoured(gluons.first, !anti.first); cl2->addColoured(softRems_.first, anti.second); cl2->addColoured(gluons.second, !anti.second); //reset counter tries = 1; } if(dbg) cerr << "generated " << i << "th soft scatters\n"; } // Solve the reshuffling equation to rescale the remnant momenta double bisectReshuffling(const vector& particles, Energy w, double target = -16., double maxLevel = 80.) { double level = 0; double left = 0; double right = 1; double check = -1.; double xi = -1; while ( level < maxLevel ) { xi = (left+right)*pow(0.5,level+1.); check = 0.; for (vector::const_iterator p = particles.begin(); p != particles.end(); ++p){ check += sqrt(sqr(xi)*((*p)->momentum().vect().mag2())+sqr((*p)->mass()))/w; } if ( check==1. || log10(abs(1.-check)) <= target ) break; left *= 2.; right *= 2.; if ( check >= 1. ) { right -= 1.; ++level; } if ( check < 1. ) { left += 1.; ++level; } } return xi; } LorentzRotation HwRemDecayer::rotate(const LorentzMomentum &p) const { LorentzRotation R; static const double ptcut = 1e-20; Energy2 pt2 = sqr(p.x())+sqr(p.y()); Energy2 pp2 = sqr(p.z())+pt2; double phi, theta; if(pt2 <= pp2*ptcut) { if(p.z() > ZERO) theta = 0.; else theta = Constants::pi; phi = 0.; } else { Energy pp = sqrt(pp2); Energy pt = sqrt(pt2); double ct = p.z()/pp; double cf = p.x()/pt; phi = -acos(cf); theta = acos(ct); } // Rotate first around the z axis to put p in the x-z plane // Then rotate around the Y axis to put p on the z axis R.rotateZ(phi).rotateY(theta); return R; } struct vectorSort{ bool operator() (Lorentz5Momentum i,Lorentz5Momentum j) {return(i.rapidity() < j.rapidity());} } ySort; void HwRemDecayer::doSoftInteractions_multiPeriph(unsigned int N) { if(N == 0) return; int Nmpi = N; for(int j=0;jmaximumCMEnergy()); + //Energy energy(generator()->maximumCMEnergy()); //double reference = sqr(energy/TeV); // double ladderMult_; // Parametrization of the ladder multiplicity // ladderMult_ = ladderNorm_ * pow( ( reference ) , ladderPower_ ); double avgN = 2.*ladderMult_*log((softRems_.first->momentum() +softRems_.second->momentum()).m()/mg_) + ladderbFactor_; initTotRap_ = abs(softRems_.first->momentum().rapidity()) +abs(softRems_.second->momentum().rapidity()); // Generate the poisson distribution with mean avgN N=UseRandom::rndPoisson(avgN); valOfN_=N; if(N <= 1){ // j--; //TODO: Do we want to make all Nmpi soft MPIs? // Compare to MaxTryMPI for hard mpis. continue; } if(!softRems_.first || !softRems_.second) throw Exception() << "HwRemDecayer::doSoftInteractions: no " << "Remnants available." << Exception::runerror; if( ptmin_ == -1.*GeV ) throw Exception() << "HwRemDecayer::doSoftInteractions: init " << "code has not been called! call initSoftInteractions." << Exception::runerror; // The remnants PPtr rem1 = softRems_.first; PPtr rem2 = softRems_.second; // Vector for the ladder particles vector ladderMomenta; // Remnant momenta Lorentz5Momentum r1(softRems_.first->momentum()), r2(softRems_.second->momentum()); Lorentz5Momentum cm =r1+r2; // Initialize partons in the ladder // The toy masses are needed for the correct calculation of the available energy Lorentz5Momentum sumMomenta; for(unsigned int i = 0; i < N; i++) { // choose constituents Energy newMass = ZERO; Energy toyMass; if(i<2){ // u and d have the same mass so its enough to use u toyMass = getParticleData(ParticleID::u)->constituentMass(); } else{ toyMass = getParticleData(ParticleID::g)->constituentMass(); } Lorentz5Momentum cp(ZERO,ZERO,ZERO,newMass,newMass); // dummy container for the momentum that is used for momentum conservation Lorentz5Momentum dummy(ZERO,ZERO,ZERO,toyMass,toyMass); ladderMomenta.push_back(cp); sumMomenta+=dummy; } // Get the beam energy tcPPair beam(generator()->currentEventHandler()->currentCollision()->incoming()); - Lorentz5Momentum P1(beam.first->momentum()), P2(beam.second->momentum()); + //Lorentz5Momentum P1(beam.first->momentum()), P2(beam.second->momentum()); // Calculate available energy for the partons - double x1,x2; + double x1;//,x2; double param = (1./(valOfN_+1.))*initTotRap_; do{ // Need 1-x instead of x to get the proper final momenta // TODO: physical to use different x's (see comment below) x1 = UseRandom::rndGauss( gaussWidth_ , exp(-param) ); // x2 = UseRandom::rndGauss( gaussWidth_ , exp(-param) ); }while(x1 < 0 || x1>=1.0); // x2 < 0 || x2>=1.0); // Remnants 1 and 2 need to be rescaled later by this amount Lorentz5Momentum ig1 = x1*r1; Lorentz5Momentum ig2 = x1*r2; //TODO: x2*r2 // requires boost of Ladder in x1/x2-dependent // frame. // The available energy that is used to generate the ladder // sumMomenta is the the sum of rest masses of the ladder partons // the available energy goes all into the kinematics Energy availableEnergy = (ig1+ig2).m() - sumMomenta.m(); // If not enough energy then continue // The available energy has to be larger then the rest mass of the remnants if ( availableEnergy < ZERO ) { // j--; //TODO: Do we want to make all Nmpi soft MPIs? continue; } unsigned int its(0); // Generate the momenta of the partons in the ladder if ( !(doPhaseSpaceGenerationGluons(ladderMomenta,availableEnergy,its)) ){ // j--; //TODO: Do we want to make all Nmpi soft MPIs? continue; } // Add gluon mass and rescale Lorentz5Momentum totalMomPartons; Lorentz5Momentum totalMassLessPartons; // Sort the ladder partons according to their rapidity and then choose which ones will be the quarks sort(ladderMomenta.begin(),ladderMomenta.end(),ySort); int countPartons=0; long quarkID=0; // Choose between up and down quarks int choice = UseRandom::rnd2(1,1); switch (choice) { case 0: quarkID = ParticleID::u; break; case 1: quarkID = ParticleID::d; break; } for (auto &p:ladderMomenta){ totalMomPartons+=p; // Set the mass of the gluons and the two quarks in the ladder - if(countPartons==0 || countPartons==(ladderMomenta.size()-1)){ + if(countPartons==0 || countPartons==int(ladderMomenta.size()-1)){ p.setMass( getParticleData(quarkID)->constituentMass() ); }else{ p.setMass( getParticleData(ParticleID::g)->constituentMass() ); } p.rescaleEnergy(); countPartons++; } // Continue if energy conservation is violated if ( abs(availableEnergy - totalMomPartons.m()) > 1e-8*GeV){ // j--; //TODO: Do we want to make all Nmpi soft MPIs? continue; } // Boost momenta into CM frame const Boost boostv(-totalMomPartons.boostVector()); Lorentz5Momentum totalMomentumAfterBoost; for ( unsigned int i=0; i remnants; rem1->set5Momentum(r1); rem2->set5Momentum(r2); remnants.push_back(rem1); remnants.push_back(rem2); vector reshuffledRemnants; Lorentz5Momentum totalMomentumAll; // Bisect reshuffling for rescaling of remnants double xi_remnants = bisectReshuffling(remnants,remainingEnergy); // Rescale remnants for ( auto &rems: remnants ) { Lorentz5Momentum reshuffledMomentum; reshuffledMomentum = xi_remnants*rems->momentum(); reshuffledMomentum.setMass(getParticleData(softRems_.first->id())->constituentMass()); reshuffledMomentum.rescaleEnergy(); reshuffledMomentum.boost(-boostvR); rems->set5Momentum(reshuffledMomentum); totalMomentumAll+=reshuffledMomentum; } // Then the other particles for ( auto &p:ladderMomenta ) { p.boost(-boostvR); totalMomentumAll+=p; } // sort again sort(ladderMomenta.begin(),ladderMomenta.end(),ySort); // Do the colour connections // Original rems are the ones which are connected to other parts of the event PPair oldRems_ = softRems_; pair anti = make_pair(oldRems_.first->hasAntiColour(), oldRems_.second->hasAntiColour()); // Replace first remnant softRems_.first = addParticle(softRems_.first, softRems_.first->id(), remnants[0]->momentum()); // Connect the old remnant to the new remnant oldRems_.first->colourLine(anti.first)->addColoured(softRems_.first, anti.first); // Replace second remnant softRems_.second = addParticle(softRems_.second, softRems_.second->id(), remnants[1]->momentum()); // This connects the old remnants to the new remnants oldRems_.second->colourLine(anti.second)->addColoured(softRems_.second, anti.second); // Add all partons to the first remnant for the event record vector partons; vector quarks; int count=0; // Choose the colour connections and position of quark antiquark // Choose between R1-q-g..g-qbar-R2 or R1-qbar-g...g-q-R2 // (place of quark antiquarks in the ladder) int quarkPosition = UseRandom::rnd2(1,1); for (auto &p:ladderMomenta){ if(p.mass()==getParticleData(ParticleID::u)->constituentMass()){ if(count==0){ if(quarkPosition==0){ quarks.push_back(addParticle(softRems_.first, quarkID, p)); count++; }else{ quarks.push_back(addParticle(softRems_.first, -quarkID, p)); count++; } }else{ if(quarkPosition==0){ quarks.push_back(addParticle(softRems_.first, -quarkID, p)); }else{ quarks.push_back(addParticle(softRems_.first, quarkID, p)); } } }else{ partons.push_back(addParticle(softRems_.first, ParticleID::g, p)); } softRems_.first = addParticle(softRems_.first, softRems_.first->id(), softRems_.first->momentum()); oldRems_.first->colourLine(anti.first)->addColoured(softRems_.first, anti.first); } // Need to differenciate between the two quark positions, this defines the // colour connections to the new remnants and old remnants if(quarkPosition==0){ // ladder self contained if(partons.size()==0 && quarks.size()>0){ ColinePtr clq = new_ptr(ColourLine()); clq->addColoured(quarks[0]); clq->addAntiColoured(quarks[1]); } ColinePtr clfirst = new_ptr(ColourLine()); ColinePtr cllast = new_ptr(ColourLine()); if(partons.size()>0){ clfirst->addColoured(quarks[0]); clfirst->addAntiColoured(partons[0]); cllast->addAntiColoured(quarks[1]); cllast->addColoured(partons[partons.size()-1]); //now the remaining gluons for (unsigned int i=0; iaddColoured(partons[i]); cl->addAntiColoured(partons[i+1]); } } } else { if(partons.size()==0 && quarks.size()>0){ ColinePtr clq = new_ptr(ColourLine()); clq->addAntiColoured(quarks[0]); clq->addColoured(quarks[1]); } ColinePtr clfirst = new_ptr(ColourLine()); ColinePtr cllast = new_ptr(ColourLine()); if(partons.size()>0){ clfirst->addAntiColoured(quarks[0]); clfirst->addColoured(partons[0]); cllast->addColoured(quarks[1]); cllast->addAntiColoured(partons[partons.size()-1]); //now the remaining gluons for (unsigned int i=0; iaddAntiColoured(partons[i]); cl->addColoured(partons[i+1]); } } }// end colour connection loop }// end Nmpi loop }//end function // Do the phase space generation here is 1 to 1 the same from UA5 model bool HwRemDecayer::doPhaseSpaceGenerationGluons(vector &softGluons, Energy CME, unsigned int &its) const{ // Define the parameters unsigned int _maxtries = 300; double alog = log(CME*CME/GeV2); unsigned int ncl = softGluons.size(); // calculate the slope parameters for the different clusters // outside loop to save time vector mom(ncl); // Sets the slopes depending on the constituent quarks of the cluster for(unsigned int ix=0;ix xi(ncl); vector tempEnergy(ncl); Energy sum1(ZERO); double yy(0.); // We want to make sure that the first Pt is from the // desired pt-distribution. If we select the first pt in the // trial loop we introduce a bias. Energy firstPt=softPt(); while(its < _maxtries) { ++its; Energy sumx = ZERO; Energy sumy = ZERO; unsigned int iterations(0); unsigned int _maxtriesNew = 100; while(iterations < _maxtriesNew) { iterations++; Energy sumxIt = ZERO; Energy sumyIt = ZERO; bool success=false; Energy pTmax=ZERO; for(unsigned int i = 0; ipT2...pTN //2) pT1>pT2>..>pTN //3) flat //4) y dependent //5) Frist then flat int triesPt=0; Energy pt; - Energy ptTest; + //Energy ptTest; switch(PtDistribution_) { case 0: //default softPt() pt=softPt(); break; case 1: //pTordered if(i==0){ pt=softPt(); pTmax=pt; }else{ do{ pt=softPt(); }while(pt>pTmax); } break; case 2: //strongly pT ordered if ( i==0 ) { pt=softPt(); pTmax=pt; } else { do { if ( triesPt==20 ) { pt=pTmax; break; } pt=softPt(); triesPt++; } while ( pt>pTmax ); pTmax=pt; } break; case 3: //flat pt = UseRandom::rnd(0.0,(double)(ptmin_/GeV))*GeV; break; case 4: //flat below first pT if ( i==0 ) { pt = firstPt; } else { pt = firstPt * UseRandom::rnd(); } break; case 5: //flat but rising below first pT if ( i==0 ) { pt=firstPt; } else { pt = firstPt * pow(UseRandom::rnd(),1/2); } } Energy2 ptp = pt*pt; if(ptp <= ZERO) pt = - sqrt(-ptp); else pt = sqrt(ptp); // randomize azimuth Energy px,py; //randomize the azimuth, but the last one should cancel all others if(i CME) continue; // randomize the mom vector to get the first and the compensating parton // at all possible positions: long (*p_irnd)(long) = UseRandom::irnd; random_shuffle(mom.begin(),mom.end(),p_irnd); for(unsigned int i = 0; i=1; i--) xi[i+1] = (xi[i]-ximin)/ximax; xi[1] = 1.; yy= log(CME*CME/(mom[0].z()*mom[1].z())); bool suceeded=false; Energy sum2,sum3,sum4; for(unsigned int j = 0; j<10; j++) { sum1 = sum2 = sum3 = sum4 = ZERO; for(unsigned int i = 0; i 100) eps *= 10.; } if(its==_maxtries){ return false; } // throw Exception() << "Can't generate soft underlying event in " // << "UA5Handler::generateCylindricalPS" // << Exception::eventerror; double zz = log(CME/sum1); for(unsigned int i = 0; iDiquark or Rem->quark "decay" if(theRems.first) { diquarks.first = finalSplit(theRems.first, theContent.first.RemID(), theUsed.first); theMaps.first.push_back(make_pair(diquarks.first, tPPtr())); } if(theRems.second) { diquarks.second = finalSplit(theRems.second, theContent.second.RemID(), theUsed.second); theMaps.second.push_back(make_pair(diquarks.second, tPPtr())); } setRemMasses(); if(theRems.first) { fixColours(theMaps.first, theanti.first, colourDisrupt); if(theContent.first.hadron->id()==ParticleID::pomeron&& pomeronStructure_==0) fixColours(theMaps.first, !theanti.first, colourDisrupt); } if(theRems.second) { fixColours(theMaps.second, theanti.second, colourDisrupt); if(theContent.second.hadron->id()==ParticleID::pomeron&& pomeronStructure_==0) fixColours(theMaps.second, !theanti.second, colourDisrupt); } if( !theRems.first || !theRems.second ) return; //stop here if we don't have two remnants softRems_ = diquarks; doSoftInteractions(softInt); } HwRemDecayer::HadronContent HwRemDecayer::getHadronContent(tcPPtr hadron) const { HadronContent hc; hc.hadron = hadron->dataPtr(); long id(hadron->id()); // baryon if(BaryonMatcher::Check(hadron->data())) { hc.sign = id < 0? -1: 1; hc.flav.push_back((id = abs(id)/10)%10); hc.flav.push_back((id /= 10)%10); hc.flav.push_back((id /= 10)%10); hc.extracted = -1; } else if(hadron->data().id()==ParticleID::gamma || (hadron->data().id()==ParticleID::pomeron && pomeronStructure_==1)) { hc.sign = 1; for(int ix=1;ix<6;++ix) { hc.flav.push_back( ix); hc.flav.push_back(-ix); } } else if(hadron->data().id()==ParticleID::pomeron ) { hc.sign = 1; hc.flav.push_back(ParticleID::g); hc.flav.push_back(ParticleID::g); } else if(hadron->data().id()==ParticleID::reggeon ) { hc.sign = 1; for(int ix=1;ix<3;++ix) { hc.flav.push_back( ix); hc.flav.push_back(-ix); } } hc.pomeronStructure = pomeronStructure_; return hc; } long HwRemDecayer::HadronContent::RemID() const{ if(extracted == -1) throw Exception() << "Try to build a Diquark id without " << "having extracted something in " << "HwRemDecayer::RemID(...)" << Exception::runerror; //the hadron was a meson or photon if(flav.size()==2) return sign*flav[(extracted+1)%2]; long remId; int id1(sign*flav[(extracted+1)%3]), id2(sign*flav[(extracted+2)%3]), sign(0), spin(0); if (abs(id1) > abs(id2)) swap(id1, id2); sign = (id1 < 0) ? -1 : 1; // Needed for the spin 0/1 part remId = id2*1000+id1*100; // Now decide if we have spin 0 diquark or spin 1 diquark if(id1 == id2) spin = 3; // spin 1 else spin = 1; // otherwise spin 0 remId += sign*spin; return remId; } tPPtr HwRemDecayer::addParticle(tcPPtr parent, long id, Lorentz5Momentum p) const { PPtr newp = new_ptr(Particle(getParticleData(id))); newp->set5Momentum(p); // Add the new remnant to the step, but don't do colour connections thestep->addDecayProduct(parent,newp,false); return newp; } void HwRemDecayer::findChildren(tPPtr part,vector & particles) const { if(part->children().empty()) particles.push_back(part); else { for(unsigned int ix=0;ixchildren().size();++ix) findChildren(part->children()[ix],particles); } } ParticleVector HwRemDecayer::decay(const DecayMode &, const Particle &, Step &) const { throw Exception() << "HwRemDecayer::decay(...) " << "must not be called explicitely." << Exception::runerror; } void HwRemDecayer::persistentOutput(PersistentOStream & os) const { os << ounit(_kinCutoff, GeV) << _range << _zbin << _ybin << _nbinmax << _alphaS << _alphaEM << DISRemnantOpt_ << maxtrySoft_ << colourDisrupt_ << ladderPower_<< ladderNorm_ << ladderMult_ << ladderbFactor_ << pomeronStructure_ << ounit(mg_,GeV) << ounit(ptmin_,GeV) << ounit(beta_,sqr(InvGeV)) << allowTop_ << multiPeriph_ << valOfN_ << initTotRap_ << PtDistribution_; } void HwRemDecayer::persistentInput(PersistentIStream & is, int) { is >> iunit(_kinCutoff, GeV) >> _range >> _zbin >> _ybin >> _nbinmax >> _alphaS >> _alphaEM >> DISRemnantOpt_ >> maxtrySoft_ >> colourDisrupt_ >> ladderPower_ >> ladderNorm_ >> ladderMult_ >> ladderbFactor_ >> pomeronStructure_ >> iunit(mg_,GeV) >> iunit(ptmin_,GeV) >> iunit(beta_,sqr(InvGeV)) >> allowTop_ >> multiPeriph_ >> valOfN_ >> initTotRap_ >> PtDistribution_; } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigHwRemDecayer("Herwig::HwRemDecayer", "HwShower.so"); void HwRemDecayer::Init() { static ClassDocumentation documentation ("The HwRemDecayer class decays the remnant for Herwig"); static Parameter interfaceZBinSize ("ZBinSize", "The size of the vbins in z for the interpolation of the splitting function.", &HwRemDecayer::_zbin, 0.05, 0.001, 0.1, false, false, Interface::limited); static Parameter interfaceMaxBin ("MaxBin", "Maximum number of z bins", &HwRemDecayer::_nbinmax, 100, 10, 1000, false, false, Interface::limited); static Reference interfaceAlphaS ("AlphaS", "Pointer to object to calculate the strong coupling", &HwRemDecayer::_alphaS, false, false, true, false, false); static Reference interfaceAlphaEM ("AlphaEM", "Pointer to object to calculate the electromagnetic coupling", &HwRemDecayer::_alphaEM, false, false, true, false, false); static Parameter interfaceKinCutoff ("KinCutoff", "Parameter kinCutoff used to constrain qtilde", &HwRemDecayer::_kinCutoff, GeV, 0.75*GeV, 0.5*GeV, 10.0*GeV, false, false, Interface::limited); static Parameter interfaceEmissionRange ("EmissionRange", "Factor above the minimum possible value in which the forced splitting is allowed.", &HwRemDecayer::_range, 1.1, 1.0, 10.0, false, false, Interface::limited); static Switch interfaceDISRemnantOption ("DISRemnantOption", "Options for the treatment of the remnant in DIS", &HwRemDecayer::DISRemnantOpt_, 0, false, false); static SwitchOption interfaceDISRemnantOptionDefault (interfaceDISRemnantOption, "Default", "Use the minimum number of particles needed to take the recoil" " and allow the lepton to be used if needed", 0); static SwitchOption interfaceDISRemnantOptionNoLepton (interfaceDISRemnantOption, "NoLepton", "Use the minimum number of particles needed to take the recoil but" " veto events where the lepton kinematics would need to be altered", 1); static SwitchOption interfaceDISRemnantOptionAllParticles (interfaceDISRemnantOption, "AllParticles", "Use all particles in the colour connected system to take the recoil" " and use the lepton if needed.", 2); static SwitchOption interfaceDISRemnantOptionAllParticlesNoLepton (interfaceDISRemnantOption, "AllParticlesNoLepton", "Use all the particles in the colour connected system to take the" " recoil but don't use the lepton.", 3); static Parameter interfaceMaxTrySoft ("MaxTrySoft", "The maximum number of regeneration attempts for an additional soft scattering", &HwRemDecayer::maxtrySoft_, 10, 0, 100, false, false, Interface::limited); static Parameter interfacecolourDisrupt ("colourDisrupt", "Fraction of connections to additional soft subprocesses, which are colour disrupted.", &HwRemDecayer::colourDisrupt_, 1.0, 0.0, 1.0, false, false, Interface::limited); static Parameter interaceladderPower ("ladderPower", "The power factor in the ladder parameterization.", &HwRemDecayer::ladderPower_, 1.0, -5.0, 10.0, false, false, Interface::limited); static Parameter interfaceladderNorm ("ladderNorm", "The normalization factor in the ladder parameterization", &HwRemDecayer::ladderNorm_, 1.0, 0.0, 10.0, false, false, Interface::limited); static Parameter interfaceladderMult ("ladderMult", "The ladder multiplicity factor ", &HwRemDecayer::ladderMult_, 1.0, 0.0, 10.0, false, false, Interface::limited); static Parameter interfaceladderbFactor ("ladderbFactor", "The additive factor in the multiperipheral ladder multiplicity.", &HwRemDecayer::ladderbFactor_, 1.0, 0.0, 10.0, false, false, Interface::limited); static Parameter interfacegaussWidth ("gaussWidth", "The gaussian width of the fluctuation of longitudinal momentum fraction.", &HwRemDecayer::gaussWidth_, 0.1, 0.0, 1.0, false, false, Interface::limited); static Switch interfacePomeronStructure ("PomeronStructure", "Option for the treatment of the valance structure of the pomeron", &HwRemDecayer::pomeronStructure_, 0, false, false); static SwitchOption interfacePomeronStructureGluon (interfacePomeronStructure, "Gluon", "Assume the pomeron is a two gluon state", 0); static SwitchOption interfacePomeronStructureQQBar (interfacePomeronStructure, "QQBar", "Assumne the pomeron is q qbar as for the photon," " this option is not recommended and is provide for compatiblity with POMWIG", 1); static Switch interfaceAllowTop ("AllowTop", "Allow top quarks in the hadron", &HwRemDecayer::allowTop_, false, false, false); static SwitchOption interfaceAllowTopNo (interfaceAllowTop, "No", "Don't allow them", false); static SwitchOption interfaceAllowTopYes (interfaceAllowTop, "Yes", "Allow them", true); static Switch interfaceMultiPeriph ("MultiPeriph", "Use multiperipheral kinematics", &HwRemDecayer::multiPeriph_, false, false, false); static SwitchOption interfaceMultiPeriphNo (interfaceMultiPeriph, "No", "Don't use multiperipheral", false); static SwitchOption interfaceMultiPeriphYes (interfaceMultiPeriph, "Yes", "Use multiperipheral kinematics", true); static Switch interfacePtDistribution ("PtDistribution", "Options for different pT generation methods", &HwRemDecayer::PtDistribution_, 0, false, false); static SwitchOption interfacePtDistributionDefault (interfacePtDistribution, "Default", "Default generation of pT", 0); static SwitchOption interfacePtDistributionOrdered (interfacePtDistribution, "Ordered", "Ordered generation of pT,where the first pT is the hardest", 1); static SwitchOption interfacePtDistributionStronglyOrdered (interfacePtDistribution, "StronglyOrdered", "Strongly ordered generation of pT", 2); static SwitchOption interfacePtDistributionFlat (interfacePtDistribution, "Flat", "Sample from a flat pT distribution", 3); static SwitchOption interfacePtDistributionFlatOrdered (interfacePtDistribution, "FlatOrdered", "First pT normal, then flat", 4); static SwitchOption interfacePtDistributionFlatOrdered2 (interfacePtDistribution, "FlatOrdered2", "First pT normal, then flat but steep", 5); } bool HwRemDecayer::canHandle(tcPDPtr particle, tcPDPtr parton) const { if(! (StandardQCDPartonMatcher::Check(*parton) || parton->id()==ParticleID::gamma) ) { if(abs(parton->id())==ParticleID::t) { if(!allowTop_) throw Exception() << "Top is not allow as a parton in the remant handling, please " << "use a PDF which does not contain top for the remnant" << " handling (preferred) or allow top in the remnant using\n" << " set " << fullName() << ":AllowTop Yes\n" << Exception::runerror; } else return false; } return HadronMatcher::Check(*particle) || particle->id()==ParticleID::gamma || particle->id()==ParticleID::pomeron || particle->id()==ParticleID::reggeon; } bool HwRemDecayer::isPartonic(tPPtr parton) const { if(parton->parents().empty()) return false; tPPtr parent = parton->parents()[0]; bool partonic = false; for(unsigned int ix=0;ixchildren().size();++ix) { if(dynamic_ptr_cast(parent->children()[ix])) { partonic = true; break; } } return partonic; } diff --git a/Shower/Dipole/Base/Dipole.cc b/Shower/Dipole/Base/Dipole.cc --- a/Shower/Dipole/Base/Dipole.cc +++ b/Shower/Dipole/Base/Dipole.cc @@ -1,455 +1,455 @@ // -*- C++ -*- // // Dipole.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 Dipole class. // #include "Dipole.h" #include "Herwig/Shower/Dipole/Utility/DipolePartonSplitter.h" using namespace Herwig; Dipole::Dipole() : theParticles(), thePDFs(), theFractions(1.0,1.0), theIndices(), theDecaying(false,false), theOffShell(false,false), theScales(0.0*GeV,0.0*GeV) {} Dipole::Dipole(const pair& newParticles, const pair& newPDFs, pair newFractions, pair newScales) : theParticles(newParticles), thePDFs(newPDFs), theFractions(newFractions), theIndices(), theDecaying(false,false), theOffShell(false,false), theScales(newScales) { theIndices.first = DipoleIndex(theParticles.first->dataPtr(), theParticles.second->dataPtr(), newPDFs.first,newPDFs.second, theDecaying.first,theDecaying.second, theOffShell.first,theOffShell.second); theIndices.second = theIndices.first; theIndices.second.swap(); } Dipole::Dipole(const pair& newParticles, const pair& newPDFs, pair newFractions, pair decaying, pair offShell, pair newScales) : theParticles(newParticles), thePDFs(newPDFs), theFractions(newFractions), theIndices(), theDecaying(decaying), theOffShell(offShell), theScales(newScales) { theIndices.first = DipoleIndex(theParticles.first->dataPtr(), theParticles.second->dataPtr(), newPDFs.first,newPDFs.second, theDecaying.first,theDecaying.second, theOffShell.first,theOffShell.second); theIndices.second = theIndices.first; theIndices.second.swap(); } void Dipole::update() { theIndices.first = DipoleIndex(theParticles.first->dataPtr(), theParticles.second->dataPtr(), thePDFs.first,thePDFs.second, theDecaying.first,theDecaying.second, theOffShell.first,theOffShell.second); theIndices.second = theIndices.first; theIndices.second.swap(); assert(DipolePartonSplitter::colourConnected(theParticles.first, theParticles.second)); } pair Dipole::split(DipoleSplittingInfo& dsplit, bool colourSpectator, - bool subleadingNc) const { + bool ) const { // check contracts assert(dsplit.splittingKinematics()); assert(dsplit.emitterData() && dsplit.emissionData() && dsplit.spectatorData()); if ( !colourSpectator ) { assert(index(dsplit.configuration()) == dsplit.index()); assert(emitterX(dsplit.configuration()) == dsplit.emitterX()); assert(spectatorX(dsplit.configuration()) == dsplit.spectatorX()); } else { assert(emitterX(dsplit.configuration()) == dsplit.emitterX()); assert(emitterPDF(dsplit.configuration()) == dsplit.index().emitterPDF()); assert((dsplit.configuration().first ? theParticles.first->dataPtr() : theParticles.second->dataPtr()) == dsplit.index().emitterData()); } // generate full kinematics dsplit.splittingKinematics()->generateKinematics( emitter(dsplit.configuration())->momentum(), spectator(dsplit.configuration())->momentum(), dsplit); // Treat the case of decay splittings as backward evolution. // i.e. Put the new emitter and new emission or new spectator // and new emission respectively into the new dipoles. bool emitter_decay = dsplit.index().incomingDecayEmitter(); if ( emitter_decay ) assert(false); bool spectator_decay = dsplit.index().incomingDecaySpectator(); tPPtr oldSpectator = spectator(dsplit.configuration()); PPtr newSpectator; // get a new spectator if ( !colourSpectator ) { newSpectator = dsplit.spectatorData()->produceParticle( dsplit.splittingKinematics()->lastSpectatorMomentum()); DipolePartonSplitter::change(oldSpectator, newSpectator, spectatorPDF(dsplit.configuration()).pdf(), spectator_decay); dsplit.spectator(oldSpectator); dsplit.splitSpectator(newSpectator); } else { newSpectator = oldSpectator; } // perform the splitting tPPtr oldEmitter = emitter(dsplit.configuration()); PPtr newEmitter, newEmission; double z = dsplit.lastZ(); // Do not swap momenta for splittings different from g->gg or // initial state emitters bool noSwap = !(dsplit.emitterData()->id() == ParticleID::g && dsplit.emissionData()->id() == ParticleID::g ) || dsplit.index().initialStateEmitter(); if ( noSwap || z > UseRandom::rnd(1.0) ) { newEmitter = dsplit.emitterData()->produceParticle( dsplit.splittingKinematics()->lastEmitterMomentum()); newEmission = dsplit.emissionData()->produceParticle( dsplit.splittingKinematics()->lastEmissionMomentum()); } else { newEmitter = dsplit.emitterData()->produceParticle( dsplit.splittingKinematics()->lastEmissionMomentum()); newEmission = dsplit.emissionData()->produceParticle( dsplit.splittingKinematics()->lastEmitterMomentum()); } newEmitter->scale(sqr(dsplit.lastPt())); newEmission->scale(sqr(dsplit.lastPt())); newSpectator->scale(oldSpectator->scale()); DipolePartonSplitter::split(oldEmitter,newEmitter,newEmission, oldSpectator,emitterPDF(dsplit.configuration()).pdf(), emitter_decay); dsplit.emitter(oldEmitter); dsplit.splitEmitter(newEmitter); dsplit.emission(newEmission); double emitter_x = emitterX(dsplit.configuration()) / dsplit.lastEmitterZ(); double spectator_x = spectatorX(dsplit.configuration()) / dsplit.lastSpectatorZ(); PDF emitter_pdf = emitterPDF(dsplit.configuration()); PDF spectator_pdf = spectatorPDF(dsplit.configuration()); // Communicate off-shell parton flags // Note that as gluons aren't off-shell, the only possibility // in qcd splittings is gluon emissions off an off-shell emitter // -> off-shell emitter => off-shell new emitter bool emitter_off_shell = dsplit.index().offShellEmitter(); bool spectator_off_shell = dsplit.index().offShellSpectator(); // now check how we need to arrange the children // assignment is 0 = emitter, 1 = emission, 2 = spectator int left = 0; int middle = 1; int right = 2; if (dsplit.configuration().first) { // spectator is unique right = 2; // middle is the one connecting to the spectator if (DipolePartonSplitter::colourConnected(newSpectator,newEmission)) { middle = 1; left = 0; } else { assert(DipolePartonSplitter::colourConnected(newSpectator,newEmitter)); middle = 0; left = 1; } } else { // spectator is unique left = 2; // middle is the one connecting to the spectator if (DipolePartonSplitter::colourConnected(newSpectator,newEmission)) { middle = 1; right = 0; } else { assert(DipolePartonSplitter::colourConnected(newSpectator,newEmitter)); middle = 0; right = 1; } } pair left_particles; pair right_particles; pair left_pdfs; pair right_pdfs; pair left_fractions; pair right_fractions; // Pairs containing indicators for decayed particles pair left_decays = {false,false}; pair right_decays = {false,false}; // Pairs containing indicators for off-shell particles pair left_off_shells = {false,false}; pair right_off_shells = {false,false}; switch (left) { case 0: if (emitter_decay) { assert(false); left_decays.first = emitter_decay; } left_particles.first = newEmitter; left_pdfs.first = emitter_pdf; left_fractions.first = emitter_x; left_off_shells.first = emitter_off_shell; break; case 1: left_particles.first = newEmission; left_pdfs.first = PDF(); left_fractions.first = 1.; left_decays.first = false; left_off_shells.first = false; break; case 2: left_particles.first = newSpectator; left_pdfs.first = spectator_pdf; left_fractions.first = spectator_x; left_decays.first = spectator_decay; left_off_shells.first = spectator_off_shell; break; } switch (middle) { case 0: if (emitter_decay) { assert(false); left_decays.second = emitter_decay; } left_particles.second = newEmitter; left_pdfs.second = emitter_pdf; left_fractions.second = emitter_x; left_off_shells.second = emitter_off_shell; break; case 1: left_particles.second = newEmission; left_pdfs.second = PDF(); left_fractions.second = 1.; left_decays.second = false; left_off_shells.second = false; break; case 2: left_decays.second = spectator_decay; left_particles.second = newSpectator; left_pdfs.second = spectator_pdf; left_fractions.second = spectator_x; left_off_shells.second = spectator_off_shell; break; } right_particles.first = left_particles.second; right_pdfs.first = left_pdfs.second; right_fractions.first = left_fractions.second; right_decays.first = left_decays.second; right_off_shells.first = left_off_shells.second; switch (right) { case 0: if (emitter_decay) { assert(false); right_decays.second = emitter_decay; } right_particles.second = newEmitter; right_pdfs.second = emitter_pdf; right_fractions.second = emitter_x; right_off_shells.second = emitter_off_shell; break; case 1: right_particles.second = newEmission; right_pdfs.second = PDF(); right_fractions.second = 1.; right_decays.second = false; right_off_shells.second = false; break; case 2: right_particles.second = newSpectator; right_pdfs.second = spectator_pdf; right_fractions.second = spectator_x; right_decays.second = spectator_decay; right_off_shells.second = spectator_off_shell; break; } Energy scale = dsplit.lastPt(); return { Dipole(left_particles, left_pdfs, left_fractions, left_decays, left_off_shells, {scale,scale}), Dipole(right_particles, right_pdfs, right_fractions, right_decays, right_off_shells, {scale,scale})}; } void Dipole::tmpsplit(DipoleSplittingInfo& dsplit, bool colourSpectator) const { // generate full kinematics dsplit.splittingKinematics()->generateKinematics(emitter(dsplit.configuration())->momentum(), spectator(dsplit.configuration())->momentum(), dsplit); tPPtr oldSpectator = spectator(dsplit.configuration()); PPtr newSpectator; // get a new spectator if ( !colourSpectator ) { newSpectator = dsplit.spectatorData()->produceParticle(dsplit.splittingKinematics()->lastSpectatorMomentum()); dsplit.spectator(oldSpectator); dsplit.splitSpectator(newSpectator); } else { newSpectator = oldSpectator; } // perform the splitting tPPtr oldEmitter = emitter(dsplit.configuration()); PPtr newEmitter = dsplit.emitterData()->produceParticle(dsplit.splittingKinematics()->lastEmitterMomentum()); PPtr newEmission = dsplit.emissionData()->produceParticle(dsplit.splittingKinematics()->lastEmissionMomentum()); dsplit.emitter(oldEmitter); dsplit.splitEmitter(newEmitter); dsplit.emission(newEmission); } void Dipole::recoil (DipoleSplittingInfo& dsplit) { // check contracts assert(dsplit.splittingKinematics()); assert(dsplit.spectatorData()); assert(spectatorX(dsplit.spectatorConfiguration()) == dsplit.spectatorX()); assert(spectatorPDF(dsplit.spectatorConfiguration()) == dsplit.index().spectatorPDF()); assert((dsplit.spectatorConfiguration().first ? theParticles.first->dataPtr() : theParticles.second->dataPtr()) == dsplit.index().spectatorData()); tPPtr oldSpectator = spectator(dsplit.spectatorConfiguration()); PPtr newSpectator = dsplit.spectatorData()->produceParticle( dsplit.splittingKinematics()->lastSpectatorMomentum()); DipolePartonSplitter::change(oldSpectator,newSpectator, spectatorPDF(dsplit.spectatorConfiguration()).pdf()); newSpectator->scale(sqr(dsplit.lastPt())); dsplit.spectator(oldSpectator); dsplit.splitSpectator(newSpectator); if ( dsplit.spectatorConfiguration().first ) { theParticles.second = newSpectator; theFractions.second /= dsplit.lastSpectatorZ(); } else { theParticles.first = newSpectator; theFractions.first /= dsplit.lastSpectatorZ(); } } void Dipole::print(ostream& os) const { os << "--- "; // Check for decays first if ( theDecaying.first || theDecaying.second) { assert(!(theDecaying.first && theDecaying.second)); if ( theDecaying.first && !theDecaying.second ) os << "Decay IF"; else if ( theDecaying.second && !theDecaying.first ) os << "Decay FI"; } else if ( !thePDFs.first.pdf() && !thePDFs.second.pdf() ) os << "FF"; else if ( thePDFs.first.pdf() && !thePDFs.second.pdf() ) os << "IF"; else if ( !thePDFs.first.pdf() && thePDFs.second.pdf() ) os << "FI"; else os << "II"; os << " Dipole ------------------------------------------------------------------\n"; if ( !theParticles.first || !theParticles.second ) { os << " *** This Dipole has not been setup properly. ***\n"; } else { os << " particles\n" << *theParticles.first << *theParticles.second; os << " scales/GeV = (" << (theScales.first/GeV) << "," << (theScales.second/GeV) << ") fractions = (" << theFractions.first << "," << theFractions.second << ")\n"; } os << "--------------------------------------------------------------------------------\n"; os << flush; } diff --git a/Shower/Dipole/Base/DipoleEventRecord.cc b/Shower/Dipole/Base/DipoleEventRecord.cc --- a/Shower/Dipole/Base/DipoleEventRecord.cc +++ b/Shower/Dipole/Base/DipoleEventRecord.cc @@ -1,1965 +1,1965 @@ // -*- C++ -*- // // DipoleEventRecord.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 DipoleEventRecord class. // #include "DipoleEventRecord.h" #include "Herwig/Shower/Dipole/DipoleShowerHandler.h" #include "Herwig/Shower/Dipole/Utility/DipolePartonSplitter.h" #include "Herwig/Shower/ShowerHandler.h" #include "ThePEG/PDT/DecayMode.h" #include "Herwig/Decay/HwDecayerBase.h" #include "ThePEG/Repository/EventGenerator.h" #include "ThePEG/PDF/PartonExtractor.h" #include "Herwig/Shower/RealEmissionProcess.h" #include "Herwig/MatrixElement/Matchbox/Base/MatchboxMEBase.h" #include "Herwig/MatrixElement/Matchbox/Base/MatchboxAmplitude.h" #include #include #include using namespace Herwig; PList DipoleEventRecord::colourOrdered(PPair & in, PList & out) { PList colour_ordered; size_t done_size = out.size(); if (in.first->coloured()) ++done_size; if (in.second && in.second->coloured()) ++done_size; while (colour_ordered.size() != done_size) { PPtr current; // start with singlets, as long as we have some if (find(colour_ordered.begin(),colour_ordered.end(),in.first) == colour_ordered.end() && in.first->coloured()) { if (!in.first->hasColour() || !in.first->hasAntiColour()) current = in.first; } if (!current) { for (PList::iterator p = out.begin(); p != out.end(); ++p) { if (find(colour_ordered.begin(),colour_ordered.end(),*p) == colour_ordered.end() && (**p).coloured()) { if (!(**p).hasColour() || !(**p).hasAntiColour()) { current = *p; break; } } } } if (!current) { if (in.second && find(colour_ordered.begin(),colour_ordered.end(),in.second) == colour_ordered.end() && in.second->coloured()) { if (!in.second->hasColour() || !in.second->hasAntiColour()) current = in.second; } } // then go on with anything else if (!current) { if (find(colour_ordered.begin(),colour_ordered.end(),in.first) == colour_ordered.end() && in.first->coloured()) { current = in.first; } } if (!current) { for (PList::iterator p = out.begin(); p != out.end(); ++p) { if (find(colour_ordered.begin(),colour_ordered.end(),*p) == colour_ordered.end() && (**p).coloured()) { current = *p; break; } } } if (!current) { if (in.second && find(colour_ordered.begin(),colour_ordered.end(),in.second) == colour_ordered.end() && in.second->coloured()) { current = in.second; } } assert(current); PPtr next; Ptr::ptr walk_the_line; while (true) { if (!walk_the_line) { if (current->hasColour()) { walk_the_line = current->colourLine(); } else if (current->hasAntiColour()) { walk_the_line = current->antiColourLine(); } } if (!next) for (tPVector::const_iterator p = walk_the_line->coloured().begin(); p != walk_the_line->coloured().end(); ++p) { if (*p == current) continue; if (find(out.begin(),out.end(),*p) != out.end() || *p == in.first || (in.second && *p == in.second)) { next = *p; if (next->hasColour() && next->hasAntiColour()) { walk_the_line = walk_the_line == next->colourLine() ? next->antiColourLine() : next->colourLine(); } break; } } if (!next) for (tPVector::const_iterator p = walk_the_line->antiColoured().begin(); p != walk_the_line->antiColoured().end(); ++p) { if (*p == current) continue; if (find(out.begin(),out.end(),*p) != out.end() || *p == in.first || (in.second && *p == in.second)) { next = *p; if (next->hasColour() && next->hasAntiColour()) { walk_the_line = walk_the_line == next->colourLine() ? next->antiColourLine() : next->colourLine(); } break; } } assert(next); colour_ordered.push_back(current); current = next; // done if next is not a gluon or next is already in colour_ordered if ((current->hasColour() && !current->hasAntiColour()) || (!current->hasColour() && current->hasAntiColour())) { colour_ordered.push_back(current); break; } if (next->hasColour() && next->hasAntiColour()) { if (find(colour_ordered.begin(),colour_ordered.end(),next) != colour_ordered.end()) break; } next = PPtr(); } } return colour_ordered; } void DipoleEventRecord::popChain() { assert(!theChains.empty()); theDoneChains.push_back(DipoleChain()); theDoneChains.back().dipoles().splice(theDoneChains.back().dipoles().begin(),theChains.front().dipoles()); theChains.pop_front(); } void DipoleEventRecord::popChain(list::iterator ch) { assert(!theChains.empty()); theDoneChains.push_back(DipoleChain()); theDoneChains.back().dipoles().splice(theDoneChains.back().dipoles().begin(),ch->dipoles()); theChains.erase(ch); } void DipoleEventRecord::popChains(const list::iterator>& chs) { assert(!theChains.empty()); for ( list::iterator>::const_iterator ch = chs.begin(); ch != chs.end(); ++ch ) { theDoneChains.push_back(DipoleChain()); theDoneChains.back().dipoles().splice(theDoneChains.back().dipoles().begin(),(*ch)->dipoles()); } for ( list::iterator>::const_iterator ch = chs.begin(); ch != chs.end(); ++ch ) theChains.erase(*ch); } DipoleIndex DipoleEventRecord::mergeIndex(list::iterator firstDipole, const pair& whichFirst, list::iterator secondDipole, const pair& whichSecond) const { tcPDPtr emitterData = whichFirst.first ? firstDipole->leftParticle()->dataPtr() : firstDipole->rightParticle()->dataPtr(); tcPDPtr spectatorData = whichSecond.first ? secondDipole->leftParticle()->dataPtr() : secondDipole->rightParticle()->dataPtr(); const PDF& emitterPDF = whichFirst.first ? firstDipole->leftPDF() : firstDipole->rightPDF(); const PDF& spectatorPDF = whichSecond.first ? secondDipole->leftPDF() : secondDipole->rightPDF(); return DipoleIndex(emitterData,spectatorData,emitterPDF,spectatorPDF); } SubleadingSplittingInfo DipoleEventRecord::mergeSplittingInfo(list::iterator firstChain, list::iterator firstDipole, const pair& whichFirst, list::iterator secondChain, list::iterator secondDipole, const pair& whichSecond) const { SubleadingSplittingInfo res; res.index(mergeIndex(firstDipole,whichFirst,secondDipole,whichSecond)); res.emitter(whichFirst.first ? firstDipole->leftParticle() : firstDipole->rightParticle()); res.spectator(whichSecond.first ? secondDipole->leftParticle() : secondDipole->rightParticle()); res.emitterX(whichFirst.first ? firstDipole->leftFraction() : firstDipole->rightFraction()); res.spectatorX(whichSecond.first ? secondDipole->leftFraction() : secondDipole->rightFraction()); res.configuration(whichFirst); res.spectatorConfiguration(whichSecond); res.emitterChain(firstChain); res.emitterDipole(firstDipole); res.spectatorChain(secondChain); res.spectatorDipole(secondDipole); return res; } void DipoleEventRecord::getSubleadingSplittings(list& res) { static pair left(true,false); static pair right(false,true); res.clear(); for ( list::iterator cit = theChains.begin(); cit != theChains.end(); ++cit ) { for ( list::iterator dit = cit->dipoles().begin(); dit != cit->dipoles().end(); ++dit ) { for ( list::iterator djt = dit; djt != cit->dipoles().end(); ++djt ) { res.push_back(mergeSplittingInfo(cit,dit,left,cit,djt,left)); res.push_back(mergeSplittingInfo(cit,dit,right,cit,djt,right)); if ( dit != djt ) { res.push_back(mergeSplittingInfo(cit,dit,left,cit,djt,right)); res.push_back(mergeSplittingInfo(cit,dit,right,cit,djt,left)); } } } list::iterator cjt = cit; ++cjt; for ( ; cjt != theChains.end(); ++cjt ) { for ( list::iterator dit = cit->dipoles().begin(); dit != cit->dipoles().end(); ++dit ) { for ( list::iterator djt = cjt->dipoles().begin(); djt != cjt->dipoles().end(); ++djt ) { res.push_back(mergeSplittingInfo(cit,dit,left,cjt,djt,left)); res.push_back(mergeSplittingInfo(cit,dit,right,cjt,djt,right)); res.push_back(mergeSplittingInfo(cit,dit,left,cjt,djt,right)); res.push_back(mergeSplittingInfo(cit,dit,right,cjt,djt,left)); } } } } } void DipoleEventRecord::splitSubleading(SubleadingSplittingInfo& dsplit, pair::iterator,list::iterator>& childIterators, DipoleChain*& firstChain, DipoleChain*& secondChain) { if ( dsplit.emitterDipole() == dsplit.spectatorDipole() ) { assert(dsplit.emitterChain() == dsplit.spectatorChain()); split(dsplit.emitterDipole(),dsplit.emitterChain(),dsplit, childIterators,firstChain,secondChain,false); } else { // first need to recoil, then split recoil(dsplit.spectatorDipole(),dsplit.spectatorChain(),dsplit); split(dsplit.emitterDipole(),dsplit.emitterChain(),dsplit, childIterators,firstChain,secondChain,true); } } void DipoleEventRecord::findChains(const PList& ordered, const set& offShellPartons, const bool decay) { // All uses of findChains should guarantee // a non-empty list of particles assert( !ordered.empty() ); theChains.clear(); theDoneChains.clear(); DipoleChain current_chain; // this whole thing needs to have a more elegant implementation at some point bool startIsTriplet = (ordered.front()->hasColour() && !ordered.front()->hasAntiColour()) || (!ordered.front()->hasColour() && ordered.front()->hasAntiColour()); bool endIsTriplet = (ordered.back()->hasColour() && !ordered.back()->hasAntiColour()) || (!ordered.back()->hasColour() && ordered.back()->hasAntiColour()); if (!( ordered.size() == 2 && startIsTriplet && endIsTriplet)) { PList::const_iterator theStart = ordered.begin(); bool onceMore = false; for (PList::const_iterator p = ordered.begin(); p != ordered.end(); ++p) { PList::const_iterator next_it = p != --ordered.end() ? std::next(p) : ordered.begin(); if (!DipolePartonSplitter::colourConnected(*p,*next_it)) { // it may have happened that we need to close the chain due to another // chain starting right now; see the above global comment for this fix bool startIsOctet = (**theStart).hasColour() && (**theStart).hasAntiColour(); bool endIsOctet = (**p).hasColour() && (**p).hasAntiColour(); if ( DipolePartonSplitter::colourConnected(*p,*theStart) && startIsOctet && endIsOctet ) { swap(next_it,theStart); onceMore = true; } else { theStart = next_it; current_chain.check(); // Randomize the chains agains biasing of directions. if(UseRandom::rndbool()) theChains.push_back(current_chain); else theChains.insert(theChains.begin(),current_chain); current_chain.dipoles().clear(); continue; } } pair initial_state (false,false); initial_state.first = (*p == incoming().first || *p == incoming().second); initial_state.second = (*next_it == incoming().first || *next_it == incoming().second); pair which_in (-1,-1); if (initial_state.first) which_in.first = *p == incoming().first ? 0 : 1; if (initial_state.second) which_in.second = *next_it == incoming().first ? 0 : 1; pair xs (1.,1.); if (initial_state.first) xs.first = *p == incoming().first ? fractions().first : fractions().second; if (initial_state.second) xs.second = *next_it == incoming().first ? fractions().first : fractions().second; pair pdf; if ( which_in.first == 0 ) pdf.first = pdfs().first; else if ( which_in.first == 1 ) pdf.first = pdfs().second; if ( which_in.second == 0 ) pdf.second = pdfs().first; else if ( which_in.second == 1 ) pdf.second = pdfs().second; // In the case of a decay process register which // parton is incoming to the decay pair decayed_parton (false,false); if (decay) { decayed_parton.first = (*p == currentDecay()->incoming()[0].first); decayed_parton.second = (*next_it == currentDecay()->incoming()[0].first); } // Identify if either parton can have an off-shell mass // The first test for partons with zero nominal mass should // avoid issues of e.g. non-zero mass gluons pair off_shell (false,false); // Note we could do away with the offShellPartons set but, // to be safe in the case of an off-shell parton with a mass // *very* close to its on-shell mass, we would need to include tests on the // offShell indicators in the DipoleIndex == and < operators AND // in canHandle and canHandleEquivalent in each massive kernel. // Testing these in every splitting will probably be more expensive // than doing the following checks for each hard process and decay process // Only do off-shell check if the nominal mass is non-zero if ( (*p)->nominalMass() != ZERO ) { if ( offShellPartons.find(abs((*p)->id())) != offShellPartons.end() ) off_shell.first = true; else assert( abs((*p)->mass() - (*p)->nominalMass()) < (*p)->nominalMass()*1.e-5 && "There is an off-shell coloured particle in the hard process or a decay" "which needs to be added to DipoleShowerHandler:OffShellInShower." ); } if ( (*next_it)->nominalMass() != ZERO ) { if ( offShellPartons.find(abs((*next_it)->id())) != offShellPartons.end() ) off_shell.second = true; else assert( abs((*next_it)->mass() - (*next_it)->nominalMass()) < (*next_it)->nominalMass()*1.e-5 && "There is an off-shell coloured particle in the hard process or a decay" "which needs to be added to DipoleShowerHandler:OffShellInShower." ); } current_chain.dipoles().push_back(Dipole({*p,*next_it},pdf,xs, decayed_parton, off_shell)); if ( onceMore ) { next_it = theStart; current_chain.check(); // Randomize the chains agains biasing of directions. if(UseRandom::rndbool()) theChains.push_back(current_chain); else theChains.insert(theChains.begin(),current_chain); current_chain.dipoles().clear(); onceMore = false; } } } else { // treat 2 -> singlet, singlet -> 2 and 1 + singlet -> 1 + singlet special // to prevent duplicate dipole assert(DipolePartonSplitter::colourConnected(ordered.front(),ordered.back())); pair initial_state (false,false); initial_state.first = (ordered.front() == incoming().first || ordered.front() == incoming().second); initial_state.second = (ordered.back() == incoming().first || ordered.back() == incoming().second); pair which_in (-1,-1); if (initial_state.first) which_in.first = ordered.front() == incoming().first ? 0 : 1; if (initial_state.second) which_in.second = ordered.back() == incoming().first ? 0 : 1; pair xs (1.,1.); if (initial_state.first) xs.first = ordered.front() == incoming().first ? fractions().first : fractions().second; if (initial_state.second) xs.second = ordered.back() == incoming().first ? fractions().first : fractions().second; pair pdf; if ( which_in.first == 0 ) pdf.first = pdfs().first; else if ( which_in.first == 1 ) pdf.first = pdfs().second; if ( which_in.second == 0 ) pdf.second = pdfs().first; else if ( which_in.second == 1 ) pdf.second = pdfs().second; // In the case of a decay process register which // parton is incoming to the decay pair decayed_parton (false,false); if (decay) { decayed_parton.first = (ordered.front() == currentDecay()->incoming()[0].first); decayed_parton.second = (ordered.back() == currentDecay()->incoming()[0].first); } // Identify if either parton can have an off-shell mass // The first test for partons with zero nominal mass should // avoid issues of e.g. non-zero mass gluons pair off_shell (false,false); // Only do off-shell check if the nominal mass is non-zero if ( ordered.front()->nominalMass() != ZERO ) { if ( offShellPartons.find(abs(ordered.front()->id())) != offShellPartons.end() ) off_shell.first = true; else assert( abs(ordered.front()->mass() - ordered.front()->nominalMass()) < ordered.front()->nominalMass()*1.e-5 && "There is an off-shell coloured particle in the hard process or a decay" "which needs to be added to DipoleShowerHandler:OffShellInShower." ); } if ( ordered.back()->nominalMass() != ZERO ) { if ( offShellPartons.find(abs(ordered.back()->id())) != offShellPartons.end() ) off_shell.second = true; else assert( abs(ordered.back()->mass() - ordered.back()->nominalMass()) < ordered.back()->nominalMass()*1.e-5 && "There is an off-shell coloured particle in the hard process or a decay" "which needs to be added to DipoleShowerHandler:OffShellInShower." ); } current_chain.dipoles().push_back(Dipole({ordered.front(),ordered.back()}, pdf,xs, decayed_parton, off_shell)); } if (!current_chain.dipoles().empty()) { current_chain.check(); // Randomize the chains agains biasing of directions. if(UseRandom::rndbool()) theChains.push_back(current_chain); else theChains.insert(theChains.begin(),current_chain); } } const map& DipoleEventRecord::prepare(tSubProPtr subpro, tStdXCombPtr xc, StepPtr step, const pair& pdf,tPPair beam, bool firstInteraction, const set& offShellPartons, bool dipoles) { // set the subprocess subProcess(subpro); // clear the event record outgoing().clear(); theHard.clear(); theOriginals.clear(); theDecays.clear(); theCurrentDecay = PerturbativeProcessPtr(); subEmDone = 0; if ( doSubleadingNc && firstInteraction ) { theDensityOperator.clear(); continueSubleadingNc = true; const Ptr::tptr MBXCombPtr = dynamic_ptr_cast::tptr >(xc); if ( !MBXCombPtr ) { throw Exception() << "Cannot cast StandardXComb as MatchboxXComb. " << "Matchbox is required for " << "colour matrix element corrections." << Exception::runerror; } // Set the colour basis if it has not been set if ( !theDensityOperator.colourBasis() ) { theDensityOperator.colourBasis(MBXCombPtr->matchboxME()->matchboxAmplitude()->colourBasis()); } else if ( theDensityOperator.colourBasis() != MBXCombPtr->matchboxME()->matchboxAmplitude()->colourBasis() ) { throw Exception() << "The colour basis used in the colour matrix " << "element corrections should not change between events. " << Exception::runerror; } } else { continueSubleadingNc = false; } // extract incoming particles PPair in = subpro->incoming(); // get the incoming momentum fractions // don't take these from the XComb as it may be null pair xs; ThePEG::Direction<0> dir(true); xs.first = in.first->momentum().dirPlus()/beam.first->momentum().dirPlus(); dir.reverse(); xs.second = in.second->momentum().dirPlus()/beam.second->momentum().dirPlus(); xcombPtr(xc); pdfs() = pdf; fractions() = xs; // use ShowerHandler to split up the hard process PerturbativeProcessPtr hard; DecayProcessMap decay; // Special handling for the first interaction: // If a post subprocess handler (e.g. QED radiation) // is applied, there may be particles in the step object not // present in the subprocess object (other than any remnants). // These need to be included in any transformations due to // II splittings in ::update. if ( firstInteraction ) { // Initialise a PVector for the outgoing tPVector hardProcOutgoing; // Include all outgoing particles that are not remnants for ( auto & part : step->particles() ) if ( part->id() != 82 ) { hardProcOutgoing.push_back(part); } ShowerHandler::currentHandler()->splitHardProcess(hardProcOutgoing, hard, decay); } // For secondary collisions we must use the // subProcess object and not the step as the // step stores all outgoing from the entire collision else ShowerHandler::currentHandler()->splitHardProcess(tPVector(subpro->outgoing().begin(), subpro->outgoing().end()), hard,decay); // vectors for originals and copies of the particles vector original; vector copies; // fill originals for(unsigned int ix=0;ix<2;++ix) original.push_back(hard->incoming()[ix].first); for(unsigned int ix=0;ixoutgoing().size();++ix) original.push_back(hard->outgoing()[ix].first); for(DecayProcessMap::const_iterator it=decay.begin();it!=decay.end();++it) { fillFromDecays(it->second, original); } // and make copies for ( vector::const_iterator p = original.begin(); p != original.end(); ++p ) { PPtr copy = new_ptr(Particle(**p)); copies.push_back(copy); theOriginals[*p] = copy; } // isolate the colour of the copies from the originals colourIsolate(original,copies); // set the incoming particles incoming().first = copies[0]; ParticleVector children = incoming().first->children(); for ( ParticleVector::const_iterator c = children.begin(); c != children.end(); ++c ) incoming().first->abandonChild(*c); incoming().second = copies[1]; children = incoming().second->children(); for ( ParticleVector::const_iterator c = children.begin(); c != children.end(); ++c ) incoming().second->abandonChild(*c); // set the outgoing particles for the hard process for(unsigned int ix=0;ixoutgoing().size();++ix) { if(hard->outgoing()[ix].first->coloured()) outgoing().push_back(theOriginals[hard->outgoing()[ix].first]); else theHard.push_back(theOriginals[hard->outgoing()[ix].first]); } if ( dipoles ) { PList cordered = colourOrdered(incoming(),outgoing()); if ( !cordered.empty() ) findChains(cordered, offShellPartons, false); } // sort out the decays for(auto const & dec : decay) { // If the decay particle is in original it needs // to be added to the decays and the decay needs to be // changed to the copied particles. if ( theOriginals.find(dec.second->incoming()[0].first) != theOriginals.end() ) { theDecays[theOriginals[dec.second->incoming()[0].first]] = dec.second; PerturbativeProcessPtr decayProc = theDecays[theOriginals[dec.second->incoming()[0].first]]; separateDecay(decayProc); } else { assert( find( copies.begin(), copies.end(), dec.second->incoming()[0].first ) != copies.end() ); theDecays[dec.second->incoming()[0].first] = dec.second; } } PList::const_iterator XFirst, XLast; if ( !theHard.empty() ) { XFirst = theHard.begin(); XLast = theHard.end(); } else { XFirst = outgoing().begin(); XLast = outgoing().end(); } thePX = (**XFirst).momentum(); ++XFirst; for ( ; XFirst != XLast; ++XFirst ) thePX += (**XFirst).momentum(); identifyEventType(); if ( doSubleadingNc ) { theParticlesBefore.clear(); theParticlesAfter.clear(); theMomentaAfter.clear(); theParticleIndices.clear(); // Set the particles and fill the dictionary theParticleIndices[incoming().first] = 0; theParticleIndices[incoming().second] = 1; size_t i = 2; theParticlesAfter.reserve(2 + outgoing().size() + theHard.size()); theParticlesAfter.push_back(incoming().first->dataPtr()); theParticlesAfter.push_back(incoming().second->dataPtr()); theMomentaAfter.push_back(incoming().first->momentum()); theMomentaAfter.push_back(incoming().second->momentum()); for ( PList::const_iterator it = outgoing().begin(); it != outgoing().end(); it++ ) { theParticlesAfter.push_back((*it)->dataPtr()); theMomentaAfter.push_back((*it)->momentum()); theParticleIndices[*it] = i; i++; } // theHard is not added to theParticleIndices, as they aren't needed there for ( PList::const_iterator it = theHard.begin(); it != theHard.end(); it++ ) { theParticlesAfter.push_back((*it)->dataPtr()); theMomentaAfter.push_back((*it)->momentum()); } // theParticlesAfter is required for fill const Ptr::tptr MBXCombPtr = dynamic_ptr_cast::tptr >(xc); if ( !MBXCombPtr ) { throw Exception() << "Cannot cast StandardXComb as MatchboxXComb. " << "Matchbox is required for " << "colour matrix element corrections." << Exception::runerror; } theDensityOperator.fill(MBXCombPtr,theParticlesAfter,theMomentaAfter); } return theOriginals; } void DipoleEventRecord::slimprepare(tSubProPtr subpro, tStdXCombPtr xc, const pair& pdf,tPPair beam, const set& offShellPartons, bool dipoles) { // set the subprocess subProcess(subpro); // clear the event record outgoing().clear(); theHard.clear(); theOriginals.clear(); theDecays.clear(); theCurrentDecay = PerturbativeProcessPtr(); // extract incoming particles PPair in = subpro->incoming(); // get the beam // get the incoming momentum fractions // don't take these from the XComb as it may be null pair xs; ThePEG::Direction<0> dir(true); xs.first = in.first->momentum().dirPlus()/beam.first->momentum().dirPlus(); dir.reverse(); xs.second = in.second->momentum().dirPlus()/beam.second->momentum().dirPlus(); xcombPtr(xc); pdfs() = pdf; fractions() = xs; incoming() = in; for(unsigned int ix=0;ixoutgoing().size();++ix) { if(subpro->outgoing()[ix]->coloured()) outgoing().push_back(subpro->outgoing()[ix]); } if ( dipoles ) { PList cordered = colourOrdered(incoming(),outgoing()); if ( !cordered.empty() ) findChains(cordered, offShellPartons, false); } } void DipoleEventRecord::fillFromDecays(PerturbativeProcessPtr decayProc, vector& original) { // Loop over the outgoing of the given perturbative process for ( auto const & outIt : decayProc->outgoing() ) { // Add the outgoing particle to the vector of original particles original.push_back(outIt.first); // Iterate through the outgoing if ( outIt.second ) fillFromDecays( outIt.second, original); } } void DipoleEventRecord::separateDecay(PerturbativeProcessPtr decayProc) { // Iteratively replace all entries in the incoming // with their copies. for ( auto & inIt : decayProc->incoming() ) { if ( theOriginals.find( inIt.first ) != theOriginals.end() ) inIt.first = theOriginals[inIt.first]; } // Iteratively replace all entries in the outgoing // with their copies. for ( auto & outIt : decayProc->outgoing()) { if ( theOriginals.count( outIt.first ) ) outIt.first = theOriginals[outIt.first]; if ( outIt.second ) separateDecay(outIt.second); } } void DipoleEventRecord::clear() { ShowerEventRecord::clear(); theDecays.clear(); theHard.clear(); theChains.clear(); theDoneChains.clear(); theOriginals.clear(); theDensityOperator.clear(); theParticlesBefore.clear(); theParticlesAfter.clear(); theMomentaAfter.clear(); theNextDecays.clear(); } pair DipoleEventRecord::tmpupdate(DipoleSplittingInfo& dsplit) { PVector inc; PVector out; tcPPtr IF = incoming().first; tcPPtr IS = incoming().second; tcPPtr DE = dsplit.emitter(); tcPPtr DS = dsplit.spectator(); if ( IF != DE && IF != DS ) { PPtr p = IF->data().produceParticle(IF->momentum()); inc.push_back(p); } else if ( IF == DE ) inc.push_back( dsplit.splitEmitter() ); else if ( IF == DS ) inc.push_back( dsplit.splitSpectator() ); if ( IS != DE && IS != DS ) { PPtr p = IS->data().produceParticle(IS->momentum()); inc.push_back(p); } else if ( IS == DE ) inc.push_back( dsplit.splitEmitter() ); else if ( IS == DS ) inc.push_back( dsplit.splitSpectator() ); if ( IF != DE && IS != DE) out.push_back( dsplit.splitEmitter()); if ( IF != DS && IS != DS) out.push_back( dsplit.splitSpectator()); out.push_back( dsplit.emission()); for ( tcPPtr h : theHard ){ PPtr p = h->data().produceParticle(h->momentum()); if ( dsplit.splittingKinematics()->doesTransform() ) { dsplit.splittingKinematics()->transform(p); } out.push_back(p); } for ( tcPPtr p : outgoing() ) if ( p != DE && p != DS && p != dsplit.emission() ){ PPtr ou = p->data().produceParticle(p->momentum());; if ( dsplit.splittingKinematics()->doesTransform() ){ dsplit.splittingKinematics()->transform(ou); } out.push_back(ou); } return {inc,out}; } void DipoleEventRecord::update(DipoleSplittingInfo& dsplit) { if ( continueSubleadingNc ) { subEmDone++; theParticlesBefore = theParticlesAfter; } if ( incoming().first == dsplit.emitter() ) { intermediates().push_back(dsplit.emitter()); incoming().first = dsplit.splitEmitter(); fractions().first /= dsplit.lastEmitterZ(); if ( continueSubleadingNc ) { theParticleIndices[dsplit.splitEmitter()] = 0; theParticlesAfter[0] = dsplit.splitEmitter()->dataPtr(); theEmitterEmissionIndices.first = 0; theEmitterEmissionIndices.second.first = 0; } } else if ( incoming().first == dsplit.spectator() ) { intermediates().push_back(dsplit.spectator()); incoming().first = dsplit.splitSpectator(); fractions().first /= dsplit.lastSpectatorZ(); if ( continueSubleadingNc ) { theParticleIndices[dsplit.splitSpectator()] = 0; theParticlesAfter[0] = dsplit.splitSpectator()->dataPtr(); theSpectatorIndices.first = 0; theSpectatorIndices.second = 0; } } if ( incoming().second == dsplit.emitter() ) { intermediates().push_back(dsplit.emitter()); incoming().second = dsplit.splitEmitter(); fractions().second /= dsplit.lastEmitterZ(); if ( continueSubleadingNc ) { theParticleIndices[dsplit.splitEmitter()] = 1; theParticlesAfter[1] = dsplit.splitEmitter()->dataPtr(); theEmitterEmissionIndices.first = 1; theEmitterEmissionIndices.second.first = 1; } } else if ( incoming().second == dsplit.spectator() ) { intermediates().push_back(dsplit.spectator()); incoming().second = dsplit.splitSpectator(); fractions().second /= dsplit.lastSpectatorZ(); if ( continueSubleadingNc ) { theParticleIndices[dsplit.splitSpectator()] = 1; theParticlesAfter[1] = dsplit.splitSpectator()->dataPtr(); theSpectatorIndices.first = 1; theSpectatorIndices.second = 1; } } PList::iterator pos; pos = find(outgoing().begin(), outgoing().end(), dsplit.emitter()); if (pos != outgoing().end()) { intermediates().push_back(*pos); *pos = dsplit.splitEmitter(); if ( continueSubleadingNc ) { // The two first elements in theParticlesBefore/After are the incoming theEmitterEmissionIndices.first = 2 + distance(outgoing().begin(), pos); theEmitterEmissionIndices.second.first = theEmitterEmissionIndices.first; theParticlesAfter[theEmitterEmissionIndices.second.first] = dsplit.splitEmitter()->dataPtr(); theParticleIndices[dsplit.splitEmitter()] = theEmitterEmissionIndices.second.first; } } pos = find(outgoing().begin(), outgoing().end(), dsplit.spectator()); if (pos != outgoing().end()) { intermediates().push_back(*pos); *pos = dsplit.splitSpectator(); if ( continueSubleadingNc ) { // The two first elements in theParticlesBefore/After are the incoming theSpectatorIndices.first = 2 + distance(outgoing().begin(), pos); theSpectatorIndices.second = theSpectatorIndices.first; theParticlesAfter[theSpectatorIndices.second] = dsplit.splitSpectator()->dataPtr(); theParticleIndices[dsplit.splitSpectator()] = theSpectatorIndices.second; } } if ( continueSubleadingNc ) { theEmitterEmissionIndices.second.second = 2 + outgoing().size(); theParticlesAfter.insert(theParticlesAfter.begin()+theEmitterEmissionIndices.second.second, dsplit.emission()->dataPtr()); theMomentaAfter.insert(theMomentaAfter.begin()+theEmitterEmissionIndices.second.second, dsplit.emission()->momentum()); theParticleIndices[dsplit.emission()] = theEmitterEmissionIndices.second.second; } outgoing().push_back(dsplit.emission()); if (dsplit.splittingKinematics()->doesTransform()) { for (PList::iterator h = theHard.begin(); h != theHard.end(); ++h) dsplit.splittingKinematics()->transform(*h); for (PList::iterator p = intermediates().begin(); p != intermediates().end(); ++p) dsplit.splittingKinematics()->transform(*p); for (PList::iterator p = outgoing().begin(); p != outgoing().end(); ++p) { if ((*p) != dsplit.splitEmitter() && (*p) != dsplit.splitSpectator() && (*p) != dsplit.emission()) dsplit.splittingKinematics()->transform(*p); } if ( continueSubleadingNc ) { theMomentaAfter[0] = incoming().first->momentum(); theMomentaAfter[1] = incoming().second->momentum(); size_t i = 2; for (PList::iterator p = outgoing().begin(); p != outgoing().end(); p++) { theMomentaAfter[i] = (*p)->momentum(); i++; } for (PList::iterator p = theHard.begin(); p != theHard.end(); p++) { theMomentaAfter[i] = (*p)->momentum(); i++; } } } else if ( continueSubleadingNc ) { theMomentaAfter[theEmitterEmissionIndices.second.first] = dsplit.splitEmitter()->momentum();// theMomentaAfter[theSpectatorIndices.second] = dsplit.splitSpectator()->momentum();// } // Stop with subleading emissions if the limit has been reached if ( doSubleadingNc ) if ( subEmDone == subleadingNcEmissionsLimit ) continueSubleadingNc = false; // Handle updates related to decays // Showering of decay processes // Treat the evolution of the incoming // decayed particle as in backward evolution if ( dsplit.isDecayProc() ) { // Create a pointer to the decay process PerturbativeProcessPtr decayProc = currentDecay(); // Add the emission to the outgoing of the decay process decayProc->outgoing().push_back( {dsplit.emission(), PerturbativeProcessPtr() }); // Bools to be used throughout const bool decayedEmtr = dsplit.index().incomingDecayEmitter(); const bool decayedSpec = dsplit.index().incomingDecaySpectator(); /* In the current implementation, **following the hard process** all particles in theDecays evolve independently e.g. if we have W -> XYZ where all X, Y and Z need to be showered and decayed, we only identify them as needing decaying (and hence put them in theDecays) AFTER showering the decay of W. Hence, XYZ are not even in theDecays until W has been fully showered and then they are decayed and showered completely independently KEY POINT - Never need to update other entries of theDecays Note: The PPtr in theDecays should remain unchanged and all changes should be made to the relative PerturbativeProcess. */ // Splittings from dipoles in the decay process which // do not have the decayed parton as emitter or spectator. // Update the decay process in theDecays if ( !decayedEmtr && !decayedSpec ) { // Find and replace the old spectator and // emitter in the outgoing of the decay process bool decayProcEm = false; bool decayProcSp = false; for ( auto & outIt : decayProc->outgoing() ) { if ( !decayProcEm && outIt.first == dsplit.emitter() ) { outIt = {dsplit.splitEmitter(), PerturbativeProcessPtr()}; decayProcEm = true; } if ( !decayProcSp && outIt.first == dsplit.spectator() ) { outIt = {dsplit.splitSpectator(), PerturbativeProcessPtr() }; decayProcSp = true; } if ( decayProcEm && decayProcSp ) break; } // Test that nothing strange is happening assert( (decayProcEm && decayProcSp) ); return; } // The spectator is the decayed particle else if ( decayedSpec ) { // Update the dipole event record intermediates intermediates().push_back(dsplit.splitSpectator()); // Update the the decayProcess incoming decayProc->incoming().clear(); decayProc->incoming().push_back({dsplit.splitSpectator(),decayProc}); // Update the decay process outgoing // Replace the old emitter with the new emitter for ( auto & outEmtrIt : decayProc->outgoing() ) { if ( outEmtrIt.first == dsplit.emitter() ){ outEmtrIt = {dsplit.splitEmitter(), PerturbativeProcessPtr() }; break; } } // Perform the recoil transformation // Find all particles in the recoil system PList recoilSystem; for ( auto const & outIt : decayProc->outgoing() ) { if ( outIt.first != dsplit.splitEmitter() && outIt.first != dsplit.emission() ) { recoilSystem.push_back(outIt.first); } } dsplit.splittingKinematics()->decayRecoil( recoilSystem ); return; } // The emitter is the decayed particle else { throw Exception() << "DipoleEventRecord: The emitter as a decayed particle is currently not implemented." << Exception::runerror; assert( currentDecay()->incoming()[0].first == dsplit.emitter() && decayedEmtr && !decayedSpec ); // Update the dipole event record intermediates intermediates().push_back(dsplit.splitEmitter()); // Update the the decayProcess incoming decayProc->incoming().clear(); decayProc->incoming().push_back({dsplit.splitEmitter(),decayProc}); // Update the decay process outgoing // Replace the old spectator with the new spectator for (auto & outSpecIt : decayProc->outgoing() ) { if ( outSpecIt.first == dsplit.spectator() ){ outSpecIt = { dsplit.splitSpectator(), PerturbativeProcessPtr() }; break; } } // Perform the recoil transformation assert(dsplit.splittingKinematics()->isDecay()); // Find all particles in the recoil system PList recoilSystem; for ( auto const & outIt : decayProc->outgoing() ) { if ( outIt.first != dsplit.splitSpectator() && outIt.first != dsplit.emission() ) { recoilSystem.push_back(outIt.first); } } dsplit.splittingKinematics()->decayRecoil( recoilSystem ); return; } } if ( continueSubleadingNc ) { // Fixed alphaS double alphaS = 0.118; map,Complex> Vijk; double Vtemp; const Lorentz5Momentum pEmission = dsplit.emission()->momentum(); // Special cases for the density operator evolution // g->qqbar splitting bool splitAGluon = (dsplit.emitter()->id() == ParticleID::g) && (dsplit.emission()->id() != ParticleID::g); // initial state g->qqbar splitting bool initialGluonSplitting = (dsplit.splitEmitter()->id() == ParticleID::g) && (dsplit.emission()->id() != ParticleID::g); if ( initialGluonSplitting ) assert(dsplit.splitEmitter() == incoming().first || dsplit.splitEmitter() == incoming().second); // Set up the dictionary std::tuple tmpTuple; map tmpMap; size_t n = theEmitterEmissionIndices.second.second; theEmissionsMap.clear(); if ( splitAGluon || initialGluonSplitting ) { tmpTuple = std::make_tuple(theEmitterEmissionIndices.first, theEmitterEmissionIndices.second.first, theEmitterEmissionIndices.second.second); tmpMap.clear(); for ( size_t j = 0; j < theParticlesBefore.size(); j++ ) { if ( j != theEmitterEmissionIndices.first ) tmpMap[j] = j; } theEmissionsMap[tmpTuple] = tmpMap; } else { for ( size_t i = 0; i < theParticlesBefore.size(); i++ ) { if ( theParticlesBefore[i]->coloured() ) { tmpTuple = std::make_tuple(i,i,n); tmpMap.clear(); for ( size_t j = 0; j < theParticlesBefore.size(); j++ ) { if ( j != i ) tmpMap[j] = j; } theEmissionsMap[tmpTuple] = tmpMap; } } } Energy2 pEmitpEmis; Energy2 pEmispSpec; Lorentz5Momentum pEmitter; Lorentz5Momentum pSpectator; // Calculate all required dipole factors int i,k; typedef map,map > dictMap; for(dictMap::const_iterator ijit = theEmissionsMap.begin(); ijit != theEmissionsMap.end(); ijit++) { i = std::get<1>(ijit->first); pEmitter = theMomentaAfter[i]; pEmitpEmis = pEmitter*pEmission; for(dictMap::const_iterator kit = theEmissionsMap.begin(); kit != theEmissionsMap.end(); kit++) { // For gluon splitting ijit == kit if ( ijit != kit ) { k = std::get<1>(kit->first); pSpectator = theMomentaAfter[k]; pEmispSpec = pEmission*pSpectator; Vtemp = 4*Constants::pi*alphaS*dipoleKernelForEvolution(i, k, pEmitter*pSpectator, pEmitpEmis, pEmispSpec); Vijk.insert(make_pair(make_pair(i,k),Complex(Vtemp,0.0))); } else if ( splitAGluon || initialGluonSplitting ) { k = std::get<1>(kit->first); Vijk.insert(make_pair(make_pair(i,k),Complex(1.0,0.0))); } } } theDensityOperator.evolve(Vijk,theParticlesBefore,theParticlesAfter, theEmissionsMap,splitAGluon,initialGluonSplitting); } } double DipoleEventRecord::dipoleKernelForEvolution(size_t em, size_t spec, Energy2 pEmitpSpec, Energy2 pEmitpEmis, Energy2 pEmispSpec) { double Vijk; if ( densityOperatorEvolution == 3 ) { if ( em == theEmitterEmissionIndices.second.first && spec == theSpectatorIndices.second ) { Vijk = 1.0; } else { Vijk = 0.0; } } else if ( densityOperatorEvolution == 2 ) { Vijk = 1.0; } else { if ( densityOperatorEvolution == 0 ) { if ( pEmitpEmis < densityOperatorCutoff ) pEmitpEmis = densityOperatorCutoff; if ( pEmispSpec < densityOperatorCutoff ) pEmispSpec = densityOperatorCutoff; } Vijk = ((pEmitpSpec)/GeV2)/((pEmitpEmis/GeV2)* (pEmispSpec/GeV2)); } return Vijk; } void DipoleEventRecord::split(list::iterator dip, list::iterator ch, DipoleSplittingInfo& dsplit, pair::iterator,list::iterator>& childIterators, DipoleChain*& firstChain, DipoleChain*& secondChain, bool colourSpectator) { static DipoleChain empty; pair children = dip->split(dsplit,colourSpectator, continueSubleadingNc); list::iterator breakup = ch->insertSplitting(dip,children,childIterators); if ( breakup == ch->dipoles().end() ) { firstChain = &(*ch); secondChain = ∅ } else { DipoleChain other; other.dipoles().splice(other.dipoles().end(),ch->dipoles(),breakup,ch->dipoles().end()); chains().push_back(other); firstChain = &(*ch); secondChain = &(chains().back()); // explicitly fix iterators in case the splice implementation // at hand does invalidate iterators (the SGI docu says, it doesn't, // but it seems that this behaviour is not part of the standard) childIterators.first = --firstChain->dipoles().end(); childIterators.second = secondChain->dipoles().begin(); } if ( !colourSpectator ) { update(dsplit); // otherwise done by recoil(...) } } pair DipoleEventRecord::tmpsplit(list::iterator dip, list::iterator , DipoleSplittingInfo& dsplit, pair::iterator,list::iterator>& , DipoleChain*& , DipoleChain*& , bool colourSpectator) { dip->tmpsplit(dsplit,colourSpectator); return tmpupdate(dsplit); // otherwise done by recoil(...) } void DipoleEventRecord::recoil(list::iterator dip, list::iterator ch, DipoleSplittingInfo& dsplit) { dip->recoil(dsplit); ch->updateDipole(dip); update(dsplit); } list::iterator,list::iterator> > DipoleEventRecord::inDipoles() { list::iterator,list::iterator> > res; for ( list::iterator chit = theDoneChains.begin(); chit != theDoneChains.end(); ++chit ) { bool haveOne = false; for ( list::iterator dit = chit->dipoles().begin(); dit != chit->dipoles().end(); ++dit ) { if ( dit->leftPDF().pdf() || dit->rightPDF().pdf() ) { haveOne = true; break; } } if ( haveOne ) { theChains.splice(theChains.begin(),theDoneChains,chit); for ( list::iterator dit = theChains.front().dipoles().begin(); dit != theChains.front().dipoles().end(); ++dit ) { if ( dit->leftPDF().pdf() || dit->rightPDF().pdf() ) { res.push_back({dit,theChains.begin()}); } } } } return res; } void DipoleEventRecord::transform(const LorentzRotation& rot) { Lorentz5Momentum tmp; for (PList::iterator p = intermediates().begin(); p != intermediates().end(); ++p) { tmp = (**p).momentum(); if ( (*p)->spinInfo() ) (*p)->spinInfo()->transform(tmp, rot); tmp = rot * tmp; (**p).set5Momentum(tmp); } for (PList::iterator h = theHard.begin(); h != theHard.end(); ++h) { tmp = (**h).momentum(); if ( (*h)->spinInfo() ) (*h)->spinInfo()->transform(tmp, rot); tmp = rot * tmp; (**h).set5Momentum(tmp); } for (PList::iterator p = outgoing().begin(); p != outgoing().end(); ++p) { tmp = (**p).momentum(); if ( (*p)->spinInfo() ) (*p)->spinInfo()->transform(tmp, rot); tmp = rot * tmp; (**p).set5Momentum(tmp); } } tPPair DipoleEventRecord::fillEventRecord(StepPtr step, bool firstInteraction, bool) { PPtr inSubPro = subProcess()->incoming().first; PPtr inParticle; if ( !(inSubPro->parents().empty()) ) inParticle = inSubPro->parents()[0]; else inParticle = inSubPro; PPtr inParton = theOriginals[inSubPro]; theOriginals.erase(inSubPro); updateColour(incoming().first,true); if ( inParticle != inSubPro ) inParticle->abandonChild(inSubPro); inParton->addChild(inSubPro); if ( inParticle != inSubPro ) inParticle->addChild(incoming().first); intermediates().push_back(inSubPro); intermediates().push_back(inParton); // Repeat all the above for the second incoming particle inSubPro = subProcess()->incoming().second; if ( !(inSubPro->parents().empty()) ) inParticle = inSubPro->parents()[0]; else inParticle = inSubPro; inParton = theOriginals[inSubPro]; theOriginals.erase(inSubPro); updateColour(incoming().second,true); if ( inParticle != inSubPro ) inParticle->abandonChild(inSubPro); inParton->addChild(inSubPro); if ( inParticle != inSubPro ) inParticle->addChild(incoming().second); intermediates().push_back(inSubPro); intermediates().push_back(inParton); // theOriginals is populated in ::prepare and contains all of the incoming and outgoing particles of the original hard process // Here outgoing particles from theOriginals are added into the intermediates() while ( !theOriginals.empty() ) { PPtr outSubPro = theOriginals.begin()->first; PPtr outParton = theOriginals.begin()->second; // workaround for OS X Mavericks LLVM libc++ #ifdef _LIBCPP_VERSION map::const_iterator beg = theOriginals.begin(); #else map::iterator beg = theOriginals.begin(); #endif theOriginals.erase(beg); updateColour(outParton,true); outSubPro->addChild(outParton); intermediates().push_back(outSubPro); } // Update the intermediates of the step step->addIntermediates(intermediates().begin(),intermediates().end()); for (auto const & p : outgoing()) step->addDecayProduct( p ); for (auto const & p : theHard) step->addDecayProduct( p ); if ( firstInteraction && (incoming().first->coloured() || incoming().second->coloured() ) ) { ShowerHandler::currentHandler()->lastExtractor() ->newRemnants(subProcess()->incoming(),incoming(),step); } step->addIntermediate(incoming().first); step->addIntermediate(incoming().second); return incoming(); } bool DipoleEventRecord::prepareDecay( PerturbativeProcessPtr decayProc, const set& offShellPartons ) { // Create objects containing the incoming and outgoing partons, // required as inputs for colourOrdered. PList out; for( auto const & dec : decayProc->outgoing()) { if(dec.first->coloured()) { out.push_back(dec.first); } } // Only need to shower if we have coloured outgoing particles if ( out.empty() ) return false; else { // For the incoming, use a PPair containing the incoming and a null pointer PPair in; in.first = decayProc->incoming()[0].first; // Chains are found later if the subleading shower is used if ( !doSubleadingNc ) { // Create an ordered list of particles PList cordered; cordered = colourOrdered(in,out); // Find the dipole chains for this decay findChains(cordered,offShellPartons,true); } return true; } } Energy DipoleEventRecord::decay(PPtr incoming, bool& powhegEmission) { // get the process PerturbativeProcessPtr process = theDecays[incoming]; assert(process); //tDMPtr decayMode = new_ptr(DecayMode()); tDMPtr decayMode = DMPtr(); // Do not decay particles that have already been decayed // Note the herwig decayer deals with colour connections if ( process->outgoing().empty() ) { process->incoming()[0].first = incoming; DecayProcessMap decay; // Decay the particle, returning a pointer to the decay mode decayMode = ShowerHandler::currentHandler()->decay(process,decay,true); } // Sort out the colour connections of particles already decayed else { // sort out the colour of the incoming map cmap; if(incoming->colourLine()) cmap[process->incoming()[0].first->colourLine()] = incoming->colourLine(); if(incoming->antiColourLine()) cmap[process->incoming()[0].first->antiColourLine()] = incoming->antiColourLine(); // fix colours of outgoing for(auto const & outg : process->outgoing()) { map::iterator it = cmap.find(outg.first->colourLine()); if(it!=cmap.end()) { ColinePtr c1=outg.first->colourLine(); c1->removeColoured(outg.first); it->second->addColoured(outg.first); } it = cmap.find(outg.first->antiColourLine()); if(it!=cmap.end()) { ColinePtr c1=outg.first->antiColourLine(); c1->removeAntiColoured(outg.first); it->second->addAntiColoured(outg.first); } } // swap the incoming process->incoming()[0].first = incoming; } // Set the scale of all particles involved in the decay process to the // mass of the decaying particle // Initialise the scale for the evolution of // the parton shower following the decay Energy showerScale = ZERO; // Set the scale for the evolution of the shower showerScale = process->incoming()[0].first->momentum().m(); Energy2 decayScaleSqr = sqr( showerScale ); process->incoming()[0].first->scale( decayScaleSqr ); for(auto & outg : process->outgoing()) { outg.first->scale( decayScaleSqr ); } // Update the decaying particle in the process and the event PList::iterator posOut = find(outgoing().begin(), outgoing().end(), incoming); PList::iterator posHard = find(hard().begin(), hard().end(), incoming); assert((posOut!=outgoing().end() && posHard==hard().end()) || (posOut==outgoing().end() && posHard!=hard().end()) ); if ( posOut!=outgoing().end() ) { outgoing().erase(posOut); } else { hard().erase(posHard); } intermediates().push_back(process->incoming()[0].first); // Populate the children of the incoming for(auto const & outg : process->outgoing()) { PPtr outgoing = outg.first; process->incoming()[0].first->addChild(outgoing); } // If a decayed particle is not decayed above, // e.g. a W in a 3-body top decay, find its decaymode. if ( powhegEmission && !decayMode ) { string tag = incoming->dataPtr()->name() + "->"; // Must use OrderedParticles for a tag search ShowerHandler::OrderedParticles decayOut; for(auto const & outg : process->outgoing()) { decayOut.insert(outg.first->dataPtr()); } // Construct the tag for(auto const & dec : decayOut) { if( dec!=*decayOut.begin() ) tag += ","; tag +=dec->name(); } tag += ";"; // Find the decay mode decayMode = ShowerHandler::currentHandler()->findDecayMode(tag); } // Perform the powheg emission if ( powhegEmission ) { if ( decayMode ) { HwDecayerBasePtr decayer; decayer = dynamic_ptr_cast(decayMode->decayer()); if ( decayer->hasPOWHEGCorrection() ) { // Construct a real emission process and populate its // incoming and outcoming prior to any powheg emission RealEmissionProcessPtr born = new_ptr( RealEmissionProcess() ); born->bornIncoming().push_back( incoming ); for(auto const & outg : process->outgoing()) { born->bornOutgoing().push_back(outg.first); } // Generate any powheg emission, returning 'real' RealEmissionProcessPtr real = decayer->generateHardest( born ); // If an emission has been attempted // (Note if the emission fails, a null ptr is returned) if ( real ) { showerScale = real->pT()[ShowerInteraction::QCD]; // If an emission is generated sort out the particles if ( !real->outgoing().empty() ) { // Update the decay process // Note: Do not use the new incoming particle PPtr oldEmitter; PPtr newEmitter; // Use the name recoiler to avoid confusion with // the spectator in the POWHEGDecayer // i.e. the recoiler can be coloured or non-coloured PPtr oldRecoiler; PPtr newRecoiler; if ( real->emitter() == 1 ) { oldEmitter = real->bornOutgoing()[0]; oldRecoiler = real->bornOutgoing()[1]; newEmitter = real->outgoing()[0]; newRecoiler = real->outgoing()[1]; } else if ( real->emitter() == 2) { oldEmitter = real->bornOutgoing()[1]; oldRecoiler = real->bornOutgoing()[0]; newEmitter = real->outgoing()[1]; newRecoiler = real->outgoing()[0]; } PPtr emitted = real->outgoing()[ real->emitted()-1]; // Update the scales newRecoiler->scale(oldRecoiler->scale()); newEmitter->scale(sqr(showerScale)); emitted->scale(sqr(showerScale)); // Update the colour flow of the new outgoing particles // Note the emitted and newEmitter are already colour // connected by the powheg emission function emitted->incomingColour(oldEmitter, oldEmitter->id()<0); if ( newRecoiler->coloured() ) newRecoiler->incomingColour(oldRecoiler, oldRecoiler->id()<0); // Update the children of the outgoing oldRecoiler->addChild( newRecoiler ); oldEmitter->addChild( newEmitter ); oldEmitter->addChild( emitted ); // Note: The particles in the pert proc outgoing and both outgoing // vectors of the real emission proc are in the same order for(unsigned int ix=0;ixbornOutgoing().size();++ix) { // Update the decay process assert(process->outgoing()[ix].first == real->bornOutgoing()[ix]); process->outgoing()[ix].first = real->outgoing()[ix]; // Add the outgoing from the born // decay to the event intermediates intermediates().push_back(real->bornOutgoing()[ix]); } // Add the emitted to the outgoing of the decay process process->outgoing().push_back( { emitted, PerturbativeProcessPtr() } ); } // Else, if no emission above pTmin, set particle scales else { for(auto & outg : process->outgoing()) { outg.first->scale( sqr(showerScale) ); } powhegEmission = false; } } // No powheg emission occurred: else powhegEmission = false; } // No powheg emission occurred: else powhegEmission = false; } // No powheg emission occurred: else powhegEmission = false; } // Copy the outgoing from the decay // process to the event record for(auto const & outg : process->outgoing()) { if ( outg.first->coloured() ) outgoing().push_back(outg.first); else hard().push_back(outg.first); } return showerScale; } void DipoleEventRecord::updateDecayMom( PPtr decayParent, PerturbativeProcessPtr decayProc ) { // Only particles that have already been decayed // should be passed to this function assert( !(decayProc->outgoing().empty()) ); // Create a list of the children to update their momenta PList children; for ( auto const & outg : decayProc->outgoing() ) { children.push_back( outg.first ); } // Boost the children PList::iterator beginChildren = children.begin(); PList::iterator endChildren = children.end(); const Momentum3 transformMom = decayParent->momentum().vect(); Lorentz5Momentum sum = ThePEG::UtilityBase::sumMomentum(beginChildren, endChildren); LorentzRotation rot = ThePEG::UtilityBase::transformToCMS(sum); rot = ThePEG::UtilityBase::transformFromCMS (Lorentz5Momentum(transformMom, sqrt(transformMom.mag2() + sum.m2()))) * rot; // Must transform the spinInfo using the momentum prior to transforming for ( const auto& p : children ) { if ( p->spinInfo() ) p->spinInfo()->transform(p->momentum(),rot); } ThePEG::UtilityBase::transform(beginChildren, endChildren, rot ); } void DipoleEventRecord::updateDecayChainMom( PPtr decayParent, PerturbativeProcessPtr decayProc ) { // Note - this updates the momenta of the // outgoing of the given decay process // Update the momenta of the outgoing from this decay updateDecayMom( decayParent, decayProc ); // Iteratively update the momenta of the rest of the decay chain for ( auto & outg : decayProc->outgoing() ) { // If a child has a corresponding pert proc // then it has decay products if ( outg.second ) { for ( auto & dec : theDecays ) { if ( dec.second == outg.second ) { // If the particle has spininfo if ( dec.first->spinInfo() ) { // Copied from DipoleVertexRecord::updateSpinInfo, // would be better to use a common function // Update any spin information const Lorentz5Momentum& oldMom = dec.first->momentum(); const Lorentz5Momentum& newMom = outg.first->momentum(); // Rotation from old momentum to +ve z-axis LorentzRotation oldToZAxis; Axis axisOld(oldMom.vect().unit()); if( axisOld.perp2() > 1e-12 ) { double sinth(sqrt(1.-sqr(axisOld.z()))); oldToZAxis.rotate( -acos(axisOld.z()),Axis(-axisOld.y()/sinth,axisOld.x()/sinth,0.)); } // Rotation from new momentum to +ve z-axis LorentzRotation newToZAxis; Axis axisNew(newMom.vect().unit()); if( axisNew.perp2() > 1e-12 ) { double sinth(sqrt(1.-sqr(axisNew.z()))); newToZAxis.rotate( -acos(axisNew.z()),Axis(-axisNew.y()/sinth,axisNew.x()/sinth,0.)); } // Boost from old momentum to new momentum along z-axis Lorentz5Momentum momOldRotated = oldToZAxis*Lorentz5Momentum(oldMom); Lorentz5Momentum momNewRotated = newToZAxis*Lorentz5Momentum(newMom); Energy2 a = sqr(momOldRotated.z()) + sqr(momNewRotated.t()); Energy2 b = 2.*momOldRotated.t()*momOldRotated.z(); Energy2 c = sqr(momOldRotated.t()) - sqr(momNewRotated.t()); double beta; // The rotated momentum should always lie along the +ve z-axis if ( momOldRotated.z() > ZERO ) beta = (-b + sqrt(sqr(b)-4.*a*c)) / 2. / a; else beta = (-b - sqrt(sqr(b)-4.*a*c)) / 2. / a; LorentzRotation boostOldToNew(0., 0., beta); // Total transform LorentzRotation transform = (newToZAxis.inverse())*boostOldToNew*oldToZAxis; // Transform spin info and mom dec.first->spinInfo()->transform(oldMom, transform); } dec.first->setMomentum(outg.first->momentum()); break; } } // Iteratively update any decay products if ( !outg.second->outgoing().empty() ) updateDecayChainMom( outg.first, outg.second ); } } } void DipoleEventRecord::updateDecays(PerturbativeProcessPtr decayProc, bool iterate) { // Note - This does not update the momenta of the outgoing // of decayProc. // i.e. it is for use following the (non-)showering // of a decay when the daughter momentum are correct. // With iterate = true, this updates the rest of the decay chain. // Update the list of next decays if ( decayProc == theCurrentDecay && !theNextDecays.empty() ) { assert( theNextDecays.back() == decayProc->incoming()[0].first ); theNextDecays.pop_back(); } // Loop over the outgoing from this decay for ( auto & outg : decayProc->outgoing() ) { if ( outg.second && !outg.second->outgoing().empty() ) { // Outgoing particles which have already been decayed PPtr newDecayed = outg.first; PerturbativeProcessPtr newDecayProc = outg.second; // Update the outgoing momenta from this decay updateDecayMom( newDecayed, newDecayProc); // If this decay is already in theDecays then erase it for ( auto const & dec : theDecays ) { if(dec.second==newDecayProc) { theDecays.erase(dec.first); break; } } // Add to theDecays theDecays[newDecayed] = newDecayProc; // Update the list of next decays - if ( decayProc = theCurrentDecay ) + if ( decayProc == theCurrentDecay ) theNextDecays.push_back(newDecayed); // Iteratively update theDecays from the decay chain if ( iterate ) updateDecays( newDecayProc ); } // Deal with any outgoing which need to be decayed else if ( ShowerHandler::currentHandler()->decaysInShower(outg.first->id()) ) { PerturbativeProcessPtr newDecay=new_ptr(PerturbativeProcess()); newDecay->incoming().push_back({ outg.first , decayProc } ); theDecays[outg.first] = newDecay; // Update the list of next decays if ( decayProc ) theNextDecays.push_back(outg.first); } } } void DipoleEventRecord::debugLastEvent(ostream& os) const { bool first = ShowerHandler::currentHandler()->firstInteraction(); os << "--- DipoleEventRecord ----------------------------------------------------------\n"; os << " the " << (first ? "hard" : "secondary") << " subprocess is:\n" << (*subProcess()); os << " using PDF's " << pdfs().first.pdf() << " and " << pdfs().second.pdf() << "\n"; os << " chains showering currently:\n"; for ( list::const_iterator chit = theChains.begin(); chit != theChains.end(); ++chit ) os << (*chit); os << " chains which finished showering:\n"; for ( list::const_iterator chit = theDoneChains.begin(); chit != theDoneChains.end(); ++chit ) os << (*chit); os << "--------------------------------------------------------------------------------\n"; os << flush; } diff --git a/Shower/Dipole/Colorea/HelAmps_sm.cc b/Shower/Dipole/Colorea/HelAmps_sm.cc --- a/Shower/Dipole/Colorea/HelAmps_sm.cc +++ b/Shower/Dipole/Colorea/HelAmps_sm.cc @@ -1,1027 +1,1024 @@ //========================================================================== // This file has been automatically generated for C++ Standalone by // MadGraph5_aMC@NLO v. 2.5.4, 2017-03-28 // By the MadGraph5_aMC@NLO Development Team // Visit launchpad.net/madgraph5 and amcatnlo.web.cern.ch //========================================================================== #include "HelAmps_sm.h" #include #include #include #include using namespace std; namespace MG5_sm_COLOREA { void ixxxxx(double p[4], double fmass, int nhel, int nsf, complex fi[6]) { complex chi[2]; double sf[2], sfomega[2], omega[2], pp, pp3, sqp0p3, sqm[2]; int ip, im, nh; fi[0] = complex (-p[0] * nsf, -p[3] * nsf); fi[1] = complex (-p[1] * nsf, -p[2] * nsf); nh = nhel * nsf; if (fmass != 0.0) { pp = min(p[0], sqrt(p[1] * p[1] + p[2] * p[2] + p[3] * p[3])); if (pp == 0.0) { sqm[0] = sqrt(std::abs(fmass)); sqm[1] = Sgn(sqm[0], fmass); ip = (1 + nh)/2; im = (1 - nh)/2; fi[2] = ip * sqm[ip]; fi[3] = im * nsf * sqm[ip]; fi[4] = ip * nsf * sqm[im]; fi[5] = im * sqm[im]; } else { sf[0] = (1 + nsf + (1 - nsf) * nh) * 0.5; sf[1] = (1 + nsf - (1 - nsf) * nh) * 0.5; omega[0] = sqrt(p[0] + pp); omega[1] = fmass/omega[0]; ip = (1 + nh)/2; im = (1 - nh)/2; sfomega[0] = sf[0] * omega[ip]; sfomega[1] = sf[1] * omega[im]; pp3 = max(pp + p[3], 0.0); chi[0] = complex (sqrt(pp3 * 0.5/pp), 0); if (pp3 == 0.0) { chi[1] = complex (-nh, 0); } else { chi[1] = complex (nh * p[1], p[2])/sqrt(2.0 * pp * pp3); } fi[2] = sfomega[0] * chi[im]; fi[3] = sfomega[0] * chi[ip]; fi[4] = sfomega[1] * chi[im]; fi[5] = sfomega[1] * chi[ip]; } } else { if (p[1] == 0.0 and p[2] == 0.0 and p[3] < 0.0) { sqp0p3 = 0.0; } else { sqp0p3 = sqrt(max(p[0] + p[3], 0.0)) * nsf; } chi[0] = complex (sqp0p3, 0.0); if (sqp0p3 == 0.0) { chi[1] = complex (-nhel * sqrt(2.0 * p[0]), 0.0); } else { chi[1] = complex (nh * p[1], p[2])/sqp0p3; } if (nh == 1) { fi[2] = complex (0.0, 0.0); fi[3] = complex (0.0, 0.0); fi[4] = chi[0]; fi[5] = chi[1]; } else { fi[2] = chi[1]; fi[3] = chi[0]; fi[4] = complex (0.0, 0.0); fi[5] = complex (0.0, 0.0); } } return; } double Sgn(double a, double b) { return (b < 0)? - abs(a):abs(a); } void txxxxx(double p[4], double tmass, int nhel, int nst, complex tc[18]) { complex ft[6][4], ep[4], em[4], e0[4]; double pt, pt2, pp, pzpt, emp, sqh, sqs; int i, j; sqh = sqrt(0.5); sqs = sqrt(0.5/3); pt2 = p[1] * p[1] + p[2] * p[2]; pp = min(p[0], sqrt(pt2 + p[3] * p[3])); pt = min(pp, sqrt(pt2)); ft[4][0] = complex (p[0] * nst, p[3] * nst); ft[5][0] = complex (p[1] * nst, p[2] * nst); // construct eps+ if(nhel >= 0) { if(pp == 0) { ep[0] = complex (0, 0); ep[1] = complex (-sqh, 0); ep[2] = complex (0, nst * sqh); ep[3] = complex (0, 0); } else { ep[0] = complex (0, 0); ep[3] = complex (pt/pp * sqh, 0); if(pt != 0) { pzpt = p[3]/(pp * pt) * sqh; ep[1] = complex (-p[1] * pzpt, -nst * p[2]/pt * sqh); ep[2] = complex (-p[2] * pzpt, nst * p[1]/pt * sqh); } else { ep[1] = complex (-sqh, 0); ep[2] = complex (0, nst * Sgn(sqh, p[3])); } } } // construct eps- if(nhel <= 0) { if(pp == 0) { em[0] = complex (0, 0); em[1] = complex (sqh, 0); em[2] = complex (0, nst * sqh); em[3] = complex (0, 0); } else { em[0] = complex (0, 0); em[3] = complex (-pt/pp * sqh, 0); if(pt != 0) { pzpt = -p[3]/(pp * pt) * sqh; em[1] = complex (-p[1] * pzpt, -nst * p[2]/pt * sqh); em[2] = complex (-p[2] * pzpt, nst * p[1]/pt * sqh); } else { em[1] = complex (sqh, 0); em[2] = complex (0, nst * Sgn(sqh, p[3])); } } } // construct eps0 if(std::labs(nhel) <= 1) { if(pp == 0) { e0[0] = complex (0, 0); e0[1] = complex (0, 0); e0[2] = complex (0, 0); e0[3] = complex (1, 0); } else { emp = p[0]/(tmass * pp); e0[0] = complex (pp/tmass, 0); e0[3] = complex (p[3] * emp, 0); if(pt != 0) { e0[1] = complex (p[1] * emp, 0); e0[2] = complex (p[2] * emp, 0); } else { e0[1] = complex (0, 0); e0[2] = complex (0, 0); } } } if(nhel == 2) { for(j = 0; j < 4; j++ ) { for(i = 0; i < 4; i++ ) ft[i][j] = ep[i] * ep[j]; } } else if(nhel == -2) { for(j = 0; j < 4; j++ ) { for(i = 0; i < 4; i++ ) ft[i][j] = em[i] * em[j]; } } else if(tmass == 0) { for(j = 0; j < 4; j++ ) { for(i = 0; i < 4; i++ ) ft[i][j] = 0; } } else if(tmass != 0) { if(nhel == 1) { for(j = 0; j < 4; j++ ) { for(i = 0; i < 4; i++ ) ft[i][j] = sqh * (ep[i] * e0[j] + e0[i] * ep[j]); } } else if(nhel == 0) { for(j = 0; j < 4; j++ ) { for(i = 0; i < 4; i++ ) ft[i][j] = sqs * (ep[i] * em[j] + em[i] * ep[j] + 2.0 * e0[i] * e0[j]); } } else if(nhel == -1) { for(j = 0; j < 4; j++ ) { for(i = 0; i < 4; i++ ) ft[i][j] = sqh * (em[i] * e0[j] + e0[i] * em[j]); } } else { std::cerr << "Invalid helicity in txxxxx.\n"; std::exit(1); } } tc[0] = ft[4][0]; tc[1] = ft[5][0]; for(j = 0; j < 4; j++ ) { for(i = 0; i < 4; i++ ) tc[j * 4 + i + 2] = ft[j][i]; } } void vxxxxx(double p[4], double vmass, int nhel, int nsv, complex vc[6]) { double hel, hel0, pt, pt2, pp, pzpt, emp, sqh; int nsvahl; sqh = sqrt(0.5); hel = double(nhel); nsvahl = nsv * std::abs(hel); pt2 = (p[1] * p[1]) + (p[2] * p[2]); pp = min(p[0], sqrt(pt2 + (p[3] * p[3]))); pt = min(pp, sqrt(pt2)); vc[0] = complex (p[0] * nsv, p[3] * nsv); vc[1] = complex (p[1] * nsv, p[2] * nsv); if (vmass != 0.0) { hel0 = 1.0 - std::abs(hel); if(pp == 0.0) { vc[2] = complex (0.0, 0.0); vc[3] = complex (-hel * sqh, 0.0); vc[4] = complex (0.0, nsvahl * sqh); vc[5] = complex (hel0, 0.0); } else { emp = p[0]/(vmass * pp); vc[2] = complex (hel0 * pp/vmass, 0.0); vc[5] = complex (hel0 * p[3] * emp + hel * pt/pp * sqh, 0.0); if (pt != 0.0) { pzpt = p[3]/(pp * pt) * sqh * hel; vc[3] = complex (hel0 * p[1] * emp - p[1] * pzpt, -nsvahl * p[2]/pt * sqh); vc[4] = complex (hel0 * p[2] * emp - p[2] * pzpt, nsvahl * p[1]/pt * sqh); } else { vc[3] = complex (-hel * sqh, 0.0); vc[4] = complex (0.0, nsvahl * Sgn(sqh, p[3])); } } } else { pp = p[0]; pt = sqrt((p[1] * p[1]) + (p[2] * p[2])); vc[2] = complex (0.0, 0.0); vc[5] = complex (hel * pt/pp * sqh, 0.0); if (pt != 0.0) { pzpt = p[3]/(pp * pt) * sqh * hel; vc[3] = complex (-p[1] * pzpt, -nsv * p[2]/pt * sqh); vc[4] = complex (-p[2] * pzpt, nsv * p[1]/pt * sqh); } else { vc[3] = complex (-hel * sqh, 0.0); vc[4] = complex (0.0, nsv * Sgn(sqh, p[3])); } } return; } void sxxxxx(double p[4], int nss, complex sc[3]) { sc[2] = complex (1.00, 0.00); sc[0] = complex (p[0] * nss, p[3] * nss); sc[1] = complex (p[1] * nss, p[2] * nss); return; } void oxxxxx(double p[4], double fmass, int nhel, int nsf, complex fo[6]) { complex chi[2]; double sf[2], sfomeg[2], omega[2], pp, pp3, sqp0p3, sqm[2]; int nh, ip, im; fo[0] = complex (p[0] * nsf, p[3] * nsf); fo[1] = complex (p[1] * nsf, p[2] * nsf); nh = nhel * nsf; if (fmass != 0.000) { pp = min(p[0], sqrt((p[1] * p[1]) + (p[2] * p[2]) + (p[3] * p[3]))); if (pp == 0.000) { sqm[0] = sqrt(std::abs(fmass)); sqm[1] = Sgn(sqm[0], fmass); ip = -((1 - nh)/2) * nhel; im = (1 + nh)/2 * nhel; fo[2] = im * sqm[std::abs(ip)]; fo[3] = ip * nsf * sqm[std::abs(ip)]; fo[4] = im * nsf * sqm[std::abs(im)]; fo[5] = ip * sqm[std::abs(im)]; } else { pp = min(p[0], sqrt((p[1] * p[1]) + (p[2] * p[2]) + (p[3] * p[3]))); sf[0] = double(1 + nsf + (1 - nsf) * nh) * 0.5; sf[1] = double(1 + nsf - (1 - nsf) * nh) * 0.5; omega[0] = sqrt(p[0] + pp); omega[1] = fmass/omega[0]; ip = (1 + nh)/2; im = (1 - nh)/2; sfomeg[0] = sf[0] * omega[ip]; sfomeg[1] = sf[1] * omega[im]; pp3 = max(pp + p[3], 0.00); chi[0] = complex (sqrt(pp3 * 0.5/pp), 0.00); if (pp3 == 0.00) { chi[1] = complex (-nh, 0.00); } else { chi[1] = complex (nh * p[1], -p[2])/sqrt(2.0 * pp * pp3); } fo[2] = sfomeg[1] * chi[im]; fo[3] = sfomeg[1] * chi[ip]; fo[4] = sfomeg[0] * chi[im]; fo[5] = sfomeg[0] * chi[ip]; } } else { if((p[1] == 0.00) and (p[2] == 0.00) and (p[3] < 0.00)) { sqp0p3 = 0.00; } else { sqp0p3 = sqrt(max(p[0] + p[3], 0.00)) * nsf; } chi[0] = complex (sqp0p3, 0.00); if(sqp0p3 == 0.000) { chi[1] = complex (-nhel, 0.00) * sqrt(2.0 * p[0]); } else { chi[1] = complex (nh * p[1], -p[2])/sqp0p3; } if(nh == 1) { fo[2] = chi[0]; fo[3] = chi[1]; fo[4] = complex (0.00, 0.00); fo[5] = complex (0.00, 0.00); } else { fo[2] = complex (0.00, 0.00); fo[3] = complex (0.00, 0.00); fo[4] = chi[1]; fo[5] = chi[0]; } } return; } void FFV1P0_3(std::complex F1[], std::complex F2[], std::complex COUP, double M3, double W3, std::complex V3[]) { static std::complex cI = std::complex (0., 1.); double P3[4]; std::complex denom; V3[0] = +F1[0] + F2[0]; V3[1] = +F1[1] + F2[1]; P3[0] = -V3[0].real(); P3[1] = -V3[1].real(); P3[2] = -V3[1].imag(); P3[3] = -V3[0].imag(); denom = COUP/((P3[0] * P3[0]) - (P3[1] * P3[1]) - (P3[2] * P3[2]) - (P3[3] * P3[3]) - M3 * (M3 - cI * W3)); V3[2] = denom * (-cI) * (F1[2] * F2[4] + F1[3] * F2[5] + F1[4] * F2[2] + F1[5] * F2[3]); V3[3] = denom * (-cI) * (F1[4] * F2[3] + F1[5] * F2[2] - F1[2] * F2[5] - F1[3] * F2[4]); V3[4] = denom * (-cI) * (-cI * (F1[2] * F2[5] + F1[5] * F2[2]) + cI * (F1[3] * F2[4] + F1[4] * F2[3])); V3[5] = denom * (-cI) * (F1[3] * F2[5] + F1[4] * F2[2] - F1[2] * F2[4] - F1[5] * F2[3]); } void FFV2_2(std::complex F1[], std::complex V3[], std::complex COUP, double M2, double W2, std::complex F2[]) { static std::complex cI = std::complex (0., 1.); double P2[4]; std::complex denom; F2[0] = +F1[0] + V3[0]; F2[1] = +F1[1] + V3[1]; P2[0] = -F2[0].real(); P2[1] = -F2[1].real(); P2[2] = -F2[1].imag(); P2[3] = -F2[0].imag(); denom = COUP/((P2[0] * P2[0]) - (P2[1] * P2[1]) - (P2[2] * P2[2]) - (P2[3] * P2[3]) - M2 * (M2 - cI * W2)); F2[2] = denom * cI * (F1[2] * (P2[0] * (V3[2] + V3[5]) + (P2[1] * (-1.) * (V3[3] + cI * (V3[4])) + (P2[2] * (+cI * (V3[3]) - V3[4]) - P2[3] * (V3[2] + V3[5])))) + F1[3] * (P2[0] * (V3[3] - cI * (V3[4])) + (P2[1] * (V3[5] - V3[2]) + (P2[2] * (-cI * (V3[5]) + cI * (V3[2])) + P2[3] * (+cI * (V3[4]) - V3[3]))))); F2[3] = denom * cI * (F1[2] * (P2[0] * (V3[3] + cI * (V3[4])) + (P2[1] * (-1.) * (V3[2] + V3[5]) + (P2[2] * (-1.) * (+cI * (V3[2] + V3[5])) + P2[3] * (V3[3] + cI * (V3[4]))))) + F1[3] * (P2[0] * (V3[2] - V3[5]) + (P2[1] * (+cI * (V3[4]) - V3[3]) + (P2[2] * (-1.) * (V3[4] + cI * (V3[3])) + P2[3] * (V3[2] - V3[5]))))); F2[4] = denom * - cI * M2 * (F1[2] * (-1.) * (V3[2] + V3[5]) + F1[3] * (+cI * (V3[4]) - V3[3])); F2[5] = denom * cI * M2 * (F1[2] * (V3[3] + cI * (V3[4])) + F1[3] * (V3[2] - V3[5])); } void FFV2_5_2(std::complex F1[], std::complex V3[], std::complex COUP1, std::complex COUP2, double M2, double W2, std::complex F2[]) { std::complex Ftmp[6]; - std::complex denom; int i; FFV2_2(F1, V3, COUP1, M2, W2, F2); FFV5_2(F1, V3, COUP2, M2, W2, Ftmp); i = 2; while (i < 6) { F2[i] = F2[i] + Ftmp[i]; i++; } } void FFV1_2(std::complex F1[], std::complex V3[], std::complex COUP, double M2, double W2, std::complex F2[]) { static std::complex cI = std::complex (0., 1.); double P2[4]; std::complex denom; F2[0] = +F1[0] + V3[0]; F2[1] = +F1[1] + V3[1]; P2[0] = -F2[0].real(); P2[1] = -F2[1].real(); P2[2] = -F2[1].imag(); P2[3] = -F2[0].imag(); denom = COUP/((P2[0] * P2[0]) - (P2[1] * P2[1]) - (P2[2] * P2[2]) - (P2[3] * P2[3]) - M2 * (M2 - cI * W2)); F2[2] = denom * cI * (F1[2] * (P2[0] * (V3[2] + V3[5]) + (P2[1] * (-1.) * (V3[3] + cI * (V3[4])) + (P2[2] * (+cI * (V3[3]) - V3[4]) - P2[3] * (V3[2] + V3[5])))) + (F1[3] * (P2[0] * (V3[3] - cI * (V3[4])) + (P2[1] * (V3[5] - V3[2]) + (P2[2] * (-cI * (V3[5]) + cI * (V3[2])) + P2[3] * (+cI * (V3[4]) - V3[3])))) + M2 * (F1[4] * (V3[2] - V3[5]) + F1[5] * (+cI * (V3[4]) - V3[3])))); F2[3] = denom * (-cI) * (F1[2] * (P2[0] * (-1.) * (V3[3] + cI * (V3[4])) + (P2[1] * (V3[2] + V3[5]) + (P2[2] * (+cI * (V3[2] + V3[5])) - P2[3] * (V3[3] + cI * (V3[4]))))) + (F1[3] * (P2[0] * (V3[5] - V3[2]) + (P2[1] * (V3[3] - cI * (V3[4])) + (P2[2] * (V3[4] + cI * (V3[3])) + P2[3] * (V3[5] - V3[2])))) + M2 * (F1[4] * (V3[3] + cI * (V3[4])) - F1[5] * (V3[2] + V3[5])))); F2[4] = denom * (-cI) * (F1[4] * (P2[0] * (V3[5] - V3[2]) + (P2[1] * (V3[3] + cI * (V3[4])) + (P2[2] * (V3[4] - cI * (V3[3])) + P2[3] * (V3[5] - V3[2])))) + (F1[5] * (P2[0] * (V3[3] - cI * (V3[4])) + (P2[1] * (-1.) * (V3[2] + V3[5]) + (P2[2] * (+cI * (V3[2] + V3[5])) + P2[3] * (V3[3] - cI * (V3[4]))))) + M2 * (F1[2] * (-1.) * (V3[2] + V3[5]) + F1[3] * (+cI * (V3[4]) - V3[3])))); F2[5] = denom * cI * (F1[4] * (P2[0] * (-1.) * (V3[3] + cI * (V3[4])) + (P2[1] * (V3[2] - V3[5]) + (P2[2] * (-cI * (V3[5]) + cI * (V3[2])) + P2[3] * (V3[3] + cI * (V3[4]))))) + (F1[5] * (P2[0] * (V3[2] + V3[5]) + (P2[1] * (+cI * (V3[4]) - V3[3]) + (P2[2] * (-1.) * (V3[4] + cI * (V3[3])) - P2[3] * (V3[2] + V3[5])))) + M2 * (F1[2] * (V3[3] + cI * (V3[4])) + F1[3] * (V3[2] - V3[5])))); } void FFV2_0(std::complex F1[], std::complex F2[], std::complex V3[], std::complex COUP, std::complex & vertex) { static std::complex cI = std::complex (0., 1.); std::complex TMP9; TMP9 = (F1[2] * (F2[4] * (V3[2] + V3[5]) + F2[5] * (V3[3] + cI * (V3[4]))) + F1[3] * (F2[4] * (V3[3] - cI * (V3[4])) + F2[5] * (V3[2] - V3[5]))); vertex = COUP * - cI * TMP9; } void FFV2_5_0(std::complex F1[], std::complex F2[], std::complex V3[], std::complex COUP1, std::complex COUP2, std::complex & vertex) { std::complex tmp; FFV2_0(F1, F2, V3, COUP1, vertex); FFV5_0(F1, F2, V3, COUP2, tmp); vertex = vertex + tmp; } void FFV5_1(std::complex F2[], std::complex V3[], std::complex COUP, double M1, double W1, std::complex F1[]) { static std::complex cI = std::complex (0., 1.); double P1[4]; std::complex denom; F1[0] = +F2[0] + V3[0]; F1[1] = +F2[1] + V3[1]; P1[0] = -F1[0].real(); P1[1] = -F1[1].real(); P1[2] = -F1[1].imag(); P1[3] = -F1[0].imag(); denom = COUP/((P1[0] * P1[0]) - (P1[1] * P1[1]) - (P1[2] * P1[2]) - (P1[3] * P1[3]) - M1 * (M1 - cI * W1)); F1[2] = denom * 4. * cI * (F2[2] * (P1[0] * (V3[5] - V3[2]) + (P1[1] * (V3[3] - cI * (V3[4])) + (P1[2] * (V3[4] + cI * (V3[3])) + P1[3] * (V3[5] - V3[2])))) + (+1./4. * (M1 * (F2[5] * (V3[3] + cI * (V3[4])) + 4. * (F2[4] * 1./4. * (V3[2] + V3[5])))) + F2[3] * (P1[0] * (V3[3] + cI * (V3[4])) + (P1[1] * (-1.) * (V3[2] + V3[5]) + (P1[2] * (-1.) * (+cI * (V3[2] + V3[5])) + P1[3] * (V3[3] + cI * (V3[4]))))))); F1[3] = denom * 4. * cI * (F2[2] * (P1[0] * (V3[3] - cI * (V3[4])) + (P1[1] * (V3[5] - V3[2]) + (P1[2] * (-cI * (V3[5]) + cI * (V3[2])) + P1[3] * (+cI * (V3[4]) - V3[3])))) + (+1./4. * (M1 * (F2[5] * (V3[2] - V3[5]) + 4. * (F2[4] * 1./4. * (V3[3] - cI * (V3[4]))))) + F2[3] * (P1[0] * (-1.) * (V3[2] + V3[5]) + (P1[1] * (V3[3] + cI * (V3[4])) + (P1[2] * (V3[4] - cI * (V3[3])) + P1[3] * (V3[2] + V3[5])))))); F1[4] = denom * (-cI) * (F2[4] * (P1[0] * (V3[2] + V3[5]) + (P1[1] * (+cI * (V3[4]) - V3[3]) + (P1[2] * (-1.) * (V3[4] + cI * (V3[3])) - P1[3] * (V3[2] + V3[5])))) + (F2[5] * (P1[0] * (V3[3] + cI * (V3[4])) + (P1[1] * (V3[5] - V3[2]) + (P1[2] * (-cI * (V3[2]) + cI * (V3[5])) - P1[3] * (V3[3] + cI * (V3[4]))))) + M1 * (F2[2] * 4. * (V3[5] - V3[2]) + 4. * (F2[3] * (V3[3] + cI * (V3[4])))))); F1[5] = denom * cI * (F2[4] * (P1[0] * (+cI * (V3[4]) - V3[3]) + (P1[1] * (V3[2] + V3[5]) + (P1[2] * (-1.) * (+cI * (V3[2] + V3[5])) + P1[3] * (+cI * (V3[4]) - V3[3])))) + (F2[5] * (P1[0] * (V3[5] - V3[2]) + (P1[1] * (V3[3] + cI * (V3[4])) + (P1[2] * (V3[4] - cI * (V3[3])) + P1[3] * (V3[5] - V3[2])))) + M1 * (F2[2] * 4. * (+cI * (V3[4]) - V3[3]) + 4. * (F2[3] * (V3[2] + V3[5]))))); } void FFV1_0(std::complex F1[], std::complex F2[], std::complex V3[], std::complex COUP, std::complex & vertex) { static std::complex cI = std::complex (0., 1.); std::complex TMP13; TMP13 = (F1[2] * (F2[4] * (V3[2] + V3[5]) + F2[5] * (V3[3] + cI * (V3[4]))) + (F1[3] * (F2[4] * (V3[3] - cI * (V3[4])) + F2[5] * (V3[2] - V3[5])) + (F1[4] * (F2[2] * (V3[2] - V3[5]) - F2[3] * (V3[3] + cI * (V3[4]))) + F1[5] * (F2[2] * (+cI * (V3[4]) - V3[3]) + F2[3] * (V3[2] + V3[5]))))); vertex = COUP * - cI * TMP13; } void VVVV4P0_1(std::complex V2[], std::complex V3[], std::complex V4[], std::complex COUP, double M1, double W1, std::complex V1[]) { static std::complex cI = std::complex (0., 1.); std::complex TMP12; std::complex TMP11; double P1[4]; std::complex denom; V1[0] = +V2[0] + V3[0] + V4[0]; V1[1] = +V2[1] + V3[1] + V4[1]; P1[0] = -V1[0].real(); P1[1] = -V1[1].real(); P1[2] = -V1[1].imag(); P1[3] = -V1[0].imag(); TMP11 = (V2[2] * V4[2] - V2[3] * V4[3] - V2[4] * V4[4] - V2[5] * V4[5]); TMP12 = (V3[2] * V4[2] - V3[3] * V4[3] - V3[4] * V4[4] - V3[5] * V4[5]); denom = COUP/((P1[0] * P1[0]) - (P1[1] * P1[1]) - (P1[2] * P1[2]) - (P1[3] * P1[3]) - M1 * (M1 - cI * W1)); V1[2] = denom * (-cI * (V3[2] * TMP11) + cI * (V2[2] * TMP12)); V1[3] = denom * (-cI * (V3[3] * TMP11) + cI * (V2[3] * TMP12)); V1[4] = denom * (-cI * (V3[4] * TMP11) + cI * (V2[4] * TMP12)); V1[5] = denom * (-cI * (V3[5] * TMP11) + cI * (V2[5] * TMP12)); } void VVVV3P0_1(std::complex V2[], std::complex V3[], std::complex V4[], std::complex COUP, double M1, double W1, std::complex V1[]) { static std::complex cI = std::complex (0., 1.); std::complex TMP12; double P1[4]; std::complex TMP6; std::complex denom; V1[0] = +V2[0] + V3[0] + V4[0]; V1[1] = +V2[1] + V3[1] + V4[1]; P1[0] = -V1[0].real(); P1[1] = -V1[1].real(); P1[2] = -V1[1].imag(); P1[3] = -V1[0].imag(); TMP6 = (V3[2] * V2[2] - V3[3] * V2[3] - V3[4] * V2[4] - V3[5] * V2[5]); TMP12 = (V3[2] * V4[2] - V3[3] * V4[3] - V3[4] * V4[4] - V3[5] * V4[5]); denom = COUP/((P1[0] * P1[0]) - (P1[1] * P1[1]) - (P1[2] * P1[2]) - (P1[3] * P1[3]) - M1 * (M1 - cI * W1)); V1[2] = denom * (-cI * (TMP6 * V4[2]) + cI * (V2[2] * TMP12)); V1[3] = denom * (-cI * (TMP6 * V4[3]) + cI * (V2[3] * TMP12)); V1[4] = denom * (-cI * (TMP6 * V4[4]) + cI * (V2[4] * TMP12)); V1[5] = denom * (-cI * (TMP6 * V4[5]) + cI * (V2[5] * TMP12)); } void VVV1_0(std::complex V1[], std::complex V2[], std::complex V3[], std::complex COUP, std::complex & vertex) { static std::complex cI = std::complex (0., 1.); std::complex TMP2; std::complex TMP1; double P1[4]; std::complex TMP0; double P2[4]; std::complex TMP7; double P3[4]; std::complex TMP6; std::complex TMP5; std::complex TMP4; std::complex TMP3; std::complex TMP8; P1[0] = V1[0].real(); P1[1] = V1[1].real(); P1[2] = V1[1].imag(); P1[3] = V1[0].imag(); P2[0] = V2[0].real(); P2[1] = V2[1].real(); P2[2] = V2[1].imag(); P2[3] = V2[0].imag(); P3[0] = V3[0].real(); P3[1] = V3[1].real(); P3[2] = V3[1].imag(); P3[3] = V3[0].imag(); TMP8 = (V1[2] * P3[0] - V1[3] * P3[1] - V1[4] * P3[2] - V1[5] * P3[3]); TMP5 = (V2[2] * P3[0] - V2[3] * P3[1] - V2[4] * P3[2] - V2[5] * P3[3]); TMP4 = (P1[0] * V2[2] - P1[1] * V2[3] - P1[2] * V2[4] - P1[3] * V2[5]); TMP7 = (V1[2] * P2[0] - V1[3] * P2[1] - V1[4] * P2[2] - V1[5] * P2[3]); TMP6 = (V3[2] * V2[2] - V3[3] * V2[3] - V3[4] * V2[4] - V3[5] * V2[5]); TMP1 = (V2[2] * V1[2] - V2[3] * V1[3] - V2[4] * V1[4] - V2[5] * V1[5]); TMP0 = (V3[2] * P1[0] - V3[3] * P1[1] - V3[4] * P1[2] - V3[5] * P1[3]); TMP3 = (V3[2] * V1[2] - V3[3] * V1[3] - V3[4] * V1[4] - V3[5] * V1[5]); TMP2 = (V3[2] * P2[0] - V3[3] * P2[1] - V3[4] * P2[2] - V3[5] * P2[3]); vertex = COUP * (TMP1 * (-cI * (TMP0) + cI * (TMP2)) + (TMP3 * (-cI * (TMP5) + cI * (TMP4)) + TMP6 * (-cI * (TMP7) + cI * (TMP8)))); } void FFV2_3(std::complex F1[], std::complex F2[], std::complex COUP, double M3, double W3, std::complex V3[]) { static std::complex cI = std::complex (0., 1.); std::complex denom; std::complex TMP10; double P3[4]; double OM3; OM3 = 0.; if (M3 != 0.) OM3 = 1./(M3 * M3); V3[0] = +F1[0] + F2[0]; V3[1] = +F1[1] + F2[1]; P3[0] = -V3[0].real(); P3[1] = -V3[1].real(); P3[2] = -V3[1].imag(); P3[3] = -V3[0].imag(); TMP10 = (F1[2] * (F2[4] * (P3[0] + P3[3]) + F2[5] * (P3[1] + cI * (P3[2]))) + F1[3] * (F2[4] * (P3[1] - cI * (P3[2])) + F2[5] * (P3[0] - P3[3]))); denom = COUP/((P3[0] * P3[0]) - (P3[1] * P3[1]) - (P3[2] * P3[2]) - (P3[3] * P3[3]) - M3 * (M3 - cI * W3)); V3[2] = denom * (-cI) * (F1[2] * F2[4] + F1[3] * F2[5] - P3[0] * OM3 * TMP10); V3[3] = denom * (-cI) * (-F1[2] * F2[5] - F1[3] * F2[4] - P3[1] * OM3 * TMP10); V3[4] = denom * (-cI) * (-cI * (F1[2] * F2[5]) + cI * (F1[3] * F2[4]) - P3[2] * OM3 * TMP10); V3[5] = denom * (-cI) * (F1[3] * F2[5] - F1[2] * F2[4] - P3[3] * OM3 * TMP10); } void FFV2_4_3(std::complex F1[], std::complex F2[], std::complex COUP1, std::complex COUP2, double M3, double W3, std::complex V3[]) { - std::complex denom; - int i; + int i; std::complex Vtmp[6]; FFV2_3(F1, F2, COUP1, M3, W3, V3); FFV4_3(F1, F2, COUP2, M3, W3, Vtmp); i = 2; while (i < 6) { V3[i] = V3[i] + Vtmp[i]; i++; } } void FFV5_2(std::complex F1[], std::complex V3[], std::complex COUP, double M2, double W2, std::complex F2[]) { static std::complex cI = std::complex (0., 1.); double P2[4]; std::complex denom; F2[0] = +F1[0] + V3[0]; F2[1] = +F1[1] + V3[1]; P2[0] = -F2[0].real(); P2[1] = -F2[1].real(); P2[2] = -F2[1].imag(); P2[3] = -F2[0].imag(); denom = COUP/((P2[0] * P2[0]) - (P2[1] * P2[1]) - (P2[2] * P2[2]) - (P2[3] * P2[3]) - M2 * (M2 - cI * W2)); F2[2] = denom * cI * (F1[2] * (P2[0] * (V3[2] + V3[5]) + (P2[1] * (-1.) * (V3[3] + cI * (V3[4])) + (P2[2] * (+cI * (V3[3]) - V3[4]) - P2[3] * (V3[2] + V3[5])))) + (F1[3] * (P2[0] * (V3[3] - cI * (V3[4])) + (P2[1] * (V3[5] - V3[2]) + (P2[2] * (-cI * (V3[5]) + cI * (V3[2])) + P2[3] * (+cI * (V3[4]) - V3[3])))) + M2 * (F1[4] * 4. * (V3[2] - V3[5]) + 4. * (F1[5] * (+cI * (V3[4]) - V3[3]))))); F2[3] = denom * cI * (F1[2] * (P2[0] * (V3[3] + cI * (V3[4])) + (P2[1] * (-1.) * (V3[2] + V3[5]) + (P2[2] * (-1.) * (+cI * (V3[2] + V3[5])) + P2[3] * (V3[3] + cI * (V3[4]))))) + (F1[3] * (P2[0] * (V3[2] - V3[5]) + (P2[1] * (+cI * (V3[4]) - V3[3]) + (P2[2] * (-1.) * (V3[4] + cI * (V3[3])) + P2[3] * (V3[2] - V3[5])))) + M2 * (F1[4] * (-4.) * (V3[3] + cI * (V3[4])) + 4. * (F1[5] * (V3[2] + V3[5]))))); F2[4] = denom * (-4. * cI) * (F1[4] * (P2[0] * (V3[5] - V3[2]) + (P2[1] * (V3[3] + cI * (V3[4])) + (P2[2] * (V3[4] - cI * (V3[3])) + P2[3] * (V3[5] - V3[2])))) + (+1./4. * (M2 * (F1[3] * (+cI * (V3[4]) - V3[3]) + 4. * (F1[2] * (-1./4.) * (V3[2] + V3[5])))) + F1[5] * (P2[0] * (V3[3] - cI * (V3[4])) + (P2[1] * (-1.) * (V3[2] + V3[5]) + (P2[2] * (+cI * (V3[2] + V3[5])) + P2[3] * (V3[3] - cI * (V3[4]))))))); F2[5] = denom * (-4. * cI) * (F1[4] * (P2[0] * (V3[3] + cI * (V3[4])) + (P2[1] * (V3[5] - V3[2]) + (P2[2] * (-cI * (V3[2]) + cI * (V3[5])) - P2[3] * (V3[3] + cI * (V3[4]))))) + (+1./4. * (M2 * (F1[3] * (V3[5] - V3[2]) + 4. * (F1[2] * (-1./4.) * (V3[3] + cI * (V3[4]))))) + F1[5] * (P2[0] * (-1.) * (V3[2] + V3[5]) + (P2[1] * (V3[3] - cI * (V3[4])) + (P2[2] * (V3[4] + cI * (V3[3])) + P2[3] * (V3[2] + V3[5])))))); } void FFV2_1(std::complex F2[], std::complex V3[], std::complex COUP, double M1, double W1, std::complex F1[]) { static std::complex cI = std::complex (0., 1.); double P1[4]; std::complex denom; F1[0] = +F2[0] + V3[0]; F1[1] = +F2[1] + V3[1]; P1[0] = -F1[0].real(); P1[1] = -F1[1].real(); P1[2] = -F1[1].imag(); P1[3] = -F1[0].imag(); denom = COUP/((P1[0] * P1[0]) - (P1[1] * P1[1]) - (P1[2] * P1[2]) - (P1[3] * P1[3]) - M1 * (M1 - cI * W1)); F1[2] = denom * cI * M1 * (F2[4] * (V3[2] + V3[5]) + F2[5] * (V3[3] + cI * (V3[4]))); F1[3] = denom * - cI * M1 * (F2[4] * (+cI * (V3[4]) - V3[3]) + F2[5] * (V3[5] - V3[2])); F1[4] = denom * (-cI) * (F2[4] * (P1[0] * (V3[2] + V3[5]) + (P1[1] * (+cI * (V3[4]) - V3[3]) + (P1[2] * (-1.) * (V3[4] + cI * (V3[3])) - P1[3] * (V3[2] + V3[5])))) + F2[5] * (P1[0] * (V3[3] + cI * (V3[4])) + (P1[1] * (V3[5] - V3[2]) + (P1[2] * (-cI * (V3[2]) + cI * (V3[5])) - P1[3] * (V3[3] + cI * (V3[4])))))); F1[5] = denom * (-cI) * (F2[4] * (P1[0] * (V3[3] - cI * (V3[4])) + (P1[1] * (-1.) * (V3[2] + V3[5]) + (P1[2] * (+cI * (V3[2] + V3[5])) + P1[3] * (V3[3] - cI * (V3[4]))))) + F2[5] * (P1[0] * (V3[2] - V3[5]) + (P1[1] * (-1.) * (V3[3] + cI * (V3[4])) + (P1[2] * (+cI * (V3[3]) - V3[4]) + P1[3] * (V3[2] - V3[5]))))); } void FFV2_5_1(std::complex F2[], std::complex V3[], std::complex COUP1, std::complex COUP2, double M1, double W1, std::complex F1[]) { - std::complex denom; - int i; + int i; std::complex Ftmp[6]; FFV2_1(F2, V3, COUP1, M1, W1, F1); FFV5_1(F2, V3, COUP2, M1, W1, Ftmp); i = 2; while (i < 6) { F1[i] = F1[i] + Ftmp[i]; i++; } } void FFV5_0(std::complex F1[], std::complex F2[], std::complex V3[], std::complex COUP, std::complex & vertex) { static std::complex cI = std::complex (0., 1.); std::complex TMP15; std::complex TMP16; TMP15 = (F1[2] * (F2[4] * (V3[2] + V3[5]) + F2[5] * (V3[3] + cI * (V3[4]))) + F1[3] * (F2[4] * (V3[3] - cI * (V3[4])) + F2[5] * (V3[2] - V3[5]))); TMP16 = (F1[4] * (F2[2] * (V3[2] - V3[5]) - F2[3] * (V3[3] + cI * (V3[4]))) + F1[5] * (F2[2] * (+cI * (V3[4]) - V3[3]) + F2[3] * (V3[2] + V3[5]))); vertex = COUP * (-1.) * (+cI * (TMP15) + 4. * cI * (TMP16)); } void FFV1_1(std::complex F2[], std::complex V3[], std::complex COUP, double M1, double W1, std::complex F1[]) { static std::complex cI = std::complex (0., 1.); double P1[4]; std::complex denom; F1[0] = +F2[0] + V3[0]; F1[1] = +F2[1] + V3[1]; P1[0] = -F1[0].real(); P1[1] = -F1[1].real(); P1[2] = -F1[1].imag(); P1[3] = -F1[0].imag(); denom = COUP/((P1[0] * P1[0]) - (P1[1] * P1[1]) - (P1[2] * P1[2]) - (P1[3] * P1[3]) - M1 * (M1 - cI * W1)); F1[2] = denom * cI * (F2[2] * (P1[0] * (V3[5] - V3[2]) + (P1[1] * (V3[3] - cI * (V3[4])) + (P1[2] * (V3[4] + cI * (V3[3])) + P1[3] * (V3[5] - V3[2])))) + (F2[3] * (P1[0] * (V3[3] + cI * (V3[4])) + (P1[1] * (-1.) * (V3[2] + V3[5]) + (P1[2] * (-1.) * (+cI * (V3[2] + V3[5])) + P1[3] * (V3[3] + cI * (V3[4]))))) + M1 * (F2[4] * (V3[2] + V3[5]) + F2[5] * (V3[3] + cI * (V3[4]))))); F1[3] = denom * (-cI) * (F2[2] * (P1[0] * (+cI * (V3[4]) - V3[3]) + (P1[1] * (V3[2] - V3[5]) + (P1[2] * (-cI * (V3[2]) + cI * (V3[5])) + P1[3] * (V3[3] - cI * (V3[4]))))) + (F2[3] * (P1[0] * (V3[2] + V3[5]) + (P1[1] * (-1.) * (V3[3] + cI * (V3[4])) + (P1[2] * (+cI * (V3[3]) - V3[4]) - P1[3] * (V3[2] + V3[5])))) + M1 * (F2[4] * (+cI * (V3[4]) - V3[3]) + F2[5] * (V3[5] - V3[2])))); F1[4] = denom * (-cI) * (F2[4] * (P1[0] * (V3[2] + V3[5]) + (P1[1] * (+cI * (V3[4]) - V3[3]) + (P1[2] * (-1.) * (V3[4] + cI * (V3[3])) - P1[3] * (V3[2] + V3[5])))) + (F2[5] * (P1[0] * (V3[3] + cI * (V3[4])) + (P1[1] * (V3[5] - V3[2]) + (P1[2] * (-cI * (V3[2]) + cI * (V3[5])) - P1[3] * (V3[3] + cI * (V3[4]))))) + M1 * (F2[2] * (V3[5] - V3[2]) + F2[3] * (V3[3] + cI * (V3[4]))))); F1[5] = denom * cI * (F2[4] * (P1[0] * (+cI * (V3[4]) - V3[3]) + (P1[1] * (V3[2] + V3[5]) + (P1[2] * (-1.) * (+cI * (V3[2] + V3[5])) + P1[3] * (+cI * (V3[4]) - V3[3])))) + (F2[5] * (P1[0] * (V3[5] - V3[2]) + (P1[1] * (V3[3] + cI * (V3[4])) + (P1[2] * (V3[4] - cI * (V3[3])) + P1[3] * (V3[5] - V3[2])))) + M1 * (F2[2] * (+cI * (V3[4]) - V3[3]) + F2[3] * (V3[2] + V3[5])))); } void FFV4_3(std::complex F1[], std::complex F2[], std::complex COUP, double M3, double W3, std::complex V3[]) { static std::complex cI = std::complex (0., 1.); std::complex denom; std::complex TMP10; double P3[4]; double OM3; std::complex TMP14; OM3 = 0.; if (M3 != 0.) OM3 = 1./(M3 * M3); V3[0] = +F1[0] + F2[0]; V3[1] = +F1[1] + F2[1]; P3[0] = -V3[0].real(); P3[1] = -V3[1].real(); P3[2] = -V3[1].imag(); P3[3] = -V3[0].imag(); TMP14 = (F1[4] * (F2[2] * (P3[0] - P3[3]) - F2[3] * (P3[1] + cI * (P3[2]))) + F1[5] * (F2[2] * (+cI * (P3[2]) - P3[1]) + F2[3] * (P3[0] + P3[3]))); TMP10 = (F1[2] * (F2[4] * (P3[0] + P3[3]) + F2[5] * (P3[1] + cI * (P3[2]))) + F1[3] * (F2[4] * (P3[1] - cI * (P3[2])) + F2[5] * (P3[0] - P3[3]))); denom = COUP/((P3[0] * P3[0]) - (P3[1] * P3[1]) - (P3[2] * P3[2]) - (P3[3] * P3[3]) - M3 * (M3 - cI * W3)); V3[2] = denom * (-2. * cI) * (OM3 * - 1./2. * P3[0] * (TMP10 + 2. * (TMP14)) + (+1./2. * (F1[2] * F2[4] + F1[3] * F2[5]) + F1[4] * F2[2] + F1[5] * F2[3])); V3[3] = denom * (-2. * cI) * (OM3 * - 1./2. * P3[1] * (TMP10 + 2. * (TMP14)) + (-1./2. * (F1[2] * F2[5] + F1[3] * F2[4]) + F1[4] * F2[3] + F1[5] * F2[2])); V3[4] = denom * 2. * cI * (OM3 * 1./2. * P3[2] * (TMP10 + 2. * (TMP14)) + (+1./2. * cI * (F1[2] * F2[5]) - 1./2. * cI * (F1[3] * F2[4]) - cI * (F1[4] * F2[3]) + cI * (F1[5] * F2[2]))); V3[5] = denom * 2. * cI * (OM3 * 1./2. * P3[3] * (TMP10 + 2. * (TMP14)) + (+1./2. * (F1[2] * F2[4]) - 1./2. * (F1[3] * F2[5]) - F1[4] * F2[2] + F1[5] * F2[3])); } void VVVV1P0_1(std::complex V2[], std::complex V3[], std::complex V4[], std::complex COUP, double M1, double W1, std::complex V1[]) { static std::complex cI = std::complex (0., 1.); std::complex TMP11; double P1[4]; std::complex TMP6; std::complex denom; V1[0] = +V2[0] + V3[0] + V4[0]; V1[1] = +V2[1] + V3[1] + V4[1]; P1[0] = -V1[0].real(); P1[1] = -V1[1].real(); P1[2] = -V1[1].imag(); P1[3] = -V1[0].imag(); TMP6 = (V3[2] * V2[2] - V3[3] * V2[3] - V3[4] * V2[4] - V3[5] * V2[5]); TMP11 = (V2[2] * V4[2] - V2[3] * V4[3] - V2[4] * V4[4] - V2[5] * V4[5]); denom = COUP/((P1[0] * P1[0]) - (P1[1] * P1[1]) - (P1[2] * P1[2]) - (P1[3] * P1[3]) - M1 * (M1 - cI * W1)); V1[2] = denom * (-cI * (TMP6 * V4[2]) + cI * (V3[2] * TMP11)); V1[3] = denom * (-cI * (TMP6 * V4[3]) + cI * (V3[3] * TMP11)); V1[4] = denom * (-cI * (TMP6 * V4[4]) + cI * (V3[4] * TMP11)); V1[5] = denom * (-cI * (TMP6 * V4[5]) + cI * (V3[5] * TMP11)); } void VVV1P0_1(std::complex V2[], std::complex V3[], std::complex COUP, double M1, double W1, std::complex V1[]) { static std::complex cI = std::complex (0., 1.); std::complex TMP2; double P1[4]; std::complex TMP0; double P2[4]; double P3[4]; std::complex TMP6; std::complex TMP5; std::complex TMP4; std::complex denom; P2[0] = V2[0].real(); P2[1] = V2[1].real(); P2[2] = V2[1].imag(); P2[3] = V2[0].imag(); P3[0] = V3[0].real(); P3[1] = V3[1].real(); P3[2] = V3[1].imag(); P3[3] = V3[0].imag(); V1[0] = +V2[0] + V3[0]; V1[1] = +V2[1] + V3[1]; P1[0] = -V1[0].real(); P1[1] = -V1[1].real(); P1[2] = -V1[1].imag(); P1[3] = -V1[0].imag(); TMP5 = (V2[2] * P3[0] - V2[3] * P3[1] - V2[4] * P3[2] - V2[5] * P3[3]); TMP4 = (P1[0] * V2[2] - P1[1] * V2[3] - P1[2] * V2[4] - P1[3] * V2[5]); TMP6 = (V3[2] * V2[2] - V3[3] * V2[3] - V3[4] * V2[4] - V3[5] * V2[5]); TMP0 = (V3[2] * P1[0] - V3[3] * P1[1] - V3[4] * P1[2] - V3[5] * P1[3]); TMP2 = (V3[2] * P2[0] - V3[3] * P2[1] - V3[4] * P2[2] - V3[5] * P2[3]); denom = COUP/((P1[0] * P1[0]) - (P1[1] * P1[1]) - (P1[2] * P1[2]) - (P1[3] * P1[3]) - M1 * (M1 - cI * W1)); V1[2] = denom * (TMP6 * (-cI * (P2[0]) + cI * (P3[0])) + (V2[2] * (-cI * (TMP0) + cI * (TMP2)) + V3[2] * (-cI * (TMP5) + cI * (TMP4)))); V1[3] = denom * (TMP6 * (-cI * (P2[1]) + cI * (P3[1])) + (V2[3] * (-cI * (TMP0) + cI * (TMP2)) + V3[3] * (-cI * (TMP5) + cI * (TMP4)))); V1[4] = denom * (TMP6 * (-cI * (P2[2]) + cI * (P3[2])) + (V2[4] * (-cI * (TMP0) + cI * (TMP2)) + V3[4] * (-cI * (TMP5) + cI * (TMP4)))); V1[5] = denom * (TMP6 * (-cI * (P2[3]) + cI * (P3[3])) + (V2[5] * (-cI * (TMP0) + cI * (TMP2)) + V3[5] * (-cI * (TMP5) + cI * (TMP4)))); } } // end namespace MG5_sm_COLOREA diff --git a/Shower/Dipole/Colorea/eeuugg.cc b/Shower/Dipole/Colorea/eeuugg.cc --- a/Shower/Dipole/Colorea/eeuugg.cc +++ b/Shower/Dipole/Colorea/eeuugg.cc @@ -1,292 +1,291 @@ //========================================================================== // This file has been automatically generated for C++ Standalone by // MadGraph5_aMC@NLO v. 2.5.4, 2017-03-28 // By the MadGraph5_aMC@NLO Development Team // Visit launchpad.net/madgraph5 and amcatnlo.web.cern.ch //========================================================================== // and was then modified by J. Bellm. #include "eeuugg.h" #include "HelAmps_sm.h" #include using namespace MG5_sm_COLOREA; //========================================================================== // Class member functions for calculating the matrix elements for // Process: e+ e- > u u~ g g WEIGHTED<=6 @1 //-------------------------------------------------------------------------- // Initialize process. vector eeuugg::producePermutation(double r,vector < double * > & momenta){ setMomenta(momenta); sigmaKin(); static const int res[2][5] = { {5, 6, 3, 4, 0}, {6, 5, 3, 4, 0}}; double jampsum=0.; for( int i=0;i<2;i++) jampsum+=jamp2[0][i]; // std::cout<<"\njampsum "< r )return std::vector(res[i], res[i] + sizeof res[i] / sizeof res[i][0]); } std::cerr<<"\nproducePermutation: Upps.. Something went wrong!!\n"<(); } void eeuugg::initProc(string param_card_name) { cout<<"\nColorea: Init process eeuugg for rearrangement (arXiv:1801.06113)."; // Instantiate the model class and set parameters that stay fixed during run pars = Parameters_sm::getInstance(); SLHAReader_COLOREA slha(param_card_name); pars->setIndependentParameters(slha); pars->setIndependentCouplings(); // pars->printIndependentParameters(); // pars->printIndependentCouplings(); // Set external particle masses for this matrix element mME.push_back(pars->ZERO); mME.push_back(pars->ZERO); mME.push_back(pars->ZERO); mME.push_back(pars->ZERO); mME.push_back(pars->ZERO); mME.push_back(pars->ZERO); jamp2[0] = new double[2]; } //-------------------------------------------------------------------------- // Evaluate |M|^2, part independent of incoming flavour. void eeuugg::sigmaKin() { // Set the parameters which change event by event pars->setDependentParameters(); pars->setDependentCouplings(); static bool firsttime = true; if (firsttime) { // pars->printDependentParameters(); // pars->printDependentCouplings(); firsttime = false; } // Reset color flows for(int i = 0; i < 2; i++ ) jamp2[0][i] = 0.; // Local variables and constants const int ncomb = 64; static bool goodhel[ncomb] = {ncomb * false}; static int ntry = 0, sum_hel = 0, ngood = 0; static int igood[ncomb]; static int jhel; double t[nprocesses]; // Helicities for the process static const int helicities[ncomb][nexternal] = {{-1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1, 1}, {-1, -1, -1, -1, 1, -1}, {-1, -1, -1, -1, 1, 1}, {-1, -1, -1, 1, -1, -1}, {-1, -1, -1, 1, -1, 1}, {-1, -1, -1, 1, 1, -1}, {-1, -1, -1, 1, 1, 1}, {-1, -1, 1, -1, -1, -1}, {-1, -1, 1, -1, -1, 1}, {-1, -1, 1, -1, 1, -1}, {-1, -1, 1, -1, 1, 1}, {-1, -1, 1, 1, -1, -1}, {-1, -1, 1, 1, -1, 1}, {-1, -1, 1, 1, 1, -1}, {-1, -1, 1, 1, 1, 1}, {-1, 1, -1, -1, -1, -1}, {-1, 1, -1, -1, -1, 1}, {-1, 1, -1, -1, 1, -1}, {-1, 1, -1, -1, 1, 1}, {-1, 1, -1, 1, -1, -1}, {-1, 1, -1, 1, -1, 1}, {-1, 1, -1, 1, 1, -1}, {-1, 1, -1, 1, 1, 1}, {-1, 1, 1, -1, -1, -1}, {-1, 1, 1, -1, -1, 1}, {-1, 1, 1, -1, 1, -1}, {-1, 1, 1, -1, 1, 1}, {-1, 1, 1, 1, -1, -1}, {-1, 1, 1, 1, -1, 1}, {-1, 1, 1, 1, 1, -1}, {-1, 1, 1, 1, 1, 1}, {1, -1, -1, -1, -1, -1}, {1, -1, -1, -1, -1, 1}, {1, -1, -1, -1, 1, -1}, {1, -1, -1, -1, 1, 1}, {1, -1, -1, 1, -1, -1}, {1, -1, -1, 1, -1, 1}, {1, -1, -1, 1, 1, -1}, {1, -1, -1, 1, 1, 1}, {1, -1, 1, -1, -1, -1}, {1, -1, 1, -1, -1, 1}, {1, -1, 1, -1, 1, -1}, {1, -1, 1, -1, 1, 1}, {1, -1, 1, 1, -1, -1}, {1, -1, 1, 1, -1, 1}, {1, -1, 1, 1, 1, -1}, {1, -1, 1, 1, 1, 1}, {1, 1, -1, -1, -1, -1}, {1, 1, -1, -1, -1, 1}, {1, 1, -1, -1, 1, -1}, {1, 1, -1, -1, 1, 1}, {1, 1, -1, 1, -1, -1}, {1, 1, -1, 1, -1, 1}, {1, 1, -1, 1, 1, -1}, {1, 1, -1, 1, 1, 1}, {1, 1, 1, -1, -1, -1}, {1, 1, 1, -1, -1, 1}, {1, 1, 1, -1, 1, -1}, {1, 1, 1, -1, 1, 1}, {1, 1, 1, 1, -1, -1}, {1, 1, 1, 1, -1, 1}, {1, 1, 1, 1, 1, -1}, {1, 1, 1, 1, 1, 1}}; // Denominators: spins, colors and identical particles const int denominators[nprocesses] = {8}; ntry = ntry + 1; // Reset the matrix elements for(int i = 0; i < nprocesses; i++ ) { matrix_element[i] = 0.; } // Define permutation int perm[nexternal]; for(int i = 0; i < nexternal; i++ ) { perm[i] = i; } if (sum_hel == 0 || ntry < 10) { // Calculate the matrix element for all helicities for(int ihel = 0; ihel < ncomb; ihel++ ) { if (goodhel[ihel] || ntry < 2) { calculate_wavefunctions(perm, helicities[ihel]); t[0] = matrix_1_epem_uuxgg(); double tsum = 0; for(int iproc = 0; iproc < nprocesses; iproc++ ) { matrix_element[iproc] += t[iproc]; tsum += t[iproc]; } // Store which helicities give non-zero result if (tsum != 0. && !goodhel[ihel]) { goodhel[ihel] = true; ngood++; igood[ngood] = ihel; } } } jhel = 0; sum_hel = min(sum_hel, ngood); } else { // Only use the "good" helicities for(int j = 0; j < sum_hel; j++ ) { jhel++; if (jhel >= ngood) jhel = 0; double hwgt = double(ngood)/double(sum_hel); int ihel = igood[jhel]; calculate_wavefunctions(perm, helicities[ihel]); t[0] = matrix_1_epem_uuxgg(); for(int iproc = 0; iproc < nprocesses; iproc++ ) { matrix_element[iproc] += t[iproc] * hwgt; } } } for (int i = 0; i < nprocesses; i++ ) matrix_element[i] /= denominators[i]; } //-------------------------------------------------------------------------- // Evaluate |M|^2 for each subprocess void eeuugg::calculate_wavefunctions(const int perm[], const int hel[]) { // Calculate wavefunctions for all processes // Calculate all wavefunctions oxxxxx(p[perm[0]], mME[0], hel[0], -1, w[0]); ixxxxx(p[perm[1]], mME[1], hel[1], +1, w[1]); oxxxxx(p[perm[2]], mME[2], hel[2], +1, w[2]); ixxxxx(p[perm[3]], mME[3], hel[3], -1, w[3]); vxxxxx(p[perm[4]], mME[4], hel[4], +1, w[4]); vxxxxx(p[perm[5]], mME[5], hel[5], +1, w[5]); FFV1P0_3(w[1], w[0], pars->GC_3, pars->ZERO, pars->ZERO, w[6]); FFV1_1(w[2], w[4], pars->GC_11, pars->ZERO, pars->ZERO, w[7]); FFV1_2(w[3], w[6], pars->GC_2, pars->ZERO, pars->ZERO, w[8]); FFV2_4_3(w[1], w[0], pars->GC_50, pars->GC_59, pars->mdl_MZ, pars->mdl_WZ, w[9]); FFV2_5_2(w[3], w[9], pars->GC_51, pars->GC_58, pars->ZERO, pars->ZERO, w[10]); FFV1_2(w[3], w[5], pars->GC_11, pars->ZERO, pars->ZERO, w[11]); FFV1_1(w[2], w[5], pars->GC_11, pars->ZERO, pars->ZERO, w[12]); FFV1_2(w[3], w[4], pars->GC_11, pars->ZERO, pars->ZERO, w[13]); FFV1_1(w[2], w[6], pars->GC_2, pars->ZERO, pars->ZERO, w[14]); FFV2_5_1(w[2], w[9], pars->GC_51, pars->GC_58, pars->ZERO, pars->ZERO, w[15]); VVV1P0_1(w[4], w[5], pars->GC_10, pars->ZERO, pars->ZERO, w[16]); // Calculate all amplitudes // Amplitude(s) for diagram number 0 FFV1_0(w[8], w[7], w[5], pars->GC_11, amp[0]); FFV1_0(w[10], w[7], w[5], pars->GC_11, amp[1]); FFV1_0(w[11], w[7], w[6], pars->GC_2, amp[2]); FFV2_5_0(w[11], w[7], w[9], pars->GC_51, pars->GC_58, amp[3]); FFV1_0(w[8], w[12], w[4], pars->GC_11, amp[4]); FFV1_0(w[10], w[12], w[4], pars->GC_11, amp[5]); FFV1_0(w[13], w[12], w[6], pars->GC_2, amp[6]); FFV2_5_0(w[13], w[12], w[9], pars->GC_51, pars->GC_58, amp[7]); FFV1_0(w[13], w[14], w[5], pars->GC_11, amp[8]); FFV1_0(w[13], w[15], w[5], pars->GC_11, amp[9]); FFV1_0(w[11], w[14], w[4], pars->GC_11, amp[10]); FFV1_0(w[11], w[15], w[4], pars->GC_11, amp[11]); FFV1_0(w[3], w[14], w[16], pars->GC_11, amp[12]); FFV1_0(w[8], w[2], w[16], pars->GC_11, amp[13]); FFV1_0(w[3], w[15], w[16], pars->GC_11, amp[14]); FFV1_0(w[10], w[2], w[16], pars->GC_11, amp[15]); } double eeuugg::matrix_1_epem_uuxgg() { //int i, j; // Local variables //const int ngraphs = 16; //const int ncolor = 2; - std::complex ztemp; std::complex jamp[2]; // The color matrix; //static const double denom[ncolor] = {3, 3}; //static const double cf[ncolor][ncolor] = {{16, -2}, {-2, 16}}; // Calculate color flows jamp[0] = +amp[0] + amp[1] + amp[2] + amp[3] + amp[10] + amp[11] - std::complex (0, 1) * amp[12] - std::complex (0, 1) * amp[13] - std::complex (0, 1) * amp[14] - std::complex (0, 1) * amp[15]; jamp[1] = +amp[4] + amp[5] + amp[6] + amp[7] + amp[8] + amp[9] + std::complex (0, 1) * amp[12] + std::complex (0, 1) * amp[13] + std::complex (0, 1) * amp[14] + std::complex (0, 1) * amp[15]; // Store the leading color flows for choice of color for(int i = 0; i < 2; i++ ) jamp2[0][i] += real(jamp[i] * conj(jamp[i])); return -1.; } double eeuugg::get_jamp2(int i) { return jamp2[0][i]; } int eeuugg::colorstring(int i, int j) { static const double res[2][5] = { {5, 6, 3, 4, 0}, {6, 5, 3, 4, 0}}; return res[i][j]; } int eeuugg::NCol() { const int ncolor = 2; return ncolor; } diff --git a/Shower/Dipole/Colorea/eeuuggg.cc b/Shower/Dipole/Colorea/eeuuggg.cc --- a/Shower/Dipole/Colorea/eeuuggg.cc +++ b/Shower/Dipole/Colorea/eeuuggg.cc @@ -1,532 +1,531 @@ //========================================================================== // This file has been automatically generated for C++ Standalone by // MadGraph5_aMC@NLO v. 2.5.4, 2017-03-28 // By the MadGraph5_aMC@NLO Development Team // Visit launchpad.net/madgraph5 and amcatnlo.web.cern.ch //========================================================================== // and was then modified by J. Bellm. #include "eeuuggg.h" #include "HelAmps_sm.h" #include using namespace MG5_sm_COLOREA; //========================================================================== // Class member functions for calculating the matrix elements for // Process: e+ e- > u u~ g g g WEIGHTED<=7 @1 //-------------------------------------------------------------------------- // Initialize process. vector eeuuggg::producePermutation(double r,vector < double * > & momenta){ static bool initialized=false; if (!initialized){ initProc("param_card.dat"); initialized=true; } setMomenta(momenta); sigmaKin(); static const int res[6][6] = { {5, 6, 7, 3, 4, 0}, {5, 7, 6, 3, 4, 0}, {6, 5, 7, 3, 4, 0}, {6, 7, 5, 3, 4, 0}, {7, 5, 6, 3, 4, 0}, {7, 6, 5, 3, 4, 0}}; double jampsum=0.; for( int i=0;i<6;i++) jampsum+=jamp2[0][i]; double cur=0.; for(int i=0;i<6;i++){ cur+=jamp2[0][i]; if( cur/jampsum > r )return std::vector(res[i], res[i] + sizeof res[i] / sizeof res[i][0]); } //std::cout<<"producePermutation: Upps.. Something went wrong!!"; return std::vector(); } void eeuuggg::initProc(string param_card_name) { // Instantiate the model class and set parameters that stay fixed during run cout<<"\nColorea: Init process eeuuggg for rearrangement (arXiv:1801.06113)."; pars = Parameters_sm::getInstance(); SLHAReader_COLOREA slha(param_card_name); pars->setIndependentParameters(slha); pars->setIndependentCouplings(); // pars->printIndependentParameters(); // pars->printIndependentCouplings(); // Set external particle masses for this matrix element mME.push_back(pars->ZERO); mME.push_back(pars->ZERO); mME.push_back(pars->ZERO); mME.push_back(pars->ZERO); mME.push_back(pars->ZERO); mME.push_back(pars->ZERO); mME.push_back(pars->ZERO); jamp2[0] = new double[6]; } //-------------------------------------------------------------------------- // Evaluate |M|^2, part independent of incoming flavour. void eeuuggg::sigmaKin() { // Set the parameters which change event by event pars->setDependentParameters(); pars->setDependentCouplings(); static bool firsttime = true; if (firsttime) { // pars->printDependentParameters(); // pars->printDependentCouplings(); firsttime = false; } // Reset color flows for(int i = 0; i < 6; i++ ) jamp2[0][i] = 0.; // Local variables and constants const int ncomb = 128; static bool goodhel[ncomb] = {ncomb * false}; static int ntry = 0, sum_hel = 0, ngood = 0; static int igood[ncomb]; static int jhel; // std::complex * * wfs; double t[nprocesses]; // Helicities for the process static const int helicities[ncomb][nexternal] = {{-1, -1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1, -1, 1}, {-1, -1, -1, -1, -1, 1, -1}, {-1, -1, -1, -1, -1, 1, 1}, {-1, -1, -1, -1, 1, -1, -1}, {-1, -1, -1, -1, 1, -1, 1}, {-1, -1, -1, -1, 1, 1, -1}, {-1, -1, -1, -1, 1, 1, 1}, {-1, -1, -1, 1, -1, -1, -1}, {-1, -1, -1, 1, -1, -1, 1}, {-1, -1, -1, 1, -1, 1, -1}, {-1, -1, -1, 1, -1, 1, 1}, {-1, -1, -1, 1, 1, -1, -1}, {-1, -1, -1, 1, 1, -1, 1}, {-1, -1, -1, 1, 1, 1, -1}, {-1, -1, -1, 1, 1, 1, 1}, {-1, -1, 1, -1, -1, -1, -1}, {-1, -1, 1, -1, -1, -1, 1}, {-1, -1, 1, -1, -1, 1, -1}, {-1, -1, 1, -1, -1, 1, 1}, {-1, -1, 1, -1, 1, -1, -1}, {-1, -1, 1, -1, 1, -1, 1}, {-1, -1, 1, -1, 1, 1, -1}, {-1, -1, 1, -1, 1, 1, 1}, {-1, -1, 1, 1, -1, -1, -1}, {-1, -1, 1, 1, -1, -1, 1}, {-1, -1, 1, 1, -1, 1, -1}, {-1, -1, 1, 1, -1, 1, 1}, {-1, -1, 1, 1, 1, -1, -1}, {-1, -1, 1, 1, 1, -1, 1}, {-1, -1, 1, 1, 1, 1, -1}, {-1, -1, 1, 1, 1, 1, 1}, {-1, 1, -1, -1, -1, -1, -1}, {-1, 1, -1, -1, -1, -1, 1}, {-1, 1, -1, -1, -1, 1, -1}, {-1, 1, -1, -1, -1, 1, 1}, {-1, 1, -1, -1, 1, -1, -1}, {-1, 1, -1, -1, 1, -1, 1}, {-1, 1, -1, -1, 1, 1, -1}, {-1, 1, -1, -1, 1, 1, 1}, {-1, 1, -1, 1, -1, -1, -1}, {-1, 1, -1, 1, -1, -1, 1}, {-1, 1, -1, 1, -1, 1, -1}, {-1, 1, -1, 1, -1, 1, 1}, {-1, 1, -1, 1, 1, -1, -1}, {-1, 1, -1, 1, 1, -1, 1}, {-1, 1, -1, 1, 1, 1, -1}, {-1, 1, -1, 1, 1, 1, 1}, {-1, 1, 1, -1, -1, -1, -1}, {-1, 1, 1, -1, -1, -1, 1}, {-1, 1, 1, -1, -1, 1, -1}, {-1, 1, 1, -1, -1, 1, 1}, {-1, 1, 1, -1, 1, -1, -1}, {-1, 1, 1, -1, 1, -1, 1}, {-1, 1, 1, -1, 1, 1, -1}, {-1, 1, 1, -1, 1, 1, 1}, {-1, 1, 1, 1, -1, -1, -1}, {-1, 1, 1, 1, -1, -1, 1}, {-1, 1, 1, 1, -1, 1, -1}, {-1, 1, 1, 1, -1, 1, 1}, {-1, 1, 1, 1, 1, -1, -1}, {-1, 1, 1, 1, 1, -1, 1}, {-1, 1, 1, 1, 1, 1, -1}, {-1, 1, 1, 1, 1, 1, 1}, {1, -1, -1, -1, -1, -1, -1}, {1, -1, -1, -1, -1, -1, 1}, {1, -1, -1, -1, -1, 1, -1}, {1, -1, -1, -1, -1, 1, 1}, {1, -1, -1, -1, 1, -1, -1}, {1, -1, -1, -1, 1, -1, 1}, {1, -1, -1, -1, 1, 1, -1}, {1, -1, -1, -1, 1, 1, 1}, {1, -1, -1, 1, -1, -1, -1}, {1, -1, -1, 1, -1, -1, 1}, {1, -1, -1, 1, -1, 1, -1}, {1, -1, -1, 1, -1, 1, 1}, {1, -1, -1, 1, 1, -1, -1}, {1, -1, -1, 1, 1, -1, 1}, {1, -1, -1, 1, 1, 1, -1}, {1, -1, -1, 1, 1, 1, 1}, {1, -1, 1, -1, -1, -1, -1}, {1, -1, 1, -1, -1, -1, 1}, {1, -1, 1, -1, -1, 1, -1}, {1, -1, 1, -1, -1, 1, 1}, {1, -1, 1, -1, 1, -1, -1}, {1, -1, 1, -1, 1, -1, 1}, {1, -1, 1, -1, 1, 1, -1}, {1, -1, 1, -1, 1, 1, 1}, {1, -1, 1, 1, -1, -1, -1}, {1, -1, 1, 1, -1, -1, 1}, {1, -1, 1, 1, -1, 1, -1}, {1, -1, 1, 1, -1, 1, 1}, {1, -1, 1, 1, 1, -1, -1}, {1, -1, 1, 1, 1, -1, 1}, {1, -1, 1, 1, 1, 1, -1}, {1, -1, 1, 1, 1, 1, 1}, {1, 1, -1, -1, -1, -1, -1}, {1, 1, -1, -1, -1, -1, 1}, {1, 1, -1, -1, -1, 1, -1}, {1, 1, -1, -1, -1, 1, 1}, {1, 1, -1, -1, 1, -1, -1}, {1, 1, -1, -1, 1, -1, 1}, {1, 1, -1, -1, 1, 1, -1}, {1, 1, -1, -1, 1, 1, 1}, {1, 1, -1, 1, -1, -1, -1}, {1, 1, -1, 1, -1, -1, 1}, {1, 1, -1, 1, -1, 1, -1}, {1, 1, -1, 1, -1, 1, 1}, {1, 1, -1, 1, 1, -1, -1}, {1, 1, -1, 1, 1, -1, 1}, {1, 1, -1, 1, 1, 1, -1}, {1, 1, -1, 1, 1, 1, 1}, {1, 1, 1, -1, -1, -1, -1}, {1, 1, 1, -1, -1, -1, 1}, {1, 1, 1, -1, -1, 1, -1}, {1, 1, 1, -1, -1, 1, 1}, {1, 1, 1, -1, 1, -1, -1}, {1, 1, 1, -1, 1, -1, 1}, {1, 1, 1, -1, 1, 1, -1}, {1, 1, 1, -1, 1, 1, 1}, {1, 1, 1, 1, -1, -1, -1}, {1, 1, 1, 1, -1, -1, 1}, {1, 1, 1, 1, -1, 1, -1}, {1, 1, 1, 1, -1, 1, 1}, {1, 1, 1, 1, 1, -1, -1}, {1, 1, 1, 1, 1, -1, 1}, {1, 1, 1, 1, 1, 1, -1}, {1, 1, 1, 1, 1, 1, 1}}; // Denominators: spins, colors and identical particles const int denominators[nprocesses] = {24}; ntry = ntry + 1; // Reset the matrix elements for(int i = 0; i < nprocesses; i++ ) { matrix_element[i] = 0.; } // Define permutation int perm[nexternal]; for(int i = 0; i < nexternal; i++ ) { perm[i] = i; } if (sum_hel == 0 || ntry < 10) { // Calculate the matrix element for all helicities for(int ihel = 0; ihel < ncomb; ihel++ ) { if (goodhel[ihel] || ntry < 2) { calculate_wavefunctions(perm, helicities[ihel]); t[0] = matrix_1_epem_uuxggg(); double tsum = 0; for(int iproc = 0; iproc < nprocesses; iproc++ ) { matrix_element[iproc] += t[iproc]; tsum += t[iproc]; } // Store which helicities give non-zero result if (tsum != 0. && !goodhel[ihel]) { goodhel[ihel] = true; ngood++; igood[ngood] = ihel; } } } jhel = 0; sum_hel = min(sum_hel, ngood); } else { // Only use the "good" helicities for(int j = 0; j < sum_hel; j++ ) { jhel++; if (jhel >= ngood) jhel = 0; double hwgt = double(ngood)/double(sum_hel); int ihel = igood[jhel]; calculate_wavefunctions(perm, helicities[ihel]); t[0] = matrix_1_epem_uuxggg(); for(int iproc = 0; iproc < nprocesses; iproc++ ) { matrix_element[iproc] += t[iproc] * hwgt; } } } for (int i = 0; i < nprocesses; i++ ) matrix_element[i] /= denominators[i]; } //========================================================================== // Private class member functions //-------------------------------------------------------------------------- // Evaluate |M|^2 for each subprocess void eeuuggg::calculate_wavefunctions(const int perm[], const int hel[]) { // Calculate wavefunctions for all processes // int i;//, j; // Calculate all wavefunctions oxxxxx(p[perm[0]], mME[0], hel[0], -1, w[0]); ixxxxx(p[perm[1]], mME[1], hel[1], +1, w[1]); oxxxxx(p[perm[2]], mME[2], hel[2], +1, w[2]); ixxxxx(p[perm[3]], mME[3], hel[3], -1, w[3]); vxxxxx(p[perm[4]], mME[4], hel[4], +1, w[4]); vxxxxx(p[perm[5]], mME[5], hel[5], +1, w[5]); vxxxxx(p[perm[6]], mME[6], hel[6], +1, w[6]); FFV1P0_3(w[1], w[0], pars->GC_3, pars->ZERO, pars->ZERO, w[7]); FFV1_1(w[2], w[4], pars->GC_11, pars->ZERO, pars->ZERO, w[8]); FFV1_2(w[3], w[7], pars->GC_2, pars->ZERO, pars->ZERO, w[9]); FFV1_1(w[8], w[5], pars->GC_11, pars->ZERO, pars->ZERO, w[10]); FFV1_1(w[8], w[6], pars->GC_11, pars->ZERO, pars->ZERO, w[11]); FFV2_4_3(w[1], w[0], pars->GC_50, pars->GC_59, pars->mdl_MZ, pars->mdl_WZ, w[12]); FFV2_5_2(w[3], w[12], pars->GC_51, pars->GC_58, pars->ZERO, pars->ZERO, w[13]); FFV1_2(w[3], w[5], pars->GC_11, pars->ZERO, pars->ZERO, w[14]); FFV1_1(w[8], w[7], pars->GC_2, pars->ZERO, pars->ZERO, w[15]); FFV1_2(w[14], w[7], pars->GC_2, pars->ZERO, pars->ZERO, w[16]); FFV2_5_1(w[8], w[12], pars->GC_51, pars->GC_58, pars->ZERO, pars->ZERO, w[17]); FFV2_5_2(w[14], w[12], pars->GC_51, pars->GC_58, pars->ZERO, pars->ZERO, w[18]); FFV1_2(w[3], w[6], pars->GC_11, pars->ZERO, pars->ZERO, w[19]); FFV1_2(w[19], w[7], pars->GC_2, pars->ZERO, pars->ZERO, w[20]); FFV2_5_2(w[19], w[12], pars->GC_51, pars->GC_58, pars->ZERO, pars->ZERO, w[21]); VVV1P0_1(w[5], w[6], pars->GC_10, pars->ZERO, pars->ZERO, w[22]); FFV1_1(w[2], w[5], pars->GC_11, pars->ZERO, pars->ZERO, w[23]); FFV1_1(w[23], w[4], pars->GC_11, pars->ZERO, pars->ZERO, w[24]); FFV1_1(w[23], w[6], pars->GC_11, pars->ZERO, pars->ZERO, w[25]); FFV1_2(w[3], w[4], pars->GC_11, pars->ZERO, pars->ZERO, w[26]); FFV1_1(w[23], w[7], pars->GC_2, pars->ZERO, pars->ZERO, w[27]); FFV1_2(w[26], w[7], pars->GC_2, pars->ZERO, pars->ZERO, w[28]); FFV2_5_1(w[23], w[12], pars->GC_51, pars->GC_58, pars->ZERO, pars->ZERO, w[29]); FFV2_5_2(w[26], w[12], pars->GC_51, pars->GC_58, pars->ZERO, pars->ZERO, w[30]); VVV1P0_1(w[4], w[6], pars->GC_10, pars->ZERO, pars->ZERO, w[31]); FFV1_1(w[2], w[6], pars->GC_11, pars->ZERO, pars->ZERO, w[32]); FFV1_1(w[32], w[4], pars->GC_11, pars->ZERO, pars->ZERO, w[33]); FFV1_1(w[32], w[5], pars->GC_11, pars->ZERO, pars->ZERO, w[34]); FFV1_1(w[32], w[7], pars->GC_2, pars->ZERO, pars->ZERO, w[35]); FFV2_5_1(w[32], w[12], pars->GC_51, pars->GC_58, pars->ZERO, pars->ZERO, w[36]); VVV1P0_1(w[4], w[5], pars->GC_10, pars->ZERO, pars->ZERO, w[37]); FFV1_1(w[2], w[7], pars->GC_2, pars->ZERO, pars->ZERO, w[38]); FFV1_2(w[26], w[5], pars->GC_11, pars->ZERO, pars->ZERO, w[39]); FFV1_2(w[26], w[6], pars->GC_11, pars->ZERO, pars->ZERO, w[40]); FFV2_5_1(w[2], w[12], pars->GC_51, pars->GC_58, pars->ZERO, pars->ZERO, w[41]); FFV1_2(w[14], w[4], pars->GC_11, pars->ZERO, pars->ZERO, w[42]); FFV1_2(w[14], w[6], pars->GC_11, pars->ZERO, pars->ZERO, w[43]); FFV1_2(w[19], w[4], pars->GC_11, pars->ZERO, pars->ZERO, w[44]); FFV1_2(w[19], w[5], pars->GC_11, pars->ZERO, pars->ZERO, w[45]); FFV1_2(w[3], w[37], pars->GC_11, pars->ZERO, pars->ZERO, w[46]); VVV1P0_1(w[37], w[6], pars->GC_10, pars->ZERO, pars->ZERO, w[47]); FFV1_1(w[2], w[37], pars->GC_11, pars->ZERO, pars->ZERO, w[48]); FFV1_2(w[3], w[31], pars->GC_11, pars->ZERO, pars->ZERO, w[49]); VVV1P0_1(w[31], w[5], pars->GC_10, pars->ZERO, pars->ZERO, w[50]); FFV1_1(w[2], w[31], pars->GC_11, pars->ZERO, pars->ZERO, w[51]); FFV1_2(w[3], w[22], pars->GC_11, pars->ZERO, pars->ZERO, w[52]); VVV1P0_1(w[4], w[22], pars->GC_10, pars->ZERO, pars->ZERO, w[53]); FFV1_1(w[2], w[22], pars->GC_11, pars->ZERO, pars->ZERO, w[54]); VVVV1P0_1(w[4], w[5], w[6], pars->GC_12, pars->ZERO, pars->ZERO, w[55]); VVVV3P0_1(w[4], w[5], w[6], pars->GC_12, pars->ZERO, pars->ZERO, w[56]); VVVV4P0_1(w[4], w[5], w[6], pars->GC_12, pars->ZERO, pars->ZERO, w[57]); // Calculate all amplitudes // Amplitude(s) for diagram number 0 FFV1_0(w[9], w[10], w[6], pars->GC_11, amp[0]); FFV1_0(w[9], w[11], w[5], pars->GC_11, amp[1]); FFV1_0(w[13], w[10], w[6], pars->GC_11, amp[2]); FFV1_0(w[13], w[11], w[5], pars->GC_11, amp[3]); FFV1_0(w[14], w[15], w[6], pars->GC_11, amp[4]); FFV1_0(w[16], w[8], w[6], pars->GC_11, amp[5]); FFV1_0(w[14], w[17], w[6], pars->GC_11, amp[6]); FFV1_0(w[18], w[8], w[6], pars->GC_11, amp[7]); FFV1_0(w[19], w[15], w[5], pars->GC_11, amp[8]); FFV1_0(w[20], w[8], w[5], pars->GC_11, amp[9]); FFV1_0(w[19], w[17], w[5], pars->GC_11, amp[10]); FFV1_0(w[21], w[8], w[5], pars->GC_11, amp[11]); FFV1_0(w[3], w[15], w[22], pars->GC_11, amp[12]); FFV1_0(w[9], w[8], w[22], pars->GC_11, amp[13]); FFV1_0(w[3], w[17], w[22], pars->GC_11, amp[14]); FFV1_0(w[13], w[8], w[22], pars->GC_11, amp[15]); FFV1_0(w[9], w[24], w[6], pars->GC_11, amp[16]); FFV1_0(w[9], w[25], w[4], pars->GC_11, amp[17]); FFV1_0(w[13], w[24], w[6], pars->GC_11, amp[18]); FFV1_0(w[13], w[25], w[4], pars->GC_11, amp[19]); FFV1_0(w[26], w[27], w[6], pars->GC_11, amp[20]); FFV1_0(w[28], w[23], w[6], pars->GC_11, amp[21]); FFV1_0(w[26], w[29], w[6], pars->GC_11, amp[22]); FFV1_0(w[30], w[23], w[6], pars->GC_11, amp[23]); FFV1_0(w[19], w[27], w[4], pars->GC_11, amp[24]); FFV1_0(w[20], w[23], w[4], pars->GC_11, amp[25]); FFV1_0(w[19], w[29], w[4], pars->GC_11, amp[26]); FFV1_0(w[21], w[23], w[4], pars->GC_11, amp[27]); FFV1_0(w[3], w[27], w[31], pars->GC_11, amp[28]); FFV1_0(w[9], w[23], w[31], pars->GC_11, amp[29]); FFV1_0(w[3], w[29], w[31], pars->GC_11, amp[30]); FFV1_0(w[13], w[23], w[31], pars->GC_11, amp[31]); FFV1_0(w[9], w[33], w[5], pars->GC_11, amp[32]); FFV1_0(w[9], w[34], w[4], pars->GC_11, amp[33]); FFV1_0(w[13], w[33], w[5], pars->GC_11, amp[34]); FFV1_0(w[13], w[34], w[4], pars->GC_11, amp[35]); FFV1_0(w[26], w[35], w[5], pars->GC_11, amp[36]); FFV1_0(w[28], w[32], w[5], pars->GC_11, amp[37]); FFV1_0(w[26], w[36], w[5], pars->GC_11, amp[38]); FFV1_0(w[30], w[32], w[5], pars->GC_11, amp[39]); FFV1_0(w[14], w[35], w[4], pars->GC_11, amp[40]); FFV1_0(w[16], w[32], w[4], pars->GC_11, amp[41]); FFV1_0(w[14], w[36], w[4], pars->GC_11, amp[42]); FFV1_0(w[18], w[32], w[4], pars->GC_11, amp[43]); FFV1_0(w[3], w[35], w[37], pars->GC_11, amp[44]); FFV1_0(w[9], w[32], w[37], pars->GC_11, amp[45]); FFV1_0(w[3], w[36], w[37], pars->GC_11, amp[46]); FFV1_0(w[13], w[32], w[37], pars->GC_11, amp[47]); FFV1_0(w[39], w[38], w[6], pars->GC_11, amp[48]); FFV1_0(w[40], w[38], w[5], pars->GC_11, amp[49]); FFV1_0(w[39], w[41], w[6], pars->GC_11, amp[50]); FFV1_0(w[40], w[41], w[5], pars->GC_11, amp[51]); FFV1_0(w[26], w[38], w[22], pars->GC_11, amp[52]); FFV1_0(w[28], w[2], w[22], pars->GC_11, amp[53]); FFV1_0(w[26], w[41], w[22], pars->GC_11, amp[54]); FFV1_0(w[30], w[2], w[22], pars->GC_11, amp[55]); FFV1_0(w[42], w[38], w[6], pars->GC_11, amp[56]); FFV1_0(w[43], w[38], w[4], pars->GC_11, amp[57]); FFV1_0(w[42], w[41], w[6], pars->GC_11, amp[58]); FFV1_0(w[43], w[41], w[4], pars->GC_11, amp[59]); FFV1_0(w[14], w[38], w[31], pars->GC_11, amp[60]); FFV1_0(w[16], w[2], w[31], pars->GC_11, amp[61]); FFV1_0(w[14], w[41], w[31], pars->GC_11, amp[62]); FFV1_0(w[18], w[2], w[31], pars->GC_11, amp[63]); FFV1_0(w[44], w[38], w[5], pars->GC_11, amp[64]); FFV1_0(w[45], w[38], w[4], pars->GC_11, amp[65]); FFV1_0(w[44], w[41], w[5], pars->GC_11, amp[66]); FFV1_0(w[45], w[41], w[4], pars->GC_11, amp[67]); FFV1_0(w[19], w[38], w[37], pars->GC_11, amp[68]); FFV1_0(w[20], w[2], w[37], pars->GC_11, amp[69]); FFV1_0(w[19], w[41], w[37], pars->GC_11, amp[70]); FFV1_0(w[21], w[2], w[37], pars->GC_11, amp[71]); FFV1_0(w[46], w[38], w[6], pars->GC_11, amp[72]); FFV1_0(w[3], w[38], w[47], pars->GC_11, amp[73]); FFV1_0(w[9], w[48], w[6], pars->GC_11, amp[74]); FFV1_0(w[9], w[2], w[47], pars->GC_11, amp[75]); FFV1_0(w[46], w[41], w[6], pars->GC_11, amp[76]); FFV1_0(w[3], w[41], w[47], pars->GC_11, amp[77]); FFV1_0(w[13], w[48], w[6], pars->GC_11, amp[78]); FFV1_0(w[13], w[2], w[47], pars->GC_11, amp[79]); FFV1_0(w[49], w[38], w[5], pars->GC_11, amp[80]); FFV1_0(w[3], w[38], w[50], pars->GC_11, amp[81]); FFV1_0(w[9], w[51], w[5], pars->GC_11, amp[82]); FFV1_0(w[9], w[2], w[50], pars->GC_11, amp[83]); FFV1_0(w[49], w[41], w[5], pars->GC_11, amp[84]); FFV1_0(w[3], w[41], w[50], pars->GC_11, amp[85]); FFV1_0(w[13], w[51], w[5], pars->GC_11, amp[86]); FFV1_0(w[13], w[2], w[50], pars->GC_11, amp[87]); FFV1_0(w[52], w[38], w[4], pars->GC_11, amp[88]); FFV1_0(w[3], w[38], w[53], pars->GC_11, amp[89]); FFV1_0(w[9], w[54], w[4], pars->GC_11, amp[90]); FFV1_0(w[9], w[2], w[53], pars->GC_11, amp[91]); FFV1_0(w[52], w[41], w[4], pars->GC_11, amp[92]); FFV1_0(w[3], w[41], w[53], pars->GC_11, amp[93]); FFV1_0(w[13], w[54], w[4], pars->GC_11, amp[94]); FFV1_0(w[13], w[2], w[53], pars->GC_11, amp[95]); FFV1_0(w[3], w[38], w[55], pars->GC_11, amp[96]); FFV1_0(w[3], w[38], w[56], pars->GC_11, amp[97]); FFV1_0(w[3], w[38], w[57], pars->GC_11, amp[98]); FFV1_0(w[9], w[2], w[55], pars->GC_11, amp[99]); FFV1_0(w[9], w[2], w[56], pars->GC_11, amp[100]); FFV1_0(w[9], w[2], w[57], pars->GC_11, amp[101]); FFV1_0(w[3], w[41], w[55], pars->GC_11, amp[102]); FFV1_0(w[3], w[41], w[56], pars->GC_11, amp[103]); FFV1_0(w[3], w[41], w[57], pars->GC_11, amp[104]); FFV1_0(w[13], w[2], w[55], pars->GC_11, amp[105]); FFV1_0(w[13], w[2], w[56], pars->GC_11, amp[106]); FFV1_0(w[13], w[2], w[57], pars->GC_11, amp[107]); } double eeuuggg::matrix_1_epem_uuxggg() { int i;//, j; // Local variables // const int ngraphs = 108; const int ncolor = 6; - std::complex ztemp; std::complex jamp[ncolor]; // The color matrix; // static const double denom[ncolor] = {9, 9, 9, 9, 9, 9}; // static const double cf[ncolor][ncolor] = {{64, -8, -8, 1, 1, 10}, {-8, 64, 1, // 10, -8, 1}, {-8, 1, 64, -8, 10, 1}, {1, 10, -8, 64, 1, -8}, {1, -8, 10, // 1, 64, -8}, {10, 1, 1, -8, -8, 64}}; // Calculate color flows jamp[0] = +amp[0] + amp[2] + amp[8] + amp[9] + amp[10] + amp[11] - std::complex (0, 1) * amp[12] - std::complex (0, 1) * amp[13] - std::complex (0, 1) * amp[14] - std::complex (0, 1) * amp[15] + amp[65] + amp[67] - std::complex (0, 1) * amp[68] - std::complex (0, 1) * amp[69] - std::complex (0, 1) * amp[70] - std::complex (0, 1) * amp[71] - amp[73] - std::complex (0, 1) * amp[74] - amp[75] - amp[77] - std::complex (0, 1) * amp[78] - amp[79] - std::complex (0, 1) * amp[88] - amp[89] - amp[91] - std::complex (0, 1) * amp[92] - amp[93] - amp[95] + amp[98] - amp[96] + amp[101] - amp[99] + amp[104] - amp[102] + amp[107] - amp[105]; jamp[1] = +amp[1] + amp[3] + amp[4] + amp[5] + amp[6] + amp[7] + std::complex (0, 1) * amp[12] + std::complex (0, 1) * amp[13] + std::complex (0, 1) * amp[14] + std::complex (0, 1) * amp[15] + amp[57] + amp[59] - std::complex (0, 1) * amp[60] - std::complex (0, 1) * amp[61] - std::complex (0, 1) * amp[62] - std::complex (0, 1) * amp[63] - amp[81] - std::complex (0, 1) * amp[82] - amp[83] - amp[85] - std::complex (0, 1) * amp[86] - amp[87] + std::complex (0, 1) * amp[88] + amp[89] + amp[91] + std::complex (0, 1) * amp[92] + amp[93] + amp[95] + amp[96] + amp[97] + amp[99] + amp[100] + amp[102] + amp[103] + amp[105] + amp[106]; jamp[2] = +amp[16] + amp[18] + amp[24] + amp[25] + amp[26] + amp[27] - std::complex (0, 1) * amp[28] - std::complex (0, 1) * amp[29] - std::complex (0, 1) * amp[30] - std::complex (0, 1) * amp[31] + amp[64] + amp[66] + std::complex (0, 1) * amp[68] + std::complex (0, 1) * amp[69] + std::complex (0, 1) * amp[70] + std::complex (0, 1) * amp[71] + amp[73] + std::complex (0, 1) * amp[74] + amp[75] + amp[77] + std::complex (0, 1) * amp[78] + amp[79] - std::complex (0, 1) * amp[80] + amp[81] + amp[83] - std::complex (0, 1) * amp[84] + amp[85] + amp[87] - amp[98] - amp[97] - amp[101] - amp[100] - amp[104] - amp[103] - amp[107] - amp[106]; jamp[3] = +amp[17] + amp[19] + amp[20] + amp[21] + amp[22] + amp[23] + std::complex (0, 1) * amp[28] + std::complex (0, 1) * amp[29] + std::complex (0, 1) * amp[30] + std::complex (0, 1) * amp[31] + amp[49] + amp[51] - std::complex (0, 1) * amp[52] - std::complex (0, 1) * amp[53] - std::complex (0, 1) * amp[54] - std::complex (0, 1) * amp[55] + std::complex (0, 1) * amp[80] - amp[81] - amp[83] + std::complex (0, 1) * amp[84] - amp[85] - amp[87] + amp[89] - std::complex (0, 1) * amp[90] + amp[91] + amp[93] - std::complex (0, 1) * amp[94] + amp[95] + amp[96] + amp[97] + amp[99] + amp[100] + amp[102] + amp[103] + amp[105] + amp[106]; jamp[4] = +amp[32] + amp[34] + amp[40] + amp[41] + amp[42] + amp[43] - std::complex (0, 1) * amp[44] - std::complex (0, 1) * amp[45] - std::complex (0, 1) * amp[46] - std::complex (0, 1) * amp[47] + amp[56] + amp[58] + std::complex (0, 1) * amp[60] + std::complex (0, 1) * amp[61] + std::complex (0, 1) * amp[62] + std::complex (0, 1) * amp[63] - std::complex (0, 1) * amp[72] + amp[73] + amp[75] - std::complex (0, 1) * amp[76] + amp[77] + amp[79] + amp[81] + std::complex (0, 1) * amp[82] + amp[83] + amp[85] + std::complex (0, 1) * amp[86] + amp[87] - amp[98] - amp[97] - amp[101] - amp[100] - amp[104] - amp[103] - amp[107] - amp[106]; jamp[5] = +amp[33] + amp[35] + amp[36] + amp[37] + amp[38] + amp[39] + std::complex (0, 1) * amp[44] + std::complex (0, 1) * amp[45] + std::complex (0, 1) * amp[46] + std::complex (0, 1) * amp[47] + amp[48] + amp[50] + std::complex (0, 1) * amp[52] + std::complex (0, 1) * amp[53] + std::complex (0, 1) * amp[54] + std::complex (0, 1) * amp[55] + std::complex (0, 1) * amp[72] - amp[73] - amp[75] + std::complex (0, 1) * amp[76] - amp[77] - amp[79] - amp[89] + std::complex (0, 1) * amp[90] - amp[91] - amp[93] + std::complex (0, 1) * amp[94] - amp[95] + amp[98] - amp[96] + amp[101] - amp[99] + amp[104] - amp[102] + amp[107] - amp[105]; // Store the leading color flows for choice of color for(i = 0; i < ncolor; i++ ) jamp2[0][i] += real(jamp[i] * conj(jamp[i])); return -1.; } double eeuuggg::get_jamp2(int i) { return jamp2[0][i]; } int eeuuggg::colorstring(int i, int j) { static const double res[6][6] = { {5, 6, 7, 3, 4, 0}, {5, 7, 6, 3, 4, 0}, {6, 5, 7, 3, 4, 0}, {6, 7, 5, 3, 4, 0}, {7, 5, 6, 3, 4, 0}, {7, 6, 5, 3, 4, 0}}; return res[i][j]; } int eeuuggg::NCol() { const int ncolor = 6; return ncolor; } diff --git a/Shower/Dipole/Colorea/eeuugggg.cc b/Shower/Dipole/Colorea/eeuugggg.cc --- a/Shower/Dipole/Colorea/eeuugggg.cc +++ b/Shower/Dipole/Colorea/eeuugggg.cc @@ -1,3120 +1,3119 @@ //========================================================================== // This file has been automatically generated for C++ Standalone by // MadGraph5_aMC@NLO v. 2.5.4, 2017-03-28 // By the MadGraph5_aMC@NLO Development Team // Visit launchpad.net/madgraph5 and amcatnlo.web.cern.ch //========================================================================== // and was then modified by J. Bellm. #include "eeuugggg.h" #include "HelAmps_sm.h" #include using namespace MG5_sm_COLOREA; //========================================================================== // Class member functions for calculating the matrix elements for // Process: e+ e- > u u~ g g g g WEIGHTED<=8 @1 //-------------------------------------------------------------------------- // Initialize process. vector eeuugggg::producePermutation(double r,vector < double * > & momenta){ static bool initialized=false; if (!initialized){ initProc("param_card.dat"); initialized=true; } setMomenta(momenta); sigmaKin(); static const int res[24][8] = { {5, 6, 7, 8, 3, 4, 0, 0}, {5, 6, 8, 7, 3, 4, 0, 0}, {5, 7, 6, 8, 3, 4, 0, 0}, {5, 7, 8, 6, 3, 4, 0, 0}, {5, 8, 6, 7, 3, 4, 0, 0}, {5, 8, 7, 6, 3, 4, 0, 0}, {6, 5, 7, 8, 3, 4, 0, 0}, {6, 5, 8, 7, 3, 4, 0, 0}, {6, 7, 5, 8, 3, 4, 0, 0}, {6, 7, 8, 5, 3, 4, 0, 0}, {6, 8, 5, 7, 3, 4, 0, 0}, {6, 8, 7, 5, 3, 4, 0, 0}, {7, 5, 6, 8, 3, 4, 0, 0}, {7, 5, 8, 6, 3, 4, 0, 0}, {7, 6, 5, 8, 3, 4, 0, 0}, {7, 6, 8, 5, 3, 4, 0, 0}, {7, 8, 5, 6, 3, 4, 0, 0}, {7, 8, 6, 5, 3, 4, 0, 0}, {8, 5, 6, 7, 3, 4, 0, 0}, {8, 5, 7, 6, 3, 4, 0, 0}, {8, 6, 5, 7, 3, 4, 0, 0}, {8, 6, 7, 5, 3, 4, 0, 0}, {8, 7, 5, 6, 3, 4, 0, 0}, {8, 7, 6, 5, 3, 4, 0, 0}}; double jampsum=0.; for( int i=0;i<24;i++) jampsum+=jamp2[0][i]; double cur=0.; for(int i=0;i<24;i++){ cur+=jamp2[0][i]; if( cur/jampsum > r )return std::vector(res[i], res[i] + sizeof res[i] / sizeof res[i][0]); } //std::cout<<"producePermutation: Upps.. Something went wrong!!"; return std::vector(); } void eeuugggg::initProc(string param_card_name) { cout<<"\nColorea: Init process eeuugggg for rearrangement (arXiv:1801.06113)."; // Instantiate the model class and set parameters that stay fixed during run pars = Parameters_sm::getInstance(); SLHAReader_COLOREA slha(param_card_name); pars->setIndependentParameters(slha); pars->setIndependentCouplings(); // pars->printIndependentParameters(); // pars->printIndependentCouplings(); // Set external particle masses for this matrix element mME.push_back(pars->ZERO); mME.push_back(pars->ZERO); mME.push_back(pars->ZERO); mME.push_back(pars->ZERO); mME.push_back(pars->ZERO); mME.push_back(pars->ZERO); mME.push_back(pars->ZERO); mME.push_back(pars->ZERO); jamp2[0] = new double[24]; } //-------------------------------------------------------------------------- // Evaluate |M|^2, part independent of incoming flavour. void eeuugggg::sigmaKin() { // Set the parameters which change event by event pars->setDependentParameters(); pars->setDependentCouplings(); static bool firsttime = true; if (firsttime) { // pars->printDependentParameters(); // pars->printDependentCouplings(); firsttime = false; } // Reset color flows for(int i = 0; i < 24; i++ ) jamp2[0][i] = 0.; // Local variables and constants const int ncomb = 256; static bool goodhel[ncomb] = {ncomb * false}; static int ntry = 0, sum_hel = 0, ngood = 0; static int igood[ncomb]; static int jhel; // std::complex * * wfs; double t[nprocesses]; // Helicities for the process static const int helicities[ncomb][nexternal] = {{-1, -1, -1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1, -1, -1, 1}, {-1, -1, -1, -1, -1, -1, 1, -1}, {-1, -1, -1, -1, -1, -1, 1, 1}, {-1, -1, -1, -1, -1, 1, -1, -1}, {-1, -1, -1, -1, -1, 1, -1, 1}, {-1, -1, -1, -1, -1, 1, 1, -1}, {-1, -1, -1, -1, -1, 1, 1, 1}, {-1, -1, -1, -1, 1, -1, -1, -1}, {-1, -1, -1, -1, 1, -1, -1, 1}, {-1, -1, -1, -1, 1, -1, 1, -1}, {-1, -1, -1, -1, 1, -1, 1, 1}, {-1, -1, -1, -1, 1, 1, -1, -1}, {-1, -1, -1, -1, 1, 1, -1, 1}, {-1, -1, -1, -1, 1, 1, 1, -1}, {-1, -1, -1, -1, 1, 1, 1, 1}, {-1, -1, -1, 1, -1, -1, -1, -1}, {-1, -1, -1, 1, -1, -1, -1, 1}, {-1, -1, -1, 1, -1, -1, 1, -1}, {-1, -1, -1, 1, -1, -1, 1, 1}, {-1, -1, -1, 1, -1, 1, -1, -1}, {-1, -1, -1, 1, -1, 1, -1, 1}, {-1, -1, -1, 1, -1, 1, 1, -1}, {-1, -1, -1, 1, -1, 1, 1, 1}, {-1, -1, -1, 1, 1, -1, -1, -1}, {-1, -1, -1, 1, 1, -1, -1, 1}, {-1, -1, -1, 1, 1, -1, 1, -1}, {-1, -1, -1, 1, 1, -1, 1, 1}, {-1, -1, -1, 1, 1, 1, -1, -1}, {-1, -1, -1, 1, 1, 1, -1, 1}, {-1, -1, -1, 1, 1, 1, 1, -1}, {-1, -1, -1, 1, 1, 1, 1, 1}, {-1, -1, 1, -1, -1, -1, -1, -1}, {-1, -1, 1, -1, -1, -1, -1, 1}, {-1, -1, 1, -1, -1, -1, 1, -1}, {-1, -1, 1, -1, -1, -1, 1, 1}, {-1, -1, 1, -1, -1, 1, -1, -1}, {-1, -1, 1, -1, -1, 1, -1, 1}, {-1, -1, 1, -1, -1, 1, 1, -1}, {-1, -1, 1, -1, -1, 1, 1, 1}, {-1, -1, 1, -1, 1, -1, -1, -1}, {-1, -1, 1, -1, 1, -1, -1, 1}, {-1, -1, 1, -1, 1, -1, 1, -1}, {-1, -1, 1, -1, 1, -1, 1, 1}, {-1, -1, 1, -1, 1, 1, -1, -1}, {-1, -1, 1, -1, 1, 1, -1, 1}, {-1, -1, 1, -1, 1, 1, 1, -1}, {-1, -1, 1, -1, 1, 1, 1, 1}, {-1, -1, 1, 1, -1, -1, -1, -1}, {-1, -1, 1, 1, -1, -1, -1, 1}, {-1, -1, 1, 1, -1, -1, 1, -1}, {-1, -1, 1, 1, -1, -1, 1, 1}, {-1, -1, 1, 1, -1, 1, -1, -1}, {-1, -1, 1, 1, -1, 1, -1, 1}, {-1, -1, 1, 1, -1, 1, 1, -1}, {-1, -1, 1, 1, -1, 1, 1, 1}, {-1, -1, 1, 1, 1, -1, -1, -1}, {-1, -1, 1, 1, 1, -1, -1, 1}, {-1, -1, 1, 1, 1, -1, 1, -1}, {-1, -1, 1, 1, 1, -1, 1, 1}, {-1, -1, 1, 1, 1, 1, -1, -1}, {-1, -1, 1, 1, 1, 1, -1, 1}, {-1, -1, 1, 1, 1, 1, 1, -1}, {-1, -1, 1, 1, 1, 1, 1, 1}, {-1, 1, -1, -1, -1, -1, -1, -1}, {-1, 1, -1, -1, -1, -1, -1, 1}, {-1, 1, -1, -1, -1, -1, 1, -1}, {-1, 1, -1, -1, -1, -1, 1, 1}, {-1, 1, -1, -1, -1, 1, -1, -1}, {-1, 1, -1, -1, -1, 1, -1, 1}, {-1, 1, -1, -1, -1, 1, 1, -1}, {-1, 1, -1, -1, -1, 1, 1, 1}, {-1, 1, -1, -1, 1, -1, -1, -1}, {-1, 1, -1, -1, 1, -1, -1, 1}, {-1, 1, -1, -1, 1, -1, 1, -1}, {-1, 1, -1, -1, 1, -1, 1, 1}, {-1, 1, -1, -1, 1, 1, -1, -1}, {-1, 1, -1, -1, 1, 1, -1, 1}, {-1, 1, -1, -1, 1, 1, 1, -1}, {-1, 1, -1, -1, 1, 1, 1, 1}, {-1, 1, -1, 1, -1, -1, -1, -1}, {-1, 1, -1, 1, -1, -1, -1, 1}, {-1, 1, -1, 1, -1, -1, 1, -1}, {-1, 1, -1, 1, -1, -1, 1, 1}, {-1, 1, -1, 1, -1, 1, -1, -1}, {-1, 1, -1, 1, -1, 1, -1, 1}, {-1, 1, -1, 1, -1, 1, 1, -1}, {-1, 1, -1, 1, -1, 1, 1, 1}, {-1, 1, -1, 1, 1, -1, -1, -1}, {-1, 1, -1, 1, 1, -1, -1, 1}, {-1, 1, -1, 1, 1, -1, 1, -1}, {-1, 1, -1, 1, 1, -1, 1, 1}, {-1, 1, -1, 1, 1, 1, -1, -1}, {-1, 1, -1, 1, 1, 1, -1, 1}, {-1, 1, -1, 1, 1, 1, 1, -1}, {-1, 1, -1, 1, 1, 1, 1, 1}, {-1, 1, 1, -1, -1, -1, -1, -1}, {-1, 1, 1, -1, -1, -1, -1, 1}, {-1, 1, 1, -1, -1, -1, 1, -1}, {-1, 1, 1, -1, -1, -1, 1, 1}, {-1, 1, 1, -1, -1, 1, -1, -1}, {-1, 1, 1, -1, -1, 1, -1, 1}, {-1, 1, 1, -1, -1, 1, 1, -1}, {-1, 1, 1, -1, -1, 1, 1, 1}, {-1, 1, 1, -1, 1, -1, -1, -1}, {-1, 1, 1, -1, 1, -1, -1, 1}, {-1, 1, 1, -1, 1, -1, 1, -1}, {-1, 1, 1, -1, 1, -1, 1, 1}, {-1, 1, 1, -1, 1, 1, -1, -1}, {-1, 1, 1, -1, 1, 1, -1, 1}, {-1, 1, 1, -1, 1, 1, 1, -1}, {-1, 1, 1, -1, 1, 1, 1, 1}, {-1, 1, 1, 1, -1, -1, -1, -1}, {-1, 1, 1, 1, -1, -1, -1, 1}, {-1, 1, 1, 1, -1, -1, 1, -1}, {-1, 1, 1, 1, -1, -1, 1, 1}, {-1, 1, 1, 1, -1, 1, -1, -1}, {-1, 1, 1, 1, -1, 1, -1, 1}, {-1, 1, 1, 1, -1, 1, 1, -1}, {-1, 1, 1, 1, -1, 1, 1, 1}, {-1, 1, 1, 1, 1, -1, -1, -1}, {-1, 1, 1, 1, 1, -1, -1, 1}, {-1, 1, 1, 1, 1, -1, 1, -1}, {-1, 1, 1, 1, 1, -1, 1, 1}, {-1, 1, 1, 1, 1, 1, -1, -1}, {-1, 1, 1, 1, 1, 1, -1, 1}, {-1, 1, 1, 1, 1, 1, 1, -1}, {-1, 1, 1, 1, 1, 1, 1, 1}, {1, -1, -1, -1, -1, -1, -1, -1}, {1, -1, -1, -1, -1, -1, -1, 1}, {1, -1, -1, -1, -1, -1, 1, -1}, {1, -1, -1, -1, -1, -1, 1, 1}, {1, -1, -1, -1, -1, 1, -1, -1}, {1, -1, -1, -1, -1, 1, -1, 1}, {1, -1, -1, -1, -1, 1, 1, -1}, {1, -1, -1, -1, -1, 1, 1, 1}, {1, -1, -1, -1, 1, -1, -1, -1}, {1, -1, -1, -1, 1, -1, -1, 1}, {1, -1, -1, -1, 1, -1, 1, -1}, {1, -1, -1, -1, 1, -1, 1, 1}, {1, -1, -1, -1, 1, 1, -1, -1}, {1, -1, -1, -1, 1, 1, -1, 1}, {1, -1, -1, -1, 1, 1, 1, -1}, {1, -1, -1, -1, 1, 1, 1, 1}, {1, -1, -1, 1, -1, -1, -1, -1}, {1, -1, -1, 1, -1, -1, -1, 1}, {1, -1, -1, 1, -1, -1, 1, -1}, {1, -1, -1, 1, -1, -1, 1, 1}, {1, -1, -1, 1, -1, 1, -1, -1}, {1, -1, -1, 1, -1, 1, -1, 1}, {1, -1, -1, 1, -1, 1, 1, -1}, {1, -1, -1, 1, -1, 1, 1, 1}, {1, -1, -1, 1, 1, -1, -1, -1}, {1, -1, -1, 1, 1, -1, -1, 1}, {1, -1, -1, 1, 1, -1, 1, -1}, {1, -1, -1, 1, 1, -1, 1, 1}, {1, -1, -1, 1, 1, 1, -1, -1}, {1, -1, -1, 1, 1, 1, -1, 1}, {1, -1, -1, 1, 1, 1, 1, -1}, {1, -1, -1, 1, 1, 1, 1, 1}, {1, -1, 1, -1, -1, -1, -1, -1}, {1, -1, 1, -1, -1, -1, -1, 1}, {1, -1, 1, -1, -1, -1, 1, -1}, {1, -1, 1, -1, -1, -1, 1, 1}, {1, -1, 1, -1, -1, 1, -1, -1}, {1, -1, 1, -1, -1, 1, -1, 1}, {1, -1, 1, -1, -1, 1, 1, -1}, {1, -1, 1, -1, -1, 1, 1, 1}, {1, -1, 1, -1, 1, -1, -1, -1}, {1, -1, 1, -1, 1, -1, -1, 1}, {1, -1, 1, -1, 1, -1, 1, -1}, {1, -1, 1, -1, 1, -1, 1, 1}, {1, -1, 1, -1, 1, 1, -1, -1}, {1, -1, 1, -1, 1, 1, -1, 1}, {1, -1, 1, -1, 1, 1, 1, -1}, {1, -1, 1, -1, 1, 1, 1, 1}, {1, -1, 1, 1, -1, -1, -1, -1}, {1, -1, 1, 1, -1, -1, -1, 1}, {1, -1, 1, 1, -1, -1, 1, -1}, {1, -1, 1, 1, -1, -1, 1, 1}, {1, -1, 1, 1, -1, 1, -1, -1}, {1, -1, 1, 1, -1, 1, -1, 1}, {1, -1, 1, 1, -1, 1, 1, -1}, {1, -1, 1, 1, -1, 1, 1, 1}, {1, -1, 1, 1, 1, -1, -1, -1}, {1, -1, 1, 1, 1, -1, -1, 1}, {1, -1, 1, 1, 1, -1, 1, -1}, {1, -1, 1, 1, 1, -1, 1, 1}, {1, -1, 1, 1, 1, 1, -1, -1}, {1, -1, 1, 1, 1, 1, -1, 1}, {1, -1, 1, 1, 1, 1, 1, -1}, {1, -1, 1, 1, 1, 1, 1, 1}, {1, 1, -1, -1, -1, -1, -1, -1}, {1, 1, -1, -1, -1, -1, -1, 1}, {1, 1, -1, -1, -1, -1, 1, -1}, {1, 1, -1, -1, -1, -1, 1, 1}, {1, 1, -1, -1, -1, 1, -1, -1}, {1, 1, -1, -1, -1, 1, -1, 1}, {1, 1, -1, -1, -1, 1, 1, -1}, {1, 1, -1, -1, -1, 1, 1, 1}, {1, 1, -1, -1, 1, -1, -1, -1}, {1, 1, -1, -1, 1, -1, -1, 1}, {1, 1, -1, -1, 1, -1, 1, -1}, {1, 1, -1, -1, 1, -1, 1, 1}, {1, 1, -1, -1, 1, 1, -1, -1}, {1, 1, -1, -1, 1, 1, -1, 1}, {1, 1, -1, -1, 1, 1, 1, -1}, {1, 1, -1, -1, 1, 1, 1, 1}, {1, 1, -1, 1, -1, -1, -1, -1}, {1, 1, -1, 1, -1, -1, -1, 1}, {1, 1, -1, 1, -1, -1, 1, -1}, {1, 1, -1, 1, -1, -1, 1, 1}, {1, 1, -1, 1, -1, 1, -1, -1}, {1, 1, -1, 1, -1, 1, -1, 1}, {1, 1, -1, 1, -1, 1, 1, -1}, {1, 1, -1, 1, -1, 1, 1, 1}, {1, 1, -1, 1, 1, -1, -1, -1}, {1, 1, -1, 1, 1, -1, -1, 1}, {1, 1, -1, 1, 1, -1, 1, -1}, {1, 1, -1, 1, 1, -1, 1, 1}, {1, 1, -1, 1, 1, 1, -1, -1}, {1, 1, -1, 1, 1, 1, -1, 1}, {1, 1, -1, 1, 1, 1, 1, -1}, {1, 1, -1, 1, 1, 1, 1, 1}, {1, 1, 1, -1, -1, -1, -1, -1}, {1, 1, 1, -1, -1, -1, -1, 1}, {1, 1, 1, -1, -1, -1, 1, -1}, {1, 1, 1, -1, -1, -1, 1, 1}, {1, 1, 1, -1, -1, 1, -1, -1}, {1, 1, 1, -1, -1, 1, -1, 1}, {1, 1, 1, -1, -1, 1, 1, -1}, {1, 1, 1, -1, -1, 1, 1, 1}, {1, 1, 1, -1, 1, -1, -1, -1}, {1, 1, 1, -1, 1, -1, -1, 1}, {1, 1, 1, -1, 1, -1, 1, -1}, {1, 1, 1, -1, 1, -1, 1, 1}, {1, 1, 1, -1, 1, 1, -1, -1}, {1, 1, 1, -1, 1, 1, -1, 1}, {1, 1, 1, -1, 1, 1, 1, -1}, {1, 1, 1, -1, 1, 1, 1, 1}, {1, 1, 1, 1, -1, -1, -1, -1}, {1, 1, 1, 1, -1, -1, -1, 1}, {1, 1, 1, 1, -1, -1, 1, -1}, {1, 1, 1, 1, -1, -1, 1, 1}, {1, 1, 1, 1, -1, 1, -1, -1}, {1, 1, 1, 1, -1, 1, -1, 1}, {1, 1, 1, 1, -1, 1, 1, -1}, {1, 1, 1, 1, -1, 1, 1, 1}, {1, 1, 1, 1, 1, -1, -1, -1}, {1, 1, 1, 1, 1, -1, -1, 1}, {1, 1, 1, 1, 1, -1, 1, -1}, {1, 1, 1, 1, 1, -1, 1, 1}, {1, 1, 1, 1, 1, 1, -1, -1}, {1, 1, 1, 1, 1, 1, -1, 1}, {1, 1, 1, 1, 1, 1, 1, -1}, {1, 1, 1, 1, 1, 1, 1, 1}}; // Denominators: spins, colors and identical particles const int denominators[nprocesses] = {96}; ntry = ntry + 1; // Reset the matrix elements for(int i = 0; i < nprocesses; i++ ) { matrix_element[i] = 0.; } // Define permutation int perm[nexternal]; for(int i = 0; i < nexternal; i++ ) { perm[i] = i; } if (sum_hel == 0 || ntry < 10) { // Calculate the matrix element for all helicities for(int ihel = 0; ihel < ncomb; ihel++ ) { if (goodhel[ihel] || ntry < 2) { calculate_wavefunctions(perm, helicities[ihel]); t[0] = matrix_1_epem_uuxgggg(); double tsum = 0; for(int iproc = 0; iproc < nprocesses; iproc++ ) { matrix_element[iproc] += t[iproc]; tsum += t[iproc]; } // Store which helicities give non-zero result if (tsum != 0. && !goodhel[ihel]) { goodhel[ihel] = true; ngood++; igood[ngood] = ihel; } } } jhel = 0; sum_hel = min(sum_hel, ngood); } else { // Only use the "good" helicities for(int j = 0; j < sum_hel; j++ ) { jhel++; if (jhel >= ngood) jhel = 0; double hwgt = double(ngood)/double(sum_hel); int ihel = igood[jhel]; calculate_wavefunctions(perm, helicities[ihel]); t[0] = matrix_1_epem_uuxgggg(); for(int iproc = 0; iproc < nprocesses; iproc++ ) { matrix_element[iproc] += t[iproc] * hwgt; } } } for (int i = 0; i < nprocesses; i++ ) matrix_element[i] /= denominators[i]; } //-------------------------------------------------------------------------- // Evaluate |M|^2 for each subprocess void eeuugggg::calculate_wavefunctions(const int perm[], const int hel[]) { // Calculate all wavefunctions oxxxxx(p[perm[0]], mME[0], hel[0], -1, w[0]); ixxxxx(p[perm[1]], mME[1], hel[1], +1, w[1]); oxxxxx(p[perm[2]], mME[2], hel[2], +1, w[2]); ixxxxx(p[perm[3]], mME[3], hel[3], -1, w[3]); vxxxxx(p[perm[4]], mME[4], hel[4], +1, w[4]); vxxxxx(p[perm[5]], mME[5], hel[5], +1, w[5]); vxxxxx(p[perm[6]], mME[6], hel[6], +1, w[6]); vxxxxx(p[perm[7]], mME[7], hel[7], +1, w[7]); FFV1P0_3(w[1], w[0], pars->GC_3, pars->ZERO, pars->ZERO, w[8]); FFV1_1(w[2], w[4], pars->GC_11, pars->ZERO, pars->ZERO, w[9]); FFV1_2(w[3], w[8], pars->GC_2, pars->ZERO, pars->ZERO, w[10]); FFV1_1(w[9], w[5], pars->GC_11, pars->ZERO, pars->ZERO, w[11]); FFV1_2(w[10], w[6], pars->GC_11, pars->ZERO, pars->ZERO, w[12]); FFV1_2(w[10], w[7], pars->GC_11, pars->ZERO, pars->ZERO, w[13]); FFV1_1(w[9], w[6], pars->GC_11, pars->ZERO, pars->ZERO, w[14]); FFV1_2(w[10], w[5], pars->GC_11, pars->ZERO, pars->ZERO, w[15]); FFV1_1(w[9], w[7], pars->GC_11, pars->ZERO, pars->ZERO, w[16]); FFV2_4_3(w[1], w[0], pars->GC_50, pars->GC_59, pars->mdl_MZ, pars->mdl_WZ, w[17]); FFV2_5_2(w[3], w[17], pars->GC_51, pars->GC_58, pars->ZERO, pars->ZERO, w[18]); FFV1_2(w[18], w[6], pars->GC_11, pars->ZERO, pars->ZERO, w[19]); FFV1_2(w[18], w[7], pars->GC_11, pars->ZERO, pars->ZERO, w[20]); FFV1_2(w[18], w[5], pars->GC_11, pars->ZERO, pars->ZERO, w[21]); FFV1_2(w[3], w[5], pars->GC_11, pars->ZERO, pars->ZERO, w[22]); FFV1_1(w[9], w[8], pars->GC_2, pars->ZERO, pars->ZERO, w[23]); FFV1_2(w[22], w[6], pars->GC_11, pars->ZERO, pars->ZERO, w[24]); FFV1_2(w[22], w[7], pars->GC_11, pars->ZERO, pars->ZERO, w[25]); FFV1_2(w[22], w[8], pars->GC_2, pars->ZERO, pars->ZERO, w[26]); FFV2_5_1(w[9], w[17], pars->GC_51, pars->GC_58, pars->ZERO, pars->ZERO, w[27]); FFV2_5_2(w[22], w[17], pars->GC_51, pars->GC_58, pars->ZERO, pars->ZERO, w[28]); VVV1P0_1(w[6], w[7], pars->GC_10, pars->ZERO, pars->ZERO, w[29]); FFV1_2(w[3], w[6], pars->GC_11, pars->ZERO, pars->ZERO, w[30]); FFV1_2(w[30], w[5], pars->GC_11, pars->ZERO, pars->ZERO, w[31]); FFV1_2(w[30], w[7], pars->GC_11, pars->ZERO, pars->ZERO, w[32]); FFV1_2(w[30], w[8], pars->GC_2, pars->ZERO, pars->ZERO, w[33]); FFV2_5_2(w[30], w[17], pars->GC_51, pars->GC_58, pars->ZERO, pars->ZERO, w[34]); VVV1P0_1(w[5], w[7], pars->GC_10, pars->ZERO, pars->ZERO, w[35]); FFV1_2(w[3], w[7], pars->GC_11, pars->ZERO, pars->ZERO, w[36]); FFV1_2(w[36], w[5], pars->GC_11, pars->ZERO, pars->ZERO, w[37]); FFV1_2(w[36], w[6], pars->GC_11, pars->ZERO, pars->ZERO, w[38]); FFV1_2(w[36], w[8], pars->GC_2, pars->ZERO, pars->ZERO, w[39]); FFV2_5_2(w[36], w[17], pars->GC_51, pars->GC_58, pars->ZERO, pars->ZERO, w[40]); VVV1P0_1(w[5], w[6], pars->GC_10, pars->ZERO, pars->ZERO, w[41]); FFV1_2(w[3], w[41], pars->GC_11, pars->ZERO, pars->ZERO, w[42]); VVV1P0_1(w[41], w[7], pars->GC_10, pars->ZERO, pars->ZERO, w[43]); FFV1_1(w[9], w[41], pars->GC_11, pars->ZERO, pars->ZERO, w[44]); FFV1_2(w[3], w[35], pars->GC_11, pars->ZERO, pars->ZERO, w[45]); VVV1P0_1(w[35], w[6], pars->GC_10, pars->ZERO, pars->ZERO, w[46]); FFV1_1(w[9], w[35], pars->GC_11, pars->ZERO, pars->ZERO, w[47]); FFV1_2(w[3], w[29], pars->GC_11, pars->ZERO, pars->ZERO, w[48]); VVV1P0_1(w[5], w[29], pars->GC_10, pars->ZERO, pars->ZERO, w[49]); FFV1_1(w[9], w[29], pars->GC_11, pars->ZERO, pars->ZERO, w[50]); VVVV1P0_1(w[5], w[6], w[7], pars->GC_12, pars->ZERO, pars->ZERO, w[51]); VVVV3P0_1(w[5], w[6], w[7], pars->GC_12, pars->ZERO, pars->ZERO, w[52]); VVVV4P0_1(w[5], w[6], w[7], pars->GC_12, pars->ZERO, pars->ZERO, w[53]); FFV1_1(w[2], w[5], pars->GC_11, pars->ZERO, pars->ZERO, w[54]); FFV1_1(w[54], w[4], pars->GC_11, pars->ZERO, pars->ZERO, w[55]); FFV1_1(w[54], w[6], pars->GC_11, pars->ZERO, pars->ZERO, w[56]); FFV1_2(w[10], w[4], pars->GC_11, pars->ZERO, pars->ZERO, w[57]); FFV1_1(w[54], w[7], pars->GC_11, pars->ZERO, pars->ZERO, w[58]); FFV1_2(w[18], w[4], pars->GC_11, pars->ZERO, pars->ZERO, w[59]); FFV1_2(w[3], w[4], pars->GC_11, pars->ZERO, pars->ZERO, w[60]); FFV1_1(w[54], w[8], pars->GC_2, pars->ZERO, pars->ZERO, w[61]); FFV1_2(w[60], w[6], pars->GC_11, pars->ZERO, pars->ZERO, w[62]); FFV1_2(w[60], w[7], pars->GC_11, pars->ZERO, pars->ZERO, w[63]); FFV1_2(w[60], w[8], pars->GC_2, pars->ZERO, pars->ZERO, w[64]); FFV2_5_1(w[54], w[17], pars->GC_51, pars->GC_58, pars->ZERO, pars->ZERO, w[65]); FFV2_5_2(w[60], w[17], pars->GC_51, pars->GC_58, pars->ZERO, pars->ZERO, w[66]); FFV1_2(w[30], w[4], pars->GC_11, pars->ZERO, pars->ZERO, w[67]); VVV1P0_1(w[4], w[7], pars->GC_10, pars->ZERO, pars->ZERO, w[68]); FFV1_2(w[36], w[4], pars->GC_11, pars->ZERO, pars->ZERO, w[69]); VVV1P0_1(w[4], w[6], pars->GC_10, pars->ZERO, pars->ZERO, w[70]); FFV1_2(w[3], w[70], pars->GC_11, pars->ZERO, pars->ZERO, w[71]); VVV1P0_1(w[70], w[7], pars->GC_10, pars->ZERO, pars->ZERO, w[72]); FFV1_1(w[54], w[70], pars->GC_11, pars->ZERO, pars->ZERO, w[73]); FFV1_2(w[3], w[68], pars->GC_11, pars->ZERO, pars->ZERO, w[74]); VVV1P0_1(w[68], w[6], pars->GC_10, pars->ZERO, pars->ZERO, w[75]); FFV1_1(w[54], w[68], pars->GC_11, pars->ZERO, pars->ZERO, w[76]); VVV1P0_1(w[4], w[29], pars->GC_10, pars->ZERO, pars->ZERO, w[77]); FFV1_1(w[54], w[29], pars->GC_11, pars->ZERO, pars->ZERO, w[78]); VVVV1P0_1(w[4], w[6], w[7], pars->GC_12, pars->ZERO, pars->ZERO, w[79]); VVVV3P0_1(w[4], w[6], w[7], pars->GC_12, pars->ZERO, pars->ZERO, w[80]); VVVV4P0_1(w[4], w[6], w[7], pars->GC_12, pars->ZERO, pars->ZERO, w[81]); FFV1_1(w[2], w[6], pars->GC_11, pars->ZERO, pars->ZERO, w[82]); FFV1_1(w[82], w[4], pars->GC_11, pars->ZERO, pars->ZERO, w[83]); FFV1_1(w[82], w[5], pars->GC_11, pars->ZERO, pars->ZERO, w[84]); FFV1_1(w[82], w[7], pars->GC_11, pars->ZERO, pars->ZERO, w[85]); FFV1_1(w[82], w[8], pars->GC_2, pars->ZERO, pars->ZERO, w[86]); FFV1_2(w[60], w[5], pars->GC_11, pars->ZERO, pars->ZERO, w[87]); FFV2_5_1(w[82], w[17], pars->GC_51, pars->GC_58, pars->ZERO, pars->ZERO, w[88]); FFV1_2(w[22], w[4], pars->GC_11, pars->ZERO, pars->ZERO, w[89]); VVV1P0_1(w[4], w[5], pars->GC_10, pars->ZERO, pars->ZERO, w[90]); FFV1_2(w[3], w[90], pars->GC_11, pars->ZERO, pars->ZERO, w[91]); VVV1P0_1(w[90], w[7], pars->GC_10, pars->ZERO, pars->ZERO, w[92]); FFV1_1(w[82], w[90], pars->GC_11, pars->ZERO, pars->ZERO, w[93]); VVV1P0_1(w[68], w[5], pars->GC_10, pars->ZERO, pars->ZERO, w[94]); FFV1_1(w[82], w[68], pars->GC_11, pars->ZERO, pars->ZERO, w[95]); VVV1P0_1(w[4], w[35], pars->GC_10, pars->ZERO, pars->ZERO, w[96]); FFV1_1(w[82], w[35], pars->GC_11, pars->ZERO, pars->ZERO, w[97]); VVVV1P0_1(w[4], w[5], w[7], pars->GC_12, pars->ZERO, pars->ZERO, w[98]); VVVV3P0_1(w[4], w[5], w[7], pars->GC_12, pars->ZERO, pars->ZERO, w[99]); VVVV4P0_1(w[4], w[5], w[7], pars->GC_12, pars->ZERO, pars->ZERO, w[100]); FFV1_1(w[2], w[7], pars->GC_11, pars->ZERO, pars->ZERO, w[101]); FFV1_1(w[101], w[4], pars->GC_11, pars->ZERO, pars->ZERO, w[102]); FFV1_1(w[101], w[5], pars->GC_11, pars->ZERO, pars->ZERO, w[103]); FFV1_1(w[101], w[6], pars->GC_11, pars->ZERO, pars->ZERO, w[104]); FFV1_1(w[101], w[8], pars->GC_2, pars->ZERO, pars->ZERO, w[105]); FFV2_5_1(w[101], w[17], pars->GC_51, pars->GC_58, pars->ZERO, pars->ZERO, w[106]); VVV1P0_1(w[90], w[6], pars->GC_10, pars->ZERO, pars->ZERO, w[107]); FFV1_1(w[101], w[90], pars->GC_11, pars->ZERO, pars->ZERO, w[108]); VVV1P0_1(w[70], w[5], pars->GC_10, pars->ZERO, pars->ZERO, w[109]); FFV1_1(w[101], w[70], pars->GC_11, pars->ZERO, pars->ZERO, w[110]); VVV1P0_1(w[4], w[41], pars->GC_10, pars->ZERO, pars->ZERO, w[111]); FFV1_1(w[101], w[41], pars->GC_11, pars->ZERO, pars->ZERO, w[112]); VVVV1P0_1(w[4], w[5], w[6], pars->GC_12, pars->ZERO, pars->ZERO, w[113]); VVVV3P0_1(w[4], w[5], w[6], pars->GC_12, pars->ZERO, pars->ZERO, w[114]); VVVV4P0_1(w[4], w[5], w[6], pars->GC_12, pars->ZERO, pars->ZERO, w[115]); FFV1_1(w[2], w[8], pars->GC_2, pars->ZERO, pars->ZERO, w[116]); FFV1_1(w[116], w[6], pars->GC_11, pars->ZERO, pars->ZERO, w[117]); FFV1_1(w[116], w[7], pars->GC_11, pars->ZERO, pars->ZERO, w[118]); FFV1_1(w[116], w[5], pars->GC_11, pars->ZERO, pars->ZERO, w[119]); FFV2_5_1(w[2], w[17], pars->GC_51, pars->GC_58, pars->ZERO, pars->ZERO, w[120]); FFV1_1(w[120], w[6], pars->GC_11, pars->ZERO, pars->ZERO, w[121]); FFV1_1(w[120], w[7], pars->GC_11, pars->ZERO, pars->ZERO, w[122]); FFV1_1(w[120], w[5], pars->GC_11, pars->ZERO, pars->ZERO, w[123]); FFV1_2(w[60], w[41], pars->GC_11, pars->ZERO, pars->ZERO, w[124]); FFV1_1(w[2], w[41], pars->GC_11, pars->ZERO, pars->ZERO, w[125]); FFV1_2(w[60], w[35], pars->GC_11, pars->ZERO, pars->ZERO, w[126]); FFV1_1(w[2], w[35], pars->GC_11, pars->ZERO, pars->ZERO, w[127]); FFV1_2(w[60], w[29], pars->GC_11, pars->ZERO, pars->ZERO, w[128]); FFV1_1(w[2], w[29], pars->GC_11, pars->ZERO, pars->ZERO, w[129]); FFV1_1(w[116], w[4], pars->GC_11, pars->ZERO, pars->ZERO, w[130]); FFV1_1(w[120], w[4], pars->GC_11, pars->ZERO, pars->ZERO, w[131]); FFV1_2(w[22], w[70], pars->GC_11, pars->ZERO, pars->ZERO, w[132]); FFV1_1(w[2], w[70], pars->GC_11, pars->ZERO, pars->ZERO, w[133]); FFV1_2(w[22], w[68], pars->GC_11, pars->ZERO, pars->ZERO, w[134]); FFV1_1(w[2], w[68], pars->GC_11, pars->ZERO, pars->ZERO, w[135]); FFV1_2(w[22], w[29], pars->GC_11, pars->ZERO, pars->ZERO, w[136]); FFV1_2(w[30], w[90], pars->GC_11, pars->ZERO, pars->ZERO, w[137]); FFV1_1(w[2], w[90], pars->GC_11, pars->ZERO, pars->ZERO, w[138]); FFV1_2(w[30], w[68], pars->GC_11, pars->ZERO, pars->ZERO, w[139]); FFV1_2(w[30], w[35], pars->GC_11, pars->ZERO, pars->ZERO, w[140]); FFV1_2(w[36], w[90], pars->GC_11, pars->ZERO, pars->ZERO, w[141]); FFV1_2(w[36], w[70], pars->GC_11, pars->ZERO, pars->ZERO, w[142]); FFV1_2(w[36], w[41], pars->GC_11, pars->ZERO, pars->ZERO, w[143]); FFV1P0_3(w[3], w[116], pars->GC_11, pars->ZERO, pars->ZERO, w[144]); VVVV1P0_1(w[90], w[6], w[7], pars->GC_12, pars->ZERO, pars->ZERO, w[145]); VVVV3P0_1(w[90], w[6], w[7], pars->GC_12, pars->ZERO, pars->ZERO, w[146]); VVVV4P0_1(w[90], w[6], w[7], pars->GC_12, pars->ZERO, pars->ZERO, w[147]); FFV1P0_3(w[10], w[2], pars->GC_11, pars->ZERO, pars->ZERO, w[148]); FFV1P0_3(w[3], w[120], pars->GC_11, pars->ZERO, pars->ZERO, w[149]); FFV1P0_3(w[18], w[2], pars->GC_11, pars->ZERO, pars->ZERO, w[150]); VVV1P0_1(w[90], w[29], pars->GC_10, pars->ZERO, pars->ZERO, w[151]); VVVV1P0_1(w[70], w[5], w[7], pars->GC_12, pars->ZERO, pars->ZERO, w[152]); VVVV3P0_1(w[70], w[5], w[7], pars->GC_12, pars->ZERO, pars->ZERO, w[153]); VVVV4P0_1(w[70], w[5], w[7], pars->GC_12, pars->ZERO, pars->ZERO, w[154]); VVV1P0_1(w[70], w[35], pars->GC_10, pars->ZERO, pars->ZERO, w[155]); VVVV1P0_1(w[68], w[5], w[6], pars->GC_12, pars->ZERO, pars->ZERO, w[156]); VVVV3P0_1(w[68], w[5], w[6], pars->GC_12, pars->ZERO, pars->ZERO, w[157]); VVVV4P0_1(w[68], w[5], w[6], pars->GC_12, pars->ZERO, pars->ZERO, w[158]); VVV1P0_1(w[68], w[41], pars->GC_10, pars->ZERO, pars->ZERO, w[159]); VVVV1P0_1(w[4], w[41], w[7], pars->GC_12, pars->ZERO, pars->ZERO, w[160]); VVVV3P0_1(w[4], w[41], w[7], pars->GC_12, pars->ZERO, pars->ZERO, w[161]); VVVV4P0_1(w[4], w[41], w[7], pars->GC_12, pars->ZERO, pars->ZERO, w[162]); VVVV1P0_1(w[4], w[35], w[6], pars->GC_12, pars->ZERO, pars->ZERO, w[163]); VVVV3P0_1(w[4], w[35], w[6], pars->GC_12, pars->ZERO, pars->ZERO, w[164]); VVVV4P0_1(w[4], w[35], w[6], pars->GC_12, pars->ZERO, pars->ZERO, w[165]); VVVV1P0_1(w[4], w[5], w[29], pars->GC_12, pars->ZERO, pars->ZERO, w[166]); VVVV3P0_1(w[4], w[5], w[29], pars->GC_12, pars->ZERO, pars->ZERO, w[167]); VVVV4P0_1(w[4], w[5], w[29], pars->GC_12, pars->ZERO, pars->ZERO, w[168]); FFV1_2(w[3], w[113], pars->GC_11, pars->ZERO, pars->ZERO, w[169]); FFV1_2(w[3], w[114], pars->GC_11, pars->ZERO, pars->ZERO, w[170]); FFV1_2(w[3], w[115], pars->GC_11, pars->ZERO, pars->ZERO, w[171]); VVV1P0_1(w[113], w[7], pars->GC_10, pars->ZERO, pars->ZERO, w[172]); VVV1P0_1(w[114], w[7], pars->GC_10, pars->ZERO, pars->ZERO, w[173]); VVV1P0_1(w[115], w[7], pars->GC_10, pars->ZERO, pars->ZERO, w[174]); FFV1_1(w[2], w[113], pars->GC_11, pars->ZERO, pars->ZERO, w[175]); FFV1_1(w[2], w[114], pars->GC_11, pars->ZERO, pars->ZERO, w[176]); FFV1_1(w[2], w[115], pars->GC_11, pars->ZERO, pars->ZERO, w[177]); FFV1_2(w[3], w[98], pars->GC_11, pars->ZERO, pars->ZERO, w[178]); FFV1_2(w[3], w[99], pars->GC_11, pars->ZERO, pars->ZERO, w[179]); FFV1_2(w[3], w[100], pars->GC_11, pars->ZERO, pars->ZERO, w[180]); VVV1P0_1(w[98], w[6], pars->GC_10, pars->ZERO, pars->ZERO, w[181]); VVV1P0_1(w[99], w[6], pars->GC_10, pars->ZERO, pars->ZERO, w[182]); VVV1P0_1(w[100], w[6], pars->GC_10, pars->ZERO, pars->ZERO, w[183]); FFV1_1(w[2], w[98], pars->GC_11, pars->ZERO, pars->ZERO, w[184]); FFV1_1(w[2], w[99], pars->GC_11, pars->ZERO, pars->ZERO, w[185]); FFV1_1(w[2], w[100], pars->GC_11, pars->ZERO, pars->ZERO, w[186]); FFV1_2(w[3], w[79], pars->GC_11, pars->ZERO, pars->ZERO, w[187]); FFV1_2(w[3], w[80], pars->GC_11, pars->ZERO, pars->ZERO, w[188]); FFV1_2(w[3], w[81], pars->GC_11, pars->ZERO, pars->ZERO, w[189]); VVV1P0_1(w[79], w[5], pars->GC_10, pars->ZERO, pars->ZERO, w[190]); VVV1P0_1(w[80], w[5], pars->GC_10, pars->ZERO, pars->ZERO, w[191]); VVV1P0_1(w[81], w[5], pars->GC_10, pars->ZERO, pars->ZERO, w[192]); FFV1_1(w[2], w[79], pars->GC_11, pars->ZERO, pars->ZERO, w[193]); FFV1_1(w[2], w[80], pars->GC_11, pars->ZERO, pars->ZERO, w[194]); FFV1_1(w[2], w[81], pars->GC_11, pars->ZERO, pars->ZERO, w[195]); FFV1_2(w[3], w[51], pars->GC_11, pars->ZERO, pars->ZERO, w[196]); FFV1_2(w[3], w[52], pars->GC_11, pars->ZERO, pars->ZERO, w[197]); FFV1_2(w[3], w[53], pars->GC_11, pars->ZERO, pars->ZERO, w[198]); VVV1P0_1(w[4], w[51], pars->GC_10, pars->ZERO, pars->ZERO, w[199]); VVV1P0_1(w[4], w[52], pars->GC_10, pars->ZERO, pars->ZERO, w[200]); VVV1P0_1(w[4], w[53], pars->GC_10, pars->ZERO, pars->ZERO, w[201]); FFV1_1(w[2], w[51], pars->GC_11, pars->ZERO, pars->ZERO, w[202]); FFV1_1(w[2], w[52], pars->GC_11, pars->ZERO, pars->ZERO, w[203]); FFV1_1(w[2], w[53], pars->GC_11, pars->ZERO, pars->ZERO, w[204]); // Calculate all amplitudes // Amplitude(s) for diagram number 0 FFV1_0(w[12], w[11], w[7], pars->GC_11, amp[0]); FFV1_0(w[13], w[11], w[6], pars->GC_11, amp[1]); FFV1_0(w[15], w[14], w[7], pars->GC_11, amp[2]); FFV1_0(w[13], w[14], w[5], pars->GC_11, amp[3]); FFV1_0(w[15], w[16], w[6], pars->GC_11, amp[4]); FFV1_0(w[12], w[16], w[5], pars->GC_11, amp[5]); FFV1_0(w[19], w[11], w[7], pars->GC_11, amp[6]); FFV1_0(w[20], w[11], w[6], pars->GC_11, amp[7]); FFV1_0(w[21], w[14], w[7], pars->GC_11, amp[8]); FFV1_0(w[20], w[14], w[5], pars->GC_11, amp[9]); FFV1_0(w[21], w[16], w[6], pars->GC_11, amp[10]); FFV1_0(w[19], w[16], w[5], pars->GC_11, amp[11]); FFV1_0(w[24], w[23], w[7], pars->GC_11, amp[12]); FFV1_0(w[25], w[23], w[6], pars->GC_11, amp[13]); FFV1_0(w[26], w[14], w[7], pars->GC_11, amp[14]); FFV1_0(w[26], w[16], w[6], pars->GC_11, amp[15]); FFV1_0(w[25], w[14], w[8], pars->GC_2, amp[16]); FFV1_0(w[24], w[16], w[8], pars->GC_2, amp[17]); FFV1_0(w[24], w[27], w[7], pars->GC_11, amp[18]); FFV1_0(w[25], w[27], w[6], pars->GC_11, amp[19]); FFV1_0(w[28], w[14], w[7], pars->GC_11, amp[20]); FFV1_0(w[28], w[16], w[6], pars->GC_11, amp[21]); FFV2_5_0(w[25], w[14], w[17], pars->GC_51, pars->GC_58, amp[22]); FFV2_5_0(w[24], w[16], w[17], pars->GC_51, pars->GC_58, amp[23]); FFV1_0(w[22], w[23], w[29], pars->GC_11, amp[24]); FFV1_0(w[26], w[9], w[29], pars->GC_11, amp[25]); FFV1_0(w[22], w[27], w[29], pars->GC_11, amp[26]); FFV1_0(w[28], w[9], w[29], pars->GC_11, amp[27]); FFV1_0(w[31], w[23], w[7], pars->GC_11, amp[28]); FFV1_0(w[32], w[23], w[5], pars->GC_11, amp[29]); FFV1_0(w[33], w[11], w[7], pars->GC_11, amp[30]); FFV1_0(w[33], w[16], w[5], pars->GC_11, amp[31]); FFV1_0(w[32], w[11], w[8], pars->GC_2, amp[32]); FFV1_0(w[31], w[16], w[8], pars->GC_2, amp[33]); FFV1_0(w[31], w[27], w[7], pars->GC_11, amp[34]); FFV1_0(w[32], w[27], w[5], pars->GC_11, amp[35]); FFV1_0(w[34], w[11], w[7], pars->GC_11, amp[36]); FFV1_0(w[34], w[16], w[5], pars->GC_11, amp[37]); FFV2_5_0(w[32], w[11], w[17], pars->GC_51, pars->GC_58, amp[38]); FFV2_5_0(w[31], w[16], w[17], pars->GC_51, pars->GC_58, amp[39]); FFV1_0(w[30], w[23], w[35], pars->GC_11, amp[40]); FFV1_0(w[33], w[9], w[35], pars->GC_11, amp[41]); FFV1_0(w[30], w[27], w[35], pars->GC_11, amp[42]); FFV1_0(w[34], w[9], w[35], pars->GC_11, amp[43]); FFV1_0(w[37], w[23], w[6], pars->GC_11, amp[44]); FFV1_0(w[38], w[23], w[5], pars->GC_11, amp[45]); FFV1_0(w[39], w[11], w[6], pars->GC_11, amp[46]); FFV1_0(w[39], w[14], w[5], pars->GC_11, amp[47]); FFV1_0(w[38], w[11], w[8], pars->GC_2, amp[48]); FFV1_0(w[37], w[14], w[8], pars->GC_2, amp[49]); FFV1_0(w[37], w[27], w[6], pars->GC_11, amp[50]); FFV1_0(w[38], w[27], w[5], pars->GC_11, amp[51]); FFV1_0(w[40], w[11], w[6], pars->GC_11, amp[52]); FFV1_0(w[40], w[14], w[5], pars->GC_11, amp[53]); FFV2_5_0(w[38], w[11], w[17], pars->GC_51, pars->GC_58, amp[54]); FFV2_5_0(w[37], w[14], w[17], pars->GC_51, pars->GC_58, amp[55]); FFV1_0(w[36], w[23], w[41], pars->GC_11, amp[56]); FFV1_0(w[39], w[9], w[41], pars->GC_11, amp[57]); FFV1_0(w[36], w[27], w[41], pars->GC_11, amp[58]); FFV1_0(w[40], w[9], w[41], pars->GC_11, amp[59]); FFV1_0(w[42], w[23], w[7], pars->GC_11, amp[60]); FFV1_0(w[3], w[23], w[43], pars->GC_11, amp[61]); FFV1_0(w[10], w[44], w[7], pars->GC_11, amp[62]); FFV1_0(w[10], w[16], w[41], pars->GC_11, amp[63]); FFV1_0(w[10], w[9], w[43], pars->GC_11, amp[64]); FFV1_0(w[42], w[16], w[8], pars->GC_2, amp[65]); FFV1_0(w[42], w[27], w[7], pars->GC_11, amp[66]); FFV1_0(w[3], w[27], w[43], pars->GC_11, amp[67]); FFV1_0(w[18], w[44], w[7], pars->GC_11, amp[68]); FFV1_0(w[18], w[16], w[41], pars->GC_11, amp[69]); FFV1_0(w[18], w[9], w[43], pars->GC_11, amp[70]); FFV2_5_0(w[42], w[16], w[17], pars->GC_51, pars->GC_58, amp[71]); FFV1_0(w[45], w[23], w[6], pars->GC_11, amp[72]); FFV1_0(w[3], w[23], w[46], pars->GC_11, amp[73]); FFV1_0(w[10], w[47], w[6], pars->GC_11, amp[74]); FFV1_0(w[10], w[14], w[35], pars->GC_11, amp[75]); FFV1_0(w[10], w[9], w[46], pars->GC_11, amp[76]); FFV1_0(w[45], w[14], w[8], pars->GC_2, amp[77]); FFV1_0(w[45], w[27], w[6], pars->GC_11, amp[78]); FFV1_0(w[3], w[27], w[46], pars->GC_11, amp[79]); FFV1_0(w[18], w[47], w[6], pars->GC_11, amp[80]); FFV1_0(w[18], w[14], w[35], pars->GC_11, amp[81]); FFV1_0(w[18], w[9], w[46], pars->GC_11, amp[82]); FFV2_5_0(w[45], w[14], w[17], pars->GC_51, pars->GC_58, amp[83]); FFV1_0(w[48], w[23], w[5], pars->GC_11, amp[84]); FFV1_0(w[3], w[23], w[49], pars->GC_11, amp[85]); FFV1_0(w[10], w[11], w[29], pars->GC_11, amp[86]); FFV1_0(w[10], w[50], w[5], pars->GC_11, amp[87]); FFV1_0(w[10], w[9], w[49], pars->GC_11, amp[88]); FFV1_0(w[48], w[11], w[8], pars->GC_2, amp[89]); FFV1_0(w[48], w[27], w[5], pars->GC_11, amp[90]); FFV1_0(w[3], w[27], w[49], pars->GC_11, amp[91]); FFV1_0(w[18], w[11], w[29], pars->GC_11, amp[92]); FFV1_0(w[18], w[50], w[5], pars->GC_11, amp[93]); FFV1_0(w[18], w[9], w[49], pars->GC_11, amp[94]); FFV2_5_0(w[48], w[11], w[17], pars->GC_51, pars->GC_58, amp[95]); FFV1_0(w[3], w[23], w[51], pars->GC_11, amp[96]); FFV1_0(w[3], w[23], w[52], pars->GC_11, amp[97]); FFV1_0(w[3], w[23], w[53], pars->GC_11, amp[98]); FFV1_0(w[10], w[9], w[51], pars->GC_11, amp[99]); FFV1_0(w[10], w[9], w[52], pars->GC_11, amp[100]); FFV1_0(w[10], w[9], w[53], pars->GC_11, amp[101]); FFV1_0(w[3], w[27], w[51], pars->GC_11, amp[102]); FFV1_0(w[3], w[27], w[52], pars->GC_11, amp[103]); FFV1_0(w[3], w[27], w[53], pars->GC_11, amp[104]); FFV1_0(w[18], w[9], w[51], pars->GC_11, amp[105]); FFV1_0(w[18], w[9], w[52], pars->GC_11, amp[106]); FFV1_0(w[18], w[9], w[53], pars->GC_11, amp[107]); FFV1_0(w[12], w[55], w[7], pars->GC_11, amp[108]); FFV1_0(w[13], w[55], w[6], pars->GC_11, amp[109]); FFV1_0(w[57], w[56], w[7], pars->GC_11, amp[110]); FFV1_0(w[13], w[56], w[4], pars->GC_11, amp[111]); FFV1_0(w[57], w[58], w[6], pars->GC_11, amp[112]); FFV1_0(w[12], w[58], w[4], pars->GC_11, amp[113]); FFV1_0(w[19], w[55], w[7], pars->GC_11, amp[114]); FFV1_0(w[20], w[55], w[6], pars->GC_11, amp[115]); FFV1_0(w[59], w[56], w[7], pars->GC_11, amp[116]); FFV1_0(w[20], w[56], w[4], pars->GC_11, amp[117]); FFV1_0(w[59], w[58], w[6], pars->GC_11, amp[118]); FFV1_0(w[19], w[58], w[4], pars->GC_11, amp[119]); FFV1_0(w[62], w[61], w[7], pars->GC_11, amp[120]); FFV1_0(w[63], w[61], w[6], pars->GC_11, amp[121]); FFV1_0(w[64], w[56], w[7], pars->GC_11, amp[122]); FFV1_0(w[64], w[58], w[6], pars->GC_11, amp[123]); FFV1_0(w[63], w[56], w[8], pars->GC_2, amp[124]); FFV1_0(w[62], w[58], w[8], pars->GC_2, amp[125]); FFV1_0(w[62], w[65], w[7], pars->GC_11, amp[126]); FFV1_0(w[63], w[65], w[6], pars->GC_11, amp[127]); FFV1_0(w[66], w[56], w[7], pars->GC_11, amp[128]); FFV1_0(w[66], w[58], w[6], pars->GC_11, amp[129]); FFV2_5_0(w[63], w[56], w[17], pars->GC_51, pars->GC_58, amp[130]); FFV2_5_0(w[62], w[58], w[17], pars->GC_51, pars->GC_58, amp[131]); FFV1_0(w[60], w[61], w[29], pars->GC_11, amp[132]); FFV1_0(w[64], w[54], w[29], pars->GC_11, amp[133]); FFV1_0(w[60], w[65], w[29], pars->GC_11, amp[134]); FFV1_0(w[66], w[54], w[29], pars->GC_11, amp[135]); FFV1_0(w[67], w[61], w[7], pars->GC_11, amp[136]); FFV1_0(w[32], w[61], w[4], pars->GC_11, amp[137]); FFV1_0(w[33], w[55], w[7], pars->GC_11, amp[138]); FFV1_0(w[33], w[58], w[4], pars->GC_11, amp[139]); FFV1_0(w[32], w[55], w[8], pars->GC_2, amp[140]); FFV1_0(w[67], w[58], w[8], pars->GC_2, amp[141]); FFV1_0(w[67], w[65], w[7], pars->GC_11, amp[142]); FFV1_0(w[32], w[65], w[4], pars->GC_11, amp[143]); FFV1_0(w[34], w[55], w[7], pars->GC_11, amp[144]); FFV1_0(w[34], w[58], w[4], pars->GC_11, amp[145]); FFV2_5_0(w[32], w[55], w[17], pars->GC_51, pars->GC_58, amp[146]); FFV2_5_0(w[67], w[58], w[17], pars->GC_51, pars->GC_58, amp[147]); FFV1_0(w[30], w[61], w[68], pars->GC_11, amp[148]); FFV1_0(w[33], w[54], w[68], pars->GC_11, amp[149]); FFV1_0(w[30], w[65], w[68], pars->GC_11, amp[150]); FFV1_0(w[34], w[54], w[68], pars->GC_11, amp[151]); FFV1_0(w[69], w[61], w[6], pars->GC_11, amp[152]); FFV1_0(w[38], w[61], w[4], pars->GC_11, amp[153]); FFV1_0(w[39], w[55], w[6], pars->GC_11, amp[154]); FFV1_0(w[39], w[56], w[4], pars->GC_11, amp[155]); FFV1_0(w[38], w[55], w[8], pars->GC_2, amp[156]); FFV1_0(w[69], w[56], w[8], pars->GC_2, amp[157]); FFV1_0(w[69], w[65], w[6], pars->GC_11, amp[158]); FFV1_0(w[38], w[65], w[4], pars->GC_11, amp[159]); FFV1_0(w[40], w[55], w[6], pars->GC_11, amp[160]); FFV1_0(w[40], w[56], w[4], pars->GC_11, amp[161]); FFV2_5_0(w[38], w[55], w[17], pars->GC_51, pars->GC_58, amp[162]); FFV2_5_0(w[69], w[56], w[17], pars->GC_51, pars->GC_58, amp[163]); FFV1_0(w[36], w[61], w[70], pars->GC_11, amp[164]); FFV1_0(w[39], w[54], w[70], pars->GC_11, amp[165]); FFV1_0(w[36], w[65], w[70], pars->GC_11, amp[166]); FFV1_0(w[40], w[54], w[70], pars->GC_11, amp[167]); FFV1_0(w[71], w[61], w[7], pars->GC_11, amp[168]); FFV1_0(w[3], w[61], w[72], pars->GC_11, amp[169]); FFV1_0(w[10], w[73], w[7], pars->GC_11, amp[170]); FFV1_0(w[10], w[58], w[70], pars->GC_11, amp[171]); FFV1_0(w[10], w[54], w[72], pars->GC_11, amp[172]); FFV1_0(w[71], w[58], w[8], pars->GC_2, amp[173]); FFV1_0(w[71], w[65], w[7], pars->GC_11, amp[174]); FFV1_0(w[3], w[65], w[72], pars->GC_11, amp[175]); FFV1_0(w[18], w[73], w[7], pars->GC_11, amp[176]); FFV1_0(w[18], w[58], w[70], pars->GC_11, amp[177]); FFV1_0(w[18], w[54], w[72], pars->GC_11, amp[178]); FFV2_5_0(w[71], w[58], w[17], pars->GC_51, pars->GC_58, amp[179]); FFV1_0(w[74], w[61], w[6], pars->GC_11, amp[180]); FFV1_0(w[3], w[61], w[75], pars->GC_11, amp[181]); FFV1_0(w[10], w[76], w[6], pars->GC_11, amp[182]); FFV1_0(w[10], w[56], w[68], pars->GC_11, amp[183]); FFV1_0(w[10], w[54], w[75], pars->GC_11, amp[184]); FFV1_0(w[74], w[56], w[8], pars->GC_2, amp[185]); FFV1_0(w[74], w[65], w[6], pars->GC_11, amp[186]); FFV1_0(w[3], w[65], w[75], pars->GC_11, amp[187]); FFV1_0(w[18], w[76], w[6], pars->GC_11, amp[188]); FFV1_0(w[18], w[56], w[68], pars->GC_11, amp[189]); FFV1_0(w[18], w[54], w[75], pars->GC_11, amp[190]); FFV2_5_0(w[74], w[56], w[17], pars->GC_51, pars->GC_58, amp[191]); FFV1_0(w[48], w[61], w[4], pars->GC_11, amp[192]); FFV1_0(w[3], w[61], w[77], pars->GC_11, amp[193]); FFV1_0(w[10], w[55], w[29], pars->GC_11, amp[194]); FFV1_0(w[10], w[78], w[4], pars->GC_11, amp[195]); FFV1_0(w[10], w[54], w[77], pars->GC_11, amp[196]); FFV1_0(w[48], w[55], w[8], pars->GC_2, amp[197]); FFV1_0(w[48], w[65], w[4], pars->GC_11, amp[198]); FFV1_0(w[3], w[65], w[77], pars->GC_11, amp[199]); FFV1_0(w[18], w[55], w[29], pars->GC_11, amp[200]); FFV1_0(w[18], w[78], w[4], pars->GC_11, amp[201]); FFV1_0(w[18], w[54], w[77], pars->GC_11, amp[202]); FFV2_5_0(w[48], w[55], w[17], pars->GC_51, pars->GC_58, amp[203]); FFV1_0(w[3], w[61], w[79], pars->GC_11, amp[204]); FFV1_0(w[3], w[61], w[80], pars->GC_11, amp[205]); FFV1_0(w[3], w[61], w[81], pars->GC_11, amp[206]); FFV1_0(w[10], w[54], w[79], pars->GC_11, amp[207]); FFV1_0(w[10], w[54], w[80], pars->GC_11, amp[208]); FFV1_0(w[10], w[54], w[81], pars->GC_11, amp[209]); FFV1_0(w[3], w[65], w[79], pars->GC_11, amp[210]); FFV1_0(w[3], w[65], w[80], pars->GC_11, amp[211]); FFV1_0(w[3], w[65], w[81], pars->GC_11, amp[212]); FFV1_0(w[18], w[54], w[79], pars->GC_11, amp[213]); FFV1_0(w[18], w[54], w[80], pars->GC_11, amp[214]); FFV1_0(w[18], w[54], w[81], pars->GC_11, amp[215]); FFV1_0(w[15], w[83], w[7], pars->GC_11, amp[216]); FFV1_0(w[13], w[83], w[5], pars->GC_11, amp[217]); FFV1_0(w[57], w[84], w[7], pars->GC_11, amp[218]); FFV1_0(w[13], w[84], w[4], pars->GC_11, amp[219]); FFV1_0(w[57], w[85], w[5], pars->GC_11, amp[220]); FFV1_0(w[15], w[85], w[4], pars->GC_11, amp[221]); FFV1_0(w[21], w[83], w[7], pars->GC_11, amp[222]); FFV1_0(w[20], w[83], w[5], pars->GC_11, amp[223]); FFV1_0(w[59], w[84], w[7], pars->GC_11, amp[224]); FFV1_0(w[20], w[84], w[4], pars->GC_11, amp[225]); FFV1_0(w[59], w[85], w[5], pars->GC_11, amp[226]); FFV1_0(w[21], w[85], w[4], pars->GC_11, amp[227]); FFV1_0(w[87], w[86], w[7], pars->GC_11, amp[228]); FFV1_0(w[63], w[86], w[5], pars->GC_11, amp[229]); FFV1_0(w[64], w[84], w[7], pars->GC_11, amp[230]); FFV1_0(w[64], w[85], w[5], pars->GC_11, amp[231]); FFV1_0(w[63], w[84], w[8], pars->GC_2, amp[232]); FFV1_0(w[87], w[85], w[8], pars->GC_2, amp[233]); FFV1_0(w[87], w[88], w[7], pars->GC_11, amp[234]); FFV1_0(w[63], w[88], w[5], pars->GC_11, amp[235]); FFV1_0(w[66], w[84], w[7], pars->GC_11, amp[236]); FFV1_0(w[66], w[85], w[5], pars->GC_11, amp[237]); FFV2_5_0(w[63], w[84], w[17], pars->GC_51, pars->GC_58, amp[238]); FFV2_5_0(w[87], w[85], w[17], pars->GC_51, pars->GC_58, amp[239]); FFV1_0(w[60], w[86], w[35], pars->GC_11, amp[240]); FFV1_0(w[64], w[82], w[35], pars->GC_11, amp[241]); FFV1_0(w[60], w[88], w[35], pars->GC_11, amp[242]); FFV1_0(w[66], w[82], w[35], pars->GC_11, amp[243]); FFV1_0(w[89], w[86], w[7], pars->GC_11, amp[244]); FFV1_0(w[25], w[86], w[4], pars->GC_11, amp[245]); FFV1_0(w[26], w[83], w[7], pars->GC_11, amp[246]); FFV1_0(w[26], w[85], w[4], pars->GC_11, amp[247]); FFV1_0(w[25], w[83], w[8], pars->GC_2, amp[248]); FFV1_0(w[89], w[85], w[8], pars->GC_2, amp[249]); FFV1_0(w[89], w[88], w[7], pars->GC_11, amp[250]); FFV1_0(w[25], w[88], w[4], pars->GC_11, amp[251]); FFV1_0(w[28], w[83], w[7], pars->GC_11, amp[252]); FFV1_0(w[28], w[85], w[4], pars->GC_11, amp[253]); FFV2_5_0(w[25], w[83], w[17], pars->GC_51, pars->GC_58, amp[254]); FFV2_5_0(w[89], w[85], w[17], pars->GC_51, pars->GC_58, amp[255]); FFV1_0(w[22], w[86], w[68], pars->GC_11, amp[256]); FFV1_0(w[26], w[82], w[68], pars->GC_11, amp[257]); FFV1_0(w[22], w[88], w[68], pars->GC_11, amp[258]); FFV1_0(w[28], w[82], w[68], pars->GC_11, amp[259]); FFV1_0(w[69], w[86], w[5], pars->GC_11, amp[260]); FFV1_0(w[37], w[86], w[4], pars->GC_11, amp[261]); FFV1_0(w[39], w[83], w[5], pars->GC_11, amp[262]); FFV1_0(w[39], w[84], w[4], pars->GC_11, amp[263]); FFV1_0(w[37], w[83], w[8], pars->GC_2, amp[264]); FFV1_0(w[69], w[84], w[8], pars->GC_2, amp[265]); FFV1_0(w[69], w[88], w[5], pars->GC_11, amp[266]); FFV1_0(w[37], w[88], w[4], pars->GC_11, amp[267]); FFV1_0(w[40], w[83], w[5], pars->GC_11, amp[268]); FFV1_0(w[40], w[84], w[4], pars->GC_11, amp[269]); FFV2_5_0(w[37], w[83], w[17], pars->GC_51, pars->GC_58, amp[270]); FFV2_5_0(w[69], w[84], w[17], pars->GC_51, pars->GC_58, amp[271]); FFV1_0(w[36], w[86], w[90], pars->GC_11, amp[272]); FFV1_0(w[39], w[82], w[90], pars->GC_11, amp[273]); FFV1_0(w[36], w[88], w[90], pars->GC_11, amp[274]); FFV1_0(w[40], w[82], w[90], pars->GC_11, amp[275]); FFV1_0(w[91], w[86], w[7], pars->GC_11, amp[276]); FFV1_0(w[3], w[86], w[92], pars->GC_11, amp[277]); FFV1_0(w[10], w[93], w[7], pars->GC_11, amp[278]); FFV1_0(w[10], w[85], w[90], pars->GC_11, amp[279]); FFV1_0(w[10], w[82], w[92], pars->GC_11, amp[280]); FFV1_0(w[91], w[85], w[8], pars->GC_2, amp[281]); FFV1_0(w[91], w[88], w[7], pars->GC_11, amp[282]); FFV1_0(w[3], w[88], w[92], pars->GC_11, amp[283]); FFV1_0(w[18], w[93], w[7], pars->GC_11, amp[284]); FFV1_0(w[18], w[85], w[90], pars->GC_11, amp[285]); FFV1_0(w[18], w[82], w[92], pars->GC_11, amp[286]); FFV2_5_0(w[91], w[85], w[17], pars->GC_51, pars->GC_58, amp[287]); FFV1_0(w[74], w[86], w[5], pars->GC_11, amp[288]); FFV1_0(w[3], w[86], w[94], pars->GC_11, amp[289]); FFV1_0(w[10], w[95], w[5], pars->GC_11, amp[290]); FFV1_0(w[10], w[84], w[68], pars->GC_11, amp[291]); FFV1_0(w[10], w[82], w[94], pars->GC_11, amp[292]); FFV1_0(w[74], w[84], w[8], pars->GC_2, amp[293]); FFV1_0(w[74], w[88], w[5], pars->GC_11, amp[294]); FFV1_0(w[3], w[88], w[94], pars->GC_11, amp[295]); FFV1_0(w[18], w[95], w[5], pars->GC_11, amp[296]); FFV1_0(w[18], w[84], w[68], pars->GC_11, amp[297]); FFV1_0(w[18], w[82], w[94], pars->GC_11, amp[298]); FFV2_5_0(w[74], w[84], w[17], pars->GC_51, pars->GC_58, amp[299]); FFV1_0(w[45], w[86], w[4], pars->GC_11, amp[300]); FFV1_0(w[3], w[86], w[96], pars->GC_11, amp[301]); FFV1_0(w[10], w[83], w[35], pars->GC_11, amp[302]); FFV1_0(w[10], w[97], w[4], pars->GC_11, amp[303]); FFV1_0(w[10], w[82], w[96], pars->GC_11, amp[304]); FFV1_0(w[45], w[83], w[8], pars->GC_2, amp[305]); FFV1_0(w[45], w[88], w[4], pars->GC_11, amp[306]); FFV1_0(w[3], w[88], w[96], pars->GC_11, amp[307]); FFV1_0(w[18], w[83], w[35], pars->GC_11, amp[308]); FFV1_0(w[18], w[97], w[4], pars->GC_11, amp[309]); FFV1_0(w[18], w[82], w[96], pars->GC_11, amp[310]); FFV2_5_0(w[45], w[83], w[17], pars->GC_51, pars->GC_58, amp[311]); FFV1_0(w[3], w[86], w[98], pars->GC_11, amp[312]); FFV1_0(w[3], w[86], w[99], pars->GC_11, amp[313]); FFV1_0(w[3], w[86], w[100], pars->GC_11, amp[314]); FFV1_0(w[10], w[82], w[98], pars->GC_11, amp[315]); FFV1_0(w[10], w[82], w[99], pars->GC_11, amp[316]); FFV1_0(w[10], w[82], w[100], pars->GC_11, amp[317]); FFV1_0(w[3], w[88], w[98], pars->GC_11, amp[318]); FFV1_0(w[3], w[88], w[99], pars->GC_11, amp[319]); FFV1_0(w[3], w[88], w[100], pars->GC_11, amp[320]); FFV1_0(w[18], w[82], w[98], pars->GC_11, amp[321]); FFV1_0(w[18], w[82], w[99], pars->GC_11, amp[322]); FFV1_0(w[18], w[82], w[100], pars->GC_11, amp[323]); FFV1_0(w[15], w[102], w[6], pars->GC_11, amp[324]); FFV1_0(w[12], w[102], w[5], pars->GC_11, amp[325]); FFV1_0(w[57], w[103], w[6], pars->GC_11, amp[326]); FFV1_0(w[12], w[103], w[4], pars->GC_11, amp[327]); FFV1_0(w[57], w[104], w[5], pars->GC_11, amp[328]); FFV1_0(w[15], w[104], w[4], pars->GC_11, amp[329]); FFV1_0(w[21], w[102], w[6], pars->GC_11, amp[330]); FFV1_0(w[19], w[102], w[5], pars->GC_11, amp[331]); FFV1_0(w[59], w[103], w[6], pars->GC_11, amp[332]); FFV1_0(w[19], w[103], w[4], pars->GC_11, amp[333]); FFV1_0(w[59], w[104], w[5], pars->GC_11, amp[334]); FFV1_0(w[21], w[104], w[4], pars->GC_11, amp[335]); FFV1_0(w[87], w[105], w[6], pars->GC_11, amp[336]); FFV1_0(w[62], w[105], w[5], pars->GC_11, amp[337]); FFV1_0(w[64], w[103], w[6], pars->GC_11, amp[338]); FFV1_0(w[64], w[104], w[5], pars->GC_11, amp[339]); FFV1_0(w[62], w[103], w[8], pars->GC_2, amp[340]); FFV1_0(w[87], w[104], w[8], pars->GC_2, amp[341]); FFV1_0(w[87], w[106], w[6], pars->GC_11, amp[342]); FFV1_0(w[62], w[106], w[5], pars->GC_11, amp[343]); FFV1_0(w[66], w[103], w[6], pars->GC_11, amp[344]); FFV1_0(w[66], w[104], w[5], pars->GC_11, amp[345]); FFV2_5_0(w[62], w[103], w[17], pars->GC_51, pars->GC_58, amp[346]); FFV2_5_0(w[87], w[104], w[17], pars->GC_51, pars->GC_58, amp[347]); FFV1_0(w[60], w[105], w[41], pars->GC_11, amp[348]); FFV1_0(w[64], w[101], w[41], pars->GC_11, amp[349]); FFV1_0(w[60], w[106], w[41], pars->GC_11, amp[350]); FFV1_0(w[66], w[101], w[41], pars->GC_11, amp[351]); FFV1_0(w[89], w[105], w[6], pars->GC_11, amp[352]); FFV1_0(w[24], w[105], w[4], pars->GC_11, amp[353]); FFV1_0(w[26], w[102], w[6], pars->GC_11, amp[354]); FFV1_0(w[26], w[104], w[4], pars->GC_11, amp[355]); FFV1_0(w[24], w[102], w[8], pars->GC_2, amp[356]); FFV1_0(w[89], w[104], w[8], pars->GC_2, amp[357]); FFV1_0(w[89], w[106], w[6], pars->GC_11, amp[358]); FFV1_0(w[24], w[106], w[4], pars->GC_11, amp[359]); FFV1_0(w[28], w[102], w[6], pars->GC_11, amp[360]); FFV1_0(w[28], w[104], w[4], pars->GC_11, amp[361]); FFV2_5_0(w[24], w[102], w[17], pars->GC_51, pars->GC_58, amp[362]); FFV2_5_0(w[89], w[104], w[17], pars->GC_51, pars->GC_58, amp[363]); FFV1_0(w[22], w[105], w[70], pars->GC_11, amp[364]); FFV1_0(w[26], w[101], w[70], pars->GC_11, amp[365]); FFV1_0(w[22], w[106], w[70], pars->GC_11, amp[366]); FFV1_0(w[28], w[101], w[70], pars->GC_11, amp[367]); FFV1_0(w[67], w[105], w[5], pars->GC_11, amp[368]); FFV1_0(w[31], w[105], w[4], pars->GC_11, amp[369]); FFV1_0(w[33], w[102], w[5], pars->GC_11, amp[370]); FFV1_0(w[33], w[103], w[4], pars->GC_11, amp[371]); FFV1_0(w[31], w[102], w[8], pars->GC_2, amp[372]); FFV1_0(w[67], w[103], w[8], pars->GC_2, amp[373]); FFV1_0(w[67], w[106], w[5], pars->GC_11, amp[374]); FFV1_0(w[31], w[106], w[4], pars->GC_11, amp[375]); FFV1_0(w[34], w[102], w[5], pars->GC_11, amp[376]); FFV1_0(w[34], w[103], w[4], pars->GC_11, amp[377]); FFV2_5_0(w[31], w[102], w[17], pars->GC_51, pars->GC_58, amp[378]); FFV2_5_0(w[67], w[103], w[17], pars->GC_51, pars->GC_58, amp[379]); FFV1_0(w[30], w[105], w[90], pars->GC_11, amp[380]); FFV1_0(w[33], w[101], w[90], pars->GC_11, amp[381]); FFV1_0(w[30], w[106], w[90], pars->GC_11, amp[382]); FFV1_0(w[34], w[101], w[90], pars->GC_11, amp[383]); FFV1_0(w[91], w[105], w[6], pars->GC_11, amp[384]); FFV1_0(w[3], w[105], w[107], pars->GC_11, amp[385]); FFV1_0(w[10], w[108], w[6], pars->GC_11, amp[386]); FFV1_0(w[10], w[104], w[90], pars->GC_11, amp[387]); FFV1_0(w[10], w[101], w[107], pars->GC_11, amp[388]); FFV1_0(w[91], w[104], w[8], pars->GC_2, amp[389]); FFV1_0(w[91], w[106], w[6], pars->GC_11, amp[390]); FFV1_0(w[3], w[106], w[107], pars->GC_11, amp[391]); FFV1_0(w[18], w[108], w[6], pars->GC_11, amp[392]); FFV1_0(w[18], w[104], w[90], pars->GC_11, amp[393]); FFV1_0(w[18], w[101], w[107], pars->GC_11, amp[394]); FFV2_5_0(w[91], w[104], w[17], pars->GC_51, pars->GC_58, amp[395]); FFV1_0(w[71], w[105], w[5], pars->GC_11, amp[396]); FFV1_0(w[3], w[105], w[109], pars->GC_11, amp[397]); FFV1_0(w[10], w[110], w[5], pars->GC_11, amp[398]); FFV1_0(w[10], w[103], w[70], pars->GC_11, amp[399]); FFV1_0(w[10], w[101], w[109], pars->GC_11, amp[400]); FFV1_0(w[71], w[103], w[8], pars->GC_2, amp[401]); FFV1_0(w[71], w[106], w[5], pars->GC_11, amp[402]); FFV1_0(w[3], w[106], w[109], pars->GC_11, amp[403]); FFV1_0(w[18], w[110], w[5], pars->GC_11, amp[404]); FFV1_0(w[18], w[103], w[70], pars->GC_11, amp[405]); FFV1_0(w[18], w[101], w[109], pars->GC_11, amp[406]); FFV2_5_0(w[71], w[103], w[17], pars->GC_51, pars->GC_58, amp[407]); FFV1_0(w[42], w[105], w[4], pars->GC_11, amp[408]); FFV1_0(w[3], w[105], w[111], pars->GC_11, amp[409]); FFV1_0(w[10], w[102], w[41], pars->GC_11, amp[410]); FFV1_0(w[10], w[112], w[4], pars->GC_11, amp[411]); FFV1_0(w[10], w[101], w[111], pars->GC_11, amp[412]); FFV1_0(w[42], w[102], w[8], pars->GC_2, amp[413]); FFV1_0(w[42], w[106], w[4], pars->GC_11, amp[414]); FFV1_0(w[3], w[106], w[111], pars->GC_11, amp[415]); FFV1_0(w[18], w[102], w[41], pars->GC_11, amp[416]); FFV1_0(w[18], w[112], w[4], pars->GC_11, amp[417]); FFV1_0(w[18], w[101], w[111], pars->GC_11, amp[418]); FFV2_5_0(w[42], w[102], w[17], pars->GC_51, pars->GC_58, amp[419]); FFV1_0(w[3], w[105], w[113], pars->GC_11, amp[420]); FFV1_0(w[3], w[105], w[114], pars->GC_11, amp[421]); FFV1_0(w[3], w[105], w[115], pars->GC_11, amp[422]); FFV1_0(w[10], w[101], w[113], pars->GC_11, amp[423]); FFV1_0(w[10], w[101], w[114], pars->GC_11, amp[424]); FFV1_0(w[10], w[101], w[115], pars->GC_11, amp[425]); FFV1_0(w[3], w[106], w[113], pars->GC_11, amp[426]); FFV1_0(w[3], w[106], w[114], pars->GC_11, amp[427]); FFV1_0(w[3], w[106], w[115], pars->GC_11, amp[428]); FFV1_0(w[18], w[101], w[113], pars->GC_11, amp[429]); FFV1_0(w[18], w[101], w[114], pars->GC_11, amp[430]); FFV1_0(w[18], w[101], w[115], pars->GC_11, amp[431]); FFV1_0(w[87], w[117], w[7], pars->GC_11, amp[432]); FFV1_0(w[87], w[118], w[6], pars->GC_11, amp[433]); FFV1_0(w[62], w[119], w[7], pars->GC_11, amp[434]); FFV1_0(w[62], w[118], w[5], pars->GC_11, amp[435]); FFV1_0(w[63], w[119], w[6], pars->GC_11, amp[436]); FFV1_0(w[63], w[117], w[5], pars->GC_11, amp[437]); FFV1_0(w[87], w[121], w[7], pars->GC_11, amp[438]); FFV1_0(w[87], w[122], w[6], pars->GC_11, amp[439]); FFV1_0(w[62], w[123], w[7], pars->GC_11, amp[440]); FFV1_0(w[62], w[122], w[5], pars->GC_11, amp[441]); FFV1_0(w[63], w[123], w[6], pars->GC_11, amp[442]); FFV1_0(w[63], w[121], w[5], pars->GC_11, amp[443]); FFV1_0(w[124], w[116], w[7], pars->GC_11, amp[444]); FFV1_0(w[63], w[116], w[41], pars->GC_11, amp[445]); FFV1_0(w[60], w[116], w[43], pars->GC_11, amp[446]); FFV1_0(w[64], w[125], w[7], pars->GC_11, amp[447]); FFV1_0(w[64], w[2], w[43], pars->GC_11, amp[448]); FFV1_0(w[63], w[125], w[8], pars->GC_2, amp[449]); FFV1_0(w[124], w[120], w[7], pars->GC_11, amp[450]); FFV1_0(w[63], w[120], w[41], pars->GC_11, amp[451]); FFV1_0(w[60], w[120], w[43], pars->GC_11, amp[452]); FFV1_0(w[66], w[125], w[7], pars->GC_11, amp[453]); FFV1_0(w[66], w[2], w[43], pars->GC_11, amp[454]); FFV2_5_0(w[63], w[125], w[17], pars->GC_51, pars->GC_58, amp[455]); FFV1_0(w[126], w[116], w[6], pars->GC_11, amp[456]); FFV1_0(w[62], w[116], w[35], pars->GC_11, amp[457]); FFV1_0(w[60], w[116], w[46], pars->GC_11, amp[458]); FFV1_0(w[64], w[127], w[6], pars->GC_11, amp[459]); FFV1_0(w[64], w[2], w[46], pars->GC_11, amp[460]); FFV1_0(w[62], w[127], w[8], pars->GC_2, amp[461]); FFV1_0(w[126], w[120], w[6], pars->GC_11, amp[462]); FFV1_0(w[62], w[120], w[35], pars->GC_11, amp[463]); FFV1_0(w[60], w[120], w[46], pars->GC_11, amp[464]); FFV1_0(w[66], w[127], w[6], pars->GC_11, amp[465]); FFV1_0(w[66], w[2], w[46], pars->GC_11, amp[466]); FFV2_5_0(w[62], w[127], w[17], pars->GC_51, pars->GC_58, amp[467]); FFV1_0(w[87], w[116], w[29], pars->GC_11, amp[468]); FFV1_0(w[128], w[116], w[5], pars->GC_11, amp[469]); FFV1_0(w[60], w[116], w[49], pars->GC_11, amp[470]); FFV1_0(w[64], w[129], w[5], pars->GC_11, amp[471]); FFV1_0(w[64], w[2], w[49], pars->GC_11, amp[472]); FFV1_0(w[87], w[129], w[8], pars->GC_2, amp[473]); FFV1_0(w[87], w[120], w[29], pars->GC_11, amp[474]); FFV1_0(w[128], w[120], w[5], pars->GC_11, amp[475]); FFV1_0(w[60], w[120], w[49], pars->GC_11, amp[476]); FFV1_0(w[66], w[129], w[5], pars->GC_11, amp[477]); FFV1_0(w[66], w[2], w[49], pars->GC_11, amp[478]); FFV2_5_0(w[87], w[129], w[17], pars->GC_51, pars->GC_58, amp[479]); FFV1_0(w[60], w[116], w[51], pars->GC_11, amp[480]); FFV1_0(w[60], w[116], w[52], pars->GC_11, amp[481]); FFV1_0(w[60], w[116], w[53], pars->GC_11, amp[482]); FFV1_0(w[64], w[2], w[51], pars->GC_11, amp[483]); FFV1_0(w[64], w[2], w[52], pars->GC_11, amp[484]); FFV1_0(w[64], w[2], w[53], pars->GC_11, amp[485]); FFV1_0(w[60], w[120], w[51], pars->GC_11, amp[486]); FFV1_0(w[60], w[120], w[52], pars->GC_11, amp[487]); FFV1_0(w[60], w[120], w[53], pars->GC_11, amp[488]); FFV1_0(w[66], w[2], w[51], pars->GC_11, amp[489]); FFV1_0(w[66], w[2], w[52], pars->GC_11, amp[490]); FFV1_0(w[66], w[2], w[53], pars->GC_11, amp[491]); FFV1_0(w[89], w[117], w[7], pars->GC_11, amp[492]); FFV1_0(w[89], w[118], w[6], pars->GC_11, amp[493]); FFV1_0(w[24], w[130], w[7], pars->GC_11, amp[494]); FFV1_0(w[24], w[118], w[4], pars->GC_11, amp[495]); FFV1_0(w[25], w[130], w[6], pars->GC_11, amp[496]); FFV1_0(w[25], w[117], w[4], pars->GC_11, amp[497]); FFV1_0(w[89], w[121], w[7], pars->GC_11, amp[498]); FFV1_0(w[89], w[122], w[6], pars->GC_11, amp[499]); FFV1_0(w[24], w[131], w[7], pars->GC_11, amp[500]); FFV1_0(w[24], w[122], w[4], pars->GC_11, amp[501]); FFV1_0(w[25], w[131], w[6], pars->GC_11, amp[502]); FFV1_0(w[25], w[121], w[4], pars->GC_11, amp[503]); FFV1_0(w[132], w[116], w[7], pars->GC_11, amp[504]); FFV1_0(w[25], w[116], w[70], pars->GC_11, amp[505]); FFV1_0(w[22], w[116], w[72], pars->GC_11, amp[506]); FFV1_0(w[26], w[133], w[7], pars->GC_11, amp[507]); FFV1_0(w[26], w[2], w[72], pars->GC_11, amp[508]); FFV1_0(w[25], w[133], w[8], pars->GC_2, amp[509]); FFV1_0(w[132], w[120], w[7], pars->GC_11, amp[510]); FFV1_0(w[25], w[120], w[70], pars->GC_11, amp[511]); FFV1_0(w[22], w[120], w[72], pars->GC_11, amp[512]); FFV1_0(w[28], w[133], w[7], pars->GC_11, amp[513]); FFV1_0(w[28], w[2], w[72], pars->GC_11, amp[514]); FFV2_5_0(w[25], w[133], w[17], pars->GC_51, pars->GC_58, amp[515]); FFV1_0(w[134], w[116], w[6], pars->GC_11, amp[516]); FFV1_0(w[24], w[116], w[68], pars->GC_11, amp[517]); FFV1_0(w[22], w[116], w[75], pars->GC_11, amp[518]); FFV1_0(w[26], w[135], w[6], pars->GC_11, amp[519]); FFV1_0(w[26], w[2], w[75], pars->GC_11, amp[520]); FFV1_0(w[24], w[135], w[8], pars->GC_2, amp[521]); FFV1_0(w[134], w[120], w[6], pars->GC_11, amp[522]); FFV1_0(w[24], w[120], w[68], pars->GC_11, amp[523]); FFV1_0(w[22], w[120], w[75], pars->GC_11, amp[524]); FFV1_0(w[28], w[135], w[6], pars->GC_11, amp[525]); FFV1_0(w[28], w[2], w[75], pars->GC_11, amp[526]); FFV2_5_0(w[24], w[135], w[17], pars->GC_51, pars->GC_58, amp[527]); FFV1_0(w[89], w[116], w[29], pars->GC_11, amp[528]); FFV1_0(w[136], w[116], w[4], pars->GC_11, amp[529]); FFV1_0(w[22], w[116], w[77], pars->GC_11, amp[530]); FFV1_0(w[26], w[129], w[4], pars->GC_11, amp[531]); FFV1_0(w[26], w[2], w[77], pars->GC_11, amp[532]); FFV1_0(w[89], w[129], w[8], pars->GC_2, amp[533]); FFV1_0(w[89], w[120], w[29], pars->GC_11, amp[534]); FFV1_0(w[136], w[120], w[4], pars->GC_11, amp[535]); FFV1_0(w[22], w[120], w[77], pars->GC_11, amp[536]); FFV1_0(w[28], w[129], w[4], pars->GC_11, amp[537]); FFV1_0(w[28], w[2], w[77], pars->GC_11, amp[538]); FFV2_5_0(w[89], w[129], w[17], pars->GC_51, pars->GC_58, amp[539]); FFV1_0(w[22], w[116], w[79], pars->GC_11, amp[540]); FFV1_0(w[22], w[116], w[80], pars->GC_11, amp[541]); FFV1_0(w[22], w[116], w[81], pars->GC_11, amp[542]); FFV1_0(w[26], w[2], w[79], pars->GC_11, amp[543]); FFV1_0(w[26], w[2], w[80], pars->GC_11, amp[544]); FFV1_0(w[26], w[2], w[81], pars->GC_11, amp[545]); FFV1_0(w[22], w[120], w[79], pars->GC_11, amp[546]); FFV1_0(w[22], w[120], w[80], pars->GC_11, amp[547]); FFV1_0(w[22], w[120], w[81], pars->GC_11, amp[548]); FFV1_0(w[28], w[2], w[79], pars->GC_11, amp[549]); FFV1_0(w[28], w[2], w[80], pars->GC_11, amp[550]); FFV1_0(w[28], w[2], w[81], pars->GC_11, amp[551]); FFV1_0(w[67], w[119], w[7], pars->GC_11, amp[552]); FFV1_0(w[67], w[118], w[5], pars->GC_11, amp[553]); FFV1_0(w[31], w[130], w[7], pars->GC_11, amp[554]); FFV1_0(w[31], w[118], w[4], pars->GC_11, amp[555]); FFV1_0(w[32], w[130], w[5], pars->GC_11, amp[556]); FFV1_0(w[32], w[119], w[4], pars->GC_11, amp[557]); FFV1_0(w[67], w[123], w[7], pars->GC_11, amp[558]); FFV1_0(w[67], w[122], w[5], pars->GC_11, amp[559]); FFV1_0(w[31], w[131], w[7], pars->GC_11, amp[560]); FFV1_0(w[31], w[122], w[4], pars->GC_11, amp[561]); FFV1_0(w[32], w[131], w[5], pars->GC_11, amp[562]); FFV1_0(w[32], w[123], w[4], pars->GC_11, amp[563]); FFV1_0(w[137], w[116], w[7], pars->GC_11, amp[564]); FFV1_0(w[32], w[116], w[90], pars->GC_11, amp[565]); FFV1_0(w[30], w[116], w[92], pars->GC_11, amp[566]); FFV1_0(w[33], w[138], w[7], pars->GC_11, amp[567]); FFV1_0(w[33], w[2], w[92], pars->GC_11, amp[568]); FFV1_0(w[32], w[138], w[8], pars->GC_2, amp[569]); FFV1_0(w[137], w[120], w[7], pars->GC_11, amp[570]); FFV1_0(w[32], w[120], w[90], pars->GC_11, amp[571]); FFV1_0(w[30], w[120], w[92], pars->GC_11, amp[572]); FFV1_0(w[34], w[138], w[7], pars->GC_11, amp[573]); FFV1_0(w[34], w[2], w[92], pars->GC_11, amp[574]); FFV2_5_0(w[32], w[138], w[17], pars->GC_51, pars->GC_58, amp[575]); FFV1_0(w[139], w[116], w[5], pars->GC_11, amp[576]); FFV1_0(w[31], w[116], w[68], pars->GC_11, amp[577]); FFV1_0(w[30], w[116], w[94], pars->GC_11, amp[578]); FFV1_0(w[33], w[135], w[5], pars->GC_11, amp[579]); FFV1_0(w[33], w[2], w[94], pars->GC_11, amp[580]); FFV1_0(w[31], w[135], w[8], pars->GC_2, amp[581]); FFV1_0(w[139], w[120], w[5], pars->GC_11, amp[582]); FFV1_0(w[31], w[120], w[68], pars->GC_11, amp[583]); FFV1_0(w[30], w[120], w[94], pars->GC_11, amp[584]); FFV1_0(w[34], w[135], w[5], pars->GC_11, amp[585]); FFV1_0(w[34], w[2], w[94], pars->GC_11, amp[586]); FFV2_5_0(w[31], w[135], w[17], pars->GC_51, pars->GC_58, amp[587]); FFV1_0(w[67], w[116], w[35], pars->GC_11, amp[588]); FFV1_0(w[140], w[116], w[4], pars->GC_11, amp[589]); FFV1_0(w[30], w[116], w[96], pars->GC_11, amp[590]); FFV1_0(w[33], w[127], w[4], pars->GC_11, amp[591]); FFV1_0(w[33], w[2], w[96], pars->GC_11, amp[592]); FFV1_0(w[67], w[127], w[8], pars->GC_2, amp[593]); FFV1_0(w[67], w[120], w[35], pars->GC_11, amp[594]); FFV1_0(w[140], w[120], w[4], pars->GC_11, amp[595]); FFV1_0(w[30], w[120], w[96], pars->GC_11, amp[596]); FFV1_0(w[34], w[127], w[4], pars->GC_11, amp[597]); FFV1_0(w[34], w[2], w[96], pars->GC_11, amp[598]); FFV2_5_0(w[67], w[127], w[17], pars->GC_51, pars->GC_58, amp[599]); FFV1_0(w[30], w[116], w[98], pars->GC_11, amp[600]); FFV1_0(w[30], w[116], w[99], pars->GC_11, amp[601]); FFV1_0(w[30], w[116], w[100], pars->GC_11, amp[602]); FFV1_0(w[33], w[2], w[98], pars->GC_11, amp[603]); FFV1_0(w[33], w[2], w[99], pars->GC_11, amp[604]); FFV1_0(w[33], w[2], w[100], pars->GC_11, amp[605]); FFV1_0(w[30], w[120], w[98], pars->GC_11, amp[606]); FFV1_0(w[30], w[120], w[99], pars->GC_11, amp[607]); FFV1_0(w[30], w[120], w[100], pars->GC_11, amp[608]); FFV1_0(w[34], w[2], w[98], pars->GC_11, amp[609]); FFV1_0(w[34], w[2], w[99], pars->GC_11, amp[610]); FFV1_0(w[34], w[2], w[100], pars->GC_11, amp[611]); FFV1_0(w[69], w[119], w[6], pars->GC_11, amp[612]); FFV1_0(w[69], w[117], w[5], pars->GC_11, amp[613]); FFV1_0(w[37], w[130], w[6], pars->GC_11, amp[614]); FFV1_0(w[37], w[117], w[4], pars->GC_11, amp[615]); FFV1_0(w[38], w[130], w[5], pars->GC_11, amp[616]); FFV1_0(w[38], w[119], w[4], pars->GC_11, amp[617]); FFV1_0(w[69], w[123], w[6], pars->GC_11, amp[618]); FFV1_0(w[69], w[121], w[5], pars->GC_11, amp[619]); FFV1_0(w[37], w[131], w[6], pars->GC_11, amp[620]); FFV1_0(w[37], w[121], w[4], pars->GC_11, amp[621]); FFV1_0(w[38], w[131], w[5], pars->GC_11, amp[622]); FFV1_0(w[38], w[123], w[4], pars->GC_11, amp[623]); FFV1_0(w[141], w[116], w[6], pars->GC_11, amp[624]); FFV1_0(w[38], w[116], w[90], pars->GC_11, amp[625]); FFV1_0(w[36], w[116], w[107], pars->GC_11, amp[626]); FFV1_0(w[39], w[138], w[6], pars->GC_11, amp[627]); FFV1_0(w[39], w[2], w[107], pars->GC_11, amp[628]); FFV1_0(w[38], w[138], w[8], pars->GC_2, amp[629]); FFV1_0(w[141], w[120], w[6], pars->GC_11, amp[630]); FFV1_0(w[38], w[120], w[90], pars->GC_11, amp[631]); FFV1_0(w[36], w[120], w[107], pars->GC_11, amp[632]); FFV1_0(w[40], w[138], w[6], pars->GC_11, amp[633]); FFV1_0(w[40], w[2], w[107], pars->GC_11, amp[634]); FFV2_5_0(w[38], w[138], w[17], pars->GC_51, pars->GC_58, amp[635]); FFV1_0(w[142], w[116], w[5], pars->GC_11, amp[636]); FFV1_0(w[37], w[116], w[70], pars->GC_11, amp[637]); FFV1_0(w[36], w[116], w[109], pars->GC_11, amp[638]); FFV1_0(w[39], w[133], w[5], pars->GC_11, amp[639]); FFV1_0(w[39], w[2], w[109], pars->GC_11, amp[640]); FFV1_0(w[37], w[133], w[8], pars->GC_2, amp[641]); FFV1_0(w[142], w[120], w[5], pars->GC_11, amp[642]); FFV1_0(w[37], w[120], w[70], pars->GC_11, amp[643]); FFV1_0(w[36], w[120], w[109], pars->GC_11, amp[644]); FFV1_0(w[40], w[133], w[5], pars->GC_11, amp[645]); FFV1_0(w[40], w[2], w[109], pars->GC_11, amp[646]); FFV2_5_0(w[37], w[133], w[17], pars->GC_51, pars->GC_58, amp[647]); FFV1_0(w[69], w[116], w[41], pars->GC_11, amp[648]); FFV1_0(w[143], w[116], w[4], pars->GC_11, amp[649]); FFV1_0(w[36], w[116], w[111], pars->GC_11, amp[650]); FFV1_0(w[39], w[125], w[4], pars->GC_11, amp[651]); FFV1_0(w[39], w[2], w[111], pars->GC_11, amp[652]); FFV1_0(w[69], w[125], w[8], pars->GC_2, amp[653]); FFV1_0(w[69], w[120], w[41], pars->GC_11, amp[654]); FFV1_0(w[143], w[120], w[4], pars->GC_11, amp[655]); FFV1_0(w[36], w[120], w[111], pars->GC_11, amp[656]); FFV1_0(w[40], w[125], w[4], pars->GC_11, amp[657]); FFV1_0(w[40], w[2], w[111], pars->GC_11, amp[658]); FFV2_5_0(w[69], w[125], w[17], pars->GC_51, pars->GC_58, amp[659]); FFV1_0(w[36], w[116], w[113], pars->GC_11, amp[660]); FFV1_0(w[36], w[116], w[114], pars->GC_11, amp[661]); FFV1_0(w[36], w[116], w[115], pars->GC_11, amp[662]); FFV1_0(w[39], w[2], w[113], pars->GC_11, amp[663]); FFV1_0(w[39], w[2], w[114], pars->GC_11, amp[664]); FFV1_0(w[39], w[2], w[115], pars->GC_11, amp[665]); FFV1_0(w[36], w[120], w[113], pars->GC_11, amp[666]); FFV1_0(w[36], w[120], w[114], pars->GC_11, amp[667]); FFV1_0(w[36], w[120], w[115], pars->GC_11, amp[668]); FFV1_0(w[40], w[2], w[113], pars->GC_11, amp[669]); FFV1_0(w[40], w[2], w[114], pars->GC_11, amp[670]); FFV1_0(w[40], w[2], w[115], pars->GC_11, amp[671]); FFV1_0(w[91], w[117], w[7], pars->GC_11, amp[672]); FFV1_0(w[91], w[118], w[6], pars->GC_11, amp[673]); VVV1_0(w[107], w[7], w[144], pars->GC_10, amp[674]); FFV1_0(w[3], w[118], w[107], pars->GC_11, amp[675]); VVV1_0(w[92], w[6], w[144], pars->GC_10, amp[676]); FFV1_0(w[3], w[117], w[92], pars->GC_11, amp[677]); FFV1_0(w[3], w[116], w[145], pars->GC_11, amp[678]); FFV1_0(w[3], w[116], w[146], pars->GC_11, amp[679]); FFV1_0(w[3], w[116], w[147], pars->GC_11, amp[680]); FFV1_0(w[12], w[138], w[7], pars->GC_11, amp[681]); FFV1_0(w[13], w[138], w[6], pars->GC_11, amp[682]); VVV1_0(w[107], w[7], w[148], pars->GC_10, amp[683]); FFV1_0(w[13], w[2], w[107], pars->GC_11, amp[684]); VVV1_0(w[92], w[6], w[148], pars->GC_10, amp[685]); FFV1_0(w[12], w[2], w[92], pars->GC_11, amp[686]); FFV1_0(w[10], w[2], w[145], pars->GC_11, amp[687]); FFV1_0(w[10], w[2], w[146], pars->GC_11, amp[688]); FFV1_0(w[10], w[2], w[147], pars->GC_11, amp[689]); FFV1_0(w[91], w[121], w[7], pars->GC_11, amp[690]); FFV1_0(w[91], w[122], w[6], pars->GC_11, amp[691]); VVV1_0(w[107], w[7], w[149], pars->GC_10, amp[692]); FFV1_0(w[3], w[122], w[107], pars->GC_11, amp[693]); VVV1_0(w[92], w[6], w[149], pars->GC_10, amp[694]); FFV1_0(w[3], w[121], w[92], pars->GC_11, amp[695]); FFV1_0(w[3], w[120], w[145], pars->GC_11, amp[696]); FFV1_0(w[3], w[120], w[146], pars->GC_11, amp[697]); FFV1_0(w[3], w[120], w[147], pars->GC_11, amp[698]); FFV1_0(w[19], w[138], w[7], pars->GC_11, amp[699]); FFV1_0(w[20], w[138], w[6], pars->GC_11, amp[700]); VVV1_0(w[107], w[7], w[150], pars->GC_10, amp[701]); FFV1_0(w[20], w[2], w[107], pars->GC_11, amp[702]); VVV1_0(w[92], w[6], w[150], pars->GC_10, amp[703]); FFV1_0(w[19], w[2], w[92], pars->GC_11, amp[704]); FFV1_0(w[18], w[2], w[145], pars->GC_11, amp[705]); FFV1_0(w[18], w[2], w[146], pars->GC_11, amp[706]); FFV1_0(w[18], w[2], w[147], pars->GC_11, amp[707]); FFV1_0(w[91], w[116], w[29], pars->GC_11, amp[708]); FFV1_0(w[48], w[116], w[90], pars->GC_11, amp[709]); FFV1_0(w[3], w[116], w[151], pars->GC_11, amp[710]); FFV1_0(w[10], w[138], w[29], pars->GC_11, amp[711]); FFV1_0(w[10], w[129], w[90], pars->GC_11, amp[712]); FFV1_0(w[10], w[2], w[151], pars->GC_11, amp[713]); FFV1_0(w[48], w[138], w[8], pars->GC_2, amp[714]); FFV1_0(w[91], w[129], w[8], pars->GC_2, amp[715]); FFV1_0(w[91], w[120], w[29], pars->GC_11, amp[716]); FFV1_0(w[48], w[120], w[90], pars->GC_11, amp[717]); FFV1_0(w[3], w[120], w[151], pars->GC_11, amp[718]); FFV1_0(w[18], w[138], w[29], pars->GC_11, amp[719]); FFV1_0(w[18], w[129], w[90], pars->GC_11, amp[720]); FFV1_0(w[18], w[2], w[151], pars->GC_11, amp[721]); FFV2_5_0(w[48], w[138], w[17], pars->GC_51, pars->GC_58, amp[722]); FFV2_5_0(w[91], w[129], w[17], pars->GC_51, pars->GC_58, amp[723]); FFV1_0(w[71], w[119], w[7], pars->GC_11, amp[724]); FFV1_0(w[71], w[118], w[5], pars->GC_11, amp[725]); VVV1_0(w[109], w[7], w[144], pars->GC_10, amp[726]); FFV1_0(w[3], w[118], w[109], pars->GC_11, amp[727]); VVV1_0(w[72], w[5], w[144], pars->GC_10, amp[728]); FFV1_0(w[3], w[119], w[72], pars->GC_11, amp[729]); FFV1_0(w[3], w[116], w[152], pars->GC_11, amp[730]); FFV1_0(w[3], w[116], w[153], pars->GC_11, amp[731]); FFV1_0(w[3], w[116], w[154], pars->GC_11, amp[732]); FFV1_0(w[15], w[133], w[7], pars->GC_11, amp[733]); FFV1_0(w[13], w[133], w[5], pars->GC_11, amp[734]); VVV1_0(w[109], w[7], w[148], pars->GC_10, amp[735]); FFV1_0(w[13], w[2], w[109], pars->GC_11, amp[736]); VVV1_0(w[72], w[5], w[148], pars->GC_10, amp[737]); FFV1_0(w[15], w[2], w[72], pars->GC_11, amp[738]); FFV1_0(w[10], w[2], w[152], pars->GC_11, amp[739]); FFV1_0(w[10], w[2], w[153], pars->GC_11, amp[740]); FFV1_0(w[10], w[2], w[154], pars->GC_11, amp[741]); FFV1_0(w[71], w[123], w[7], pars->GC_11, amp[742]); FFV1_0(w[71], w[122], w[5], pars->GC_11, amp[743]); VVV1_0(w[109], w[7], w[149], pars->GC_10, amp[744]); FFV1_0(w[3], w[122], w[109], pars->GC_11, amp[745]); VVV1_0(w[72], w[5], w[149], pars->GC_10, amp[746]); FFV1_0(w[3], w[123], w[72], pars->GC_11, amp[747]); FFV1_0(w[3], w[120], w[152], pars->GC_11, amp[748]); FFV1_0(w[3], w[120], w[153], pars->GC_11, amp[749]); FFV1_0(w[3], w[120], w[154], pars->GC_11, amp[750]); FFV1_0(w[21], w[133], w[7], pars->GC_11, amp[751]); FFV1_0(w[20], w[133], w[5], pars->GC_11, amp[752]); VVV1_0(w[109], w[7], w[150], pars->GC_10, amp[753]); FFV1_0(w[20], w[2], w[109], pars->GC_11, amp[754]); VVV1_0(w[72], w[5], w[150], pars->GC_10, amp[755]); FFV1_0(w[21], w[2], w[72], pars->GC_11, amp[756]); FFV1_0(w[18], w[2], w[152], pars->GC_11, amp[757]); FFV1_0(w[18], w[2], w[153], pars->GC_11, amp[758]); FFV1_0(w[18], w[2], w[154], pars->GC_11, amp[759]); FFV1_0(w[71], w[116], w[35], pars->GC_11, amp[760]); FFV1_0(w[45], w[116], w[70], pars->GC_11, amp[761]); FFV1_0(w[3], w[116], w[155], pars->GC_11, amp[762]); FFV1_0(w[10], w[133], w[35], pars->GC_11, amp[763]); FFV1_0(w[10], w[127], w[70], pars->GC_11, amp[764]); FFV1_0(w[10], w[2], w[155], pars->GC_11, amp[765]); FFV1_0(w[45], w[133], w[8], pars->GC_2, amp[766]); FFV1_0(w[71], w[127], w[8], pars->GC_2, amp[767]); FFV1_0(w[71], w[120], w[35], pars->GC_11, amp[768]); FFV1_0(w[45], w[120], w[70], pars->GC_11, amp[769]); FFV1_0(w[3], w[120], w[155], pars->GC_11, amp[770]); FFV1_0(w[18], w[133], w[35], pars->GC_11, amp[771]); FFV1_0(w[18], w[127], w[70], pars->GC_11, amp[772]); FFV1_0(w[18], w[2], w[155], pars->GC_11, amp[773]); FFV2_5_0(w[45], w[133], w[17], pars->GC_51, pars->GC_58, amp[774]); FFV2_5_0(w[71], w[127], w[17], pars->GC_51, pars->GC_58, amp[775]); FFV1_0(w[74], w[119], w[6], pars->GC_11, amp[776]); FFV1_0(w[74], w[117], w[5], pars->GC_11, amp[777]); VVV1_0(w[94], w[6], w[144], pars->GC_10, amp[778]); FFV1_0(w[3], w[117], w[94], pars->GC_11, amp[779]); VVV1_0(w[75], w[5], w[144], pars->GC_10, amp[780]); FFV1_0(w[3], w[119], w[75], pars->GC_11, amp[781]); FFV1_0(w[3], w[116], w[156], pars->GC_11, amp[782]); FFV1_0(w[3], w[116], w[157], pars->GC_11, amp[783]); FFV1_0(w[3], w[116], w[158], pars->GC_11, amp[784]); FFV1_0(w[15], w[135], w[6], pars->GC_11, amp[785]); FFV1_0(w[12], w[135], w[5], pars->GC_11, amp[786]); VVV1_0(w[94], w[6], w[148], pars->GC_10, amp[787]); FFV1_0(w[12], w[2], w[94], pars->GC_11, amp[788]); VVV1_0(w[75], w[5], w[148], pars->GC_10, amp[789]); FFV1_0(w[15], w[2], w[75], pars->GC_11, amp[790]); FFV1_0(w[10], w[2], w[156], pars->GC_11, amp[791]); FFV1_0(w[10], w[2], w[157], pars->GC_11, amp[792]); FFV1_0(w[10], w[2], w[158], pars->GC_11, amp[793]); FFV1_0(w[74], w[123], w[6], pars->GC_11, amp[794]); FFV1_0(w[74], w[121], w[5], pars->GC_11, amp[795]); VVV1_0(w[94], w[6], w[149], pars->GC_10, amp[796]); FFV1_0(w[3], w[121], w[94], pars->GC_11, amp[797]); VVV1_0(w[75], w[5], w[149], pars->GC_10, amp[798]); FFV1_0(w[3], w[123], w[75], pars->GC_11, amp[799]); FFV1_0(w[3], w[120], w[156], pars->GC_11, amp[800]); FFV1_0(w[3], w[120], w[157], pars->GC_11, amp[801]); FFV1_0(w[3], w[120], w[158], pars->GC_11, amp[802]); FFV1_0(w[21], w[135], w[6], pars->GC_11, amp[803]); FFV1_0(w[19], w[135], w[5], pars->GC_11, amp[804]); VVV1_0(w[94], w[6], w[150], pars->GC_10, amp[805]); FFV1_0(w[19], w[2], w[94], pars->GC_11, amp[806]); VVV1_0(w[75], w[5], w[150], pars->GC_10, amp[807]); FFV1_0(w[21], w[2], w[75], pars->GC_11, amp[808]); FFV1_0(w[18], w[2], w[156], pars->GC_11, amp[809]); FFV1_0(w[18], w[2], w[157], pars->GC_11, amp[810]); FFV1_0(w[18], w[2], w[158], pars->GC_11, amp[811]); FFV1_0(w[74], w[116], w[41], pars->GC_11, amp[812]); FFV1_0(w[42], w[116], w[68], pars->GC_11, amp[813]); FFV1_0(w[3], w[116], w[159], pars->GC_11, amp[814]); FFV1_0(w[10], w[135], w[41], pars->GC_11, amp[815]); FFV1_0(w[10], w[125], w[68], pars->GC_11, amp[816]); FFV1_0(w[10], w[2], w[159], pars->GC_11, amp[817]); FFV1_0(w[42], w[135], w[8], pars->GC_2, amp[818]); FFV1_0(w[74], w[125], w[8], pars->GC_2, amp[819]); FFV1_0(w[74], w[120], w[41], pars->GC_11, amp[820]); FFV1_0(w[42], w[120], w[68], pars->GC_11, amp[821]); FFV1_0(w[3], w[120], w[159], pars->GC_11, amp[822]); FFV1_0(w[18], w[135], w[41], pars->GC_11, amp[823]); FFV1_0(w[18], w[125], w[68], pars->GC_11, amp[824]); FFV1_0(w[18], w[2], w[159], pars->GC_11, amp[825]); FFV2_5_0(w[42], w[135], w[17], pars->GC_51, pars->GC_58, amp[826]); FFV2_5_0(w[74], w[125], w[17], pars->GC_51, pars->GC_58, amp[827]); FFV1_0(w[42], w[130], w[7], pars->GC_11, amp[828]); FFV1_0(w[42], w[118], w[4], pars->GC_11, amp[829]); VVV1_0(w[111], w[7], w[144], pars->GC_10, amp[830]); FFV1_0(w[3], w[118], w[111], pars->GC_11, amp[831]); VVV1_0(w[4], w[43], w[144], pars->GC_10, amp[832]); FFV1_0(w[3], w[130], w[43], pars->GC_11, amp[833]); FFV1_0(w[3], w[116], w[160], pars->GC_11, amp[834]); FFV1_0(w[3], w[116], w[161], pars->GC_11, amp[835]); FFV1_0(w[3], w[116], w[162], pars->GC_11, amp[836]); FFV1_0(w[57], w[125], w[7], pars->GC_11, amp[837]); FFV1_0(w[13], w[125], w[4], pars->GC_11, amp[838]); VVV1_0(w[111], w[7], w[148], pars->GC_10, amp[839]); FFV1_0(w[13], w[2], w[111], pars->GC_11, amp[840]); VVV1_0(w[4], w[43], w[148], pars->GC_10, amp[841]); FFV1_0(w[57], w[2], w[43], pars->GC_11, amp[842]); FFV1_0(w[10], w[2], w[160], pars->GC_11, amp[843]); FFV1_0(w[10], w[2], w[161], pars->GC_11, amp[844]); FFV1_0(w[10], w[2], w[162], pars->GC_11, amp[845]); FFV1_0(w[42], w[131], w[7], pars->GC_11, amp[846]); FFV1_0(w[42], w[122], w[4], pars->GC_11, amp[847]); VVV1_0(w[111], w[7], w[149], pars->GC_10, amp[848]); FFV1_0(w[3], w[122], w[111], pars->GC_11, amp[849]); VVV1_0(w[4], w[43], w[149], pars->GC_10, amp[850]); FFV1_0(w[3], w[131], w[43], pars->GC_11, amp[851]); FFV1_0(w[3], w[120], w[160], pars->GC_11, amp[852]); FFV1_0(w[3], w[120], w[161], pars->GC_11, amp[853]); FFV1_0(w[3], w[120], w[162], pars->GC_11, amp[854]); FFV1_0(w[59], w[125], w[7], pars->GC_11, amp[855]); FFV1_0(w[20], w[125], w[4], pars->GC_11, amp[856]); VVV1_0(w[111], w[7], w[150], pars->GC_10, amp[857]); FFV1_0(w[20], w[2], w[111], pars->GC_11, amp[858]); VVV1_0(w[4], w[43], w[150], pars->GC_10, amp[859]); FFV1_0(w[59], w[2], w[43], pars->GC_11, amp[860]); FFV1_0(w[18], w[2], w[160], pars->GC_11, amp[861]); FFV1_0(w[18], w[2], w[161], pars->GC_11, amp[862]); FFV1_0(w[18], w[2], w[162], pars->GC_11, amp[863]); FFV1_0(w[45], w[130], w[6], pars->GC_11, amp[864]); FFV1_0(w[45], w[117], w[4], pars->GC_11, amp[865]); VVV1_0(w[96], w[6], w[144], pars->GC_10, amp[866]); FFV1_0(w[3], w[117], w[96], pars->GC_11, amp[867]); VVV1_0(w[4], w[46], w[144], pars->GC_10, amp[868]); FFV1_0(w[3], w[130], w[46], pars->GC_11, amp[869]); FFV1_0(w[3], w[116], w[163], pars->GC_11, amp[870]); FFV1_0(w[3], w[116], w[164], pars->GC_11, amp[871]); FFV1_0(w[3], w[116], w[165], pars->GC_11, amp[872]); FFV1_0(w[57], w[127], w[6], pars->GC_11, amp[873]); FFV1_0(w[12], w[127], w[4], pars->GC_11, amp[874]); VVV1_0(w[96], w[6], w[148], pars->GC_10, amp[875]); FFV1_0(w[12], w[2], w[96], pars->GC_11, amp[876]); VVV1_0(w[4], w[46], w[148], pars->GC_10, amp[877]); FFV1_0(w[57], w[2], w[46], pars->GC_11, amp[878]); FFV1_0(w[10], w[2], w[163], pars->GC_11, amp[879]); FFV1_0(w[10], w[2], w[164], pars->GC_11, amp[880]); FFV1_0(w[10], w[2], w[165], pars->GC_11, amp[881]); FFV1_0(w[45], w[131], w[6], pars->GC_11, amp[882]); FFV1_0(w[45], w[121], w[4], pars->GC_11, amp[883]); VVV1_0(w[96], w[6], w[149], pars->GC_10, amp[884]); FFV1_0(w[3], w[121], w[96], pars->GC_11, amp[885]); VVV1_0(w[4], w[46], w[149], pars->GC_10, amp[886]); FFV1_0(w[3], w[131], w[46], pars->GC_11, amp[887]); FFV1_0(w[3], w[120], w[163], pars->GC_11, amp[888]); FFV1_0(w[3], w[120], w[164], pars->GC_11, amp[889]); FFV1_0(w[3], w[120], w[165], pars->GC_11, amp[890]); FFV1_0(w[59], w[127], w[6], pars->GC_11, amp[891]); FFV1_0(w[19], w[127], w[4], pars->GC_11, amp[892]); VVV1_0(w[96], w[6], w[150], pars->GC_10, amp[893]); FFV1_0(w[19], w[2], w[96], pars->GC_11, amp[894]); VVV1_0(w[4], w[46], w[150], pars->GC_10, amp[895]); FFV1_0(w[59], w[2], w[46], pars->GC_11, amp[896]); FFV1_0(w[18], w[2], w[163], pars->GC_11, amp[897]); FFV1_0(w[18], w[2], w[164], pars->GC_11, amp[898]); FFV1_0(w[18], w[2], w[165], pars->GC_11, amp[899]); FFV1_0(w[48], w[130], w[5], pars->GC_11, amp[900]); FFV1_0(w[48], w[119], w[4], pars->GC_11, amp[901]); VVV1_0(w[77], w[5], w[144], pars->GC_10, amp[902]); FFV1_0(w[3], w[119], w[77], pars->GC_11, amp[903]); VVV1_0(w[4], w[49], w[144], pars->GC_10, amp[904]); FFV1_0(w[3], w[130], w[49], pars->GC_11, amp[905]); FFV1_0(w[3], w[116], w[166], pars->GC_11, amp[906]); FFV1_0(w[3], w[116], w[167], pars->GC_11, amp[907]); FFV1_0(w[3], w[116], w[168], pars->GC_11, amp[908]); FFV1_0(w[57], w[129], w[5], pars->GC_11, amp[909]); FFV1_0(w[15], w[129], w[4], pars->GC_11, amp[910]); VVV1_0(w[77], w[5], w[148], pars->GC_10, amp[911]); FFV1_0(w[15], w[2], w[77], pars->GC_11, amp[912]); VVV1_0(w[4], w[49], w[148], pars->GC_10, amp[913]); FFV1_0(w[57], w[2], w[49], pars->GC_11, amp[914]); FFV1_0(w[10], w[2], w[166], pars->GC_11, amp[915]); FFV1_0(w[10], w[2], w[167], pars->GC_11, amp[916]); FFV1_0(w[10], w[2], w[168], pars->GC_11, amp[917]); FFV1_0(w[48], w[131], w[5], pars->GC_11, amp[918]); FFV1_0(w[48], w[123], w[4], pars->GC_11, amp[919]); VVV1_0(w[77], w[5], w[149], pars->GC_10, amp[920]); FFV1_0(w[3], w[123], w[77], pars->GC_11, amp[921]); VVV1_0(w[4], w[49], w[149], pars->GC_10, amp[922]); FFV1_0(w[3], w[131], w[49], pars->GC_11, amp[923]); FFV1_0(w[3], w[120], w[166], pars->GC_11, amp[924]); FFV1_0(w[3], w[120], w[167], pars->GC_11, amp[925]); FFV1_0(w[3], w[120], w[168], pars->GC_11, amp[926]); FFV1_0(w[59], w[129], w[5], pars->GC_11, amp[927]); FFV1_0(w[21], w[129], w[4], pars->GC_11, amp[928]); VVV1_0(w[77], w[5], w[150], pars->GC_10, amp[929]); FFV1_0(w[21], w[2], w[77], pars->GC_11, amp[930]); VVV1_0(w[4], w[49], w[150], pars->GC_10, amp[931]); FFV1_0(w[59], w[2], w[49], pars->GC_11, amp[932]); FFV1_0(w[18], w[2], w[166], pars->GC_11, amp[933]); FFV1_0(w[18], w[2], w[167], pars->GC_11, amp[934]); FFV1_0(w[18], w[2], w[168], pars->GC_11, amp[935]); FFV1_0(w[169], w[116], w[7], pars->GC_11, amp[936]); FFV1_0(w[170], w[116], w[7], pars->GC_11, amp[937]); FFV1_0(w[171], w[116], w[7], pars->GC_11, amp[938]); FFV1_0(w[3], w[116], w[172], pars->GC_11, amp[939]); FFV1_0(w[3], w[116], w[173], pars->GC_11, amp[940]); FFV1_0(w[3], w[116], w[174], pars->GC_11, amp[941]); FFV1_0(w[10], w[175], w[7], pars->GC_11, amp[942]); FFV1_0(w[10], w[176], w[7], pars->GC_11, amp[943]); FFV1_0(w[10], w[177], w[7], pars->GC_11, amp[944]); FFV1_0(w[10], w[2], w[172], pars->GC_11, amp[945]); FFV1_0(w[10], w[2], w[173], pars->GC_11, amp[946]); FFV1_0(w[10], w[2], w[174], pars->GC_11, amp[947]); FFV1_0(w[169], w[120], w[7], pars->GC_11, amp[948]); FFV1_0(w[170], w[120], w[7], pars->GC_11, amp[949]); FFV1_0(w[171], w[120], w[7], pars->GC_11, amp[950]); FFV1_0(w[3], w[120], w[172], pars->GC_11, amp[951]); FFV1_0(w[3], w[120], w[173], pars->GC_11, amp[952]); FFV1_0(w[3], w[120], w[174], pars->GC_11, amp[953]); FFV1_0(w[18], w[175], w[7], pars->GC_11, amp[954]); FFV1_0(w[18], w[176], w[7], pars->GC_11, amp[955]); FFV1_0(w[18], w[177], w[7], pars->GC_11, amp[956]); FFV1_0(w[18], w[2], w[172], pars->GC_11, amp[957]); FFV1_0(w[18], w[2], w[173], pars->GC_11, amp[958]); FFV1_0(w[18], w[2], w[174], pars->GC_11, amp[959]); FFV1_0(w[178], w[116], w[6], pars->GC_11, amp[960]); FFV1_0(w[179], w[116], w[6], pars->GC_11, amp[961]); FFV1_0(w[180], w[116], w[6], pars->GC_11, amp[962]); FFV1_0(w[3], w[116], w[181], pars->GC_11, amp[963]); FFV1_0(w[3], w[116], w[182], pars->GC_11, amp[964]); FFV1_0(w[3], w[116], w[183], pars->GC_11, amp[965]); FFV1_0(w[10], w[184], w[6], pars->GC_11, amp[966]); FFV1_0(w[10], w[185], w[6], pars->GC_11, amp[967]); FFV1_0(w[10], w[186], w[6], pars->GC_11, amp[968]); FFV1_0(w[10], w[2], w[181], pars->GC_11, amp[969]); FFV1_0(w[10], w[2], w[182], pars->GC_11, amp[970]); FFV1_0(w[10], w[2], w[183], pars->GC_11, amp[971]); FFV1_0(w[178], w[120], w[6], pars->GC_11, amp[972]); FFV1_0(w[179], w[120], w[6], pars->GC_11, amp[973]); FFV1_0(w[180], w[120], w[6], pars->GC_11, amp[974]); FFV1_0(w[3], w[120], w[181], pars->GC_11, amp[975]); FFV1_0(w[3], w[120], w[182], pars->GC_11, amp[976]); FFV1_0(w[3], w[120], w[183], pars->GC_11, amp[977]); FFV1_0(w[18], w[184], w[6], pars->GC_11, amp[978]); FFV1_0(w[18], w[185], w[6], pars->GC_11, amp[979]); FFV1_0(w[18], w[186], w[6], pars->GC_11, amp[980]); FFV1_0(w[18], w[2], w[181], pars->GC_11, amp[981]); FFV1_0(w[18], w[2], w[182], pars->GC_11, amp[982]); FFV1_0(w[18], w[2], w[183], pars->GC_11, amp[983]); FFV1_0(w[187], w[116], w[5], pars->GC_11, amp[984]); FFV1_0(w[188], w[116], w[5], pars->GC_11, amp[985]); FFV1_0(w[189], w[116], w[5], pars->GC_11, amp[986]); FFV1_0(w[3], w[116], w[190], pars->GC_11, amp[987]); FFV1_0(w[3], w[116], w[191], pars->GC_11, amp[988]); FFV1_0(w[3], w[116], w[192], pars->GC_11, amp[989]); FFV1_0(w[10], w[193], w[5], pars->GC_11, amp[990]); FFV1_0(w[10], w[194], w[5], pars->GC_11, amp[991]); FFV1_0(w[10], w[195], w[5], pars->GC_11, amp[992]); FFV1_0(w[10], w[2], w[190], pars->GC_11, amp[993]); FFV1_0(w[10], w[2], w[191], pars->GC_11, amp[994]); FFV1_0(w[10], w[2], w[192], pars->GC_11, amp[995]); FFV1_0(w[187], w[120], w[5], pars->GC_11, amp[996]); FFV1_0(w[188], w[120], w[5], pars->GC_11, amp[997]); FFV1_0(w[189], w[120], w[5], pars->GC_11, amp[998]); FFV1_0(w[3], w[120], w[190], pars->GC_11, amp[999]); FFV1_0(w[3], w[120], w[191], pars->GC_11, amp[1000]); FFV1_0(w[3], w[120], w[192], pars->GC_11, amp[1001]); FFV1_0(w[18], w[193], w[5], pars->GC_11, amp[1002]); FFV1_0(w[18], w[194], w[5], pars->GC_11, amp[1003]); FFV1_0(w[18], w[195], w[5], pars->GC_11, amp[1004]); FFV1_0(w[18], w[2], w[190], pars->GC_11, amp[1005]); FFV1_0(w[18], w[2], w[191], pars->GC_11, amp[1006]); FFV1_0(w[18], w[2], w[192], pars->GC_11, amp[1007]); FFV1_0(w[196], w[116], w[4], pars->GC_11, amp[1008]); FFV1_0(w[197], w[116], w[4], pars->GC_11, amp[1009]); FFV1_0(w[198], w[116], w[4], pars->GC_11, amp[1010]); FFV1_0(w[3], w[116], w[199], pars->GC_11, amp[1011]); FFV1_0(w[3], w[116], w[200], pars->GC_11, amp[1012]); FFV1_0(w[3], w[116], w[201], pars->GC_11, amp[1013]); FFV1_0(w[10], w[202], w[4], pars->GC_11, amp[1014]); FFV1_0(w[10], w[203], w[4], pars->GC_11, amp[1015]); FFV1_0(w[10], w[204], w[4], pars->GC_11, amp[1016]); FFV1_0(w[10], w[2], w[199], pars->GC_11, amp[1017]); FFV1_0(w[10], w[2], w[200], pars->GC_11, amp[1018]); FFV1_0(w[10], w[2], w[201], pars->GC_11, amp[1019]); FFV1_0(w[196], w[120], w[4], pars->GC_11, amp[1020]); FFV1_0(w[197], w[120], w[4], pars->GC_11, amp[1021]); FFV1_0(w[198], w[120], w[4], pars->GC_11, amp[1022]); FFV1_0(w[3], w[120], w[199], pars->GC_11, amp[1023]); FFV1_0(w[3], w[120], w[200], pars->GC_11, amp[1024]); FFV1_0(w[3], w[120], w[201], pars->GC_11, amp[1025]); FFV1_0(w[18], w[202], w[4], pars->GC_11, amp[1026]); FFV1_0(w[18], w[203], w[4], pars->GC_11, amp[1027]); FFV1_0(w[18], w[204], w[4], pars->GC_11, amp[1028]); FFV1_0(w[18], w[2], w[199], pars->GC_11, amp[1029]); FFV1_0(w[18], w[2], w[200], pars->GC_11, amp[1030]); FFV1_0(w[18], w[2], w[201], pars->GC_11, amp[1031]); } double eeuugggg::matrix_1_epem_uuxgggg() { // int i, j; // Local variables // const int ngraphs = 1032; const int ncolor = 24; - std::complex ztemp; std::complex jamp[ncolor]; // The color matrix; //static const double denom[ncolor] = {54, 54, 54, 54, 54, 54, 54, 54, 54, 54, // 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54}; /*static const double cf[ncolor][ncolor] = {{512, -64, -64, 8, 8, 80, -64, 8, 8, -1, -1, -10, 8, -1, 80, -10, 71, 62, -1, -10, -10, 62, 62, -28}, {-64, 512, 8, 80, -64, 8, 8, -64, -1, -10, 8, -1, -1, -10, -10, 62, 62, -28, 8, -1, 80, -10, 71, 62}, {-64, 8, 512, -64, 80, 8, 8, -1, 80, -10, 71, 62, -64, 8, 8, -1, -1, -10, -10, -1, 62, -28, -10, 62}, {8, 80, -64, 512, 8, -64, -1, -10, -10, 62, 62, -28, 8, -64, -1, -10, 8, -1, -1, 8, 71, 62, 80, -10}, {8, -64, 80, 8, 512, -64, -1, 8, 71, 62, 80, -10, -10, -1, 62, -28, -10, 62, -64, 8, 8, -1, -1, -10}, {80, 8, 8, -64, -64, 512, -10, -1, 62, -28, -10, 62, -1, 8, 71, 62, 80, -10, 8, -64, -1, -10, 8, -1}, {-64, 8, 8, -1, -1, -10, 512, -64, -64, 8, 8, 80, 80, -10, 8, -1, 62, 71, -10, 62, -1, -10, -28, 62}, {8, -64, -1, -10, 8, -1, -64, 512, 8, 80, -64, 8, -10, 62, -1, -10, -28, 62, 80, -10, 8, -1, 62, 71}, {8, -1, 80, -10, 71, 62, -64, 8, 512, -64, 80, 8, 8, -1, -64, 8, -10, -1, 62, -28, -10, -1, 62, -10}, {-1, -10, -10, 62, 62, -28, 8, 80, -64, 512, 8, -64, -1, -10, 8, -64, -1, 8, 71, 62, -1, 8, -10, 80}, {-1, 8, 71, 62, 80, -10, 8, -64, 80, 8, 512, -64, 62, -28, -10, -1, 62, -10, 8, -1, -64, 8, -10, -1}, {-10, -1, 62, -28, -10, 62, 80, 8, 8, -64, -64, 512, 71, 62, -1, 8, -10, 80, -1, -10, 8, -64, -1, 8}, {8, -1, -64, 8, -10, -1, 80, -10, 8, -1, 62, 71, 512, -64, -64, 8, 8, 80, 62, -10, -28, 62, -1, -10}, {-1, -10, 8, -64, -1, 8, -10, 62, -1, -10, -28, 62, -64, 512, 8, 80, -64, 8, -10, 80, 62, 71, 8, -1}, {80, -10, 8, -1, 62, 71, 8, -1, -64, 8, -10, -1, -64, 8, 512, -64, 80, 8, -28, 62, 62, -10, -10, -1}, {-10, 62, -1, -10, -28, 62, -1, -10, 8, -64, -1, 8, 8, 80, -64, 512, 8, -64, 62, 71, -10, 80, -1, 8}, {71, 62, -1, 8, -10, 80, 62, -28, -10, -1, 62, -10, 8, -64, 80, 8, 512, -64, -1, 8, -10, -1, -64, 8}, {62, -28, -10, -1, 62, -10, 71, 62, -1, 8, -10, 80, 80, 8, 8, -64, -64, 512, -10, -1, -1, 8, 8, -64}, {-1, 8, -10, -1, -64, 8, -10, 80, 62, 71, 8, -1, 62, -10, -28, 62, -1, -10, 512, -64, -64, 8, 8, 80}, {-10, -1, -1, 8, 8, -64, 62, -10, -28, 62, -1, -10, -10, 80, 62, 71, 8, -1, -64, 512, 8, 80, -64, 8}, {-10, 80, 62, 71, 8, -1, -1, 8, -10, -1, -64, 8, -28, 62, 62, -10, -10, -1, -64, 8, 512, -64, 80, 8}, {62, -10, -28, 62, -1, -10, -10, -1, -1, 8, 8, -64, 62, 71, -10, 80, -1, 8, 8, 80, -64, 512, 8, -64}, {62, 71, -10, 80, -1, 8, -28, 62, 62, -10, -10, -1, -1, 8, -10, -1, -64, 8, 8, -64, 80, 8, 512, -64}, {-28, 62, 62, -10, -10, -1, 62, 71, -10, 80, -1, 8, -10, -1, -1, 8, 8, -64, 80, 8, 8, -64, -64, 512}}; */ // Calculate color flows jamp[0] = +amp[1] + amp[7] + amp[45] + amp[46] + amp[48] + amp[51] + amp[52] + amp[54] - std::complex (0, 1) * amp[56] - std::complex (0, 1) * amp[57] - std::complex (0, 1) * amp[58] - std::complex (0, 1) * amp[59] - amp[61] - std::complex (0, 1) * amp[62] - amp[64] - amp[67] - std::complex (0, 1) * amp[68] - amp[70] - std::complex (0, 1) * amp[84] - amp[85] - std::complex (0, 1) * amp[86] - amp[88] - std::complex (0, 1) * amp[89] - std::complex (0, 1) * amp[90] - amp[91] - std::complex (0, 1) * amp[92] - amp[94] - std::complex (0, 1) * amp[95] + amp[98] - amp[96] + amp[101] - amp[99] + amp[104] - amp[102] + amp[107] - amp[105] + amp[616] + amp[622] - std::complex (0, 1) * amp[625] - amp[626] - std::complex (0, 1) * amp[627] - amp[628] - std::complex (0, 1) * amp[629] - std::complex (0, 1) * amp[631] - amp[632] - std::complex (0, 1) * amp[633] - amp[634] - std::complex (0, 1) * amp[635] - std::complex (0, 1) * amp[649] - amp[650] - amp[652] - std::complex (0, 1) * amp[655] - amp[656] - amp[658] + amp[662] - amp[660] + amp[665] - amp[663] + amp[668] - amp[666] + amp[671] - amp[669] + std::complex (0, 1) * amp[674] - std::complex (0, 1) * amp[680] + std::complex (0, 1) * amp[678] - std::complex (0, 1) * amp[682] + std::complex (0, 1) * amp[683] - amp[684] - std::complex (0, 1) * amp[689] + std::complex (0, 1) * amp[687] + std::complex (0, 1) * amp[692] - std::complex (0, 1) * amp[698] + std::complex (0, 1) * amp[696] - std::complex (0, 1) * amp[700] + std::complex (0, 1) * amp[701] - amp[702] - std::complex (0, 1) * amp[707] + std::complex (0, 1) * amp[705] - amp[709] + std::complex (0, 1) * amp[710] - amp[711] + std::complex (0, 1) * amp[713] - amp[714] - amp[717] + std::complex (0, 1) * amp[718] - amp[719] + std::complex (0, 1) * amp[721] - amp[722] + std::complex (0, 1) * amp[830] + std::complex (0, 1) * amp[832] - amp[833] - std::complex (0, 1) * amp[836] + std::complex (0, 1) * amp[834] + std::complex (0, 1) * amp[839] - amp[840] + std::complex (0, 1) * amp[841] - std::complex (0, 1) * amp[845] + std::complex (0, 1) * amp[843] + std::complex (0, 1) * amp[848] + std::complex (0, 1) * amp[850] - amp[851] - std::complex (0, 1) * amp[854] + std::complex (0, 1) * amp[852] + std::complex (0, 1) * amp[857] - amp[858] + std::complex (0, 1) * amp[859] - std::complex (0, 1) * amp[863] + std::complex (0, 1) * amp[861] - std::complex (0, 1) * amp[900] + std::complex (0, 1) * amp[904] - amp[905] - std::complex (0, 1) * amp[908] + std::complex (0, 1) * amp[906] + std::complex (0, 1) * amp[913] - std::complex (0, 1) * amp[917] + std::complex (0, 1) * amp[915] - std::complex (0, 1) * amp[918] + std::complex (0, 1) * amp[922] - amp[923] - std::complex (0, 1) * amp[926] + std::complex (0, 1) * amp[924] + std::complex (0, 1) * amp[931] - std::complex (0, 1) * amp[935] + std::complex (0, 1) * amp[933] - std::complex (0, 1) * amp[941] + std::complex (0, 1) * amp[939] + amp[944] - amp[942] - std::complex (0, 1) * amp[947] + std::complex (0, 1) * amp[945] - std::complex (0, 1) * amp[953] + std::complex (0, 1) * amp[951] + amp[956] - amp[954] - std::complex (0, 1) * amp[959] + std::complex (0, 1) * amp[957] + amp[1010] - amp[1008] - std::complex (0, 1) * amp[1013] + std::complex (0, 1) * amp[1011] - std::complex (0, 1) * amp[1019] + std::complex (0, 1) * amp[1017] + amp[1022] - amp[1020] - std::complex (0, 1) * amp[1025] + std::complex (0, 1) * amp[1023] - std::complex (0, 1) * amp[1031] + std::complex (0, 1) * amp[1029]; jamp[1] = +amp[0] + amp[6] + amp[29] + amp[30] + amp[32] + amp[35] + amp[36] + amp[38] - std::complex (0, 1) * amp[40] - std::complex (0, 1) * amp[41] - std::complex (0, 1) * amp[42] - std::complex (0, 1) * amp[43] - amp[73] - std::complex (0, 1) * amp[74] - amp[76] - amp[79] - std::complex (0, 1) * amp[80] - amp[82] + std::complex (0, 1) * amp[84] + amp[85] + std::complex (0, 1) * amp[86] + amp[88] + std::complex (0, 1) * amp[89] + std::complex (0, 1) * amp[90] + amp[91] + std::complex (0, 1) * amp[92] + amp[94] + std::complex (0, 1) * amp[95] + amp[96] + amp[97] + amp[99] + amp[100] + amp[102] + amp[103] + amp[105] + amp[106] + amp[556] + amp[562] - std::complex (0, 1) * amp[565] - amp[566] - std::complex (0, 1) * amp[567] - amp[568] - std::complex (0, 1) * amp[569] - std::complex (0, 1) * amp[571] - amp[572] - std::complex (0, 1) * amp[573] - amp[574] - std::complex (0, 1) * amp[575] - std::complex (0, 1) * amp[589] - amp[590] - amp[592] - std::complex (0, 1) * amp[595] - amp[596] - amp[598] + amp[602] - amp[600] + amp[605] - amp[603] + amp[608] - amp[606] + amp[611] - amp[609] + std::complex (0, 1) * amp[676] - std::complex (0, 1) * amp[678] - std::complex (0, 1) * amp[679] - std::complex (0, 1) * amp[681] + std::complex (0, 1) * amp[685] - amp[686] - std::complex (0, 1) * amp[687] - std::complex (0, 1) * amp[688] + std::complex (0, 1) * amp[694] - std::complex (0, 1) * amp[696] - std::complex (0, 1) * amp[697] - std::complex (0, 1) * amp[699] + std::complex (0, 1) * amp[703] - amp[704] - std::complex (0, 1) * amp[705] - std::complex (0, 1) * amp[706] + amp[709] - std::complex (0, 1) * amp[710] + amp[711] - std::complex (0, 1) * amp[713] + amp[714] + amp[717] - std::complex (0, 1) * amp[718] + amp[719] - std::complex (0, 1) * amp[721] + amp[722] + std::complex (0, 1) * amp[866] + std::complex (0, 1) * amp[868] - amp[869] - std::complex (0, 1) * amp[872] + std::complex (0, 1) * amp[870] + std::complex (0, 1) * amp[875] - amp[876] + std::complex (0, 1) * amp[877] - std::complex (0, 1) * amp[881] + std::complex (0, 1) * amp[879] + std::complex (0, 1) * amp[884] + std::complex (0, 1) * amp[886] - amp[887] - std::complex (0, 1) * amp[890] + std::complex (0, 1) * amp[888] + std::complex (0, 1) * amp[893] - amp[894] + std::complex (0, 1) * amp[895] - std::complex (0, 1) * amp[899] + std::complex (0, 1) * amp[897] + std::complex (0, 1) * amp[900] - std::complex (0, 1) * amp[904] + amp[905] + std::complex (0, 1) * amp[908] - std::complex (0, 1) * amp[906] - std::complex (0, 1) * amp[913] + std::complex (0, 1) * amp[917] - std::complex (0, 1) * amp[915] + std::complex (0, 1) * amp[918] - std::complex (0, 1) * amp[922] + amp[923] + std::complex (0, 1) * amp[926] - std::complex (0, 1) * amp[924] - std::complex (0, 1) * amp[931] + std::complex (0, 1) * amp[935] - std::complex (0, 1) * amp[933] - std::complex (0, 1) * amp[965] + std::complex (0, 1) * amp[963] + amp[968] - amp[966] - std::complex (0, 1) * amp[971] + std::complex (0, 1) * amp[969] - std::complex (0, 1) * amp[977] + std::complex (0, 1) * amp[975] + amp[980] - amp[978] - std::complex (0, 1) * amp[983] + std::complex (0, 1) * amp[981] + amp[1008] + amp[1009] - std::complex (0, 1) * amp[1011] - std::complex (0, 1) * amp[1012] - std::complex (0, 1) * amp[1017] - std::complex (0, 1) * amp[1018] + amp[1020] + amp[1021] - std::complex (0, 1) * amp[1023] - std::complex (0, 1) * amp[1024] - std::complex (0, 1) * amp[1029] - std::complex (0, 1) * amp[1030]; jamp[2] = +amp[3] + amp[9] + amp[44] + amp[47] + amp[49] + amp[50] + amp[53] + amp[55] + std::complex (0, 1) * amp[56] + std::complex (0, 1) * amp[57] + std::complex (0, 1) * amp[58] + std::complex (0, 1) * amp[59] + amp[61] + std::complex (0, 1) * amp[62] + amp[64] + amp[67] + std::complex (0, 1) * amp[68] + amp[70] - std::complex (0, 1) * amp[72] + amp[73] - std::complex (0, 1) * amp[75] + amp[76] - std::complex (0, 1) * amp[77] - std::complex (0, 1) * amp[78] + amp[79] - std::complex (0, 1) * amp[81] + amp[82] - std::complex (0, 1) * amp[83] - amp[98] - amp[97] - amp[101] - amp[100] - amp[104] - amp[103] - amp[107] - amp[106] + amp[614] + amp[620] - std::complex (0, 1) * amp[637] - amp[638] - std::complex (0, 1) * amp[639] - amp[640] - std::complex (0, 1) * amp[641] - std::complex (0, 1) * amp[643] - amp[644] - std::complex (0, 1) * amp[645] - amp[646] - std::complex (0, 1) * amp[647] + std::complex (0, 1) * amp[649] + amp[650] + amp[652] + std::complex (0, 1) * amp[655] + amp[656] + amp[658] + amp[660] + amp[661] + amp[663] + amp[664] + amp[666] + amp[667] + amp[669] + amp[670] + std::complex (0, 1) * amp[726] - std::complex (0, 1) * amp[732] + std::complex (0, 1) * amp[730] - std::complex (0, 1) * amp[734] + std::complex (0, 1) * amp[735] - amp[736] - std::complex (0, 1) * amp[741] + std::complex (0, 1) * amp[739] + std::complex (0, 1) * amp[744] - std::complex (0, 1) * amp[750] + std::complex (0, 1) * amp[748] - std::complex (0, 1) * amp[752] + std::complex (0, 1) * amp[753] - amp[754] - std::complex (0, 1) * amp[759] + std::complex (0, 1) * amp[757] - amp[761] + std::complex (0, 1) * amp[762] - amp[763] + std::complex (0, 1) * amp[765] - amp[766] - amp[769] + std::complex (0, 1) * amp[770] - amp[771] + std::complex (0, 1) * amp[773] - amp[774] - std::complex (0, 1) * amp[830] - std::complex (0, 1) * amp[832] + amp[833] + std::complex (0, 1) * amp[836] - std::complex (0, 1) * amp[834] - std::complex (0, 1) * amp[839] + amp[840] - std::complex (0, 1) * amp[841] + std::complex (0, 1) * amp[845] - std::complex (0, 1) * amp[843] - std::complex (0, 1) * amp[848] - std::complex (0, 1) * amp[850] + amp[851] + std::complex (0, 1) * amp[854] - std::complex (0, 1) * amp[852] - std::complex (0, 1) * amp[857] + amp[858] - std::complex (0, 1) * amp[859] + std::complex (0, 1) * amp[863] - std::complex (0, 1) * amp[861] - std::complex (0, 1) * amp[864] - std::complex (0, 1) * amp[868] + amp[869] - std::complex (0, 1) * amp[870] - std::complex (0, 1) * amp[871] - std::complex (0, 1) * amp[877] - std::complex (0, 1) * amp[879] - std::complex (0, 1) * amp[880] - std::complex (0, 1) * amp[882] - std::complex (0, 1) * amp[886] + amp[887] - std::complex (0, 1) * amp[888] - std::complex (0, 1) * amp[889] - std::complex (0, 1) * amp[895] - std::complex (0, 1) * amp[897] - std::complex (0, 1) * amp[898] - std::complex (0, 1) * amp[939] - std::complex (0, 1) * amp[940] + amp[942] + amp[943] - std::complex (0, 1) * amp[945] - std::complex (0, 1) * amp[946] - std::complex (0, 1) * amp[951] - std::complex (0, 1) * amp[952] + amp[954] + amp[955] - std::complex (0, 1) * amp[957] - std::complex (0, 1) * amp[958] - amp[1010] - amp[1009] + std::complex (0, 1) * amp[1013] + std::complex (0, 1) * amp[1012] + std::complex (0, 1) * amp[1019] + std::complex (0, 1) * amp[1018] - amp[1022] - amp[1021] + std::complex (0, 1) * amp[1025] + std::complex (0, 1) * amp[1024] + std::complex (0, 1) * amp[1031] + std::complex (0, 1) * amp[1030]; jamp[3] = +amp[2] + amp[8] + amp[13] + amp[14] + amp[16] + amp[19] + amp[20] + amp[22] - std::complex (0, 1) * amp[24] - std::complex (0, 1) * amp[25] - std::complex (0, 1) * amp[26] - std::complex (0, 1) * amp[27] + std::complex (0, 1) * amp[72] - amp[73] + std::complex (0, 1) * amp[75] - amp[76] + std::complex (0, 1) * amp[77] + std::complex (0, 1) * amp[78] - amp[79] + std::complex (0, 1) * amp[81] - amp[82] + std::complex (0, 1) * amp[83] + amp[85] - std::complex (0, 1) * amp[87] + amp[88] + amp[91] - std::complex (0, 1) * amp[93] + amp[94] + amp[96] + amp[97] + amp[99] + amp[100] + amp[102] + amp[103] + amp[105] + amp[106] + amp[496] + amp[502] - std::complex (0, 1) * amp[505] - amp[506] - std::complex (0, 1) * amp[507] - amp[508] - std::complex (0, 1) * amp[509] - std::complex (0, 1) * amp[511] - amp[512] - std::complex (0, 1) * amp[513] - amp[514] - std::complex (0, 1) * amp[515] - std::complex (0, 1) * amp[529] - amp[530] - amp[532] - std::complex (0, 1) * amp[535] - amp[536] - amp[538] + amp[542] - amp[540] + amp[545] - amp[543] + amp[548] - amp[546] + amp[551] - amp[549] + std::complex (0, 1) * amp[728] - std::complex (0, 1) * amp[730] - std::complex (0, 1) * amp[731] - std::complex (0, 1) * amp[733] + std::complex (0, 1) * amp[737] - amp[738] - std::complex (0, 1) * amp[739] - std::complex (0, 1) * amp[740] + std::complex (0, 1) * amp[746] - std::complex (0, 1) * amp[748] - std::complex (0, 1) * amp[749] - std::complex (0, 1) * amp[751] + std::complex (0, 1) * amp[755] - amp[756] - std::complex (0, 1) * amp[757] - std::complex (0, 1) * amp[758] + amp[761] - std::complex (0, 1) * amp[762] + amp[763] - std::complex (0, 1) * amp[765] + amp[766] + amp[769] - std::complex (0, 1) * amp[770] + amp[771] - std::complex (0, 1) * amp[773] + amp[774] + std::complex (0, 1) * amp[864] + std::complex (0, 1) * amp[868] - amp[869] + std::complex (0, 1) * amp[870] + std::complex (0, 1) * amp[871] + std::complex (0, 1) * amp[877] + std::complex (0, 1) * amp[879] + std::complex (0, 1) * amp[880] + std::complex (0, 1) * amp[882] + std::complex (0, 1) * amp[886] - amp[887] + std::complex (0, 1) * amp[888] + std::complex (0, 1) * amp[889] + std::complex (0, 1) * amp[895] + std::complex (0, 1) * amp[897] + std::complex (0, 1) * amp[898] + std::complex (0, 1) * amp[902] - std::complex (0, 1) * amp[904] + amp[905] - std::complex (0, 1) * amp[906] - std::complex (0, 1) * amp[907] + std::complex (0, 1) * amp[911] - amp[912] - std::complex (0, 1) * amp[913] - std::complex (0, 1) * amp[915] - std::complex (0, 1) * amp[916] + std::complex (0, 1) * amp[920] - std::complex (0, 1) * amp[922] + amp[923] - std::complex (0, 1) * amp[924] - std::complex (0, 1) * amp[925] + std::complex (0, 1) * amp[929] - amp[930] - std::complex (0, 1) * amp[931] - std::complex (0, 1) * amp[933] - std::complex (0, 1) * amp[934] - std::complex (0, 1) * amp[989] + std::complex (0, 1) * amp[987] + amp[992] - amp[990] - std::complex (0, 1) * amp[995] + std::complex (0, 1) * amp[993] - std::complex (0, 1) * amp[1001] + std::complex (0, 1) * amp[999] + amp[1004] - amp[1002] - std::complex (0, 1) * amp[1007] + std::complex (0, 1) * amp[1005] + amp[1008] + amp[1009] - std::complex (0, 1) * amp[1011] - std::complex (0, 1) * amp[1012] - std::complex (0, 1) * amp[1017] - std::complex (0, 1) * amp[1018] + amp[1020] + amp[1021] - std::complex (0, 1) * amp[1023] - std::complex (0, 1) * amp[1024] - std::complex (0, 1) * amp[1029] - std::complex (0, 1) * amp[1030]; jamp[4] = +amp[5] + amp[11] + amp[28] + amp[31] + amp[33] + amp[34] + amp[37] + amp[39] + std::complex (0, 1) * amp[40] + std::complex (0, 1) * amp[41] + std::complex (0, 1) * amp[42] + std::complex (0, 1) * amp[43] - std::complex (0, 1) * amp[60] + amp[61] - std::complex (0, 1) * amp[63] + amp[64] - std::complex (0, 1) * amp[65] - std::complex (0, 1) * amp[66] + amp[67] - std::complex (0, 1) * amp[69] + amp[70] - std::complex (0, 1) * amp[71] + amp[73] + std::complex (0, 1) * amp[74] + amp[76] + amp[79] + std::complex (0, 1) * amp[80] + amp[82] - amp[98] - amp[97] - amp[101] - amp[100] - amp[104] - amp[103] - amp[107] - amp[106] + amp[554] + amp[560] - std::complex (0, 1) * amp[577] - amp[578] - std::complex (0, 1) * amp[579] - amp[580] - std::complex (0, 1) * amp[581] - std::complex (0, 1) * amp[583] - amp[584] - std::complex (0, 1) * amp[585] - amp[586] - std::complex (0, 1) * amp[587] + std::complex (0, 1) * amp[589] + amp[590] + amp[592] + std::complex (0, 1) * amp[595] + amp[596] + amp[598] + amp[600] + amp[601] + amp[603] + amp[604] + amp[606] + amp[607] + amp[609] + amp[610] + std::complex (0, 1) * amp[778] - std::complex (0, 1) * amp[784] + std::complex (0, 1) * amp[782] - std::complex (0, 1) * amp[786] + std::complex (0, 1) * amp[787] - amp[788] - std::complex (0, 1) * amp[793] + std::complex (0, 1) * amp[791] + std::complex (0, 1) * amp[796] - std::complex (0, 1) * amp[802] + std::complex (0, 1) * amp[800] - std::complex (0, 1) * amp[804] + std::complex (0, 1) * amp[805] - amp[806] - std::complex (0, 1) * amp[811] + std::complex (0, 1) * amp[809] - amp[813] + std::complex (0, 1) * amp[814] - amp[815] + std::complex (0, 1) * amp[817] - amp[818] - amp[821] + std::complex (0, 1) * amp[822] - amp[823] + std::complex (0, 1) * amp[825] - amp[826] - std::complex (0, 1) * amp[828] - std::complex (0, 1) * amp[832] + amp[833] - std::complex (0, 1) * amp[834] - std::complex (0, 1) * amp[835] - std::complex (0, 1) * amp[841] - std::complex (0, 1) * amp[843] - std::complex (0, 1) * amp[844] - std::complex (0, 1) * amp[846] - std::complex (0, 1) * amp[850] + amp[851] - std::complex (0, 1) * amp[852] - std::complex (0, 1) * amp[853] - std::complex (0, 1) * amp[859] - std::complex (0, 1) * amp[861] - std::complex (0, 1) * amp[862] - std::complex (0, 1) * amp[866] - std::complex (0, 1) * amp[868] + amp[869] + std::complex (0, 1) * amp[872] - std::complex (0, 1) * amp[870] - std::complex (0, 1) * amp[875] + amp[876] - std::complex (0, 1) * amp[877] + std::complex (0, 1) * amp[881] - std::complex (0, 1) * amp[879] - std::complex (0, 1) * amp[884] - std::complex (0, 1) * amp[886] + amp[887] + std::complex (0, 1) * amp[890] - std::complex (0, 1) * amp[888] - std::complex (0, 1) * amp[893] + amp[894] - std::complex (0, 1) * amp[895] + std::complex (0, 1) * amp[899] - std::complex (0, 1) * amp[897] - std::complex (0, 1) * amp[963] - std::complex (0, 1) * amp[964] + amp[966] + amp[967] - std::complex (0, 1) * amp[969] - std::complex (0, 1) * amp[970] - std::complex (0, 1) * amp[975] - std::complex (0, 1) * amp[976] + amp[978] + amp[979] - std::complex (0, 1) * amp[981] - std::complex (0, 1) * amp[982] - amp[1010] - amp[1009] + std::complex (0, 1) * amp[1013] + std::complex (0, 1) * amp[1012] + std::complex (0, 1) * amp[1019] + std::complex (0, 1) * amp[1018] - amp[1022] - amp[1021] + std::complex (0, 1) * amp[1025] + std::complex (0, 1) * amp[1024] + std::complex (0, 1) * amp[1031] + std::complex (0, 1) * amp[1030]; jamp[5] = +amp[4] + amp[10] + amp[12] + amp[15] + amp[17] + amp[18] + amp[21] + amp[23] + std::complex (0, 1) * amp[24] + std::complex (0, 1) * amp[25] + std::complex (0, 1) * amp[26] + std::complex (0, 1) * amp[27] + std::complex (0, 1) * amp[60] - amp[61] + std::complex (0, 1) * amp[63] - amp[64] + std::complex (0, 1) * amp[65] + std::complex (0, 1) * amp[66] - amp[67] + std::complex (0, 1) * amp[69] - amp[70] + std::complex (0, 1) * amp[71] - amp[85] + std::complex (0, 1) * amp[87] - amp[88] - amp[91] + std::complex (0, 1) * amp[93] - amp[94] + amp[98] - amp[96] + amp[101] - amp[99] + amp[104] - amp[102] + amp[107] - amp[105] + amp[494] + amp[500] - std::complex (0, 1) * amp[517] - amp[518] - std::complex (0, 1) * amp[519] - amp[520] - std::complex (0, 1) * amp[521] - std::complex (0, 1) * amp[523] - amp[524] - std::complex (0, 1) * amp[525] - amp[526] - std::complex (0, 1) * amp[527] + std::complex (0, 1) * amp[529] + amp[530] + amp[532] + std::complex (0, 1) * amp[535] + amp[536] + amp[538] + amp[540] + amp[541] + amp[543] + amp[544] + amp[546] + amp[547] + amp[549] + amp[550] + std::complex (0, 1) * amp[780] - std::complex (0, 1) * amp[782] - std::complex (0, 1) * amp[783] - std::complex (0, 1) * amp[785] + std::complex (0, 1) * amp[789] - amp[790] - std::complex (0, 1) * amp[791] - std::complex (0, 1) * amp[792] + std::complex (0, 1) * amp[798] - std::complex (0, 1) * amp[800] - std::complex (0, 1) * amp[801] - std::complex (0, 1) * amp[803] + std::complex (0, 1) * amp[807] - amp[808] - std::complex (0, 1) * amp[809] - std::complex (0, 1) * amp[810] + amp[813] - std::complex (0, 1) * amp[814] + amp[815] - std::complex (0, 1) * amp[817] + amp[818] + amp[821] - std::complex (0, 1) * amp[822] + amp[823] - std::complex (0, 1) * amp[825] + amp[826] + std::complex (0, 1) * amp[828] + std::complex (0, 1) * amp[832] - amp[833] + std::complex (0, 1) * amp[834] + std::complex (0, 1) * amp[835] + std::complex (0, 1) * amp[841] + std::complex (0, 1) * amp[843] + std::complex (0, 1) * amp[844] + std::complex (0, 1) * amp[846] + std::complex (0, 1) * amp[850] - amp[851] + std::complex (0, 1) * amp[852] + std::complex (0, 1) * amp[853] + std::complex (0, 1) * amp[859] + std::complex (0, 1) * amp[861] + std::complex (0, 1) * amp[862] - std::complex (0, 1) * amp[902] + std::complex (0, 1) * amp[904] - amp[905] + std::complex (0, 1) * amp[906] + std::complex (0, 1) * amp[907] - std::complex (0, 1) * amp[911] + amp[912] + std::complex (0, 1) * amp[913] + std::complex (0, 1) * amp[915] + std::complex (0, 1) * amp[916] - std::complex (0, 1) * amp[920] + std::complex (0, 1) * amp[922] - amp[923] + std::complex (0, 1) * amp[924] + std::complex (0, 1) * amp[925] - std::complex (0, 1) * amp[929] + amp[930] + std::complex (0, 1) * amp[931] + std::complex (0, 1) * amp[933] + std::complex (0, 1) * amp[934] - std::complex (0, 1) * amp[987] - std::complex (0, 1) * amp[988] + amp[990] + amp[991] - std::complex (0, 1) * amp[993] - std::complex (0, 1) * amp[994] - std::complex (0, 1) * amp[999] - std::complex (0, 1) * amp[1000] + amp[1002] + amp[1003] - std::complex (0, 1) * amp[1005] - std::complex (0, 1) * amp[1006] + amp[1010] - amp[1008] - std::complex (0, 1) * amp[1013] + std::complex (0, 1) * amp[1011] - std::complex (0, 1) * amp[1019] + std::complex (0, 1) * amp[1017] + amp[1022] - amp[1020] - std::complex (0, 1) * amp[1025] + std::complex (0, 1) * amp[1023] - std::complex (0, 1) * amp[1031] + std::complex (0, 1) * amp[1029]; jamp[6] = +amp[109] + amp[115] + amp[153] + amp[154] + amp[156] + amp[159] + amp[160] + amp[162] - std::complex (0, 1) * amp[164] - std::complex (0, 1) * amp[165] - std::complex (0, 1) * amp[166] - std::complex (0, 1) * amp[167] - amp[169] - std::complex (0, 1) * amp[170] - amp[172] - amp[175] - std::complex (0, 1) * amp[176] - amp[178] - std::complex (0, 1) * amp[192] - amp[193] - std::complex (0, 1) * amp[194] - amp[196] - std::complex (0, 1) * amp[197] - std::complex (0, 1) * amp[198] - amp[199] - std::complex (0, 1) * amp[200] - amp[202] - std::complex (0, 1) * amp[203] + amp[206] - amp[204] + amp[209] - amp[207] + amp[212] - amp[210] + amp[215] - amp[213] + amp[617] + amp[623] + std::complex (0, 1) * amp[625] + amp[626] + std::complex (0, 1) * amp[627] + amp[628] + std::complex (0, 1) * amp[629] + std::complex (0, 1) * amp[631] + amp[632] + std::complex (0, 1) * amp[633] + amp[634] + std::complex (0, 1) * amp[635] - std::complex (0, 1) * amp[636] + amp[638] + amp[640] - std::complex (0, 1) * amp[642] + amp[644] + amp[646] - amp[662] - amp[661] - amp[665] - amp[664] - amp[668] - amp[667] - amp[671] - amp[670] - std::complex (0, 1) * amp[674] + std::complex (0, 1) * amp[680] - std::complex (0, 1) * amp[678] + std::complex (0, 1) * amp[682] - std::complex (0, 1) * amp[683] + amp[684] + std::complex (0, 1) * amp[689] - std::complex (0, 1) * amp[687] - std::complex (0, 1) * amp[692] + std::complex (0, 1) * amp[698] - std::complex (0, 1) * amp[696] + std::complex (0, 1) * amp[700] - std::complex (0, 1) * amp[701] + amp[702] + std::complex (0, 1) * amp[707] - std::complex (0, 1) * amp[705] + amp[709] - std::complex (0, 1) * amp[710] + amp[711] - std::complex (0, 1) * amp[713] + amp[714] + amp[717] - std::complex (0, 1) * amp[718] + amp[719] - std::complex (0, 1) * amp[721] + amp[722] - std::complex (0, 1) * amp[726] - std::complex (0, 1) * amp[728] - amp[729] + std::complex (0, 1) * amp[732] + std::complex (0, 1) * amp[731] - std::complex (0, 1) * amp[735] + amp[736] - std::complex (0, 1) * amp[737] + std::complex (0, 1) * amp[741] + std::complex (0, 1) * amp[740] - std::complex (0, 1) * amp[744] - std::complex (0, 1) * amp[746] - amp[747] + std::complex (0, 1) * amp[750] + std::complex (0, 1) * amp[749] - std::complex (0, 1) * amp[753] + amp[754] - std::complex (0, 1) * amp[755] + std::complex (0, 1) * amp[759] + std::complex (0, 1) * amp[758] - std::complex (0, 1) * amp[901] - std::complex (0, 1) * amp[902] - amp[903] + std::complex (0, 1) * amp[908] + std::complex (0, 1) * amp[907] - std::complex (0, 1) * amp[911] + std::complex (0, 1) * amp[917] + std::complex (0, 1) * amp[916] - std::complex (0, 1) * amp[919] - std::complex (0, 1) * amp[920] - amp[921] + std::complex (0, 1) * amp[926] + std::complex (0, 1) * amp[925] - std::complex (0, 1) * amp[929] + std::complex (0, 1) * amp[935] + std::complex (0, 1) * amp[934] + std::complex (0, 1) * amp[941] + std::complex (0, 1) * amp[940] - amp[944] - amp[943] + std::complex (0, 1) * amp[947] + std::complex (0, 1) * amp[946] + std::complex (0, 1) * amp[953] + std::complex (0, 1) * amp[952] - amp[956] - amp[955] + std::complex (0, 1) * amp[959] + std::complex (0, 1) * amp[958] + amp[986] - amp[984] + std::complex (0, 1) * amp[989] - std::complex (0, 1) * amp[987] + std::complex (0, 1) * amp[995] - std::complex (0, 1) * amp[993] + amp[998] - amp[996] + std::complex (0, 1) * amp[1001] - std::complex (0, 1) * amp[999] + std::complex (0, 1) * amp[1007] - std::complex (0, 1) * amp[1005]; jamp[7] = +amp[108] + amp[114] + amp[137] + amp[138] + amp[140] + amp[143] + amp[144] + amp[146] - std::complex (0, 1) * amp[148] - std::complex (0, 1) * amp[149] - std::complex (0, 1) * amp[150] - std::complex (0, 1) * amp[151] - amp[181] - std::complex (0, 1) * amp[182] - amp[184] - amp[187] - std::complex (0, 1) * amp[188] - amp[190] + std::complex (0, 1) * amp[192] + amp[193] + std::complex (0, 1) * amp[194] + amp[196] + std::complex (0, 1) * amp[197] + std::complex (0, 1) * amp[198] + amp[199] + std::complex (0, 1) * amp[200] + amp[202] + std::complex (0, 1) * amp[203] + amp[204] + amp[205] + amp[207] + amp[208] + amp[210] + amp[211] + amp[213] + amp[214] + amp[557] + amp[563] + std::complex (0, 1) * amp[565] + amp[566] + std::complex (0, 1) * amp[567] + amp[568] + std::complex (0, 1) * amp[569] + std::complex (0, 1) * amp[571] + amp[572] + std::complex (0, 1) * amp[573] + amp[574] + std::complex (0, 1) * amp[575] - std::complex (0, 1) * amp[576] + amp[578] + amp[580] - std::complex (0, 1) * amp[582] + amp[584] + amp[586] - amp[602] - amp[601] - amp[605] - amp[604] - amp[608] - amp[607] - amp[611] - amp[610] - std::complex (0, 1) * amp[676] + std::complex (0, 1) * amp[678] + std::complex (0, 1) * amp[679] + std::complex (0, 1) * amp[681] - std::complex (0, 1) * amp[685] + amp[686] + std::complex (0, 1) * amp[687] + std::complex (0, 1) * amp[688] - std::complex (0, 1) * amp[694] + std::complex (0, 1) * amp[696] + std::complex (0, 1) * amp[697] + std::complex (0, 1) * amp[699] - std::complex (0, 1) * amp[703] + amp[704] + std::complex (0, 1) * amp[705] + std::complex (0, 1) * amp[706] - amp[709] + std::complex (0, 1) * amp[710] - amp[711] + std::complex (0, 1) * amp[713] - amp[714] - amp[717] + std::complex (0, 1) * amp[718] - amp[719] + std::complex (0, 1) * amp[721] - amp[722] - std::complex (0, 1) * amp[778] - std::complex (0, 1) * amp[780] - amp[781] + std::complex (0, 1) * amp[784] + std::complex (0, 1) * amp[783] - std::complex (0, 1) * amp[787] + amp[788] - std::complex (0, 1) * amp[789] + std::complex (0, 1) * amp[793] + std::complex (0, 1) * amp[792] - std::complex (0, 1) * amp[796] - std::complex (0, 1) * amp[798] - amp[799] + std::complex (0, 1) * amp[802] + std::complex (0, 1) * amp[801] - std::complex (0, 1) * amp[805] + amp[806] - std::complex (0, 1) * amp[807] + std::complex (0, 1) * amp[811] + std::complex (0, 1) * amp[810] + std::complex (0, 1) * amp[901] + std::complex (0, 1) * amp[902] + amp[903] - std::complex (0, 1) * amp[908] - std::complex (0, 1) * amp[907] + std::complex (0, 1) * amp[911] - std::complex (0, 1) * amp[917] - std::complex (0, 1) * amp[916] + std::complex (0, 1) * amp[919] + std::complex (0, 1) * amp[920] + amp[921] - std::complex (0, 1) * amp[926] - std::complex (0, 1) * amp[925] + std::complex (0, 1) * amp[929] - std::complex (0, 1) * amp[935] - std::complex (0, 1) * amp[934] + std::complex (0, 1) * amp[965] + std::complex (0, 1) * amp[964] - amp[968] - amp[967] + std::complex (0, 1) * amp[971] + std::complex (0, 1) * amp[970] + std::complex (0, 1) * amp[977] + std::complex (0, 1) * amp[976] - amp[980] - amp[979] + std::complex (0, 1) * amp[983] + std::complex (0, 1) * amp[982] + amp[984] + amp[985] + std::complex (0, 1) * amp[987] + std::complex (0, 1) * amp[988] + std::complex (0, 1) * amp[993] + std::complex (0, 1) * amp[994] + amp[996] + amp[997] + std::complex (0, 1) * amp[999] + std::complex (0, 1) * amp[1000] + std::complex (0, 1) * amp[1005] + std::complex (0, 1) * amp[1006]; jamp[8] = +amp[111] + amp[117] + amp[152] + amp[155] + amp[157] + amp[158] + amp[161] + amp[163] + std::complex (0, 1) * amp[164] + std::complex (0, 1) * amp[165] + std::complex (0, 1) * amp[166] + std::complex (0, 1) * amp[167] + amp[169] + std::complex (0, 1) * amp[170] + amp[172] + amp[175] + std::complex (0, 1) * amp[176] + amp[178] - std::complex (0, 1) * amp[180] + amp[181] - std::complex (0, 1) * amp[183] + amp[184] - std::complex (0, 1) * amp[185] - std::complex (0, 1) * amp[186] + amp[187] - std::complex (0, 1) * amp[189] + amp[190] - std::complex (0, 1) * amp[191] - amp[206] - amp[205] - amp[209] - amp[208] - amp[212] - amp[211] - amp[215] - amp[214] + amp[612] + amp[618] + std::complex (0, 1) * amp[636] - amp[638] - amp[640] + std::complex (0, 1) * amp[642] - amp[644] - amp[646] - std::complex (0, 1) * amp[648] + amp[650] - std::complex (0, 1) * amp[651] + amp[652] - std::complex (0, 1) * amp[653] - std::complex (0, 1) * amp[654] + amp[656] - std::complex (0, 1) * amp[657] + amp[658] - std::complex (0, 1) * amp[659] + amp[660] + amp[661] + amp[663] + amp[664] + amp[666] + amp[667] + amp[669] + amp[670] + std::complex (0, 1) * amp[726] + std::complex (0, 1) * amp[728] + amp[729] - std::complex (0, 1) * amp[732] - std::complex (0, 1) * amp[731] + std::complex (0, 1) * amp[735] - amp[736] + std::complex (0, 1) * amp[737] - std::complex (0, 1) * amp[741] - std::complex (0, 1) * amp[740] + std::complex (0, 1) * amp[744] + std::complex (0, 1) * amp[746] + amp[747] - std::complex (0, 1) * amp[750] - std::complex (0, 1) * amp[749] + std::complex (0, 1) * amp[753] - amp[754] + std::complex (0, 1) * amp[755] - std::complex (0, 1) * amp[759] - std::complex (0, 1) * amp[758] - std::complex (0, 1) * amp[776] + std::complex (0, 1) * amp[780] + amp[781] - std::complex (0, 1) * amp[782] - std::complex (0, 1) * amp[783] + std::complex (0, 1) * amp[789] - std::complex (0, 1) * amp[791] - std::complex (0, 1) * amp[792] - std::complex (0, 1) * amp[794] + std::complex (0, 1) * amp[798] + amp[799] - std::complex (0, 1) * amp[800] - std::complex (0, 1) * amp[801] + std::complex (0, 1) * amp[807] - std::complex (0, 1) * amp[809] - std::complex (0, 1) * amp[810] - amp[812] - std::complex (0, 1) * amp[814] - amp[816] - std::complex (0, 1) * amp[817] - amp[819] - amp[820] - std::complex (0, 1) * amp[822] - amp[824] - std::complex (0, 1) * amp[825] - amp[827] - std::complex (0, 1) * amp[830] + std::complex (0, 1) * amp[836] + std::complex (0, 1) * amp[835] - std::complex (0, 1) * amp[838] - std::complex (0, 1) * amp[839] + amp[840] + std::complex (0, 1) * amp[845] + std::complex (0, 1) * amp[844] - std::complex (0, 1) * amp[848] + std::complex (0, 1) * amp[854] + std::complex (0, 1) * amp[853] - std::complex (0, 1) * amp[856] - std::complex (0, 1) * amp[857] + amp[858] + std::complex (0, 1) * amp[863] + std::complex (0, 1) * amp[862] - std::complex (0, 1) * amp[939] - std::complex (0, 1) * amp[940] + amp[942] + amp[943] - std::complex (0, 1) * amp[945] - std::complex (0, 1) * amp[946] - std::complex (0, 1) * amp[951] - std::complex (0, 1) * amp[952] + amp[954] + amp[955] - std::complex (0, 1) * amp[957] - std::complex (0, 1) * amp[958] - amp[986] - amp[985] - std::complex (0, 1) * amp[989] - std::complex (0, 1) * amp[988] - std::complex (0, 1) * amp[995] - std::complex (0, 1) * amp[994] - amp[998] - amp[997] - std::complex (0, 1) * amp[1001] - std::complex (0, 1) * amp[1000] - std::complex (0, 1) * amp[1007] - std::complex (0, 1) * amp[1006]; jamp[9] = +amp[110] + amp[116] + amp[121] + amp[122] + amp[124] + amp[127] + amp[128] + amp[130] - std::complex (0, 1) * amp[132] - std::complex (0, 1) * amp[133] - std::complex (0, 1) * amp[134] - std::complex (0, 1) * amp[135] + std::complex (0, 1) * amp[180] - amp[181] + std::complex (0, 1) * amp[183] - amp[184] + std::complex (0, 1) * amp[185] + std::complex (0, 1) * amp[186] - amp[187] + std::complex (0, 1) * amp[189] - amp[190] + std::complex (0, 1) * amp[191] + amp[193] - std::complex (0, 1) * amp[195] + amp[196] + amp[199] - std::complex (0, 1) * amp[201] + amp[202] + amp[204] + amp[205] + amp[207] + amp[208] + amp[210] + amp[211] + amp[213] + amp[214] + amp[436] + amp[442] - std::complex (0, 1) * amp[445] - amp[446] - std::complex (0, 1) * amp[447] - amp[448] - std::complex (0, 1) * amp[449] - std::complex (0, 1) * amp[451] - amp[452] - std::complex (0, 1) * amp[453] - amp[454] - std::complex (0, 1) * amp[455] - std::complex (0, 1) * amp[469] - amp[470] - amp[472] - std::complex (0, 1) * amp[475] - amp[476] - amp[478] + amp[482] - amp[480] + amp[485] - amp[483] + amp[488] - amp[486] + amp[491] - amp[489] + std::complex (0, 1) * amp[776] - std::complex (0, 1) * amp[780] - amp[781] + std::complex (0, 1) * amp[782] + std::complex (0, 1) * amp[783] - std::complex (0, 1) * amp[789] + std::complex (0, 1) * amp[791] + std::complex (0, 1) * amp[792] + std::complex (0, 1) * amp[794] - std::complex (0, 1) * amp[798] - amp[799] + std::complex (0, 1) * amp[800] + std::complex (0, 1) * amp[801] - std::complex (0, 1) * amp[807] + std::complex (0, 1) * amp[809] + std::complex (0, 1) * amp[810] + amp[812] + std::complex (0, 1) * amp[814] + amp[816] + std::complex (0, 1) * amp[817] + amp[819] + amp[820] + std::complex (0, 1) * amp[822] + amp[824] + std::complex (0, 1) * amp[825] + amp[827] - std::complex (0, 1) * amp[832] - std::complex (0, 1) * amp[834] - std::complex (0, 1) * amp[835] - std::complex (0, 1) * amp[837] - std::complex (0, 1) * amp[841] - amp[842] - std::complex (0, 1) * amp[843] - std::complex (0, 1) * amp[844] - std::complex (0, 1) * amp[850] - std::complex (0, 1) * amp[852] - std::complex (0, 1) * amp[853] - std::complex (0, 1) * amp[855] - std::complex (0, 1) * amp[859] - amp[860] - std::complex (0, 1) * amp[861] - std::complex (0, 1) * amp[862] + std::complex (0, 1) * amp[902] + amp[903] - std::complex (0, 1) * amp[904] - std::complex (0, 1) * amp[906] - std::complex (0, 1) * amp[907] + std::complex (0, 1) * amp[911] - std::complex (0, 1) * amp[913] - amp[914] - std::complex (0, 1) * amp[915] - std::complex (0, 1) * amp[916] + std::complex (0, 1) * amp[920] + amp[921] - std::complex (0, 1) * amp[922] - std::complex (0, 1) * amp[924] - std::complex (0, 1) * amp[925] + std::complex (0, 1) * amp[929] - std::complex (0, 1) * amp[931] - amp[932] - std::complex (0, 1) * amp[933] - std::complex (0, 1) * amp[934] + amp[984] + amp[985] + std::complex (0, 1) * amp[987] + std::complex (0, 1) * amp[988] + std::complex (0, 1) * amp[993] + std::complex (0, 1) * amp[994] + amp[996] + amp[997] + std::complex (0, 1) * amp[999] + std::complex (0, 1) * amp[1000] + std::complex (0, 1) * amp[1005] + std::complex (0, 1) * amp[1006] + std::complex (0, 1) * amp[1013] - std::complex (0, 1) * amp[1011] + amp[1016] - amp[1014] + std::complex (0, 1) * amp[1019] - std::complex (0, 1) * amp[1017] + std::complex (0, 1) * amp[1025] - std::complex (0, 1) * amp[1023] + amp[1028] - amp[1026] + std::complex (0, 1) * amp[1031] - std::complex (0, 1) * amp[1029]; jamp[10] = +amp[113] + amp[119] + amp[136] + amp[139] + amp[141] + amp[142] + amp[145] + amp[147] + std::complex (0, 1) * amp[148] + std::complex (0, 1) * amp[149] + std::complex (0, 1) * amp[150] + std::complex (0, 1) * amp[151] - std::complex (0, 1) * amp[168] + amp[169] - std::complex (0, 1) * amp[171] + amp[172] - std::complex (0, 1) * amp[173] - std::complex (0, 1) * amp[174] + amp[175] - std::complex (0, 1) * amp[177] + amp[178] - std::complex (0, 1) * amp[179] + amp[181] + std::complex (0, 1) * amp[182] + amp[184] + amp[187] + std::complex (0, 1) * amp[188] + amp[190] - amp[206] - amp[205] - amp[209] - amp[208] - amp[212] - amp[211] - amp[215] - amp[214] + amp[552] + amp[558] + std::complex (0, 1) * amp[576] - amp[578] - amp[580] + std::complex (0, 1) * amp[582] - amp[584] - amp[586] - std::complex (0, 1) * amp[588] + amp[590] - std::complex (0, 1) * amp[591] + amp[592] - std::complex (0, 1) * amp[593] - std::complex (0, 1) * amp[594] + amp[596] - std::complex (0, 1) * amp[597] + amp[598] - std::complex (0, 1) * amp[599] + amp[600] + amp[601] + amp[603] + amp[604] + amp[606] + amp[607] + amp[609] + amp[610] - std::complex (0, 1) * amp[724] + std::complex (0, 1) * amp[728] + amp[729] - std::complex (0, 1) * amp[730] - std::complex (0, 1) * amp[731] + std::complex (0, 1) * amp[737] - std::complex (0, 1) * amp[739] - std::complex (0, 1) * amp[740] - std::complex (0, 1) * amp[742] + std::complex (0, 1) * amp[746] + amp[747] - std::complex (0, 1) * amp[748] - std::complex (0, 1) * amp[749] + std::complex (0, 1) * amp[755] - std::complex (0, 1) * amp[757] - std::complex (0, 1) * amp[758] - amp[760] - std::complex (0, 1) * amp[762] - amp[764] - std::complex (0, 1) * amp[765] - amp[767] - amp[768] - std::complex (0, 1) * amp[770] - amp[772] - std::complex (0, 1) * amp[773] - amp[775] + std::complex (0, 1) * amp[778] + std::complex (0, 1) * amp[780] + amp[781] - std::complex (0, 1) * amp[784] - std::complex (0, 1) * amp[783] + std::complex (0, 1) * amp[787] - amp[788] + std::complex (0, 1) * amp[789] - std::complex (0, 1) * amp[793] - std::complex (0, 1) * amp[792] + std::complex (0, 1) * amp[796] + std::complex (0, 1) * amp[798] + amp[799] - std::complex (0, 1) * amp[802] - std::complex (0, 1) * amp[801] + std::complex (0, 1) * amp[805] - amp[806] + std::complex (0, 1) * amp[807] - std::complex (0, 1) * amp[811] - std::complex (0, 1) * amp[810] - std::complex (0, 1) * amp[866] + std::complex (0, 1) * amp[872] + std::complex (0, 1) * amp[871] - std::complex (0, 1) * amp[874] - std::complex (0, 1) * amp[875] + amp[876] + std::complex (0, 1) * amp[881] + std::complex (0, 1) * amp[880] - std::complex (0, 1) * amp[884] + std::complex (0, 1) * amp[890] + std::complex (0, 1) * amp[889] - std::complex (0, 1) * amp[892] - std::complex (0, 1) * amp[893] + amp[894] + std::complex (0, 1) * amp[899] + std::complex (0, 1) * amp[898] - std::complex (0, 1) * amp[963] - std::complex (0, 1) * amp[964] + amp[966] + amp[967] - std::complex (0, 1) * amp[969] - std::complex (0, 1) * amp[970] - std::complex (0, 1) * amp[975] - std::complex (0, 1) * amp[976] + amp[978] + amp[979] - std::complex (0, 1) * amp[981] - std::complex (0, 1) * amp[982] - amp[986] - amp[985] - std::complex (0, 1) * amp[989] - std::complex (0, 1) * amp[988] - std::complex (0, 1) * amp[995] - std::complex (0, 1) * amp[994] - amp[998] - amp[997] - std::complex (0, 1) * amp[1001] - std::complex (0, 1) * amp[1000] - std::complex (0, 1) * amp[1007] - std::complex (0, 1) * amp[1006]; jamp[11] = +amp[112] + amp[118] + amp[120] + amp[123] + amp[125] + amp[126] + amp[129] + amp[131] + std::complex (0, 1) * amp[132] + std::complex (0, 1) * amp[133] + std::complex (0, 1) * amp[134] + std::complex (0, 1) * amp[135] + std::complex (0, 1) * amp[168] - amp[169] + std::complex (0, 1) * amp[171] - amp[172] + std::complex (0, 1) * amp[173] + std::complex (0, 1) * amp[174] - amp[175] + std::complex (0, 1) * amp[177] - amp[178] + std::complex (0, 1) * amp[179] - amp[193] + std::complex (0, 1) * amp[195] - amp[196] - amp[199] + std::complex (0, 1) * amp[201] - amp[202] + amp[206] - amp[204] + amp[209] - amp[207] + amp[212] - amp[210] + amp[215] - amp[213] + amp[434] + amp[440] - std::complex (0, 1) * amp[457] - amp[458] - std::complex (0, 1) * amp[459] - amp[460] - std::complex (0, 1) * amp[461] - std::complex (0, 1) * amp[463] - amp[464] - std::complex (0, 1) * amp[465] - amp[466] - std::complex (0, 1) * amp[467] + std::complex (0, 1) * amp[469] + amp[470] + amp[472] + std::complex (0, 1) * amp[475] + amp[476] + amp[478] + amp[480] + amp[481] + amp[483] + amp[484] + amp[486] + amp[487] + amp[489] + amp[490] + std::complex (0, 1) * amp[724] - std::complex (0, 1) * amp[728] - amp[729] + std::complex (0, 1) * amp[730] + std::complex (0, 1) * amp[731] - std::complex (0, 1) * amp[737] + std::complex (0, 1) * amp[739] + std::complex (0, 1) * amp[740] + std::complex (0, 1) * amp[742] - std::complex (0, 1) * amp[746] - amp[747] + std::complex (0, 1) * amp[748] + std::complex (0, 1) * amp[749] - std::complex (0, 1) * amp[755] + std::complex (0, 1) * amp[757] + std::complex (0, 1) * amp[758] + amp[760] + std::complex (0, 1) * amp[762] + amp[764] + std::complex (0, 1) * amp[765] + amp[767] + amp[768] + std::complex (0, 1) * amp[770] + amp[772] + std::complex (0, 1) * amp[773] + amp[775] - std::complex (0, 1) * amp[868] - std::complex (0, 1) * amp[870] - std::complex (0, 1) * amp[871] - std::complex (0, 1) * amp[873] - std::complex (0, 1) * amp[877] - amp[878] - std::complex (0, 1) * amp[879] - std::complex (0, 1) * amp[880] - std::complex (0, 1) * amp[886] - std::complex (0, 1) * amp[888] - std::complex (0, 1) * amp[889] - std::complex (0, 1) * amp[891] - std::complex (0, 1) * amp[895] - amp[896] - std::complex (0, 1) * amp[897] - std::complex (0, 1) * amp[898] - std::complex (0, 1) * amp[902] - amp[903] + std::complex (0, 1) * amp[904] + std::complex (0, 1) * amp[906] + std::complex (0, 1) * amp[907] - std::complex (0, 1) * amp[911] + std::complex (0, 1) * amp[913] + amp[914] + std::complex (0, 1) * amp[915] + std::complex (0, 1) * amp[916] - std::complex (0, 1) * amp[920] - amp[921] + std::complex (0, 1) * amp[922] + std::complex (0, 1) * amp[924] + std::complex (0, 1) * amp[925] - std::complex (0, 1) * amp[929] + std::complex (0, 1) * amp[931] + amp[932] + std::complex (0, 1) * amp[933] + std::complex (0, 1) * amp[934] + amp[986] - amp[984] + std::complex (0, 1) * amp[989] - std::complex (0, 1) * amp[987] + std::complex (0, 1) * amp[995] - std::complex (0, 1) * amp[993] + amp[998] - amp[996] + std::complex (0, 1) * amp[1001] - std::complex (0, 1) * amp[999] + std::complex (0, 1) * amp[1007] - std::complex (0, 1) * amp[1005] + std::complex (0, 1) * amp[1011] + std::complex (0, 1) * amp[1012] + amp[1014] + amp[1015] + std::complex (0, 1) * amp[1017] + std::complex (0, 1) * amp[1018] + std::complex (0, 1) * amp[1023] + std::complex (0, 1) * amp[1024] + amp[1026] + amp[1027] + std::complex (0, 1) * amp[1029] + std::complex (0, 1) * amp[1030]; jamp[12] = +amp[217] + amp[223] + amp[261] + amp[262] + amp[264] + amp[267] + amp[268] + amp[270] - std::complex (0, 1) * amp[272] - std::complex (0, 1) * amp[273] - std::complex (0, 1) * amp[274] - std::complex (0, 1) * amp[275] - amp[277] - std::complex (0, 1) * amp[278] - amp[280] - amp[283] - std::complex (0, 1) * amp[284] - amp[286] - std::complex (0, 1) * amp[300] - amp[301] - std::complex (0, 1) * amp[302] - amp[304] - std::complex (0, 1) * amp[305] - std::complex (0, 1) * amp[306] - amp[307] - std::complex (0, 1) * amp[308] - amp[310] - std::complex (0, 1) * amp[311] + amp[314] - amp[312] + amp[317] - amp[315] + amp[320] - amp[318] + amp[323] - amp[321] + amp[615] + amp[621] - std::complex (0, 1) * amp[624] + amp[626] + amp[628] - std::complex (0, 1) * amp[630] + amp[632] + amp[634] + std::complex (0, 1) * amp[637] + amp[638] + std::complex (0, 1) * amp[639] + amp[640] + std::complex (0, 1) * amp[641] + std::complex (0, 1) * amp[643] + amp[644] + std::complex (0, 1) * amp[645] + amp[646] + std::complex (0, 1) * amp[647] - amp[662] - amp[661] - amp[665] - amp[664] - amp[668] - amp[667] - amp[671] - amp[670] - std::complex (0, 1) * amp[674] - std::complex (0, 1) * amp[676] - amp[677] + std::complex (0, 1) * amp[680] + std::complex (0, 1) * amp[679] - std::complex (0, 1) * amp[683] + amp[684] - std::complex (0, 1) * amp[685] + std::complex (0, 1) * amp[689] + std::complex (0, 1) * amp[688] - std::complex (0, 1) * amp[692] - std::complex (0, 1) * amp[694] - amp[695] + std::complex (0, 1) * amp[698] + std::complex (0, 1) * amp[697] - std::complex (0, 1) * amp[701] + amp[702] - std::complex (0, 1) * amp[703] + std::complex (0, 1) * amp[707] + std::complex (0, 1) * amp[706] - std::complex (0, 1) * amp[726] + std::complex (0, 1) * amp[732] - std::complex (0, 1) * amp[730] + std::complex (0, 1) * amp[734] - std::complex (0, 1) * amp[735] + amp[736] + std::complex (0, 1) * amp[741] - std::complex (0, 1) * amp[739] - std::complex (0, 1) * amp[744] + std::complex (0, 1) * amp[750] - std::complex (0, 1) * amp[748] + std::complex (0, 1) * amp[752] - std::complex (0, 1) * amp[753] + amp[754] + std::complex (0, 1) * amp[759] - std::complex (0, 1) * amp[757] + amp[761] - std::complex (0, 1) * amp[762] + amp[763] - std::complex (0, 1) * amp[765] + amp[766] + amp[769] - std::complex (0, 1) * amp[770] + amp[771] - std::complex (0, 1) * amp[773] + amp[774] - std::complex (0, 1) * amp[865] - std::complex (0, 1) * amp[866] - amp[867] + std::complex (0, 1) * amp[872] + std::complex (0, 1) * amp[871] - std::complex (0, 1) * amp[875] + std::complex (0, 1) * amp[881] + std::complex (0, 1) * amp[880] - std::complex (0, 1) * amp[883] - std::complex (0, 1) * amp[884] - amp[885] + std::complex (0, 1) * amp[890] + std::complex (0, 1) * amp[889] - std::complex (0, 1) * amp[893] + std::complex (0, 1) * amp[899] + std::complex (0, 1) * amp[898] + std::complex (0, 1) * amp[941] + std::complex (0, 1) * amp[940] - amp[944] - amp[943] + std::complex (0, 1) * amp[947] + std::complex (0, 1) * amp[946] + std::complex (0, 1) * amp[953] + std::complex (0, 1) * amp[952] - amp[956] - amp[955] + std::complex (0, 1) * amp[959] + std::complex (0, 1) * amp[958] + amp[962] - amp[960] + std::complex (0, 1) * amp[965] - std::complex (0, 1) * amp[963] + std::complex (0, 1) * amp[971] - std::complex (0, 1) * amp[969] + amp[974] - amp[972] + std::complex (0, 1) * amp[977] - std::complex (0, 1) * amp[975] + std::complex (0, 1) * amp[983] - std::complex (0, 1) * amp[981]; jamp[13] = +amp[216] + amp[222] + amp[245] + amp[246] + amp[248] + amp[251] + amp[252] + amp[254] - std::complex (0, 1) * amp[256] - std::complex (0, 1) * amp[257] - std::complex (0, 1) * amp[258] - std::complex (0, 1) * amp[259] - amp[289] - std::complex (0, 1) * amp[290] - amp[292] - amp[295] - std::complex (0, 1) * amp[296] - amp[298] + std::complex (0, 1) * amp[300] + amp[301] + std::complex (0, 1) * amp[302] + amp[304] + std::complex (0, 1) * amp[305] + std::complex (0, 1) * amp[306] + amp[307] + std::complex (0, 1) * amp[308] + amp[310] + std::complex (0, 1) * amp[311] + amp[312] + amp[313] + amp[315] + amp[316] + amp[318] + amp[319] + amp[321] + amp[322] + amp[497] + amp[503] + std::complex (0, 1) * amp[505] + amp[506] + std::complex (0, 1) * amp[507] + amp[508] + std::complex (0, 1) * amp[509] + std::complex (0, 1) * amp[511] + amp[512] + std::complex (0, 1) * amp[513] + amp[514] + std::complex (0, 1) * amp[515] - std::complex (0, 1) * amp[516] + amp[518] + amp[520] - std::complex (0, 1) * amp[522] + amp[524] + amp[526] - amp[542] - amp[541] - amp[545] - amp[544] - amp[548] - amp[547] - amp[551] - amp[550] - std::complex (0, 1) * amp[728] + std::complex (0, 1) * amp[730] + std::complex (0, 1) * amp[731] + std::complex (0, 1) * amp[733] - std::complex (0, 1) * amp[737] + amp[738] + std::complex (0, 1) * amp[739] + std::complex (0, 1) * amp[740] - std::complex (0, 1) * amp[746] + std::complex (0, 1) * amp[748] + std::complex (0, 1) * amp[749] + std::complex (0, 1) * amp[751] - std::complex (0, 1) * amp[755] + amp[756] + std::complex (0, 1) * amp[757] + std::complex (0, 1) * amp[758] - amp[761] + std::complex (0, 1) * amp[762] - amp[763] + std::complex (0, 1) * amp[765] - amp[766] - amp[769] + std::complex (0, 1) * amp[770] - amp[771] + std::complex (0, 1) * amp[773] - amp[774] - std::complex (0, 1) * amp[778] - amp[779] - std::complex (0, 1) * amp[780] + std::complex (0, 1) * amp[784] + std::complex (0, 1) * amp[783] - std::complex (0, 1) * amp[787] - std::complex (0, 1) * amp[789] + amp[790] + std::complex (0, 1) * amp[793] + std::complex (0, 1) * amp[792] - std::complex (0, 1) * amp[796] - amp[797] - std::complex (0, 1) * amp[798] + std::complex (0, 1) * amp[802] + std::complex (0, 1) * amp[801] - std::complex (0, 1) * amp[805] - std::complex (0, 1) * amp[807] + amp[808] + std::complex (0, 1) * amp[811] + std::complex (0, 1) * amp[810] + std::complex (0, 1) * amp[865] + std::complex (0, 1) * amp[866] + amp[867] - std::complex (0, 1) * amp[872] - std::complex (0, 1) * amp[871] + std::complex (0, 1) * amp[875] - std::complex (0, 1) * amp[881] - std::complex (0, 1) * amp[880] + std::complex (0, 1) * amp[883] + std::complex (0, 1) * amp[884] + amp[885] - std::complex (0, 1) * amp[890] - std::complex (0, 1) * amp[889] + std::complex (0, 1) * amp[893] - std::complex (0, 1) * amp[899] - std::complex (0, 1) * amp[898] + amp[960] + amp[961] + std::complex (0, 1) * amp[963] + std::complex (0, 1) * amp[964] + std::complex (0, 1) * amp[969] + std::complex (0, 1) * amp[970] + amp[972] + amp[973] + std::complex (0, 1) * amp[975] + std::complex (0, 1) * amp[976] + std::complex (0, 1) * amp[981] + std::complex (0, 1) * amp[982] + std::complex (0, 1) * amp[989] + std::complex (0, 1) * amp[988] - amp[992] - amp[991] + std::complex (0, 1) * amp[995] + std::complex (0, 1) * amp[994] + std::complex (0, 1) * amp[1001] + std::complex (0, 1) * amp[1000] - amp[1004] - amp[1003] + std::complex (0, 1) * amp[1007] + std::complex (0, 1) * amp[1006]; jamp[14] = +amp[219] + amp[225] + amp[260] + amp[263] + amp[265] + amp[266] + amp[269] + amp[271] + std::complex (0, 1) * amp[272] + std::complex (0, 1) * amp[273] + std::complex (0, 1) * amp[274] + std::complex (0, 1) * amp[275] + amp[277] + std::complex (0, 1) * amp[278] + amp[280] + amp[283] + std::complex (0, 1) * amp[284] + amp[286] - std::complex (0, 1) * amp[288] + amp[289] - std::complex (0, 1) * amp[291] + amp[292] - std::complex (0, 1) * amp[293] - std::complex (0, 1) * amp[294] + amp[295] - std::complex (0, 1) * amp[297] + amp[298] - std::complex (0, 1) * amp[299] - amp[314] - amp[313] - amp[317] - amp[316] - amp[320] - amp[319] - amp[323] - amp[322] + amp[613] + amp[619] + std::complex (0, 1) * amp[624] - amp[626] - amp[628] + std::complex (0, 1) * amp[630] - amp[632] - amp[634] + std::complex (0, 1) * amp[648] - amp[650] + std::complex (0, 1) * amp[651] - amp[652] + std::complex (0, 1) * amp[653] + std::complex (0, 1) * amp[654] - amp[656] + std::complex (0, 1) * amp[657] - amp[658] + std::complex (0, 1) * amp[659] + amp[662] - amp[660] + amp[665] - amp[663] + amp[668] - amp[666] + amp[671] - amp[669] + std::complex (0, 1) * amp[674] + std::complex (0, 1) * amp[676] + amp[677] - std::complex (0, 1) * amp[680] - std::complex (0, 1) * amp[679] + std::complex (0, 1) * amp[683] - amp[684] + std::complex (0, 1) * amp[685] - std::complex (0, 1) * amp[689] - std::complex (0, 1) * amp[688] + std::complex (0, 1) * amp[692] + std::complex (0, 1) * amp[694] + amp[695] - std::complex (0, 1) * amp[698] - std::complex (0, 1) * amp[697] + std::complex (0, 1) * amp[701] - amp[702] + std::complex (0, 1) * amp[703] - std::complex (0, 1) * amp[707] - std::complex (0, 1) * amp[706] - std::complex (0, 1) * amp[777] + std::complex (0, 1) * amp[778] + amp[779] - std::complex (0, 1) * amp[784] + std::complex (0, 1) * amp[782] + std::complex (0, 1) * amp[787] - std::complex (0, 1) * amp[793] + std::complex (0, 1) * amp[791] - std::complex (0, 1) * amp[795] + std::complex (0, 1) * amp[796] + amp[797] - std::complex (0, 1) * amp[802] + std::complex (0, 1) * amp[800] + std::complex (0, 1) * amp[805] - std::complex (0, 1) * amp[811] + std::complex (0, 1) * amp[809] + amp[812] + std::complex (0, 1) * amp[814] + amp[816] + std::complex (0, 1) * amp[817] + amp[819] + amp[820] + std::complex (0, 1) * amp[822] + amp[824] + std::complex (0, 1) * amp[825] + amp[827] + std::complex (0, 1) * amp[830] - std::complex (0, 1) * amp[836] - std::complex (0, 1) * amp[835] + std::complex (0, 1) * amp[838] + std::complex (0, 1) * amp[839] - amp[840] - std::complex (0, 1) * amp[845] - std::complex (0, 1) * amp[844] + std::complex (0, 1) * amp[848] - std::complex (0, 1) * amp[854] - std::complex (0, 1) * amp[853] + std::complex (0, 1) * amp[856] + std::complex (0, 1) * amp[857] - amp[858] - std::complex (0, 1) * amp[863] - std::complex (0, 1) * amp[862] - std::complex (0, 1) * amp[941] + std::complex (0, 1) * amp[939] + amp[944] - amp[942] - std::complex (0, 1) * amp[947] + std::complex (0, 1) * amp[945] - std::complex (0, 1) * amp[953] + std::complex (0, 1) * amp[951] + amp[956] - amp[954] - std::complex (0, 1) * amp[959] + std::complex (0, 1) * amp[957] - amp[962] - amp[961] - std::complex (0, 1) * amp[965] - std::complex (0, 1) * amp[964] - std::complex (0, 1) * amp[971] - std::complex (0, 1) * amp[970] - amp[974] - amp[973] - std::complex (0, 1) * amp[977] - std::complex (0, 1) * amp[976] - std::complex (0, 1) * amp[983] - std::complex (0, 1) * amp[982]; jamp[15] = +amp[218] + amp[224] + amp[229] + amp[230] + amp[232] + amp[235] + amp[236] + amp[238] - std::complex (0, 1) * amp[240] - std::complex (0, 1) * amp[241] - std::complex (0, 1) * amp[242] - std::complex (0, 1) * amp[243] + std::complex (0, 1) * amp[288] - amp[289] + std::complex (0, 1) * amp[291] - amp[292] + std::complex (0, 1) * amp[293] + std::complex (0, 1) * amp[294] - amp[295] + std::complex (0, 1) * amp[297] - amp[298] + std::complex (0, 1) * amp[299] + amp[301] - std::complex (0, 1) * amp[303] + amp[304] + amp[307] - std::complex (0, 1) * amp[309] + amp[310] + amp[312] + amp[313] + amp[315] + amp[316] + amp[318] + amp[319] + amp[321] + amp[322] + amp[437] + amp[443] + std::complex (0, 1) * amp[445] + amp[446] + std::complex (0, 1) * amp[447] + amp[448] + std::complex (0, 1) * amp[449] + std::complex (0, 1) * amp[451] + amp[452] + std::complex (0, 1) * amp[453] + amp[454] + std::complex (0, 1) * amp[455] - std::complex (0, 1) * amp[456] + amp[458] + amp[460] - std::complex (0, 1) * amp[462] + amp[464] + amp[466] - amp[482] - amp[481] - amp[485] - amp[484] - amp[488] - amp[487] - amp[491] - amp[490] + std::complex (0, 1) * amp[777] - std::complex (0, 1) * amp[778] - amp[779] + std::complex (0, 1) * amp[784] - std::complex (0, 1) * amp[782] - std::complex (0, 1) * amp[787] + std::complex (0, 1) * amp[793] - std::complex (0, 1) * amp[791] + std::complex (0, 1) * amp[795] - std::complex (0, 1) * amp[796] - amp[797] + std::complex (0, 1) * amp[802] - std::complex (0, 1) * amp[800] - std::complex (0, 1) * amp[805] + std::complex (0, 1) * amp[811] - std::complex (0, 1) * amp[809] - amp[812] - std::complex (0, 1) * amp[814] - amp[816] - std::complex (0, 1) * amp[817] - amp[819] - amp[820] - std::complex (0, 1) * amp[822] - amp[824] - std::complex (0, 1) * amp[825] - amp[827] + std::complex (0, 1) * amp[832] + std::complex (0, 1) * amp[834] + std::complex (0, 1) * amp[835] + std::complex (0, 1) * amp[837] + std::complex (0, 1) * amp[841] + amp[842] + std::complex (0, 1) * amp[843] + std::complex (0, 1) * amp[844] + std::complex (0, 1) * amp[850] + std::complex (0, 1) * amp[852] + std::complex (0, 1) * amp[853] + std::complex (0, 1) * amp[855] + std::complex (0, 1) * amp[859] + amp[860] + std::complex (0, 1) * amp[861] + std::complex (0, 1) * amp[862] + std::complex (0, 1) * amp[866] + amp[867] + std::complex (0, 1) * amp[868] - std::complex (0, 1) * amp[872] + std::complex (0, 1) * amp[870] + std::complex (0, 1) * amp[875] + std::complex (0, 1) * amp[877] + amp[878] - std::complex (0, 1) * amp[881] + std::complex (0, 1) * amp[879] + std::complex (0, 1) * amp[884] + amp[885] + std::complex (0, 1) * amp[886] - std::complex (0, 1) * amp[890] + std::complex (0, 1) * amp[888] + std::complex (0, 1) * amp[893] + std::complex (0, 1) * amp[895] + amp[896] - std::complex (0, 1) * amp[899] + std::complex (0, 1) * amp[897] + amp[960] + amp[961] + std::complex (0, 1) * amp[963] + std::complex (0, 1) * amp[964] + std::complex (0, 1) * amp[969] + std::complex (0, 1) * amp[970] + amp[972] + amp[973] + std::complex (0, 1) * amp[975] + std::complex (0, 1) * amp[976] + std::complex (0, 1) * amp[981] + std::complex (0, 1) * amp[982] - std::complex (0, 1) * amp[1013] - std::complex (0, 1) * amp[1012] - amp[1016] - amp[1015] - std::complex (0, 1) * amp[1019] - std::complex (0, 1) * amp[1018] - std::complex (0, 1) * amp[1025] - std::complex (0, 1) * amp[1024] - amp[1028] - amp[1027] - std::complex (0, 1) * amp[1031] - std::complex (0, 1) * amp[1030]; jamp[16] = +amp[221] + amp[227] + amp[244] + amp[247] + amp[249] + amp[250] + amp[253] + amp[255] + std::complex (0, 1) * amp[256] + std::complex (0, 1) * amp[257] + std::complex (0, 1) * amp[258] + std::complex (0, 1) * amp[259] - std::complex (0, 1) * amp[276] + amp[277] - std::complex (0, 1) * amp[279] + amp[280] - std::complex (0, 1) * amp[281] - std::complex (0, 1) * amp[282] + amp[283] - std::complex (0, 1) * amp[285] + amp[286] - std::complex (0, 1) * amp[287] + amp[289] + std::complex (0, 1) * amp[290] + amp[292] + amp[295] + std::complex (0, 1) * amp[296] + amp[298] - amp[314] - amp[313] - amp[317] - amp[316] - amp[320] - amp[319] - amp[323] - amp[322] + amp[492] + amp[498] + std::complex (0, 1) * amp[516] - amp[518] - amp[520] + std::complex (0, 1) * amp[522] - amp[524] - amp[526] - std::complex (0, 1) * amp[528] + amp[530] - std::complex (0, 1) * amp[531] + amp[532] - std::complex (0, 1) * amp[533] - std::complex (0, 1) * amp[534] + amp[536] - std::complex (0, 1) * amp[537] + amp[538] - std::complex (0, 1) * amp[539] + amp[540] + amp[541] + amp[543] + amp[544] + amp[546] + amp[547] + amp[549] + amp[550] - std::complex (0, 1) * amp[672] + std::complex (0, 1) * amp[676] + amp[677] - std::complex (0, 1) * amp[678] - std::complex (0, 1) * amp[679] + std::complex (0, 1) * amp[685] - std::complex (0, 1) * amp[687] - std::complex (0, 1) * amp[688] - std::complex (0, 1) * amp[690] + std::complex (0, 1) * amp[694] + amp[695] - std::complex (0, 1) * amp[696] - std::complex (0, 1) * amp[697] + std::complex (0, 1) * amp[703] - std::complex (0, 1) * amp[705] - std::complex (0, 1) * amp[706] - amp[708] - std::complex (0, 1) * amp[710] - amp[712] - std::complex (0, 1) * amp[713] - amp[715] - amp[716] - std::complex (0, 1) * amp[718] - amp[720] - std::complex (0, 1) * amp[721] - amp[723] + std::complex (0, 1) * amp[778] + amp[779] + std::complex (0, 1) * amp[780] - std::complex (0, 1) * amp[784] - std::complex (0, 1) * amp[783] + std::complex (0, 1) * amp[787] + std::complex (0, 1) * amp[789] - amp[790] - std::complex (0, 1) * amp[793] - std::complex (0, 1) * amp[792] + std::complex (0, 1) * amp[796] + amp[797] + std::complex (0, 1) * amp[798] - std::complex (0, 1) * amp[802] - std::complex (0, 1) * amp[801] + std::complex (0, 1) * amp[805] + std::complex (0, 1) * amp[807] - amp[808] - std::complex (0, 1) * amp[811] - std::complex (0, 1) * amp[810] - std::complex (0, 1) * amp[902] + std::complex (0, 1) * amp[908] + std::complex (0, 1) * amp[907] - std::complex (0, 1) * amp[910] - std::complex (0, 1) * amp[911] + amp[912] + std::complex (0, 1) * amp[917] + std::complex (0, 1) * amp[916] - std::complex (0, 1) * amp[920] + std::complex (0, 1) * amp[926] + std::complex (0, 1) * amp[925] - std::complex (0, 1) * amp[928] - std::complex (0, 1) * amp[929] + amp[930] + std::complex (0, 1) * amp[935] + std::complex (0, 1) * amp[934] - amp[962] - amp[961] - std::complex (0, 1) * amp[965] - std::complex (0, 1) * amp[964] - std::complex (0, 1) * amp[971] - std::complex (0, 1) * amp[970] - amp[974] - amp[973] - std::complex (0, 1) * amp[977] - std::complex (0, 1) * amp[976] - std::complex (0, 1) * amp[983] - std::complex (0, 1) * amp[982] - std::complex (0, 1) * amp[987] - std::complex (0, 1) * amp[988] + amp[990] + amp[991] - std::complex (0, 1) * amp[993] - std::complex (0, 1) * amp[994] - std::complex (0, 1) * amp[999] - std::complex (0, 1) * amp[1000] + amp[1002] + amp[1003] - std::complex (0, 1) * amp[1005] - std::complex (0, 1) * amp[1006]; jamp[17] = +amp[220] + amp[226] + amp[228] + amp[231] + amp[233] + amp[234] + amp[237] + amp[239] + std::complex (0, 1) * amp[240] + std::complex (0, 1) * amp[241] + std::complex (0, 1) * amp[242] + std::complex (0, 1) * amp[243] + std::complex (0, 1) * amp[276] - amp[277] + std::complex (0, 1) * amp[279] - amp[280] + std::complex (0, 1) * amp[281] + std::complex (0, 1) * amp[282] - amp[283] + std::complex (0, 1) * amp[285] - amp[286] + std::complex (0, 1) * amp[287] - amp[301] + std::complex (0, 1) * amp[303] - amp[304] - amp[307] + std::complex (0, 1) * amp[309] - amp[310] + amp[314] - amp[312] + amp[317] - amp[315] + amp[320] - amp[318] + amp[323] - amp[321] + amp[432] + amp[438] + std::complex (0, 1) * amp[456] - amp[458] - amp[460] + std::complex (0, 1) * amp[462] - amp[464] - amp[466] - std::complex (0, 1) * amp[468] + amp[470] - std::complex (0, 1) * amp[471] + amp[472] - std::complex (0, 1) * amp[473] - std::complex (0, 1) * amp[474] + amp[476] - std::complex (0, 1) * amp[477] + amp[478] - std::complex (0, 1) * amp[479] + amp[480] + amp[481] + amp[483] + amp[484] + amp[486] + amp[487] + amp[489] + amp[490] + std::complex (0, 1) * amp[672] - std::complex (0, 1) * amp[676] - amp[677] + std::complex (0, 1) * amp[678] + std::complex (0, 1) * amp[679] - std::complex (0, 1) * amp[685] + std::complex (0, 1) * amp[687] + std::complex (0, 1) * amp[688] + std::complex (0, 1) * amp[690] - std::complex (0, 1) * amp[694] - amp[695] + std::complex (0, 1) * amp[696] + std::complex (0, 1) * amp[697] - std::complex (0, 1) * amp[703] + std::complex (0, 1) * amp[705] + std::complex (0, 1) * amp[706] + amp[708] + std::complex (0, 1) * amp[710] + amp[712] + std::complex (0, 1) * amp[713] + amp[715] + amp[716] + std::complex (0, 1) * amp[718] + amp[720] + std::complex (0, 1) * amp[721] + amp[723] - std::complex (0, 1) * amp[866] - amp[867] - std::complex (0, 1) * amp[868] + std::complex (0, 1) * amp[872] - std::complex (0, 1) * amp[870] - std::complex (0, 1) * amp[875] - std::complex (0, 1) * amp[877] - amp[878] + std::complex (0, 1) * amp[881] - std::complex (0, 1) * amp[879] - std::complex (0, 1) * amp[884] - amp[885] - std::complex (0, 1) * amp[886] + std::complex (0, 1) * amp[890] - std::complex (0, 1) * amp[888] - std::complex (0, 1) * amp[893] - std::complex (0, 1) * amp[895] - amp[896] + std::complex (0, 1) * amp[899] - std::complex (0, 1) * amp[897] + std::complex (0, 1) * amp[904] - std::complex (0, 1) * amp[908] + std::complex (0, 1) * amp[906] - std::complex (0, 1) * amp[909] + std::complex (0, 1) * amp[913] + amp[914] - std::complex (0, 1) * amp[917] + std::complex (0, 1) * amp[915] + std::complex (0, 1) * amp[922] - std::complex (0, 1) * amp[926] + std::complex (0, 1) * amp[924] - std::complex (0, 1) * amp[927] + std::complex (0, 1) * amp[931] + amp[932] - std::complex (0, 1) * amp[935] + std::complex (0, 1) * amp[933] + amp[962] - amp[960] + std::complex (0, 1) * amp[965] - std::complex (0, 1) * amp[963] + std::complex (0, 1) * amp[971] - std::complex (0, 1) * amp[969] + amp[974] - amp[972] + std::complex (0, 1) * amp[977] - std::complex (0, 1) * amp[975] + std::complex (0, 1) * amp[983] - std::complex (0, 1) * amp[981] + std::complex (0, 1) * amp[1011] + std::complex (0, 1) * amp[1012] + amp[1014] + amp[1015] + std::complex (0, 1) * amp[1017] + std::complex (0, 1) * amp[1018] + std::complex (0, 1) * amp[1023] + std::complex (0, 1) * amp[1024] + amp[1026] + amp[1027] + std::complex (0, 1) * amp[1029] + std::complex (0, 1) * amp[1030]; jamp[18] = +amp[325] + amp[331] + amp[369] + amp[370] + amp[372] + amp[375] + amp[376] + amp[378] - std::complex (0, 1) * amp[380] - std::complex (0, 1) * amp[381] - std::complex (0, 1) * amp[382] - std::complex (0, 1) * amp[383] - amp[385] - std::complex (0, 1) * amp[386] - amp[388] - amp[391] - std::complex (0, 1) * amp[392] - amp[394] - std::complex (0, 1) * amp[408] - amp[409] - std::complex (0, 1) * amp[410] - amp[412] - std::complex (0, 1) * amp[413] - std::complex (0, 1) * amp[414] - amp[415] - std::complex (0, 1) * amp[416] - amp[418] - std::complex (0, 1) * amp[419] + amp[422] - amp[420] + amp[425] - amp[423] + amp[428] - amp[426] + amp[431] - amp[429] + amp[555] + amp[561] - std::complex (0, 1) * amp[564] + amp[566] + amp[568] - std::complex (0, 1) * amp[570] + amp[572] + amp[574] + std::complex (0, 1) * amp[577] + amp[578] + std::complex (0, 1) * amp[579] + amp[580] + std::complex (0, 1) * amp[581] + std::complex (0, 1) * amp[583] + amp[584] + std::complex (0, 1) * amp[585] + amp[586] + std::complex (0, 1) * amp[587] - amp[602] - amp[601] - amp[605] - amp[604] - amp[608] - amp[607] - amp[611] - amp[610] - std::complex (0, 1) * amp[674] - amp[675] - std::complex (0, 1) * amp[676] + std::complex (0, 1) * amp[680] + std::complex (0, 1) * amp[679] - std::complex (0, 1) * amp[683] - std::complex (0, 1) * amp[685] + amp[686] + std::complex (0, 1) * amp[689] + std::complex (0, 1) * amp[688] - std::complex (0, 1) * amp[692] - amp[693] - std::complex (0, 1) * amp[694] + std::complex (0, 1) * amp[698] + std::complex (0, 1) * amp[697] - std::complex (0, 1) * amp[701] - std::complex (0, 1) * amp[703] + amp[704] + std::complex (0, 1) * amp[707] + std::complex (0, 1) * amp[706] - std::complex (0, 1) * amp[778] + std::complex (0, 1) * amp[784] - std::complex (0, 1) * amp[782] + std::complex (0, 1) * amp[786] - std::complex (0, 1) * amp[787] + amp[788] + std::complex (0, 1) * amp[793] - std::complex (0, 1) * amp[791] - std::complex (0, 1) * amp[796] + std::complex (0, 1) * amp[802] - std::complex (0, 1) * amp[800] + std::complex (0, 1) * amp[804] - std::complex (0, 1) * amp[805] + amp[806] + std::complex (0, 1) * amp[811] - std::complex (0, 1) * amp[809] + amp[813] - std::complex (0, 1) * amp[814] + amp[815] - std::complex (0, 1) * amp[817] + amp[818] + amp[821] - std::complex (0, 1) * amp[822] + amp[823] - std::complex (0, 1) * amp[825] + amp[826] - std::complex (0, 1) * amp[829] - std::complex (0, 1) * amp[830] - amp[831] + std::complex (0, 1) * amp[836] + std::complex (0, 1) * amp[835] - std::complex (0, 1) * amp[839] + std::complex (0, 1) * amp[845] + std::complex (0, 1) * amp[844] - std::complex (0, 1) * amp[847] - std::complex (0, 1) * amp[848] - amp[849] + std::complex (0, 1) * amp[854] + std::complex (0, 1) * amp[853] - std::complex (0, 1) * amp[857] + std::complex (0, 1) * amp[863] + std::complex (0, 1) * amp[862] + amp[938] - amp[936] + std::complex (0, 1) * amp[941] - std::complex (0, 1) * amp[939] + std::complex (0, 1) * amp[947] - std::complex (0, 1) * amp[945] + amp[950] - amp[948] + std::complex (0, 1) * amp[953] - std::complex (0, 1) * amp[951] + std::complex (0, 1) * amp[959] - std::complex (0, 1) * amp[957] + std::complex (0, 1) * amp[965] + std::complex (0, 1) * amp[964] - amp[968] - amp[967] + std::complex (0, 1) * amp[971] + std::complex (0, 1) * amp[970] + std::complex (0, 1) * amp[977] + std::complex (0, 1) * amp[976] - amp[980] - amp[979] + std::complex (0, 1) * amp[983] + std::complex (0, 1) * amp[982]; jamp[19] = +amp[324] + amp[330] + amp[353] + amp[354] + amp[356] + amp[359] + amp[360] + amp[362] - std::complex (0, 1) * amp[364] - std::complex (0, 1) * amp[365] - std::complex (0, 1) * amp[366] - std::complex (0, 1) * amp[367] - amp[397] - std::complex (0, 1) * amp[398] - amp[400] - amp[403] - std::complex (0, 1) * amp[404] - amp[406] + std::complex (0, 1) * amp[408] + amp[409] + std::complex (0, 1) * amp[410] + amp[412] + std::complex (0, 1) * amp[413] + std::complex (0, 1) * amp[414] + amp[415] + std::complex (0, 1) * amp[416] + amp[418] + std::complex (0, 1) * amp[419] + amp[420] + amp[421] + amp[423] + amp[424] + amp[426] + amp[427] + amp[429] + amp[430] + amp[495] + amp[501] - std::complex (0, 1) * amp[504] + amp[506] + amp[508] - std::complex (0, 1) * amp[510] + amp[512] + amp[514] + std::complex (0, 1) * amp[517] + amp[518] + std::complex (0, 1) * amp[519] + amp[520] + std::complex (0, 1) * amp[521] + std::complex (0, 1) * amp[523] + amp[524] + std::complex (0, 1) * amp[525] + amp[526] + std::complex (0, 1) * amp[527] - amp[542] - amp[541] - amp[545] - amp[544] - amp[548] - amp[547] - amp[551] - amp[550] - std::complex (0, 1) * amp[726] - amp[727] - std::complex (0, 1) * amp[728] + std::complex (0, 1) * amp[732] + std::complex (0, 1) * amp[731] - std::complex (0, 1) * amp[735] - std::complex (0, 1) * amp[737] + amp[738] + std::complex (0, 1) * amp[741] + std::complex (0, 1) * amp[740] - std::complex (0, 1) * amp[744] - amp[745] - std::complex (0, 1) * amp[746] + std::complex (0, 1) * amp[750] + std::complex (0, 1) * amp[749] - std::complex (0, 1) * amp[753] - std::complex (0, 1) * amp[755] + amp[756] + std::complex (0, 1) * amp[759] + std::complex (0, 1) * amp[758] - std::complex (0, 1) * amp[780] + std::complex (0, 1) * amp[782] + std::complex (0, 1) * amp[783] + std::complex (0, 1) * amp[785] - std::complex (0, 1) * amp[789] + amp[790] + std::complex (0, 1) * amp[791] + std::complex (0, 1) * amp[792] - std::complex (0, 1) * amp[798] + std::complex (0, 1) * amp[800] + std::complex (0, 1) * amp[801] + std::complex (0, 1) * amp[803] - std::complex (0, 1) * amp[807] + amp[808] + std::complex (0, 1) * amp[809] + std::complex (0, 1) * amp[810] - amp[813] + std::complex (0, 1) * amp[814] - amp[815] + std::complex (0, 1) * amp[817] - amp[818] - amp[821] + std::complex (0, 1) * amp[822] - amp[823] + std::complex (0, 1) * amp[825] - amp[826] + std::complex (0, 1) * amp[829] + std::complex (0, 1) * amp[830] + amp[831] - std::complex (0, 1) * amp[836] - std::complex (0, 1) * amp[835] + std::complex (0, 1) * amp[839] - std::complex (0, 1) * amp[845] - std::complex (0, 1) * amp[844] + std::complex (0, 1) * amp[847] + std::complex (0, 1) * amp[848] + amp[849] - std::complex (0, 1) * amp[854] - std::complex (0, 1) * amp[853] + std::complex (0, 1) * amp[857] - std::complex (0, 1) * amp[863] - std::complex (0, 1) * amp[862] + amp[936] + amp[937] + std::complex (0, 1) * amp[939] + std::complex (0, 1) * amp[940] + std::complex (0, 1) * amp[945] + std::complex (0, 1) * amp[946] + amp[948] + amp[949] + std::complex (0, 1) * amp[951] + std::complex (0, 1) * amp[952] + std::complex (0, 1) * amp[957] + std::complex (0, 1) * amp[958] + std::complex (0, 1) * amp[989] + std::complex (0, 1) * amp[988] - amp[992] - amp[991] + std::complex (0, 1) * amp[995] + std::complex (0, 1) * amp[994] + std::complex (0, 1) * amp[1001] + std::complex (0, 1) * amp[1000] - amp[1004] - amp[1003] + std::complex (0, 1) * amp[1007] + std::complex (0, 1) * amp[1006]; jamp[20] = +amp[327] + amp[333] + amp[368] + amp[371] + amp[373] + amp[374] + amp[377] + amp[379] + std::complex (0, 1) * amp[380] + std::complex (0, 1) * amp[381] + std::complex (0, 1) * amp[382] + std::complex (0, 1) * amp[383] + amp[385] + std::complex (0, 1) * amp[386] + amp[388] + amp[391] + std::complex (0, 1) * amp[392] + amp[394] - std::complex (0, 1) * amp[396] + amp[397] - std::complex (0, 1) * amp[399] + amp[400] - std::complex (0, 1) * amp[401] - std::complex (0, 1) * amp[402] + amp[403] - std::complex (0, 1) * amp[405] + amp[406] - std::complex (0, 1) * amp[407] - amp[422] - amp[421] - amp[425] - amp[424] - amp[428] - amp[427] - amp[431] - amp[430] + amp[553] + amp[559] + std::complex (0, 1) * amp[564] - amp[566] - amp[568] + std::complex (0, 1) * amp[570] - amp[572] - amp[574] + std::complex (0, 1) * amp[588] - amp[590] + std::complex (0, 1) * amp[591] - amp[592] + std::complex (0, 1) * amp[593] + std::complex (0, 1) * amp[594] - amp[596] + std::complex (0, 1) * amp[597] - amp[598] + std::complex (0, 1) * amp[599] + amp[602] - amp[600] + amp[605] - amp[603] + amp[608] - amp[606] + amp[611] - amp[609] + std::complex (0, 1) * amp[674] + amp[675] + std::complex (0, 1) * amp[676] - std::complex (0, 1) * amp[680] - std::complex (0, 1) * amp[679] + std::complex (0, 1) * amp[683] + std::complex (0, 1) * amp[685] - amp[686] - std::complex (0, 1) * amp[689] - std::complex (0, 1) * amp[688] + std::complex (0, 1) * amp[692] + amp[693] + std::complex (0, 1) * amp[694] - std::complex (0, 1) * amp[698] - std::complex (0, 1) * amp[697] + std::complex (0, 1) * amp[701] + std::complex (0, 1) * amp[703] - amp[704] - std::complex (0, 1) * amp[707] - std::complex (0, 1) * amp[706] - std::complex (0, 1) * amp[725] + std::complex (0, 1) * amp[726] + amp[727] - std::complex (0, 1) * amp[732] + std::complex (0, 1) * amp[730] + std::complex (0, 1) * amp[735] - std::complex (0, 1) * amp[741] + std::complex (0, 1) * amp[739] - std::complex (0, 1) * amp[743] + std::complex (0, 1) * amp[744] + amp[745] - std::complex (0, 1) * amp[750] + std::complex (0, 1) * amp[748] + std::complex (0, 1) * amp[753] - std::complex (0, 1) * amp[759] + std::complex (0, 1) * amp[757] + amp[760] + std::complex (0, 1) * amp[762] + amp[764] + std::complex (0, 1) * amp[765] + amp[767] + amp[768] + std::complex (0, 1) * amp[770] + amp[772] + std::complex (0, 1) * amp[773] + amp[775] + std::complex (0, 1) * amp[866] - std::complex (0, 1) * amp[872] - std::complex (0, 1) * amp[871] + std::complex (0, 1) * amp[874] + std::complex (0, 1) * amp[875] - amp[876] - std::complex (0, 1) * amp[881] - std::complex (0, 1) * amp[880] + std::complex (0, 1) * amp[884] - std::complex (0, 1) * amp[890] - std::complex (0, 1) * amp[889] + std::complex (0, 1) * amp[892] + std::complex (0, 1) * amp[893] - amp[894] - std::complex (0, 1) * amp[899] - std::complex (0, 1) * amp[898] - amp[938] - amp[937] - std::complex (0, 1) * amp[941] - std::complex (0, 1) * amp[940] - std::complex (0, 1) * amp[947] - std::complex (0, 1) * amp[946] - amp[950] - amp[949] - std::complex (0, 1) * amp[953] - std::complex (0, 1) * amp[952] - std::complex (0, 1) * amp[959] - std::complex (0, 1) * amp[958] - std::complex (0, 1) * amp[965] + std::complex (0, 1) * amp[963] + amp[968] - amp[966] - std::complex (0, 1) * amp[971] + std::complex (0, 1) * amp[969] - std::complex (0, 1) * amp[977] + std::complex (0, 1) * amp[975] + amp[980] - amp[978] - std::complex (0, 1) * amp[983] + std::complex (0, 1) * amp[981]; jamp[21] = +amp[326] + amp[332] + amp[337] + amp[338] + amp[340] + amp[343] + amp[344] + amp[346] - std::complex (0, 1) * amp[348] - std::complex (0, 1) * amp[349] - std::complex (0, 1) * amp[350] - std::complex (0, 1) * amp[351] + std::complex (0, 1) * amp[396] - amp[397] + std::complex (0, 1) * amp[399] - amp[400] + std::complex (0, 1) * amp[401] + std::complex (0, 1) * amp[402] - amp[403] + std::complex (0, 1) * amp[405] - amp[406] + std::complex (0, 1) * amp[407] + amp[409] - std::complex (0, 1) * amp[411] + amp[412] + amp[415] - std::complex (0, 1) * amp[417] + amp[418] + amp[420] + amp[421] + amp[423] + amp[424] + amp[426] + amp[427] + amp[429] + amp[430] + amp[435] + amp[441] - std::complex (0, 1) * amp[444] + amp[446] + amp[448] - std::complex (0, 1) * amp[450] + amp[452] + amp[454] + std::complex (0, 1) * amp[457] + amp[458] + std::complex (0, 1) * amp[459] + amp[460] + std::complex (0, 1) * amp[461] + std::complex (0, 1) * amp[463] + amp[464] + std::complex (0, 1) * amp[465] + amp[466] + std::complex (0, 1) * amp[467] - amp[482] - amp[481] - amp[485] - amp[484] - amp[488] - amp[487] - amp[491] - amp[490] + std::complex (0, 1) * amp[725] - std::complex (0, 1) * amp[726] - amp[727] + std::complex (0, 1) * amp[732] - std::complex (0, 1) * amp[730] - std::complex (0, 1) * amp[735] + std::complex (0, 1) * amp[741] - std::complex (0, 1) * amp[739] + std::complex (0, 1) * amp[743] - std::complex (0, 1) * amp[744] - amp[745] + std::complex (0, 1) * amp[750] - std::complex (0, 1) * amp[748] - std::complex (0, 1) * amp[753] + std::complex (0, 1) * amp[759] - std::complex (0, 1) * amp[757] - amp[760] - std::complex (0, 1) * amp[762] - amp[764] - std::complex (0, 1) * amp[765] - amp[767] - amp[768] - std::complex (0, 1) * amp[770] - amp[772] - std::complex (0, 1) * amp[773] - amp[775] + std::complex (0, 1) * amp[830] + amp[831] + std::complex (0, 1) * amp[832] - std::complex (0, 1) * amp[836] + std::complex (0, 1) * amp[834] + std::complex (0, 1) * amp[839] + std::complex (0, 1) * amp[841] + amp[842] - std::complex (0, 1) * amp[845] + std::complex (0, 1) * amp[843] + std::complex (0, 1) * amp[848] + amp[849] + std::complex (0, 1) * amp[850] - std::complex (0, 1) * amp[854] + std::complex (0, 1) * amp[852] + std::complex (0, 1) * amp[857] + std::complex (0, 1) * amp[859] + amp[860] - std::complex (0, 1) * amp[863] + std::complex (0, 1) * amp[861] + std::complex (0, 1) * amp[868] + std::complex (0, 1) * amp[870] + std::complex (0, 1) * amp[871] + std::complex (0, 1) * amp[873] + std::complex (0, 1) * amp[877] + amp[878] + std::complex (0, 1) * amp[879] + std::complex (0, 1) * amp[880] + std::complex (0, 1) * amp[886] + std::complex (0, 1) * amp[888] + std::complex (0, 1) * amp[889] + std::complex (0, 1) * amp[891] + std::complex (0, 1) * amp[895] + amp[896] + std::complex (0, 1) * amp[897] + std::complex (0, 1) * amp[898] + amp[936] + amp[937] + std::complex (0, 1) * amp[939] + std::complex (0, 1) * amp[940] + std::complex (0, 1) * amp[945] + std::complex (0, 1) * amp[946] + amp[948] + amp[949] + std::complex (0, 1) * amp[951] + std::complex (0, 1) * amp[952] + std::complex (0, 1) * amp[957] + std::complex (0, 1) * amp[958] - std::complex (0, 1) * amp[1013] - std::complex (0, 1) * amp[1012] - amp[1016] - amp[1015] - std::complex (0, 1) * amp[1019] - std::complex (0, 1) * amp[1018] - std::complex (0, 1) * amp[1025] - std::complex (0, 1) * amp[1024] - amp[1028] - amp[1027] - std::complex (0, 1) * amp[1031] - std::complex (0, 1) * amp[1030]; jamp[22] = +amp[329] + amp[335] + amp[352] + amp[355] + amp[357] + amp[358] + amp[361] + amp[363] + std::complex (0, 1) * amp[364] + std::complex (0, 1) * amp[365] + std::complex (0, 1) * amp[366] + std::complex (0, 1) * amp[367] - std::complex (0, 1) * amp[384] + amp[385] - std::complex (0, 1) * amp[387] + amp[388] - std::complex (0, 1) * amp[389] - std::complex (0, 1) * amp[390] + amp[391] - std::complex (0, 1) * amp[393] + amp[394] - std::complex (0, 1) * amp[395] + amp[397] + std::complex (0, 1) * amp[398] + amp[400] + amp[403] + std::complex (0, 1) * amp[404] + amp[406] - amp[422] - amp[421] - amp[425] - amp[424] - amp[428] - amp[427] - amp[431] - amp[430] + amp[493] + amp[499] + std::complex (0, 1) * amp[504] - amp[506] - amp[508] + std::complex (0, 1) * amp[510] - amp[512] - amp[514] + std::complex (0, 1) * amp[528] - amp[530] + std::complex (0, 1) * amp[531] - amp[532] + std::complex (0, 1) * amp[533] + std::complex (0, 1) * amp[534] - amp[536] + std::complex (0, 1) * amp[537] - amp[538] + std::complex (0, 1) * amp[539] + amp[542] - amp[540] + amp[545] - amp[543] + amp[548] - amp[546] + amp[551] - amp[549] - std::complex (0, 1) * amp[673] + std::complex (0, 1) * amp[674] + amp[675] - std::complex (0, 1) * amp[680] + std::complex (0, 1) * amp[678] + std::complex (0, 1) * amp[683] - std::complex (0, 1) * amp[689] + std::complex (0, 1) * amp[687] - std::complex (0, 1) * amp[691] + std::complex (0, 1) * amp[692] + amp[693] - std::complex (0, 1) * amp[698] + std::complex (0, 1) * amp[696] + std::complex (0, 1) * amp[701] - std::complex (0, 1) * amp[707] + std::complex (0, 1) * amp[705] + amp[708] + std::complex (0, 1) * amp[710] + amp[712] + std::complex (0, 1) * amp[713] + amp[715] + amp[716] + std::complex (0, 1) * amp[718] + amp[720] + std::complex (0, 1) * amp[721] + amp[723] + std::complex (0, 1) * amp[726] + amp[727] + std::complex (0, 1) * amp[728] - std::complex (0, 1) * amp[732] - std::complex (0, 1) * amp[731] + std::complex (0, 1) * amp[735] + std::complex (0, 1) * amp[737] - amp[738] - std::complex (0, 1) * amp[741] - std::complex (0, 1) * amp[740] + std::complex (0, 1) * amp[744] + amp[745] + std::complex (0, 1) * amp[746] - std::complex (0, 1) * amp[750] - std::complex (0, 1) * amp[749] + std::complex (0, 1) * amp[753] + std::complex (0, 1) * amp[755] - amp[756] - std::complex (0, 1) * amp[759] - std::complex (0, 1) * amp[758] + std::complex (0, 1) * amp[902] - std::complex (0, 1) * amp[908] - std::complex (0, 1) * amp[907] + std::complex (0, 1) * amp[910] + std::complex (0, 1) * amp[911] - amp[912] - std::complex (0, 1) * amp[917] - std::complex (0, 1) * amp[916] + std::complex (0, 1) * amp[920] - std::complex (0, 1) * amp[926] - std::complex (0, 1) * amp[925] + std::complex (0, 1) * amp[928] + std::complex (0, 1) * amp[929] - amp[930] - std::complex (0, 1) * amp[935] - std::complex (0, 1) * amp[934] - amp[938] - amp[937] - std::complex (0, 1) * amp[941] - std::complex (0, 1) * amp[940] - std::complex (0, 1) * amp[947] - std::complex (0, 1) * amp[946] - amp[950] - amp[949] - std::complex (0, 1) * amp[953] - std::complex (0, 1) * amp[952] - std::complex (0, 1) * amp[959] - std::complex (0, 1) * amp[958] - std::complex (0, 1) * amp[989] + std::complex (0, 1) * amp[987] + amp[992] - amp[990] - std::complex (0, 1) * amp[995] + std::complex (0, 1) * amp[993] - std::complex (0, 1) * amp[1001] + std::complex (0, 1) * amp[999] + amp[1004] - amp[1002] - std::complex (0, 1) * amp[1007] + std::complex (0, 1) * amp[1005]; jamp[23] = +amp[328] + amp[334] + amp[336] + amp[339] + amp[341] + amp[342] + amp[345] + amp[347] + std::complex (0, 1) * amp[348] + std::complex (0, 1) * amp[349] + std::complex (0, 1) * amp[350] + std::complex (0, 1) * amp[351] + std::complex (0, 1) * amp[384] - amp[385] + std::complex (0, 1) * amp[387] - amp[388] + std::complex (0, 1) * amp[389] + std::complex (0, 1) * amp[390] - amp[391] + std::complex (0, 1) * amp[393] - amp[394] + std::complex (0, 1) * amp[395] - amp[409] + std::complex (0, 1) * amp[411] - amp[412] - amp[415] + std::complex (0, 1) * amp[417] - amp[418] + amp[422] - amp[420] + amp[425] - amp[423] + amp[428] - amp[426] + amp[431] - amp[429] + amp[433] + amp[439] + std::complex (0, 1) * amp[444] - amp[446] - amp[448] + std::complex (0, 1) * amp[450] - amp[452] - amp[454] + std::complex (0, 1) * amp[468] - amp[470] + std::complex (0, 1) * amp[471] - amp[472] + std::complex (0, 1) * amp[473] + std::complex (0, 1) * amp[474] - amp[476] + std::complex (0, 1) * amp[477] - amp[478] + std::complex (0, 1) * amp[479] + amp[482] - amp[480] + amp[485] - amp[483] + amp[488] - amp[486] + amp[491] - amp[489] + std::complex (0, 1) * amp[673] - std::complex (0, 1) * amp[674] - amp[675] + std::complex (0, 1) * amp[680] - std::complex (0, 1) * amp[678] - std::complex (0, 1) * amp[683] + std::complex (0, 1) * amp[689] - std::complex (0, 1) * amp[687] + std::complex (0, 1) * amp[691] - std::complex (0, 1) * amp[692] - amp[693] + std::complex (0, 1) * amp[698] - std::complex (0, 1) * amp[696] - std::complex (0, 1) * amp[701] + std::complex (0, 1) * amp[707] - std::complex (0, 1) * amp[705] - amp[708] - std::complex (0, 1) * amp[710] - amp[712] - std::complex (0, 1) * amp[713] - amp[715] - amp[716] - std::complex (0, 1) * amp[718] - amp[720] - std::complex (0, 1) * amp[721] - amp[723] - std::complex (0, 1) * amp[830] - amp[831] - std::complex (0, 1) * amp[832] + std::complex (0, 1) * amp[836] - std::complex (0, 1) * amp[834] - std::complex (0, 1) * amp[839] - std::complex (0, 1) * amp[841] - amp[842] + std::complex (0, 1) * amp[845] - std::complex (0, 1) * amp[843] - std::complex (0, 1) * amp[848] - amp[849] - std::complex (0, 1) * amp[850] + std::complex (0, 1) * amp[854] - std::complex (0, 1) * amp[852] - std::complex (0, 1) * amp[857] - std::complex (0, 1) * amp[859] - amp[860] + std::complex (0, 1) * amp[863] - std::complex (0, 1) * amp[861] - std::complex (0, 1) * amp[904] + std::complex (0, 1) * amp[908] - std::complex (0, 1) * amp[906] + std::complex (0, 1) * amp[909] - std::complex (0, 1) * amp[913] - amp[914] + std::complex (0, 1) * amp[917] - std::complex (0, 1) * amp[915] - std::complex (0, 1) * amp[922] + std::complex (0, 1) * amp[926] - std::complex (0, 1) * amp[924] + std::complex (0, 1) * amp[927] - std::complex (0, 1) * amp[931] - amp[932] + std::complex (0, 1) * amp[935] - std::complex (0, 1) * amp[933] + amp[938] - amp[936] + std::complex (0, 1) * amp[941] - std::complex (0, 1) * amp[939] + std::complex (0, 1) * amp[947] - std::complex (0, 1) * amp[945] + amp[950] - amp[948] + std::complex (0, 1) * amp[953] - std::complex (0, 1) * amp[951] + std::complex (0, 1) * amp[959] - std::complex (0, 1) * amp[957] + std::complex (0, 1) * amp[1013] - std::complex (0, 1) * amp[1011] + amp[1016] - amp[1014] + std::complex (0, 1) * amp[1019] - std::complex (0, 1) * amp[1017] + std::complex (0, 1) * amp[1025] - std::complex (0, 1) * amp[1023] + amp[1028] - amp[1026] + std::complex (0, 1) * amp[1031] - std::complex (0, 1) * amp[1029]; // Store the leading color flows for choice of color for(int i = 0; i < ncolor; i++ ) jamp2[0][i] += real(jamp[i] * conj(jamp[i])); return -1.; } double eeuugggg::get_jamp2(int i) { return jamp2[0][i]; } int eeuugggg::colorstring(int i, int j) { static const int res[24][8] = { {5, 6, 7, 8, 3, 4, 0, 0}, {5, 6, 8, 7, 3, 4, 0, 0}, {5, 7, 6, 8, 3, 4, 0, 0}, {5, 7, 8, 6, 3, 4, 0, 0}, {5, 8, 6, 7, 3, 4, 0, 0}, {5, 8, 7, 6, 3, 4, 0, 0}, {6, 5, 7, 8, 3, 4, 0, 0}, {6, 5, 8, 7, 3, 4, 0, 0}, {6, 7, 5, 8, 3, 4, 0, 0}, {6, 7, 8, 5, 3, 4, 0, 0}, {6, 8, 5, 7, 3, 4, 0, 0}, {6, 8, 7, 5, 3, 4, 0, 0}, {7, 5, 6, 8, 3, 4, 0, 0}, {7, 5, 8, 6, 3, 4, 0, 0}, {7, 6, 5, 8, 3, 4, 0, 0}, {7, 6, 8, 5, 3, 4, 0, 0}, {7, 8, 5, 6, 3, 4, 0, 0}, {7, 8, 6, 5, 3, 4, 0, 0}, {8, 5, 6, 7, 3, 4, 0, 0}, {8, 5, 7, 6, 3, 4, 0, 0}, {8, 6, 5, 7, 3, 4, 0, 0}, {8, 6, 7, 5, 3, 4, 0, 0}, {8, 7, 5, 6, 3, 4, 0, 0}, {8, 7, 6, 5, 3, 4, 0, 0}}; return res[i][j]; } int eeuugggg::NCol() { static const int ncolor = 24; return ncolor; } diff --git a/Shower/Dipole/Kinematics/FFMassiveKinematics.h b/Shower/Dipole/Kinematics/FFMassiveKinematics.h --- a/Shower/Dipole/Kinematics/FFMassiveKinematics.h +++ b/Shower/Dipole/Kinematics/FFMassiveKinematics.h @@ -1,305 +1,299 @@ // -*- C++ -*- // // FFMassiveKinematics.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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. // #ifndef HERWIG_FFMassiveKinematics_H #define HERWIG_FFMassiveKinematics_H // // This is the declaration of the FFMassiveKinematics class. // #include "DipoleSplittingKinematics.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Simon Platzer, Stephen Webster * * \brief FFMassiveKinematics implements massive splittings * off a final-final dipole. * */ class FFMassiveKinematics: public DipoleSplittingKinematics { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ FFMassiveKinematics(); /** * The destructor. */ virtual ~FFMassiveKinematics(); //@} public: /** * Return the boundaries in between the evolution * variable random number is to be sampled; the lower * cuoff is assumed to correspond to the infrared cutoff. */ virtual pair kappaSupport(const DipoleSplittingInfo& dIndex) const; /** * Return the boundaries in between the momentum * fraction random number is to be sampled. */ virtual pair xiSupport(const DipoleSplittingInfo& dIndex) const; /** * Return the boundaries on the momentum fraction */ virtual pair zBoundaries(Energy, const DipoleSplittingInfo&, const DipoleSplittingKernel&) const { return {0.0,1.0}; } /** * Return the dipole scale associated to the * given pair of emitter and spectator. This * should be the invariant mass or absolute value * final/final or initial/initial and the absolute * value of the momentum transfer for intial/final or * final/initial dipoles. */ virtual Energy dipoleScale(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator) const; /** * Return the maximum pt for the given dipole scale. */ virtual Energy ptMax(Energy dScale, double emX, double specX, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel& split) const; /** * Return the maximum pt for the given dipole scale. */ virtual Energy ptMax(Energy dScale, double, double, const DipoleIndex& dIndex, const DipoleSplittingKernel& split, tPPtr emitter, tPPtr spectator) const; /** * Return the maximum pt for the given dipole scale. */ virtual Energy ptMax(Energy, double, double, const DipoleIndex&, const DipoleSplittingKernel&) const { // Only the DipoleSplittingInfo version should be used for massive // dipoles, for now anyway. assert(false); return ZERO; } /** * Return the maximum virtuality for the given dipole scale. */ virtual Energy QMax(Energy dScale, double emX, double specX, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel& split) const; /** * Return the maximum virtuality for the given dipole scale. */ virtual Energy QMax(Energy, double, double, const DipoleIndex&, const DipoleSplittingKernel&) const { // Only the DipoleSplittingInfo version should be used for massive // dipoles, for now anyway. assert(false); return ZERO; } /** * Return the pt given a virtuality. */ virtual Energy PtFromQ(Energy scale, const DipoleSplittingInfo&) const; /** * Return the virtuality given a pt. */ virtual Energy QFromPt(Energy scale, const DipoleSplittingInfo&) const; /** * Return the random number associated to * the given pt. */ virtual double ptToRandom(Energy pt, Energy dScale, double emX, double specX, const DipoleIndex& dIndex, const DipoleSplittingKernel& split) const; /** * Generate splitting variables given three random numbers * and the momentum fractions of the emitter and spectator. * Return true on success. */ virtual bool generateSplitting(double kappa, double xi, double phi, DipoleSplittingInfo& dIndex, const DipoleSplittingKernel& split); /** * Generate the full kinematics given emitter and * spectator momentum and a previously completeted * DipoleSplittingInfo object. */ virtual void generateKinematics(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator, const DipoleSplittingInfo& dInfo); public: /** * Triangular / Kallen function */ template inline T rootOfKallen (T a, T b, T c) const { if ( a*a + b*b + c*c - 2.*(a*b + a*c + b*c) > ZERO ) return sqrt(a*a + b*b + c*c - 2.*(a*b + a*c + b*c) ) ; else return ZERO; } /** * Perform a rotation on both momenta such that the first one will * point along the (positive) z axis. Rotate back to the original * reference frame by applying rotateUz(returnedVector) to each momentum. */ ThreeVector rotateToZ (Lorentz5Momentum& pTarget, Lorentz5Momentum& p1){ ThreeVector oldAxis = pTarget.vect().unit(); double ct = oldAxis.z(); double st = sqrt( 1.-sqr(ct) ); // cos,sin(theta) double cp = oldAxis.x()/st; double sp = oldAxis.y()/st; // cos,sin(phi) pTarget.setZ( pTarget.vect().mag() ); pTarget.setX( 0.*GeV ); pTarget.setY( 0.*GeV ); Lorentz5Momentum p1old = p1; p1.setX( sp*p1old.x() - cp*p1old.y() ); p1.setY( ct*cp*p1old.x() + ct*sp*p1old.y() - st*p1old.z() ); p1.setZ( st*cp*p1old.x() + st*sp*p1old.y() + ct*p1old.z() ); return oldAxis; } public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initFFMassiveKinematics; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FFMassiveKinematics & operator=(const FFMassiveKinematics &) = delete; - - /** - * Option to use the full jacobian, including the z->zprime jacobian. - **/ - bool theFullJacobian; - }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of FFMassiveKinematics. */ template <> struct BaseClassTrait { /** Typedef of the first base class of FFMassiveKinematics. */ typedef Herwig::DipoleSplittingKinematics NthBase; }; /** This template specialization informs ThePEG about the name of * the FFMassiveKinematics class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::FFMassiveKinematics"; } /** * The name of a file containing the dynamic library where the class * FFMassiveKinematics is implemented. It may also include several, space-separated, * libraries if the class FFMassiveKinematics depends on other classes (base classes * excepted). In this case the listed libraries will be dynamically * linked in the order they are specified. */ static string library() { return "HwDipoleShower.so"; } }; /** @endcond */ } #endif /* HERWIG_FFMassiveKinematics_H */ diff --git a/Shower/Dipole/Kinematics/FIMassiveDecayKinematics.h b/Shower/Dipole/Kinematics/FIMassiveDecayKinematics.h --- a/Shower/Dipole/Kinematics/FIMassiveDecayKinematics.h +++ b/Shower/Dipole/Kinematics/FIMassiveDecayKinematics.h @@ -1,331 +1,327 @@ // -*- C++ -*- // // FIMassiveDecayKinematics.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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. // #ifndef HERWIG_FIMassiveDecayKinematics_H #define HERWIG_FIMassiveDecayKinematics_H // // This is the declaration of the FIMassiveDecayKinematics class. // #include "DipoleSplittingKinematics.h" #include "ThePEG/EventRecord/Particle.h" #include "ThePEG/Utilities/UtilityBase.h" namespace Herwig { using namespace ThePEG; /** * \ingroup DipoleShower * \author Stephen Webster * * \brief FIMassiveDecayKinematics implements massive splittings * off a final-initial decay dipole. * */ class FIMassiveDecayKinematics: public DipoleSplittingKinematics { public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ FIMassiveDecayKinematics(); /** * The destructor. */ virtual ~FIMassiveDecayKinematics(); //@} public: /** * Return the boundaries in between the evolution * variable random number is to be sampled; the lower * cuoff is assumed to correspond to the infrared cutoff. */ virtual pair kappaSupport(const DipoleSplittingInfo& dIndex) const; /** * Return the boundaries in between the momentum * fraction random number is to be sampled. */ virtual pair xiSupport(const DipoleSplittingInfo& dIndex) const; /** * Return the boundaries on the momentum fraction */ virtual pair zBoundaries(Energy, const DipoleSplittingInfo&, const DipoleSplittingKernel&) const { return {0.0,1.0}; } /** * Return the dipole scale associated to the * given pair of emitter and spectator. This * should be the invariant mass or absolute value * final/final or initial/initial and the absolute * value of the momentum transfer for intial/final or * final/initial dipoles. */ virtual Energy dipoleScale(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator) const; /** * Return the mass of the system absorbing * the recoil in the dipole splitting. * This is only used in decay dipoles. */ virtual Energy recoilMassKin(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator) const; /** * Return the maximum pt for the given dipole scale. */ virtual Energy ptMax(Energy dScale, double emX, double specX, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel& split) const; /** * Return the maximum pt for the given dipole scale. */ virtual Energy ptMax(Energy dScale, double, double, const DipoleIndex& dIndex, const DipoleSplittingKernel& split, tPPtr emitter, tPPtr spectator) const; /** * Return the maximum virtuality for the given dipole scale. */ virtual Energy QMax(Energy dScale, double emX, double specX, const DipoleSplittingInfo& dInfo, const DipoleSplittingKernel& split) const; /** * Return the maximum pt for the given dipole scale. */ virtual Energy ptMax(Energy, double, double, const DipoleIndex&, const DipoleSplittingKernel&) const { // Only the DipoleSplittingInfo version should be used for the decays. assert(false); return ZERO; } /** * Return the maximum virtuality for the given dipole scale. */ virtual Energy QMax(Energy, double, double, const DipoleIndex&, const DipoleSplittingKernel&) const { // Only the DipoleSplittingInfo version should be used for the decays. assert(false); return ZERO; } /** * Return the pt given a virtuality. */ virtual Energy PtFromQ(Energy scale, const DipoleSplittingInfo&) const; /** * Return the virtuality given a pt. */ virtual Energy QFromPt(Energy scale, const DipoleSplittingInfo&) const; /** * Return the random number associated to * the given pt. */ virtual double ptToRandom(Energy pt, Energy dScale, double emX, double specX, const DipoleIndex& dIndex, const DipoleSplittingKernel& split) const; /** * Generate splitting variables given three random numbers * and the momentum fractions of the emitter and spectator. * Return true on success. */ virtual bool generateSplitting(double kappa, double xi, double phi, DipoleSplittingInfo& info, const DipoleSplittingKernel& split); /** * Generate the full kinematics given emitter and * spectator momentum and a previously completeted * DipoleSplittingInfo object. */ virtual void generateKinematics(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator, const DipoleSplittingInfo& dInfo); /** * Return the nVector as required for spin correlations. */ virtual Lorentz5Momentum nVector(const Lorentz5Momentum& pEmitter, const Lorentz5Momentum& pSpectator, const DipoleSplittingInfo& dInfo) const; /* * Return true if this splitting is of a dipole which contains * a decayed parton and requires the remnant to absorb the recoil. */ virtual bool isDecay() const { return true; } /** * Perform the recoil in the case of a decayed parton */ virtual void decayRecoil ( PList& recoilSystem ) { PList::iterator beginRecoil = recoilSystem.begin(); PList::iterator endRecoil = recoilSystem.end(); // This is the final momentum that we must transform the system to const Momentum3 transformMom = splitRecoilMomentum().vect(); // Calculate required Lorentz rotation Lorentz5Momentum sum = ThePEG::UtilityBase::sumMomentum(beginRecoil, endRecoil); LorentzRotation rot = ThePEG::UtilityBase::transformToCMS(sum); rot = ThePEG::UtilityBase::transformFromCMS (Lorentz5Momentum(transformMom, sqrt(transformMom.mag2() + sum.m2()))) * rot; // Transform the particle spinInfo if required for ( const auto& p : recoilSystem ) { if ( p->spinInfo() ) p->spinInfo()->transform(p->momentum(),rot); } ThePEG::UtilityBase::transform(beginRecoil, endRecoil, rot ); } public: /** * Triangular / Kallen function */ template inline T rootOfKallen (T a, T b, T c) const { if ( a*a + b*b + c*c - 2.*(a*b + a*c + b*c) > ZERO ) return sqrt(a*a + b*b + c*c - 2.*(a*b + a*c + b*c) ) ; else return ZERO; } public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The static object used to initialize the description of this class. * Indicates that this is a concrete class with persistent data. */ static ClassDescription initFIMassiveDecayKinematics; /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ FIMassiveDecayKinematics & operator=(const FIMassiveDecayKinematics &) = delete; - - /** - * Option to use the full jacobian, including the z->zprime jacobian. - **/ - bool theFullJacobian; + }; } #include "ThePEG/Utilities/ClassTraits.h" namespace ThePEG { /** @cond TRAITSPECIALIZATIONS */ /** This template specialization informs ThePEG about the * base classes of FIMassiveDecayKinematics. */ template <> struct BaseClassTrait { /** Typedef of the first base class of FIMassiveDecayKinematics. */ typedef Herwig::DipoleSplittingKinematics NthBase; }; /** This template specialization informs ThePEG about the name of * the FIMassiveDecayKinematics class and the shared object where it is defined. */ template <> struct ClassTraits : public ClassTraitsBase { /** Return a platform-independent class name */ static string className() { return "Herwig::FIMassiveDecayKinematics"; } /** * The name of a file containing the dynamic library where the class * FIMassiveDecayKinematics is implemented. It may also include several, space-separated, * libraries if the class FIMassiveDecayKinematics depends on other classes (base classes * excepted). In this case the listed libraries will be dynamically * linked in the order they are specified. */ static string library() { return "HwDipoleShower.so"; } }; /** @endcond */ } #endif /* HERWIG_FIMassiveDecayKinematics_H */ diff --git a/Shower/Dipole/Merging/Node.cc b/Shower/Dipole/Merging/Node.cc --- a/Shower/Dipole/Merging/Node.cc +++ b/Shower/Dipole/Merging/Node.cc @@ -1,489 +1,489 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the Node class. // #include "Node.h" #include "MergingFactory.h" #include "Merger.h" using namespace Herwig; Node::Node(MatchboxMEBasePtr nodeME, int cutstage, MergerPtr mh) :Interfaced(), thenodeMEPtr(nodeME), thedipol(), theparent(), theCutStage(cutstage), - isOrdered(true), + //isOrdered(true), theSubtractedReal(false), theVirtualContribution(false), theMergingHelper(mh) { nodeME->maxMultCKKW(1); nodeME->minMultCKKW(0); } Node::Node(NodePtr deephead, NodePtr head, SubtractionDipolePtr dipol, MatchboxMEBasePtr nodeME, int cutstage) :Interfaced(), thenodeMEPtr(nodeME), thedipol(dipol), theparent(head), theDeepHead(deephead), theCutStage(cutstage), -isOrdered(true), +//isOrdered(true), theSubtractedReal(false), theVirtualContribution(false), theMergingHelper() //The subnodes have no merging helper { } Node::~Node() { } SubtractionDipolePtr Node::dipole() const { return thedipol; } /** returns the matrix element pointer */ const MatchboxMEBasePtr Node::nodeME() const { return thenodeMEPtr; } /** access the matrix element pointer */ MatchboxMEBasePtr Node::nodeME() { return thenodeMEPtr; } pair Node::getInOut( ){ PVector in; const auto me= nodeME(); const auto pd=me->mePartonData(); for( auto i : {0 , 1} ) in.push_back(pd[i]->produceParticle( me->lastMEMomenta()[i] ) ); PVector out; for ( size_t i = 2;i< pd.size();i++ ){ PPtr p = pd[i]->produceParticle( me->lastMEMomenta()[i] ); out.push_back( p ); } return { in , out }; } int Node::legsize() const {return nodeME()->legsize();} NodePtr Node::randomChild() { return thechildren[UseRandom::irnd(thechildren.size())]; } bool Node::allAbove(Energy pt) { for (NodePtr child : thechildren) if ( child->pT() < pt ) return false; return true; } Energy Node::maxChildPt(){ Energy maxi=-1*GeV; for (NodePtr child : thechildren)maxi=max(child->pT(),maxi); return maxi; } bool Node::isInHistoryOf(NodePtr other) { while (other->parent()) { if (other == this) return true; other = other->parent(); } return false; } void Node::flushCaches() { if (didflush) return; didflush=true; for ( auto const & ch: thechildren) { ch->xcomb()->clean(); ch->nodeME()->flushCaches(); ch->flushCaches(); } } void Node::setKinematics() { for (auto const & ch: thechildren) { ch->dipole()->setXComb(ch->xcomb()); ch->dipole()->setKinematics(); ch->nodeME()->setKinematics(); ch->setKinematics(); } } void Node::clearKinematics() { for (auto const & ch: thechildren) { ch->dipole()->setXComb(ch->xcomb()); ch->nodeME()->clearKinematics(); ch->dipole()->clearKinematics(); ch->clearKinematics(); } } bool Node::generateKinematics(const double *r, bool directCut) { didflush=false; // If there are no children to the child process we are done. if(children().empty()) return true; assert(parent()); if ( ! directCut && pT() < deepHead()->MH()->mergePt()) { // Real emission: // If there are children to the child process, // we now require that all subsequent children // with pt < merging scale are in their ME region. // Since the possible children of the real emission // contribution are now in their ME region, // it is clear that a second clustering is possible // -- modulo phase space restrictions. // Therefore the real emission contribution // are unitarised and the cross section is // hardly modified. auto inOutPair = getInOut(); NodePtr rc = randomChild(); rc->dipole()->setXComb(rc->xcomb()); if(!rc->dipole()->generateKinematics(r))assert(false); // If not in ME -> return false if(!deepHead()->MH()->matrixElementRegion( inOutPair.first , inOutPair.second , rc->pT() , deepHead()->MH()->mergePt() ) )return false; } for (auto & ch : children() ) { ch->dipole()->setXComb(ch->xcomb()); if ( !ch->dipole()->generateKinematics(r) ) { assert(false); } ch->generateKinematics( r, true); } return true; } bool Node::firstgenerateKinematics(const double *r, bool directCut) { didflush=false; // This is called form the merging helper for the first node. So: assert(!parent()); assert(xcomb()); if(MH()->treefactory()->nonQCDCuts()){ tcPDVector outdata(xcomb()->mePartonData().begin()+2, xcomb()->mePartonData().end()); vector outmomenta(xcomb()->meMomenta().begin()+2, xcomb()->meMomenta().end()); if ( !MH()->treefactory()->nonQCDCuts()->passCuts(outdata,outmomenta, xcomb()->mePartonData()[0], xcomb()->mePartonData()[1]) ) return false; } ///// This should not be needed!!! ///// ( Warning inMerger::matrixElementRegion gets triggered.) flushCaches(); //Set here the new merge Pt for the next phase space point.( Smearing!!!) MH()->smearMergePt(); // If there are no children to this node, we are done here: if (children().empty()) return true; // directCut is for born and for virtual contributions. // if directCut is true, then cut on the first ME region. // call recursiv generate kinematics for subsequent nodes. if ( directCut ){ auto inOutPair = getInOut(); NodePtr rc = randomChild(); rc->dipole()->setXComb(rc->xcomb()); if ( !rc->dipole()->generateKinematics(r) ) { return false; } rc->nodeME()->setXComb(rc->xcomb()); if(MH()->gamma() == 1.){ if(!MH()->matrixElementRegion( inOutPair.first , inOutPair.second , rc->pT() , MH()->mergePt() ) ){ return false; } }else{ // Different treatment if gamma is not 1. // Since the dipoles need to be calculated always // their alpha region is touched. // AlphaRegion != MERegion !!! bool inAlphaPS = false; for (auto const & ch: thechildren) { ch->dipole()->setXComb(ch->xcomb()); if ( !ch->dipole()->generateKinematics(r) ) return false; MH()->treefactory()->setAlphaParameter( MH()->gamma() ); inAlphaPS |= ch->dipole()->aboveAlpha(); MH()->treefactory()->setAlphaParameter( 1. ); } NodePtr rc = randomChild(); if(!inAlphaPS&& !MH()->matrixElementRegion( inOutPair.first , inOutPair.second , rc->pT() , MH()->mergePt() ) ) return false; } } for (auto const & ch: thechildren) { ch->dipole()->setXComb(ch->xcomb()); if ( !ch->dipole()->generateKinematics(r) ) { cout<<"\nCould not generate dipole kinematics";;return false; } if( ! ch->generateKinematics(r,directCut) )return false; } return true; } StdXCombPtr Node::xcomb() const { assert(thexcomb); return thexcomb; } StdXCombPtr Node::xcomb(){ if(thexcomb)return thexcomb; assert(parent()); thexcomb=dipole()->makeBornXComb(parent()->xcomb()); xcomb()->head(parent()->xcomb()); dipole()->setXComb(thexcomb); return thexcomb; } void Node::setXComb(tStdXCombPtr xc) { assert ( !parent() ); thexcomb=xc; assert(thexcomb->lastParticles().first); } #include "Herwig/MatrixElement/Matchbox/Base/DipoleRepository.h" void Node::birth(const vector & vec) { // produce the children vector dipoles = nodeME()->getDipoles(DipoleRepository::dipoles( nodeME()->factory()->dipoleSet()), vec, true); for ( auto const & dip : dipoles ) { dip->doSubtraction(); NodePtr node = new_ptr(Node(theDeepHead, this, dip, dip->underlyingBornME(), theDeepHead->cutStage())); thechildren.push_back(node); } } vector Node::getNextOrderedNodes(bool normal, double hardScaleFactor) const { vector temp = children(); vector res; for (NodePtr const & child : children()) { if(deepHead()->MH()->mergePt()>child->pT()) { res.clear(); return res; } } for (NodePtr const & child: children()) { if (parent()&& normal) { if ( child->pT() < pT() ) { continue; } } if ( child->children().size() != 0 ) { for (NodePtr itChild: child->children()) { if( itChild->pT() > child->pT()&&child->inShowerPS(itChild->pT()) ) { res.push_back(child); break; } } } else { const auto sc=child->nodeME()->factory()->scaleChoice(); sc->setXComb(child->xcomb()); if ( sqr(hardScaleFactor)* sc->renormalizationScale() >= sqr(child->pT()) && child->inShowerPS(hardScaleFactor*sqrt(sc->renormalizationScale()))) { res.push_back(child); } } } return res; } bool Node::inShowerPS(Energy hardpT)const { // Here we decide if the current phase space // point can be reached from the underlying Node. // Full phase space available -> Tilde Kinematic is always fine. if(deepHead()->MH()->openZBoundaries()==1) return true; double z_ = dipole()->lastZ(); // restrict according to hard scale if(deepHead()->MH()->openZBoundaries()==0){ pair zbounds = dipole()->tildeKinematics()->zBounds(pT(), hardpT); return (zbounds.first temp = getNextOrderedNodes(normal, hardScaleFactor); Energy minpt = Constants::MaxEnergy; Selector subprosel; while (temp.size() != 0) { minpt = Constants::MaxEnergy; subprosel.clear(); for (NodePtr const & child : temp) { assert(deepHead()->MH()->largeNBasis()); if( child->dipole()->underlyingBornME()->largeNColourCorrelatedME2( {child->dipole()->bornEmitter(), child->dipole()->bornSpectator()}, deepHead()->MH()->largeNBasis()) != 0. ) { double weight = 1.; if ( deepHead()->MH()->chooseHistory() == 0 ) weight = abs(child->dipole()->dSigHatDR()/nanobarn); else if ( deepHead()->MH()->chooseHistory() == 1 ) weight = abs(child->dipole()->dSigHatDR()/child->nodeME()->dSigHatDRB()); else if ( deepHead()->MH()->chooseHistory() == 2 ) weight = 1.; else if ( deepHead()->MH()->chooseHistory() == 3 ) weight = 1_GeV/child->pT(); else assert(false); if(weight != 0.) { subprosel.insert(weight , child); minpt = min(minpt, child->pT()); } } } if (subprosel.empty()) return res; res = subprosel.select(UseRandom::rnd()); temp = res->getNextOrderedNodes(true, hardScaleFactor); } return res; } pair Node::calcDipandPS(Energy scale)const { return dipole()->dipandPs(sqr(scale), deepHead()->MH()->largeNBasis()); } CrossSection Node::calcPs(Energy scale)const { return dipole()->ps(sqr(scale), deepHead()->MH()->largeNBasis()); } CrossSection Node::calcDip(Energy scale)const { return dipole()->dip(sqr(scale)); } IBPtr Node::clone() const { return new_ptr(*this); } IBPtr Node::fullclone() const { return new_ptr(*this); } #include "ThePEG/Persistency/PersistentOStream.h" void Node::persistentOutput(PersistentOStream & os) const { os << thexcomb<< thenodeMEPtr<< thedipol<< thechildren<< theparent<< theProjector<< theDeepHead<< theCutStage<< ounit(theRunningPt, GeV)<< theSubtractedReal<< theVirtualContribution<< theMergingHelper; } #include "ThePEG/Persistency/PersistentIStream.h" void Node::persistentInput(PersistentIStream & is, int) { is >> thexcomb>> thenodeMEPtr>> thedipol>> thechildren>> theparent>> theProjector>> theDeepHead>> theCutStage>> iunit(theRunningPt, GeV)>> theSubtractedReal>> theVirtualContribution>> theMergingHelper; } // *** 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). #include "ThePEG/Utilities/DescribeClass.h" DescribeClass describeHerwigNode("Herwig::Node", "HwDipoleShower.so"); void Node::Init() { static ClassDocumentation documentation("There is no documentation for the Node class"); } diff --git a/Shower/Dipole/Merging/Node.h b/Shower/Dipole/Merging/Node.h --- a/Shower/Dipole/Merging/Node.h +++ b/Shower/Dipole/Merging/Node.h @@ -1,237 +1,237 @@ // -*- C++ -*- #ifndef Herwig_Node_H #define Herwig_Node_H // // This is the declaration of the Node class. // #include "Node.fh" #include "MergingFactory.fh" #include "Merger.h" #include "ThePEG/Config/ThePEG.h" #include "ThePEG/Config/std.h" #include "ThePEG/Interface/Interfaced.h" #include "Herwig/MatrixElement/Matchbox/Base/MatchboxMEBase.fh" #include "Herwig/MatrixElement/Matchbox/Dipoles/SubtractionDipole.fh" #include "Herwig/Shower/Dipole/Base/DipoleEventRecord.h" #include "ThePEG/MatrixElement/MEBase.h" #include namespace Herwig { using namespace ThePEG; /** * Here is the documentation of the Node class. * * @see \ref NodeInterfaces "The interfaces" * defined for Node. */ class Node : public Interfaced { public: /** @name Standard constructors and destructors. */ //@{ Node (){}; // constructor for first nodes Node(MatchboxMEBasePtr nodeME , int cutstage , MergerPtr mh ); // another constructor for underlying nodes Node(NodePtr deephead, NodePtr head, SubtractionDipolePtr dipol, MatchboxMEBasePtr nodeME, int cutstage); /// The destructor. virtual ~Node(); //@} public: // get children from vector void birth(const vector & vec); /// recursive setXComb. proStage is the number of clusterings /// before the projectors get filled. void setXComb(tStdXCombPtr xc); /// calculate the dipole and ps approximation pair calcDipandPS(Energy scale)const; /// calculate the ps approximation CrossSection calcPs(Energy scale)const; /// calculate the dipole CrossSection calcDip(Energy scale)const; /// recursive flush caches and clean up XCombs. void flushCaches(); /// recursive clearKinematics void clearKinematics(); /// recursive setKinematics void setKinematics(); /// recursive generateKinematics using tilde kinematics of the dipoles bool generateKinematics(const double *r, bool directCut); /// generate the kinamatics of the first node bool firstgenerateKinematics(const double *r, bool directCut); //return the ME const MatchboxMEBasePtr nodeME() const; //return the node ME MatchboxMEBasePtr nodeME(); //return the parent Node NodePtr parent() const {return theparent;} /// vector of children nodes created in birth vector< NodePtr > children() const {return thechildren;} //pick a random child (flat) NodePtr randomChild(); /// true if all children show scales above pt bool allAbove(Energy pt); /// return maximum of all child pts. Energy maxChildPt(); /// true if the node is in the history of other. bool isInHistoryOf(NodePtr other); /// legsize of the node ME int legsize() const; /// set the first node (first men). only use in factory void deepHead(NodePtr deephead) {theDeepHead = deephead;} /// return the first node NodePtr deepHead() const {return theDeepHead;} /// returns the dipol of the node. SubtractionDipolePtr dipole() const; /// return the xcomb StdXCombPtr xcomb() const; /// return the xcomb (if not created, create one from head) StdXCombPtr xcomb() ; /// return the current running pt Energy runningPt() const { return theRunningPt; } /// set the current running pt void runningPt(Energy x) { theRunningPt=x; } /// return the cut stage to cut on merging pt in generate kinematics int cutStage() const { return theCutStage; } /// get a vector of the next nodes, ordered in pt (and in parton shower phace space) vector getNextOrderedNodes(bool normal=true, double hardscalefactor=1.) const; //true if the node is in shower history for a given pt bool inShowerPS(Energy hardpt)const; //get the history NodePtr getHistory(bool normal=true, double hardscalefactor=1.); //true if node correspond to a subtracted real. bool subtractedReal() const {return theSubtractedReal;} /// set if node correspont to a subtracted real. void subtractedReal(bool x) { theSubtractedReal = x;} //true if node correspond to a virtual contribution. bool virtualContribution() const { return theVirtualContribution ;} /// set if node correspont to a virtual contribution. void virtualContribution(bool x) {theVirtualContribution = x;} //pointer to the merging helper MergerPtr MH()const{return theMergingHelper;} /// set the merging helper void MH(MergerPtr a){theMergingHelper=a;} /// pT of the dipole Energy pT()const{return dipole()->lastPt();} /// get incoming and outgoing particles (TODO: expensive) pair getInOut(); private: /// the Matrixelement representing this node. MatchboxMEBasePtr thenodeMEPtr; /// the dipol used to substract /// and generate kinematics using tilde kinematics SubtractionDipolePtr thedipol; /// the parent node NodePtr theparent; /// The godfather node of whole tree.(Firstnode) NodePtr theDeepHead; /** * The CutStage is number of clusterings which are possible without * introducing a merging scale to cut away singularities. * -> subtracted MEs have the CutStage 1. * -> virtual and normal tree level ME get 0. */ int theCutStage; /// tell if node belongs to an ordered history - bool isOrdered; + // bool isOrdered; /// flag to tell if node is subtracted real bool theSubtractedReal; /// flag to tell if node is virtual contribution bool theVirtualContribution; /// the merging helper MergerPtr theMergingHelper; //the xcomb of the node StdXCombPtr thexcomb; /// vector of the children node vector< NodePtr > thechildren; /// the current running pt Energy theRunningPt; /// The nodes of the projection stage. NodePtr theProjector; /// flag not to enter infinite loop. (There should be a better solution...) bool didflush=false; public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} // If needed, insert declarations of virtual function defined in the // InterfacedBase class here (using ThePEG-interfaced-decl in Emacs). private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ Node & operator=(const Node &) = delete; }; } #endif /* Herwig_Node_H */ diff --git a/Shower/QTilde/QTildeShowerHandler.h b/Shower/QTilde/QTildeShowerHandler.h --- a/Shower/QTilde/QTildeShowerHandler.h +++ b/Shower/QTilde/QTildeShowerHandler.h @@ -1,846 +1,841 @@ // -*- C++ -*- #ifndef Herwig_QTildeShowerHandler_H #define Herwig_QTildeShowerHandler_H // // This is the declaration of the QTildeShowerHandler class. // #include "QTildeShowerHandler.fh" #include "Herwig/Shower/ShowerHandler.h" #include "Herwig/Shower/QTilde/SplittingFunctions/SplittingGenerator.h" #include "Herwig/Shower/QTilde/Base/ShowerTree.h" #include "Herwig/Shower/QTilde/Base/ShowerProgenitor.fh" #include "Herwig/Shower/QTilde/Base/HardTree.h" #include "Herwig/Shower/QTilde/Base/Branching.h" #include "Herwig/Shower/QTilde/Base/ShowerVeto.h" #include "Herwig/Shower/QTilde/Base/FullShowerVeto.h" #include "Herwig/Shower/QTilde/Kinematics/KinematicsReconstructor.fh" #include "Herwig/Shower/QTilde/Base/PartnerFinder.fh" #include "Herwig/Shower/QTilde/SplittingFunctions/SudakovFormFactor.fh" #include "Herwig/MatrixElement/HwMEBase.h" #include "Herwig/Decay/HwDecayerBase.h" #include "Herwig/MatrixElement/Matchbox/Matching/ShowerApproximation.h" #include "Herwig/Shower/RealEmissionProcess.h" #include "Herwig/Utilities/Statistic.h" namespace Herwig { using namespace ThePEG; /** * The QTildeShowerHandler class. * * @see \ref QTildeShowerHandlerInterfaces "The interfaces" * defined for QTildeShowerHandler. */ class QTildeShowerHandler: public ShowerHandler { public: /** * Pointer to an XComb object */ typedef Ptr::pointer XCPtr; public: /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ QTildeShowerHandler(); /** * The destructor. */ virtual ~QTildeShowerHandler(); //@} public: /** * At the end of the Showering, transform ShowerParticle objects * into ThePEG particles and fill the event record with them. * Notice that the parent/child relationships and the * transformation from ShowerColourLine objects into ThePEG * ColourLine ones must be properly handled. */ void fillEventRecord(); /** * Return the relevant hard scale to be used in the profile scales */ virtual Energy hardScale() const { return muPt; } /** * Hook to allow vetoing of event after showering hard sub-process * as in e.g. MLM merging. */ virtual bool showerHardProcessVeto() const { return false; } /** * Generate hard emissions for CKKW etc */ virtual HardTreePtr generateCKKW(ShowerTreePtr tree) const; /** * Members to perform the shower */ //@{ /** * Perform the shower of the hard process */ virtual void showerHardProcess(ShowerTreePtr,XCPtr); /** * Perform the shower of a decay */ virtual void showerDecay(ShowerTreePtr); //@} /** * Access to the flags and shower variables */ //@{ /** * Get the SplittingGenerator */ tSplittingGeneratorPtr splittingGenerator() const { return _splittingGenerator; } /** * Mode for hard emissions */ int hardEmission() const {return _hardEmission;} //@} /** * Connect the Hard and Shower trees */ virtual void connectTrees(ShowerTreePtr showerTree, HardTreePtr hardTree, bool hard ); /** * Access to switches for spin correlations */ //@{ /** * Soft correlations */ unsigned int softCorrelations() const { return _softOpt; } /** * Any correlations */ virtual bool correlations() const { return spinCorrelations()!=0||_softOpt!=0; } //@} public: /** * Access methods to access the objects */ //@{ /** * Access to the KinematicsReconstructor object */ tKinematicsReconstructorPtr kinematicsReconstructor() const { return _reconstructor; } /** * Access to the PartnerFinder object */ tPartnerFinderPtr partnerFinder() const { return _partnerfinder; } //@} protected: /** * Perform the shower */ void doShowering(bool hard,XCPtr); /** * Generate the hard matrix element correction */ virtual RealEmissionProcessPtr hardMatrixElementCorrection(bool); /** * Generate the hardest emission */ virtual void hardestEmission(bool hard); /** * Set up for applying a matrix element correction */ void setupMECorrection(RealEmissionProcessPtr real); /** * Extract the particles to be showered, set the evolution scales * and apply the hard matrix element correction * @param hard Whether this is a hard process or decay * @return The particles to be showered */ virtual vector setupShower(bool hard); /** * set the colour partners */ virtual void setEvolutionPartners(bool hard,ShowerInteraction, bool clear); /** * Methods to perform the evolution of an individual particle, including * recursive calling on the products */ //@{ /** * It does the forward evolution of the time-like input particle * (and recursively for all its radiation products). * accepting only emissions which conforms to the showerVariables * and soft matrix element correction. * If at least one emission has occurred then the method returns true. * @param particle The particle to be showered */ virtual bool timeLikeShower(tShowerParticlePtr particle, ShowerInteraction, Branching fb, bool first); /** * It does the backward evolution of the space-like input particle * (and recursively for all its time-like radiation products). * accepting only emissions which conforms to the showerVariables. * If at least one emission has occurred then the method returns true * @param particle The particle to be showered * @param beam The beam particle */ virtual bool spaceLikeShower(tShowerParticlePtr particle,PPtr beam, ShowerInteraction); /** * If does the forward evolution of the input on-shell particle * involved in a decay * (and recursively for all its time-like radiation products). * accepting only emissions which conforms to the showerVariables. * @param particle The particle to be showered * @param maxscale The maximum scale for the shower. * @param minimumMass The minimum mass of the final-state system */ virtual bool spaceLikeDecayShower(tShowerParticlePtr particle, const ShowerParticle::EvolutionScales & maxScales, Energy minimumMass,ShowerInteraction, Branching fb); /** * Truncated shower from a time-like particle */ virtual bool truncatedTimeLikeShower(tShowerParticlePtr particle, HardBranchingPtr branch, ShowerInteraction type, Branching fb, bool first); /** * Truncated shower from a space-like particle */ virtual bool truncatedSpaceLikeShower(tShowerParticlePtr particle,PPtr beam, HardBranchingPtr branch, ShowerInteraction type); /** * Truncated shower from a time-like particle */ virtual bool truncatedSpaceLikeDecayShower(tShowerParticlePtr particle, const ShowerParticle::EvolutionScales & maxScales, Energy minimumMass, HardBranchingPtr branch, ShowerInteraction type, Branching fb); //@} /** * Switches for matrix element corrections */ //@{ /** * Any ME correction? */ bool MECOn() const { return _hardEmission == 1; } /** * Any hard ME correction? */ bool hardMEC() const { return _hardEmission == 1 && (_meCorrMode == 1 || _meCorrMode == 2); } /** * Any soft ME correction? */ bool softMEC() const { return _hardEmission == 1 && (_meCorrMode == 1 || _meCorrMode > 2); } //@} /** * Is the truncated shower on? */ bool isTruncatedShowerON() const {return _trunc_Mode;} /** * Switch for intrinsic pT */ //@{ /** * Any intrinsic pT? */ bool ipTon() const { return _iptrms != ZERO || ( _beta == 1.0 && _gamma != ZERO && _iptmax !=ZERO ); } //@} /**@name Additional shower vetoes */ //@{ /** * Insert a veto. */ void addVeto (ShowerVetoPtr v) { _vetoes.push_back(v); } /** * Remove a veto. */ void removeVeto (ShowerVetoPtr v) { vector::iterator vit = find(_vetoes.begin(),_vetoes.end(),v); if (vit != _vetoes.end()) _vetoes.erase(vit); } //@} /** * Switches for vetoing hard emissions */ //@{ /** * Returns true if the hard veto read-in is to be applied to only * the primary collision and false otherwise. */ bool hardVetoReadOption() const {return _hardVetoReadOption;} //@} /** * Enhancement factors for radiation needed to generate the soft matrix * element correction. */ //@{ /** * Access the enhancement factor for initial-state radiation */ double initialStateRadiationEnhancementFactor() const { return _initialenhance; } /** * Access the enhancement factor for final-state radiation */ double finalStateRadiationEnhancementFactor() const { return _finalenhance; } /** * Set the enhancement factor for initial-state radiation */ void initialStateRadiationEnhancementFactor(double in) { _initialenhance=in; } /** * Set the enhancement factor for final-state radiation */ void finalStateRadiationEnhancementFactor(double in) { _finalenhance=in; } //@} /** * Access to set/get the HardTree currently beinging showered */ //@{ /** * The HardTree currently being showered */ tHardTreePtr hardTree() {return _hardtree;} /** * The HardTree currently being showered */ void hardTree(tHardTreePtr in) {_hardtree = in;} //@} /** * Access/set the beam particle for the current initial-state shower */ //@{ /** * Get the beam particle data */ Ptr::const_pointer beamParticle() const { return _beam; } /** * Set the beam particle data */ void setBeamParticle(Ptr::const_pointer in) { _beam=in; } //@} /** * Set/Get the current tree being evolver for inheriting classes */ //@{ /** * Get the tree */ tShowerTreePtr currentTree() { return _currenttree; } /** * Set the tree */ void currentTree(tShowerTreePtr tree) { _currenttree=tree; } //@} /** * Access the maximum number of attempts to generate the shower */ unsigned int maximumTries() const { return _maxtry; } /** * Set/Get the ShowerProgenitor for the current shower */ //@{ /** * Access the progenitor */ ShowerProgenitorPtr progenitor() { return _progenitor; } /** * Set the progenitor */ void progenitor(ShowerProgenitorPtr in) { _progenitor=in; } //@} /** * Calculate the intrinsic \f$p_T\f$. */ virtual void generateIntrinsicpT(vector); /** * Access to the intrinsic \f$p_T\f$ for inheriting classes */ map > & intrinsicpT() { return _intrinsic; } /** * find the maximally allowed pt acc to the hard process. */ void setupMaximumScales(const vector &,XCPtr); /** * find the relevant hard scales for profile scales. */ void setupHardScales(const vector &,XCPtr); /** * Convert the HardTree into an extra shower emission */ void convertHardTree(bool hard,ShowerInteraction type); protected: /** * Find the parton extracted from the incoming particle after ISR */ PPtr findFirstParton(tPPtr seed) const; /** * Fix Remnant connections after ISR */ tPPair remakeRemnant(tPPair oldp); protected: /** * Start the shower of a timelike particle */ virtual bool startTimeLikeShower(ShowerInteraction); /** * Update of the time-like stuff */ void updateHistory(tShowerParticlePtr particle); /** * Start the shower of a spacelike particle */ virtual bool startSpaceLikeShower(PPtr,ShowerInteraction); /** * Start the shower of a spacelike particle */ virtual bool startSpaceLikeDecayShower(const ShowerParticle::EvolutionScales & maxScales, Energy minimumMass,ShowerInteraction); /** * Select the branching for the next time-like emission */ Branching selectTimeLikeBranching(tShowerParticlePtr particle, ShowerInteraction type, HardBranchingPtr branch); /** * Select the branching for the next space-like emission in a decay */ Branching selectSpaceLikeDecayBranching(tShowerParticlePtr particle, const ShowerParticle::EvolutionScales & maxScales, Energy minmass,ShowerInteraction type, HardBranchingPtr branch); /** * Create the timelike child of a branching */ ShowerParticleVector createTimeLikeChildren(tShowerParticlePtr particle, IdList ids); /** * Vetos for the timelike shower */ virtual bool timeLikeVetoed(const Branching &,ShowerParticlePtr); /** * Vetos for the spacelike shower */ virtual bool spaceLikeVetoed(const Branching &,ShowerParticlePtr); /** * Vetos for the spacelike shower */ virtual bool spaceLikeDecayVetoed(const Branching &,ShowerParticlePtr); /** * Only generate the hard emission, for testing only. */ bool hardOnly() const {return _limitEmissions==3;} /** * Check the flags */ void checkFlags(); /** * */ void addFSRUsingDecayPOWHEG(HardTreePtr ISRTree); public: /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); protected: /** * The main method which manages the showering of a subprocess. */ virtual tPPair cascade(tSubProPtr sub, XCPtr xcomb); /** * Decay a ShowerTree */ void decay(ShowerTreePtr tree, ShowerDecayMap & decay); protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} protected: /** * Initialize this object after the setup phase before saving an * EventGenerator to disk. * @throws InitException if object could not be initialized properly. */ virtual void doinit(); /** * Initialize this object. Called in the run phase just before * a run begins. */ virtual void doinitrun(); //@} private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ QTildeShowerHandler & operator=(const QTildeShowerHandler &) = delete; private: /** * Stuff from the ShowerHandler */ //@{ /** * The ShowerTree for the hard process */ ShowerTreePtr hard_; /** * The ShowerTree for the decays */ ShowerDecayMap decay_; /** * The ShowerTrees for which the initial shower */ vector done_; //@} private : /** * Pointer to the splitting generator */ SplittingGeneratorPtr _splittingGenerator; /** * Maximum number of tries to generate the shower of a particular tree */ unsigned int _maxtry; /** * Matrix element correction switch */ unsigned int _meCorrMode; /** * Control of the reconstruction option */ unsigned int _evolutionScheme; /** * If hard veto pT scale is being read-in this determines * whether the read-in value is applied to primary and * secondary (MPI) scatters or just the primary one, with * the usual computation of the veto being performed for * the secondary (MPI) scatters. */ bool _hardVetoReadOption; /** * rms intrinsic pT of Gaussian distribution */ Energy _iptrms; /** * Proportion of inverse quadratic intrinsic pT distribution */ double _beta; /** * Parameter for inverse quadratic: 2*Beta*Gamma/(sqr(Gamma)+sqr(intrinsicpT)) */ Energy _gamma; /** * Upper bound on intrinsic pT for inverse quadratic */ Energy _iptmax; /** * Limit the number of emissions for testing */ unsigned int _limitEmissions; /** * The progenitor of the current shower */ ShowerProgenitorPtr _progenitor; /** * Matrix element */ HwMEBasePtr _hardme; /** * Decayer */ HwDecayerBasePtr _decayme; /** * The ShowerTree currently being showered */ ShowerTreePtr _currenttree; /** * The HardTree currently being showered */ HardTreePtr _hardtree; /** * Radiation enhancement factors for use with the veto algorithm * if needed by the soft matrix element correction */ //@{ /** * Enhancement factor for initial-state radiation */ double _initialenhance; /** * Enhancement factor for final-state radiation */ double _finalenhance; //@} /** * The beam particle data for the current initial-state shower */ Ptr::const_pointer _beam; /** * Storage of the intrinsic \f$p_t\f$ of the particles */ map > _intrinsic; /** * Vetoes */ vector _vetoes; /** * Full Shower Vetoes */ vector _fullShowerVetoes; /** * Number of iterations for reweighting */ unsigned int _nReWeight; /** * Whether or not we are reweighting */ bool _reWeight; /** * number of IS emissions */ unsigned int _nis; /** * Number of FS emissions */ unsigned int _nfs; /** * The option for wqhich interactions to use */ ShowerInteraction interaction_; /** * Truncated shower switch */ bool _trunc_Mode; - - /** - * Count of the number of truncated emissions - */ - unsigned int _truncEmissions; /** * Mode for the hard emissions */ int _hardEmission; /** * Option for the kernal for soft correlations */ unsigned int _softOpt; /** * Option for hard radiation in POWHEG events */ bool _hardPOWHEG; /** * True if no warnings about incorrect hard emission * mode setting have been issued yet */ static bool _hardEmissionWarn; /** * True if no warnings about missing truncated shower * have been issued yet */ static bool _missingTruncWarn; /** * The relevant hard scale to be used in the profile scales */ Energy muPt; private: /** * Pointer to the various objects */ //@{ /** * Pointer to the KinematicsReconstructor object */ KinematicsReconstructorPtr _reconstructor; /** * Pointer to the PartnerFinder object */ PartnerFinderPtr _partnerfinder; //@} }; } #endif /* HERWIG_QTildeShowerHandler_H */ diff --git a/Shower/UEBase.h b/Shower/UEBase.h --- a/Shower/UEBase.h +++ b/Shower/UEBase.h @@ -1,141 +1,146 @@ // -*- C++ -*- #ifndef HERWIG_UEBase_H #define HERWIG_UEBase_H // // This is the declaration of the UEBase class. // #include "ThePEG/Interface/Interfaced.h" #include "ThePEG/Handlers/StandardXComb.fh" #include "UEBase.fh" namespace Herwig { using namespace ThePEG; /** * Abstract base class used to minimize the dependence between * MPIHandler and all Shower classes. * * \author Manuel B\"ahr * * @see \ref UEBaseInterfaces "The interfaces" * defined for UEBase. */ class UEBase: public Interfaced { public: /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); /** @name Virtual functions used for the generation of additional interactions . */ //@{ /** * Some initialization code eventually. */ virtual void initialize() {} /** * Return true or false depending on the generator setup. */ virtual bool beamOK() const = 0; /** * Return true or false depending on whether soft interactions are enabled. */ virtual bool softInt() const {return false;} /** * Return the value of the pt cutoff. */ virtual Energy Ptmin() const = 0; /** * Return the slope of the soft pt spectrum. Only necessary when the * soft part is modelled. */ virtual InvEnergy2 beta() const {return ZERO;} /** * Some finalize code eventually. */ virtual void finalize() {} /** * Clean up method called after each event. */ virtual void clean() {} /** * Return the number of different hard processes. Use 0 as default to * not require implementation. */ virtual unsigned int additionalHardProcs() const {return 0;} /** * return the hard multiplicity of process i. Can't be constant in my * case because drawing from the probability distribution also * specifies the soft multiplicity that has to be stored.... */ virtual unsigned int multiplicity(unsigned int i=0) = 0; /** * Generate a additional interaction for ProcessHandler sel. Method * can't be const because it saves the state of the underlying XComb * object on it's way. */ virtual tStdXCombPtr generate(unsigned int sel=0) = 0; /** * Return the type of algorithm. */ virtual int Algorithm() const = 0; /** * Return the value of the hard Process pt cutoff for vetoing. */ virtual Energy PtForVeto() const = 0; /** * Return the fraction of colour disrupted subprocesses. Use default 0 * so that it is not required to implement. */ virtual double colourDisrupt() const {return 0.0;} /** * Return the soft multiplicity. Use 0 as default to not require * implementation. */ virtual unsigned int softMultiplicity() const {return 0;} //@} /** * Return the inelastic cross section ( sigmaND + sigmaDiff ) */ virtual CrossSection inelasticXSec() const =0; - + /** - * Return the diffractiv cross section assumed by the model. + * Return the diffractiv cross section (sigmaDiff) assumed by the model. */ virtual CrossSection diffractiveXSec() const =0; + + /** + * Return the non-diffractiv cross section (sigmaND) assumed by the model. + */ + virtual CrossSection nonDiffractiveXSec() const =0; private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ UEBase & operator=(const UEBase &) = delete; }; } #endif /* HERWIG_UEBase_H */ diff --git a/UnderlyingEvent/MPIHandler.cc b/UnderlyingEvent/MPIHandler.cc --- a/UnderlyingEvent/MPIHandler.cc +++ b/UnderlyingEvent/MPIHandler.cc @@ -1,874 +1,828 @@ // -*- C++ -*- // // MPIHandler.cc is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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 MPIHandler class. // #include "MPIHandler.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Handlers/StandardXComb.h" #include "ThePEG/Handlers/SubProcessHandler.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Parameter.h" #include "ThePEG/Interface/Reference.h" #include "ThePEG/Interface/RefVector.h" #include "ThePEG/Interface/ParVector.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/MatrixElement/MEBase.h" #include "ThePEG/Handlers/CascadeHandler.h" #include "ThePEG/Cuts/Cuts.h" #include "ThePEG/Cuts/JetCuts.h" #include "ThePEG/Cuts/SimpleKTCut.h" #include "ThePEG/PDF/PartonExtractor.h" #include "gsl/gsl_sf_bessel.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; MPIHandler * MPIHandler::currentHandler_ = 0; bool MPIHandler::beamOK() const { return (HadronMatcher::Check(*eventHandler()->incoming().first) && HadronMatcher::Check(*eventHandler()->incoming().second) ); } tStdXCombPtr MPIHandler::generate(unsigned int sel) { //generate a certain process if(sel+1 > processHandlers().size()) throw Exception() << "MPIHandler::generate called with argument out of range" << Exception::runerror; return processHandlers()[sel]->generate(); } IBPtr MPIHandler::clone() const { return new_ptr(*this); } IBPtr MPIHandler::fullclone() const { return new_ptr(*this); } void MPIHandler::finalize() { if( beamOK() ){ statistics(); } } void MPIHandler::initialize() { currentHandler_ = this; useMe(); theHandler = generator()->currentEventHandler(); //stop if the EventHandler is not present: assert(theHandler); //check if MPI is wanted if( !beamOK() ){ throw Exception() << "You have requested multiple parton-parton scattering,\n" << "but the model is not forseen for the beam setup you chose.\n" << "You should therefore disable that by setting XXXGenerator:EventHandler:" << "CascadeHandler:MPIHandler to NULL" << Exception::runerror; } numSubProcs_ = subProcesses().size(); if( numSubProcs_ != cuts().size() ) throw Exception() << "MPIHandler::each SubProcess needs a Cuts Object" << "ReferenceVectors are not equal in size" << Exception::runerror; if( additionalMultiplicities_.size()+1 != numSubProcs_ ) throw Exception() << "MPIHandler: each additional SubProcess needs " << "a multiplicity assigned. This can be done in with " << "insert MPIHandler:additionalMultiplicities 0 1" << Exception::runerror; //identicalToUE_ = 0 hard process is identical to ue, -1 no one if( identicalToUE_ > (int)numSubProcs_ || identicalToUE_ < -1 ) throw Exception() << "MPIHandler:identicalToUE has disallowed value" << Exception::runerror; // override the cuts for the additional scatters if energyExtrapolation_ is // set if (energyExtrapolation_ != 0 ) { overrideUECuts(); } tcPDPtr gluon=getParticleData(ParticleID::g); //determine ptmin Ptmin_ = cuts()[0]->minKT(gluon); if(identicalToUE_ == -1){ algorithm_ = 2; }else{ if(identicalToUE_ == 0){ //Need to work a bit, in case of LesHouches events for QCD2to2 Ptr::pointer eH = dynamic_ptr_cast::pointer>(eventHandler()); if( eH ) { PtOfQCDProc_ = eH->cuts()->minKT(gluon); // find the jet cut in the new style cuts for(unsigned int ix=0;ixcuts()->multiCuts().size();++ix) { Ptr::pointer jetCuts = dynamic_ptr_cast::pointer>(eH->cuts()->multiCuts()[ix]); if(jetCuts) { Energy ptMin=1e30*GeV; for(unsigned int iy=0;iyjetRegions().size();++iy) { ptMin = min(ptMin,jetCuts->jetRegions()[iy]->ptMin()); } if(ptMin<1e29*GeV&&ptMin>PtOfQCDProc_) PtOfQCDProc_ = ptMin; } } } else { if(PtOfQCDProc_ == -1.0*GeV) throw Exception() << "MPIHandler: You need to specify the pt cutoff " << "used to in the LesHouches file for QCD2to2 events" << Exception::runerror; } } else { PtOfQCDProc_ = cuts()[identicalToUE_]->minKT(gluon); } if(PtOfQCDProc_ > 2*Ptmin_) algorithm_ = 1; else algorithm_ = 0; if(PtOfQCDProc_ == ZERO)//pure MinBias mode algorithm_ = -1; } //Init all subprocesses for(unsigned int i=0; iinitialize(subProcesses()[i], cuts()[i], eventHandler()); processHandlers().back()->initrun(); } //now calculate the individual Probabilities XSVector UEXSecs; UEXSecs.push_back(processHandlers()[0]->integratedXSec()); //save the hard cross section hardXSec_ = UEXSecs.front(); //determine sigma_soft and beta if(softInt_){//check that soft ints are requested GSLBisection rootFinder; if(twoComp_){ //two component model /* GSLMultiRoot eqSolver; slopeAndTotalXSec eq(this); pair res = eqSolver.value(eq, 10*millibarn, 0.6*GeV2); softXSec_ = res.first; softMu2_ = res.second; */ slopeBisection fs(this); try{ softMu2_ = rootFinder.value(fs, 0.3*GeV2, 1.*GeV2); softXSec_ = fs.softXSec(); }catch(GSLBisection::IntervalError){ try{ // Very low energies (e.g. 200 GeV) need this. // Very high energies (e.g. 100 TeV) produce issues with // this choice. This is a temp. fix. softMu2_ = rootFinder.value(fs, 0.25*GeV2, 1.3*GeV2); softXSec_ = fs.softXSec(); }catch(GSLBisection::IntervalError){ throw Exception() << "\n**********************************************************\n" "* Inconsistent MPI parameter choice for this beam energy *\n" "**********************************************************\n" "MPIHandler parameter choice is unable to reproduce\n" "the total cross section. Please check arXiv:0806.2949\n" "for the allowed parameter space." << Exception::runerror; } } }else{ //single component model TotalXSecBisection fn(this); try{ softXSec_ = rootFinder.value(fn, 0*millibarn, 5000*millibarn); }catch(GSLBisection::IntervalError){ throw Exception() << "\n**********************************************************\n" "* Inconsistent MPI parameter choice for this beam energy *\n" "**********************************************************\n" "MPIHandler parameter choice is unable to reproduce\n" "the total cross section. Please check arXiv:0806.2949\n" "for the allowed parameter space." << Exception::runerror; } } //now get the differential cross section at ptmin ProHdlPtr qcd = new_ptr(ProcessHandler()); Energy eps = 0.1*GeV; Energy ptminPlus = Ptmin_ + eps; Ptr::pointer ktCut = new_ptr(SimpleKTCut(ptminPlus)); ktCut->init(); ktCut->initrun(); CutsPtr qcdCut = new_ptr(Cuts(2*ptminPlus)); qcdCut->add(dynamic_ptr_cast(ktCut)); qcdCut->init(); qcdCut->initrun(); qcd->initialize(subProcesses()[0], qcdCut, eventHandler()); qcd->initrun(); // ds/dp_T^2 = 1/2/p_T ds/dp_T DiffXSec hardPlus = (hardXSec_-qcd->integratedXSec())/(2*Ptmin_*eps); betaBisection fn2(softXSec_, hardPlus, Ptmin_); try{ beta_ = rootFinder.value(fn2, -10/GeV2, 2/GeV2); }catch(GSLBisection::IntervalError){ try{ // Very low energies (e.g. 200 GeV) need this. // Very high energies (e.g. 100 TeV) produce issues with // this choice. This is a temp. fix. beta_ = rootFinder.value(fn2, -5/GeV2, 8./GeV2); }catch(GSLBisection::IntervalError){ throw Exception() << "MPIHandler: slope of soft pt spectrum couldn't be " << "determined." << Exception::runerror; } } } Probs(UEXSecs); //MultDistribution("probs.test"); UEXSecs.clear(); } void MPIHandler::MultDistribution(string filename) const { ofstream file; double p(0.0), pold(0.0); file.open(filename.c_str()); //theMultiplicities Selector::const_iterator it = theMultiplicities.begin(); while(it != theMultiplicities.end()){ p = it->first; file << it->second.first << " " << it->second.second << " " << p-pold << '\n'; it++; pold = p; } file << "sum of all probabilities: " << theMultiplicities.sum() << endl; file.close(); } void MPIHandler::statistics() const { ostream & file = generator()->misc(); string line = "=======================================" "=======================================\n"; for(unsigned int i=0; istatistics(file, tot); file << "\n"; } if(softInt_){ file << line << "Eikonalized and soft cross sections:\n\n" << "Model parameters: " << "ptmin: " << Ptmin_/GeV << " GeV" << ", mu2: " << invRadius_/sqr(1.*GeV) << " GeV2\n" << " " << "DL mode: " << DLmode_ << ", CMenergy: " << generator()->maximumCMEnergy()/GeV << " GeV" << '\n' << "hard inclusive cross section (mb): " << hardXSec_/millibarn << '\n' << "soft inclusive cross section (mb): " << softXSec_/millibarn << '\n' << "total cross section (mb): " << totalXSecExp()/millibarn << '\n' << "inelastic cross section (mb): " << inelXSec_/millibarn << '\n' - << "diffractive cross section (mb): " - << diffratio_*totalXSecExp()/millibarn << '\n' + // TODO: Include diffrative Cross Section in calculation + // << "diffractive cross section (mb): " + // << diffratio_*totalXSecExp()/millibarn << '\n' << "soft inv radius (GeV2): " << softMu2_/GeV2 << '\n' << "slope of soft pt spectrum (1/GeV2): " << beta_*sqr(1.*GeV) << '\n' << "Average hard multiplicity: " << avgNhard_ << '\n' << "Average soft multiplicity: " << avgNsoft_ << '\n' << line << endl; }else{ file << line << "Eikonalized and soft cross sections:\n\n" << "Model parameters: " << "ptmin: " << Ptmin_/GeV << " GeV" << ", mu2: " << invRadius_/sqr(1.*GeV) << " GeV2\n" << " " << ", CMenergy: " << generator()->maximumCMEnergy()/GeV << " GeV" << '\n' << "hard inclusive cross section (mb): " << hardXSec_/millibarn << '\n' << "Average hard multiplicity: " << avgNhard_ << '\n' << line << endl; } } unsigned int MPIHandler::multiplicity(unsigned int sel){ if(sel==0){//draw from the pretabulated distribution MPair m = theMultiplicities.select(UseRandom::rnd()); softMult_ = m.second; return m.first; } else{ //fixed multiplicities for the additional hard scatters if(additionalMultiplicities_.size() < sel) throw Exception() << "MPIHandler::multiplicity: process index " << "is out of range" << Exception::runerror; return additionalMultiplicities_[sel-1]; } } void MPIHandler::Probs(XSVector UEXSecs) { GSLIntegrator integrator; unsigned int iH(1), iS(0); double P(0.0); double P0(0.0);//the probability for i hard and zero soft scatters Length bmax(500.0*sqrt(millibarn)); //only one UE process will be drawn from a probability distribution, //so check that. assert(UEXSecs.size() == 1); for ( XSVector::const_iterator it = UEXSecs.begin(); it != UEXSecs.end(); ++it ) { iH = 0; //get the inel xsec Eikonalization inelint(this, -1, *it, softXSec_, softMu2_); - - - auto nondiffXS=integrator.value(inelint, ZERO, bmax); - inelXSec_ = nondiffXS+diffratio_*totalXSecExp(); + inelXSec_ = integrator.value(inelint, ZERO, bmax); avgNhard_ = 0.0; avgNsoft_ = 0.0; bmax = 10.0*sqrt(millibarn); do{//loop over hard ints if(Algorithm()>-1 && iH==0){ iH++; continue; } iS = 0; do{//loop over soft ints if( ( Algorithm() == -1 && iS==0 && iH==0 ) ){ iS++; continue; } Eikonalization integrand(this, iH*100+iS, *it, softXSec_, softMu2_); if(Algorithm() > 0){ P = integrator.value(integrand, ZERO, bmax) / *it; }else{ - P = integrator.value(integrand, ZERO, bmax) / nondiffXS; + P = integrator.value(integrand, ZERO, bmax) / inelXSec_; } //store the probability if(Algorithm()>-1){ theMultiplicities.insert(P, make_pair(iH-1, iS)); avgNhard_ += P*(iH-1); }else{ theMultiplicities.insert(P, make_pair(iH, iS)); avgNhard_ += P*(iH); } avgNsoft_ += P*iS; if(iS==0) P0 = P; iS++; } while ( (iS < maxScatters_) && (iS < 5 || P > 1.e-15 ) && softInt_ ); iH++; } while ( (iH < maxScatters_) && (iH < 5 || P0 > 1.e-15) ); } } // calculate the integrand Length Eikonalization::operator() (Length b) const { unsigned int Nhard(0), Nsoft(0); //fac is just: d^2b=fac*db despite that large number Length fac(Constants::twopi*b); double chiTot(( theHandler->OverlapFunction(b)*hardXSec_ + theHandler->OverlapFunction(b, softMu2_)*softXSec_ ) / 2.0); //total cross section wanted if(theoption == -2) return 2 * fac * ( 1 - exp(-chiTot) ); //inelastic cross section if(theoption == -1) return fac * ( 1 - exp(- 2.0 * chiTot) ); if(theoption >= 0){ //encode multiplicities as: N_hard*100 + N_soft Nhard = theoption/100; Nsoft = theoption%100; if(theHandler->Algorithm() > 0){ //P_n*sigma_hard: n-1 extra scatters + 1 hard scatterer != hardXSec_ return fac * Nhard * theHandler->poisson(b, hardXSec_, Nhard) * theHandler->poisson(b, softXSec_, Nsoft, softMu2_); }else{ //P_n*sigma_inel: n extra scatters return fac * theHandler->poisson(b, hardXSec_, Nhard) * theHandler->poisson(b, softXSec_, Nsoft, softMu2_); } }else{ throw Exception() << "Parameter theoption in Struct Eikonalization in " << "MPIHandler.cc has not allowed value" << Exception::runerror; return 0.0*meter; } } InvEnergy2 slopeBisection::operator() (Energy2 softMu2) const { GSLBisection root; //single component model TotalXSecBisection fn(handler_, softMu2); try{ softXSec_ = root.value(fn, 0*millibarn, 5000*millibarn); }catch(GSLBisection::IntervalError){ throw Exception() << "MPIHandler 2-Component model didn't work out." << Exception::runerror; } return handler_->slopeDiff(softXSec_, softMu2); } LengthDiff slopeInt::operator() (Length b) const { //fac is just: d^2b=fac*db Length fac(Constants::twopi*b); double chiTot(( handler_->OverlapFunction(b)*hardXSec_ + handler_->OverlapFunction(b, softMu2_)*softXSec_ ) / 2.0); InvEnergy2 b2 = sqr(b/hbarc); //B*sigma_tot return fac * b2 * ( 1 - exp(-chiTot) ); } -double MPIHandler::factorial (unsigned int n) const { - - static double f[] = {1.,1.,2.,6.,24.,120.,720.,5040.,40320.,362880.,3.6288e6, - 3.99168e7,4.790016e8,6.2270208e9,8.71782912e10,1.307674368e12, - 2.0922789888e13,3.55687428096e14,6.402373705728e15,1.21645100408832e17, - 2.43290200817664e18,5.10909421717094e19,1.12400072777761e21, - 2.5852016738885e22,6.20448401733239e23,1.5511210043331e25, - 4.03291461126606e26,1.08888694504184e28,3.04888344611714e29, - 8.8417619937397e30,2.65252859812191e32,8.22283865417792e33, - 2.63130836933694e35,8.68331761881189e36,2.95232799039604e38, - 1.03331479663861e40,3.71993326789901e41,1.37637530912263e43, - 5.23022617466601e44,2.03978820811974e46,8.15915283247898e47, - 3.34525266131638e49,1.40500611775288e51,6.04152630633738e52, - 2.65827157478845e54,1.1962222086548e56,5.50262215981209e57, - 2.58623241511168e59,1.24139155925361e61,6.08281864034268e62, - 3.04140932017134e64,1.55111875328738e66,8.06581751709439e67, - 4.27488328406003e69,2.30843697339241e71,1.26964033536583e73, - 7.10998587804863e74,4.05269195048772e76,2.35056133128288e78, - 1.3868311854569e80,8.32098711274139e81,5.07580213877225e83, - 3.14699732603879e85,1.98260831540444e87,1.26886932185884e89, - 8.24765059208247e90,5.44344939077443e92,3.64711109181887e94, - 2.48003554243683e96,1.71122452428141e98,1.19785716699699e100, - 8.50478588567862e101,6.12344583768861e103,4.47011546151268e105, - 3.30788544151939e107,2.48091408113954e109,1.88549470166605e111, - 1.45183092028286e113,1.13242811782063e115,8.94618213078298e116, - 7.15694570462638e118,5.79712602074737e120,4.75364333701284e122, - 3.94552396972066e124,3.31424013456535e126,2.81710411438055e128, - 2.42270953836727e130,2.10775729837953e132,1.85482642257398e134, - 1.65079551609085e136,1.48571596448176e138,1.3520015276784e140, - 1.24384140546413e142,1.15677250708164e144,1.08736615665674e146, - 1.03299784882391e148,9.9167793487095e149,9.61927596824821e151, - 9.42689044888325e153,9.33262154439442e155,9.33262154439442e157}; - - if(n > maxScatters_) - throw Exception() << "MPIHandler::factorial called with too large argument" - << Exception::runerror; - else - return f[n]; -} - InvArea MPIHandler::OverlapFunction(Length b, Energy2 mu2) const { if(mu2 == ZERO) mu2 = invRadius_; InvLength mu = sqrt(mu2)/hbarc; return (sqr(mu)/96/Constants::pi)*pow(mu*b, 3)*(gsl_sf_bessel_Kn(3, mu*b)); } double MPIHandler::poisson(Length b, CrossSection sigma, unsigned int N, Energy2 mu2) const { if(sigma > 0*millibarn){ return pow(OverlapFunction(b, mu2)*sigma, (double)N)/factorial(N) *exp(-OverlapFunction(b, mu2)*sigma); }else{ return (N==0) ? 1.0 : 0.0; } } CrossSection MPIHandler::totalXSecDiff(CrossSection softXSec, Energy2 softMu2) const { GSLIntegrator integrator; Eikonalization integrand(this, -2, hardXSec_, softXSec, softMu2); Length bmax = 500.0*sqrt(millibarn); - CrossSection minbiasXS = integrator.value(integrand, ZERO, bmax); - - auto totalXS=totalXSecExp(); - CrossSection tot=minbiasXS+diffratio_*totalXS; - - return (tot-totalXS); + CrossSection tot = integrator.value(integrand, ZERO, bmax); + return (tot-totalXSecExp()); } InvEnergy2 MPIHandler::slopeDiff(CrossSection softXSec, Energy2 softMu2) const { GSLIntegrator integrator; Eikonalization integrand(this, -2, hardXSec_, softXSec, softMu2); Length bmax = 500.0*sqrt(millibarn); CrossSection tot = integrator.value(integrand, ZERO, bmax); slopeInt integrand2(this, hardXSec_, softXSec, softMu2); return integrator.value(integrand2, ZERO, bmax)/tot - slopeExp(); } CrossSection MPIHandler::totalXSecExp() const { if(totalXSecExp_ != 0*millibarn) return totalXSecExp_; double pom_old = 0.0808; CrossSection coef_old = 21.7*millibarn; double pom_new_hard = 0.452; CrossSection coef_new_hard = 0.0139*millibarn; double pom_new_soft = 0.0667; CrossSection coef_new_soft = 24.22*millibarn; Energy energy(generator()->maximumCMEnergy()); switch(DLmode_){ case 1://old DL extrapolation return coef_old * pow(energy/GeV, 2*pom_old); break; case 2://old DL extrapolation fixed to CDF return 81.8*millibarn * pow(energy/1800.0/GeV, 2*pom_old); break; case 3://new DL extrapolation - return coef_new_hard * pow(energy/GeV, 2*pom_new_hard) + + return 0.8*coef_new_hard * pow(energy/GeV, 2*pom_new_hard) + coef_new_soft * pow(energy/GeV, 2*pom_new_soft); break; default: throw Exception() << "MPIHandler::totalXSecExp non-existing mode selected" << Exception::runerror; } } InvEnergy2 MPIHandler::slopeExp() const{ //Currently return the slope as calculated in the pomeron fit by //Donnachie & Landshoff Energy energy(generator()->maximumCMEnergy()); //slope at Energy e_0 = 1800*GeV; InvEnergy2 b_0 = 17/GeV2; return b_0 + log(energy/e_0)/GeV2; } void MPIHandler::overrideUECuts() { if(energyExtrapolation_==1) Ptmin_ = EEparamA_ * log(generator()->maximumCMEnergy() / EEparamB_); else if(energyExtrapolation_==2) Ptmin_ = pT0_*pow(double(generator()->maximumCMEnergy()/refScale_),b_); else assert(false); // create a new SimpleKTCut object with the calculated ptmin value Ptr::pointer newUEktCut = new_ptr(SimpleKTCut(Ptmin_)); newUEktCut->init(); newUEktCut->initrun(); // create a new Cuts object with MHatMin = 2 * Ptmin_ CutsPtr newUEcuts = new_ptr(Cuts(2*Ptmin_)); newUEcuts->add(dynamic_ptr_cast(newUEktCut)); newUEcuts->init(); newUEcuts->initrun(); // replace the old Cuts object cuts()[0] = newUEcuts; } void MPIHandler::persistentOutput(PersistentOStream & os) const { os << theMultiplicities << theHandler << theSubProcesses << theCuts << theProcessHandlers << additionalMultiplicities_ << identicalToUE_ << ounit(PtOfQCDProc_, GeV) << ounit(Ptmin_, GeV) << ounit(hardXSec_, millibarn) << ounit(softXSec_, millibarn) << ounit(beta_, 1/GeV2) << algorithm_ << ounit(invRadius_, GeV2) << numSubProcs_ << colourDisrupt_ << softInt_ << twoComp_ << DLmode_ << ounit(totalXSecExp_, millibarn) << energyExtrapolation_ << ounit(EEparamA_, GeV) << ounit(EEparamB_, GeV) << ounit(refScale_,GeV) << ounit(pT0_,GeV) << b_ << avgNhard_ << avgNsoft_ << softMult_ << ounit(inelXSec_, millibarn) << ounit(softMu2_, GeV2) << diffratio_; } void MPIHandler::persistentInput(PersistentIStream & is, int) { is >> theMultiplicities >> theHandler >> theSubProcesses >> theCuts >> theProcessHandlers >> additionalMultiplicities_ >> identicalToUE_ >> iunit(PtOfQCDProc_, GeV) >> iunit(Ptmin_, GeV) >> iunit(hardXSec_, millibarn) >> iunit(softXSec_, millibarn) >> iunit(beta_, 1/GeV2) >> algorithm_ >> iunit(invRadius_, GeV2) >> numSubProcs_ >> colourDisrupt_ >> softInt_ >> twoComp_ >> DLmode_ >> iunit(totalXSecExp_, millibarn) >> energyExtrapolation_ >> iunit(EEparamA_, GeV) >> iunit(EEparamB_, GeV) >> iunit(refScale_,GeV) >> iunit(pT0_,GeV) >> b_ >> avgNhard_ >> avgNsoft_ >> softMult_ >> iunit(inelXSec_, millibarn) >> iunit(softMu2_, GeV2) >> diffratio_; currentHandler_ = this; } void MPIHandler::clean() { // ThePEG's event handler's usual event cleanup doesn't reach these // XCombs. Need to do it by hand here. for ( size_t i = 0; i < theSubProcesses.size(); ++i ) { theSubProcesses[i]->pExtractor()->lastXCombPtr()->clean(); } } // The following static variable is needed for the type // description system in ThePEG. DescribeClass describeHerwigMPIHandler("Herwig::MPIHandler", "JetCuts.so SimpleKTCut.so HwMPI.so"); void MPIHandler::Init() { static ClassDocumentation documentation ("The MPIHandler class is the main administrator of the multiple interaction model", "The underlying event was simulated with an eikonal model for multiple partonic interactions." "Details can be found in Ref.~\\cite{Bahr:2008dy,Bahr:2009ek}.", "%\\cite{Bahr:2008dy}\n" "\\bibitem{Bahr:2008dy}\n" " M.~Bahr, S.~Gieseke and M.~H.~Seymour,\n" " ``Simulation of multiple partonic interactions in Herwig,''\n" " JHEP {\\bf 0807}, 076 (2008)\n" " [arXiv:0803.3633 [hep-ph]].\n" " %%CITATION = JHEPA,0807,076;%%\n" "\\bibitem{Bahr:2009ek}\n" " M.~Bahr, J.~M.~Butterworth, S.~Gieseke and M.~H.~Seymour,\n" " ``Soft interactions in Herwig,''\n" " arXiv:0905.4671 [hep-ph].\n" " %%CITATION = ARXIV:0905.4671;%%\n" ); static RefVector interfaceSubhandlers ("SubProcessHandlers", "The list of sub-process handlers used in this EventHandler. ", &MPIHandler::theSubProcesses, -1, false, false, true, false, false); static RefVector interfaceCuts ("Cuts", "List of cuts used for the corresponding list of subprocesses. These cuts " "should not be overidden in individual sub-process handlers.", &MPIHandler::theCuts, -1, false, false, true, false, false); static Parameter interfaceInvRadius ("InvRadius", "The inverse hadron radius squared used in the overlap function", &MPIHandler::invRadius_, GeV2, 2.0*GeV2, 0.2*GeV2, 4.0*GeV2, true, false, Interface::limited); static ParVector interfaceadditionalMultiplicities ("additionalMultiplicities", "specify the multiplicities of secondary hard processes (multiple parton scattering)", &MPIHandler::additionalMultiplicities_, -1, 0, 0, 3, false, false, true); static Parameter interfaceIdenticalToUE ("IdenticalToUE", "Specify which of the hard processes is identical to the UE one (QCD dijets)", &MPIHandler::identicalToUE_, -1, 0, 0, false, false, Interface::nolimits); static Parameter interfacePtOfQCDProc ("PtOfQCDProc", "Specify the value of the pt cutoff for the process that is identical to the UE one", &MPIHandler::PtOfQCDProc_, GeV, -1.0*GeV, ZERO, ZERO, false, false, Interface::nolimits); static Parameter interfacecolourDisrupt ("colourDisrupt", "Fraction of connections to additional subprocesses, which are colour disrupted.", &MPIHandler::colourDisrupt_, 0.0, 0.0, 1.0, false, false, Interface::limited); static Parameter interfaceDiffRatio ("DiffractiveRatio", - "Fraction of diffractive cross section in total cross section.", + "Fraction of diffractive cross section in inelastic cross section.", &MPIHandler::diffratio_, 0.2, 0.0, 1.0, false, false, Interface::limited); static Switch interfacesoftInt ("softInt", "Switch to enable soft interactions", &MPIHandler::softInt_, true, false, false); static SwitchOption interfacesoftIntYes (interfacesoftInt, "Yes", "enable the two component model", true); static SwitchOption interfacesoftIntNo (interfacesoftInt, "No", "disable the model", false); static Switch interEnergyExtrapolation ("EnergyExtrapolation", "Switch to ignore the cuts object at MPIHandler:Cuts[0]. " "Instead, extrapolate the pt cut.", &MPIHandler::energyExtrapolation_, 2, false, false); static SwitchOption interEnergyExtrapolationLog (interEnergyExtrapolation, "Log", "Use logarithmic dependence, ptmin = A * log (sqrt(s) / B).", 1); static SwitchOption interEnergyExtrapolationPower (interEnergyExtrapolation, "Power", "Use power law, ptmin = pt_0 * (sqrt(s) / E_0)^b.", 2); static SwitchOption interEnergyExtrapolationNo (interEnergyExtrapolation, "No", "Use manually set value for the minimal pt, " "specified in MPIHandler:Cuts[0]:OneCuts[0]:MinKT.", 0); static Parameter interfaceEEparamA ("EEparamA", "Parameter A in the empirical parametrization " "ptmin = A * log (sqrt(s) / B)", &MPIHandler::EEparamA_, GeV, 0.6*GeV, ZERO, Constants::MaxEnergy, false, false, Interface::limited); static Parameter interfaceEEparamB ("EEparamB", "Parameter B in the empirical parametrization " "ptmin = A * log (sqrt(s) / B)", &MPIHandler::EEparamB_, GeV, 39.0*GeV, ZERO, Constants::MaxEnergy, false, false, Interface::limited); static Switch interfacetwoComp ("twoComp", "switch to enable the model with a different radius for soft interactions", &MPIHandler::twoComp_, true, false, false); static SwitchOption interfacetwoCompYes (interfacetwoComp, "Yes", "enable the two component model", true); static SwitchOption interfacetwoCompNo (interfacetwoComp, "No", "disable the model", false); static Parameter interfaceMeasuredTotalXSec ("MeasuredTotalXSec", "Value for the total cross section (assuming rho=0). If non-zero, this " "overwrites the Donnachie-Landshoff parametrizations.", &MPIHandler::totalXSecExp_, millibarn, 0.0*millibarn, 0.0*millibarn, 0*millibarn, false, false, Interface::lowerlim); static Switch interfaceDLmode ("DLmode", "Choice of Donnachie-Landshoff parametrization for the total cross section.", &MPIHandler::DLmode_, 2, false, false); static SwitchOption interfaceDLmodeStandard (interfaceDLmode, "Standard", "Standard parametrization with s**0.08", 1); static SwitchOption interfaceDLmodeCDF (interfaceDLmode, "CDF", "Standard parametrization but normalization fixed to CDF's measured value", 2); static SwitchOption interfaceDLmodeNew (interfaceDLmode, "New", "Parametrization taking hard and soft pomeron contributions into account", 3); static Parameter interfaceReferenceScale ("ReferenceScale", "The reference energy for power law energy extrapolation of pTmin", &MPIHandler::refScale_, GeV, 7000.0*GeV, 0.0*GeV, 20000.*GeV, false, false, Interface::limited); static Parameter interfacepTmin0 ("pTmin0", "The pTmin at the reference scale for power law extrapolation of pTmin.", &MPIHandler::pT0_, GeV, 3.11*GeV, 0.0*GeV, 10.0*GeV, false, false, Interface::limited); static Parameter interfacePower ("Power", "The power for power law extrapolation of the pTmin cut-off.", &MPIHandler::b_, 0.21, 0.0, 10.0, false, false, Interface::limited); } diff --git a/UnderlyingEvent/MPIHandler.h b/UnderlyingEvent/MPIHandler.h --- a/UnderlyingEvent/MPIHandler.h +++ b/UnderlyingEvent/MPIHandler.h @@ -1,895 +1,897 @@ // -*- C++ -*- // // MPIHandler.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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. // #ifndef HERWIG_MPIHandler_H #define HERWIG_MPIHandler_H // // This is the declaration of the MPIHandler class. // #include "ThePEG/Interface/Interfaced.h" #include "ThePEG/Handlers/StandardEventHandler.h" #include "ThePEG/Repository/EventGenerator.h" #include "Herwig/PDT/StandardMatchers.h" #include "Herwig/Utilities/GSLBisection.h" //#include "Herwig/Utilities/GSLMultiRoot.h" #include "Herwig/Utilities/GSLIntegrator.h" #include "Herwig/Shower/UEBase.h" #include #include "ProcessHandler.h" #include "MPIHandler.fh" namespace Herwig { using namespace ThePEG; /** \ingroup UnderlyingEvent * \class MPIHandler * This class is responsible for generating additional * semi hard partonic interactions. * * \author Manuel B\"ahr * * @see \ref MPIHandlerInterfaces "The interfaces" * defined for MPIHandler. * @see ProcessHandler * @see ShowerHandler * @see HwRemDecayer */ class MPIHandler: public UEBase { /** * Maximum number of scatters */ static const unsigned int maxScatters_ = 99; /** * Class for the integration is a friend to access private members */ friend struct Eikonalization; friend struct TotalXSecBisection; friend struct slopeAndTotalXSec; friend struct slopeInt; friend struct slopeBisection; public: /** A vector of SubProcessHandlers. */ typedef vector SubHandlerList; /** A vector of Cuts. */ typedef vector CutsList; /** A vector of ProcessHandlers. */ typedef vector ProcessHandlerList; /** A vector of cross sections. */ typedef vector XSVector; /** A pair of multiplicities: hard, soft. */ typedef pair MPair; /** @name Standard constructors and destructors. */ //@{ /** * The default constructor. */ MPIHandler(): softMult_(0), identicalToUE_(-1), PtOfQCDProc_(-1.0*GeV), Ptmin_(-1.0*GeV), hardXSec_(0*millibarn), softXSec_(0*millibarn), totalXSecExp_(0*millibarn), softMu2_(ZERO), beta_(100.0/GeV2), algorithm_(2), numSubProcs_(0), colourDisrupt_(0.0), softInt_(true), twoComp_(true), DLmode_(2), avgNhard_(0.0), avgNsoft_(0.0), energyExtrapolation_(2), EEparamA_(0.6*GeV), EEparamB_(37.5*GeV), refScale_(7000.*GeV), pT0_(3.11*GeV), b_(0.21) {} /** * The destructor. */ virtual ~MPIHandler(){} //@} public: /** @name Methods for the MPI generation. */ //@{ /* * @return true if for this beam setup MPI can be generated */ virtual bool beamOK() const; /** * Return true or false depending on whether soft interactions are enabled. */ virtual bool softInt() const {return softInt_;} /** * Get the soft multiplicity from the pretabulated multiplicity * distribution. Generated in multiplicity in the first place. * @return the number of extra soft events in this collision */ virtual unsigned int softMultiplicity() const {return softMult_;} /** * Sample from the pretabulated multiplicity distribution. * @return the number of extra events in this collision */ virtual unsigned int multiplicity(unsigned int sel=0); /** * Select a StandardXComb according to it's weight * @return that StandardXComb Object * @param sel is the subprocess that should be returned, * if more than one is specified. */ virtual tStdXCombPtr generate(unsigned int sel=0); //@} /** @name Functions used by the persistent I/O system. */ //@{ /** * Function used to write out object persistently. * @param os the persistent output stream written to. */ void persistentOutput(PersistentOStream & os) const; /** * Function used to read in object persistently. * @param is the persistent input stream read from. * @param version the version number of the object when written. */ void persistentInput(PersistentIStream & is, int version); //@} /** * The standard Init function used to initialize the interfaces. * Called exactly once for each class by the class description system * before the main function starts or * when this class is dynamically loaded. */ static void Init(); /** * Initialize this Multiple Interaction handler and all related objects needed to * generate additional events. */ virtual void initialize(); /** * Finalize this Multiple Interaction handler and all related objects needed to * generate additional events. */ virtual void finalize(); /** * Clean up the XCombs from our subprocesses after each event. * ThePEG cannot see them, so the usual cleaning misses these. */ virtual void clean(); /** * Write out accumulated statistics about integrated cross sections. */ void statistics() const; /** * The level of statistics. Controlls the amount of statistics * written out after each run to the EventGenerators * .out file. Simply the EventHandler method is called here. */ int statLevel() const {return eventHandler()->statLevel();} /** * Return the hard cross section above ptmin */ CrossSection hardXSec() const { return hardXSec_; } /** * Return the soft cross section below ptmin */ CrossSection softXSec() const { return softXSec_; } /** * Return the inelastic cross section */ CrossSection inelasticXSec() const { return inelXSec_; } + /** + * Return the non-diffractive cross section assumed by the model. + * TODO: See comment at diffractiveXSec. + */ + CrossSection nonDiffractiveXSec() const { + return (1.-diffratio_)*inelXSec_; + } /** * Return the diffractive cross section assumed by the model. - * The diffractive cross section is seen as part of the + * For now the diffractive cross section is seen as a fixed part of the * inelastic cross section. + * TODO: Energy dependence and/or Include diffraction in Eikonalisation. */ CrossSection diffractiveXSec() const { - static auto totalXS=totalXSecExp(); - return diffratio_*totalXS; + return diffratio_*inelXSec_; } /** @name Simple access functions. */ //@{ /** * Return the ThePEG::EventHandler assigned to this handler. * This methods shadows ThePEG::StepHandler::eventHandler(), because * it is not virtual in ThePEG::StepHandler. This is ok, because this * method would give a null-pointer at some stages, whereas this method * gives access to the explicitely copied pointer (in initialize()) * to the ThePEG::EventHandler. */ tEHPtr eventHandler() const {return theHandler;} /** * Return the current handler */ static const MPIHandler * currentHandler() { return currentHandler_; } /** * Return theAlgorithm. */ virtual int Algorithm() const {return algorithm_;} /** * Return the ptmin parameter of the model */ virtual Energy Ptmin() const { if(Ptmin_ > ZERO) return Ptmin_; else throw Exception() << "MPIHandler::Ptmin called without initialize before" << Exception::runerror; } /** * Return the slope of the soft pt spectrum as calculated. */ virtual InvEnergy2 beta() const { if(beta_ != 100.0/GeV2) return beta_; else throw Exception() << "MPIHandler::beta called without initialization" << Exception::runerror; } /** * Return the pt Cutoff of the Interaction that is identical to the UE * one. */ virtual Energy PtForVeto() const {return PtOfQCDProc_;} /** * Return the number of additional "hard" processes ( = multiple * parton scattering) */ virtual unsigned int additionalHardProcs() const {return numSubProcs_-1;} /** * Return the fraction of colour disrupted connections to the * suprocesses. */ virtual double colourDisrupt() const {return colourDisrupt_;} protected: /** @name Clone Methods. */ //@{ /** * Make a simple clone of this object. * @return a pointer to the new object. */ virtual IBPtr clone() const; /** Make a clone of this object, possibly modifying the cloned object * to make it sane. * @return a pointer to the new object. */ virtual IBPtr fullclone() const; //@} private: /** * Access the list of sub-process handlers. */ const SubHandlerList & subProcesses() const {return theSubProcesses;} /** * Access the list of sub-process handlers. */ SubHandlerList & subProcesses() {return theSubProcesses;} /** * Access the list of cuts. */ const CutsList & cuts() const {return theCuts;} /** * Access the list of cuts. */ CutsList & cuts() {return theCuts;} /** * Access the list of sub-process handlers. */ const ProcessHandlerList & processHandlers() const {return theProcessHandlers;} /** * Access the list of sub-process handlers. */ ProcessHandlerList & processHandlers() {return theProcessHandlers;} /** * Method to calculate the individual probabilities for N scatters in the event. * @param UEXSecs is(are) the inclusiv cross section(s) for the UE process(es). */ void Probs(XSVector UEXSecs); /** * Debug method to check the individual probabilities. * @param filename is the file the output gets written to */ void MultDistribution(string filename) const; /** * Return the value of the Overlap function A(b) for a given impact * parameter \a b. * @param b impact parameter * @param mu2 = inv hadron radius squared. 0 will use the value of * invRadius_ * @return inverse area. */ InvArea OverlapFunction(Length b, Energy2 mu2=ZERO) const; /** * Method to calculate the poisson probability for expectation value * \f$ = A(b)\sigma\f$, and multiplicity N. */ double poisson(Length b, CrossSection sigma, unsigned int N, Energy2 mu2=ZERO) const; /** - * Return n! - */ - double factorial (unsigned int n) const; - - /** * Returns the total cross section for the current CMenergy. The * decision which parametrization will be used is steered by a * external parameter of this class. */ CrossSection totalXSecExp() const; /** * Difference of the calculated total cross section and the * experimental one from totalXSecExp. * @param softXSec = the soft cross section that is used * @param softMu2 = the soft radius, if 0 the hard radius will be used */ CrossSection totalXSecDiff(CrossSection softXSec, Energy2 softMu2=ZERO) const; /** * Difference of the calculated elastic slope and the * experimental one from slopeExp. * @param softXSec = the soft cross section that is used * @param softMu2 = the soft radius, if 0 the hard radius will be used */ InvEnergy2 slopeDiff(CrossSection softXSec, Energy2 softMu2=ZERO) const; /** * Returns the value of the elastic slope for the current CMenergy. * The decision which parametrization will be used is steered by a * external parameter of this class. */ InvEnergy2 slopeExp() const; /** * Calculate the minimal transverse momentum from the extrapolation */ void overrideUECuts(); private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ MPIHandler & operator=(const MPIHandler &) = delete; /** * A pointer to the EventHandler that calls us. Has to be saved, because the * method eventHandler() inherited from ThePEG::StepHandler returns a null-pointer * sometimes. Leif changed that in r1053 so that a valid pointer is present, when * calling doinitrun(). */ tEHPtr theHandler; /** * The list of SubProcessHandlers. */ SubHandlerList theSubProcesses; /** * The kinematical cuts used for this collision handler. */ CutsList theCuts; /** * List of ProcessHandler used to sample different processes independently */ ProcessHandlerList theProcessHandlers; /** * A ThePEG::Selector where the individual Probabilities P_N are stored * and the actual Multiplicities can be selected. */ Selector theMultiplicities; /** * Variable to store the soft multiplicity generated for a event. This * has to be stored as it is generated at the time of the hard * additional interactions but used later on. */ unsigned int softMult_; /** * Variable to store the multiplicity of the second hard process */ vector additionalMultiplicities_; /** * Variable to store the information, which process is identical to * the UE one (QCD dijets). * 0 means "real" hard one * n>0 means the nth additional hard scatter * -1 means no one! */ int identicalToUE_; /** * Variable to store the minimal pt of the process that is identical * to the UE one. This only has to be set, if it can't be determined * automatically (i.e. when reading QCD LesHouches files in). */ Energy PtOfQCDProc_; /** * Variable to store the parameter ptmin */ Energy Ptmin_; /** * Variable to store the hard cross section above ptmin */ CrossSection hardXSec_; /** * Variable to store the final soft cross section below ptmin */ CrossSection softXSec_; /** * Variable to store the inelastic cross section */ CrossSection inelXSec_; /** * Variable to store the total pp cross section (assuming rho=0!) as * measured at LHC. If this variable is set, this value is used in the * subsequent run instead of any of the Donnachie-Landshoff * parametrizations. */ CrossSection totalXSecExp_; /** * Variable to store the soft radius, that is calculated during * initialization for the two-component model. */ Energy2 softMu2_; /** * slope to the non-perturbative pt spectrum: \f$d\sigma/dp_T^2 = A \exp * (- beta p_T^2)\f$. Its value is determined durint initialization. */ InvEnergy2 beta_; /** * Switch to be set from outside to determine the algorithm used for * UE activity. */ int algorithm_; /** * Inverse hadron Radius squared \f$ (\mu^2) \f$. Used inside the overlap function. */ Energy2 invRadius_; /** * Member variable to store the actual number of separate SubProcesses */ unsigned int numSubProcs_; /** * Variable to store the relative number of colour disrupted * connections to additional subprocesses. This variable is used in * Herwig::HwRemDecayer but store here, to have access to all * parameters through one Object. */ double colourDisrupt_; /** * Flag to store whether soft interactions, i.e. pt < ptmin should be * simulated. */ bool softInt_; /** * Flag to steer wheather the soft part has a different radius, that * will be dynamically fixed. */ bool twoComp_; /** * Switch to determine which Donnachie & Landshoff parametrization * should be used. */ unsigned int DLmode_; /** * Variable to store the average hard multiplicity. */ double avgNhard_; /** * Variable to store the average soft multiplicity. */ double avgNsoft_; /** * The current handler */ static MPIHandler * currentHandler_; /** * Flag to store whether to calculate the minimal UE pt according to an * extrapolation formula or whether to use MPIHandler:Cuts[0]:OneCuts[0]:MinKT */ unsigned int energyExtrapolation_; /** * Parameters for the energy extrapolation formula */ Energy EEparamA_; Energy EEparamB_; Energy refScale_; Energy pT0_; double b_; /** - * Parameters to set the fraction of diffractive cross section in the total cross section. + * Parameters to set the fraction of diffractive cross section in the inelastic cross section. */ double diffratio_=0.2; protected: /** @cond EXCEPTIONCLASSES */ /** * Exception class used by the MultipleInteractionHandler, when something * during initialization went wrong. * \todo understand!!! */ class InitError: public Exception {}; /** @endcond */ }; } namespace Herwig { /** * A struct for the 2D root finding that is necessary to determine the * soft cross section and the soft radius that is needed to describe * the total cross section correctly. * NOT IN USE CURRENTLY */ struct slopeAndTotalXSec : public GSLHelper { public: /** * Constructor */ slopeAndTotalXSec(tcMPIHPtr handler): handler_(handler) {} /** second argument type */ typedef Energy2 ArgType2; /** second value type */ typedef InvEnergy2 ValType2; /** first element of the vector like function to find root for * @param softXSec soft cross-section * @param softMu2 \f$\mu^2\f$ */ CrossSection f1(ArgType softXSec, ArgType2 softMu2) const { return handler_->totalXSecDiff(softXSec, softMu2); } /** second element of the vector like function to find root for * @param softXSec soft cross-section * @param softMu2 \f$\mu^2\f$ */ InvEnergy2 f2(ArgType softXSec, ArgType2 softMu2) const { return handler_->slopeDiff(softXSec, softMu2); } /** provide the actual units of use */ virtual ValType vUnit() const {return 1.0*millibarn;} /** otherwise rounding errors may get significant */ virtual ArgType aUnit() const {return 1.0*millibarn;} /** provide the actual units of use */ ValType2 vUnit2() const {return 1.0/GeV2;} /** otherwise rounding errors may get significant */ ArgType2 aUnit2() const {return GeV2;} private: /** * Pointer to the handler */ tcMPIHPtr handler_; }; /** * A struct for the root finding that is necessary to determine the * slope of the soft pt spectrum to match the soft cross section */ struct betaBisection : public GSLHelper{ public: /** * Constructor. * @param soft = soft cross section, i.e. the integral of the soft * pt spectrum f(u=p_T^2) = dsig exp(-beta*u/u_min) * @param dsig = dsigma_hard/dp_T^2 at the p_T cutoff * @param ptmin = p_T cutoff */ betaBisection(CrossSection soft, DiffXSec dsig, Energy ptmin) : softXSec_(soft), dsig_(dsig), ptmin_(ptmin) {} /** * Operator that is used inside the GSLBisection class */ virtual Energy2 operator ()(InvEnergy2 beta) const { if( fabs(beta*GeV2) < 1.E-4 ) beta = (beta > ZERO) ? 1.E-4/GeV2 : -1.E-4/GeV2; return (exp(beta*sqr(ptmin_)) - 1.0)/beta - softXSec_/dsig_; } /** provide the actual units of use */ virtual ValType vUnit() const {return 1.0*GeV2;} /** provide the actual units of use */ virtual ArgType aUnit() const {return 1.0/GeV2;} private: /** soft cross section */ CrossSection softXSec_; /** dsigma/dp_T^2 at ptmin */ DiffXSec dsig_; /** pt cutoff */ Energy ptmin_; }; /** * A struct for the root finding that is necessary to determine the * soft cross section and soft mu2 that are needed to describe the * total cross section AND elastic slope correctly. */ struct slopeBisection : public GSLHelper { public: /** Constructor */ slopeBisection(tcMPIHPtr handler) : handler_(handler) {} /** * Return the difference of the calculated elastic slope to the * experimental one for a given value of the soft mu2. During that, * the soft cross section get fixed. */ InvEnergy2 operator ()(Energy2 arg) const; /** Return the soft cross section that has been calculated */ CrossSection softXSec() const {return softXSec_;} private: /** const pointer to the MPIHandler to give access to member functions.*/ tcMPIHPtr handler_; /** soft cross section that is determined on the fly.*/ mutable CrossSection softXSec_; }; /** * A struct for the root finding that is necessary to determine the * soft cross section that is needed to describe the total cross * section correctly. */ struct TotalXSecBisection : public GSLHelper { public: /** * Constructor * @param handler The handler * @param softMu2 \f$\mu^2\f$ */ TotalXSecBisection(tcMPIHPtr handler, Energy2 softMu2=ZERO): handler_(handler), softMu2_(softMu2) {} /** * operator to return the cross section * @param argument input cross section */ CrossSection operator ()(CrossSection argument) const { return handler_->totalXSecDiff(argument, softMu2_); } /** provide the actual units of use */ virtual ValType vUnit() const {return 1.0*millibarn;} /** otherwise rounding errors may get significant */ virtual ArgType aUnit() const {return 1.0*millibarn;} private: /** * The handler */ tcMPIHPtr handler_; /** * \f$\mu^2\f$ */ Energy2 softMu2_; }; /** * Typedef for derivative of the length */ typedef decltype(mm/GeV2) LengthDiff; /** * A struct for the integrand for the slope */ struct slopeInt : public GSLHelper{ public: /** Constructor * @param handler The handler * @param hard The hard cross section * @param soft The soft cross section * @param softMu2 \f$\mu^2\f$ */ slopeInt(tcMPIHPtr handler, CrossSection hard, CrossSection soft=0*millibarn, Energy2 softMu2=ZERO) : handler_(handler), hardXSec_(hard), softXSec_(soft), softMu2_(softMu2) {} /** * Operator to return the answer * @param arg The argument */ ValType operator ()(ArgType arg) const; private: /** * Pointer to the Handler that calls this integrand */ tcMPIHPtr handler_; /** * The hard cross section to be eikonalized */ CrossSection hardXSec_; /** * The soft cross section to be eikonalized. Default is zero */ CrossSection softXSec_; /** * The inv radius^2 of the soft interactions. */ Energy2 softMu2_; }; /** * A struct for the eikonalization of the inclusive cross section. */ struct Eikonalization : public GSLHelper{ /** * The constructor * @param handler is the pointer to the MPIHandler to get access to * MPIHandler::OverlapFunction and member variables of the MPIHandler. * @param option is a flag, whether the inelastic or the total * @param handler The handler * @param hard The hard cross section * @param soft The soft cross section * @param softMu2 \f$\mu^2\f$ * cross section should be returned (-2 or -1). For option = N > 0 the integrand * is N*(A(b)*sigma)^N/N! exp(-A(b)*sigma) this is the P_N*sigma where * P_N is the Probability of having exactly N interaction (including the hard one) * This is equation 14 from "Jimmy4: Multiparton Interactions in HERWIG for the LHC" */ Eikonalization(tcMPIHPtr handler, int option, CrossSection hard, CrossSection soft=0*millibarn, Energy2 softMu2=ZERO) : theHandler(handler), theoption(option), hardXSec_(hard), softXSec_(soft), softMu2_(softMu2) {} /** * Get the function value */ Length operator ()(Length argument) const; private: /** * Pointer to the Handler that calls this integrand */ tcMPIHPtr theHandler; /** * A flag to switch between the calculation of total and inelastic cross section * or calculations for the individual probabilities. See the constructor */ int theoption; /** * The hard cross section to be eikonalized */ CrossSection hardXSec_; /** * The soft cross section to be eikonalized. Default is zero */ CrossSection softXSec_; /** * The inv radius^2 of the soft interactions. */ Energy2 softMu2_; }; } #endif /* HERWIG_MPIHandler_H */ diff --git a/Utilities/GaussianIntegrator.h b/Utilities/GaussianIntegrator.h --- a/Utilities/GaussianIntegrator.h +++ b/Utilities/GaussianIntegrator.h @@ -1,132 +1,125 @@ // -*- C++ -*- // // GaussianIntegrator.h is a part of Herwig - A multi-purpose Monte Carlo event generator // Copyright (C) 2002-2017 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. // #ifndef HERWIG_GaussianIntegrator_H #define HERWIG_GaussianIntegrator_H // // This is the declaration of the GaussianIntegrator class. // #include "ThePEG/Pointer/ReferenceCounted.h" #include "ThePEG/Repository/CurrentGenerator.h" #include namespace Herwig { using namespace ThePEG; /** \ingroup Utilities * \author Peter Richardson * This class is designed to perform the integral of a function * using Gaussian quadrature.The method is adaptive based on using 6th,12th, * 24th,48th, or 96th order Gaussian quadrature combined with * subdivision of the integral if this is insufficient. * * The class is templated on a simple class which should provide a * T::operator () (double) const which provides the integrand for the function. */ class GaussianIntegrator : public Pointer::ReferenceCounted { public: /** @name Standard constructors and destructors. */ //@{ /** * Default Constructor */ GaussianIntegrator() - : _abserr(1.E-35), _relerr(5.E-5), _binwidth(1.E-5), - _maxint(100), _maxeval(100000) { + : _abserr(1.E-35), _relerr(5.E-5), _binwidth(1.E-5), _maxeval(100000) { // setup the weights and abscissae Init(); } /** * Specify all the parameters. * @param abserr Absolute error. * @param relerr Relative error. * @param binwidth Width of the bin as a fraction of the integration region. - * @param maxint Maximum number of intervals * @param maxeval Maximum number of function evaluations */ GaussianIntegrator(double abserr, double relerr, double binwidth, - int maxint, int maxeval) + int maxeval) : _abserr(abserr), _relerr(relerr), - _binwidth(binwidth), _maxint(maxint), + _binwidth(binwidth), _maxeval(maxeval) { // setup the weights and abscissae Init(); } /// helper type for the integration result template using ValT = decltype(std::declval() * std::declval()); /** * The value of the integral * @param lower The lower limit of integration. * @param upper The upper limit of integration. */ template inline ValT value(const T &, const typename T::ArgType lower, const typename T::ArgType upper) const; private: /** * The assignment operator is private and must never be called. * In fact, it should not even be implemented. */ GaussianIntegrator & operator=(const GaussianIntegrator &) = delete; /** * Initialise the weights and abscissae. */ void Init(); private: /** * The weights for the gaussian quadrature. */ std::vector< std::vector > _weights; /** * The abscissae. */ std::vector< std::vector > _abscissae; /** * The parameters controlling the error. */ double _abserr,_relerr; /** * The minimum width of a bin as a fraction of the integration region. */ double _binwidth; /** - * Maximum number of bins. - */ - int _maxint; - - /** * Maximum number of function evaluations. */ int _maxeval; }; } #include "GaussianIntegrator.tcc" #endif /* HERWIG_GaussianIntegrator_H */