Page MenuHomeHEPForge

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/MatrixElement/DIS/DISBase.cc b/MatrixElement/DIS/DISBase.cc
--- a/MatrixElement/DIS/DISBase.cc
+++ b/MatrixElement/DIS/DISBase.cc
@@ -1,1360 +1,1360 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the DISBase class.
//
#include "DISBase.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/MatrixElement/Tree2toNDiagram.h"
#include "Herwig++/Utilities/Maths.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/PDT/StandardMatchers.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Repository/CurrentGenerator.h"
#include "ThePEG/Helicity/Vertex/AbstractFFVVertex.h"
#include "Herwig++/PDT/StandardMatchers.h"
#include "Herwig++/Models/StandardModel/StandardModel.h"
#include <numeric>
#include "Herwig++/Shower/Base/ShowerProgenitor.h"
#include "Herwig++/Shower/Base/ShowerTree.h"
#include "Herwig++/Shower/Base/Branching.h"
#include "Herwig++/Shower/Base/HardTree.h"
using namespace Herwig;
using namespace ThePEG::Helicity;
-namespace {
-using namespace Herwig;
-using namespace ThePEG::Helicity;
-
-void debuggingMatrixElement(bool BGF,const Lorentz5Momentum & pin,
- const Lorentz5Momentum & p1,
- const Lorentz5Momentum & p2,
- tcPDPtr gluon,
- const Lorentz5Momentum & pl1,
- const Lorentz5Momentum & pl2,
- const Lorentz5Momentum & pq1,
- const Lorentz5Momentum & pq2,
- tcPDPtr lepton1,tcPDPtr lepton2,
- tcPDPtr quark1 ,tcPDPtr quark2,
- Energy2 Q2,double phi, double x2, double x3,
- double xperp, double zp, double xp,
- const vector<double> & azicoeff,
- bool normalize) {
- tcHwSMPtr hwsm=ThePEG::dynamic_ptr_cast<tcHwSMPtr>
- (CurrentGenerator::current().standardModel());
- assert(hwsm);
- vector<AbstractFFVVertexPtr> weakVertex;
- vector<PDPtr> bosons;
- AbstractFFVVertexPtr strongVertex = hwsm->vertexFFG();
- if(lepton1->id()==lepton2->id()) {
- weakVertex.push_back(hwsm->vertexFFZ());
- bosons.push_back(hwsm->getParticleData(ParticleID::Z0));
- weakVertex.push_back(hwsm->vertexFFP());
- bosons.push_back(hwsm->getParticleData(ParticleID::gamma));
- }
- else {
- weakVertex.push_back(hwsm->vertexFFW());
- bosons.push_back(hwsm->getParticleData(ParticleID::Wplus));
- }
- if(!BGF) {
- SpinorWaveFunction l1,q1,qp1;
- SpinorBarWaveFunction l2,q2,qp2;
- VectorWaveFunction gl(p2,gluon,outgoing);
- if(lepton1->id()>0) {
- l1 = SpinorWaveFunction (pl1,lepton1,incoming);
- l2 = SpinorBarWaveFunction(pl2,lepton2,outgoing);
- }
- else {
- l1 = SpinorWaveFunction (pl2,lepton2,outgoing);
- l2 = SpinorBarWaveFunction(pl1,lepton1,incoming);
- }
- if(quark1->id()>0) {
- q1 = SpinorWaveFunction (pq1,quark1,incoming);
- q2 = SpinorBarWaveFunction(pq2,quark2,outgoing);
- qp1 = SpinorWaveFunction (pin,quark1,incoming);
- qp2 = SpinorBarWaveFunction(p1 ,quark2,outgoing);
- }
- else {
- q1 = SpinorWaveFunction (pq2,quark2,outgoing);
- q2 = SpinorBarWaveFunction(pq1,quark1,incoming);
- qp1 = SpinorWaveFunction (p1 ,quark2,outgoing);
- qp2 = SpinorBarWaveFunction(pin,quark1,incoming);
- }
- double lome(0.),realme(0.);
- for(unsigned int lhel1=0;lhel1<2;++lhel1) {
- l1.reset(lhel1);
- for(unsigned int lhel2=0;lhel2<2;++lhel2) {
- l2.reset(lhel2);
- for(unsigned int qhel1=0;qhel1<2;++qhel1) {
- q1.reset(qhel1);
- qp1.reset(qhel1);
- for(unsigned int qhel2=0;qhel2<2;++qhel2) {
- q2.reset(qhel2);
- qp2.reset(qhel2);
- // leading order matrix element
- Complex diagLO(0.);
- for(unsigned int ix=0;ix<weakVertex.size();++ix) {
- VectorWaveFunction inter =
- weakVertex[ix]->evaluate(Q2,3,bosons[ix],l1,l2);
- diagLO += weakVertex[ix]->evaluate(Q2,q1,q2,inter);
- }
- lome += norm(diagLO);
- // real emission matrix element
- for(unsigned int ghel=0;ghel<2;++ghel) {
- gl.reset(2*ghel);
- Complex diagReal(0.);
- for(unsigned int ix=0;ix<weakVertex.size();++ix) {
- VectorWaveFunction inter =
- weakVertex[ix]->evaluate(Q2,3,bosons[ix],l1,l2);
- SpinorWaveFunction off1 =
- strongVertex->evaluate(Q2,5,qp1.particle(),qp1,gl);
- Complex diag1 = weakVertex[ix]->evaluate(Q2,off1,qp2,inter);
- SpinorBarWaveFunction off2 =
- strongVertex->evaluate(Q2,5,qp2.particle(),qp2,gl);
- Complex diag2 = weakVertex[ix]->evaluate(Q2,qp1,off2,inter);
- diagReal += diag1+diag2;
- }
- realme += norm(diagReal);
- }
- }
- }
- }
- }
- double test1 = realme/lome/hwsm->alphaS(Q2)*Q2*UnitRemoval::InvE2;
- double cphi(cos(phi));
- double test2;
- if(normalize) {
- test2 = 8.*Constants::pi/(1.-xp)/(1.-zp)*
- (azicoeff[0]+azicoeff[1]*cphi+azicoeff[2]*sqr(cphi))*
- (1.+sqr(xp)*(sqr(x2)+1.5*sqr(xperp)));
- }
- else {
- test2 = 8.*Constants::pi/(1.-xp)/(1.-zp)*
- (azicoeff[0]+azicoeff[1]*cphi+azicoeff[2]*sqr(cphi));
- }
- cerr << "testing RATIO A " << test1/test2 << "\n";
- }
- else {
- SpinorWaveFunction l1,q1,qp1;
- SpinorBarWaveFunction l2,q2,qp2;
- VectorWaveFunction gl(pin,gluon,incoming);
- if(lepton1->id()>0) {
- l1 = SpinorWaveFunction (pl1,lepton1,incoming);
- l2 = SpinorBarWaveFunction(pl2,lepton2,outgoing);
- }
- else {
- l1 = SpinorWaveFunction (pl2,lepton2,outgoing);
- l2 = SpinorBarWaveFunction(pl1,lepton1,incoming);
- }
- if(quark1->id()>0) {
- q1 = SpinorWaveFunction (pq1,quark1 ,incoming);
- q2 = SpinorBarWaveFunction(pq2,quark2 ,outgoing);
- qp2 = SpinorBarWaveFunction(p1 ,quark2 ,outgoing);
- qp1 = SpinorWaveFunction (p2 ,quark1->CC(),outgoing);
- }
- else {
- q1 = SpinorWaveFunction (pq2,quark2 ,outgoing);
- q2 = SpinorBarWaveFunction(pq1,quark1 ,incoming);
- qp2 = SpinorBarWaveFunction(p2 ,quark1->CC(),outgoing);
- qp1 = SpinorWaveFunction (p1 ,quark2 ,outgoing);
- }
- double lome(0.),realme(0.);
- for(unsigned int lhel1=0;lhel1<2;++lhel1) {
- l1.reset(lhel1);
- for(unsigned int lhel2=0;lhel2<2;++lhel2) {
- l2.reset(lhel2);
- for(unsigned int qhel1=0;qhel1<2;++qhel1) {
- q1.reset(qhel1);
- qp1.reset(qhel1);
- for(unsigned int qhel2=0;qhel2<2;++qhel2) {
- q2.reset(qhel2);
- qp2.reset(qhel2);
- // leading order matrix element
- Complex diagLO(0.);
- for(unsigned int ix=0;ix<weakVertex.size();++ix) {
- VectorWaveFunction inter =
- weakVertex[ix]->evaluate(Q2,3,bosons[ix],l1,l2);
- diagLO += weakVertex[ix]->evaluate(Q2,q1,q2,inter);
- }
- lome += norm(diagLO);
- // real emission matrix element
- for(unsigned int ghel=0;ghel<2;++ghel) {
- gl.reset(2*ghel);
- Complex diagReal(0.);
- for(unsigned int ix=0;ix<weakVertex.size();++ix) {
- VectorWaveFunction inter =
- weakVertex[ix]->evaluate(Q2,3,bosons[ix],l1,l2);
- SpinorWaveFunction off1 =
- strongVertex->evaluate(Q2,5,qp1.particle(),qp1,gl);
- Complex diag1 = weakVertex[ix]->evaluate(Q2,off1,qp2,inter);
- SpinorBarWaveFunction off2 =
- strongVertex->evaluate(Q2,5,qp2.particle(),qp2,gl);
- Complex diag2 = weakVertex[ix]->evaluate(Q2,qp1,off2,inter);
- diagReal += diag1+diag2;
- }
- realme += norm(diagReal);
- }
- }
- }
- }
- }
- double test1 = realme/lome/hwsm->alphaS(Q2)*Q2*UnitRemoval::InvE2;
- double cphi(cos(phi));
- double test2;
- if(normalize) {
- test2 = 8.*Constants::pi/zp/(1.-zp)*
- (azicoeff[0]+azicoeff[1]*cphi+azicoeff[2]*sqr(cphi))*
- sqr(xp)*(sqr(x3)+sqr(x2)+3.*sqr(xperp));
- }
- else {
- test2 = 8.*Constants::pi/zp/(1.-zp)*
- (azicoeff[0]+azicoeff[1]*cphi+azicoeff[2]*sqr(cphi));
- }
- cerr << "testing RATIO B " << test1/test2 << "\n";
- }
-}
-
-}
+// namespace {
+// using namespace Herwig;
+// using namespace ThePEG::Helicity;
+//
+// void debuggingMatrixElement(bool BGF,const Lorentz5Momentum & pin,
+// const Lorentz5Momentum & p1,
+// const Lorentz5Momentum & p2,
+// tcPDPtr gluon,
+// const Lorentz5Momentum & pl1,
+// const Lorentz5Momentum & pl2,
+// const Lorentz5Momentum & pq1,
+// const Lorentz5Momentum & pq2,
+// tcPDPtr lepton1,tcPDPtr lepton2,
+// tcPDPtr quark1 ,tcPDPtr quark2,
+// Energy2 Q2,double phi, double x2, double x3,
+// double xperp, double zp, double xp,
+// const vector<double> & azicoeff,
+// bool normalize) {
+// tcHwSMPtr hwsm=ThePEG::dynamic_ptr_cast<tcHwSMPtr>
+// (CurrentGenerator::current().standardModel());
+// assert(hwsm);
+// vector<AbstractFFVVertexPtr> weakVertex;
+// vector<PDPtr> bosons;
+// AbstractFFVVertexPtr strongVertex = hwsm->vertexFFG();
+// if(lepton1->id()==lepton2->id()) {
+// weakVertex.push_back(hwsm->vertexFFZ());
+// bosons.push_back(hwsm->getParticleData(ParticleID::Z0));
+// weakVertex.push_back(hwsm->vertexFFP());
+// bosons.push_back(hwsm->getParticleData(ParticleID::gamma));
+// }
+// else {
+// weakVertex.push_back(hwsm->vertexFFW());
+// bosons.push_back(hwsm->getParticleData(ParticleID::Wplus));
+// }
+// if(!BGF) {
+// SpinorWaveFunction l1,q1,qp1;
+// SpinorBarWaveFunction l2,q2,qp2;
+// VectorWaveFunction gl(p2,gluon,outgoing);
+// if(lepton1->id()>0) {
+// l1 = SpinorWaveFunction (pl1,lepton1,incoming);
+// l2 = SpinorBarWaveFunction(pl2,lepton2,outgoing);
+// }
+// else {
+// l1 = SpinorWaveFunction (pl2,lepton2,outgoing);
+// l2 = SpinorBarWaveFunction(pl1,lepton1,incoming);
+// }
+// if(quark1->id()>0) {
+// q1 = SpinorWaveFunction (pq1,quark1,incoming);
+// q2 = SpinorBarWaveFunction(pq2,quark2,outgoing);
+// qp1 = SpinorWaveFunction (pin,quark1,incoming);
+// qp2 = SpinorBarWaveFunction(p1 ,quark2,outgoing);
+// }
+// else {
+// q1 = SpinorWaveFunction (pq2,quark2,outgoing);
+// q2 = SpinorBarWaveFunction(pq1,quark1,incoming);
+// qp1 = SpinorWaveFunction (p1 ,quark2,outgoing);
+// qp2 = SpinorBarWaveFunction(pin,quark1,incoming);
+// }
+// double lome(0.),realme(0.);
+// for(unsigned int lhel1=0;lhel1<2;++lhel1) {
+// l1.reset(lhel1);
+// for(unsigned int lhel2=0;lhel2<2;++lhel2) {
+// l2.reset(lhel2);
+// for(unsigned int qhel1=0;qhel1<2;++qhel1) {
+// q1.reset(qhel1);
+// qp1.reset(qhel1);
+// for(unsigned int qhel2=0;qhel2<2;++qhel2) {
+// q2.reset(qhel2);
+// qp2.reset(qhel2);
+// // leading order matrix element
+// Complex diagLO(0.);
+// for(unsigned int ix=0;ix<weakVertex.size();++ix) {
+// VectorWaveFunction inter =
+// weakVertex[ix]->evaluate(Q2,3,bosons[ix],l1,l2);
+// diagLO += weakVertex[ix]->evaluate(Q2,q1,q2,inter);
+// }
+// lome += norm(diagLO);
+// // real emission matrix element
+// for(unsigned int ghel=0;ghel<2;++ghel) {
+// gl.reset(2*ghel);
+// Complex diagReal(0.);
+// for(unsigned int ix=0;ix<weakVertex.size();++ix) {
+// VectorWaveFunction inter =
+// weakVertex[ix]->evaluate(Q2,3,bosons[ix],l1,l2);
+// SpinorWaveFunction off1 =
+// strongVertex->evaluate(Q2,5,qp1.particle(),qp1,gl);
+// Complex diag1 = weakVertex[ix]->evaluate(Q2,off1,qp2,inter);
+// SpinorBarWaveFunction off2 =
+// strongVertex->evaluate(Q2,5,qp2.particle(),qp2,gl);
+// Complex diag2 = weakVertex[ix]->evaluate(Q2,qp1,off2,inter);
+// diagReal += diag1+diag2;
+// }
+// realme += norm(diagReal);
+// }
+// }
+// }
+// }
+// }
+// double test1 = realme/lome/hwsm->alphaS(Q2)*Q2*UnitRemoval::InvE2;
+// double cphi(cos(phi));
+// double test2;
+// if(normalize) {
+// test2 = 8.*Constants::pi/(1.-xp)/(1.-zp)*
+// (azicoeff[0]+azicoeff[1]*cphi+azicoeff[2]*sqr(cphi))*
+// (1.+sqr(xp)*(sqr(x2)+1.5*sqr(xperp)));
+// }
+// else {
+// test2 = 8.*Constants::pi/(1.-xp)/(1.-zp)*
+// (azicoeff[0]+azicoeff[1]*cphi+azicoeff[2]*sqr(cphi));
+// }
+// cerr << "testing RATIO A " << test1/test2 << "\n";
+// }
+// else {
+// SpinorWaveFunction l1,q1,qp1;
+// SpinorBarWaveFunction l2,q2,qp2;
+// VectorWaveFunction gl(pin,gluon,incoming);
+// if(lepton1->id()>0) {
+// l1 = SpinorWaveFunction (pl1,lepton1,incoming);
+// l2 = SpinorBarWaveFunction(pl2,lepton2,outgoing);
+// }
+// else {
+// l1 = SpinorWaveFunction (pl2,lepton2,outgoing);
+// l2 = SpinorBarWaveFunction(pl1,lepton1,incoming);
+// }
+// if(quark1->id()>0) {
+// q1 = SpinorWaveFunction (pq1,quark1 ,incoming);
+// q2 = SpinorBarWaveFunction(pq2,quark2 ,outgoing);
+// qp2 = SpinorBarWaveFunction(p1 ,quark2 ,outgoing);
+// qp1 = SpinorWaveFunction (p2 ,quark1->CC(),outgoing);
+// }
+// else {
+// q1 = SpinorWaveFunction (pq2,quark2 ,outgoing);
+// q2 = SpinorBarWaveFunction(pq1,quark1 ,incoming);
+// qp2 = SpinorBarWaveFunction(p2 ,quark1->CC(),outgoing);
+// qp1 = SpinorWaveFunction (p1 ,quark2 ,outgoing);
+// }
+// double lome(0.),realme(0.);
+// for(unsigned int lhel1=0;lhel1<2;++lhel1) {
+// l1.reset(lhel1);
+// for(unsigned int lhel2=0;lhel2<2;++lhel2) {
+// l2.reset(lhel2);
+// for(unsigned int qhel1=0;qhel1<2;++qhel1) {
+// q1.reset(qhel1);
+// qp1.reset(qhel1);
+// for(unsigned int qhel2=0;qhel2<2;++qhel2) {
+// q2.reset(qhel2);
+// qp2.reset(qhel2);
+// // leading order matrix element
+// Complex diagLO(0.);
+// for(unsigned int ix=0;ix<weakVertex.size();++ix) {
+// VectorWaveFunction inter =
+// weakVertex[ix]->evaluate(Q2,3,bosons[ix],l1,l2);
+// diagLO += weakVertex[ix]->evaluate(Q2,q1,q2,inter);
+// }
+// lome += norm(diagLO);
+// // real emission matrix element
+// for(unsigned int ghel=0;ghel<2;++ghel) {
+// gl.reset(2*ghel);
+// Complex diagReal(0.);
+// for(unsigned int ix=0;ix<weakVertex.size();++ix) {
+// VectorWaveFunction inter =
+// weakVertex[ix]->evaluate(Q2,3,bosons[ix],l1,l2);
+// SpinorWaveFunction off1 =
+// strongVertex->evaluate(Q2,5,qp1.particle(),qp1,gl);
+// Complex diag1 = weakVertex[ix]->evaluate(Q2,off1,qp2,inter);
+// SpinorBarWaveFunction off2 =
+// strongVertex->evaluate(Q2,5,qp2.particle(),qp2,gl);
+// Complex diag2 = weakVertex[ix]->evaluate(Q2,qp1,off2,inter);
+// diagReal += diag1+diag2;
+// }
+// realme += norm(diagReal);
+// }
+// }
+// }
+// }
+// }
+// double test1 = realme/lome/hwsm->alphaS(Q2)*Q2*UnitRemoval::InvE2;
+// double cphi(cos(phi));
+// double test2;
+// if(normalize) {
+// test2 = 8.*Constants::pi/zp/(1.-zp)*
+// (azicoeff[0]+azicoeff[1]*cphi+azicoeff[2]*sqr(cphi))*
+// sqr(xp)*(sqr(x3)+sqr(x2)+3.*sqr(xperp));
+// }
+// else {
+// test2 = 8.*Constants::pi/zp/(1.-zp)*
+// (azicoeff[0]+azicoeff[1]*cphi+azicoeff[2]*sqr(cphi));
+// }
+// cerr << "testing RATIO B " << test1/test2 << "\n";
+// }
+// }
+//
+// }
DISBase::DISBase() : initial_(6.), final_(3.),
procProb_(0.35),
comptonInt_(0.), bgfInt_(0.),
comptonWeight_(50.), BGFWeight_(150.),
pTmin_(0.1*GeV),
scaleOpt_(1), muF_(100.*GeV), scaleFact_(1.),
contrib_(0), power_(0.1)
{}
DISBase::~DISBase() {}
void DISBase::persistentOutput(PersistentOStream & os) const {
os << comptonInt_ << bgfInt_ << procProb_ << initial_ << final_ << alpha_
<< ounit(pTmin_,GeV) << comptonWeight_ << BGFWeight_ << gluon_
<< ounit(muF_,GeV) << scaleFact_ << scaleOpt_ << contrib_<< power_;
}
void DISBase::persistentInput(PersistentIStream & is, int) {
is >> comptonInt_ >> bgfInt_ >> procProb_ >> initial_ >> final_ >> alpha_
>> iunit(pTmin_,GeV) >> comptonWeight_ >> BGFWeight_ >> gluon_
>> iunit(muF_,GeV) >> scaleFact_ >> scaleOpt_ >> contrib_ >> power_;
}
AbstractClassDescription<DISBase> DISBase::initDISBase;
// Definition of the static class description member.
void DISBase::Init() {
static ClassDocumentation<DISBase> documentation
("The DISBase class provides the base class for the "
"implementation of DIS type processes including the "
"hard corrections in either the old-fashioned matrix "
"element correction of POWHEG approaches");
static Parameter<DISBase,double> interfaceProcessProbability
("ProcessProbability",
"The probabilty of the QCD compton process for the process selection",
&DISBase::procProb_, 0.3, 0.0, 1.,
false, false, Interface::limited);
static Reference<DISBase,ShowerAlpha> interfaceCoupling
("Coupling",
"Pointer to the object to calculate the coupling for the correction",
&DISBase::alpha_, false, false, true, false, false);
static Parameter<DISBase,Energy> interfacepTMin
("pTMin",
"The minimum pT",
&DISBase::pTmin_, GeV, 1.*GeV, 0.0*GeV, 10.0*GeV,
false, false, Interface::limited);
static Parameter<DISBase,double> interfaceComptonWeight
("ComptonWeight",
"Weight for the overestimate ofthe compton channel",
&DISBase::comptonWeight_, 50.0, 0.0, 100.0,
false, false, Interface::limited);
static Parameter<DISBase,double> interfaceBGFWeight
("BGFWeight",
"Weight for the overestimate of the BGF channel",
&DISBase::BGFWeight_, 100.0, 0.0, 1000.0,
false, false, Interface::limited);
static Switch<DISBase,unsigned int> interfaceContribution
("Contribution",
"Which contributions to the cross section to include",
&DISBase::contrib_, 0, 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<DISBase,unsigned int> interfaceScaleOption
("ScaleOption",
"Option for the choice of factorization (and renormalization) scale",
&DISBase::scaleOpt_, 1, false, false);
static SwitchOption interfaceDynamic
(interfaceScaleOption,
"Dynamic",
"Dynamic factorization scale equal to the current sqrt(sHat())",
1);
static SwitchOption interfaceFixed
(interfaceScaleOption,
"Fixed",
"Use a fixed factorization scale set with FactorizationScaleValue",
2);
static Parameter<DISBase,Energy> interfaceFactorizationScale
("FactorizationScale",
"Value to use in the event of a fixed factorization scale",
&DISBase::muF_, GeV, 100.0*GeV, 1.0*GeV, 500.0*GeV,
true, false, Interface::limited);
static Parameter<DISBase,double> interfaceScaleFactor
("ScaleFactor",
"The factor used before Q2 if using a running scale",
&DISBase::scaleFact_, 1.0, 0.0, 10.0,
false, false, Interface::limited);
static Parameter<DISBase,double> interfaceSamplingPower
("SamplingPower",
"Power for the sampling of xp",
&DISBase::power_, 0.6, 0.0, 1.,
false, false, Interface::limited);
}
void DISBase::doinit() {
HwMEBase::doinit();
// integrals of me over phase space
double r5=sqrt(5.),darg((r5-1.)/(r5+1.)),ath(0.5*log((1.+1./r5)/(1.-1./r5)));
comptonInt_ = 2.*(-21./20.-6./(5.*r5)*ath+sqr(Constants::pi)/3.
-2.*Math::ReLi2(1.-darg)-2.*Math::ReLi2(1.-1./darg));
bgfInt_ = 121./9.-56./r5*ath;
// extract the gluon ParticleData objects
gluon_ = getParticleData(ParticleID::g);
}
void DISBase::initializeMECorrection(ShowerTreePtr tree, double & initial,
double & final) {
initial = initial_;
final = final_;
// incoming particles
for(map<ShowerProgenitorPtr,ShowerParticlePtr>::const_iterator
cit=tree->incomingLines().begin();cit!=tree->incomingLines().end();++cit) {
if(QuarkMatcher::Check(cit->first->progenitor()->data())) {
partons_[0] = cit->first->progenitor()->dataPtr();
pq_[0] = cit->first->progenitor()->momentum();
}
else if(LeptonMatcher::Check(cit->first->progenitor()->data())) {
leptons_[0] = cit->first->progenitor()->dataPtr();
pl_[0] = cit->first->progenitor()->momentum();
}
}
// outgoing particles
for(map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator
cit=tree->outgoingLines().begin();cit!=tree->outgoingLines().end();++cit) {
if(QuarkMatcher::Check(cit->first->progenitor()->data())) {
partons_[1] = cit->first->progenitor()->dataPtr();
pq_[1] = cit->first->progenitor()->momentum();
}
else if(LeptonMatcher::Check(cit->first->progenitor()->data())) {
leptons_[1] = cit->first->progenitor()->dataPtr();
pl_[1] = cit->first->progenitor()->momentum();
}
}
// extract the born variables
q_ =pl_[0]-pl_[1];
q2_ = -q_.m2();
double yB = (q_*pq_[0])/(pl_[0]*pq_[0]);
l_ = 2./yB-1.;
// calculate the A coefficient for the correlations
acoeff_ = A(leptons_[0],leptons_[1],
partons_[0],partons_[1],q2_);
}
void DISBase::applyHardMatrixElementCorrection(ShowerTreePtr tree) {
static const double eps=1e-6;
// find the incoming and outgoing quarks and leptons
ShowerParticlePtr quark[2],lepton[2];
PPtr hadron;
// incoming particles
for(map<ShowerProgenitorPtr,ShowerParticlePtr>::const_iterator
cit=tree->incomingLines().begin();cit!=tree->incomingLines().end();++cit) {
if(QuarkMatcher::Check(cit->first->progenitor()->data())) {
hadron = cit->first->original()->parents()[0];
quark [0] = cit->first->progenitor();
beam_ = cit->first->beam();
}
else if(LeptonMatcher::Check(cit->first->progenitor()->data())) {
lepton[0] = cit->first->progenitor();
}
}
pdf_ = beam_->pdf();
assert(beam_&&pdf_&&quark[0]&&lepton[0]);
// outgoing particles
for(map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator
cit=tree->outgoingLines().begin();cit!=tree->outgoingLines().end();++cit) {
if(QuarkMatcher::Check(cit->first->progenitor()->data()))
quark [1] = cit->first->progenitor();
else if(LeptonMatcher::Check(cit->first->progenitor()->data())) {
lepton[1] = cit->first->progenitor();
}
}
// momentum fraction
assert(quark[1]&&lepton[1]);
xB_ = quark[0]->x();
// calculate the matrix element
vector<double> azicoeff;
// select the type of process
bool BGF = UseRandom::rnd()>procProb_;
double xp,zp,wgt,x1,x2,x3,xperp;
// generate a QCD compton process
if(!BGF) {
wgt = generateComptonPoint(xp,zp);
if(xp<eps) return;
// common pieces
Energy2 scale = q2_*((1.-xp)*(1-zp)*zp/xp+1.);
wgt *= 2./3./Constants::pi*alpha_->value(scale)/procProb_;
// PDF piece
wgt *= pdf_->xfx(beam_,quark[0]->dataPtr(),scale,xB_/xp)/
pdf_->xfx(beam_,quark[0]->dataPtr(),q2_ ,xB_);
// other bits
xperp = sqrt(4.*(1.-xp)*(1.-zp)*zp/xp);
x1 = -1./xp;
x2 = 1.-(1.-zp)/xp;
x3 = 2.+x1-x2;
// matrix element pieces
azicoeff = ComptonME(xp,x2,xperp,true);
}
// generate a BGF process
else {
wgt = generateBGFPoint(xp,zp);
if(xp<eps) return;
// common pieces
Energy2 scale = q2_*((1.-xp)*(1-zp)*zp/xp+1);
wgt *= 0.25/Constants::pi*alpha_->value(scale)/(1.-procProb_);
// PDF piece
wgt *= pdf_->xfx(beam_,gluon_ ,scale,xB_/xp)/
pdf_->xfx(beam_,quark[0]->dataPtr(),q2_ ,xB_);
// other bits
xperp = sqrt(4.*(1.-xp)*(1.-zp)*zp/xp);
x1 = -1./xp;
x2 = 1.-(1.-zp)/xp;
x3 = 2.+x1-x2;
// matrix element pieces
azicoeff = BGFME(xp,x2,x3,xperp,true);
}
// compute the azimuthal average of the weight
wgt *= (azicoeff[0]+0.5*azicoeff[2]);
// decide whether or not to accept the weight
if(UseRandom::rnd()>wgt) return;
// if generate generate phi
unsigned int itry(0);
double phimax = std::accumulate(azicoeff.begin(),azicoeff.end(),0.);
double phiwgt,phi;
do {
phi = UseRandom::rnd()*Constants::twopi;
double cphi(cos(phi));
phiwgt = azicoeff[0]+azicoeff[1]*cphi+azicoeff[2]*sqr(cphi);
++itry;
}
while (phimax*UseRandom::rnd() > phiwgt && itry<200);
if(itry==200) throw Exception() << "Too many tries in DISMECorrection"
<< "::applyHardMatrixElementCorrection() to"
<< " generate phi" << Exception::eventerror;
// construct lorentz transform from lab to breit frame
Lorentz5Momentum phadron = hadron->momentum();
phadron.setMass(0.*GeV);
phadron.rescaleEnergy();
Lorentz5Momentum pcmf = phadron+0.5/xB_*q_;
pcmf.rescaleMass();
LorentzRotation rot(-pcmf.boostVector());
Lorentz5Momentum pbeam = rot*phadron;
Axis axis(pbeam.vect().unit());
double sinth(sqrt(sqr(axis.x())+sqr(axis.y())));
rot.rotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.));
Lorentz5Momentum pl = rot*pl_[0];
rot.rotateZ(-atan2(pl.y(),pl.x()));
pl_[0] *= rot;
pl_[1] *= rot;
pq_[0] *= rot;
pq_[1] *= rot;
// compute the new incoming and outgoing momenta
Energy Q(sqrt(q2_));
Lorentz5Momentum p1 = Lorentz5Momentum( 0.5*Q*xperp*cos(phi), 0.5*Q*xperp*sin(phi),
-0.5*Q*x2,0.*GeV,0.*GeV);
p1.rescaleEnergy();
Lorentz5Momentum p2 = Lorentz5Momentum(-0.5*Q*xperp*cos(phi),-0.5*Q*xperp*sin(phi),
-0.5*Q*x3,0.*GeV,0.*GeV);
p2.rescaleEnergy();
Lorentz5Momentum pin(0.*GeV,0.*GeV,-0.5*x1*Q,-0.5*x1*Q,0.*GeV);
// debuggingMatrixElement(BGF,pin,p1,p2,gluon_,pl_[0],pl_[1],pq_[0],pq_[1],
// lepton[0]->dataPtr(),lepton[1]->dataPtr(),
// quark [0]->dataPtr(),quark [1]->dataPtr(),
// q2_,phi,x2,x3,xperp,zp,xp,azicoeff,true);
// we need the Lorentz transform back to the lab
rot.invert();
// transform the momenta to lab frame
pin *= rot;
p1 *= rot;
p2 *= rot;
// test to ensure outgoing particles can be put on-shell
if(!BGF) {
if(p1.e()<quark[1]->dataPtr()->constituentMass()) return;
if(p2.e()<gluon_ ->constituentMass()) return;
}
else {
if(p1.e()<quark[1]->dataPtr() ->constituentMass()) return;
if(p2.e()<quark[0]->dataPtr()->CC()->constituentMass()) return;
}
// create the new particles and add to ShowerTree
bool isquark = quark[0]->colourLine();
if(!BGF) {
PPtr newin = new_ptr(Particle(*quark[0]));
newin->set5Momentum(pin);
PPtr newg = gluon_ ->produceParticle(p2 );
PPtr newout = quark[1]->dataPtr()->produceParticle(p1 );
ColinePtr col=isquark ?
quark[0]->colourLine() : quark[0]->antiColourLine();
ColinePtr newline=new_ptr(ColourLine());
// final-state emission
if(xp>zp) {
col->removeColoured(newout,!isquark);
col->addColoured(newin,!isquark);
col->addColoured(newg,!isquark);
newline->addColoured(newg,isquark);
newline->addColoured(newout,!isquark);
}
// initial-state emission
else {
col->removeColoured(newin ,!isquark);
col->addColoured(newout,!isquark);
col->addColoured(newg,isquark);
newline->addColoured(newg,!isquark);
newline->addColoured(newin,!isquark);
}
PPtr orig;
for(map<ShowerProgenitorPtr,ShowerParticlePtr>::const_iterator
cit=tree->incomingLines().begin();cit!=tree->incomingLines().end();++cit) {
if(cit->first->progenitor()!=quark[0]) continue;
// remove old particles from colour line
col->removeColoured(cit->first->copy(),!isquark);
col->removeColoured(cit->first->progenitor(),!isquark);
// insert new particles
cit->first->copy(newin);
ShowerParticlePtr sp(new_ptr(ShowerParticle(*newin,1,false)));
cit->first->progenitor(sp);
tree->incomingLines()[cit->first]=sp;
sp->x(xB_/xp);
cit->first->perturbative(xp>zp);
if(xp<=zp) orig=cit->first->original();
}
for(map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator
cit=tree->outgoingLines().begin();cit!=tree->outgoingLines().end();++cit) {
if(cit->first->progenitor()!=quark[1]) continue;
// remove old particles from colour line
col->removeColoured(cit->first->copy(),!isquark);
col->removeColoured(cit->first->progenitor(),!isquark);
// insert new particles
cit->first->copy(newout);
ShowerParticlePtr sp(new_ptr(ShowerParticle(*newout,1,true)));
cit->first->progenitor(sp);
tree->outgoingLines()[cit->first]=sp;
cit->first->perturbative(xp<=zp);
if(xp>zp) orig=cit->first->original();
}
assert(orig);
// add the gluon
ShowerParticlePtr sg=new_ptr(ShowerParticle(*newg,1,true));
ShowerProgenitorPtr gluon=new_ptr(ShowerProgenitor(orig,newg,sg));
gluon->perturbative(false);
tree->outgoingLines().insert(make_pair(gluon,sg));
tree->hardMatrixElementCorrection(true);
}
else {
PPtr newin = gluon_ ->produceParticle(pin);
PPtr newqbar = quark[0]->dataPtr()->CC()->produceParticle(p2 );
PPtr newout = quark[1]->dataPtr() ->produceParticle(p1 );
ColinePtr col=isquark ? quark[0]->colourLine() : quark[0]->antiColourLine();
ColinePtr newline=new_ptr(ColourLine());
col ->addColoured(newin ,!isquark);
newline->addColoured(newin , isquark);
col ->addColoured(newout ,!isquark);
newline->addColoured(newqbar, isquark);
PPtr orig;
for(map<ShowerProgenitorPtr,ShowerParticlePtr>::const_iterator
cit=tree->incomingLines().begin();cit!=tree->incomingLines().end();++cit) {
if(cit->first->progenitor()!=quark[0]) continue;
// remove old particles from colour line
col->removeColoured(cit->first->copy(),!isquark);
col->removeColoured(cit->first->progenitor(),!isquark);
// insert new particles
cit->first->copy(newin);
ShowerParticlePtr sp(new_ptr(ShowerParticle(*newin,1,false)));
cit->first->progenitor(sp);
tree->incomingLines()[cit->first]=sp;
sp->x(xB_/xp);
cit->first->perturbative(false);
orig=cit->first->original();
}
for(map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator
cit=tree->outgoingLines().begin();cit!=tree->outgoingLines().end();++cit) {
if(cit->first->progenitor()!=quark[1]) continue;
// remove old particles from colour line
col->removeColoured(cit->first->copy(),!isquark);
col->removeColoured(cit->first->progenitor(),!isquark);
// insert new particles
cit->first->copy(newout);
ShowerParticlePtr sp(new_ptr(ShowerParticle(*newout,1,true)));
cit->first->progenitor(sp);
tree->outgoingLines()[cit->first]=sp;
cit->first->perturbative(true);
}
assert(orig);
// add the (anti)quark
ShowerParticlePtr sqbar=new_ptr(ShowerParticle(*newqbar,1,true));
ShowerProgenitorPtr qbar=new_ptr(ShowerProgenitor(orig,newqbar,sqbar));
qbar->perturbative(false);
tree->outgoingLines().insert(make_pair(qbar,sqbar));
tree->hardMatrixElementCorrection(true);
}
}
bool DISBase::softMatrixElementVeto(ShowerProgenitorPtr initial,
ShowerParticlePtr parent, Branching br) {
bool veto = !UseRandom::rndbool(parent->isFinalState() ? 1./final_ : 1./initial_);
// check if me correction should be applied
long id[2]={initial->id(),parent->id()};
if(id[0]!=id[1]||id[1]==ParticleID::g) return veto;
// get the pT
Energy pT=br.kinematics->pT();
// check if hardest so far
if(pT<initial->highestpT()) return veto;
double kappa(sqr(br.kinematics->scale())/q2_),z(br.kinematics->z());
double zk((1.-z)*kappa);
// final-state
double wgt(0.);
if(parent->isFinalState()) {
double zp=z,xp=1./(1.+z*zk);
double xperp = sqrt(4.*(1.-xp)*(1.-zp)*zp/xp);
double x2 = 1.-(1.-zp)/xp;
vector<double> azicoeff = ComptonME(xp,x2,xperp,false);
wgt = (azicoeff[0]+0.5*azicoeff[2])*xp/(1.+sqr(z))/final_;
if(wgt<.0||wgt>1.) {
ostringstream wstring;
wstring << "Soft ME correction weight too large or "
<< "negative for FSR in DISBase::"
<< "softMatrixElementVeto() soft weight "
<< " xp = " << xp << " zp = " << zp
<< " weight = " << wgt << "\n";
generator()->logWarning( Exception(wstring.str(),
Exception::warning) );
}
}
else {
double xp = 2.*z/(1.+zk+sqrt(sqr(1.+zk)-4.*z*zk));
double zp = 0.5* (1.-zk+sqrt(sqr(1.+zk)-4.*z*zk));
double xperp = sqrt(4.*(1.-xp)*(1.-zp)*zp/xp);
double x1 = -1./xp, x2 = 1.-(1.-zp)/xp, x3 = 2.+x1-x2;
// compton
if(br.ids[0]!=ParticleID::g) {
vector<double> azicoeff = ComptonME(xp,x2,xperp,false);
wgt = (azicoeff[0]+0.5*azicoeff[2])*xp*(1.-z)/(1.-xp)/(1.+sqr(z))/
(1.-zp+xp-2.*xp*(1.-zp));
}
// BGF
else {
vector<double> azicoeff = BGFME(xp,x2,x3,xperp,true);
wgt = (azicoeff[0]+0.5*azicoeff[2])*xp/(1.-zp+xp-2.*xp*(1.-zp))/(sqr(z)+sqr(1.-z));
}
wgt /=initial_;
if(wgt<.0||wgt>1.) {
ostringstream wstring;
wstring << "Soft ME correction weight too large or "
<< "negative for ISR in DISBase::"
<< "softMatrixElementVeto() soft weight "
<< " xp = " << xp << " zp = " << zp
<< " weight = " << wgt << "\n";
generator()->logWarning( Exception(wstring.str(),
Exception::warning) );
}
}
// if not vetoed
if(UseRandom::rndbool(wgt)) {
initial->highestpT(pT);
return false;
}
// otherwise
parent->vetoEmission(br.type,br.kinematics->scale());
return true;
}
double DISBase::generateComptonPoint(double &xp, double & zp) {
static const double maxwgt = 1.;
double wgt;
do {
xp = UseRandom::rnd();
double zpmin = xp, zpmax = 1./(1.+xp*(1.-xp));
zp = 1.-pow((1.-zpmin)/(1.-zpmax),UseRandom::rnd())*(1.-zpmax);
wgt = log((1.-zpmin)/(1.-zpmax))*(1.-zp);
if(UseRandom::rndbool()) swap(xp,zp);
double xperp2 = 4.*(1.-xp)*(1.-zp)*zp/xp,x2=1.-(1.-zp)/xp;
wgt *= 2.*(1.+sqr(xp)*(sqr(x2)+1.5*xperp2))/(1.-xp)/(1.-zp);
if(wgt>maxwgt) {
ostringstream wstring;
wstring << "DISBase::generateComptonPoint "
<< "Weight greater than maximum "
<< "wgt = " << wgt << " maxwgt = 1\n";
generator()->logWarning( Exception(wstring.str(),
Exception::warning) );
}
}
while(wgt<UseRandom::rnd()*maxwgt);
return comptonInt_;
}
double DISBase::generateBGFPoint(double &xp, double & zp) {
static const double maxwgt = 25.;
double wgt;
do {
xp = UseRandom::rnd();
double zpmax = 1./(1.+xp*(1.-xp)), zpmin = 1.-zpmax;
zp = 1.-pow((1.-zpmin)/(1.-zpmax),UseRandom::rnd())*(1.-zpmax);
wgt = log((1.-zpmin)/(1.-zpmax))*(1.-zp);
double x1 = -1./xp;
double x2 = 1.-(1.-zp)/xp;
double x3 = 2.+x1-x2;
double xperp2 = 4.*(1.-xp)*(1.-zp)*zp/xp;
wgt *= sqr(xp)/(1.-zp)*(sqr(x3)+sqr(x2)+3.*xperp2);
if(wgt>maxwgt) {
ostringstream wstring;
wstring << "DISBase::generateBGFPoint "
<< "Weight greater than maximum "
<< "wgt = " << wgt << " maxwgt = 1\n";
generator()->logWarning( Exception(wstring.str(),
Exception::warning) );
}
}
while(wgt<UseRandom::rnd()*maxwgt);
return bgfInt_;
// static const double maxwgt = 2.,npow=0.34,ac=1.0;
// double wgt;
// do {
// double rho = UseRandom::rnd();
// xp = 1.-pow(rho,1./(1.-npow));
// wgt = (sqr(xp)+ac+sqr(1.-xp));
// if(wgt>1.+ac) cerr << "testing violates BGF maxA " << wgt << "\n";
// }
// while(wgt<UseRandom::rnd()*(1.+ac));
// double xpwgt = -((6.-5.*npow+sqr(npow))*ac-3.*npow+sqr(npow)+4)
// /(sqr(npow)*(npow-6.)+11.*npow-6.);
// xpwgt *= pow(1.-xp,npow)/wgt;
// double xp2(sqr(xp)),lxp(log(xp)),xp4(sqr(xp2)),lxp1(log(1.-xp));
// double zpwgt = (2.*xp4*(lxp+lxp1-3.)+4.*xp*xp2*(3.-lxp-lxp1)
// +xp2*(-13.+lxp+lxp1)+xp*(+7.+lxp+lxp1)-lxp-lxp1-1.)/(1.+xp-xp2);
// do {
// double zpmax = 1./(1.+xp*(1.-xp)), zpmin = 1.-zpmax;
// zp = 1.-pow((1.-zpmin)/(1.-zpmax),UseRandom::rnd())*(1.-zpmax);
// wgt = log((1.-zpmin)/(1.-zpmax))*(1.-zp);
// double x1 = -1./xp;
// double x2 = 1.-(1.-zp)/xp;
// double x3 = 2.+x1-x2;
// double xperp2 = 4.*(1.-xp)*(1.-zp)*zp/xp;
// wgt *= sqr(xp)/(1.-zp)*(sqr(x3)+sqr(x2)+3.*xperp2);
// if(wgt>maxwgt*zpwgt) cerr << "testing violates BGF maxB " << wgt/xpwgt << "\n";
// }
// while(wgt<UseRandom::rnd()*maxwgt);
// return zpwgt*xpwgt;
}
vector<double> DISBase::ComptonME(double xp, double x2, double xperp,
bool norm) {
vector<double> output(3,0.);
double cos2 = x2 /sqrt(sqr(x2)+sqr(xperp));
double sin2 = xperp/sqrt(sqr(x2)+sqr(xperp));
double root = sqrt(sqr(l_)-1.);
output[0] = sqr(cos2)+acoeff_*cos2*l_+sqr(l_);
output[1] = -acoeff_*cos2*root*sin2-2.*l_*root*sin2;
output[2] = sqr(root)*sqr(sin2);
double lo(1+acoeff_*l_+sqr(l_));
double denom = norm ? 1.+sqr(xp)*(sqr(x2)+1.5*sqr(xperp)) : 1.;
double fact = sqr(xp)*(sqr(x2)+sqr(xperp))/lo;
for(unsigned int ix=0;ix<output.size();++ix)
output[ix] = ((ix==0 ? 1. : 0.) +fact*output[ix])/denom;
return output;
}
vector<double> DISBase::BGFME(double xp, double x2, double x3,
double xperp, bool norm) {
vector<double> output(3,0.);
double cos2 = x2 /sqrt(sqr(x2)+sqr(xperp));
double sin2 = xperp/sqrt(sqr(x2)+sqr(xperp));
double fact2 = sqr(xp)*(sqr(x2)+sqr(xperp));
double cos3 = x3 /sqrt(sqr(x3)+sqr(xperp));
double sin3 = xperp/sqrt(sqr(x3)+sqr(xperp));
double fact3 = sqr(xp)*(sqr(x3)+sqr(xperp));
double root = sqrt(sqr(l_)-1.);
output[0] = fact2*(sqr(cos2)+acoeff_*cos2*l_+sqr(l_)) +
fact3*(sqr(cos3)-acoeff_*cos3*l_+sqr(l_));
output[1] = - fact2*(acoeff_*cos2*root*sin2+2.*l_*root*sin2)
- fact3*(acoeff_*cos3*root*sin3-2.*l_*root*sin3);
output[2] = fact2*(sqr(root)*sqr(sin2)) +
fact3*(sqr(root)*sqr(sin3));
double lo(1+acoeff_*l_+sqr(l_));
double denom = norm ? sqr(xp)*(sqr(x3)+sqr(x2)+3.*sqr(xperp))*lo : lo;
for(unsigned int ix=0;ix<output.size();++ix) output[ix] /= denom;
return output;
}
HardTreePtr DISBase::generateHardest(ShowerTreePtr tree,
vector<ShowerInteraction::Type> inter) {
bool found = false;
// check if generating QCD radiation
for(unsigned int ix=0;ix<inter.size();++ix) {
found |= inter[ix]==ShowerInteraction::QCD;
}
if(!found) return HardTreePtr();
ShowerParticlePtr quark[2],lepton[2];
PPtr hadron;
// incoming particles
for(map<ShowerProgenitorPtr,ShowerParticlePtr>::const_iterator
cit=tree->incomingLines().begin();cit!=tree->incomingLines().end();++cit) {
if(QuarkMatcher::Check(cit->first->progenitor()->data())) {
hadron = cit->first->original()->parents()[0];
quark [0] = cit->first->progenitor();
beam_ = cit->first->beam();
}
else if(LeptonMatcher::Check(cit->first->progenitor()->data())) {
lepton[0] = cit->first->progenitor();
leptons_[0] = lepton[0]->dataPtr();
}
}
pdf_=beam_->pdf();
assert(beam_&&pdf_&&quark[0]&&lepton[0]);
// outgoing particles
for(map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator
cit=tree->outgoingLines().begin();cit!=tree->outgoingLines().end();++cit) {
if(QuarkMatcher::Check(cit->first->progenitor()->data()))
quark [1] = cit->first->progenitor();
else if(LeptonMatcher::Check(cit->first->progenitor()->data())) {
lepton[1] = cit->first->progenitor();
leptons_[1] = lepton[1]->dataPtr();
}
}
assert(quark[1]&&lepton[1]);
// Particle data objects
for(unsigned int ix=0;ix<2;++ix) partons_[ix] = quark[ix]->dataPtr();
// extract the born variables
q_ =lepton[0]->momentum()-lepton[1]->momentum();
q2_ = -q_.m2();
xB_ = quark[0]->x();
double yB =
( q_*quark[0]->momentum())/
(lepton[0]->momentum()*quark[0]->momentum());
l_ = 2./yB-1.;
// construct lorentz transform from lab to breit frame
Lorentz5Momentum phadron = hadron->momentum();
phadron.setMass(0.*GeV);
phadron.rescaleRho();
Lorentz5Momentum pb = quark[0]->momentum();
Lorentz5Momentum pbasis = phadron;
Axis axis(q_.vect().unit());
double sinth(sqrt(sqr(axis.x())+sqr(axis.y())));
LorentzRotation rot_ = LorentzRotation();
if(axis.perp2()>1e-20) {
rot_.setRotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.));
rot_.rotateX(Constants::pi);
}
if(abs(1.-q_.e()/q_.vect().mag())>1e-6) rot_.boostZ( q_.e()/q_.vect().mag());
pb *= rot_;
if(pb.perp2()/GeV2>1e-20) {
Boost trans = -1./pb.e()*pb.vect();
trans.setZ(0.);
rot_.boost(trans);
}
Lorentz5Momentum pl = rot_*lepton[0]->momentum();
rot_.rotateZ(-atan2(pl.y(),pl.x()));
// momenta of the particles
pl_[0]=rot_*lepton[0]->momentum();
pl_[1]=rot_*lepton[1]->momentum();
pq_[0]=rot_* quark[0]->momentum();
pq_[1]=rot_* quark[1]->momentum();
q_ *= rot_;
// coefficient for the matrix elements
acoeff_ = A(lepton[0]->dataPtr(),lepton[1]->dataPtr(),
quark [0]->dataPtr(),quark [1]->dataPtr(),q2_);
// generate a compton point
generateCompton();
generateBGF();
// no valid emission, return
if(pTCompton_<ZERO&&pTBGF_<ZERO) return HardTreePtr();
// type of emission, pick highest pT
bool isCompton=pTCompton_>pTBGF_;
// // find the sudakov for the branching
// SudakovPtr sudakov;
// // ISR
// if(ComptonISFS_||!isCompton) {
// BranchingList branchings=evolver()->splittingGenerator()->initialStateBranchings();
// long index = abs(partons_[0]->id());
// IdList br(3);
// if(isCompton) {
// br[0] = index;
// br[1] = index;
// br[2] = ParticleID::g;
// }
// else {
// br[0] = ParticleID::g;
// br[1] = abs(partons_[0]->id());
// br[2] = -abs(partons_[0]->id());
// }
// for(BranchingList::const_iterator cit = branchings.lower_bound(index);
// cit != branchings.upper_bound(index); ++cit ) {
// IdList ids = cit->second.second;
// if(ids[0]==br[0]&&ids[1]==br[1]&&ids[2]==br[2]) {
// sudakov=cit->second.first;
// break;
// }
// }
// }
// // FSR
// else {
// BranchingList branchings =
// evolver()->splittingGenerator()->finalStateBranchings();
// long index=abs(partons_[1]->id());
// for(BranchingList::const_iterator cit = branchings.lower_bound(index);
// cit != branchings.upper_bound(index); ++cit ) {
// IdList ids = cit->second.second;
// if(ids[0]==index&&ids[1]==index&&ids[2]==ParticleID::g) {
// sudakov = cit->second.first;
// break;
// }
// }
// }
// if(!sudakov) throw Exception() << "Can't find Sudakov for the hard emission in "
// << "DISBase::generateHardest()"
// << Exception::runerror;
// add the leptons
vector<HardBranchingPtr> spaceBranchings,allBranchings;
spaceBranchings.push_back(new_ptr(HardBranching(lepton[0],SudakovPtr(),
HardBranchingPtr(),
HardBranching::Incoming)));
allBranchings.push_back(spaceBranchings.back());
allBranchings.push_back(new_ptr(HardBranching(lepton[1],SudakovPtr(),
HardBranchingPtr(),
HardBranching::Outgoing)));
// compton hardest
if(isCompton) {
rot_.invert();
for(unsigned int ix=0;ix<ComptonMomenta_.size();++ix) {
ComptonMomenta_[ix].transform(rot_);
}
ShowerParticlePtr newqout (new_ptr(ShowerParticle(partons_[1],true)));
newqout->set5Momentum(ComptonMomenta_[1]);
ShowerParticlePtr newg(new_ptr(ShowerParticle(gluon_,true)));
newg->set5Momentum(ComptonMomenta_[2]);
ShowerParticlePtr newqin (new_ptr(ShowerParticle(partons_[0],false )));
newqin->set5Momentum(ComptonMomenta_[0]);
if(ComptonISFS_) {
ShowerParticlePtr newspace(new_ptr(ShowerParticle(partons_[0],false)));
newspace->set5Momentum(ComptonMomenta_[0]-ComptonMomenta_[2]);
HardBranchingPtr spaceBranch(new_ptr(HardBranching(newqin,SudakovPtr(),
HardBranchingPtr(),
HardBranching::Incoming)));
HardBranchingPtr offBranch(new_ptr(HardBranching(newspace,SudakovPtr(),
spaceBranch,
HardBranching::Incoming)));
spaceBranch->addChild(offBranch);
HardBranchingPtr g(new_ptr(HardBranching(newg,SudakovPtr(),spaceBranch,
HardBranching::Outgoing)));
spaceBranch->addChild(g);
spaceBranch->type(offBranch->branchingParticle()->id()>0 ?
ShowerPartnerType::QCDColourLine : ShowerPartnerType::QCDAntiColourLine);
HardBranchingPtr outBranch(new_ptr(HardBranching(newqout,SudakovPtr(),
HardBranchingPtr(),
HardBranching::Outgoing)));
spaceBranchings.push_back(spaceBranch);
allBranchings.push_back(offBranch);
allBranchings.push_back(outBranch);
ColinePtr newin(new_ptr(ColourLine())),newout(new_ptr(ColourLine()));
newin->addColoured(newqin,partons_[0]->id()<0);
newin->addColoured(newg ,partons_[0]->id()<0);
newout->addColoured(newspace,partons_[0]->id()<0);
newout->addColoured(newqout,partons_[1]->id()<0);
newout->addColoured(newg ,partons_[1]->id()>0);
ColinePtr newline(new_ptr(ColourLine()));
newline->addColoured(newspace,newspace->dataPtr()->iColour()!=PDT::Colour3);
newline->addColoured(newqout ,newspace->dataPtr()->iColour()!=PDT::Colour3);
}
else {
ShowerParticlePtr newtime(new_ptr(ShowerParticle(partons_[1],true)));
newtime->set5Momentum(ComptonMomenta_[1]+ComptonMomenta_[2]);
HardBranchingPtr spaceBranch(new_ptr(HardBranching(newqin,SudakovPtr(),
HardBranchingPtr(),
HardBranching::Incoming)));
HardBranchingPtr offBranch(new_ptr(HardBranching(newtime,SudakovPtr(),
HardBranchingPtr(),
HardBranching::Outgoing)));
HardBranchingPtr g(new_ptr(HardBranching(newg,SudakovPtr(),offBranch,
HardBranching::Outgoing)));
HardBranchingPtr outBranch(new_ptr(HardBranching(newqout,SudakovPtr(),offBranch,
HardBranching::Outgoing)));
offBranch->addChild(outBranch);
offBranch->addChild(g);
offBranch->type(offBranch->branchingParticle()->id()>0 ?
ShowerPartnerType::QCDColourLine : ShowerPartnerType::QCDAntiColourLine);
spaceBranchings.push_back(spaceBranch);
allBranchings.push_back(spaceBranch);
allBranchings.push_back(offBranch);
ColinePtr newline(new_ptr(ColourLine()));
newline->addColoured(newqin ,newqin->dataPtr()->iColour()!=PDT::Colour3);
newline->addColoured(newtime,newqin->dataPtr()->iColour()!=PDT::Colour3);
}
}
// BGF hardest
else {
rot_.invert();
for(unsigned int ix=0;ix<BGFMomenta_.size();++ix) {
BGFMomenta_[ix].transform(rot_);
}
ShowerParticlePtr newq (new_ptr(ShowerParticle(partons_[1],true)));
newq->set5Momentum(BGFMomenta_[1]);
ShowerParticlePtr newqbar(new_ptr(ShowerParticle(partons_[0]->CC(),true)));
newqbar->set5Momentum(BGFMomenta_[2]);
ShowerParticlePtr newg (new_ptr(ShowerParticle(gluon_,false)));
newg->set5Momentum(BGFMomenta_[0]);
ShowerParticlePtr newspace(new_ptr(ShowerParticle(partons_[0],false)));
newspace->set5Momentum(BGFMomenta_[0]-BGFMomenta_[2]);
HardBranchingPtr spaceBranch(new_ptr(HardBranching(newg,SudakovPtr(),HardBranchingPtr(),
HardBranching::Incoming)));
HardBranchingPtr offBranch(new_ptr(HardBranching(newspace,SudakovPtr(),spaceBranch,
HardBranching::Incoming)));
HardBranchingPtr qbar(new_ptr(HardBranching(newqbar,SudakovPtr(),spaceBranch,
HardBranching::Outgoing)));
spaceBranch->addChild(offBranch);
spaceBranch->addChild(qbar);
spaceBranch->type(offBranch->branchingParticle()->id()>0 ?
ShowerPartnerType::QCDColourLine : ShowerPartnerType::QCDAntiColourLine);
HardBranchingPtr outBranch(new_ptr(HardBranching(newq,SudakovPtr(),
HardBranchingPtr(),
HardBranching::Outgoing)));
spaceBranchings.push_back(spaceBranch);
allBranchings.push_back(offBranch);
allBranchings.push_back(outBranch);
ColinePtr newline(new_ptr(ColourLine()));
newline->addColoured(newspace,newspace->dataPtr()->iColour()!=PDT::Colour3);
newline->addColoured(newq ,newspace->dataPtr()->iColour()!=PDT::Colour3);
}
HardTreePtr newTree(new_ptr(HardTree(allBranchings,spaceBranchings,
ShowerInteraction::QCD)));
// Set the maximum pt for all other emissions and connect hard and shower tree
Energy pT = isCompton ? pTCompton_ : pTBGF_;
// incoming particles
for(map<ShowerProgenitorPtr,ShowerParticlePtr>::const_iterator
cit=tree->incomingLines().begin();cit!=tree->incomingLines().end();++cit) {
// set maximum pT
if(QuarkMatcher::Check(cit->first->progenitor()->data()))
cit->first->maximumpT(pT,ShowerInteraction::QCD);
for(set<HardBranchingPtr>::iterator cjt=newTree->branchings().begin();
cjt!=newTree->branchings().end();++cjt) {
if(!(*cjt)->branchingParticle()->isFinalState()&&
(*cjt)->branchingParticle()->id()==cit->first->progenitor()->id()) {
newTree->connect(cit->first->progenitor(),*cjt);
tPPtr beam =cit->first->original();
if(!beam->parents().empty()) beam=beam->parents()[0];
(*cjt)->beam(beam);
HardBranchingPtr parent=(*cjt)->parent();
while(parent) {
parent->beam(beam);
parent=parent->parent();
};
}
}
}
// outgoing particles
for(map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator
cit=tree->outgoingLines().begin();cit!=tree->outgoingLines().end();++cit) {
// set maximum pT
if(QuarkMatcher::Check(cit->first->progenitor()->data()))
cit->first->maximumpT(pT,ShowerInteraction::QCD);
for(set<HardBranchingPtr>::iterator cjt=newTree->branchings().begin();
cjt!=newTree->branchings().end();++cjt) {
if((*cjt)->branchingParticle()->isFinalState()&&
(*cjt)->branchingParticle()->id()==cit->first->progenitor()->id()) {
newTree->connect(cit->first->progenitor(),*cjt);
}
}
}
return newTree;
}
void DISBase::generateCompton() {
// maximum value of the xT
double xT = sqrt((1.-xB_)/xB_);
double xTMin = 2.*pTmin_/sqrt(q2_);
double zp;
// prefactor
double a = alpha_->overestimateValue()*comptonWeight_/Constants::twopi;
// loop to generate kinematics
double wgt(0.),xp(0.);
vector<double> azicoeff;
do {
wgt = 0.;
// intergration variables dxT/xT^3
xT *= 1./sqrt(1.-2.*log(UseRandom::rnd())/a*sqr(xT));
// zp
zp = UseRandom::rnd();
xp = 1./(1.+0.25*sqr(xT)/zp/(1.-zp));
// check allowed
if(xp<xB_||xp>1.) continue;
// phase-space piece of the weight
wgt = 8.*(1.-xp)*zp/comptonWeight_;
// PDF piece of the weight
Energy2 scale = q2_*((1.-xp)*(1-zp)*zp/xp+1.);
wgt *= pdf_->xfx(beam_,partons_[0],scale,xB_/xp)/
pdf_->xfx(beam_,partons_[0],q2_ ,xB_);
// me piece of the weight
double x2 = 1.-(1.-zp)/xp;
azicoeff = ComptonME(xp,x2,xT,false);
wgt *= 4./3.*alpha_->ratio(0.25*q2_*sqr(xT))*(azicoeff[0]+0.5*azicoeff[2]);
if(wgt>1.||wgt<0.) {
ostringstream wstring;
wstring << "DISBase::generateCompton() "
<< "Weight greater than one or less than zero"
<< "wgt = " << wgt << "\n";
generator()->logWarning( Exception(wstring.str(),
Exception::warning) );
}
}
while(xT>xTMin&&UseRandom::rnd()>wgt);
if(xT<=xTMin) {
pTCompton_=-GeV;
return;
}
// generate phi
unsigned int itry(0);
double phimax = std::accumulate(azicoeff.begin(),azicoeff.end(),0.);
double phiwgt,phi;
do {
phi = UseRandom::rnd()*Constants::twopi;
double cphi(cos(phi));
phiwgt = azicoeff[0]+azicoeff[1]*cphi+azicoeff[2]*sqr(cphi);
++itry;
}
while (phimax*UseRandom::rnd() > phiwgt && itry<200);
if(itry==200) throw Exception() << "Too many tries in DISMECorrection"
<< "::generateCompton() to"
<< " generate phi" << Exception::eventerror;
// momenta for the configuration
Energy Q(sqrt(q2_));
double x1 = -1./xp;
double x2 = 1.-(1.-zp)/xp;
double x3 = 2.+x1-x2;
Lorentz5Momentum p1( 0.5*Q*xT*cos(phi), 0.5*Q*xT*sin(phi),
-0.5*Q*x2, 0.5*Q*sqrt(sqr(xT)+sqr(x2)));
Lorentz5Momentum p2(-0.5*Q*xT*cos(phi), -0.5*Q*xT*sin(phi),
-0.5*Q*x3, 0.5*Q*sqrt(sqr(xT)+sqr(x3)));
Lorentz5Momentum p0(ZERO,ZERO,-0.5*Q*x1,-0.5*Q*x1);
pTCompton_ = 0.5*Q*xT;
ComptonMomenta_.resize(3);
ComptonMomenta_[0] = p0;
ComptonMomenta_[1] = p1;
ComptonMomenta_[2] = p2;
ComptonISFS_ = zp>xp;
// debuggingMatrixElement(false,p0,p1,p2,gluon_,pl_[0],pl_[1],pq_[0],pq_[1],
// leptons_[0],leptons_[1],
// partons_[0],partons_[1],
// q2_,phi,x2,x3,xT,zp,xp,azicoeff,false);
}
void DISBase::generateBGF() {
// maximum value of the xT
double xT = (1.-xB_)/xB_;
double xTMin = 2.*max(pTmin_,pTCompton_)/sqrt(q2_);
double zp;
// prefactor
double a = alpha_->overestimateValue()*BGFWeight_/Constants::twopi;
// loop to generate kinematics
double wgt(0.),xp(0.);
vector<double> azicoeff;
do {
wgt = 0.;
// intergration variables dxT/xT^3
xT *= 1./sqrt(1.-2.*log(UseRandom::rnd())/a*sqr(xT));
// zp
zp = UseRandom::rnd();
xp = 1./(1.+0.25*sqr(xT)/zp/(1.-zp));
// check allowed
if(xp<xB_||xp>1.) continue;
// phase-space piece of the weight
wgt = 8.*sqr(1.-xp)*zp/BGFWeight_;
// PDF piece of the weight
Energy2 scale = q2_*((1.-xp)*(1-zp)*zp/xp+1.);
wgt *= pdf_->xfx(beam_,gluon_ ,scale,xB_/xp)/
pdf_->xfx(beam_,partons_[0],q2_ ,xB_);
// me piece of the weight
double x1 = -1./xp;
double x2 = 1.-(1.-zp)/xp;
double x3 = 2.+x1-x2;
azicoeff = BGFME(xp,x2,x3,xT,false);
wgt *= 0.5*alpha_->ratio(0.25*q2_*sqr(xT))*
(azicoeff[0]+0.5*azicoeff[2]);
if(wgt>1.||wgt<0.) {
ostringstream wstring;
wstring << "DISBase::generateBGF() "
<< "Weight greater than one or less than zero"
<< "wgt = " << wgt << "\n";
generator()->logWarning( Exception(wstring.str(),
Exception::warning) );
}
}
while(xT>xTMin&&UseRandom::rnd()>wgt);
if(xT<=xTMin) {
pTBGF_=-GeV;
return;
}
// generate phi
unsigned int itry(0);
double phimax = std::accumulate(azicoeff.begin(),azicoeff.end(),0.);
double phiwgt,phi;
do {
phi = UseRandom::rnd()*Constants::twopi;
double cphi(cos(phi));
phiwgt = azicoeff[0]+azicoeff[1]*cphi+azicoeff[2]*sqr(cphi);
++itry;
}
while (phimax*UseRandom::rnd() > phiwgt && itry<200);
if(itry==200) throw Exception() << "Too many tries in DISMECorrection"
<< "::generateBGF() to"
<< " generate phi" << Exception::eventerror;
// momenta for the configuration
Energy Q(sqrt(q2_));
double x1 = -1./xp;
double x2 = 1.-(1.-zp)/xp;
double x3 = 2.+x1-x2;
Lorentz5Momentum p1( 0.5*Q*xT*cos(phi), 0.5*Q*xT*sin(phi),
-0.5*Q*x2, 0.5*Q*sqrt(sqr(xT)+sqr(x2)));
Lorentz5Momentum p2(-0.5*Q*xT*cos(phi), -0.5*Q*xT*sin(phi),
-0.5*Q*x3, 0.5*Q*sqrt(sqr(xT)+sqr(x3)));
Lorentz5Momentum p0(ZERO,ZERO,-0.5*Q*x1,-0.5*Q*x1);
pTBGF_=0.5*Q*xT;
BGFMomenta_.resize(3);
BGFMomenta_[0]=p0;
BGFMomenta_[1]=p1;
BGFMomenta_[2]=p2;
// debuggingMatrixElement(true,p0,p1,p2,gluon_,pl_[0],pl_[1],pq_[0],pq_[1],
// leptons_[0],leptons_[1],
// partons_[0],partons_[1],
// q2_,phi,x2,x3,xT,zp,xp,azicoeff,false);
}
int DISBase::nDim() const {
return HwMEBase::nDim() + (contrib_>0 ? 1 : 0 );
}
bool DISBase::generateKinematics(const double * r) {
// Born kinematics
if(!HwMEBase::generateKinematics(r)) return false;
if(contrib_!=0) {
// hadron and momentum fraction
if(HadronMatcher::Check(*lastParticles().first->dataPtr())) {
hadron_ = dynamic_ptr_cast<tcBeamPtr>(lastParticles().first->dataPtr());
xB_ = lastX1();
}
else {
hadron_ = dynamic_ptr_cast<tcBeamPtr>(lastParticles().second->dataPtr());
xB_ = lastX2();
}
// Q2
q2_ = -(meMomenta()[0]-meMomenta()[2]).m2();
// xp
int ndim=nDim();
double rhomin = pow(1.-xB_,1.-power_);
double rho = r[ndim-1]*rhomin;
xp_ = 1.-pow(rho,1./(1.-power_));
jac_ = rhomin/(1.-power_)*pow(1.-xp_,power_);
jacobian(jacobian()*jac_);
}
return true;
}
Energy2 DISBase::scale() const {
return scaleOpt_ == 1 ?
-sqr(scaleFact_)*tHat() : sqr(scaleFact_*muF_);
}
CrossSection DISBase::dSigHatDR() const {
return NLOWeight()*HwMEBase::dSigHatDR();
}
double DISBase::NLOWeight() const {
// If only leading order is required return 1:
if(contrib_==0) return 1.;
// scale and prefactors
Energy2 mu2(scale());
double aS = SM().alphaS(mu2);
double CFfact = 4./3.*aS/Constants::twopi;
double TRfact = 1./2.*aS/Constants::twopi;
// LO + dipole subtracted virtual + collinear quark bit with LO pdf
double virt = 1.+CFfact*(-4.5-1./3.*sqr(Constants::pi)+1.5*log(q2_/mu2/(1.-xB_))
+2.*log(1.-xB_)*log(q2_/mu2)+sqr(log(1.-xB_)));
virt /= jac_;
// PDF from leading-order
double loPDF = hadron_->pdf()->xfx(hadron_,mePartonData()[1],mu2,xB_)/xB_;
// NLO gluon PDF
tcPDPtr gluon = getParticleData(ParticleID::g);
double gPDF = hadron_->pdf()->xfx(hadron_,gluon,mu2,xB_/xp_)*xp_/xB_;
// NLO quark PDF
double qPDF = hadron_->pdf()->xfx(hadron_,mePartonData()[1],mu2,xB_/xp_)*xp_/xB_;
// collinear counterterms
// gluon
double collg =
TRfact/xp_*gPDF*(2.*xp_*(1.-xp_)+(sqr(xp_)+sqr(1.-xp_))*log((1.-xp_)*q2_/xp_/mu2));
// quark
double collq =
CFfact/xp_*qPDF*(1-xp_-2./(1.-xp_)*log(xp_)-(1.+xp_)*log((1.-xp_)/xp_*q2_/mu2))+
CFfact/xp_*(qPDF-xp_*loPDF)*(2./(1.-xp_)*log(q2_*(1.-xp_)/mu2)-1.5/(1.-xp_));
// calculate the A coefficient for the real pieces
double a(A(mePartonData()[0],mePartonData()[2],
mePartonData()[1],mePartonData()[3],q2_));
// cacluate lepton kinematic variables
Lorentz5Momentum q = meMomenta()[0]-meMomenta()[2];
double yB = (q*meMomenta()[1])/(meMomenta()[0]*meMomenta()[1]);
double l = 2./yB-1.;
// q -> qg term
double realq = CFfact/xp_/(1.+a*l+sqr(l))*qPDF/loPDF*
(2.+2.*sqr(l)-xp_+3.*xp_*sqr(l)+a*l*(2.*xp_+1.));
// g -> q qbar term
double realg =-TRfact/xp_/(1.+a*l+sqr(l))*gPDF/loPDF*
((1.+sqr(l)+2.*(1.-3.*sqr(l))*xp_*(1.-xp_))
+2.*a*l*(1.-2.*xp_*(1.-xp_)));
// return the full result
double wgt = virt+((collq+collg)/loPDF+realq+realg);
// double f2g = gPDF/xp_*TRfact*((sqr(1-xp_)+sqr(xp_))*log((1-xp_)/xp_)+
// 8*xp_*(1.-xp_)-1.);
// double f2q =
// loPDF/jac_*(1.+CFfact*(-1.5*log(1.-xB_)+sqr(log(1.-xB_))
// -sqr(Constants::pi)/3.-4.5))
// +qPDF *CFfact/xp_*(3.+2.*xp_-(1.+xp_)*log(1.-xp_)
// -(1.+sqr(xp_))/(1.-xp_)*log(xp_))
// +(qPDF-xp_*loPDF)*CFfact/xp_*(2.*log(1.-xp_)/(1.-xp_)-1.5/(1.-xp_));
// double wgt = (f2g+f2q)/loPDF;
return contrib_ == 1 ? max(0.,wgt) : max(0.,-wgt);
}
diff --git a/MatrixElement/Powheg/MEPP2VVPowhegAC.cc b/MatrixElement/Powheg/MEPP2VVPowhegAC.cc
deleted file mode 100644
--- a/MatrixElement/Powheg/MEPP2VVPowhegAC.cc
+++ /dev/null
@@ -1,3771 +0,0 @@
-// -*- C++ -*-
-//
-// MEPP2VVPowheg.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 MEPP2VVPowheg class.
-//
-
-#include "MEPP2VVPowheg.h"
-#include "ThePEG/Interface/Switch.h"
-#include "ThePEG/Interface/Parameter.h"
-#include "ThePEG/Interface/ClassDocumentation.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 "Herwig++/Models/StandardModel/StandardModel.h"
-#include "Herwig++/MatrixElement/HardVertex.h"
-
-using namespace Herwig;
-
-MEPP2VVPowheg::MEPP2VVPowheg() :
- tiny(1.e-10), CF_(4./3.), TR_(0.5), NC_(3.),
- contrib_(1), channels_(0), nlo_alphaS_opt_(0) , fixed_alphaS_(0.1180346226),
- removebr_(1), scaleopt_(1), mu_F_(100.*GeV), mu_UV_(100.*GeV),
- ckm_(3,vector<Complex>(3,0.0)),
- helicityConservation_(true) {
- massOption(vector<unsigned int>(2,1));
-}
-
-void MEPP2VVPowheg::persistentOutput(PersistentOStream & os) const {
- os << contrib_ << channels_ << nlo_alphaS_opt_ << fixed_alphaS_
- << removebr_ << scaleopt_ << ounit(mu_F_,GeV) << ounit(mu_UV_,GeV)
- << ckm_ << helicityConservation_
- << FFPvertex_ << FFWvertex_ << FFZvertex_ << WWWvertex_ << FFGvertex_;
-}
-
-void MEPP2VVPowheg::persistentInput(PersistentIStream & is, int) {
- is >> contrib_ >> channels_ >> nlo_alphaS_opt_ >> fixed_alphaS_
- >> removebr_ >> scaleopt_ >> iunit(mu_F_,GeV) >> iunit(mu_UV_,GeV)
- >> ckm_ >> helicityConservation_
- >> FFPvertex_ >> FFWvertex_ >> FFZvertex_ >> WWWvertex_ >> FFGvertex_;
-}
-
-ClassDescription<MEPP2VVPowheg> MEPP2VVPowheg::initMEPP2VVPowheg;
-// Definition of the static class description member.
-
-void MEPP2VVPowheg::Init() {
-
- static Switch<MEPP2VVPowheg,unsigned int> interfaceContribution
- ("Contribution",
- "Which contributions to the cross section to include",
- &MEPP2VVPowheg::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<MEPP2VVPowheg,unsigned int> interfaceChannels
- ("Channels",
- "Which channels to include in the cross section",
- &MEPP2VVPowheg::channels_, 0, false, false);
- static SwitchOption interfaceChannelsAll
- (interfaceChannels,
- "All",
- "All channels required for the full NLO cross section: qqb, qg, gqb",
- 0);
- static SwitchOption interfaceChannelsAnnihilation
- (interfaceChannels,
- "Annihilation",
- "Only include the qqb annihilation channel, omitting qg and gqb channels",
- 1);
- static SwitchOption interfaceChannelsCompton
- (interfaceChannels,
- "Compton",
- "Only include the qg and gqb compton channels, omitting all qqb processes",
- 2);
-
- static Switch<MEPP2VVPowheg,unsigned int> interfaceNLOalphaSopt
- ("NLOalphaSopt",
- "An option allowing you to supply a fixed value of alpha_S "
- "through the FixedNLOAlphaS interface.",
- &MEPP2VVPowheg::nlo_alphaS_opt_, 0, false, false);
- static SwitchOption interfaceNLOalphaSoptRunningAlphaS
- (interfaceNLOalphaSopt,
- "RunningAlphaS",
- "Use the usual running QCD coupling evaluated at scale mu_UV2()",
- 0);
- static SwitchOption interfaceNLOalphaSoptFixedAlphaS
- (interfaceNLOalphaSopt,
- "FixedAlphaS",
- "Use a constant QCD coupling for comparison/debugging purposes",
- 1);
-
- static Parameter<MEPP2VVPowheg,double> interfaceFixedNLOalphaS
- ("FixedNLOalphaS",
- "The value of alphaS to use for the nlo weight if nlo_alphaS_opt_=1",
- &MEPP2VVPowheg::fixed_alphaS_, 0.1180346226, 0., 1.0,
- false, false, Interface::limited);
-
- static Switch<MEPP2VVPowheg,unsigned int> interfaceremovebr
- ("removebr",
- "Whether to multiply the event weights by the MCFM branching ratios",
- &MEPP2VVPowheg::removebr_, 1, false, false);
- static SwitchOption interfaceProductionCrossSection
- (interfaceremovebr,
- "true",
- "Do not multiply in the branching ratios (default running)",
- 1);
- static SwitchOption interfaceIncludeBRs
- (interfaceremovebr,
- "false",
- "Multiply by MCFM branching ratios for comparison/debugging purposes",
- 0);
-
- static Switch<MEPP2VVPowheg,unsigned int> interfaceScaleOption
- ("ScaleOption",
- "Option for running / fixing EW and QCD factorization & renormalization scales",
- &MEPP2VVPowheg::scaleopt_, 1, false, false);
- static SwitchOption interfaceDynamic
- (interfaceScaleOption,
- "Dynamic",
- "QCD factorization & renormalization scales are (mT(V1)+mT(V2))/2. "
- "EW scale is (mV1^2+mV2^2)/2 (similar to MCatNLO)",
- 1);
- static SwitchOption interfaceFixed
- (interfaceScaleOption,
- "Fixed",
- "QCD factorization fixed to value by FactorizationScaleValue."
- "EW and QCD renormalization scales fixed by RenormalizationScaleValue.",
- 2);
-
- static Parameter<MEPP2VVPowheg,Energy> interfaceFactorizationScaleValue
- ("FactorizationScaleValue",
- "Value to use for the QCD factorization scale if fixed scales"
- "have been requested with the ScaleOption interface.",
- &MEPP2VVPowheg::mu_F_, GeV, 100.0*GeV, 50.0*GeV, 500.0*GeV,
- true, false, Interface::limited);
-
- static Parameter<MEPP2VVPowheg,Energy> interfaceRenormalizationScaleValue
- ("RenormalizationScaleValue",
- "Value to use for the EW and QCD renormalization scales if fixed "
- "scales have been requested with the ScaleOption interface.",
- &MEPP2VVPowheg::mu_UV_, GeV, 100.0*GeV, 50.0*GeV, 500.0*GeV,
- true, false, Interface::limited);
-
-}
-
-Energy2 MEPP2VVPowheg::scale() const {
- // N.B. This scale is the electroweak scale!
- // It is used in the evaluation of the LO code
- // in the MEPP2VV base class. This means it
- // should appear in the denominator of the
- // NLOweight here and all other LO parts like
- // the function for the lumi ratio (Lhat). It
- // should also be used for evaluating any EW
- // parameters / vertices in the numerator.
- // The scaleopt_ == 1 "running" option is
- // chosen to be like the MC@NLO one (it ought
- // to be more like sHat instead?).
- return scaleopt_ == 1 ?
- 0.5*(meMomenta()[2].m2()+meMomenta()[3].m2()) : sqr(mu_UV_);
-}
-
-Energy2 MEPP2VVPowheg::mu_F2() const {
- return scaleopt_ == 1 ?
- ((H_.k1r()).m2()+k1r_perp2_lab_+(H_.k2r()).m2()+k2r_perp2_lab_)/2. : sqr(mu_F_);
-}
-
-Energy2 MEPP2VVPowheg::mu_UV2() const {
- return scaleopt_ == 1 ?
- ((H_.k1r()).m2()+k1r_perp2_lab_+(H_.k2r()).m2()+k2r_perp2_lab_)/2. : sqr(mu_UV_);
-}
-
-void MEPP2VVPowheg::doinit() {
- MEPP2VV::doinit();
- // get the vertices we need
- // get a pointer to the standard model object in the run
- static const tcHwSMPtr hwsm
- = dynamic_ptr_cast<tcHwSMPtr>(standardModel());
- if (!hwsm) throw InitException()
- << "missing hwsm pointer in MEPP2VVPowheg::doinit()"
- << Exception::abortnow;
- // get pointers to all required Vertex objects
- FFPvertex_ = hwsm->vertexFFP();
- FFZvertex_ = hwsm->vertexFFZ();
- WWWvertex_ = hwsm->vertexWWW();
- FFWvertex_ = hwsm->vertexFFW();
- FFGvertex_ = hwsm->vertexFFG();
- // get the ckm object
- Ptr<StandardCKM>::pointer
- theCKM=dynamic_ptr_cast<Ptr<StandardCKM>::pointer>(SM().CKM());
- if(!theCKM) throw InitException() << "MEPP2VVPowheg::doinit() "
- << "the CKM object must be the Herwig one"
- << Exception::runerror;
- unsigned int ix,iy;
- // get the CKM matrix (unsquared for interference)
- vector< vector<Complex > > CKM(theCKM->getUnsquaredMatrix(SM().families()));
- for(ix=0;ix<3;++ix){for(iy=0;iy<3;++iy){ckm_[ix][iy]=CKM[ix][iy];}}
-}
-
-int MEPP2VVPowheg::nDim() const {
- int output = MEPP2VV::nDim();
- // See related comment in MEPP2VVPowheg::generateKinematics!
- if(contrib_>0) output += 2;
- return output;
-}
-
-bool MEPP2VVPowheg::generateKinematics(const double * r) {
- // N.B. A fix was made to make theta2 a radiative
- // variable in r4532. Originally theta2 was take to
- // be the azimuthal angle coming from the generation
- // of the Born kinematics inherited from MEPP2VV i.e.
- // before the change theta2 was a random number between
- // 0 and 2pi. On changing theta2 was set to be
- // theta2 = (*(r+3)) * 2.*Constants::pi;
- // and nDim returned if(contrib_>0) output += 3;
- // In the months following it was noticed that agreement
- // with MCFM was per mille at Tevatron energies but got
- // close to 1 percent for LHC energies (for all VV
- // processes). After searching back up the svn branch
- // running 2M events each time, the change was spotted
- // to occur on r4532. Changing:
- // if(contrib_>0) output += 3;
- // in ::nDim() and also,
- // xt = (*(r +nDim() -3));
- // y = (*(r +nDim() -2)) * 2. - 1.;
- // theta2 = (*(r +nDim() -1)) * 2.*Constants::pi;
- // did not fix the problem. The following code gives the
- // same good level of agreement at LHC and TVT:
- double xt( -999.);
- double y( -999.);
- double theta2( -999.);
- if(contrib_>0) {
- // Generate the radiative integration variables:
- xt = (*(r +nDim() -2));
- y = (*(r +nDim() -1)) * 2. - 1.;
- theta2 = UseRandom::rnd() * 2.*Constants::pi;
- }
-
- // Continue with lo matrix element code:
- bool output(MEPP2VV::generateKinematics(r));
-
- // Work out the kinematics for the leading order / virtual process
- // and also get the leading order luminosity function:
- getKinematics(xt,y,theta2);
-
- return output;
-}
-
-double MEPP2VVPowheg::me2() const {
- double output(0.0);
- useMe();
- output = MEPP2VV::me2();
- double mcfm_brs(1.);
- if(!removebr_) {
- switch(MEPP2VV::process()) {
- case 1: // W+(->e+,nu_e) W-(->e-,nu_ebar) (MCFM: 61 [nproc])
- mcfm_brs *= 0.109338816;
- mcfm_brs *= 0.109338816;
- break;
- case 2: // W+/-(mu+,nu_mu / mu-,nu_mubar) Z(nu_e,nu_ebar)
- // (MCFM: 72+77 [nproc])
- mcfm_brs *= 0.109338816;
- mcfm_brs *= 0.06839002;
- break;
- case 3: // Z(mu-,mu+) Z(e-,e+) (MCFM: 86 [nproc])
- mcfm_brs *= 0.034616433;
- mcfm_brs *= 0.034616433;
- mcfm_brs *= 2.; // as identical particle factor 1/2 is now obsolete.
- break;
- case 4: // W+(mu+,nu_mu) Z(nu_e,nu_ebar) (MCFM: 72 [nproc])
- mcfm_brs *= 0.109338816;
- mcfm_brs *= 0.06839002;
- break;
- case 5: // W-(mu-,nu_mubar) Z(nu_e,nu_ebar) (MCFM: 77 [nproc])
- mcfm_brs *= 0.109338816;
- mcfm_brs *= 0.06839002;
- break;
- }
- }
-
- // Store the value of the leading order squared matrix element:
- lo_me2_ = output;
- output *= NLOweight();
- output *= mcfm_brs;
- return output;
-}
-
-void MEPP2VVPowheg::getKinematics(double xt, double y, double theta2) {
-
- // In this member we want to get the lo_lumi_ as this is a
- // common denominator in the NLO weight. We want also the
- // bornVVKinematics object and all of the realVVKinematics
- // objects needed for the NLO weight.
-
- // Check if the W- is first in W+W- production. Already confirmed
- // mePartonData()[0] is a quark, and mePartonData()[1] is an antiquark.
- // We assume mePartonData[2] and mePartonData[3] are, respectively,
- // W+/- Z, W+/- W-/+, or Z Z.
- bool wminus_first(false);
- if((mePartonData()[2]->id()==-24)&&(mePartonData()[3]->id()==24))
- wminus_first=true;
-
- // Now get all data on the LO process needed for the NLO computation:
-
- // The +z hadron in the lab:
- hadron_A_=dynamic_ptr_cast<Ptr<BeamParticleData>::transient_const_pointer>
- (lastParticles().first->dataPtr());
- // The -z hadron in the lab:
- hadron_B_=dynamic_ptr_cast<Ptr<BeamParticleData>::transient_const_pointer>
- (lastParticles().second->dataPtr());
-
- // Leading order momentum fractions:
- double xa(lastX1()); // The +z momentum fraction in the lab.
- double xb(lastX2()); // The -z momentum fraction in the lab.
-
- // Particle data for incoming +z & -z QCD particles respectively:
- ab_ = lastPartons().first ->dataPtr(); // The +z momentum parton in the lab.
- bb_ = lastPartons().second->dataPtr(); // The -z momentum parton in the lab.
-
- // We checked TVT & LHC for all VV channels with 10K events:
- // lastParticles().first ->momentum().z() is always positive
- // lastParticles().second->momentum().z() is always negative
- // lastParticles().first ->momentum().z()*xa=lastPartons().first ->momentum().z() 1 in 10^6
- // lastParticles().second->momentum().z()*xb=lastPartons().second->momentum().z() 1 in 10^6
-
- // Set the quark and antiquark data pointers.
- quark_ = mePartonData()[0];
- antiquark_ = mePartonData()[1];
- if(quark_->id()<0) swap(quark_,antiquark_);
-
- // Now in _our_ calculation we basically define the +z axis as being
- // given by the direction of the incoming quark for q+qb & q+g processes
- // and the incoming gluon for g+qbar processes. So now we might need to
- // flip the values of hadron_A_, hadron_B_, ab_, bb_, xa, xb accordingly:
- flipped_ = false;
- if(ab_->id()!=quark_->id()) {
- flipped_ = true;
- swap(hadron_A_,hadron_B_);
- swap(ab_,bb_);
- swap(xa,xb);
- }
- // So hadron_A_ is the thing containing a quark (ab_) with momentum frac xa,
- // hadron_B_ is the thing containing an antiquark (bb_) with momentum frac xb.
-
- // Now get the partonic flux for the Born process:
- lo_lumi_ = hadron_A_->pdf()->xfx(hadron_A_,ab_,scale(),xa)/xa
- * hadron_B_->pdf()->xfx(hadron_B_,bb_,scale(),xb)/xb;
-
- // For W+W- events make sure k1 corresponds to the W+ momentum:
- if(MEPP2VV::process()==1&&wminus_first) swap(meMomenta()[2],meMomenta()[3]);
-
- // Create the object containing all 2->2 __kinematic__ information:
- B_ = bornVVKinematics(meMomenta(),xa,xb);
- // We checked that meMomenta()[0] (quark) is in the +z direction and meMomenta()[1]
- // is in the -z direction (antiquark).
-
- // Revert momentum swap in case meMomenta and mePartonData correlation
- // needs preserving for other things.
- if(MEPP2VV::process()==1&&wminus_first) swap(meMomenta()[2],meMomenta()[3]);
-
- // Check the Born kinematics objects is internally consistent:
- // B_.sanityCheck();
-
- // If we are going beyond leading order then lets calculate all of
- // the necessary real emission kinematics.
- if(contrib_>0) {
- // Soft limit of the 2->3 real emission kinematics:
- S_ = realVVKinematics(B_, 1., y, theta2);
- // Soft-collinear limit of the 2->3 kinematics (emission in +z direction):
- SCp_ = realVVKinematics(B_, 1., 1., theta2);
- // Soft-collinear limit of the 2->3 kinematics (emission in -z direction):
- SCm_ = realVVKinematics(B_, 1.,-1., theta2);
- // Collinear limit of the 2->3 kinematics (emission in +z direction):
- Cp_ = realVVKinematics(B_, xt, 1., theta2);
- // Collinear limit of the 2->3 kinematics (emission in -z direction):
- Cm_ = realVVKinematics(B_, xt,-1., theta2);
- // The resolved 2->3 real emission kinematics:
- H_ = realVVKinematics(B_, xt, y, theta2);
-
- // Borrowed from VVhardGenerator (lab momenta of k1,k2):
- Energy pT(sqrt(H_.pT2_in_lab()));
- LorentzRotation yzRotation;
- yzRotation.setRotateX(-atan2(pT/GeV,sqrt(B_.sb())/GeV));
- LorentzRotation boostFrompTisZero;
- boostFrompTisZero.setBoostY(-pT/sqrt(B_.sb()+pT*pT));
- LorentzRotation boostFromYisZero;
- boostFromYisZero.setBoostZ(tanh(B_.Yb()));
- k1r_perp2_lab_ = (boostFromYisZero*boostFrompTisZero*yzRotation*(H_.k1r())).perp2();
- k2r_perp2_lab_ = (boostFromYisZero*boostFrompTisZero*yzRotation*(H_.k2r())).perp2();
-
- // Check all the real kinematics objects are internally consistent:
- // S_.sanityCheck();
- // SCp_.sanityCheck();
- // SCm_.sanityCheck();
- // Cp_.sanityCheck();
- // Cm_.sanityCheck();
- // H_.sanityCheck();
- }
-
- return;
-}
-
-
-double MEPP2VVPowheg::NLOweight() const {
- // If only leading order is required return 1:
- if(contrib_==0) return lo_me()/lo_me2_;
-
- // Calculate alpha_S and alpha_S/(2*pi).
- alphaS_ = nlo_alphaS_opt_==1 ? fixed_alphaS_ : SM().alphaS(mu_UV2());
- double alsOn2pi(alphaS_/2./pi);
-
- // Particle data objects for the new plus and minus colliding partons.
- tcPDPtr gluon;
- gluon = getParticleData(ParticleID::g);
-
- // Get the all couplings.
- gW_ = sqrt(4.0*pi*SM().alphaEM(scale())/SM().sin2ThetaW());
- sin2ThetaW_ = SM().sin2ThetaW();
- double cosThetaW(sqrt(1.-sin2ThetaW_));
- guL_ = gW_/2./cosThetaW*( 1.-4./3.*sin2ThetaW_);
- gdL_ = gW_/2./cosThetaW*(-1.+2./3.*sin2ThetaW_);
- guR_ = gW_/2./cosThetaW*( -4./3.*sin2ThetaW_);
- gdR_ = gW_/2./cosThetaW*( +2./3.*sin2ThetaW_);
- eZ_ = gW_*cosThetaW;
- eZ2_ = sqr(eZ_);
-
- // MCFM has gwsq = 0.4389585130009 -> gw = 0.662539442600115
- // Here we have gW_ = 0.662888
- // MCFM has xw = 0.22224653300000 -> sqrt(xw) = 0.471430306
- // Here we have 0.222247
- // MCFM has esq = 0.097557007645279 -> e = 0.31234117187024679
- // Here we have 4.0*pi*SM().alphaEM(sqr(100.*GeV)) = 0.0976596
-
- // If the process is W-Z instead of W+Z we must transform these
- // couplings as follows, according to NPB 383(1992)3-44 Eq.3.23
- if(mePartonData()[2]->id()==-24&&mePartonData()[3]->id()==23) {
- swap(guL_,gdL_);
- eZ_ *= -1.;
- }
-
- // Get the CKM entry. Note that this code was debugged
- // considerably; the call to CKM(particle,particle)
- // did not appear to work, so we extract the elements
- // as follows below. The right numbers now appear to
- // to be associated with the right quarks.
- double Kij(-999.);
- // W+Z / W-Z
- if(abs(mePartonData()[2]->id())==24&&mePartonData()[3]->id()==23) {
- int up_id(-999),dn_id(-999);
- if(abs(quark_->id())%2==0&&abs(antiquark_->id())%2==1) {
- up_id = abs(quark_->id());
- dn_id = abs(antiquark_->id());
- }
- else if(abs(quark_->id())%2==1&&abs(antiquark_->id())%2==0) {
- up_id = abs(antiquark_->id());
- dn_id = abs(quark_->id());
- }
- else {
- cout << "MEPP2VVPowheg:" << endl;
- cout << "WZ needs an up and a down type quark as incoming!" << endl;
- }
- up_id /= 2;
- up_id -= 1;
- dn_id -= 1;
- dn_id /= 2;
- Kij = sqrt(SM().CKM(up_id,dn_id));
- }
- // W+W-
- else if(abs(mePartonData()[2]->id())==24&&abs(mePartonData()[3]->id())==24) {
- if(abs(quark_->id())%2==0&&abs(antiquark_->id())%2==0) {
- int up_ida(abs(quark_->id())/2-1);
- int up_idb(abs(antiquark_->id())/2-1);
- Kij = sqrt(std::norm( CKM(up_ida,0)*CKM(up_idb,0)
- + CKM(up_ida,1)*CKM(up_idb,1)
- + CKM(up_ida,2)*CKM(up_idb,2)));
- }
- else if(abs(quark_->id())%2==1&&abs(antiquark_->id())%2==1) {
- int dn_ida((abs(quark_->id())-1)/2);
- int dn_idb((abs(antiquark_->id())-1)/2);
- Kij = sqrt(std::norm( CKM(0,dn_ida)*CKM(0,dn_idb)
- + CKM(1,dn_ida)*CKM(1,dn_idb)
- + CKM(2,dn_ida)*CKM(2,dn_idb)));
- }
- else {
- cout << "MEPP2VVPowheg:" << endl;
- cout << "WW needs 2 down-type / 2 up-type!" << endl;
- }
- }
- // ZZ
- else if(mePartonData()[2]->id()==23&&mePartonData()[3]->id()==23) {
- Kij = 2.*sqrt(2.)/gW_;
- }
- else {
- cout << "MEPP2VVPowheg: incompatible final state particles!" << endl;
- }
-
- Fij2_ = sqr(gW_/2./sqrt(2.)*Kij);
-
- // Get the leading order matrix element (this is necessary!)
- M_Born_ = M_Born_WZ(B_);
- // // Get the regular part of the virtual correction (only needed for sanityCheck()!)
- // M_V_regular_ = M_V_regular(S_);
- // // Get the q + qbar real emission matrix element (only needed for sanityCheck()!)
- // t_u_M_R_qqb_ = t_u_M_R_qqb(H_);
-
- // Calculate the integrand
- double wgt(0.);
- double wqqb(0.);
- double wgqb(0.);
- double wqg(0.);
- double wqqbvirt(0.);
- double wqqbcollin(0.);
- double wqqbreal(0.);
- double wqgcollin(0.);
- double wqgreal(0.);
- double wgqbcollin(0.);
- double wgqbreal(0.);
-
- if(channels_==0||channels_==1) {
- // q+qb
- wqqbvirt = Vtilde_universal(S_) + M_V_regular(S_)/lo_me2_;
- wqqbcollin = alsOn2pi*( Ctilde_Ltilde_qq_on_x(quark_,antiquark_,Cp_)
- + Ctilde_Ltilde_qq_on_x(quark_,antiquark_,Cm_) );
- wqqbreal = alsOn2pi*Rtilde_Ltilde_qqb_on_x(quark_,antiquark_);
- wqqb = wqqbvirt + wqqbcollin + wqqbreal;
- }
- if(channels_==0||channels_==2) {
- // q+g
- wqgcollin = alsOn2pi*Ctilde_Ltilde_gq_on_x(quark_,gluon,Cm_);
- wqgreal = alsOn2pi*Rtilde_Ltilde_qg_on_x(quark_,gluon);
- wqg = wqgreal + wqgcollin;
- // g+qb
- wgqbcollin = alsOn2pi*Ctilde_Ltilde_gq_on_x(gluon,antiquark_,Cp_);
- wgqbreal = alsOn2pi*Rtilde_Ltilde_gqb_on_x(gluon,antiquark_);
- wgqb = wgqbreal+wgqbcollin;
- }
- // total contribution
- wgt = 1.+(wqqb+wgqb+wqg);
- // If restricting to qg, gqb channels then subtract the LO contribution:
- if(channels_==2) wgt -= 1.;
-
- if(isnan(wgt)||isinf(wgt)) {
- cout << "MEPP2VVPowheg:: NLO weight "
- << "is bad: wgt = " << wgt << endl;
- cout << "MEPP2VVPowheg sanityCheck invoked!" << endl;
- cout << ab_->PDGName() << ", "
- << bb_->PDGName() << ", "
- << mePartonData()[2]->PDGName() << ", "
- << mePartonData()[3]->PDGName() << endl;
- cout << "lo_me2_ - M_Born_ (rel) = "
- << lo_me2_-M_Born_ << " ("
- << (lo_me2_-M_Born_)/M_Born_ << ")\n";
- cout << "lo_me2_, M_Born_ " << lo_me2_ << ", " << M_Born_ << endl;
- cout << "xr = " << H_.xr() << " 1-xr = " << 1.-H_.xr() << " y = " << H_.y() << endl;
- cout << "tkr = " << H_.tkr()/GeV2 << " ukr = " << H_.ukr()/GeV2 << endl;
- cout << "root(sb) = " << sqrt(B_.sb())/GeV << endl;
- cout << "sb+tb+ub = "
- << B_.sb()/GeV2 << " + "
- << B_.tb()/GeV2 << " + " << B_.ub()/GeV2 << endl;
- cout << "sqrt(k12) " << sqrt(H_.k12r())/GeV << endl;
- cout << "sqrt(k22) " << sqrt(H_.k22r())/GeV << endl;
- cout << "sqr(Kij) " << Kij*Kij << endl;
- cout << "wqqbvirt " << wqqbvirt << endl;
- cout << "wqqbcollin " << wqqbcollin << endl;
- cout << "wqqbreal " << wqqbreal << endl;
- cout << "wqqb " << wqqb << endl;
- cout << "wqgcollin " << wqgcollin << endl;
- cout << "wqgreal " << wqgreal << endl;
- cout << "wqg " << wqg << endl;
- cout << "wgqbcollin " << wgqbcollin << endl;
- cout << "wgqbreal " << wgqbreal << endl;
- cout << "wgqb " << wgqb << endl;
- cout << "wgt " << wgt << endl;
- throw Exception() << "MEPP2VVPowheg:: NLO weight "
- << "is bad: " << wgt
- << Exception::eventerror;
- }
- return contrib_==1 ? max(0.,wgt) : max(0.,-wgt);
-}
-
-double MEPP2VVPowheg::Lhat_ab(tcPDPtr a, tcPDPtr b,
- realVVKinematics Kinematics) const {
- if(!(abs(a->id())<=6||a->id()==21)||!(abs(b->id())<=6||b->id()==21))
- cout << "MEPP2VVPowheg::Lhat_ab: Error,"
- << "particle a = " << a->PDGName() << ", "
- << "particle b = " << b->PDGName() << endl;
- double nlo_lumi(-999.);
- double x1(Kinematics.x1r()),x2(Kinematics.x2r());
- nlo_lumi = (hadron_A_->pdf()->xfx(hadron_A_,a,mu_F2(),x1)/x1)
- * (hadron_B_->pdf()->xfx(hadron_B_,b,mu_F2(),x2)/x2);
- return nlo_lumi / lo_lumi_;
-}
-
-double MEPP2VVPowheg::Vtilde_universal(realVVKinematics S) const {
- double xbar_y = S.xbar();
- double y = S.y();
- double eta1b(S.bornVariables().eta1b());
- double eta2b(S.bornVariables().eta2b());
- Energy2 sb(S.s2r());
- return alphaS_/2./pi*CF_
- * ( log(sb/mu_F2())
- * (3. + 4.*log(eta1b)+4.*log(eta2b))
- + 8.*sqr(log(eta1b)) +8.*sqr(log(eta2b))
- - 2.*sqr(pi)/3.
- )
- + alphaS_/2./pi*CF_
- * ( 8./(1.+y)*log(sqrt(1.-xbar_y)/eta2b)
- + 8./(1.-y)*log(sqrt(1.-xbar_y)/eta1b)
- );
-}
-
-double MEPP2VVPowheg::Ctilde_Ltilde_qq_on_x(tcPDPtr a, tcPDPtr b,
- realVVKinematics C) const {
- if(C.y()!= 1.&&C.y()!=-1.)
- cout << "\nCtilde_qq::y value not allowed.";
- if(C.y()== 1.&&!(abs(a->id())>0&&abs(a->id()<7)))
- cout << "\nCtilde_qq::for Cqq^plus a must be a quark! id = "
- << a->id() << "\n";
- if(C.y()==-1.&&!(abs(b->id())>0&&abs(b->id()<7)))
- cout << "\nCtilde_qq::for Cqq^minus b must be a quark! id = "
- << b->id() << "\n";
- double xt = C.xt();
- double x = C.xr();
- double etab = C.y() == 1. ? C.bornVariables().eta1b()
- : C.bornVariables().eta2b() ;
- Energy2 sb(C.s2r());
- if(fabs(1.-xt)<=tiny||fabs(1.-H_.xr())<=tiny) return 0.;
- return ( ( (1./(1.-xt))*log(sb/mu_F2()/x)+4.*log(etab)/(1.-xt)
- + 2.*log(1.-xt)/(1.-xt)
- )*CF_*(1.+sqr(x))
- + sqr(etab)*CF_*(1.-x)
- )*Lhat_ab(a,b,C) / x
- - ( ( (1./(1.-xt))*log(sb/mu_F2() )+4.*log(etab)/(1.-xt)
- + 2.*log(1.-xt)/(1.-xt)
- )*CF_*2.
- )*Lhat_ab(a,b,S_);
-}
-
-double MEPP2VVPowheg::Ctilde_Ltilde_gq_on_x(tcPDPtr a, tcPDPtr b,
- realVVKinematics C) const {
- if(C.y()!= 1.&&C.y()!=-1.)
- cout << "\nCtilde_gq::y value not allowed.";
- if(C.y()== 1.&&a->id()!=21)
- cout << "\nCtilde_gq::for Cgq^plus a must be a gluon! id = "
- << a->id() << "\n";
- if(C.y()==-1.&&b->id()!=21)
- cout << "\nCtilde_gq::for Cgq^minus b must be a gluon! id = "
- << b->id() << "\n";
- double xt = C.xt();
- double x = C.xr();
- double etab = C.y() == 1. ? C.bornVariables().eta1b()
- : C.bornVariables().eta2b() ;
- Energy2 sb(C.s2r());
- return ( ( (1./(1.-xt))*log(sb/mu_F2()/x)+4.*log(etab)/(1.-xt)
- + 2.*log(1.-xt)/(1.-xt)
- )*(1.-x)*TR_*(sqr(x)+sqr(1.-x))
- + sqr(etab)*TR_*2.*x*(1.-x)
- )*Lhat_ab(a,b,C) / x;
-}
-
-double MEPP2VVPowheg::Rtilde_Ltilde_qqb_on_x(tcPDPtr a , tcPDPtr b) const {
- if(!(abs(a->id())<=6||a->id()==21)||!(abs(b->id())<=6||b->id()==21))
- cout << "MEPP2VVPowheg::Rtilde_Ltilde_qqb_on_x: Error,"
- << "particle a = " << a->PDGName() << ", "
- << "particle b = " << b->PDGName() << endl;
- double xt(H_.xt());
- double y(H_.y());
- Energy2 s(H_.sr());
- Energy2 sCp(Cp_.sr());
- Energy2 sCm(Cm_.sr());
- Energy2 s2(H_.s2r());
-
-// Energy2 t_u_M_R_qqb_H (t_u_M_R_qqb(H_ ));
-// Energy2 t_u_M_R_qqb_Cp(t_u_M_R_qqb(Cp_));
-// Energy2 t_u_M_R_qqb_Cm(t_u_M_R_qqb(Cm_));
-
- Energy2 t_u_M_R_qqb_H (t_u_M_R_qqb_hel_amp(H_));
- Energy2 t_u_M_R_qqb_Cp(8.*pi*alphaS_*Cp_.sr()/Cp_.xr()
- *CF_*(1.+sqr(Cp_.xr()))*lo_me2_);
- Energy2 t_u_M_R_qqb_Cm(8.*pi*alphaS_*Cm_.sr()/Cm_.xr()
- *CF_*(1.+sqr(Cm_.xr()))*lo_me2_);
-
- int config(0);
- if(fabs(1.-xt)<=tiny||fabs(1.-H_.xr())<=tiny) return 0.;
- if(fabs(1.-y )<=tiny) { t_u_M_R_qqb_H = t_u_M_R_qqb_Cp ; config = 1; }
- if(fabs(1.+y )<=tiny) { t_u_M_R_qqb_H = t_u_M_R_qqb_Cm ; config = -1; }
- if(fabs(H_.tkr()/s)<=tiny) { t_u_M_R_qqb_H = t_u_M_R_qqb_Cp ; config = 1; }
- if(fabs(H_.ukr()/s)<=tiny) { t_u_M_R_qqb_H = t_u_M_R_qqb_Cm ; config = -1; }
-
- if(config== 0)
- return
- ( ( (t_u_M_R_qqb_H*Lhat_ab(a,b,H_)/s - t_u_M_R_qqb_Cp*Lhat_ab(a,b,Cp_)/sCp)
- )*2./(1.-y)/(1.-xt)
- + ( (t_u_M_R_qqb_H*Lhat_ab(a,b,H_)/s - t_u_M_R_qqb_Cm*Lhat_ab(a,b,Cm_)/sCm)
- )*2./(1.+y)/(1.-xt)
- ) / lo_me2_ / 8. / pi / alphaS_;
- else if(config== 1)
- return
- ( (t_u_M_R_qqb_H*Lhat_ab(a,b,H_)/s - t_u_M_R_qqb_Cm*Lhat_ab(a,b,Cm_)/sCm)
- )*2./(1.+y)/(1.-xt) / lo_me2_ / 8. / pi / alphaS_;
- else if(config==-1)
- return
- ( (t_u_M_R_qqb_H*Lhat_ab(a,b,H_)/s - t_u_M_R_qqb_Cp*Lhat_ab(a,b,Cp_)/sCp)
- )*2./(1.-y)/(1.-xt) / lo_me2_ / 8. / pi / alphaS_;
- else
- throw Exception()
- << "MEPP2VVPowheg::Rtilde_Ltilde_qqb_on_x\n"
- << "The configuration is not identified as hard / soft / fwd collinear or bwd collinear."
- << "config = " << config << "\n"
- << "xt = " << xt << " 1.-xt = " << 1.-xt << "\n"
- << "y = " << y << " 1.-y = " << 1.-y << "\n"
- << Exception::eventerror;
-}
-
-double MEPP2VVPowheg::Rtilde_Ltilde_gqb_on_x(tcPDPtr a , tcPDPtr b) const {
- if(!(abs(a->id())<=6||a->id()==21)||!(abs(b->id())<=6||b->id()==21))
- cout << "MEPP2VVPowheg::Rtilde_Ltilde_gqb_on_x: Error,"
- << "particle a = " << a->PDGName() << ", "
- << "particle b = " << b->PDGName() << endl;
- double xt(H_.xt());
- double y(H_.y());
- Energy2 s(H_.sr());
- Energy2 sCp(Cp_.sr());
- Energy2 sCm(Cm_.sr());
- Energy2 s2(H_.s2r());
-
-// Energy2 t_u_M_R_gqb_H (t_u_M_R_gqb(H_ ));
-// Energy2 t_u_M_R_gqb_Cp(t_u_M_R_gqb(Cp_));
-// Energy2 t_u_M_R_gqb_Cm(t_u_M_R_gqb(Cm_));
-
- Energy2 t_u_M_R_gqb_H (t_u_M_R_gqb_hel_amp(H_));
- Energy2 t_u_M_R_gqb_Cp(8.*pi*alphaS_*Cp_.sr()/Cp_.xr()*(1.-Cp_.xr())
- *TR_*(sqr(Cp_.xr())+sqr(1.-Cp_.xr()))*lo_me2_);
- //Energy2 t_u_M_R_gqb_Cm(t_u_M_R_gqb(Cm_));
- Energy2 t_u_M_R_gqb_Cm(t_u_M_R_gqb_hel_amp(Cm_));
-
- int config(0);
- if(fabs(1.-xt)<=tiny||fabs(1.-H_.xr())<=tiny) return 0.;
- if(fabs(1.-y )<=tiny) { t_u_M_R_gqb_H = t_u_M_R_gqb_Cp ; config = 1; }
- if(fabs(1.+y )<=tiny) { t_u_M_R_gqb_H = t_u_M_R_gqb_Cm ; config = -1; }
- if(fabs(H_.tkr()/s)<=tiny) { t_u_M_R_gqb_H = t_u_M_R_gqb_Cp ; config = 1; }
- if(fabs(H_.ukr()/s)<=tiny) { t_u_M_R_gqb_H = t_u_M_R_gqb_Cm ; config = -1; }
-
- if(config== 0)
- return
- ( ( (t_u_M_R_gqb_H*Lhat_ab(a,b,H_)/s - t_u_M_R_gqb_Cp*Lhat_ab(a,b,Cp_)/sCp)
- )*2./(1.-y)/(1.-xt)
- + ( (t_u_M_R_gqb_H*Lhat_ab(a,b,H_)/s - t_u_M_R_gqb_Cm*Lhat_ab(a,b,Cm_)/sCm)
- )*2./(1.+y)/(1.-xt)
- ) / lo_me2_ / 8. / pi / alphaS_;
- else if(config== 1)
- return
- ( (t_u_M_R_gqb_H*Lhat_ab(a,b,H_)/s - t_u_M_R_gqb_Cm*Lhat_ab(a,b,Cm_)/sCm)
- )*2./(1.+y)/(1.-xt) / lo_me2_ / 8. / pi / alphaS_;
- else if(config==-1)
- return
- ( (t_u_M_R_gqb_H*Lhat_ab(a,b,H_)/s - t_u_M_R_gqb_Cp*Lhat_ab(a,b,Cp_)/sCp)
- )*2./(1.-y)/(1.-xt) / lo_me2_ / 8. / pi / alphaS_;
- else
- throw Exception()
- << "MEPP2VVPowheg::Rtilde_Ltilde_gqb_on_x\n"
- << "The configuration is not identified as hard / soft / fwd collinear or bwd collinear."
- << "config = " << config << "\n"
- << "xt = " << xt << " 1.-xt = " << 1.-xt << "\n"
- << "y = " << y << " 1.-y = " << 1.-y << "\n"
- << Exception::eventerror;
-}
-
-double MEPP2VVPowheg::Rtilde_Ltilde_qg_on_x(tcPDPtr a , tcPDPtr b) const {
- if(!(abs(a->id())<=6||a->id()==21)||!(abs(b->id())<=6||b->id()==21))
- cout << "MEPP2VVPowheg::Rtilde_Ltilde_qg_on_x: Error,"
- << "particle a = " << a->PDGName() << ", "
- << "particle b = " << b->PDGName() << endl;
- double xt(H_.xt());
- double y(H_.y());
- Energy2 s(H_.sr());
- Energy2 sCp(Cp_.sr());
- Energy2 sCm(Cm_.sr());
- Energy2 s2(H_.s2r());
-
-// Energy2 t_u_M_R_qg_H (t_u_M_R_qg(H_ ));
-// Energy2 t_u_M_R_qg_Cp(t_u_M_R_qg(Cp_));
-// Energy2 t_u_M_R_qg_Cm(t_u_M_R_qg(Cm_));
-
- Energy2 t_u_M_R_qg_H (t_u_M_R_qg_hel_amp(H_));
- //Energy2 t_u_M_R_qg_Cp(t_u_M_R_qg(Cp_));
- Energy2 t_u_M_R_qg_Cp(t_u_M_R_qg_hel_amp(Cp_));
- Energy2 t_u_M_R_qg_Cm(8.*pi*alphaS_*Cm_.sr()/Cm_.xr()*(1.-Cm_.xr())
- *TR_*(sqr(Cm_.xr())+sqr(1.-Cm_.xr()))*lo_me2_);
-
- int config(0);
- if(fabs(1.-xt)<=tiny||fabs(1.-H_.xr())<=tiny) return 0.;
- if(fabs(1.-y )<=tiny) { t_u_M_R_qg_H = t_u_M_R_qg_Cp ; config = 1; }
- if(fabs(1.+y )<=tiny) { t_u_M_R_qg_H = t_u_M_R_qg_Cm ; config = -1; }
- if(fabs(H_.tkr()/s)<=tiny) { t_u_M_R_qg_H = t_u_M_R_qg_Cp ; config = 1; }
- if(fabs(H_.ukr()/s)<=tiny) { t_u_M_R_qg_H = t_u_M_R_qg_Cm ; config = -1; }
-
- if(config== 0)
- return
- ( ( (t_u_M_R_qg_H*Lhat_ab(a,b,H_)/s - t_u_M_R_qg_Cp*Lhat_ab(a,b,Cp_)/sCp)
- )*2./(1.-y)/(1.-xt)
- + ( (t_u_M_R_qg_H*Lhat_ab(a,b,H_)/s - t_u_M_R_qg_Cm*Lhat_ab(a,b,Cm_)/sCm)
- )*2./(1.+y)/(1.-xt)
- ) / lo_me2_ / 8. / pi / alphaS_;
- else if(config== 1)
- return
- ( (t_u_M_R_qg_H*Lhat_ab(a,b,H_)/s - t_u_M_R_qg_Cm*Lhat_ab(a,b,Cm_)/sCm)
- )*2./(1.+y)/(1.-xt) / lo_me2_ / 8. / pi / alphaS_;
- else if(config==-1)
- return
- ( (t_u_M_R_qg_H*Lhat_ab(a,b,H_)/s - t_u_M_R_qg_Cp*Lhat_ab(a,b,Cp_)/sCp)
- )*2./(1.-y)/(1.-xt) / lo_me2_ / 8. / pi / alphaS_;
- else
- throw Exception()
- << "MEPP2VVPowheg::Rtilde_Ltilde_qg_on_x\n"
- << "The configuration is not identified as hard / soft / fwd collinear or bwd collinear."
- << "config = " << config << "\n"
- << "xt = " << xt << " 1.-xt = " << 1.-xt << "\n"
- << "y = " << y << " 1.-y = " << 1.-y << "\n"
- << Exception::eventerror;
-}
-
-/***************************************************************************/
-// The following three functions are identically \tilde{I}_{4,t},
-// \tilde{I}_{3,WZ} and \tilde{I}_{3,W} given in Eqs. B.8,B.9,B.10
-// of NPB 383(1992)3-44, respectively. They are related to / derived
-// from the loop integrals in Eqs. A.3, A.5 and A.8 of the same paper.
-InvEnergy4 TildeI4t(Energy2 s, Energy2 t, Energy2 mW2, Energy2 mZ2);
-InvEnergy2 TildeI3WZ(Energy2 s, Energy2 mW2, Energy2 mZ2, double beta);
-InvEnergy2 TildeI3W(Energy2 s, Energy2 t, Energy2 mW2);
-
-/***************************************************************************/
-// The following six functions are identically I_{dd}^{(1)}, I_{ud}^{(1)},
-// I_{uu}^{(1)}, F_{u}^{(1)}, F_{d}^{(1)}, H^{(1)} from Eqs. B.4, B.5, B.3,
-// B.3, B.6, B.7 of NPB 383(1992)3-44, respectively. They make up the
-// one-loop matrix element. Ixx functions correspond to the graphs
-// with no TGC, Fx functions are due to non-TGC graphs interfering
-// with TGC graphs, while the H function is due purely to TGC graphs.
-double Idd1(Energy2 s,Energy2 t,Energy2 u,Energy2 mW2,Energy2 mZ2,double beta);
-double Iud1(Energy2 s,Energy2 t,Energy2 u,Energy2 mW2,Energy2 mZ2,double beta);
-double Iuu1(Energy2 s,Energy2 t,Energy2 u,Energy2 mW2,Energy2 mZ2,double beta);
-Energy2 Fu1(Energy2 s,Energy2 t,Energy2 u,Energy2 mW2,Energy2 mZ2,double beta);
-Energy2 Fd1(Energy2 s,Energy2 t,Energy2 u,Energy2 mW2,Energy2 mZ2,double beta);
-Energy4 H1 (Energy2 s,Energy2 t,Energy2 u,Energy2 mW2,Energy2 mZ2);
-
-/***************************************************************************/
-// M_V_Regular is the regular part of the one-loop matrix element
-// exactly as defined in Eqs. B.1 and B.2 of of NPB 383(1992)3-44.
-double MEPP2VVPowheg::M_V_regular(realVVKinematics S) const {
- Energy2 s(S.bornVariables().sb());
- Energy2 t(S.bornVariables().tb());
- Energy2 u(S.bornVariables().ub());
- Energy2 mW2(S.k12r()); // N.B. the diboson masses are preserved in getting
- Energy2 mZ2(S.k22r()); // the 2->2 from the 2->3 kinematics.
- double beta(S.betaxr()); // N.B. for x=1 \beta_x=\beta in NPB 383(1992)3-44.
-
- double cosThetaW(sqrt(1.-sin2ThetaW_));
- double eZ2(eZ2_);
- double eZ(eZ_);
- double gdL(gdL_);
- double guL(guL_);
- double gdR(gdR_);
- double guR(guR_);
-
- // W+W-
- if(abs(mePartonData()[2]->id())==24&&abs(mePartonData()[3]->id())==24) {
- double e2(sqr(gW_)*sin2ThetaW_);
- if(abs(quark_->id())%2==0&&abs(antiquark_->id())%2==0) {
- // N.B. OLD eZ used to calculate new eZ2 *then* new eZ is set!
- if(quark_->id()==-antiquark_->id()) {
- eZ2 = 1./2.*sqr(s-mW2)/Fij2_
- * (e2*e2/s/s*(sqr( 2./3.+eZ*(guL+guR)/2./e2*s/(s-mW2/sqr(cosThetaW)))
- +sqr( eZ*(guL-guR)/2./e2*s/(s-mW2/sqr(cosThetaW))))
- );
- eZ = -1./2./Fij2_/(gW_*gW_/4./sqrt(Fij2_))*(s-mW2)
- * (gW_*gW_*e2/4./s *( 2./3.+2.*eZ*guL/2./e2*s/(s-mW2/sqr(cosThetaW))));
- } else {
- eZ2 =0.;
- eZ =0.;
- }
- gdL = gW_/sqrt(2.);
- guL = 0.;
- }
- else if(abs(quark_->id())%2==1&&abs(antiquark_->id())%2==1) {
- // N.B. OLD eZ used to calculate new eZ2 *then* new eZ is set!
- if(quark_->id()==-antiquark_->id()) {
- eZ2 = 1./2.*sqr(s-mW2)/Fij2_
- * (e2*e2/s/s*(sqr(-1./3.+eZ*(gdL+gdR)/2./e2*s/(s-mW2/sqr(cosThetaW)))
- +sqr( eZ*(gdL-gdR)/2./e2*s/(s-mW2/sqr(cosThetaW))))
- );
- eZ = -1./2./Fij2_/(gW_*gW_/4./sqrt(Fij2_))*(s-mW2)
- * (gW_*gW_*e2/4./s *(-1./3.+2.*eZ*gdL/2./e2*s/(s-mW2/sqr(cosThetaW))));
- } else {
- eZ2 =0.;
- eZ =0.;
- }
- guL = gW_/sqrt(2.);
- gdL = 0.;
- }
- }
- // ZZ
- else if(mePartonData()[2]->id()==23&&mePartonData()[3]->id()==23) {
- eZ = 0.;
- eZ2 = 0.;
- double gV2,gA2;
- gV2 = sqr(guL/2.-gW_/2./cosThetaW*2./3.*sin2ThetaW_);
- gA2 = sqr(guL/2.+gW_/2./cosThetaW*2./3.*sin2ThetaW_);
- guL = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.;
- gV2 = sqr(gdL/2.+gW_/2./cosThetaW*1./3.*sin2ThetaW_);
- gA2 = sqr(gdL/2.-gW_/2./cosThetaW*1./3.*sin2ThetaW_);
- gdL = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.;
- if(abs(quark_->id())%2==0&&abs(antiquark_->id())%2==0) gdL = guL;
- else if(abs(quark_->id())%2==1&&abs(antiquark_->id())%2==1) guL = gdL;
- else {
- cout << "MEPP2VVPowheg:" << endl;
- cout << "ZZ needs 2 down-type / 2 up-type!" << endl;
- }
- }
-
- return 4.*pi*alphaS_*Fij2_*CF_*(1./sqr(4.*pi))/NC_
- * ( gdL*gdL*Idd1(s,t,u,mW2,mZ2,beta)
- + gdL*guL*Iud1(s,t,u,mW2,mZ2,beta)
- + guL*guL*Iuu1(s,t,u,mW2,mZ2,beta)
- - eZ/(s-mW2) * ( gdL*Fd1(s,t,u,mW2,mZ2,beta)
- - guL*Fu1(s,t,u,mW2,mZ2,beta)
- )
- + (16.-8.*pi*pi/3.)*(-1./(4.*(Fij2_)*NC_))*sum_hel_amps_only_s_sqr // att: sum_hel_amps_only_s_sqr not declared here!
- // + eZ2/sqr(s-mW2)* H1(s,t,u,mW2,mZ2)
- );
-}
-
-/***************************************************************************/
-InvEnergy4 TildeI4t(Energy2 s, Energy2 t, Energy2 mW2, Energy2 mZ2) {
- double sqrBrackets;
- sqrBrackets = ( sqr(log(-t/mW2))/2.+log(-t/mW2)*log(-t/mZ2)/2.
- - 2.*log(-t/mW2)*log((mW2-t)/mW2)-2.*ReLi2(t/mW2)
- );
-
- swap(mW2,mZ2);
- sqrBrackets+= ( sqr(log(-t/mW2))/2.+log(-t/mW2)*log(-t/mZ2)/2.
- - 2.*log(-t/mW2)*log((mW2-t)/mW2)-2.*ReLi2(t/mW2)
- );
- swap(mW2,mZ2);
-
- return sqrBrackets/s/t;
-}
-
-InvEnergy2 TildeI3WZ(Energy2 s, Energy2 mW2, Energy2 mZ2, double beta) {
- Energy2 sig(mZ2+mW2);
- Energy2 del(mZ2-mW2);
- double sqrBrackets ;
- sqrBrackets = ( ReLi2(2.*mW2/(sig-del*(del/s+beta)))
- + ReLi2((1.-del/s+beta)/2.)
- + sqr(log((1.-del/s+beta)/2.))/2.
- + log((1.-del/s-beta)/2.)*log((1.+del/s-beta)/2.)
- );
-
- beta *= -1;
- sqrBrackets -= ( ReLi2(2.*mW2/(sig-del*(del/s+beta)))
- + ReLi2((1.-del/s+beta)/2.)
- + sqr(log((1.-del/s+beta)/2.))/2.
- + log((1.-del/s-beta)/2.)*log((1.+del/s-beta)/2.)
- );
- beta *= -1;
-
- swap(mW2,mZ2);
- del *= -1.;
- sqrBrackets += ( ReLi2(2.*mW2/(sig-del*(del/s+beta)))
- + ReLi2((1.-del/s+beta)/2.)
- + sqr(log((1.-del/s+beta)/2.))/2.
- + log((1.-del/s-beta)/2.)*log((1.+del/s-beta)/2.)
- );
- swap(mW2,mZ2);
- del *= -1.;
-
- beta *= -1;
- swap(mW2,mZ2);
- del *= -1.;
- sqrBrackets -= ( ReLi2(2.*mW2/(sig-del*(del/s+beta)))
- + ReLi2((1.-del/s+beta)/2.)
- + sqr(log((1.-del/s+beta)/2.))/2.
- + log((1.-del/s-beta)/2.)*log((1.+del/s-beta)/2.)
- );
- beta *= -1;
- swap(mW2,mZ2);
- del *= -1.;
-
- return sqrBrackets/s/beta;
-}
-
-InvEnergy2 TildeI3W(Energy2 s, Energy2 t, Energy2 mW2) {
- return
- 1./(mW2-t)*(sqr(log(mW2/s))/2.-sqr(log(-t/s))/2.-sqr(pi)/2.);
-}
-
-/***************************************************************************/
-double Idd1(Energy2 s, Energy2 t, Energy2 u, Energy2 mW2, Energy2 mZ2, double beta) {
- Energy2 sig(mZ2+mW2);
- Energy2 del(mZ2-mW2);
- double Val(0.);
-
- Val += 2.*(22.*t*t+t*(19.*s-18.*sig)+18.*mW2*mZ2)/t/t
- - 8.*(u*t+2*s*sig)/mW2/mZ2
- - 2.*sqr(t-u)/t/s/sqr(beta);
-
- Val += +( 2.*(8.*t*t+4.*t*(s-3.*sig)+4*sqr(sig)-5.*s*sig+s*s)/t/s/sqr(beta)
- + 4.*(t*(3.*u+s)-3.*mW2*mZ2)/t/t
- + 6.*(t+u)*sqr(t-u)/t/s/s/sqr(sqr(beta))
- )*log(-t/s);
-
- Val += +( ( 8.*t*t*(-2.*s+del)+8.*t*(-s*s+3.*s*sig-2.*del*sig)
- - 2.*(s-sig)*(s*s-4.*s*sig+3.*del*sig)
- )/t/s/s/beta/beta
- + 16.*s*(t-mZ2)/(t*(u+s)-mW2*mZ2)
- + 2.*(4.*t*t+t*(10.*s-3.*mZ2-9.*mW2)+12.*mW2*mZ2)/t/t
- -6.*(s-del)*(t+u)*sqr(t-u)/t/s/s/s/sqr(sqr(beta))
- )*log(-t/mW2);
-
- Val += ( - ( 4.*t*t*(2.*sig-3.*s)
- - 4.*t*(s-sig)*(2.*s-3.*sig)
- - 2.*(s-2.*sig)*sqr(s-sig)
- )/t/s/beta/beta
- + ( 4.*sig*t-3.*s*s+4.*s*sig
- - 4.*(mW2*mW2+mZ2*mZ2)
- )/t
- - 3.*sqr(t*t-u*u)/t/s/s/sqr(sqr(beta))
- )*TildeI3WZ(s,mW2,mZ2,beta);
-
- Val += +( 4.*(t*u+2.*s*sig)/3./mW2/mZ2 - 4.*(t-2.*u)/3./t
- )*pi*pi;
-
- Val += -( 4.*s*(t*u-2.*mW2*mZ2)/t
- )*TildeI4t(s,t,mW2,mZ2);
-
- Val += ( 8.*(t-mW2)*(u*t-2.*mW2*mZ2)/t/t
- )*TildeI3W(s,t,mW2);
-
- swap(mW2,mZ2);
- del *= -1;
- Val += 2.*(22.*t*t+t*(19.*s-18.*sig)+18.*mW2*mZ2)/t/t
- - 8.*(u*t+2*s*sig)/mW2/mZ2
- - 2.*sqr(t-u)/t/s/sqr(beta);
-
- Val += +( 2.*(8.*t*t+4.*t*(s-3.*sig)+4*sqr(sig)-5.*s*sig+s*s)/t/s/sqr(beta)
- + 4.*(t*(3.*u+s)-3.*mW2*mZ2)/t/t
- + 6.*(t+u)*sqr(t-u)/t/s/s/sqr(sqr(beta))
- )*log(-t/s);
-
- Val += +( ( 8.*t*t*(-2.*s+del)+8.*t*(-s*s+3.*s*sig-2.*del*sig)
- - 2.*(s-sig)*(s*s-4.*s*sig+3.*del*sig)
- )/t/s/s/beta/beta
- + 16.*s*(t-mZ2)/(t*(u+s)-mW2*mZ2)
- + 2.*(4.*t*t+t*(10.*s-3.*mZ2-9.*mW2)+12.*mW2*mZ2)/t/t
- -6.*(s-del)*(t+u)*sqr(t-u)/t/s/s/s/sqr(sqr(beta))
- )*log(-t/mW2);
-
- Val += ( - ( 4.*t*t*(2.*sig-3.*s)
- - 4.*t*(s-sig)*(2.*s-3.*sig)
- - 2.*(s-2.*sig)*sqr(s-sig)
- )/t/s/beta/beta
- + ( 4.*sig*t-3.*s*s+4.*s*sig
- - 4.*(mW2*mW2+mZ2*mZ2)
- )/t
- - 3.*sqr(t*t-u*u)/t/s/s/sqr(sqr(beta))
- )*TildeI3WZ(s,mW2,mZ2,beta);
-
- Val += +( 4.*(t*u+2.*s*sig)/3./mW2/mZ2 - 4.*(t-2.*u)/3./t
- )*pi*pi;
-
- Val += -( 4.*s*(t*u-2.*mW2*mZ2)/t
- )*TildeI4t(s,t,mW2,mZ2);
-
- Val += ( 8.*(t-mW2)*(u*t-2.*mW2*mZ2)/t/t
- )*TildeI3W(s,t,mW2);
- swap(mW2,mZ2);
- del *= -1;
-
- return Val;
-}
-
-/***************************************************************************/
-double Iud1(Energy2 s, Energy2 t, Energy2 u, Energy2 mW2, Energy2 mZ2, double beta) {
- Energy2 sig(mZ2+mW2);
- Energy2 del(mZ2-mW2);
- double Val(0.);
-
- Val += 2.*(4.*t*t+t*(9.*s-4.*sig)-18.*s*sig)/t/u
- + 8.*(t*u+2.*s*sig)/mW2/mZ2
- + 4.*s*s*(2.*t-sig)/u/(mW2*mZ2-t*(u+s))
- - 2.*sqr(t-u)/u/s/sqr(beta);
-
- Val += ( 2.*(8.*t*t-4.*t*(s+3.*sig)-(s-sig)*(3.*s+4.*sig))/u/s/sqr(beta)
- + 6.*(t+u)*sqr(t-u)/u/s/s/sqr(sqr(beta))
- - 12.*s*(t-sig)/t/u
- )*log(-t/s);
-
- Val += ( (2./u/s/s/sqr(beta))*( 4.*t*t*(-2.*s+del)
- + 4.*t*(s*s+s*(mZ2+5.*mW2)-2.*sig*del)
- + (s-sig)*(3.*s*s+8.*mW2*s-3.*sig*del)
- )
- + (2.*t*(18.*s+3.*mW2+mZ2)-24.*s*sig)/t/u
- - 8.*s*(2.*t*t-t*(3.*s+4.*mZ2+2.*mW2)+2.*mZ2*(s+sig))
- /u/(mW2*mZ2-t*(u+s))
- - 8.*s*s*t*(2.*t-sig)*(t-mZ2)/u/sqr(mW2*mZ2-t*(u+s))
- + 6.*(s-del)*(s-sig)*sqr(t-u)/u/s/s/s/sqr(sqr(beta))
- )*log(-t/mW2);
-
- Val += ( -2.*(2.*t*t*(2.*sig-3.*s)+6.*sig*t*(s-sig)+sqr(s-sig)*(s+2.*sig))
- /u/s/sqr(beta)
- +3.*s*(4.*t-4.*sig-s)/u
- -3.*sqr(s-sig)*sqr(t-u)/u/s/s/sqr(sqr(beta))
- )*TildeI3WZ(s,mW2,mZ2,beta);
-
- Val += ( 4.*(u+4.*s)/3./u - 4.*(u*t+2.*s*sig)/3./mW2/mZ2
- )*pi*pi;
-
- Val += -( 16.*s*(t-sig)*(t-mW2)/t/u
- )*TildeI3W(s,t,mW2);
-
- Val += ( 8.*s*s*(t-sig)/u
- )*TildeI4t(s,t,mW2,mZ2);
-
- swap(t,u);
- Val += 2.*(4.*t*t+t*(9.*s-4.*sig)-18.*s*sig)/t/u
- + 8.*(t*u+2.*s*sig)/mW2/mZ2
- + 4.*s*s*(2.*t-sig)/u/(mW2*mZ2-t*(u+s))
- - 2.*sqr(t-u)/u/s/sqr(beta);
-
- Val += ( 2.*(8.*t*t-4.*t*(s+3.*sig)-(s-sig)*(3.*s+4.*sig))/u/s/sqr(beta)
- + 6.*(t+u)*sqr(t-u)/u/s/s/sqr(sqr(beta))
- - 12.*s*(t-sig)/t/u
- )*log(-t/s);
-
- Val += ( (2./u/s/s/sqr(beta))*( 4.*t*t*(-2.*s+del)
- + 4.*t*(s*s+s*(mZ2+5.*mW2)-2.*sig*del)
- + (s-sig)*(3.*s*s+8.*mW2*s-3.*sig*del)
- )
- + (2.*t*(18.*s+3.*mW2+mZ2)-24.*s*sig)/t/u
- - 8.*s*(2.*t*t-t*(3.*s+4.*mZ2+2.*mW2)+2.*mZ2*(s+sig))
- /u/(mW2*mZ2-t*(u+s))
- - 8.*s*s*t*(2.*t-sig)*(t-mZ2)/u/sqr(mW2*mZ2-t*(u+s))
- + 6.*(s-del)*(s-sig)*sqr(t-u)/u/s/s/s/sqr(sqr(beta))
- )*log(-t/mW2);
-
- Val += ( -2.*(2.*t*t*(2.*sig-3.*s)+6.*sig*t*(s-sig)+sqr(s-sig)*(s+2.*sig))
- /u/s/sqr(beta)
- +3.*s*(4.*t-4.*sig-s)/u
- -3.*sqr(s-sig)*sqr(t-u)/u/s/s/sqr(sqr(beta))
- )*TildeI3WZ(s,mW2,mZ2,beta);
-
- Val += ( 4.*(u+4.*s)/3./u - 4.*(u*t+2.*s*sig)/3./mW2/mZ2
- )*pi*pi;
-
- Val += -( 16.*s*(t-sig)*(t-mW2)/t/u
- )*TildeI3W(s,t,mW2);
-
- Val += ( 8.*s*s*(t-sig)/u
- )*TildeI4t(s,t,mW2,mZ2);
- swap(t,u);
-
- swap(mW2,mZ2);
- del *= -1;
- Val += 2.*(4.*t*t+t*(9.*s-4.*sig)-18.*s*sig)/t/u
- + 8.*(t*u+2.*s*sig)/mW2/mZ2
- + 4.*s*s*(2.*t-sig)/u/(mW2*mZ2-t*(u+s))
- - 2.*sqr(t-u)/u/s/sqr(beta);
-
- Val += ( 2.*(8.*t*t-4.*t*(s+3.*sig)-(s-sig)*(3.*s+4.*sig))/u/s/sqr(beta)
- + 6.*(t+u)*sqr(t-u)/u/s/s/sqr(sqr(beta))
- - 12.*s*(t-sig)/t/u
- )*log(-t/s);
-
- Val += ( (2./u/s/s/sqr(beta))*( 4.*t*t*(-2.*s+del)
- + 4.*t*(s*s+s*(mZ2+5.*mW2)-2.*sig*del)
- + (s-sig)*(3.*s*s+8.*mW2*s-3.*sig*del)
- )
- + (2.*t*(18.*s+3.*mW2+mZ2)-24.*s*sig)/t/u
- - 8.*s*(2.*t*t-t*(3.*s+4.*mZ2+2.*mW2)+2.*mZ2*(s+sig))
- /u/(mW2*mZ2-t*(u+s))
- - 8.*s*s*t*(2.*t-sig)*(t-mZ2)/u/sqr(mW2*mZ2-t*(u+s))
- + 6.*(s-del)*(s-sig)*sqr(t-u)/u/s/s/s/sqr(sqr(beta))
- )*log(-t/mW2);
-
- Val += ( -2.*(2.*t*t*(2.*sig-3.*s)+6.*sig*t*(s-sig)+sqr(s-sig)*(s+2.*sig))
- /u/s/sqr(beta)
- +3.*s*(4.*t-4.*sig-s)/u
- -3.*sqr(s-sig)*sqr(t-u)/u/s/s/sqr(sqr(beta))
- )*TildeI3WZ(s,mW2,mZ2,beta);
-
- Val += ( 4.*(u+4.*s)/3./u - 4.*(u*t+2.*s*sig)/3./mW2/mZ2
- )*pi*pi;
-
- Val += -( 16.*s*(t-sig)*(t-mW2)/t/u
- )*TildeI3W(s,t,mW2);
-
- Val += ( 8.*s*s*(t-sig)/u
- )*TildeI4t(s,t,mW2,mZ2);
- swap(mW2,mZ2);
- del *= -1;
-
- swap(t,u);
- swap(mW2,mZ2);
- del *= -1;
- Val += 2.*(4.*t*t+t*(9.*s-4.*sig)-18.*s*sig)/t/u
- + 8.*(t*u+2.*s*sig)/mW2/mZ2
- + 4.*s*s*(2.*t-sig)/u/(mW2*mZ2-t*(u+s))
- - 2.*sqr(t-u)/u/s/sqr(beta);
-
- Val += ( 2.*(8.*t*t-4.*t*(s+3.*sig)-(s-sig)*(3.*s+4.*sig))/u/s/sqr(beta)
- + 6.*(t+u)*sqr(t-u)/u/s/s/sqr(sqr(beta))
- - 12.*s*(t-sig)/t/u
- )*log(-t/s);
-
- Val += ( (2./u/s/s/sqr(beta))*( 4.*t*t*(-2.*s+del)
- + 4.*t*(s*s+s*(mZ2+5.*mW2)-2.*sig*del)
- + (s-sig)*(3.*s*s+8.*mW2*s-3.*sig*del)
- )
- + (2.*t*(18.*s+3.*mW2+mZ2)-24.*s*sig)/t/u
- - 8.*s*(2.*t*t-t*(3.*s+4.*mZ2+2.*mW2)+2.*mZ2*(s+sig))
- /u/(mW2*mZ2-t*(u+s))
- - 8.*s*s*t*(2.*t-sig)*(t-mZ2)/u/sqr(mW2*mZ2-t*(u+s))
- + 6.*(s-del)*(s-sig)*sqr(t-u)/u/s/s/s/sqr(sqr(beta))
- )*log(-t/mW2);
-
- Val += ( -2.*(2.*t*t*(2.*sig-3.*s)+6.*sig*t*(s-sig)+sqr(s-sig)*(s+2.*sig))
- /u/s/sqr(beta)
- +3.*s*(4.*t-4.*sig-s)/u
- -3.*sqr(s-sig)*sqr(t-u)/u/s/s/sqr(sqr(beta))
- )*TildeI3WZ(s,mW2,mZ2,beta);
-
- Val += ( 4.*(u+4.*s)/3./u - 4.*(u*t+2.*s*sig)/3./mW2/mZ2
- )*pi*pi;
-
- Val += -( 16.*s*(t-sig)*(t-mW2)/t/u
- )*TildeI3W(s,t,mW2);
-
- Val += ( 8.*s*s*(t-sig)/u
- )*TildeI4t(s,t,mW2,mZ2);
- swap(t,u);
- swap(mW2,mZ2);
- del *= -1;
-
- return Val;
-}
-
-/***************************************************************************/
-double Iuu1(Energy2 s, Energy2 t, Energy2 u, Energy2 mW2, Energy2 mZ2, double beta) {
- double Val(Idd1(s,u,t,mW2,mZ2,beta));
- return Val;
-}
-
-/***************************************************************************/
-Energy2 Fd1 (Energy2 s, Energy2 t, Energy2 u, Energy2 mW2, Energy2 mZ2, double beta) {
- Energy2 sig(mZ2+mW2);
- Energy2 del(mZ2-mW2);
- Energy2 Val(0.*GeV2);
-
- Val += 4.*(17.*t*t+t*(11.*s-13.*sig)+17.*(s*sig+mW2*mZ2))/t
- + 16.*(s-sig)*(t*u+2.*s*sig)/mW2/mZ2
- + 4*s*s*(2.*t-sig)/(t*(u+s)-mW2*mZ2);
-
- Val += ( 8.*(t-u)/sqr(beta)
- - 4.*(3.*t*t-t*(s+3.*sig)+3.*(s*sig+mW2*mZ2))/t
- )*log(-t/s);
-
- Val += ( 8.*(t*t-t*(2.*s+3.*mW2+mZ2)+3.*(s*sig+mW2*mZ2))/t
- + 8.*s*(t*(3.*s+2.*sig)-2.*mZ2*(s+sig))/(t*(u+s)-mW2*mZ2)
- + 8.*s*s*t*(2.*t-sig)*(t-mZ2)/sqr(t*(u+s)-mW2*mZ2)
- - 8.*(s-del)*(t-u)/s/sqr(beta)
- )*log(-t/mW2);
-
- Val += ( 4.*(s-sig)*(t-u)/sqr(beta)
- + 4.*(sig-3.*s)*t
- + 4.*(4.*s*sig-mZ2*mZ2-mW2*mW2)
- )*TildeI3WZ(s,mW2,mZ2,beta);
-
- Val += -( 8.*(3.*t*t+2.*t*(2.*s-sig)+2.*(s*sig+mW2*mZ2))/3./t
- + 8.*(s-sig)*(t*u+2.*s*sig)/3./mW2/mZ2
- )*pi*pi;
-
- Val += ( 4.*(s*t*t-s*(s+sig)*t+2.*s*(s*sig+mW2*mZ2))
- )*TildeI4t(s,t,mW2,mZ2);
-
- Val += -( 8.*(t-mW2)*(t*t-t*(s+sig)+2.*(s*sig+mW2*mZ2))/t
- )*TildeI3W(s,t,mW2);
-
-
- swap(mW2,mZ2);
- del *= -1;
- Val += 4.*(17.*t*t+t*(11.*s-13.*sig)+17.*(s*sig+mW2*mZ2))/t
- + 16.*(s-sig)*(t*u+2.*s*sig)/mW2/mZ2
- + 4*s*s*(2.*t-sig)/(t*(u+s)-mW2*mZ2);
-
- Val += ( 8.*(t-u)/sqr(beta)
- - 4.*(3.*t*t-t*(s+3.*sig)+3.*(s*sig+mW2*mZ2))/t
- )*log(-t/s);
-
- Val += ( 8.*(t*t-t*(2.*s+3.*mW2+mZ2)+3.*(s*sig+mW2*mZ2))/t
- + 8.*s*(t*(3.*s+2.*sig)-2.*mZ2*(s+sig))/(t*(u+s)-mW2*mZ2)
- + 8.*s*s*t*(2.*t-sig)*(t-mZ2)/sqr(t*(u+s)-mW2*mZ2)
- - 8.*(s-del)*(t-u)/s/sqr(beta)
- )*log(-t/mW2);
-
- Val += ( 4.*(s-sig)*(t-u)/sqr(beta)
- + 4.*(sig-3.*s)*t
- + 4.*(4.*s*sig-mZ2*mZ2-mW2*mW2)
- )*TildeI3WZ(s,mW2,mZ2,beta);
-
- Val += -( 8.*(3.*t*t+2.*t*(2.*s-sig)+2.*(s*sig+mW2*mZ2))/3./t
- + 8.*(s-sig)*(t*u+2.*s*sig)/3./mW2/mZ2
- )*pi*pi;
-
- Val += ( 4.*(s*t*t-s*(s+sig)*t+2.*s*(s*sig+mW2*mZ2))
- )*TildeI4t(s,t,mW2,mZ2);
-
- Val += -( 8.*(t-mW2)*(t*t-t*(s+sig)+2.*(s*sig+mW2*mZ2))/t
- )*TildeI3W(s,t,mW2);
- swap(mW2,mZ2);
- del *= -1;
-
- return Val;
-}
-
-/***************************************************************************/
-Energy2 Fu1 (Energy2 s, Energy2 t, Energy2 u, Energy2 mW2, Energy2 mZ2, double beta) {
- Energy2 Val(Fd1(s,u,t,mW2,mZ2,beta));
- return Val;
-}
-
-/***************************************************************************/
-Energy4 H1 (Energy2 s, Energy2 t, Energy2 u, Energy2 mW2, Energy2 mZ2) {
- Energy2 sig(mZ2+mW2);
- Energy2 del(mZ2-mW2);
- Energy4 Val(0.*GeV2*GeV2);
- Val = 8.*t*t+8.*t*(s-sig)+s*s+6.*s*sig+mZ2*mZ2+10.*mW2*mZ2+mW2*mW2
- - sqr(s-sig)*(t*u+2.*s*sig)/mW2/mZ2;
- //Val = (16.-8.*pi*pi/3.)*(-1./(4.*(Fij2_)*NC_))*(s-mW2)/eZ*(s-mW2)/eZ*lo_me_s; //eq. 1.15, still need to replace eZ
- Val *= ( 16.-8.*pi*pi/3.);
- return Val;
-}
-
-Energy2 t_u_Rdd(Energy2 s , Energy2 tk , Energy2 uk , Energy2 q1 , Energy2 q2,
- Energy2 mW2, Energy2 mZ2);
-Energy2 t_u_Rud(Energy2 s , Energy2 tk , Energy2 uk , Energy2 q1 , Energy2 q2,
- Energy2 q1h, Energy2 q2h, Energy2 mW2, Energy2 mZ2);
-Energy2 t_u_Ruu(Energy2 s , Energy2 tk , Energy2 uk, Energy2 q1h, Energy2 q2h,
- Energy2 mW2, Energy2 mZ2);
-Energy4 t_u_RZds(Energy2 s ,Energy2 tk , Energy2 uk , Energy2 q1, Energy2 q2,
- Energy2 s2,Energy2 mW2, Energy2 mZ2);
-Energy4 t_u_RZda(Energy2 s , Energy2 tk , Energy2 uk , Energy2 q1, Energy2 q2,
- Energy2 s2, Energy2 mW2, Energy2 mZ2);
-Energy4 t_u_RZd(Energy2 s , Energy2 tk , Energy2 uk , Energy2 q1 , Energy2 q2 ,
- Energy2 s2 , Energy2 mW2, Energy2 mZ2);
-Energy4 t_u_RZu(Energy2 s , Energy2 tk , Energy2 uk , Energy2 q1h, Energy2 q2h,
- Energy2 s2 , Energy2 mW2, Energy2 mZ2);
-Energy6 t_u_RZs(Energy2 s , Energy2 tk , Energy2 uk , Energy2 q1, Energy2 q2,
- Energy2 s2, Energy2 mW2, Energy2 mZ2);
-Energy6 t_u_RZa(Energy2 s , Energy2 tk , Energy2 uk , Energy2 q1, Energy2 q2,
- Energy2 s2, Energy2 mW2, Energy2 mZ2);
-Energy6 t_u_RZ(Energy2 s , Energy2 tk , Energy2 uk , Energy2 q1, Energy2 q2,
- Energy2 s2 , Energy2 mW2, Energy2 mZ2);
-
-/***************************************************************************/
-// t_u_M_R_qqb is the real emission q + qb -> n + g matrix element
-// exactly as defined in Eqs. C.1 of NPB 383(1992)3-44, multiplied by
-// tk * uk!
-Energy2 MEPP2VVPowheg::t_u_M_R_qqb(realVVKinematics R) const {
- // First the Born variables:
- Energy2 s2(R.s2r());
- Energy2 mW2(R.k12r());
- Energy2 mZ2(R.k22r());
- // Then the rest:
- Energy2 s(R.sr());
- Energy2 tk(R.tkr());
- Energy2 uk(R.ukr());
- Energy2 q1(R.q1r());
- Energy2 q2(R.q2r());
- Energy2 q1h(R.q1hatr());
- Energy2 q2h(R.q2hatr());
- Energy2 w1(R.w1r());
- Energy2 w2(R.w2r());
-
- double cosThetaW(sqrt(1.-sin2ThetaW_));
- double eZ2(eZ2_);
- double eZ(eZ_);
- double gdL(gdL_);
- double guL(guL_);
- double gdR(gdR_);
- double guR(guR_);
-
- // W+W-
- if(abs(mePartonData()[2]->id())==24&&abs(mePartonData()[3]->id())==24) {
- double e2(sqr(gW_)*sin2ThetaW_);
- if(abs(quark_->id())%2==0&&abs(antiquark_->id())%2==0) {
- // N.B. OLD eZ used to calculate new eZ2 *then* new eZ is set!
- if(quark_->id()==-antiquark_->id()) {
- eZ2 = 1./2.*sqr(s2-mW2)/Fij2_
- * (e2*e2/s2/s2*(sqr( 2./3.+eZ*(guL+guR)/2./e2*s2/(s2-mW2/sqr(cosThetaW)))
- +sqr( eZ*(guL-guR)/2./e2*s2/(s2-mW2/sqr(cosThetaW))))
- );
- eZ = -1./2./Fij2_/(gW_*gW_/4./sqrt(Fij2_))*(s2-mW2)
- * (gW_*gW_*e2/4./s2 *( 2./3.+2.*eZ*guL/2./e2*s2/(s2-mW2/sqr(cosThetaW))));
- } else {
- eZ2 =0.;
- eZ =0.;
- }
- gdL = gW_/sqrt(2.);
- guL = 0.;
- }
- else if(abs(quark_->id())%2==1&&abs(antiquark_->id())%2==1) {
- // N.B. OLD eZ used to calculate new eZ2 *then* new eZ is set!
- if(quark_->id()==-antiquark_->id()) {
- eZ2 = 1./2.*sqr(s2-mW2)/Fij2_
- * (e2*e2/s2/s2*(sqr(-1./3.+eZ*(gdL+gdR)/2./e2*s2/(s2-mW2/sqr(cosThetaW)))
- +sqr( eZ*(gdL-gdR)/2./e2*s2/(s2-mW2/sqr(cosThetaW))))
- );
- eZ = -1./2./Fij2_/(gW_*gW_/4./sqrt(Fij2_))*(s2-mW2)
- * (gW_*gW_*e2/4./s2 *(-1./3.+2.*eZ*gdL/2./e2*s2/(s2-mW2/sqr(cosThetaW))));
- } else {
- eZ2 =0.;
- eZ =0.;
- }
- guL = gW_/sqrt(2.);
- gdL = 0.;
- }
- }
- // ZZ
- else if(mePartonData()[2]->id()==23&&mePartonData()[3]->id()==23) {
- eZ = 0.;
- eZ2 = 0.;
- double gV2,gA2;
- gV2 = sqr(guL/2.-gW_/2./cosThetaW*2./3.*sin2ThetaW_);
- gA2 = sqr(guL/2.+gW_/2./cosThetaW*2./3.*sin2ThetaW_);
- guL = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.;
- gV2 = sqr(gdL/2.+gW_/2./cosThetaW*1./3.*sin2ThetaW_);
- gA2 = sqr(gdL/2.-gW_/2./cosThetaW*1./3.*sin2ThetaW_);
- gdL = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.;
- if(abs(quark_->id())%2==0&&abs(antiquark_->id())%2==0) gdL = guL;
- else if(abs(quark_->id())%2==1&&abs(antiquark_->id())%2==1) guL = gdL;
- else {
- cout << "MEPP2VVPowheg:" << endl;
- cout << "ZZ needs 2 down-type / 2 up-type!" << endl;
- }
- }
-
- return -2.*pi*alphaS_*Fij2_*CF_/NC_
- * ( gdL*gdL*t_u_Rdd(s,tk,uk,q1,q2,mW2,mZ2)
- + 2.*gdL*guL*t_u_Rud(s,tk,uk,q1,q2,q1h,q2h,mW2,mZ2)
- + guL*guL*t_u_Ruu(s,tk,uk,q1h,q2h,mW2,mZ2)
- - 2.*eZ/(s2-mW2) * ( gdL
- * t_u_RZd(s,tk,uk,q1 ,q2 ,s2,mW2,mZ2)
- - guL
- * t_u_RZu(s,tk,uk,q1h,q2h,s2,mW2,mZ2)
- )
- + eZ2/sqr(s2-mW2) *t_u_RZ(s,tk,uk,q1,q2,s2,mW2,mZ2)
- );
-}
-
-Energy2 t_u_Rdd(Energy2 s ,Energy2 tk ,Energy2 uk ,Energy2 q1,Energy2 q2,
- Energy2 mW2, Energy2 mZ2) {
- Energy2 Val(0.*GeV2);
-
- Val += 4.*(q2*(uk+2.*s+q2)+q1*(s+q1))/mW2/mZ2*uk
- + 16.*(uk+s)/q2*uk
- - 4.*(2.*uk+4.*s+q2)/mW2*uk
- - 4.*(2.*uk+5.*s+q2+2.*q1-mW2)/mZ2*uk
- + 4.*q1*s*(s+q1)/mW2/mZ2
- + 16.*s*(s+q2-mZ2-mW2)/q1
- - 4.*s*(4.*s+q2+q1)/mW2
- + 16.*mW2*mZ2*s/q1/q2
- + 4.*s
- + 16.*mZ2*(tk-2.*mW2)/q1/q2/q2*tk*uk
- + 16.*(2.*mZ2+mW2-tk)/q1/q2*tk*uk
- + 16.*mW2*(s-mZ2-mW2)/q1/q2*uk
- + 16.*mZ2*(q1-2.*mW2)/q2/q2*uk
- + 32.*mW2*mW2*mZ2/q1/q2/q2*uk
- + 16.*mW2/q1*uk
- + 4.*uk
- + 8./q2*tk*uk
- + 4.*q1/mW2/mZ2*tk*uk
- - 24./q1*tk*uk
- - 4./mW2*tk*uk;
-
- swap(mW2,mZ2);
- swap(q1,q2);
- swap(tk,uk);
- Val += 4.*(q2*(uk+2.*s+q2)+q1*(s+q1))/mW2/mZ2*uk
- + 16.*(uk+s)/q2*uk
- - 4.*(2.*uk+4.*s+q2)/mW2*uk
- - 4.*(2.*uk+5.*s+q2+2.*q1-mW2)/mZ2*uk
- + 4.*q1*s*(s+q1)/mW2/mZ2
- + 16.*s*(s+q2-mZ2-mW2)/q1
- - 4.*s*(4.*s+q2+q1)/mW2
- + 16.*mW2*mZ2*s/q1/q2
- + 4.*s
- + 16.*mZ2*(tk-2.*mW2)/q1/q2/q2*tk*uk
- + 16.*(2.*mZ2+mW2-tk)/q1/q2*tk*uk
- + 16.*mW2*(s-mZ2-mW2)/q1/q2*uk
- + 16.*mZ2*(q1-2.*mW2)/q2/q2*uk
- + 32.*mW2*mW2*mZ2/q1/q2/q2*uk
- + 16.*mW2/q1*uk
- + 4.*uk
- + 8./q2*tk*uk
- + 4.*q1/mW2/mZ2*tk*uk
- - 24./q1*tk*uk
- - 4./mW2*tk*uk;
- swap(mW2,mZ2);
- swap(q1,q2);
- swap(tk,uk);
-
- return Val;
-}
-Energy2 t_u_Rud(Energy2 s ,Energy2 tk ,Energy2 uk ,Energy2 q1,Energy2 q2,
- Energy2 q1h,Energy2 q2h,Energy2 mW2, Energy2 mZ2) {
- Energy2 Val(0.*GeV2);
-
- Val += (uk*s*(uk+3.*s+q1h)+s*s*(s+mZ2)-(s+uk)*(2.*mZ2*s+3.*mW2*s+mW2*q1h)
- ) * 8./q1/q2h/q2*uk
- - (uk*(uk+3.*s+q1h-mW2)-(q2+s)*(q2-s)+s*(q2-mW2)+q1h*(q2-mW2)+mW2*q2
- ) * 4.*s/mZ2/q1/q2h*uk
- - 4.*((s+uk+q2h-2.*mZ2)*(s+q1h-mZ2)-mZ2*q1)/mW2/q2*uk
- + 4.*(2.*s*uk+2.*mW2*uk+5.*s*s+2.*q1h*s-2.*mZ2*s)/q1/q2h*uk
- + 4.*(2.*s*uk-s*s-2.*q1h*s+2.*mW2*s+2.*mW2*q1h)/q1/q2h/q2*tk*uk
- + ((2.*uk+s)*(s+q1h)+s*(q2+q2h)+2.*q2*(s+q2h)-q1*s+q1*q2+q1h*q2h
- ) /mW2/mZ2*uk
- + 8.*s*(uk-q1h+mZ2)/q1/q2*uk
- + 4.*s*(-uk+s-q2+q1+q1h)/mZ2/q2h*uk
- + 4.*s*(-uk-q2+q1h)/mZ2/q1*uk
- + 8.*(mZ2*uk-s*s+mW2*s-2.*mZ2*q1-2.*mZ2*q1h)/q2h/q2*uk
- + 2.*(-uk-9.*s-4.*q2-5.*q2h-3.*q1-4.*q1h+8.*mZ2)/mW2*uk
- + 2.*(-4.*uk+3.*s+5.*q1+4.*q1h)/q2h*uk
- + 2.*(s*tk+q2*tk+s*s-q2*q2+q1h*q2)/mW2/mZ2*tk
- - 8.*s*(tk+s+q1h)/mW2/q2*tk
- + 2.*(-tk+3.*s+q2-q1h)/mW2*tk
- - 8.*s*s*s/q1h/q2
- - 2.*s*q2*(s+q2)/mW2/mZ2
- + 2.*s*(2.*s+q2)/mZ2
- + 2.*s*(2.*s+q2)/mW2
- - 16.*s*s/q1h
- - 2.*s
- - 16.*s*s/q1h/q2*tk
- - 8.*s/q2*tk
- - 16.*s/q1h*tk
- + 6.*s/mZ2*tk
- + 4.*s/q1*uk
- + 4.*s/mZ2*uk
- + 12.*uk
- + 4.*s*(tk+q1h-mW2)/mZ2/q1/q2h*tk*uk
- + 2.*(s+4.*q1+5.*q1h-4.*mZ2)/q2*uk
- - 4.*s*s*s/q1h/q1/q2h/q2*tk*uk
- - 4.*s*s/q1h/q2h/q2*tk*uk
- - 4.*s*s/q1h/q1/q2*tk*uk
- + 8.*s*s/mW2/q1h/q2*tk*uk
- - 4.*s*s/q1h/q1/q2h*tk*uk
- + 4.*(s+mZ2)/mW2/q2*tk*uk
- - 4.*s/q1h/q2h*tk*uk
- - 4.*s/q1h/q1*tk*uk
- + 12.*s/mW2/q1h*tk*uk
- - (s+4.*q2)/mW2/mZ2*tk*uk
- - 4.*(s+2.*mZ2)/q2h/q2*tk*uk
- - 4.*(3.*s+2.*q1h)/q1/q2*tk*uk
- - 8.*mW2/q1/q2h*tk*uk
- + 8./q2h*tk*uk
- + 8./q1*tk*uk;
-
- swap(mW2,mZ2);
- swap(q1,q2);
- swap(tk,uk);
- swap(q1h,q2h); // Note this swap is done in accordance with MC@NLO.
- // It is not in NPB 383(1992)3-44 Eq.C.4!
- Val += (uk*s*(uk+3.*s+q1h)+s*s*(s+mZ2)-(s+uk)*(2.*mZ2*s+3.*mW2*s+mW2*q1h)
- ) * 8./q1/q2h/q2*uk
- - (uk*(uk+3.*s+q1h-mW2)-(q2+s)*(q2-s)+s*(q2-mW2)+q1h*(q2-mW2)+mW2*q2
- ) * 4.*s/mZ2/q1/q2h*uk
- - 4.*((s+uk+q2h-2.*mZ2)*(s+q1h-mZ2)-mZ2*q1)/mW2/q2*uk
- + 4.*(2.*s*uk+2.*mW2*uk+5.*s*s+2.*q1h*s-2.*mZ2*s)/q1/q2h*uk
- + 4.*(2.*s*uk-s*s-2.*q1h*s+2.*mW2*s+2.*mW2*q1h)/q1/q2h/q2*tk*uk
- + ((2.*uk+s)*(s+q1h)+s*(q2+q2h)+2.*q2*(s+q2h)-q1*s+q1*q2+q1h*q2h
- ) /mW2/mZ2*uk
- + 8.*s*(uk-q1h+mZ2)/q1/q2*uk
- + 4.*s*(-uk+s-q2+q1+q1h)/mZ2/q2h*uk
- + 4.*s*(-uk-q2+q1h)/mZ2/q1*uk
- + 8.*(mZ2*uk-s*s+mW2*s-2.*mZ2*q1-2.*mZ2*q1h)/q2h/q2*uk
- + 2.*(-uk-9.*s-4.*q2-5.*q2h-3.*q1-4.*q1h+8.*mZ2)/mW2*uk
- + 2.*(-4.*uk+3.*s+5.*q1+4.*q1h)/q2h*uk
- + 2.*(s*tk+q2*tk+s*s-q2*q2+q1h*q2)/mW2/mZ2*tk
- - 8.*s*(tk+s+q1h)/mW2/q2*tk
- + 2.*(-tk+3.*s+q2-q1h)/mW2*tk
- - 8.*s*s*s/q1h/q2
- - 2.*s*q2*(s+q2)/mW2/mZ2
- + 2.*s*(2.*s+q2)/mZ2
- + 2.*s*(2.*s+q2)/mW2
- - 16.*s*s/q1h
- - 2.*s
- - 16.*s*s/q1h/q2*tk
- - 8.*s/q2*tk
- - 16.*s/q1h*tk
- + 6.*s/mZ2*tk
- + 4.*s/q1*uk
- + 4.*s/mZ2*uk
- + 12.*uk
- + 4.*s*(tk+q1h-mW2)/mZ2/q1/q2h*tk*uk
- + 2.*(s+4.*q1+5.*q1h-4.*mZ2)/q2*uk
- - 4.*s*s*s/q1h/q1/q2h/q2*tk*uk
- - 4.*s*s/q1h/q2h/q2*tk*uk
- - 4.*s*s/q1h/q1/q2*tk*uk
- + 8.*s*s/mW2/q1h/q2*tk*uk
- - 4.*s*s/q1h/q1/q2h*tk*uk
- + 4.*(s+mZ2)/mW2/q2*tk*uk
- - 4.*s/q1h/q2h*tk*uk
- - 4.*s/q1h/q1*tk*uk
- + 12.*s/mW2/q1h*tk*uk
- - (s+4.*q2)/mW2/mZ2*tk*uk
- - 4.*(s+2.*mZ2)/q2h/q2*tk*uk
- - 4.*(3.*s+2.*q1h)/q1/q2*tk*uk
- - 8.*mW2/q1/q2h*tk*uk
- + 8./q2h*tk*uk
- + 8./q1*tk*uk;
- swap(mW2,mZ2);
- swap(q1,q2);
- swap(tk,uk);
- swap(q1h,q2h); // Note this swap is done in accordance with MC@NLO.
- // It is not in NPB 383(1992)3-44 Eq.C.4!
-
- swap(tk,uk);
- swap(q1,q2h);
- swap(q2,q1h);
- Val += (uk*s*(uk+3.*s+q1h)+s*s*(s+mZ2)-(s+uk)*(2.*mZ2*s+3.*mW2*s+mW2*q1h)
- ) * 8./q1/q2h/q2*uk
- - (uk*(uk+3.*s+q1h-mW2)-(q2+s)*(q2-s)+s*(q2-mW2)+q1h*(q2-mW2)+mW2*q2
- ) * 4.*s/mZ2/q1/q2h*uk
- - 4.*((s+uk+q2h-2.*mZ2)*(s+q1h-mZ2)-mZ2*q1)/mW2/q2*uk
- + 4.*(2.*s*uk+2.*mW2*uk+5.*s*s+2.*q1h*s-2.*mZ2*s)/q1/q2h*uk
- + 4.*(2.*s*uk-s*s-2.*q1h*s+2.*mW2*s+2.*mW2*q1h)/q1/q2h/q2*tk*uk
- + ((2.*uk+s)*(s+q1h)+s*(q2+q2h)+2.*q2*(s+q2h)-q1*s+q1*q2+q1h*q2h
- ) /mW2/mZ2*uk
- + 8.*s*(uk-q1h+mZ2)/q1/q2*uk
- + 4.*s*(-uk+s-q2+q1+q1h)/mZ2/q2h*uk
- + 4.*s*(-uk-q2+q1h)/mZ2/q1*uk
- + 8.*(mZ2*uk-s*s+mW2*s-2.*mZ2*q1-2.*mZ2*q1h)/q2h/q2*uk
- + 2.*(-uk-9.*s-4.*q2-5.*q2h-3.*q1-4.*q1h+8.*mZ2)/mW2*uk
- + 2.*(-4.*uk+3.*s+5.*q1+4.*q1h)/q2h*uk
- + 2.*(s*tk+q2*tk+s*s-q2*q2+q1h*q2)/mW2/mZ2*tk
- - 8.*s*(tk+s+q1h)/mW2/q2*tk
- + 2.*(-tk+3.*s+q2-q1h)/mW2*tk
- - 8.*s*s*s/q1h/q2
- - 2.*s*q2*(s+q2)/mW2/mZ2
- + 2.*s*(2.*s+q2)/mZ2
- + 2.*s*(2.*s+q2)/mW2
- - 16.*s*s/q1h
- - 2.*s
- - 16.*s*s/q1h/q2*tk
- - 8.*s/q2*tk
- - 16.*s/q1h*tk
- + 6.*s/mZ2*tk
- + 4.*s/q1*uk
- + 4.*s/mZ2*uk
- + 12.*uk
- + 4.*s*(tk+q1h-mW2)/mZ2/q1/q2h*tk*uk
- + 2.*(s+4.*q1+5.*q1h-4.*mZ2)/q2*uk
- - 4.*s*s*s/q1h/q1/q2h/q2*tk*uk
- - 4.*s*s/q1h/q2h/q2*tk*uk
- - 4.*s*s/q1h/q1/q2*tk*uk
- + 8.*s*s/mW2/q1h/q2*tk*uk
- - 4.*s*s/q1h/q1/q2h*tk*uk
- + 4.*(s+mZ2)/mW2/q2*tk*uk
- - 4.*s/q1h/q2h*tk*uk
- - 4.*s/q1h/q1*tk*uk
- + 12.*s/mW2/q1h*tk*uk
- - (s+4.*q2)/mW2/mZ2*tk*uk
- - 4.*(s+2.*mZ2)/q2h/q2*tk*uk
- - 4.*(3.*s+2.*q1h)/q1/q2*tk*uk
- - 8.*mW2/q1/q2h*tk*uk
- + 8./q2h*tk*uk
- + 8./q1*tk*uk;
- swap(tk,uk);
- swap(q1,q2h);
- swap(q2,q1h);
-
- swap(mW2,mZ2);
- swap(q1,q1h);
- swap(q2,q2h);
- Val += (uk*s*(uk+3.*s+q1h)+s*s*(s+mZ2)-(s+uk)*(2.*mZ2*s+3.*mW2*s+mW2*q1h)
- ) * 8./q1/q2h/q2*uk
- - (uk*(uk+3.*s+q1h-mW2)-(q2+s)*(q2-s)+s*(q2-mW2)+q1h*(q2-mW2)+mW2*q2
- ) * 4.*s/mZ2/q1/q2h*uk
- - 4.*((s+uk+q2h-2.*mZ2)*(s+q1h-mZ2)-mZ2*q1)/mW2/q2*uk
- + 4.*(2.*s*uk+2.*mW2*uk+5.*s*s+2.*q1h*s-2.*mZ2*s)/q1/q2h*uk
- + 4.*(2.*s*uk-s*s-2.*q1h*s+2.*mW2*s+2.*mW2*q1h)/q1/q2h/q2*tk*uk
- + ((2.*uk+s)*(s+q1h)+s*(q2+q2h)+2.*q2*(s+q2h)-q1*s+q1*q2+q1h*q2h
- ) /mW2/mZ2*uk
- + 8.*s*(uk-q1h+mZ2)/q1/q2*uk
- + 4.*s*(-uk+s-q2+q1+q1h)/mZ2/q2h*uk
- + 4.*s*(-uk-q2+q1h)/mZ2/q1*uk
- + 8.*(mZ2*uk-s*s+mW2*s-2.*mZ2*q1-2.*mZ2*q1h)/q2h/q2*uk
- + 2.*(-uk-9.*s-4.*q2-5.*q2h-3.*q1-4.*q1h+8.*mZ2)/mW2*uk
- + 2.*(-4.*uk+3.*s+5.*q1+4.*q1h)/q2h*uk
- + 2.*(s*tk+q2*tk+s*s-q2*q2+q1h*q2)/mW2/mZ2*tk
- - 8.*s*(tk+s+q1h)/mW2/q2*tk
- + 2.*(-tk+3.*s+q2-q1h)/mW2*tk
- - 8.*s*s*s/q1h/q2
- - 2.*s*q2*(s+q2)/mW2/mZ2
- + 2.*s*(2.*s+q2)/mZ2
- + 2.*s*(2.*s+q2)/mW2
- - 16.*s*s/q1h
- - 2.*s
- - 16.*s*s/q1h/q2*tk
- - 8.*s/q2*tk
- - 16.*s/q1h*tk
- + 6.*s/mZ2*tk
- + 4.*s/q1*uk
- + 4.*s/mZ2*uk
- + 12.*uk
- + 4.*s*(tk+q1h-mW2)/mZ2/q1/q2h*tk*uk
- + 2.*(s+4.*q1+5.*q1h-4.*mZ2)/q2*uk
- - 4.*s*s*s/q1h/q1/q2h/q2*tk*uk
- - 4.*s*s/q1h/q2h/q2*tk*uk
- - 4.*s*s/q1h/q1/q2*tk*uk
- + 8.*s*s/mW2/q1h/q2*tk*uk
- - 4.*s*s/q1h/q1/q2h*tk*uk
- + 4.*(s+mZ2)/mW2/q2*tk*uk
- - 4.*s/q1h/q2h*tk*uk
- - 4.*s/q1h/q1*tk*uk
- + 12.*s/mW2/q1h*tk*uk
- - (s+4.*q2)/mW2/mZ2*tk*uk
- - 4.*(s+2.*mZ2)/q2h/q2*tk*uk
- - 4.*(3.*s+2.*q1h)/q1/q2*tk*uk
- - 8.*mW2/q1/q2h*tk*uk
- + 8./q2h*tk*uk
- + 8./q1*tk*uk;
- swap(mW2,mZ2);
- swap(q1,q1h);
- swap(q2,q2h);
-
- return Val;
- }
-
-Energy2 t_u_Ruu(Energy2 s ,Energy2 tk ,Energy2 uk ,Energy2 q1h,Energy2 q2h,
- Energy2 mW2, Energy2 mZ2) {
- return t_u_Rdd(s,tk,uk,q1h,q2h,mZ2,mW2);
-}
-
-Energy4 t_u_RZds(Energy2 s ,Energy2 tk ,Energy2 uk ,Energy2 q1,Energy2 q2,
- Energy2 s2, Energy2 mW2, Energy2 mZ2) {
- Energy4 Val(0.*GeV2*GeV2);
- Energy2 sig(mZ2+mW2);
-
- Val += ( q1*q2*(5./2.*s*s+5.*s*tk+3.*tk*tk)+(tk*uk*uk+q1*q1*q2)*(tk+s)
- + q1*(tk*tk*uk+s*uk*uk-s*s*tk+s*s*uk)+q1*q1*q1*(uk+s)-q1*q1*s*s2
- ) * 8./q1/q2
- - ( tk*tk*(4.*uk+s+q1-2.*q2)+tk*(sqr(q1+q2)-q1*s-3.*q2*s-2.*q1*q1)
- - q1*s*(4.*s-2.*q1-q2)+tk*uk*(q1+3.*s)
- ) * 4.*sig/q1/q2
- - 4.*sig*sig*(s*(2.*s+q1)+tk*(uk+5./2.*tk+5.*s+q1+q2)
- )/mW2/mZ2
- + 2.*sig*s2*(4.*sqr(s+tk)+tk*(uk+s+4.*q1+2.*q2)+2.*q1*(2.*s+q1)
- )/mW2/mZ2
- + 4.*sig*sig*(s2+s-q1+q2)/q1/q2*tk
- - 16.*mW2*mZ2*(tk*uk/2.+q2*tk-q1*s)/q1/q2
- - 4.*s2*s2*q1*(tk+s+q1)/mW2/mZ2
- + sig*sig*sig*(uk+tk)/mW2/mZ2
- + 4.*mW2*mZ2*sig*(uk+tk)/q1/q2;
-
- swap(mW2,mZ2);
- swap(q1,q2);
- swap(tk,uk);
- Val += ( q1*q2*(5./2.*s*s+5.*s*tk+3.*tk*tk)+(tk*uk*uk+q1*q1*q2)*(tk+s)
- + q1*(tk*tk*uk+s*uk*uk-s*s*tk+s*s*uk)+q1*q1*q1*(uk+s)-q1*q1*s*s2
- ) * 8./q1/q2
- - ( tk*tk*(4.*uk+s+q1-2.*q2)+tk*(sqr(q1+q2)-q1*s-3.*q2*s-2.*q1*q1)
- - q1*s*(4.*s-2.*q1-q2)+tk*uk*(q1+3.*s)
- ) * 4.*sig/q1/q2
- - 4.*sig*sig*(s*(2.*s+q1)+tk*(uk+5./2.*tk+5.*s+q1+q2)
- )/mW2/mZ2
- + 2.*sig*s2*(4.*sqr(s+tk)+tk*(uk+s+4.*q1+2.*q2)+2.*q1*(2.*s+q1)
- )/mW2/mZ2
- + 4.*sig*sig*(s2+s-q1+q2)/q1/q2*tk
- - 16.*mW2*mZ2*(tk*uk/2.+q2*tk-q1*s)/q1/q2
- - 4.*s2*s2*q1*(tk+s+q1)/mW2/mZ2
- + sig*sig*sig*(uk+tk)/mW2/mZ2
- + 4.*mW2*mZ2*sig*(uk+tk)/q1/q2;
- swap(mW2,mZ2);
- swap(q1,q2);
- swap(tk,uk);
-
- return Val;
-}
-Energy4 t_u_RZda(Energy2 s ,Energy2 tk ,Energy2 uk ,Energy2 q1,Energy2 q2,
- Energy2 s2, Energy2 mW2, Energy2 mZ2) {
- Energy4 Val(0.*GeV2*GeV2);
-
- Val += 4.*mZ2*(2.*uk*uk-s*tk+q1*(uk-tk-s+q1+0.5*q2)+q2*(s-3.*q2)
- ) /q1/q2*tk
- - 4.*mZ2*mZ2*(q1-tk-2.*s-q2)/q1/q2*tk
- - 2.*mZ2*(tk+2.*s+2.*q2)/mW2*tk
- - 2.*s2*(s+2.*q2)/mZ2*tk
- + 8.*mW2*mZ2*mZ2/q1/q2*tk
- + 2.*mZ2*mZ2/mW2*tk;
-
- swap(mW2,mZ2); // N.B. Here we subtract!
- Val -= 4.*mZ2*(2.*uk*uk-s*tk+q1*(uk-tk-s+q1+0.5*q2)+q2*(s-3.*q2)
- ) /q1/q2*tk
- - 4.*mZ2*mZ2*(q1-tk-2.*s-q2)/q1/q2*tk
- - 2.*mZ2*(tk+2.*s+2.*q2)/mW2*tk
- - 2.*s2*(s+2.*q2)/mZ2*tk
- + 8.*mW2*mZ2*mZ2/q1/q2*tk
- + 2.*mZ2*mZ2/mW2*tk;
- swap(mW2,mZ2);
-
- swap(q1,q2); // N.B. Here we subtract!
- swap(tk,uk);
- Val -= 4.*mZ2*(2.*uk*uk-s*tk+q1*(uk-tk-s+q1+0.5*q2)+q2*(s-3.*q2)
- ) /q1/q2*tk
- - 4.*mZ2*mZ2*(q1-tk-2.*s-q2)/q1/q2*tk
- - 2.*mZ2*(tk+2.*s+2.*q2)/mW2*tk
- - 2.*s2*(s+2.*q2)/mZ2*tk
- + 8.*mW2*mZ2*mZ2/q1/q2*tk
- + 2.*mZ2*mZ2/mW2*tk;
- swap(q1,q2);
- swap(tk,uk);
-
- swap(mW2,mZ2); // N.B. Here we add!
- swap(q1,q2);
- swap(tk,uk);
- Val += 4.*mZ2*(2.*uk*uk-s*tk+q1*(uk-tk-s+q1+0.5*q2)+q2*(s-3.*q2)
- ) /q1/q2*tk
- - 4.*mZ2*mZ2*(q1-tk-2.*s-q2)/q1/q2*tk
- - 2.*mZ2*(tk+2.*s+2.*q2)/mW2*tk
- - 2.*s2*(s+2.*q2)/mZ2*tk
- + 8.*mW2*mZ2*mZ2/q1/q2*tk
- + 2.*mZ2*mZ2/mW2*tk;
- swap(mW2,mZ2);
- swap(q1,q2);
- swap(tk,uk);
-
- return Val;
-}
-Energy4 t_u_RZd(Energy2 s , Energy2 tk , Energy2 uk , Energy2 q1 , Energy2 q2 ,
- Energy2 s2, Energy2 mW2, Energy2 mZ2) {
- Energy4 Val(0.*GeV2*GeV2);
-
- Val = t_u_RZds(s,tk,uk,q1,q2,s2,mW2,mZ2)
- + t_u_RZda(s,tk,uk,q1,q2,s2,mW2,mZ2);
-
- return Val;
-}
-Energy4 t_u_RZu(Energy2 s , Energy2 tk , Energy2 uk , Energy2 q1h, Energy2 q2h,
- Energy2 s2, Energy2 mW2, Energy2 mZ2) {
- Energy4 Val(0.*GeV2*GeV2);
-
- Val = t_u_RZd(s,tk,uk,q1h,q2h,s2,mZ2,mW2);
-
- return Val;
-}
-Energy6 t_u_RZs(Energy2 s,Energy2 tk,Energy2 uk,Energy2 q1,Energy2 q2,
- Energy2 s2,Energy2 mW2,Energy2 mZ2) {
- Energy6 Val(0.*GeV2*GeV2*GeV2);
- Energy2 sig(mZ2+mW2);
-
- Val += 2.*sig*sig*s2*( tk*(3.*uk+9.*tk+19.*s+6.*q1+4.*q2)+8.*s*s+6.*q1*s
- + 2.*q1*q1
- )/mW2/mZ2
- - 2.*sig*sig*sig*(tk*(3.*uk+6.*tk+11.*s+2.*q1+2.*q2)+2.*s*(2.*s+q1))
- / mW2/mZ2
- - 2.*sig*s2*s2*(tk*(uk+4.*tk+9.*s+6.*q1+2.*q2)+4.*sqr(s+q1)-2.*q1*s)
- /mW2/mZ2
- - 16.*sig*(2.*tk*(uk/2.-tk-s+q1+q2)-s*(3.*s/2.-2.*q1))
- + 8.*s2*(s*(s/2.+tk)+4.*q1*(tk+s+q1))
- + 4.*s2*s2*s2*q1*(tk+s+q1)/mW2/mZ2
- + 8.*sig*sig*(2.*tk+s/2.)
- + 2.*sig*sig*sig*sig*tk/mW2/mZ2
- + 32.*mW2*mZ2*s;
-
- swap(mW2,mZ2);
- swap(q1,q2);
- swap(tk,uk);
- Val += 2.*sig*sig*s2*( tk*(3.*uk+9.*tk+19.*s+6.*q1+4.*q2)+8.*s*s+6.*q1*s
- + 2.*q1*q1
- )/mW2/mZ2
- - 2.*sig*sig*sig*(tk*(3.*uk+6.*tk+11.*s+2.*q1+2.*q2)+2.*s*(2.*s+q1))
- / mW2/mZ2
- - 2.*sig*s2*s2*(tk*(uk+4.*tk+9.*s+6.*q1+2.*q2)+4.*sqr(s+q1)-2.*q1*s)
- /mW2/mZ2
- - 16.*sig*(2.*tk*(uk/2.-tk-s+q1+q2)-s*(3.*s/2.-2.*q1))
- + 8.*s2*(s*(s/2.+tk)+4.*q1*(tk+s+q1))
- + 4.*s2*s2*s2*q1*(tk+s+q1)/mW2/mZ2
- + 8.*sig*sig*(2.*tk+s/2.)
- + 2.*sig*sig*sig*sig*tk/mW2/mZ2
- + 32.*mW2*mZ2*s;
- swap(mW2,mZ2);
- swap(q1,q2);
- swap(tk,uk);
-
- return Val;
-}
-Energy6 t_u_RZa(Energy2 s,Energy2 tk,Energy2 uk,Energy2 q1,Energy2 q2,
- Energy2 s2,Energy2 mW2,Energy2 mZ2) {
- Energy6 Val(0.*GeV2*GeV2*GeV2);
- Energy2 sig(mZ2+mW2);
-
- Val += - 2.*mZ2*(2.*tk+11.*s+18.*q2)*tk
- - 2.*mZ2*mZ2*(2.*tk+3.*s+2.*q2)/mW2*tk
- + 2.*mZ2*s2*(tk+3.*s+4.*q2)/mW2*tk
- - 2.*s2*s2*(s+2.*q2)/mW2*tk
- + 2.*mZ2*mZ2*mZ2/mW2*tk
- + 20.*mZ2*mZ2*tk;
-
- swap(mW2,mZ2);
- Val -= - 2.*mZ2*(2.*tk+11.*s+18.*q2)*tk
- - 2.*mZ2*mZ2*(2.*tk+3.*s+2.*q2)/mW2*tk
- + 2.*mZ2*s2*(tk+3.*s+4.*q2)/mW2*tk
- - 2.*s2*s2*(s+2.*q2)/mW2*tk
- + 2.*mZ2*mZ2*mZ2/mW2*tk
- + 20.*mZ2*mZ2*tk;
- swap(mW2,mZ2);
-
- swap(q1,q2);
- swap(tk,uk);
- Val -= - 2.*mZ2*(2.*tk+11.*s+18.*q2)*tk
- - 2.*mZ2*mZ2*(2.*tk+3.*s+2.*q2)/mW2*tk
- + 2.*mZ2*s2*(tk+3.*s+4.*q2)/mW2*tk
- - 2.*s2*s2*(s+2.*q2)/mW2*tk
- + 2.*mZ2*mZ2*mZ2/mW2*tk
- + 20.*mZ2*mZ2*tk;
- swap(q1,q2);
- swap(tk,uk);
-
- swap(mW2,mZ2);
- swap(q1,q2);
- swap(tk,uk);
- Val += - 2.*mZ2*(2.*tk+11.*s+18.*q2)*tk
- - 2.*mZ2*mZ2*(2.*tk+3.*s+2.*q2)/mW2*tk
- + 2.*mZ2*s2*(tk+3.*s+4.*q2)/mW2*tk
- - 2.*s2*s2*(s+2.*q2)/mW2*tk
- + 2.*mZ2*mZ2*mZ2/mW2*tk
- + 20.*mZ2*mZ2*tk;
- swap(mW2,mZ2);
- swap(q1,q2);
- swap(tk,uk);
-
- return Val;
-}
-Energy6 t_u_RZ(Energy2 s , Energy2 tk , Energy2 uk , Energy2 q1, Energy2 q2,
- Energy2 s2, Energy2 mW2, Energy2 mZ2) {
- Energy6 Val(0.*GeV2*GeV2*GeV2);
-
- Val = t_u_RZs(s,tk,uk,q1,q2,s2,mW2,mZ2)
- + t_u_RZa(s,tk,uk,q1,q2,s2,mW2,mZ2);
-
- return Val;
-}
-
-/***************************************************************************/
-// t_u_M_R_qg is the real emission q + qb -> n + g matrix element
-// exactly as defined in Eqs. C.9 of NPB 383(1992)3-44, multiplied by
-// tk * uk!
-Energy2 MEPP2VVPowheg::t_u_M_R_qg(realVVKinematics R) const {
- // First the Born variables:
- Energy2 s2(R.s2r());
- Energy2 mW2(R.k12r());
- Energy2 mZ2(R.k22r());
- // Then the rest:
- Energy2 s(R.sr());
- Energy2 tk(R.tkr());
- Energy2 uk(R.ukr());
- Energy2 q1(R.q1r());
- Energy2 q2(R.q2r());
- Energy2 q1h(R.q1hatr());
- Energy2 q2h(R.q2hatr());
- Energy2 w1(R.w1r());
- Energy2 w2(R.w2r());
-
- double cosThetaW(sqrt(1.-sin2ThetaW_));
- double eZ2(eZ2_);
- double eZ(eZ_);
- double gdL(gdL_);
- double guL(guL_);
- double gdR(gdR_);
- double guR(guR_);
-
- // W+W-
- if(abs(mePartonData()[2]->id())==24&&abs(mePartonData()[3]->id())==24) {
- double e2(sqr(gW_)*sin2ThetaW_);
- if(abs(quark_->id())%2==0&&abs(antiquark_->id())%2==0) {
- // N.B. OLD eZ used to calculate new eZ2 *then* new eZ is set!
- if(quark_->id()==-antiquark_->id()) {
- eZ2 = 1./2.*sqr(s2-mW2)/Fij2_
- * (e2*e2/s2/s2*(sqr( 2./3.+eZ*(guL+guR)/2./e2*s2/(s2-mW2/sqr(cosThetaW)))
- +sqr( eZ*(guL-guR)/2./e2*s2/(s2-mW2/sqr(cosThetaW))))
- );
- eZ = -1./2./Fij2_/(gW_*gW_/4./sqrt(Fij2_))*(s2-mW2)
- * (gW_*gW_*e2/4./s2 *( 2./3.+2.*eZ*guL/2./e2*s2/(s2-mW2/sqr(cosThetaW))));
- } else {
- eZ2 =0.;
- eZ =0.;
- }
- gdL = gW_/sqrt(2.);
- guL = 0.;
- }
- else if(abs(quark_->id())%2==1&&abs(antiquark_->id())%2==1) {
- // N.B. OLD eZ used to calculate new eZ2 *then* new eZ is set!
- if(quark_->id()==-antiquark_->id()) {
- eZ2 = 1./2.*sqr(s2-mW2)/Fij2_
- * (e2*e2/s2/s2*(sqr(-1./3.+eZ*(gdL+gdR)/2./e2*s2/(s2-mW2/sqr(cosThetaW)))
- +sqr( eZ*(gdL-gdR)/2./e2*s2/(s2-mW2/sqr(cosThetaW))))
- );
- eZ = -1./2./Fij2_/(gW_*gW_/4./sqrt(Fij2_))*(s2-mW2)
- * (gW_*gW_*e2/4./s2 *(-1./3.+2.*eZ*gdL/2./e2*s2/(s2-mW2/sqr(cosThetaW))));
- } else {
- eZ2 =0.;
- eZ =0.;
- }
- guL = gW_/sqrt(2.);
- gdL = 0.;
- }
- }
- // ZZ
- else if(mePartonData()[2]->id()==23&&mePartonData()[3]->id()==23) {
- eZ = 0.;
- eZ2 = 0.;
- double gV2,gA2;
- gV2 = sqr(guL/2.-gW_/2./cosThetaW*2./3.*sin2ThetaW_);
- gA2 = sqr(guL/2.+gW_/2./cosThetaW*2./3.*sin2ThetaW_);
- guL = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.;
- gV2 = sqr(gdL/2.+gW_/2./cosThetaW*1./3.*sin2ThetaW_);
- gA2 = sqr(gdL/2.-gW_/2./cosThetaW*1./3.*sin2ThetaW_);
- gdL = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.;
- if(abs(quark_->id())%2==0&&abs(antiquark_->id())%2==0) gdL = guL;
- else if(abs(quark_->id())%2==1&&abs(antiquark_->id())%2==1) guL = gdL;
- else {
- cout << "MEPP2VVPowheg:" << endl;
- cout << "ZZ needs 2 down-type / 2 up-type!" << endl;
- }
- }
-
- Energy2 Val(0.*GeV2);
-
- swap(s,tk);
- swap(q2,w2);
- swap(q2h,w1);
- Val = -2.*pi*alphaS_*Fij2_*CF_/NC_
- * ( gdL*gdL*t_u_Rdd(s,tk,uk,q1,q2,mW2,mZ2)
- + 2.*gdL*guL*t_u_Rud(s,tk,uk,q1,q2,q1h,q2h,mW2,mZ2)
- + guL*guL*t_u_Ruu(s,tk,uk,q1h,q2h,mW2,mZ2)
- - 2.*eZ/(s2-mW2) * ( gdL
- * t_u_RZd(s,tk,uk,q1 ,q2 ,s2,mW2,mZ2)
- - guL
- * t_u_RZu(s,tk,uk,q1h,q2h,s2,mW2,mZ2)
- )
- + eZ2/sqr(s2-mW2) *t_u_RZ(s,tk,uk,q1,q2,s2,mW2,mZ2)
- );
- swap(s,tk);
- swap(q2,w2);
- swap(q2h,w1);
-
- Val *= -tk/s * TR_/CF_;
-
- return Val;
-}
-/***************************************************************************/
-// t_u_M_R_gqb is the real emission g + qb -> n + q matrix element
-// exactly as defined in Eqs. C.9 of NPB 383(1992)3-44, multiplied by
-// tk * uk!
-Energy2 MEPP2VVPowheg::t_u_M_R_gqb(realVVKinematics R) const {
- // First the Born variables:
- Energy2 s2(R.s2r());
- Energy2 mW2(R.k12r());
- Energy2 mZ2(R.k22r());
- // Then the rest:
- Energy2 s(R.sr());
- Energy2 tk(R.tkr());
- Energy2 uk(R.ukr());
- Energy2 q1(R.q1r());
- Energy2 q2(R.q2r());
- Energy2 q1h(R.q1hatr());
- Energy2 q2h(R.q2hatr());
- Energy2 w1(R.w1r());
- Energy2 w2(R.w2r());
-
- double cosThetaW(sqrt(1.-sin2ThetaW_));
- double eZ2(eZ2_);
- double eZ(eZ_);
- double gdL(gdL_);
- double guL(guL_);
- double gdR(gdR_);
- double guR(guR_);
-
- // W+W-
- if(abs(mePartonData()[2]->id())==24&&abs(mePartonData()[3]->id())==24) {
- double e2(sqr(gW_)*sin2ThetaW_);
- if(abs(quark_->id())%2==0&&abs(antiquark_->id())%2==0) {
- // N.B. OLD eZ used to calculate new eZ2 *then* new eZ is set!
- if(quark_->id()==-antiquark_->id()) {
- eZ2 = 1./2.*sqr(s2-mW2)/Fij2_
- * (e2*e2/s2/s2*(sqr( 2./3.+eZ*(guL+guR)/2./e2*s2/(s2-mW2/sqr(cosThetaW)))
- +sqr( eZ*(guL-guR)/2./e2*s2/(s2-mW2/sqr(cosThetaW))))
- );
- eZ = -1./2./Fij2_/(gW_*gW_/4./sqrt(Fij2_))*(s2-mW2)
- * (gW_*gW_*e2/4./s2 *( 2./3.+2.*eZ*guL/2./e2*s2/(s2-mW2/sqr(cosThetaW))));
- } else {
- eZ2 =0.;
- eZ =0.;
- }
- gdL = gW_/sqrt(2.);
- guL = 0.;
- }
- else if(abs(quark_->id())%2==1&&abs(antiquark_->id())%2==1) {
- // N.B. OLD eZ used to calculate new eZ2 *then* new eZ is set!
- if(quark_->id()==-antiquark_->id()) {
- eZ2 = 1./2.*sqr(s2-mW2)/Fij2_
- * (e2*e2/s2/s2*(sqr(-1./3.+eZ*(gdL+gdR)/2./e2*s2/(s2-mW2/sqr(cosThetaW)))
- +sqr( eZ*(gdL-gdR)/2./e2*s2/(s2-mW2/sqr(cosThetaW))))
- );
- eZ = -1./2./Fij2_/(gW_*gW_/4./sqrt(Fij2_))*(s2-mW2)
- * (gW_*gW_*e2/4./s2 *(-1./3.+2.*eZ*gdL/2./e2*s2/(s2-mW2/sqr(cosThetaW))));
- } else {
- eZ2 =0.;
- eZ =0.;
- }
- guL = gW_/sqrt(2.);
- gdL = 0.;
- }
- }
- // ZZ
- else if(mePartonData()[2]->id()==23&&mePartonData()[3]->id()==23) {
- eZ = 0.;
- eZ2 = 0.;
- double gV2,gA2;
- gV2 = sqr(guL/2.-gW_/2./cosThetaW*2./3.*sin2ThetaW_);
- gA2 = sqr(guL/2.+gW_/2./cosThetaW*2./3.*sin2ThetaW_);
- guL = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.;
- gV2 = sqr(gdL/2.+gW_/2./cosThetaW*1./3.*sin2ThetaW_);
- gA2 = sqr(gdL/2.-gW_/2./cosThetaW*1./3.*sin2ThetaW_);
- gdL = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.;
- if(abs(quark_->id())%2==0&&abs(antiquark_->id())%2==0) gdL = guL;
- else if(abs(quark_->id())%2==1&&abs(antiquark_->id())%2==1) guL = gdL;
- else {
- cout << "MEPP2VVPowheg:" << endl;
- cout << "ZZ needs 2 down-type / 2 up-type!" << endl;
- }
- }
-
- Energy2 Val(0.*GeV2);
-
- swap(s,uk);
- swap(q1,w1);
- swap(q1h,w2);
- Val = -2.*pi*alphaS_*Fij2_*CF_/NC_
- * ( gdL*gdL*t_u_Rdd(s,tk,uk,q1,q2,mW2,mZ2)
- + 2.*gdL*guL*t_u_Rud(s,tk,uk,q1,q2,q1h,q2h,mW2,mZ2)
- + guL*guL*t_u_Ruu(s,tk,uk,q1h,q2h,mW2,mZ2)
- - 2.*eZ/(s2-mW2) * ( gdL
- * t_u_RZd(s,tk,uk,q1 ,q2 ,s2,mW2,mZ2)
- - guL
- * t_u_RZu(s,tk,uk,q1h,q2h,s2,mW2,mZ2)
- )
- + eZ2/sqr(s2-mW2) *t_u_RZ(s,tk,uk,q1,q2,s2,mW2,mZ2)
- );
- swap(s,uk);
- swap(q1,w1);
- swap(q1h,w2);
-
- Val *= -uk/s * TR_/CF_;
-
- return Val;
-}
-
-/***************************************************************************/
-// The following six functions are I_{dd}^{(0)}, I_{ud}^{(0)},
-// I_{uu}^{(0)}, F_{u}^{(0)}, F_{d}^{(0)}, H^{(0)} from Eqs. 3.9 - 3.14
-// They make up the Born matrix element. Ixx functions correspond to the
-// graphs with no TGC, Fx functions are due to non-TGC graphs interfering
-// with TGC graphs, while the H function is due purely to TGC graphs.
-double Idd0(Energy2 s,Energy2 t,Energy2 u,Energy2 mW2,Energy2 mZ2);
-double Iud0(Energy2 s,Energy2 t,Energy2 u,Energy2 mW2,Energy2 mZ2);
-double Iuu0(Energy2 s,Energy2 t,Energy2 u,Energy2 mW2,Energy2 mZ2);
-Energy2 Fu0(Energy2 s,Energy2 t,Energy2 u,Energy2 mW2,Energy2 mZ2);
-Energy2 Fd0(Energy2 s,Energy2 t,Energy2 u,Energy2 mW2,Energy2 mZ2);
-Energy4 H0 (Energy2 s,Energy2 t,Energy2 u,Energy2 mW2,Energy2 mZ2);
-
-/***************************************************************************/
-// M_Born_WZ is the Born matrix element exactly as defined in Eqs. 3.3-3.14
-// of of NPB 383(1992)3-44 (with a spin*colour averaging factor 1./4./NC_/NC_).
-double MEPP2VVPowheg::M_Born_WZ(bornVVKinematics B) const {
- Energy2 s(B.sb());
- Energy2 t(B.tb());
- Energy2 u(B.ub());
- Energy2 mW2(B.k12b()); // N.B. the diboson masses are preserved in getting
- Energy2 mZ2(B.k22b()); // the 2->2 from the 2->3 kinematics.
-
- double cosThetaW(sqrt(1.-sin2ThetaW_));
- double eZ2(eZ2_);
- double eZ(eZ_);
- double gdL(gdL_);
- double guL(guL_);
- double gdR(gdR_);
- double guR(guR_);
-
- // W+W-
- if(abs(mePartonData()[2]->id())==24&&abs(mePartonData()[3]->id())==24) {
- double e2(sqr(gW_)*sin2ThetaW_);
- if(abs(quark_->id())%2==0&&abs(antiquark_->id())%2==0) {
- // N.B. OLD eZ used to calculate new eZ2 *then* new eZ is set!
- if(quark_->id()==-antiquark_->id()) {
- eZ2 = 1./2.*sqr(s-mW2)/Fij2_
- * (e2*e2/s/s*(sqr( 2./3.+eZ*(guL+guR)/2./e2*s/(s-mW2/sqr(cosThetaW)))
- +sqr( eZ*(guL-guR)/2./e2*s/(s-mW2/sqr(cosThetaW))))
- );
- eZ = -1./2./Fij2_/(gW_*gW_/4./sqrt(Fij2_))*(s-mW2)
- * (gW_*gW_*e2/4./s *( 2./3.+2.*eZ*guL/2./e2*s/(s-mW2/sqr(cosThetaW))));
- } else {
- eZ2 =0.;
- eZ =0.;
- }
- gdL = gW_/sqrt(2.);
- guL = 0.;
- }
- else if(abs(quark_->id())%2==1&&abs(antiquark_->id())%2==1) {
- // N.B. OLD eZ used to calculate new eZ2 *then* new eZ is set!
- if(quark_->id()==-antiquark_->id()) {
- eZ2 = 1./2.*sqr(s-mW2)/Fij2_
- * (e2*e2/s/s*(sqr(-1./3.+eZ*(gdL+gdR)/2./e2*s/(s-mW2/sqr(cosThetaW)))
- +sqr( eZ*(gdL-gdR)/2./e2*s/(s-mW2/sqr(cosThetaW))))
- );
- eZ = -1./2./Fij2_/(gW_*gW_/4./sqrt(Fij2_))*(s-mW2)
- * (gW_*gW_*e2/4./s *(-1./3.+2.*eZ*gdL/2./e2*s/(s-mW2/sqr(cosThetaW))));
- } else {
- eZ2 =0.;
- eZ =0.;
- }
- guL = gW_/sqrt(2.);
- gdL = 0.;
- }
- }
- // ZZ
- else if(mePartonData()[2]->id()==23&&mePartonData()[3]->id()==23) {
- eZ = 0.;
- eZ2 = 0.;
- double gV2,gA2;
- gV2 = sqr(guL/2.-gW_/2./cosThetaW*2./3.*sin2ThetaW_);
- gA2 = sqr(guL/2.+gW_/2./cosThetaW*2./3.*sin2ThetaW_);
- guL = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.;
- gV2 = sqr(gdL/2.+gW_/2./cosThetaW*1./3.*sin2ThetaW_);
- gA2 = sqr(gdL/2.-gW_/2./cosThetaW*1./3.*sin2ThetaW_);
- gdL = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.;
- if(abs(quark_->id())%2==0&&abs(antiquark_->id())%2==0) gdL = guL;
- else if(abs(quark_->id())%2==1&&abs(antiquark_->id())%2==1) guL = gdL;
- else {
- cout << "MEPP2VVPowheg:" << endl;
- cout << "ZZ needs 2 down-type / 2 up-type!" << endl;
- }
- }
-
- return Fij2_/2./NC_
- * (
- gdL*gdL*Idd0(s,t,u,mW2,mZ2)
- + 2.*gdL*guL*Iud0(s,t,u,mW2,mZ2)
- + guL*guL*Iuu0(s,t,u,mW2,mZ2)
- - 2.*eZ/(s-mW2) * ( gdL*Fd0(s,t,u,mW2,mZ2)
- - guL*Fu0(s,t,u,mW2,mZ2)
- )
- + eZ2/sqr(s-mW2) * H0(s,t,u,mW2,mZ2)
- );
-}
-
-/***************************************************************************/
-double Idd0(Energy2 s, Energy2 t, Energy2 u, Energy2 mW2, Energy2 mZ2) {
- return 8.*((u*t/mW2/mZ2-1.)/4.+s/2.*(mW2+mZ2)/mW2/mZ2)
- + 8.*(u/t-mW2*mZ2/t/t);
-}
-
-/***************************************************************************/
-double Iud0(Energy2 s, Energy2 t, Energy2 u, Energy2 mW2, Energy2 mZ2) {
- return - 8.*((u*t/mW2/mZ2-1.)/4.+s/2.*(mW2+mZ2)/mW2/mZ2)
- + 8.*s/t/u*(mW2+mZ2);
-}
-
-/***************************************************************************/
-double Iuu0(Energy2 s, Energy2 t, Energy2 u, Energy2 mW2, Energy2 mZ2) {
- return Idd0(s,u,t,mW2,mZ2);
-}
-
-/***************************************************************************/
-Energy2 Fd0 (Energy2 s, Energy2 t, Energy2 u, Energy2 mW2, Energy2 mZ2) {
- return - 8.*s*( (u*t/mW2/mZ2-1.)*(1.-(mW2+mZ2)/s-4.*mW2*mZ2/s/t)/4.
- + (mW2+mZ2)/2./mW2/mZ2*(s-mW2-mZ2+2.*mW2*mZ2/t)
- );
-}
-
-/***************************************************************************/
-Energy2 Fu0 (Energy2 s, Energy2 t, Energy2 u, Energy2 mW2, Energy2 mZ2) {
- return Fd0(s,u,t,mW2,mZ2);
-}
-
-/***************************************************************************/
-Energy4 H0 (Energy2 s, Energy2 t, Energy2 u, Energy2 mW2, Energy2 mZ2) {
- return 8.*s*s*(u*t/mW2/mZ2-1.)*( 1./4.-(mW2+mZ2)/2./s
- + (sqr(mW2+mZ2)+8.*mW2*mZ2)/4./s/s
- )
- + 8.*s*s*(mW2+mZ2)/mW2/mZ2*(s/2.-mW2-mZ2+sqr(mW2-mZ2)/2./s);
-}
-
-/***************************************************************************/
-bool MEPP2VVPowheg::sanityCheck() const {
-
- bool alarm(false);
-
- Energy2 prefacs(8.*pi*alphaS_*S_.sr() /S_.xr() );
- Energy2 prefacsp(8.*pi*alphaS_*SCp_.sr() /SCp_.xr() );
- Energy2 prefacsm(8.*pi*alphaS_*SCm_.sr() /SCm_.xr() );
- Energy2 prefacp(8.*pi*alphaS_*Cp_.sr()/Cp_.xr());
- Energy2 prefacm(8.*pi*alphaS_*Cm_.sr()/Cm_.xr());
-
- double xp(Cp_.xr());
- double xm(Cm_.xr());
-
- double M_B_WW(M_Born_WW(B_));
- double M_B_ZZ(M_Born_ZZ(B_));
- double M_V_reg_WW(M_V_regular_WW(S_));
- double M_V_reg_ZZ(M_V_regular_ZZ(S_));
- Energy2 t_u_qqb_WW(t_u_M_R_qqb_WW(H_));
- Energy2 t_u_qqb_ZZ(t_u_M_R_qqb_ZZ(H_));
-
- // Check that the native leading order Herwig++ matrix
- // element is equivalent to the WZ leading order matrix
- // element in NPB 383 (1992) 3-44, with the relevant WZ->WW
- // WZ->ZZ transformation applied (M_Born_).
-// if(fabs((lo_me2_ - M_Born_)/M_Born_)>1.e-2) {
-// alarm=true;
-// cout << "lo_me2_ - M_Born_ (%) = "
-// << lo_me2_ - M_Born_ << " ("
-// << (lo_me2_ - M_Born_)/M_Born_*100. << ")\n";
-// }
-
- // Check that the transformation from NPB 383 (1992) 3-44 WZ
- // matrix elements to WW matrix elements actually works, by
- // comparing them to the explicit WW matrix elements in
- // NPB 410 (1993) 280-324.
- if(abs(mePartonData()[2]->id())==24&&abs(mePartonData()[3]->id())==24) {
- if(fabs((M_Born_ -M_B_WW )/M_B_WW )>1.e-6) {
- alarm=true;
- cout << "WZ->WW transformation error!\n";
- cout << "M_Born_ - M_B_WW (rel) = "
- << M_Born_ - M_B_WW << " ("
- << (M_Born_ - M_B_WW)/M_B_WW << ")\n";
- cout << "M_Born_ = " << M_Born_ << endl;
- cout << "M_B_WW = " << M_B_WW << endl;
- }
- if(fabs((M_V_regular_-M_V_reg_WW)/M_V_reg_WW)>1.e-6) {
- alarm=true;
- cout << "WZ->WW transformation error!\n";
- cout << "M_V_regular_ - M_V_reg_WW (rel) = "
- << M_V_regular_ - M_V_reg_WW << " ("
- << (M_V_regular_ - M_V_reg_WW)/M_V_reg_WW << ")\n";
- cout << "M_V_regular_ = " << M_V_regular_ << endl;
- cout << "M_V_reg_WW = " << M_V_reg_WW << endl;
- }
- if(fabs((t_u_M_R_qqb_-t_u_qqb_WW)/t_u_qqb_WW)>1.e-6) {
- alarm=true;
- cout << "WZ->WW transformation error!\n";
- cout << "t_u_M_R_qqb_ - t_u_qqb_WW (rel) = "
- << (t_u_M_R_qqb_ - t_u_qqb_WW)/GeV2 << " ("
- << (t_u_M_R_qqb_ - t_u_qqb_WW)/t_u_qqb_WW << ")\n";
- cout << "t_u_M_R_qqb_ = " << t_u_M_R_qqb_/GeV2 << endl;
- cout << "t_u_qqb_WW = " << t_u_qqb_WW /GeV2 << endl;
- }
- }
-
- // Check that the transformation from NPB 383 (1992) 3-44 WZ
- // matrix elements to ZZ matrix elements actually works, by
- // comparing them to the explicit ZZ matrix elements in
- // NPB 357 (1991) 409-438.
- if(abs(mePartonData()[2]->id())==23&&abs(mePartonData()[3]->id())==23) {
- if(fabs((M_Born_ -M_B_ZZ )/M_B_ZZ )>1.e-6) {
- alarm=true;
- cout << "WZ->ZZ transformation error!\n";
- cout << "M_Born_ - M_B_ZZ (rel) = "
- << M_Born_ - M_B_ZZ << " ("
- << (M_Born_ - M_B_ZZ)/M_B_ZZ << ")\n";
- cout << "M_Born_ = " << M_Born_ << endl;
- cout << "M_B_ZZ = " << M_B_ZZ << endl;
- }
- if(fabs((M_V_regular_-M_V_reg_ZZ)/M_V_reg_ZZ)>1.e-6) {
- alarm=true;
- cout << "WZ->ZZ transformation error!\n";
- cout << "M_V_regular_ - M_V_reg_ZZ (rel) = "
- << M_V_regular_ - M_V_reg_ZZ << " ("
- << (M_V_regular_ - M_V_reg_ZZ)/M_V_reg_ZZ << ")\n";
- cout << "M_V_regular_ = " << M_V_regular_ << endl;
- cout << "M_V_reg_ZZ = " << M_V_reg_ZZ << endl;
- }
- if(fabs((t_u_M_R_qqb_-t_u_qqb_ZZ)/t_u_qqb_ZZ)>1.e-6) {
- alarm=true;
- cout << "WZ->ZZ transformation error!\n";
- cout << "t_u_M_R_qqb_ - t_u_qqb_ZZ (rel) = "
- << (t_u_M_R_qqb_ - t_u_qqb_ZZ)/GeV2 << " ("
- << (t_u_M_R_qqb_ - t_u_qqb_ZZ)/t_u_qqb_ZZ << ")\n";
- cout << "t_u_M_R_qqb_ = " << t_u_M_R_qqb_/GeV2 << endl;
- cout << "t_u_qqb_ZZ = " << t_u_qqb_ZZ /GeV2 << endl;
- }
- }
-
- // Check the soft limit of the q + qbar matrix element.
- Energy2 absDiff_qqbs
- = t_u_M_R_qqb(S_) - prefacs*2.*CF_*M_Born_;
- double relDiff_qqbs = absDiff_qqbs / t_u_M_R_qqb(S_);
- if(fabs(relDiff_qqbs)>1.e-6) {
- alarm=true;
- cout << "\n";
- cout << "t_u_M_R_qqb(S_) " << t_u_M_R_qqb(S_) /GeV2 << endl;
- cout << "t_u_M_R_qqb(S_)-8*pi*alphaS*sHat/x*2*Cab*M_Born_ (rel):\n"
- << absDiff_qqbs / GeV2 << " (" << relDiff_qqbs << ")\n";
- }
-
- // Check the positive soft-collinearlimit of the q + qbar matrix element.
- Energy2 absDiff_qqbsp
- = t_u_M_R_qqb(SCp_) - prefacsp*2.*CF_*M_Born_;
- double relDiff_qqbsp = absDiff_qqbsp / t_u_M_R_qqb(SCp_);
- if(fabs(relDiff_qqbsp)>1.e-6) {
- alarm=true;
- cout << "\n";
- cout << "t_u_M_R_qqb(SCp_) " << t_u_M_R_qqb(SCp_)/GeV2 << endl;
- cout << "t_u_M_R_qqb(SCp_)-8*pi*alphaS*sHat/x*2*Cab*M_Born_ (rel):\n"
- << absDiff_qqbsp / GeV2 << " (" << relDiff_qqbsp << ")\n";
- }
-
- // Check the negative soft-collinearlimit of the q + qbar matrix element.
- Energy2 absDiff_qqbsm
- = t_u_M_R_qqb(SCm_) - prefacsm*2.*CF_*M_Born_;
- double relDiff_qqbsm = absDiff_qqbsm / t_u_M_R_qqb(SCm_);
- if(fabs(relDiff_qqbsm)>1.e-6) {
- alarm=true;
- cout << "\n";
- cout << "t_u_M_R_qqb(SCm_) " << t_u_M_R_qqb(SCm_)/GeV2 << endl;
- cout << "t_u_M_R_qqb(SCm_)-8*pi*alphaS*sHat/x*2*Cab*M_Born_ (rel):\n"
- << absDiff_qqbsm / GeV2 << " (" << relDiff_qqbsm << ")\n";
- }
-
- // Check the positive collinearlimit of the q + qbar matrix element.
- Energy2 absDiff_qqbp
- = t_u_M_R_qqb(Cp_) - prefacp*CF_*(1.+xp*xp)*M_Born_;
- double relDiff_qqbp = absDiff_qqbp / t_u_M_R_qqb(Cp_);
- if(fabs(relDiff_qqbp)>1.e-6) {
- alarm=true;
- cout << "\n";
- cout << "t_u_M_R_qqb(Cp_) " << t_u_M_R_qqb(Cp_) /GeV2 << endl;
- cout << "t_u_M_R_qqb(Cp_)-8*pi*alphaS*sHat/x*(1-x)*Pqq*M_Born_ (rel):\n"
- << absDiff_qqbp / GeV2 << " (" << relDiff_qqbp << ")\n";
- }
-
- // Check the negative collinearlimit of the q + qbar matrix element.
- Energy2 absDiff_qqbm
- = t_u_M_R_qqb(Cm_) - prefacm*CF_*(1.+xm*xm)*M_Born_;
- double relDiff_qqbm = absDiff_qqbm / t_u_M_R_qqb(Cm_);
- if(fabs(relDiff_qqbm)>1.e-6) {
- alarm=true;
- cout << "\n";
- cout << "t_u_M_R_qqb(Cm_) " << t_u_M_R_qqb(Cm_) /GeV2 << endl;
- cout << "t_u_M_R_qqb(Cm_)-8*pi*alphaS*sHat/x*(1-x)*Pqq*M_Born_ (rel):\n"
- << absDiff_qqbm / GeV2 << " (" << relDiff_qqbm << ")\n";
- }
-
- // Check the positive collinear limit of the g + qbar matrix element.
- Energy2 absDiff_gqbp
- = t_u_M_R_gqb(Cp_) - prefacp*(1.-xp)*TR_*(xp*xp+sqr(1.-xp))*M_Born_;
- double relDiff_gqbp = absDiff_gqbp/ t_u_M_R_gqb(Cp_);
- if(fabs(relDiff_gqbp)>1.e-6) {
- alarm=true;
- cout << "\n";
- cout << "t_u_M_R_gqb(Cp_) " << t_u_M_R_gqb(Cp_) /GeV2 << endl;
- cout << "t_u_M_R_gqb(Cp_)-8*pi*alphaS*sHat/x*(1-x)*Pgq*M_Born_ (rel):\n"
- << absDiff_gqbp / GeV2 << " (" << relDiff_gqbp << ")\n";
- }
-
- // Check the negative collinear limit of the q + g matrix element.
- Energy2 absDiff_qgm
- = t_u_M_R_qg(Cm_) - prefacm*(1.-xm)*TR_*(xm*xm+sqr(1.-xm))*M_Born_;
- double relDiff_qgm = absDiff_qgm / t_u_M_R_qg(Cm_);
- if(fabs(relDiff_qgm)>1.e-6) {
- alarm=true;
- cout << "\n";
- cout << "t_u_M_R_qg(Cm_) " << t_u_M_R_qg(Cm_) /GeV2 << endl;
- cout << "t_u_M_R_qg(Cm_)-8*pi*alphaS*sHat/x*(1-x)*Pgq*M_Born_ (rel):\n"
- << absDiff_qgm / GeV2 << " (" << relDiff_qgm << ")\n";
- }
-
- return alarm;
-}
-
-/***************************************************************************/
-// M_Born_ZZ is the Born matrix element exactly as defined in Eqs. 2.18-2.19
-// of of NPB 357(1991)409-438.
-double MEPP2VVPowheg::M_Born_ZZ(bornVVKinematics B) const {
- Energy2 s(B.sb());
- Energy2 t(B.tb());
- Energy2 u(B.ub());
- Energy2 mW2(B.k12b()); // N.B. the diboson masses are preserved in getting
- Energy2 mZ2(B.k22b()); // the 2->2 from the 2->3 kinematics.
- double cosThetaW(sqrt(1.-sin2ThetaW_));
-
- double gV2,gA2,gX,gY,gZ;
- gV2 = sqr(guL_/2.-gW_/2./cosThetaW*2./3.*sin2ThetaW_);
- gA2 = sqr(guL_/2.+gW_/2./cosThetaW*2./3.*sin2ThetaW_);
- gX = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.;
- gV2 = sqr(gdL_/2.+gW_/2./cosThetaW*1./3.*sin2ThetaW_);
- gA2 = sqr(gdL_/2.-gW_/2./cosThetaW*1./3.*sin2ThetaW_);
- gY = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.;
- gZ = gX;
- if(abs(quark_->id())%2==1&&abs(antiquark_->id())%2==1) gZ = gY;
-
- return 1./NC_*sqr(gZ*2.)*(t/u+u/t+4.*mZ2*s/t/u-mZ2*mZ2*(1./t/t+1./u/u));
-
-}
-
-/***************************************************************************/
-// M_V_regular_ZZ is the one-loop ZZ matrix element exactly as defined in
-// Eqs. B.1 & B.2 of NPB 357(1991)409-438.
-double MEPP2VVPowheg::M_V_regular_ZZ(realVVKinematics S) const {
- Energy2 s(S.bornVariables().sb());
- Energy2 t(S.bornVariables().tb());
- Energy2 u(S.bornVariables().ub());
- Energy2 mW2(S.k12r()); // N.B. the diboson masses are preserved in getting
- Energy2 mZ2(S.k22r()); // the 2->2 from the 2->3 kinematics.
- double beta(S.betaxr()); // N.B. for x=1 \beta_x=\beta in NPB 383(1992)3-44.
- double cosThetaW(sqrt(1.-sin2ThetaW_));
-
- double gV2,gA2,gX,gY,gZ;
- gV2 = sqr(guL_/2.-gW_/2./cosThetaW*2./3.*sin2ThetaW_);
- gA2 = sqr(guL_/2.+gW_/2./cosThetaW*2./3.*sin2ThetaW_);
- gX = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.;
- gV2 = sqr(gdL_/2.+gW_/2./cosThetaW*1./3.*sin2ThetaW_);
- gA2 = sqr(gdL_/2.-gW_/2./cosThetaW*1./3.*sin2ThetaW_);
- gY = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.;
- gZ = gX;
- if(abs(quark_->id())%2==1&&abs(antiquark_->id())%2==1) gZ = gY;
-
- double M_V_reg(0.);
- M_V_reg = 2.*s*sqr(gZ*2.)*4.*pi*alphaS_*CF_/NC_/sqr(4.*pi)/2.
- *( 2.*sqr(t+mZ2)/sqr(beta)/s/t/u + 4.*s/(t-mZ2)/u
- - ( 16.*t*t*t+(28.*s-68.*mZ2)*t*t+(18.*s*s-36.*mZ2*s+88.*mZ2*mZ2)*t
- + 18.*mZ2*mZ2*s-36.*mZ2*mZ2*mZ2
- )/t/t/s/u
- + ( 12.*s/(t-mZ2)/u-4.*mZ2*s/sqr(t-mZ2)/u+2.*(t+4.*s)/s/u
- - 6.*(s*s+mZ2*mZ2)/s/t/u+6.*mZ2*mZ2*(2.*mZ2-s)/t/t/s/u
- )*log(-t/mZ2)
- + ( - ( 5.*t*t*t+(8.*s-18.*mZ2)*t*t+(6.*s*s+25.*mZ2*mZ2)*t
- + 6.*mZ2*mZ2*s-12.*mZ2*mZ2*mZ2
- )/t/t/s/u
- - 12.*mZ2*sqr(t+mZ2)/sqr(sqr(beta))/s/s/t/u
- + ( 3.*t*t-26.*mZ2*t-25.*mZ2*mZ2)/sqr(beta)/s/t/u
- )*log(s/mZ2)
- + ( (-2.*t*t+8.*mZ2*t-2.*s*s-12.*mZ2*mZ2)/u + 4.*mZ2*mZ2*(2.*mZ2-s)/t/u)
- / (s*t)
- * ( 2.*sqr(log(-t/mZ2))-4.*log(-t/mZ2)*log((mZ2-t)/mZ2)-4.*ReLi2(t/mZ2))
- + ( 4.*(t*t-5.*mZ2*t+s*s+10.*mZ2*mZ2)/s/u
- + 4.*mZ2*(-s*s+2.*mZ2*s-10.*mZ2*mZ2)/s/t/u
- + 8.*mZ2*mZ2*mZ2*(2.*mZ2-s)/t/t/s/u
- )
- / (t-mZ2)
- * (pi*pi/2.+log(-t/mZ2)*log(-t/s)-1./2.*sqr(log(-t/mZ2)))
- + ( ( (2.*s-3.*mZ2)*t*t+(6.*mZ2*mZ2-8.*mZ2*s)*t+2.*s*s*s-4.*mZ2*s*s
- + 12.*mZ2*mZ2*s-3.*mZ2*mZ2*mZ2
- ) /s/t/u
- + 12.*mZ2*mZ2*sqr(t+mZ2)/sqr(sqr(beta))/s/s/t/u
- - (mZ2*t*t-30.*mZ2*mZ2*t-27.*mZ2*mZ2*mZ2)/beta/beta/s/t/u
- )
- / (beta*s)
- * (pi*pi/3.+sqr(log((1.-beta)/(1.+beta)))+4.*ReLi2(-(1.-beta)/(1.+beta)))
- + (4.*(t+4.*s-4.*mZ2)/3./s/u+4.*sqr(s-2.*mZ2)/3./s/t/u)*pi*pi
- );
-
- swap(t,u);
- M_V_reg += 2.*s*sqr(gZ*2.)*4.*pi*alphaS_*CF_/NC_/sqr(4.*pi)/2.
- *( 2.*sqr(t+mZ2)/sqr(beta)/s/t/u + 4.*s/(t-mZ2)/u
- - ( 16.*t*t*t+(28.*s-68.*mZ2)*t*t+(18.*s*s-36.*mZ2*s+88.*mZ2*mZ2)*t
- + 18.*mZ2*mZ2*s-36.*mZ2*mZ2*mZ2
- )/t/t/s/u
- + ( 12.*s/(t-mZ2)/u-4.*mZ2*s/sqr(t-mZ2)/u+2.*(t+4.*s)/s/u
- - 6.*(s*s+mZ2*mZ2)/s/t/u+6.*mZ2*mZ2*(2.*mZ2-s)/t/t/s/u
- )*log(-t/mZ2)
- + ( - ( 5.*t*t*t+(8.*s-18.*mZ2)*t*t+(6.*s*s+25.*mZ2*mZ2)*t
- + 6.*mZ2*mZ2*s-12.*mZ2*mZ2*mZ2
- )/t/t/s/u
- - 12.*mZ2*sqr(t+mZ2)/sqr(sqr(beta))/s/s/t/u
- + ( 3.*t*t-26.*mZ2*t-25.*mZ2*mZ2)/sqr(beta)/s/t/u
- )*log(s/mZ2)
- + ( (-2.*t*t+8.*mZ2*t-2.*s*s-12.*mZ2*mZ2)/u + 4.*mZ2*mZ2*(2.*mZ2-s)/t/u)
- / (s*t)
- * ( 2.*sqr(log(-t/mZ2))-4.*log(-t/mZ2)*log((mZ2-t)/mZ2)-4.*ReLi2(t/mZ2))
- + ( 4.*(t*t-5.*mZ2*t+s*s+10.*mZ2*mZ2)/s/u
- + 4.*mZ2*(-s*s+2.*mZ2*s-10.*mZ2*mZ2)/s/t/u
- + 8.*mZ2*mZ2*mZ2*(2.*mZ2-s)/t/t/s/u
- )
- / (t-mZ2)
- * (pi*pi/2.+log(-t/mZ2)*log(-t/s)-1./2.*sqr(log(-t/mZ2)))
- + ( ( (2.*s-3.*mZ2)*t*t+(6.*mZ2*mZ2-8.*mZ2*s)*t+2.*s*s*s-4.*mZ2*s*s
- + 12.*mZ2*mZ2*s-3.*mZ2*mZ2*mZ2
- ) /s/t/u
- + 12.*mZ2*mZ2*sqr(t+mZ2)/sqr(sqr(beta))/s/s/t/u
- - (mZ2*t*t-30.*mZ2*mZ2*t-27.*mZ2*mZ2*mZ2)/beta/beta/s/t/u
- )
- / (beta*s)
- * (pi*pi/3.+sqr(log((1.-beta)/(1.+beta)))+4.*ReLi2(-(1.-beta)/(1.+beta)))
- + (4.*(t+4.*s-4.*mZ2)/3./s/u+4.*sqr(s-2.*mZ2)/3./s/t/u)*pi*pi
- );
-
- return M_V_reg;
-}
-
-/***************************************************************************/
-// t_u_M_R_qqb_ZZ is the real emission q + qb -> n + g matrix element
-// exactly as defined in Eqs. C.1 of NPB 357(1991)409-438, multiplied by
-// tk * uk!
-Energy2 MEPP2VVPowheg::t_u_M_R_qqb_ZZ(realVVKinematics R) const {
- // First the Born variables:
- Energy2 s2(R.s2r());
- Energy2 mW2(R.k12r());
- Energy2 mZ2(R.k22r());
- // Then the rest:
- Energy2 s(R.sr());
- Energy2 tk(R.tkr());
- Energy2 uk(R.ukr());
- Energy2 q1(R.q1r());
- Energy2 q2(R.q2r());
- Energy2 q1h(R.q1hatr());
- Energy2 q2h(R.q2hatr());
- Energy2 w1(R.w1r());
- Energy2 w2(R.w2r());
-
- double cosThetaW(sqrt(1.-sin2ThetaW_));
-
- double gV2,gA2,gX,gY,gZ;
- gV2 = sqr(guL_/2.-gW_/2./cosThetaW*2./3.*sin2ThetaW_);
- gA2 = sqr(guL_/2.+gW_/2./cosThetaW*2./3.*sin2ThetaW_);
- gX = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.;
- gV2 = sqr(gdL_/2.+gW_/2./cosThetaW*1./3.*sin2ThetaW_);
- gA2 = sqr(gdL_/2.-gW_/2./cosThetaW*1./3.*sin2ThetaW_);
- gY = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.;
- gZ = gX;
- if(abs(quark_->id())%2==1&&abs(antiquark_->id())%2==1) gZ = gY;
-
- Energy2 t_u_qqb(0.*GeV2);
- t_u_qqb = (2.*s)*sqr(gZ*2.)*4.*pi*alphaS_*CF_/NC_/2.
- * ( - ( tk*uk*uk+2.*s*uk*uk-tk*tk*uk
- - 2.*s*tk*uk+mZ2*(tk*tk-uk*uk+2.*s*uk-2.*s*tk-2.*s*s)
- )/q1h/q1/q2h/s*tk
- + 2.*(tk*uk*uk-mZ2*uk*(s+3.*tk)+mZ2*mZ2*(2.*uk-s))/q1/q2/s
- + ( tk*uk*(uk+s)-mZ2*(uk*uk+3.*tk*uk+3.*s*uk+s*tk)
- + 2.*mZ2*mZ2*(uk+tk+2.*s)
- )/q1h/q1/q2/s*tk
- + ( tk*(uk*uk+tk*uk-s*s)+mZ2*(4.*s*uk-3.*tk*uk-tk*tk+4.*s*s)
- )/q1h/q2/s
- - ( tk*uk+s*uk-s*tk-s*s+2.*mZ2*(s-tk) ) /q1h/q1/s*tk
- + q2*(tk*uk-s*uk-2.*s*tk-2.*s*s)/q1/q2h/s
- + 2.*(tk*uk-tk*tk-s*tk-s*s+mZ2*(2.*s-uk))/q1/s
- - 2.*mZ2*(uk*uk-2.*mZ2*uk+2.*mZ2*mZ2)/q1/q1/q2/s*tk
- + (2.*s*uk+tk*tk+3.*s*tk+2*s*s)/q1h/s
- + q1*(uk+s)*(uk+tk)/q1h/q2h/s
- + (tk*uk+s*uk+3.*s*tk+2.*s*s-mZ2*(uk+tk+2.*s))/q1h/q2h/s*uk
- + (uk-tk)/2./q1h/q2h/s*(q1*(uk+s)/q2/tk-q2*(tk+s)/q1/uk)*tk*uk
- + (tk-2.*mZ2)*(uk-2.*mZ2)/q1h/q1/q2h/q2*tk*uk
- - (q1*q1+q2*q2)/q1/q2
- - 2.*mZ2*(q2-2.*mZ2)/q1/q1/s*tk
- );
-
- swap(tk ,uk );
- swap(q1 ,q2 );
- swap(q1h,q2h);
- t_u_qqb += (2.*s)*sqr(gZ*2.)*4.*pi*alphaS_*CF_/NC_/2.
- * ( - ( tk*uk*uk+2.*s*uk*uk-tk*tk*uk
- - 2.*s*tk*uk+mZ2*(tk*tk-uk*uk+2.*s*uk-2.*s*tk-2.*s*s)
- )/q1h/q1/q2h/s*tk
- + 2.*(tk*uk*uk-mZ2*uk*(s+3.*tk)+mZ2*mZ2*(2.*uk-s))/q1/q2/s
- + ( tk*uk*(uk+s)-mZ2*(uk*uk+3.*tk*uk+3.*s*uk+s*tk)
- + 2.*mZ2*mZ2*(uk+tk+2.*s)
- )/q1h/q1/q2/s*tk
- + ( tk*(uk*uk+tk*uk-s*s)+mZ2*(4.*s*uk-3.*tk*uk-tk*tk+4.*s*s)
- )/q1h/q2/s
- - ( tk*uk+s*uk-s*tk-s*s+2.*mZ2*(s-tk) ) /q1h/q1/s*tk
- + q2*(tk*uk-s*uk-2.*s*tk-2.*s*s)/q1/q2h/s
- + 2.*(tk*uk-tk*tk-s*tk-s*s+mZ2*(2.*s-uk))/q1/s
- - 2.*mZ2*(uk*uk-2.*mZ2*uk+2.*mZ2*mZ2)/q1/q1/q2/s*tk
- + (2.*s*uk+tk*tk+3.*s*tk+2*s*s)/q1h/s
- + q1*(uk+s)*(uk+tk)/q1h/q2h/s
- + (tk*uk+s*uk+3.*s*tk+2.*s*s-mZ2*(uk+tk+2.*s))/q1h/q2h/s*uk
- + (uk-tk)/2./q1h/q2h/s*(q1*(uk+s)/q2/tk-q2*(tk+s)/q1/uk)*tk*uk
- + (tk-2.*mZ2)*(uk-2.*mZ2)/q1h/q1/q2h/q2*tk*uk
- - (q1*q1+q2*q2)/q1/q2
- - 2.*mZ2*(q2-2.*mZ2)/q1/q1/s*tk
- );
- swap(tk ,uk );
- swap(q1 ,q2 );
- swap(q1h,q2h);
-
- swap(q1 ,q1h);
- swap(q2 ,q2h);
- t_u_qqb += (2.*s)*sqr(gZ*2.)*4.*pi*alphaS_*CF_/NC_/2.
- * ( - ( tk*uk*uk+2.*s*uk*uk-tk*tk*uk
- - 2.*s*tk*uk+mZ2*(tk*tk-uk*uk+2.*s*uk-2.*s*tk-2.*s*s)
- )/q1h/q1/q2h/s*tk
- + 2.*(tk*uk*uk-mZ2*uk*(s+3.*tk)+mZ2*mZ2*(2.*uk-s))/q1/q2/s
- + ( tk*uk*(uk+s)-mZ2*(uk*uk+3.*tk*uk+3.*s*uk+s*tk)
- + 2.*mZ2*mZ2*(uk+tk+2.*s)
- )/q1h/q1/q2/s*tk
- + ( tk*(uk*uk+tk*uk-s*s)+mZ2*(4.*s*uk-3.*tk*uk-tk*tk+4.*s*s)
- )/q1h/q2/s
- - ( tk*uk+s*uk-s*tk-s*s+2.*mZ2*(s-tk) ) /q1h/q1/s*tk
- + q2*(tk*uk-s*uk-2.*s*tk-2.*s*s)/q1/q2h/s
- + 2.*(tk*uk-tk*tk-s*tk-s*s+mZ2*(2.*s-uk))/q1/s
- - 2.*mZ2*(uk*uk-2.*mZ2*uk+2.*mZ2*mZ2)/q1/q1/q2/s*tk
- + (2.*s*uk+tk*tk+3.*s*tk+2*s*s)/q1h/s
- + q1*(uk+s)*(uk+tk)/q1h/q2h/s
- + (tk*uk+s*uk+3.*s*tk+2.*s*s-mZ2*(uk+tk+2.*s))/q1h/q2h/s*uk
- + (uk-tk)/2./q1h/q2h/s*(q1*(uk+s)/q2/tk-q2*(tk+s)/q1/uk)*tk*uk
- + (tk-2.*mZ2)*(uk-2.*mZ2)/q1h/q1/q2h/q2*tk*uk
- - (q1*q1+q2*q2)/q1/q2
- - 2.*mZ2*(q2-2.*mZ2)/q1/q1/s*tk
- );
- swap(q1 ,q1h);
- swap(q2 ,q2h);
-
- swap(tk ,uk );
- swap(q1 ,q2h);
- swap(q2 ,q1h);
- t_u_qqb += (2.*s)*sqr(gZ*2.)*4.*pi*alphaS_*CF_/NC_/2.
- * ( - ( tk*uk*uk+2.*s*uk*uk-tk*tk*uk
- - 2.*s*tk*uk+mZ2*(tk*tk-uk*uk+2.*s*uk-2.*s*tk-2.*s*s)
- )/q1h/q1/q2h/s*tk
- + 2.*(tk*uk*uk-mZ2*uk*(s+3.*tk)+mZ2*mZ2*(2.*uk-s))/q1/q2/s
- + ( tk*uk*(uk+s)-mZ2*(uk*uk+3.*tk*uk+3.*s*uk+s*tk)
- + 2.*mZ2*mZ2*(uk+tk+2.*s)
- )/q1h/q1/q2/s*tk
- + ( tk*(uk*uk+tk*uk-s*s)+mZ2*(4.*s*uk-3.*tk*uk-tk*tk+4.*s*s)
- )/q1h/q2/s
- - ( tk*uk+s*uk-s*tk-s*s+2.*mZ2*(s-tk) ) /q1h/q1/s*tk
- + q2*(tk*uk-s*uk-2.*s*tk-2.*s*s)/q1/q2h/s
- + 2.*(tk*uk-tk*tk-s*tk-s*s+mZ2*(2.*s-uk))/q1/s
- - 2.*mZ2*(uk*uk-2.*mZ2*uk+2.*mZ2*mZ2)/q1/q1/q2/s*tk
- + (2.*s*uk+tk*tk+3.*s*tk+2*s*s)/q1h/s
- + q1*(uk+s)*(uk+tk)/q1h/q2h/s
- + (tk*uk+s*uk+3.*s*tk+2.*s*s-mZ2*(uk+tk+2.*s))/q1h/q2h/s*uk
- + (uk-tk)/2./q1h/q2h/s*(q1*(uk+s)/q2/tk-q2*(tk+s)/q1/uk)*tk*uk
- + (tk-2.*mZ2)*(uk-2.*mZ2)/q1h/q1/q2h/q2*tk*uk
- - (q1*q1+q2*q2)/q1/q2
- - 2.*mZ2*(q2-2.*mZ2)/q1/q1/s*tk
- );
- swap(tk ,uk );
- swap(q1 ,q2h);
- swap(q2 ,q1h);
-
- return t_u_qqb;
-}
-
-/***************************************************************************/
-// M_B_WW is the Born matrix element exactly as defined in Eqs. 3.2-3.8
-// of of NPB 410(1993)280-384.
-double MEPP2VVPowheg::M_Born_WW(bornVVKinematics B) const {
- Energy2 s(B.sb());
- Energy2 t(B.tb());
- Energy2 u(B.ub());
- Energy2 mW2(B.k12b()); // N.B. the diboson masses are preserved in getting
- Energy2 mZ2(B.k22b()); // the 2->2 from the 2->3 kinematics.
-
- bool up_type = abs(quark_->id())%2==0 ? true : false;
- double Qi = up_type ? 2./3. : -1./3. ;
- double giL = up_type ? guL_/2. : gdL_/2.;
- double giR = up_type ? guR_/2. : gdR_/2.;
- double e2 = sqr(gW_)*sin2ThetaW_;
-
- double cos2ThetaW(1.-sin2ThetaW_);
-
- double ctt_i(gW_*gW_*gW_*gW_/16.);
- InvEnergy2 cts_i(gW_*gW_*e2/4./s *(Qi+2.*eZ_*giL/e2*s/(s-mW2/cos2ThetaW)));
- InvEnergy4 css_i(e2*e2/s/s*(sqr(Qi+eZ_*(giL+giR)/e2*s/(s-mW2/cos2ThetaW))
- +sqr( eZ_*(giL-giR)/e2*s/(s-mW2/cos2ThetaW)))
- );
-
- ctt_i *= 8.*Fij2_/gW_/gW_;
- cts_i *= sqrt(8.*Fij2_/gW_/gW_);
- if(quark_->id()!=-antiquark_->id()) {
- cts_i = 0./GeV2;
- css_i = 0./GeV2/GeV2;
- }
-
- if(!up_type) swap(t,u);
- double signf = up_type ? 1. : -1.;
-
- return 1./4./NC_
- * (
- ctt_i*( 16.*(u*t/mW2/mW2-1.)*(1./4.+mW2*mW2/t/t)+16.*s/mW2)
- - cts_i*( 16.*(u*t/mW2/mW2-1.)*(s/4.-mW2/2.-mW2*mW2/t)
- + 16.*s*(s/mW2-2.+2.*mW2/t)
- )
- *signf
- +
- css_i*( 8.*(u*t/mW2/mW2-1.)*(s*s/4.-s*mW2+3.*mW2*mW2)
- + 8.*s*s*(s/mW2-4.)
- )
- );
-}
-
-/***************************************************************************/
-// M_V_regular_WW is the regular part of the one-loop WW matrix element
-// exactly as defined in Eqs. C.1 - C.7 of of NPB 410(1993)280-324 ***
-// modulo a factor 1/(2s) ***, which is a flux factor that those authors
-// absorb in the matrix element.
-double MEPP2VVPowheg::M_V_regular_WW(realVVKinematics S) const {
- Energy2 s(S.bornVariables().sb());
- Energy2 t(S.bornVariables().tb());
- Energy2 u(S.bornVariables().ub());
- Energy2 mW2(S.k12r()); // N.B. the diboson masses are preserved in getting
- Energy2 mZ2(S.k22r()); // the 2->2 from the 2->3 kinematics.
- double beta(S.betaxr()); // N.B. for x=1 \beta_x=\beta in NPB 383(1992)3-44.
-
- bool up_type = abs(quark_->id())%2==0 ? true : false;
- double Qi = up_type ? 2./3. : -1./3.;
- double giL = up_type ? guL_/2. : gdL_/2.;
- double giR = up_type ? guR_/2. : gdR_/2.;
- double e2 = sqr(gW_)*sin2ThetaW_;
-
- double cos2ThetaW(1.-sin2ThetaW_);
-
- double ctt_i(gW_*gW_*gW_*gW_/16.);
- InvEnergy2 cts_i(gW_*gW_*e2/4./s *(Qi+2.*eZ_*giL/e2*s/(s-mW2/cos2ThetaW)));
- InvEnergy4 css_i(e2*e2/s/s*(sqr(Qi+eZ_*(giL+giR)/e2*s/(s-mW2/cos2ThetaW))
- +sqr( eZ_*(giL-giR)/e2*s/(s-mW2/cos2ThetaW)))
- );
-
- ctt_i *= 8.*Fij2_/gW_/gW_;
- cts_i *= sqrt(8.*Fij2_/gW_/gW_);
- if(quark_->id()!=-antiquark_->id()) {
- cts_i = 0./GeV2;
- css_i = 0./GeV2/GeV2;
- }
-
- if(!up_type) swap(t,u);
- double signf = up_type ? 1. : -1.;
-
- InvEnergy4 TildeI4 = ( 2.*sqr(log(-t/mW2))-4.*log((mW2-t)/mW2)*log(-t/mW2)
- - 4.*ReLi2(t/mW2) )/s/t;
- InvEnergy2 TildeI3t = 1./(mW2-t)
- *(sqr(log(mW2/s))/2.-sqr(log(-t/s))/2.-pi*pi/2.);
- InvEnergy2 TildeI3l = 1./s/beta*( 4.*ReLi2((beta-1.)/(beta+1.))
- + sqr(log((1.-beta)/(1.+beta)))
- + pi*pi/3.);
- double Fup1_st(0.);
- Fup1_st = 4.*(80.*t*t+73.*s*t-140.*mW2*t+72.*mW2*mW2)/t/t
- - 4.*sqr(4.*t+s)/s/beta/beta/t
- - 128.*(t+2.*s)/mW2
- + 64.*t*(t+s)/mW2/mW2
- - (32.*(t*t-3.*s*t-3.*mW2*mW2)/t/t+128.*s/(t-mW2))*log(-t/mW2)
- + ( 8.*(6.*t*t+8.*s*t-19.*mW2*t+12.*mW2*mW2)/t/t
- - (32.*t*t-128.*s*t-26.*s*s)/s/beta/beta/t
- + 6.*sqr(4.*t+s)/s/sqr(sqr(beta))/t
- )*log(s/mW2)
- + 32.*s*(2.*mW2*mW2/t-u)*TildeI4
- - 64.*(t-mW2)*(2.*mW2*mW2/t/t-u/t)*TildeI3t
- + ( (16.*t*(4.*mW2-u)-49.*s*s+72.*mW2*s-48.*mW2*mW2)/2./t
- + 2.*(8.*t*t-14.*s*t-3.*s*s)/beta/beta/t
- - 3.*sqr(4.*t+s)/2./sqr(sqr(beta))/t
- )*TildeI3l
- + 32./3.*( 2.*(t+2.*s)/mW2
- - (3.*t+2.*s-4.*mW2)/t
- - t*(t+s)/mW2/mW2
- )*pi*pi;
- Energy2 Jup1_st(0.*GeV2);
- Jup1_st = -128.*(t*t+2.*s*t+2.*s*s)/mW2
- - 16.*(t*t-21.*s*t-26.*mW2*t+34.*mW2*s+17.*mW2*mW2)/t
- + 64.*s*t*(t+s)/mW2/mW2 +32.*s*s/(t-mW2)
- + ( 16.*(t-5.*s+2.*mW2)-48.*mW2*(2.*s+mW2)/t
- + 64.*s*(2.*t+s)/(t-mW2) - 32.*s*s*t/sqr(t-mW2)
- )*log(-t/mW2)
- + ( 16.*(4.*t+s)/beta/beta
- - 16.*(3.*t-2.*s)
- + 48.*mW2*(2.*t-2.*s-mW2)/t
- )*log(s/mW2)
- + 16.*s*(t*(2.*s+u)-2.*mW2*(2.*s+mW2))*TildeI4
- + 32.*(t-mW2)*(2.*mW2*(2.*s+mW2)/t-2.*s-u)*TildeI3t
- + ( 32.*s*t-12.*s*s+32.*mW2*mW2
- - 16.*mW2*(2.*t+7.*s)-4.*s*(4.*t+s)/beta/beta
- )*TildeI3l
- + 32./3.*( 2.*(t*t+2.*s*t+2.*s*s)/mW2
- - s*t*(t+s)/mW2/mW2-2.*mW2*(2.*t-2.*s-mW2)/t-t-4.*s
- )*pi*pi;
- Energy4 Kup1_st(0.*GeV2*GeV2);
- Kup1_st = 16.*( 12.*t*t+20.*s*t-24.*mW2*t+17.*s*s-4.*mW2*s+12.*mW2*mW2
- + s*s*t*(t+s)/mW2/mW2-2.*s*(2.*t*t+3.*s*t+2.*s*s)/mW2)
- *(2.-pi*pi/3.);
-
- return pi*alphaS_*CF_/NC_/(sqr(4.*pi))
- * ( ctt_i*Fup1_st - cts_i*Jup1_st*signf + css_i*Kup1_st );
-}
-
-/***************************************************************************/
-// t_u_M_R_qqb is the real emission q + qb -> n + g matrix element
-// exactly as defined in Eqs. C.1 of NPB 383(1992)3-44, multiplied by
-// tk * uk!
-Energy2 MEPP2VVPowheg::t_u_M_R_qqb_WW(realVVKinematics R) const {
- // First the Born variables:
- Energy2 s2(R.s2r());
- Energy2 mW2(R.k12r());
- Energy2 mZ2(R.k22r());
- // Then the rest:
- Energy2 s(R.sr());
- Energy2 tk(R.tkr());
- Energy2 uk(R.ukr());
- Energy2 q1(R.q1r());
- Energy2 q2(R.q2r());
- Energy2 q1h(R.q1hatr());
- Energy2 q2h(R.q2hatr());
- Energy2 w1(R.w1r());
- Energy2 w2(R.w2r());
-
- bool up_type = abs(quark_->id())%2==0 ? true : false;
- double Qi = up_type ? 2./3. : -1./3.;
- double giL = up_type ? guL_/2. : gdL_/2.;
- double giR = up_type ? guR_/2. : gdR_/2.;
- double e2 = sqr(gW_)*sin2ThetaW_;
-
- double cos2ThetaW(1.-sin2ThetaW_);
-
- double ctt_i(gW_*gW_*gW_*gW_/16.);
- InvEnergy2 cts_i(gW_*gW_*e2/4./s2*(Qi+2.*eZ_*giL/e2*s2/(s2-mW2/cos2ThetaW)));
- InvEnergy4 css_i(e2*e2/s2/s2*(sqr(Qi+eZ_*(giL+giR)/e2*s2/(s2-mW2/cos2ThetaW))
- +sqr( eZ_*(giL-giR)/e2*s2/(s2-mW2/cos2ThetaW)))
- );
-
- ctt_i *= 8.*Fij2_/gW_/gW_;
- cts_i *= sqrt(8.*Fij2_/gW_/gW_);
- if(quark_->id()!=-antiquark_->id()) {
- cts_i = 0./GeV2;
- css_i = 0./GeV2/GeV2;
- }
-
- if(!up_type) {
- swap(q1,q1h);
- swap(q2,q2h);
- }
- double signf = up_type ? 1. : -1.;
-
- Energy2 t_u_Xup(0.*GeV2);
- Energy4 t_u_Yup(0.*GeV2*GeV2);
- Energy6 t_u_Zup(0.*GeV2*GeV2*GeV2);
-
- t_u_Xup = 32.*mW2*(tk*uk+3.*q2*uk+q2*s+q1*q2)/q1/q2/q2*tk
- + 32.*mW2*q1/q2/q2*uk
- - 64.*mW2*s/q2
- - 32.*tk*(uk-q2)/q1/q2*tk
- + 64.*mW2*mW2*mW2/q1/q1/q2*tk
- - 16.*(2.*tk-2.*s-q2)/q2*uk
- + 16.*s*(2.*s+2.*q1+q2/2.)/q2
- - 8.*(4.*tk+uk+9.*s+2.*q2+2.*q1)/mW2*tk
- - 16.*s*(2.*s+q1)/mW2
- - 64.*mW2*mW2*(tk*uk+q2*tk+q1*uk-q2*s/2.)/q1/q2/q2
- + 8.*s2*q1*(tk+s+q1)/mW2/mW2;
- swap(tk,uk);
- swap(q1,q2);
- t_u_Xup += 32.*mW2*(tk*uk+3.*q2*uk+q2*s+q1*q2)/q1/q2/q2*tk
- + 32.*mW2*q1/q2/q2*uk
- - 64.*mW2*s/q2
- - 32.*tk*(uk-q2)/q1/q2*tk
- + 64.*mW2*mW2*mW2/q1/q1/q2*tk
- - 16.*(2.*tk-2.*s-q2)/q2*uk
- + 16.*s*(2.*s+2.*q1+q2/2.)/q2
- - 8.*(4.*tk+uk+9.*s+2.*q2+2.*q1)/mW2*tk
- - 16.*s*(2.*s+q1)/mW2
- - 64.*mW2*mW2*(tk*uk+q2*tk+q1*uk-q2*s/2.)/q1/q2/q2
- + 8.*s2*q1*(tk+s+q1)/mW2/mW2;
- swap(tk,uk);
- swap(q1,q2);
-
- t_u_Yup = - 16.*tk*(uk*(uk+s+q1)+q2*(s-2.*q1))/q1/q2*tk
- - 32.*mW2*mW2*s/q2
- - 32.*mW2*mW2*mW2/q1/q2*tk
- + 16.*(2.*q2*uk+s*s+q1*s+5.*q2*s+q1*q2+2.*q2*q2)/q2*tk
- - 16.*(q2*q2+s*s-q2*s)/q1*tk
- + 16.*s*(q1*s+3./2.*q2*s+q1*q2-q1*q1)/q2
- + 16.*mW2*tk*(4.*uk+s+q1-2.*q2)/q1/q2*tk
- + 16.*mW2*(3.*s*uk+q1*uk-q1*s-3.*q2*s-q1*q1+q2*q2)/q1/q2*tk
- + 16.*mW2*s*(q2-4.*s+2.*q1)/q2
- - 8.*s2*(4.*tk+uk+9.*s+4.*q1+2.*q2)/mW2*tk
- - 16.*s2*(2.*s*s+2.*q1*s+q1*q1)/mW2
- - 32.*mW2*mW2*(tk+uk/2.+2.*s-q1)/q1/q2*tk
- + 8.*s2*s2*q1*(tk+s+q1)/mW2/mW2;
- swap(tk,uk);
- swap(q1,q2);
- t_u_Yup += - 16.*tk*(uk*(uk+s+q1)+q2*(s-2.*q1))/q1/q2*tk
- - 32.*mW2*mW2*s/q2
- - 32.*mW2*mW2*mW2/q1/q2*tk
- + 16.*(2.*q2*uk+s*s+q1*s+5.*q2*s+q1*q2+2.*q2*q2)/q2*tk
- - 16.*(q2*q2+s*s-q2*s)/q1*tk
- + 16.*s*(q1*s+3./2.*q2*s+q1*q2-q1*q1)/q2
- + 16.*mW2*tk*(4.*uk+s+q1-2.*q2)/q1/q2*tk
- + 16.*mW2*(3.*s*uk+q1*uk-q1*s-3.*q2*s-q1*q1+q2*q2)/q1/q2*tk
- + 16.*mW2*s*(q2-4.*s+2.*q1)/q2
- - 8.*s2*(4.*tk+uk+9.*s+4.*q1+2.*q2)/mW2*tk
- - 16.*s2*(2.*s*s+2.*q1*s+q1*q1)/mW2
- - 32.*mW2*mW2*(tk+uk/2.+2.*s-q1)/q1/q2*tk
- + 8.*s2*s2*q1*(tk+s+q1)/mW2/mW2;
- swap(tk,uk);
- swap(q1,q2);
-
- t_u_Zup = 8.*s2*(9.*tk+3.*uk+20.*s+10.*q1+4.*q2)*tk
- + 8.*s2*(17./2.*s*s+10.*q1*s+6.*q1*q1)
- - 4.*s2*s2*(4.*tk+uk+9.*s+6.*q1+2.*q2)/mW2*tk
- - 8.*s2*s2*(2.*s*s+3.*q1*s+2.*q1*q1)/mW2
- - 16.*mW2*(2.*tk+5.*uk+7.*s+6.*q1+6.*q2)*tk
- - 16.*mW2*s*(s+6.*q1)
- + 4.*s2*s2*s2*q1*(tk+s+q1)/mW2/mW2
- + 48.*mW2*mW2*s2;
- swap(tk,uk);
- swap(q1,q2);
- t_u_Zup += 8.*s2*(9.*tk+3.*uk+20.*s+10.*q1+4.*q2)*tk
- + 8.*s2*(17./2.*s*s+10.*q1*s+6.*q1*q1)
- - 4.*s2*s2*(4.*tk+uk+9.*s+6.*q1+2.*q2)/mW2*tk
- - 8.*s2*s2*(2.*s*s+3.*q1*s+2.*q1*q1)/mW2
- - 16.*mW2*(2.*tk+5.*uk+7.*s+6.*q1+6.*q2)*tk
- - 16.*mW2*s*(s+6.*q1)
- + 4.*s2*s2*s2*q1*(tk+s+q1)/mW2/mW2
- + 48.*mW2*mW2*s2;
- swap(tk,uk);
- swap(q1,q2);
-
- return -pi*alphaS_*CF_/NC_
- * ( ctt_i*t_u_Xup - cts_i*t_u_Yup*signf + css_i*t_u_Zup );
-
-}
-
-/***************************************************************************/
-// The game here is to get this helicity amplitude squared to return all the
-// same values as t_u_M_R_qqb above, TIMES a further factor tk*uk!
-Energy2 MEPP2VVPowheg::t_u_M_R_qqb_hel_amp(realVVKinematics R) const {
- using namespace ThePEG::Helicity;
-
-// qqb_hel_amps_.reset(ProductionMatrixElement(PDT::Spin1Half,PDT::Spin1Half,
-// PDT::Spin1,PDT::Spin1,
-// PDT::Spin1));
-
- double sum_hel_amps_sqr(0.);
-
- tcPDPtr p1data(quark_);
- tcPDPtr p2data(antiquark_);
- tcPDPtr k1data(mePartonData()[2]);
- tcPDPtr k2data(mePartonData()[3]);
- tcPDPtr kdata(getParticleData(ParticleID::g));
- if(k1data->id()==-24&&k2data->id()==24) swap(k1data,k2data);
-
- SpinorWaveFunction qSpinor(R.p1r(),p1data,incoming);
- SpinorBarWaveFunction qbSpinor(R.p2r(),p2data,incoming);
- vector<SpinorWaveFunction> q;
- vector<SpinorBarWaveFunction> qb;
- for(unsigned int ix=0;ix<2;ix++) {
- qSpinor.reset(ix);
- qbSpinor.reset(ix);
- q.push_back(qSpinor);
- qb.push_back(qbSpinor);
- }
-
- VectorWaveFunction v1Polarization(R.k1r(),k1data,outgoing);
- VectorWaveFunction v2Polarization(R.k2r(),k2data,outgoing);
- vector<VectorWaveFunction> v1;
- vector<VectorWaveFunction> v2;
- for(unsigned int ix=0;ix<3;ix++) {
- v1Polarization.reset(ix);
- v2Polarization.reset(ix);
- v1.push_back(v1Polarization);
- v2.push_back(v2Polarization);
- }
-
- VectorWaveFunction gPolarization(R.kr(),kdata,outgoing);
- vector<VectorWaveFunction> g;
- for(unsigned int ix=0;ix<3;ix+=2) {
- gPolarization.reset(ix);
- g.push_back(gPolarization);
- }
-
- AbstractFFVVertexPtr ffg = FFGvertex_;
- AbstractFFVVertexPtr ffv1 = k1data->id()==23 ? FFZvertex_ : FFWvertex_;
- AbstractFFVVertexPtr ffv2 = k2data->id()==23 ? FFZvertex_ : FFWvertex_;
-
- // Collecting information for intermediate fermions
- vector<tcPDPtr> tc;
- if(abs(k1data->id())==24&&abs(k2data->id())==24) {
- if(abs(p1data->id())%2==0)
- for(int ix=0;ix<3;++ix) tc.push_back(getParticleData(1+2*ix));
- else
- for(int ix=0;ix<3;++ix) tc.push_back(getParticleData(2+2*ix));
- }
- else if(k1data->id()==23&&k2data->id()==23) tc.push_back(p1data);
- else if(abs(k1data->id())==24&&k2data->id()==23) tc.push_back(p2data);
-
- // Loop over helicities summing the relevant diagrams
- for(unsigned int p1hel=0;p1hel<2;++p1hel) {
- for(unsigned int p2hel=0;p2hel<2;++p2hel) {
- for(unsigned int khel=0;khel<2;++khel) {
- SpinorWaveFunction p1_k = ffg->evaluate(mu_UV2(),5,p1data,q[p1hel],g[khel]);
- SpinorBarWaveFunction p2_k = ffg->evaluate(mu_UV2(),5,p2data,qb[p2hel],g[khel]);
- for(unsigned int k1hel=0;k1hel<3;++k1hel) {
- for(unsigned int k2hel=0;k2hel<3;++k2hel) {
- // If helicity is exactly conserved (massless quarks) skip if p1hel=p2hel
- // but if the production ME is required first fill it with (0.,0.).
- if((p1hel==p2hel)&&helicityConservation_) {
-// if(getMatrix) {
-// if(khel==0)
-// qqb_hel_amps_(p1hel,p2hel,k1hel,k2hel,0) = Complex(0.,0.);
-// else
-// qqb_hel_amps_(p1hel,p2hel,k1hel,k2hel,2) = Complex(0.,0.);
-// }
- continue;
- }
- vector<Complex> diagrams;
- // Get all t-channel diagram contributions
- tcPDPtr intermediate_t;
- for(unsigned int ix=0;ix<tc.size();ix++) {
- intermediate_t = (!(k1data->id()==24&&k2data->id()==-24)) ? p2data : tc[ix];
- SpinorWaveFunction p1_v1 = ffv1->evaluate(scale(),5,intermediate_t,q[p1hel],v1[k1hel]);
- SpinorBarWaveFunction p2_v2 = ffv2->evaluate(scale(),5,intermediate_t,qb[p2hel],v2[k2hel]);
- // First calculate all the off-shell fermion currents
- // Now calculate the 6 t-channel diagrams
- // q+qb->g+v1+v2, q+qb->v1+g+v2, q+qb->v1+v2+g
- if(!((k1data->id()==24&&k2data->id()==-24)&&(abs(p1data->id())%2==1))) {
- diagrams.push_back(ffv1->evaluate(scale(),p1_k,p2_v2,v1[k1hel]));
- diagrams.push_back(ffg->evaluate(mu_UV2(),p1_v1,p2_v2,g[khel]));
- diagrams.push_back(ffv2->evaluate(scale(),p1_v1,p2_k,v2[k2hel]));
- }
- intermediate_t = (!(k1data->id()==24&&k2data->id()==-24)) ? p1data : tc[ix];
- SpinorWaveFunction p1_v2 = ffv2->evaluate(scale(),5,intermediate_t,q[p1hel],v2[k2hel]);
- SpinorBarWaveFunction p2_v1 = ffv1->evaluate(scale(),5,intermediate_t,qb[p2hel],v1[k1hel]);
- // q+qb->g+v2+v1, q+qb->v2+g+v1, q+qb->v2+v1+g
- if(!((k1data->id()==24&&k2data->id()==-24)&&(abs(p1data->id())%2==0))) {
- diagrams.push_back(ffv2->evaluate(scale(),p1_k,p2_v1,v2[k2hel]));
- diagrams.push_back(ffg->evaluate(mu_UV2(),p1_v2,p2_v1,g[khel]));
- diagrams.push_back(ffv1->evaluate(scale(),p1_v2,p2_k,v1[k1hel]));
- }
- }
- // Note: choosing 3 as the second argument in WWWvertex_->evaluate()
- // sets option 3 in thepeg/Helicity/Vertex/VertexBase.cc , which
- // means the propagator does not contain a width factor (which is
- // good re. gauge invariance).
- // If W+Z / W-Z calculate the two V+jet-like s-channel diagrams
- if(abs(k1data->id())==24&&k2data->id()==23) {
- // The off-shell s-channel boson current
- VectorWaveFunction k1_k2 =
- WWWvertex_->evaluate(scale(),3,k1data->CC(),v2[k2hel],v1[k1hel]);
- // q+qb->g+v1*->g+v1+v2, q+qb->v1*+g->v1+v2+g
- diagrams.push_back(ffv1->evaluate(scale(),p1_k,qb[p2hel],k1_k2));
- diagrams.push_back(ffv1->evaluate(scale(),q[p1hel],p2_k,k1_k2));
- }
- // If W+W- calculate the four V+jet-like s-channel diagrams
- if((k1data->id()==24&&k2data->id()==-24)&&(p1data->id()==-p2data->id())) {
- // The off-shell s-channel boson current
- VectorWaveFunction k1_k2;
- // q+qb->g+Z0*->g+v1+v2,q+qb->Z0*+g->v1+v2+g,
- tcPDPtr Z0 = getParticleData(ParticleID::Z0);
- k1_k2 = WWWvertex_->evaluate(scale(),3,Z0,v2[k2hel],v1[k1hel]);
- diagrams.push_back(FFZvertex_->evaluate(scale(),p1_k,qb[p2hel],k1_k2));
- diagrams.push_back(FFZvertex_->evaluate(scale(),q[p1hel],p2_k,k1_k2));
- // q+qb->g+gamma*->g+v1+v2,q+qb->gamma*+g->v1+v2+g,
- tcPDPtr gamma = getParticleData(ParticleID::gamma);
- k1_k2 = WWWvertex_->evaluate(scale(),3,gamma,v2[k2hel],v1[k1hel]);
- diagrams.push_back(FFPvertex_->evaluate(scale(),p1_k,qb[p2hel],k1_k2));
- diagrams.push_back(FFPvertex_->evaluate(scale(),q[p1hel],p2_k,k1_k2));
- }
- // Add up all diagrams to get the total amplitude:
- Complex hel_amp(0.);
- for(unsigned int ix=0;ix<diagrams.size();ix++) hel_amp += diagrams[ix];
- // If we need to fill the production ME we do it here:
-// if(getMatrix) {
-// if(khel==0)
-// qqb_hel_amps_(p1hel,p2hel,k1hel,k2hel,0) = hel_amp;
-// else
-// qqb_hel_amps_(p1hel,p2hel,k1hel,k2hel,2) = hel_amp;
-// }
- sum_hel_amps_sqr += norm(hel_amp);
- }
- }
- }
- }
- }
-
- // Fill up the remaining bits of the production ME, corresponding
- // to longitudinal gluon polarization, with (0.,0.).
-// if(getMatrix) {
-// for(unsigned int p1hel=0;p1hel<2;++p1hel) {
-// for(unsigned int p2hel=0;p2hel<2;++p2hel) {
-// for(unsigned int k1hel=0;k1hel<3;++k1hel) {
-// for(unsigned int k2hel=0;k2hel<3;++k2hel) {
-// qqb_hel_amps_(p1hel,p2hel,k1hel,k2hel,1) = Complex(0.,0.);
-// }
-// }
-// }
-// }
-// }
-
- // Spin and colour averaging factors = 1/4 * CF * 1/3 = 1/9
- sum_hel_amps_sqr /= 9.;
-
- // Symmetry factor for identical Z bosons in the final state
- if(k1data->id()==23&&k2data->id()==23) sum_hel_amps_sqr /= 2.;
-
- return sum_hel_amps_sqr*R.tkr()*R.ukr()*UnitRemoval::InvE2;
-}
-
-/***************************************************************************/
-// The game here is to get this helicity amplitude squared to return all the
-// same values as t_u_M_R_qg above, TIMES a further factor tk*uk!
-Energy2 MEPP2VVPowheg::t_u_M_R_qg_hel_amp(realVVKinematics R) const {
- using namespace ThePEG::Helicity;
-
-// qg_hel_amps_.reset(ProductionMatrixElement(PDT::Spin1Half,PDT::Spin1,
-// PDT::Spin1,PDT::Spin1,
-// PDT::Spin1Half));
-
- double sum_hel_amps_sqr(0.);
-
- tcPDPtr p1data(quark_);
- tcPDPtr p2data(getParticleData(ParticleID::g));
- tcPDPtr k1data(mePartonData()[2]);
- tcPDPtr k2data(mePartonData()[3]);
- tcPDPtr kdata (antiquark_->CC());
- if(k1data->id()==-24&&k2data->id()==24) swap(k1data,k2data);
-
- SpinorWaveFunction qinSpinor(R.p1r(),p1data,incoming);
- SpinorBarWaveFunction qoutSpinor(R.kr(),kdata,outgoing);
- vector<SpinorWaveFunction> qin;
- vector<SpinorBarWaveFunction> qout;
- for(unsigned int ix=0;ix<2;ix++) {
- qinSpinor.reset(ix);
- qoutSpinor.reset(ix);
- qin.push_back(qinSpinor);
- qout.push_back(qoutSpinor);
- }
-
- VectorWaveFunction v1Polarization(R.k1r(),k1data,outgoing);
- VectorWaveFunction v2Polarization(R.k2r(),k2data,outgoing);
- vector<VectorWaveFunction> v1;
- vector<VectorWaveFunction> v2;
- for(unsigned int ix=0;ix<3;ix++) {
- v1Polarization.reset(ix);
- v2Polarization.reset(ix);
- v1.push_back(v1Polarization);
- v2.push_back(v2Polarization);
- }
-
- VectorWaveFunction gPolarization(R.p2r(),p2data,incoming);
- vector<VectorWaveFunction> g;
- for(unsigned int ix=0;ix<3;ix+=2) {
- gPolarization.reset(ix);
- g.push_back(gPolarization);
- }
-
- AbstractFFVVertexPtr ffg = FFGvertex_;
- AbstractFFVVertexPtr ffv1 = k1data->id()==23 ? FFZvertex_ : FFWvertex_;
- AbstractFFVVertexPtr ffv2 = k2data->id()==23 ? FFZvertex_ : FFWvertex_;
-
- // Collecting information for intermediate fermions
- vector<tcPDPtr> tc;
- if(abs(k1data->id())==24&&abs(k2data->id())==24) {
- if(abs(p1data->id())%2==0)
- for(int ix=0;ix<3;++ix) tc.push_back(getParticleData(1+2*ix));
- else
- for(int ix=0;ix<3;++ix) tc.push_back(getParticleData(2+2*ix));
- }
- else if(k1data->id()==23&&k2data->id()==23) tc.push_back(p1data);
- else if(abs(k1data->id())==24&&k2data->id()==23) tc.push_back(kdata->CC());
-
- // Loop over helicities summing the relevant diagrams
- for(unsigned int p1hel=0;p1hel<2;++p1hel) {
- for(unsigned int p2hel=0;p2hel<2;++p2hel) {
- for(unsigned int khel=0;khel<2;++khel) {
- SpinorWaveFunction p1_p2 = ffg->evaluate(mu_UV2(),5,p1data,qin[p1hel],g[p2hel]);
- SpinorBarWaveFunction p2_k = ffg->evaluate(mu_UV2(),5,kdata->CC(),qout[khel],g[p2hel]);
- for(unsigned int k1hel=0;k1hel<3;++k1hel) {
- for(unsigned int k2hel=0;k2hel<3;++k2hel) {
- // If helicity is exactly conserved (massless quarks) skip if p1hel!=khel
- // but if the production ME is required first fill it with (0.,0.).
- if((p1hel!=khel)&&helicityConservation_) {
-// if(getMatrix) {
-// if(p2hel==0)
-// qg_hel_amps_(p1hel,0,k1hel,k2hel,khel) = Complex(0.,0.);
-// else
-// qg_hel_amps_(p1hel,2,k1hel,k2hel,khel) = Complex(0.,0.);
-// }
- continue;
- }
- vector<Complex> diagrams;
- // Get all t-channel diagram contributions
- tcPDPtr intermediate_q;
- for(unsigned int ix=0;ix<tc.size();ix++) {
- intermediate_q = (!(k1data->id()==24&&k2data->id()==-24)) ? antiquark_ : tc[ix];
- SpinorWaveFunction p1_v1 = ffv1->evaluate(scale(),5,intermediate_q,qin[p1hel],v1[k1hel]);
- SpinorBarWaveFunction k_v2 = ffv2->evaluate(scale(),5,intermediate_q,qout[khel],v2[k2hel]);
- // First calculate all the off-shell fermion currents
- // Now calculate the 6 abelian diagrams
- // q+g->v1+v2+q with 2 t-channel propagators, 1 s- and 1 t-channel and 2 t-channel ones.
- if(!((k1data->id()==24&&k2data->id()==-24)&&(abs(p1data->id())%2==1))) {
- diagrams.push_back(ffv2->evaluate(scale(),p1_v1,p2_k,v2[k2hel]));
- diagrams.push_back(ffg->evaluate(mu_UV2(),p1_v1,k_v2,g[p2hel]));
- diagrams.push_back(ffv1->evaluate(scale(),p1_p2,k_v2,v1[k1hel]));
- }
- intermediate_q = (!(k1data->id()==24&&k2data->id()==-24)) ? p1data : tc[ix];
- SpinorWaveFunction p1_v2 = ffv2->evaluate(scale(),5,intermediate_q,qin[p1hel],v2[k2hel]);
- SpinorBarWaveFunction k_v1 = ffv1->evaluate(scale(),5,intermediate_q,qout[khel],v1[k1hel]);
- // q+g->v2+v1+q, with 2 t-channel propagators, 1 s- and 1 t-channel and 2 t-channel ones.
- if(!((k1data->id()==24&&k2data->id()==-24)&&(abs(p1data->id())%2==0))) {
- diagrams.push_back(ffv1->evaluate(scale(),p1_v2,p2_k,v1[k1hel]));
- diagrams.push_back(ffg->evaluate(mu_UV2(),p1_v2,k_v1,g[p2hel]));
- diagrams.push_back(ffv2->evaluate(scale(),p1_p2,k_v1,v2[k2hel]));
- }
- }
- // If W+Z / W-Z calculate the two V+jet-like s-channel diagrams
- if(abs(k1data->id())==24&&k2data->id()==23) {
- // The off-shell s-channel boson current
- VectorWaveFunction k1_k2 =
- WWWvertex_->evaluate(scale(),3,k1data->CC(),v2[k2hel],v1[k1hel]);
- // q+qb->g+v1*->g+v1+v2, q+qb->v1*+g->v1+v2+g
- diagrams.push_back(ffv1->evaluate(scale(),p1_p2,qout[khel],k1_k2));
- diagrams.push_back(ffv1->evaluate(scale(),qin[p1hel],p2_k,k1_k2));
- }
- // If W+W- calculate the four V+jet-like s-channel diagrams
- if((k1data->id()==24&&k2data->id()==-24)&&(p1data->id()==kdata->id())) {
- // The off-shell s-channel boson current
- VectorWaveFunction k1_k2;
- // q+qb->g+Z0*->g+v1+v2,q+qb->Z0*+g->v1+v2+g,
- tcPDPtr Z0 = getParticleData(ParticleID::Z0);
- k1_k2 = WWWvertex_->evaluate(scale(),3,Z0,v2[k2hel],v1[k1hel]);
- diagrams.push_back(FFZvertex_->evaluate(scale(),p1_p2,qout[khel],k1_k2));
- diagrams.push_back(FFZvertex_->evaluate(scale(),qin[p1hel],p2_k,k1_k2));
- // q+qb->g+gamma*->g+v1+v2,q+qb->gamma*+g->v1+v2+g,
- tcPDPtr gamma = getParticleData(ParticleID::gamma);
- k1_k2 = WWWvertex_->evaluate(scale(),3,gamma,v2[k2hel],v1[k1hel]);
- diagrams.push_back(FFPvertex_->evaluate(scale(),p1_p2,qout[khel],k1_k2));
- diagrams.push_back(FFPvertex_->evaluate(scale(),qin[p1hel],p2_k,k1_k2));
- }
- // Add up all diagrams to get the total amplitude:
- Complex hel_amp(0.);
- for(unsigned int ix=0;ix<diagrams.size();ix++) hel_amp += diagrams[ix];
- // If we need to fill the production ME we do it here:
-// if(getMatrix) {
-// if(p2hel==0)
-// qg_hel_amps_(p1hel,0,k1hel,k2hel,khel) = hel_amp;
-// else
-// qg_hel_amps_(p1hel,2,k1hel,k2hel,khel) = hel_amp;
-// }
- sum_hel_amps_sqr += norm(hel_amp);
- }
- }
- }
- }
- }
-
- // Fill up the remaining bits of the production ME, corresponding
- // to longitudinal gluon polarization, with (0.,0.).
-// if(getMatrix) {
-// for(unsigned int p1hel=0;p1hel<2;++p1hel) {
-// for(unsigned int k1hel=0;k1hel<3;++k1hel) {
-// for(unsigned int k2hel=0;k2hel<3;++k2hel) {
-// for(unsigned int khel=0;khel<2;++khel) {
-// qg_hel_amps_(p1hel,1,k1hel,k2hel,khel) = Complex(0.,0.);
-// }
-// }
-// }
-// }
-// }
-
- // Spin and colour averaging factors = 1/4 * TR * 1/3 = 1/24
- sum_hel_amps_sqr /= 24.;
-
- // Symmetry factor for identical Z bosons in the final state
- if(k1data->id()==23&&k2data->id()==23) sum_hel_amps_sqr /= 2.;
-
- return sum_hel_amps_sqr*R.tkr()*R.ukr()*UnitRemoval::InvE2;
-}
-
-/***************************************************************************/
-// The game here is to get this helicity amplitude squared to return all the
-// same values as t_u_M_R_gqb above, TIMES a further factor tk*uk!
-Energy2 MEPP2VVPowheg::t_u_M_R_gqb_hel_amp(realVVKinematics R) const {
- using namespace ThePEG::Helicity;
-
-// gqb_hel_amps_.reset(ProductionMatrixElement(PDT::Spin1,PDT::Spin1Half,
-// PDT::Spin1,PDT::Spin1,
-// PDT::Spin1Half));
-
- double sum_hel_amps_sqr(0.);
-
- tcPDPtr p1data(getParticleData(ParticleID::g));
- tcPDPtr p2data(antiquark_);
- tcPDPtr k1data(mePartonData()[2]);
- tcPDPtr k2data(mePartonData()[3]);
- tcPDPtr kdata (quark_->CC());
- if(k1data->id()==-24&&k2data->id()==24) swap(k1data,k2data);
-
- SpinorBarWaveFunction qbinSpinor(R.p2r(),p2data,incoming);
- SpinorWaveFunction qboutSpinor(R.kr(),kdata,outgoing);
- vector<SpinorBarWaveFunction> qbin;
- vector<SpinorWaveFunction> qbout;
- for(unsigned int ix=0;ix<2;ix++) {
- qbinSpinor.reset(ix);
- qboutSpinor.reset(ix);
- qbin.push_back(qbinSpinor);
- qbout.push_back(qboutSpinor);
- }
-
- VectorWaveFunction v1Polarization(R.k1r(),k1data,outgoing);
- VectorWaveFunction v2Polarization(R.k2r(),k2data,outgoing);
- vector<VectorWaveFunction> v1;
- vector<VectorWaveFunction> v2;
- for(unsigned int ix=0;ix<3;ix++) {
- v1Polarization.reset(ix);
- v2Polarization.reset(ix);
- v1.push_back(v1Polarization);
- v2.push_back(v2Polarization);
- }
-
- VectorWaveFunction gPolarization(R.p1r(),p1data,incoming);
- vector<VectorWaveFunction> g;
- for(unsigned int ix=0;ix<3;ix+=2) {
- gPolarization.reset(ix);
- g.push_back(gPolarization);
- }
-
- AbstractFFVVertexPtr ffg = FFGvertex_;
- AbstractFFVVertexPtr ffv1 = k1data->id()==23 ? FFZvertex_ : FFWvertex_;
- AbstractFFVVertexPtr ffv2 = k2data->id()==23 ? FFZvertex_ : FFWvertex_;
-
- // Collecting information for intermediate fermions
- vector<tcPDPtr> tc;
- if(abs(k1data->id())==24&&abs(k2data->id())==24) {
- if(abs(p2data->id())%2==0)
- for(int ix=0;ix<3;++ix) tc.push_back(getParticleData(1+2*ix));
- else
- for(int ix=0;ix<3;++ix) tc.push_back(getParticleData(2+2*ix));
- }
- else if(k1data->id()==23&&k2data->id()==23) tc.push_back(p2data);
- else if(abs(k1data->id())==24&&k2data->id()==23) tc.push_back(kdata->CC());
-
- // Loop over helicities summing the relevant diagrams
- for(unsigned int p1hel=0;p1hel<2;++p1hel) {
- for(unsigned int p2hel=0;p2hel<2;++p2hel) {
- for(unsigned int khel=0;khel<2;++khel) {
- SpinorBarWaveFunction p1_p2 = ffg->evaluate(mu_UV2(),5,p2data,qbin[p2hel],g[p1hel]);
- SpinorWaveFunction p1_k = ffg->evaluate(mu_UV2(),5,kdata->CC(),qbout[khel],g[p1hel]);
- for(unsigned int k1hel=0;k1hel<3;++k1hel) {
- for(unsigned int k2hel=0;k2hel<3;++k2hel) {
- // If helicity is exactly conserved (massless quarks) skip if p2hel!=khel
- // but if the production ME is required first fill it with (0.,0.).
- if((p2hel!=khel)&&helicityConservation_) {
-// if(getMatrix) {
-// if(p1hel==0)
-// gqb_hel_amps_(0,p2hel,k1hel,k2hel,khel) = Complex(0.,0.);
-// else
-// gqb_hel_amps_(2,p2hel,k1hel,k2hel,khel) = Complex(0.,0.);
-// }
- continue;
- }
- vector<Complex> diagrams;
- // Get all t-channel diagram contributions
- tcPDPtr intermediate_q;
- for(unsigned int ix=0;ix<tc.size();ix++) {
- intermediate_q = (!(k1data->id()==24&&k2data->id()==-24)) ? quark_ : tc[ix];
- SpinorBarWaveFunction p2_v1 = ffv1->evaluate(scale(),5,intermediate_q,qbin[p2hel],v1[k1hel]);
- SpinorWaveFunction k_v2 = ffv2->evaluate(scale(),5,intermediate_q,qbout[khel],v2[k2hel]);
- // First calculate all the off-shell fermion currents
- // Now calculate the 6 abelian diagrams q+g->v1+v2+q
- // with 2 t-channel propagators, 1 s- and 1 t-channel
- // and 2 t-channel ones.
- if(!((k1data->id()==24&&k2data->id()==-24)&&(abs(p2data->id())%2==0))) {
- diagrams.push_back(ffv2->evaluate(scale(),p1_k,p2_v1,v2[k2hel]));
- diagrams.push_back(ffg->evaluate(mu_UV2(),k_v2,p2_v1,g[p1hel]));
- diagrams.push_back(ffv1->evaluate(scale(),k_v2,p1_p2,v1[k1hel]));
- }
- intermediate_q = (!(k1data->id()==24&&k2data->id()==-24)) ? p2data : tc[ix];
- SpinorBarWaveFunction p2_v2 = ffv2->evaluate(scale(),5,intermediate_q,qbin[p2hel],v2[k2hel]);
- SpinorWaveFunction k_v1 = ffv1->evaluate(scale(),5,intermediate_q,qbout[khel],v1[k1hel]);
- // q+g->v2+v1+q, with 2 t-channel propagators, 1 s- and 1 t-channel and 2 t-channel ones.
- if(!((k1data->id()==24&&k2data->id()==-24)&&(abs(p2data->id())%2==1))) {
- diagrams.push_back(ffv1->evaluate(scale(),p1_k,p2_v2,v1[k1hel]));
- diagrams.push_back(ffg->evaluate(mu_UV2(),k_v1,p2_v2,g[p1hel]));
- diagrams.push_back(ffv2->evaluate(scale(),k_v1,p1_p2,v2[k2hel]));
- }
- }
- // If W+Z / W-Z calculate the two V+jet-like s-channel diagrams
- if(abs(k1data->id())==24&&k2data->id()==23) {
- // The off-shell s-channel boson current
- VectorWaveFunction k1_k2 =
- WWWvertex_->evaluate(scale(),3,k1data->CC(),v2[k2hel],v1[k1hel]);
- // q+qb->g+v1*->g+v1+v2, q+qb->v1*+g->v1+v2+g
- diagrams.push_back(ffv1->evaluate(scale(),qbout[khel],p1_p2,k1_k2));
- diagrams.push_back(ffv1->evaluate(scale(),p1_k,qbin[p2hel],k1_k2));
- }
- // If W+W- calculate the four V+jet-like s-channel diagrams
- if((k1data->id()==24&&k2data->id()==-24)&&(p2data->id()==kdata->id())) {
- // The off-shell s-channel boson current
- VectorWaveFunction k1_k2;
- // q+qb->g+Z0*->g+v1+v2,q+qb->Z0*+g->v1+v2+g,
- tcPDPtr Z0 = getParticleData(ParticleID::Z0);
- k1_k2 = WWWvertex_->evaluate(scale(),3,Z0,v2[k2hel],v1[k1hel]);
- diagrams.push_back(FFZvertex_->evaluate(scale(),qbout[khel],p1_p2,k1_k2));
- diagrams.push_back(FFZvertex_->evaluate(scale(),p1_k,qbin[p2hel],k1_k2));
- // q+qb->g+gamma*->g+v1+v2,q+qb->gamma*+g->v1+v2+g,
- tcPDPtr gamma = getParticleData(ParticleID::gamma);
- k1_k2 = WWWvertex_->evaluate(scale(),3,gamma,v2[k2hel],v1[k1hel]);
- diagrams.push_back(FFPvertex_->evaluate(scale(),qbout[khel],p1_p2,k1_k2));
- diagrams.push_back(FFPvertex_->evaluate(scale(),p1_k,qbin[p2hel],k1_k2));
- }
- // Add up all diagrams to get the total amplitude:
- Complex hel_amp(0.);
- for(unsigned int ix=0;ix<diagrams.size();ix++) hel_amp += diagrams[ix];
- // If we need to fill the production ME we do it here:
-// if(getMatrix) {
-// if(p1hel==0)
-// gqb_hel_amps_(0,p2hel,k1hel,k2hel,khel) = hel_amp;
-// else
-// gqb_hel_amps_(2,p2hel,k1hel,k2hel,khel) = hel_amp;
-// }
- sum_hel_amps_sqr += norm(hel_amp);
- }
- }
- }
- }
- }
-
- // Fill up the remaining bits of the production ME, corresponding
- // to longitudinal gluon polarization, with (0.,0.).
-// if(getMatrix) {
-// for(unsigned int p2hel=0;p2hel<2;++p2hel) {
-// for(unsigned int k1hel=0;k1hel<3;++k1hel) {
-// for(unsigned int k2hel=0;k2hel<3;++k2hel) {
-// for(unsigned int khel=0;khel<2;++khel) {
-// gqb_hel_amps_(1,p2hel,k1hel,k2hel,khel) = Complex(0.,0.);
-// }
-// }
-// }
-// }
-// }
-
- // Spin and colour averaging factors = 1/4 * TR * 1/3 = 1/24
- sum_hel_amps_sqr /= 24.;
-
- // Symmetry factor for identical Z bosons in the final state
- if(k1data->id()==23&&k2data->id()==23) sum_hel_amps_sqr /= 2.;
-
- return sum_hel_amps_sqr*R.tkr()*R.ukr()*UnitRemoval::InvE2;
-}
-
-double MEPP2VVPowheg::lo_me() const {
- using namespace ThePEG::Helicity;
-
- double sum_hel_amps_sqr(0.);
-
- tcPDPtr p1data(quark_);
- tcPDPtr p2data(antiquark_);
- tcPDPtr k1data(mePartonData()[2]);
- tcPDPtr k2data(mePartonData()[3]);
- if(k1data->id()==-24&&k2data->id()==24) swap(k1data,k2data); // Should never actually occur.
-
- SpinorWaveFunction qSpinor(B_.p1b(),p1data,incoming);
- SpinorBarWaveFunction qbSpinor(B_.p2b(),p2data,incoming);
- vector<SpinorWaveFunction> q;
- vector<SpinorBarWaveFunction> qb;
- for(unsigned int ix=0;ix<2;ix++) {
- qSpinor.reset(ix);
- qbSpinor.reset(ix);
- q.push_back(qSpinor);
- qb.push_back(qbSpinor);
- }
-
- VectorWaveFunction v1Polarization(B_.k1b(),k1data,outgoing);
- VectorWaveFunction v2Polarization(B_.k2b(),k2data,outgoing);
- vector<VectorWaveFunction> v1;
- vector<VectorWaveFunction> v2;
- for(unsigned int ix=0;ix<3;ix++) {
- v1Polarization.reset(ix);
- v2Polarization.reset(ix);
- v1.push_back(v1Polarization);
- v2.push_back(v2Polarization);
- }
-
- AbstractFFVVertexPtr ffv1 = k1data->id()==23 ? FFZvertex_ : FFWvertex_;
- AbstractFFVVertexPtr ffv2 = k2data->id()==23 ? FFZvertex_ : FFWvertex_;
-
- // Collecting information for intermediate fermions
- vector<tcPDPtr> tc;
- if(abs(k1data->id())==24&&abs(k2data->id())==24) {
- if(abs(p1data->id())%2==0)
- for(int ix=0;ix<3;++ix) tc.push_back(getParticleData(1+2*ix));
- else
- for(int ix=0;ix<3;++ix) tc.push_back(getParticleData(2+2*ix));
- }
- else if(k1data->id()==23&&k2data->id()==23) tc.push_back(p1data);
- else if(abs(k1data->id())==24&&k2data->id()==23) tc.push_back(p2data);
-
- // Loop over helicities summing the relevant diagrams
- for(unsigned int p1hel=0;p1hel<2;++p1hel) {
- for(unsigned int p2hel=0;p2hel<2;++p2hel) {
- if((p1hel==p2hel)&&helicityConservation_) continue;
- for(unsigned int k1hel=0;k1hel<3;++k1hel) {
- for(unsigned int k2hel=0;k2hel<3;++k2hel) {
- vector<Complex> diagrams;
- // Get all t-channel diagram contributions
- tcPDPtr intermediate_t;
- for(unsigned int ix=0;ix<tc.size();ix++) {
- intermediate_t = (!(k1data->id()==24&&k2data->id()==-24)) ? p2data : tc[ix];
- SpinorWaveFunction p1_v1 = ffv1->evaluate(scale(),5,intermediate_t,q[p1hel],v1[k1hel]);
- // First calculate all the off-shell fermion currents
- // Now calculate the 6 t-channel diagrams
- // q+qb->v1+v2
- if(!((k1data->id()==24&&k2data->id()==-24)&&(abs(p1data->id())%2==1)))
- diagrams.push_back(ffv2->evaluate(scale(),p1_v1,qb[p2hel],v2[k2hel]));
- intermediate_t = (!(k1data->id()==24&&k2data->id()==-24)) ? p1data : tc[ix];
- SpinorWaveFunction p1_v2 = ffv2->evaluate(scale(),5,intermediate_t,q[p1hel],v2[k2hel]);
- // q+qb->v2+v1
- if(!((k1data->id()==24&&k2data->id()==-24)&&(abs(p1data->id())%2==0)))
- diagrams.push_back(ffv1->evaluate(scale(),p1_v2,qb[p2hel],v1[k1hel]));
- }
- // If W+Z / W-Z calculate the two V+jet-like s-channel diagrams
- if(abs(k1data->id())==24&&k2data->id()==23) {
- // The off-shell s-channel boson current
- VectorWaveFunction k1_k2 =
- WWWvertex_->evaluate(scale(),3,k1data->CC(),v2[k2hel],v1[k1hel]);
- // q+qb->v1*->v1+v2
- diagrams.push_back(ffv1->evaluate(scale(),q[p1hel],qb[p2hel],k1_k2));
- }
- // If W+W- calculate the four V+jet-like s-channel diagrams
- if((k1data->id()==24&&k2data->id()==-24)&&(p1data->id()==-p2data->id())) {
- // The off-shell s-channel boson current
- VectorWaveFunction k1_k2;
- // q+qb->Z0*->v1+v2
- tcPDPtr Z0 = getParticleData(ParticleID::Z0);
- k1_k2 = WWWvertex_->evaluate(scale(),3,Z0,v2[k2hel],v1[k1hel]);
- diagrams.push_back(FFZvertex_->evaluate(scale(),q[p1hel],qb[p2hel],k1_k2));
- // q+qb->gamma*->v1+v2
- tcPDPtr gamma = getParticleData(ParticleID::gamma);
- k1_k2 = WWWvertex_->evaluate(scale(),3,gamma,v2[k2hel],v1[k1hel]);
- diagrams.push_back(FFPvertex_->evaluate(scale(),q[p1hel],qb[p2hel],k1_k2));
- }
- // Add up all diagrams to get the total amplitude:
- Complex hel_amp(0.);
- for(unsigned int ix=0;ix<diagrams.size();ix++) hel_amp += diagrams[ix];
- // If we need to fill the production ME we do it here:
-// if(getMatrix) lo_hel_amps_(p1hel,p2hel,k1hel,k2hel) = hel_amp;
- sum_hel_amps_sqr += norm(hel_amp);
- }
- }
- }
- }
-
- // Spin and colour averaging factors = 1/4 * 1/3 = 1/12
- sum_hel_amps_sqr /= 12.;
-
- // Symmetry factor for identical Z bosons in the final state
- if(k1data->id()==23&&k2data->id()==23) sum_hel_amps_sqr /= 2.;
-
- return sum_hel_amps_sqr;
-}
-
-// here we define LO ME for s-channel only, i.e. to calculate |A^{0}_{S}|^2
-double MEPP2VVPowheg::lo_s_me() const {
- using namespace ThePEG::Helicity;
-
- double sum_hel_amps_only_s_sqr(0.);
-
- tcPDPtr p1data(quark_);
- tcPDPtr p2data(antiquark_);
- tcPDPtr k1data(mePartonData()[2]);
- tcPDPtr k2data(mePartonData()[3]);
- if(k1data->id()==-24&&k2data->id()==24) swap(k1data,k2data); // Should never actually occur.
-
- SpinorWaveFunction qSpinor(B_.p1b(),p1data,incoming);
- SpinorBarWaveFunction qbSpinor(B_.p2b(),p2data,incoming);
- vector<SpinorWaveFunction> q;
- vector<SpinorBarWaveFunction> qb;
- for(unsigned int ix=0;ix<2;ix++) {
- qSpinor.reset(ix);
- qbSpinor.reset(ix);
- q.push_back(qSpinor);
- qb.push_back(qbSpinor);
- }
-
- VectorWaveFunction v1Polarization(B_.k1b(),k1data,outgoing);
- VectorWaveFunction v2Polarization(B_.k2b(),k2data,outgoing);
- vector<VectorWaveFunction> v1;
- vector<VectorWaveFunction> v2;
- for(unsigned int ix=0;ix<3;ix++) {
- v1Polarization.reset(ix);
- v2Polarization.reset(ix);
- v1.push_back(v1Polarization);
- v2.push_back(v2Polarization);
- }
-
- AbstractFFVVertexPtr ffv1 = k1data->id()==23 ? FFZvertex_ : FFWvertex_;
- AbstractFFVVertexPtr ffv2 = k2data->id()==23 ? FFZvertex_ : FFWvertex_;
-
- // Collecting information for intermediate fermions
- vector<tcPDPtr> tc;
- if(abs(k1data->id())==24&&abs(k2data->id())==24) {
- if(abs(p1data->id())%2==0)
- for(int ix=0;ix<3;++ix) tc.push_back(getParticleData(1+2*ix));
- else
- for(int ix=0;ix<3;++ix) tc.push_back(getParticleData(2+2*ix));
- }
- else if(k1data->id()==23&&k2data->id()==23) tc.push_back(p1data);
- else if(abs(k1data->id())==24&&k2data->id()==23) tc.push_back(p2data);
-
- // Loop over helicities summing the relevant diagrams
- for(unsigned int p1hel=0;p1hel<2;++p1hel) {
- for(unsigned int p2hel=0;p2hel<2;++p2hel) {
- if((p1hel==p2hel)&&helicityConservation_) continue;
- for(unsigned int k1hel=0;k1hel<3;++k1hel) {
- for(unsigned int k2hel=0;k2hel<3;++k2hel) {
- vector<Complex> diagrams;
- // If W+Z / W-Z calculate the two V+jet-like s-channel diagrams
- if(abs(k1data->id())==24&&k2data->id()==23) {
- // The off-shell s-channel boson current
- VectorWaveFunction k1_k2 =
- WWWvertex_->evaluate(scale(),3,k1data->CC(),v2[k2hel],v1[k1hel]);
- // q+qb->v1*->v1+v2
- diagrams.push_back(ffv1->evaluate(scale(),q[p1hel],qb[p2hel],k1_k2));
- }
- // If W+W- calculate the four V+jet-like s-channel diagrams
- if((k1data->id()==24&&k2data->id()==-24)&&(p1data->id()==-p2data->id())) {
- // The off-shell s-channel boson current
- VectorWaveFunction k1_k2;
- // q+qb->Z0*->v1+v2
- tcPDPtr Z0 = getParticleData(ParticleID::Z0);
- k1_k2 = WWWvertex_->evaluate(scale(),3,Z0,v2[k2hel],v1[k1hel]);
- diagrams.push_back(FFZvertex_->evaluate(scale(),q[p1hel],qb[p2hel],k1_k2));
- // q+qb->gamma*->v1+v2
- tcPDPtr gamma = getParticleData(ParticleID::gamma);
- k1_k2 = WWWvertex_->evaluate(scale(),3,gamma,v2[k2hel],v1[k1hel]);
- diagrams.push_back(FFPvertex_->evaluate(scale(),q[p1hel],qb[p2hel],k1_k2));
- }
- // Add up all diagrams to get the total amplitude:
- Complex hel_amp_s(0.);
- for(unsigned int ix=0;ix<diagrams.size();ix++) hel_amp_s += diagrams[ix];
- // If we need to fill the production ME we do it here:
-// if(getMatrix) lo_hel_amps_(p1hel,p2hel,k1hel,k2hel) = hel_amp_s;
- sum_hel_amps_only_s_sqr += norm(hel_amp_s);
- }
- }
- }
- }
-
- // Spin and colour averaging factors = 1/4 * 1/3 = 1/12
- sum_hel_amps_only_s_sqr /= 12.;
-
- // Symmetry factor for identical Z bosons in the final state
- if(k1data->id()==23&&k2data->id()==23) sum_hel_amps_only_s_sqr /= 2.;
-
- return sum_hel_amps_only_s_sqr;
-}
diff --git a/Models/Susy/RPV/RPV.cc b/Models/Susy/RPV/RPV.cc
--- a/Models/Susy/RPV/RPV.cc
+++ b/Models/Susy/RPV/RPV.cc
@@ -1,733 +1,733 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the RPV class.
//
#include "RPV.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace Herwig;
void RPV::persistentOutput(PersistentOStream & os ) const {
os << lambdaLLE_ << lambdaLQD_ << lambdaUDD_ << ounit(vnu_,GeV)
<< upSquarkMix_ << downSquarkMix_ << triLinearOnly_
<< LLEVertex_ << LQDVertex_ << UDDVertex_
<< ounit(epsilon_,GeV) << ounit(epsB_,GeV);
}
void RPV::persistentInput(PersistentIStream & is, int) {
is >> lambdaLLE_ >> lambdaLQD_ >> lambdaUDD_ >> iunit(vnu_,GeV)
>> upSquarkMix_ >> downSquarkMix_ >> triLinearOnly_
>> LLEVertex_ >> LQDVertex_ >> UDDVertex_
>> iunit(epsilon_,GeV) >> iunit(epsB_,GeV);
}
// Static variable needed for the type description system in ThePEG.
DescribeClass<RPV,MSSM>
describeHerwigRPV("Herwig::RPV", "HwSusy.so HwRPV.so");
void RPV::Init() {
static ClassDocumentation<RPV> documentation
("The RPV class is the base class for the implementation of the"
" R-parity violating MSSM.");
static Reference<RPV,AbstractFFSVertex> interfaceLLEVertex
("Vertex/LLE",
"The vertex for the trillinear LLE interaction",
&RPV::LLEVertex_, false, false, true, false, false);
static Reference<RPV,AbstractFFSVertex> interfaceLQDVertex
("Vertex/LQD",
"The vertex for the trillinear LQD interaction",
&RPV::LQDVertex_, false, false, true, false, false);
static Reference<RPV,AbstractFFSVertex> interfaceUDDVertex
("Vertex/UDD",
"The vertex for the trillinear UDD interaction",
&RPV::UDDVertex_, false, false, true, false, false);
static Switch<RPV,bool> interfaceTriLinearOnly
("TriLinearOnly",
"Only include trilinears and take rest of model to be MSSM",
&RPV::triLinearOnly_, false, false, false);
static SwitchOption interfaceTriLinearOnlyYes
(interfaceTriLinearOnly,
"Yes",
"Trilinears + MSSM",
true);
static SwitchOption interfaceTriLinearOnlyNo
(interfaceTriLinearOnly,
"No",
"All RPV couplings and mixings",
false);
}
void RPV::extractParameters(bool checkmodel) {
MSSM::extractParameters(false);
if(checkmodel) {
map<string,ParamMap>::const_iterator pit;
pit = parameters().find("modsel");
if(pit == parameters().end()) return;
ParamMap::const_iterator it;
// nmssm or mssm
it = pit->second.find(3);
int inmssm = (it != pit->second.end()) ? int(it->second) : 0;
if(inmssm != 0)
throw Exception() << "R-parity violating MSSM model"
<< " used but NMSSM read in." << Exception::runerror;
// RPV
it = pit->second.find(4);
int irpv = (it != pit->second.end()) ? int(it->second) : 0;
if(irpv != 1) throw Exception() << "RPV model used but no RPV in input file"
<< Exception::runerror;
// CPV
it = pit->second.find(5);
int icpv = (it != pit->second.end()) ? int(it->second) : 0;
if(icpv != 0) throw Exception() << "RPV model does not support CPV"
<< Exception::runerror;
// flavour violation
it = pit->second.find(6);
int ifv = (it != pit->second.end()) ? int(it->second) : 0;
if(ifv != 0) throw Exception() << "RPV model does not support "
<< "flavour violation"
<< Exception::runerror;
}
// get the RPV parameters
// lambda
map<string,ParamMap>::const_iterator pit;
pit=parameters().find("rvlamlle");
if( pit != parameters().end() ) {
for(ParamMap::const_iterator it = pit->second.begin();
it!=pit->second.end();++it) {
if(it->first==-1) continue;
int i = it->first/100-1;
int k = it->first%10-1;
int j = (it->first%100)/10-1;
lambdaLLE_[i][j][k] = it->second;
}
}
// lambda'
pit=parameters().find("rvlamlqd");
if( pit != parameters().end() ) {
for(ParamMap::const_iterator it = pit->second.begin();
it!=pit->second.end();++it) {
if(it->first==-1) continue;
int i = it->first/100-1;
int k = it->first%10-1;
int j = (it->first%100)/10-1;
lambdaLQD_[i][j][k] = it->second;
}
}
// lambda''
pit=parameters().find("rvlamudd");
if( pit != parameters().end() ) {
for(ParamMap::const_iterator it = pit->second.begin();
it!=pit->second.end();++it) {
if(it->first==-1) continue;
int i = it->first/100-1;
int k = it->first%10-1;
int j = (it->first%100)/10-1;
lambdaUDD_[i][j][k] = it->second;
}
}
// sneutrino vevs
pit=parameters().find("rvsnvev");
vnu_.resize(3);
if( pit != parameters().end() ) {
for(ParamMap::const_iterator it = pit->second.begin();
it!=pit->second.end();++it) {
if(it->first>0) {
assert(it->first>=1&&it->first<=3);
vnu_[it->first-1] = it->second*GeV;
}
}
}
// bilinears
pit=parameters().find("rvkappa");
epsilon_.resize(3);
if( pit != parameters().end() ) {
for(ParamMap::const_iterator it = pit->second.begin();
it!=pit->second.end();++it) {
if(it->first>0) {
assert(it->first>=1&&it->first<=3);
epsilon_[it->first-1] = it->second*GeV;
}
}
}
// blinear soft terms
pit=parameters().find("rvd");
epsB_.resize(3);
if( pit != parameters().end() ) {
for(ParamMap::const_iterator it = pit->second.begin();
it!=pit->second.end();++it) {
if(it->first>0) {
assert(it->first>=1&&it->first<=3);
epsB_[it->first-1] = it->second*GeV;
}
}
}
}
void RPV::createMixingMatrices() {
map<string,pair<MatrixSize, MixingVector> >::const_iterator it;
for(it=mixings().begin();it!=mixings().end();++it) {
string name=it->first;
// pseudo-scalar higgs mixing
if (name == "rvamix") {
MixingMatrixPtr temp;
createMixingMatrix(temp,name,it->second.second,it->second.first);
CPoddHiggsMix(temp);
}
else if (name == "rvlmix") {
MixingMatrixPtr temp;
createMixingMatrix(temp,name,it->second.second,it->second.first);
ChargedHiggsMix(temp);
}
else if (name == "dsqmix" ) {
createMixingMatrix(downSquarkMix_,name,it->second.second,it->second.first);
}
else if (name == "usqmix" ) {
createMixingMatrix(upSquarkMix_,name,it->second.second,it->second.first);
}
}
// base class for neutralinos and charginos
MSSM::createMixingMatrices();
// now adjust the mixing matrices to have our structure
// first bloodly SPHENO as it doesn't obey the SLHA
map<string,StringMap>::const_iterator sit = info().find("spinfo");
string program;
if(sit!=info().end()) {
StringMap::const_iterator pit = sit->second.find(1);
if(pit!=sit->second.end()) program = pit->second;
}
if(program=="SPheno") {
map<string,ParamMap>::const_iterator fit=parameters().find("mass");
if(fit==parameters().end())
throw Exception() << "BLOCK MASS not found in input file"
<< " can't set masses of SUSY particles"
<< Exception::runerror;
// adjust the charged scalars
map<double,long> massMap;
massMap[findValue(fit, 37,"mass", "37")] = 37;
massMap[findValue(fit,1000011,"mass","1000011")] = 1000011;
massMap[findValue(fit,1000013,"mass","1000013")] = 1000013;
massMap[findValue(fit,1000015,"mass","1000015")] = 1000015;
massMap[findValue(fit,2000011,"mass","2000011")] = 2000011;
massMap[findValue(fit,2000013,"mass","2000013")] = 2000013;
massMap[findValue(fit,2000015,"mass","2000015")] = 2000015;
massMap[getParticleData(24)->mass()/GeV ] = 24;
vector<int> move;
for(map<double,long>::iterator mit=massMap.begin();mit!=massMap.end();++mit) {
if (mit->second== 37) move.push_back(0);
else if(mit->second==1000011) move.push_back(1);
else if(mit->second==1000013) move.push_back(2);
else if(mit->second==1000015) move.push_back(3);
else if(mit->second==2000011) move.push_back(4);
else if(mit->second==2000013) move.push_back(5);
else if(mit->second==2000015) move.push_back(6);
else if(mit->second== 24) move.push_back(7);
}
CMatrix oldMat = ChargedHiggsMix()->getMatrix();
CMatrix newMat(8,vector<Complex>(8,0.));
for(unsigned int ix=0;ix<8;++ix) {
for(unsigned int iy=0;iy<8;++iy)
newMat[move[ix]][iy] = oldMat[ix][iy];
}
ChargedHiggsMix(new_ptr(MixingMatrix(newMat,ChargedHiggsMix()->getIds())));
// adjust the pseudoscalars
massMap.clear();
massMap[findValue(fit, 36,"mass", "36")] = 36;
// extract the pseudoscalar masses and change the ids for the pseudoscalars
// to those from the SLHA if needed
if(fit->second.find(2000012)!=fit->second.end()) {
massMap[findValue(fit,2000012,"mass","2000012")] = 1000017;
idMap().insert(make_pair(2000012,1000017));
}
else {
massMap[findValue(fit,1000017,"mass","1000017")] = 1000017;
}
if(fit->second.find(2000014)!=fit->second.end()) {
massMap[findValue(fit,2000014,"mass","2000014")] = 1000018;
idMap().insert(make_pair(2000014,1000018));
}
else {
massMap[findValue(fit,1000018,"mass","1000018")] = 1000018;
}
if(fit->second.find(2000016)!=fit->second.end()) {
massMap[findValue(fit,2000016,"mass","2000016")] = 1000019;
idMap().insert(make_pair(2000016,1000019));
}
else {
massMap[findValue(fit,1000019,"mass","1000019")] = 1000019;
}
move.clear(); move.push_back(4);
for(map<double,long>::iterator mit=massMap.begin();mit!=massMap.end();++mit) {
if (mit->second== 36) move.push_back(0);
else if(mit->second==1000017) move.push_back(1);
else if(mit->second==1000018) move.push_back(2);
else if(mit->second==1000019) move.push_back(3);
}
oldMat = CPoddHiggsMix()->getMatrix();
newMat = CMatrix(5,vector<Complex>(5,0.));
for(unsigned int ix=0;ix<5;++ix) {
for(unsigned int iy=0;iy<5;++iy)
newMat[move[ix]][iy] = oldMat[ix][iy];
}
CPoddHiggsMix(new_ptr(MixingMatrix(newMat,CPoddHiggsMix()->getIds())));
// adjust the neutral scalars
massMap.clear();
massMap[findValue(fit, 25,"mass", "25")] = 25;
massMap[findValue(fit, 35,"mass", "35")] = 35;
massMap[findValue(fit,1000012,"mass","1000012")] = 1000012;
massMap[findValue(fit,1000014,"mass","1000014")] = 1000014;
massMap[findValue(fit,1000016,"mass","1000016")] = 1000016;
move.clear();
for(map<double,long>::iterator mit=massMap.begin();mit!=massMap.end();++mit) {
if (mit->second== 25) move.push_back(0);
else if(mit->second== 35) move.push_back(1);
else if(mit->second==1000012) move.push_back(2);
else if(mit->second==1000014) move.push_back(3);
else if(mit->second==1000016) move.push_back(4);
}
oldMat = CPevenHiggsMix()->getMatrix();
newMat = CMatrix(5,vector<Complex>(5,0.));
for(unsigned int ix=0;ix<5;++ix) {
for(unsigned int iy=0;iy<5;++iy)
newMat[move[ix]][iy] = oldMat[ix][iy];
}
CPevenHiggsMix(new_ptr(MixingMatrix(newMat,CPevenHiggsMix()->getIds())));
// neutralino mixing
move.resize(7);
move[0] = 3; move[1] = 4; move[2] = 5; move[3] = 6;
move[4] = 0; move[5] = 1; move[6] = 2;
oldMat = neutralinoMix()->getMatrix();
newMat = CMatrix(7,vector<Complex>(7,0.));
for(unsigned int ix=0;ix<7;++ix) {
for(unsigned int iy=0;iy<7;++iy)
newMat[ix][move[iy]] = oldMat[ix][iy];
}
neutralinoMix(new_ptr(MixingMatrix(newMat,neutralinoMix()->getIds())));
// chargino mixing
move.resize(5);
move[0] = 3; move[1] = 4;
move[2] = 0; move[3] = 1; move[4] = 2;
oldMat = charginoUMix()->getMatrix();
newMat = CMatrix(5,vector<Complex>(5,0.));
for(unsigned int ix=0;ix<5;++ix) {
for(unsigned int iy=0;iy<5;++iy)
newMat[ix][move[iy]] = oldMat[ix][iy];
}
charginoUMix(new_ptr(MixingMatrix(newMat,charginoUMix()->getIds())));
oldMat = charginoVMix()->getMatrix();
newMat = CMatrix(5,vector<Complex>(5,0.));
for(unsigned int ix=0;ix<5;++ix) {
for(unsigned int iy=0;iy<5;++iy)
newMat[ix][move[iy]] = oldMat[ix][iy];
}
charginoVMix(new_ptr(MixingMatrix(newMat,charginoVMix()->getIds())));
}
// we don't want neutrinos first then neutralinos so swap them
// neutralinos first then neutrinos
if ( neutralinoMix()->size().first == 7 ) {
vector<int> move(7);
move[0] = 4; move[1] = 5; move[2] = 6;
move[3] = 0; move[4] = 1; move[5] = 2; move[6] = 3;
CMatrix oldMat = neutralinoMix()->getMatrix();
CMatrix newMat(7,vector<Complex>(7,0.));
for(unsigned int ix=0;ix<7;++ix) {
for(unsigned int iy=0;iy<7;++iy)
newMat[move[ix]][move[iy]] = oldMat[ix][iy];
}
neutralinoMix(new_ptr(MixingMatrix(newMat,neutralinoMix()->getIds())));
}
// charginos the same, i.e. charginos first then charged leptons
if(charginoUMix()->size().first != charginoVMix()->size().first ||
charginoUMix()->size().second != charginoVMix()->size().second )
throw Exception() << "Chargino U and V mixing matrices must have the same size.\n"
<< "Check your SLHA file!" << Exception::runerror;
if ( charginoUMix()->size().first == 5 ) {
vector<int> move(5);
move[0] = 2; move[1] = 3; move[2] = 4;
move[3] = 0; move[4] = 1;
CMatrix oldMat = charginoUMix()->getMatrix();
CMatrix newMat = CMatrix(5,vector<Complex>(5,0.));
for(unsigned int ix=0;ix<5;++ix) {
for(unsigned int iy=0;iy<5;++iy)
newMat[move[ix]][move[iy]] = oldMat[ix][iy];
}
charginoUMix(new_ptr(MixingMatrix(newMat,charginoUMix()->getIds())));
oldMat = charginoVMix()->getMatrix();
newMat = CMatrix(5,vector<Complex>(5,0.));
for(unsigned int ix=0;ix<5;++ix) {
for(unsigned int iy=0;iy<5;++iy)
newMat[move[ix]][move[iy]] = oldMat[ix][iy];
}
charginoVMix(new_ptr(MixingMatrix(newMat,charginoVMix()->getIds())));
}
const MatrixSize & n = neutralinoMix()->size();
const MatrixSize & u = charginoUMix()->size();
const MatrixSize & h = CPevenHiggsMix()->size();
const MatrixSize & a = CPoddHiggsMix()->size();
const MatrixSize & l = ChargedHiggsMix()->size();
bool nBig = n.first == 7 && n.second == 7;
bool nSmall = n.first == 4 && n.second == 4;
if ( ! (nBig || nSmall) )
throw Exception()
<< "Mixing matrices have inconsistent sizes:\n"
<< "(RV)Nmix " << n.first << ',' << n.second << '\n'
<< Exception::runerror;
bool uBig = u.first == 5 && u.second == 5;
bool uSmall = u.first == 2 && u.second == 2;
if ( ! (uBig || uSmall) )
throw Exception()
<< "Mixing matrices have inconsistent sizes:\n"
<< "(RV)Umix " << u.first << ',' << u.second << '\n'
<< Exception::runerror;
bool hBig = h.first == 5 && h.second == 5;
bool hSmall = h.first == 2 && h.second == 2;
if ( ! (hBig || hSmall) )
throw Exception()
<< "Mixing matrices have inconsistent sizes:\n"
<< "(RV)Hmix " << h.first << ',' << h.second << '\n'
<< Exception::runerror;
bool aBig = (a.first == 4 || a.first == 5) && a.second == 5;
bool aSmall = a.first == 1 && a.second == 2;
if ( ! (aBig || aSmall) )
throw Exception()
<< "Mixing matrices have inconsistent sizes:\n"
<< "RVAmix " << a.first << ',' << a.second << '\n'
<< Exception::runerror;
bool lBig = (l.first == 7 || l.first == 8) && l.second == 8;
bool lSmall = l.first == 1 && l.second == 2;
if ( ! (lBig || lSmall) )
throw Exception()
<< "Mixing matrices have inconsistent sizes:\n"
<< "RVLmix " << l.first << ',' << l.second << '\n'
<< Exception::runerror;
bool allBig = nBig && uBig && hBig && aBig && lBig;
bool allSmall = nSmall && uSmall && hSmall && aSmall && lSmall;
bool allSmallExceptN = nBig && uSmall && hSmall && aSmall && lSmall;
if ( allSmallExceptN ) {
cerr << "Warning: Truncating Nmix to 4,4 for consistency "
<< "with other mixing matrices.\n";
CMatrix oldMat = neutralinoMix()->getMatrix();
CMatrix newMat(4,vector<Complex>(4,0.));
for(unsigned int ix=0;ix<4;++ix)
for(unsigned int iy=0;iy<4;++iy)
newMat[ix][iy] = oldMat[ix][iy];
assert( neutralinoMix()->getIds().size() >= 4 );
vector<long>::const_iterator beg = neutralinoMix()->getIds().begin();
vector<long>::const_iterator end = beg + 4;
neutralinoMix(new_ptr(MixingMatrix(newMat,vector<long>(beg,end))));
return;
}
else if ( ! (allBig || allSmall) ) {
throw Exception()
<< "Mixing matrices have inconsistent sizes:\n"
<< "(RV)Nmix " << n.first << ',' << n.second << '\n'
<< "(RV)Umix " << u.first << ',' << u.second << '\n'
<< "(RV)Hmix " << h.first << ',' << h.second << '\n'
<< "RVAmix " << a.first << ',' << a.second << '\n'
<< "RVLmix " << l.first << ',' << l.second << '\n'
<< Exception::runerror;
}
// reduce to MSSM + trilinear if requested
if(triLinearOnly_) {
// reduce size of n
if(neutralinoMix()->size().first ==7) {
CMatrix mix(4,vector<Complex>(4,0.));
unsigned int irow=0;
int imax[7]={-1,-1,-1,-1,-1,-1,-1};
for(unsigned int ix=0;ix<7;++ix) {
double maxComp(0.);
for(unsigned int iy=0;iy<7;++iy) {
double value = abs((*neutralinoMix())(ix,iy));
if(value>maxComp) {
maxComp = value;
imax[ix] = iy;
}
}
// neutralino
if(imax[ix]<=3) {
for(unsigned int iy=0;iy<4;++iy) mix[irow][iy] = (*neutralinoMix())(ix,iy);
++irow;
assert(irow<=4);
}
// neutrino
else {
idMap()[neutralinoMix()->getIds()[ix]] = neutralinoMix()->getIds()[imax[ix]];
}
}
vector<long> ids = neutralinoMix()->getIds();
ids.resize(4);
neutralinoMix(new_ptr(MixingMatrix(mix,ids)));
}
// reduce size of u
if(charginoUMix()->size().first ==5) {
CMatrix mix(2,vector<Complex>(2,0.));
unsigned int irow=0;
int imax[5]={-1,-1,-1,-1,-1};
for(unsigned int ix=0;ix<5;++ix) {
double maxComp(0.);
for(unsigned int iy=0;iy<5;++iy) {
double value = abs((*charginoUMix())(ix,iy));
if(value>maxComp) {
maxComp = value;
imax[ix] = iy;
}
}
// chargino
if(imax[ix]<=1) {
for(unsigned int iy=0;iy<2;++iy) mix[irow][iy] = (*charginoUMix())(ix,iy);
++irow;
assert(irow<=2);
}
// charged lepton
else {
idMap()[abs(charginoUMix()->getIds()[ix])] = abs(charginoUMix()->getIds()[imax[ix]]);
}
}
vector<long> ids = charginoUMix()->getIds();
ids.resize(2);
charginoUMix(new_ptr(MixingMatrix(mix,ids)));
}
// reduce size of v
if(charginoVMix()->size().first ==5) {
CMatrix mix(2,vector<Complex>(2,0.));
unsigned int irow=0;
int imax[5]={-1,-1,-1,-1,-1};
for(unsigned int ix=0;ix<5;++ix) {
double maxComp(0.);
for(unsigned int iy=0;iy<5;++iy) {
double value = abs((*charginoVMix())(ix,iy));
if(value>maxComp) {
maxComp = value;
imax[ix] = iy;
}
}
// chargino
if(imax[ix]<=1) {
for(unsigned int iy=0;iy<2;++iy) mix[irow][iy] = (*charginoVMix())(ix,iy);
++irow;
assert(irow<=2);
}
}
vector<long> ids = charginoVMix()->getIds();
ids.resize(2);
charginoVMix(new_ptr(MixingMatrix(mix,ids)));
}
// reduce size of pseudo scalar mixing
if(CPoddHiggsMix()) {
MixingVector hmix;
double beta = atan(tanBeta());
hmix.push_back(MixingElement(1,1,sin(beta)));
hmix.push_back(MixingElement(1,2,cos(beta)));
vector<long> ids(1,36);
MixingMatrixPtr newMix = new_ptr(MixingMatrix(1,2));
(*newMix).setIds(ids);
for(unsigned int ix=0; ix < hmix.size(); ++ix)
(*newMix)(hmix[ix].row-1,hmix[ix].col-1) = hmix[ix].value;
CPoddHiggsMix(newMix);
}
// reduce size of true scalar mixing
if(CPevenHiggsMix()->size().first==5) {
double alpha(0.);
CMatrix mix(2,vector<Complex>(2,0.));
unsigned int irow=0;
int imax[5]={-1,-1,-1,-1,-1};
for(unsigned int ix=0;ix<5;++ix) {
double maxComp(0.);
for(unsigned int iy=0;iy<5;++iy) {
double value = abs((*CPevenHiggsMix())(ix,iy));
if(value>maxComp) {
maxComp = value;
imax[ix] = iy;
}
}
// neutral Higgs
if(imax[ix]<=1) {
for(unsigned int iy=0;iy<2;++iy) mix[irow][iy] = (*CPevenHiggsMix())(ix,iy);
if(irow==0)
alpha = atan2(-(*CPevenHiggsMix())(ix,0).real(),(*CPevenHiggsMix())(ix,1).real());
++irow;
assert(irow<=2);
}
}
vector<long> ids = CPevenHiggsMix()->getIds();
ids.resize(2);
CPevenHiggsMix(new_ptr(MixingMatrix(mix,ids)));
higgsMixingAngle(alpha);
}
else {
bool readAlpha = false;
map<string,ParamMap>::const_iterator pit=parameters().find("alpha");
if(pit!=parameters().end()) {
ParamMap::const_iterator it = pit->second.find(1);
if(it!=pit->second.end()) {
readAlpha = true;
higgsMixingAngle(it->second);
}
}
if(!readAlpha)
throw Exception() << "In the RPV model BLOCK ALPHA which must be"
<< " present in the SLHA file is missing"
<< Exception::runerror;
}
// reduce size of charged scalar mixing
if(ChargedHiggsMix()->size().first>=7) {
CMatrix mix(2,vector<Complex>(2,0.));
unsigned int istau(0);
int imax[8]={-1,-1,-1,-1,-1,-1,-1,-1};
for(unsigned int ix=0;ix<ChargedHiggsMix()->size().first;++ix) {
double maxComp(0.);
for(unsigned int iy=0;iy<8;++iy) {
double value = abs((*ChargedHiggsMix())(ix,iy));
if(value>maxComp) {
maxComp = value;
imax[ix] = iy;
}
}
if(imax[ix]<=1) imax[ix]=0;
else --imax[ix];
idMap()[abs(ChargedHiggsMix()->getIds()[ix])] = abs(ChargedHiggsMix()->getIds()[imax[ix]]);
if(abs(ChargedHiggsMix()->getIds()[imax[ix]])%10==5) {
mix[istau][0] = (*ChargedHiggsMix())(ix,4);
mix[istau][1] = (*ChargedHiggsMix())(ix,7);
if(istau==0) idMap()[abs(ChargedHiggsMix()->getIds()[ix])] = 1000015;
else idMap()[abs(ChargedHiggsMix()->getIds()[ix])] = 2000015;
istau+=1;
assert(istau<=2);
}
}
// set up the stau mixing matrix
vector<long> ids(2);
ids[0] = 1000015;
ids[1] = 2000015;
stauMix(new_ptr(MixingMatrix(mix,ids)));
// delete 7x7
MixingVector hmix;
double beta = atan(tanBeta());
hmix.push_back(MixingElement(1,1,sin(beta)));
hmix.push_back(MixingElement(1,2,cos(beta)));
ids.clear();
ids.resize(1,37);
MixingMatrixPtr newMix = new_ptr(MixingMatrix(1,2));
(*newMix).setIds(ids);
for(unsigned int ix=0; ix < hmix.size(); ++ix)
(*newMix)(hmix[ix].row-1,hmix[ix].col-1) = hmix[ix].value;
ChargedHiggsMix(newMix);
}
// reduce size of up squark mixing
if( upSquarkMix_ ) {
CMatrix mix(2,vector<Complex>(2,0.));
unsigned int istop(0);
int imax[6]={-1,-1,-1,-1,-1,-1};
for(unsigned int ix=0;ix<6;++ix) {
double maxComp(0.);
for(unsigned int iy=0;iy<6;++iy) {
double value = abs((*upSquarkMix_)(ix,iy));
if(value>maxComp) {
maxComp = value;
imax[ix] = iy;
}
}
idMap()[upSquarkMix_->getIds()[ix]] = upSquarkMix_->getIds()[imax[ix]];
if(upSquarkMix_->getIds()[imax[ix]]%10==6) {
mix[istop][0] = (*upSquarkMix_)(ix,2);
mix[istop][1] = (*upSquarkMix_)(ix,5);
if(istop==0) idMap()[upSquarkMix_->getIds()[ix]] = 1000006;
else idMap()[upSquarkMix_->getIds()[ix]] = 2000006;
istop+=1;
assert(istop<=2);
}
}
// set up the stop mixing matrix
vector<long> ids(2);
ids[0] = 1000006;
ids[1] = 2000006;
stopMix(new_ptr(MixingMatrix(mix,ids)));
// delete 6x6
upSquarkMix_ = MixingMatrixPtr();
}
// reduce size of down squark mixing
if( downSquarkMix_ ) {
CMatrix mix(2,vector<Complex>(2,0.));
unsigned int isbot(0);
int imax[6]={-1,-1,-1,-1,-1,-1};
for(unsigned int ix=0;ix<6;++ix) {
double maxComp(0.);
for(unsigned int iy=0;iy<6;++iy) {
double value = abs((*downSquarkMix_)(ix,iy));
if(value>maxComp) {
maxComp = value;
imax[ix] = iy;
}
}
idMap()[downSquarkMix_->getIds()[ix]] = downSquarkMix_->getIds()[imax[ix]];
if(downSquarkMix_->getIds()[imax[ix]]%10==5) {
mix[isbot][0] = (*downSquarkMix_)(ix,2);
mix[isbot][1] = (*downSquarkMix_)(ix,5);
if(isbot==0) idMap()[downSquarkMix_->getIds()[ix]] = 1000005;
else idMap()[downSquarkMix_->getIds()[ix]] = 2000005;
isbot+=1;
assert(isbot<=2);
}
}
// set up the sbottom mixing matrix
vector<long> ids(2);
ids[0] = 1000005;
ids[1] = 2000005;
sbottomMix(new_ptr(MixingMatrix(mix,ids)));
// delete 6x6
downSquarkMix_ = MixingMatrixPtr();
}
// get the masses as we will have to mess with them
map<string,ParamMap>::const_iterator fit=parameters().find("mass");
ParamMap theMasses = fit->second;
for(long id=1000017;id<=1000019;++id) {
if(theMasses.find(id)==theMasses.end()) continue;
double mass = abs(theMasses.find(id)->second);
// find scalar partner
double mdiff=1e30;
- long new_id;
+ long new_id = 0;
for(ParamMap::const_iterator it=theMasses.begin();it!=theMasses.end();++it) {
double diff = abs(abs(it->second)-mass);
if(diff<mdiff) {
mdiff = diff;
new_id = it->first;
}
}
if(idMap().find(new_id)!=idMap().end()) {
idMap()[id] = idMap()[new_id];
}
else {
idMap()[id] = new_id;
}
}
}
}
void RPV::doinit() {
MSSM::doinit();
addVertex(LLEVertex_);
addVertex(LQDVertex_);
addVertex(UDDVertex_);
}
diff --git a/Shower/Base/Evolver.cc b/Shower/Base/Evolver.cc
--- a/Shower/Base/Evolver.cc
+++ b/Shower/Base/Evolver.cc
@@ -1,2284 +1,2286 @@
// -*- C++ -*-
//
// Evolver.cc is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 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 Evolver class.
//
#include "Evolver.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/RefVector.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "Herwig++/Shower/Base/ShowerParticle.h"
#include "ThePEG/Utilities/EnumIO.h"
#include "ShowerKinematics.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Handlers/EventHandler.h"
#include "ThePEG/Utilities/Throw.h"
#include "ShowerTree.h"
#include "ShowerProgenitor.h"
#include "KinematicsReconstructor.h"
#include "PartnerFinder.h"
#include "ThePEG/Handlers/StandardXComb.h"
#include "ThePEG/PDT/DecayMode.h"
#include "Herwig++/Shower/ShowerHandler.h"
#include "ThePEG/Utilities/DescribeClass.h"
using namespace Herwig;
DescribeClass<Evolver,Interfaced>
describeEvolver ("Herwig::Evolver","HwShower.so");
IBPtr Evolver::clone() const {
return new_ptr(*this);
}
IBPtr Evolver::fullclone() const {
return new_ptr(*this);
}
void Evolver::persistentOutput(PersistentOStream & os) const {
os << _model << _splittingGenerator << _maxtry
<< _meCorrMode << _hardVetoMode << _hardVetoRead << _hardVetoReadOption
<< _limitEmissions
<< ounit(_iptrms,GeV) << _beta << ounit(_gamma,GeV) << ounit(_iptmax,GeV)
<< _vetoes << _trunc_Mode << _hardEmissionMode
<< _colourEvolutionMethod << _reconOpt << _hardScaleFactor
<< interaction_<< interactions_.size();
for(unsigned int ix=0;ix<interactions_.size();++ix)
os << oenum(interactions_[ix]);
}
void Evolver::persistentInput(PersistentIStream & is, int) {
unsigned int isize;
is >> _model >> _splittingGenerator >> _maxtry
>> _meCorrMode >> _hardVetoMode >> _hardVetoRead >> _hardVetoReadOption
>> _limitEmissions
>> iunit(_iptrms,GeV) >> _beta >> iunit(_gamma,GeV) >> iunit(_iptmax,GeV)
>> _vetoes >> _trunc_Mode >> _hardEmissionMode
>> _colourEvolutionMethod >> _reconOpt >> _hardScaleFactor
>> interaction_ >> isize;
interactions_.resize(isize);
for(unsigned int ix=0;ix<interactions_.size();++ix)
is >> ienum(interactions_[ix]);
}
void Evolver::doinit() {
Interfaced::doinit();
if(interaction_==0) {
interactions_.push_back(ShowerInteraction::QCD);
interactions_.push_back(ShowerInteraction::QED);
}
else if(interaction_==1) {
interactions_.push_back(ShowerInteraction::QCD);
}
else if(interaction_==2) {
interactions_.push_back(ShowerInteraction::QED);
interactions_.push_back(ShowerInteraction::QCD);
}
else if(interaction_==3) {
interactions_.push_back(ShowerInteraction::QED);
}
else if(interaction_==4) {
interactions_.push_back(ShowerInteraction::Both);
}
}
void Evolver::Init() {
static ClassDocumentation<Evolver> documentation
("This class is responsible for carrying out the showering,",
"including the kinematics reconstruction, in a given scale range,"
"including the option of the POWHEG approach to simulated next-to-leading order"
" radiation\\cite{Nason:2004rx}.",
"%\\cite{Nason:2004rx}\n"
"\\bibitem{Nason:2004rx}\n"
" P.~Nason,\n"
" ``A new method for combining NLO QCD with shower Monte Carlo algorithms,''\n"
" JHEP {\\bf 0411} (2004) 040\n"
" [arXiv:hep-ph/0409146].\n"
" %%CITATION = JHEPA,0411,040;%%\n");
static Reference<Evolver,SplittingGenerator>
interfaceSplitGen("SplittingGenerator",
"A reference to the SplittingGenerator object",
&Herwig::Evolver::_splittingGenerator,
false, false, true, false);
static Reference<Evolver,ShowerModel> interfaceShowerModel
("ShowerModel",
"The pointer to the object which defines the shower evolution model.",
&Evolver::_model, false, false, true, false, false);
static Parameter<Evolver,unsigned int> interfaceMaxTry
("MaxTry",
"The maximum number of attempts to generate the shower from a"
" particular ShowerTree",
&Evolver::_maxtry, 100, 1, 1000,
false, false, Interface::limited);
static Switch<Evolver, unsigned int> ifaceMECorrMode
("MECorrMode",
"Choice of the ME Correction Mode",
&Evolver::_meCorrMode, 1, false, false);
static SwitchOption off
(ifaceMECorrMode,"No","MECorrections off", 0);
static SwitchOption on
(ifaceMECorrMode,"Yes","hard+soft on", 1);
static SwitchOption hard
(ifaceMECorrMode,"Hard","only hard on", 2);
static SwitchOption soft
(ifaceMECorrMode,"Soft","only soft on", 3);
static Switch<Evolver, unsigned int> ifaceHardVetoMode
("HardVetoMode",
"Choice of the Hard Veto Mode",
&Evolver::_hardVetoMode, 1, false, false);
static SwitchOption HVoff
(ifaceHardVetoMode,"No","hard vetos off", 0);
static SwitchOption HVon
(ifaceHardVetoMode,"Yes","hard vetos on", 1);
static SwitchOption HVIS
(ifaceHardVetoMode,"Initial", "only IS emissions vetoed", 2);
static SwitchOption HVFS
(ifaceHardVetoMode,"Final","only FS emissions vetoed", 3);
static Switch<Evolver, unsigned int> ifaceHardVetoRead
("HardVetoScaleSource",
"If hard veto scale is to be read",
&Evolver::_hardVetoRead, 0, false, false);
static SwitchOption HVRcalc
(ifaceHardVetoRead,"Calculate","Calculate from hard process", 0);
static SwitchOption HVRread
(ifaceHardVetoRead,"Read","Read from XComb->lastScale", 1);
static Switch<Evolver, bool> ifaceHardVetoReadOption
("HardVetoReadOption",
"Apply read-in scale veto to all collisions or just the primary one?",
&Evolver::_hardVetoReadOption, false, false, false);
static SwitchOption AllCollisions
(ifaceHardVetoReadOption,
"AllCollisions",
"Read-in pT veto applied to primary and secondary collisions.",
false);
static SwitchOption PrimaryCollision
(ifaceHardVetoReadOption,
"PrimaryCollision",
"Read-in pT veto applied to primary but not secondary collisions.",
true);
static Parameter<Evolver, Energy> ifaceiptrms
("IntrinsicPtGaussian",
"RMS of intrinsic pT of Gaussian distribution:\n"
"2*(1-Beta)*exp(-sqr(intrinsicpT/RMS))/sqr(RMS)",
&Evolver::_iptrms, GeV, ZERO, ZERO, 1000000.0*GeV,
false, false, Interface::limited);
static Parameter<Evolver, double> ifacebeta
("IntrinsicPtBeta",
"Proportion of inverse quadratic distribution in generating intrinsic pT.\n"
"(1-Beta) is the proportion of Gaussian distribution",
&Evolver::_beta, 0, 0, 1,
false, false, Interface::limited);
static Parameter<Evolver, Energy> ifacegamma
("IntrinsicPtGamma",
"Parameter for inverse quadratic:\n"
"2*Beta*Gamma/(sqr(Gamma)+sqr(intrinsicpT))",
&Evolver::_gamma,GeV, ZERO, ZERO, 100000.0*GeV,
false, false, Interface::limited);
static Parameter<Evolver, Energy> ifaceiptmax
("IntrinsicPtIptmax",
"Upper bound on intrinsic pT for inverse quadratic",
&Evolver::_iptmax,GeV, ZERO, ZERO, 100000.0*GeV,
false, false, Interface::limited);
static RefVector<Evolver,ShowerVeto> ifaceVetoes
("Vetoes",
"The vetoes to be checked during showering",
&Evolver::_vetoes, -1,
false,false,true,true,false);
static Switch<Evolver,unsigned int> interfaceLimitEmissions
("LimitEmissions",
"Limit the number and type of emissions for testing",
&Evolver::_limitEmissions, 0, false, false);
static SwitchOption interfaceLimitEmissionsNoLimit
(interfaceLimitEmissions,
"NoLimit",
"Allow an arbitrary number of emissions",
0);
static SwitchOption interfaceLimitEmissionsOneInitialStateEmission
(interfaceLimitEmissions,
"OneInitialStateEmission",
"Allow one emission in the initial state and none in the final state",
1);
static SwitchOption interfaceLimitEmissionsOneFinalStateEmission
(interfaceLimitEmissions,
"OneFinalStateEmission",
"Allow one emission in the final state and none in the initial state",
2);
static SwitchOption interfaceLimitEmissionsHardOnly
(interfaceLimitEmissions,
"HardOnly",
"Only allow radiation from the hard ME correction",
3);
static SwitchOption interfaceLimitEmissionsOneEmission
(interfaceLimitEmissions,
"OneEmission",
"Allow one emission in either the final state or initial state, but not both",
4);
static Switch<Evolver,bool> interfaceTruncMode
("TruncatedShower", "Include the truncated shower?",
&Evolver::_trunc_Mode, 1, false, false);
static SwitchOption interfaceTruncMode0
(interfaceTruncMode,"No","Truncated Shower is OFF", 0);
static SwitchOption interfaceTruncMode1
(interfaceTruncMode,"Yes","Truncated Shower is ON", 1);
static Switch<Evolver,unsigned int> interfaceHardEmissionMode
("HardEmissionMode",
"Whether to use ME corrections or POWHEG for the hardest emission",
&Evolver::_hardEmissionMode, 0, false, false);
static SwitchOption interfaceHardEmissionModeMECorrection
(interfaceHardEmissionMode,
"MECorrection",
"Old fashioned ME correction",
0);
static SwitchOption interfaceHardEmissionModePOWHEG
(interfaceHardEmissionMode,
"POWHEG",
"Powheg style hard emission",
1);
static Switch<Evolver,int> interfaceColourEvolutionMethod
("ColourEvolutionMethod",
"Choice of method for choosing the colour factor in gluon evolution",
&Evolver::_colourEvolutionMethod, 0, false, false);
static SwitchOption interfaceColourEvolutionMethodDefault
(interfaceColourEvolutionMethod,
"Default",
"Colour factor is CA for all scales",
0);
static SwitchOption interfaceColourEvolutionMethodHalfCA
(interfaceColourEvolutionMethod,
"HalfCA",
"Only use half the normal radiation until second scale is reached",
1);
static Switch<Evolver,unsigned int > interfaceInteractions
("Interactions",
"The interactions to be used in the shower",
&Evolver::interaction_, 1, false, false);
static SwitchOption interfaceInteractionsQCDFirst
(interfaceInteractions,
"QCDFirst",
"QCD first then QED",
0);
static SwitchOption interfaceInteractionsQCDOnly
(interfaceInteractions,
"QCDOnly",
"Only QCD",
1);
static SwitchOption interfaceInteractionsQEDFirst
(interfaceInteractions,
"QEDFirst",
"QED first then QCD",
2);
static SwitchOption interfaceInteractionsQEDOnly
(interfaceInteractions,
"QEDOnly",
"Only QED",
3);
static SwitchOption interfaceInteractionsBothAtOnce
(interfaceInteractions,
"BothAtOnce",
"Generate both at the same time",
4);
static Switch<Evolver,unsigned int> interfaceReconstructionOption
("ReconstructionOption",
"Treatment of the reconstruction of the transverse momentum of "
"a branching from the evolution scale.",
&Evolver::_reconOpt, 0, false, false);
static SwitchOption interfaceReconstructionOptionCutOff
(interfaceReconstructionOption,
"CutOff",
"Use the cut-off masses in the calculation",
0);
static SwitchOption interfaceReconstructionOptionOffShell
(interfaceReconstructionOption,
"OffShell",
"Use the off-shell masses in the calculation",
1);
static Parameter<Evolver,double> interfaceHardScaleFactor
("HardScaleFactor",
"Set the factor to multiply the hard veto scale.",
&Evolver::_hardScaleFactor, 1.0, 0.0, 0,
false, false, Interface::lowerlim);
}
void Evolver::generateIntrinsicpT(vector<ShowerProgenitorPtr> particlesToShower) {
_intrinsic.clear();
if ( !ipTon() || !isISRadiationON() ) return;
// don't do anything for the moment for secondary scatters
if( !ShowerHandler::currentHandler()->firstInteraction() ) return;
// generate intrinsic pT
for(unsigned int ix=0;ix<particlesToShower.size();++ix) {
// only consider initial-state particles
if(particlesToShower[ix]->progenitor()->isFinalState()) continue;
if(!particlesToShower[ix]->progenitor()->dataPtr()->coloured()) continue;
Energy ipt;
if(UseRandom::rnd() > _beta) {
ipt=_iptrms*sqrt(-log(UseRandom::rnd()));
}
else {
ipt=_gamma*sqrt(pow(1.+sqr(_iptmax/_gamma), UseRandom::rnd())-1.);
}
pair<Energy,double> pt = make_pair(ipt,UseRandom::rnd(Constants::twopi));
_intrinsic[particlesToShower[ix]] = pt;
}
}
void Evolver::setupMaximumScales(const vector<ShowerProgenitorPtr> & p,
XCPtr xcomb) {
// let POWHEG events radiate freely
if(_hardEmissionMode==1&&hardTree()) {
vector<ShowerProgenitorPtr>::const_iterator ckt = p.begin();
for (; ckt != p.end(); ckt++) (*ckt)->maxHardPt(Constants::MaxEnergy);
return;
}
// return if no vetos
if (!hardVetoOn()) return;
// find out if hard partonic subprocess.
bool isPartonic(false);
map<ShowerProgenitorPtr,ShowerParticlePtr>::const_iterator
cit = _currenttree->incomingLines().begin();
Lorentz5Momentum pcm;
for(; cit!=currentTree()->incomingLines().end(); ++cit) {
pcm += cit->first->progenitor()->momentum();
isPartonic |= cit->first->progenitor()->coloured();
}
// find maximum pt from hard process, the maximum pt from all outgoing
// coloured lines (this is simpler and more general than
// 2stu/(s^2+t^2+u^2)). Maximum scale for scattering processes will
// be transverse mass.
Energy ptmax = -1.0*GeV;
// general case calculate the scale
if (!hardVetoXComb()||
(hardVetoReadOption()&&
!ShowerHandler::currentHandler()->firstInteraction())) {
// scattering process
if(currentTree()->isHard()) {
assert(xcomb);
// coloured incoming particles
if (isPartonic) {
map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator
cjt = currentTree()->outgoingLines().begin();
for(; cjt!=currentTree()->outgoingLines().end(); ++cjt) {
if (cjt->first->progenitor()->coloured())
ptmax = max(ptmax,cjt->first->progenitor()->momentum().mt());
}
}
if (ptmax < ZERO) ptmax = pcm.m();
if(hardVetoXComb()&&hardVetoReadOption()&&
!ShowerHandler::currentHandler()->firstInteraction()) {
ptmax=min(ptmax,sqrt(xcomb->lastScale()));
}
}
// decay, incoming() is the decaying particle.
else {
ptmax = currentTree()->incomingLines().begin()->first
->progenitor()->momentum().mass();
}
}
// hepeup.SCALUP is written into the lastXComb by the
// LesHouchesReader itself - use this by user's choice.
// Can be more general than this.
else {
if(currentTree()->isHard()) {
assert(xcomb);
ptmax = sqrt( xcomb->lastScale() );
}
else {
ptmax = currentTree()->incomingLines().begin()->first
->progenitor()->momentum().mass();
}
}
ptmax *= hardScaleFactor();
// set maxHardPt for all progenitors. For partonic processes this
// is now the max pt in the FS, for non-partonic processes or
// processes with no coloured FS the invariant mass of the IS
vector<ShowerProgenitorPtr>::const_iterator ckt = p.begin();
for (; ckt != p.end(); ckt++) (*ckt)->maxHardPt(ptmax);
}
void Evolver::showerHardProcess(ShowerTreePtr hard, XCPtr xcomb) {
_hardme = HwMEBasePtr();
// extract the matrix element
tStdXCombPtr lastXC = dynamic_ptr_cast<tStdXCombPtr>(xcomb);
if(lastXC) {
_hardme = dynamic_ptr_cast<HwMEBasePtr>(lastXC->matrixElement());
}
_decayme = HwDecayerBasePtr();
// set the current tree
currentTree(hard);
hardTree(HardTreePtr());
// number of attempts if more than one interaction switched on
unsigned int interactionTry=0;
do {
try {
// generate the showering
doShowering(true,xcomb);
// if no vetos return
return;
}
catch (InteractionVeto) {
currentTree()->clear();
++interactionTry;
}
}
while(interactionTry<=5);
throw Exception() << "Too many tries for shower in "
<< "Evolver::showerHardProcess()"
<< Exception::eventerror;
}
void Evolver::hardMatrixElementCorrection(bool hard) {
// set the initial enhancement factors for the soft correction
_initialenhance = 1.;
_finalenhance = 1.;
// if hard matrix element switched off return
if(!MECOn()) return;
// see if we can get the correction from the matrix element
// or decayer
if(hard) {
if(_hardme&&_hardme->hasMECorrection()) {
_hardme->initializeMECorrection(_currenttree,
_initialenhance,_finalenhance);
if(hardMEC())
_hardme->applyHardMatrixElementCorrection(_currenttree);
}
}
else {
if(_decayme&&_decayme->hasMECorrection()) {
_decayme->initializeMECorrection(_currenttree,
_initialenhance,_finalenhance);
if(hardMEC())
_decayme->applyHardMatrixElementCorrection(_currenttree);
}
}
}
bool Evolver::timeLikeShower(tShowerParticlePtr particle,
ShowerInteraction::Type type,
bool first) {
// don't do anything if not needed
if(_limitEmissions == 1 || hardOnly() ||
( _limitEmissions == 2 && _nfs != 0) ||
( _limitEmissions == 4 && _nfs + _nis != 0) ) return false;
ShowerParticleVector theChildren;
int ntry=0;
do {
++ntry;
// generate the emission
Branching fb;
while (true) {
fb=_splittingGenerator->chooseForwardBranching(*particle,_finalenhance,type);
// no emission return
if(!fb.kinematics) return false;
// if emission OK break
if(!timeLikeVetoed(fb,particle)) break;
// otherwise reset scale and continue - SO IS involved in veto algorithm
particle->vetoEmission(fb.type,fb.kinematics->scale());
}
// has emitted
// Assign the shower kinematics to the emitting particle.
particle->showerKinematics(fb.kinematics);
// Assign the splitting function to the emitting particle.
// For the time being we are considering only 1->2 branching
// Create the ShowerParticle objects for the two children of
// the emitting particle; set the parent/child relationship
// if same as definition create particles, otherwise create cc
tcPDPtr pdata[2];
for(unsigned int ix=0;ix<2;++ix) pdata[ix]=getParticleData(fb.ids[ix+1]);
if(particle->id()!=fb.ids[0]) {
for(unsigned int ix=0;ix<2;++ix) {
tPDPtr cc(pdata[ix]->CC());
if(cc) pdata[ix]=cc;
}
}
theChildren.push_back(new_ptr(ShowerParticle(pdata[0],true)));
theChildren.push_back(new_ptr(ShowerParticle(pdata[1],true)));
// update the children
particle->showerKinematics()->
updateChildren(particle, theChildren,fb.type);
// update number of emissions
++_nfs;
if(_limitEmissions!=0) return true;
// shower the first particle
timeLikeShower(theChildren[0],type,false);
// shower the second particle
timeLikeShower(theChildren[1],type,false);
// that's if for old approach
if(_reconOpt==0) break;
// branching has happened
particle->showerKinematics()->
updateParent(particle, theChildren,fb.type);
// clean up the vetoed emission
if(particle->virtualMass()==ZERO) {
particle->showerKinematics(ShoKinPtr());
for(unsigned int ix=0;ix<theChildren.size();++ix)
particle->abandonChild(theChildren[ix]);
theChildren.clear();
}
}
while(particle->virtualMass()==ZERO&&ntry<50);
if(first)
particle->showerKinematics()->resetChildren(particle,theChildren);
return true;
}
bool
Evolver::spaceLikeShower(tShowerParticlePtr particle, PPtr beam,
ShowerInteraction::Type type) {
//using the pdf's associated with the ShowerHandler assures, that
//modified pdf's are used for the secondary interactions via
//CascadeHandler::resetPDFs(...)
tcPDFPtr pdf;
if(ShowerHandler::currentHandler()->firstPDF().particle() == _beam)
pdf = ShowerHandler::currentHandler()->firstPDF().pdf();
if(ShowerHandler::currentHandler()->secondPDF().particle() == _beam)
pdf = ShowerHandler::currentHandler()->secondPDF().pdf();
Energy freeze = ShowerHandler::currentHandler()->pdfFreezingScale();
// don't do anything if not needed
if(_limitEmissions == 2 || hardOnly() ||
( _limitEmissions == 1 && _nis != 0 ) ||
( _limitEmissions == 4 && _nis + _nfs != 0 ) ) return false;
Branching bb;
// generate branching
while (true) {
bb=_splittingGenerator->chooseBackwardBranching(*particle,beam,
_initialenhance,
_beam,type,
pdf,freeze);
// return if no emission
if(!bb.kinematics) return false;
// if not vetoed break
if(!spaceLikeVetoed(bb,particle)) break;
// otherwise reset scale and continue
particle->vetoEmission(bb.type,bb.kinematics->scale());
}
// assign the splitting function and shower kinematics
particle->showerKinematics(bb.kinematics);
// For the time being we are considering only 1->2 branching
// particles as in Sudakov form factor
tcPDPtr part[2]={getParticleData(bb.ids[0]),
getParticleData(bb.ids[2])};
if(particle->id()!=bb.ids[1]) {
if(part[0]->CC()) part[0]=part[0]->CC();
if(part[1]->CC()) part[1]=part[1]->CC();
}
// Now create the actual particles, make the otherChild a final state
// particle, while the newParent is not
ShowerParticlePtr newParent=new_ptr(ShowerParticle(part[0],false));
ShowerParticlePtr otherChild = new_ptr(ShowerParticle(part[1],true,true));
ShowerParticleVector theChildren;
theChildren.push_back(particle);
theChildren.push_back(otherChild);
//this updates the evolution scale
particle->showerKinematics()->
updateParent(newParent, theChildren,bb.type);
// update the history if needed
_currenttree->updateInitialStateShowerProduct(_progenitor,newParent);
_currenttree->addInitialStateBranching(particle,newParent,otherChild);
// for the reconstruction of kinematics, parent/child
// relationships are according to the branching process:
// now continue the shower
++_nis;
bool emitted = _limitEmissions==0 ?
spaceLikeShower(newParent,beam,type) : false;
// now reconstruct the momentum
if(!emitted) {
if(_intrinsic.find(_progenitor)==_intrinsic.end()) {
bb.kinematics->updateLast(newParent,ZERO,ZERO);
}
else {
pair<Energy,double> kt=_intrinsic[_progenitor];
bb.kinematics->updateLast(newParent,
kt.first*cos(kt.second),
kt.first*sin(kt.second));
}
}
particle->showerKinematics()->
updateChildren(newParent, theChildren,bb.type);
if(_limitEmissions!=0) return true;
// perform the shower of the final-state particle
timeLikeShower(otherChild,type,true);
// return the emitted
return true;
}
void Evolver::showerDecay(ShowerTreePtr decay) {
_decayme = HwDecayerBasePtr();
_hardme = HwMEBasePtr();
// find the decayer
// try the normal way if possible
tDMPtr dm = decay->incomingLines().begin()->first->original() ->decayMode();
if(!dm) dm = decay->incomingLines().begin()->first->copy() ->decayMode();
if(!dm) dm = decay->incomingLines().begin()->first->progenitor()->decayMode();
// otherwise make a string and look it up
if(!dm) {
string tag = decay->incomingLines().begin()->first->original()->dataPtr()->name()
+ "->";
for(map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator
it=decay->outgoingLines().begin();it!=decay->outgoingLines().end();++it) {
if(it!=decay->outgoingLines().begin()) tag += ",";
tag += it->first->original()->dataPtr()->name();
}
tag += ";";
dm = generator()->findDecayMode(tag);
}
if(dm) _decayme = dynamic_ptr_cast<HwDecayerBasePtr>(dm->decayer());
// set the ShowerTree to be showered
currentTree(decay);
decay->applyTransforms();
hardTree(HardTreePtr());
unsigned int interactionTry=0;
do {
try {
// generate the showering
doShowering(false,XCPtr());
// if no vetos return
return;
}
catch (InteractionVeto) {
currentTree()->clear();
++interactionTry;
}
}
while(interactionTry<=5);
throw Exception() << "Too many tries for QED shower in Evolver::showerDecay()"
<< Exception::eventerror;
}
bool Evolver::spaceLikeDecayShower(tShowerParticlePtr particle,
const ShowerParticle::EvolutionScales & maxScales,
Energy minmass,ShowerInteraction::Type type) {
Branching fb;
while (true) {
fb=_splittingGenerator->chooseDecayBranching(*particle,maxScales,minmass,
_initialenhance,type);
// return if no radiation
if(!fb.kinematics) return false;
// if not vetoed break
if(!spaceLikeDecayVetoed(fb,particle)) break;
// otherwise reset scale and continue
particle->vetoEmission(fb.type,fb.kinematics->scale());
}
// has emitted
// Assign the shower kinematics to the emitting particle.
particle->showerKinematics(fb.kinematics);
// For the time being we are considering only 1->2 branching
// Create the ShowerParticle objects for the two children of
// the emitting particle; set the parent/child relationship
// if same as definition create particles, otherwise create cc
tcPDPtr pdata[2];
for(unsigned int ix=0;ix<2;++ix) pdata[ix]=getParticleData(fb.ids[ix+1]);
if(particle->id()!=fb.ids[0]) {
for(unsigned int ix=0;ix<2;++ix) {
tPDPtr cc(pdata[ix]->CC());
if(cc) pdata[ix]=cc;
}
}
ShowerParticleVector theChildren;
theChildren.push_back(new_ptr(ShowerParticle(pdata[0],true)));
theChildren.push_back(new_ptr(ShowerParticle(pdata[1],true)));
// some code moved to updateChildren
particle->showerKinematics()->
updateChildren(particle, theChildren, fb.type);
// In the case of splittings which involves coloured particles,
// set properly the colour flow of the branching.
// update the history if needed
_currenttree->updateInitialStateShowerProduct(_progenitor,theChildren[0]);
_currenttree->addInitialStateBranching(particle,theChildren[0],theChildren[1]);
// shower the first particle
spaceLikeDecayShower(theChildren[0],maxScales,minmass,type);
// shower the second particle
timeLikeShower(theChildren[1],type,true);
// branching has happened
return true;
}
vector<ShowerProgenitorPtr> Evolver::setupShower(bool hard) {
// generate POWHEG hard emission if needed
if(_hardEmissionMode==1) hardestEmission(hard);
ShowerInteraction::Type inter = interactions_[0];
if(_hardtree&&inter!=ShowerInteraction::Both) {
inter = _hardtree->interaction();
}
// set the initial colour partners
setEvolutionPartners(hard,inter,false);
// generate hard me if needed
if(_hardEmissionMode==0) hardMatrixElementCorrection(hard);
// get the particles to be showered
vector<ShowerProgenitorPtr> particlesToShower =
currentTree()->extractProgenitors();
// remake the colour partners if needed
if(_hardEmissionMode==0 && _currenttree->hardMatrixElementCorrection()) {
setEvolutionPartners(hard,interactions_[0],true);
_currenttree->resetShowerProducts();
}
// return the answer
return particlesToShower;
}
void Evolver::setEvolutionPartners(bool hard,ShowerInteraction::Type type,
bool clear) {
// match the particles in the ShowerTree and hardTree
if(hardTree() && !hardTree()->connect(currentTree()))
throw Exception() << "Can't match trees in "
<< "Evolver::setEvolutionPartners()"
<< Exception::eventerror;
// extract the progenitors
vector<ShowerParticlePtr> particles =
currentTree()->extractProgenitorParticles();
// clear the partners if needed
if(clear) {
for(unsigned int ix=0;ix<particles.size();++ix) {
particles[ix]->partner(ShowerParticlePtr());
particles[ix]->clearPartners();
}
}
// sort out the colour partners
if(hardTree()) {
// find the partner
for(unsigned int ix=0;ix<particles.size();++ix) {
tHardBranchingPtr partner =
hardTree()->particles()[particles[ix]]->colourPartner();
if(!partner) continue;
for(map<ShowerParticlePtr,tHardBranchingPtr>::const_iterator
it=hardTree()->particles().begin();
it!=hardTree()->particles().end();++it) {
if(it->second==partner) particles[ix]->partner(it->first);
}
if(!particles[ix]->partner())
throw Exception() << "Can't match partners in "
<< "Evolver::setEvolutionPartners()"
<< Exception::eventerror;
}
}
// Set the initial evolution scales
showerModel()->partnerFinder()->
setInitialEvolutionScales(particles,!hard,type,!_hardtree);
}
void Evolver::updateHistory(tShowerParticlePtr particle) {
if(!particle->children().empty()) {
ShowerParticleVector theChildren;
for(unsigned int ix=0;ix<particle->children().size();++ix) {
ShowerParticlePtr part = dynamic_ptr_cast<ShowerParticlePtr>
(particle->children()[ix]);
theChildren.push_back(part);
}
// update the history if needed
if(particle==_currenttree->getFinalStateShowerProduct(_progenitor))
_currenttree->updateFinalStateShowerProduct(_progenitor,
particle,theChildren);
_currenttree->addFinalStateBranching(particle,theChildren);
for(unsigned int ix=0;ix<theChildren.size();++ix)
updateHistory(theChildren[ix]);
}
}
bool Evolver::startTimeLikeShower(ShowerInteraction::Type type) {
if(hardTree()) {
map<ShowerParticlePtr,tHardBranchingPtr>::const_iterator
eit=hardTree()->particles().end(),
mit = hardTree()->particles().find(progenitor()->progenitor());
if( mit != eit && !mit->second->children().empty() ) {
bool output=truncatedTimeLikeShower(progenitor()->progenitor(),
mit->second ,type);
if(output) updateHistory(progenitor()->progenitor());
return output;
}
}
bool output = hardOnly() ? false :
timeLikeShower(progenitor()->progenitor() ,type,true) ;
if(output) updateHistory(progenitor()->progenitor());
return output;
}
bool Evolver::startSpaceLikeShower(PPtr parent, ShowerInteraction::Type type) {
if(hardTree()) {
map<ShowerParticlePtr,tHardBranchingPtr>::const_iterator
eit =hardTree()->particles().end(),
mit = hardTree()->particles().find(progenitor()->progenitor());
if( mit != eit && mit->second->parent() ) {
return truncatedSpaceLikeShower( progenitor()->progenitor(),
parent, mit->second->parent(), type );
}
}
return hardOnly() ? false :
spaceLikeShower(progenitor()->progenitor(),parent,type);
}
bool Evolver::
startSpaceLikeDecayShower(const ShowerParticle::EvolutionScales & maxScales,
Energy minimumMass,ShowerInteraction::Type type) {
if(hardTree()) {
map<ShowerParticlePtr,tHardBranchingPtr>::const_iterator
eit =hardTree()->particles().end(),
mit = hardTree()->particles().find(progenitor()->progenitor());
if( mit != eit && mit->second->parent() ) {
HardBranchingPtr branch=mit->second;
while(branch->parent()) branch=branch->parent();
return truncatedSpaceLikeDecayShower(progenitor()->progenitor(),maxScales,
minimumMass, branch ,type);
}
}
return hardOnly() ? false :
spaceLikeDecayShower(progenitor()->progenitor(),maxScales,minimumMass,type);
}
bool Evolver::timeLikeVetoed(const Branching & fb,
ShowerParticlePtr particle) {
// work out type of interaction
ShowerInteraction::Type type = fb.type==ShowerPartnerType::QED ?
ShowerInteraction::QED : ShowerInteraction::QCD;
// check whether emission was harder than largest pt of hard subprocess
if ( hardVetoFS() && fb.kinematics->pT() > _progenitor->maxHardPt() )
return true;
// soft matrix element correction veto
if( softMEC()) {
if(_hardme && _hardme->hasMECorrection()) {
if(_hardme->softMatrixElementVeto(_progenitor,particle,fb))
return true;
}
else if(_decayme && _decayme->hasMECorrection()) {
if(_decayme->softMatrixElementVeto(_progenitor,particle,fb))
return true;
}
}
// veto on maximum pt
if(fb.kinematics->pT()>_progenitor->maximumpT(type)) return true;
// general vetos
if (fb.kinematics && !_vetoes.empty()) {
bool vetoed=false;
for (vector<ShowerVetoPtr>::iterator v = _vetoes.begin();
v != _vetoes.end(); ++v) {
bool test = (**v).vetoTimeLike(_progenitor,particle,fb);
switch((**v).vetoType()) {
case ShowerVeto::Emission:
vetoed |= test;
break;
case ShowerVeto::Shower:
if(test) throw VetoShower();
break;
case ShowerVeto::Event:
if(test) throw Veto();
break;
}
}
if(vetoed) return true;
}
return false;
}
bool Evolver::spaceLikeVetoed(const Branching & bb,
ShowerParticlePtr particle) {
// work out type of interaction
ShowerInteraction::Type type = bb.type==ShowerPartnerType::QED ?
ShowerInteraction::QED : ShowerInteraction::QCD;
// check whether emission was harder than largest pt of hard subprocess
if (hardVetoIS() && bb.kinematics->pT() > _progenitor->maxHardPt())
return true;
// apply the soft correction
if( softMEC() && _hardme && _hardme->hasMECorrection() ) {
if(_hardme->softMatrixElementVeto(_progenitor,particle,bb))
return true;
}
// the more general vetos
// check vs max pt for the shower
if(bb.kinematics->pT()>_progenitor->maximumpT(type)) return true;
if (!_vetoes.empty()) {
bool vetoed=false;
for (vector<ShowerVetoPtr>::iterator v = _vetoes.begin();
v != _vetoes.end(); ++v) {
bool test = (**v).vetoSpaceLike(_progenitor,particle,bb);
switch ((**v).vetoType()) {
case ShowerVeto::Emission:
vetoed |= test;
break;
case ShowerVeto::Shower:
if(test) throw VetoShower();
break;
case ShowerVeto::Event:
if(test) throw Veto();
break;
}
}
if (vetoed) return true;
}
return false;
}
bool Evolver::spaceLikeDecayVetoed( const Branching & fb,
ShowerParticlePtr particle) {
// work out type of interaction
ShowerInteraction::Type type = fb.type==ShowerPartnerType::QED ?
ShowerInteraction::QED : ShowerInteraction::QCD;
// apply the soft correction
if( softMEC() && _decayme && _decayme->hasMECorrection() ) {
if(_decayme->softMatrixElementVeto(_progenitor,particle,fb))
return true;
}
// veto on hardest pt in the shower
if(fb.kinematics->pT()> _progenitor->maximumpT(type)) return true;
// general vetos
if (!_vetoes.empty()) {
bool vetoed=false;
for (vector<ShowerVetoPtr>::iterator v = _vetoes.begin();
v != _vetoes.end(); ++v) {
bool test = (**v).vetoSpaceLike(_progenitor,particle,fb);
switch((**v).vetoType()) {
case ShowerVeto::Emission:
vetoed |= test;
break;
case ShowerVeto::Shower:
if(test) throw VetoShower();
break;
case ShowerVeto::Event:
if(test) throw Veto();
break;
}
if (vetoed) return true;
}
}
return false;
}
void Evolver::hardestEmission(bool hard) {
HardTreePtr ISRTree;
if( ( _hardme && _hardme->hasPOWHEGCorrection()!=0) ||
( _decayme && _decayme->hasPOWHEGCorrection()!=0)) {
if(_hardme) {
assert(hard);
if(interaction_==4) {
vector<ShowerInteraction::Type> inter(2);
inter[0] = ShowerInteraction::QCD;
inter[1] = ShowerInteraction::QED;
_hardtree = _hardme->generateHardest( currentTree(),inter );
}
else {
_hardtree = _hardme->generateHardest( currentTree(),interactions_ );
}
}
else {
assert(!hard);
_hardtree = _decayme->generateHardest( currentTree() );
}
// store initial state POWHEG radiation
if(_hardtree && _hardme && _hardme->hasPOWHEGCorrection()==1)
ISRTree=_hardtree;
}
else {
_hardtree = ShowerHandler::currentHandler()->generateCKKW(currentTree());
}
// if hard me doesn't have a FSR powheg
// correction use decay powheg correction
if (_hardme && _hardme->hasPOWHEGCorrection()<2) {
// check for intermediate colour singlet resonance
const ParticleVector inter = _hardme->subProcess()->intermediates();
if (inter.size()!=1 ||
inter[0]->momentum().m2()/GeV2 < 0 ||
inter[0]->dataPtr()->iColour()!=PDT::Colour0){
if(_hardtree) connectTrees(currentTree(),_hardtree,hard);
return;
}
map<ShowerProgenitorPtr, tShowerParticlePtr > out = currentTree()->outgoingLines();
// ignore cases where outgoing particles are not coloured
if (out.size()!=2 ||
out. begin()->second->dataPtr()->iColour()==PDT::Colour0 ||
out.rbegin()->second->dataPtr()->iColour()==PDT::Colour0) {
if(_hardtree) connectTrees(currentTree(),_hardtree,hard);
return;
}
// look up decay mode
tDMPtr dm;
string tag;
string inParticle = inter[0]->dataPtr()->name() + "->";
vector<string> outParticles;
outParticles.push_back(out.begin ()->first->progenitor()->dataPtr()->name());
outParticles.push_back(out.rbegin()->first->progenitor()->dataPtr()->name());
for (int it=0; it<2; ++it){
tag = inParticle + outParticles[it] + "," + outParticles[(it+1)%2] + ";";
dm = generator()->findDecayMode(tag);
if(dm) break;
}
// get the decayer
HwDecayerBasePtr decayer;
if(dm) decayer = dynamic_ptr_cast<HwDecayerBasePtr>(dm->decayer());
// check if decayer has a FSR POWHEG correction
if (!decayer || decayer->hasPOWHEGCorrection()<2){
if(_hardtree) connectTrees(currentTree(),_hardtree,hard);
return;
}
// generate the hardest emission
ShowerDecayMap decay;
PPtr in = new_ptr(*inter[0]);
ShowerTreePtr decayTree = new_ptr(ShowerTree(in, decay));
HardTreePtr FSRTree = decayer->generateHardest(decayTree);
if (!FSRTree) {
if(_hardtree) connectTrees(currentTree(),_hardtree,hard);
return;
}
// if there is no ISRTree make _hardtree from FSRTree
if (!ISRTree){
vector<HardBranchingPtr> inBranch,hardBranch;
for(map<ShowerProgenitorPtr,ShowerParticlePtr>::const_iterator
cit =currentTree()->incomingLines().begin();
cit!=currentTree()->incomingLines().end();++cit ) {
inBranch.push_back(new_ptr(HardBranching(cit->second,SudakovPtr(),
HardBranchingPtr(),
HardBranching::Incoming)));
inBranch.back()->beam(cit->first->original()->parents()[0]);
hardBranch.push_back(inBranch.back());
}
if(inBranch[0]->branchingParticle()->dataPtr()->coloured()) {
inBranch[0]->colourPartner(inBranch[1]);
inBranch[1]->colourPartner(inBranch[0]);
}
for(set<HardBranchingPtr>::iterator it=FSRTree->branchings().begin();
it!=FSRTree->branchings().end();++it) {
if((**it).branchingParticle()->id()!=in->id())
hardBranch.push_back(*it);
}
hardBranch[2]->colourPartner(hardBranch[3]);
hardBranch[3]->colourPartner(hardBranch[2]);
HardTreePtr newTree = new_ptr(HardTree(hardBranch,inBranch,
ShowerInteraction::QCD));
_hardtree = newTree;
}
// Otherwise modify the ISRTree to include the emission in FSRTree
else {
vector<tShowerParticlePtr> FSROut, ISROut;
set<HardBranchingPtr>::iterator itFSR, itISR;
// get outgoing particles
for(itFSR =FSRTree->branchings().begin();
itFSR!=FSRTree->branchings().end();++itFSR){
if ((**itFSR).status()==HardBranching::Outgoing)
FSROut.push_back((*itFSR)->branchingParticle());
}
for(itISR =ISRTree->branchings().begin();
itISR!=ISRTree->branchings().end();++itISR){
if ((**itISR).status()==HardBranching::Outgoing)
ISROut.push_back((*itISR)->branchingParticle());
}
// find COM frame formed by outgoing particles
LorentzRotation eventFrameFSR, eventFrameISR;
eventFrameFSR = ((FSROut[0]->momentum()+FSROut[1]->momentum()).findBoostToCM());
eventFrameISR = ((ISROut[0]->momentum()+ISROut[1]->momentum()).findBoostToCM());
// find rotation between ISR and FSR frames
int j=0;
if (ISROut[0]->id()!=FSROut[0]->id()) j=1;
eventFrameISR.rotateZ( (eventFrameFSR*FSROut[0]->momentum()).phi()-
(eventFrameISR*ISROut[j]->momentum()).phi() );
eventFrameISR.rotateY( (eventFrameFSR*FSROut[0]->momentum()).theta()-
(eventFrameISR*ISROut[j]->momentum()).theta() );
eventFrameISR.invert();
for (itFSR=FSRTree->branchings().begin();
itFSR!=FSRTree->branchings().end();++itFSR){
if ((**itFSR).branchingParticle()->id()==in->id()) continue;
for (itISR =ISRTree->branchings().begin();
itISR!=ISRTree->branchings().end();++itISR){
if ((**itISR).status()==HardBranching::Incoming) continue;
if ((**itFSR).branchingParticle()->id()==
(**itISR).branchingParticle()->id()){
// rotate FSRTree particle to ISRTree event frame
(**itISR).branchingParticle()->setMomentum(eventFrameISR*
eventFrameFSR*
(**itFSR).branchingParticle()->momentum());
(**itISR).branchingParticle()->rescaleMass();
// add the children of the FSRTree particles to the ISRTree
if(!(**itFSR).children().empty()){
(**itISR).addChild((**itFSR).children()[0]);
(**itISR).addChild((**itFSR).children()[1]);
// rotate momenta to ISRTree event frame
(**itISR).children()[0]->branchingParticle()->setMomentum(eventFrameISR*
eventFrameFSR*
(**itFSR).children()[0]->branchingParticle()->momentum());
(**itISR).children()[1]->branchingParticle()->setMomentum(eventFrameISR*
eventFrameFSR*
(**itFSR).children()[1]->branchingParticle()->momentum());
}
}
}
}
_hardtree = ISRTree;
}
}
if(_hardtree){
connectTrees(currentTree(),_hardtree,hard);
}
}
bool Evolver::truncatedTimeLikeShower(tShowerParticlePtr particle,
HardBranchingPtr branch,
ShowerInteraction::Type type) {
int ntry=0;
do {
++ntry;
Branching fb;
unsigned int iout=0;
tcPDPtr pdata[2];
while (true) {
// no truncated shower break
if(!isTruncatedShowerON()||hardOnly()) break;
// generate emission
fb=splittingGenerator()->chooseForwardBranching(*particle,1.,type);
// no emission break
if(!fb.kinematics) break;
// check haven't evolved too far
if(fb.kinematics->scale() < branch->scale()) {
fb=Branching();
break;
}
// get the particle data objects
for(unsigned int ix=0;ix<2;++ix) pdata[ix]=getParticleData(fb.ids[ix+1]);
if(particle->id()!=fb.ids[0]) {
for(unsigned int ix=0;ix<2;++ix) {
tPDPtr cc(pdata[ix]->CC());
if(cc) pdata[ix]=cc;
}
}
// find the truncated line
iout=0;
if(pdata[0]->id()!=pdata[1]->id()) {
if(pdata[0]->id()==particle->id()) iout=1;
else if (pdata[1]->id()==particle->id()) iout=2;
}
else if(pdata[0]->id()==particle->id()) {
if(fb.kinematics->z()>0.5) iout=1;
else iout=2;
}
// apply the vetos for the truncated shower
// no flavour changing branchings
if(iout==0) {
particle->vetoEmission(fb.type,fb.kinematics->scale());
continue;
}
double zsplit = iout==1 ? fb.kinematics->z() : 1-fb.kinematics->z();
// only if same interaction for forced branching
ShowerInteraction::Type type2 = fb.type==ShowerPartnerType::QED ?
ShowerInteraction::QED : ShowerInteraction::QCD;
// and evolution
if(type2==branch->sudakov()->interactionType()) {
if(zsplit < 0.5 || // hardest line veto
fb.kinematics->scale()*zsplit < branch->scale() ) { // angular ordering veto
particle->vetoEmission(fb.type,fb.kinematics->scale());
continue;
}
}
// pt veto
if(fb.kinematics->pT() > progenitor()->maximumpT(type2)) {
particle->vetoEmission(fb.type,fb.kinematics->scale());
continue;
}
// should do base class vetos as well
if(timeLikeVetoed(fb,particle)) {
particle->vetoEmission(fb.type,fb.kinematics->scale());
continue;
}
break;
}
// if no branching force trunctaed emission
if(!fb.kinematics) {
// construct the kinematics for the hard emission
ShoKinPtr showerKin=
branch->sudakov()->createFinalStateBranching(branch->scale(),
branch->children()[0]->z(),
branch->phi(),
branch->children()[0]->pT());
showerKin->initialize( *particle,PPtr() );
IdList idlist(3);
idlist[0] = particle->id();
idlist[1] = branch->children()[0]->branchingParticle()->id();
idlist[2] = branch->children()[1]->branchingParticle()->id();
fb = Branching( showerKin, idlist, branch->sudakov(),branch->type() );
// Assign the shower kinematics to the emitting particle.
particle->showerKinematics( fb.kinematics );
// Assign the splitting function to the emitting particle.
// For the time being we are considering only 1->2 branching
// Create the ShowerParticle objects for the two children of
// the emitting particle; set the parent/child relationship
// if same as definition create particles, otherwise create cc
ShowerParticleVector theChildren;
theChildren.push_back(new_ptr(ShowerParticle(branch->children()[0]->
branchingParticle()->dataPtr(),true)));
theChildren.push_back(new_ptr(ShowerParticle(branch->children()[1]->
branchingParticle()->dataPtr(),true)));
particle->showerKinematics()->
updateChildren(particle, theChildren,fb.type);
// shower the first particle
if( branch->children()[0]->children().empty() ) {
if( ! hardOnly() )
timeLikeShower(theChildren[0],type,false);
}
else {
truncatedTimeLikeShower( theChildren[0],branch->children()[0],type);
}
// shower the second particle
if( branch->children()[1]->children().empty() ) {
if( ! hardOnly() )
timeLikeShower( theChildren[1] , type,false);
}
else {
truncatedTimeLikeShower( theChildren[1],branch->children()[1] ,type);
}
// that's if for old approach
if(_reconOpt==0) return true;
// branching has happened
particle->showerKinematics()->updateParent(particle, theChildren,fb.type);
// clean up the vetoed emission
if(particle->virtualMass()==ZERO) {
particle->showerKinematics(ShoKinPtr());
for(unsigned int ix=0;ix<theChildren.size();++ix)
particle->abandonChild(theChildren[ix]);
theChildren.clear();
}
else return true;
}
// has emitted
// Assign the shower kinematics to the emitting particle.
particle->showerKinematics(fb.kinematics);
// Assign the splitting function to the emitting particle.
// For the time being we are considering only 1->2 branching
// Create the ShowerParticle objects for the two children of
// the emitting particle; set the parent/child relationship
// if same as definition create particles, otherwise create cc
ShowerParticleVector theChildren;
theChildren.push_back( new_ptr( ShowerParticle( pdata[0], true ) ) );
theChildren.push_back( new_ptr( ShowerParticle( pdata[1], true ) ) );
particle->showerKinematics()->
updateChildren( particle, theChildren , fb.type);
// shower the first particle
if( iout == 1 ) truncatedTimeLikeShower( theChildren[0], branch , type );
else timeLikeShower( theChildren[0] , type,false);
// shower the second particle
if( iout == 2 ) truncatedTimeLikeShower( theChildren[1], branch , type );
else timeLikeShower( theChildren[1] , type,false);
// that's if for old approach
if(_reconOpt==0) return true;
// branching has happened
particle->showerKinematics()->updateParent(particle, theChildren,fb.type);
// clean up the vetoed emission
if(particle->virtualMass()==ZERO) {
particle->showerKinematics(ShoKinPtr());
for(unsigned int ix=0;ix<theChildren.size();++ix)
particle->abandonChild(theChildren[ix]);
theChildren.clear();
}
else return true;
}
while(ntry<50);
return false;
}
bool Evolver::truncatedSpaceLikeShower(tShowerParticlePtr particle, PPtr beam,
HardBranchingPtr branch,
ShowerInteraction::Type type) {
tcPDFPtr pdf;
if(ShowerHandler::currentHandler()->firstPDF().particle() == beamParticle())
pdf = ShowerHandler::currentHandler()->firstPDF().pdf();
if(ShowerHandler::currentHandler()->secondPDF().particle() == beamParticle())
pdf = ShowerHandler::currentHandler()->secondPDF().pdf();
Energy freeze = ShowerHandler::currentHandler()->pdfFreezingScale();
Branching bb;
// parameters of the force branching
double z(0.);
HardBranchingPtr timelike;
for( unsigned int ix = 0; ix < branch->children().size(); ++ix ) {
if( branch->children()[ix]->status() ==HardBranching::Outgoing) {
timelike = branch->children()[ix];
}
if( branch->children()[ix]->status() ==HardBranching::Incoming )
z = branch->children()[ix]->z();
}
// generate truncated branching
tcPDPtr part[2];
if(z>=0.&&z<=1.) {
while (true) {
if( !isTruncatedShowerON() || hardOnly() ) break;
bb = splittingGenerator()->chooseBackwardBranching( *particle,
beam, 1., beamParticle(),
type , pdf,freeze);
if( !bb.kinematics || bb.kinematics->scale() < branch->scale() ) {
bb = Branching();
break;
}
// particles as in Sudakov form factor
part[0] = getParticleData( bb.ids[0] );
part[1] = getParticleData( bb.ids[2] );
//is emitter anti-particle
if( particle->id() != bb.ids[1]) {
if( part[0]->CC() ) part[0] = part[0]->CC();
if( part[1]->CC() ) part[1] = part[1]->CC();
}
double zsplit = bb.kinematics->z();
// apply the vetos for the truncated shower
// if doesn't carry most of momentum
ShowerInteraction::Type type2 = bb.type==ShowerPartnerType::QED ?
ShowerInteraction::QED : ShowerInteraction::QCD;
if(type2==branch->sudakov()->interactionType() &&
zsplit < 0.5) {
particle->vetoEmission(bb.type,bb.kinematics->scale());
continue;
}
// others
if( part[0]->id() != particle->id() || // if particle changes type
bb.kinematics->pT() > progenitor()->maximumpT(type2) || // pt veto
bb.kinematics->scale() < branch->scale()) { // angular ordering veto
particle->vetoEmission(bb.type,bb.kinematics->scale());
continue;
}
// and those from the base class
if(spaceLikeVetoed(bb,particle)) {
particle->vetoEmission(bb.type,bb.kinematics->scale());
continue;
}
break;
}
}
if( !bb.kinematics ) {
//do the hard emission
ShoKinPtr kinematics =
branch->sudakov()->createInitialStateBranching( branch->scale(), z, branch->phi(),
branch->children()[0]->pT() );
kinematics->initialize( *particle, beam );
// assign the splitting function and shower kinematics
particle->showerKinematics( kinematics );
// For the time being we are considering only 1->2 branching
// Now create the actual particles, make the otherChild a final state
// particle, while the newParent is not
ShowerParticlePtr newParent =
new_ptr( ShowerParticle( branch->branchingParticle()->dataPtr(), false ) );
ShowerParticlePtr otherChild =
new_ptr( ShowerParticle( timelike->branchingParticle()->dataPtr(),
true, true ) );
ShowerParticleVector theChildren;
theChildren.push_back( particle );
theChildren.push_back( otherChild );
particle->showerKinematics()->
updateParent( newParent, theChildren, branch->type());
// update the history if needed
currentTree()->updateInitialStateShowerProduct( progenitor(), newParent );
currentTree()->addInitialStateBranching( particle, newParent, otherChild );
// for the reconstruction of kinematics, parent/child
// relationships are according to the branching process:
// now continue the shower
bool emitted=false;
if(!hardOnly()) {
if( branch->parent() ) {
emitted = truncatedSpaceLikeShower( newParent, beam, branch->parent() , type);
}
else {
emitted = spaceLikeShower( newParent, beam , type);
}
}
if( !emitted ) {
if( intrinsicpT().find( progenitor() ) == intrinsicpT().end() ) {
kinematics->updateLast( newParent, ZERO, ZERO );
}
else {
pair<Energy,double> kt = intrinsicpT()[progenitor()];
kinematics->updateLast( newParent,
kt.first*cos( kt.second ),
kt.first*sin( kt.second ) );
}
}
particle->showerKinematics()->
updateChildren( newParent, theChildren,bb.type);
if(hardOnly()) return true;
// perform the shower of the final-state particle
if( timelike->children().empty() ) {
timeLikeShower( otherChild , type,true);
}
else {
truncatedTimeLikeShower( otherChild, timelike , type);
}
// return the emitted
return true;
}
// assign the splitting function and shower kinematics
particle->showerKinematics( bb.kinematics );
// For the time being we are considering only 1->2 branching
// Now create the actual particles, make the otherChild a final state
// particle, while the newParent is not
ShowerParticlePtr newParent = new_ptr( ShowerParticle( part[0], false ) );
ShowerParticlePtr otherChild = new_ptr( ShowerParticle( part[1], true, true ) );
ShowerParticleVector theChildren;
theChildren.push_back( particle );
theChildren.push_back( otherChild );
particle->showerKinematics()->
updateParent( newParent, theChildren, bb.type);
// update the history if needed
currentTree()->updateInitialStateShowerProduct( progenitor(), newParent );
currentTree()->addInitialStateBranching( particle, newParent, otherChild );
// for the reconstruction of kinematics, parent/child
// relationships are according to the branching process:
// now continue the shower
bool emitted = truncatedSpaceLikeShower( newParent, beam, branch,type);
// now reconstruct the momentum
if( !emitted ) {
if( intrinsicpT().find( progenitor() ) == intrinsicpT().end() ) {
bb.kinematics->updateLast( newParent, ZERO, ZERO );
}
else {
pair<Energy,double> kt = intrinsicpT()[ progenitor() ];
bb.kinematics->updateLast( newParent,
kt.first*cos( kt.second ),
kt.first*sin( kt.second ) );
}
}
particle->showerKinematics()->
updateChildren( newParent, theChildren, bb.type);
// perform the shower of the final-state particle
timeLikeShower( otherChild , type,true);
// return the emitted
return true;
}
bool Evolver::
truncatedSpaceLikeDecayShower(tShowerParticlePtr particle,
const ShowerParticle::EvolutionScales & maxScales,
Energy minmass, HardBranchingPtr branch,
ShowerInteraction::Type type) {
Branching fb;
unsigned int iout=0;
tcPDPtr pdata[2];
while (true) {
// no truncated shower break
if(!isTruncatedShowerON()||hardOnly()) break;
fb=splittingGenerator()->chooseDecayBranching(*particle,maxScales,minmass,1.,type);
// return if no radiation
if(!fb.kinematics) break;
// check haven't evolved too far
if(fb.kinematics->scale() < branch->scale()) {
fb=Branching();
break;
}
// get the particle data objects
for(unsigned int ix=0;ix<2;++ix) pdata[ix]=getParticleData(fb.ids[ix+1]);
if(particle->id()!=fb.ids[0]) {
for(unsigned int ix=0;ix<2;++ix) {
tPDPtr cc(pdata[ix]->CC());
if(cc) pdata[ix]=cc;
}
}
// find the truncated line
iout=0;
if(pdata[0]->id()!=pdata[1]->id()) {
if(pdata[0]->id()==particle->id()) iout=1;
else if (pdata[1]->id()==particle->id()) iout=2;
}
else if(pdata[0]->id()==particle->id()) {
if(fb.kinematics->z()>0.5) iout=1;
else iout=2;
}
// apply the vetos for the truncated shower
// no flavour changing branchings
if(iout==0) {
particle->vetoEmission(fb.type,fb.kinematics->scale());
continue;
}
ShowerInteraction::Type type2 = fb.type==ShowerPartnerType::QED ?
ShowerInteraction::QED : ShowerInteraction::QCD;
double zsplit = iout==1 ? fb.kinematics->z() : 1-fb.kinematics->z();
if(type2==branch->sudakov()->interactionType()) {
if(zsplit < 0.5 || // hardest line veto
fb.kinematics->scale()*zsplit < branch->scale() ) { // angular ordering veto
particle->vetoEmission(fb.type,fb.kinematics->scale());
continue;
}
}
// pt veto
if(fb.kinematics->pT() > progenitor()->maximumpT(type2)) {
particle->vetoEmission(fb.type,fb.kinematics->scale());
continue;
}
// should do base class vetos as well
// if not vetoed break
if(!spaceLikeDecayVetoed(fb,particle)) break;
// otherwise reset scale and continue
particle->vetoEmission(fb.type,fb.kinematics->scale());
}
- // if no branching insert hard emission and continue
- if(!fb.kinematics) {
- // construct the kinematics for the hard emission
- ShoKinPtr showerKin=
- branch->sudakov()->createDecayBranching(branch->scale(),
- branch->children()[0]->z(),
- branch->phi(),
- branch->children()[0]->pT());
- showerKin->initialize( *particle,PPtr() );
- IdList idlist(3);
- idlist[0] = particle->id();
- idlist[1] = branch->children()[0]->branchingParticle()->id();
- idlist[2] = branch->children()[1]->branchingParticle()->id();
- // TODO fix this
- // why is this here, does this ever happen???
- assert(false);
- fb = Branching( showerKin, idlist, branch->sudakov(),ShowerPartnerType::QCDColourLine );
- // Assign the shower kinematics to the emitting particle.
- particle->showerKinematics( fb.kinematics );
- // Assign the splitting function to the emitting particle.
- // For the time being we are considering only 1->2 branching
- // Create the ShowerParticle objects for the two children of
- // the emitting particle; set the parent/child relationship
- // if same as definition create particles, otherwise create cc
- ShowerParticleVector theChildren;
- theChildren.push_back(new_ptr(ShowerParticle(branch->children()[0]->
- branchingParticle()->dataPtr(),true)));
- theChildren.push_back(new_ptr(ShowerParticle(branch->children()[1]->
- branchingParticle()->dataPtr(),true)));
- particle->showerKinematics()->
- updateChildren(particle, theChildren,fb.type);
- if(theChildren[0]->id()==particle->id()) {
- // update the history if needed
- currentTree()->updateInitialStateShowerProduct(progenitor(),theChildren[0]);
- currentTree()->addInitialStateBranching(particle,theChildren[0],theChildren[1]);
- // shower the space-like particle
- if( branch->children()[0]->children().empty() ) {
- if( ! hardOnly() ) spaceLikeDecayShower(theChildren[0],maxScales,minmass,type);
- }
- else {
- truncatedSpaceLikeDecayShower( theChildren[0],maxScales,minmass,
- branch->children()[0],type);
- }
- // shower the second particle
- if( branch->children()[1]->children().empty() ) {
- if( ! hardOnly() ) timeLikeShower( theChildren[1] , type,true);
- }
- else {
- truncatedTimeLikeShower( theChildren[1],branch->children()[1] ,type);
- }
- }
- else {
- // update the history if needed
- currentTree()->updateInitialStateShowerProduct(progenitor(),theChildren[1]);
- currentTree()->addInitialStateBranching(particle,theChildren[0],theChildren[1]);
- // shower the space-like particle
- if( branch->children()[1]->children().empty() ) {
- if( ! hardOnly() ) spaceLikeDecayShower(theChildren[1],maxScales,minmass,type);
- }
- else {
- truncatedSpaceLikeDecayShower( theChildren[1],maxScales,minmass,
- branch->children()[1],type);
- }
- // shower the second particle
- if( branch->children()[0]->children().empty() ) {
- if( ! hardOnly() ) timeLikeShower( theChildren[0] , type,true);
- }
- else {
- truncatedTimeLikeShower( theChildren[0],branch->children()[0] ,type);
- }
- }
- return true;
- }
+ // TODO: QED branch seems to always have kinematics here
+ // before QED merge, would insert hard emission and continue
+ assert(fb.kinematics);
+// if (!fb.kinematics) {
+// // construct the kinematics for the hard emission
+// ShoKinPtr showerKin=
+// branch->sudakov()->createDecayBranching(branch->scale(),
+// branch->children()[0]->z(),
+// branch->phi(),
+// branch->children()[0]->pT());
+// showerKin->initialize( *particle,PPtr() );
+// IdList idlist(3);
+// idlist[0] = particle->id();
+// idlist[1] = branch->children()[0]->branchingParticle()->id();
+// idlist[2] = branch->children()[1]->branchingParticle()->id();
+// // TODO fix this
+// // why is this here, does this ever happen???
+// assert(false);
+// fb = Branching( showerKin, idlist, branch->sudakov(),ShowerPartnerType::QCDColourLine );
+// // Assign the shower kinematics to the emitting particle.
+// particle->showerKinematics( fb.kinematics );
+// // Assign the splitting function to the emitting particle.
+// // For the time being we are considering only 1->2 branching
+// // Create the ShowerParticle objects for the two children of
+// // the emitting particle; set the parent/child relationship
+// // if same as definition create particles, otherwise create cc
+// ShowerParticleVector theChildren;
+// theChildren.push_back(new_ptr(ShowerParticle(branch->children()[0]->
+// branchingParticle()->dataPtr(),true)));
+// theChildren.push_back(new_ptr(ShowerParticle(branch->children()[1]->
+// branchingParticle()->dataPtr(),true)));
+// particle->showerKinematics()->
+// updateChildren(particle, theChildren,fb.type);
+// if(theChildren[0]->id()==particle->id()) {
+// // update the history if needed
+// currentTree()->updateInitialStateShowerProduct(progenitor(),theChildren[0]);
+// currentTree()->addInitialStateBranching(particle,theChildren[0],theChildren[1]);
+// // shower the space-like particle
+// if( branch->children()[0]->children().empty() ) {
+// if( ! hardOnly() ) spaceLikeDecayShower(theChildren[0],maxScales,minmass,type);
+// }
+// else {
+// truncatedSpaceLikeDecayShower( theChildren[0],maxScales,minmass,
+// branch->children()[0],type);
+// }
+// // shower the second particle
+// if( branch->children()[1]->children().empty() ) {
+// if( ! hardOnly() ) timeLikeShower( theChildren[1] , type,true);
+// }
+// else {
+// truncatedTimeLikeShower( theChildren[1],branch->children()[1] ,type);
+// }
+// }
+// else {
+// // update the history if needed
+// currentTree()->updateInitialStateShowerProduct(progenitor(),theChildren[1]);
+// currentTree()->addInitialStateBranching(particle,theChildren[0],theChildren[1]);
+// // shower the space-like particle
+// if( branch->children()[1]->children().empty() ) {
+// if( ! hardOnly() ) spaceLikeDecayShower(theChildren[1],maxScales,minmass,type);
+// }
+// else {
+// truncatedSpaceLikeDecayShower( theChildren[1],maxScales,minmass,
+// branch->children()[1],type);
+// }
+// // shower the second particle
+// if( branch->children()[0]->children().empty() ) {
+// if( ! hardOnly() ) timeLikeShower( theChildren[0] , type,true);
+// }
+// else {
+// truncatedTimeLikeShower( theChildren[0],branch->children()[0] ,type);
+// }
+// }
+// return true;
+// }
// has emitted
// Assign the shower kinematics to the emitting particle.
particle->showerKinematics(fb.kinematics);
// For the time being we are considering only 1->2 branching
// Create the ShowerParticle objects for the two children of
// the emitting particle; set the parent/child relationship
// if same as definition create particles, otherwise create cc
ShowerParticleVector theChildren;
theChildren.push_back(new_ptr(ShowerParticle(pdata[0],true)));
theChildren.push_back(new_ptr(ShowerParticle(pdata[1],true)));
particle->showerKinematics()->updateChildren(particle, theChildren,fb.type);
// In the case of splittings which involves coloured particles,
// set properly the colour flow of the branching.
// update the history if needed
currentTree()->updateInitialStateShowerProduct(progenitor(),theChildren[0]);
currentTree()->addInitialStateBranching(particle,theChildren[0],theChildren[1]);
// shower the first particle
truncatedSpaceLikeDecayShower(theChildren[0],maxScales,minmass,branch,type);
// shower the second particle
timeLikeShower(theChildren[1],type,true);
// branching has happened
return true;
}
bool Evolver::constructDecayTree(vector<ShowerProgenitorPtr> & particlesToShower,
ShowerInteraction::Type inter) {
Energy ptmax(-GeV);
// get the maximum pt is all ready a hard tree
if(hardTree()) {
for(unsigned int ix=0;ix<particlesToShower.size();++ix) {
if(particlesToShower[ix]->maximumpT(inter)>ptmax&&
particlesToShower[ix]->progenitor()->isFinalState())
ptmax = particlesToShower[ix]->maximumpT(inter);
}
}
vector<HardBranchingPtr> spaceBranchings,allBranchings;
for(unsigned int ix=0;ix<particlesToShower.size();++ix) {
if(particlesToShower[ix]->progenitor()->isFinalState()) {
HardBranchingPtr newBranch;
if(particlesToShower[ix]->hasEmitted()) {
newBranch =
new_ptr(HardBranching(particlesToShower[ix]->progenitor(),
particlesToShower[ix]->progenitor()->
showerKinematics()->SudakovFormFactor(),
HardBranchingPtr(),HardBranching::Outgoing));
constructTimeLikeLine(newBranch,particlesToShower[ix]->progenitor());
}
else {
newBranch =
new_ptr(HardBranching(particlesToShower[ix]->progenitor(),
SudakovPtr(),HardBranchingPtr(),
HardBranching::Outgoing));
}
allBranchings.push_back(newBranch);
}
else {
HardBranchingPtr newBranch;
if(particlesToShower[ix]->hasEmitted()) {
newBranch =
new_ptr(HardBranching(particlesToShower[ix]->progenitor(),
particlesToShower[ix]->progenitor()->
showerKinematics()->SudakovFormFactor(),
HardBranchingPtr(),HardBranching::Decay));
constructTimeLikeLine(newBranch,particlesToShower[ix]->progenitor());
HardBranchingPtr last=newBranch;
do {
for(unsigned int ix=0;ix<last->children().size();++ix) {
if(last->children()[ix]->branchingParticle()->id()==
particlesToShower[ix]->id()) {
last = last->children()[ix];
continue;
}
}
}
while(!last->children().empty());
last->status(HardBranching::Incoming);
spaceBranchings.push_back(newBranch);
allBranchings .push_back(last);
}
else {
newBranch =
new_ptr(HardBranching(particlesToShower[ix]->progenitor(),
SudakovPtr(),HardBranchingPtr(),
HardBranching::Incoming));
spaceBranchings.push_back(newBranch);
allBranchings .push_back(newBranch);
}
}
}
HardTreePtr QCDTree = new_ptr(HardTree(allBranchings,spaceBranchings,inter));
// set the charge partners
ShowerParticleVector particles;
particles.push_back(spaceBranchings.back()->branchingParticle());
for(set<HardBranchingPtr>::iterator cit=QCDTree->branchings().begin();
cit!=QCDTree->branchings().end();++cit) {
if((*cit)->status()==HardBranching::Outgoing)
particles.push_back((*cit)->branchingParticle());
}
// get the partners
showerModel()->partnerFinder()->setInitialEvolutionScales(particles,true,inter,true);
// do the inverse recon
if(!showerModel()->kinematicsReconstructor()->
deconstructDecayJets(QCDTree,this,inter)) {
return false;
}
// clear the old shower
currentTree()->clear();
// set the hard tree
hardTree(QCDTree);
// set the charge partners
setEvolutionPartners(false,inter,false);
// get the particles to be showered
map<ShowerProgenitorPtr,ShowerParticlePtr>::const_iterator cit;
map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator cjt;
particlesToShower.clear();
// incoming particles
for(cit=currentTree()->incomingLines().begin();
cit!=currentTree()->incomingLines().end();++cit)
particlesToShower.push_back(((*cit).first));
assert(particlesToShower.size()==1);
// outgoing particles
for(cjt=currentTree()->outgoingLines().begin();
cjt!=currentTree()->outgoingLines().end();++cjt) {
particlesToShower.push_back(((*cjt).first));
if(ptmax>ZERO) particlesToShower.back()->maximumpT(ptmax,inter);
}
for(unsigned int ix=0;ix<particlesToShower.size();++ix) {
map<ShowerParticlePtr,tHardBranchingPtr>::const_iterator
eit=hardTree()->particles().end(),
mit = hardTree()->particles().find(particlesToShower[ix]->progenitor());
if( mit != eit) {
if(mit->second->status()==HardBranching::Outgoing)
particlesToShower[ix]->progenitor()->set5Momentum(mit->second->pVector());
}
}
return true;
}
bool Evolver::constructHardTree(vector<ShowerProgenitorPtr> & particlesToShower,
ShowerInteraction::Type inter) {
bool noEmission = true;
vector<HardBranchingPtr> spaceBranchings,allBranchings;
for(unsigned int ix=0;ix<particlesToShower.size();++ix) {
if(particlesToShower[ix]->progenitor()->isFinalState()) {
HardBranchingPtr newBranch;
if(particlesToShower[ix]->hasEmitted()) {
noEmission = false;
newBranch =
new_ptr(HardBranching(particlesToShower[ix]->progenitor(),
particlesToShower[ix]->progenitor()->
showerKinematics()->SudakovFormFactor(),
HardBranchingPtr(),HardBranching::Outgoing));
constructTimeLikeLine(newBranch,particlesToShower[ix]->progenitor());
}
else {
newBranch =
new_ptr(HardBranching(particlesToShower[ix]->progenitor(),
SudakovPtr(),HardBranchingPtr(),
HardBranching::Outgoing));
}
allBranchings.push_back(newBranch);
}
else {
HardBranchingPtr first,last;
if(!particlesToShower[ix]->progenitor()->parents().empty()) {
noEmission = false;
constructSpaceLikeLine(particlesToShower[ix]->progenitor(),
first,last,SudakovPtr(),
particlesToShower[ix]->original()->parents()[0]);
}
else {
first = new_ptr(HardBranching(particlesToShower[ix]->progenitor(),
SudakovPtr(),HardBranchingPtr(),
HardBranching::Incoming));
if(particlesToShower[ix]->original()->parents().empty())
first->beam(particlesToShower[ix]->original());
else
first->beam(particlesToShower[ix]->original()->parents()[0]);
last = first;
}
spaceBranchings.push_back(first);
allBranchings.push_back(last);
}
}
if(!noEmission) {
HardTreePtr QCDTree = new_ptr(HardTree(allBranchings,spaceBranchings,
inter));
// set the charge partners
ShowerParticleVector particles;
for(set<HardBranchingPtr>::iterator cit=QCDTree->branchings().begin();
cit!=QCDTree->branchings().end();++cit) {
particles.push_back((*cit)->branchingParticle());
}
// get the partners
showerModel()->partnerFinder()->setInitialEvolutionScales(particles,false,
inter,true);
// do the inverse recon
if(!showerModel()->kinematicsReconstructor()->
deconstructHardJets(QCDTree,this,inter))
throw Exception() << "Can't to shower deconstruction for QED shower in"
<< "QEDEvolver::showerHard" << Exception::eventerror;
// set the hard tree
hardTree(QCDTree);
}
// clear the old shower
currentTree()->clear();
// set the charge partners
setEvolutionPartners(true,inter,false);
// get the particles to be showered
particlesToShower = currentTree()->extractProgenitors();
// reset momenta
if(hardTree()) {
for(unsigned int ix=0;ix<particlesToShower.size();++ix) {
map<ShowerParticlePtr,tHardBranchingPtr>::const_iterator
eit=hardTree()->particles().end(),
mit = hardTree()->particles().find(particlesToShower[ix]->progenitor());
if( mit != eit) {
particlesToShower[ix]->progenitor()->set5Momentum(mit->second->showerMomentum());
}
}
}
return true;
}
void Evolver::constructTimeLikeLine(tHardBranchingPtr branch,
tShowerParticlePtr particle) {
for(unsigned int ix=0;ix<particle->children().size();++ix) {
HardBranching::Status status = branch->status();
tShowerParticlePtr child =
dynamic_ptr_cast<ShowerParticlePtr>(particle->children()[ix]);
if(child->children().empty()) {
HardBranchingPtr newBranch =
new_ptr(HardBranching(child,SudakovPtr(),branch,status));
branch->addChild(newBranch);
}
else {
HardBranchingPtr newBranch =
new_ptr(HardBranching(child,child->showerKinematics()->SudakovFormFactor(),
branch,status));
constructTimeLikeLine(newBranch,child);
branch->addChild(newBranch);
}
}
// sort out the type of interaction
if(!branch->children().empty()) {
if(branch->branchingParticle()->id()==ParticleID::gamma ||
branch->children()[0]->branchingParticle()->id()==ParticleID::gamma ||
branch->children()[1]->branchingParticle()->id()==ParticleID::gamma)
branch->type(ShowerPartnerType::QED);
else {
if(branch->branchingParticle()->id()==
branch->children()[0]->branchingParticle()->id()) {
if(branch->branchingParticle()->dataPtr()->iColour()==PDT::Colour8) {
tShowerParticlePtr emittor =
branch->branchingParticle()->showerKinematics()->z()>0.5 ?
branch->children()[0]->branchingParticle() :
branch->children()[1]->branchingParticle();
if(branch->branchingParticle()->colourLine()==emittor->colourLine())
branch->type(ShowerPartnerType::QCDAntiColourLine);
else if(branch->branchingParticle()->antiColourLine()==emittor->antiColourLine())
branch->type(ShowerPartnerType::QCDColourLine);
else
assert(false);
}
else if(branch->branchingParticle()->colourLine()) {
branch->type(ShowerPartnerType::QCDColourLine);
}
else if(branch->branchingParticle()->antiColourLine()) {
branch->type(ShowerPartnerType::QCDAntiColourLine);
}
else
assert(false);
}
else if(branch->branchingParticle()->id()==ParticleID::g &&
branch->children()[0]->branchingParticle()->id()==
-branch->children()[1]->branchingParticle()->id()) {
if(branch->branchingParticle()->showerKinematics()->z()>0.5)
branch->type(ShowerPartnerType::QCDAntiColourLine);
else
branch->type(ShowerPartnerType::QCDColourLine);
}
else
assert(false);
}
}
}
void Evolver::constructSpaceLikeLine(tShowerParticlePtr particle,
HardBranchingPtr & first,
HardBranchingPtr & last,
SudakovPtr sud,PPtr beam) {
if(!particle) return;
if(!particle->parents().empty()) {
tShowerParticlePtr parent =
dynamic_ptr_cast<ShowerParticlePtr>(particle->parents()[0]);
SudakovPtr newSud=particle->showerKinematics()->SudakovFormFactor();
constructSpaceLikeLine(parent,first,last,newSud,beam);
}
HardBranchingPtr newBranch =
new_ptr(HardBranching(particle,sud,last,HardBranching::Incoming));
newBranch->beam(beam);
if(!first) {
first=newBranch;
last =newBranch;
return;
}
last->addChild(newBranch);
tShowerParticlePtr timeChild =
dynamic_ptr_cast<ShowerParticlePtr>(particle->parents()[0]->children()[1]);
HardBranchingPtr timeBranch;
if(!timeChild->children().empty()) {
timeBranch =
new_ptr(HardBranching(timeChild,
timeChild->showerKinematics()->SudakovFormFactor(),
last,HardBranching::Outgoing));
constructTimeLikeLine(timeBranch,timeChild);
}
else {
timeBranch =
new_ptr(HardBranching(timeChild,SudakovPtr(),last,HardBranching::Outgoing));
}
last->addChild(timeBranch);
// sort out the type
if(last->branchingParticle() ->id() == ParticleID::gamma ||
newBranch->branchingParticle() ->id() == ParticleID::gamma ||
timeBranch->branchingParticle()->id() == ParticleID::gamma) {
last->type(ShowerPartnerType::QED);
}
else if(last->branchingParticle()->id()==newBranch->branchingParticle()->id()) {
if(last->branchingParticle()->id()==ParticleID::g) {
if(last->branchingParticle()->colourLine()==
newBranch->branchingParticle()->colourLine()) {
last->type(ShowerPartnerType::QCDAntiColourLine);
}
else {
last->type(ShowerPartnerType::QCDColourLine);
}
}
else if(last->branchingParticle()->hasColour()) {
last->type(ShowerPartnerType::QCDColourLine);
}
else if(last->branchingParticle()->hasAntiColour()) {
last->type(ShowerPartnerType::QCDAntiColourLine);
}
else
assert(false);
}
else if(newBranch->branchingParticle()->id()==ParticleID::g) {
if(last->branchingParticle()->hasColour()) {
last->type(ShowerPartnerType::QCDAntiColourLine);
}
else if(last->branchingParticle()->hasAntiColour()) {
last->type(ShowerPartnerType::QCDColourLine);
}
else
assert(false);
}
else if(newBranch->branchingParticle()->hasColour()) {
last->type(ShowerPartnerType::QCDColourLine);
}
else if(newBranch->branchingParticle()->hasAntiColour()) {
last->type(ShowerPartnerType::QCDAntiColourLine);
}
else {
assert(false);
}
last=newBranch;
}
void Evolver::connectTrees(ShowerTreePtr showerTree,
HardTreePtr hardTree, bool hard ) {
ShowerParticleVector particles;
// find the Sudakovs
for(set<HardBranchingPtr>::iterator cit=hardTree->branchings().begin();
cit!=hardTree->branchings().end();++cit) {
// Sudakovs for ISR
if((**cit).parent()&&(**cit).status()==HardBranching::Incoming) {
++_nis;
IdList br(3);
br[0] = (**cit).parent()->branchingParticle()->id();
br[1] = (**cit). branchingParticle()->id();
br[2] = (**cit).parent()->children()[0]==*cit ?
(**cit).parent()->children()[1]->branchingParticle()->id() :
(**cit).parent()->children()[0]->branchingParticle()->id();
BranchingList branchings = splittingGenerator()->initialStateBranchings();
if(br[1]<0&&br[0]==br[1]) {
br[0] = abs(br[0]);
br[1] = abs(br[1]);
}
else if(br[1]<0) {
br[1] = -br[1];
br[2] = -br[2];
}
long index = abs(br[1]);
SudakovPtr sudakov;
for(BranchingList::const_iterator cjt = branchings.lower_bound(index);
cjt != branchings.upper_bound(index); ++cjt ) {
IdList ids = cjt->second.second;
if(ids[0]==br[0]&&ids[1]==br[1]&&ids[2]==br[2]) {
sudakov=cjt->second.first;
break;
}
}
if(!sudakov) throw Exception() << "Can't find Sudakov for the hard emission in "
<< "Evolver::connectTrees() for ISR"
<< Exception::runerror;
(**cit).parent()->sudakov(sudakov);
}
// Sudakovs for FSR
else if(!(**cit).children().empty()) {
++_nfs;
IdList br(3);
br[0] = (**cit) .branchingParticle()->id();
br[1] = (**cit).children()[0]->branchingParticle()->id();
br[2] = (**cit).children()[1]->branchingParticle()->id();
BranchingList branchings = splittingGenerator()->finalStateBranchings();
if(br[0]<0) {
br[0] = abs(br[0]);
br[1] = abs(br[1]);
br[2] = abs(br[2]);
}
long index = br[0];
SudakovPtr sudakov;
for(BranchingList::const_iterator cjt = branchings.lower_bound(index);
cjt != branchings.upper_bound(index); ++cjt ) {
IdList ids = cjt->second.second;
if(ids[0]==br[0]&&ids[1]==br[1]&&ids[2]==br[2]) {
sudakov=cjt->second.first;
break;
}
}
if(!sudakov) throw Exception() << "Can't find Sudakov for the hard emission in "
<< "Evolver::connectTrees()"
<< Exception::runerror;
(**cit).sudakov(sudakov);
}
}
// calculate the evolution scale
for(set<HardBranchingPtr>::iterator cit=hardTree->branchings().begin();
cit!=hardTree->branchings().end();++cit) {
particles.push_back((*cit)->branchingParticle());
}
showerModel()->partnerFinder()->
setInitialEvolutionScales(particles,!hard,hardTree->interaction(),
!hardTree->partnersSet());
hardTree->partnersSet(true);
// inverse reconstruction
if(hard)
showerModel()->kinematicsReconstructor()->
deconstructHardJets(hardTree,ShowerHandler::currentHandler()->evolver(),
hardTree->interaction());
else
showerModel()->kinematicsReconstructor()->
deconstructDecayJets(hardTree,ShowerHandler::currentHandler()->evolver(),
hardTree->interaction());
// now reset the momenta of the showering particles
vector<ShowerProgenitorPtr> particlesToShower;
for(map<ShowerProgenitorPtr,ShowerParticlePtr>::const_iterator
cit=showerTree->incomingLines().begin();
cit!=showerTree->incomingLines().end();++cit )
particlesToShower.push_back(cit->first);
// extract the showering particles
for(map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator
cit=showerTree->outgoingLines().begin();
cit!=showerTree->outgoingLines().end();++cit )
particlesToShower.push_back(cit->first);
// match them
vector<bool> matched(particlesToShower.size(),false);
for(set<HardBranchingPtr>::const_iterator cit=hardTree->branchings().begin();
cit!=hardTree->branchings().end();++cit) {
Energy2 dmin( 1e30*GeV2 );
int iloc(-1);
for(unsigned int ix=0;ix<particlesToShower.size();++ix) {
if(matched[ix]) continue;
if( (**cit).branchingParticle()->id() != particlesToShower[ix]->progenitor()->id() ) continue;
if( (**cit).branchingParticle()->isFinalState() !=
particlesToShower[ix]->progenitor()->isFinalState() ) continue;
Energy2 dtest =
sqr( particlesToShower[ix]->progenitor()->momentum().x() - (**cit).showerMomentum().x() ) +
sqr( particlesToShower[ix]->progenitor()->momentum().y() - (**cit).showerMomentum().y() ) +
sqr( particlesToShower[ix]->progenitor()->momentum().z() - (**cit).showerMomentum().z() ) +
sqr( particlesToShower[ix]->progenitor()->momentum().t() - (**cit).showerMomentum().t() );
// add mass difference for identical particles (e.g. Z0 Z0 production)
dtest += 1e10*sqr(particlesToShower[ix]->progenitor()->momentum().m()-
(**cit).showerMomentum().m());
if( dtest < dmin ) {
iloc = ix;
dmin = dtest;
}
}
if(iloc<0) throw Exception() << "Failed to match shower and hard trees in Evolver::hardestEmission"
<< Exception::eventerror;
particlesToShower[iloc]->progenitor()->set5Momentum((**cit).showerMomentum());
matched[iloc] = true;
}
// correction boosts for daughter trees
for(map<tShowerTreePtr,pair<tShowerProgenitorPtr,tShowerParticlePtr> >::const_iterator
tit = showerTree->treelinks().begin();
tit != showerTree->treelinks().end();++tit) {
ShowerTreePtr decayTree = tit->first;
map<ShowerProgenitorPtr,ShowerParticlePtr>::const_iterator
cit = decayTree->incomingLines().begin();
// reset the momentum of the decay particle
Lorentz5Momentum oldMomentum = cit->first->progenitor()->momentum();
Lorentz5Momentum newMomentum = tit->second.second->momentum();
LorentzRotation boost( oldMomentum.findBoostToCM(),oldMomentum.e()/oldMomentum.mass());
boost.boost (-newMomentum.findBoostToCM(),newMomentum.e()/newMomentum.mass());
decayTree->transform(boost,true);
}
}
void Evolver::doShowering(bool hard,XCPtr xcomb) {
// order of the interactions
bool showerOrder(true);
// zero number of emissions
_nis = _nfs = 0;
// extract particles to shower
vector<ShowerProgenitorPtr> particlesToShower(setupShower(hard));
// setup the maximum scales for the shower
if (hardVetoOn()) setupMaximumScales(particlesToShower,xcomb);
// specific stuff for hard processes and decays
Energy minmass(ZERO), mIn(ZERO);
// hard process generate the intrinsic p_T once and for all
if(hard) {
generateIntrinsicpT(particlesToShower);
}
// decay compute the minimum mass of the final-state
else {
for(unsigned int ix=0;ix<particlesToShower.size();++ix) {
if(particlesToShower[ix]->progenitor()->isFinalState()) {
if(particlesToShower[ix]->progenitor()->dataPtr()->stable())
minmass += particlesToShower[ix]->progenitor()->dataPtr()->constituentMass();
else
minmass += particlesToShower[ix]->progenitor()->mass();
}
else {
mIn = particlesToShower[ix]->progenitor()->mass();
}
}
// throw exception if decay can't happen
if ( minmass > mIn ) {
throw Exception() << "Evolver.cc: Mass of decaying particle is "
<< "below constituent masses of decay products."
<< Exception::eventerror;
}
}
// check if interactions in right order
if(hardTree() && interaction_!=4 &&
hardTree()->interaction()!=interactions_[0]) {
assert(interactions_.size()==2);
showerOrder = false;
swap(interactions_[0],interactions_[1]);
}
// loop over possible interactions
for(unsigned int inter=0;inter<interactions_.size();++inter) {
// set up for second pass if required
if(inter!=0) {
// zero intrinsic pt so only added first time round
intrinsicpT().clear();
// construct the tree and throw veto if not possible
if(!(hard ?
constructHardTree (particlesToShower,interactions_[inter]) :
constructDecayTree(particlesToShower,interactions_[inter])))
throw InteractionVeto();
}
// main shower loop
unsigned int ntry(0);
bool reconstructed = false;
do {
// clear results of last attempt if needed
if(ntry!=0) {
currentTree()->clear();
setEvolutionPartners(hard,interactions_[inter],true);
_nis = _nfs = 0;
}
// generate the shower
// pick random starting point
unsigned int istart=UseRandom::irnd(particlesToShower.size());
unsigned int istop = particlesToShower.size();
// loop over particles with random starting point
for(unsigned int ix=istart;ix<=istop;++ix) {
if(ix==particlesToShower.size()) {
if(istart!=0) {
istop = istart-1;
ix=0;
}
else break;
}
// extract the progenitor
progenitor(particlesToShower[ix]);
// final-state radiation
if(progenitor()->progenitor()->isFinalState()) {
if(!isFSRadiationON()) continue;
// perform shower
progenitor()->hasEmitted(startTimeLikeShower(interactions_[inter]));
}
// initial-state radiation
else {
if(!isISRadiationON()) continue;
// hard process
if(hard) {
// get the PDF
setBeamParticle(_progenitor->beam());
assert(beamParticle());
// perform the shower
// set the beam particle
tPPtr beamparticle=progenitor()->original();
if(!beamparticle->parents().empty())
beamparticle=beamparticle->parents()[0];
// generate the shower
progenitor()->hasEmitted(startSpaceLikeShower(beamparticle,
interactions_[inter]));
}
// decay
else {
// skip colour and electrically neutral particles
if(!progenitor()->progenitor()->dataPtr()->coloured() &&
!progenitor()->progenitor()->dataPtr()->charged()) {
progenitor()->hasEmitted(false);
continue;
}
// perform shower
// set the scales correctly. The current scale is the maximum scale for
// emission not the starting scale
ShowerParticle::EvolutionScales maxScales(progenitor()->progenitor()->scales());
progenitor()->progenitor()->scales() = ShowerParticle::EvolutionScales();
if(progenitor()->progenitor()->dataPtr()->charged()) {
progenitor()->progenitor()->scales().QED = progenitor()->progenitor()->mass();
progenitor()->progenitor()->scales().QED_noAO = progenitor()->progenitor()->mass();
}
if(progenitor()->progenitor()->hasColour()) {
progenitor()->progenitor()->scales().QCD_c = progenitor()->progenitor()->mass();
progenitor()->progenitor()->scales().QCD_c_noAO = progenitor()->progenitor()->mass();
}
if(progenitor()->progenitor()->hasAntiColour()) {
progenitor()->progenitor()->scales().QCD_ac = progenitor()->progenitor()->mass();
progenitor()->progenitor()->scales().QCD_ac_noAO = progenitor()->progenitor()->mass();
}
// perform the shower
progenitor()->hasEmitted(startSpaceLikeDecayShower(maxScales,minmass,
interactions_[inter]));
}
}
}
// do the kinematic reconstruction, checking if it worked
reconstructed = hard ?
showerModel()->kinematicsReconstructor()->
reconstructHardJets (currentTree(),intrinsicpT(),interactions_[inter]) :
showerModel()->kinematicsReconstructor()->
reconstructDecayJets(currentTree(),interactions_[inter]);
}
while(!reconstructed&&maximumTries()>++ntry);
// check if failed to generate the shower
if(ntry==maximumTries()) {
if(hard)
throw ShowerHandler::ShowerTriesVeto(ntry);
else
throw Exception() << "Failed to generate the shower after "
<< ntry << " attempts in Evolver::showerDecay()"
<< Exception::eventerror;
}
}
// tree has now showered
_currenttree->hasShowered(true);
if(!showerOrder) swap(interactions_[0],interactions_[1]);
hardTree(HardTreePtr());
}
diff --git a/Shower/Base/ShowerParticle.cc b/Shower/Base/ShowerParticle.cc
--- a/Shower/Base/ShowerParticle.cc
+++ b/Shower/Base/ShowerParticle.cc
@@ -1,43 +1,54 @@
// -*- C++ -*-
//
// ShowerParticle.cc is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 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 ShowerParticle class.
//
#include "ShowerParticle.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
+#include <ostream>
using namespace Herwig;
PPtr ShowerParticle::clone() const {
return new_ptr(*this);
}
PPtr ShowerParticle::fullclone() const {
return new_ptr(*this);
}
ClassDescription<ShowerParticle> ShowerParticle::initShowerParticle;
// Definition of the static class description member.
void ShowerParticle::vetoEmission(ShowerPartnerType::Type type, Energy scale) {
scales_.QED = min(scale,scales_.QED );
scales_.QED_noAO = min(scale,scales_.QED_noAO );
scales_.QCD_c = min(scale,scales_.QCD_c );
scales_.QCD_c_noAO = min(scale,scales_.QCD_c_noAO );
scales_.QCD_ac = min(scale,scales_.QCD_ac );
scales_.QCD_ac_noAO = min(scale,scales_.QCD_ac_noAO);
}
void ShowerParticle::addPartner(EvolutionPartner in ) {
partners_.push_back(in);
}
+
+ostream & operator<<(ostream & os, const ShowerParticle::EvolutionScales & es) {
+ os << "Scales: QED=" << es.QED / GeV
+ << " QCD_c=" << es.QCD_c / GeV
+ << " QCD_ac=" << es.QCD_ac / GeV
+ << " QED_noAO=" << es.QED_noAO / GeV
+ << " QCD_c_noAO" << es.QCD_c_noAO / GeV
+ << " QCD_ac_noAO" << es.QCD_ac_noAO / GeV
+ << '\n';
+}
diff --git a/Shower/Base/ShowerParticle.h b/Shower/Base/ShowerParticle.h
--- a/Shower/Base/ShowerParticle.h
+++ b/Shower/Base/ShowerParticle.h
@@ -1,440 +1,443 @@
// -*- C++ -*-
//
// ShowerParticle.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 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.
//
#ifndef HERWIG_ShowerParticle_H
#define HERWIG_ShowerParticle_H
//
// This is the declaration of the ShowerParticle class.
//
#include "ThePEG/EventRecord/Particle.h"
#include "Herwig++/Shower/SplittingFunctions/SplittingFunction.fh"
#include "Herwig++/Shower/ShowerConfig.h"
#include "ShowerKinematics.h"
#include "ShowerParticle.fh"
+#include <iosfwd>
namespace Herwig {
using namespace ThePEG;
/** \ingroup Shower
* This class represents a particle in the showering process.
* It inherits from the Particle class of ThePEG and has some
* specifics information useful only during the showering process.
*
* Notice that:
* - for forward evolution, it is clear what is meant by parent/child;
* for backward evolution, however, it depends whether we want
* to keep a physical picture or a Monte-Carlo effective one.
* In the former case, an incoming particle (emitting particle)
* splits into an emitted particle and the emitting particle after
* the emission: the latter two are then children of the
* emitting particle, the parent. In the Monte-Carlo effective
* picture, we have that the particle close to the hard subprocess,
* with higher (space-like) virtuality, splits into an emitted particle
* and the emitting particle at lower virtuality: the latter two are,
* in this case, the children of the first one, the parent. However we
* choose a more physical picture where the new emitting particle is the
* parented of the emitted final-state particle and the original emitting
* particle.
* - the pointer to a SplitFun object is set only in the case
* that the particle has undergone a shower emission. This is similar to
* the case of the decay of a normal Particle where
* the pointer to a Decayer object is set only in the case
* that the particle has undergone to a decay.
* In the case of particle connected directly to the hard subprocess,
* there is no pointer to the hard subprocess, but there is a method
* isFromHardSubprocess() which returns true only in this case.
*
* @see Particle
* @see ShowerConfig
* @see ShowerKinematics
*/
class ShowerParticle: public Particle {
public:
/**
* Struct for all the info on an evolution partner
*/
struct EvolutionPartner {
/**
* Constructor
*/
EvolutionPartner(tShowerParticlePtr p,double w, ShowerPartnerType::Type t,
Energy s) : partner(p), weight(w), type(t), scale(s)
{}
/**
* The partner
*/
tShowerParticlePtr partner;
/**
* Weight
*/
double weight;
/**
* Type
*/
ShowerPartnerType::Type type;
/**
* The assoicated evolution scale
*/
Energy scale;
};
/**
* Struct to store the evolution scales
*/
struct EvolutionScales {
/**
* Constructor
*/
EvolutionScales() : QED(),QCD_c(),QCD_ac(),
QED_noAO(),QCD_c_noAO(),QCD_ac_noAO()
{}
/**
* QED scale
*/
Energy QED;
/**
* QCD colour scale
*/
Energy QCD_c;
/**
* QCD anticolour scale
*/
Energy QCD_ac;
/**
* QED scale
*/
Energy QED_noAO;
/**
* QCD colour scale
*/
Energy QCD_c_noAO;
/**
* QCD anticolour scale
*/
Energy QCD_ac_noAO;
};
/** @name Construction and descruction functions. */
//@{
/**
* Standard Constructor. Note that the default constructor is
* private - there is no particle without a pointer to a
* ParticleData object.
* @param x the ParticleData object
* @param fs Whether or not the particle is an inital or final-state particle
* @param tls Whether or not the particle initiates a time-like shower
*/
ShowerParticle(tcEventPDPtr x, bool fs, bool tls=false)
: Particle(x), _isFinalState(fs),
_perturbative(0), _initiatesTLS(tls), _x(1.0), _showerKinematics(),
_vMass(ZERO), _thePEGBase() {}
/**
* Copy constructor from a ThePEG Particle
* @param x ThePEG particle
* @param pert Where the particle came from
* @param fs Whether or not the particle is an inital or final-state particle
* @param tls Whether or not the particle initiates a time-like shower
*/
ShowerParticle(const Particle & x, unsigned int pert, bool fs, bool tls=false)
: Particle(x), _isFinalState(fs),
_perturbative(pert), _initiatesTLS(tls), _x(1.0), _showerKinematics(),
_vMass(ZERO), _thePEGBase(&x) {}
//@}
public:
/**
* Access/Set various flags about the state of the particle
*/
//@{
/**
* Access the flag that tells if the particle is final state
* or initial state.
*/
bool isFinalState() const { return _isFinalState; }
/**
* Access the flag that tells if the particle is initiating a
* time like shower when it has been emitted in an initial state shower.
*/
bool initiatesTLS() const { return _initiatesTLS; }
/**
* Access the flag which tells us where the particle came from
* This is 0 for a particle produced in the shower, 1 if the particle came
* from the hard sub-process and 2 is it came from a decay.
*/
unsigned int perturbative() const { return _perturbative; }
//@}
/**
* Set/Get the momentum fraction for initial-state particles
*/
//@{
/**
* For an initial state particle get the fraction of the beam momentum
*/
void x(double x) { _x = x; }
/**
* For an initial state particle set the fraction of the beam momentum
*/
double x() const { return _x; }
//@}
/**
* Set/Get methods for the ShowerKinematics objects
*/
//@{
/**
* Access/ the ShowerKinematics object.
*/
const ShoKinPtr & showerKinematics() const { return _showerKinematics; }
/**
* Set the ShowerKinematics object.
*/
void showerKinematics(const ShoKinPtr in) { _showerKinematics = in; }
//@}
/**
* Members relating to the initial evolution scale and partner for the particle
*/
//@{
/**
* Veto emission at a given scale
*/
void vetoEmission(ShowerPartnerType::Type type, Energy scale);
/**
* Access to the evolution scales
*/
const EvolutionScales & scales() const {return scales_;}
/**
* Access to the evolution scales
*/
EvolutionScales & scales() {return scales_;}
/**
* Return the virtual mass\f$
*/
Energy virtualMass() const { return _vMass; }
/**
* Set the virtual mass
*/
void virtualMass(Energy mass) { _vMass = mass; }
/**
* Return the partner
*/
tShowerParticlePtr partner() const { return _partner; }
/**
* Set the partner
*/
void partner(const tShowerParticlePtr partner) { _partner = partner; }
/**
* Get the possible partners
*/
vector<EvolutionPartner> & partners() { return partners_; }
/**
* Add a possible partners
*/
void addPartner(EvolutionPartner in );
/**
* Clear the evolution partners
*/
void clearPartners() { partners_.clear(); }
/**
* Return the progenitor of the shower
*/
tShowerParticlePtr progenitor() const { return _progenitor; }
/**
* Set the progenitor of the shower
*/
void progenitor(const tShowerParticlePtr progenitor) { _progenitor = progenitor; }
//@}
/**
* Members to store and provide access to variables for a specific
* shower evolution scheme
*/
//@{
struct Parameters {
Parameters() : alpha(1.), beta(), ptx(), pty(), pt() {}
double alpha;
double beta;
Energy ptx;
Energy pty;
Energy pt;
};
/**
* Set the vector containing dimensionless variables
*/
Parameters & showerParameters() { return _parameters; }
//@}
/**
* If this particle came from the hard process get a pointer to ThePEG particle
* it came from
*/
const tcPPtr thePEGBase() const { return _thePEGBase; }
protected:
/**
* Standard clone function.
*/
virtual PPtr clone() const;
/**
* Standard clone function.
*/
virtual PPtr fullclone() const;
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<ShowerParticle> initShowerParticle;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
ShowerParticle & operator=(const ShowerParticle &);
private:
/**
* Whether the particle is in the final or initial state
*/
bool _isFinalState;
/**
* Whether the particle came from
*/
unsigned int _perturbative;
/**
* Does a particle produced in the backward shower initiate a time-like shower
*/
bool _initiatesTLS;
/**
* Dimensionless parameters
*/
Parameters _parameters;
/**
* The beam energy fraction for particle's in the initial state
*/
double _x;
/**
* The shower kinematics for the particle
*/
ShoKinPtr _showerKinematics;
/**
* Storage of the evolution scales
*/
EvolutionScales scales_;
/**
* Virtual mass
*/
Energy _vMass;
/**
* Partners
*/
tShowerParticlePtr _partner;
/**
* Pointer to ThePEG Particle this ShowerParticle was created from
*/
const tcPPtr _thePEGBase;
/**
* Progenitor
*/
tShowerParticlePtr _progenitor;
/**
* Partners
*/
vector<EvolutionPartner> partners_;
};
+ostream & operator<<(ostream & os, const ShowerParticle::EvolutionScales & es);
+
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of ShowerParticle. */
template <>
struct BaseClassTrait<Herwig::ShowerParticle,1> {
/** Typedef of the first base class of ShowerParticle. */
typedef Particle NthBase;
};
/** This template specialization informs ThePEG about the name of
* the ShowerParticle class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::ShowerParticle>
: public ClassTraitsBase<Herwig::ShowerParticle> {
/** Return a platform-independent class name */
static string className() { return "Herwig::ShowerParticle"; }
/** Create a Event object. */
static TPtr create() { return TPtr::Create(Herwig::ShowerParticle(tcEventPDPtr(),true)); }
};
/** @endcond */
}
#endif /* HERWIG_ShowerParticle_H */
diff --git a/Shower/Default/QTildeReconstructor.cc b/Shower/Default/QTildeReconstructor.cc
--- a/Shower/Default/QTildeReconstructor.cc
+++ b/Shower/Default/QTildeReconstructor.cc
@@ -1,2389 +1,2388 @@
// -*- C++ -*-
//
// QTildeReconstructor.cc is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 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 QTildeReconstructor class.
//
#include "QTildeReconstructor.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/EventRecord/Event.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/RefVector.h"
#include "Herwig++/Shower/Base/Evolver.h"
#include "Herwig++/Shower/Base/PartnerFinder.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "Herwig++/Shower/SplittingFunctions/SplittingFunction.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/EventRecord/ColourLine.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include <cassert>
using namespace Herwig;
DescribeClass<QTildeReconstructor,KinematicsReconstructor>
describeQTildeReconstructor("Herwig::QTildeReconstructor", "HwShower.so");
namespace {
enum SystemType { UNDEFINED=-1, II, IF, F ,I };
struct ColourSingletSystem {
ColourSingletSystem() : type(UNDEFINED) {}
ColourSingletSystem(SystemType intype,ShowerProgenitorPtr inpart)
: type(intype),jets(1,inpart) {}
/**
* The type of system
*/
SystemType type;
/**
* The jets in the system
*/
vector<ShowerProgenitorPtr> jets;
};
struct ColourSingletShower {
ColourSingletShower() : type(UNDEFINED) {}
ColourSingletShower(SystemType intype,HardBranchingPtr inpart)
: type(intype),jets(1,inpart) {}
/**
* The type of system
*/
SystemType type;
/**
* The jets in the system
*/
vector<HardBranchingPtr> jets;
};
void combineFinalStateSystem(vector<ColourSingletSystem> & systems) {
// check that 1 particle final-state systems which can be combine
bool canCombine(true);
for(unsigned int ix=0;ix<systems.size();++ix) {
if(systems[ix].type!=F) continue;
if(systems[ix].jets.size()!=1) canCombine = false;
}
// return if can't combine
if(!canCombine) return;
// otherwise combine them
vector<ColourSingletSystem> oldsystems=systems;
systems.clear();
ColourSingletSystem finalState;
finalState.type = F;
for(unsigned int ix=0;ix<oldsystems.size();++ix) {
if(oldsystems[ix].type==F) {
for(unsigned int iy=0;iy<oldsystems[ix].jets.size();++iy)
finalState.jets.push_back(oldsystems[ix].jets[iy]);
}
else
systems.push_back(oldsystems[ix]);
}
systems.push_back(finalState);
}
void combineFinalStateShower(vector<ColourSingletShower> & systems) {
// check that 1 particle final-state systems which can be combine
bool canCombine(true);
for(unsigned int ix=0;ix<systems.size();++ix) {
if(systems[ix].type!=F) continue;
if(systems[ix].jets.size()!=1) canCombine = false;
}
// return if can't combine
if(!canCombine) return;
// otherwise combine them
vector<ColourSingletShower> oldsystems=systems;
systems.clear();
ColourSingletShower finalState;
finalState.type = F;
for(unsigned int ix=0;ix<oldsystems.size();++ix) {
if(oldsystems[ix].type==F) {
for(unsigned int iy=0;iy<oldsystems[ix].jets.size();++iy)
finalState.jets.push_back(oldsystems[ix].jets[iy]);
}
else
systems.push_back(oldsystems[ix]);
}
systems.push_back(finalState);
}
/**
* Return colour line progenitor pointer for ShowerProgenitor
*/
Ptr<ThePEG::ColourLine>::transient_pointer
CL(ShowerProgenitorPtr a, unsigned int index=0) {
return const_ptr_cast<ThePEG::tColinePtr>(a->progenitor()->colourInfo()->colourLines()[index]);
}
/**
* Return progenitor colour line size for ShowerProgenitor
*/
unsigned int CLSIZE(ShowerProgenitorPtr a) {
return a->progenitor()->colourInfo()->colourLines().size();
}
/**
* Return anti-colour line progenitor pointer for ShowerProgenitor
*/
Ptr<ThePEG::ColourLine>::transient_pointer
ACL(ShowerProgenitorPtr a, unsigned int index=0) {
return const_ptr_cast<ThePEG::tColinePtr>(a->progenitor()->colourInfo()->antiColourLines()[index]);
}
/**
* Return progenitor anti-colour line size for ShowerProgenitor
*/
unsigned int ACLSIZE(ShowerProgenitorPtr a) {
return a->progenitor()->colourInfo()->antiColourLines().size();
}
/**
* Return colour line size
*/
unsigned int CLSIZE(set<HardBranchingPtr>::const_iterator & a) {
return (*a)->branchingParticle()->colourInfo()->colourLines().size();
}
/**
* Return anti-colour line size
*/
unsigned int ACLSIZE(set<HardBranchingPtr>::const_iterator & a) {
return (*a)->branchingParticle()->colourInfo()->antiColourLines().size();
}
}
void QTildeReconstructor::persistentOutput(PersistentOStream & os) const {
os << _reconopt << _initialBoost << ounit(_minQ,GeV) << _noRescale
<< _noRescaleVector;
}
void QTildeReconstructor::persistentInput(PersistentIStream & is, int) {
is >> _reconopt >> _initialBoost >> iunit(_minQ,GeV) >> _noRescale
>> _noRescaleVector;
}
void QTildeReconstructor::Init() {
static ClassDocumentation<QTildeReconstructor> documentation
( "This class is responsible for the kinematics reconstruction of the showering,",
" including the kinematics reshuffling necessary to compensate for the recoil"
"of the emissions." );
static Switch<QTildeReconstructor,unsigned int> interfaceReconstructionOption
("ReconstructionOption",
"Option for the kinematics reconstruction",
&QTildeReconstructor::_reconopt, 0, false, false);
static SwitchOption interfaceReconstructionOptionGeneral
(interfaceReconstructionOption,
"General",
"Use the general solution which ignores the colour structure for all processes",
0);
static SwitchOption interfaceReconstructionOptionColour
(interfaceReconstructionOption,
"Colour",
"Use the colour structure of the process to determine the reconstruction procedure.",
1);
static Parameter<QTildeReconstructor,Energy> interfaceMinimumQ2
("MinimumQ2",
"The minimum Q2 for the reconstruction of initial-final systems",
&QTildeReconstructor::_minQ, GeV, 0.001*GeV, 1e-6*GeV, 10.0*GeV,
false, false, Interface::limited);
static RefVector<QTildeReconstructor,ParticleData> interfaceNoRescale
("NoRescale",
"Particles which shouldn't be rescaled to be on shell by the shower",
&QTildeReconstructor::_noRescaleVector, -1, false, false, true, false, false);
static Switch<QTildeReconstructor,unsigned int> interfaceInitialInitialBoostOption
("InitialInitialBoostOption",
"Option for how the boost from the system before ISR to that after ISR is applied.",
&QTildeReconstructor::_initialBoost, 0, false, false);
static SwitchOption interfaceInitialInitialBoostOptionOneBoost
(interfaceInitialInitialBoostOption,
"OneBoost",
"Apply one boost from old CMS to new CMS",
0);
static SwitchOption interfaceInitialInitialBoostOptionLongTransBoost
(interfaceInitialInitialBoostOption,
"LongTransBoost",
"First apply a longitudinal and then a transverse boost",
1);
}
void QTildeReconstructor::doinit() {
KinematicsReconstructor::doinit();
_noRescale = set<cPDPtr>(_noRescaleVector.begin(),_noRescaleVector.end());
}
bool QTildeReconstructor::
reconstructTimeLikeJet(const tShowerParticlePtr particleJetParent,
unsigned int iopt) const {
assert(particleJetParent);
bool emitted=true;
// if this is not a fixed point in the reconstruction
if( !particleJetParent->children().empty() ) {
// if not a reconstruction fixpoint, dig deeper for all children:
for ( ParticleVector::const_iterator cit =
particleJetParent->children().begin();
cit != particleJetParent->children().end(); ++cit )
reconstructTimeLikeJet(dynamic_ptr_cast<ShowerParticlePtr>(*cit),iopt);
}
// it is a reconstruction fixpoint, ie kinematical data has to be available
else {
// check if the parent was part of the shower
ShowerParticlePtr jetGrandParent;
if(!particleJetParent->parents().empty())
jetGrandParent= dynamic_ptr_cast<ShowerParticlePtr>
(particleJetParent->parents()[0]);
// update if so
if (jetGrandParent) {
if (jetGrandParent->showerKinematics()) {
if(particleJetParent->id()==_progenitor->id()&&
!_progenitor->data().stable()) {
jetGrandParent->showerKinematics()->reconstructLast(particleJetParent,iopt,
_progenitor->mass());
}
else {
jetGrandParent->showerKinematics()->reconstructLast(particleJetParent,iopt);
}
}
}
// otherwise
else {
Energy dm = particleJetParent->data().constituentMass();
if (abs(dm-particleJetParent->momentum().m())>0.001*MeV
&&particleJetParent->dataPtr()->stable()
&&particleJetParent->id()!=ParticleID::gamma
&&_noRescale.find(particleJetParent->dataPtr())==_noRescale.end()) {
Lorentz5Momentum dum = particleJetParent->momentum();
if(dm>dum.e()) throw KinematicsReconstructionVeto();
dum.setMass(dm);
dum.rescaleRho();
particleJetParent->set5Momentum(dum);
}
else {
emitted=false;
}
}
}
// recursion has reached an endpoint once, ie we can reconstruct the
// kinematics from the children.
if( !particleJetParent->children().empty() )
particleJetParent->showerKinematics()
->reconstructParent( particleJetParent, particleJetParent->children() );
return emitted;
}
bool QTildeReconstructor::
reconstructHardJets(ShowerTreePtr hard,
const map<tShowerProgenitorPtr,
pair<Energy,double> > & intrinsic,
ShowerInteraction::Type type) const {
_currentTree = hard;
_intrinsic=intrinsic;
// extract the particles from the ShowerTree
vector<ShowerProgenitorPtr> ShowerHardJets=hard->extractProgenitors();
try {
// old recon method, using new member functions
if(_reconopt==0) {
reconstructGeneralSystem(ShowerHardJets);
}
// reconstruction based on coloured systems
else {
// identify the colour singlet systems
vector<ColourSingletSystem> systems;
vector<bool> done(ShowerHardJets.size(),false);
for(unsigned int ix=0;ix<ShowerHardJets.size();++ix) {
// if not treated create new system
if(done[ix]) continue;
systems.push_back(ColourSingletSystem(UNDEFINED,ShowerHardJets[ix]));
done[ix] = true;
if(!ShowerHardJets[ix]->progenitor()->coloured()) continue;
// now find the colour connected particles
vector<unsigned int> iloc(1,ix);
do {
vector<unsigned int> temp=findPartners(iloc.back(),ShowerHardJets);
iloc.pop_back();
for(unsigned int iy=0;iy<temp.size();++iy) {
if(!done[temp[iy]]) {
done[temp[iy]] = true;
iloc.push_back(temp[iy]);
systems.back().jets.push_back(ShowerHardJets[temp[iy]]);
}
}
}
while(!iloc.empty());
}
// catagorize the systems
unsigned int nnun(0),nnii(0),nnif(0),nnf(0),nni(0);
for(unsigned int ix=0;ix<systems.size();++ix) {
unsigned int ni(0),nf(0);
for(unsigned int iy=0;iy<systems[ix].jets.size();++iy) {
if(systems[ix].jets[iy]->progenitor()->isFinalState()) ++nf;
else ++ni;
}
// type
// initial-initial
if(ni==2&&nf==0) {
systems[ix].type = II;
++nnii;
}
// initial only
else if(ni==1&&nf==0) {
systems[ix].type = I;
++nni;
}
// initial-final
else if(ni==1&&nf>0) {
systems[ix].type = IF;
++nnif;
}
// final only
else if(ni==0&&nf>0) {
systems[ix].type = F;
++nnf;
}
// otherwise unknown
else {
systems[ix].type = UNDEFINED;
++nnun;
}
}
// now decide what to do
// initial-initial connection and final-state colour singlet systems
LorentzRotation toRest,fromRest;
bool applyBoost(false);
bool general(false);
// Drell-Yan type
if(nnun==0&&nnii==1&&nnif==0&&nnf>0&&nni==0) {
// reconstruct initial-initial system
for(unsigned int ix=0;ix<systems.size();++ix) {
if(systems[ix].type==II)
reconstructInitialInitialSystem(applyBoost,toRest,fromRest,
systems[ix].jets);
}
if(type==ShowerInteraction::QED||
type==ShowerInteraction::Both) {
combineFinalStateSystem(systems);
general=false;
}
}
// DIS and VBF type
else if(nnun==0&&nnii==0&&((nnif==1&&nnf>0&&nni==1)||
(nnif==2&& nni==0))) {
// check these systems can be reconstructed
for(unsigned int ix=0;ix<systems.size();++ix) {
// compute q^2
if(systems[ix].type!=IF) continue;
Lorentz5Momentum q;
for(unsigned int iy=0;iy<systems[ix].jets.size();++iy) {
if(systems[ix].jets[iy]->progenitor()->isFinalState())
q += systems[ix].jets[iy]->progenitor()->momentum();
else
q -= systems[ix].jets[iy]->progenitor()->momentum();
}
q.rescaleMass();
// check above cut
if(abs(q.m())>=_minQ) continue;
if(nnif==1&&nni==1) {
throw KinematicsReconstructionVeto();
}
else {
general = true;
break;
}
}
if(!general) {
for(unsigned int ix=0;ix<systems.size();++ix) {
if(systems[ix].type==IF)
reconstructInitialFinalSystem(systems[ix].jets);
}
}
}
// e+e- type
else if(nnun==0&&nnii==0&&nnif==0&&nnf>0&&nni==2) {
general = type==ShowerInteraction::QED;
}
// general type
else {
general = true;
}
// final-state systems except for general recon
if(!general) {
for(unsigned int ix=0;ix<systems.size();++ix) {
if(systems[ix].type==F)
reconstructFinalStateSystem(applyBoost,toRest,fromRest,
systems[ix].jets);
}
}
else {
reconstructGeneralSystem(ShowerHardJets);
}
}
}
catch(KinematicsReconstructionVeto) {
_progenitor=tShowerParticlePtr();
_intrinsic.clear();
_currentTree = tShowerTreePtr();
return false;
}
_progenitor=tShowerParticlePtr();
_intrinsic.clear();
// ensure x<1
for(map<ShowerProgenitorPtr,ShowerParticlePtr>::const_iterator
cit=hard->incomingLines().begin();cit!=hard->incomingLines().end();++cit) {
tPPtr parent = cit->first->progenitor();
while (!parent->parents().empty()) {
parent = parent->parents()[0];
}
tPPtr hadron;
if ( cit->first->original()->parents().empty() ) {
hadron = cit->first->original();
}
else {
hadron = cit->first->original()->parents()[0];
}
if( ! (hadron->id() == parent->id() && hadron->children().size() <= 1)
&& parent->momentum().rho() > hadron->momentum().rho()) {
_currentTree = tShowerTreePtr();
return false;
}
}
_currentTree = tShowerTreePtr();
return true;
}
double
QTildeReconstructor::solveKfactor(const Energy & root_s,
const JetKinVect & jets) const {
Energy2 s = sqr(root_s);
// must be at least two jets
if ( jets.size() < 2) throw KinematicsReconstructionVeto();
// sum of jet masses must be less than roots
if(momConsEq( 0.0, root_s, jets )>ZERO) throw KinematicsReconstructionVeto();
// if two jets simple solution
if ( jets.size() == 2 ) {
static const Energy2 eps = 1.0e-4 * MeV2;
if ( sqr(jets[0].p.x()+jets[1].p.x()) < eps &&
sqr(jets[0].p.y()+jets[1].p.y()) < eps &&
sqr(jets[0].p.z()+jets[1].p.z()) < eps ) {
Energy test = (jets[0].p+jets[1].p).vect().mag();
if(test > 1.0e-4 * MeV) throw KinematicsReconstructionVeto();
Energy2 m1sq(jets[0].q.m2()),m2sq(jets[1].q.m2());
return sqrt( ( sqr(s - m1sq - m2sq) - 4.*m1sq*m2sq )
/(4.*s*jets[0].p.vect().mag2()) );
}
else throw KinematicsReconstructionVeto();
}
// i.e. jets.size() > 2, numerically
// check convergence, if it's a problem maybe use Newton iteration?
else {
double k1 = 0.,k2 = 1.,k = 0.;
if ( momConsEq( k1, root_s, jets ) < ZERO ) {
while ( momConsEq( k2, root_s, jets ) < ZERO ) {
k1 = k2;
k2 *= 2;
}
while ( fabs( (k1 - k2)/(k1 + k2) ) > 1.e-10 ) {
if( momConsEq( k2, root_s, jets ) == ZERO ) {
return k2;
} else {
k = (k1+k2)/2.;
if ( momConsEq( k, root_s, jets ) > ZERO ) {
k2 = k;
} else {
k1 = k;
}
}
}
return k1;
} else throw KinematicsReconstructionVeto();
}
throw KinematicsReconstructionVeto();
}
bool QTildeReconstructor::
reconstructSpaceLikeJet( const tShowerParticlePtr p) const {
bool emitted = true;
tShowerParticlePtr child;
tShowerParticlePtr parent;
if(!p->parents().empty())
parent = dynamic_ptr_cast<ShowerParticlePtr>(p->parents()[0]);
if(parent) {
emitted=true;
reconstructSpaceLikeJet(parent);
}
// if branching reconstruct time-like child
if(p->children().size()==2)
child = dynamic_ptr_cast<ShowerParticlePtr>(p->children()[1]);
if(p->perturbative()==0 && child) {
dynamic_ptr_cast<ShowerParticlePtr>(p->children()[0])->
showerKinematics()->reconstructParent(p,p->children());
if(!child->children().empty()) {
_progenitor=child;
reconstructTimeLikeJet(child,0);
// calculate the momentum of the particle
Lorentz5Momentum pnew=p->momentum()-child->momentum();
pnew.rescaleMass();
p->children()[0]->set5Momentum(pnew);
}
}
return emitted;
}
Boost QTildeReconstructor::
solveBoostBeta( const double k, const Lorentz5Momentum & newq,
const Lorentz5Momentum & oldp ) {
// try something different, purely numerical first:
// a) boost to rest frame of newq, b) boost with kp/E
Energy q = newq.vect().mag();
Energy2 qs = sqr(q);
Energy2 Q2 = newq.m2();
Energy kp = k*(oldp.vect().mag());
Energy2 kps = sqr(kp);
// usually we take the minus sign, since this boost will be smaller.
// we only require |k \vec p| = |\vec q'| which leaves the sign of
// the boost open but the 'minus' solution gives a smaller boost
// parameter, i.e. the result should be closest to the previous
// result. this is to be changed if we would get many momentum
// conservation violations at the end of the shower from a hard
// process.
double betam = (q*sqrt(qs + Q2) - kp*sqrt(kps + Q2))/(kps + qs + Q2);
// move directly to 'return'
Boost beta = -betam*(k/kp)*oldp.vect();
// note that (k/kp)*oldp.vect() = oldp.vect()/oldp.vect().mag() but cheaper.
// leave this out if it's running properly!
if ( betam >= 0 ) return beta;
else return Boost(0., 0., 0.);
}
bool QTildeReconstructor::
reconstructDecayJets(ShowerTreePtr decay,
ShowerInteraction::Type) const {
_currentTree = decay;
try {
// extract the particles from the ShowerTree
vector<ShowerProgenitorPtr> ShowerHardJets=decay->extractProgenitors();
bool radiated[2]={false,false};
// find the decaying particle and check if particles radiated
ShowerProgenitorPtr initial;
for(unsigned int ix=0;ix<ShowerHardJets.size();++ix) {
// only consider initial-state jets
if(ShowerHardJets[ix]->progenitor()->isFinalState()) {
radiated[1] |=ShowerHardJets[ix]->hasEmitted();
}
else {
initial=ShowerHardJets[ix];
radiated[0]|=ShowerHardJets[ix]->hasEmitted();
}
}
// find boost to the rest frame if needed
Boost boosttorest=-initial->progenitor()->momentum().boostVector();
double gammarest =
initial->progenitor()->momentum().e()/
initial->progenitor()->momentum().mass();
// check if need to boost to rest frame
bool gottaBoost = (boosttorest.mag() > 1e-12);
// if initial state radiation reconstruct the jet and set up the basis vectors
Lorentz5Momentum pjet;
Lorentz5Momentum nvect;
// find the partner
ShowerParticlePtr partner = initial->progenitor()->partner();
Lorentz5Momentum ppartner[2];
if(partner) ppartner[0]=partner->momentum();
// get the n reference vector
if(partner) {
if(initial->progenitor()->showerKinematics()) {
nvect = initial->progenitor()->showerKinematics()->getBasis()[1];
}
else {
Lorentz5Momentum ppartner=initial->progenitor()->partner()->momentum();
if(gottaBoost) ppartner.boost(boosttorest,gammarest);
nvect = Lorentz5Momentum( ZERO,0.5*initial->progenitor()->mass()*
ppartner.vect().unit());
nvect.boost(-boosttorest,gammarest);
}
}
// if ISR
if(radiated[0]) {
// reconstruct the decay jet
reconstructDecayJet(initial->progenitor());
// momentum of decaying particle after ISR
pjet=initial->progenitor()->momentum()
-decay->incomingLines().begin()->second->momentum();
pjet.rescaleMass();
}
// boost initial state jet and basis vector if needed
if(gottaBoost) {
pjet.boost(boosttorest,gammarest);
nvect.boost(boosttorest,gammarest);
ppartner[0].boost(boosttorest,gammarest);
}
// loop over the final-state particles and do the reconstruction
JetKinVect possiblepartners;
JetKinVect jetKinematics;
bool atLeastOnce = radiated[0];
LorentzRotation restboost(boosttorest,gammarest);
Energy inmass(ZERO);
for(unsigned int ix=0;ix<ShowerHardJets.size();++ix) {
// only consider final-state jets
if(!ShowerHardJets[ix]->progenitor()->isFinalState()) {
inmass=ShowerHardJets[ix]->progenitor()->mass();
continue;
}
// do the reconstruction
JetKinStruct tempJetKin;
tempJetKin.parent = ShowerHardJets[ix]->progenitor();
if(ShowerHardJets.size()==2) {
Lorentz5Momentum dum=ShowerHardJets[ix]->progenitor()->momentum();
dum.setMass(inmass);
dum.rescaleRho();
tempJetKin.parent->set5Momentum(dum);
}
tempJetKin.p = ShowerHardJets[ix]->progenitor()->momentum();
if(gottaBoost) tempJetKin.p.boost(boosttorest,gammarest);
_progenitor=tempJetKin.parent;
atLeastOnce |= reconstructTimeLikeJet(tempJetKin.parent,0);
if(gottaBoost) deepTransform(tempJetKin.parent,restboost);
tempJetKin.q = ShowerHardJets[ix]->progenitor()->momentum();
jetKinematics.push_back(tempJetKin);
}
if(partner) ppartner[1]=partner->momentum();
// calculate the rescaling parameters
double k1,k2;
Lorentz5Momentum qt;
if(!solveDecayKFactor(initial->progenitor()->mass(),nvect,pjet,
jetKinematics,partner,ppartner,k1,k2,qt)) {
_currentTree = tShowerTreePtr();
return false;
}
// apply boosts and rescalings to final-state jets
for(JetKinVect::iterator it = jetKinematics.begin();
it != jetKinematics.end(); ++it) {
LorentzRotation Trafo = LorentzRotation();
if(it->parent!=partner) {
// boost for rescaling
if(atLeastOnce) {
map<tShowerTreePtr,pair<tShowerProgenitorPtr,
tShowerParticlePtr> >::const_iterator tit;
for(tit = _currentTree->treelinks().begin();
tit != _currentTree->treelinks().end();++tit) {
if(tit->second.first && tit->second.second==it->parent)
break;
}
if(it->parent->children().empty()&&!it->parent->spinInfo() &&
tit==_currentTree->treelinks().end()) {
Lorentz5Momentum pnew(k2*it->p.vect(),
sqrt(sqr(k2*it->p.vect().mag())+it->q.mass2()),
it->q.mass());
it->parent->set5Momentum(pnew);
}
else {
// rescaling boost can't ever work in this case
if(k2<0. && it->q.mass()==ZERO)
throw KinematicsReconstructionVeto();
Trafo = solveBoost(k2, it->q, it->p);
}
}
if(gottaBoost) Trafo.boost(-boosttorest,gammarest);
if(atLeastOnce || gottaBoost) deepTransform(it->parent,Trafo);
}
else {
Lorentz5Momentum pnew=ppartner[0];
pnew *=k1;
pnew-=qt;
pnew.setMass(ppartner[1].mass());
pnew.rescaleEnergy();
LorentzRotation Trafo=solveBoost(1.,ppartner[1],pnew);
if(gottaBoost) Trafo.boost(-boosttorest,gammarest);
deepTransform(partner,Trafo);
}
}
}
catch(KinematicsReconstructionVeto) {
_currentTree = tShowerTreePtr();
return false;
}
_currentTree = tShowerTreePtr();
return true;
}
bool QTildeReconstructor::
reconstructDecayJet( const tShowerParticlePtr p) const {
if(p->children().empty()) return false;
tShowerParticlePtr child;
// if branching reconstruct time-like child
child = dynamic_ptr_cast<ShowerParticlePtr>(p->children()[1]);
if(child) {
_progenitor=child;
reconstructTimeLikeJet(child,1);
// calculate the momentum of the particle
Lorentz5Momentum pnew=p->momentum()-child->momentum();
pnew.rescaleMass();
p->children()[0]->set5Momentum(pnew);
child=dynamic_ptr_cast<ShowerParticlePtr>(p->children()[0]);
reconstructDecayJet(child);
return true;
}
return false;
}
bool QTildeReconstructor::
solveDecayKFactor(Energy mb,
const Lorentz5Momentum & n,
const Lorentz5Momentum & pjet,
const JetKinVect & jetKinematics,
ShowerParticlePtr partner,
Lorentz5Momentum ppartner[2],
double & k1, double & k2,
Lorentz5Momentum & qt) const {
Energy2 pjn = partner ? pjet.vect()*n.vect() : ZERO;
Energy2 pcn = partner ? ppartner[0].vect()*n.vect() : 1.*MeV2;
Energy2 nmag = n.vect().mag2();
Lorentz5Momentum pn = partner ? (pjn/nmag)*n : Lorentz5Momentum();
qt=pjet-pn; qt.setE(ZERO);
Energy2 pt2=qt.vect().mag2();
Energy Ejet = pjet.e();
// magnitudes of the momenta for fast access
vector<Energy2> pmag;
Energy total(Ejet);
for(unsigned int ix=0;ix<jetKinematics.size();++ix) {
pmag.push_back(jetKinematics[ix].p.vect().mag2());
total+=jetKinematics[ix].q.mass();
}
// return if no possible solution
if(total>mb) return false;
Energy2 pcmag=ppartner[0].vect().mag2();
// used newton-raphson to get the rescaling
static const Energy eps=1e-8*GeV;
long double d1(1.),d2(1.);
Energy roots, ea, ec, ds;
unsigned int ix=0;
do {
++ix;
d2 = d1 + pjn/pcn;
roots = Ejet;
ds = ZERO;
for(unsigned int iy=0;iy<jetKinematics.size();++iy) {
if(jetKinematics[iy].parent==partner) continue;
ea = sqrt(sqr(d2)*pmag[iy]+jetKinematics[iy].q.mass2());
roots += ea;
ds += d2/ea*pmag[iy];
}
if(partner) {
ec = sqrt(sqr(d1)*pcmag + pt2 + ppartner[1].mass2());
roots += ec;
ds += d1/ec*pcmag;
}
d1 += (mb-roots)/ds;
d2 = d1 + pjn/pcn;
}
while(abs(mb-roots)>eps && ix<100);
k1=d1;
k2=d2;
// return true if N-R succeed, otherwise false
return ix<100;
}
bool QTildeReconstructor::
deconstructDecayJets(HardTreePtr decay, cEvolverPtr,
ShowerInteraction::Type) const {
// extract the momenta of the particles
vector<Lorentz5Momentum> pin;
vector<Lorentz5Momentum> pout;
// on-shell masses of the decay products
vector<Energy> mon;
Energy mbar(-GeV);
// the hard branchings of the particles
set<HardBranchingPtr>::iterator cit;
set<HardBranchingPtr> branchings=decay->branchings();
// properties of the incoming particle
bool ISR = false;
HardBranchingPtr initial;
Lorentz5Momentum qisr;
// find the incoming particle, both before and after
// any ISR
for(cit=branchings.begin();cit!=branchings.end();++cit){
if((*cit)->status()==HardBranching::Incoming||
(*cit)->status()==HardBranching::Decay) {
// search back up isr if needed
HardBranchingPtr branch = *cit;
while(branch->parent()) branch=branch->parent();
initial=branch;
// momentum or original parent
pin.push_back(branch->branchingParticle()->momentum());
// ISR?
ISR = !branch->branchingParticle()->children().empty();
// ISR momentum
qisr = pin.back()-(**cit).branchingParticle()->momentum();
qisr.rescaleMass();
}
}
assert(pin.size()==1);
// compute boost to rest frame
Boost boostv=-pin[0].boostVector();
// partner for ISR
ShowerParticlePtr partner;
Lorentz5Momentum ppartner;
if(initial->branchingParticle()->partner()) {
partner=initial->branchingParticle()->partner();
ppartner=partner->momentum();
}
// momentum of the decay products
for(cit=branchings.begin();cit!=branchings.end();++cit) {
if((*cit)->status()!=HardBranching::Outgoing) continue;
// find the mass of the particle
// including special treatment for off-shell resonances
// to preserve off-shell mass
Energy mass;
if(!(**cit).branchingParticle()->dataPtr()->stable()) {
HardBranchingPtr branch=*cit;
while(!branch->children().empty()) {
for(unsigned int ix=0;ix<branch->children().size();++ix) {
if(branch->children()[ix]->branchingParticle()->id()==
(**cit).branchingParticle()->id()) {
branch = branch->children()[ix];
continue;
}
}
};
mass = branch->branchingParticle()->mass();
}
else {
mass = (**cit).branchingParticle()->dataPtr()->mass();
}
// if not evolution partner of decaying particle
if((*cit)->branchingParticle()!=partner) {
pout.push_back((*cit)->branchingParticle()->momentum());
mon.push_back(mass);
}
// evolution partner of decaying particle
else {
mbar = mass;
}
}
// boost all the momenta to the rest frame of the decaying particle
for(unsigned int ix=0;ix<pout.size();++ix) pout[ix].boost(boostv);
if(initial->branchingParticle()->partner()) {
ppartner.boost(boostv);
qisr.boost(boostv);
}
// compute the rescaling factors
double k1,k2;
if(!ISR) {
if(partner) {
pout.push_back(ppartner);
mon.push_back(mbar);
}
k1=k2=inverseRescalingFactor(pout,mon,pin[0].mass());
if(partner) {
pout.pop_back();
mon.pop_back();
}
}
else {
if(!inverseDecayRescalingFactor(pout,mon,pin[0].mass(),
ppartner,mbar,k1,k2)) return false;
}
// now calculate the p reference vectors
unsigned int ifinal=0;
for(cit=branchings.begin();cit!=branchings.end();++cit) {
if((**cit).status()!=HardBranching::Outgoing) continue;
// for partners other than colour partner of decaying particle
if((*cit)->branchingParticle()!=partner) {
Lorentz5Momentum pvect = (*cit)->branchingParticle()->momentum();
pvect.boost(boostv);
pvect /= k1;
pvect.setMass(mon[ifinal]);
++ifinal;
pvect.rescaleEnergy();
pvect.boost(-boostv);
(*cit)->pVector(pvect);
(*cit)->showerMomentum(pvect);
}
// for colour partner of decaying particle
else {
Lorentz5Momentum pvect = (*cit)->branchingParticle()->momentum();
pvect.boost(boostv);
Lorentz5Momentum qtotal;
for(unsigned int ix=0;ix<pout.size();++ix) qtotal+=pout[ix];
Lorentz5Momentum qperp =
qisr-(qisr.vect()*qtotal.vect())/(qtotal.vect().mag2())*qtotal;
pvect +=qperp;
pvect /=k2;
pvect.setMass(mbar);
pvect.rescaleEnergy();
pvect.boost(-boostv);
(*cit)->pVector(pvect);
(*cit)->showerMomentum(pvect);
}
}
// // find the evolution partners
// ShowerParticleVector particles;
// particles.push_back((**decay->incoming().begin()).branchingParticle());
// for(cit=branchings.begin();cit!=branchings.end();++cit) {
// if((**cit).status()==HardBranching::Outgoing)
// particles.push_back((*cit)->branchingParticle());
// }
// // partners should
// evolver->showerModel()->partnerFinder()
// ->setInitialEvolutionScales(particles,true,type,false);
// For initial-state if needed
if(initial) {
tShowerParticlePtr newPartner=initial->branchingParticle()->partner();
if(newPartner) {
tHardBranchingPtr branch;
for( set<HardBranchingPtr>::iterator clt = branchings.begin();
clt != branchings.end(); ++clt ) {
if((**clt).branchingParticle()==newPartner) {
initial->colourPartner(*clt);
branch=*clt;
break;
}
}
Lorentz5Momentum pvect = initial->branchingParticle()->momentum();
initial->pVector(pvect);
Lorentz5Momentum ptemp = branch->pVector();
ptemp.boost(boostv);
Lorentz5Momentum nvect = Lorentz5Momentum( ZERO,
0.5*initial->branchingParticle()->mass()*
ptemp.vect().unit());
nvect.boost(-boostv);
initial->nVector(nvect);
}
}
// calculate the reference vectors, then for outgoing particles
for(cit=branchings.begin();cit!=branchings.end();++cit){
if((**cit).status()!=HardBranching::Outgoing) continue;
// find the partner branchings
tShowerParticlePtr newPartner=(*cit)->branchingParticle()->partner();
if(!newPartner) continue;
tHardBranchingPtr branch;
for( set<HardBranchingPtr>::iterator clt = branchings.begin();
clt != branchings.end(); ++clt ) {
if(cit==clt) continue;
if((**clt).branchingParticle()==newPartner) {
(**cit).colourPartner(*clt);
branch=*clt;
break;
}
}
if((**decay->incoming().begin()).branchingParticle()==newPartner) {
(**cit).colourPartner(*decay->incoming().begin());
branch = *decay->incoming().begin();
}
// final-state colour partner
if(branch->status()==HardBranching::Outgoing) {
Boost boost=((*cit)->pVector()+branch->pVector()).findBoostToCM();
Lorentz5Momentum pcm = branch->pVector();
pcm.boost(boost);
Lorentz5Momentum nvect = Lorentz5Momentum(ZERO,pcm.vect());
nvect.boost( -boost);
(*cit)->nVector(nvect);
}
// initial-state colour partner
else {
Boost boost=branch->pVector().findBoostToCM();
Lorentz5Momentum pcm = (*cit)->pVector();
pcm.boost(boost);
Lorentz5Momentum nvect = Lorentz5Momentum( ZERO, -pcm.vect());
nvect.boost( -boost);
(*cit)->nVector(nvect);
}
}
// now compute the new momenta
// and calculate the shower variables
for(cit=branchings.begin();cit!=branchings.end();++cit) {
if((**cit).status()!=HardBranching::Outgoing) continue;
LorentzRotation B=LorentzRotation(-boostv);
LorentzRotation A=LorentzRotation(boostv),R;
if((*cit)->branchingParticle()==partner) {
Lorentz5Momentum qnew;
Energy2 dot=(*cit)->pVector()*(*cit)->nVector();
double beta = 0.5*((*cit)->branchingParticle()->momentum().m2()
-sqr((*cit)->pVector().mass()))/dot;
qnew=(*cit)->pVector()+beta*(*cit)->nVector();
qnew.rescaleMass();
// compute the boost
R=B*solveBoost(A*qnew,A*(*cit)->branchingParticle()->momentum())*A;
}
else {
Lorentz5Momentum qnew;
if((*cit)->branchingParticle()->partner()) {
Energy2 dot=(*cit)->pVector()*(*cit)->nVector();
double beta = 0.5*((*cit)->branchingParticle()->momentum().m2()
-sqr((*cit)->pVector().mass()))/dot;
qnew=(*cit)->pVector()+beta*(*cit)->nVector();
qnew.rescaleMass();
}
else {
qnew = (*cit)->pVector();
}
// compute the boost
R=B*solveBoost(A*qnew,A*(*cit)->branchingParticle()->momentum())*A;
}
// reconstruct the momenta
(*cit)->setMomenta(R,1.0,Lorentz5Momentum());
}
if(initial) {
initial->setMomenta(LorentzRotation(),1.0,Lorentz5Momentum());
}
return true;
}
double QTildeReconstructor::
inverseRescalingFactor(vector<Lorentz5Momentum> pout,
vector<Energy> mon, Energy roots) const {
double lambda=1.;
if(pout.size()==2) {
double mu_q1(pout[0].m()/roots), mu_q2(pout[1].m()/roots);
double mu_p1(mon[0]/roots) , mu_p2(mon[1]/roots);
lambda =
((1.+mu_q1+mu_q2)*(1.-mu_q1-mu_q2)*(mu_q1-1.-mu_q2)*(mu_q2-1.-mu_q1))/
((1.+mu_p1+mu_p2)*(1.-mu_p1-mu_p2)*(mu_p1-1.-mu_p2)*(mu_p2-1.-mu_p1));
if(lambda<0.)
throw Exception() << "Rescaling factor is imaginary in QTildeReconstructor::"
<< "inverseRescalingFactor lambda^2= " << lambda
<< Exception::eventerror;
lambda = sqrt(lambda);
}
else {
unsigned int ntry=0;
// compute magnitudes once for speed
vector<Energy2> pmag;
for(unsigned int ix=0;ix<pout.size();++ix) {
pmag.push_back(pout[ix].vect().mag2());
}
// Newton-Raphson for the rescaling
vector<Energy> root(pout.size());
do {
// compute new energies
Energy sum(ZERO);
for(unsigned int ix=0;ix<pout.size();++ix) {
root[ix] = sqrt(pmag[ix]/sqr(lambda)+sqr(mon[ix]));
sum+=root[ix];
}
// if accuracy reached exit
if(abs(sum/roots-1.)<1e-10) break;
// use Newton-Raphson to compute new guess for lambda
Energy numer(ZERO),denom(ZERO);
for(unsigned int ix=0;ix<pout.size();++ix) {
numer +=root[ix];
denom +=pmag[ix]/root[ix];
}
numer-=roots;
double fact = 1.+sqr(lambda)*numer/denom;
if(fact<0.) fact=0.5;
lambda *=fact;
++ntry;
}
while(ntry<100);
}
if(isnan(lambda))
throw Exception() << "Rescaling factor is nan in QTildeReconstructor::"
<< "inverseRescalingFactor "
<< Exception::eventerror;
return lambda;
}
bool QTildeReconstructor::
deconstructGeneralSystem(HardTreePtr tree,
cEvolverPtr evolver,
ShowerInteraction::Type type) const {
// extract incoming and outgoing particles
ColourSingletShower in,out;
for(set<HardBranchingPtr>::const_iterator it=tree->branchings().begin();
it!=tree->branchings().end();++it) {
if((**it).status()==HardBranching::Incoming) in .jets.push_back(*it);
else out.jets.push_back(*it);
}
LorentzRotation toRest,fromRest;
bool applyBoost(false);
// do the initial-state reconstruction
deconstructInitialInitialSystem(applyBoost,toRest,fromRest,
tree,in.jets,type);
// do the final-state reconstruction
deconstructFinalStateSystem(toRest,fromRest,tree,
out.jets,evolver,type);
// only at this point that we can be sure all the reference vectors
// are correct
for(set<HardBranchingPtr>::const_iterator it=tree->branchings().begin();
it!=tree->branchings().end();++it) {
if((**it).status()==HardBranching::Incoming) continue;
if((**it).branchingParticle()->coloured())
(**it).setMomenta(LorentzRotation(),1.,Lorentz5Momentum(),false);
}
for(set<HardBranchingPtr>::const_iterator it=tree->incoming().begin();
it!=tree->incoming().end();++it) {
(**it).setMomenta(LorentzRotation(),1.,Lorentz5Momentum(),false);
}
return true;
}
bool QTildeReconstructor::deconstructHardJets(HardTreePtr tree,
cEvolverPtr evolver,
ShowerInteraction::Type type) const {
// inverse of old recon method
if(_reconopt==0) {
return deconstructGeneralSystem(tree,evolver,type);
}
// inverse of reconstruction based on coloured systems
else {
// identify the colour singlet systems
vector<ColourSingletShower> systems;
set<HardBranchingPtr> done;
for(set<HardBranchingPtr>::const_iterator it=tree->branchings().begin();
it!=tree->branchings().end();++it) {
// if not treated create new system
if(done.find(*it)!=done.end()) continue;
done.insert(*it);
systems.push_back(ColourSingletShower(UNDEFINED,*it));
if(!(**it).branchingParticle()->coloured()) continue;
// now find the colour connected particles
findPartners(*it,done,tree->branchings(),systems.back().jets);
}
// catagorize the systems
unsigned int nnun(0),nnii(0),nnif(0),nnf(0),nni(0);
for(unsigned int ix=0;ix<systems.size();++ix) {
unsigned int ni(0),nf(0);
for(unsigned int iy=0;iy<systems[ix].jets.size();++iy) {
if(systems[ix].jets[iy]->status()==HardBranching::Outgoing) ++nf;
else ++ni;
}
// type
// initial-initial
if(ni==2&&nf==0) {
systems[ix].type = II;
++nnii;
}
// initial only
else if(ni==1&&nf==0) {
systems[ix].type = I;
++nni;
}
// initial-final
else if(ni==1&&nf>0) {
systems[ix].type = IF;
++nnif;
}
// final only
else if(ni==0&&nf>0) {
systems[ix].type = F;
++nnf;
}
// otherwise unknown
else {
systems[ix].type = UNDEFINED;
++nnun;
}
}
// now decide what to do
LorentzRotation toRest,fromRest;
bool applyBoost(false);
bool general(false);
// initial-initial connection and final-state colour singlet systems
// Drell-Yan type
if(nnun==0&&nnii==1&&nnif==0&&nnf>0&&nni==0) {
// reconstruct initial-initial system
for(unsigned int ix=0;ix<systems.size();++ix) {
if(systems[ix].type==II)
deconstructInitialInitialSystem(applyBoost,toRest,fromRest,tree,
systems[ix].jets,type);
}
if(type==ShowerInteraction::QED) {
combineFinalStateShower(systems);
general=false;
}
}
// DIS and VBF type
else if(nnun==0&&nnii==0&&((nnif==1&&nnf>0&&nni==1)||
(nnif==2&& nni==0))) {
for(unsigned int ix=0;ix<systems.size();++ix) {
if(systems[ix].type==IF)
deconstructInitialFinalSystem(tree,systems[ix].jets,evolver,type);
}
}
// e+e- type
else if(nnun==0&&nnii==0&&nnif==0&&nnf>0&&nni==2) {
// only FS needed
// but need to boost to rest frame if QED ISR
Lorentz5Momentum ptotal;
for(unsigned int ix=0;ix<systems.size();++ix) {
if(systems[ix].type==I)
ptotal += systems[ix].jets[0]->branchingParticle()->momentum();
}
toRest = LorentzRotation(ptotal.findBoostToCM());
fromRest = toRest;
fromRest.invert();
if(type==ShowerInteraction::QED) {
combineFinalStateShower(systems);
general=false;
}
}
// general type
else {
general = true;
}
// final-state systems except for general recon
if(!general) {
for(unsigned int ix=0;ix<systems.size();++ix) {
if(systems[ix].type==F)
deconstructFinalStateSystem(toRest,fromRest,tree,
systems[ix].jets,evolver,type);
}
// only at this point that we can be sure all the reference vectors
// are correct
for(set<HardBranchingPtr>::const_iterator it=tree->branchings().begin();
it!=tree->branchings().end();++it) {
if((**it).status()==HardBranching::Incoming) continue;
if((**it).branchingParticle()->coloured())
(**it).setMomenta(LorentzRotation(),1.,Lorentz5Momentum(),false);
}
for(set<HardBranchingPtr>::const_iterator it=tree->incoming().begin();
it!=tree->incoming().end();++it) {
(**it).setMomenta(LorentzRotation(),1.,Lorentz5Momentum(),false);
}
return true;
}
else {
return deconstructGeneralSystem(tree,evolver,type);
}
return true;
}
}
vector<unsigned int> QTildeReconstructor::
findPartners(unsigned int iloc ,
vector<ShowerProgenitorPtr> jets) const {
vector<unsigned int> output;
for(unsigned int iy=0;iy<jets.size();++iy) {
if(!jets[iy]->progenitor()->data().coloured()||iy==iloc) continue;
bool isPartner = false;
// both in either initial or final state
if(jets[iloc]->progenitor()->isFinalState()!=jets[iy]->progenitor()->isFinalState()) {
//loop over all the colours of both
for(unsigned int ix=0; ix<CLSIZE(jets[iloc]); ++ix){
for(unsigned int jx=0; jx<CLSIZE(jets[iy]); ++jx){
if(CL(jets[iloc],ix) && CL(jets[iloc],ix)==CL(jets[iy],jx))
isPartner = true;
}
}
if(!isPartner){
//loop over anti colours of both
for(unsigned int ix=0; ix<ACLSIZE(jets[iloc]); ++ix){
for(unsigned int jx=0; jx<ACLSIZE(jets[iy]); ++jx){
if(ACL(jets[iloc],ix) && ACL(jets[iloc],ix)==ACL(jets[iy],jx))
isPartner = true;
}
}
}
}
else{
//loop over the colours of the first and the anti-colours of the other
for(unsigned int ix=0; ix<CLSIZE(jets[iloc]); ++ix){
for(unsigned int jx=0; jx<ACLSIZE(jets[iy]); ++jx){
if(CL(jets[iloc],ix) && CL(jets[iloc],ix)==ACL(jets[iy],jx))
isPartner = true;
}
}
if(!isPartner){
//loop over the anti-colours of the first and the colours of the other
for(unsigned int ix=0; ix<ACLSIZE(jets[iloc]); ++ix){
for(unsigned int jx=0; jx<CLSIZE(jets[iy]); jx++){
if(ACL(jets[iloc],ix) && ACL(jets[iloc],ix)==CL(jets[iy],jx))
isPartner = true;
}
}
}
}
// special for sources/sinks
if(jets[iloc]->progenitor()->colourLine()) {
if(jets[iloc]->progenitor()->colourLine()->sourceNeighbours().first) {
tColinePair lines = jets[iloc]->progenitor()->colourLine()->sourceNeighbours();
if(lines.first == jets[iy]->progenitor()-> colourLine() ||
lines.first == jets[iy]->progenitor()-> colourLine() ||
lines.second == jets[iy]->progenitor()->antiColourLine() ||
lines.second == jets[iy]->progenitor()->antiColourLine())
isPartner = true;
}
if(jets[iloc]->progenitor()->colourLine()->sinkNeighbours().first) {
tColinePair lines = jets[iloc]->progenitor()->colourLine()->sinkNeighbours();
if(lines.first == jets[iy]->progenitor()-> colourLine() ||
lines.first == jets[iy]->progenitor()-> colourLine() ||
lines.second == jets[iy]->progenitor()->antiColourLine() ||
lines.second == jets[iy]->progenitor()->antiColourLine())
isPartner = true;
}
}
if(jets[iloc]->progenitor()->antiColourLine()) {
if(jets[iloc]->progenitor()->antiColourLine()->sourceNeighbours().first) {
tColinePair lines = jets[iloc]->progenitor()->antiColourLine()->sourceNeighbours();
if(lines.first == jets[iy]->progenitor()-> colourLine() ||
lines.first == jets[iy]->progenitor()-> colourLine() ||
lines.second == jets[iy]->progenitor()->antiColourLine() ||
lines.second == jets[iy]->progenitor()->antiColourLine())
isPartner = true;
}
if(jets[iloc]->progenitor()->antiColourLine()->sinkNeighbours().first) {
tColinePair lines = jets[iloc]->progenitor()->antiColourLine()->sinkNeighbours();
if(lines.first == jets[iy]->progenitor()-> colourLine() ||
lines.first == jets[iy]->progenitor()-> colourLine() ||
lines.second == jets[iy]->progenitor()->antiColourLine() ||
lines.second == jets[iy]->progenitor()->antiColourLine())
isPartner = true;
}
}
if(isPartner)
output.push_back(iy);
}
return output;
}
void QTildeReconstructor::
reconstructInitialFinalSystem(vector<ShowerProgenitorPtr> jets) const {
Lorentz5Momentum pin[2],pout[2];
- bool atLeastOnce(false);
for(unsigned int ix=0;ix<jets.size();++ix) {
// final-state parton
if(jets[ix]->progenitor()->isFinalState()) {
pout[0] +=jets[ix]->progenitor()->momentum();
_progenitor = jets[ix]->progenitor();
- atLeastOnce |= reconstructTimeLikeJet(jets[ix]->progenitor(),0);
+ reconstructTimeLikeJet(jets[ix]->progenitor(),0);
}
// initial-state parton
else {
pin[0] +=jets[ix]->progenitor()->momentum();
- atLeastOnce |= reconstructSpaceLikeJet(jets[ix]->progenitor());
+ reconstructSpaceLikeJet(jets[ix]->progenitor());
assert(!jets[ix]->original()->parents().empty());
}
}
// add intrinsic pt if needed
- atLeastOnce |= addIntrinsicPt(jets);
+ addIntrinsicPt(jets);
// momenta after showering
for(unsigned int ix=0;ix<jets.size();++ix) {
if(jets[ix]->progenitor()->isFinalState())
pout[1] += jets[ix]->progenitor()->momentum();
else
pin[1] += jets[ix]->progenitor()->momentum();
}
// work out the boost to the Breit frame
Lorentz5Momentum pa = pout[0]-pin[0];
Lorentz5Momentum pb = pin[0];
Axis axis(pa.vect().unit());
LorentzRotation rot;
double sinth(sqrt(sqr(axis.x())+sqr(axis.y())));
rot.setRotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.));
rot.rotateX(Constants::pi);
rot.boostZ( pa.e()/pa.vect().mag());
Lorentz5Momentum ptemp=rot*pb;
Boost trans = -1./ptemp.e()*ptemp.vect();
trans.setZ(0.);
rot.boost(trans);
pa *=rot;
// project and calculate rescaling
// reference vectors
Lorentz5Momentum n1(ZERO,ZERO,-pa.z(),-pa.z());
Lorentz5Momentum n2(ZERO,ZERO, pa.z(),-pa.z());
Energy2 n1n2 = n1*n2;
// decompose the momenta
Lorentz5Momentum qbp=rot*pin[1],qcp= rot*pout[1];
double a[2],b[2];
a[0] = n2*qbp/n1n2;
b[0] = n1*qbp/n1n2;
Lorentz5Momentum qperp = qbp-a[0]*n1-b[0]*n2;
a[1] = 0.5*(qcp.m2()-qperp.m2())/n1n2;
b[1] = 1.;
double A(0.5*a[0]),B(b[0]*a[0]-a[1]*b[1]-0.25),C(-0.5*b[0]);
if(sqr(B)-4.*A*C<0.) throw KinematicsReconstructionVeto();
double kb = 0.5*(-B+sqrt(sqr(B)-4.*A*C))/A;
double kc = (a[0]*kb-0.5)/a[1];
if(kc==0.) throw KinematicsReconstructionVeto();
Lorentz5Momentum pnew[2] = { a[0]*kb*n1+b[0]/kb*n2+qperp,
a[1]*kc*n1+b[1]/kc*n2+qperp};
LorentzRotation rotinv=rot.inverse();
LorentzRotation transb=rotinv*solveBoostZ(pnew[0],qbp)*rot;
LorentzRotation transc=rotinv*solveBoost(pnew[1],qcp)*rot;
for(unsigned int ix=0;ix<jets.size();++ix) {
if(jets[ix]->progenitor()->isFinalState())
deepTransform(jets[ix]->progenitor(),transc);
else {
tPPtr parent;
boostChain(jets[ix]->progenitor(),transb,parent);
}
}
}
bool QTildeReconstructor::addIntrinsicPt(vector<ShowerProgenitorPtr> jets) const {
bool added=false;
// add the intrinsic pt if needed
for(unsigned int ix=0;ix<jets.size();++ix) {
// only for initial-state particles which haven't radiated
if(jets[ix]->progenitor()->isFinalState()||
jets[ix]->hasEmitted()) continue;
if(_intrinsic.find(jets[ix])==_intrinsic.end()) continue;
pair<Energy,double> pt=_intrinsic[jets[ix]];
Energy etemp = jets[ix]->original()->parents()[0]->momentum().z();
Lorentz5Momentum
p_basis(ZERO, ZERO, etemp, abs(etemp)),
n_basis(ZERO, ZERO,-etemp, abs(etemp));
double alpha = jets[ix]->progenitor()->x();
double beta = 0.5*(sqr(jets[ix]->progenitor()->data().mass())+
sqr(pt.first))/alpha/(p_basis*n_basis);
Lorentz5Momentum pnew=alpha*p_basis+beta*n_basis;
pnew.setX(pt.first*cos(pt.second));
pnew.setY(pt.first*sin(pt.second));
pnew.rescaleMass();
jets[ix]->progenitor()->set5Momentum(pnew);
added = true;
}
return added;
}
LorentzRotation QTildeReconstructor::
solveBoost(const double k, const Lorentz5Momentum & newq,
const Lorentz5Momentum & oldp ) const {
Energy q = newq.vect().mag();
Energy2 qs = sqr(q);
Energy2 Q2 = newq.mass2();
Energy kp = k*(oldp.vect().mag());
Energy2 kps = sqr(kp);
double betam = (q*newq.e() - kp*sqrt(kps + Q2))/(kps + qs + Q2);
Boost beta = -betam*(k/kp)*oldp.vect();
double gamma = 0.;
if(Q2/sqr(oldp.e())>1e-4) {
if(betam<0.5) {
gamma = 1./sqrt(1.-sqr(betam));
}
else {
gamma = ( kps+ qs + Q2)/
sqrt(2.*kps*qs + kps*Q2 + qs*Q2 + sqr(Q2) + 2.*q*newq.e()*kp*sqrt(kps + Q2));
}
}
else {
if(k>0) {
gamma = 4.*kps*qs/sqr(kps +qs) + 2.*sqr(kps-qs)*Q2/pow<3,1>(kps +qs)
- 0.25*( sqr(kps) + 14.*kps*qs + sqr(qs))*sqr(kps-qs)/(pow<4,1>(kps +qs)*kps*qs)*sqr(Q2);
}
else {
gamma = 0.25*sqr(Q2)/(kps*qs)*(1. - 0.5*(kps+qs)/(kps*qs)*Q2);
}
gamma = 1./sqrt(gamma);
}
// note that (k/kp)*oldp.vect() = oldp.vect()/oldp.vect().mag() but cheaper.
ThreeVector<Energy2> ax = newq.vect().cross( oldp.vect() );
double delta = newq.vect().angle( oldp.vect() );
LorentzRotation R;
using Constants::pi;
Energy2 scale1 = sqr(newq.x())+ sqr(newq.y())+sqr(newq.z());
Energy2 scale2 = sqr(oldp.x())+ sqr(oldp.y())+sqr(oldp.z());
if ( ax.mag2()/scale1/scale2 > 1e-28 ) {
R.rotate( delta, unitVector(ax) ).boost( beta , gamma );
}
else if(abs(delta-pi)/pi < 0.001) {
double phi=2.*pi*UseRandom::rnd();
Axis axis(cos(phi),sin(phi),0.);
axis.rotateUz(newq.vect().unit());
R.rotate(delta,axis).boost( beta , gamma );
}
else {
R.boost( beta , gamma );
}
return R;
}
LorentzRotation QTildeReconstructor::solveBoost(const Lorentz5Momentum & q,
const Lorentz5Momentum & p ) const {
Energy modp = p.vect().mag();
Energy modq = q.vect().mag();
double betam = (p.e()*modp-q.e()*modq)/(sqr(modq)+sqr(modp)+p.mass2());
Boost beta = -betam*q.vect().unit();
ThreeVector<Energy2> ax = p.vect().cross( q.vect() );
double delta = p.vect().angle( q.vect() );
LorentzRotation R;
using Constants::pi;
if ( ax.mag2()/GeV2/MeV2 > 1e-16 ) {
R.rotate( delta, unitVector(ax) ).boost( beta );
}
else {
R.boost( beta );
}
return R;
}
LorentzRotation QTildeReconstructor::solveBoostZ(const Lorentz5Momentum & q,
const Lorentz5Momentum & p ) const {
static const Energy2 eps2 = 1e-8*GeV2;
static const Energy eps = 1e-4 *GeV;
LorentzRotation R;
double beta;
Energy2 den = (p.t()*q.t()-p.z()*q.z());
Energy2 num = -(p.z()*q.t()-q.z()*p.t());
if(abs(den)<eps2||abs(num)<eps2) {
if(abs(p.t()-abs(p.z()))<eps&&abs(q.t()-abs(q.z()))<eps) {
double ratio = sqr(q.t()/p.t());
beta = -(1.-ratio)/(1.+ratio);
}
else {
beta=0.;
}
}
else {
beta = num/den;
}
R.boostZ(beta);
Lorentz5Momentum ptest = R*p;
if(ptest.z()/q.z() < 0. || ptest.t()/q.t() < 0. ) {
throw KinematicsReconstructionVeto();
}
return R;
}
void QTildeReconstructor::
reconstructFinalStateSystem(bool applyBoost,
const LorentzRotation & toRest,
const LorentzRotation & fromRest,
vector<ShowerProgenitorPtr> jets) const {
// special for case of individual particle
if(jets.size()==1) {
LorentzRotation trans(toRest);
trans.transform(fromRest);
deepTransform(jets[0]->progenitor(),trans);
return;
}
bool radiated(false);
// find the hard process centre-of-mass energy
Lorentz5Momentum pcm;
// check if radiated and calculate total momentum
for(unsigned int ix=0;ix<jets.size();++ix) {
radiated |=jets[ix]->hasEmitted();
pcm += jets[ix]->progenitor()->momentum();
}
// check if in CMF frame
Boost beta_cm = pcm.findBoostToCM();
bool gottaBoost = (beta_cm.mag() > 1e-12);
// collection of pointers to initial hard particle and jet momenta
// for final boosts
JetKinVect jetKinematics;
vector<ShowerProgenitorPtr>::const_iterator cit;
for(cit = jets.begin(); cit != jets.end(); cit++) {
JetKinStruct tempJetKin;
tempJetKin.parent = (*cit)->progenitor();
if(gottaBoost) {
tempJetKin.parent->boost(beta_cm);
map<tShowerTreePtr,pair<tShowerProgenitorPtr,
tShowerParticlePtr> >::const_iterator tit;
for(tit = _currentTree->treelinks().begin();
tit != _currentTree->treelinks().end();++tit) {
if(tit->second.first && tit->second.second==tempJetKin.parent)
tit->first->transform(LorentzRotation(beta_cm),false);
}
}
tempJetKin.p = (*cit)->progenitor()->momentum();
_progenitor=tempJetKin.parent;
radiated |= reconstructTimeLikeJet((*cit)->progenitor(),0);
tempJetKin.q = (*cit)->progenitor()->momentum();
jetKinematics.push_back(tempJetKin);
}
// find the rescaling factor
double k = 0.0;
if(radiated) {
k = solveKfactor(pcm.m(), jetKinematics);
}
// perform the rescaling and boosts
for(JetKinVect::iterator it = jetKinematics.begin();
it != jetKinematics.end(); ++it) {
LorentzRotation Trafo = LorentzRotation();
if(radiated) Trafo = solveBoost(k, it->q, it->p);
if(gottaBoost) Trafo.boost(-beta_cm);
if(applyBoost) {
Trafo.transform( toRest);
Trafo.transform(fromRest);
}
if(radiated || gottaBoost || applyBoost) deepTransform(it->parent,Trafo);
}
}
void QTildeReconstructor::
reconstructInitialInitialSystem(bool & applyBoost,
LorentzRotation & toRest,
LorentzRotation & fromRest,
vector<ShowerProgenitorPtr> jets) const {
bool radiated = false;
Lorentz5Momentum pcm;
// check whether particles radiated and calculate total momentum
for( unsigned int ix = 0; ix < jets.size(); ++ix ) {
radiated |= jets[ix]->hasEmitted();
pcm += jets[ix]->progenitor()->momentum();
}
// check if intrinsic pt to be added
radiated |= !_intrinsic.empty();
// if no radiation return
if(!radiated) return;
// initial state shuffling
applyBoost=false;
vector<Lorentz5Momentum> p, pq, p_in;
for(unsigned int ix=0;ix<jets.size();++ix) {
// at momentum to vector
p_in.push_back(jets[ix]->progenitor()->momentum());
// reconstruct the jet
radiated |= reconstructSpaceLikeJet(jets[ix]->progenitor());
assert(!jets[ix]->original()->parents().empty());
Energy etemp = jets[ix]->original()->parents()[0]->momentum().z();
Lorentz5Momentum ptemp = Lorentz5Momentum(ZERO, ZERO, etemp, abs(etemp));
pq.push_back(ptemp);
}
// add the intrinsic pt if needed
radiated |=addIntrinsicPt(jets);
for(unsigned int ix=0;ix<jets.size();++ix) {
p.push_back(jets[ix]->progenitor()->momentum());
}
double x1 = p_in[0].z()/pq[0].z();
double x2 = p_in[1].z()/pq[1].z();
Energy MDY = (p_in[0] + p_in[1]).m();
Energy2 S = (pq[0]+pq[1]).m2();
// if not need don't apply boosts
if(!(radiated && p.size() == 2 && pq.size() == 2)) return;
applyBoost=true;
// find alphas and betas in terms of desired basis
Energy2 p12 = pq[0]*pq[1];
double a[2] = {p[0]*pq[1]/p12,p[1]*pq[1]/p12};
double b[2] = {p[0]*pq[0]/p12,p[1]*pq[0]/p12};
Lorentz5Momentum p1p = p[0] - a[0]*pq[0] - b[0]*pq[1];
Lorentz5Momentum p2p = p[1] - a[1]*pq[0] - b[1]*pq[1];
// compute kappa
Energy2 A = a[0]*b[1]*S;
Energy2 B = Energy2(sqr(MDY)) - (a[0]*b[0]+a[1]*b[1])*S - (p1p+p2p).m2();
Energy2 C = a[1]*b[0]*S;
double rad = 1.-4.*A*C/sqr(B);
if(rad < 0.) throw KinematicsReconstructionVeto();
double kp = B/(2.*A)*(1.+sqrt(rad));
// now compute k1, k2
rad = kp*(b[0]+kp*b[1])/(kp*a[0]+a[1])*(x1/x2);
if(rad <= 0.) throw KinematicsReconstructionVeto();
double k1 = sqrt(rad);
double k2 = kp/k1;
double beta[2] =
{getBeta((a[0]+b[0]), (a[0]-b[0]), (k1*a[0]+b[0]/k1), (k1*a[0]-b[0]/k1)),
getBeta((a[1]+b[1]), (a[1]-b[1]), (a[1]/k2+k2*b[1]), (a[1]/k2-k2*b[1]))};
if (pq[0].z() > ZERO) {
beta[0] = -beta[0];
beta[1] = -beta[1];
}
// apply the boosts
Lorentz5Momentum newcmf;
for(unsigned int ix=0;ix<jets.size();++ix) {
tPPtr toBoost = jets[ix]->progenitor();
Boost betaboost(0, 0, beta[ix]);
tPPtr parent;
boostChain(toBoost, LorentzRotation(betaboost),parent);
if(parent->momentum().e()/pq[ix].e()>1.||
parent->momentum().z()/pq[ix].z()>1.) throw KinematicsReconstructionVeto();
newcmf+=toBoost->momentum();
}
if(newcmf.m()<ZERO||newcmf.e()<ZERO) throw KinematicsReconstructionVeto();
// do one boost
toRest = LorentzRotation(pcm.findBoostToCM());
if(_initialBoost==0) {
fromRest = LorentzRotation(newcmf.boostVector());
}
else if(_initialBoost==1) {
// first apply longitudinal boost
double beta = newcmf.z()/sqrt(newcmf.m2()+sqr(newcmf.z()));
fromRest=LorentzRotation(Boost(0.,0.,beta));
// then transverse one
Energy pT = sqrt(sqr(newcmf.x())+sqr(newcmf.y()));
beta = pT/newcmf.t();
fromRest.boost(Boost(beta*newcmf.x()/pT,beta*newcmf.y()/pT,0.));
}
else
assert(false);
}
void QTildeReconstructor::
deconstructInitialInitialSystem(bool & applyBoost,
LorentzRotation & toRest,
LorentzRotation & fromRest,
HardTreePtr tree,
vector<HardBranchingPtr> jets,
ShowerInteraction::Type) const {
// get the momenta of the particles
vector<Lorentz5Momentum> pin;
vector<Lorentz5Momentum> pq;
vector<HardBranchingPtr>::iterator cit;
for(cit=jets.begin();cit!=jets.end();++cit) {
pin.push_back((*cit)->branchingParticle()->momentum());
Energy etemp = (*cit)->beam()->momentum().z();
pq.push_back(Lorentz5Momentum(ZERO, ZERO,etemp, abs(etemp)));
}
bool order = (*tree->incoming().begin())->beam()->momentum().z()/pq[0].z()<0.;
assert(pin.size()==2);
// decompose the momenta
double alpha[2],beta[2];
Energy2 p12=pq[0]*pq[1];
Lorentz5Momentum pt[2];
for(unsigned int ix=0;ix<2;++ix) {
alpha[ix] = pin[ix]*pq[1]/p12;
beta [ix] = pin[ix]*pq[0]/p12;
pt[ix] = pin[ix]-alpha[ix]*pq[0]-beta[ix]*pq[1];
}
// parton level centre-of-mass
Lorentz5Momentum pcm=pin[0]+pin[1];
pcm.rescaleMass();
double rap=pcm.rapidity();
// hadron level cmf
Energy2 s = (pq[0] +pq[1] ).m2();
// calculate the x values
assert(pcm.mass2()>ZERO);
double x0 = sqrt(pcm.mass2()/s*exp(2.*rap));
double x[2]={x0, pcm.mass2()/s/x0};
if(pq[0].z()<ZERO) swap(x[0],x[1]);
double k1=alpha[0]/x[0],k2=beta[1]/x[1];
double alphanew[2]={alpha[0]/k1,alpha[1]*k2};
double betanew [2]={beta [0]*k1,beta [1]/k2};
double boost[2];
for(unsigned int ix=0;ix<2;++ix) {
boost[ix] = getBeta(alpha [ix]+beta [ix], alpha[ix] -beta [ix],
alphanew[ix]+betanew[ix], alphanew[ix]-betanew[ix]);
if (pq[0].z() > ZERO) beta[ix]*=-1.;
}
// apply the boost the the particles
// first incoming particle
if(order) swap(pq[0],pq[1]);
// now apply the boosts
Boost betaboost(0.,0.,-boost[0]);
LorentzRotation R;
R.boost(betaboost);
set<HardBranchingPtr>::const_iterator cjt=tree->incoming().begin();
(*cjt)->pVector(pq[0]);
(*cjt)->nVector(pq[1]);
(*cjt)->setMomenta(R,1.,Lorentz5Momentum());
// second incoming particle
betaboost = Boost(0.,0.,-boost[1]);
R=LorentzRotation(betaboost);
++cjt;
(*cjt)->pVector(pq[1]);
(*cjt)->nVector(pq[0]);
(*cjt)->setMomenta(R,1.,Lorentz5Momentum());
jets[0]->showerMomentum(x[0]*jets[0]->pVector());
jets[1]->showerMomentum(x[1]*jets[1]->pVector());
// and calculate the boosts
applyBoost=true;
// do one boost
if(_initialBoost==0) {
toRest = LorentzRotation(-pcm.boostVector());
}
else if(_initialBoost==1) {
// first the transverse boost
Energy pT = sqrt(sqr(pcm.x())+sqr(pcm.y()));
double beta = -pT/pcm.t();
toRest=LorentzRotation(Boost(beta*pcm.x()/pT,beta*pcm.y()/pT,0.));
// the longitudinal
beta = pcm.z()/sqrt(pcm.m2()+sqr(pcm.z()));
toRest.boost(Boost(0.,0.,-beta));
}
else
assert(false);
fromRest = LorentzRotation((jets[0]->showerMomentum()+
jets[1]->showerMomentum()).boostVector());
}
void QTildeReconstructor::
deconstructFinalStateSystem(const LorentzRotation & toRest,
const LorentzRotation & fromRest,
HardTreePtr tree, vector<HardBranchingPtr> jets,
cEvolverPtr evolver,
ShowerInteraction::Type type) const {
if(jets.size()==1) {
LorentzRotation R(toRest);
R.transform(fromRest);
// \todo What does this do? tree->showerRot( R );
jets[0]->original(R*jets[0]->branchingParticle()->momentum());
jets[0]->showerMomentum(R*jets[0]->branchingParticle()->momentum());
// find the colour partners
ShowerParticleVector particles;
vector<Lorentz5Momentum> ptemp;
set<HardBranchingPtr>::const_iterator cjt;
for(cjt=tree->branchings().begin();cjt!=tree->branchings().end();++cjt) {
ptemp.push_back((**cjt).branchingParticle()->momentum());
(**cjt).branchingParticle()->set5Momentum((**cjt).showerMomentum());
particles.push_back((**cjt).branchingParticle());
}
evolver->showerModel()->partnerFinder()
->setInitialEvolutionScales(particles,false,type,false);
// calculate the reference vectors
unsigned int iloc(0);
set<HardBranchingPtr>::iterator clt;
for(cjt=tree->branchings().begin();cjt!=tree->branchings().end();++cjt) {
// reset the momentum
(**cjt).branchingParticle()->set5Momentum(ptemp[iloc]);
++iloc;
// sort out the partners
tShowerParticlePtr partner =
(*cjt)->branchingParticle()->partner();
if(!partner) continue;
for(clt=tree->branchings().begin();clt!=tree->branchings().end();++clt) {
if((**clt).branchingParticle()==partner) {
(**cjt).colourPartner(*clt);
break;
}
}
tHardBranchingPtr branch;
for(clt=tree->branchings().begin();clt!=tree->branchings().end();++clt) {
if(clt==cjt) continue;
if((*clt)->branchingParticle()==partner) {
branch=*clt;
break;
}
}
}
return;
}
vector<HardBranchingPtr>::iterator cit;
vector<Lorentz5Momentum> pout;
vector<Energy> mon;
for(cit=jets.begin();cit!=jets.end();++cit) {
pout.push_back((*cit)->branchingParticle()->momentum());
// KH - 230909 - If the particle has no children then it will
// not have showered and so it should be "on-shell" so we can
// get it's mass from it's momentum. This means that the
// inverseRescalingFactor doesn't give any nans or do things
// it shouldn't if it gets e.g. two Z bosons generated with
// off-shell masses. This is for sure not the best solution.
// PR 1/1/10 modification to previous soln
if((*cit)->branchingParticle()->children().size()==0 ||
(!(*cit)->branchingParticle()->dataPtr()->coloured() &&
!(*cit)->branchingParticle()->dataPtr()->stable()) )
mon.push_back(pout.back().mass());
else
mon.push_back((*cit)->branchingParticle()->dataPtr()->mass());
}
// boost all the momenta to the rest frame of the decaying particle
Lorentz5Momentum pin;
for(unsigned int ix=0;ix<pout.size();++ix) {
pout[ix].transform(toRest);
pin += pout[ix];
}
pin.rescaleMass();
// rescaling factor
double lambda=inverseRescalingFactor(pout,mon,pin.mass());
if (lambda< 1.e-10) throw KinematicsReconstructionVeto();
// now calculate the p reference vectors
for(cit=jets.begin();cit!=jets.end();++cit){
Lorentz5Momentum pvect = (*cit)->branchingParticle()->momentum();
pvect.transform(toRest);
pvect /= lambda;
if((*cit)->branchingParticle()->children().size()==0 ||
(!(*cit)->branchingParticle()->dataPtr()->coloured() &&
!(*cit)->branchingParticle()->dataPtr()->stable()) )
pvect.setMass((*cit)->branchingParticle()->momentum().mass());
else
pvect.setMass((*cit)->branchingParticle()->dataPtr()->mass());
pvect.rescaleEnergy();
pvect.transform(fromRest);
(*cit)->pVector(pvect);
(*cit)->showerMomentum(pvect);
}
// find the colour partners
ShowerParticleVector particles;
vector<Lorentz5Momentum> ptemp;
set<HardBranchingPtr>::const_iterator cjt;
for(cjt=tree->branchings().begin();cjt!=tree->branchings().end();++cjt) {
ptemp.push_back((**cjt).branchingParticle()->momentum());
(**cjt).branchingParticle()->set5Momentum((**cjt).showerMomentum());
particles.push_back((**cjt).branchingParticle());
}
evolver->showerModel()->partnerFinder()
->setInitialEvolutionScales(particles,false,type,false);
// calculate the reference vectors
unsigned int iloc(0);
set<HardBranchingPtr>::iterator clt;
for(cjt=tree->branchings().begin();cjt!=tree->branchings().end();++cjt) {
// reset the momentum
(**cjt).branchingParticle()->set5Momentum(ptemp[iloc]);
++iloc;
}
for(cjt=tree->branchings().begin();cjt!=tree->branchings().end();++cjt) {
// sort out the partners
tShowerParticlePtr partner =
(*cjt)->branchingParticle()->partner();
if(!partner) continue;
for(clt=tree->branchings().begin();clt!=tree->branchings().end();++clt) {
if((**clt).branchingParticle()==partner) {
(**cjt).colourPartner(*clt);
break;
}
}
tHardBranchingPtr branch;
for(clt=tree->branchings().begin();clt!=tree->branchings().end();++clt) {
if(clt==cjt) continue;
if((*clt)->branchingParticle()==partner) {
branch=*clt;
break;
}
}
// compute the reference vectors
// both incoming, should all ready be done
if((**cjt).status()==HardBranching::Incoming &&
(**clt).status()==HardBranching::Incoming) {
continue;
}
// both outgoing
else if((**cjt).status()!=HardBranching::Incoming&&
branch->status()==HardBranching::Outgoing) {
Boost boost=((*cjt)->pVector()+branch->pVector()).findBoostToCM();
Lorentz5Momentum pcm = branch->pVector();
pcm.boost(boost);
Lorentz5Momentum nvect = Lorentz5Momentum(ZERO,pcm.vect());
nvect.boost( -boost);
(**cjt).nVector(nvect);
}
else if((**cjt).status()==HardBranching::Incoming) {
Lorentz5Momentum pa = -(**cjt).showerMomentum()+branch->showerMomentum();
Lorentz5Momentum pb = (**cjt).showerMomentum();
Axis axis(pa.vect().unit());
LorentzRotation rot;
double sinth(sqrt(sqr(axis.x())+sqr(axis.y())));
rot.setRotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.));
rot.rotateX(Constants::pi);
rot.boostZ( pa.e()/pa.vect().mag());
pb*=rot;
Boost trans = -1./pb.e()*pb.vect();
trans.setZ(0.);
rot.boost(trans);
Energy scale=(**cjt).beam()->momentum().e();
Lorentz5Momentum pbasis(ZERO,(**cjt).beam()->momentum().vect().unit()*scale);
Lorentz5Momentum pcm = rot*pbasis;
rot.invert();
(**cjt).nVector(rot*Lorentz5Momentum(ZERO,-pcm.vect()));
tHardBranchingPtr branch2 = *cjt;;
while (branch2->parent()) {
branch2=branch2->parent();
branch2->nVector(rot*Lorentz5Momentum(ZERO,-pcm.vect()));
}
}
else if(branch->status()==HardBranching::Incoming) {
(**cjt).nVector(Lorentz5Momentum(ZERO,branch->showerMomentum().vect()));
}
}
// now compute the new momenta
for(cjt=tree->branchings().begin();cjt!=tree->branchings().end();++cjt) {
if(!(*cjt)->branchingParticle()->isFinalState()) continue;
Lorentz5Momentum qnew;
if((*cjt)->branchingParticle()->partner()) {
Energy2 dot=(*cjt)->pVector()*(*cjt)->nVector();
double beta = 0.5*((*cjt)->branchingParticle()->momentum().m2()
-sqr((*cjt)->pVector().mass()))/dot;
qnew=(*cjt)->pVector()+beta*(*cjt)->nVector();
qnew.rescaleMass();
}
else {
qnew = (*cjt)->pVector();
}
// qnew is the unshuffled momentum in the rest frame of the p basis vectors,
// for the simple case Z->q qbar g this was checked against analytic formulae.
// compute the boost
LorentzRotation R=solveBoost(qnew,
toRest*(*cjt)->branchingParticle()->momentum())*toRest;
(*cjt)->setMomenta(R,1.0,Lorentz5Momentum());
}
}
Energy QTildeReconstructor::momConsEq(const double & k,
const Energy & root_s,
const JetKinVect & jets) const {
static const Energy2 eps=1e-8*GeV2;
Energy dum = ZERO;
for(JetKinVect::const_iterator it = jets.begin(); it != jets.end(); ++it) {
Energy2 dum2 = (it->q).m2() + sqr(k)*(it->p).vect().mag2();
if(dum2 < ZERO) {
if(dum2 < -eps) throw KinematicsReconstructionVeto();
dum2 = ZERO;
}
dum += sqrt(dum2);
}
return dum - root_s;
}
void QTildeReconstructor::boostChain(tPPtr p, const LorentzRotation &bv,
tPPtr & parent) const {
if(!p->parents().empty()) boostChain(p->parents()[0], bv,parent);
else parent=p;
p->transform(bv);
if(p->children().size()==2) {
if(dynamic_ptr_cast<ShowerParticlePtr>(p->children()[1]))
deepTransform(p->children()[1],bv);
}
}
void QTildeReconstructor::
reconstructGeneralSystem(vector<ShowerProgenitorPtr> & ShowerHardJets) const {
// general recon, all initial-state in one system and final-state
// in another
ColourSingletSystem in,out;
for(unsigned int ix=0;ix<ShowerHardJets.size();++ix) {
if(ShowerHardJets[ix]->progenitor()->isFinalState())
out.jets.push_back(ShowerHardJets[ix]);
else
in.jets.push_back(ShowerHardJets[ix]);
}
// reconstruct initial-initial system
LorentzRotation toRest,fromRest;
bool applyBoost(false);
reconstructInitialInitialSystem(applyBoost,toRest,fromRest,in.jets);
// reconstruct the final-state systems
reconstructFinalStateSystem(applyBoost,toRest,fromRest,out.jets);
}
bool QTildeReconstructor::
inverseDecayRescalingFactor(vector<Lorentz5Momentum> pout,
vector<Energy> mon,Energy roots,
Lorentz5Momentum ppartner, Energy mbar,
double & k1, double & k2) const {
ThreeVector<Energy> qtotal;
vector<Energy2> pmag;
for(unsigned int ix=0;ix<pout.size();++ix) {
pmag.push_back(pout[ix].vect().mag2());
qtotal+=pout[ix].vect();
}
Energy2 dot1 = qtotal*ppartner.vect();
Energy2 qmag2=qtotal.mag2();
double a = -dot1/qmag2;
static const Energy eps=1e-10*GeV;
unsigned int itry(0);
Energy numer(ZERO),denom(ZERO);
k1=1.;
do {
++itry;
numer=denom=0.*GeV;
double k12=sqr(k1);
for(unsigned int ix=0;ix<pout.size();++ix) {
Energy en = sqrt(pmag[ix]/k12+sqr(mon[ix]));
numer += en;
denom += pmag[ix]/en;
}
Energy en = sqrt(qmag2/k12+sqr(mbar));
numer += en-roots;
denom += qmag2/en;
k1 += numer/denom*k12*k1;
if(abs(k1)>1e10) return false;
}
while (abs(numer)>eps&&itry<100);
k1 = abs(k1);
k2 = a*k1;
return itry<100;
}
void QTildeReconstructor::
findPartners(HardBranchingPtr branch,set<HardBranchingPtr> & done,
const set<HardBranchingPtr> & branchings,
vector<HardBranchingPtr> & jets) const {
tShowerParticlePtr part=branch->branchingParticle();
unsigned int partNumColourLines =
branch->branchingParticle()->colourInfo()-> colourLines().size();
unsigned int partNumAColourLines =
branch->branchingParticle()->colourInfo()->antiColourLines().size();
for(set<HardBranchingPtr>::const_iterator cit=branchings.begin();
cit!=branchings.end();++cit) {
if(done.find(*cit)!=done.end()||!(**cit).branchingParticle()->coloured())
continue;
bool isPartner = false;
// one initial and one final
if(branch->status()!=(**cit).status()) {
if(part->colourLine()) {
for(unsigned int ix=0; ix<partNumColourLines; ++ix){
for(unsigned int jx=0; jx<CLSIZE(cit); ++jx){
if(part->colourInfo()->colourLines()[ix] ==
(**cit).branchingParticle()->colourInfo()->colourLines()[jx]){
isPartner = true;
break;
}
}
}
}
if(part->antiColourLine()) {
for(unsigned int ix=0; ix<partNumAColourLines; ++ix){
for(unsigned int jx=0; jx<ACLSIZE(cit); ++jx){
if(part->colourInfo()->antiColourLines()[ix] ==
(**cit).branchingParticle()->colourInfo()->antiColourLines()[jx]){
isPartner = true;
break;
}
}
}
}
}
// both in either initial or final state
else {
if(part->colourLine()) {
for(unsigned int ix=0; ix<partNumColourLines; ++ix) {
for(unsigned int jx=0; jx<ACLSIZE(cit); ++jx) {
if(part->colourInfo()->colourLines()[ix] ==
(**cit).branchingParticle()->colourInfo()->antiColourLines()[jx]){
isPartner = true;
break;
}
}
}
}
if(part->antiColourLine()) {
for(unsigned int ix=0; ix<partNumAColourLines; ++ix){
for(unsigned int jx=0; jx<CLSIZE(cit); ++jx){
if(part->colourInfo()->antiColourLines()[ix] ==
(**cit).branchingParticle()->colourInfo()->colourLines()[jx]){
isPartner = true;
break;
}
}
}
}
}
if(isPartner) {
jets.push_back(*cit);
done.insert(*cit);
findPartners(*cit,done,branchings,jets);
}
}
}
void QTildeReconstructor::
deconstructInitialFinalSystem(HardTreePtr tree,vector<HardBranchingPtr> jets,
cEvolverPtr evolver,
ShowerInteraction::Type type) const {
HardBranchingPtr incoming;
Lorentz5Momentum pin[2],pout[2],pbeam;
HardBranchingPtr initial;
Energy mc(ZERO);
for(unsigned int ix=0;ix<jets.size();++ix) {
// final-state parton
if(jets[ix]->status()==HardBranching::Outgoing) {
pout[0] += jets[ix]->branchingParticle()->momentum();
mc = jets[ix]->branchingParticle()->thePEGBase() ?
jets[ix]->branchingParticle()->thePEGBase()->mass() :
jets[ix]->branchingParticle()->dataPtr()->mass();
}
// initial-state parton
else {
pin[0] += jets[ix]->branchingParticle()->momentum();
initial = jets[ix];
pbeam = jets[ix]->beam()->momentum();
Energy scale=pbeam.t();
pbeam = Lorentz5Momentum(ZERO,pbeam.vect().unit()*scale);
incoming = jets[ix];
while(incoming->parent()) incoming = incoming->parent();
}
}
if(jets.size()>2) {
pout[0].rescaleMass();
mc = pout[0].mass();
}
// work out the boost to the Breit frame
Lorentz5Momentum pa = pout[0]-pin[0];
Axis axis(pa.vect().unit());
LorentzRotation rot;
double sinth(sqrt(sqr(axis.x())+sqr(axis.y())));
if(axis.perp2()>0.) {
rot.setRotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.));
rot.rotateX(Constants::pi);
rot.boostZ( pa.e()/pa.vect().mag());
}
// transverse part
Lorentz5Momentum paxis=rot*pbeam;
Boost trans = -1./paxis.e()*paxis.vect();
trans.setZ(0.);
rot.boost(trans);
pa *= rot;
// reference vectors
Lorentz5Momentum n1(ZERO,ZERO,-pa.z(),-pa.z());
Lorentz5Momentum n2(ZERO,ZERO, pa.z(),-pa.z());
Energy2 n1n2 = n1*n2;
// decompose the momenta
Lorentz5Momentum qbp=rot*pin[0],qcp= rot*pout[0];
double a[2],b[2];
a[0] = n2*qbp/n1n2;
b[0] = n1*qbp/n1n2;
a[1] = n2*qcp/n1n2;
b[1] = n1*qcp/n1n2;
Lorentz5Momentum qperp = qbp-a[0]*n1-b[0]*n2;
// before reshuffling
Energy Q = abs(pa.z());
double c = sqr(mc/Q);
Lorentz5Momentum pb(ZERO,ZERO,0.5*Q*(1.+c),0.5*Q*(1.+c));
Lorentz5Momentum pc(ZERO,ZERO,0.5*Q*(c-1.),0.5*Q*(1.+c));
double anew[2],bnew[2];
anew[0] = pb*n2/n1n2;
bnew[0] = 0.5*(qbp.m2()-qperp.m2())/n1n2/anew[0];
bnew[1] = pc*n1/n1n2;
anew[1] = 0.5*qcp.m2()/bnew[1]/n1n2;
Lorentz5Momentum qnewb = (anew[0]*n1+bnew[0]*n2+qperp);
Lorentz5Momentum qnewc = (anew[1]*n1+bnew[1]*n2);
// initial-state boost
LorentzRotation rotinv=rot.inverse();
LorentzRotation transb=rotinv*solveBoostZ(qnewb,qbp)*rot;
// final-state boost
LorentzRotation transc=rotinv*solveBoost(qnewc,qcp)*rot;
// this will need changing for more than one outgoing particle
// set the pvectors
for(unsigned int ix=0;ix<jets.size();++ix) {
if(jets[ix]->status()==HardBranching::Incoming) {
jets[ix]->pVector(pbeam);
jets[ix]->showerMomentum(rotinv*pb);
incoming->pVector(jets[ix]->pVector());
}
else {
jets[ix]->pVector(rotinv*pc);
jets[ix]->showerMomentum(jets[ix]->pVector());
}
}
// find the colour partners
ShowerParticleVector particles;
vector<Lorentz5Momentum> ptemp;
set<HardBranchingPtr>::const_iterator cjt;
for(cjt=tree->branchings().begin();cjt!=tree->branchings().end();++cjt) {
ptemp.push_back((**cjt).branchingParticle()->momentum());
(**cjt).branchingParticle()->set5Momentum((**cjt).showerMomentum());
particles.push_back((**cjt).branchingParticle());
}
evolver->showerModel()->partnerFinder()
->setInitialEvolutionScales(particles,false,type,false);
unsigned int iloc(0);
for(cjt=tree->branchings().begin();cjt!=tree->branchings().end();++cjt) {
// reset the momentum
(**cjt).branchingParticle()->set5Momentum(ptemp[iloc]);
++iloc;
}
for(vector<HardBranchingPtr>::const_iterator cjt=jets.begin();
cjt!=jets.end();++cjt) {
// sort out the partners
tShowerParticlePtr partner =
(*cjt)->branchingParticle()->partner();
if(!partner) continue;
tHardBranchingPtr branch;
for(set<HardBranchingPtr>::const_iterator
clt=tree->branchings().begin();clt!=tree->branchings().end();++clt) {
if((**clt).branchingParticle()==partner) {
(**cjt).colourPartner(*clt);
branch=*clt;
break;
}
}
// compute the reference vectors
// both incoming, should all ready be done
if((**cjt).status()==HardBranching::Incoming &&
branch->status()==HardBranching::Incoming) {
Energy etemp = (*cjt)->beam()->momentum().z();
Lorentz5Momentum nvect(ZERO, ZERO,-etemp, abs(etemp));
tHardBranchingPtr branch2 = *cjt;
(**cjt).nVector(nvect);
while (branch2->parent()) {
branch2=branch2->parent();
branch2->nVector(nvect);
}
}
// both outgoing
else if((**cjt).status()==HardBranching::Outgoing&&
branch->status()==HardBranching::Outgoing) {
Boost boost=((*cjt)->pVector()+branch->pVector()).findBoostToCM();
Lorentz5Momentum pcm = branch->pVector();
pcm.boost(boost);
Lorentz5Momentum nvect = Lorentz5Momentum(ZERO,pcm.vect());
nvect.boost( -boost);
(**cjt).nVector(nvect);
}
else if((**cjt).status()==HardBranching::Incoming) {
Lorentz5Momentum pa = -(**cjt).showerMomentum()+branch->showerMomentum();
Lorentz5Momentum pb = (**cjt).showerMomentum();
Axis axis(pa.vect().unit());
LorentzRotation rot;
double sinth(sqrt(sqr(axis.x())+sqr(axis.y())));
if(axis.perp2()>1e-20) {
rot.setRotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.));
rot.rotateX(Constants::pi);
}
if(abs(1.-pa.e()/pa.vect().mag())>1e-6) rot.boostZ( pa.e()/pa.vect().mag());
pb*=rot;
Boost trans = -1./pb.e()*pb.vect();
trans.setZ(0.);
rot.boost(trans);
Energy scale=(**cjt).beam()->momentum().t();
Lorentz5Momentum pbasis(ZERO,(**cjt).beam()->momentum().vect().unit()*scale);
Lorentz5Momentum pcm = rot*pbasis;
rot.invert();
Lorentz5Momentum nvect = rot*Lorentz5Momentum(ZERO,-pcm.vect());
(**cjt).nVector(nvect);
tHardBranchingPtr branch2 = *cjt;
while (branch2->parent()) {
branch2=branch2->parent();
branch2->nVector(nvect);
}
}
else if(branch->status()==HardBranching::Incoming) {
Lorentz5Momentum nvect=Lorentz5Momentum(ZERO,branch->showerMomentum().vect());
(**cjt).nVector(nvect);
}
}
// now compute the new momenta
for(vector<HardBranchingPtr>::const_iterator cjt=jets.begin();
cjt!=jets.end();++cjt) {
if((**cjt).status()==HardBranching::Outgoing) {
(**cjt).setMomenta(transc,1.,Lorentz5Momentum());
}
}
incoming->setMomenta(transb,1.,Lorentz5Momentum());
}
void QTildeReconstructor::deepTransform(PPtr particle,
const LorentzRotation & r,
bool match,
PPtr original) const {
Lorentz5Momentum porig = particle->momentum();
if(!original) original = particle;
for ( int i = 0, N = particle->children().size(); i < N; ++i ) {
deepTransform(particle->children()[i],r,
particle->children()[i]->id()==original->id()&&match,original);
}
particle->transform(r);
if ( particle->next() ) deepTransform(particle->next(),r,match,original);
if(!match) return;
if(!particle->children().empty()) return;
// check if there's a daughter tree which also needs boosting
map<tShowerTreePtr,pair<tShowerProgenitorPtr,tShowerParticlePtr> >::const_iterator tit;
for(tit = _currentTree->treelinks().begin();
tit != _currentTree->treelinks().end();++tit) {
// if there is, boost it
if(tit->second.first && tit->second.second==original) {
Lorentz5Momentum pnew = tit->first->incomingLines().begin()
->first->progenitor()->momentum();
pnew *= tit->first->transform();
Lorentz5Momentum pdiff = porig-pnew;
Energy2 test = sqr(pdiff.x()) + sqr(pdiff.y()) +
sqr(pdiff.z()) + sqr(pdiff.t());
LorentzRotation rot;
if(test>1e-6*GeV2) rot = solveBoost(porig,pnew);
tit->first->transform(r*rot,false);
}
}
}
diff --git a/Shower/Default/QTildeShowerKinematics1to2.cc b/Shower/Default/QTildeShowerKinematics1to2.cc
--- a/Shower/Default/QTildeShowerKinematics1to2.cc
+++ b/Shower/Default/QTildeShowerKinematics1to2.cc
@@ -1,133 +1,132 @@
// -*- C++ -*-
//
// QTildeShowerKinematics1to2.cc is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 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 QTildeShowerKinematics1to2 class.
//
#include "QTildeShowerKinematics1to2.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "Herwig++/Shower/Base/ShowerParticle.h"
#include "ThePEG/Repository/CurrentGenerator.h"
using namespace Herwig;
vector<Lorentz5Momentum> QTildeShowerKinematics1to2::getBasis() const {
vector<Lorentz5Momentum> dum;
dum.push_back( _pVector );
dum.push_back( _nVector );
return dum;
}
void QTildeShowerKinematics1to2::setBasis(const Lorentz5Momentum &p,
const Lorentz5Momentum & n) {
_pVector=p;
_nVector=n;
}
Lorentz5Momentum QTildeShowerKinematics1to2::
sudakov2Momentum(double alpha, double beta, Energy px,
Energy py,unsigned int iopt) const {
if(isnan(beta)||isinf(beta))
throw Exception() << "beta infinite in "
<< "QTildeShowerKinematics1to2::sudakov2Momentum()"
<< Exception::eventerror;
Lorentz5Momentum dq;
if(iopt==0) {
const Boost beta_bb = -(_pVector + _nVector).boostVector();
Lorentz5Momentum p_bb = _pVector;
Lorentz5Momentum n_bb = _nVector;
p_bb.boost( beta_bb );
n_bb.boost( beta_bb );
// set first in b2b frame along z-axis (assuming that p and n are
// b2b as checked above)
dq=Lorentz5Momentum(ZERO, ZERO, (alpha - beta)*p_bb.vect().mag(),
alpha*p_bb.t() + beta*n_bb.t());
// add transverse components
dq.setX(px);
dq.setY(py);
// rotate to have z-axis parallel to p
// this rotation changed by PR to a different rotation with the same effect
// but different azimuthal angle to make implementing spin correlations easier
// dq.rotateUz( unitVector(p_bb.vect()) );
Axis axis(p_bb.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.));
dq.transform(rot);
}
else if(axis.z()<0.) {
dq.setZ(-dq.z());
}
// boost back
dq.boost( -beta_bb );
dq.rescaleMass();
// return the momentum
}
else {
const Boost beta_bb = -pVector().boostVector();
Lorentz5Momentum p_bb = pVector();
Lorentz5Momentum n_bb = nVector();
p_bb.boost( beta_bb );
n_bb.boost( beta_bb );
// set first in b2b frame along z-axis (assuming that p and n are
// b2b as checked above)
dq=Lorentz5Momentum (ZERO, ZERO, 0.5*beta*pVector().mass(),
alpha*pVector().mass() + 0.5*beta*pVector().mass());
// add transverse components
dq.setX(px);
dq.setY(py);
// changed to be same as other case
// dq.rotateUz( unitVector(n_bb.vect()) );
Axis axis(n_bb.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.));
dq.transform(rot);
}
else if(axis.z()<0.) {
dq.setZ(-dq.z());
}
// boost back
dq.boost( -beta_bb );
dq.rescaleMass();
}
return dq;
}
void QTildeShowerKinematics1to2::printScales(tShowerParticlePtr parent,
tShowerParticlePtr child1,
tShowerParticlePtr child2) const {
- assert(false);
// CurrentGenerator::log() << *parent << "\n" << *child1 << " "
// << *child2 << "\n";
// CurrentGenerator::log() << "testing parent\n";
// for(map<ShowerPartnerType::Type,pair<Energy,Energy> >::const_iterator
// it = parent->evolutionScales().begin();
// it!=parent->evolutionScales().end();++it) {
// CurrentGenerator::log() << it->first << " " << it->second.first/GeV << " "
// << it->second.second/GeV << "\n";
// }
// CurrentGenerator::log() << "testing child[0]\n";
// for(map<ShowerPartnerType::Type,pair<Energy,Energy> >::const_iterator
// it = child1->evolutionScales().begin();
// it!=child1->evolutionScales().end();++it) {
// CurrentGenerator::log() << it->first << " " << it->second.first/GeV << " "
// << it->second.second/GeV << "\n";
// }
// CurrentGenerator::log() << "testing child[1]\n";
// for(map<ShowerPartnerType::Type,pair<Energy,Energy> >::const_iterator
// it = child2->evolutionScales().begin();
// it!=child2->evolutionScales().end();++it) {
// CurrentGenerator::log() << it->first << " " << it->second.first/GeV << " "
// << it->second.second/GeV << "\n";
// }
}

File Metadata

Mime Type
text/x-diff
Expires
Mon, Jan 20, 10:08 PM (1 d, 7 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4195247
Default Alt Text
(420 KB)

Event Timeline