Page Menu
Home
HEPForge
Search
Configure Global Search
Log In
Files
F7879704
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
114 KB
Subscribers
None
View Options
diff --git a/Decay/Perturbative/SMTopDecayer.cc b/Decay/Perturbative/SMTopDecayer.cc
--- a/Decay/Perturbative/SMTopDecayer.cc
+++ b/Decay/Perturbative/SMTopDecayer.cc
@@ -1,1193 +1,1193 @@
// -*- C++ -*-
//
// SMTopDecayer.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 SMTopDecayer class.
//
#include "SMTopDecayer.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/ParVector.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/DecayMode.h"
#include "Herwig++/Decay/DecayVertex.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
#include "Herwig++/PDT/ThreeBodyAllOn1IntegralCalculator.h"
using namespace Herwig;
using namespace ThePEG::Helicity;
SMTopDecayer::SMTopDecayer()
: _wquarkwgt(6,0.),_wleptonwgt(3,0.), _xg_sampling(1.5),
_initialenhance(1.), _finalenhance(2.3), _useMEforT2(true) {
_wleptonwgt[0] = 0.302583;
_wleptonwgt[1] = 0.301024;
_wleptonwgt[2] = 0.299548;
_wquarkwgt[0] = 0.851719;
_wquarkwgt[1] = 0.0450162;
_wquarkwgt[2] = 0.0456962;
_wquarkwgt[3] = 0.859839;
_wquarkwgt[4] = 3.9704e-06;
_wquarkwgt[5] = 0.000489657;
generateIntermediates(true);
}
bool SMTopDecayer::accept(tcPDPtr parent, const tPDVector & children) const {
if(abs(parent->id()) != ParticleID::t) return false;
int id0(0),id1(0),id2(0);
for(tPDVector::const_iterator it = children.begin();
it != children.end();++it) {
int id=(**it).id(),absid(abs(id));
if(absid==ParticleID::b&&double(id)/double(parent->id())>0) {
id0=id;
}
else {
switch (absid) {
case ParticleID::nu_e:
case ParticleID::nu_mu:
case ParticleID::nu_tau:
id1 = id;
break;
case ParticleID::eminus:
case ParticleID::muminus:
case ParticleID::tauminus:
id2 = id;
break;
case ParticleID::b:
case ParticleID::d:
case ParticleID::s:
id1 = id;
break;
case ParticleID::u:
case ParticleID::c:
id2=id;
break;
default :
break;
}
}
}
if(id0==0||id1==0||id2==0) return false;
if(double(id1)/double(id2)>0) return false;
return true;
}
ParticleVector SMTopDecayer::decay(const Particle & parent,
const tPDVector & children) const {
int id1(0),id2(0);
for(tPDVector::const_iterator it = children.begin();
it != children.end();++it) {
int id=(**it).id(),absid=abs(id);
if(absid == ParticleID::b && double(id)/double(parent.id())>0) continue;
//leptons
if(absid > 10 && absid%2==0) id1=absid;
if(absid > 10 && absid%2==1) id2=absid;
//quarks
if(absid < 10 && absid%2==0) id2=absid;
if(absid < 10 && absid%2==1) id1=absid;
}
unsigned int imode(0);
if(id2 >=11 && id2<=16) imode = (id1-12)/2;
else imode = id1+1+id2/2;
bool cc = parent.id() == ParticleID::tbar;
ParticleVector out(generate(true,cc,imode,parent));
//arrange colour flow
PPtr pparent=const_ptr_cast<PPtr>(&parent);
out[1]->incomingColour(pparent,out[1]->id()<0);
ParticleVector products = out[0]->children();
if(products[0]->hasColour())
products[0]->colourNeighbour(products[1],true);
else if(products[0]->hasAntiColour())
products[0]->colourNeighbour(products[1],false);
return out;
}
void SMTopDecayer::persistentOutput(PersistentOStream & os) const {
os << _wvertex << _wquarkwgt << _wleptonwgt << _wplus << _alpha
<< _initialenhance << _finalenhance << _xg_sampling << _useMEforT2;
}
void SMTopDecayer::persistentInput(PersistentIStream & is, int) {
is >> _wvertex >> _wquarkwgt >> _wleptonwgt >> _wplus >> _alpha
>> _initialenhance >> _finalenhance >> _xg_sampling >> _useMEforT2;
}
ClassDescription<SMTopDecayer> SMTopDecayer::initSMTopDecayer;
// Definition of the static class description member.
void SMTopDecayer::Init() {
static ClassDocumentation<SMTopDecayer> documentation
("This is the implementation of the SMTopDecayer which "
"decays top quarks into bottom quarks and either leptons "
"or quark-antiquark pairs including the matrix element for top decay",
"The matrix element correction for top decay \\cite{Hamilton:2006ms}.",
"%\\cite{Hamilton:2006ms}\n"
"\\bibitem{Hamilton:2006ms}\n"
" K.~Hamilton and P.~Richardson,\n"
" ``A simulation of QCD radiation in top quark decays,''\n"
" JHEP {\\bf 0702}, 069 (2007)\n"
" [arXiv:hep-ph/0612236].\n"
" %%CITATION = JHEPA,0702,069;%%\n");
static ParVector<SMTopDecayer,double> interfaceQuarkWeights
("QuarkWeights",
"Maximum weights for the hadronic decays",
&SMTopDecayer::_wquarkwgt, 6, 1.0, 0.0, 10.0,
false, false, Interface::limited);
static ParVector<SMTopDecayer,double> interfaceLeptonWeights
("LeptonWeights",
"Maximum weights for the semi-leptonic decays",
&SMTopDecayer::_wleptonwgt, 3, 1.0, 0.0, 10.0,
false, false, Interface::limited);
static Parameter<SMTopDecayer,double> interfaceEnhancementFactor
("InitialEnhancementFactor",
"The enhancement factor for initial-state radiation in the shower to ensure"
" the weight for the matrix element correction is less than one.",
&SMTopDecayer::_initialenhance, 1.0, 1.0, 10000.0,
false, false, Interface::limited);
static Parameter<SMTopDecayer,double> interfaceFinalEnhancementFactor
("FinalEnhancementFactor",
"The enhancement factor for final-state radiation in the shower to ensure"
" the weight for the matrix element correction is less than one",
&SMTopDecayer::_finalenhance, 1.6, 1.0, 1000.0,
false, false, Interface::limited);
static Parameter<SMTopDecayer,double> interfaceSamplingTopHardMEC
("SamplingTopHardMEC",
"The importance sampling power for choosing an initial xg, "
"to sample xg according to xg^-_xg_sampling",
&SMTopDecayer::_xg_sampling, 1.5, 1.2, 2.0,
false, false, Interface::limited);
static Switch<SMTopDecayer,bool> interfaceUseMEForT2
("UseMEForT2",
"Use the matrix element correction, if available to fill the T2"
" region for the decay shower and don't fill using the shower",
&SMTopDecayer::_useMEforT2, true, false, false);
static SwitchOption interfaceUseMEForT2Shower
(interfaceUseMEForT2,
"Shower",
"Use the shower to fill the T2 region",
false);
static SwitchOption interfaceUseMEForT2ME
(interfaceUseMEForT2,
"ME",
"Use the Matrix element to fill the T2 region",
true);
static Reference<SMTopDecayer,ShowerAlpha> interfaceCoupling
("Coupling",
"Pointer to the object to calculate the coupling for the correction",
&SMTopDecayer::_alpha, false, false, true, false, false);
}
double SMTopDecayer::me2(const int, const Particle & inpart,
const ParticleVector & decay,
MEOption meopt) const {
// spinors etc for the decaying particle
if(meopt==Initialize) {
// spinors and rho
if(inpart.id()>0)
SpinorWaveFunction ::calculateWaveFunctions(_inHalf,_rho,
const_ptr_cast<tPPtr>(&inpart),
incoming);
else
SpinorBarWaveFunction::calculateWaveFunctions(_inHalfBar,_rho,
const_ptr_cast<tPPtr>(&inpart),
incoming);
ME(DecayMatrixElement(PDT::Spin1Half,PDT::Spin1Half,
PDT::Spin1Half,PDT::Spin1Half));
}
// setup spin info when needed
if(meopt==Terminate) {
// for the decaying particle
if(inpart.id()>0) {
SpinorWaveFunction::
constructSpinInfo(_inHalf,const_ptr_cast<tPPtr>(&inpart),incoming,true);
SpinorBarWaveFunction::constructSpinInfo(_inHalfBar,decay[0],outgoing,true);
SpinorWaveFunction ::constructSpinInfo(_outHalf ,decay[1],outgoing,true);
SpinorBarWaveFunction::constructSpinInfo(_outHalfBar,decay[2],outgoing,true);
}
else {
SpinorBarWaveFunction::
constructSpinInfo(_inHalfBar,const_ptr_cast<tPPtr>(&inpart),incoming,true);
SpinorWaveFunction::constructSpinInfo(_inHalf,decay[0],outgoing,true);
SpinorBarWaveFunction::constructSpinInfo(_outHalfBar,decay[1],outgoing,true);
SpinorWaveFunction ::constructSpinInfo(_outHalf ,decay[2],outgoing,true);
}
}
// spinors for the decay product
if(inpart.id()>0) {
SpinorBarWaveFunction::calculateWaveFunctions(_inHalfBar ,decay[0],outgoing);
SpinorWaveFunction ::calculateWaveFunctions(_outHalf ,decay[1],outgoing);
SpinorBarWaveFunction::calculateWaveFunctions(_outHalfBar,decay[2],outgoing);
}
else {
SpinorWaveFunction ::calculateWaveFunctions(_inHalf ,decay[0],outgoing);
SpinorBarWaveFunction::calculateWaveFunctions(_outHalfBar,decay[1],outgoing);
SpinorWaveFunction ::calculateWaveFunctions(_outHalf ,decay[2],outgoing);
}
Energy2 scale(sqr(inpart.mass()));
if(inpart.id() == ParticleID::t) {
//Define intermediate vector wave-function for Wplus
tcPDPtr Wplus(getParticleData(ParticleID::Wplus));
VectorWaveFunction inter;
unsigned int thel,bhel,fhel,afhel;
for(thel = 0;thel<2;++thel){
for(bhel = 0;bhel<2;++bhel){
inter = _wvertex->evaluate(scale,1,Wplus,_inHalf[thel],
_inHalfBar[bhel]);
for(afhel=0;afhel<2;++afhel){
for(fhel=0;fhel<2;++fhel){
ME()(thel,bhel,afhel,fhel) =
_wvertex->evaluate(scale,_outHalf[afhel],
_outHalfBar[fhel],inter);
}
}
}
}
}
else if(inpart.id() == ParticleID::tbar) {
VectorWaveFunction inter;
tcPDPtr Wminus(getParticleData(ParticleID::Wminus));
unsigned int tbhel,bbhel,afhel,fhel;
for(tbhel = 0;tbhel<2;++tbhel){
for(bbhel = 0;bbhel<2;++bbhel){
inter = _wvertex->
evaluate(scale,1,Wminus,_inHalf[bbhel],_inHalfBar[tbhel]);
for(afhel=0;afhel<2;++afhel){
for(fhel=0;fhel<2;++fhel){
ME()(tbhel,bbhel,fhel,afhel) =
_wvertex->evaluate(scale,_outHalf[afhel],
_outHalfBar[fhel],inter);
}
}
}
}
}
double output = (ME().contract(_rho)).real();
if(abs(decay[1]->id())<=6) output *=3.;
return output;
}
void SMTopDecayer::doinit() {
DecayIntegrator::doinit();
//get vertices from SM object
tcHwSMPtr hwsm = dynamic_ptr_cast<tcHwSMPtr>(standardModel());
if(!hwsm) throw InitException() << "Must have Herwig::StandardModel in "
<< "SMTopDecayer::doinit()";
_wvertex = hwsm->vertexFFW();
//initialise
_wvertex->init();
//set up decay modes
_wplus = getParticleData(ParticleID::Wplus);
DecayPhaseSpaceModePtr mode;
DecayPhaseSpaceChannelPtr Wchannel;
tPDVector extpart(4);
vector<double> wgt(1,1.0);
extpart[0] = getParticleData(ParticleID::t);
extpart[1] = getParticleData(ParticleID::b);
//lepton modes
for(int i=11; i<17;i+=2) {
extpart[2] = getParticleData(-i);
extpart[3] = getParticleData(i+1);
mode = new_ptr(DecayPhaseSpaceMode(extpart,this));
Wchannel = new_ptr(DecayPhaseSpaceChannel(mode));
Wchannel->addIntermediate(extpart[0],0,0.0,-1,1);
Wchannel->addIntermediate(_wplus,0,0.0,2,3);
Wchannel->init();
mode->addChannel(Wchannel);
addMode(mode,_wleptonwgt[(i-11)/2],wgt);
}
//quark modes
unsigned int iz=0;
for(int ix=1;ix<6;ix+=2) {
for(int iy=2;iy<6;iy+=2) {
// check that the combination of particles is allowed
if(_wvertex->allowed(-ix,iy,ParticleID::Wminus)) {
extpart[2] = getParticleData(-ix);
extpart[3] = getParticleData( iy);
mode = new_ptr(DecayPhaseSpaceMode(extpart,this));
Wchannel = new_ptr(DecayPhaseSpaceChannel(mode));
Wchannel->addIntermediate(extpart[0],0,0.0,-1,1);
Wchannel->addIntermediate(_wplus,0,0.0,2,3);
Wchannel->init();
mode->addChannel(Wchannel);
addMode(mode,_wquarkwgt[iz],wgt);
++iz;
}
else {
throw InitException() << "SMTopDecayer::doinit() the W vertex"
<< "cannot handle all the quark modes"
<< Exception::abortnow;
}
}
}
}
void SMTopDecayer::dataBaseOutput(ofstream & os,bool header) const {
if(header) os << "update decayers set parameters=\"";
// parameters for the DecayIntegrator base class
for(unsigned int ix=0;ix<_wquarkwgt.size();++ix) {
os << "newdef " << name() << ":QuarkWeights " << ix << " "
<< _wquarkwgt[ix] << "\n";
}
for(unsigned int ix=0;ix<_wleptonwgt.size();++ix) {
os << "newdef " << name() << ":LeptonWeights " << ix << " "
<< _wleptonwgt[ix] << "\n";
}
DecayIntegrator::dataBaseOutput(os,false);
if(header) os << "\n\" where BINARY ThePEGName=\"" << fullName() << "\";" << endl;
}
void SMTopDecayer::doinitrun() {
DecayIntegrator::doinitrun();
if(initialize()) {
for(unsigned int ix=0;ix<numberModes();++ix) {
if(ix<3) _wleptonwgt[ix ] = mode(ix)->maxWeight();
else _wquarkwgt [ix-3] = mode(ix)->maxWeight();
}
}
}
WidthCalculatorBasePtr SMTopDecayer::threeBodyMEIntegrator(const DecayMode & dm) const {
// identify W decay products
int sign = dm.parent()->id() > 0 ? 1 : -1;
int iferm(0),ianti(0);
for(ParticleMSet::const_iterator pit=dm.products().begin();
pit!=dm.products().end();++pit) {
int id = (**pit).id();
if(id*sign != ParticleID::b) {
if (id*sign > 0 ) iferm = id*sign;
else ianti = id*sign;
}
}
assert(iferm!=0&&ianti!=0);
// work out which mode we are doing
int imode(-1);
for(unsigned int ix=0;ix<numberModes();++ix) {
if(mode(ix)->externalParticles(2)->id() == ianti &&
mode(ix)->externalParticles(3)->id() == iferm ) {
imode = ix;
break;
}
}
assert(imode>=0);
// get the masses we need
Energy m[3] = {mode(imode)->externalParticles(1)->mass(),
mode(imode)->externalParticles(3)->mass(),
mode(imode)->externalParticles(2)->mass()};
return
new_ptr(ThreeBodyAllOn1IntegralCalculator<SMTopDecayer>
(3,_wplus->mass(),_wplus->width(),0.0,*this,imode,m[0],m[1],m[2]));
}
InvEnergy SMTopDecayer::threeBodydGammads(const int imode, const Energy2 mt2,
const Energy2 mffb2, const Energy mb,
const Energy mf, const Energy mfb) const {
Energy mffb(sqrt(mffb2));
Energy mw(_wplus->mass());
Energy2 mw2(sqr(mw)),gw2(sqr(_wplus->width()));
Energy mt(sqrt(mt2));
Energy Eb = 0.5*(mt2-mffb2-sqr(mb))/mffb;
Energy Ef = 0.5*(mffb2-sqr(mfb)+sqr(mf))/mffb;
Energy Ebm = sqrt(sqr(Eb)-sqr(mb));
Energy Efm = sqrt(sqr(Ef)-sqr(mf));
Energy2 upp = sqr(Eb+Ef)-sqr(Ebm-Efm);
Energy2 low = sqr(Eb+Ef)-sqr(Ebm+Efm);
InvEnergy width=(dGammaIntegrand(mffb2,upp,mt,mb,mf,mfb,mw)-
dGammaIntegrand(mffb2,low,mt,mb,mf,mfb,mw))
/32./mt2/mt/8/pow(Constants::pi,3)/(sqr(mffb2-mw2)+mw2*gw2);
// couplings
width *= 0.25*sqr(4.*Constants::pi*generator()->standardModel()->alphaEM(mt2)/
generator()->standardModel()->sin2ThetaW());
width *= generator()->standardModel()->CKM(*mode(imode)->externalParticles(0),
*mode(imode)->externalParticles(1));
if(abs(mode(imode)->externalParticles(2)->id())<=6) {
width *=3.;
if(abs(mode(imode)->externalParticles(2)->id())%2==0)
width *=generator()->standardModel()->CKM(*mode(imode)->externalParticles(2),
*mode(imode)->externalParticles(3));
else
width *=generator()->standardModel()->CKM(*mode(imode)->externalParticles(3),
*mode(imode)->externalParticles(2));
}
// final spin average
assert(!isnan(width*GeV));
return 0.5*width;
}
Energy6 SMTopDecayer::dGammaIntegrand(Energy2 mffb2, Energy2 mbf2, Energy mt,
Energy mb, Energy mf, Energy mfb, Energy mw) const {
Energy2 mt2(sqr(mt)) ,mb2(sqr(mb)) ,mf2(sqr(mf )),mfb2(sqr(mfb )),mw2(sqr(mw ));
Energy4 mt4(sqr(mt2)),mb4(sqr(mb2)),mf4(sqr(mf2)),mfb4(sqr(mfb2)),mw4(sqr(mw2));
return -mbf2 * ( + 6 * mb2 * mf2 * mfb2 * mffb2 + 6 * mb2 * mt2 * mfb2 * mffb2
+ 6 * mb2 * mt2 * mf2 * mffb2 + 12 * mb2 * mt2 * mf2 * mfb2
- 3 * mb2 * mfb4 * mffb2 + 3 * mb2 * mf2 * mffb2 * mffb2
- 3 * mb2 * mf4 * mffb2 - 6 * mb2 * mt2 * mfb4
- 6 * mb2 * mt2 * mf4 - 3 * mb4 * mfb2 * mffb2
- 3 * mb4 * mf2 * mffb2 - 6 * mb4 * mf2 * mfb2
+ 3 * mt4 * mf4 + 3 * mb4 * mfb4
+ 3 * mb4 * mf4 + 3 * mt4 * mfb4
+ 3 * mb2 * mfb2 * mffb2 * mffb2 + 3 * mt2 * mfb2 * mffb2 * mffb2
- 3 * mt2 * mfb4 * mffb2 + 3 * mt2 * mf2 * mffb2 * mffb2
- 3 * mt2 * mf4 * mffb2 - 3 * mt4 * mfb2 * mffb2
- 3 * mt4 * mf2 * mffb2 - 6 * mt4 * mf2 * mfb2
+ 6 * mt2 * mf2 * mfb2 * mffb2 + 12 * mt2 * mf2 * mw4
+ 12 * mb2 * mfb2 * mw4 + 12 * mb2 * mt2 * mw4
+ 6 * mw2 * mt2 * mfb2 * mbf2 - 12 * mw2 * mt2 * mf2 * mffb2
- 6 * mw2 * mt2 * mf2 * mbf2 - 12 * mw2 * mt2 * mf2 * mfb2
- 12 * mw2 * mb2 * mfb2 * mffb2 - 6 * mw2 * mb2 * mfb2 * mbf2
+ 6 * mw2 * mb2 * mf2 * mbf2 - 12 * mw2 * mb2 * mf2 * mfb2
- 12 * mw2 * mb2 * mt2 * mfb2 - 12 * mw2 * mb2 * mt2 * mf2
+ 12 * mf2 * mfb2 * mw4 + 4 * mbf2 * mbf2 * mw4
- 6 * mfb2 * mbf2 * mw4 - 6 * mf2 * mbf2 * mw4
- 6 * mt2 * mbf2 * mw4 - 6 * mb2 * mbf2 * mw4
+ 12 * mw2 * mt2 * mf4 + 12 * mw2 * mt4 * mf2
+ 12 * mw2 * mb2 * mfb4 + 12 * mw2 * mb4 * mfb2) /mw4 / 3.;
}
void SMTopDecayer::initializeMECorrection(ShowerTreePtr tree, double & initial,
double & final) {
// check the outgoing particles
map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator cit;
ShowerParticlePtr part[2];
unsigned int ix(0);
for(cit=tree->outgoingLines().begin();cit!=tree->outgoingLines().end();++cit) {
part[ix]=cit->first->progenitor();
++ix;
}
// check the final-state particles and get the masses
if(abs(part[0]->id())==ParticleID::Wplus&&abs(part[1]->id())==ParticleID::b) {
_ma=part[0]->mass();
_mc=part[1]->mass();
}
else if(abs(part[1]->id())==ParticleID::Wplus&&abs(part[0]->id())==ParticleID::b) {
_ma=part[1]->mass();
_mc=part[0]->mass();
}
else {
return;
}
// set the top mass
_mt=tree->incomingLines().begin()->first->progenitor()->mass();
// set the gluon mass
_mg=getParticleData(ParticleID::g)->constituentMass();
// set the radiation enhancement factors
initial = _initialenhance;
final = _finalenhance;
// reduced mass parameters
_a=sqr(_ma/_mt);
_g=sqr(_mg/_mt);
_c=sqr(_mc/_mt);
useMe();
}
void SMTopDecayer::applyHardMatrixElementCorrection(ShowerTreePtr tree) {
// Get b and a and put them in particle vector ba in that order...
ParticleVector ba;
map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator cit;
for(cit=tree->outgoingLines().begin();cit!=tree->outgoingLines().end();++cit)
ba.push_back(cit->first->copy());
PPtr temp;
if(abs(ba[0]->id())!=5) swap(ba[0],ba[1]);
// Get the starting scales for the showers $\tilde{\kappa}_{b}$
// $\tilde{\kappa}_{c}$. These are needed in order to know the boundary
// of the dead zone.
double ktb(0.),ktc(0.);
map<ShowerProgenitorPtr,ShowerParticlePtr>::const_iterator cjt;
for(cjt = tree->incomingLines().begin();
cjt!= tree->incomingLines().end();++cjt) {
if(abs(cjt->first->progenitor()->id())==6)
ktb=sqr(cjt->first->progenitor()->evolutionScale()/_mt);
}
for(cit = tree->outgoingLines().begin();
cit!= tree->outgoingLines().end();++cit) {
if(abs(cit->first->progenitor()->id())==5)
ktc=sqr(cit->first->progenitor()->evolutionScale()/_mt);
}
if (ktb<=0.||ktc<=0.) {
throw Exception()
<< "SMTopDecayer::applyHardMatrixElementCorrection()"
<< " did not set ktb,ktc"
<< Exception::abortnow;
}
_ktb = ktb;
_ktc = ktc;
// Now decide if we get an emission into the dead region.
// If there is an emission newfs stores momenta for a,c,g
// according to NLO decay matrix element.
vector<Lorentz5Momentum> newfs = applyHard(ba,ktb,ktc);
// If there was no gluon emitted return.
if(newfs.size()!=3) return;
// Sanity checks to ensure energy greater than mass etc :)
bool check = true;
tcPDPtr gluondata=getParticleData(ParticleID::g);
if (newfs[0].e()<ba[0]->data().constituentMass()) check = false;
if (newfs[1].e()<ba[1]->mass()) check = false;
if (newfs[2].e()<gluondata->constituentMass()) check = false;
// Return if insane:
if (!check) return;
// Set masses in 5-vectors:
newfs[0].setMass(ba[0]->mass());
newfs[1].setMass(ba[1]->mass());
newfs[2].setMass(ZERO);
// The next part of this routine sets the colour structure.
// To do this for decays we assume that the gluon comes from c!
// First create new particle objects for c, a and gluon:
PPtr newg = gluondata->produceParticle(newfs[2]);
PPtr newc,newa;
newc = ba[0]->data().produceParticle(newfs[0]);
newa = ba[1];
newa->set5Momentum(newfs[1]);
// set the colour lines
ColinePtr col;
if(ba[0]->id()>0) {
col=ba[0]->colourLine();
col->addColoured(newg);
newg->colourNeighbour(newc);
}
else {
col=ba[0]->antiColourLine();
col->addAntiColoured(newg);
newg->antiColourNeighbour(newc);
}
// change the existing quark and antiquark
PPtr orig;
for(cit=tree->outgoingLines().begin();cit!=tree->outgoingLines().end();++cit) {
if(cit->first->progenitor()->id()==newc->id()) {
// remove old particles from colour line
if(newc->id()>0) {
col->removeColoured(cit->first->copy());
col->removeColoured(cit->first->progenitor());
}
else {
col->removeAntiColoured(cit->first->copy());
col->removeAntiColoured(cit->first->progenitor());
}
// insert new particles
cit->first->copy(newc);
ShowerParticlePtr sp(new_ptr(ShowerParticle(*newc,2,true)));
cit->first->progenitor(sp);
tree->outgoingLines()[cit->first]=sp;
cit->first->perturbative(false);
orig=cit->first->original();
}
else {
cit->first->copy(newa);
ShowerParticlePtr sp(new_ptr(ShowerParticle(*newa,2,true)));
map<tShowerTreePtr,pair<tShowerProgenitorPtr,
tShowerParticlePtr> >::const_iterator tit;
for(tit = tree->treelinks().begin();
tit != tree->treelinks().end();++tit) {
if(tit->second.first && tit->second.second==cit->first->progenitor())
break;
}
cit->first->progenitor(sp);
if(tit!=tree->treelinks().end())
tree->updateLink(tit->first,make_pair(cit->first,sp));
tree->outgoingLines()[cit->first]=sp;
cit->first->perturbative(true);
}
}
// Add the gluon to the shower:
ShowerParticlePtr sg =new_ptr(ShowerParticle(*newg,2,true));
ShowerProgenitorPtr gluon=new_ptr(ShowerProgenitor(orig,newg,sg));
gluon->perturbative(false);
tree->outgoingLines().insert(make_pair(gluon,sg));
if(!inTheDeadRegion(_xg,_xa,_ktb,_ktc)) {
generator()->log()
<< "SMTopDecayer::applyHardMatrixElementCorrection()\n"
<< "Just found a point that escaped from the dead region!\n"
<< " _xg: " << _xg << " _xa: " << _xa
<< " newfs.size(): " << newfs.size() << endl;
}
tree->hardMatrixElementCorrection(true);
}
vector<Lorentz5Momentum> SMTopDecayer::
applyHard(const ParticleVector &p,double ktb, double ktc) {
// ********************************* //
// First we see if we get a dead //
// region event: _xa,_xg //
// ********************************* //
vector<Lorentz5Momentum> fs;
// Return if there is no (NLO) gluon emission:
double weight = getHard(ktb,ktc);
if(weight>1.) {
generator()->log() << "Weight greater than 1 for hard emission in "
<< "SMTopDecayer::applyHard xg = " << _xg
<< " xa = " << _xa << "\n";
weight=1.;
}
// Accept/Reject
if (weight<UseRandom::rnd()||p.size()!= 2) return fs;
// Drop events if getHard returned a negative weight
// as in events that, somehow have escaped from the dead region
// or, worse, the allowed region.
if(weight<0.) return fs;
// Calculate xc by momentum conservation:
_xc = 2.-_xa-_xg;
// ************************************ //
// Now we get the boosts & rotations to //
// go from lab to top rest frame with //
// a in the +z direction. //
// ************************************ //
Lorentz5Momentum pa_lab,pb_lab,pc_lab,pg_lab;
// Calculate momentum of b:
pb_lab = p[0]->momentum() + p[1]->momentum();
// Define/assign momenta of c,a and the gluon:
if(abs(p[0]->id())==5) {
pc_lab = p[0]->momentum();
pa_lab = p[1]->momentum();
} else {
pc_lab = p[1]->momentum();
pa_lab = p[0]->momentum();
}
// Calculate the boost to the b rest frame:
SpinOneLorentzRotation rot0(pb_lab.findBoostToCM());
// Calculate the rotation matrix to position a along the +z direction
// in the rest frame of b and does a random rotation about z:
SpinOneLorentzRotation rot1 = rotateToZ(rot0*pa_lab);
// Calculate the boost from the b rest frame back to the lab:
// and the inverse of the random rotation about the z-axis and the
// rotation required to align a with +z:
SpinOneLorentzRotation invrot = rot0.inverse()*rot1.inverse();
// ************************************ //
// Now we construct the momenta in the //
// b rest frame using _xa,_xg. //
// First we construct b, then c and g, //
// finally we generate a by momentum //
// conservation. //
// ************************************ //
Lorentz5Momentum pa_brf, pb_brf(_mt), pc_brf, pg_brf;
// First we set the top quark to being on-shell and at rest.
// Second we set the energies of c and g,
pc_brf.setE(0.5*_mt*(2.-_xa-_xg));
pg_brf.setE(0.5*_mt*_xg);
// then their masses,
pc_brf.setMass(_mc);
pg_brf.setMass(ZERO);
// Now set the z-component of c and g. For pg we simply start from
// _xa and _xg, while for pc we assume it is equal to minus the sum
// of the z-components of a (assumed to point in the +z direction) and g.
double root=sqrt(_xa*_xa-4.*_a);
pg_brf.setZ(_mt*(1.-_xa-_xg+0.5*_xa*_xg-_c+_a)/root);
pc_brf.setZ(-1.*( pg_brf.z()+_mt*0.5*root));
// Now set the y-component of c and g's momenta
pc_brf.setY(ZERO);
pg_brf.setY(ZERO);
// Now set the x-component of c and g's momenta
pg_brf.setX(sqrt(sqr(pg_brf.t())-sqr(pg_brf.z())));
pc_brf.setX(-pg_brf.x());
// Momenta b,c,g are now set. Now we obtain a from momentum conservation,
pa_brf = pb_brf-pc_brf-pg_brf;
pa_brf.setMass(pa_brf.m());
pa_brf.rescaleEnergy();
// ************************************ //
// Now we orient the momenta and boost //
// them back to the original lab frame. //
// ************************************ //
// As in herwig6507 we assume that, in the rest frame
// of b, we have aligned the W boson momentum in the
// +Z direction by rot1*rot0*pa_lab, therefore
// we obtain the new pa_lab by applying:
// invrot*pa_brf.
pa_lab = invrot*pa_brf;
pb_lab = invrot*pb_brf;
pc_lab = invrot*pc_brf;
pg_lab = invrot*pg_brf;
fs.push_back(pc_lab);
fs.push_back(pa_lab);
fs.push_back(pg_lab);
return fs;
}
double SMTopDecayer::getHard(double ktb, double ktc) {
// zero the variables
_xg = 0.;
_xa = 0.;
_xc = 0.;
// Get a phase space point in the dead region:
double volume_factor = deadRegionxgxa(ktb,ktc);
// if outside region return -1
if(volume_factor<0) return volume_factor;
// Compute the weight for this phase space point:
double weight = volume_factor*me(_xa,_xg)*(1.+_a-_c-_xa);
// Alpha_S and colour factors - this hard wired Alpha_S needs removing.
weight *= (4./3.)/Constants::pi
*(_alpha->value(_mt*_mt*_xg*(1.-_xa+_a-_c)
/(2.-_xg-_xa-_c)));
return weight;
}
bool SMTopDecayer::softMatrixElementVeto(ShowerProgenitorPtr initial,
ShowerParticlePtr parent,Branching br) {
// check if we need to apply the full correction
- unsigned int id[2]={abs(initial->progenitor()->id()),abs(parent->id())};
+ long id[2]={abs(initial->progenitor()->id()),abs(parent->id())};
// the initial-state correction
if(id[0]==ParticleID::t&&id[1]==ParticleID::t)
{
Energy pt=br.kinematics->pT();
// check if hardest so far
// if not just need to remove effect of enhancement
bool veto(false);
// if not hardest so far
if(pt<initial->highestpT())
veto=!UseRandom::rndbool(1./_initialenhance);
// if hardest so far do calculation
else
{
// values of kappa and z
double z(br.kinematics->z()),kappa(sqr(br.kinematics->scale()/_mt));
// parameters for the translation
double w(1.-(1.-z)*(kappa-1.)),u(1.+_a-_c-(1.-z)*kappa),v(sqr(u)-4.*_a*w*z);
// veto if outside phase space
if(v<0.)
veto=true;
// otherwise calculate the weight
else
{
v = sqrt(v);
double xa((0.5*(u+v)/w+0.5*(u-v)/z)),xg((1.-z)*kappa);
double f(me(xa,xg)),
J(0.5*(u+v)/sqr(w)-0.5*(u-v)/sqr(z)+_a*sqr(w-z)/(v*w*z));
double wgt(f*J*2./kappa/(1.+sqr(z)-2.*z/kappa)/_initialenhance);
// This next `if' prevents the hardest emission from the
// top shower ever entering the so-called T2 region of the
// phase space if that region is to be populated by the hard MEC.
if(_useMEforT2&&xg>xgbcut(_ktb)) wgt = 0.;
if(wgt>1.) {
generator()->log() << "Violation of maximum for initial-state "
<< " soft veto in "
<< "SMTopDecayer::softMatrixElementVeto"
<< "xg = " << xg << " xa = " << xa
<< "weight = " << wgt << "\n";
wgt=1.;
}
// compute veto from weight
veto = !UseRandom::rndbool(wgt);
}
// if not vetoed reset max
if(!veto) initial->highestpT(pt);
}
// if vetoing reset the scale
if(veto) parent->setEvolutionScale(br.kinematics->scale());
// return the veto
return veto;
}
// final-state correction
else if(id[0]==ParticleID::b&&id[1]==ParticleID::b)
{
Energy pt=br.kinematics->pT();
// check if hardest so far
// if not just need to remove effect of enhancement
bool veto(false);
// if not hardest so far
if(pt<initial->highestpT()) return !UseRandom::rndbool(1./_finalenhance);
// if hardest so far do calculation
// values of kappa and z
double z(br.kinematics->z()),kappa(sqr(br.kinematics->scale()/_mt));
// momentum fractions
double xa(1.+_a-_c-z*(1.-z)*kappa),r(0.5*(1.+_c/(1.+_a-xa))),root(sqr(xa)-4.*_a);
if(root<0.) {
generator()->log() << "Imaginary root for final-state veto in "
<< "SMTopDecayer::softMatrixElementVeto"
<< "\nz = " << z << "\nkappa = " << kappa
<< "\nxa = " << xa
<< "\nroot^2= " << root;
parent->setEvolutionScale(br.kinematics->scale());
return true;
}
root=sqrt(root);
double xg((2.-xa)*(1.-r)-(z-r)*root);
// xfact (below) is supposed to equal xg/(1-z).
double xfact(z*kappa/2./(z*(1.-z)*kappa+_c)*(2.-xa-root)+root);
// calculate the full result
double f(me(xa,xg));
// jacobian
double J(z*root);
double wgt(f*J*2.*kappa/(1.+sqr(z)-2.*_c/kappa/z)/sqr(xfact)/_finalenhance);
if(wgt>1.) {
generator()->log() << "Violation of maximum for final-state soft veto in "
<< "SMTopDecayer::softMatrixElementVeto"
<< "xg = " << xg << " xa = " << xa
<< "weight = " << wgt << "\n";
wgt=1.;
}
// compute veto from weight
veto = !UseRandom::rndbool(wgt);
// if not vetoed reset max
if(!veto) initial->highestpT(pt);
// if vetoing reset the scale
if(veto) parent->setEvolutionScale(br.kinematics->scale());
// return the veto
return veto;
}
// otherwise don't veto
else return !UseRandom::rndbool(1./_finalenhance);
}
double SMTopDecayer::me(double xw,double xg) {
double prop(1.+_a-_c-xw),xg2(sqr(xg));
double lambda=sqrt(1.+_a*_a+_c*_c-2.*_a-2.*_c-2.*_a*_c);
double denom=(1.-2*_a*_a+_a+_c*_a+_c*_c-2.*_c);
double wgt=-_c*xg2/prop+(1.-_a+_c)*xg-(prop*(1 - xg)+xg2)
+(0.5*(1.+2.*_a+_c)*sqr(prop-xg)*xg+2.*_a*prop*xg2)/denom;
return wgt/(lambda*prop);
}
// This function is auxiliary to the xab function.
double SMTopDecayer::xgbr(int toggle) {
return 1.+toggle*sqrt(_a)-_c*(1.-toggle*sqrt(_a))/(1.-_a);
}
// This function is auxiliary to the xab function.
double SMTopDecayer::ktr(double xgb, int toggle) {
return 2.*xgb/
(xgb+toggle*sqrt((1.-1./_a)
*(xgb-xgbr( 1))
*(xgb-xgbr(-1))));
}
// Function xab determines xa (2*W energy fraction) for a given value
// of xg (2*gluon energy fraction) and kappa tilde (q tilde squared over
// m_top squared). Hence this function allows you to draw 1: the total
// phase space volume in the xa vs xg plane 2: for a given value of
// kappa tilde (i.e. starting evolution scale) the associated contour
// in the xa vs xg plane (and hence the regions that either shower can
// populate). This calculation is done assuming the emission came from
// the top quark i.e. kappa tilde here is the q tilde squared of the TOP
// quark divided by m_top squared.
double SMTopDecayer::xab(double xgb, double kt, int toggle) {
double xab;
if(toggle==2) {
// This applies for g==0.&&kt==ktr(a,c,0.,xgb,1).
xab = -2.*_a*(xgb-2.)/(1.+_a-_c-xgb);
} else if(toggle==1) {
// This applies for kt==1&&g==0.
double lambda = sqrt(sqr(xgb-1.+_a+_c)-4.*_a*_c);
xab = (0.5/(kt-xgb))*(kt*(1.+_a-_c-xgb)-lambda)
+ (0.5/(kt+xgb*(1.-kt)))*(kt*(1.+_a-_c-xgb)+lambda);
} else {
// This is the form of xab FOR _g=0.
double ktmktrpktmktrm = kt*kt - 4.*_a*(kt-1.)*xgb*xgb
/ (sqr(1.-_a-_c-xgb)-4.*_a*_c);
if(fabs(kt-(2.*xgb-2.*_g)/(xgb-sqrt(xgb*xgb-4.*_g)))/kt>1.e-6) {
double lambda = sqrt((sqr(1.-_a-_c-xgb)-4.*_a*_c)*ktmktrpktmktrm);
xab = (0.5/(kt-xgb))*(kt*(1.+_a-_c-xgb)-lambda)
+ (0.5/(kt+xgb*(1.-kt)))*(kt*(1.+_a-_c-xgb)+lambda);
}
else {
// This is the value of xa as a function of xb when kt->infinity.
// Where we take any kt > (2.*xgb-2.*_g)/(xgb-sqrt(xgb*xgb-4.*_g))
// as being effectively infinite. This kt value is actually the
// maximum allowed value kt can have if the phase space is calculated
// without the approximation of _g=0 (massless gluon). This formula
// for xab below is then valid for _g=0 AND kt=infinity only.
xab = ( 2.*_c+_a*(xgb-2.)
+ 3.*xgb
- xgb*(_c+xgb+sqrt(_a*_a-2.*(_c-xgb+1.)*_a+sqr(_c+xgb-1.)))
- 2.
)/2./(xgb-1.);
}
}
if(isnan(xab)) {
double ktmktrpktmktrm = ( sqr(xgb*kt-2.*(xgb-_g))
-kt*kt*(1.-1./_a)*(xgb-xgbr( 1)-_g/(1.+sqrt(_a)))
*(xgb-xgbr(-1)-_g/(1.-sqrt(_a)))
)/
(xgb*xgb-(1.-1./_a)*(xgb-xgbr( 1)-_g/(1.+sqrt(_a)))
*(xgb-xgbr(-1)-_g/(1.-sqrt(_a)))
);
double lambda = sqrt((xgb-1.+sqr(sqrt(_a)+sqrt(_c-_g)))
*(xgb-1.+sqr(sqrt(_a)-sqrt(_c-_g)))*
ktmktrpktmktrm);
xab = (0.5/(kt-xgb+_g))*(kt*(1.+_a-_c+_g-xgb)-lambda)
+ (0.5/(kt+xgb*(1.-kt)-_g))*(kt*(1.+_a-_c+_g-xgb)+lambda);
if(isnan(xab))
throw Exception() << "TopMECorrection::xab complex x_a value.\n"
<< " xgb = " << xgb << "\n"
<< " xab = " << xab << "\n"
<< " toggle = " << toggle << "\n"
<< " ktmktrpktmktrm = " << ktmktrpktmktrm
<< Exception::eventerror;
}
return xab;
}
// xgbcut is the point along the xg axis where the upper bound on the
// top quark (i.e. b) emission phase space goes back on itself in the
// xa vs xg plane i.e. roughly mid-way along the xg axis in
// the xa vs xg Dalitz plot.
double SMTopDecayer::xgbcut(double kt) {
double lambda2 = 1.+_a*_a+_c*_c-2.*_a-2.*_c-2.*_a*_c;
double num1 = kt*kt*(1.-_a-_c);
double num2 = 2.*kt*sqrt(_a*(kt*kt*_c+lambda2*(kt-1.)));
return (num1-num2)/(kt*kt-4.*_a*(kt-1.));
}
double SMTopDecayer::xaccut(double kt) {
return 1.+_a-_c-0.25*kt;
}
double SMTopDecayer::z(double xac, double kt,
int toggle1, int toggle2) {
double z = -1.0;
if(toggle2==0) {
z = (kt+toggle1*sqrt(kt*(kt-4.*(1.+_a-_c-xac))))/(2.*kt);
} else if(toggle2==1) {
z = ((1.+_a+_c-xac)+toggle1*(1.+_a-_c-xac))
/(2.*(1.+_a-xac));
} else if(toggle2==2) {
z = 0.5;
} else {
throw Exception() << "Cannot determine z in SMTopDecayer::z()"
<< Exception::eventerror;
}
return z;
}
double SMTopDecayer::xgc(double xac, double kt,
int toggle1, int toggle2) {
double tiny(1.e-6);
double xaToMinBoundary(xac*xac-4.*_a);
if(xaToMinBoundary<0) {
if(fabs(xaToMinBoundary/(1.-_a)/(1.-_a))<tiny)
xaToMinBoundary *= -1.;
else
throw Exception() << "SMTopDecayer::xgc xa not in phase space!"
<< Exception::eventerror;
}
return (2.-xac)*(1.-0.5*(1.+_c/(1.+_a-xac)))
-(z(xac,kt,toggle1,toggle2)-0.5*(1.+_c/(1.+_a-xac)))
*sqrt(xaToMinBoundary);
}
double SMTopDecayer::xginvc0(double xg , double kt) {
// The function xg(kappa_tilde_c,xa) surely, enough, draws a
// line of constant kappa_tilde_c in the xg, xa Dalitz plot.
// Such a function can therefore draw the upper and lower
// edges of the phase space for emission from c (the b-quark).
// However, to sample the soft part of the dead zone effectively
// we want to generate a value of xg first and THEN distribute
// xa in the associated allowed part of the dead zone. Hence, the
// function we want, to define the dead zone in xa for a given
// xg, is the inverse of xg(kappa_tilde_c,xa). The full expression
// for xg(kappa_tilde_c,xa) is complicated and, sure enough,
// does not invert. Therefore we try to overestimate the size
// of the dead zone initially, rejecting events which do not
// fall exactly inside it afterwards, with the immediate aim
// of getting an approximate version of xg(kappa_tilde_c,xa)
// that can be inverted. We do this by simply setting c=0 i.e.
// the b-quark mass to zero (and the gluon mass of course), in
// the full expression xg(...). The result of inverting this
// function is the output of this routine (a value of xa) hence
// the name xginvc0. xginvc0 is calculated to be,
// xginvc0 = (1./3.)*(1.+a+pow((U+sqrt(4.*V*V*V+U*U))/2.,1./3.)
// -V*pow(2./(U+sqrt(4.*V*V*V+U*U)),1./3.)
// )
// U = 2.*a*a*a - 66.*a*a + 9.*a*kt*xg + 18.*a*kt
// - 66.*a + 27.*kt*xg*xg - 45.*kt*xg +18.*kt +2. ;
// V = -1.-a*a-14.*a-3.kt*xg+3.*kt;
// This function, as with many functions in this ME correction,
// is plagued by cuts that have to handled carefully in numerical
// implementation. We have analysed the cuts and hence we implement
// it in the following way, with a series of 'if' statements.
//
// A useful -definition- to know in deriving the v<0 terms is
// that tanh^-1(z) = 0.5*(log(1.+z)-log(1.-z)).
double u,v,output;
u = 2.*_a*_a*_a-66.*_a*_a
+9.*xg*kt*_a+18.*kt*_a
-66.*_a+27.*xg*xg*kt
-45.*xg*kt+18.*kt+2.;
v = -_a*_a-14.*_a-3.*xg*kt+3.*kt-1.;
double u2=u*u,v3=v*v*v;
if(v<0.) {
if(u>0.&&(4.*v3+u2)<0.) output = cos( atan(sqrt(-4.*v3-u2)/u)/3.);
else if(u>0.&&(4.*v3+u2)>0.) output = cosh(atanh(sqrt( 4.*v3+u2)/u)/3.);
else output = cos(( atan(sqrt(-4.*v3-u2)/u)
+Constants::pi)/3.);
output *= 2.*sqrt(-v);
} else {
output = sinh(log((u+sqrt(4.*v3+u2))/(2.*sqrt(v3)))/3.);
output *= 2.*sqrt(v);
}
if(isnan(output)||isinf(output)) {
throw Exception() << "TopMECorrection::xginvc0:\n"
<< "possible numerical instability detected.\n"
<< "\n v = " << v << " u = " << u << "\n4.*v3+u2 = " << 4.*v3+u2
<< "\n_a = " << _a << " ma = " << sqrt(_a*_mt*_mt/GeV2)
<< "\n_c = " << _c << " mc = " << sqrt(_c*_mt*_mt/GeV2)
<< "\n_g = " << _g << " mg = " << sqrt(_g*_mt*_mt/GeV2)
<< Exception::eventerror;
}
return ( 1.+_a +output)/3.;
}
double SMTopDecayer::approxDeadMaxxa(double xg,double ktb,double ktc) {
double maxxa(0.);
double x = min(xginvc0(xg,ktc),
xab(xg,(2.*xg-2.*_g)/(xg-sqrt(xg*xg-4.*_g)),0));
double y(-9999999999.);
if(xg>2.*sqrt(_g)&&xg<=xgbcut(ktb)) {
y = max(xab(xg,ktb,0),xab(xg,1.,1));
} else if(xg>=xgbcut(ktb)&&xg<=1.-sqr(sqrt(_a)+sqrt(_c))) {
y = max(xab(xg,ktr(xg,1),2),xab(xg,1.,1));
}
if(xg>2.*sqrt(_g)&&xg<=1.-sqr(sqrt(_a)+sqrt(_c))) {
if(x>=y) { maxxa = x ; }
else { maxxa = -9999999.; }
} else {
maxxa = -9999999.;
}
return maxxa;
}
double SMTopDecayer::approxDeadMinxa(double xg,double ktb,double ktc) {
double minxa(0.);
double x = min(xginvc0(xg,ktc),
xab(xg,(2.*xg-2.*_g)/(xg-sqrt(xg*xg-4.*_g)),0));
double y(-9999999999.);
if(xg>2.*sqrt(_g)&&xg<=xgbcut(ktb)) {
y = max(xab(xg,ktb,0),xab(xg,1.,1));
} else if(xg>=xgbcut(ktb)&&xg<=1.-sqr(sqrt(_a)+sqrt(_c))) {
if(_useMEforT2) y = xab(xg,1.,1);
else y = max(xab(xg,ktr(xg,1),2),xab(xg,1.,1));
}
if(xg>2.*sqrt(_g)&&xg<=1.-sqr(sqrt(_a)+sqrt(_c))) {
if(x>=y) { minxa = y ; }
else { minxa = 9999999.; }
} else {
minxa = 9999999.;
}
return minxa;
}
// This function returns true if the phase space point (xg,xa) is in the
// kinematically allowed phase space.
bool SMTopDecayer::inTheAllowedRegion(double xg , double xa) {
bool output(true);
if(xg<2.*sqrt(_g)||xg>1.-sqr(sqrt(_a)+sqrt(_c))) output = false;
if(xa<xab(xg,1.,1)) output = false;
if(xa>xab(xg,(2.*xg-2.*_g)/(xg-sqrt(xg*xg-4.*_g)),0)) output = false;
return output;
}
// This function returns true if the phase space point (xg,xa) is in the
// approximate (overestimated) dead region.
bool SMTopDecayer::inTheApproxDeadRegion(double xg , double xa,
double ktb, double ktc) {
bool output(true);
if(!inTheAllowedRegion(xg,xa)) output = false;
if(xa<approxDeadMinxa(xg,ktb,ktc)) output = false;
if(xa>approxDeadMaxxa(xg,ktb,ktc)) output = false;
return output;
}
// This function returns true if the phase space point (xg,xa) is in the
// dead region.
bool SMTopDecayer::inTheDeadRegion(double xg , double xa,
double ktb, double ktc) {
bool output(true);
if(!inTheApproxDeadRegion(xg,xa,ktb,ktc)) output = false;
if(xa>xaccut(ktc)) {
if(xg<xgc(max(xaccut(ktc),2.*sqrt(_a)),ktc, 1,2)&&
xg>xgc(xa,ktc, 1,0)) { output = false; }
if(xg>xgc(max(xaccut(ktc),2.*sqrt(_a)),ktc,-1,2)&&
xg<xgc(xa,ktc,-1,0)) { output = false; }
}
return output;
}
// This function attempts to generate a phase space point in the dead
// region and returns the associated phase space volume factor needed for
// the associated event weight.
double SMTopDecayer::deadRegionxgxa(double ktb,double ktc) {
_xg=0.;
_xa=0.;
// Here we set limits on xg and generate a value inside the bounds.
double xgmin(2.*sqrt(_g)),xgmax(1.-sqr(sqrt(_a)+sqrt(_c)));
// Generate _xg.
if(_xg_sampling==2.) {
_xg=xgmin*xgmax/(xgmin+UseRandom::rnd()*(xgmax-xgmin));
} else {
_xg=xgmin*xgmax/pow(( pow(xgmin,_xg_sampling-1.)
+ UseRandom::rnd()*(pow(xgmax,_xg_sampling-1.)
-pow(xgmin,_xg_sampling-1.))
),1./(_xg_sampling-1.));
}
// Here we set the bounds on _xa for given _xg.
if(_xg<xgmin||xgmin>xgmax)
throw Exception() << "TopMECorrection::deadRegionxgxa:\n"
<< "upper xg bound is less than the lower xg bound.\n"
<< "\n_xg = " << _xg
<< "\n2.*sqrt(_g) = " << 2.*sqrt(_g)
<< "\n_a = " << _a << " ma = " << sqrt(_a*_mt*_mt/GeV2)
<< "\n_c = " << _c << " mc = " << sqrt(_c*_mt*_mt/GeV2)
<< "\n_g = " << _g << " mg = " << sqrt(_g*_mt*_mt/GeV2)
<< Exception::eventerror;
double xamin(approxDeadMinxa(_xg,ktb,ktc));
double xamax(approxDeadMaxxa(_xg,ktb,ktc));
// Are the bounds sensible? If not return.
if(xamax<=xamin) return -1.;
_xa=1.+_a-(1.+_a-xamax)*pow((1.+_a-xamin)/(1.+_a-xamax),UseRandom::rnd());
// If outside the allowed region return -1.
if(!inTheDeadRegion(_xg,_xa,ktb,ktc)) return -1.;
// The integration volume for the weight
double xg_vol,xa_vol;
if(_xg_sampling==2.) {
xg_vol = (xgmax-xgmin)
/ (xgmax*xgmin);
} else {
xg_vol = (pow(xgmax,_xg_sampling-1.)-pow(xgmin,_xg_sampling-1.))
/ ((_xg_sampling-1.)*pow(xgmax*xgmin,_xg_sampling-1.));
}
xa_vol = log((1.+_a-xamin)/(1.+_a-xamax));
// Here we return the integral volume factor multiplied by the part of the
// weight left over which is not included in the BRACES function, i.e.
// the part of _xg^-2 which is not absorbed in the integration measure.
return xg_vol*xa_vol*pow(_xg,_xg_sampling-2.);
}
LorentzRotation SMTopDecayer::rotateToZ(Lorentz5Momentum v) {
// compute the rotation matrix
LorentzRotation trans;
// rotate so in z-y plane
trans.rotateZ(-atan2(v.y(),v.x()));
// rotate so along Z
trans.rotateY(-acos(v.z()/v.vect().mag()));
// generate random rotation
double c,s,cs;
do
{
c = 2.*UseRandom::rnd()-1.;
s = 2.*UseRandom::rnd()-1.;
cs = c*c+s*s;
}
while(cs>1.||cs==0.);
double cost=(c*c-s*s)/cs,sint=2.*c*s/cs;
// apply random azimuthal rotation
trans.rotateZ(atan2(sint,cost));
return trans;
}
diff --git a/MatrixElement/DIS/DISBase.cc b/MatrixElement/DIS/DISBase.cc
--- a/MatrixElement/DIS/DISBase.cc
+++ b/MatrixElement/DIS/DISBase.cc
@@ -1,1371 +1,1370 @@
// -*- 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>
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";
}
}
}
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->setEvolutionScale(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) {
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);
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);
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);
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);
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);
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);
}
}
}
// set the evolution partners and scales
ShowerParticleVector particles;
for(set<HardBranchingPtr>::iterator cit=newTree->branchings().begin();
cit!=newTree->branchings().end();++cit) {
particles.push_back((*cit)->branchingParticle());
}
// evolver()->showerModel()->partnerFinder()->
// setInitialEvolutionScales(particles,true,ShowerInteraction::QCD,true);
// // Calculate the shower variables:
// evolver()->showerModel()->kinematicsReconstructor()->
// deconstructHardJets(newTree,evolver(),ShowerInteraction::QCD);
// for(set<HardBranchingPtr>::iterator cjt=newTree->branchings().begin();
// cjt!=newTree->branchings().end();++cjt) {
// if(cjt==newTree->branchings().begin()) {
// (**cjt).showerMomentum((**cjt).branchingParticle()->momentum());
// ++cjt;
// (**cjt).showerMomentum((**cjt).branchingParticle()->momentum());
// ++cjt;
// }
// // incoming
// if((**cjt).status()==HardBranching::Incoming) {
// quark[0]->set5Momentum((**cjt).showerMomentum());
// }
// // outgoing
// else {
// quark[1]->set5Momentum((**cjt).showerMomentum());
// }
// }
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/Models/Sextet/SextetFFSVertex.cc b/Models/Sextet/SextetFFSVertex.cc
--- a/Models/Sextet/SextetFFSVertex.cc
+++ b/Models/Sextet/SextetFFSVertex.cc
@@ -1,216 +1,216 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the SextetFFSVertex class.
//
#include "SextetFFSVertex.h"
#include "SextetModel.h"
#include "SextetParticles.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace Herwig;
IBPtr SextetFFSVertex::clone() const {
return new_ptr(*this);
}
IBPtr SextetFFSVertex::fullclone() const {
return new_ptr(*this);
}
void SextetFFSVertex::persistentOutput(PersistentOStream & os) const {
os << g1L_ << g1R_ << g1pR_ << g1ppR_ << g3L_;
}
void SextetFFSVertex::persistentInput(PersistentIStream & is, int) {
is >> g1L_ >> g1R_ >> g1pR_ >> g1ppR_ >> g3L_;
}
// *** Attention *** The following static variable is needed for the type
// description system in ThePEG. Please check that the template arguments
// are correct (the class and its base class), and that the constructor
// arguments are correct (the class name and the name of the dynamically
// loadable library where the class implementation can be found).
DescribeClass<SextetFFSVertex,Helicity::FFSVertex>
describeSextetFFSVertex("Herwig::SextetFFSVertex", "HwSextetModel.so");
void SextetFFSVertex::Init() {
static ClassDocumentation<SextetFFSVertex> documentation
("The SextetFFSVertex class implements the coupling of two "
"fermions to a scalar sextet particle.");
}
void SextetFFSVertex::doinit() {
orderInGs (0);
orderInGem(1);
SextetModelPtr model =
dynamic_ptr_cast<SextetModelPtr>(generator()->standardModel());
if(!model) throw Exception() << "Must be using the SextetModel"
<< " in SextetGSSVertex::doinit()"
<< Exception::runerror;
// extract the couplings
g1L_ = model->g1L();
g1R_ = model->g1R();
g1pR_ = model->g1pR();
g1ppR_ = model->g1ppR();
g3L_ = model->g3L();
// add the enabled particles
if(model->ScalarSingletY43Enabled()) {
for(long ix=0;ix<3;++ix) {
long iu = 2*ix + 2;
if(g1ppR_[ix]!=0.) {
addToList( iu, iu, ParticleID::ScalarDQSingletY43bar);
addToList( -iu, -iu, ParticleID::ScalarDQSingletY43);
}
}
}
if(model->ScalarSingletY13Enabled()) {
for(long ix=0;ix<3;++ix) {
long iu = 2*ix + 2;
long id = 2*ix + 1;
if(g1L_[ix]!=0. || g1R_[ix]!=0.) {
addToList( id, iu, ParticleID::ScalarDQSingletY13bar);
addToList( -id, -iu, ParticleID::ScalarDQSingletY13);
}
}
}
if(model->ScalarSingletY23Enabled()) {
for(long ix=0;ix<3;++ix) {
long id = 2*ix + 1;
if(g1pR_[ix]!=0. ) {
addToList( id, id,ParticleID::ScalarDQSingletY23bar);
addToList(-id,-id,ParticleID::ScalarDQSingletY23);
}
}
}
if(model->ScalarTripletY13Enabled()) {
for(long ix=0;ix<3;++ix) {
long iu = 2*ix + 2;
long id = 2*ix + 1;
if(g3L_[ix]!=0. ) {
addToList( iu, iu, ParticleID::ScalarDQTripletPbar);
addToList( -iu, -iu, ParticleID::ScalarDQTripletP);
addToList( iu, id, ParticleID::ScalarDQTriplet0bar);
addToList( -iu, -id, ParticleID::ScalarDQTriplet0);
addToList( id, id, ParticleID::ScalarDQTripletMbar);
addToList( -id, -id, ParticleID::ScalarDQTripletM);
}
}
}
Helicity::FFSVertex::doinit();
}
-void SextetFFSVertex::setCoupling(Energy2 q2,tcPDPtr part1,
- tcPDPtr part2,tcPDPtr part3) {
+void SextetFFSVertex::setCoupling(Energy2,tcPDPtr part1,
+ tcPDPtr part2,tcPDPtr part3) {
long q1ID=(abs(part1->id())), q2ID=(abs(part2->id())),
sDQID=(abs(part3->id()));
//check scalar diquark
assert( sDQID == ParticleID::ScalarDQSingletY43 ||
sDQID == ParticleID::ScalarDQSingletY13 ||
sDQID == ParticleID::ScalarDQSingletY23 ||
sDQID == ParticleID::ScalarDQTripletP ||
sDQID == ParticleID::ScalarDQTriplet0 ||
sDQID == ParticleID::ScalarDQTripletM);
//check quarks
assert(!(q1ID>6) && !(q2ID>6));
bool part1Up = (q1ID==2 || q1ID==4 || q1ID==6) ? true : false;
bool part2Up = (q2ID==2 || q2ID==4 || q2ID==6) ? true : false;
Complex cRight, cLeft, prefactor(1.);
if(sDQID==ParticleID::ScalarDQSingletY43){
//should both be up type
assert(part1Up && part2Up);
if(q1ID==2)
cRight=Complex(g1ppR_[0]);
else if(q1ID==4)
cRight=Complex(g1ppR_[1]);
else
cRight=Complex(g1ppR_[2]);
cLeft=Complex(0.);
}
if(sDQID==ParticleID::ScalarDQSingletY13){
//should be one up one down type
assert((part1Up && !part2Up) || (!part1Up && part2Up));
long upType;
if(part1Up)
upType=q1ID;
else
upType=q2ID;
if(upType==2){
cRight=Complex(g1R_[0]);
cLeft=Complex(2.*g1L_[0]);
}
else if(upType==4){
cRight=Complex(g1R_[1]);
cLeft=Complex(2.*g1L_[1]);
}
else
cRight=Complex(g1R_[2]);{
cLeft=Complex(2.*g1L_[2]);
}
}
if(sDQID==ParticleID::ScalarDQSingletY23){
//should both be down type
assert(!part1Up && !part2Up);
if(q1ID==1)
cRight=Complex(g1pR_[0]);
else if(q1ID==3)
cRight=Complex(g1pR_[1]);
else
cRight=Complex(g1pR_[2]);
cLeft=Complex(0.);
}
if(sDQID==ParticleID::ScalarDQTripletP){
//should both be up type
assert(part1Up && part2Up);
if(q1ID==2)
cLeft=Complex(g3L_[0]);
else if(q1ID==4)
cLeft=Complex(g3L_[1]);
else
cLeft=Complex(g3L_[2]);
cRight=Complex(0.);
}
if(sDQID==ParticleID::ScalarDQTriplet0){
//should both one up and down type
assert((part1Up && !part2Up) || (!part1Up && part2Up));
//possibly doesn't couple
long upType;
if(part1Up)
upType=q1ID;
else
upType=q2ID;
if(upType==2)
cLeft=Complex(g3L_[0]);
else if(upType==4)
cLeft=Complex(g3L_[1]);
else
cLeft=Complex(g3L_[2]);
cRight=Complex(0.);
}
if(sDQID==ParticleID::ScalarDQTripletM){
//should one both be down type
assert(!part1Up && !part2Up);
if(q1ID==1)
cLeft=Complex(g3L_[0]);
else if(q1ID==3)
cLeft=Complex(g3L_[1]);
else
cLeft=Complex(g3L_[2]);
cRight=Complex(0.);
prefactor=Complex(-1.);
}
left(cLeft);
right(cRight);
norm(prefactor);
}
diff --git a/Models/Sextet/SextetFFVVertex.cc b/Models/Sextet/SextetFFVVertex.cc
--- a/Models/Sextet/SextetFFVVertex.cc
+++ b/Models/Sextet/SextetFFVVertex.cc
@@ -1,171 +1,171 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the SextetFFVVertex class.
//
#include "SextetFFVVertex.h"
#include "SextetModel.h"
#include "SextetParticles.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace Herwig;
IBPtr SextetFFVVertex::clone() const {
return new_ptr(*this);
}
IBPtr SextetFFVVertex::fullclone() const {
return new_ptr(*this);
}
void SextetFFVVertex::persistentOutput(PersistentOStream & os) const {
os << g2_ << g2p_ ;
}
void SextetFFVVertex::persistentInput(PersistentIStream & is, int) {
is >> g2_ >> g2p_ ;
}
// *** Attention *** The following static variable is needed for the type
// description system in ThePEG. Please check that the template arguments
// are correct (the class and its base class), and that the constructor
// arguments are correct (the class name and the name of the dynamically
// loadable library where the class implementation can be found).
DescribeClass<SextetFFVVertex,Helicity::FFVVertex>
describeSextetFFVVertex("Herwig::SextetFFVVertex", "HwSextetModel.so");
void SextetFFVVertex::Init() {
static ClassDocumentation<SextetFFVVertex> documentation
("The SextetFFVVertex class implements the coupling of two "
"fermions to a scalar sextet particle.");
}
void SextetFFVVertex::doinit() {
orderInGs (0);
orderInGem(1);
SextetModelPtr model =
dynamic_ptr_cast<SextetModelPtr>(generator()->standardModel());
if(!model) throw Exception() << "Must be using the SextetModel"
<< " in SextetGSSVertex::doinit()"
<< Exception::runerror;
// extract the couplings
g2_ = model->g2();
g2p_= model->g2p();
// add the enabled particles
if(model->VectorDoubletY16Enabled()) {
for(long ix=0;ix<3;++ix) {
long iu = 2*ix + 2;
long id = 2*ix + 1;
if(g2_[ix]!=0.) {
addToList( -id, -iu, ParticleID::VectorDQY16P);
addToList( id, iu, ParticleID::VectorDQY16Pbar);
addToList( -id, -id, ParticleID::VectorDQY16M);
addToList( id, id, ParticleID::VectorDQY16Mbar);
}
}
}
if(model->VectorDoubletY56Enabled()) {
for(long ix=0;ix<3;++ix) {
long iu = 2*ix + 2;
long id = 2*ix + 1;
if(g2p_[ix]!=0.) {
addToList( -iu, -iu, ParticleID::VectorDQY56P);
addToList( iu, iu, ParticleID::VectorDQY56Pbar);
addToList( -id, -iu, ParticleID::VectorDQY56M);
addToList( id, iu, ParticleID::VectorDQY56Mbar);
}
}
}
Helicity::FFVVertex::doinit();
}
-void SextetFFVVertex::setCoupling(Energy2 q2,tcPDPtr part1,
- tcPDPtr part2,tcPDPtr part3) {
+void SextetFFVVertex::setCoupling(Energy2, tcPDPtr part1,
+ tcPDPtr part2,tcPDPtr part3) {
long q1ID=(abs(part1->id())), q2ID=(abs(part2->id())),
vDQID=(abs(part3->id()));
//check scalar diquark
assert( vDQID == ParticleID::VectorDQY16P ||
vDQID == ParticleID::VectorDQY16M ||
vDQID == ParticleID::VectorDQY56P ||
vDQID == ParticleID::VectorDQY56M);
//check quarks
assert(!(q1ID>6) && !(q2ID>6));
bool part1Up = (q1ID==2 || q1ID==4 || q1ID==6) ? true : false;
bool part2Up = (q2ID==2 || q2ID==4 || q2ID==6) ? true : false;
Complex cRight(1.,1.), cLeft(1.,1.), prefactor(1.,0.);
if(vDQID==ParticleID::VectorDQY16P){
//should be one up and down type
assert((!part1Up && part2Up) || (part1Up && !part2Up));
long upType;
if(part1Up)
upType=q1ID;
else
upType=q2ID;
if(upType==2)
cRight=Complex(g2_[0]);
else if(upType==4)
cRight=Complex(g2_[1]);
else
cRight=Complex(g2_[2]);
cLeft=Complex(0.);
}
if(vDQID==ParticleID::VectorDQY16M) {
//should be both be down type
assert(!part1Up && !part2Up);
if(q1ID==1)
cRight=Complex(g2_[0]);
else if(q1ID==2)
cRight=Complex(g2_[1]);
else
cRight=Complex(g2_[2]);
cLeft=Complex(0.);
}
if(vDQID==ParticleID::VectorDQY56P) {
//should both be up type
assert(part1Up && part2Up);
if(q1ID==2)
cRight=Complex(g2p_[0]);
else if(q1ID==4)
cRight=Complex(g2p_[1]);
else
cRight=Complex(g2p_[2]);
cLeft=Complex(0.);
}
if(vDQID==ParticleID::VectorDQY56M){
//should be one up and down type
assert((!part1Up && part2Up) || (part1Up && !part2Up));
long upType;
if(part1Up)
upType=q1ID;
else
upType=q2ID;
if(upType==2)
cRight=Complex(g2p_[0]);
else if(upType==4)
cRight=Complex(g2p_[1]);
else
cRight=Complex(g2p_[2]);
cLeft=Complex(0.);
}
left(cLeft);
right(cRight);
norm(prefactor);
}
diff --git a/Models/StandardModel/SMWWWWVertex.cc b/Models/StandardModel/SMWWWWVertex.cc
--- a/Models/StandardModel/SMWWWWVertex.cc
+++ b/Models/StandardModel/SMWWWWVertex.cc
@@ -1,164 +1,164 @@
// -*- C++ -*-
//
// SMWWWWVertex.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 SMWWWWVertex class.
//
#include "SMWWWWVertex.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace Herwig;
using namespace ThePEG;
SMWWWWVertex::SMWWWWVertex()
: _couplast(0.0), _q2last(sqr(Constants::MaxEnergy)),
_vfact(4,0.0), _sw2(0.), _cw2(0.) {
orderInGem(2);
orderInGs(0);
}
void SMWWWWVertex::doinit() {
// particles
addToList(24, -24, 24, -24);
addToList(23, 24, 23, -24);
addToList(22, 24, 22, -24);
addToList(22, 24, 23, -24);
VVVVVertex::doinit();
// couplings
_sw2 = sin2ThetaW();
_cw2 = 1.-_sw2;
double sw = sqrt(_sw2);
double cw = sqrt(_cw2);
_vfact[0] = -1./_sw2;
_vfact[1] = _cw2/_sw2;
_vfact[2] = 1.;
_vfact[3] = cw/sw;
// pointer for intermediate particles
_gamma = getParticleData(ThePEG::ParticleID::gamma);
_Z0 = getParticleData(ThePEG::ParticleID::Z0);
_wplus = getParticleData(ThePEG::ParticleID::Wplus);
_wminus = getParticleData(ThePEG::ParticleID::Wminus);
}
void SMWWWWVertex::persistentOutput(PersistentOStream & os) const {
os << _gamma << _Z0 << _wplus << _wminus
<< _vfact << _sw2 << _cw2;
}
void SMWWWWVertex::persistentInput(PersistentIStream & is, int) {
is >> _gamma >> _Z0 >> _wplus >> _wminus
>> _vfact >> _sw2 >> _cw2;
}
ClassDescription<SMWWWWVertex>SMWWWWVertex::initSMWWWWVertex;
// Definition of the static class description member.
void SMWWWWVertex::Init() {
static ClassDocumentation<SMWWWWVertex> documentation
("The SMWWWWVertex class is the implementation of the"
" Standard Model quartic electroweka gauge boson coupling.");
}
// couplings for the WWWW vertex
void SMWWWWVertex::setCoupling(Energy2 q2,tcPDPtr a,tcPDPtr b,
tcPDPtr c,tcPDPtr d) {
// id's of the particles
- int id[4]={a->id(),b->id(),c->id(),d->id()};
+ long id[4]={a->id(),b->id(),c->id(),d->id()};
// order the particles
int ngamma(0),nz(0);
int iorder[4];
for(int ix=0;ix<4;++ix) {
if (id[ix]==22) ++ngamma;
else if (id[ix]==23) ++nz;
}
// if photons or Z's
if(ngamma!=0 || nz!=0) {
int iy=0;
// put the photons first
for(int ix=0;iy<ngamma&&ix<4;++ix) {
if(id[ix]==22) {
iorder[iy]=ix;
++iy;
}
}
// then the Z bosons
for(int ix=0;iy<ngamma+nz&&ix<4;++ix) {
if(id[ix]==23) {
iorder[iy]=ix;
++iy;
}
}
// then the W+
for(int ix=0;iy<3&&ix<4;++ix) {
if(id[ix]==24) {
iorder[iy]=ix;
++iy;
}
}
assert(iy==3);
// finally the W-
for(int ix=0;iy<4&&ix<4;++ix) {
if(id[ix]==-24) {
iorder[iy]=ix;
++iy;
}
}
assert(iy==4);
}
else {
int iy=0;
// first the W+
for(int ix=0;iy<3&&ix<4;++ix) {
if(id[ix]==24) {
iorder[iy]=ix;
++iy;
}
}
assert(iy==2);
// finally the W-
for(int ix=0;iy<4&&ix<4;++ix) {
if(id[ix]==-24) {
iorder[iy]=ix;
++iy;
}
}
assert(iy==4);
setIntermediate(_gamma,_Z0,_sw2,_cw2);
}
setOrder(iorder[0],iorder[1],iorder[2],iorder[3]);
setType(2);
// first the overall normalisation
if(q2!=_q2last||_couplast==0.) {
_couplast = sqr(electroMagneticCoupling(q2));
_q2last=q2;
}
// id's of the first two particles
int ida(0),idb(0);
if(iorder[0]==0) ida = abs(a->id());
else if(iorder[0]==1) ida = abs(b->id());
else if(iorder[0]==2) ida = abs(c->id());
else if(iorder[0]==3) ida = abs(d->id());
if(iorder[1]==0) idb = abs(a->id());
else if(iorder[1]==1) idb = abs(b->id());
else if(iorder[1]==2) idb = abs(c->id());
else if(iorder[1]==3) idb = abs(d->id());
// WWWW coupling
if(ida==24) norm(_vfact[0]*_couplast);
// ZZWW coupling
else if(ida==23&&idb==23) norm(_vfact[1]*_couplast);
// gamma gamma WW coupling
else if(ida==22&&idb==22) norm(_couplast);
// gamma Z WW coupling
else if(ida==22&&idb==23) norm(_vfact[3]*_couplast);
else assert(false);
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Tue, Nov 19, 8:42 PM (1 d, 8 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3806136
Default Alt Text
(114 KB)
Attached To
rHERWIGHG herwighg
Event Timeline
Log In to Comment