Page MenuHomeHEPForge

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/Shower/Base/Evolver.cc b/Shower/Base/Evolver.cc
--- a/Shower/Base/Evolver.cc
+++ b/Shower/Base/Evolver.cc
@@ -1,1663 +1,1664 @@
// -*- C++ -*-
//
// Evolver.cc is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the Evolver class.
//
#include "Evolver.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/RefVector.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "Herwig++/Shower/Base/ShowerParticle.h"
#include "ShowerKinematics.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Handlers/EventHandler.h"
#include "ThePEG/Utilities/Throw.h"
#include "ShowerTree.h"
#include "ShowerProgenitor.h"
#include "KinematicsReconstructor.h"
#include "PartnerFinder.h"
#include "ThePEG/Handlers/StandardXComb.h"
#include "ThePEG/PDT/DecayMode.h"
#include "Herwig++/Shower/ShowerHandler.h"
+#include "ThePEG/Utilities/DescribeClass.h"
using namespace Herwig;
+DescribeClass<Evolver,Interfaced>
+describeEvolver ("Herwig::Evolver","HwShower.so");
+
IBPtr Evolver::clone() const {
return new_ptr(*this);
}
IBPtr Evolver::fullclone() const {
return new_ptr(*this);
}
void Evolver::persistentOutput(PersistentOStream & os) const {
os << _model << _splittingGenerator << _maxtry
<< _meCorrMode << _hardVetoMode << _hardVetoRead << _hardVetoReadOption
<< _limitEmissions
<< ounit(_iptrms,GeV) << _beta << ounit(_gamma,GeV) << ounit(_iptmax,GeV)
<< _vetoes << _hardonly << _trunc_Mode << _hardEmissionMode
<< _colourEvolutionMethod << _reconOpt;
}
void Evolver::persistentInput(PersistentIStream & is, int) {
is >> _model >> _splittingGenerator >> _maxtry
>> _meCorrMode >> _hardVetoMode >> _hardVetoRead >> _hardVetoReadOption
>> _limitEmissions
>> iunit(_iptrms,GeV) >> _beta >> iunit(_gamma,GeV) >> iunit(_iptmax,GeV)
>> _vetoes >> _hardonly >> _trunc_Mode >> _hardEmissionMode
>> _colourEvolutionMethod >> _reconOpt;
}
-ClassDescription<Evolver> Evolver::initEvolver;
-// Definition of the static class description member.
-
void Evolver::Init() {
static ClassDocumentation<Evolver> documentation
("This class is responsible for carrying out the showering,",
"including the kinematics reconstruction, in a given scale range,"
"including the option of the POWHEG approach to simulated next-to-leading order"
" radiation\\cite{Nason:2004rx}.",
"%\\cite{Nason:2004rx}\n"
"\\bibitem{Nason:2004rx}\n"
" P.~Nason,\n"
" ``A new method for combining NLO QCD with shower Monte Carlo algorithms,''\n"
" JHEP {\\bf 0411} (2004) 040\n"
" [arXiv:hep-ph/0409146].\n"
" %%CITATION = JHEPA,0411,040;%%\n");
static Reference<Evolver,SplittingGenerator>
interfaceSplitGen("SplittingGenerator",
"A reference to the SplittingGenerator object",
&Herwig::Evolver::_splittingGenerator,
false, false, true, false);
static Reference<Evolver,ShowerModel> interfaceShowerModel
("ShowerModel",
"The pointer to the object which defines the shower evolution model.",
&Evolver::_model, false, false, true, false, false);
static Parameter<Evolver,unsigned int> interfaceMaxTry
("MaxTry",
"The maximum number of attempts to generate the shower from a"
" particular ShowerTree",
&Evolver::_maxtry, 100, 1, 1000,
false, false, Interface::limited);
static Switch<Evolver, unsigned int> ifaceMECorrMode
("MECorrMode",
"Choice of the ME Correction Mode",
&Evolver::_meCorrMode, 1, false, false);
static SwitchOption off
(ifaceMECorrMode,"No","MECorrections off", 0);
static SwitchOption on
(ifaceMECorrMode,"Yes","hard+soft on", 1);
static SwitchOption hard
(ifaceMECorrMode,"Hard","only hard on", 2);
static SwitchOption soft
(ifaceMECorrMode,"Soft","only soft on", 3);
static Switch<Evolver, unsigned int> ifaceHardVetoMode
("HardVetoMode",
"Choice of the Hard Veto Mode",
&Evolver::_hardVetoMode, 1, false, false);
static SwitchOption HVoff
(ifaceHardVetoMode,"No","hard vetos off", 0);
static SwitchOption HVon
(ifaceHardVetoMode,"Yes","hard vetos on", 1);
static SwitchOption HVIS
(ifaceHardVetoMode,"Initial", "only IS emissions vetoed", 2);
static SwitchOption HVFS
(ifaceHardVetoMode,"Final","only FS emissions vetoed", 3);
static Switch<Evolver, unsigned int> ifaceHardVetoRead
("HardVetoScaleSource",
"If hard veto scale is to be read",
&Evolver::_hardVetoRead, 0, false, false);
static SwitchOption HVRcalc
(ifaceHardVetoRead,"Calculate","Calculate from hard process", 0);
static SwitchOption HVRread
(ifaceHardVetoRead,"Read","Read from XComb->lastScale", 1);
static Switch<Evolver, bool> ifaceHardVetoReadOption
("HardVetoReadOption",
"Apply read-in scale veto to all collisions or just the primary one?",
&Evolver::_hardVetoReadOption, false, false, false);
static SwitchOption AllCollisions
(ifaceHardVetoReadOption,
"AllCollisions",
"Read-in pT veto applied to primary and secondary collisions.",
false);
static SwitchOption PrimaryCollision
(ifaceHardVetoReadOption,
"PrimaryCollision",
"Read-in pT veto applied to primary but not secondary collisions.",
true);
static Parameter<Evolver, Energy> ifaceiptrms
("IntrinsicPtGaussian",
"RMS of intrinsic pT of Gaussian distribution:\n"
"2*(1-Beta)*exp(-sqr(intrinsicpT/RMS))/sqr(RMS)",
&Evolver::_iptrms, GeV, ZERO, ZERO, 1000000.0*GeV,
false, false, Interface::limited);
static Parameter<Evolver, double> ifacebeta
("IntrinsicPtBeta",
"Proportion of inverse quadratic distribution in generating intrinsic pT.\n"
"(1-Beta) is the proportion of Gaussian distribution",
&Evolver::_beta, 0, 0, 1,
false, false, Interface::limited);
static Parameter<Evolver, Energy> ifacegamma
("IntrinsicPtGamma",
"Parameter for inverse quadratic:\n"
"2*Beta*Gamma/(sqr(Gamma)+sqr(intrinsicpT))",
&Evolver::_gamma,GeV, ZERO, ZERO, 100000.0*GeV,
false, false, Interface::limited);
static Parameter<Evolver, Energy> ifaceiptmax
("IntrinsicPtIptmax",
"Upper bound on intrinsic pT for inverse quadratic",
&Evolver::_iptmax,GeV, ZERO, ZERO, 100000.0*GeV,
false, false, Interface::limited);
static RefVector<Evolver,ShowerVeto> ifaceVetoes
("Vetoes",
"The vetoes to be checked during showering",
&Evolver::_vetoes, -1,
false,false,true,true,false);
static Switch<Evolver,unsigned int> interfaceLimitEmissions
("LimitEmissions",
"Limit the number and type of emissions for testing",
&Evolver::_limitEmissions, 0, false, false);
static SwitchOption interfaceLimitEmissionsNoLimit
(interfaceLimitEmissions,
"NoLimit",
"Allow an arbitrary number of emissions",
0);
static SwitchOption interfaceLimitEmissionsOneInitialStateEmission
(interfaceLimitEmissions,
"OneInitialStateEmission",
"Allow one emission in the initial state and none in the final state",
1);
static SwitchOption interfaceLimitEmissionsOneFinalStateEmission
(interfaceLimitEmissions,
"OneFinalStateEmission",
"Allow one emission in the final state and none in the initial state",
2);
static SwitchOption interfaceLimitEmissionsHardOnly
(interfaceLimitEmissions,
"HardOnly",
"Only allow radiation from the hard ME correction",
3);
static Switch<Evolver,bool> interfaceHardOnly
("HardOnly",
"Only generate the emission supplied by the hardest emission"
" generator, for testing only.",
&Evolver::_hardonly, false, false, false);
static SwitchOption interfaceHardOnlyNo
(interfaceHardOnly,
"No",
"Generate full shower",
false);
static SwitchOption interfaceHardOnlyYes
(interfaceHardOnly,
"Yes",
"Only the hardest emission",
true);
static Switch<Evolver,bool> interfaceTruncMode
("TruncatedShower", "Include the truncated shower?",
&Evolver::_trunc_Mode, 1, false, false);
static SwitchOption interfaceTruncMode0
(interfaceTruncMode,"No","Truncated Shower is OFF", 0);
static SwitchOption interfaceTruncMode1
(interfaceTruncMode,"Yes","Truncated Shower is ON", 1);
static Switch<Evolver,unsigned int> interfaceHardEmissionMode
("HardEmissionMode",
"Whether to use ME corrections or POWHEG for the hardest emission",
&Evolver::_hardEmissionMode, 0, false, false);
static SwitchOption interfaceHardEmissionModeMECorrection
(interfaceHardEmissionMode,
"MECorrection",
"Old fashioned ME correction",
0);
static SwitchOption interfaceHardEmissionModePOWHEG
(interfaceHardEmissionMode,
"POWHEG",
"Powheg style hard emission",
1);
static Switch<Evolver,int> interfaceColourEvolutionMethod
("ColourEvolutionMethod",
"Choice of method for choosing the colour factor in gluon evolution",
&Evolver::_colourEvolutionMethod, 0, false, false);
static SwitchOption interfaceColourEvolutionMethodDefault
(interfaceColourEvolutionMethod,
"Default",
"Colour factor is CA for all scales",
0);
static SwitchOption interfaceColourEvolutionMethodHalfCA
(interfaceColourEvolutionMethod,
"HalfCA",
"Only use half the normal radiation until second scale is reached",
1);
static Switch<Evolver,unsigned int> interfaceReconstructionOption
("ReconstructionOption",
"Treatment of the reconstruction of the transverse momentum of "
"a branching from the evolution scale.",
&Evolver::_reconOpt, 0, false, false);
static SwitchOption interfaceReconstructionOptionCutOff
(interfaceReconstructionOption,
"CutOff",
"Use the cut-off masses in the calculation",
0);
static SwitchOption interfaceReconstructionOptionOffShell
(interfaceReconstructionOption,
"OffShell",
"Use the off-shell masses in the calculation",
1);
}
void Evolver::generateIntrinsicpT(vector<ShowerProgenitorPtr> particlesToShower) {
_intrinsic.clear();
if ( !ipTon() || !isISRadiationON() ) return;
// don't do anything for the moment for secondary scatters
if( !ShowerHandler::currentHandler()->firstInteraction() ) return;
// generate intrinsic pT
for(unsigned int ix=0;ix<particlesToShower.size();++ix) {
// only consider initial-state particles
if(particlesToShower[ix]->progenitor()->isFinalState()) continue;
if(!particlesToShower[ix]->progenitor()->dataPtr()->coloured()) continue;
Energy ipt;
if(UseRandom::rnd() > _beta) {
ipt=_iptrms*sqrt(-log(UseRandom::rnd()));
}
else {
ipt=_gamma*sqrt(pow(1.+sqr(_iptmax/_gamma), UseRandom::rnd())-1.);
}
pair<Energy,double> pt = make_pair(ipt,UseRandom::rnd(Constants::twopi));
_intrinsic[particlesToShower[ix]] = pt;
}
}
void Evolver::setupMaximumScales(ShowerTreePtr hard,
vector<ShowerProgenitorPtr> p) {
// find out if hard partonic subprocess.
bool isPartonic(false);
map<ShowerProgenitorPtr,ShowerParticlePtr>::const_iterator
cit = _currenttree->incomingLines().begin();
Lorentz5Momentum pcm;
for(; cit!=hard->incomingLines().end(); ++cit) {
pcm += cit->first->progenitor()->momentum();
isPartonic |= cit->first->progenitor()->coloured();
}
// find maximum pt from hard process, the maximum pt from all outgoing
// coloured lines (this is simpler and more general than
// 2stu/(s^2+t^2+u^2)). Maximum scale for scattering processes will
// be transverse mass.
Energy ptmax = -1.0*GeV;
// general case calculate the scale
if (!hardVetoXComb()||
(hardVetoReadOption()&&
!ShowerHandler::currentHandler()->firstInteraction())) {
// scattering process
if(hard->isHard()) {
// coloured incoming particles
if (isPartonic) {
map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator
cjt = hard->outgoingLines().begin();
for(; cjt!=hard->outgoingLines().end(); ++cjt) {
if (cjt->first->progenitor()->coloured())
ptmax = max(ptmax,cjt->first->progenitor()->momentum().mt());
}
}
if (ptmax < ZERO) ptmax = pcm.m();
if(hardVetoXComb()&&hardVetoReadOption()&&
!ShowerHandler::currentHandler()->firstInteraction()) {
ptmax=min(ptmax,sqrt(ShowerHandler::currentHandler()
->lastXCombPtr()->lastScale()));
}
}
// decay, incoming() is the decaying particle.
else {
ptmax = hard->incomingLines().begin()->first
->progenitor()->momentum().mass();
}
}
// hepeup.SCALUP is written into the lastXComb by the
// LesHouchesReader itself - use this by user's choice.
// Can be more general than this.
else {
ptmax = sqrt( ShowerHandler::currentHandler()
->lastXCombPtr()->lastScale() );
}
// set maxHardPt for all progenitors. For partonic processes this
// is now the max pt in the FS, for non-partonic processes or
// processes with no coloured FS the invariant mass of the IS
vector<ShowerProgenitorPtr>::const_iterator ckt = p.begin();
for (; ckt != p.end(); ckt++) (*ckt)->maxHardPt(ptmax);
}
void Evolver::showerHardProcess(ShowerTreePtr hard, XCPtr xcomb) {
_hardme = HwMEBasePtr();
// extract the matrix element
tStdXCombPtr lastXC = dynamic_ptr_cast<tStdXCombPtr>(xcomb);
if(lastXC) {
_hardme = dynamic_ptr_cast<HwMEBasePtr>(lastXC->matrixElement());
}
_decayme = HwDecayerBasePtr();
// set the current tree
currentTree(hard);
// zero number of emissions
_nis = _nfs = 0;
// extract particles to shower
vector<ShowerProgenitorPtr> particlesToShower=setupShower(true);
// setup the maximum scales for the shower, given by the hard process
if (hardVetoOn()) setupMaximumScales(currentTree(), particlesToShower);
// generate the intrinsic p_T once and for all
generateIntrinsicpT(particlesToShower);
// main shower loop
unsigned int ntry(0);
do {
// clear results of last attempt if needed
if(ntry!=0) {
currentTree()->clear();
setEvolutionPartners(true,ShowerInteraction::QCD);
_nis = _nfs = 0;
}
// generate the shower
// pick random starting point
unsigned int istart=UseRandom::irnd(particlesToShower.size());
unsigned int istop = particlesToShower.size();
// loop over particles with random starting point
for(unsigned int ix=istart;ix<=istop;++ix) {
if(ix==particlesToShower.size()) {
if(istart!=0) {
istop = istart-1;
ix=0;
}
else break;
}
// set the progenitor
_progenitor=particlesToShower[ix];
// initial-state
if(!_progenitor->progenitor()->isFinalState()) {
if(!isISRadiationON()) continue;
// get the PDF
setBeamParticle(_progenitor->beam());
assert(beamParticle());
// perform the shower
// set the beam particle
tPPtr beamparticle=progenitor()->original();
if(!beamparticle->parents().empty())
beamparticle=beamparticle->parents()[0];
// generate the shower
progenitor()->hasEmitted(startSpaceLikeShower(beamparticle,
ShowerInteraction::QCD));
}
// final-state
else {
if(!isFSRadiationON()) continue;
// perform shower
progenitor()->hasEmitted(startTimeLikeShower(ShowerInteraction::QCD));
}
}
}
while(!showerModel()->kinematicsReconstructor()->
reconstructHardJets(hard,intrinsicpT())&&
maximumTries()>++ntry);
_hardme=HwMEBasePtr();
_hardtree=HardTreePtr();
if(_maxtry==ntry) throw ShowerHandler::ShowerTriesVeto(ntry);
// the tree has now showered
_currenttree->hasShowered(true);
}
void Evolver::hardMatrixElementCorrection(bool hard) {
// set the initial enhancement factors for the soft correction
_initialenhance = 1.;
_finalenhance = 1.;
// if hard matrix element switched off return
if(!MECOn()) return;
// see if we can get the correction from the matrix element
// or decayer
if(hard) {
if(_hardme&&_hardme->hasMECorrection()) {
_hardme->initializeMECorrection(_currenttree,
_initialenhance,_finalenhance);
if(hardMEC())
_hardme->applyHardMatrixElementCorrection(_currenttree);
}
}
else {
if(_decayme&&_decayme->hasMECorrection()) {
_decayme->initializeMECorrection(_currenttree,
_initialenhance,_finalenhance);
if(hardMEC())
_decayme->applyHardMatrixElementCorrection(_currenttree);
}
}
}
double Evolver::getReductionFactor(tShowerParticlePtr particle) {
// octet -> octet octet reduction factor
if ( _colourEvolutionMethod == 1 ) {
// Determine which colour factor to use for octet->octet octet
// There are three possibilities.
// 1) Radiation is emitted from a hard parton, or the primary emission
// of a hard parton, at a scale above the progenitor's second
// scale, and we have half as much radiation.
// 2) Radiation is emitted from a hard parton, or the primary emission
// of a hard parton, at a scale below the progenitor's second
// scale, and we have the normal amount of radiation
// 3) Radiation is emitted from a secondary emission of a hard parton,
// and we have the normal amount of radiation
if (getParticleData(particle->id())->iColour()==PDT::Colour8) {
// Particle is an octet
if (particle->radiationLine() == 1 || particle->radiationLine() == 2) {
// Particle is connected along hard progenitor's radiation line
if (particle->evolutionScale() > particle->progenitor()->evolutionScale2() ) {
// Particle radiaties with half strength
return 0.5;
}
}
}
}
return 1.0;
}
bool Evolver::timeLikeShower(tShowerParticlePtr particle,
ShowerInteraction::Type type,
bool first) {
// don't do anything if not needed
if(_limitEmissions == 1 || _limitEmissions == 3 ||
( _limitEmissions == 2 && _nfs != 0) ) return false;
// octet -> octet octet reduction factor
double reduction = getReductionFactor(particle);
ShowerParticleVector theChildren;
int ntry=0;
do {
++ntry;
// generate the emission
Branching fb;
while (true) {
fb=_splittingGenerator->chooseForwardBranching(*particle,reduction*_finalenhance,type);
// no emission return
if(!fb.kinematics) return false;
// if emission OK break
if(!timeLikeVetoed(fb,particle)) break;
// otherwise reset scale and continue - SO IS involved in veto algorithm
particle->setEvolutionScale(fb.kinematics->scale());
}
// has emitted
// Assign the shower kinematics to the emitting particle.
particle->setShowerKinematics(fb.kinematics);
// Assign the splitting function to the emitting particle.
// For the time being we are considering only 1->2 branching
// Create the ShowerParticle objects for the two children of
// the emitting particle; set the parent/child relationship
// if same as definition create particles, otherwise create cc
tcPDPtr pdata[2];
for(unsigned int ix=0;ix<2;++ix) pdata[ix]=getParticleData(fb.ids[ix+1]);
if(particle->id()!=fb.ids[0]) {
for(unsigned int ix=0;ix<2;++ix) {
tPDPtr cc(pdata[ix]->CC());
if(cc) pdata[ix]=cc;
}
}
theChildren.push_back(new_ptr(ShowerParticle(pdata[0],true)));
theChildren.push_back(new_ptr(ShowerParticle(pdata[1],true)));
// update the children
particle->showerKinematics()->updateChildren(particle, theChildren,true);
// update number of emissions
++_nfs;
if(_limitEmissions!=0) return true;
// shower the first particle
timeLikeShower(theChildren[0],type,false);
// shower the second particle
timeLikeShower(theChildren[1],type,false);
// that's if for old approach
if(_reconOpt==0) break;
// branching has happened
particle->showerKinematics()->updateParent(particle, theChildren,true);
// clean up the vetoed emission
if(particle->virtualMass()==ZERO) {
particle->setShowerKinematics(ShoKinPtr());
for(unsigned int ix=0;ix<theChildren.size();++ix)
particle->abandonChild(theChildren[ix]);
theChildren.clear();
}
}
while(particle->virtualMass()==ZERO&&ntry<50);
if(first)
particle->showerKinematics()->resetChildren(particle,theChildren);
return true;
}
bool
Evolver::spaceLikeShower(tShowerParticlePtr particle, PPtr beam,
ShowerInteraction::Type type) {
//using the pdf's associated with the ShowerHandler assures, that
//modified pdf's are used for the secondary interactions via
//CascadeHandler::resetPDFs(...)
tcPDFPtr pdf;
if(ShowerHandler::currentHandler()->firstPDF().particle() == _beam)
pdf = ShowerHandler::currentHandler()->firstPDF().pdf();
if(ShowerHandler::currentHandler()->secondPDF().particle() == _beam)
pdf = ShowerHandler::currentHandler()->secondPDF().pdf();
Energy freeze = ShowerHandler::currentHandler()->pdfFreezingScale();
// don't do anything if not needed
if(_limitEmissions == 2 || _limitEmissions == 3 ||
( _limitEmissions == 1 && _nis != 0 ) ) return false;
// octet -> octet octet reduction factor
double reduction = getReductionFactor(particle);
Branching bb;
// generate branching
while (true) {
bb=_splittingGenerator->chooseBackwardBranching(*particle,beam,
reduction*_initialenhance,
_beam,type,
pdf,freeze);
// return if no emission
if(!bb.kinematics) return false;
// if not vetoed break
if(!spaceLikeVetoed(bb,particle)) break;
// otherwise reset scale and continue
particle->setEvolutionScale(bb.kinematics->scale());
}
// assign the splitting function and shower kinematics
particle->setShowerKinematics(bb.kinematics);
// For the time being we are considering only 1->2 branching
// particles as in Sudakov form factor
tcPDPtr part[2]={getParticleData(bb.ids[0]),
getParticleData(bb.ids[2])};
if(particle->id()!=bb.ids[1]) {
if(part[0]->CC()) part[0]=part[0]->CC();
if(part[1]->CC()) part[1]=part[1]->CC();
}
// Now create the actual particles, make the otherChild a final state
// particle, while the newParent is not
ShowerParticlePtr newParent=new_ptr(ShowerParticle(part[0],false));
ShowerParticlePtr otherChild = new_ptr(ShowerParticle(part[1],true,true));
ShowerParticleVector theChildren;
theChildren.push_back(particle);
theChildren.push_back(otherChild);
//this updates the evolution scale
particle->showerKinematics()->updateParent(newParent, theChildren,true);
// update the history if needed
_currenttree->updateInitialStateShowerProduct(_progenitor,newParent);
_currenttree->addInitialStateBranching(particle,newParent,otherChild);
// for the reconstruction of kinematics, parent/child
// relationships are according to the branching process:
// now continue the shower
++_nis;
bool emitted = _limitEmissions==0 ?
spaceLikeShower(newParent,beam,type) : false;
// now reconstruct the momentum
if(!emitted) {
if(_intrinsic.find(_progenitor)==_intrinsic.end()) {
bb.kinematics->updateLast(newParent,ZERO,ZERO);
}
else {
pair<Energy,double> kt=_intrinsic[_progenitor];
bb.kinematics->updateLast(newParent,
kt.first*cos(kt.second),
kt.first*sin(kt.second));
}
}
particle->showerKinematics()->updateChildren(newParent, theChildren,true);
if(_limitEmissions!=0) return true;
// perform the shower of the final-state particle
timeLikeShower(otherChild,type,true);
// return the emitted
return true;
}
void Evolver::showerDecay(ShowerTreePtr decay) {
_decayme = HwDecayerBasePtr();
_hardme = HwMEBasePtr();
// find the decayer
// try the normal way if possible
tDMPtr dm = decay->incomingLines().begin()->first->original() ->decayMode();
if(!dm) dm = decay->incomingLines().begin()->first->copy() ->decayMode();
if(!dm) dm = decay->incomingLines().begin()->first->progenitor()->decayMode();
// otherwise make a string and look it up
if(!dm) {
string tag = decay->incomingLines().begin()->first->original()->dataPtr()->name()
+ "->";
for(map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator
it=decay->outgoingLines().begin();it!=decay->outgoingLines().end();++it) {
if(it!=decay->outgoingLines().begin()) tag += ",";
tag += it->first->original()->dataPtr()->name();
}
tag += ";";
dm = generator()->findDecayMode(tag);
}
if(dm) _decayme = dynamic_ptr_cast<HwDecayerBasePtr>(dm->decayer());
// set the ShowerTree to be showered
currentTree(decay);
decay->applyTransforms();
// extract particles to be shower, set scales and
// perform hard matrix element correction
vector<ShowerProgenitorPtr> particlesToShower=setupShower(false);
setupMaximumScales(currentTree(), particlesToShower);
// compute the minimum mass of the final-state
Energy minmass(ZERO), mIn(ZERO);
for(unsigned int ix=0;ix<particlesToShower.size();++ix) {
if(particlesToShower[ix]->progenitor()->isFinalState()) {
if(particlesToShower[ix]->progenitor()->dataPtr()->stable())
minmass += particlesToShower[ix]->progenitor()->dataPtr()->constituentMass();
else
minmass += particlesToShower[ix]->progenitor()->mass();
}
else {
mIn = particlesToShower[ix]->progenitor()->mass();
}
}
if ( minmass > mIn ) {
throw Exception() << "Evolver.cc: Mass of decaying particle is "
<< "below constituent masses of decay products."
<< Exception::eventerror;
}
// main showering loop
unsigned int ntry(0);
do {
// clear results of last attempt
if(ntry!=0) {
currentTree()->clear();
setEvolutionPartners(false,ShowerInteraction::QCD);
}
unsigned int istart=UseRandom::irnd(particlesToShower.size());
unsigned int istop = particlesToShower.size();
// loop over particles with random starting point
for(unsigned int ix=istart;ix<=istop;++ix) {
if(ix==particlesToShower.size()) {
if(istart!=0) {
istop = istart-1;
ix=0;
}
else break;
}
// extract the progenitor
progenitor(particlesToShower[ix]);
// final-state radiation
if(progenitor()->progenitor()->isFinalState()) {
if(!isFSRadiationON()) continue;
// perform shower
progenitor()->hasEmitted(startTimeLikeShower(ShowerInteraction::QCD));
}
// initial-state radiation
else {
if(!isISRadiationON()) continue;
// perform shower
// set the scales correctly. The current scale is the maximum scale for
// emission not the starting scale
Energy maxscale=progenitor()->progenitor()->evolutionScale();
Energy startScale=progenitor()->progenitor()->mass();
progenitor()->progenitor()->setEvolutionScale(startScale);
// perform the shower
progenitor()->hasEmitted(startSpaceLikeDecayShower(maxscale,minmass,
ShowerInteraction::QCD));
}
}
}
while(!showerModel()->kinematicsReconstructor()->reconstructDecayJets(decay)&&
maximumTries()>++ntry);
_decayme = HwDecayerBasePtr();
if(maximumTries()==ntry)
throw Exception() << "Failed to generate the shower after "
<< ntry << " attempts in Evolver::showerDecay()"
<< Exception::eventerror;
// tree has now showered
_currenttree->hasShowered(true);
}
bool Evolver::spaceLikeDecayShower(tShowerParticlePtr particle,
Energy maxscale,
Energy minmass,ShowerInteraction::Type type) {
// octet -> octet octet reduction factor
double reduction = getReductionFactor(particle);
Branching fb;
while (true) {
fb=_splittingGenerator->chooseDecayBranching(*particle,maxscale,minmass,
reduction*_initialenhance,type);
// return if no radiation
if(!fb.kinematics) return false;
// if not vetoed break
if(!spaceLikeDecayVetoed(fb,particle)) break;
// otherwise reset scale and continue
particle->setEvolutionScale(fb.kinematics->scale());
}
// has emitted
// Assign the shower kinematics to the emitting particle.
particle->setShowerKinematics(fb.kinematics);
// For the time being we are considering only 1->2 branching
// Create the ShowerParticle objects for the two children of
// the emitting particle; set the parent/child relationship
// if same as definition create particles, otherwise create cc
tcPDPtr pdata[2];
for(unsigned int ix=0;ix<2;++ix) pdata[ix]=getParticleData(fb.ids[ix+1]);
if(particle->id()!=fb.ids[0]) {
for(unsigned int ix=0;ix<2;++ix) {
tPDPtr cc(pdata[ix]->CC());
if(cc) pdata[ix]=cc;
}
}
ShowerParticleVector theChildren;
theChildren.push_back(new_ptr(ShowerParticle(pdata[0],true)));
theChildren.push_back(new_ptr(ShowerParticle(pdata[1],true)));
// some code moved to updateChildren
particle->showerKinematics()->updateChildren(particle, theChildren,true);
// In the case of splittings which involves coloured particles,
// set properly the colour flow of the branching.
// update the history if needed
_currenttree->updateInitialStateShowerProduct(_progenitor,theChildren[0]);
_currenttree->addInitialStateBranching(particle,theChildren[0],theChildren[1]);
// shower the first particle
spaceLikeDecayShower(theChildren[0],maxscale,minmass,type);
// shower the second particle
timeLikeShower(theChildren[1],type,true);
// branching has happened
return true;
}
vector<ShowerProgenitorPtr> Evolver::setupShower(bool hard) {
// generate POWHEG hard emission if needed
if(_hardEmissionMode==1) hardestEmission(hard);
// set the initial colour partners
setEvolutionPartners(hard,ShowerInteraction::QCD);
// get the particles to be showered
map<ShowerProgenitorPtr, ShowerParticlePtr>::const_iterator cit;
map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator cjt;
// generate hard me if needed
if(_hardEmissionMode==0) hardMatrixElementCorrection(hard);
// get the particles to be showered
vector<ShowerProgenitorPtr> particlesToShower;
// incoming particles
for(cit=currentTree()->incomingLines().begin();
cit!=currentTree()->incomingLines().end();++cit)
particlesToShower.push_back((*cit).first);
assert((particlesToShower.size()==1&&!hard)||
(particlesToShower.size()==2&&hard));
// outgoing particles
for(cjt=currentTree()->outgoingLines().begin();
cjt!=currentTree()->outgoingLines().end();++cjt)
particlesToShower.push_back(((*cjt).first));
// remake the colour partners if needed
if(_hardEmissionMode==0 && _currenttree->hardMatrixElementCorrection()) {
setEvolutionPartners(hard,ShowerInteraction::QCD);
_currenttree->resetShowerProducts();
}
return particlesToShower;
}
void Evolver::setEvolutionPartners(bool hard,ShowerInteraction::Type ) {
map<ShowerProgenitorPtr, ShowerParticlePtr>::const_iterator cit;
map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator cjt;
vector<ShowerParticlePtr> particles;
// match the particles in the ShowerTree and hardTree
if(hardTree() && !hardTree()->connect(currentTree()))
throw Exception() << "Can't match trees in "
<< "Evolver::setEvolutionPartners()"
<< Exception::eventerror;
// sort out the colour partners
for(cit=currentTree()->incomingLines().begin();
cit!=currentTree()->incomingLines().end();++cit)
particles.push_back(cit->first->progenitor());
assert((particles.size()==1&&!hard)||(particles.size()==2&&hard));
// outgoing particles
for(cjt=currentTree()->outgoingLines().begin();
cjt!=currentTree()->outgoingLines().end();++cjt)
particles.push_back(cjt->first->progenitor());
if(hardTree()) {
// find the partner
for(unsigned int ix=0;ix<particles.size();++ix) {
tHardBranchingPtr partner =
hardTree()->particles()[particles[ix]]->colourPartner();
if(!partner) continue;
for(map<ShowerParticlePtr,tHardBranchingPtr>::const_iterator
it=hardTree()->particles().begin();
it!=hardTree()->particles().end();++it) {
if(it->second==partner) particles[ix]->setPartner(it->first);
}
if(!particles[ix]->partner())
throw Exception() << "Can't match partners in "
<< "Evolver::setEvolutionPartners()"
<< Exception::eventerror;
}
}
// Set the initial evolution scales
showerModel()->partnerFinder()->
setInitialEvolutionScales(particles,!hard,ShowerInteraction::QCD,!_hardtree);
}
void Evolver::updateHistory(tShowerParticlePtr particle) {
if(!particle->children().empty()) {
ShowerParticleVector theChildren;
for(unsigned int ix=0;ix<particle->children().size();++ix) {
ShowerParticlePtr part = dynamic_ptr_cast<ShowerParticlePtr>
(particle->children()[ix]);
theChildren.push_back(part);
}
// update the history if needed
if(particle==_currenttree->getFinalStateShowerProduct(_progenitor))
_currenttree->updateFinalStateShowerProduct(_progenitor,
particle,theChildren);
_currenttree->addFinalStateBranching(particle,theChildren);
for(unsigned int ix=0;ix<theChildren.size();++ix)
updateHistory(theChildren[ix]);
}
}
bool Evolver::startTimeLikeShower(ShowerInteraction::Type type) {
if(hardTree()) {
map<ShowerParticlePtr,tHardBranchingPtr>::const_iterator
eit=hardTree()->particles().end(),
mit = hardTree()->particles().find(progenitor()->progenitor());
if( mit != eit && !mit->second->children().empty() ) {
bool output=truncatedTimeLikeShower(progenitor()->progenitor(),
mit->second ,type);
if(output) updateHistory(progenitor()->progenitor());
return output;
}
}
bool output = hardOnly() ? false :
timeLikeShower(progenitor()->progenitor() ,type,true) ;
if(output) updateHistory(progenitor()->progenitor());
return output;
}
bool Evolver::startSpaceLikeShower(PPtr parent, ShowerInteraction::Type type) {
if(hardTree()) {
map<ShowerParticlePtr,tHardBranchingPtr>::const_iterator
eit =hardTree()->particles().end(),
mit = hardTree()->particles().find(progenitor()->progenitor());
if( mit != eit && mit->second->parent() ) {
return truncatedSpaceLikeShower( progenitor()->progenitor(),
parent, mit->second->parent(), type );
}
}
return hardOnly() ? false :
spaceLikeShower(progenitor()->progenitor(),parent,type);
}
bool Evolver::startSpaceLikeDecayShower(Energy maxscale,Energy minimumMass,
ShowerInteraction::Type type) {
if(hardTree()) {
map<ShowerParticlePtr,tHardBranchingPtr>::const_iterator
eit =hardTree()->particles().end(),
mit = hardTree()->particles().find(progenitor()->progenitor());
if( mit != eit && mit->second->parent() ) {
HardBranchingPtr branch=mit->second;
while(branch->parent()) branch=branch->parent();
return truncatedSpaceLikeDecayShower(progenitor()->progenitor(),maxscale,
minimumMass, branch ,type);
}
}
return hardOnly() ? false :
spaceLikeDecayShower(progenitor()->progenitor(),maxscale,minimumMass,type);
}
bool Evolver::timeLikeVetoed(const Branching & fb,
ShowerParticlePtr particle) {
// check whether emission was harder than largest pt of hard subprocess
if ( hardVetoFS() && fb.kinematics->pT() > _progenitor->maxHardPt() )
return true;
// soft matrix element correction veto
if( softMEC()) {
if(_hardme && _hardme->hasMECorrection()) {
if(_hardme->softMatrixElementVeto(_progenitor,particle,fb))
return true;
}
else if(_decayme && _decayme->hasMECorrection()) {
if(_decayme->softMatrixElementVeto(_progenitor,particle,fb))
return true;
}
}
// veto on maximum pt
if(fb.kinematics->pT()>_progenitor->maximumpT()) return true;
// general vetos
if (fb.kinematics && !_vetoes.empty()) {
bool vetoed=false;
for (vector<ShowerVetoPtr>::iterator v = _vetoes.begin();
v != _vetoes.end(); ++v) {
bool test = (**v).vetoTimeLike(_progenitor,particle,fb);
switch((**v).vetoType()) {
case ShowerVeto::Emission:
vetoed |= test;
break;
case ShowerVeto::Shower:
if(test) throw VetoShower();
break;
case ShowerVeto::Event:
if(test) throw Veto();
break;
}
}
if(vetoed) return true;
}
return false;
}
bool Evolver::spaceLikeVetoed(const Branching & bb,ShowerParticlePtr particle) {
// check whether emission was harder than largest pt of hard subprocess
if (hardVetoIS() && bb.kinematics->pT() > _progenitor->maxHardPt())
return true;
// apply the soft correction
if( softMEC() && _hardme && _hardme->hasMECorrection() ) {
if(_hardme->softMatrixElementVeto(_progenitor,particle,bb))
return true;
}
// the more general vetos
// check vs max pt for the shower
if(bb.kinematics->pT()>_progenitor->maximumpT()) return true;
if (!_vetoes.empty()) {
bool vetoed=false;
for (vector<ShowerVetoPtr>::iterator v = _vetoes.begin();
v != _vetoes.end(); ++v) {
bool test = (**v).vetoSpaceLike(_progenitor,particle,bb);
switch ((**v).vetoType()) {
case ShowerVeto::Emission:
vetoed |= test;
break;
case ShowerVeto::Shower:
if(test) throw VetoShower();
break;
case ShowerVeto::Event:
if(test) throw Veto();
break;
}
}
if (vetoed) return true;
}
return false;
}
bool Evolver::spaceLikeDecayVetoed( const Branching & fb,
ShowerParticlePtr particle ) {
// apply the soft correction
if( softMEC() && _decayme && _decayme->hasMECorrection() ) {
if(_decayme->softMatrixElementVeto(_progenitor,particle,fb))
return true;
}
// veto on hardest pt in the shower
if(fb.kinematics->pT()> _progenitor->maximumpT()) return true;
// general vetos
if (!_vetoes.empty()) {
bool vetoed=false;
for (vector<ShowerVetoPtr>::iterator v = _vetoes.begin();
v != _vetoes.end(); ++v) {
bool test = (**v).vetoSpaceLike(_progenitor,particle,fb);
switch((**v).vetoType()) {
case ShowerVeto::Emission:
vetoed |= test;
break;
case ShowerVeto::Shower:
if(test) throw VetoShower();
break;
case ShowerVeto::Event:
if(test) throw Veto();
break;
}
if (vetoed) return true;
}
}
return false;
}
void Evolver::hardestEmission(bool hard) {
if( ( _hardme && _hardme->hasPOWHEGCorrection()) ||
(_decayme && _decayme->hasPOWHEGCorrection())) {
if(_hardme)
_hardtree = _hardme->generateHardest( currentTree() );
else
_hardtree = _decayme->generateHardest( currentTree() );
if(!_hardtree) return;
// join up the two tree
connectTrees(currentTree(),_hardtree,hard);
}
else {
_hardtree = ShowerHandler::currentHandler()->generateCKKW(currentTree());
}
}
bool Evolver::truncatedTimeLikeShower(tShowerParticlePtr particle,
HardBranchingPtr branch,
ShowerInteraction::Type type) {
int ntry=0;
do {
++ntry;
Branching fb;
unsigned int iout=0;
tcPDPtr pdata[2];
while (true) {
// no truncated shower break
if(!isTruncatedShowerON()||hardOnly()) break;
// generate emission
fb=splittingGenerator()->chooseForwardBranching(*particle,1.,type);
// no emission break
if(!fb.kinematics) break;
// check haven't evolved too far
if(fb.kinematics->scale() < branch->scale()) {
fb=Branching();
break;
}
// get the particle data objects
for(unsigned int ix=0;ix<2;++ix) pdata[ix]=getParticleData(fb.ids[ix+1]);
if(particle->id()!=fb.ids[0]) {
for(unsigned int ix=0;ix<2;++ix) {
tPDPtr cc(pdata[ix]->CC());
if(cc) pdata[ix]=cc;
}
}
// find the truncated line
iout=0;
if(pdata[0]->id()!=pdata[1]->id()) {
if(pdata[0]->id()==particle->id()) iout=1;
else if (pdata[1]->id()==particle->id()) iout=2;
}
else if(pdata[0]->id()==particle->id()) {
if(fb.kinematics->z()>0.5) iout=1;
else iout=2;
}
// apply the vetos for the truncated shower
// no flavour changing branchings
if(iout==0) {
particle->setEvolutionScale(fb.kinematics->scale());
continue;
}
double zsplit = iout==1 ? fb.kinematics->z() : 1-fb.kinematics->z();
// only if same interaction for forced branching
// and evolution
if(type==branch->sudakov()->interactionType()) {
if(zsplit < 0.5 || // hardest line veto
fb.kinematics->scale()*zsplit < branch->scale() ) { // angular ordering veto
particle->setEvolutionScale(fb.kinematics->scale());
continue;
}
}
// pt veto
if(fb.kinematics->pT() > progenitor()->maximumpT()) {
particle->setEvolutionScale(fb.kinematics->scale());
continue;
}
// should do base class vetos as well
if(timeLikeVetoed(fb,particle)) {
particle->setEvolutionScale(fb.kinematics->scale());
continue;
}
break;
}
// if no branching force trunctaed emission
if(!fb.kinematics) {
// construct the kinematics for the hard emission
ShoKinPtr showerKin=
branch->sudakov()->createFinalStateBranching(branch->scale(),
branch->children()[0]->z(),
branch->phi(),
branch->children()[0]->pT());
particle->setEvolutionScale(branch->scale() );
showerKin->initialize( *particle,PPtr() );
IdList idlist(3);
idlist[0] = particle->id();
idlist[1] = branch->children()[0]->branchingParticle()->id();
idlist[2] = branch->children()[1]->branchingParticle()->id();
fb = Branching( showerKin, idlist, branch->sudakov() );
// Assign the shower kinematics to the emitting particle.
particle->setShowerKinematics( fb.kinematics );
// Assign the splitting function to the emitting particle.
// For the time being we are considering only 1->2 branching
// Create the ShowerParticle objects for the two children of
// the emitting particle; set the parent/child relationship
// if same as definition create particles, otherwise create cc
ShowerParticleVector theChildren;
theChildren.push_back(new_ptr(ShowerParticle(branch->children()[0]->
branchingParticle()->dataPtr(),true)));
theChildren.push_back(new_ptr(ShowerParticle(branch->children()[1]->
branchingParticle()->dataPtr(),true)));
particle->showerKinematics()->
updateChildren(particle, theChildren,type==branch->sudakov()->interactionType());
// shower the first particle
if( branch->children()[0]->children().empty() ) {
if( ! hardOnly() )
timeLikeShower(theChildren[0],type,false);
}
else {
truncatedTimeLikeShower( theChildren[0],branch->children()[0],type);
}
// shower the second particle
if( branch->children()[1]->children().empty() ) {
if( ! hardOnly() )
timeLikeShower( theChildren[1] , type,false);
}
else {
truncatedTimeLikeShower( theChildren[1],branch->children()[1] ,type);
}
// that's if for old approach
if(_reconOpt==0) return true;
// branching has happened
particle->showerKinematics()->updateParent(particle, theChildren,true);
// clean up the vetoed emission
if(particle->virtualMass()==ZERO) {
particle->setShowerKinematics(ShoKinPtr());
for(unsigned int ix=0;ix<theChildren.size();++ix)
particle->abandonChild(theChildren[ix]);
theChildren.clear();
}
else return true;
}
// has emitted
// Assign the shower kinematics to the emitting particle.
particle->setShowerKinematics(fb.kinematics);
// Assign the splitting function to the emitting particle.
// For the time being we are considering only 1->2 branching
// Create the ShowerParticle objects for the two children of
// the emitting particle; set the parent/child relationship
// if same as definition create particles, otherwise create cc
ShowerParticleVector theChildren;
theChildren.push_back( new_ptr( ShowerParticle( pdata[0], true ) ) );
theChildren.push_back( new_ptr( ShowerParticle( pdata[1], true ) ) );
particle->showerKinematics()->
updateChildren( particle, theChildren , true);
// shower the first particle
if( iout == 1 ) truncatedTimeLikeShower( theChildren[0], branch , type );
else timeLikeShower( theChildren[0] , type,false);
// shower the second particle
if( iout == 2 ) truncatedTimeLikeShower( theChildren[1], branch , type );
else timeLikeShower( theChildren[1] , type,false);
// that's if for old approach
if(_reconOpt==0) return true;
// branching has happened
particle->showerKinematics()->updateParent(particle, theChildren,true);
// clean up the vetoed emission
if(particle->virtualMass()==ZERO) {
particle->setShowerKinematics(ShoKinPtr());
for(unsigned int ix=0;ix<theChildren.size();++ix)
particle->abandonChild(theChildren[ix]);
theChildren.clear();
}
else return true;
}
while(ntry<50);
return false;
}
bool Evolver::truncatedSpaceLikeShower(tShowerParticlePtr particle, PPtr beam,
HardBranchingPtr branch,
ShowerInteraction::Type type) {
tcPDFPtr pdf;
if(ShowerHandler::currentHandler()->firstPDF().particle() == beamParticle())
pdf = ShowerHandler::currentHandler()->firstPDF().pdf();
if(ShowerHandler::currentHandler()->secondPDF().particle() == beamParticle())
pdf = ShowerHandler::currentHandler()->secondPDF().pdf();
Energy freeze = ShowerHandler::currentHandler()->pdfFreezingScale();
Branching bb;
// generate branching
tcPDPtr part[2];
while (true) {
if( !isTruncatedShowerON() || hardOnly() ) break;
bb = splittingGenerator()->chooseBackwardBranching( *particle,
beam, 1., beamParticle(),
type , pdf,freeze);
if( !bb.kinematics || bb.kinematics->scale() < branch->scale() ) {
bb = Branching();
break;
}
// particles as in Sudakov form factor
part[0] = getParticleData( bb.ids[0] );
part[1] = getParticleData( bb.ids[2] );
//is emitter anti-particle
if( particle->id() != bb.ids[1]) {
if( part[0]->CC() ) part[0] = part[0]->CC();
if( part[1]->CC() ) part[1] = part[1]->CC();
}
double zsplit = bb.kinematics->z();
// apply the vetos for the truncated shower
// if doesn't carry most of momentum
if(type==branch->sudakov()->interactionType() &&
zsplit < 0.5) {
particle->setEvolutionScale(bb.kinematics->scale() );
continue;
}
// others
if( part[0]->id() != particle->id() || // if particle changes type
bb.kinematics->pT() > progenitor()->maximumpT() || // pt veto
bb.kinematics->scale() < branch->scale()) { // angular ordering veto
particle->setEvolutionScale(bb.kinematics->scale() );
continue;
}
// and those from the base class
if(spaceLikeVetoed(bb,particle)) {
particle->setEvolutionScale(bb.kinematics->scale() );
continue;
}
break;
}
if( !bb.kinematics ) {
//do the hard emission
double z(0.);
HardBranchingPtr timelike;
for( unsigned int ix = 0; ix < branch->children().size(); ++ix ) {
if( branch->children()[ix]->status() ==HardBranching::Outgoing) {
timelike = branch->children()[ix];
}
if( branch->children()[ix]->status() ==HardBranching::Incoming )
z = branch->children()[ix]->z();
}
ShoKinPtr kinematics =
branch->sudakov()->createInitialStateBranching( branch->scale(), z, branch->phi(),
branch->children()[0]->pT() );
kinematics->initialize( *particle, beam );
// assign the splitting function and shower kinematics
particle->setShowerKinematics( kinematics );
// For the time being we are considering only 1->2 branching
// Now create the actual particles, make the otherChild a final state
// particle, while the newParent is not
ShowerParticlePtr newParent =
new_ptr( ShowerParticle( branch->branchingParticle()->dataPtr(), false ) );
ShowerParticlePtr otherChild =
new_ptr( ShowerParticle( timelike->branchingParticle()->dataPtr(),
true, true ) );
ShowerParticleVector theChildren;
theChildren.push_back( particle );
theChildren.push_back( otherChild );
particle->showerKinematics()->
updateParent( newParent, theChildren, type==branch->sudakov()->interactionType() );
// update the history if needed
currentTree()->updateInitialStateShowerProduct( progenitor(), newParent );
currentTree()->addInitialStateBranching( particle, newParent, otherChild );
// for the reconstruction of kinematics, parent/child
// relationships are according to the branching process:
// now continue the shower
bool emitted=false;
if(!hardOnly()) {
if( branch->parent() ) {
emitted = truncatedSpaceLikeShower( newParent, beam, branch->parent() , type);
}
else {
emitted = spaceLikeShower( newParent, beam , type);
}
}
if( !emitted ) {
if( intrinsicpT().find( progenitor() ) == intrinsicpT().end() ) {
kinematics->updateLast( newParent, ZERO, ZERO );
}
else {
pair<Energy,double> kt = intrinsicpT()[progenitor()];
kinematics->updateLast( newParent,
kt.first*cos( kt.second ),
kt.first*sin( kt.second ) );
}
}
particle->showerKinematics()->
updateChildren( newParent, theChildren,
type==branch->sudakov()->interactionType() );
if(hardOnly()) return true;
// perform the shower of the final-state particle
if( timelike->children().empty() ) {
timeLikeShower( otherChild , type,true);
}
else {
truncatedTimeLikeShower( otherChild, timelike , type);
}
// return the emitted
return true;
}
// assign the splitting function and shower kinematics
particle->setShowerKinematics( bb.kinematics );
// For the time being we are considering only 1->2 branching
// Now create the actual particles, make the otherChild a final state
// particle, while the newParent is not
ShowerParticlePtr newParent = new_ptr( ShowerParticle( part[0], false ) );
ShowerParticlePtr otherChild = new_ptr( ShowerParticle( part[1], true, true ) );
ShowerParticleVector theChildren;
theChildren.push_back( particle );
theChildren.push_back( otherChild );
particle->showerKinematics()->updateParent( newParent, theChildren , true);
// update the history if needed
currentTree()->updateInitialStateShowerProduct( progenitor(), newParent );
currentTree()->addInitialStateBranching( particle, newParent, otherChild );
// for the reconstruction of kinematics, parent/child
// relationships are according to the branching process:
// now continue the shower
bool emitted = truncatedSpaceLikeShower( newParent, beam, branch,type);
// now reconstruct the momentum
if( !emitted ) {
if( intrinsicpT().find( progenitor() ) == intrinsicpT().end() ) {
bb.kinematics->updateLast( newParent, ZERO, ZERO );
}
else {
pair<Energy,double> kt = intrinsicpT()[ progenitor() ];
bb.kinematics->updateLast( newParent,
kt.first*cos( kt.second ),
kt.first*sin( kt.second ) );
}
}
particle->showerKinematics()->updateChildren( newParent, theChildren , true);
// perform the shower of the final-state particle
timeLikeShower( otherChild , type,true);
// return the emitted
return true;
}
bool Evolver::
truncatedSpaceLikeDecayShower(tShowerParticlePtr particle, Energy maxscale,
Energy minmass, HardBranchingPtr branch,
ShowerInteraction::Type type) {
Branching fb;
unsigned int iout=0;
tcPDPtr pdata[2];
while (true) {
// no truncated shower break
if(!isTruncatedShowerON()||hardOnly()) break;
fb=splittingGenerator()->chooseDecayBranching(*particle,maxscale,minmass,1.,type);
// return if no radiation
if(!fb.kinematics) break;
// check haven't evolved too far
if(fb.kinematics->scale() < branch->scale()) {
fb=Branching();
break;
}
// get the particle data objects
for(unsigned int ix=0;ix<2;++ix) pdata[ix]=getParticleData(fb.ids[ix+1]);
if(particle->id()!=fb.ids[0]) {
for(unsigned int ix=0;ix<2;++ix) {
tPDPtr cc(pdata[ix]->CC());
if(cc) pdata[ix]=cc;
}
}
// find the truncated line
iout=0;
if(pdata[0]->id()!=pdata[1]->id()) {
if(pdata[0]->id()==particle->id()) iout=1;
else if (pdata[1]->id()==particle->id()) iout=2;
}
else if(pdata[0]->id()==particle->id()) {
if(fb.kinematics->z()>0.5) iout=1;
else iout=2;
}
// apply the vetos for the truncated shower
// no flavour changing branchings
if(iout==0) {
particle->setEvolutionScale(fb.kinematics->scale());
continue;
}
double zsplit = iout==1 ? fb.kinematics->z() : 1-fb.kinematics->z();
if(type==branch->sudakov()->interactionType()) {
if(zsplit < 0.5 || // hardest line veto
fb.kinematics->scale()*zsplit < branch->scale() ) { // angular ordering veto
particle->setEvolutionScale(fb.kinematics->scale());
continue;
}
}
// pt veto
if(fb.kinematics->pT() > progenitor()->maximumpT()) {
particle->setEvolutionScale(fb.kinematics->scale());
continue;
}
// should do base class vetos as well
// if not vetoed break
if(!spaceLikeDecayVetoed(fb,particle)) break;
// otherwise reset scale and continue
particle->setEvolutionScale(fb.kinematics->scale());
}
// if no branching set decay matrix and return
if(!fb.kinematics) {
// construct the kinematics for the hard emission
ShoKinPtr showerKin=
branch->sudakov()->createDecayBranching(branch->scale(),
branch->children()[0]->z(),
branch->phi(),
branch->children()[0]->pT());
particle->setEvolutionScale(branch->scale() );
showerKin->initialize( *particle,PPtr() );
IdList idlist(3);
idlist[0] = particle->id();
idlist[1] = branch->children()[0]->branchingParticle()->id();
idlist[2] = branch->children()[1]->branchingParticle()->id();
fb = Branching( showerKin, idlist, branch->sudakov() );
// Assign the shower kinematics to the emitting particle.
particle->setShowerKinematics( fb.kinematics );
// Assign the splitting function to the emitting particle.
// For the time being we are considering only 1->2 branching
// Create the ShowerParticle objects for the two children of
// the emitting particle; set the parent/child relationship
// if same as definition create particles, otherwise create cc
ShowerParticleVector theChildren;
theChildren.push_back(new_ptr(ShowerParticle(branch->children()[0]->
branchingParticle()->dataPtr(),true)));
theChildren.push_back(new_ptr(ShowerParticle(branch->children()[1]->
branchingParticle()->dataPtr(),true)));
particle->showerKinematics()->
updateChildren(particle, theChildren,
type==branch->sudakov()->interactionType());
if(theChildren[0]->id()==particle->id()) {
// update the history if needed
currentTree()->updateInitialStateShowerProduct(progenitor(),theChildren[0]);
currentTree()->addInitialStateBranching(particle,theChildren[0],theChildren[1]);
// shower the space-like particle
if( branch->children()[0]->children().empty() ) {
if( ! hardOnly() ) spaceLikeDecayShower(theChildren[0],maxscale,minmass,type);
}
else {
truncatedSpaceLikeDecayShower( theChildren[0],maxscale,minmass,
branch->children()[0],type);
}
// shower the second particle
if( branch->children()[1]->children().empty() ) {
if( ! hardOnly() ) timeLikeShower( theChildren[1] , type,true);
}
else {
truncatedTimeLikeShower( theChildren[1],branch->children()[1] ,type);
}
}
else {
// update the history if needed
currentTree()->updateInitialStateShowerProduct(progenitor(),theChildren[1]);
currentTree()->addInitialStateBranching(particle,theChildren[0],theChildren[1]);
// shower the space-like particle
if( branch->children()[1]->children().empty() ) {
if( ! hardOnly() ) spaceLikeDecayShower(theChildren[1],maxscale,minmass,type);
}
else {
truncatedSpaceLikeDecayShower( theChildren[1],maxscale,minmass,
branch->children()[1],type);
}
// shower the second particle
if( branch->children()[0]->children().empty() ) {
if( ! hardOnly() ) timeLikeShower( theChildren[0] , type,true);
}
else {
truncatedTimeLikeShower( theChildren[0],branch->children()[0] ,type);
}
}
return true;
}
// has emitted
// Assign the shower kinematics to the emitting particle.
particle->setShowerKinematics(fb.kinematics);
// For the time being we are considering only 1->2 branching
// Create the ShowerParticle objects for the two children of
// the emitting particle; set the parent/child relationship
// if same as definition create particles, otherwise create cc
ShowerParticleVector theChildren;
theChildren.push_back(new_ptr(ShowerParticle(pdata[0],true)));
theChildren.push_back(new_ptr(ShowerParticle(pdata[1],true)));
particle->showerKinematics()->updateChildren(particle, theChildren,true);
// In the case of splittings which involves coloured particles,
// set properly the colour flow of the branching.
// update the history if needed
currentTree()->updateInitialStateShowerProduct(progenitor(),theChildren[0]);
currentTree()->addInitialStateBranching(particle,theChildren[0],theChildren[1]);
// shower the first particle
truncatedSpaceLikeDecayShower(theChildren[0],maxscale,minmass,branch,type);
// shower the second particle
timeLikeShower(theChildren[1],type,true);
// branching has happened
return true;
}
void Evolver::connectTrees(ShowerTreePtr showerTree,
HardTreePtr hardTree, bool hard ) const {
ShowerParticleVector particles;
// find the Sudakovs
for(set<HardBranchingPtr>::iterator cit=hardTree->branchings().begin();
cit!=hardTree->branchings().end();++cit) {
// Sudakovs for ISR
if((**cit).parent()&&(**cit).status()==HardBranching::Incoming) {
IdList br(3);
br[0] = (**cit).parent()->branchingParticle()->id();
br[1] = (**cit). branchingParticle()->id();
br[2] = (**cit).parent()->children()[0]==*cit ?
(**cit).parent()->children()[1]->branchingParticle()->id() :
(**cit).parent()->children()[0]->branchingParticle()->id();
BranchingList branchings = splittingGenerator()->initialStateBranchings();
if(br[1]<0&&br[0]==br[1]) {
br[0] = abs(br[0]);
br[1] = abs(br[1]);
}
else if(br[1]<0) {
br[1] = -br[1];
br[2] = -br[2];
}
long index = abs(br[1]);
SudakovPtr sudakov;
for(BranchingList::const_iterator cjt = branchings.lower_bound(index);
cjt != branchings.upper_bound(index); ++cjt ) {
IdList ids = cjt->second.second;
if(ids[0]==br[0]&&ids[1]==br[1]&&ids[2]==br[2]) {
sudakov=cjt->second.first;
break;
}
}
if(!sudakov) throw Exception() << "Can't find Sudakov for the hard emission in "
<< "Evolver::connectTrees() for ISR"
<< Exception::runerror;
(**cit).parent()->sudakov(sudakov);
}
// Sudakovs for FSR
else if(!(**cit).children().empty()) {
IdList br(3);
br[0] = (**cit) .branchingParticle()->id();
br[1] = (**cit).children()[0]->branchingParticle()->id();
br[2] = (**cit).children()[1]->branchingParticle()->id();
BranchingList branchings = splittingGenerator()->finalStateBranchings();
if(br[0]<0) {
br[0] = abs(br[0]);
br[1] = abs(br[1]);
br[2] = abs(br[2]);
}
long index = br[0];
SudakovPtr sudakov;
for(BranchingList::const_iterator cjt = branchings.lower_bound(index);
cjt != branchings.upper_bound(index); ++cjt ) {
IdList ids = cjt->second.second;
if(ids[0]==br[0]&&ids[1]==br[1]&&ids[2]==br[2]) {
sudakov=cjt->second.first;
break;
}
}
if(!sudakov) throw Exception() << "Can't find Sudakov for the hard emission in "
<< "Evolver::connectTrees()"
<< Exception::runerror;
(**cit).sudakov(sudakov);
}
}
// calculate the evolution scale
for(set<HardBranchingPtr>::iterator cit=hardTree->branchings().begin();
cit!=hardTree->branchings().end();++cit) {
particles.push_back((*cit)->branchingParticle());
}
showerModel()->partnerFinder()->
setInitialEvolutionScales(particles,!hard,hardTree->interaction(),true);
// inverse reconstruction
if(hard)
showerModel()->kinematicsReconstructor()->
deconstructHardJets(hardTree,ShowerHandler::currentHandler()->evolver(),
hardTree->interaction());
else
showerModel()->kinematicsReconstructor()->
deconstructDecayJets(hardTree,ShowerHandler::currentHandler()->evolver(),
hardTree->interaction());
// now reset the momenta of the showering particles
vector<ShowerProgenitorPtr> particlesToShower;
for(map<ShowerProgenitorPtr,ShowerParticlePtr>::const_iterator
cit=showerTree->incomingLines().begin();
cit!=showerTree->incomingLines().end();++cit )
particlesToShower.push_back(cit->first);
// extract the showering particles
for(map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator
cit=showerTree->outgoingLines().begin();
cit!=showerTree->outgoingLines().end();++cit )
particlesToShower.push_back(cit->first);
// match them
vector<bool> matched(particlesToShower.size(),false);
for(set<HardBranchingPtr>::const_iterator cit=hardTree->branchings().begin();
cit!=hardTree->branchings().end();++cit) {
Energy2 dmin( 1e30*GeV2 );
int iloc(-1);
for(unsigned int ix=0;ix<particlesToShower.size();++ix) {
if(matched[ix]) continue;
if( (**cit).branchingParticle()->id() != particlesToShower[ix]->progenitor()->id() ) continue;
if( (**cit).branchingParticle()->isFinalState() !=
particlesToShower[ix]->progenitor()->isFinalState() ) continue;
Energy2 dtest =
sqr( particlesToShower[ix]->progenitor()->momentum().x() - (**cit).showerMomentum().x() ) +
sqr( particlesToShower[ix]->progenitor()->momentum().y() - (**cit).showerMomentum().y() ) +
sqr( particlesToShower[ix]->progenitor()->momentum().z() - (**cit).showerMomentum().z() ) +
sqr( particlesToShower[ix]->progenitor()->momentum().t() - (**cit).showerMomentum().t() );
// add mass difference for identical particles (e.g. Z0 Z0 production)
dtest += 1e10*sqr(particlesToShower[ix]->progenitor()->momentum().m()-
(**cit).showerMomentum().m());
if( dtest < dmin ) {
iloc = ix;
dmin = dtest;
}
}
if(iloc<0) throw Exception() << "Failed to match shower and hard trees in Evolver::hardestEmission"
<< Exception::eventerror;
particlesToShower[iloc]->progenitor()->set5Momentum((**cit).showerMomentum());
matched[iloc] = true;
}
// correction boosts for daughter trees
for(map<tShowerTreePtr,pair<tShowerProgenitorPtr,tShowerParticlePtr> >::const_iterator
tit = showerTree->treelinks().begin();
tit != showerTree->treelinks().end();++tit) {
ShowerTreePtr decayTree = tit->first;
map<ShowerProgenitorPtr,ShowerParticlePtr>::const_iterator
cit = decayTree->incomingLines().begin();
// reset the momentum of the decay particle
Lorentz5Momentum oldMomentum = cit->first->progenitor()->momentum();
Lorentz5Momentum newMomentum = tit->second.second->momentum();
LorentzRotation boost( oldMomentum.findBoostToCM(),oldMomentum.e()/oldMomentum.mass());
boost.boost (-newMomentum.findBoostToCM(),newMomentum.e()/newMomentum.mass());
decayTree->transform(boost,true);
}
}
diff --git a/Shower/Base/Evolver.h b/Shower/Base/Evolver.h
--- a/Shower/Base/Evolver.h
+++ b/Shower/Base/Evolver.h
@@ -1,712 +1,671 @@
// -*- C++ -*-
//
// Evolver.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_Evolver_H
#define HERWIG_Evolver_H
//
// This is the declaration of the Evolver class.
//
#include "ThePEG/Interface/Interfaced.h"
#include "Herwig++/Shower/SplittingFunctions/SplittingGenerator.h"
#include "ShowerModel.h"
#include "ThePEG/PDF/BeamParticleData.h"
#include "ShowerTree.h"
#include "ShowerProgenitor.fh"
#include "Herwig++/Shower/ShowerHandler.fh"
#include "Branching.h"
#include "ShowerVeto.h"
#include "HardTree.h"
#include "ThePEG/Handlers/XComb.h"
#include "Evolver.fh"
#include "Herwig++/MatrixElement/HwMEBase.h"
#include "Herwig++/Decay/HwDecayerBase.h"
namespace Herwig {
using namespace ThePEG;
/** \ingroup Shower
* The Evolver class class performs the sohwer evolution of hard scattering
* and decay processes in Herwig++.
*
* @see \ref EvolverInterfaces "The interfaces"
* defined for Evolver.
*/
class Evolver: public Interfaced {
/**
* The ShowerHandler is a friend to set some parameters at initialisation
*/
friend class ShowerHandler;
public:
/**
* Pointer to an XComb object
*/
typedef Ptr<XComb>::pointer XCPtr;
public:
/**
* Default Constructor
*/
Evolver() : _maxtry(100), _meCorrMode(1), _hardVetoMode(1),
_hardVetoRead(0), _reconOpt(0), _hardVetoReadOption(false),
_iptrms(ZERO), _beta(0.), _gamma(ZERO), _iptmax(),
_limitEmissions(0), _initialenhance(1.), _finalenhance(1.),
_hardonly(false), _trunc_Mode(true), _hardEmissionMode(0),
_colourEvolutionMethod(0)
{}
/**
* Members to perform the shower
*/
//@{
/**
* Perform the shower of the hard process
*/
virtual void showerHardProcess(ShowerTreePtr,XCPtr);
/**
* Perform the shower of a decay
*/
virtual void showerDecay(ShowerTreePtr);
//@}
/**
* Access to the flags and shower variables
*/
//@{
/**
* Is there any showering switched on
*/
bool showeringON() const { return isISRadiationON() || isFSRadiationON(); }
/**
* It returns true/false if the initial-state radiation is on/off.
*/
bool isISRadiationON() const { return _splittingGenerator->isISRadiationON(); }
/**
* It returns true/false if the final-state radiation is on/off.
*/
bool isFSRadiationON() const { return _splittingGenerator->isFSRadiationON(); }
/**
* Get the ShowerModel
*/
ShowerModelPtr showerModel() const {return _model;}
/**
* Get the SplittingGenerator
*/
tSplittingGeneratorPtr splittingGenerator() const { return _splittingGenerator; }
//@}
/**
* Connect the Hard and Shower trees
*/
virtual void connectTrees(ShowerTreePtr showerTree, HardTreePtr hardTree, bool hard )const;
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/**
* Generate the hard matrix element correction
*/
virtual void hardMatrixElementCorrection(bool);
/**
* Generate the hardest emission
*/
virtual void hardestEmission(bool hard);
/**
* Extract the particles to be showered, set the evolution scales
* and apply the hard matrix element correction
* @param hard Whether this is a hard process or decay
* @return The particles to be showered
*/
virtual vector<ShowerProgenitorPtr> setupShower(bool hard);
/**
* set the colour partners
*/
virtual void setEvolutionPartners(bool hard,ShowerInteraction::Type);
/**
* Methods to perform the evolution of an individual particle, including
* recursive calling on the products
*/
//@{
/**
* It does the forward evolution of the time-like input particle
* (and recursively for all its radiation products).
* accepting only emissions which conforms to the showerVariables
* and soft matrix element correction.
* If at least one emission has occurred then the method returns true.
* @param particle The particle to be showered
*/
virtual bool timeLikeShower(tShowerParticlePtr particle, ShowerInteraction::Type,
bool first);
/**
* It does the backward evolution of the space-like input particle
* (and recursively for all its time-like radiation products).
* accepting only emissions which conforms to the showerVariables.
* If at least one emission has occurred then the method returns true
* @param particle The particle to be showered
* @param beam The beam particle
*/
virtual bool spaceLikeShower(tShowerParticlePtr particle,PPtr beam,
ShowerInteraction::Type);
/**
* If does the forward evolution of the input on-shell particle
* involved in a decay
* (and recursively for all its time-like radiation products).
* accepting only emissions which conforms to the showerVariables.
* @param particle The particle to be showered
* @param maxscale The maximum scale for the shower.
* @param minimumMass The minimum mass of the final-state system
*/
virtual bool spaceLikeDecayShower(tShowerParticlePtr particle,
Energy maxscale,
Energy minimumMass,
ShowerInteraction::Type);
/**
* Truncated shower from a time-like particle
*/
virtual bool truncatedTimeLikeShower(tShowerParticlePtr particle,
HardBranchingPtr branch,
ShowerInteraction::Type type);
/**
* Truncated shower from a space-like particle
*/
virtual bool truncatedSpaceLikeShower(tShowerParticlePtr particle,PPtr beam,
HardBranchingPtr branch,
ShowerInteraction::Type type);
/**
* Truncated shower from a time-like particle
*/
virtual bool truncatedSpaceLikeDecayShower(tShowerParticlePtr particle,
Energy maxscale, Energy minimumMass,
HardBranchingPtr branch,
ShowerInteraction::Type type);
//@}
/**
* Switches for matrix element corrections
*/
//@{
/**
* Any ME correction?
*/
bool MECOn() const {
return _meCorrMode > 0 && _hardEmissionMode==0;
}
/**
* Any hard ME correction?
*/
bool hardMEC() const {
return (_meCorrMode == 1 || _meCorrMode == 2) && _hardEmissionMode==0;
}
/**
* Any soft ME correction?
*/
bool softMEC() const {
return (_meCorrMode == 1 || _meCorrMode > 2) && _hardEmissionMode==0;
}
//@}
/**
* Is the truncated shower on?
*/
bool isTruncatedShowerON() const {return _trunc_Mode;}
/**
* Switch for intrinsic pT
*/
//@{
/**
* Any intrinsic pT?
*/
bool ipTon() const {
return _iptrms != ZERO || ( _beta == 1.0 && _gamma != ZERO && _iptmax !=ZERO );
}
//@}
/**@name Additional shower vetoes */
//@{
/**
* Insert a veto.
*/
void addVeto (ShowerVetoPtr v) { _vetoes.push_back(v); }
/**
* Remove a veto.
*/
void removeVeto (ShowerVetoPtr v) {
vector<ShowerVetoPtr>::iterator vit = find(_vetoes.begin(),_vetoes.end(),v);
if (vit != _vetoes.end())
_vetoes.erase(vit);
}
//@}
/**
* Switches for vetoing hard emissions
*/
//@{
/**
* Vetos on?
*/
bool hardVetoOn() const { return _hardVetoMode > 0; }
/**
* veto hard emissions in IS shower?
*/
bool hardVetoIS() const { return _hardVetoMode == 1 || _hardVetoMode == 2; }
/**
* veto hard emissions in FS shower?
*/
bool hardVetoFS() const { return _hardVetoMode == 1 || _hardVetoMode > 2; }
/**
* veto hard emissions according to lastScale from XComb?
*/
bool hardVetoXComb() const {return (_hardVetoRead == 1);}
/**
* Returns true if the hard veto read-in is to be applied to only
* the primary collision and false otherwise.
*/
bool hardVetoReadOption() const {return _hardVetoReadOption;}
//@}
/**
* Enhancement factors for radiation needed to generate the soft matrix
* element correction.
*/
//@{
/**
* Access the enhancement factor for initial-state radiation
*/
double initialStateRadiationEnhancementFactor() const { return _initialenhance; }
/**
* Access the enhancement factor for final-state radiation
*/
double finalStateRadiationEnhancementFactor() const { return _finalenhance; }
/**
* Set the enhancement factor for initial-state radiation
*/
void initialStateRadiationEnhancementFactor(double in) { _initialenhance=in; }
/**
* Set the enhancement factor for final-state radiation
*/
void finalStateRadiationEnhancementFactor(double in) { _finalenhance=in; }
//@}
/**
* Access to set/get the HardTree currently beinging showered
*/
//@{
/**
* The HardTree currently being showered
*/
tHardTreePtr hardTree() {return _hardtree;}
/**
* The HardTree currently being showered
*/
void hardTree(tHardTreePtr in) {_hardtree = in;}
//@}
/**
* Access/set the beam particle for the current initial-state shower
*/
//@{
/**
* Get the beam particle data
*/
Ptr<BeamParticleData>::const_pointer beamParticle() const { return _beam; }
/**
* Set the beam particle data
*/
void setBeamParticle(Ptr<BeamParticleData>::const_pointer in) { _beam=in; }
//@}
/**
* Set/Get the current tree being evolverd for inheriting classes
*/
//@{
/**
* Get the tree
*/
tShowerTreePtr currentTree() { return _currenttree; }
/**
* Set the tree
*/
void currentTree(tShowerTreePtr tree) { _currenttree=tree; }
//@}
/**
* Access the maximum number of attempts to generate the shower
*/
unsigned int maximumTries() const { return _maxtry; }
/**
* Set/Get the ShowerProgenitor for the current shower
*/
//@{
/**
* Access the progenitor
*/
ShowerProgenitorPtr progenitor() { return _progenitor; }
/**
* Set the progenitor
*/
void progenitor(ShowerProgenitorPtr in) { _progenitor=in; }
//@}
/**
* Calculate the intrinsic \f$p_T\f$.
*/
virtual void generateIntrinsicpT(vector<ShowerProgenitorPtr>);
/**
* Access to the intrinsic \f$p_T\f$ for inheriting classes
*/
map<tShowerProgenitorPtr,pair<Energy,double> > & intrinsicpT() { return _intrinsic; }
/**
* find the maximally allowed pt acc to the hard process.
*/
void setupMaximumScales(ShowerTreePtr, vector<ShowerProgenitorPtr>);
protected:
/**
* Start the shower of a timelike particle
*/
virtual bool startTimeLikeShower(ShowerInteraction::Type);
/**
* Update of the time-like stuff
*/
void updateHistory(tShowerParticlePtr particle);
/**
* Start the shower of a spacelike particle
*/
virtual bool startSpaceLikeShower(PPtr,ShowerInteraction::Type);
/**
* Start the shower of a spacelike particle
*/
virtual bool startSpaceLikeDecayShower(Energy maxscale,Energy minimumMass,
ShowerInteraction::Type);
/**
* Vetos for the timelike shower
*/
virtual bool timeLikeVetoed(const Branching &,ShowerParticlePtr);
/**
* Vetos for the spacelike shower
*/
virtual bool spaceLikeVetoed(const Branching &,ShowerParticlePtr);
/**
* Vetos for the spacelike shower
*/
virtual bool spaceLikeDecayVetoed(const Branching &,ShowerParticlePtr);
/**
* Only generate the hard emission, for testing only.
*/
bool hardOnly() const {return _hardonly;}
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
virtual IBPtr fullclone() const;
//@}
private:
/**
* Get the octet -> octet octet reduction factor.
*/
double getReductionFactor(tShowerParticlePtr particle);
/**
- * The static object used to initialize the description of this class.
- * Indicates that this is a concrete class with persistent data.
- */
- static ClassDescription<Evolver> initEvolver;
-
- /**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
Evolver & operator=(const Evolver &);
private:
/**
* Pointer to the model for the shower evolution model
*/
ShowerModelPtr _model;
/**
* Pointer to the splitting generator
*/
SplittingGeneratorPtr _splittingGenerator;
/**
* Maximum number of tries to generate the shower of a particular tree
*/
unsigned int _maxtry;
/**
* Matrix element correction switch
*/
unsigned int _meCorrMode;
/**
* Hard emission veto switch
*/
unsigned int _hardVetoMode;
/**
* Hard veto to be read switch
*/
unsigned int _hardVetoRead;
/**
* Control of the reconstruction option
*/
unsigned int _reconOpt;
/**
* If hard veto pT scale is being read-in this determines
* whether the read-in value is applied to primary and
* secondary (MPI) scatters or just the primary one, with
* the usual computation of the veto being performed for
* the secondary (MPI) scatters.
*/
bool _hardVetoReadOption;
/**
* rms intrinsic pT of Gaussian distribution
*/
Energy _iptrms;
/**
* Proportion of inverse quadratic intrinsic pT distribution
*/
double _beta;
/**
* Parameter for inverse quadratic: 2*Beta*Gamma/(sqr(Gamma)+sqr(intrinsicpT))
*/
Energy _gamma;
/**
* Upper bound on intrinsic pT for inverse quadratic
*/
Energy _iptmax;
/**
* Limit the number of emissions for testing
*/
unsigned int _limitEmissions;
/**
* The progenitor of the current shower
*/
ShowerProgenitorPtr _progenitor;
/**
* Matrix element
*/
HwMEBasePtr _hardme;
/**
* Decayer
*/
HwDecayerBasePtr _decayme;
/**
* The ShowerTree currently being showered
*/
ShowerTreePtr _currenttree;
/**
* The HardTree currently being showered
*/
HardTreePtr _hardtree;
/**
* Radiation enhancement factors for use with the veto algorithm
* if needed by the soft matrix element correction
*/
//@{
/**
* Enhancement factor for initial-state radiation
*/
double _initialenhance;
/**
* Enhancement factor for final-state radiation
*/
double _finalenhance;
//@}
/**
* The beam particle data for the current initial-state shower
*/
Ptr<BeamParticleData>::const_pointer _beam;
/**
* Storage of the intrinsic \f$p_t\f$ of the particles
*/
map<tShowerProgenitorPtr,pair<Energy,double> > _intrinsic;
/**
* Vetoes
*/
vector<ShowerVetoPtr> _vetoes;
/**
* number of IS emissions
*/
unsigned int _nis;
/**
* Number of FS emissions
*/
unsigned int _nfs;
/**
* Only generate the emission from the hardest emission
* generate for testing only
*/
bool _hardonly;
/**
* Truncated shower switch
*/
bool _trunc_Mode;
/**
* Count of the number of truncated emissions
*/
unsigned int _truncEmissions;
/**
* Mode for the hard emissions
*/
unsigned int _hardEmissionMode;
/**
* Colour evolution method
*/
int _colourEvolutionMethod;
};
}
-#include "ThePEG/Utilities/ClassTraits.h"
-
-namespace ThePEG {
-
-/** @cond TRAITSPECIALIZATIONS */
-
-/** This template specialization informs ThePEG about the
- * base classes of Evolver. */
-template <>
-struct BaseClassTrait<Herwig::Evolver,1> {
- /** Typedef of the first base class of Evolver. */
- typedef Interfaced NthBase;
-};
-
-/** This template specialization informs ThePEG about the name of
- * the Evolver class and the shared object where it is defined. */
-template <>
-struct ClassTraits<Herwig::Evolver>
- : public ClassTraitsBase<Herwig::Evolver> {
- /** Return a platform-independent class name */
- static string className() { return "Herwig::Evolver"; }
- /**
- * The name of a file containing the dynamic library where the class
- * Evolver is implemented. It may also include several, space-separated,
- * libraries if the class Evolver depends on other classes (base classes
- * excepted). In this case the listed libraries will be dynamically
- * linked in the order they are specified.
- */
- static string library() { return "HwShower.so"; }
-};
-
-/** @endcond */
-
-}
-
#endif /* HERWIG_Evolver_H */
diff --git a/Shower/Base/KinematicsReconstructor.cc b/Shower/Base/KinematicsReconstructor.cc
--- a/Shower/Base/KinematicsReconstructor.cc
+++ b/Shower/Base/KinematicsReconstructor.cc
@@ -1,30 +1,30 @@
// -*- C++ -*-
//
// KinematicsReconstructor.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 KinematicsReconstructor class.
//
#include "KinematicsReconstructor.h"
#include "ThePEG/Interface/ClassDocumentation.h"
+#include "ThePEG/Utilities/DescribeClass.h"
using namespace Herwig;
-AbstractNoPIOClassDescription<KinematicsReconstructor>
-KinematicsReconstructor::initKinematicsReconstructor;
-// Definition of the static class description member.
+DescribeAbstractNoPIOClass<KinematicsReconstructor,Interfaced>
+describeKinematicsReconstructor ("Herwig::KinematicsReconstructor","HwShower.so");
void KinematicsReconstructor::Init() {
static ClassDocumentation<KinematicsReconstructor> documentation
( "This class is responsible for the kinematics reconstruction of the showering,",
" including the kinematics reshuffling necessary to compensate for the recoil"
"of the emissions." );
}
diff --git a/Shower/Base/KinematicsReconstructor.h b/Shower/Base/KinematicsReconstructor.h
--- a/Shower/Base/KinematicsReconstructor.h
+++ b/Shower/Base/KinematicsReconstructor.h
@@ -1,173 +1,132 @@
// -*- C++ -*-
//
// KinematicsReconstructor.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_KinematicsReconstructor_H
#define HERWIG_KinematicsReconstructor_H
//
// This is the declaration of the KinematicsReconstructor class.
//
#include "ThePEG/Interface/Interfaced.h"
#include "ShowerParticle.h"
#include "ShowerProgenitor.h"
#include "ShowerTree.h"
#include "HardTree.h"
#include "Evolver.fh"
#include "KinematicsReconstructor.fh"
#include <cassert>
namespace Herwig {
using namespace ThePEG;
/**\ingroup Shower
* Exception class
* used to communicate failure of kinematics
* reconstruction.
*/
struct KinematicsReconstructionVeto {};
/** \ingroup Shower
*
* This class is responsible for the kinematical reconstruction
* after each showering step, and also for the necessary Lorentz boosts
* in order to preserve energy-momentum conservation in the overall collision,
* and also the invariant mass and the rapidity of the hard subprocess system.
* In the case of multi-step showering, there will be not unnecessary
* kinematical reconstructions.
*
* Notice:
* - although we often use the term "jet" in either methods or variables names,
* or in comments, which could appear applicable only for QCD showering,
* there is indeed no "dynamics" represented in this class: only kinematics
* is involved, as the name of this class remainds. Therefore it can be used
* for any kind of showers (QCD-,QED-,EWK-,... bremsstrahlung).
*
* @see \ref KinematicsReconstructorInterfaces "The interfaces"
* defined for KinematicsReconstructor.
*/
class KinematicsReconstructor: public Interfaced {
public:
/**
* Methods to reconstruct the kinematics of a scattering or decay process
*/
//@{
/**
* Given the ShowerTree for the shower from a hard process
* the method does the reconstruction of the jets,
* including the appropriate boosts (kinematics reshufflings)
* needed to conserve the total energy-momentum of the collision
* and preserving the invariant mass and the rapidity of the
* hard subprocess system.
*/
virtual bool reconstructHardJets(ShowerTreePtr hard,
const map<tShowerProgenitorPtr,
pair<Energy,double> > & pt) const=0;
/**
* Given the ShowerTree for a decay shower
* the method does the reconstruction of the jets,
* including the appropriate boosts (kinematics reshufflings)
* needed to conserve the total energy-momentum of the collision
* and preserving the invariant mass and the rapidity of the
* hard subprocess system.
*/
virtual bool reconstructDecayJets(ShowerTreePtr decay) const=0;
//@}
/**
* Methods to invert the reconstruction of the shower for
* a scattering or decay process and calculate
* the variables used to generate the
* shower given the particles produced.
* This is needed for the CKKW and POWHEG approaches
*/
//@{
/**
* Given the particles, with a history which we wish to interpret
* as a shower reconstruct the variables used to generate the
* shower for a decay process
*/
virtual bool deconstructDecayJets(HardTreePtr decay,cEvolverPtr,
ShowerInteraction::Type) const=0;
/**
* Given the particles, with a history which we wish to interpret
* as a shower reconstruct the variables used to generate the shower
* for a hard process
*/
virtual bool deconstructHardJets(HardTreePtr hard,cEvolverPtr,
ShowerInteraction::Type) const=0;
//@}
public:
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
private:
/**
- * The static object used to initialize the description of this class.
- * Indicates that this is an concrete class without persistent data.
- */
- static AbstractNoPIOClassDescription<KinematicsReconstructor> initKinematicsReconstructor;
-
- /**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
KinematicsReconstructor & operator=(const KinematicsReconstructor &);
};
}
-#include "ThePEG/Utilities/ClassTraits.h"
-
-namespace ThePEG {
-
-/** @cond TRAITSPECIALIZATIONS */
-
-/** This template specialization informs ThePEG about the
- * base classes of KinematicsReconstructor. */
-template <>
-struct BaseClassTrait<Herwig::KinematicsReconstructor,1> {
- /** Typedef of the first base class of KinematicsReconstructor. */
- typedef Interfaced NthBase;
-};
-
-/** This template specialization informs ThePEG about the name of
- * the KinematicsReconstructor class and the shared object where it is defined. */
-template <>
-struct ClassTraits<Herwig::KinematicsReconstructor>
- : public ClassTraitsBase<Herwig::KinematicsReconstructor> {
- /** Return a platform-independent class name */
- static string className() { return "Herwig::KinematicsReconstructor"; }
- /**
- * The name of a file containing the dynamic library where the class
- * KinematicsReconstructor is implemented. It may also include several, space-separated,
- * libraries if the class KinematicsReconstructor depends on other classes (base classes
- * excepted). In this case the listed libraries will be dynamically
- * linked in the order they are specified.
- */
- static string library() { return "HwShower.so"; }
-};
-
-/** @endcond */
-
-}
-
#endif /* HERWIG_KinematicsReconstructor_H */
diff --git a/Shower/Base/PartnerFinder.cc b/Shower/Base/PartnerFinder.cc
--- a/Shower/Base/PartnerFinder.cc
+++ b/Shower/Base/PartnerFinder.cc
@@ -1,378 +1,379 @@
// -*- C++ -*-
//
// PartnerFinder.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 PartnerFinder class.
//
#include "PartnerFinder.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ShowerParticle.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Interface/Switch.h"
+#include "ThePEG/Utilities/DescribeClass.h"
using namespace Herwig;
+DescribeAbstractClass<PartnerFinder,Interfaced>
+describePartnerFinder ("Herwig::PartnerFinder","HwShower.so");
+
// some useful functions to avoid using #define
namespace {
// return bool if final-state particle
inline bool FS(const tShowerParticlePtr a) {
return a->isFinalState();
}
// return colour line pointer
inline Ptr<ThePEG::ColourLine>::transient_pointer
CL(const ShowerParticleVector::const_iterator & a, unsigned int index=0) {
return (*a)->colourInfo()->colourLines().empty() ? ThePEG::tColinePtr() :
const_ptr_cast<ThePEG::tColinePtr>((*a)->colourInfo()->colourLines()[index]);
}
// return colour line size
inline unsigned int
CLSIZE(const ShowerParticleVector::const_iterator & a) {
return (*a)->colourInfo()->colourLines().size();
}
inline Ptr<ThePEG::ColourLine>::transient_pointer
ACL(const ShowerParticleVector::const_iterator & a, unsigned int index=0) {
return (*a)->colourInfo()->antiColourLines().empty() ? ThePEG::tColinePtr() :
const_ptr_cast<ThePEG::tColinePtr>((*a)->colourInfo()->antiColourLines()[index]);
}
inline unsigned int
ACLSIZE(const ShowerParticleVector::const_iterator & a) {
return (*a)->colourInfo()->antiColourLines().size();
}
}
void PartnerFinder::persistentOutput(PersistentOStream & os) const {
os << _approach << _partnerMethod;
}
void PartnerFinder::persistentInput(PersistentIStream & is, int) {
is >> _approach >> _partnerMethod;
}
-AbstractClassDescription<PartnerFinder> PartnerFinder::initPartnerFinder;
-// Definition of the static class description member.
-
void PartnerFinder::Init() {
static ClassDocumentation<PartnerFinder> documentation
("This class is responsible for finding the partners for each interaction types ",
"and within the evolution scale range specified by the ShowerVariables ",
"then to determine the initial evolution scales for each pair of partners.");
static Parameter<PartnerFinder,int> approach
("Approximation",
"This is a test variable to consider the different approaches of "
"which colour dipoles of a hard process will shower.",
&PartnerFinder::_approach, 0, 1, 0,false,false,false);
static Switch<PartnerFinder,int> interfacePartnerMethod
("PartnerMethod",
"Choice of partner finding method for gluon evolution.",
&PartnerFinder::_partnerMethod, 0, false, false);
static SwitchOption interfacePartnerMethodRandom
(interfacePartnerMethod,
"Random",
"Choose partners of a gluon randomly.",
0);
static SwitchOption interfacePartnerMethodMaximum
(interfacePartnerMethod,
"Maximum",
"Choose partner of gluon with largest angle.",
1);
}
bool PartnerFinder::setInitialEvolutionScales(const ShowerParticleVector &particles,
const bool isDecayCase,
#ifndef NDEBUG
ShowerInteraction::Type type,
#else
ShowerInteraction::Type,
#endif
const bool setPartners) {
assert(type==ShowerInteraction::QCD);
return setInitialQCDEvolutionScales(particles,isDecayCase,setPartners);
}
bool PartnerFinder::setInitialQCDEvolutionScales(const ShowerParticleVector &particles,
const bool isDecayCase,
const bool setPartners) {
// set the partners and the scales
if(setPartners) {
// Loop over particles and consider only coloured particles which don't
// have already their colour partner fixed and that don't have children
// (the latter requirement is relaxed in the case isDecayCase is true).
// Build a map which has as key one of these particles (i.e. a pointer
// to a ShowerParticle object) and as a corresponding value the vector
// of all its possible *normal* candidate colour partners, defined as follows:
// --- have colour, and no children (this is not required in the case
// isDecayCase is true);
// --- if both are initial (incoming) state particles, then the (non-null) colourLine()
// of one of them must match the (non-null) antiColourLine() of the other.
// --- if one is an initial (incoming) state particle and the other is
// a final (outgoing) state particle, then both must have the
// same (non-null) colourLine() or the same (non-null) antiColourLine();
// Notice that this definition exclude the special case of baryon-violating
// processes (as in R-parity Susy), which will show up as particles
// without candidate colour partners, and that we will be treated a part later
// (this means that no modifications of the following loop is needed!)
ShowerParticleVector::const_iterator cit, cjt;
// Define variables needed for angular and radiation line analysis
double angle[2] = { 0.0, 0.0 };
int radiationLine[2] = { 0, 0 };
int ait = 0;
for(cit = particles.begin(); cit != particles.end(); ++cit) {
if(!(*cit)->data().coloured()) continue;
// We now have a coloured particle
tShowerParticleVector partners;
if (_partnerMethod == 1){
// Angular analysis need to be reset for each particle
angle[0] = 0;
angle[1] = 0;
radiationLine[0] = 0;
radiationLine[1] = 0;
ait = 0;
}
for(cjt = particles.begin(); cjt != particles.end(); ++cjt) {
if(!(*cjt)->data().coloured()||cit==cjt) continue;
bool isPartner = false;
if(FS(*cit) != FS(*cjt)){
//loop over all the colours of both particles
for(unsigned int ix=0; ix<CLSIZE(cit); ++ix){
for(unsigned int jx=0; jx<CLSIZE(cjt); ++jx){
if((CL(cit,ix) && CL(cit,ix)==CL(cjt,jx))) {
isPartner = true;
}
}
}
if(!isPartner){
//loop over all the anti-colours of both particles
for(unsigned int ix=0; ix<ACLSIZE(cit); ++ix){
for(unsigned int jx=0; jx<ACLSIZE(cjt); ++jx){
if((ACL(cit,ix) && ACL(cit,ix)==ACL(cjt,jx))) {
isPartner = true;
}
}
}
}
}
else {
//loop over the colours of the first particle and the anti-colours of the other
for(unsigned int ix=0; ix<CLSIZE(cit); ++ix){
for(unsigned int jx=0; jx<ACLSIZE(cjt); ++jx){
if(CL(cit,ix) && CL(cit,ix)==ACL(cjt,jx)) {
isPartner = true;
}
}
}
if(!isPartner){
//loop over the anti-colours of the first particle and the colours of the other
for(unsigned int ix=0; ix<ACLSIZE(cit); ++ix){
for(unsigned int jx=0; jx<CLSIZE(cjt); jx++){
if(ACL(cit,ix) && ACL(cit,ix)==CL(cjt,jx)) {
isPartner = true;
}
}
}
}
}
if(isPartner) {
if (_partnerMethod == 1 && ACLSIZE(cit)<=1&&CLSIZE(cjt)<=1) {
// Find the angle to the potential partner
angle[ait] = (*cit)->momentum().vect().angle((*cjt)->momentum().vect());
// Find out which colour line is connected to the partner
// Colour line has value 1, anti-colour line has value 2
if( CL(cit) == CL(cjt) || CL(cit) == ACL(cjt)) radiationLine[ait] = 1;
if(ACL(cit) == CL(cjt) || ACL(cit) == ACL(cjt)) radiationLine[ait] = 2;
ait++;
}
partners.push_back(*cjt);
}
}
if (partners.empty()) {
// special for RPV
tColinePtr col = CL(cit);
if(FS(*cit)&&col&&col->sourceNeighbours().first) {
tColinePair cpair = col->sourceNeighbours();
for(cjt=particles.begin();cjt!=particles.end();++cjt) {
if(( FS(*cjt) && ( CL(cjt) == cpair.first || CL(cjt) == cpair.second))||
(!FS(*cjt) && (ACL(cjt) == cpair.first || ACL(cjt) == cpair.second ))) {
partners.push_back(*cjt);
}
}
}
else if(col&&col->sinkNeighbours().first) {
tColinePair cpair = col->sinkNeighbours();
for(cjt=particles.begin();cjt!=particles.end();++cjt) {
if(( FS(*cjt) && (ACL(cjt) == cpair.first || ACL(cjt) == cpair.second))||
(!FS(*cjt) && ( CL(cjt) == cpair.first || CL(cjt) == cpair.second))) {
partners.push_back(*cjt);
}
}
}
col = ACL(cit);
if(FS(*cit)&&col&&col->sinkNeighbours().first) {
tColinePair cpair = col->sinkNeighbours();
for(cjt=particles.begin();cjt!=particles.end();++cjt) {
if(( FS(*cjt) && (ACL(cjt) == cpair.first || ACL(cjt) == cpair.second))||
(!FS(*cjt) && ( CL(cjt) == cpair.first || CL(cjt) == cpair.second ))) {
partners.push_back(*cjt);
}
}
}
else if(col&&col->sourceNeighbours().first) {
tColinePair cpair = col->sourceNeighbours();
for(cjt=particles.begin();cjt!=particles.end();++cjt) {
if(( FS(*cjt) && ( CL(cjt) == cpair.first || CL(cjt) == cpair.second))||
(!FS(*cjt) && (ACL(cjt) == cpair.first ||ACL(cjt) == cpair.second))) {
partners.push_back(*cjt);
}
}
}
}
if(partners.empty()) {
throw Exception() << "`Failed to make colour connections in "
<< "PartnerFinder::setQCDInitialEvolutionScales"
<< (**cit)
<< Exception::eventerror;
}
// In the case of more than one candidate colour partners,
// there are now two approaches to choosing the partner. The
// first method is based on two assumptions:
// 1) the choice of which is the colour partner is done
// *randomly* between the available candidates.
// 2) the choice of which is the colour partner is done
// *independently* from each particle: in other words,
// if for a particle "i" its selected colour partner is
// the particle "j", then the colour partner of "j"
// does not have to be necessarily "i".
// The second method always chooses the furthest partner
// for hard gluons and gluinos.
// First make a random choice of partner
int position = UseRandom::irnd(partners.size());
// Set the scale from the random partner
pair<Energy,Energy> pairScales =
calculateInitialEvolutionScales(ShowerPPair(*cit,partners[position]),
isDecayCase);
pair<Energy,Energy> pairScales2;
if (_partnerMethod == 1){
// Override choice of partner
if ((*cit)->perturbative() == 1 && getParticleData((*cit)->id())->iColour()==PDT::Colour8){
// Parton is a hard octet
// Determine largest angle
if (angle[1]>0 && angle[0]<angle[1]) position=1;
else position=0;
}
// Override scale for hard octet
if (position==1){
pairScales = calculateInitialEvolutionScales(ShowerPPair(*cit,partners[1]),
isDecayCase);
if (getParticleData((*cit)->id())->iColour()==PDT::Colour8){
// Set the second scale for hard octets
pairScales2 = calculateInitialEvolutionScales(ShowerPPair(*cit,partners[0]),
isDecayCase);
}
}
else {
pairScales = calculateInitialEvolutionScales(ShowerPPair(*cit,partners[0]),
isDecayCase);
if (getParticleData((*cit)->id())->iColour()==PDT::Colour8){
// Set the second scale for hard octets
pairScales2 = calculateInitialEvolutionScales(ShowerPPair(*cit,partners[1]),
isDecayCase);
}
}
if ((*cit)->perturbative() == 1 && getParticleData((*cit)->id())->iColour()==PDT::Colour8){
// Set radiation lines for hard octets
(*cit)->setRadiationLine(radiationLine[position]);
if( !(*cit)->progenitor() ){
// Set the hard partons to be the progenitors of the shower
(*cit)->setProgenitor(*cit);
// Set the second evolution scale of the progenitor
(*cit)->setEvolutionScale2(pairScales2.first);
}
}
else if ((*cit)->perturbative() == 1 && (getParticleData((*cit)->id())->iColour()==PDT::Colour3 ||
getParticleData((*cit)->id())->iColour()==PDT::Colour3bar)){
// Set radiation lines for hard triplets
if( !(*cit)->progenitor() ){
// Set the hard partons to be the progenitors of the shower
(*cit)->setProgenitor(*cit);
// Set the second evolution scale of the progenitor
(*cit)->setEvolutionScale2(pairScales2.first);
// Set the radiation line
(*cit)->setRadiationLine(0);
}
}
}
switch(_approach) {
case 0: // Totally random (unless chosen above)
(*cit)->setEvolutionScale(pairScales.first);
(*cit)->setPartner(partners[position]);
break;
case 1: // Partner is also set, if it has already been set, pick 50/50
if(!(*cit)->partner() || UseRandom::rndbool()) {
(*cit)->setEvolutionScale(pairScales.first);
(*cit)->setPartner(partners[position]);
}
if(!partners[position]->partner() || UseRandom::rndbool()) {
partners[position]->setEvolutionScale(pairScales.second);
partners[position]->setPartner(*cit);
}
break;
default:
throw Exception() << "Invalid approach for setting colour partner in"
<< " PartnerFinder::setQCDInitialEvolutionScale()"
<< Exception::abortnow;
}
}
}
// partners all ready set only do the scales
else {
for(ShowerParticleVector::const_iterator cit = particles.begin();
cit != particles.end(); ++cit) {
if(!(**cit).dataPtr()->coloured()) continue;
tShowerParticlePtr partner = (**cit).partner();
pair<Energy,Energy> pairScales =
calculateInitialEvolutionScales(ShowerPPair(*cit,partner),
isDecayCase);
(*cit)->setEvolutionScale(pairScales.first);
}
}
return true;
}
pair<Energy,Energy> PartnerFinder::
calculateInitialEvolutionScales(const ShowerPPair &particlePair,
const bool isDecayCase) {
bool FS1=FS(particlePair.first),FS2= FS(particlePair.second);
if(FS1 && FS2)
return calculateFinalFinalScales(particlePair);
else if(FS1 && !FS2) {
ShowerPPair a(particlePair.second, particlePair.first);
pair<Energy,Energy> rval = calculateInitialFinalScales(a,isDecayCase);
return pair<Energy,Energy>(rval.second,rval.first);
}
else if(!FS1 &&FS2)
return calculateInitialFinalScales(particlePair,isDecayCase);
else
return calculateInitialInitialScales(particlePair);
}
diff --git a/Shower/Base/PartnerFinder.h b/Shower/Base/PartnerFinder.h
--- a/Shower/Base/PartnerFinder.h
+++ b/Shower/Base/PartnerFinder.h
@@ -1,228 +1,187 @@
// -*- C++ -*-
//
// PartnerFinder.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_PartnerFinder_H
#define HERWIG_PartnerFinder_H
//
// This is the declaration of the PartnerFinder class.
//
#include "Herwig++/Shower/ShowerConfig.h"
#include "ThePEG/Interface/Interfaced.h"
#include "Evolver.fh"
#include "PartnerFinder.fh"
namespace Herwig {
using namespace ThePEG;
/**
* typedef of a pair of particle for calculating the evolution scales
*/
typedef pair<tShowerParticlePtr,tShowerParticlePtr> ShowerPPair;
/** \ingroup Shower
*
* This class is responsible of two related tasks:
* - it finds the partners
* - for each pair of partners (and interaction therefore)
* it sets the initial evolution scales of both of them.
*
* In general the finding of the partners is performed by this class but
* the calculation of the initial evolution scales should be implemented
* for different shower evolution models in classes inheriting from this one.
* Notice that a given particle has, in general, a different partner
* for each different interaction; however, given a partner, its
* initial evolution scale, Q, is purely a kinematical relationship
* between the pair, without dependence on the dynamics (i.e. type of interaction).
*
* @see \ref PartnerFinderInterfaces "The interfaces"
* defined for PartnerFinder.
*/
class PartnerFinder: public Interfaced {
public:
/**
* The default constructor.
*/
PartnerFinder() : _approach(0), _partnerMethod(0) {}
/**
* Given in input a collection of particles (ShowerParticle objects),
* each of these methods set the initial evolution scales of those particles,
* between the ones given in input, that do not have yet their
* evolution scale set.
* The input collection of particles can be either the full collection of
* showering particles (kept in the main class ShowerHandler,
* in the case isDecayCase is false, or simply, in the case isDecayCase
* is true, the decaying particle and its decay products.
* The methods returns true, unless something wrong (inconsistencies,
* or undefined values) happens.
*
* These methods are virtual but in most cases inheriting classes should not
* need to overide them as they simply find the relevant partner and call
* one of the calculateScale members to calculate the scale.
*/
//@{
/**
* Set the initial scales
* @param particles The particles to be considered
* @param isDecayCase Whether or not this is a decay
* @param setPartners Whether to set the colour partners or just the scales
*/
virtual bool setInitialEvolutionScales(const ShowerParticleVector &particles,
const bool isDecayCase,
ShowerInteraction::Type,
const bool setPartners=true);
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/**
* Members to set the scales for different interactions
*/
//@{
/**
* Set initial scales for a QCD interaction
*/
virtual bool setInitialQCDEvolutionScales(const ShowerParticleVector &particles,
const bool isDecayCase,
const bool setPartners=true);
//@}
/**
* Given a pair of particles, supposedly partners w.r.t. an interaction,
* this method returns their initial evolution scales as a pair.
* If something wrong happens, it returns the null (ZERO,ZERO) pair.
* This method is used by the above setXXXInitialEvolutionScales
* methods.
* These methods must be overiden in inheriting classes
*/
//@{
/**
* General method to calculate the initial evolution scales
*/
virtual pair<Energy,Energy> calculateInitialEvolutionScales(const ShowerPPair &,
const bool isDecayCase);
/**
* Calculate the initial evolution scales for two final-state particles
*/
virtual pair<Energy,Energy> calculateFinalFinalScales(const ShowerPPair &)=0;
/**
* Calculate the initial evolution scales for two initial-state particles
*/
virtual pair<Energy,Energy> calculateInitialInitialScales(const ShowerPPair &)=0;
/**
* Calculate the initial evolution scales for one initial
* and one final-state particles
*/
virtual pair<Energy,Energy> calculateInitialFinalScales(const ShowerPPair &,
const bool isDecayCase)=0;
//@}
/**
* The approach for the colour partners
*/
bool approach() const {return _approach;}
private:
/**
- * The static object used to initialize the description of this class.
- * Indicates that this is a concrete class with persistent data.
- */
- static AbstractClassDescription<PartnerFinder> initPartnerFinder;
-
- /**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
PartnerFinder & operator=(const PartnerFinder &);
private:
/**
* Approach to use for setting the colour partners in the random approach
*/
int _approach;
/**
* Method for choosing colour partner
*/
int _partnerMethod;
};
}
-#include "ThePEG/Utilities/ClassTraits.h"
-
-namespace ThePEG {
-
-/** @cond TRAITSPECIALIZATIONS */
-
-/** This template specialization informs ThePEG about the
- * base classes of PartnerFinder. */
-template <>
-struct BaseClassTrait<Herwig::PartnerFinder,1> {
- /** Typedef of the first base class of PartnerFinder. */
- typedef Interfaced NthBase;
-};
-
-/** This template specialization informs ThePEG about the name of
- * the PartnerFinder class and the shared object where it is defined. */
-template <>
-struct ClassTraits<Herwig::PartnerFinder>
- : public ClassTraitsBase<Herwig::PartnerFinder> {
- /** Return a platform-independent class name */
- static string className() { return "Herwig::PartnerFinder"; }
- /**
- * The name of a file containing the dynamic library where the class
- * PartnerFinder is implemented. It may also include several, space-separated,
- * libraries if the class PartnerFinder depends on other classes (base classes
- * excepted). In this case the listed libraries will be dynamically
- * linked in the order they are specified.
- */
- static string library() { return "HwShower.so"; }
-};
-
-/** @endcond */
-
-}
-
#endif /* HERWIG_PartnerFinder_H */
diff --git a/Shower/Base/ShowerModel.cc b/Shower/Base/ShowerModel.cc
--- a/Shower/Base/ShowerModel.cc
+++ b/Shower/Base/ShowerModel.cc
@@ -1,65 +1,66 @@
// -*- C++ -*-
//
// ShowerModel.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 ShowerModel class.
//
#include "ShowerModel.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/RefVector.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "KinematicsReconstructor.h"
#include "PartnerFinder.h"
#include "Evolver.h"
#include "SudakovFormFactor.h"
+#include "ThePEG/Utilities/DescribeClass.h"
using namespace Herwig;
+DescribeAbstractClass<ShowerModel,Interfaced>
+describeShowerModel ("Herwig::ShowerModel","HwShower.so");
+
void ShowerModel::persistentOutput(PersistentOStream & os) const {
os << _reconstructor << _partnerfinder << _sudakovs;
}
void ShowerModel::persistentInput(PersistentIStream & is, int) {
is >> _reconstructor >> _partnerfinder >> _sudakovs;
}
void ShowerModel::doinit() {
Interfaced::doinit();
checkConsistency();
}
-AbstractClassDescription<ShowerModel> ShowerModel::initShowerModel;
-// Definition of the static class description member.
-
void ShowerModel::Init() {
static ClassDocumentation<ShowerModel> documentation
("The ShowerModel class contains the references for the classes which"
" are specific to the shower evolution scheme.");
static Reference<ShowerModel,KinematicsReconstructor> interfaceKinematicsReconstructor
("KinematicsReconstructor",
"Reference to the KinematicsReconstructor object",
&ShowerModel::_reconstructor, false, false, true, false, false);
static Reference<ShowerModel,PartnerFinder> interfacePartnerFinder
("PartnerFinder",
"Reference to the PartnerFinder object",
&ShowerModel::_partnerfinder, false, false, true, false, false);
static RefVector<ShowerModel,SudakovFormFactor> interfaceSudakovFormFactors
("SudakovFormFactors",
"Vector of references to the SudakovFormFactor objects",
&ShowerModel::_sudakovs, -1, false, false, true, false, false);
}
diff --git a/Shower/Base/ShowerModel.h b/Shower/Base/ShowerModel.h
--- a/Shower/Base/ShowerModel.h
+++ b/Shower/Base/ShowerModel.h
@@ -1,189 +1,148 @@
// -*- C++ -*-
//
// ShowerModel.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_ShowerModel_H
#define HERWIG_ShowerModel_H
//
// This is the declaration of the ShowerModel class.
//
#include "ThePEG/Interface/Interfaced.h"
#include "KinematicsReconstructor.fh"
#include "PartnerFinder.fh"
#include "SudakovFormFactor.fh"
#include "ShowerModel.fh"
namespace Herwig {
using namespace ThePEG;
/** \ingroup Shower
*
* The ShowerModel class is a container for all the objects needed to implement a
* specific model of the shower evolution, as opposed to those which are independent
* of the evolution.
*
* In general there are four types of object
* - The KinematicsReconstructor object which is responsible for reconstruction
* of the shower kinematics after the evolution.
* - The PartnerFinder which is responsible for finding the partner and setting the
* initial evolution scale
* - A vector of SudakovFormFactor objects which will usually all be instances
* of a class implementing the SudakovFormFactor for a specific model with
* different splitting functions for different branchings
*
* For each model the checkConsistency member must be implemented to check that
* the correct objects for the model are used.
*
* @see \ref ShowerModelInterfaces "The interfaces"
* defined for ShowerModel.
*/
class ShowerModel: public Interfaced {
public:
/**
* Access methods to access the objects
*/
//@{
/**
* Access to the KinematicsReconstructor object
*/
tKinematicsReconstructorPtr kinematicsReconstructor() const { return _reconstructor; }
/**
* Access to the PartnerFinder object
*/
tPartnerFinderPtr partnerFinder() const { return _partnerfinder; }
/**
* Access to the SudakovFormFactor objects
*/
const vector<SudakovPtr> & sudakovFormFactors() const { return _sudakovs; }
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/**
* The checkConsitency member which must be implemented in classes
* inheriting from this one.
*/
virtual void checkConsistency() =0;
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit();
//@}
private:
/**
- * The static object used to initialize the description of this class.
- * Indicates that this is an abstract class with persistent data.
- */
- static AbstractClassDescription<ShowerModel> initShowerModel;
-
- /**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
ShowerModel & operator=(const ShowerModel &);
private:
/**
* Pointer to the various objects
*/
//@{
/**
* Pointer to the KinematicsReconstructor object
*/
KinematicsReconstructorPtr _reconstructor;
/**
* Pointer to the PartnerFinder object
*/
PartnerFinderPtr _partnerfinder;
/**
* Pointers to the SudakovFormFactor objects
*/
vector<SudakovPtr> _sudakovs;
//@}
};
}
-#include "ThePEG/Utilities/ClassTraits.h"
-
-namespace ThePEG {
-
-/** @cond TRAITSPECIALIZATIONS */
-
-/** This template specialization informs ThePEG about the
- * base classes of ShowerModel. */
-template <>
-struct BaseClassTrait<Herwig::ShowerModel,1> {
- /** Typedef of the first base class of ShowerModel. */
- typedef Interfaced NthBase;
-};
-
-/** This template specialization informs ThePEG about the name of
- * the ShowerModel class and the shared object where it is defined. */
-template <>
-struct ClassTraits<Herwig::ShowerModel>
- : public ClassTraitsBase<Herwig::ShowerModel> {
- /** Return a platform-independent class name */
- static string className() { return "Herwig::ShowerModel"; }
- /**
- * The name of a file containing the dynamic library where the class
- * ShowerModel is implemented. It may also include several, space-separated,
- * libraries if the class ShowerModel depends on other classes (base classes
- * excepted). In this case the listed libraries will be dynamically
- * linked in the order they are specified.
- */
- static string library() { return "HwShower.so"; }
-};
-
-/** @endcond */
-
-}
-
#endif /* HERWIG_ShowerModel_H */
diff --git a/Shower/Base/ShowerVeto.cc b/Shower/Base/ShowerVeto.cc
--- a/Shower/Base/ShowerVeto.cc
+++ b/Shower/Base/ShowerVeto.cc
@@ -1,40 +1,41 @@
// -*- C++ -*-
//
// ShowerVeto.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 ShowerVeto class.
//
#include "ShowerVeto.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Utilities/EnumIO.h"
+#include "ThePEG/Utilities/DescribeClass.h"
using namespace Herwig;
+DescribeAbstractClass<ShowerVeto,Interfaced>
+describeShowerVeto ("Herwig::ShowerVeto","HwShower.so");
+
void ShowerVeto::persistentOutput(PersistentOStream & os) const {
os << oenum(_vetoType);
}
void ShowerVeto::persistentInput(PersistentIStream & is, int) {
is >> ienum(_vetoType);
}
-AbstractClassDescription<ShowerVeto> ShowerVeto::initShowerVeto;
-// Definition of the static class description member.
-
void ShowerVeto::Init() {
static ClassDocumentation<ShowerVeto> documentation
("ShowerVeto is the base class for all vetoes on showering other than "
"from matrix element corrections.");
}
diff --git a/Shower/Base/ShowerVeto.h b/Shower/Base/ShowerVeto.h
--- a/Shower/Base/ShowerVeto.h
+++ b/Shower/Base/ShowerVeto.h
@@ -1,178 +1,137 @@
// -*- C++ -*-
//
// ShowerVeto.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_ShowerVeto_H
#define HERWIG_ShowerVeto_H
//
// This is the declaration of the ShowerVeto class.
//
#include "ThePEG/Interface/Interfaced.h"
#include "ShowerVeto.fh"
#include "Herwig++/Shower/SplittingFunctions/SplittingGenerator.h"
#include "Herwig++/Shower/ShowerConfig.h"
#include "ShowerTree.fh"
#include "ShowerProgenitor.fh"
namespace Herwig {
using namespace ThePEG;
/**\ingroup Shower
* Exception class for vetoing a showering
*/
struct VetoShower { };
/**\ingroup Shower
* ShowerVeto is a general interface for performing
* vetoes during showering.
*
* @see \ref ShowerVetoInterfaces "The interfaces"
* defined for ShowerVeto.
*/
class ShowerVeto: public Interfaced {
public:
/**
* Define types of ShowerVetoes
*/
enum ShowerVetoType {
/**
* Throw away emission, if veto encountered. Set the scale to
* the scale of vetoed emission.
*/
Emission = 1,
/**
* Throw away showering
*/
Shower,
/**
* Throw away event
*/
Event
};
public:
/**
* Constructor giving the behaviour of this veto
*/
ShowerVeto (ShowerVetoType vetoType) : _vetoType(vetoType) {}
/**
* Return the type of this veto
*/
ShowerVetoType vetoType () const {return _vetoType;}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
public:
/**
* Return true, if the selected emission off the given
* particle and progenitor is vetoed.
*/
virtual bool vetoTimeLike (tcShowerProgenitorPtr, tcShowerParticlePtr,
const Branching&) = 0;
/**
* Return true, if the selected emission off the given
* particle and progenitor is vetoed.
*/
virtual bool vetoSpaceLike (tcShowerProgenitorPtr, tcShowerParticlePtr,
const Branching&) = 0;
private:
/**
- * The static object used to initialize the description of this class.
- * Indicates that this is an abstract class with persistent data.
- */
- static AbstractClassDescription<ShowerVeto> initShowerVeto;
-
- /**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
ShowerVeto & operator=(const ShowerVeto &);
private:
/**
* The type of this veto.
*/
ShowerVetoType _vetoType;
};
}
-#include "ThePEG/Utilities/ClassTraits.h"
-
-namespace ThePEG {
-
-/** @cond TRAITSPECIALIZATIONS */
-
-/** This template specialization informs ThePEG about the
- * base classes of ShowerVeto. */
-template <>
-struct BaseClassTrait<Herwig::ShowerVeto,1> {
- /** Typedef of the first base class of ShowerVeto. */
- typedef Interfaced NthBase;
-};
-
-/** This template specialization informs ThePEG about the name of
- * the ShowerVeto class and the shared object where it is defined. */
-template <>
-struct ClassTraits<Herwig::ShowerVeto>
- : public ClassTraitsBase<Herwig::ShowerVeto> {
- /** Return a platform-independent class name */
- static string className() { return "Herwig::ShowerVeto"; }
- /**
- * The name of a file containing the dynamic library where the class
- * ShowerVeto is implemented. It may also include several, space-separated,
- * libraries if the class ShowerVeto depends on other classes (base classes
- * excepted). In this case the listed libraries will be dynamically
- * linked in the order they are specified.
- */
- static string library() { return "HwShower.so"; }
-};
-
-/** @endcond */
-
-}
-
#endif /* HERWIG_ShowerVeto_H */
diff --git a/Shower/Base/SudakovFormFactor.cc b/Shower/Base/SudakovFormFactor.cc
--- a/Shower/Base/SudakovFormFactor.cc
+++ b/Shower/Base/SudakovFormFactor.cc
@@ -1,309 +1,310 @@
// -*- C++ -*-
//
// SudakovFormFactor.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 SudakovFormFactor class.
//
#include "SudakovFormFactor.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Parameter.h"
#include "ShowerKinematics.h"
+#include "ThePEG/Utilities/DescribeClass.h"
using namespace Herwig;
+DescribeAbstractClass<SudakovFormFactor,Interfaced>
+describeSudakovFormFactor ("Herwig::SudakovFormFactor","");
+
void SudakovFormFactor::persistentOutput(PersistentOStream & os) const {
os << splittingFn_ << alpha_ << pdfmax_ << particles_ << pdffactor_
<< a_ << b_ << ounit(c_,GeV) << ounit(kinCutoffScale_,GeV) << cutOffOption_
<< ounit(vgcut_,GeV) << ounit(vqcut_,GeV)
<< ounit(pTmin_,GeV) << ounit(pT2min_,GeV2);
}
void SudakovFormFactor::persistentInput(PersistentIStream & is, int) {
is >> splittingFn_ >> alpha_ >> pdfmax_ >> particles_ >> pdffactor_
>> a_ >> b_ >> iunit(c_,GeV) >> iunit(kinCutoffScale_,GeV) >> cutOffOption_
>> iunit(vgcut_,GeV) >> iunit(vqcut_,GeV)
>> iunit(pTmin_,GeV) >> iunit(pT2min_,GeV2);
}
-AbstractClassDescription<SudakovFormFactor> SudakovFormFactor::initSudakovFormFactor;
-// Definition of the static class description member.
-
void SudakovFormFactor::Init() {
static ClassDocumentation<SudakovFormFactor> documentation
("The SudakovFormFactor class is the base class for the implementation of Sudakov"
" form factors in Herwig++");
static Reference<SudakovFormFactor,SplittingFunction>
interfaceSplittingFunction("SplittingFunction",
"A reference to the SplittingFunction object",
&Herwig::SudakovFormFactor::splittingFn_,
false, false, true, false);
static Reference<SudakovFormFactor,ShowerAlpha>
interfaceAlpha("Alpha",
"A reference to the Alpha object",
&Herwig::SudakovFormFactor::alpha_,
false, false, true, false);
static Parameter<SudakovFormFactor,double> interfacePDFmax
("PDFmax",
"Maximum value of PDF weight. ",
&SudakovFormFactor::pdfmax_, 35.0, 1.0, 100000.0,
false, false, Interface::limited);
static Switch<SudakovFormFactor,unsigned int> interfacePDFFactor
("PDFFactor",
"Include additional factors in the overestimate for the PDFs",
&SudakovFormFactor::pdffactor_, 0, false, false);
static SwitchOption interfacePDFFactorOff
(interfacePDFFactor,
"Off",
"Don't include any factors",
0);
static SwitchOption interfacePDFFactorOverZ
(interfacePDFFactor,
"OverZ",
"Include an additional factor of 1/z",
1);
static SwitchOption interfacePDFFactorOverOneMinusZ
(interfacePDFFactor,
"OverOneMinusZ",
"Include an additional factor of 1/(1-z)",
2);
static SwitchOption interfacePDFFactorOverZOneMinusZ
(interfacePDFFactor,
"OverZOneMinusZ",
"Include an additional factor of 1/z/(1-z)",
3);
static Switch<SudakovFormFactor,unsigned int> interfaceCutOffOption
("CutOffOption",
"The type of cut-off to use to end the shower",
&SudakovFormFactor::cutOffOption_, 0, false, false);
static SwitchOption interfaceCutOffOptionDefault
(interfaceCutOffOption,
"Default",
"Use the standard Herwig++ cut-off on virtualities with the minimum"
" virtuality depending on the mass of the branching particle",
0);
static SwitchOption interfaceCutOffOptionFORTRAN
(interfaceCutOffOption,
"FORTRAN",
"Use a FORTRAN-like cut-off on virtualities",
1);
static SwitchOption interfaceCutOffOptionpT
(interfaceCutOffOption,
"pT",
"Use a cut on the minimum allowed pT",
2);
static Parameter<SudakovFormFactor,double> interfaceaParameter
("aParameter",
"The a parameter for the kinematic cut-off",
&SudakovFormFactor::a_, 0.3, -10.0, 10.0,
false, false, Interface::limited);
static Parameter<SudakovFormFactor,double> interfacebParameter
("bParameter",
"The b parameter for the kinematic cut-off",
&SudakovFormFactor::b_, 2.3, -10.0, 10.0,
false, false, Interface::limited);
static Parameter<SudakovFormFactor,Energy> interfacecParameter
("cParameter",
"The c parameter for the kinematic cut-off",
&SudakovFormFactor::c_, GeV, 0.3*GeV, 0.1*GeV, 10.0*GeV,
false, false, Interface::limited);
static Parameter<SudakovFormFactor,Energy>
interfaceKinScale ("cutoffKinScale",
"kinematic cutoff scale for the parton shower phase"
" space (unit [GeV])",
&SudakovFormFactor::kinCutoffScale_, GeV,
2.3*GeV, 0.001*GeV, 10.0*GeV,false,false,false);
static Parameter<SudakovFormFactor,Energy> interfaceGluonVirtualityCut
("GluonVirtualityCut",
"For the FORTRAN cut-off option the minimum virtuality of the gluon",
&SudakovFormFactor::vgcut_, GeV, 0.85*GeV, 0.1*GeV, 10.0*GeV,
false, false, Interface::limited);
static Parameter<SudakovFormFactor,Energy> interfaceQuarkVirtualityCut
("QuarkVirtualityCut",
"For the FORTRAN cut-off option the minimum virtuality added to"
" the mass for particles other than the gluon",
&SudakovFormFactor::vqcut_, GeV, 0.85*GeV, 0.1*GeV, 10.0*GeV,
false, false, Interface::limited);
static Parameter<SudakovFormFactor,Energy> interfacepTmin
("pTmin",
"The minimum pT if using a cut-off on the pT",
&SudakovFormFactor::pTmin_, GeV, 1.0*GeV, ZERO, 10.0*GeV,
false, false, Interface::limited);
}
bool SudakovFormFactor::
PDFVeto(const Energy2 t, const double x,
const tcPDPtr parton0, const tcPDPtr parton1,
Ptr<BeamParticleData>::transient_const_pointer beam) const {
assert(pdf_);
Energy2 theScale = t;
if (theScale < sqr(freeze_)) theScale = sqr(freeze_);
double newpdf(0.0), oldpdf(0.0);
//different treatment of MPI ISR is done via CascadeHandler::resetPDFs()
newpdf=pdf_->xfx(beam,parton0,theScale,x/z());
oldpdf=pdf_->xfx(beam,parton1,theScale,x);
if(newpdf<=0.) return true;
if(oldpdf<=0.) return false;
double ratio = newpdf/oldpdf;
double maxpdf(pdfmax_);
switch (pdffactor_) {
case 1:
maxpdf /= z();
break;
case 2:
maxpdf /= 1.-z();
break;
case 3:
maxpdf /= (z()*(1.-z()));
break;
}
// ratio / PDFMax must be a probability <= 1.0
if (ratio > maxpdf) {
generator()->log() << "PDFVeto warning: Ratio > " << name()
<< ":PDFmax (by a factor of "
<< ratio/maxpdf <<") for "
<< parton0->PDGName() << " to "
<< parton1->PDGName() << "\n";
}
return ratio < UseRandom::rnd()*maxpdf;
}
void SudakovFormFactor::addSplitting(const IdList & in) {
bool add=true;
for(unsigned int ix=0;ix<particles_.size();++ix) {
if(particles_[ix].size()==in.size()) {
bool match=true;
for(unsigned int iy=0;iy<in.size();++iy) {
if(particles_[ix][iy]!=in[iy]) {
match=false;
break;
}
}
if(match) {
add=false;
break;
}
}
}
if(add) particles_.push_back(in);
}
void SudakovFormFactor::removeSplitting(const IdList & in) {
for(vector<IdList>::iterator it=particles_.begin();
it!=particles_.end();++it) {
if(it->size()==in.size()) {
bool match=true;
for(unsigned int iy=0;iy<in.size();++iy) {
if((*it)[iy]!=in[iy]) {
match=false;
break;
}
}
if(match) {
vector<IdList>::iterator itemp=it;
--itemp;
particles_.erase(it);
it = itemp;
}
}
}
}
Energy2 SudakovFormFactor::guesst(Energy2 t1,unsigned int iopt,
const IdList &ids,
double enhance,bool ident) const {
unsigned int pdfopt = iopt!=1 ? 0 : pdffactor_;
double c =
1./((splittingFn_->integOverP(zlimits_.second,ids,pdfopt) -
splittingFn_->integOverP(zlimits_.first ,ids,pdfopt))*
alpha_->overestimateValue()/Constants::twopi*enhance);
assert(iopt<=2);
if(iopt==1) {
c/=pdfmax_;
if(ident) c*=0.5;
}
else if(iopt==2) c*=-1.;
if(splittingFn_->interactionOrder()==1) {
return t1*pow(UseRandom::rnd(),c);
}
else {
assert(false && "Units are dubious here.");
int nm(splittingFn()->interactionOrder()-1);
c/=Math::powi(alpha_->overestimateValue()/Constants::twopi,nm);
return t1 / pow (1. - nm*c*log(UseRandom::rnd())
* Math::powi(t1*UnitRemoval::InvE2,nm)
,1./double(nm));
}
}
double SudakovFormFactor::guessz (unsigned int iopt, const IdList &ids) const {
unsigned int pdfopt = iopt!=1 ? 0 : pdffactor_;
double lower = splittingFn_->integOverP(zlimits_.first,ids,pdfopt);
return splittingFn_->invIntegOverP
(lower + UseRandom::rnd()*(splittingFn_->integOverP(zlimits_.second,ids,pdfopt) -
lower),ids,pdfopt);
}
void SudakovFormFactor::doinit() {
Interfaced::doinit();
pT2min_ = cutOffOption()==2 ? sqr(pTmin_) : ZERO;
}
vector<Energy> SudakovFormFactor::virtualMasses(const IdList & ids) {
vector<Energy> output;
if(cutOffOption() == 0) {
for(unsigned int ix=0;ix<ids.size();++ix)
output.push_back(getParticleData(ids[ix])->mass());
Energy kinCutoff=
kinematicCutOff(kinScale(),*std::max_element(output.begin(),output.end()));
for(unsigned int ix=0;ix<output.size();++ix)
output[ix]=max(kinCutoff,output[ix]);
}
else if(cutOffOption() == 1) {
for(unsigned int ix=0;ix<ids.size();++ix) {
output.push_back(getParticleData(ids[ix])->mass());
output.back() += ids[ix]==ParticleID::g ? vgCut() : vqCut();
}
}
else if(cutOffOption() == 2) {
for(unsigned int ix=0;ix<ids.size();++ix)
output.push_back(getParticleData(ids[ix])->mass());
}
else {
throw Exception() << "Unknown option for the cut-off"
<< " in SudakovFormFactor::virtualMasses()"
<< Exception::runerror;
}
return output;
}
diff --git a/Shower/Base/SudakovFormFactor.h b/Shower/Base/SudakovFormFactor.h
--- a/Shower/Base/SudakovFormFactor.h
+++ b/Shower/Base/SudakovFormFactor.h
@@ -1,684 +1,651 @@
// -*- C++ -*-
//
// SudakovFormFactor.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_SudakovFormFactor_H
#define HERWIG_SudakovFormFactor_H
//
// This is the declaration of the SudakovFormFactor class.
//
#include "ThePEG/Interface/Interfaced.h"
#include "Herwig++/Shower/SplittingFunctions/SplittingFunction.h"
#include "Herwig++/Shower/Couplings/ShowerAlpha.h"
#include "Herwig++/Shower/SplittingFunctions/SplittingGenerator.fh"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/PDF/BeamParticleData.h"
#include <cassert>
#include "ShowerKinematics.fh"
#include "SudakovFormFactor.fh"
namespace Herwig {
using namespace ThePEG;
/**
* A typedef for the BeamParticleData
*/
typedef Ptr<BeamParticleData>::transient_const_pointer tcBeamPtr;
/** \ingroup Shower
*
* This is the definition of the Sudakov form factor class. In general this
* is the base class for the implementation of Sudakov form factors in Herwig++.
* The methods generateNextTimeBranching(), generateNextDecayBranching() and
* generateNextSpaceBranching need to be implemented in classes inheriting from this
* one.
*
* In addition a number of methods are implemented to assist with the calculation
* of the form factor using the veto algorithm in classes inheriting from this one.
*
* In general the Sudakov form-factor, for final-state radiation, is given
* by
* \f[\Delta_{ba}(\tilde{q}_{i+1},\tilde{q}_i)=
* \exp\left\{
* -\int^{\tilde{q}^2_i}_{\tilde{q}^2_{i+1}}
* \frac{{\rm d}\tilde{q}^2}{\tilde{q}^2}
* \int\frac{\alpha_S(z,\tilde{q})}{2\pi}
* P_{ba}(z,\tilde{q})\Theta(p_T)
* \right\}.
* \f]
* We can solve this to obtain the next value of the scale \f$\tilde{q}_{i+1}\f$
* given the previous value \f$\tilde{q}_i\f$
* in the following way. First we obtain a simplified form of the integrand
* which is greater than or equal to the true integrand for all values of
* \f$\tilde{q}\f$.
*
* In practice it is easiest to obtain this over estimate in pieces. The ShowerAlpha
* object contains an over estimate for \f$\alpha_S\f$, the splitting function
* contains both an over estimate of the spltting function and its integral
* which is needed to compute the over estimate of the \f$\tilde{q}\f$ integrand,
* together with an over estimate of the limit of the \f$z\f$ integral.
*
* This gives an overestimate of the integrand
* \f[g(\tilde{q}^2) = \frac{c}{\tilde{q}^2}, \f]
* where because the over estimates are chosen to be independent of \f$\tilde{q}\f$ the
* parameter
* \f[c = \frac{\alpha_{\rm over}}{2\pi}\int^{z_1}_{z_0}P_{\rm over}(z),\f]
* is a constant independent of \f$\tilde{q}\f$.
*
* The guesst() member can then be used to generate generate the value of
* \f$\tilde{q}^2\f$ according to this result. This is done by solving the Sudakov
* form factor, with the over estimates, is equal to a random number
* \f$r\f$ in the interval \f$[0,1]\f$. This gives
* \f[\tilde{q}^2_{i+1}=G^{-1}\left[G(\tilde{q}^2_i)+\ln r\right],\f]
* where \f$G(\tilde{q}^2)=c\ln(\tilde{q}^2)\f$ is the infinite integral
* of \f$g(\tilde{q}^2)\f$ and \f$G^{-1}(x)=\exp\left(\frac{x}c\right)\f$
* is its inverse.
* It this case we therefore obtain
* \f[\tilde{q}^2_{i+1}=\tilde{q}^2_ir^{\frac1c}.\f]
* The value of \f$z\f$ can then be calculated in a similar way
* \f[z = I^{-1}\left[I(z_0)+r\left(I(z_1)-I(z_0)\right)\right],\f]
* using the guessz() member,
* where \f$I=\int P(z){\rm d}z\f$ and \f$I^{-1}\f$ is its inverse.
*
* The veto algorithm then uses rejection using the ratio of the
* true value to the overestimated one to obtain the original distribution.
* This is accomplished using the
* - alphaSVeto() member for the \f$\alpha_S\f$ veto
* - SplittingFnVeto() member for the veto on the value of the splitting function.
* in general there must also be a chech that the emission is in the allowed
* phase space but this is left to the inheriting classes as it will depend
* on the ordering variable.
*
* The Sudakov form factor for the initial-scale shower is different because
* it must include the PDF which guides the backward evolution.
* It is given by
* \f[\Delta_{ba}(\tilde{q}_{i+1},\tilde{q}_i)=
* \exp\left\{
* -\int^{\tilde{q}^2_i}_{\tilde{q}^2_{i+1}}
* \frac{{\rm d}\tilde{q}^2}{\tilde{q}^2}
* \int\frac{\alpha_S(z,\tilde{q})}{2\pi}
* P_{ba}(z,\tilde{q})\frac{x'f_a(\frac{x}z,\tilde{q}^2)}{xf_b(x,\tilde{q^2})}
* \right\},
* \f]
* where \f$x\f$ is the fraction of the beam momentum the parton \f$b\f$ had before
* the backward evolution.
* This can be solve in the same way as for the final-state branching but the constant
* becomes
* \f[c = \frac{\alpha_{\rm over}}{2\pi}\int^{z_1}_{z_0}P_{\rm over}(z)PDF_{\rm max},\f]
* where
* \f[PDF_{\rm max}=\max\frac{x'f_a(\frac{x}z,\tilde{q}^2)}{xf_b(x,\tilde{q^2})},\f]
* which can be set using an interface.
* In addition the PDFVeto() member then is needed to implement the relevant veto.
*
* @see SplittingGenerator
* @see SplittingFunction
* @see ShowerAlpha
* @see \ref SudakovFormFactorInterfaces "The interfaces"
* defined for SudakovFormFactor.
*/
class SudakovFormFactor: public Interfaced {
/**
* The SplittingGenerator is a friend to insert the particles in the
* branchings at initialisation
*/
friend class SplittingGenerator;
public:
/**
* The default constructor.
*/
SudakovFormFactor() : pdfmax_(35.0), pdffactor_(0),
cutOffOption_(0), a_(0.3), b_(2.3), c_(0.3*GeV),
kinCutoffScale_( 2.3*GeV ), vgcut_(0.85*GeV),
vqcut_(0.85*GeV), pTmin_(1.*GeV), pT2min_(ZERO),
z_( 0.0 ),phi_(0.0), pT_() {}
/**
* Members to generate the scale of the next branching
*/
//@{
/**
* Return the scale of the next time-like branching. If there is no
* branching then it returns ZERO.
* @param startingScale starting scale for the evolution
* @param ids The PDG codes of the particles in the splitting
* @param cc Whether this is the charge conjugate of the branching
* @param enhance The radiation enhancement factor
* defined.
*/
virtual ShoKinPtr generateNextTimeBranching(const Energy startingScale,
const IdList &ids,const bool cc,
double enhance)=0;
/**
* Return the scale of the next space-like decay branching. If there is no
* branching then it returns ZERO.
* @param startingScale starting scale for the evolution
* @param stoppingScale stopping scale for the evolution
* @param minmass The minimum mass allowed for the spake-like particle.
* @param ids The PDG codes of the particles in the splitting
* @param cc Whether this is the charge conjugate of the branching
* defined.
* @param enhance The radiation enhancement factor
*/
virtual ShoKinPtr generateNextDecayBranching(const Energy startingScale,
const Energy stoppingScale,
const Energy minmass,
const IdList &ids,
const bool cc,
double enhance)=0;
/**
* Return the scale of the next space-like branching. If there is no
* branching then it returns ZERO.
* @param startingScale starting scale for the evolution
* @param ids The PDG codes of the particles in the splitting
* @param x The fraction of the beam momentum
* @param cc Whether this is the charge conjugate of the branching
* defined.
* @param beam The beam particle
* @param enhance The radiation enhancement factor
*/
virtual ShoKinPtr generateNextSpaceBranching(const Energy startingScale,
const IdList &ids,double x,
const bool cc,double enhance,
tcBeamPtr beam)=0;
//@}
/**
* Methods to provide public access to the private member variables
*/
//@{
/**
* Return the pointer to the SplittingFunction object.
*/
tSplittingFnPtr splittingFn() const { return splittingFn_; }
/**
* Return the pointer to the ShowerAlpha object.
*/
tShowerAlphaPtr alpha() const { return alpha_; }
/**
* The type of interaction
*/
inline ShowerInteraction::Type interactionType() const
{return splittingFn_->interactionType();}
//@}
public:
/**
* Methods to access the kinematic variables for the branching
*/
//@{
/**
* The energy fraction
*/
double z() const { return z_; }
/**
* The azimuthal angle
*/
double phi() const { return phi_; }
/**
* The transverse momentum
*/
Energy pT() const { return pT_; }
//@}
/**
* Access the maximum weight for the PDF veto
*/
double pdfMax() const { return pdfmax_;}
/**
* Method to return the evolution scale given the
* transverse momentum, \f$p_T\f$ and \f$z\f$.
*/
virtual Energy calculateScale(double z, Energy pt, IdList ids,unsigned int iopt)=0;
/**
* Method to create the ShowerKinematics object for a final-state branching
*/
virtual ShoKinPtr createFinalStateBranching(Energy scale,double z,
double phi, Energy pt)=0;
/**
* Method to create the ShowerKinematics object for an initial-state branching
*/
virtual ShoKinPtr createInitialStateBranching(Energy scale,double z,
double phi, Energy pt)=0;
/**
* Method to create the ShowerKinematics object for a decay branching
*/
virtual ShoKinPtr createDecayBranching(Energy scale,double z,
double phi, Energy pt)=0;
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit();
//@}
protected:
/**
* Methods to implement the veto algorithm to generate the scale of
* the next branching
*/
//@{
/**
* Value of the energy fraction for the veto algorithm
* @param iopt The option for calculating z
* @param ids The PDG codes of the particles in the splitting
* - 0 is final-state
* - 1 is initial-state for the hard process
* - 2 is initial-state for particle decays
*/
double guessz (unsigned int iopt, const IdList &ids) const;
/**
* Value of the scale for the veto algorithm
* @param t1 The starting valoe of the scale
* @param iopt The option for calculating t
* @param ids The PDG codes of the particles in the splitting
* - 0 is final-state
* - 1 is initial-state for the hard process
* - 2 is initial-state for particle decays
* @param enhance The radiation enhancement factor
* @param identical Whether or not the outgoing particles are identical
*/
Energy2 guesst (Energy2 t1,unsigned int iopt, const IdList &ids,
double enhance, bool identical) const;
/**
* Veto on the PDF for the initial-state shower
* @param t The scale
* @param x The fraction of the beam momentum
* @param parton0 Pointer to the particleData for the
* new parent (this is the particle we evolved back to)
* @param parton1 Pointer to the particleData for the
* original particle
* @param beam The BeamParticleData object
*/
bool PDFVeto(const Energy2 t, const double x,
const tcPDPtr parton0, const tcPDPtr parton1,
tcBeamPtr beam) const;
/**
* The veto on the splitting function.
* @param t The scale
* @param ids The PDG codes of the particles in the splitting
* @param mass Whether or not to use the massive splitting functions
* @return true if vetoed
*/
bool SplittingFnVeto(const Energy2 t,
const IdList &ids,
const bool mass) const
{ return UseRandom::rnd()>splittingFn_->ratioP(z_, t, ids,mass); }
/**
* The veto on the coupling constant
* @param pt2 The value of ther transverse momentum squared, \f$p_T^2\f$.
* @return true if vetoed
*/
bool alphaSVeto(const Energy2 pt2) const
{return UseRandom::rnd() > ThePEG::Math::powi(alpha_->ratio(pt2),
splittingFn_->interactionOrder());}
//@}
/**
* Methods to set the kinematic variables for the branching
*/
//@{
/**
* The energy fraction
*/
void z(double in) { z_=in; }
/**
* The azimuthal angle
*/
void phi(double in) { phi_=in; }
/**
* The transverse momentum
*/
void pT(Energy in) { pT_=in; }
//@}
/**
* Set/Get the limits on the energy fraction for the splitting
*/
//@{
/**
* Get the limits
*/
pair<double,double> zLimits() const { return zlimits_;}
/**
* Set the limits
*/
void zLimits(pair<double,double> in) { zlimits_=in; }
//@}
/**
* Set the particles in the splittings
*/
void addSplitting(const IdList &);
/**
* Delete the particles in the splittings
*/
void removeSplitting(const IdList &);
/**
* Access the potential branchings
*/
vector<IdList> particles() const { return particles_; }
/**
* Methods to set the member variables for inheriting classes
*/
//@{
/**
* Method to set the SplittingFunction
*/
void splittingFn(tSplittingFnPtr in) { splittingFn_ = in;}
/**
* Method to set the coupling
*/
void alpha(tShowerAlphaPtr in) { alpha_ = in; }
/**
* Method to set the maximum PDF weight
*/
void pdfMax(double in) { pdfmax_ = in;}
/**
* Get the option for the PDF factor
*/
unsigned int PDFFactor() const { return pdffactor_; }
//@}
public:
/**
* @name Methods for the cut-off
*/
//@{
/**
* The option being used
*/
unsigned int cutOffOption() const { return cutOffOption_; }
/**
* The kinematic scale
*/
Energy kinScale() const {return kinCutoffScale_;}
/**
* The virtuality cut-off on the gluon \f$Q_g=\frac{\delta-am_q}{b}\f$
* @param scale The scale \f$\delta\f$
* @param mq The quark mass \f$m_q\f$.
*/
Energy kinematicCutOff(Energy scale, Energy mq) const
{return max((scale -a_*mq)/b_,c_);}
/**
* The virtualilty cut-off for gluons
*/
Energy vgCut() const { return vgcut_; }
/**
* The virtuality cut-off for everything else
*/
Energy vqCut() const { return vqcut_; }
/**
* The minimum \f$p_T\f$ for the branching
*/
Energy pTmin() const { return pTmin_; }
/**
* The square of the minimum \f$p_T\f$
*/
Energy2 pT2min() const { return pT2min_; }
/**
* Calculate the virtual masses for a branchings
*/
vector<Energy> virtualMasses(const IdList & ids);
//@}
/**
* Set the PDF
*/
void setPDF(tcPDFPtr pdf, Energy scale) {
pdf_ = pdf;
freeze_ = scale;
}
private:
/**
- * The static object used to initialize the description of this class.
- * Indicates that this is an abstract class with persistent data.
- */
- static AbstractClassDescription<SudakovFormFactor> initSudakovFormFactor;
-
- /**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
SudakovFormFactor & operator=(const SudakovFormFactor &);
private:
/**
* Pointer to the splitting function for this Sudakov form factor
*/
SplittingFnPtr splittingFn_;
/**
* Pointer to the coupling for this Sudakov form factor
*/
ShowerAlphaPtr alpha_;
/**
* Maximum value of the PDF weight
*/
double pdfmax_;
/**
* List of the particles this Sudakov is used for to aid in setting up
* interpolation tables if needed
*/
vector<IdList> particles_;
/**
* Option for the inclusion of a factor \f$1/(1-z)\f$ in the PDF estimate
*/
unsigned pdffactor_;
private:
/**
* Option for the type of cut-off to be applied
*/
unsigned int cutOffOption_;
/**
* Parameters for the default Herwig++ cut-off option, i.e. the parameters for
* the \f$Q_g=\max(\frac{\delta-am_q}{b},c)\f$ kinematic cut-off
*/
//@{
/**
* The \f$a\f$ parameter
*/
double a_;
/**
* The \f$b\f$ parameter
*/
double b_;
/**
* The \f$c\f$ parameter
*/
Energy c_;
/**
* Kinematic cutoff used in the parton shower phase space.
*/
Energy kinCutoffScale_;
//@}
/**
* Parameters for the FORTRAN-like cut-off
*/
//@{
/**
* The virtualilty cut-off for gluons
*/
Energy vgcut_;
/**
* The virtuality cut-off for everything else
*/
Energy vqcut_;
//@}
/**
* Parameters for the \f$p_T\f$ cut-off
*/
//@{
/**
* The minimum \f$p_T\f$ for the branching
*/
Energy pTmin_;
/**
* The square of the minimum \f$p_T\f$
*/
Energy2 pT2min_;
//@}
private:
/**
* Member variables to keep the shower kinematics information
* generated by a call to generateNextTimeBranching or generateNextSpaceBranching
*/
//@{
/**
* The energy fraction
*/
double z_;
/**
* The azimuthal angle
*/
double phi_;
/**
* The transverse momentum
*/
Energy pT_;
//@}
/**
* The limits of \f$z\f$ in the splitting
*/
pair<double,double> zlimits_;
/**
* Stuff for the PDFs
*/
//@{
/**
* PDf
*/
tcPDFPtr pdf_;
/**
* Freezing scale
*/
Energy freeze_;
//@}
};
}
-#include "ThePEG/Utilities/ClassTraits.h"
-
-namespace ThePEG {
-
-/** @cond TRAITSPECIALIZATIONS */
-
-/** This template specialization informs ThePEG about the
- * base classes of SudakovFormFactor. */
-template <>
-struct BaseClassTrait<Herwig::SudakovFormFactor,1> {
- /** Typedef of the first base class of SudakovFormFactor. */
- typedef Interfaced NthBase;
-};
-
-/** This template specialization informs ThePEG about the name of
- * the SudakovFormFactor class and the shared object where it is defined. */
-template <>
-struct ClassTraits<Herwig::SudakovFormFactor>
- : public ClassTraitsBase<Herwig::SudakovFormFactor> {
- /** Return a platform-independent class name */
- static string className() { return "Herwig::SudakovFormFactor"; }
-};
-
-/** @endcond */
-
-}
-
#endif /* HERWIG_SudakovFormFactor_H */
diff --git a/Shower/Couplings/ShowerAlpha.cc b/Shower/Couplings/ShowerAlpha.cc
--- a/Shower/Couplings/ShowerAlpha.cc
+++ b/Shower/Couplings/ShowerAlpha.cc
@@ -1,50 +1,46 @@
// -*- C++ -*-
//
// ShowerAlpha.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 ShowerAlpha class.
//
#include "ShowerAlpha.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Parameter.h"
-
-#ifdef ThePEG_TEMPLATES_IN_CC_FILE
-// #include "ShowerAlpha.tcc"
-#endif
-
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
+#include "ThePEG/Utilities/DescribeClass.h"
using namespace Herwig;
+DescribeAbstractClass<ShowerAlpha,Interfaced>
+describeShowerAlpha("Herwig::ShowerAlpha","");
+
void ShowerAlpha::persistentOutput(PersistentOStream & os) const {
os << _scaleFactor;
}
void ShowerAlpha::persistentInput(PersistentIStream & is, int) {
is >> _scaleFactor;
}
-AbstractClassDescription<ShowerAlpha> ShowerAlpha::initShowerAlpha;
-// Definition of the static class description member.
-
void ShowerAlpha::Init() {
static ClassDocumentation<ShowerAlpha> documentation
("This is the abstract class from which the various types of running alphas.",
"inherit from.");
static Parameter<ShowerAlpha,double> interfaceShowerAlpha
("ScaleFactor", "Factor that multiplies the scale argument, mu, "
"of the running alpha.",
&ShowerAlpha::_scaleFactor, 0, 1.0 , 0.0 , 10.0,false,false,false);
}
diff --git a/Shower/Couplings/ShowerAlpha.h b/Shower/Couplings/ShowerAlpha.h
--- a/Shower/Couplings/ShowerAlpha.h
+++ b/Shower/Couplings/ShowerAlpha.h
@@ -1,183 +1,150 @@
// -*- C++ -*-
//
// ShowerAlpha.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_ShowerAlpha_H
#define HERWIG_ShowerAlpha_H
//
// This is the declaration of the ShowerAlpha class.
//
#include "ThePEG/Interface/Interfaced.h"
#include "ShowerAlpha.fh"
namespace Herwig {
using namespace ThePEG;
/** \ingroup Shower
*
* This class is the abstract class from which all types of running couplings
* used in the Showering derive from.
* The main purpose of this class, and the ones that derive from it, is
* to allow systematic uncertainties for the initial-state radiation and,
* independently, the final-state radiation effects, to be evaluated.
*
* This is achieved by allowing a multiplicative factor,
* which is 1.0 for the "central value",
* for the scale argument, \f$\mu^2\f$, of the running coupling. This
* factor, \f$f\f$ is given by the scaleFactor() member and the coupling
* returned by the value() member is such that
* \f[\alpha(\mu^2)\to \alpha(f\times\mu^2).\f]
* This scale factor is a parameter which is settable by the user, via the
* interface.
* Although, of course, it is not clear my how much we should scale
* in order to get a \f$1\sigma\f$ systematic error (but factors:
* 1/2 and 2 are quite common), this method provides a double side error,
* and it appears more sensible than the rough and one-sided evaluation
* obtained
* via turning off the I.S.R. and/or F.S.R. (possibilities which are,
* anyway, provided by Herwig++).
*
* @see \ref ShowerAlphaInterfaces "The interfaces"
* defined for ShowerAlpha.
*/
class ShowerAlpha: public Interfaced {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
- inline ShowerAlpha() : _scaleFactor( 1.0 ) {}
+ ShowerAlpha() : _scaleFactor( 1.0 ) {}
//@}
public:
/**
* Methods to return the coupling and the scaleFactor
*/
//@{
/**
* Pure virtual method that is supposed to return the
* running alpha value evaluated at the input scale.
* @param scale The scale
* @return The coupling
*/
virtual double value(const Energy2 scale) const = 0;
/**
* Virtual method, which
* should be overridden in a derived class to provide an
* overestimate approximation of the alpha value.
*/
virtual double overestimateValue() const = 0;
/**
* Virtual method which returns the ratio of the running alpha
* value at the input scale to the overestimated value.
* @param scale The scale
* @return The ratio
*/
virtual double ratio(const Energy2 scale) const = 0;
/**
* It returns the factor that multiplies the
* scale argument, \f$\mu^2\f$, of the running coupling.
* This is supposed to be <I>1.0</I> in normal conditions (central values)
* whereas different values can be useful for systematics evaluation
* for Initial State radiation or Final State radiation effects.
*/
- inline double scaleFactor() const {return _scaleFactor;}
+ double scaleFactor() const {return _scaleFactor;}
/**
* Initialize this coupling.
*/
- virtual inline void initialize () {}
+ virtual void initialize () {}
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
private:
/**
- * The static object used to initialize the description of this class.
- * Indicates that this is an abstract class with persistent data.
- */
- static AbstractClassDescription<ShowerAlpha> initShowerAlpha;
-
- /**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
ShowerAlpha & operator=(const ShowerAlpha &);
private:
/**
* The scale factor
*/
double _scaleFactor;
};
}
-#include "ThePEG/Utilities/ClassTraits.h"
-
-namespace ThePEG {
-
-/** @cond TRAITSPECIALIZATIONS */
-
-/** This template specialization informs ThePEG about the
- * base classes of ShowerAlpha. */
-template <>
-struct BaseClassTrait<Herwig::ShowerAlpha,1> {
- /** Typedef of the first base class of ShowerAlpha. */
- typedef Interfaced NthBase;
-};
-
-/** This template specialization informs ThePEG about the name of
- * the ShowerAlpha class and the shared object where it is defined. */
-template <>
-struct ClassTraits<Herwig::ShowerAlpha>
- : public ClassTraitsBase<Herwig::ShowerAlpha> {
- /** Return a platform-independent class name */
- static string className() { return "Herwig::ShowerAlpha"; }
-};
-
-/** @endcond */
-
-}
-
#endif /* HERWIG_ShowerAlpha_H */
diff --git a/Shower/Couplings/ShowerAlphaQCD.cc b/Shower/Couplings/ShowerAlphaQCD.cc
--- a/Shower/Couplings/ShowerAlphaQCD.cc
+++ b/Shower/Couplings/ShowerAlphaQCD.cc
@@ -1,376 +1,377 @@
// -*- C++ -*-
//
// ShowerAlphaQCD.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 ShowerAlphaQCD class.
//
#include "ShowerAlphaQCD.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/PDT/ParticleData.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Command.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Utilities/Throw.h"
+#include "ThePEG/Utilities/DescribeClass.h"
using namespace Herwig;
+DescribeClass<ShowerAlphaQCD,ShowerAlpha>
+describeShowerAlphaQCD("Herwig::ShowerAlphaQCD","HwShower.so");
+
IBPtr ShowerAlphaQCD::clone() const {
return new_ptr(*this);
}
IBPtr ShowerAlphaQCD::fullclone() const {
return new_ptr(*this);
}
void ShowerAlphaQCD::persistentOutput(PersistentOStream & os) const {
os << _asType << _asMaxNP << ounit(_qmin,GeV) << _nloop << _lambdaopt << _thresopt
<< ounit(_lambdain,GeV) << _alphain << _inopt
<< _tolerance << _maxtry << _alphamin
<< ounit(_thresholds,GeV) << ounit(_lambda,GeV);
}
void ShowerAlphaQCD::persistentInput(PersistentIStream & is, int) {
is >> _asType >> _asMaxNP >> iunit(_qmin,GeV) >> _nloop >> _lambdaopt >> _thresopt
>> iunit(_lambdain,GeV) >> _alphain >> _inopt
>> _tolerance >> _maxtry >> _alphamin
>> iunit(_thresholds,GeV) >> iunit(_lambda,GeV);
}
-ClassDescription<ShowerAlphaQCD> ShowerAlphaQCD::initShowerAlphaQCD;
-// Definition of the static class description member.
-
void ShowerAlphaQCD::Init() {
static ClassDocumentation<ShowerAlphaQCD> documentation
("This (concrete) class describes the QCD alpha running.");
static Switch<ShowerAlphaQCD, int> intAsType
("NPAlphaS",
"Behaviour of AlphaS in the NP region",
&ShowerAlphaQCD::_asType, 1, false, false);
static SwitchOption intAsTypeZero
(intAsType, "Zero","zero below Q_min", 1);
static SwitchOption intAsTypeConst
(intAsType, "Const","const as(qmin) below Q_min", 2);
static SwitchOption intAsTypeLin
(intAsType, "Linear","growing linearly below Q_min", 3);
static SwitchOption intAsTypeQuad
(intAsType, "Quadratic","growing quadratically below Q_min", 4);
static SwitchOption intAsTypeExx1
(intAsType, "Exx1", "quadratic from AlphaMaxNP down to as(Q_min)", 5);
static SwitchOption intAsTypeExx2
(intAsType, "Exx2", "const = AlphaMaxNP below Q_min", 6);
// default such that as(qmin) = 1 in the current parametrization.
// min = Lambda3
static Parameter<ShowerAlphaQCD,Energy> intQmin
("Qmin", "Q < Qmin is treated with NP parametrization as of (unit [GeV])",
&ShowerAlphaQCD::_qmin, GeV, 0.630882*GeV, 0.330445*GeV,
100.0*GeV,false,false,false);
static Parameter<ShowerAlphaQCD,double> interfaceAlphaMaxNP
("AlphaMaxNP",
"Max value of alpha in NP region, only relevant if NPAlphaS = 5,6",
&ShowerAlphaQCD::_asMaxNP, 1.0, 0., 100.0,
false, false, Interface::limited);
static Parameter<ShowerAlphaQCD,unsigned int> interfaceNumberOfLoops
("NumberOfLoops",
"The number of loops to use in the alpha_S calculation",
&ShowerAlphaQCD::_nloop, 3, 1, 3,
false, false, Interface::limited);
static Switch<ShowerAlphaQCD,bool> interfaceLambdaOption
("LambdaOption",
"Option for the calculation of the Lambda used in the simulation from the input"
" Lambda_MSbar",
&ShowerAlphaQCD::_lambdaopt, false, false, false);
static SwitchOption interfaceLambdaOptionfalse
(interfaceLambdaOption,
"Same",
"Use the same value",
false);
static SwitchOption interfaceLambdaOptionConvert
(interfaceLambdaOption,
"Convert",
"Use the conversion to the Herwig scheme from NPB349, 635",
true);
static Parameter<ShowerAlphaQCD,Energy> interfaceLambdaQCD
("LambdaQCD",
"Input value of Lambda_MSBar",
&ShowerAlphaQCD::_lambdain, MeV, 0.208364*GeV, 100.0*MeV, 500.0*MeV,
false, false, Interface::limited);
static Parameter<ShowerAlphaQCD,double> interfaceAlphaMZ
("AlphaMZ",
"The input value of the strong coupling at the Z mass ",
&ShowerAlphaQCD::_alphain, 0.118, 0.1, 0.2,
false, false, Interface::limited);
static Switch<ShowerAlphaQCD,bool> interfaceInputOption
("InputOption",
"Option for inputing the initial value of the coupling",
&ShowerAlphaQCD::_inopt, true, false, false);
static SwitchOption interfaceInputOptionAlphaMZ
(interfaceInputOption,
"AlphaMZ",
"Use the value of alpha at MZ to calculate the coupling",
true);
static SwitchOption interfaceInputOptionLambdaQCD
(interfaceInputOption,
"LambdaQCD",
"Use the input value of Lambda to calculate the coupling",
false);
static Parameter<ShowerAlphaQCD,double> interfaceTolerance
("Tolerance",
"The tolerance for discontinuities in alphaS at thresholds.",
&ShowerAlphaQCD::_tolerance, 1e-10, 1e-20, 1e-4,
false, false, Interface::limited);
static Parameter<ShowerAlphaQCD,unsigned int> interfaceMaximumIterations
("MaximumIterations",
"The maximum number of iterations for the Newton-Raphson method to converge.",
&ShowerAlphaQCD::_maxtry, 100, 10, 1000,
false, false, Interface::limited);
static Switch<ShowerAlphaQCD,bool> interfaceThresholdOption
("ThresholdOption",
"Whether to use the consistuent or normal masses for the thresholds",
&ShowerAlphaQCD::_thresopt, true, false, false);
static SwitchOption interfaceThresholdOptionCurrent
(interfaceThresholdOption,
"Current",
"Use the current masses",
true);
static SwitchOption interfaceThresholdOptionConstituent
(interfaceThresholdOption,
"Constituent",
"Use the constitent masses.",
false);
static Command<ShowerAlphaQCD> interfaceValue
("Value",
"",
&ShowerAlphaQCD::value, false);
}
void ShowerAlphaQCD::doinit() {
ShowerAlpha::doinit();
// calculate the value of 5-flavour lambda
// evaluate the initial
// value of Lambda from alphas if needed using Newton-Raphson
if(_inopt)
{_lambda[2]=computeLambda(getParticleData(ParticleID::Z0)->mass(),_alphain,5);}
// otherwise it was an input parameter
else{_lambda[2]=_lambdain;}
// convert lambda to the Monte Carlo scheme if needed
using Constants::pi;
if(_lambdaopt){_lambda[2] *=exp(0.5*(67.-3.*sqr(pi)-50./3.)/23.)/sqrt(2.);}
// compute the threshold matching
// top threshold
for(int ix=1;ix<4;++ix) {
if(_thresopt)
_thresholds[ix]=getParticleData(ix+3)->mass();
else
_thresholds[ix]=getParticleData(ix+3)->constituentMass();
}
// compute 6 flavour lambda by matching at top mass using Newton Raphson
_lambda[3]=computeLambda(_thresholds[3],alphaS(_thresholds[3],_lambda[2],5),6);
// bottom threshold
// compute 4 flavour lambda by matching at bottom mass using Newton Raphson
_lambda[1]=computeLambda(_thresholds[2],alphaS(_thresholds[2],_lambda[2],5),4);
// charm threshold
// compute 3 flavour lambda by matching at charm mass using Newton Raphson
_lambda[0]=computeLambda(_thresholds[1],alphaS(_thresholds[1],_lambda[1],4),3);
// final threshold is qmin
_thresholds[0]=_qmin;
// compute the maximum value of as
if ( _asType < 5 ) _alphamin = value(sqr(_qmin)+1.0e-8*sqr(MeV)); // approx as = 1
else _alphamin = max(_asMaxNP, value(sqr(_qmin)+1.0e-8*sqr(MeV)));
// check consistency lambda_3 < qmin
if(_lambda[0]>_qmin)
Throw<InitException>() << "The value of Qmin is less than Lambda_3 in"
<< " ShowerAlphaQCD::doinit " << Exception::abortnow;
}
double ShowerAlphaQCD::value(const Energy2 scale) const {
pair<short,Energy> nflam;
Energy q = sqrt(scale);
double val(0.);
// special handling if the scale is less than Qmin
if (q < _qmin) {
nflam = getLamNfTwoLoop(_qmin);
double val0 = alphaS(_qmin, nflam.second, nflam.first);
switch (_asType) {
case 1:
// flat, zero; the default type with no NP effects.
val = 0.;
break;
case 2:
// flat, non-zero alpha_s = alpha_s(q2min).
val = val0;
break;
case 3:
// linear in q
val = val0*q/_qmin;
break;
case 4:
// quadratic in q
val = val0*sqr(q/_qmin);
break;
case 5:
// quadratic in q, starting off at asMaxNP, ending on as(qmin)
val = (val0 - _asMaxNP)*sqr(q/_qmin) + _asMaxNP;
break;
case 6:
// just asMaxNP and constant
val = _asMaxNP;
break;
}
} else {
// the 'ordinary' case
nflam = getLamNfTwoLoop(q);
val = alphaS(q, nflam.second, nflam.first);
}
return scaleFactor() * val;
}
double ShowerAlphaQCD::overestimateValue() const {
return scaleFactor() * _alphamin;
}
double ShowerAlphaQCD::ratio(const Energy2 scale) const {
pair<short,Energy> nflam;
Energy q = sqrt(scale);
double val(0.);
// special handling if the scale is less than Qmin
if (q < _qmin) {
nflam = getLamNfTwoLoop(_qmin);
double val0 = alphaS(_qmin, nflam.second, nflam.first);
switch (_asType) {
case 1:
// flat, zero; the default type with no NP effects.
val = 0.;
break;
case 2:
// flat, non-zero alpha_s = alpha_s(q2min).
val = val0;
break;
case 3:
// linear in q
val = val0*q/_qmin;
break;
case 4:
// quadratic in q
val = val0*sqr(q/_qmin);
break;
case 5:
// quadratic in q, starting off at asMaxNP, ending on as(qmin)
val = (val0 - _asMaxNP)*sqr(q/_qmin) + _asMaxNP;
break;
case 6:
// just asMaxNP and constant
val = _asMaxNP;
break;
}
} else {
// the 'ordinary' case
nflam = getLamNfTwoLoop(q);
val = alphaS(q, nflam.second, nflam.first);
}
// denominator
return val/_alphamin;
}
string ShowerAlphaQCD::value (string scale) {
istringstream readscale(scale);
double inScale; readscale >> inScale;
Energy theScale = inScale * GeV;
initialize();
ostringstream showvalue ("");
showvalue << "alpha_s (" << theScale/GeV << " GeV) = "
<< value (sqr(theScale));
return showvalue.str();
}
pair<short, Energy> ShowerAlphaQCD::getLamNfTwoLoop(Energy q) const {
short nf = 6;
// get lambda and nf according to the thresholds
if (q < _thresholds[1]) nf = 3;
else if (q < _thresholds[2]) nf = 4;
else if (q < _thresholds[3]) nf = 5;
return pair<short,Energy>(nf, _lambda[nf-3]);
}
Energy ShowerAlphaQCD::computeLambda(Energy match,
double alpha,
unsigned int nflav) const {
Energy lamtest=200.0*MeV;
double xtest;
unsigned int ntry=0;
do
{
++ntry;
xtest=log(sqr(match/lamtest));
xtest+= (alpha-alphaS(match,lamtest,nflav))/derivativealphaS(match,lamtest,nflav);
lamtest=match/exp(0.5*xtest);
}
while(abs(alpha-alphaS(match,lamtest,nflav)) > _tolerance && ntry < _maxtry);
return lamtest;
}
double ShowerAlphaQCD::derivativealphaS(Energy q, Energy lam, int nf) const
{
using Constants::pi;
double lx = log(sqr(q/lam));
double b0 = 11. - 2./3.*nf;
double b1 = 51. - 19./3.*nf;
double b2 = 2857. - 5033./9.*nf + 325./27.*sqr(nf);
if(_nloop==1)
return -4.*pi/(b0*sqr(lx));
else if(_nloop==2)
return -4.*pi/(b0*sqr(lx))*(1.-2.*b1/sqr(b0)/lx*(1.-2.*log(lx)));
else
return -4.*pi/(b0*sqr(lx))*(1.
- 2.*b1/sqr(b0)/lx*(1.-2.*log(lx))
+ 4.*sqr(b1)/(sqr(sqr(b0))*sqr(lx))*
(1.
- 2.*log(lx)
+ 3.*(sqr(log(lx) - 0.5)+b2*b0/(8.*sqr(b1))-1.25)
)
);
}
double ShowerAlphaQCD::alphaS(Energy q, Energy lam, int nf) const {
using Constants::pi;
double lx(log(sqr(q/lam)));
double b0 = 11. - 2./3.*nf;
double b1 = 51. - 19./3.*nf;
double b2 = 2857. - 5033./9.*nf + 325./27.*sqr(nf);
// one loop
if(_nloop==1)
{return 4.*pi/(b0*lx);}
// two loop
else if(_nloop==2) {
return 4.*pi/(b0*lx)*(1.-2.*b1/sqr(b0)*log(lx)/lx);
}
// three loop
else
{return 4.*pi/(b0*lx)*(1.-2.*b1/sqr(b0)*log(lx)/lx +
4.*sqr(b1)/(sqr(sqr(b0))*sqr(lx))*
(sqr(log(lx) - 0.5) + b2*b0/(8.*sqr(b1)) - 5./4.));}
}
diff --git a/Shower/Couplings/ShowerAlphaQCD.h b/Shower/Couplings/ShowerAlphaQCD.h
--- a/Shower/Couplings/ShowerAlphaQCD.h
+++ b/Shower/Couplings/ShowerAlphaQCD.h
@@ -1,320 +1,278 @@
// -*- C++ -*-
//
// ShowerAlphaQCD.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_ShowerAlphaQCD_H
#define HERWIG_ShowerAlphaQCD_H
//
// This is the declaration of the ShowerAlphaQCD class.
//
#include "ShowerAlpha.h"
#include "ThePEG/Config/Constants.h"
namespace Herwig {
using namespace ThePEG;
/** \ingroup Shower
*
* This concrete class provides the definition of the
* pure virtual function value() and overestimateValue() for the
* strong coupling.
*
* A number of different options for the running of the coupling
* and its initial definition are supported.
*
* @see \ref ShowerAlphaQCDInterfaces "The interfaces"
* defined for ShowerAlphaQCD.
*/
class ShowerAlphaQCD: public ShowerAlpha {
public:
/**
* The default constructor.
*/
ShowerAlphaQCD() : ShowerAlpha(),
_qmin(0.630882*GeV), _asType(1), _asMaxNP(1.0),
_thresholds(4), _lambda(4),
_nloop(3),_lambdaopt(false),_thresopt(false),
_lambdain(0.208364*GeV),_alphain(0.118),_inopt(true),_tolerance(1e-10),
_maxtry(100),_alphamin(0.) {}
public:
/**
* Methods to return the coupling
*/
//@{
/**
* It returns the running coupling value evaluated at the input scale
* multiplied by the scale factor scaleFactor().
* @param scale The scale
* @return The coupling
*/
virtual double value(const Energy2 scale) const;
/**
* It returns the running coupling value evaluated at the input scale
* multiplied by the scale factor scaleFactor().
*/
virtual double overestimateValue() const;
/**
* Return the ratio of the coupling at the scale to the overestimated value
*/
virtual double ratio(const Energy2 scale) const;
/**
* Initialize this coupling.
*/
virtual void initialize() { doinit(); }
/**
* A command to initialize the coupling and write
* its value at the scale given by the argument (in GeV)
*/
string value(string);
//@}
/**
* Get the value of \f$\Lambda_{\rm QCd}\f$
* @param nf number of flavours
*/
Energy lambdaQCD(unsigned int nf) {
if (nf <= 3) return _lambda[0];
else if (nf==4 || nf==5) return _lambda[nf-3];
else return _lambda[3];
}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
virtual IBPtr fullclone() const;
//@}
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit();
//@}
private:
/**
* Member functions which calculate the coupling
*/
//@{
/**
* The 1,2,3-loop parametrization of \f$\alpha_S\f$.
* @param q The scale
* @param lam \f$\Lambda_{\rm QCD}\f$
* @param nf The number of flavours
*/
double alphaS(Energy q, Energy lam, int nf) const;
/**
* The derivative of \f$\alpha_S\f$ with respect to \f$\ln(Q^2/\Lambda^2)\f$
* @param q The scale
* @param lam \f$\Lambda_{\rm QCD}\f$
* @param nf The number of flavours
*/
double derivativealphaS(Energy q, Energy lam, int nf) const;
/**
* Compute the value of \f$Lambda\f$ needed to get the input value of
* the strong coupling at the scale given for the given number of flavours
* using the Newton-Raphson method
* @param match The scale for the coupling
* @param alpha The input coupling
* @param nflav The number of flavours
*/
Energy computeLambda(Energy match, double alpha, unsigned int nflav) const;
/**
* Return the value of \f$\Lambda\f$ and the number of flavours at the scale.
* @param q The scale
* @return The number of flavours at the scale and \f$\Lambda\f$.
*/
pair<short, Energy> getLamNfTwoLoop(Energy q) const;
//@}
private:
/**
- * The static object used to initialize the description of this class.
- * Indicates that this is a concrete class with persistent data.
- */
- static ClassDescription<ShowerAlphaQCD> initShowerAlphaQCD;
-
- /**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
ShowerAlphaQCD & operator=(const ShowerAlphaQCD &);
private:
/**
* Minimum value of the scale
*/
Energy _qmin;
/**
* Parameter controlling the behaviour of \f$\alpha_S\f$ in the
* non-perturbative region.
*/
int _asType;
/**
* Another parameter, a possible (maximum) value of alpha in the
* non-perturbative region.
*/
double _asMaxNP;
/**
* Thresholds for the different number of flavours
*/
vector<Energy> _thresholds;
/**
* \f$\Lambda\f$ for the different number of flavours
*/
vector<Energy> _lambda;
/**
* Option for the number of loops
*/
unsigned int _nloop;
/**
* Option for the translation between \f$\Lambda_{\bar{MS}}\f$ and
* \f$\Lambda_{\rm Herwig}\f$
*/
bool _lambdaopt;
/**
* Option for the threshold masses
*/
bool _thresopt;
/**
* Input value of Lambda
*/
Energy _lambdain;
/**
* Input value of \f$alpha_S(M_Z)\f$
*/
double _alphain;
/**
* Option for the calculation of Lambda from input parameters
*/
bool _inopt;
/**
* Tolerance for discontinuities at the thresholds
*/
double _tolerance;
/**
* Maximum number of iterations for the Newton-Raphson method to converge
*/
unsigned int _maxtry;
/**
* The minimum value of the coupling
*/
double _alphamin;
};
}
-#include "ThePEG/Utilities/ClassTraits.h"
-
-namespace ThePEG {
-
-/** @cond TRAITSPECIALIZATIONS */
-
-/** This template specialization informs ThePEG about the
- * base classes of ShowerAlphaQCD. */
-template <>
-struct BaseClassTrait<Herwig::ShowerAlphaQCD,1> {
- /** Typedef of the first base class of ShowerAlphaQCD. */
- typedef Herwig::ShowerAlpha NthBase;
-};
-
-/** This template specialization informs ThePEG about the name of
- * the ShowerAlphaQCD class and the shared object where it is defined. */
-template <>
-struct ClassTraits<Herwig::ShowerAlphaQCD>
- : public ClassTraitsBase<Herwig::ShowerAlphaQCD> {
- /** Return a platform-independent class name */
- static string className() { return "Herwig::ShowerAlphaQCD"; }
- /**
- * The name of a file containing the dynamic library where the class
- * ShowerAlphaQCD is implemented. It may also include several,
- * space-separated, libraries if the class ShowerAlphaQCD depends on
- * other classes (base classes excepted). In this case the listed
- * libraries will be dynamically linked in the order they are
- * specified.
- */
- static string library() { return "HwShower.so"; }
-};
-
-/** @endcond */
-
-}
-
#endif /* HERWIG_ShowerAlphaQCD_H */
diff --git a/Shower/Default/QTildeFinder.cc b/Shower/Default/QTildeFinder.cc
--- a/Shower/Default/QTildeFinder.cc
+++ b/Shower/Default/QTildeFinder.cc
@@ -1,255 +1,256 @@
// -*- C++ -*-
//
// QTildeFinder.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 QTildeFinder class.
//
#include "QTildeFinder.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "Herwig++/Shower/Base/ShowerParticle.h"
#include "ThePEG/Repository/UseRandom.h"
+#include "ThePEG/Utilities/DescribeClass.h"
using namespace Herwig;
-ClassDescription<QTildeFinder> QTildeFinder::initQTildeFinder;
-// Definition of the static class description member.
+DescribeClass<QTildeFinder,Herwig::PartnerFinder>
+describeQTildeFinder ("Herwig::QTildeFinder","HwShower.so");
void QTildeFinder::persistentOutput(PersistentOStream & os) const {
os << _finalFinalConditions << _initialFinalDecayConditions
<< _initialInitialConditions;
}
void QTildeFinder::persistentInput(PersistentIStream & is, int) {
is >> _finalFinalConditions >> _initialFinalDecayConditions
>>_initialInitialConditions;
}
void QTildeFinder::Init() {
static ClassDocumentation<QTildeFinder> documentation
("This class is responsible for finding the partners for each interaction types ",
"and within the evolution scale range specified by the ShowerVariables ",
"then to determine the initial evolution scales for each pair of partners.");
static Switch<QTildeFinder,unsigned int> interfaceFinalFinalConditions
("FinalFinalConditions",
"The initial conditions for the shower of a final-final colour connection",
&QTildeFinder::_finalFinalConditions, 0, false, false);
static SwitchOption interfaceFinalFinalConditionsSymmetric
(interfaceFinalFinalConditions,
"Symmetric",
"The symmetric choice",
0);
static SwitchOption interfaceFinalFinalConditionsColoured
(interfaceFinalFinalConditions,
"Coloured",
"Maximal radiation from the coloured particle",
1);
static SwitchOption interfaceFinalFinalConditionsAntiColoured
(interfaceFinalFinalConditions,
"AntiColoured",
"Maximal emission from the anticoloured particle",
2);
static SwitchOption interfaceFinalFinalConditionsRandom
(interfaceFinalFinalConditions,
"Random",
"Randomly selected maximal emission from one of the particles",
3);
static Switch<QTildeFinder,unsigned int> interfaceInitialFinalDecayConditions
("InitialFinalDecayConditions",
"The initial conditions for the shower of an initial-final"
" decay colour connection.",
&QTildeFinder::_initialFinalDecayConditions, 0, false, false);
static SwitchOption interfaceInitialFinalDecayConditionsSymmetric
(interfaceInitialFinalDecayConditions,
"Symmetric",
"The symmetric choice",
0);
static SwitchOption interfaceInitialFinalDecayConditionsMaximal
(interfaceInitialFinalDecayConditions,
"Maximal",
"Maximal radiation from the decay product",
1);
static SwitchOption interfaceInitialFinalDecayConditionsSmooth
(interfaceInitialFinalDecayConditions,
"Smooth",
"Smooth matching in the soft limit",
2);
static Switch<QTildeFinder,unsigned int> interfaceInitialInitialConditions
("InitialInitialConditions",
"The initial conditions for the shower of an initial-initial"
" colour connection.",
&QTildeFinder::_initialInitialConditions, 0, false, false);
static SwitchOption interfaceInitialInitialConditionsSymmetric
(interfaceInitialInitialConditions,
"Symmetric",
"The symmetric choice",
0);
static SwitchOption interfaceInitialInitialConditionsMaximiseB
(interfaceInitialInitialConditions,
"MaximiseB",
"Maximal radiation from parton b",
1);
static SwitchOption interfaceInitialInitialConditionsMaximiseC
(interfaceInitialInitialConditions,
"MaximiseC",
"Maximal radiation from parton c",
2);
}
pair<Energy,Energy> QTildeFinder::
calculateInitialFinalScales(const ShowerPPair &ppair, const bool isDecayCase) {
Lorentz5Momentum pb = ppair.first->momentum();
Lorentz5Momentum pc = ppair.second->momentum();
if(!isDecayCase) {
// In this case from JHEP 12(2003)045 we find the conditions
// ktilde_b = (1+c) and ktilde_c = (1+2c)
// We also find that c = m_c^2/Q^2. The process is a+b->c where
// particle a is not colour connected (considered as a colour singlet).
// Therefore we simply find that q_b = sqrt(Q^2+m_c^2) and
// q_c = sqrt(Q^2+2 m_c^2)
// We also assume that the first particle in the pair is the initial
// state particle and the second is the final state one c
Energy2 mc2 = sqr(ppair.second->mass());
Energy2 Q2 = -(pb-pc).m2();
return pair<Energy,Energy>(sqrt(Q2+mc2), sqrt(Q2+2*mc2));
}
else {
// In this case from JHEP 12(2003)045 we find, for the decay
// process b->c+a(neutral), the condition
// (ktilde_b-1)*(ktilde_c-c)=(1/4)*sqr(1-a+c+lambda).
// We also assume that the first particle in the pair is the initial
// state particle (b) and the second is the final state one (c).
// - We find maximal phase space coverage through emissions from
// c if we set ktilde_c = 4.*(sqr(1.-sqrt(a))-c)
// - We find the most 'symmetric' way to populate the phase space
// occurs for (ktilde_b-1)=(ktilde_c-c)=(1/2)*(1-a+c+lambda)
// - We find the most 'smooth' way to populate the phase space
// occurs for...
Energy2 mb2(sqr(ppair.first->mass()));
double a=(pb-pc).m2()/mb2;
double c=sqr(ppair.second->mass())/mb2;
double lambda = sqrt(1. + a*a + c*c - 2.*a - 2.*c - 2.*a*c);
double PROD = 0.25*sqr(1. - a + c + lambda);
double ktilde_b, ktilde_c,cosi(0.);
switch(initialFinalDecayConditions()) {
case 0: // the 'symmetric' choice
ktilde_c = 0.5*(1-a+c+lambda) + c ;
ktilde_b = 1.+PROD/(ktilde_c-c) ;
break;
case 1: // the 'maximal' choice
ktilde_c = 4.0*(sqr(1.-sqrt(a))-c);
ktilde_b = 1.+PROD/(ktilde_c-c) ;
break;
case 2: // the 'smooth' choice
// c is a problem if very small here use 1GeV as minimum
c = max(c,1.*GeV2/mb2);
cosi = (sqr(1-sqrt(c))-a)/lambda;
ktilde_b = 2.0/(1.0-cosi);
ktilde_c = (1.0-a+c+lambda)*(1.0+c-a-lambda*cosi)/(2.0*(1.0+cosi));
break;
default:
throw Exception() << "Invalid option for decay shower's phase space"
<< " QTildeFinder::calculateInitialFinalScales"
<< Exception::abortnow;
}
return pair<Energy,Energy>(sqrt(mb2*ktilde_b),sqrt(mb2*ktilde_c));
}
}
pair<Energy,Energy> QTildeFinder::
calculateInitialInitialScales(const ShowerPPair &ppair) {
// This case is quite simple. From JHEP 12(2003)045 we find the condition
// that ktilde_b = ktilde_c = 1. In this case we have the process
// b+c->a so we need merely boost to the CM frame of the two incoming
// particles and then qtilde is equal to the energy in that frame
Lorentz5Momentum p(ppair.first->momentum()+ppair.second->momentum());
p.boost(p.findBoostToCM());
Energy Q = sqrt(p.m2());
if(_initialInitialConditions==1) {
return pair<Energy,Energy>(sqrt(2.0)*Q,sqrt(0.5)*Q);
} else if(_initialInitialConditions==2) {
return pair<Energy,Energy>(sqrt(0.5)*Q,sqrt(2.0)*Q);
} else {
return pair<Energy,Energy>(Q,Q);
}
}
pair<Energy,Energy> QTildeFinder::
calculateFinalFinalScales(const ShowerPPair &particlePair) {
static const double eps=1e-8;
// Using JHEP 12(2003)045 we find that we need ktilde = 1/2(1+b-c+lambda)
// ktilde = qtilde^2/Q^2 therefore qtilde = sqrt(ktilde*Q^2)
// find momenta in rest frame of system
Lorentz5Momentum p1= particlePair.first->momentum();
Lorentz5Momentum p2 = particlePair.second->momentum();
Lorentz5Momentum p12(p1+p2);
Boost boostv=p12.findBoostToCM();
p1.boost(boostv);
p2.boost(boostv);
// calculate quantities for the scales
Energy2 Q2 = p12.m2();
double b = p1.mass2()/Q2;
double c = p2.mass2()/Q2;
if(b<0.) {
if(b<-eps) throw Exception() << "Negative Mass sqaured b = " << b
<< "in QTildeFinder::calculateFinalFinalScales()"
<< Exception::eventerror;
b = 0.;
}
if(c<0.) {
if(c<-eps) throw Exception() << "Negative Mass sqaured c = " << c
<< "in QTildeFinder::calculateFinalFinalScales()"
<< Exception::eventerror;
c = 0.;
}
// KMH & PR - 16 May 2008 - swapped lambda calculation from
// double lam=2.*p1.vect().mag()/Q; to sqrt(kallen(1,b,c)),
// which should be identical for p1 & p2 onshell in their COM
// but in the inverse construction for the Nason method, this
// was not the case, leading to misuse.
double lam=sqrt((1.+sqrt(b)+sqrt(c))*(1.-sqrt(b)-sqrt(c))
*(sqrt(b)-1.-sqrt(c))*(sqrt(c)-1.-sqrt(b)));
// symmetric case
unsigned int iopt=finalFinalConditions();
Energy firstQ,secondQ;
if(iopt==0) {
firstQ = sqrt(0.5*Q2*(1.+b-c+lam));
secondQ = sqrt(0.5*Q2*(1.-b+c+lam));
}
// assymetric choice
else {
double kappab,kappac;
// find if first particle is coloured
bool colouredFirst=particlePair.first->colourLine()&&
particlePair.first->colourLine()==particlePair.second->antiColourLine();
// calculate kappa with coloured line getting maximum
if((iopt==1&&colouredFirst)|| // first particle coloured+maximal for coloured
(iopt==2&&!colouredFirst)|| // first particle anticoloured+maximal for acoloured
(iopt==3&&UseRandom::rndbool(0.5))) { // random choice
kappab=4.*(1.-2.*sqrt(c)-b+c);
kappac=c+0.25*sqr(1.-b-c+lam)/(kappab-b);
}
else {
kappac=4.*(1.-2.*sqrt(b)-c+b);
kappab=b+0.25*sqr(1.-b-c+lam)/(kappac-c);
}
// calculate the scales
firstQ = sqrt(Q2*kappab);
secondQ = sqrt(Q2*kappac);
}
return pair<Energy,Energy>(firstQ, secondQ);
}
diff --git a/Shower/Default/QTildeFinder.h b/Shower/Default/QTildeFinder.h
--- a/Shower/Default/QTildeFinder.h
+++ b/Shower/Default/QTildeFinder.h
@@ -1,227 +1,186 @@
// -*- C++ -*-
//
// QTildeFinder.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_QTildeFinder_H
#define HERWIG_QTildeFinder_H
//
// This is the declaration of the QTildeFinder class.
//
#include "Herwig++/Shower/Base/PartnerFinder.h"
#include "Herwig++/Shower/ShowerConfig.h"
#include "ThePEG/Interface/Interfaced.h"
namespace Herwig {
using namespace ThePEG;
/** \ingroup Shower
*
* The QTildeFinder class is responsible for finding the partners and
* setting the initial evolution scales for the shower evolution described
* in JHEP 0312:045,2003.
*
* @see \ref QTildeFinderInterfaces "The interfaces"
* defined for QTildeFinder.
*/
class QTildeFinder: public PartnerFinder {
public:
/**
* The default constructor.
*/
QTildeFinder() : _finalFinalConditions(0),
_initialFinalDecayConditions(0),
_initialInitialConditions(0) {}
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/**
* Given a pair of particles, supposedly partners w.r.t. an interaction,
* this method returns their initial evolution scales as a pair.
* If something wrong happens, it returns the null (ZERO,ZERO) pair.
* This method is used by the above setXXXInitialEvolutionScales
* methods.
*/
//@{
/**
* Calculate the initial evolution scales for two final-state particles
*/
virtual pair<Energy,Energy> calculateFinalFinalScales(const ShowerPPair &);
/**
* Calculate the initial evolution scales for two initial-state particles
*/
virtual pair<Energy,Energy> calculateInitialInitialScales(const ShowerPPair &);
/**
* Calculate the initial evolution scales for one initial
* and one final-state particles
*/
virtual pair<Energy,Energy> calculateInitialFinalScales(const ShowerPPair &,
const bool isDecayCase);
//@}
/**
* Access function for the initial conditions for the shower
*/
//@{
/**
* Initial conditions for the shower of a final-final colour connection
* - 0 is the symmetric choice
* - 1 is maximal emmision from the coloured particle
* - 2 is maximal emmision from the anticoloured particle
* - 3 is randomly selected maximal emmision
*/
unsigned int finalFinalConditions() const
{return _finalFinalConditions;}
/**
* Initial conditions for the shower of an initial-final decay colour connection
* - 0 is the symmetric choice
* - 1 is maximal emission from the decay product
* - 2 is the smooth choice
*/
unsigned int initialFinalDecayConditions() const
{return _initialFinalDecayConditions;}
//@}
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
virtual IBPtr clone() const {return new_ptr(*this);}
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
virtual IBPtr fullclone() const {return new_ptr(*this);}
//@}
private:
/**
- * The static object used to initialize the description of this class.
- * Indicates that this is a concrete class with persistent data.
- */
- static ClassDescription<QTildeFinder> initQTildeFinder;
-
- /**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
QTildeFinder & operator=(const QTildeFinder &);
private:
/**
* Flags controlling the initial conditions for the shower
*/
//@{
/**
* Initial conditions for the shower with a final-final colour
* connection
*/
unsigned int _finalFinalConditions;
/**
* Initial conditions for the shower with an initial-final decay colour
* connection. This is done according to the top decay colour
* connection calculation in JHEP12(2003)_045. The options act as follows:
* 0: This is the default 'symmetric' choice which more or less divides
* the phase space evenly between the parent and its charged child.
* 1: This 'maximal' choice maximises the phase space available for
* gluons emitted from the charged child.
* 2: This (experimental) 'smooth' choice does not suffer from
* a discontinuity at the boundary between the region populated by
* emissions from the charged child and the region populated by emissions
* from the parent. This does, however, mean that the phase space
* available for emissions from the charged child is fairly minimal.
*/
unsigned int _initialFinalDecayConditions;
/**
* Initial conditions for the shower with an initial-initial colour
* connection. This is done according to the colour connection
* calculation in JHEP12(2003)_045. The options act as follows:
* 0: This is the default 'symmetric' choice which more or less divides
* the phase space evenly between the two incoming partons.
* 1: This increases the phase space for emission from "parton b".
* 2: This increases the phase space for emission from "parton c".
*/
unsigned int _initialInitialConditions;
//@}
};
}
-#include "ThePEG/Utilities/ClassTraits.h"
-
-namespace ThePEG {
-
-/** @cond TRAITSPECIALIZATIONS */
-
-/** This template specialization informs ThePEG about the
- * base classes of QTildeFinder. */
-template <>
-struct BaseClassTrait<Herwig::QTildeFinder,1> {
- /** Typedef of the first base class of QTildeFinder. */
- typedef Herwig::PartnerFinder NthBase;
-};
-
-/** This template specialization informs ThePEG about the name of
- * the QTildeFinder class and the shared object where it is defined. */
-template <>
-struct ClassTraits<Herwig::QTildeFinder>
- : public ClassTraitsBase<Herwig::QTildeFinder> {
- /** Return a platform-independent class name */
- static string className() { return "Herwig::QTildeFinder"; }
- /**
- * The name of a file containing the dynamic library where the class
- * QTildeFinder is implemented. It may also include several, space-separated,
- * libraries if the class QTildeFinder depends on other classes (base classes
- * excepted). In this case the listed libraries will be dynamically
- * linked in the order they are specified.
- */
- static string library() { return "HwShower.so"; }
-};
-
-/** @endcond */
-
-}
-
#endif /* HERWIG_QTildeFinder_H */
diff --git a/Shower/Default/QTildeModel.cc b/Shower/Default/QTildeModel.cc
--- a/Shower/Default/QTildeModel.cc
+++ b/Shower/Default/QTildeModel.cc
@@ -1,61 +1,62 @@
// -*- C++ -*-
//
// QTildeModel.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 QTildeModel class.
//
#include "QTildeModel.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "QTildeReconstructor.h"
#include "QTildeFinder.h"
#include "QTildeSudakov.h"
#include "ThePEG/Utilities/Throw.h"
#include "Herwig++/Shower/Base/Evolver.h"
+#include "ThePEG/Utilities/DescribeClass.h"
using namespace Herwig;
+DescribeNoPIOClass<QTildeModel,Herwig::ShowerModel>
+describeQTildeModel ("Herwig::QTildeModel","HwShower.so");
+
IBPtr QTildeModel::clone() const {
return new_ptr(*this);
}
IBPtr QTildeModel::fullclone() const {
return new_ptr(*this);
}
-NoPIOClassDescription<QTildeModel> QTildeModel::initQTildeModel;
-// Definition of the static class description member.
-
void QTildeModel::Init() {
static ClassDocumentation<QTildeModel> documentation
("The QTildeModel class is the ShowerModel object for the Herwig++ shower.");
}
void QTildeModel::checkConsistency() {
// check KinematicsReconstructor
if(!dynamic_ptr_cast<Ptr<QTildeReconstructor>::pointer>(kinematicsReconstructor()))
Throw<InitException>() << "KinematicsReconstructor must be either "
<< "QTildeKinematicsReconstructor or a class inheriting from it"
<< "in QTildeModel::checkConsistency()";
// check PartnerFinder
if(!dynamic_ptr_cast<Ptr<QTildeFinder>::pointer>(partnerFinder()))
Throw<InitException>() << "PartnerFinder must be either "
<< "QTildeFinder or a class inheriting from it"
<< "in QTildeModel::checkConsistency()";
// Sudakov form factors
vector<SudakovPtr>::const_iterator sit;
for(sit=sudakovFormFactors().begin();sit!=sudakovFormFactors().end();++sit) {
if(!dynamic_ptr_cast<Ptr<QTildeSudakov>::pointer>(*sit))
Throw<InitException>() << "SudakovFormFactors must be either "
<< "QTildeSudakov or a class inheriting from it"
<< "in QTildeModel::checkConsistency()";
}
}
diff --git a/Shower/Default/QTildeModel.h b/Shower/Default/QTildeModel.h
--- a/Shower/Default/QTildeModel.h
+++ b/Shower/Default/QTildeModel.h
@@ -1,118 +1,77 @@
// -*- C++ -*-
//
// QTildeModel.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_QTildeModel_H
#define HERWIG_QTildeModel_H
//
// This is the declaration of the QTildeModel class.
//
#include "Herwig++/Shower/Base/ShowerModel.h"
namespace Herwig {
using namespace ThePEG;
/** \ingroup Shower
* The QTildeModel class inherits from the ShowerModel class and implements the
* checkConsistency member for the default Herwig++ Shower.
*
* @see \ref QTildeModelInterfaces "The interfaces"
* defined for QTildeModel.
*/
class QTildeModel: public ShowerModel {
public:
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/**
* The implementation of the virtual member from the base class to
* check that the correct objects are loaded
*/
virtual void checkConsistency();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
virtual IBPtr fullclone() const;
//@}
private:
/**
- * The static object used to initialize the description of this class.
- * Indicates that this is an concrete class without persistent data.
- */
- static NoPIOClassDescription<QTildeModel> initQTildeModel;
-
- /**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
QTildeModel & operator=(const QTildeModel &);
};
}
-#include "ThePEG/Utilities/ClassTraits.h"
-
-namespace ThePEG {
-
-/** @cond TRAITSPECIALIZATIONS */
-
-/** This template specialization informs ThePEG about the
- * base classes of QTildeModel. */
-template <>
-struct BaseClassTrait<Herwig::QTildeModel,1> {
- /** Typedef of the first base class of QTildeModel. */
- typedef Herwig::ShowerModel NthBase;
-};
-
-/** This template specialization informs ThePEG about the name of
- * the QTildeModel class and the shared object where it is defined. */
-template <>
-struct ClassTraits<Herwig::QTildeModel>
- : public ClassTraitsBase<Herwig::QTildeModel> {
- /** Return a platform-independent class name */
- static string className() { return "Herwig::QTildeModel"; }
- /**
- * The name of a file containing the dynamic library where the class
- * QTildeModel is implemented. It may also include several, space-separated,
- * libraries if the class QTildeModel depends on other classes (base classes
- * excepted). In this case the listed libraries will be dynamically
- * linked in the order they are specified.
- */
- static string library() { return "HwShower.so"; }
-};
-
-/** @endcond */
-
-}
-
#endif /* HERWIG_QTildeModel_H */
diff --git a/Shower/Default/QTildeReconstructor.cc b/Shower/Default/QTildeReconstructor.cc
--- a/Shower/Default/QTildeReconstructor.cc
+++ b/Shower/Default/QTildeReconstructor.cc
@@ -1,2289 +1,2290 @@
// -*- C++ -*-
//
// QTildeReconstructor.cc is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the QTildeReconstructor class.
//
#include "QTildeReconstructor.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/EventRecord/Event.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/RefVector.h"
#include "Herwig++/Shower/Base/Evolver.h"
#include "Herwig++/Shower/Base/PartnerFinder.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "Herwig++/Shower/SplittingFunctions/SplittingFunction.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/EventRecord/ColourLine.h"
+#include "ThePEG/Utilities/DescribeClass.h"
#include <cassert>
using namespace Herwig;
+DescribeClass<QTildeReconstructor,KinematicsReconstructor>
+describeQTildeReconstructor("Herwig::QTildeReconstructor", "HwShower.so");
+
namespace {
enum SystemType { UNDEFINED=-1, II, IF, F ,I };
struct ColourSingletSystem {
ColourSingletSystem() : type(UNDEFINED) {}
ColourSingletSystem(SystemType intype,ShowerProgenitorPtr inpart)
: type(intype),jets(1,inpart) {}
/**
* The type of system
*/
SystemType type;
/**
* The jets in the system
*/
vector<ShowerProgenitorPtr> jets;
};
struct ColourSingletShower {
ColourSingletShower() : type(UNDEFINED) {}
ColourSingletShower(SystemType intype,HardBranchingPtr inpart)
: type(intype),jets(1,inpart) {}
/**
* The type of system
*/
SystemType type;
/**
* The jets in the system
*/
vector<HardBranchingPtr> jets;
};
/**
* Return colour line progenitor pointer for ShowerProgenitor
*/
Ptr<ThePEG::ColourLine>::transient_pointer
CL(ShowerProgenitorPtr a, unsigned int index=0) {
return const_ptr_cast<ThePEG::tColinePtr>(a->progenitor()->colourInfo()->colourLines()[index]);
}
/**
* Return progenitor colour line size for ShowerProgenitor
*/
unsigned int CLSIZE(ShowerProgenitorPtr a) {
return a->progenitor()->colourInfo()->colourLines().size();
}
/**
* Return anti-colour line progenitor pointer for ShowerProgenitor
*/
Ptr<ThePEG::ColourLine>::transient_pointer
ACL(ShowerProgenitorPtr a, unsigned int index=0) {
return const_ptr_cast<ThePEG::tColinePtr>(a->progenitor()->colourInfo()->antiColourLines()[index]);
}
/**
* Return progenitor anti-colour line size for ShowerProgenitor
*/
unsigned int ACLSIZE(ShowerProgenitorPtr a) {
return a->progenitor()->colourInfo()->antiColourLines().size();
}
/**
* Return colour line size
*/
unsigned int CLSIZE(set<HardBranchingPtr>::const_iterator & a) {
return (*a)->branchingParticle()->colourInfo()->colourLines().size();
}
/**
* Return anti-colour line size
*/
unsigned int ACLSIZE(set<HardBranchingPtr>::const_iterator & a) {
return (*a)->branchingParticle()->colourInfo()->antiColourLines().size();
}
}
void QTildeReconstructor::persistentOutput(PersistentOStream & os) const {
os << _reconopt << _initialBoost << ounit(_minQ,GeV) << _noRescale
<< _noRescaleVector;
}
void QTildeReconstructor::persistentInput(PersistentIStream & is, int) {
is >> _reconopt >> _initialBoost >> iunit(_minQ,GeV) >> _noRescale
>> _noRescaleVector;
}
-ClassDescription<QTildeReconstructor> QTildeReconstructor::initQTildeReconstructor;
-// Definition of the static class description member.
-
void QTildeReconstructor::Init() {
static ClassDocumentation<QTildeReconstructor> documentation
( "This class is responsible for the kinematics reconstruction of the showering,",
" including the kinematics reshuffling necessary to compensate for the recoil"
"of the emissions." );
static Switch<QTildeReconstructor,unsigned int> interfaceReconstructionOption
("ReconstructionOption",
"Option for the kinematics reconstruction",
&QTildeReconstructor::_reconopt, 0, false, false);
static SwitchOption interfaceReconstructionOptionGeneral
(interfaceReconstructionOption,
"General",
"Use the general solution which ignores the colour structure for all processes",
0);
static SwitchOption interfaceReconstructionOptionColour
(interfaceReconstructionOption,
"Colour",
"Use the colour structure of the process to determine the reconstruction procedure.",
1);
static Parameter<QTildeReconstructor,Energy> interfaceMinimumQ2
("MinimumQ2",
"The minimum Q2 for the reconstruction of initial-final systems",
&QTildeReconstructor::_minQ, GeV, 0.001*GeV, 1e-6*GeV, 10.0*GeV,
false, false, Interface::limited);
static RefVector<QTildeReconstructor,ParticleData> interfaceNoRescale
("NoRescale",
"Particles which shouldn't be rescaled to be on shell by the shower",
&QTildeReconstructor::_noRescaleVector, -1, false, false, true, false, false);
static Switch<QTildeReconstructor,unsigned int> interfaceInitialInitialBoostOption
("InitialInitialBoostOption",
"Option for how the boost from the system before ISR to that after ISR is applied.",
&QTildeReconstructor::_initialBoost, 0, false, false);
static SwitchOption interfaceInitialInitialBoostOptionOneBoost
(interfaceInitialInitialBoostOption,
"OneBoost",
"Apply one boost from old CMS to new CMS",
0);
static SwitchOption interfaceInitialInitialBoostOptionLongTransBoost
(interfaceInitialInitialBoostOption,
"LongTransBoost",
"First apply a longitudinal and then a transverse boost",
1);
}
void QTildeReconstructor::doinit() {
KinematicsReconstructor::doinit();
_noRescale = set<cPDPtr>(_noRescaleVector.begin(),_noRescaleVector.end());
}
bool QTildeReconstructor::
reconstructTimeLikeJet(const tShowerParticlePtr particleJetParent,
unsigned int iopt) const {
assert(particleJetParent);
bool emitted=true;
// if this is not a fixed point in the reconstruction
if( !particleJetParent->isReconstructionFixedPoint() ) {
// if not a reconstruction fixpoint, dig deeper for all children:
for ( ParticleVector::const_iterator cit =
particleJetParent->children().begin();
cit != particleJetParent->children().end(); ++cit )
reconstructTimeLikeJet(dynamic_ptr_cast<ShowerParticlePtr>(*cit),iopt);
}
// it is a reconstruction fixpoint, ie kinematical data has to be available
else {
// check if the parent was part of the shower
ShowerParticlePtr jetGrandParent;
if(!particleJetParent->parents().empty())
jetGrandParent= dynamic_ptr_cast<ShowerParticlePtr>
(particleJetParent->parents()[0]);
// update if so
if (jetGrandParent) {
if (jetGrandParent->showerKinematics()) {
if(particleJetParent->id()==_progenitor->id()&&
!_progenitor->data().stable()) {
jetGrandParent->showerKinematics()->reconstructLast(particleJetParent,iopt,
_progenitor->mass());
}
else {
jetGrandParent->showerKinematics()->reconstructLast(particleJetParent,iopt);
}
}
}
// otherwise
else {
Energy dm = particleJetParent->data().constituentMass();
if (abs(dm-particleJetParent->momentum().m())>0.001*MeV
&&particleJetParent->dataPtr()->stable()
&&particleJetParent->id()!=ParticleID::gamma
&&_noRescale.find(particleJetParent->dataPtr())==_noRescale.end()) {
Lorentz5Momentum dum = particleJetParent->momentum();
if(dm>dum.e()) throw KinematicsReconstructionVeto();
dum.setMass(dm);
dum.rescaleRho();
particleJetParent->set5Momentum(dum);
}
else {
emitted=false;
}
}
}
// recursion has reached an endpoint once, ie we can reconstruct the
// kinematics from the children.
if( !(particleJetParent->isReconstructionFixedPoint()) )
particleJetParent->showerKinematics()
->reconstructParent( particleJetParent, particleJetParent->children() );
return emitted;
}
bool QTildeReconstructor::
reconstructHardJets(ShowerTreePtr hard,
const map<tShowerProgenitorPtr,
pair<Energy,double> > & intrinsic) const {
_currentTree = hard;
_intrinsic=intrinsic;
// extract the particles from the ShowerTree
vector<ShowerProgenitorPtr> ShowerHardJets=hard->extractProgenitors();
try {
// old recon method, using new member functions
if(_reconopt==0) {
reconstructGeneralSystem(ShowerHardJets);
}
// reconstruction based on coloured systems
else {
// identify the colour singlet systems
vector<ColourSingletSystem> systems;
vector<bool> done(ShowerHardJets.size(),false);
for(unsigned int ix=0;ix<ShowerHardJets.size();++ix) {
// if not treated create new system
if(done[ix]) continue;
systems.push_back(ColourSingletSystem(UNDEFINED,ShowerHardJets[ix]));
done[ix] = true;
if(!ShowerHardJets[ix]->progenitor()->coloured()) continue;
// now find the colour connected particles
vector<unsigned int> iloc(1,ix);
do {
vector<unsigned int> temp=findPartners(iloc.back(),ShowerHardJets);
iloc.pop_back();
for(unsigned int iy=0;iy<temp.size();++iy) {
if(!done[temp[iy]]) {
done[temp[iy]] = true;
iloc.push_back(temp[iy]);
systems.back().jets.push_back(ShowerHardJets[temp[iy]]);
}
}
}
while(!iloc.empty());
}
// catagorize the systems
unsigned int nnun(0),nnii(0),nnif(0),nnf(0),nni(0);
for(unsigned int ix=0;ix<systems.size();++ix) {
unsigned int ni(0),nf(0);
for(unsigned int iy=0;iy<systems[ix].jets.size();++iy) {
if(systems[ix].jets[iy]->progenitor()->isFinalState()) ++nf;
else ++ni;
}
// type
// initial-initial
if(ni==2&&nf==0) {
systems[ix].type = II;
++nnii;
}
// initial only
else if(ni==1&&nf==0) {
systems[ix].type = I;
++nni;
}
// initial-final
else if(ni==1&&nf>0) {
systems[ix].type = IF;
++nnif;
}
// final only
else if(ni==0&&nf>0) {
systems[ix].type = F;
++nnf;
}
// otherwise unknown
else {
systems[ix].type = UNDEFINED;
++nnun;
}
}
// now decide what to do
// initial-initial connection and final-state colour singlet systems
LorentzRotation toRest,fromRest;
bool applyBoost(false);
bool general(false);
// Drell-Yan type
if(nnun==0&&nnii==1&&nnif==0&&nnf>0&&nni==0) {
// reconstruct initial-initial system
for(unsigned int ix=0;ix<systems.size();++ix) {
if(systems[ix].type==II)
reconstructInitialInitialSystem(applyBoost,toRest,fromRest,
systems[ix].jets);
}
}
// DIS and VBF type
else if(nnun==0&&nnii==0&&((nnif==1&&nnf>0&&nni==1)||
(nnif==2&& nni==0))) {
// check these systems can be reconstructed
for(unsigned int ix=0;ix<systems.size();++ix) {
// compute q^2
if(systems[ix].type!=IF) continue;
Lorentz5Momentum q;
for(unsigned int iy=0;iy<systems[ix].jets.size();++iy) {
if(systems[ix].jets[iy]->progenitor()->isFinalState())
q += systems[ix].jets[iy]->progenitor()->momentum();
else
q -= systems[ix].jets[iy]->progenitor()->momentum();
}
q.rescaleMass();
// check above cut
if(abs(q.m())>=_minQ) continue;
if(nnif==1&&nni==1) {
throw KinematicsReconstructionVeto();
}
else {
general = true;
break;
}
}
if(!general) {
for(unsigned int ix=0;ix<systems.size();++ix) {
if(systems[ix].type==IF)
reconstructInitialFinalSystem(systems[ix].jets);
}
}
}
// e+e- type
else if(nnun==0&&nnii==0&&nnif==0&&nnf>0&&nni==2) {
// only FS needed
}
// general type
else {
general = true;
}
// final-state systems except for general recon
if(!general) {
for(unsigned int ix=0;ix<systems.size();++ix) {
if(systems[ix].type==F)
reconstructFinalStateSystem(applyBoost,toRest,fromRest,
systems[ix].jets);
}
}
else {
reconstructGeneralSystem(ShowerHardJets);
}
}
}
catch(KinematicsReconstructionVeto) {
_progenitor=tShowerParticlePtr();
_intrinsic.clear();
_currentTree = tShowerTreePtr();
return false;
}
_progenitor=tShowerParticlePtr();
_intrinsic.clear();
// ensure x<1
for(map<ShowerProgenitorPtr,ShowerParticlePtr>::const_iterator
cit=hard->incomingLines().begin();cit!=hard->incomingLines().end();++cit) {
tPPtr parent = cit->first->progenitor();
while (!parent->parents().empty()) {
parent = parent->parents()[0];
}
tPPtr hadron;
if ( cit->first->original()->parents().empty() ) {
hadron = cit->first->original();
}
else {
hadron = cit->first->original()->parents()[0];
}
if( ! (hadron->id() == parent->id() && hadron->children().size() <= 1)
&& parent->momentum().rho() > hadron->momentum().rho()) {
_currentTree = tShowerTreePtr();
return false;
}
}
_currentTree = tShowerTreePtr();
return true;
}
double
QTildeReconstructor::solveKfactor(const Energy & root_s,
const JetKinVect & jets) const {
Energy2 s = sqr(root_s);
// must be at least two jets
if ( jets.size() < 2) throw KinematicsReconstructionVeto();
// sum of jet masses must be less than roots
if(momConsEq( 0.0, root_s, jets )>ZERO) throw KinematicsReconstructionVeto();
// if two jets simple solution
if ( jets.size() == 2 ) {
static const Energy2 eps = 1.0e-4 * MeV2;
if ( sqr(jets[0].p.x()+jets[1].p.x()) < eps &&
sqr(jets[0].p.y()+jets[1].p.y()) < eps &&
sqr(jets[0].p.z()+jets[1].p.z()) < eps ) {
Energy test = (jets[0].p+jets[1].p).vect().mag();
if(test > 1.0e-4 * MeV) throw KinematicsReconstructionVeto();
Energy2 m1sq(jets[0].q.m2()),m2sq(jets[1].q.m2());
return sqrt( ( sqr(s - m1sq - m2sq) - 4.*m1sq*m2sq )
/(4.*s*jets[0].p.vect().mag2()) );
}
else throw KinematicsReconstructionVeto();
}
// i.e. jets.size() > 2, numerically
// check convergence, if it's a problem maybe use Newton iteration?
else {
double k1 = 0.,k2 = 1.,k = 0.;
if ( momConsEq( k1, root_s, jets ) < ZERO ) {
while ( momConsEq( k2, root_s, jets ) < ZERO ) {
k1 = k2;
k2 *= 2;
}
while ( fabs( (k1 - k2)/(k1 + k2) ) > 1.e-10 ) {
if( momConsEq( k2, root_s, jets ) == ZERO ) {
return k2;
} else {
k = (k1+k2)/2.;
if ( momConsEq( k, root_s, jets ) > ZERO ) {
k2 = k;
} else {
k1 = k;
}
}
}
return k1;
} else throw KinematicsReconstructionVeto();
}
throw KinematicsReconstructionVeto();
}
bool QTildeReconstructor::
reconstructSpaceLikeJet( const tShowerParticlePtr p) const {
bool emitted = true;
tShowerParticlePtr child;
tShowerParticlePtr parent;
if(!p->parents().empty())
parent = dynamic_ptr_cast<ShowerParticlePtr>(p->parents()[0]);
if(parent) {
emitted=true;
reconstructSpaceLikeJet(parent);
}
// if branching reconstruct time-like child
if(p->children().size()==2)
child = dynamic_ptr_cast<ShowerParticlePtr>(p->children()[1]);
if(p->perturbative()==0 && child) {
dynamic_ptr_cast<ShowerParticlePtr>(p->children()[0])->
showerKinematics()->reconstructParent(p,p->children());
if(!child->children().empty()) {
_progenitor=child;
reconstructTimeLikeJet(child,0);
// calculate the momentum of the particle
Lorentz5Momentum pnew=p->momentum()-child->momentum();
pnew.rescaleMass();
p->children()[0]->set5Momentum(pnew);
}
}
return emitted;
}
Boost QTildeReconstructor::
solveBoostBeta( const double k, const Lorentz5Momentum & newq,
const Lorentz5Momentum & oldp ) {
// try something different, purely numerical first:
// a) boost to rest frame of newq, b) boost with kp/E
Energy q = newq.vect().mag();
Energy2 qs = sqr(q);
Energy2 Q2 = newq.m2();
Energy kp = k*(oldp.vect().mag());
Energy2 kps = sqr(kp);
// usually we take the minus sign, since this boost will be smaller.
// we only require |k \vec p| = |\vec q'| which leaves the sign of
// the boost open but the 'minus' solution gives a smaller boost
// parameter, i.e. the result should be closest to the previous
// result. this is to be changed if we would get many momentum
// conservation violations at the end of the shower from a hard
// process.
double betam = (q*sqrt(qs + Q2) - kp*sqrt(kps + Q2))/(kps + qs + Q2);
// move directly to 'return'
Boost beta = -betam*(k/kp)*oldp.vect();
// note that (k/kp)*oldp.vect() = oldp.vect()/oldp.vect().mag() but cheaper.
// leave this out if it's running properly!
if ( betam >= 0 ) return beta;
else return Boost(0., 0., 0.);
}
bool QTildeReconstructor::
reconstructDecayJets(ShowerTreePtr decay) const {
_currentTree = decay;
try {
// extract the particles from the ShowerTree
vector<ShowerProgenitorPtr> ShowerHardJets=decay->extractProgenitors();
bool radiated[2]={false,false};
// find the decaying particle and check if particles radiated
ShowerProgenitorPtr initial;
for(unsigned int ix=0;ix<ShowerHardJets.size();++ix) {
// only consider initial-state jets
if(ShowerHardJets[ix]->progenitor()->isFinalState()) {
radiated[1] |=ShowerHardJets[ix]->hasEmitted();
}
else {
initial=ShowerHardJets[ix];
radiated[0]|=ShowerHardJets[ix]->hasEmitted();
}
}
// find boost to the rest frame if needed
Boost boosttorest=-initial->progenitor()->momentum().boostVector();
double gammarest =
initial->progenitor()->momentum().e()/
initial->progenitor()->momentum().mass();
// check if need to boost to rest frame
bool gottaBoost = (boosttorest.mag() > 1e-12);
// if initial state radiation reconstruct the jet and set up the basis vectors
Lorentz5Momentum pjet;
Lorentz5Momentum nvect;
// find the partner
ShowerParticlePtr partner = initial->progenitor()->partner();
Lorentz5Momentum ppartner[2];
if(partner) ppartner[0]=partner->momentum();
// get the n reference vector
if(partner) {
if(initial->progenitor()->showerKinematics()) {
nvect = initial->progenitor()->showerKinematics()->getBasis()[1];
}
else {
Lorentz5Momentum ppartner=initial->progenitor()->partner()->momentum();
if(gottaBoost) ppartner.boost(boosttorest,gammarest);
nvect = Lorentz5Momentum( ZERO,0.5*initial->progenitor()->mass()*
ppartner.vect().unit());
nvect.boost(-boosttorest,gammarest);
}
}
// if ISR
if(radiated[0]) {
// reconstruct the decay jet
reconstructDecayJet(initial->progenitor());
// momentum of decaying particle after ISR
pjet=initial->progenitor()->momentum()
-decay->incomingLines().begin()->second->momentum();
pjet.rescaleMass();
}
// boost initial state jet and basis vector if needed
if(gottaBoost) {
pjet.boost(boosttorest,gammarest);
nvect.boost(boosttorest,gammarest);
ppartner[0].boost(boosttorest,gammarest);
}
// loop over the final-state particles and do the reconstruction
JetKinVect possiblepartners;
JetKinVect jetKinematics;
bool atLeastOnce = radiated[0];
LorentzRotation restboost(boosttorest,gammarest);
Energy inmass(ZERO);
for(unsigned int ix=0;ix<ShowerHardJets.size();++ix) {
// only consider final-state jets
if(!ShowerHardJets[ix]->progenitor()->isFinalState()) {
inmass=ShowerHardJets[ix]->progenitor()->mass();
continue;
}
// do the reconstruction
JetKinStruct tempJetKin;
tempJetKin.parent = ShowerHardJets[ix]->progenitor();
if(ShowerHardJets.size()==2) {
Lorentz5Momentum dum=ShowerHardJets[ix]->progenitor()->momentum();
dum.setMass(inmass);
dum.rescaleRho();
tempJetKin.parent->set5Momentum(dum);
}
tempJetKin.p = ShowerHardJets[ix]->progenitor()->momentum();
if(gottaBoost) tempJetKin.p.boost(boosttorest,gammarest);
_progenitor=tempJetKin.parent;
atLeastOnce |= reconstructTimeLikeJet(tempJetKin.parent,0);
if(gottaBoost) deepTransform(tempJetKin.parent,restboost);
tempJetKin.q = ShowerHardJets[ix]->progenitor()->momentum();
jetKinematics.push_back(tempJetKin);
}
if(partner) ppartner[1]=partner->momentum();
// calculate the rescaling parameters
double k1,k2;
Lorentz5Momentum qt;
if(!solveDecayKFactor(initial->progenitor()->mass(),nvect,pjet,
jetKinematics,partner,ppartner,k1,k2,qt)) {
_currentTree = tShowerTreePtr();
return false;
}
// apply boosts and rescalings to final-state jets
for(JetKinVect::iterator it = jetKinematics.begin();
it != jetKinematics.end(); ++it) {
LorentzRotation Trafo = LorentzRotation();
if(it->parent!=partner) {
// boost for rescaling
if(atLeastOnce) {
map<tShowerTreePtr,pair<tShowerProgenitorPtr,
tShowerParticlePtr> >::const_iterator tit;
for(tit = _currentTree->treelinks().begin();
tit != _currentTree->treelinks().end();++tit) {
if(tit->second.first && tit->second.second==it->parent)
break;
}
if(it->parent->children().empty()&&!it->parent->spinInfo() &&
tit==_currentTree->treelinks().end()) {
Lorentz5Momentum pnew(k2*it->p.vect(),
sqrt(sqr(k2*it->p.vect().mag())+it->q.mass2()),
it->q.mass());
it->parent->set5Momentum(pnew);
}
else {
Trafo = solveBoost(k2, it->q, it->p);
}
}
if(gottaBoost) Trafo.boost(-boosttorest,gammarest);
if(atLeastOnce || gottaBoost) deepTransform(it->parent,Trafo);
}
else {
Lorentz5Momentum pnew=ppartner[0];
pnew *=k1;
pnew-=qt;
pnew.setMass(ppartner[1].mass());
pnew.rescaleEnergy();
LorentzRotation Trafo=solveBoost(1.,ppartner[1],pnew);
if(gottaBoost) Trafo.boost(-boosttorest,gammarest);
deepTransform(partner,Trafo);
}
}
}
catch(KinematicsReconstructionVeto) {
_currentTree = tShowerTreePtr();
return false;
}
_currentTree = tShowerTreePtr();
return true;
}
bool QTildeReconstructor::
reconstructDecayJet( const tShowerParticlePtr p) const {
if(p->children().empty()) return false;
tShowerParticlePtr child;
// if branching reconstruct time-like child
child = dynamic_ptr_cast<ShowerParticlePtr>(p->children()[1]);
if(child) {
_progenitor=child;
reconstructTimeLikeJet(child,1);
// calculate the momentum of the particle
Lorentz5Momentum pnew=p->momentum()-child->momentum();
pnew.rescaleMass();
p->children()[0]->set5Momentum(pnew);
child=dynamic_ptr_cast<ShowerParticlePtr>(p->children()[0]);
reconstructDecayJet(child);
return true;
}
return false;
}
bool QTildeReconstructor::
solveDecayKFactor(Energy mb,
const Lorentz5Momentum & n,
const Lorentz5Momentum & pjet,
const JetKinVect & jetKinematics,
ShowerParticlePtr partner,
Lorentz5Momentum ppartner[2],
double & k1, double & k2,
Lorentz5Momentum & qt) const {
Energy2 pjn = partner ? pjet.vect()*n.vect() : ZERO;
Energy2 pcn = partner ? ppartner[0].vect()*n.vect() : 1.*MeV2;
Energy2 nmag = n.vect().mag2();
Lorentz5Momentum pn = partner ? (pjn/nmag)*n : Lorentz5Momentum();
qt=pjet-pn; qt.setE(ZERO);
Energy2 pt2=qt.vect().mag2();
Energy Ejet = pjet.e();
// magnitudes of the momenta for fast access
vector<Energy2> pmag;
Energy total(Ejet);
Lorentz5Momentum ptest;
for(unsigned int ix=0;ix<jetKinematics.size();++ix) {
pmag.push_back(jetKinematics[ix].p.vect().mag2());
total+=jetKinematics[ix].q.mass();
ptest+=jetKinematics[ix].p;
}
// return if no possible solution
if(total>mb) return false;
Energy2 pcmag=ppartner[0].vect().mag2();
// used newton-raphson to get the rescaling
static const Energy eps=1e-8*GeV;
long double d1(1.),d2(1.);
Energy roots, ea, ec, ds;
unsigned int ix=0;
do {
++ix;
d2 = d1 + pjn/pcn;
roots = Ejet;
ds = ZERO;
for(unsigned int iy=0;iy<jetKinematics.size();++iy) {
if(jetKinematics[iy].parent==partner) continue;
ea = sqrt(sqr(d2)*pmag[iy]+jetKinematics[iy].q.mass2());
roots += ea;
ds += d2/ea*pmag[iy];
}
if(partner) {
ec = sqrt(sqr(d1)*pcmag + pt2 + ppartner[1].mass2());
roots += ec;
ds += d1/ec*pcmag;
}
d1 += (mb-roots)/ds;
d2 = d1 + pjn/pcn;
}
while(abs(mb-roots)>eps && ix<100);
k1=d1;
k2=d2;
// return true if N-R succeed, otherwise false
return ix<100;
}
bool QTildeReconstructor::
deconstructDecayJets(HardTreePtr decay, cEvolverPtr,
ShowerInteraction::Type) const {
// extract the momenta of the particles
vector<Lorentz5Momentum> pin;
vector<Lorentz5Momentum> pout;
// on-shell masses of the decay products
vector<Energy> mon;
Energy mbar(-GeV);
// the hard branchings of the particles
set<HardBranchingPtr>::iterator cit;
set<HardBranchingPtr> branchings=decay->branchings();
// properties of the incoming particle
bool ISR = false;
HardBranchingPtr initial;
Lorentz5Momentum qisr;
// find the incoming particle, both before and after
// any ISR
for(cit=branchings.begin();cit!=branchings.end();++cit){
if((*cit)->status()==HardBranching::Incoming||
(*cit)->status()==HardBranching::Decay) {
// search back up isr if needed
HardBranchingPtr branch = *cit;
while(branch->parent()) branch=branch->parent();
initial=branch;
// momentum or original parent
pin.push_back(branch->branchingParticle()->momentum());
// ISR?
ISR = !branch->branchingParticle()->children().empty();
// ISR momentum
qisr = pin.back()-(**cit).branchingParticle()->momentum();
qisr.rescaleMass();
}
}
assert(pin.size()==1);
// compute boost to rest frame
Boost boostv=-pin[0].boostVector();
// partner for ISR
ShowerParticlePtr partner;
Lorentz5Momentum ppartner;
if(initial->branchingParticle()->partner()) {
partner=initial->branchingParticle()->partner();
ppartner=partner->momentum();
}
// momentum of the decay products
for(cit=branchings.begin();cit!=branchings.end();++cit) {
if((*cit)->status()!=HardBranching::Outgoing) continue;
// find the mass of the particle
// including special treatment for off-shell resonances
// to preserve off-shell mass
Energy mass;
if(!(**cit).branchingParticle()->dataPtr()->stable()) {
HardBranchingPtr branch=*cit;
while(!branch->children().empty()) {
for(unsigned int ix=0;ix<branch->children().size();++ix) {
if(branch->children()[ix]->branchingParticle()->id()==
(**cit).branchingParticle()->id()) {
branch = branch->children()[ix];
continue;
}
}
};
mass = branch->branchingParticle()->mass();
}
else {
mass = (**cit).branchingParticle()->dataPtr()->mass();
}
// if not evolution partner of decaying particle
if((*cit)->branchingParticle()!=partner) {
pout.push_back((*cit)->branchingParticle()->momentum());
mon.push_back(mass);
}
// evolution partner of decaying particle
else {
mbar = mass;
}
}
// boost all the momenta to the rest frame of the decaying particle
for(unsigned int ix=0;ix<pout.size();++ix) pout[ix].boost(boostv);
if(initial->branchingParticle()->partner()) {
ppartner.boost(boostv);
qisr.boost(boostv);
}
// compute the rescaling factors
double k1,k2;
if(!ISR) {
if(partner) {
pout.push_back(ppartner);
mon.push_back(mbar);
}
k1=k2=inverseRescalingFactor(pout,mon,pin[0].mass());
if(partner) {
pout.pop_back();
mon.pop_back();
}
}
else {
if(!inverseDecayRescalingFactor(pout,mon,pin[0].mass(),
ppartner,mbar,k1,k2)) return false;
}
// now calculate the p reference vectors
unsigned int ifinal=0;
for(cit=branchings.begin();cit!=branchings.end();++cit) {
if((**cit).status()!=HardBranching::Outgoing) continue;
// for partners other than colour partner of decaying particle
if((*cit)->branchingParticle()!=partner) {
Lorentz5Momentum pvect = (*cit)->branchingParticle()->momentum();
pvect.boost(boostv);
pvect /= k1;
pvect.setMass(mon[ifinal]);
++ifinal;
pvect.rescaleEnergy();
pvect.boost(-boostv);
(*cit)->pVector(pvect);
(*cit)->showerMomentum(pvect);
}
// for colour partner of decaying particle
else {
Lorentz5Momentum pvect = (*cit)->branchingParticle()->momentum();
pvect.boost(boostv);
Lorentz5Momentum qtotal;
for(unsigned int ix=0;ix<pout.size();++ix) qtotal+=pout[ix];
Lorentz5Momentum qperp =
qisr-(qisr.vect()*qtotal.vect())/(qtotal.vect().mag2())*qtotal;
pvect +=qperp;
pvect /=k2;
pvect.setMass(mbar);
pvect.rescaleEnergy();
pvect.boost(-boostv);
(*cit)->pVector(pvect);
(*cit)->showerMomentum(pvect);
}
}
// // find the evolution partners
// ShowerParticleVector particles;
// particles.push_back((**decay->incoming().begin()).branchingParticle());
// for(cit=branchings.begin();cit!=branchings.end();++cit) {
// if((**cit).status()==HardBranching::Outgoing)
// particles.push_back((*cit)->branchingParticle());
// }
// // partners should
// evolver->showerModel()->partnerFinder()
// ->setInitialEvolutionScales(particles,true,type,false);
// For initial-state if needed
if(initial) {
tShowerParticlePtr newPartner=initial->branchingParticle()->partner();
if(newPartner) {
tHardBranchingPtr branch;
for( set<HardBranchingPtr>::iterator clt = branchings.begin();
clt != branchings.end(); ++clt ) {
if((**clt).branchingParticle()==newPartner) {
initial->colourPartner(*clt);
branch=*clt;
break;
}
}
Lorentz5Momentum pvect = initial->branchingParticle()->momentum();
initial->pVector(pvect);
Lorentz5Momentum ptemp = branch->pVector();
ptemp.boost(boostv);
Lorentz5Momentum nvect = Lorentz5Momentum( ZERO,
0.5*initial->branchingParticle()->mass()*
ptemp.vect().unit());
nvect.boost(-boostv);
initial->nVector(nvect);
}
}
// calculate the reference vectors, then for outgoing particles
for(cit=branchings.begin();cit!=branchings.end();++cit){
if((**cit).status()!=HardBranching::Outgoing) continue;
// find the partner branchings
tShowerParticlePtr newPartner=(*cit)->branchingParticle()->partner();
if(!newPartner) continue;
tHardBranchingPtr branch;
for( set<HardBranchingPtr>::iterator clt = branchings.begin();
clt != branchings.end(); ++clt ) {
if(cit==clt) continue;
if((**clt).branchingParticle()==newPartner) {
(**cit).colourPartner(*clt);
branch=*clt;
break;
}
}
if((**decay->incoming().begin()).branchingParticle()==newPartner) {
(**cit).colourPartner(*decay->incoming().begin());
branch = *decay->incoming().begin();
}
// final-state colour partner
if(branch->status()==HardBranching::Outgoing) {
Boost boost=((*cit)->pVector()+branch->pVector()).findBoostToCM();
Lorentz5Momentum pcm = branch->pVector();
pcm.boost(boost);
Lorentz5Momentum nvect = Lorentz5Momentum(ZERO,pcm.vect());
nvect.boost( -boost);
(*cit)->nVector(nvect);
}
// initial-state colour partner
else {
Boost boost=branch->pVector().findBoostToCM();
Lorentz5Momentum pcm = (*cit)->pVector();
pcm.boost(boost);
Lorentz5Momentum nvect = Lorentz5Momentum( ZERO, -pcm.vect());
nvect.boost( -boost);
(*cit)->nVector(nvect);
}
}
// now compute the new momenta
// and calculate the shower variables
for(cit=branchings.begin();cit!=branchings.end();++cit) {
if((**cit).status()!=HardBranching::Outgoing) continue;
LorentzRotation B=LorentzRotation(-boostv);
LorentzRotation A=LorentzRotation(boostv),R;
if((*cit)->branchingParticle()==partner) {
Lorentz5Momentum qnew;
Energy2 dot=(*cit)->pVector()*(*cit)->nVector();
double beta = 0.5*((*cit)->branchingParticle()->momentum().m2()
-sqr((*cit)->pVector().mass()))/dot;
qnew=(*cit)->pVector()+beta*(*cit)->nVector();
qnew.rescaleMass();
// compute the boost
R=B*solveBoost(A*qnew,A*(*cit)->branchingParticle()->momentum())*A;
}
else {
Lorentz5Momentum qnew;
if((*cit)->branchingParticle()->partner()) {
Energy2 dot=(*cit)->pVector()*(*cit)->nVector();
double beta = 0.5*((*cit)->branchingParticle()->momentum().m2()
-sqr((*cit)->pVector().mass()))/dot;
qnew=(*cit)->pVector()+beta*(*cit)->nVector();
qnew.rescaleMass();
}
else {
qnew = (*cit)->pVector();
}
// compute the boost
R=B*solveBoost(A*qnew,A*(*cit)->branchingParticle()->momentum())*A;
}
// reconstruct the momenta
(*cit)->setMomenta(R,1.0,Lorentz5Momentum());
}
if(initial) {
initial->setMomenta(LorentzRotation(),1.0,Lorentz5Momentum());
}
return true;
}
double QTildeReconstructor::
inverseRescalingFactor(vector<Lorentz5Momentum> pout,
vector<Energy> mon, Energy roots) const {
double lambda=1.;
if(pout.size()==2) {
double mu_q1(pout[0].m()/roots), mu_q2(pout[1].m()/roots);
double mu_p1(mon[0]/roots) , mu_p2(mon[1]/roots);
lambda =
((1.+mu_q1+mu_q2)*(1.-mu_q1-mu_q2)*(mu_q1-1.-mu_q2)*(mu_q2-1.-mu_q1))/
((1.+mu_p1+mu_p2)*(1.-mu_p1-mu_p2)*(mu_p1-1.-mu_p2)*(mu_p2-1.-mu_p1));
if(lambda<0.)
throw Exception() << "Rescaling factor is imaginary in QTildeReconstructor::"
<< "inverseRescalingFactor lambda^2= " << lambda
<< Exception::eventerror;
lambda = sqrt(lambda);
}
else {
unsigned int ntry=0;
// compute magnitudes once for speed
vector<Energy2> pmag;
for(unsigned int ix=0;ix<pout.size();++ix) {
pmag.push_back(pout[ix].vect().mag2());
}
// Newton-Raphson for the rescaling
vector<Energy> root;
root.resize(pout.size());
do {
// compute new energies
Energy sum(ZERO);
for(unsigned int ix=0;ix<pout.size();++ix) {
root[ix] = sqrt(pmag[ix]/sqr(lambda)+sqr(mon[ix]));
sum+=root[ix];
}
// if accuracy reached exit
if(abs(sum/roots-1.)<1e-10) break;
// use Newton-Raphson to compute new guess for lambda
Energy numer(ZERO),denom(ZERO);
for(unsigned int ix=0;ix<pout.size();++ix) {
numer +=root[ix];
denom +=pmag[ix]/root[ix];
}
numer-=roots;
double fact = 1.+sqr(lambda)*numer/denom;
if(fact<0.) fact=0.5;
lambda *=fact;
++ntry;
}
while(ntry<100);
}
if(isnan(lambda))
throw Exception() << "Rescaling factor is nan in QTildeReconstructor::"
<< "inverseRescalingFactor "
<< Exception::eventerror;
return lambda;
}
bool QTildeReconstructor::
deconstructGeneralSystem(HardTreePtr tree,
cEvolverPtr evolver,
ShowerInteraction::Type type) const {
// extract incoming and outgoing particles
ColourSingletShower in,out;
for(set<HardBranchingPtr>::const_iterator it=tree->branchings().begin();
it!=tree->branchings().end();++it) {
if((**it).status()==HardBranching::Incoming) in .jets.push_back(*it);
else out.jets.push_back(*it);
}
// do the initial-state reconstruction
LorentzRotation toRest,fromRest;
bool applyBoost(false);
deconstructInitialInitialSystem(applyBoost,toRest,fromRest,
tree,in.jets,type);
// do the final-state reconstruction
deconstructFinalStateSystem(toRest,fromRest,tree,
out.jets,evolver,type);
// only at this point that we can be sure all the reference vectors
// are correct
for(set<HardBranchingPtr>::const_iterator it=tree->branchings().begin();
it!=tree->branchings().end();++it) {
if((**it).status()==HardBranching::Incoming) continue;
if((**it).branchingParticle()->coloured())
(**it).setMomenta(LorentzRotation(),1.,Lorentz5Momentum(),false);
}
for(set<HardBranchingPtr>::const_iterator it=tree->incoming().begin();
it!=tree->incoming().end();++it) {
(**it).setMomenta(LorentzRotation(),1.,Lorentz5Momentum(),false);
}
return true;
}
bool QTildeReconstructor::deconstructHardJets(HardTreePtr tree,
cEvolverPtr evolver,
ShowerInteraction::Type type) const {
// inverse of old recon method
if(_reconopt==0) {
return deconstructGeneralSystem(tree,evolver,type);
}
// inverse of reconstruction based on coloured systems
else {
// identify the colour singlet systems
vector<ColourSingletShower> systems;
set<HardBranchingPtr> done;
for(set<HardBranchingPtr>::const_iterator it=tree->branchings().begin();
it!=tree->branchings().end();++it) {
// if not treated create new system
if(done.find(*it)!=done.end()) continue;
done.insert(*it);
systems.push_back(ColourSingletShower(UNDEFINED,*it));
if(!(**it).branchingParticle()->coloured()) continue;
// now find the colour connected particles
findPartners(*it,done,tree->branchings(),systems.back().jets);
}
// catagorize the systems
unsigned int nnun(0),nnii(0),nnif(0),nnf(0),nni(0);
for(unsigned int ix=0;ix<systems.size();++ix) {
unsigned int ni(0),nf(0);
for(unsigned int iy=0;iy<systems[ix].jets.size();++iy) {
if(systems[ix].jets[iy]->status()==HardBranching::Outgoing) ++nf;
else ++ni;
}
// type
// initial-initial
if(ni==2&&nf==0) {
systems[ix].type = II;
++nnii;
}
// initial only
else if(ni==1&&nf==0) {
systems[ix].type = I;
++nni;
}
// initial-final
else if(ni==1&&nf>0) {
systems[ix].type = IF;
++nnif;
}
// final only
else if(ni==0&&nf>0) {
systems[ix].type = F;
++nnf;
}
// otherwise unknown
else {
systems[ix].type = UNDEFINED;
++nnun;
}
}
// now decide what to do
LorentzRotation toRest,fromRest;
bool applyBoost(false);
bool general(false);
// initial-initial connection and final-state colour singlet systems
// Drell-Yan type
if(nnun==0&&nnii==1&&nnif==0&&nnf>0&&nni==0) {
// reconstruct initial-initial system
for(unsigned int ix=0;ix<systems.size();++ix) {
if(systems[ix].type==II)
deconstructInitialInitialSystem(applyBoost,toRest,fromRest,tree,
systems[ix].jets,type);
}
}
// DIS and VBF type
else if(nnun==0&&nnii==0&&((nnif==1&&nnf>0&&nni==1)||
(nnif==2&& nni==0))) {
for(unsigned int ix=0;ix<systems.size();++ix) {
if(systems[ix].type==IF)
deconstructInitialFinalSystem(tree,systems[ix].jets,evolver,type);
}
}
// e+e- type
else if(nnun==0&&nnii==0&&nnif==0&&nnf>0&&nni==2) {
// only FS needed
// but need to boost to rest frame if QED ISR
Lorentz5Momentum ptotal;
for(unsigned int ix=0;ix<systems.size();++ix) {
if(systems[ix].type==I)
ptotal += systems[ix].jets[0]->branchingParticle()->momentum();
}
toRest = LorentzRotation(ptotal.findBoostToCM());
fromRest = toRest;
fromRest.invert();
}
// general type
else {
general = true;
}
// final-state systems except for general recon
if(!general) {
for(unsigned int ix=0;ix<systems.size();++ix) {
if(systems[ix].type==F)
deconstructFinalStateSystem(toRest,fromRest,tree,
systems[ix].jets,evolver,type);
}
}
else {
return deconstructGeneralSystem(tree,evolver,type);
}
return true;
}
}
vector<unsigned int> QTildeReconstructor::
findPartners(unsigned int iloc ,
vector<ShowerProgenitorPtr> jets) const {
vector<unsigned int> output;
for(unsigned int iy=0;iy<jets.size();++iy) {
if(!jets[iy]->progenitor()->data().coloured()||iy==iloc) continue;
bool isPartner = false;
// both in either initial or final state
if(jets[iloc]->progenitor()->isFinalState()!=jets[iy]->progenitor()->isFinalState()) {
//loop over all the colours of both
for(unsigned int ix=0; ix<CLSIZE(jets[iloc]); ++ix){
for(unsigned int jx=0; jx<CLSIZE(jets[iy]); ++jx){
if(CL(jets[iloc],ix) && CL(jets[iloc],ix)==CL(jets[iy],jx))
isPartner = true;
}
}
if(!isPartner){
//loop over anti colours of both
for(unsigned int ix=0; ix<ACLSIZE(jets[iloc]); ++ix){
for(unsigned int jx=0; jx<ACLSIZE(jets[iy]); ++jx){
if(ACL(jets[iloc],ix) && ACL(jets[iloc],ix)==ACL(jets[iy],jx))
isPartner = true;
}
}
}
}
else{
//loop over the colours of the first and the anti-colours of the other
for(unsigned int ix=0; ix<CLSIZE(jets[iloc]); ++ix){
for(unsigned int jx=0; jx<ACLSIZE(jets[iy]); ++jx){
if(CL(jets[iloc],ix) && CL(jets[iloc],ix)==ACL(jets[iy],jx))
isPartner = true;
}
}
if(!isPartner){
//loop over the anti-colours of the first and the colours of the other
for(unsigned int ix=0; ix<ACLSIZE(jets[iloc]); ++ix){
for(unsigned int jx=0; jx<CLSIZE(jets[iy]); jx++){
if(ACL(jets[iloc],ix) && ACL(jets[iloc],ix)==CL(jets[iy],jx))
isPartner = true;
}
}
}
}
// special for sources/sinks
if(jets[iloc]->progenitor()->colourLine()) {
if(jets[iloc]->progenitor()->colourLine()->sourceNeighbours().first) {
tColinePair lines = jets[iloc]->progenitor()->colourLine()->sourceNeighbours();
if(lines.first == jets[iy]->progenitor()-> colourLine() ||
lines.first == jets[iy]->progenitor()-> colourLine() ||
lines.second == jets[iy]->progenitor()->antiColourLine() ||
lines.second == jets[iy]->progenitor()->antiColourLine())
isPartner = true;
}
if(jets[iloc]->progenitor()->colourLine()->sinkNeighbours().first) {
tColinePair lines = jets[iloc]->progenitor()->colourLine()->sinkNeighbours();
if(lines.first == jets[iy]->progenitor()-> colourLine() ||
lines.first == jets[iy]->progenitor()-> colourLine() ||
lines.second == jets[iy]->progenitor()->antiColourLine() ||
lines.second == jets[iy]->progenitor()->antiColourLine())
isPartner = true;
}
}
if(jets[iloc]->progenitor()->antiColourLine()) {
if(jets[iloc]->progenitor()->antiColourLine()->sourceNeighbours().first) {
tColinePair lines = jets[iloc]->progenitor()->antiColourLine()->sourceNeighbours();
if(lines.first == jets[iy]->progenitor()-> colourLine() ||
lines.first == jets[iy]->progenitor()-> colourLine() ||
lines.second == jets[iy]->progenitor()->antiColourLine() ||
lines.second == jets[iy]->progenitor()->antiColourLine())
isPartner = true;
}
if(jets[iloc]->progenitor()->antiColourLine()->sinkNeighbours().first) {
tColinePair lines = jets[iloc]->progenitor()->antiColourLine()->sinkNeighbours();
if(lines.first == jets[iy]->progenitor()-> colourLine() ||
lines.first == jets[iy]->progenitor()-> colourLine() ||
lines.second == jets[iy]->progenitor()->antiColourLine() ||
lines.second == jets[iy]->progenitor()->antiColourLine())
isPartner = true;
}
}
if(isPartner)
output.push_back(iy);
}
return output;
}
void QTildeReconstructor::
reconstructInitialFinalSystem(vector<ShowerProgenitorPtr> jets) const {
Lorentz5Momentum pin[2],pout[2];
bool atLeastOnce(false);
for(unsigned int ix=0;ix<jets.size();++ix) {
// final-state parton
if(jets[ix]->progenitor()->isFinalState()) {
pout[0] +=jets[ix]->progenitor()->momentum();
_progenitor = jets[ix]->progenitor();
atLeastOnce |= reconstructTimeLikeJet(jets[ix]->progenitor(),0);
}
// initial-state parton
else {
pin[0] +=jets[ix]->progenitor()->momentum();
atLeastOnce |= reconstructSpaceLikeJet(jets[ix]->progenitor());
assert(!jets[ix]->original()->parents().empty());
}
}
// add intrinsic pt if needed
atLeastOnce |= addIntrinsicPt(jets);
// momenta after showering
for(unsigned int ix=0;ix<jets.size();++ix) {
if(jets[ix]->progenitor()->isFinalState())
pout[1] += jets[ix]->progenitor()->momentum();
else
pin[1] += jets[ix]->progenitor()->momentum();
}
// work out the boost to the Breit frame
Lorentz5Momentum pa = pout[0]-pin[0];
Lorentz5Momentum pb = pin[0];
Axis axis(pa.vect().unit());
LorentzRotation rot;
double sinth(sqrt(sqr(axis.x())+sqr(axis.y())));
rot.setRotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.));
rot.rotateX(Constants::pi);
rot.boostZ( pa.e()/pa.vect().mag());
Lorentz5Momentum ptemp=rot*pb;
Boost trans = -1./ptemp.e()*ptemp.vect();
trans.setZ(0.);
rot.boost(trans);
pa *=rot;
// project and calculate rescaling
// reference vectors
Lorentz5Momentum n1(ZERO,ZERO,-pa.z(),-pa.z());
Lorentz5Momentum n2(ZERO,ZERO, pa.z(),-pa.z());
Energy2 n1n2 = n1*n2;
// decompose the momenta
Lorentz5Momentum qbp=rot*pin[1],qcp= rot*pout[1];
double a[2],b[2];
a[0] = n2*qbp/n1n2;
b[0] = n1*qbp/n1n2;
Lorentz5Momentum qperp = qbp-a[0]*n1-b[0]*n2;
a[1] = 0.5*(qcp.m2()-qperp.m2())/n1n2;
b[1] = 1.;
double A(0.5*a[0]),B(b[0]*a[0]-a[1]*b[1]-0.25),C(-0.5*b[0]);
if(sqr(B)-4.*A*C<0.) throw KinematicsReconstructionVeto();
double kb = 0.5*(-B+sqrt(sqr(B)-4.*A*C))/A;
double kc = (a[0]*kb-0.5)/a[1];
if(kc==0.) throw KinematicsReconstructionVeto();
Lorentz5Momentum pnew[2] = { a[0]*kb*n1+b[0]/kb*n2+qperp,
a[1]*kc*n1+b[1]/kc*n2+qperp};
LorentzRotation rotinv=rot.inverse();
LorentzRotation transb=rotinv*solveBoostZ(pnew[0],qbp)*rot;
LorentzRotation transc=rotinv*solveBoost(pnew[1],qcp)*rot;
for(unsigned int ix=0;ix<jets.size();++ix) {
if(jets[ix]->progenitor()->isFinalState())
deepTransform(jets[ix]->progenitor(),transc);
else {
tPPtr parent;
boostChain(jets[ix]->progenitor(),transb,parent);
}
}
}
bool QTildeReconstructor::addIntrinsicPt(vector<ShowerProgenitorPtr> jets) const {
bool added=false;
// add the intrinsic pt if needed
for(unsigned int ix=0;ix<jets.size();++ix) {
// only for initial-state particles which haven't radiated
if(jets[ix]->progenitor()->isFinalState()||
jets[ix]->hasEmitted()) continue;
if(_intrinsic.find(jets[ix])==_intrinsic.end()) continue;
pair<Energy,double> pt=_intrinsic[jets[ix]];
Energy etemp = jets[ix]->original()->parents()[0]->momentum().z();
Lorentz5Momentum
p_basis(ZERO, ZERO, etemp, abs(etemp)),
n_basis(ZERO, ZERO,-etemp, abs(etemp));
double alpha = jets[ix]->progenitor()->x();
double beta = 0.5*(sqr(jets[ix]->progenitor()->data().mass())+
sqr(pt.first))/alpha/(p_basis*n_basis);
Lorentz5Momentum pnew=alpha*p_basis+beta*n_basis;
pnew.setX(pt.first*cos(pt.second));
pnew.setY(pt.first*sin(pt.second));
pnew.rescaleMass();
jets[ix]->progenitor()->set5Momentum(pnew);
added = true;
}
return added;
}
LorentzRotation QTildeReconstructor::
solveBoost(const double k, const Lorentz5Momentum & newq,
const Lorentz5Momentum & oldp ) const {
Energy q = newq.vect().mag();
Energy2 qs = sqr(q);
Energy2 Q2 = newq.mass2();
Energy kp = k*(oldp.vect().mag());
Energy2 kps = sqr(kp);
double betam = (q*newq.e() - kp*sqrt(kps + Q2))/(kps + qs + Q2);
Boost beta = -betam*(k/kp)*oldp.vect();
// note that (k/kp)*oldp.vect() = oldp.vect()/oldp.vect().mag() but cheaper.
ThreeVector<Energy2> ax = newq.vect().cross( oldp.vect() );
double delta = newq.vect().angle( oldp.vect() );
LorentzRotation R;
using Constants::pi;
if ( ax.mag2()/GeV2/MeV2 > 1e-16 ) {
R.rotate( delta, unitVector(ax) ).boost( beta );
}
else if(abs(delta-pi)/pi < 0.001) {
double phi=2.*pi*UseRandom::rnd();
Axis axis(cos(phi),sin(phi),0.);
axis.rotateUz(newq.vect().unit());
R.rotate(delta,axis).boost( beta );
}
else {
R.boost( beta );
}
return R;
}
LorentzRotation QTildeReconstructor::solveBoost(const Lorentz5Momentum & q,
const Lorentz5Momentum & p ) const {
Energy modp = p.vect().mag();
Energy modq = q.vect().mag();
double betam = (p.e()*modp-q.e()*modq)/(sqr(modq)+sqr(modp)+p.mass2());
Boost beta = -betam*q.vect().unit();
ThreeVector<Energy2> ax = p.vect().cross( q.vect() );
double delta = p.vect().angle( q.vect() );
LorentzRotation R;
using Constants::pi;
if ( ax.mag2()/GeV2/MeV2 > 1e-16 ) {
R.rotate( delta, unitVector(ax) ).boost( beta );
}
else {
R.boost( beta );
}
return R;
}
LorentzRotation QTildeReconstructor::solveBoostZ(const Lorentz5Momentum & q,
const Lorentz5Momentum & p ) const {
static const Energy2 eps2 = 1e-8*GeV2;
static const Energy eps = 1e-4 *GeV;
LorentzRotation R;
double beta;
Energy2 den = (p.t()*q.t()-p.z()*q.z());
Energy2 num = -(p.z()*q.t()-q.z()*p.t());
if(abs(den)<eps2||abs(num)<eps2) {
if(abs(p.t()-abs(p.z()))<eps&&abs(q.t()-abs(q.z()))<eps) {
double ratio = sqr(q.t()/p.t());
beta = -(1.-ratio)/(1.+ratio);
}
else {
beta=0.;
}
}
else {
beta = num/den;
}
R.boostZ(beta);
Lorentz5Momentum ptest = R*p;
if(ptest.z()/q.z() < 0. || ptest.t()/q.t() < 0. ) {
throw KinematicsReconstructionVeto();
}
return R;
}
void QTildeReconstructor::
reconstructFinalStateSystem(bool applyBoost,
const LorentzRotation & toRest,
const LorentzRotation & fromRest,
vector<ShowerProgenitorPtr> jets) const {
// special for case of individual particle
if(jets.size()==1) {
LorentzRotation trans(toRest);
trans.transform(fromRest);
deepTransform(jets[0]->progenitor(),trans);
return;
}
bool radiated(false);
// find the hard process centre-of-mass energy
Lorentz5Momentum pcm;
// check if radiated and calculate total momentum
for(unsigned int ix=0;ix<jets.size();++ix) {
radiated |=jets[ix]->hasEmitted();
pcm += jets[ix]->progenitor()->momentum();
}
// check if in CMF frame
Boost beta_cm = pcm.findBoostToCM();
bool gottaBoost = (beta_cm.mag() > 1e-12);
// collection of pointers to initial hard particle and jet momenta
// for final boosts
JetKinVect jetKinematics;
vector<ShowerProgenitorPtr>::const_iterator cit;
for(cit = jets.begin(); cit != jets.end(); cit++) {
JetKinStruct tempJetKin;
tempJetKin.parent = (*cit)->progenitor();
if(gottaBoost) {
tempJetKin.parent->boost(beta_cm);
map<tShowerTreePtr,pair<tShowerProgenitorPtr,
tShowerParticlePtr> >::const_iterator tit;
for(tit = _currentTree->treelinks().begin();
tit != _currentTree->treelinks().end();++tit) {
if(tit->second.first && tit->second.second==tempJetKin.parent)
tit->first->transform(LorentzRotation(beta_cm),false);
}
}
tempJetKin.p = (*cit)->progenitor()->momentum();
_progenitor=tempJetKin.parent;
radiated |= reconstructTimeLikeJet((*cit)->progenitor(),0);
tempJetKin.q = (*cit)->progenitor()->momentum();
jetKinematics.push_back(tempJetKin);
}
// find the rescaling factor
double k = 0.0;
if(radiated) {
k = solveKfactor(pcm.m(), jetKinematics);
}
// perform the rescaling and boosts
for(JetKinVect::iterator it = jetKinematics.begin();
it != jetKinematics.end(); ++it) {
LorentzRotation Trafo = LorentzRotation();
if(radiated) Trafo = solveBoost(k, it->q, it->p);
if(gottaBoost) Trafo.boost(-beta_cm);
if(applyBoost) {
Trafo.transform( toRest);
Trafo.transform(fromRest);
}
if(radiated || gottaBoost || applyBoost) deepTransform(it->parent,Trafo);
}
}
void QTildeReconstructor::
reconstructInitialInitialSystem(bool & applyBoost,
LorentzRotation & toRest,
LorentzRotation & fromRest,
vector<ShowerProgenitorPtr> jets) const {
bool radiated = false;
Lorentz5Momentum pcm;
// check whether particles radiated and calculate total momentum
for( unsigned int ix = 0; ix < jets.size(); ++ix ) {
radiated |= jets[ix]->hasEmitted();
pcm += jets[ix]->progenitor()->momentum();
}
// check if intrinsic pt to be added
radiated |= !_intrinsic.empty();
// if no radiation return
if(!radiated) return;
// initial state shuffling
applyBoost=false;
vector<Lorentz5Momentum> p, pq, p_in;
for(unsigned int ix=0;ix<jets.size();++ix) {
// at momentum to vector
p_in.push_back(jets[ix]->progenitor()->momentum());
// reconstruct the jet
radiated |= reconstructSpaceLikeJet(jets[ix]->progenitor());
assert(!jets[ix]->original()->parents().empty());
Energy etemp = jets[ix]->original()->parents()[0]->momentum().z();
Lorentz5Momentum ptemp = Lorentz5Momentum(ZERO, ZERO, etemp, abs(etemp));
pq.push_back(ptemp);
}
// add the intrinsic pt if needed
radiated |=addIntrinsicPt(jets);
for(unsigned int ix=0;ix<jets.size();++ix) {
p.push_back(jets[ix]->progenitor()->momentum());
}
double x1 = p_in[0].z()/pq[0].z();
double x2 = p_in[1].z()/pq[1].z();
Energy MDY = (p_in[0] + p_in[1]).m();
Energy2 S = (pq[0]+pq[1]).m2();
// if not need don't apply boosts
if(!(radiated && p.size() == 2 && pq.size() == 2)) return;
applyBoost=true;
// find alphas and betas in terms of desired basis
Energy2 p12 = pq[0]*pq[1];
double a[2] = {p[0]*pq[1]/p12,p[1]*pq[1]/p12};
double b[2] = {p[0]*pq[0]/p12,p[1]*pq[0]/p12};
Lorentz5Momentum p1p = p[0] - a[0]*pq[0] - b[0]*pq[1];
Lorentz5Momentum p2p = p[1] - a[1]*pq[0] - b[1]*pq[1];
// compute kappa
Energy2 A = a[0]*b[1]*S;
Energy2 B = Energy2(sqr(MDY)) - (a[0]*b[0]+a[1]*b[1])*S - (p1p+p2p).m2();
Energy2 C = a[1]*b[0]*S;
double rad = 1.-4.*A*C/sqr(B);
if(rad < 0.) throw KinematicsReconstructionVeto();
double kp = B/(2.*A)*(1.+sqrt(rad));
// now compute k1, k2
rad = kp*(b[0]+kp*b[1])/(kp*a[0]+a[1])*(x1/x2);
if(rad <= 0.) throw KinematicsReconstructionVeto();
double k1 = sqrt(rad);
double k2 = kp/k1;
double beta[2] =
{getBeta((a[0]+b[0]), (a[0]-b[0]), (k1*a[0]+b[0]/k1), (k1*a[0]-b[0]/k1)),
getBeta((a[1]+b[1]), (a[1]-b[1]), (a[1]/k2+k2*b[1]), (a[1]/k2-k2*b[1]))};
if (pq[0].z() > ZERO) {
beta[0] = -beta[0];
beta[1] = -beta[1];
}
// apply the boosts
Lorentz5Momentum newcmf;
for(unsigned int ix=0;ix<jets.size();++ix) {
tPPtr toBoost = jets[ix]->progenitor();
Boost betaboost(0, 0, beta[ix]);
tPPtr parent;
boostChain(toBoost, LorentzRotation(betaboost),parent);
if(parent->momentum().e()/pq[ix].e()>1.||
parent->momentum().z()/pq[ix].z()>1.) throw KinematicsReconstructionVeto();
newcmf+=toBoost->momentum();
}
if(newcmf.m()<ZERO||newcmf.e()<ZERO) throw KinematicsReconstructionVeto();
// do one boost
toRest = LorentzRotation(pcm.findBoostToCM());
if(_initialBoost==0) {
fromRest = LorentzRotation(newcmf.boostVector());
}
else if(_initialBoost==1) {
// first apply longitudinal boost
double beta = newcmf.z()/sqrt(newcmf.m2()+sqr(newcmf.z()));
fromRest=LorentzRotation(Boost(0.,0.,beta));
// then transverse one
Energy pT = sqrt(sqr(newcmf.x())+sqr(newcmf.y()));
beta = pT/newcmf.t();
fromRest.boost(Boost(beta*newcmf.x()/pT,beta*newcmf.y()/pT,0.));
}
else
assert(false);
}
void QTildeReconstructor::
deconstructInitialInitialSystem(bool & applyBoost,
LorentzRotation & toRest,
LorentzRotation & fromRest,
HardTreePtr tree,
vector<HardBranchingPtr> jets,
ShowerInteraction::Type) const {
// get the momenta of the particles
vector<Lorentz5Momentum> pin;
vector<Lorentz5Momentum> pq;
vector<HardBranchingPtr>::iterator cit;
for(cit=jets.begin();cit!=jets.end();++cit) {
pin.push_back((*cit)->branchingParticle()->momentum());
Energy etemp = (*cit)->beam()->momentum().z();
pq.push_back(Lorentz5Momentum(ZERO, ZERO,etemp, abs(etemp)));
}
bool order = (*tree->incoming().begin())->beam()->momentum().z()/pq[0].z()<0.;
assert(pin.size()==2);
// decompose the momenta
double alpha[2],beta[2];
Energy2 p12=pq[0]*pq[1];
Lorentz5Momentum pt[2];
for(unsigned int ix=0;ix<2;++ix) {
alpha[ix] = pin[ix]*pq[1]/p12;
beta [ix] = pin[ix]*pq[0]/p12;
pt[ix] = pin[ix]-alpha[ix]*pq[0]-beta[ix]*pq[1];
}
// parton level centre-of-mass
Lorentz5Momentum pcm=pin[0]+pin[1];
pcm.rescaleMass();
double rap=pcm.rapidity();
// hadron level cmf
Energy2 s = (pq[0] +pq[1] ).m2();
// calculate the x values
double x0 = sqrt(pcm.mass2()/s*exp(2.*rap));
double x[2]={x0, pcm.mass2()/s/x0};
if(pq[0].z()<ZERO) swap(x[0],x[1]);
double k1=alpha[0]/x[0],k2=beta[1]/x[1];
double alphanew[2]={alpha[0]/k1,alpha[1]*k2};
double betanew [2]={beta [0]*k1,beta [1]/k2};
double boost[2];
for(unsigned int ix=0;ix<2;++ix) {
boost[ix] = getBeta(alpha [ix]+beta [ix], alpha[ix] -beta [ix],
alphanew[ix]+betanew[ix], alphanew[ix]-betanew[ix]);
if (pq[0].z() > ZERO) beta[ix]*=-1.;
}
// apply the boost the the particles
// first incoming particle
if(order) swap(pq[0],pq[1]);
// now apply the boosts
Boost betaboost(0.,0.,-boost[0]);
LorentzRotation R;
R.boost(betaboost);
set<HardBranchingPtr>::const_iterator cjt=tree->incoming().begin();
(*cjt)->pVector(pq[0]);
(*cjt)->nVector(pq[1]);
(*cjt)->setMomenta(R,1.,Lorentz5Momentum());
// second incoming particle
betaboost = Boost(0.,0.,-boost[1]);
R=LorentzRotation(betaboost);
++cjt;
(*cjt)->pVector(pq[1]);
(*cjt)->nVector(pq[0]);
(*cjt)->setMomenta(R,1.,Lorentz5Momentum());
jets[0]->showerMomentum(x[0]*jets[0]->pVector());
jets[1]->showerMomentum(x[1]*jets[1]->pVector());
// and calculate the boosts
applyBoost=true;
// do one boost
if(_initialBoost==0) {
toRest = LorentzRotation(-pcm.boostVector());
}
else if(_initialBoost==1) {
// first the transverse boost
Energy pT = sqrt(sqr(pcm.x())+sqr(pcm.y()));
double beta = -pT/pcm.t();
toRest=LorentzRotation(Boost(beta*pcm.x()/pT,beta*pcm.y()/pT,0.));
// the longitudinal
beta = pcm.z()/sqrt(pcm.m2()+sqr(pcm.z()));
toRest.boost(Boost(0.,0.,-beta));
}
else
assert(false);
fromRest = LorentzRotation((jets[0]->showerMomentum()+
jets[1]->showerMomentum()).boostVector());
}
void QTildeReconstructor::
deconstructFinalStateSystem(const LorentzRotation & toRest,
const LorentzRotation & fromRest,
HardTreePtr tree, vector<HardBranchingPtr> jets,
cEvolverPtr evolver,
ShowerInteraction::Type type) const {
if(jets.size()==1) {
LorentzRotation R(toRest);
R.transform(fromRest);
// \todo What does this do? tree->showerRot( R );
jets[0]->original(R*jets[0]->branchingParticle()->momentum());
jets[0]->showerMomentum(R*jets[0]->branchingParticle()->momentum());
// find the colour partners
ShowerParticleVector particles;
vector<Lorentz5Momentum> ptemp;
set<HardBranchingPtr>::const_iterator cjt;
for(cjt=tree->branchings().begin();cjt!=tree->branchings().end();++cjt) {
ptemp.push_back((**cjt).branchingParticle()->momentum());
(**cjt).branchingParticle()->set5Momentum((**cjt).showerMomentum());
particles.push_back((**cjt).branchingParticle());
}
evolver->showerModel()->partnerFinder()
->setInitialEvolutionScales(particles,false,type,false);
// calculate the reference vectors
unsigned int iloc(0);
set<HardBranchingPtr>::iterator clt;
for(cjt=tree->branchings().begin();cjt!=tree->branchings().end();++cjt) {
// reset the momentum
(**cjt).branchingParticle()->set5Momentum(ptemp[iloc]);
++iloc;
// sort out the partners
tShowerParticlePtr partner =
(*cjt)->branchingParticle()->partner();
if(!partner) continue;
for(clt=tree->branchings().begin();clt!=tree->branchings().end();++clt) {
if((**clt).branchingParticle()==partner) {
(**cjt).colourPartner(*clt);
break;
}
}
tHardBranchingPtr branch;
for(clt=tree->branchings().begin();clt!=tree->branchings().end();++clt) {
if(clt==cjt) continue;
if((*clt)->branchingParticle()==partner) {
branch=*clt;
break;
}
}
}
return;
}
vector<HardBranchingPtr>::iterator cit;
vector<Lorentz5Momentum> pout;
vector<Energy> mon;
for(cit=jets.begin();cit!=jets.end();++cit) {
pout.push_back((*cit)->branchingParticle()->momentum());
// KH - 230909 - If the particle has no children then it will
// not have showered and so it should be "on-shell" so we can
// get it's mass from it's momentum. This means that the
// inverseRescalingFactor doesn't give any nans or do things
// it shouldn't if it gets e.g. two Z bosons generated with
// off-shell masses. This is for sure not the best solution.
// PR 1/1/10 modification to previous soln
if((*cit)->branchingParticle()->children().size()==0 ||
(!(*cit)->branchingParticle()->dataPtr()->coloured() &&
!(*cit)->branchingParticle()->dataPtr()->stable()) )
mon.push_back(pout.back().mass());
else
mon.push_back((*cit)->branchingParticle()->dataPtr()->mass());
}
// boost all the momenta to the rest frame of the decaying particle
Lorentz5Momentum pin;
for(unsigned int ix=0;ix<pout.size();++ix) {
pout[ix].transform(toRest);
pin += pout[ix];
}
pin.rescaleMass();
// rescaling factor
double lambda=inverseRescalingFactor(pout,mon,pin.mass());
// now calculate the p reference vectors
for(cit=jets.begin();cit!=jets.end();++cit){
Lorentz5Momentum pvect = (*cit)->branchingParticle()->momentum();
pvect.transform(toRest);
pvect /= lambda;
if((*cit)->branchingParticle()->children().size()==0 ||
(!(*cit)->branchingParticle()->dataPtr()->coloured() &&
!(*cit)->branchingParticle()->dataPtr()->stable()) )
pvect.setMass((*cit)->branchingParticle()->momentum().mass());
else
pvect.setMass((*cit)->branchingParticle()->dataPtr()->mass());
pvect.rescaleEnergy();
pvect.transform(fromRest);
(*cit)->pVector(pvect);
(*cit)->showerMomentum(pvect);
}
// find the colour partners
ShowerParticleVector particles;
vector<Lorentz5Momentum> ptemp;
set<HardBranchingPtr>::const_iterator cjt;
for(cjt=tree->branchings().begin();cjt!=tree->branchings().end();++cjt) {
ptemp.push_back((**cjt).branchingParticle()->momentum());
(**cjt).branchingParticle()->set5Momentum((**cjt).showerMomentum());
particles.push_back((**cjt).branchingParticle());
}
evolver->showerModel()->partnerFinder()
->setInitialEvolutionScales(particles,false,type,false);
// calculate the reference vectors
unsigned int iloc(0);
set<HardBranchingPtr>::iterator clt;
for(cjt=tree->branchings().begin();cjt!=tree->branchings().end();++cjt) {
// reset the momentum
(**cjt).branchingParticle()->set5Momentum(ptemp[iloc]);
++iloc;
}
for(cjt=tree->branchings().begin();cjt!=tree->branchings().end();++cjt) {
// sort out the partners
tShowerParticlePtr partner =
(*cjt)->branchingParticle()->partner();
if(!partner) continue;
for(clt=tree->branchings().begin();clt!=tree->branchings().end();++clt) {
if((**clt).branchingParticle()==partner) {
(**cjt).colourPartner(*clt);
break;
}
}
tHardBranchingPtr branch;
for(clt=tree->branchings().begin();clt!=tree->branchings().end();++clt) {
if(clt==cjt) continue;
if((*clt)->branchingParticle()==partner) {
branch=*clt;
break;
}
}
// compute the reference vectors
// both incoming, should all ready be done
if((**cjt).status()==HardBranching::Incoming &&
(**clt).status()==HardBranching::Incoming) {
continue;
}
// both outgoing
else if(!(**cjt).status()==HardBranching::Incoming&&
branch->status()==HardBranching::Outgoing) {
Boost boost=((*cjt)->pVector()+branch->pVector()).findBoostToCM();
Lorentz5Momentum pcm = branch->pVector();
pcm.boost(boost);
Lorentz5Momentum nvect = Lorentz5Momentum(ZERO,pcm.vect());
nvect.boost( -boost);
(**cjt).nVector(nvect);
}
else if((**cjt).status()==HardBranching::Incoming) {
Lorentz5Momentum pa = -(**cjt).showerMomentum()+branch->showerMomentum();
Lorentz5Momentum pb = (**cjt).showerMomentum();
Axis axis(pa.vect().unit());
LorentzRotation rot;
double sinth(sqrt(sqr(axis.x())+sqr(axis.y())));
rot.setRotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.));
rot.rotateX(Constants::pi);
rot.boostZ( pa.e()/pa.vect().mag());
pb*=rot;
Boost trans = -1./pb.e()*pb.vect();
trans.setZ(0.);
rot.boost(trans);
Energy scale=(**cjt).beam()->momentum().e();
Lorentz5Momentum pbasis(ZERO,(**cjt).beam()->momentum().vect().unit()*scale);
Lorentz5Momentum pcm = rot*pbasis;
rot.invert();
(**cjt).nVector(rot*Lorentz5Momentum(ZERO,-pcm.vect()));
tHardBranchingPtr branch2 = *cjt;;
while (branch2->parent()) {
branch2=branch2->parent();
branch2->nVector(rot*Lorentz5Momentum(ZERO,-pcm.vect()));
}
}
else if(branch->status()==HardBranching::Incoming) {
(**cjt).nVector(Lorentz5Momentum(ZERO,branch->showerMomentum().vect()));
}
}
// now compute the new momenta
for(cjt=tree->branchings().begin();cjt!=tree->branchings().end();++cjt) {
if(!(*cjt)->branchingParticle()->isFinalState()) continue;
Lorentz5Momentum qnew;
if((*cjt)->branchingParticle()->partner()) {
Energy2 dot=(*cjt)->pVector()*(*cjt)->nVector();
double beta = 0.5*((*cjt)->branchingParticle()->momentum().m2()
-sqr((*cjt)->pVector().mass()))/dot;
qnew=(*cjt)->pVector()+beta*(*cjt)->nVector();
qnew.rescaleMass();
}
else {
qnew = (*cjt)->pVector();
}
// qnew is the unshuffled momentum in the rest frame of the p basis vectors,
// for the simple case Z->q qbar g this was checked against analytic formulae.
// compute the boost
LorentzRotation R=solveBoost(qnew,
toRest*(*cjt)->branchingParticle()->momentum())*toRest;
(*cjt)->setMomenta(R,1.0,Lorentz5Momentum());
}
}
Energy QTildeReconstructor::momConsEq(const double & k,
const Energy & root_s,
const JetKinVect & jets) const {
static const Energy2 eps=1e-8*GeV2;
Energy dum = ZERO;
for(JetKinVect::const_iterator it = jets.begin(); it != jets.end(); ++it) {
Energy2 dum2 = (it->q).m2() + sqr(k)*(it->p).vect().mag2();
if(dum2 < ZERO) {
if(dum2 < -eps) throw KinematicsReconstructionVeto();
dum2 = ZERO;
}
dum += sqrt(dum2);
}
return dum - root_s;
}
void QTildeReconstructor::boostChain(tPPtr p, const LorentzRotation &bv,
tPPtr & parent) const {
if(!p->parents().empty()) boostChain(p->parents()[0], bv,parent);
else parent=p;
p->transform(bv);
if(p->children().size()==2) {
if(dynamic_ptr_cast<ShowerParticlePtr>(p->children()[1]))
deepTransform(p->children()[1],bv);
}
}
void QTildeReconstructor::
reconstructGeneralSystem(vector<ShowerProgenitorPtr> & ShowerHardJets) const {
// general recon, all initial-state in one system and final-state
// in another
ColourSingletSystem in,out;
for(unsigned int ix=0;ix<ShowerHardJets.size();++ix) {
if(ShowerHardJets[ix]->progenitor()->isFinalState())
out.jets.push_back(ShowerHardJets[ix]);
else
in.jets.push_back(ShowerHardJets[ix]);
}
// reconstruct initial-initial system
LorentzRotation toRest,fromRest;
bool applyBoost(false);
reconstructInitialInitialSystem(applyBoost,toRest,fromRest,in.jets);
// reconstruct the final-state systems
reconstructFinalStateSystem(applyBoost,toRest,fromRest,out.jets);
}
bool QTildeReconstructor::
inverseDecayRescalingFactor(vector<Lorentz5Momentum> pout,
vector<Energy> mon,Energy roots,
Lorentz5Momentum ppartner, Energy mbar,
double & k1, double & k2) const {
ThreeVector<Energy> qtotal;
vector<Energy2> pmag;
for(unsigned int ix=0;ix<pout.size();++ix) {
pmag.push_back(pout[ix].vect().mag2());
qtotal+=pout[ix].vect();
}
Energy2 dot1 = qtotal*ppartner.vect();
Energy2 qmag2=qtotal.mag2();
double a = -dot1/qmag2;
static const Energy eps=1e-10*GeV;
unsigned int itry(0);
Energy numer(ZERO),denom(ZERO);
k1=1.;
do {
++itry;
numer=denom=0.*GeV;
double k12=sqr(k1);
for(unsigned int ix=0;ix<pout.size();++ix) {
Energy en = sqrt(pmag[ix]/k12+sqr(mon[ix]));
numer += en;
denom += pmag[ix]/en;
}
Energy en = sqrt(qmag2/k12+sqr(mbar));
numer += en-roots;
denom += qmag2/en;
k1 += numer/denom*k12*k1;
if(abs(k1)>1e10) return false;
}
while (abs(numer)>eps&&itry<100);
k1 = abs(k1);
k2 = a*k1;
return itry<100;
}
void QTildeReconstructor::
findPartners(HardBranchingPtr branch,set<HardBranchingPtr> & done,
const set<HardBranchingPtr> & branchings,
vector<HardBranchingPtr> & jets) const {
tShowerParticlePtr part=branch->branchingParticle();
unsigned int partNumColourLines =
branch->branchingParticle()->colourInfo()-> colourLines().size();
unsigned int partNumAColourLines =
branch->branchingParticle()->colourInfo()->antiColourLines().size();
for(set<HardBranchingPtr>::const_iterator cit=branchings.begin();
cit!=branchings.end();++cit) {
if(done.find(*cit)!=done.end()||!(**cit).branchingParticle()->coloured())
continue;
bool isPartner = false;
// one initial and one final
if(branch->status()!=(**cit).status()) {
if(part->colourLine()) {
for(unsigned int ix=0; ix<partNumColourLines; ++ix){
for(unsigned int jx=0; jx<CLSIZE(cit); ++jx){
if(part->colourInfo()->colourLines()[ix] ==
(**cit).branchingParticle()->colourInfo()->colourLines()[jx]){
isPartner = true;
break;
}
}
}
}
if(part->antiColourLine()) {
for(unsigned int ix=0; ix<partNumAColourLines; ++ix){
for(unsigned int jx=0; jx<ACLSIZE(cit); ++jx){
if(part->colourInfo()->antiColourLines()[ix] ==
(**cit).branchingParticle()->colourInfo()->antiColourLines()[jx]){
isPartner = true;
break;
}
}
}
}
}
// both in either initial or final state
else {
if(part->colourLine()) {
for(unsigned int ix=0; ix<partNumColourLines; ++ix) {
for(unsigned int jx=0; jx<ACLSIZE(cit); ++jx) {
if(part->colourInfo()->colourLines()[ix] ==
(**cit).branchingParticle()->colourInfo()->antiColourLines()[jx]){
isPartner = true;
break;
}
}
}
}
if(part->antiColourLine()) {
for(unsigned int ix=0; ix<partNumAColourLines; ++ix){
for(unsigned int jx=0; jx<CLSIZE(cit); ++jx){
if(part->colourInfo()->antiColourLines()[ix] ==
(**cit).branchingParticle()->colourInfo()->colourLines()[jx]){
isPartner = true;
break;
}
}
}
}
}
if(isPartner) {
jets.push_back(*cit);
done.insert(*cit);
findPartners(*cit,done,branchings,jets);
}
}
}
void QTildeReconstructor::
deconstructInitialFinalSystem(HardTreePtr tree,vector<HardBranchingPtr> jets,
cEvolverPtr evolver,
ShowerInteraction::Type type) const {
HardBranchingPtr incoming;
Lorentz5Momentum pin[2],pout[2],pbeam;
HardBranchingPtr initial;
Energy mc(ZERO);
for(unsigned int ix=0;ix<jets.size();++ix) {
// final-state parton
if(jets[ix]->status()==HardBranching::Outgoing) {
pout[0] += jets[ix]->branchingParticle()->momentum();
mc = jets[ix]->branchingParticle()->getThePEGBase() ?
jets[ix]->branchingParticle()->getThePEGBase()->mass() :
jets[ix]->branchingParticle()->dataPtr()->mass();
}
// initial-state parton
else {
pin[0] += jets[ix]->branchingParticle()->momentum();
initial = jets[ix];
pbeam = jets[ix]->beam()->momentum();
Energy scale=pbeam.t();
pbeam = Lorentz5Momentum(ZERO,pbeam.vect().unit()*scale);
incoming = jets[ix];
while(incoming->parent()) incoming = incoming->parent();
}
}
if(jets.size()>2) {
pout[0].rescaleMass();
mc = pout[0].mass();
}
// work out the boost to the Breit frame
Lorentz5Momentum pa = pout[0]-pin[0];
Axis axis(pa.vect().unit());
LorentzRotation rot;
double sinth(sqrt(sqr(axis.x())+sqr(axis.y())));
if(axis.perp2()>0.) {
rot.setRotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.));
rot.rotateX(Constants::pi);
rot.boostZ( pa.e()/pa.vect().mag());
}
// transverse part
Lorentz5Momentum paxis=rot*pbeam;
Boost trans = -1./paxis.e()*paxis.vect();
trans.setZ(0.);
rot.boost(trans);
pa *= rot;
// reference vectors
Lorentz5Momentum n1(ZERO,ZERO,-pa.z(),-pa.z());
Lorentz5Momentum n2(ZERO,ZERO, pa.z(),-pa.z());
Energy2 n1n2 = n1*n2;
// decompose the momenta
Lorentz5Momentum qbp=rot*pin[0],qcp= rot*pout[0];
double a[2],b[2];
a[0] = n2*qbp/n1n2;
b[0] = n1*qbp/n1n2;
a[1] = n2*qcp/n1n2;
b[1] = n1*qcp/n1n2;
Lorentz5Momentum qperp = qbp-a[0]*n1-b[0]*n2;
// before reshuffling
Energy Q = abs(pa.z());
double c = sqr(mc/Q);
Lorentz5Momentum pb(ZERO,ZERO,0.5*Q*(1.+c),0.5*Q*(1.+c));
Lorentz5Momentum pc(ZERO,ZERO,0.5*Q*(c-1.),0.5*Q*(1.+c));
double anew[2],bnew[2];
anew[0] = pb*n2/n1n2;
bnew[0] = 0.5*(qbp.m2()-qperp.m2())/n1n2/anew[0];
bnew[1] = pc*n1/n1n2;
anew[1] = 0.5*qcp.m2()/bnew[1]/n1n2;
Lorentz5Momentum qnewb = (anew[0]*n1+bnew[0]*n2+qperp);
Lorentz5Momentum qnewc = (anew[1]*n1+bnew[1]*n2);
// initial-state boost
LorentzRotation rotinv=rot.inverse();
LorentzRotation transb=rotinv*solveBoostZ(qnewb,qbp)*rot;
// final-state boost
LorentzRotation transc=rotinv*solveBoost(qnewc,qcp)*rot;
// this will need changing for more than one outgoing particle
// set the pvectors
for(unsigned int ix=0;ix<jets.size();++ix) {
if(jets[ix]->status()==HardBranching::Incoming) {
jets[ix]->pVector(pbeam);
jets[ix]->showerMomentum(rotinv*pb);
incoming->pVector(jets[ix]->pVector());
}
else {
jets[ix]->pVector(rotinv*pc);
jets[ix]->showerMomentum(jets[ix]->pVector());
}
}
// find the colour partners
ShowerParticleVector particles;
vector<Lorentz5Momentum> ptemp;
set<HardBranchingPtr>::const_iterator cjt;
for(cjt=tree->branchings().begin();cjt!=tree->branchings().end();++cjt) {
ptemp.push_back((**cjt).branchingParticle()->momentum());
(**cjt).branchingParticle()->set5Momentum((**cjt).showerMomentum());
particles.push_back((**cjt).branchingParticle());
}
evolver->showerModel()->partnerFinder()
->setInitialEvolutionScales(particles,false,type,false);
unsigned int iloc(0);
for(cjt=tree->branchings().begin();cjt!=tree->branchings().end();++cjt) {
// reset the momentum
(**cjt).branchingParticle()->set5Momentum(ptemp[iloc]);
++iloc;
}
for(vector<HardBranchingPtr>::const_iterator cjt=jets.begin();
cjt!=jets.end();++cjt) {
// sort out the partners
tShowerParticlePtr partner =
(*cjt)->branchingParticle()->partner();
if(!partner) continue;
tHardBranchingPtr branch;
for(set<HardBranchingPtr>::const_iterator
clt=tree->branchings().begin();clt!=tree->branchings().end();++clt) {
if((**clt).branchingParticle()==partner) {
(**cjt).colourPartner(*clt);
branch=*clt;
break;
}
}
// compute the reference vectors
// both incoming, should all ready be done
if((**cjt).status()==HardBranching::Incoming &&
branch->status()==HardBranching::Incoming) {
Energy etemp = (*cjt)->beam()->momentum().z();
Lorentz5Momentum nvect(ZERO, ZERO,-etemp, abs(etemp));
tHardBranchingPtr branch2 = *cjt;
(**cjt).nVector(nvect);
while (branch2->parent()) {
branch2=branch2->parent();
branch2->nVector(nvect);
}
}
// both outgoing
else if((**cjt).status()==HardBranching::Outgoing&&
branch->status()==HardBranching::Outgoing) {
Boost boost=((*cjt)->pVector()+branch->pVector()).findBoostToCM();
Lorentz5Momentum pcm = branch->pVector();
pcm.boost(boost);
Lorentz5Momentum nvect = Lorentz5Momentum(ZERO,pcm.vect());
nvect.boost( -boost);
(**cjt).nVector(nvect);
}
else if((**cjt).status()==HardBranching::Incoming) {
Lorentz5Momentum pa = -(**cjt).showerMomentum()+branch->showerMomentum();
Lorentz5Momentum pb = (**cjt).showerMomentum();
Axis axis(pa.vect().unit());
LorentzRotation rot;
double sinth(sqrt(sqr(axis.x())+sqr(axis.y())));
if(axis.perp2()>1e-20) {
rot.setRotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.));
rot.rotateX(Constants::pi);
}
if(abs(1.-pa.e()/pa.vect().mag())>1e-6) rot.boostZ( pa.e()/pa.vect().mag());
pb*=rot;
Boost trans = -1./pb.e()*pb.vect();
trans.setZ(0.);
rot.boost(trans);
Energy scale=(**cjt).beam()->momentum().t();
Lorentz5Momentum pbasis(ZERO,(**cjt).beam()->momentum().vect().unit()*scale);
Lorentz5Momentum pcm = rot*pbasis;
rot.invert();
Lorentz5Momentum nvect = rot*Lorentz5Momentum(ZERO,-pcm.vect());
(**cjt).nVector(nvect);
tHardBranchingPtr branch2 = *cjt;
while (branch2->parent()) {
branch2=branch2->parent();
branch2->nVector(nvect);
}
}
else if(branch->status()==HardBranching::Incoming) {
Lorentz5Momentum nvect=Lorentz5Momentum(ZERO,branch->showerMomentum().vect());
(**cjt).nVector(nvect);
}
}
// now compute the new momenta
for(vector<HardBranchingPtr>::const_iterator cjt=jets.begin();
cjt!=jets.end();++cjt) {
if((**cjt).status()==HardBranching::Outgoing) {
(**cjt).setMomenta(transc,1.,Lorentz5Momentum());
}
}
incoming->setMomenta(transb,1.,Lorentz5Momentum());
}
void QTildeReconstructor::deepTransform(PPtr particle,
const LorentzRotation & r,
bool match,
PPtr original) const {
Lorentz5Momentum porig = particle->momentum();
if(!original) original = particle;
for ( int i = 0, N = particle->children().size(); i < N; ++i ) {
deepTransform(particle->children()[i],r,
particle->children()[i]->id()==original->id()&&match,original);
}
particle->transform(r);
if ( particle->next() ) deepTransform(particle->next(),r,match,original);
if(!match) return;
if(!particle->children().empty()) return;
// check if there's a daughter tree which also needs boosting
map<tShowerTreePtr,pair<tShowerProgenitorPtr,tShowerParticlePtr> >::const_iterator tit;
for(tit = _currentTree->treelinks().begin();
tit != _currentTree->treelinks().end();++tit) {
// if there is, boost it
if(tit->second.first && tit->second.second==original) {
Lorentz5Momentum pnew = tit->first->incomingLines().begin()
->first->progenitor()->momentum();
pnew *= tit->first->transform();
Lorentz5Momentum pdiff = porig-pnew;
Energy2 test = sqr(pdiff.x()) + sqr(pdiff.y()) +
sqr(pdiff.z()) + sqr(pdiff.t());
LorentzRotation rot;
if(test>1e-6*GeV2) rot = solveBoost(porig,pnew);
tit->first->transform(r*rot,false);
}
}
}
diff --git a/Shower/Default/QTildeReconstructor.h b/Shower/Default/QTildeReconstructor.h
--- a/Shower/Default/QTildeReconstructor.h
+++ b/Shower/Default/QTildeReconstructor.h
@@ -1,557 +1,516 @@
// -*- C++ -*-
//
// QTildeReconstructor.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_QTildeReconstructor_H
#define HERWIG_QTildeReconstructor_H
//
// This is the declaration of the QTildeReconstructor class.
//
#include "Herwig++/Shower/Base/KinematicsReconstructor.h"
namespace Herwig {
using namespace ThePEG;
/** \ingroup Shower
* A simple struct to store the information we need on the
* showering
*/
struct JetKinStruct {
/**
* Parent particle of the jet
*/
tShowerParticlePtr parent;
/**
* Momentum of the particle before reconstruction
*/
Lorentz5Momentum p;
/**
* Momentum of the particle after reconstruction
*/
Lorentz5Momentum q;
};
/**
* typedef for a vector of JetKinStruct
*/
typedef vector<JetKinStruct> JetKinVect;
/** \ingroup Shower
*
* This class is responsible for the kinematical reconstruction
* after each showering step, and also for the necessary Lorentz boosts
* in order to preserve energy-momentum conservation in the overall collision,
* and also the invariant mass and the rapidity of the hard subprocess system.
* In the case of multi-step showering, there will be not unnecessary
* kinematical reconstructions.
*
* There is also the option of taking a set of momenta for the particles
* and inverting the reconstruction to give the evolution variables for the
* shower.
*
* Notice:
* - although we often use the term "jet" in either methods or variables names,
* or in comments, which could appear applicable only for QCD showering,
* there is indeed no "dynamics" represented in this class: only kinematics
* is involved, as the name of this class remainds. Therefore it can be used
* for any kind of showers (QCD-,QED-,EWK-,... bremsstrahlung).
*
* @see ShowerParticle
* @see ShowerKinematics
* @see \ref QTildeReconstructorInterfaces "The interfaces"
* defined for QTildeReconstructor.
*/
class QTildeReconstructor: public KinematicsReconstructor {
public:
/**
* Default constructor
*/
QTildeReconstructor() : _reconopt(0), _initialBoost(0), _minQ(MeV) {};
/**
* Methods to reconstruct the kinematics of a scattering or decay process
*/
//@{
/**
* Given in input a vector of the particles which initiated the showers
* the method does the reconstruction of such jets,
* including the appropriate boosts (kinematics reshufflings)
* needed to conserve the total energy-momentum of the collision
* and preserving the invariant mass and the rapidity of the
* hard subprocess system.
*/
virtual bool reconstructHardJets(ShowerTreePtr hard,
const map<tShowerProgenitorPtr,
pair<Energy,double> > & pt) const;
/**
* Given in input a vector of the particles which initiated the showers
* the method does the reconstruction of such jets,
* including the appropriate boosts (kinematics reshufflings)
* needed to conserve the total energy-momentum of the collision
* and preserving the invariant mass and the rapidity of the
* hard subprocess system.
*/
virtual bool reconstructDecayJets(ShowerTreePtr decay) const;
//@}
/**
* Methods to invert the reconstruction of the shower for
* a scattering or decay process and calculate
* the variables used to generate the
* shower given the particles produced.
* This is needed for the CKKW and POWHEG approaches
*/
//@{
/**
* Given the particles, with a history which we wish to interpret
* as a shower reconstruct the variables used to generate the
* shower
*/
virtual bool deconstructDecayJets(HardTreePtr, cEvolverPtr,
ShowerInteraction::Type) const;
/**
* Given the particles, with a history which we wish to interpret
* as a shower reconstruct the variables used to generate the shower
* for a hard process
*/
virtual bool deconstructHardJets(HardTreePtr, cEvolverPtr,
ShowerInteraction::Type) const;
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/**
* Methods to reconstruct the kinematics of individual jets
*/
//@{
/**
* Given the particle (ShowerParticle object) that
* originates a forward (time-like) jet, this method reconstructs the kinematics
* of the jet. That is, by starting from the final grand-children (which
* originates directly or indirectly from particleJetParent,
* and which don't have children), and moving "backwards" (in a physical
* time picture), towards the particleJetParent, the
* ShowerKinematics objects associated with the various particles,
* which have been created during the showering, are now completed.
* In particular, at the end, we get the mass of the jet, which is the
* main information we want.
* This methods returns false if there was no radiation or rescaling required
*/
virtual bool reconstructTimeLikeJet(const tShowerParticlePtr particleJetParent,
unsigned int iopt) const;
/**
* Exactly similar to the previous one, but for a space-like jet.
* Also in this case we start from the final grand-children (which
* are childless) of the particle which originates the jet, but in
* this case we proceed "forward" (in the physical time picture)
* towards the particleJetParent.
* This methods returns false if there was no radiation or rescaling required
*/
bool reconstructSpaceLikeJet(const tShowerParticlePtr particleJetParent) const;
/**
* Exactly similar to the previous one, but for a decay jet
* This methods returns false if there was no radiation or rescaling required
*/
bool reconstructDecayJet(const tShowerParticlePtr particleJetParent) const;
//@}
/**
* Methods to perform the reconstruction of various types of colour
* singlet systems
*/
//@{
/**
* Perform the reconstruction of a system with one incoming and at least one
* outgoing particle
*/
void reconstructInitialFinalSystem(vector<ShowerProgenitorPtr>) const;
/**
* Perform the reconstruction of a system with only final-state
* particles
*/
void reconstructFinalStateSystem(bool applyBoost,
const LorentzRotation & toRest,
const LorentzRotation & fromRest,
vector<ShowerProgenitorPtr>) const;
/**
* Reconstruction of a general coloured system
*/
void reconstructGeneralSystem(vector<ShowerProgenitorPtr> & ShowerHardJets) const;
/**
* Perform the reconstruction of a system with only final-state
* particles
*/
void reconstructInitialInitialSystem(bool & applyBoost,
LorentzRotation & toRest,
LorentzRotation & fromRest,
vector<ShowerProgenitorPtr>) const;
//@}
/**
* Methods to perform the inverse reconstruction of various types of
* colour singlet systems
*/
//@{
/**
* Perform the inverse reconstruction of a system with only final-state
* particles
*/
void deconstructFinalStateSystem(const LorentzRotation & toRest,
const LorentzRotation & fromRest,
HardTreePtr,
vector<HardBranchingPtr>,
cEvolverPtr,
ShowerInteraction::Type) const;
/**
* Perform the inverse reconstruction of a system with only initial-state
* particles
*/
void deconstructInitialInitialSystem(bool & applyBoost,
LorentzRotation & toRest,
LorentzRotation & fromRest,
HardTreePtr,
vector<HardBranchingPtr>,
ShowerInteraction::Type ) const;
/**
* Perform the inverse reconstruction of a system with only initial-state
* particles
*/
void deconstructInitialFinalSystem(HardTreePtr,
vector<HardBranchingPtr>,
cEvolverPtr,
ShowerInteraction::Type ) const;
bool deconstructGeneralSystem(HardTreePtr, cEvolverPtr,
ShowerInteraction::Type) const;
//@}
/**
* Various methods for the Lorentz transforms needed to do the
* rescalings
*/
//@{
/**
* Compute the boost to get from the the old momentum to the new
*/
LorentzRotation solveBoost(const double k,
const Lorentz5Momentum & newq,
const Lorentz5Momentum & oldp) const;
/**
* Compute the boost to get from the the old momentum to the new
*/
LorentzRotation solveBoost(const Lorentz5Momentum & newq,
const Lorentz5Momentum & oldq) const;
/**
* Compute the boost to get from the the old momentum to the new
*/
LorentzRotation solveBoostZ(const Lorentz5Momentum & newq,
const Lorentz5Momentum & oldq) const;
/**
* Recursively boost the initial-state shower
* @param p The particle
* @param bv The boost
* @param parent The parent of the chain
*/
void boostChain(tPPtr p, const LorentzRotation & bv, tPPtr & parent) const;
/**
* Given a 5-momentum and a scale factor, the method returns the
* Lorentz boost that transforms the 3-vector vec{momentum} --->
* k*vec{momentum}. The method returns the null boost in the case no
* solution exists. This will only work in the case where the
* outgoing jet-momenta are parallel to the momenta of the particles
* leaving the hard subprocess.
*/
Boost solveBoostBeta( const double k, const Lorentz5Momentum & newq,
const Lorentz5Momentum & oldp);
/**
* Compute boost parameter along z axis to get (Ep, any perp, qp)
* from (E, same perp, q).
*/
double getBeta(const double E, const double q,
const double Ep, const double qp) const
{return (q*E-qp*Ep)/(sqr(qp)+sqr(E));}
//@}
/**
* Methods to calculate the various scaling factors
*/
//@{
/**
* Given a vector of 5-momenta of jets, where the 3-momenta are the initial
* ones before showering and the masses are reconstructed after the showering,
* this method returns the overall scaling factor for the 3-momenta of the
* vector of particles, vec{P}_i -> k * vec{P}_i, such to preserve energy-
* momentum conservation, i.e. after the rescaling the center of mass 5-momentum
* is equal to the one specified in input, cmMomentum.
* The method returns 0 if such factor cannot be found.
* @param root_s Centre-of-mass energy
* @param jets The jets
*/
double solveKfactor( const Energy & root_s, const JetKinVect & jets ) const;
/**
* Calculate the rescaling factors for the jets in a particle decay where
* there was initial-state radiation
* @param mb The mass of the decaying particle
* @param n The reference vector for the initial state radiation
* @param pjet The momentum of the initial-state jet
* @param jetKinematics The JetKinStruct objects for the jets
* @param partner The colour partner
* @param ppartner The momentum of the colour partner of the decaying particle
* before and after radiation
* @param k1 The rescaling parameter for the partner
* @param k2 The rescaling parameter for the outgoing singlet
* @param qt The transverse momentum vector
*/
bool solveDecayKFactor(Energy mb,
const Lorentz5Momentum & n,
const Lorentz5Momentum & pjet,
const JetKinVect & jetKinematics,
ShowerParticlePtr partner,
Lorentz5Momentum ppartner[2],
double & k1,
double & k2,
Lorentz5Momentum & qt) const;
/**
* Compute the momentum rescaling factor needed to invert the shower
* @param pout The momenta of the outgoing particles
* @param mon The on-shell masses
* @param roots The mass of the decaying particle
*/
double inverseRescalingFactor(vector<Lorentz5Momentum> pout,
vector<Energy> mon,Energy roots) const;
/**
* Compute the momentum rescaling factor needed to invert the shower
* @param pout The momenta of the outgoing particles
* @param mon The on-shell masses
* @param roots The mass of the decaying particle
* @param ppartner The momentum of the colour partner
* @param mbar The mass of the decaying particle
* @param k1 The first scaling factor
* @param k2 The second scaling factor
*/
bool inverseDecayRescalingFactor(vector<Lorentz5Momentum> pout,
vector<Energy> mon,Energy roots,
Lorentz5Momentum ppartner, Energy mbar,
double & k1, double & k2) const;
/**
* Check the rescaling conserves momentum
* @param k The rescaling
* @param root_s The centre-of-mass energy
* @param jets The jets
*/
Energy momConsEq(const double & k, const Energy & root_s,
const JetKinVect & jets) const;
//@}
/**
* Find the colour partners of a particle to identify the colour singlet
* systems for the reconstruction.
*/
vector<unsigned int> findPartners(unsigned int ,vector<ShowerProgenitorPtr>) const;
/**
* Find the colour partners for as branching to identify the colour singlet
* systems for the inverse reconstruction.
*/
void findPartners(HardBranchingPtr branch,set<HardBranchingPtr> & done,
const set<HardBranchingPtr> & branchings,
vector<HardBranchingPtr> & jets) const;
/**
* Add the intrinsic \f$p_T\f$ to the system if needed
*/
bool addIntrinsicPt(vector<ShowerProgenitorPtr>) const;
/**
* Apply a transform to the particle and any child, including child ShowerTree
* objects
* @param particle The particle
* @param r The Lorentz transformation
* @param match Whether or not to look at children etc
* @param original The original particle
*/
void deepTransform(PPtr particle,const LorentzRotation & r,
bool match=true,PPtr original=PPtr()) const;
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
virtual IBPtr clone() const {return new_ptr(*this);}
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
virtual IBPtr fullclone() const {return new_ptr(*this);}
//@}
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit();
//@}
private:
/**
- * The static object used to initialize the description of this class.
- * Indicates that this is an concrete class without persistent data.
- */
- static ClassDescription<QTildeReconstructor> initQTildeReconstructor;
-
- /**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
QTildeReconstructor & operator=(const QTildeReconstructor &);
private:
/**
* Option for handling the reconstruction
*/
unsigned int _reconopt;
/**
* Option for the boost for initial-initial reconstruction
*/
unsigned int _initialBoost;
/**
* Minimum invariant mass for initial-final dipoles to allow the
* reconstruction
*/
Energy _minQ;
/**
* The progenitor of the jet currently being reconstructed
*/
mutable tShowerParticlePtr _progenitor;
/**
* Storage of the intrinsic \f$p_T\f$
*/
mutable map<tShowerProgenitorPtr,pair<Energy,double> > _intrinsic;
/**
* Current ShowerTree
*/
mutable tShowerTreePtr _currentTree;
/**
* Particles which shouldn't have their masses rescaled as
* vector for the interface
*/
PDVector _noRescaleVector;
/**
* Particles which shouldn't have their masses rescaled as
* set for quick access
*/
set<cPDPtr> _noRescale;
};
}
-#include "ThePEG/Utilities/ClassTraits.h"
-
-namespace ThePEG {
-
-/** @cond TRAITSPECIALIZATIONS */
-
-/** This template specialization informs ThePEG about the
- * base classes of QTildeReconstructor. */
-template <>
-struct BaseClassTrait<Herwig::QTildeReconstructor,1> {
- /** Typedef of the first base class of QTildeReconstructor. */
- typedef Herwig::KinematicsReconstructor NthBase;
-};
-
-/** This template specialization informs ThePEG about the name of
- * the QTildeReconstructor class and the shared object where it is defined. */
-template <>
-struct ClassTraits<Herwig::QTildeReconstructor>
- : public ClassTraitsBase<Herwig::QTildeReconstructor> {
- /** Return a platform-independent class name */
- static string className() { return "Herwig::QTildeReconstructor"; }
- /**
- * The name of a file containing the dynamic library where the class
- * QTildeReconstructor is implemented. It may also include several, space-separated,
- * libraries if the class QTildeReconstructor depends on other classes (base classes
- * excepted). In this case the listed libraries will be dynamically
- * linked in the order they are specified.
- */
- static string library() { return "HwShower.so"; }
-};
-
-/** @endcond */
-
-}
-
#endif /* HERWIG_QTildeReconstructor_H */
diff --git a/Shower/Default/QTildeSudakov.cc b/Shower/Default/QTildeSudakov.cc
--- a/Shower/Default/QTildeSudakov.cc
+++ b/Shower/Default/QTildeSudakov.cc
@@ -1,365 +1,366 @@
// -*- C++ -*-
//
// QTildeSudakov.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 QTildeSudakov class.
//
#include "QTildeSudakov.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/PDT/ParticleData.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "Herwig++/Shower/Default/FS_QTildeShowerKinematics1to2.h"
#include "Herwig++/Shower/Default/IS_QTildeShowerKinematics1to2.h"
#include "Herwig++/Shower/Default/Decay_QTildeShowerKinematics1to2.h"
+#include "ThePEG/Utilities/DescribeClass.h"
using namespace Herwig;
-NoPIOClassDescription<QTildeSudakov> QTildeSudakov::initQTildeSudakov;
-// Definition of the static class description member.
+DescribeNoPIOClass<QTildeSudakov,Herwig::SudakovFormFactor>
+describeQTildeSudakov ("Herwig::QTildeSudakov","HwShower.so");
void QTildeSudakov::Init() {
static ClassDocumentation<QTildeSudakov> documentation
("The QTildeSudakov class implements the Sudakov form factor for ordering it"
" qtilde");
}
bool QTildeSudakov::guessTimeLike(Energy2 &t,Energy2 tmin,double enhance) {
Energy2 told = t;
// calculate limits on z and if lower>upper return
if(!computeTimeLikeLimits(t)) return false;
// guess values of t and z
t = guesst(told,0,ids_,enhance,ids_[1]==ids_[2]);
z(guessz(0,ids_));
// actual values for z-limits
if(!computeTimeLikeLimits(t)) return false;
if(t<tmin) {
t=-1.0*GeV2;
return false;
}
else
return true;
}
bool QTildeSudakov::guessSpaceLike(Energy2 &t, Energy2 tmin, const double x,
double enhance) {
Energy2 told = t;
// calculate limits on z if lower>upper return
if(!computeSpaceLikeLimits(t,x)) return false;
// guess values of t and z
t = guesst(told,1,ids_,enhance,ids_[1]==ids_[2]);
z(guessz(1,ids_));
// actual values for z-limits
if(!computeSpaceLikeLimits(t,x)) return false;
if(t<tmin) {
t=-1.0*GeV2;
return false;
}
else
return true;
}
bool QTildeSudakov::PSVeto(const Energy2 t) {
// still inside PS, return true if outside
// check vs overestimated limits
if(z() < zLimits().first || z() > zLimits().second) return true;
// compute the pts
Energy2 pt2=sqr(z()*(1.-z()))*t-masssquared_[1]*(1.-z())-masssquared_[2]*z();
if(ids_[0]!=ParticleID::g) pt2+=z()*(1.-z())*masssquared_[0];
// if pt2<0 veto
if(pt2<pT2min()) return true;
// otherwise calculate pt and return
pT(sqrt(pt2));
return false;
}
ShoKinPtr QTildeSudakov::generateNextTimeBranching(const Energy startingScale,
const IdList &ids,const bool cc,
double enhance) {
// First reset the internal kinematics variables that can
// have been eventually set in the previous call to the method.
q_ = ZERO;
z(0.);
phi(0.);
// perform initialization
Energy2 tmax(sqr(startingScale)),tmin;
initialize(ids,tmin,cc);
// check max > min
if(tmax<=tmin) return ShoKinPtr();
// calculate next value of t using veto algorithm
Energy2 t(tmax);
do {
if(!guessTimeLike(t,tmin,enhance)) break;
}
while(PSVeto(t) || SplittingFnVeto(z()*(1.-z())*t,ids,true) ||
alphaSVeto(sqr(z()*(1.-z()))*t));
if(t > ZERO) q_ = sqrt(t);
else q_ = -1.*MeV;
phi(Constants::twopi*UseRandom::rnd());
if(q_ < ZERO) return ShoKinPtr();
// return the ShowerKinematics object
return createFinalStateBranching(q_,z(),phi(),pT());
}
ShoKinPtr QTildeSudakov::
generateNextSpaceBranching(const Energy startingQ,
const IdList &ids,
double x,bool cc,
double enhance,
Ptr<BeamParticleData>::transient_const_pointer beam) {
// First reset the internal kinematics variables that can
// have been eventually set in the previous call to the method.
q_ = ZERO;
z(0.);
phi(0.);
// perform the initialization
Energy2 tmax(sqr(startingQ)),tmin;
initialize(ids,tmin,cc);
// check max > min
if(tmax<=tmin) return ShoKinPtr();
// extract the partons which are needed for the PDF veto
// Different order, incoming parton is id = 1, outgoing are id=0,2
tcPDPtr parton0 = getParticleData(ids[0]);
tcPDPtr parton1 = getParticleData(ids[1]);
if(cc) {
if(parton0->CC()) parton0 = parton0->CC();
if(parton1->CC()) parton1 = parton1->CC();
}
// calculate next value of t using veto algorithm
Energy2 t(tmax),pt2(ZERO);
do {
if(!guessSpaceLike(t,tmin,x,enhance)) break;
pt2=sqr(1.-z())*t-z()*masssquared_[2];
}
while(z() > zLimits().second ||
SplittingFnVeto((1.-z())*t/z(),ids,true) ||
alphaSVeto(sqr(1.-z())*t) ||
PDFVeto(t,x,parton0,parton1,beam) || pt2 < pT2min() );
if(t > ZERO && zLimits().first < zLimits().second) q_ = sqrt(t);
else return ShoKinPtr();
phi(Constants::twopi*UseRandom::rnd());
pT(sqrt(pt2));
// create the ShowerKinematics and return it
return createInitialStateBranching(q_,z(),phi(),pT());
}
void QTildeSudakov::initialize(const IdList & ids, Energy2 & tmin,const bool cc) {
ids_=ids;
if(cc) {
for(unsigned int ix=0;ix<ids.size();++ix) {
if(getParticleData(ids[ix])->CC()) ids_[ix]*=-1;
}
}
tmin = cutOffOption() != 2 ? ZERO : 4.*pT2min();
masses_ = virtualMasses(ids);
masssquared_.clear();
for(unsigned int ix=0;ix<masses_.size();++ix) {
masssquared_.push_back(sqr(masses_[ix]));
if(ix>0) tmin=max(masssquared_[ix],tmin);
}
}
ShoKinPtr QTildeSudakov::generateNextDecayBranching(const Energy startingScale,
const Energy stoppingScale,
const Energy minmass,
const IdList &ids,
const bool cc,
double enhance) {
// First reset the internal kinematics variables that can
// have been eventually set in the previous call to this method.
q_ = Constants::MaxEnergy;
z(0.);
phi(0.);
// perform initialisation
Energy2 tmax(sqr(stoppingScale)),tmin;
initialize(ids,tmin,cc);
tmin=sqr(startingScale);
// check some branching possible
if(tmax<=tmin) return ShoKinPtr();
// perform the evolution
Energy2 t(tmin),pt2(-MeV2);
do {
if(!guessDecay(t,tmax,minmass,enhance)) break;
pt2 = sqr(1.-z())*(t-masssquared_[0])-z()*masssquared_[2];
}
while(SplittingFnVeto((1.-z())*t/z(),ids,true)||
alphaSVeto(sqr(1.-z())*t) ||
pt2<pT2min() ||
t*(1.-z())>masssquared_[0]-sqr(minmass));
if(t > ZERO) {
q_ = sqrt(t);
pT(sqrt(pt2));
}
else return ShoKinPtr();
phi(Constants::twopi*UseRandom::rnd());
// create the ShowerKinematics object
return createDecayBranching(q_,z(),phi(),pT());
}
bool QTildeSudakov::guessDecay(Energy2 &t,Energy2 tmax, Energy minmass,
double enhance) {
// previous scale
Energy2 told = t;
// overestimated limits on z
if(tmax<masssquared_[0]) {
t=-1.0*GeV2;
return false;
}
Energy2 tm2 = tmax-masssquared_[0];
Energy tm = sqrt(tm2);
pair<double,double> limits=make_pair(sqr(minmass/masses_[0]),
1.-sqrt(masssquared_[2]+pT2min()+
0.25*sqr(masssquared_[2])/tm2)/tm
+0.5*masssquared_[2]/tm2);
zLimits(limits);
if(zLimits().second<zLimits().first) {
t=-1.0*GeV2;
return false;
}
// guess values of t and z
t = guesst(told,2,ids_,enhance,ids_[1]==ids_[2]);
z(guessz(2,ids_));
// actual values for z-limits
if(t<masssquared_[0]) {
t=-1.0*GeV2;
return false;
}
tm2 = t-masssquared_[0];
tm = sqrt(tm2);
limits=make_pair(sqr(minmass/masses_[0]),
1.-sqrt(masssquared_[2]+pT2min()+
0.25*sqr(masssquared_[2])/tm2)/tm
+0.5*masssquared_[2]/tm2);
zLimits(limits);
if(t>tmax||zLimits().second<zLimits().first) {
t=-1.0*GeV2;
return false;
}
else
return true;
}
bool QTildeSudakov::computeTimeLikeLimits(Energy2 & t) {
if (t < 1e-20 * GeV2) {
t=-1.*GeV2;
return false;
}
// special case for gluon radiating
pair<double,double> limits;
if(ids_[0]==ParticleID::g) {
// no emission possible
if(t<16.*masssquared_[1]) {
t=-1.*GeV2;
return false;
}
// overestimate of the limits
limits.first = 0.5*(1.-sqrt(1.-4.*sqrt((masssquared_[1]+pT2min())/t)));
limits.second = 1.-limits.first;
}
// special case for radiated particle is gluon
else if(ids_[2]==ParticleID::g) {
limits.first = sqrt((masssquared_[1]+pT2min())/t);
limits.second = 1.-sqrt((masssquared_[2]+pT2min())/t);
}
else if(ids_[1]==ParticleID::g) {
limits.second = sqrt((masssquared_[2]+pT2min())/t);
limits.first = 1.-sqrt((masssquared_[1]+pT2min())/t);
}
else {
limits.first = (masssquared_[1]+pT2min())/t;
limits.second = 1.-(masssquared_[2]+pT2min())/t;
}
if(limits.first>=limits.second) {
t=-1.*GeV2;
return false;
}
zLimits(limits);
return true;
}
bool QTildeSudakov::computeSpaceLikeLimits(Energy2 & t, double x) {
if (t < 1e-20 * GeV2) {
t=-1.*GeV2;
return false;
}
pair<double,double> limits;
// compute the limits
limits.first = x;
double yy = 1.+0.5*masssquared_[2]/t;
limits.second = yy - sqrt(sqr(yy)-1.+pT2min()/t);
// return false if lower>upper
zLimits(limits);
if(limits.second<limits.first) {
t=-1.*GeV2;
return false;
}
else
return true;
}
Energy QTildeSudakov::calculateScale(double zin, Energy pt, IdList ids,
unsigned int iopt) {
Energy2 tmin;
initialize(ids,tmin,false);
// final-state branching
if(iopt==0) {
Energy2 scale=(sqr(pt)+masssquared_[1]*(1.-zin)+masssquared_[2]*zin);
if(ids[0]!=ParticleID::g) scale -= zin*(1.-zin)*masssquared_[0];
scale /= sqr(zin*(1-zin));
return scale<=ZERO ? sqrt(tmin) : sqrt(scale);
}
else if(iopt==1) {
Energy2 scale=(sqr(pt)+zin*masssquared_[2])/sqr(1.-zin);
return scale<=ZERO ? sqrt(tmin) : sqrt(scale);
}
else if(iopt==2) {
Energy2 scale = (sqr(pt)+zin*masssquared_[2])/sqr(1.-zin)+masssquared_[0];
return scale<=ZERO ? sqrt(tmin) : sqrt(scale);
}
else {
throw Exception() << "Unknown option in QTildeSudakov::calculateScale() "
<< "iopt = " << iopt << Exception::runerror;
}
}
ShoKinPtr QTildeSudakov::createFinalStateBranching(Energy scale,double z,
double phi, Energy pt) {
ShoKinPtr showerKin = new_ptr(FS_QTildeShowerKinematics1to2());
showerKin->scale(scale);
showerKin->z(z);
showerKin->phi(phi);
showerKin->pT(pt);
showerKin->SudakovFormFactor(this);
return showerKin;
}
ShoKinPtr QTildeSudakov::createInitialStateBranching(Energy scale,double z,
double phi, Energy pt) {
ShoKinPtr showerKin = new_ptr(IS_QTildeShowerKinematics1to2());
showerKin->scale(scale);
showerKin->z(z);
showerKin->phi(phi);
showerKin->pT(pt);
showerKin->SudakovFormFactor(this);
return showerKin;
}
ShoKinPtr QTildeSudakov::createDecayBranching(Energy scale,double z,
double phi, Energy pt) {
ShoKinPtr showerKin = new_ptr(Decay_QTildeShowerKinematics1to2());
showerKin->scale(scale);
showerKin->z(z);
showerKin->phi(phi);
showerKin->pT(pt);
showerKin->SudakovFormFactor(this);
return showerKin;
}
diff --git a/Shower/Default/QTildeSudakov.h b/Shower/Default/QTildeSudakov.h
--- a/Shower/Default/QTildeSudakov.h
+++ b/Shower/Default/QTildeSudakov.h
@@ -1,299 +1,258 @@
// -*- C++ -*-
//
// QTildeSudakov.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_QTildeSudakov_H
#define HERWIG_QTildeSudakov_H
//
// This is the declaration of the QTildeSudakov class.
//
#include "Herwig++/Shower/Base/SudakovFormFactor.h"
namespace Herwig {
using namespace ThePEG;
/** \ingroup Shower
*
* The QTildeSudakov class implements the Sudakov form factor for evolution in
* \f$\tilde{q}^2\f$ using the veto algorithm.
*
* @see \ref QTildeSudakovInterfaces "The interfaces"
* defined for QTildeSudakov.
*/
class QTildeSudakov: public SudakovFormFactor {
public:
/**
* The default constructor.
*/
inline QTildeSudakov() {}
/**
* Members to generate the scale of the next branching
*/
//@{
/**
* Return the scale of the next time-like branching. If there is no
* branching then it returns ZERO.
* @param startingScale starting scale for the evolution
* @param ids The PDG codes of the particles in the splitting
* @param cc Whether this is the charge conjugate of the branching
* defined.
* @param enhance The radiation enhancement factor
*/
virtual ShoKinPtr generateNextTimeBranching(const Energy startingScale,
const IdList &ids,const bool cc,
double enhance);
/**
* Return the scale of the next space-like decay branching. If there is no
* branching then it returns ZERO.
* @param startingScale starting scale for the evolution
* @param stoppingScale stopping scale for the evolution
* @param minmass The minimum mass allowed for the spake-like particle.
* @param ids The PDG codes of the particles in the splitting
* @param cc Whether this is the charge conjugate of the branching
* defined.
* @param enhance The radiation enhancement factor
*/
virtual ShoKinPtr generateNextDecayBranching(const Energy startingScale,
const Energy stoppingScale,
const Energy minmass,
const IdList &ids,
const bool cc,
double enhance);
/**
* Return the scale of the next space-like branching. If there is no
* branching then it returns ZERO.
* @param startingScale starting scale for the evolution
* @param ids The PDG codes of the particles in the splitting
* @param x The fraction of the beam momentum
* @param cc Whether this is the charge conjugate of the branching
* defined.
* @param enhance The radiation enhancement factor
* @param beam The beam particle
*/
virtual ShoKinPtr generateNextSpaceBranching(const Energy startingScale,
const IdList &ids,double x,
const bool cc, double enhance,
tcBeamPtr beam);
//@}
/**
* Method to return the evolution scale given the
* transverse momentum, \f$p_T\f$ and \f$z\f$.
*/
virtual Energy calculateScale(double z, Energy pt, IdList ids,unsigned int iopt);
/**
* Method to create the ShowerKinematics object for a final-state branching
*/
virtual ShoKinPtr createFinalStateBranching(Energy scale,double z,
double phi, Energy pt);
/**
* Method to create the ShowerKinematics object for an initial-state branching
*/
virtual ShoKinPtr createInitialStateBranching(Energy scale,double z,
double phi, Energy pt);
/**
* Method to create the ShowerKinematics object for a decay branching
*/
virtual ShoKinPtr createDecayBranching(Energy scale,double z,
double phi, Energy pt);
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/**
* Methods to provide the next value of the scale before the vetos
* are applied.
*/
//@{
/**
* Value of the energy fraction and scale for time-like branching
* @param t The scale
* @param tmin The minimum scale
* @param enhance The radiation enhancement factor
* @return False if scale less than minimum, true otherwise
*/
bool guessTimeLike(Energy2 &t, Energy2 tmin, double enhance);
/**
* Value of the energy fraction and scale for time-like branching
* @param t The scale
* @param tmax The maximum scale
* @param minmass The minimum mass of the particle after the branching
* @param enhance The radiation enhancement factor
*/
bool guessDecay(Energy2 &t, Energy2 tmax,Energy minmass,
double enhance);
/**
* Value of the energy fraction and scale for space-like branching
* @param t The scale
* @param tmin The minimum scale
* @param x Fraction of the beam momentum.
* @param enhance The radiation enhancement factor
*/
bool guessSpaceLike(Energy2 &t, Energy2 tmin, const double x,
double enhance);
//@}
/**
* Initialize the values of the cut-offs and scales
* @param tmin The minimum scale
* @param ids The ids of the partics in the branching
* @param cc Whether this is the charge conjugate of the branching
*/
void initialize(const IdList & ids,Energy2 &tmin, const bool cc);
/**
* Phase Space veto member to implement the \f$\Theta\f$ function as a veto
* so that the emission is within the allowed phase space.
* @param t The scale
* @return true if vetoed
*/
bool PSVeto(const Energy2 t);
/**
* Compute the limits on \f$z\f$ for time-like branching
* @param scale The scale of the particle
* @return True if lower limit less than upper, otherwise false
*/
bool computeTimeLikeLimits(Energy2 & scale);
/**
* Compute the limits on \f$z\f$ for space-like branching
* @param scale The scale of the particle
* @param x The energy fraction of the parton
* @return True if lower limit less than upper, otherwise false
*/
bool computeSpaceLikeLimits(Energy2 & scale, double x);
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
inline virtual IBPtr clone() const {return new_ptr(*this);}
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
inline virtual IBPtr fullclone() const {return new_ptr(*this);}
//@}
private:
/**
- * The static object used to initialize the description of this class.
- * Indicates that this is an concrete class with persistent data.
- */
- static NoPIOClassDescription<QTildeSudakov> initQTildeSudakov;
-
- /**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
QTildeSudakov & operator=(const QTildeSudakov &);
private:
/**
* The evolution scale, \f$\tilde{q}\f$.
*/
Energy q_;
/**
* The Ids of the particles in the current branching
*/
IdList ids_;
/**
* The masses of the particles in the current branching
*/
vector<Energy> masses_;
/**
* The mass squared of the particles in the current branching
*/
vector<Energy2> masssquared_;
};
}
-#include "ThePEG/Utilities/ClassTraits.h"
-
-namespace ThePEG {
-
-/** @cond TRAITSPECIALIZATIONS */
-
-/** This template specialization informs ThePEG about the
- * base classes of QTildeSudakov. */
-template <>
-struct BaseClassTrait<Herwig::QTildeSudakov,1> {
- /** Typedef of the first base class of QTildeSudakov. */
- typedef Herwig::SudakovFormFactor NthBase;
-};
-
-/** This template specialization informs ThePEG about the name of
- * the QTildeSudakov class and the shared object where it is defined. */
-template <>
-struct ClassTraits<Herwig::QTildeSudakov>
- : public ClassTraitsBase<Herwig::QTildeSudakov> {
- /** Return a platform-independent class name */
- static string className() { return "Herwig::QTildeSudakov"; }
- /**
- * The name of a file containing the dynamic library where the class
- * QTildeSudakov is implemented. It may also include several, space-separated,
- * libraries if the class QTildeSudakov depends on other classes (base classes
- * excepted). In this case the listed libraries will be dynamically
- * linked in the order they are specified.
- */
- static string library() { return "HwShower.so"; }
-};
-
-/** @endcond */
-
-}
-
#endif /* HERWIG_QTildeSudakov_H */
diff --git a/Shower/ShowerHandler.cc b/Shower/ShowerHandler.cc
--- a/Shower/ShowerHandler.cc
+++ b/Shower/ShowerHandler.cc
@@ -1,734 +1,735 @@
// -*- C++ -*-
//
// ShowerHandler.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 ShowerHandler class.
//
#include "ShowerHandler.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/ParVector.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/PDF/PartonExtractor.h"
#include "ThePEG/PDF/PartonBinInstance.h"
#include "Herwig++/PDT/StandardMatchers.h"
#include "ThePEG/Cuts/Cuts.h"
#include "ThePEG/Handlers/StandardXComb.h"
#include "ThePEG/Utilities/Throw.h"
#include "Herwig++/Shower/Base/Evolver.h"
#include "Herwig++/Shower/Base/ShowerParticle.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "Herwig++/Utilities/EnumParticles.h"
#include "Herwig++/PDF/MPIPDF.h"
#include "Herwig++/PDF/MinBiasPDF.h"
#include "ThePEG/Handlers/EventHandler.h"
#include "Herwig++/Shower/Base/ShowerTree.h"
#include "Herwig++/Shower/Base/HardTree.h"
#include "Herwig++/Shower/Base/KinematicsReconstructor.h"
#include "Herwig++/Shower/Base/PartnerFinder.h"
#include "Herwig++/PDF/HwRemDecayer.h"
#include <cassert>
+#include "ThePEG/Utilities/DescribeClass.h"
using namespace Herwig;
+DescribeClass<ShowerHandler,CascadeHandler>
+describeShowerHandler ("Herwig::ShowerHandler","HwShower.so");
+
ShowerHandler::~ShowerHandler() {}
ShowerHandler * ShowerHandler::currentHandler_ = 0;
void ShowerHandler::doinit() {
CascadeHandler::doinit();
// copy particles to decay before showering from input vector to the
// set used in the simulation
particlesDecayInShower_.insert(inputparticlesDecayInShower_.begin(),
inputparticlesDecayInShower_.end());
// \todo DG: Disabled here because of momentum-violation problems
// ShowerTree::_decayInShower = particlesDecayInShower_;
}
IBPtr ShowerHandler::clone() const {
return new_ptr(*this);
}
IBPtr ShowerHandler::fullclone() const {
return new_ptr(*this);
}
ShowerHandler::ShowerHandler() :
pdfFreezingScale_(2.5*GeV),
maxtry_(10),maxtryMPI_(10),maxtryDP_(10), subProcess_() {
inputparticlesDecayInShower_.push_back( 6 ); // top
inputparticlesDecayInShower_.push_back( 23 ); // Z0
inputparticlesDecayInShower_.push_back( 24 ); // W+/-
inputparticlesDecayInShower_.push_back( 25 ); // h0
}
void ShowerHandler::doinitrun(){
CascadeHandler::doinitrun();
//can't use isMPIOn here, because the EventHandler is not set at that stage
if(MPIHandler_){
MPIHandler_->initialize();
if(MPIHandler_->softInt())
remDec_->initSoftInteractions(MPIHandler_->Ptmin(), MPIHandler_->beta());
}
// \todo DG: Disabled here because of momentum-violation problems
// Must set pre-cascade-handler to NewPhysics/DecayHandler instead
// ShowerTree::_decayInShower = particlesDecayInShower_;
}
void ShowerHandler::dofinish(){
CascadeHandler::dofinish();
if(MPIHandler_) MPIHandler_->finalize();
}
void ShowerHandler::persistentOutput(PersistentOStream & os) const {
os << evolver_ << remDec_ << ounit(pdfFreezingScale_,GeV) << maxtry_
<< maxtryMPI_ << maxtryDP_ << inputparticlesDecayInShower_
<< particlesDecayInShower_ << MPIHandler_ << PDFA_ << PDFB_;
}
void ShowerHandler::persistentInput(PersistentIStream & is, int) {
is >> evolver_ >> remDec_ >> iunit(pdfFreezingScale_,GeV) >> maxtry_
>> maxtryMPI_ >> maxtryDP_ >> inputparticlesDecayInShower_
>> particlesDecayInShower_ >> MPIHandler_ >> PDFA_ >> PDFB_;
}
-ClassDescription<ShowerHandler> ShowerHandler::initShowerHandler;
-// Definition of the static class description member.
-
void ShowerHandler::Init() {
static ClassDocumentation<ShowerHandler> documentation
("Main driver class for the showering.",
"The Shower evolution was performed using an algorithm described in "
"\\cite{Marchesini:1983bm,Marchesini:1987cf,Gieseke:2003rz,Bahr:2008pv}.",
"%\\cite{Marchesini:1983bm}\n"
"\\bibitem{Marchesini:1983bm}\n"
" G.~Marchesini and B.~R.~Webber,\n"
" ``Simulation Of QCD Jets Including Soft Gluon Interference,''\n"
" Nucl.\\ Phys.\\ B {\\bf 238}, 1 (1984).\n"
" %%CITATION = NUPHA,B238,1;%%\n"
"%\\cite{Marchesini:1987cf}\n"
"\\bibitem{Marchesini:1987cf}\n"
" G.~Marchesini and B.~R.~Webber,\n"
" ``Monte Carlo Simulation of General Hard Processes with Coherent QCD\n"
" Radiation,''\n"
" Nucl.\\ Phys.\\ B {\\bf 310}, 461 (1988).\n"
" %%CITATION = NUPHA,B310,461;%%\n"
"%\\cite{Gieseke:2003rz}\n"
"\\bibitem{Gieseke:2003rz}\n"
" S.~Gieseke, P.~Stephens and B.~Webber,\n"
" ``New formalism for QCD parton showers,''\n"
" JHEP {\\bf 0312}, 045 (2003)\n"
" [arXiv:hep-ph/0310083].\n"
" %%CITATION = JHEPA,0312,045;%%\n"
);
static Reference<ShowerHandler,Evolver>
interfaceEvolver("Evolver",
"A reference to the Evolver object",
&Herwig::ShowerHandler::evolver_,
false, false, true, false);
static Reference<ShowerHandler,HwRemDecayer>
interfaceRemDecayer("RemDecayer",
"A reference to the Remnant Decayer object",
&Herwig::ShowerHandler::remDec_,
false, false, true, false);
static Parameter<ShowerHandler,Energy> interfacePDFFreezingScale
("PDFFreezingScale",
"The PDF freezing scale",
&ShowerHandler::pdfFreezingScale_, GeV, 2.5*GeV, 2.0*GeV, 10.0*GeV,
false, false, Interface::limited);
static Parameter<ShowerHandler,unsigned int> interfaceMaxTry
("MaxTry",
"The maximum number of attempts for the main showering loop",
&ShowerHandler::maxtry_, 10, 1, 100,
false, false, Interface::limited);
static Parameter<ShowerHandler,unsigned int> interfaceMaxTryMPI
("MaxTryMPI",
"The maximum number of regeneration attempts for an additional scattering",
&ShowerHandler::maxtryMPI_, 10, 0, 100,
false, false, Interface::limited);
static Parameter<ShowerHandler,unsigned int> interfaceMaxTryDP
("MaxTryDP",
"The maximum number of regeneration attempts for an additional hard scattering",
&ShowerHandler::maxtryDP_, 10, 0, 100,
false, false, Interface::limited);
static ParVector<ShowerHandler,long> interfaceDecayInShower
("DecayInShower",
"PDG codes of the particles to be decayed in the shower",
&ShowerHandler::inputparticlesDecayInShower_, -1, 0l, -10000000l, 10000000l,
false, false, Interface::limited);
static Reference<ShowerHandler,UEBase> interfaceMPIHandler
("MPIHandler",
"The object that administers all additional scatterings.",
&ShowerHandler::MPIHandler_, false, false, true, true);
static Reference<ShowerHandler,PDFBase> interfacePDFA
("PDFA",
"The PDF for beam particle A. Overrides the particle's own PDF setting.",
&ShowerHandler::PDFA_, false, false, true, true, false);
static Reference<ShowerHandler,PDFBase> interfacePDFB
("PDFB",
"The PDF for beam particle B. Overrides the particle's own PDF setting.",
&ShowerHandler::PDFB_, false, false, true, true, false);
}
void ShowerHandler::cascade() {
tcPDFPtr first = firstPDF().pdf();
tcPDFPtr second = secondPDF().pdf();
if ( PDFA_ ) first = PDFA_;
if ( PDFB_ ) second = PDFB_;
resetPDFs(make_pair(first,second));
// get the incoming partons
tPPair incomingPartons =
eventHandler()->currentCollision()->primarySubProcess()->incoming();
// and the parton bins
PBIPair incomingBins =
make_pair(lastExtractor()->partonBinInstance(incomingPartons.first),
lastExtractor()->partonBinInstance(incomingPartons.second));
// and the incoming hadrons
tPPair incomingHadrons =
eventHandler()->currentCollision()->incoming();
remDec_->setHadronContent(incomingHadrons);
// check if incoming hadron == incoming parton
// and get the incoming hadron if exists or parton otherwise
incoming_ = make_pair(incomingBins.first ?
incomingBins.first ->particle() : incomingPartons.first,
incomingBins.second ?
incomingBins.second->particle() : incomingPartons.second);
// check the collision is of the beam particles
// and if not boost collision to the right frame
// i.e. the hadron-hadron CMF of the collision
bool btotal(false);
LorentzRotation rtotal;
if(incoming_.first != incomingHadrons.first ||
incoming_.second != incomingHadrons.second ) {
btotal = true;
boostCollision(false);
}
// set the current ShowerHandler
currentHandler_ = this;
// first shower the hard process
useMe();
try {
SubProPtr sub = eventHandler()->currentCollision()->primarySubProcess();
incomingPartons = cascade(sub,lastXCombPtr());
}
catch(ShowerTriesVeto &veto){
throw Exception() << "Failed to generate the shower after "
<< veto.tries
<< " attempts in ShowerHandler::cascade()"
<< Exception::eventerror;
}
if(showerHardProcessVeto()) throw Veto();
// if a non-hadron collision return (both incoming non-hadronic)
if( ( !incomingBins.first||
!isResolvedHadron(incomingBins.first ->particle()))&&
( !incomingBins.second||
!isResolvedHadron(incomingBins.second->particle()))) {
// boost back to lab if needed
if(btotal) boostCollision(true);
// unset the current ShowerHandler
currentHandler_ = 0;
return;
}
// get the remnants for hadronic collision
pair<tRemPPtr,tRemPPtr> remnants(getRemnants(incomingBins));
// set the starting scale of the forced splitting to the PDF freezing scale
remDec_->initialize(remnants, incoming_, *currentStep(), pdfFreezingScale());
// do the first forcedSplitting
try {
remDec_->doSplit(incomingPartons, make_pair(firstPDF() .pdf(),
secondPDF().pdf()), true);
}
catch (ExtraScatterVeto) {
throw Exception() << "Remnant extraction failed in "
<< "ShowerHandler::cascade() from primary interaction"
<< Exception::eventerror;
}
// if no MPI return
if( !isMPIOn() ) {
remDec_->finalize();
// boost back to lab if needed
if(btotal) boostCollision(true);
// unset the current ShowerHandler
currentHandler_ = 0;
return;
}
// generate the multiple scatters use modified pdf's now:
setMPIPDFs();
// additional "hard" processes
unsigned int tries(0);
// This is the loop over additional hard scatters (most of the time
// only one, but who knows...)
for(unsigned int i=1; i <= getMPIHandler()->additionalHardProcs(); i++){
//counter for regeneration
unsigned int multSecond = 0;
// generate the additional scatters
while( multSecond < getMPIHandler()->multiplicity(i) ) {
// generate the hard scatter
tStdXCombPtr lastXC = getMPIHandler()->generate(i);
SubProPtr sub = lastXC->construct();
// add to the Step
newStep()->addSubProcess(sub);
// increment the counters
tries++;
multSecond++;
if(tries == maxtryDP_)
throw Exception() << "Failed to establish the requested number "
<< "of additional hard processes. If this error "
<< "occurs often, your selection of additional "
<< "scatter is probably unphysical"
<< Exception::eventerror;
// Generate the shower. If not possible veto the event
try {
incomingPartons = cascade(sub,lastXC);
}
catch(ShowerTriesVeto &veto){
throw Exception() << "Failed to generate the shower of "
<< "a secondary hard process after "
<< veto.tries
<< " attempts in Evolver::showerHardProcess()"
<< Exception::eventerror;
}
try {
// do the forcedSplitting
remDec_->doSplit(incomingPartons, make_pair(firstPDF().pdf(),
secondPDF().pdf()), false);
}
catch(ExtraScatterVeto){
//remove all particles associated with the subprocess
newStep()->removeParticle(incomingPartons.first);
newStep()->removeParticle(incomingPartons.second);
//remove the subprocess from the list
newStep()->removeSubProcess(sub);
//regenerate the scattering
multSecond--;
continue;
}
// connect with the remnants but don't set Remnant colour,
// because that causes problems due to the multiple colour lines.
if ( !remnants.first ->extract(incomingPartons.first , false) ||
!remnants.second->extract(incomingPartons.second, false) )
throw Exception() << "Remnant extraction failed in "
<< "ShowerHandler::cascade() for additional scatter"
<< Exception::runerror;
}
}
// the underlying event processes
unsigned int ptveto(1), veto(0);
unsigned int max(getMPIHandler()->multiplicity());
for(unsigned int i=0; i<max; i++) {
// check how often this scattering has been regenerated
if(veto > maxtryMPI_) break;
//generate PSpoint
tStdXCombPtr lastXC = getMPIHandler()->generate();
SubProPtr sub = lastXC->construct();
//If Algorithm=1 additional scatters of the signal type
// with pt > ptmin have to be vetoed
//with probability 1/(m+1), where m is the number of occurances in this event
if( getMPIHandler()->Algorithm() == 1 ){
//get the pT
Energy pt = sub->outgoing().front()->momentum().perp();
if(pt > getMPIHandler()->PtForVeto() && UseRandom::rnd() < 1./(ptveto+1) ){
ptveto++;
i--;
continue;
}
}
// add to the SubProcess to the step
newStep()->addSubProcess(sub);
// Run the Shower. If not possible veto the scattering
try {
incomingPartons = cascade(sub,lastXC);
}
// discard this extra scattering, but try the next one
catch(ShowerTriesVeto) {
newStep()->removeSubProcess(sub);
//regenerate the scattering
veto++;
i--;
continue;
}
try{
//do the forcedSplitting
remDec_->doSplit(incomingPartons, make_pair(firstPDF().pdf(),
secondPDF().pdf()), false);
}
catch (ExtraScatterVeto) {
//remove all particles associated with the subprocess
newStep()->removeParticle(incomingPartons.first);
newStep()->removeParticle(incomingPartons.second);
//remove the subprocess from the list
newStep()->removeSubProcess(sub);
//regenerate the scattering
veto++;
i--;
continue;
}
//connect with the remnants but don't set Remnant colour,
//because that causes problems due to the multiple colour lines.
if ( !remnants.first ->extract(incomingPartons.first , false) ||
!remnants.second->extract(incomingPartons.second, false) )
throw Exception() << "Remnant extraction failed in "
<< "ShowerHandler::cascade() for MPI hard scattering"
<< Exception::runerror;
//reset veto counter
veto = 0;
}
// finalize the remnants
remDec_->finalize(getMPIHandler()->colourDisrupt(),
getMPIHandler()->softMultiplicity());
// boost back to lab if needed
if(btotal) boostCollision(true);
// unset the current ShowerHandler
currentHandler_ = 0;
getMPIHandler()->clean();
}
void ShowerHandler::fillEventRecord() {
// create a new step
StepPtr pstep = newStep();
assert(!done_.empty());
assert(done_[0]->isHard());
// insert the steps
for(unsigned int ix=0;ix<done_.size();++ix) {
done_[ix]->fillEventRecord(pstep,
evolver_->isISRadiationON(),
evolver_->isFSRadiationON());
}
}
void ShowerHandler::findShoweringParticles() {
// clear the storage
hard_=ShowerTreePtr();
decay_.clear();
done_.clear();
// temporary storage of the particles
set<PPtr> hardParticles;
// outgoing particles from the hard process
PVector outgoing = currentSubProcess()->outgoing();
set<PPtr> outgoingset(outgoing.begin(),outgoing.end());
// loop over the tagged particles
tPVector thetagged;
if( firstInteraction() ){
thetagged = tagged();
}
else{
thetagged.insert(thetagged.end(),
outgoing.begin(),outgoing.end());
}
bool isHard=false;
for (tParticleVector::const_iterator
taggedP = thetagged.begin();
taggedP != thetagged.end(); ++taggedP) {
// if a remnant don't consider
if(eventHandler()->currentCollision()->isRemnant(*taggedP))
continue;
// find the parent and whether its a colourless s-channel resonance
bool isDecayProd=false;
tPPtr parent;
if(!(*taggedP)->parents().empty()) {
parent = (*taggedP)->parents()[0];
// check if from s channel decaying colourless particle
isDecayProd = decayProduct(parent);
}
// add to list of outgoing hard particles if needed
isHard |=(outgoingset.find(*taggedP) != outgoingset.end());
if(isDecayProd) hardParticles.insert(findParent(parent,isHard,outgoingset));
else hardParticles.insert(*taggedP);
}
// there must be something to shower
if(hardParticles.empty())
throw Exception() << "No particles to shower in "
<< "ShowerHandler::fillShoweringParticles"
<< Exception::eventerror;
if(!isHard)
throw Exception() << "Starting on decay not yet implemented in "
<< "ShowerHandler::findShoweringParticles()"
<< Exception::runerror;
// create the hard process ShowerTree
ParticleVector out(hardParticles.begin(),hardParticles.end());
hard_=new_ptr(ShowerTree(currentSubProcess()->incoming(),out, decay_));
hard_->setParents();
}
void ShowerHandler::prepareCascade(tSubProPtr sub) {
current_ = currentStep();
subProcess_ = sub;
}
tPPair ShowerHandler::cascade(tSubProPtr sub,
XCPtr xcomb) {
prepareCascade(sub);
// start of the try block for the whole showering process
unsigned int countFailures=0;
while (countFailures<maxtry_) {
try {
// find the particles in the hard process and the decayed particles to shower
findShoweringParticles();
// if no hard process
if(!hard_) throw Exception() << "Shower starting with a decay"
<< "is not implemented"
<< Exception::runerror;
// perform the shower for the hard process
evolver_->showerHardProcess(hard_,xcomb);
done_.push_back(hard_);
hard_->updateAfterShower(decay_);
// if no decaying particles to shower break out of the loop
if(decay_.empty()) break;
// shower the decay products
while(!decay_.empty()) {
// find particle whose production process has been showered
ShowerDecayMap::iterator dit = decay_.begin();
while(!dit->second->parent()->hasShowered() && dit!=decay_.end()) ++dit;
assert(dit!=decay_.end());
// get the particle
ShowerTreePtr decayingTree = dit->second;
// remove it from the multimap
decay_.erase(dit);
// make sure the particle has been decayed
decayingTree->decay(decay_);
// now shower the decay
evolver_->showerDecay(decayingTree);
done_.push_back(decayingTree);
decayingTree->updateAfterShower(decay_);
}
// suceeded break out of the loop
break;
}
catch (KinematicsReconstructionVeto) {
++countFailures;
}
}
// if loop exited because of too many tries, throw event away
if (countFailures >= maxtry_) {
hard_=ShowerTreePtr();
decay_.clear();
done_.clear();
throw Exception() << "Too many tries for main while loop "
<< "in ShowerHandler::cascade()."
<< Exception::eventerror;
}
//enter the particles in the event record
fillEventRecord();
// clear storage
hard_=ShowerTreePtr();
decay_.clear();
done_.clear();
// non hadronic case return
if (!isResolvedHadron(incoming_.first ) &&
!isResolvedHadron(incoming_.second) )
return incoming_;
// remake the remnants (needs to be after the colours are sorted
// out in the insertion into the event record)
if ( firstInteraction() ) return remakeRemnant(sub->incoming());
//Return the new pair of incoming partons. remakeRemnant is not
//necessary here, because the secondary interactions are not yet
//connected to the remnants.
return make_pair(findFirstParton(sub->incoming().first ),
findFirstParton(sub->incoming().second));
}
PPtr ShowerHandler::findParent(PPtr original, bool & isHard,
set<PPtr> outgoingset) const {
PPtr parent=original;
isHard |=(outgoingset.find(original) != outgoingset.end());
if(!original->parents().empty()) {
PPtr orig=original->parents()[0];
if(current_->find(orig)&&decayProduct(orig)) {
parent=findParent(orig,isHard,outgoingset);
}
}
return parent;
}
ShowerHandler::RemPair
ShowerHandler::getRemnants(PBIPair incomingBins) {
RemPair remnants;
// first beam particle
if(incomingBins.first&&!incomingBins.first->remnants().empty()) {
remnants.first =
dynamic_ptr_cast<tRemPPtr>(incomingBins.first->remnants()[0] );
if(remnants.first) {
ParticleVector children=remnants.first->children();
for(unsigned int ix=0;ix<children.size();++ix) {
if(children[ix]->dataPtr()==remnants.first->dataPtr())
remnants.first = dynamic_ptr_cast<RemPPtr>(children[ix]);
}
//remove existing colour lines from the remnants
if(remnants.first->colourLine())
remnants.first->colourLine()->removeColoured(remnants.first);
if(remnants.first->antiColourLine())
remnants.first->antiColourLine()->removeAntiColoured(remnants.first);
}
}
// seconnd beam particle
if(incomingBins.second&&!incomingBins. second->remnants().empty()) {
remnants.second =
dynamic_ptr_cast<tRemPPtr>(incomingBins.second->remnants()[0] );
if(remnants.second) {
ParticleVector children=remnants.second->children();
for(unsigned int ix=0;ix<children.size();++ix) {
if(children[ix]->dataPtr()==remnants.second->dataPtr())
remnants.second = dynamic_ptr_cast<RemPPtr>(children[ix]);
}
//remove existing colour lines from the remnants
if(remnants.second->colourLine())
remnants.second->colourLine()->removeColoured(remnants.second);
if(remnants.second->antiColourLine())
remnants.second->antiColourLine()->removeAntiColoured(remnants.second);
}
}
assert(remnants.first || remnants.second);
return remnants;
}
tPPair ShowerHandler::remakeRemnant(tPPair oldp){
// get the parton extractor
PartonExtractor & pex = *lastExtractor();
// get the new partons
tPPair newp = make_pair(findFirstParton(oldp.first ),
findFirstParton(oldp.second));
// if the same do nothing
if(newp == oldp) return oldp;
// Creates the new remnants and returns the new PartonBinInstances
PBIPair newbins = pex.newRemnants(oldp, newp, newStep());
newStep()->addIntermediate(newp.first);
newStep()->addIntermediate(newp.second);
// return the new partons
return newp;
}
PPtr ShowerHandler::findFirstParton(tPPtr seed) const{
if(seed->parents().empty()) return seed;
tPPtr parent = seed->parents()[0];
//if no parent there this is a loose end which will
//be connected to the remnant soon.
if(!parent || parent == incoming_.first ||
parent == incoming_.second ) return seed;
else return findFirstParton(parent);
}
bool ShowerHandler::decayProduct(tPPtr particle) const {
// must be time-like and not incoming
if(particle->momentum().m2()<=ZERO||
particle == currentSubProcess()->incoming().first||
particle == currentSubProcess()->incoming().second) return false;
// if only 1 outgoing and this is it
if(currentSubProcess()->outgoing().size()==1 &&
currentSubProcess()->outgoing()[0]==particle) return true;
// must not be the s-channel intermediate otherwise
if(find(currentSubProcess()->incoming().first->children().begin(),
currentSubProcess()->incoming().first->children().end(),particle)!=
currentSubProcess()->incoming().first->children().end()&&
find(currentSubProcess()->incoming().second->children().begin(),
currentSubProcess()->incoming().second->children().end(),particle)!=
currentSubProcess()->incoming().second->children().end()&&
currentSubProcess()->incoming().first ->children().size()==1&&
currentSubProcess()->incoming().second->children().size()==1)
return false;
// if non-coloured this is enough
if(!particle->dataPtr()->coloured()) return true;
// if coloured must be unstable
if(particle->dataPtr()->stable()) return false;
// must not have same particle type as a child
int id = particle->id();
for(unsigned int ix=0;ix<particle->children().size();++ix)
if(particle->children()[ix]->id()==id) return false;
// otherwise its a decaying particle
return true;
}
namespace {
void addChildren(tPPtr in,set<tPPtr> & particles) {
particles.insert(in);
for(unsigned int ix=0;ix<in->children().size();++ix)
addChildren(in->children()[ix],particles);
}
}
void ShowerHandler::boostCollision(bool boost) {
// calculate boost from lab to rest
if(!boost) {
Lorentz5Momentum ptotal=incoming_.first ->momentum()+incoming_.second->momentum();
boost_ = LorentzRotation(-ptotal.boostVector());
Axis axis((boost_*incoming_.first ->momentum()).vect().unit());
if(axis.perp2()>0.) {
double sinth(sqrt(sqr(axis.x())+sqr(axis.y())));
boost_.rotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.));
}
}
// first call performs the boost and second inverse
// get the particles to be boosted
set<tPPtr> particles;
addChildren(incoming_.first,particles);
addChildren(incoming_.second,particles);
// apply the boost
for(set<tPPtr>::const_iterator cit=particles.begin();
cit!=particles.end();++cit) {
(*cit)->transform(boost_);
}
if(!boost) boost_.invert();
}
void ShowerHandler::setMPIPDFs() {
if ( !mpipdfs_.first ) {
// first have to check for MinBiasPDF
tcMinBiasPDFPtr first = dynamic_ptr_cast<tcMinBiasPDFPtr>(firstPDF().pdf());
if(first)
mpipdfs_.first = new_ptr(MPIPDF(first->originalPDF()));
else
mpipdfs_.first = new_ptr(MPIPDF(firstPDF().pdf()));
}
if ( !mpipdfs_.second ) {
tcMinBiasPDFPtr second = dynamic_ptr_cast<tcMinBiasPDFPtr>(secondPDF().pdf());
if(second)
mpipdfs_.second = new_ptr(MPIPDF(second->originalPDF()));
else
mpipdfs_.second = new_ptr(MPIPDF(secondPDF().pdf()));
}
// reset the PDFs stored in the base class
resetPDFs(mpipdfs_);
}
bool ShowerHandler::isResolvedHadron(tPPtr particle) {
if(!HadronMatcher::Check(particle->data())) return false;
for(unsigned int ix=0;ix<particle->children().size();++ix) {
if(particle->children()[ix]->id()==ParticleID::Remnant) return true;
}
return false;
}
HardTreePtr ShowerHandler::generateCKKW(ShowerTreePtr ) const {
return HardTreePtr();
}
diff --git a/Shower/ShowerHandler.h b/Shower/ShowerHandler.h
--- a/Shower/ShowerHandler.h
+++ b/Shower/ShowerHandler.h
@@ -1,502 +1,461 @@
// -*- C++ -*-
//
// ShowerHandler.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_ShowerHandler_H
#define HERWIG_ShowerHandler_H
//
// This is the declaration of the ShowerHandler class.
//
#include "ThePEG/Handlers/EventHandler.h"
#include "ThePEG/Handlers/CascadeHandler.h"
#include "Herwig++/Shower/UEBase.h"
#include "Herwig++/Shower/Base/Evolver.fh"
#include "Herwig++/Shower/Base/ShowerParticle.fh"
#include "Herwig++/Shower/Base/ShowerTree.fh"
#include "Herwig++/Shower/Base/HardTree.fh"
#include "Herwig++/PDF/HwRemDecayer.fh"
#include "ThePEG/EventRecord/RemnantParticle.fh"
#include "ShowerHandler.fh"
namespace Herwig {
/**
* Typedef for the ShowerTree for the decays
*/
typedef multimap<Energy,ShowerTreePtr,std::greater<Energy> > ShowerDecayMap;
using namespace ThePEG;
/** \ingroup Shower
*
* This class is the main driver of the shower: it is responsible for
* the proper handling of all other specific collaborating classes
* and for the storing of the produced particles in the event record.
*
* @see \ref ShowerHandlerInterfaces "The interfaces"
*
* @see ThePEG::CascadeHandler
* @see MPIHandler
* @see HwRemDecayer
*/
class ShowerHandler: public CascadeHandler {
public:
/** Typedef for a pair of ThePEG::RemnantParticle pointers. */
typedef pair<tRemPPtr, tRemPPtr> RemPair;
/**
* The default constructor.
*/
ShowerHandler();
/**
* Destructor
*/
virtual ~ShowerHandler();
public:
/**
* The main method which manages the multiple interactions and starts
* the shower by calling cascade(sub, lastXC).
*/
virtual void cascade();
/**
* Hook to allow vetoing of event after showering hard sub-process
* as in e.g. MLM merging.
*/
virtual bool showerHardProcessVeto() { return false; };
/**
* It returns true if the particle with the specified id
* is in the list of those that should be decayed during the showering
* showering.
*/
bool decaysInShower(const long id) const {
return ( particlesDecayInShower_.find( abs(id) ) !=
particlesDecayInShower_.end() );
}
public:
/**@name Methods related to PDF freezing */
//@{
/**
* Get the PDF freezing scale
*/
Energy pdfFreezingScale() const {return pdfFreezingScale_;}
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
public:
/** @name Functions to access information. */
//@{
/**
* Return true if currently the primary subprocess is showered.
*/
bool firstInteraction() const {
return ( subProcess_ ==
eventHandler()->currentCollision()->primarySubProcess() );
}
/**
* Return the currently used SubProcess.
*/
tSubProPtr currentSubProcess() const {
assert(subProcess_);
return subProcess_;
}
/**
* Return true if multiple parton interactions are switched on
* and can be used for this beam setup.
*/
bool isMPIOn() const {
return MPIHandler_ && MPIHandler_->beamOK();
}
/**
* Return the remnant decayer.
*/
tHwRemDecPtr remnantDecayer() const { return remDec_; }
//@}
/**
* Access to the Evolver
*/
tEvolverPtr evolver() const {return evolver_;}
/**
* Generate hard emissions for CKKW etc
*/
virtual HardTreePtr generateCKKW(ShowerTreePtr tree) const;
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
virtual IBPtr fullclone() const;
//@}
protected:
/**
* Prepare to shower the given subprocess
*/
void prepareCascade(tSubProPtr sub);
/**
* The main method which manages the showering of a subprocess.
*/
virtual tPPair cascade(tSubProPtr sub, XCPtr xcomb);
/**
* Return the maximum number of attempts for showering
* a given subprocess.
*/
unsigned int maxtry() const { return maxtry_; }
/**
* At the end of the Showering, transform ShowerParticle objects
* into ThePEG particles and fill the event record with them.
* Notice that the parent/child relationships and the
* transformation from ShowerColourLine objects into ThePEG
* ColourLine ones must be properly handled.
*/
void fillEventRecord();
/**
* Identify the particles in the hard process and decayed particles
* which need to be showered
*/
void findShoweringParticles();
/**
* Find the final unstable time-like parent of a particle
* @param parent The ultimate parent for the decaying particle
* @param isHard Whether nay particles in chain are from the hard process
* @param outgoing The outgoing particles from the hard process
*/
PPtr findParent(PPtr parent, bool & isHard, set<PPtr> outgoing) const;
/**
* Find the parton extracted from the incoming particle after ISR
*/
PPtr findFirstParton(tPPtr seed) const;
/**
* Fix Remnant connections after ISR
*/
tPPair remakeRemnant(tPPair oldp);
/**
* Get the remnants from the ThePEG::PartonBinInstance es and
* do some checks.
*/
RemPair getRemnants(PBIPair incbins);
/**
* Make the remnant after the shower
*/
void makeRemnants();
/**
* Reset the PDF's after the hard collision has been showered
*/
void setMPIPDFs();
/**
* Test for decay products
*/
bool decayProduct(tPPtr) const;
/**
* Boost all the particles in the collision so that the collision always occurs
* in the rest frame with the incoming particles along the z axis
*/
void boostCollision(bool boost);
/**
* Is a beam particle where hadronic structure is resolved
*/
bool isResolvedHadron(tPPtr);
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit();
/**
* Initialize this object. Called in the run phase just before
* a run begins.
*/
virtual void doinitrun();
/**
* Called at the end of the run phase.
*/
virtual void dofinish();
//@}
private:
/**
- * The static object used to initialize the description of this class.
- * Indicates that this is a concrete class with persistent data.
- */
- static ClassDescription<ShowerHandler> initShowerHandler;
-
- /**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
ShowerHandler & operator=(const ShowerHandler &);
private:
/**
* Access function for the MPIHandler, it should only be called after
* checking with isMPIOn.
*/
tUEBasePtr getMPIHandler() const {
assert(MPIHandler_);
return MPIHandler_;
}
private:
/**
* a MPIHandler to administer the creation of several (semihard)
* partonic interactions.
*/
UEBasePtr MPIHandler_;
/**
* Pointer to the evolver
*/
EvolverPtr evolver_;
/**
* Pointer to the HwRemDecayer
*/
HwRemDecPtr remDec_;
/**
* The PDF for beam particle A. Overrides the particle's own PDF setting.
*/
PDFPtr PDFA_;
/**
* The PDF for beam particle B. Overrides the particle's own PDF setting.
*/
PDFPtr PDFB_;
/**
* The PDF freezing scale
*/
Energy pdfFreezingScale_;
/**
* Maximum number of attempts for the
* main showering loop
*/
unsigned int maxtry_;
/**
* Maximum number of attempts for the regeneration of an additional
* scattering, before the number of scatters is reduced.
*/
unsigned int maxtryMPI_;
/**
* Maximum number of attempts for the regeneration of an additional
* hard scattering, before this event is vetoed.
*/
unsigned int maxtryDP_;
/**
* PDG codes of the particles which decay during showering
* this is fast storage for use during running
*/
set<long> particlesDecayInShower_;
/**
* PDG codes of the particles which decay during showering
* this is a vector that is interfaced so they can be changed
*/
vector<long> inputparticlesDecayInShower_;
/**
* The ShowerTree for the hard process
*/
ShowerTreePtr hard_;
/**
* The incoming beam particles for the current collision
*/
tPPair incoming_;
/**
* The ShowerTree for the decays
*/
ShowerDecayMap decay_;
/**
* The ShowerTrees for which the initial shower
*/
vector<ShowerTreePtr> done_;
/**
* Const pointer to the current step
*/
tcStepPtr current_;
/**
* Const pointer to the currently handeled ThePEG::SubProcess
*/
tSubProPtr subProcess_;
/**
* pointer to "this", the current ShowerHandler.
*/
static ShowerHandler * currentHandler_;
/**
* Boost to get back to the lab
*/
LorentzRotation boost_;
/**
* The MPI PDF's to be used for secondary scatters.
*/
pair <PDFPtr, PDFPtr> mpipdfs_;
public:
/**
* struct that is used to catch exceptions which are thrown
* due to energy conservation issues of additional scatters
*/
struct ExtraScatterVeto {};
/**
* struct that is used to catch exceptions which are thrown
* due to fact that the Shower has been invoked more than
* a defined threshold on a certain configuration
*/
struct ShowerTriesVeto {
/** variable to store the number of attempts */
const int tries;
/** constructor */
ShowerTriesVeto(int t) : tries(t) {}
};
/**
* pointer to "this", the current ShowerHandler.
*/
static const ShowerHandler * currentHandler() {
assert(currentHandler_);
return currentHandler_;
}
protected:
/**
* Set the current handler
*/
void setCurrentHandler() {
currentHandler_ = this;
}
};
}
-#include "ThePEG/Utilities/ClassTraits.h"
-
-namespace ThePEG {
-
-/** @cond TRAITSPECIALIZATIONS */
-
-/** This template specialization informs ThePEG about the
- * base classes of ShowerHandler. */
-template <>
-struct BaseClassTrait<Herwig::ShowerHandler,1> {
- /** Typedef of the first base class of ShowerHandler. */
- typedef CascadeHandler NthBase;
-};
-
-/** This template specialization informs ThePEG about the name of
- * the ShowerHandler class and the shared object where it is defined. */
-template <>
-struct ClassTraits<Herwig::ShowerHandler>
- : public ClassTraitsBase<Herwig::ShowerHandler> {
- /** Return a platform-independent class name */
- static string className() { return "Herwig::ShowerHandler"; }
- /**
- * The name of a file containing the dynamic library where the class
- * ShowerHandler is implemented. It may also include several, space-separated,
- * libraries if the class ShowerHandler depends on other classes (base classes
- * excepted). In this case the listed libraries will be dynamically
- * linked in the order they are specified.
- */
- static string library() { return "HwShower.so"; }
-};
-
-/** @endcond */
-
-}
-
#endif /* HERWIG_ShowerHandler_H */
diff --git a/Shower/SplittingFunctions/HalfHalfOneSplitFn.cc b/Shower/SplittingFunctions/HalfHalfOneSplitFn.cc
--- a/Shower/SplittingFunctions/HalfHalfOneSplitFn.cc
+++ b/Shower/SplittingFunctions/HalfHalfOneSplitFn.cc
@@ -1,95 +1,96 @@
// -*- C++ -*-
//
// HalfHalfOneSplitFn.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 HalfHalfOneSplitFn class.
//
#include "HalfHalfOneSplitFn.h"
#include "ThePEG/PDT/ParticleData.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include <cassert>
+#include "ThePEG/Utilities/DescribeClass.h"
using namespace Herwig;
-NoPIOClassDescription<HalfHalfOneSplitFn> HalfHalfOneSplitFn::initHalfHalfOneSplitFn;
-// Definition of the static class description member.
+DescribeNoPIOClass<HalfHalfOneSplitFn,Herwig::SplittingFunction>
+describeHalfHalfOneSplitFn ("Herwig::HalfHalfOneSplitFn","HwShower.so");
void HalfHalfOneSplitFn::Init() {
static ClassDocumentation<HalfHalfOneSplitFn> documentation
("The HalfHalfOneSplitFn class implements the q -> qg splitting function");
}
double HalfHalfOneSplitFn::P(const double z, const Energy2 t,
const IdList &ids, const bool mass) const {
double val = (1. + sqr(z))/(1.-z);
if(mass) {
Energy m = getParticleData(ids[0])->mass();
val -= 2.*sqr(m)/t;
}
return colourFactor()*val;
}
double HalfHalfOneSplitFn::overestimateP(const double z, const IdList &) const {
return 2.*colourFactor()/(1.-z);
}
double HalfHalfOneSplitFn::ratioP(const double z, const Energy2 t,
const IdList &ids, const bool mass) const {
double val = 1. + sqr(z);
if(mass) {
Energy m = getParticleData(ids[0])->mass();
val -= 2.*sqr(m)*(1.-z)/t;
}
return 0.5*val;
}
double HalfHalfOneSplitFn::integOverP(const double z, const IdList & ,
unsigned int PDFfactor) const {
switch (PDFfactor) {
case 0:
return -2.*colourFactor()*log(1.-z);
case 1:
return 2.*colourFactor()*log(z/(1.-z));
case 2:
return 2.*colourFactor()/(1.-z);
case 3:
default:
throw Exception() << "HalfHalfOneSplitFn::integOverP() invalid PDFfactor = "
<< PDFfactor << Exception::runerror;
}
}
double HalfHalfOneSplitFn::invIntegOverP(const double r, const IdList & ,
unsigned int PDFfactor) const {
switch (PDFfactor) {
case 0:
return 1. - exp(- 0.5*r/colourFactor());
case 1:
return 1./(1.-exp(-0.5*r/colourFactor()));
case 2:
return 1.-2.*colourFactor()/r;
case 3:
default:
throw Exception() << "HalfHalfOneSplitFn::invIntegOverP() invalid PDFfactor = "
<< PDFfactor << Exception::runerror;
}
}
bool HalfHalfOneSplitFn::accept(const IdList &ids) const {
// 3 particles and in and out fermion same
if(ids.size()!=3 || ids[0]!=ids[1]) return false;
tcPDPtr q=getParticleData(ids[0]);
tcPDPtr g=getParticleData(ids[2]);
if(q->iSpin()!=PDT::Spin1Half ||
g->iSpin()!=PDT::Spin1) return false;
return checkColours(ids);
}
diff --git a/Shower/SplittingFunctions/HalfHalfOneSplitFn.h b/Shower/SplittingFunctions/HalfHalfOneSplitFn.h
--- a/Shower/SplittingFunctions/HalfHalfOneSplitFn.h
+++ b/Shower/SplittingFunctions/HalfHalfOneSplitFn.h
@@ -1,193 +1,152 @@
// -*- C++ -*-
//
// HalfHalfOneSplitFn.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_HalfHalfOneSplitFn_H
#define HERWIG_HalfHalfOneSplitFn_H
//
// This is the declaration of the HalfHalfOneSplitFn class.
//
#include "SplittingFunction.h"
namespace Herwig {
using namespace ThePEG;
/**\ingroup Shower
*
* This class provides the concrete implementation of the exact leading-order
* splitting function for \f$\frac12\to q\frac12 1\f$.
*
* In this case the splitting function is given by
* \f[P(z,t) =C\left(\frac{1+z^2}{1-z}-2\frac{m^2_q}{t}\right),\f]
* where \f$C\f$ is the corresponding colour factor.
* Our choice for the overestimate is
* \f[P_{\rm over}(z) = \frac{2C}{1-z},\f]
* therefore the integral is
* \f[\int P_{\rm over}(z) {\rm d}z = -2C\ln(1-z),\f]
* and its inverse is
* \f[1-\exp\left(\frac{r}{2C}\right).\f]
*
* @see \ref HalfHalfOneSplitFnInterfaces "The interfaces"
* defined for HalfHalfOneSplitFn.
*/
class HalfHalfOneSplitFn: public SplittingFunction {
public:
/**
* The default constructor.
*/
inline HalfHalfOneSplitFn() : SplittingFunction(1) {}
/**
* Concrete implementation of the method to determine whether this splitting
* function can be used for a given set of particles.
* @param ids The PDG codes for the particles in the splitting.
*/
virtual bool accept(const IdList & ids) const;
/**
* Methods to return the splitting function.
*/
//@{
/**
* The concrete implementation of the splitting function, \f$P(z,t)\f$.
* @param z The energy fraction.
* @param t The scale.
* @param ids The PDG codes for the particles in the splitting.
* @param mass Whether or not to include the mass dependent terms
*/
virtual double P(const double z, const Energy2 t, const IdList & ids,
const bool mass) const;
/**
* The concrete implementation of the overestimate of the splitting function,
* \f$P_{\rm over}\f$.
* @param z The energy fraction.
* @param ids The PDG codes for the particles in the splitting.
*/
virtual double overestimateP(const double z, const IdList & ids) const;
/**
* The concrete implementation of the
* the ratio of the splitting function to the overestimate, i.e.
* \f$P(z,t)/P_{\rm over}(z)\f$.
* @param z The energy fraction.
* @param t The scale.
* @param ids The PDG codes for the particles in the splitting.
* @param mass Whether or not to include the mass dependent terms
*/
virtual double ratioP(const double z, const Energy2 t, const IdList & ids,
const bool mass) const;
/**
* The concrete implementation of the indefinite integral of the
* overestimated splitting function, \f$P_{\rm over}\f$.
* @param z The energy fraction.
* @param ids The PDG codes for the particles in the splitting.
* @param PDFfactor Which additional factor to include for the PDF
* 0 is no additional factor,
* 1 is \f$1/z\f$, 2 is \f$1/(1-z)\f$ and 3 is \f$1/z/(1-z)\f$
*/
virtual double integOverP(const double z, const IdList & ids,
unsigned int PDFfactor=0) const;
/**
* The concrete implementation of the inverse of the indefinite integral.
* @param r Value of the splitting function to be inverted
* @param ids The PDG codes for the particles in the splitting.
* @param PDFfactor Which additional factor to include for the PDF
* 0 is no additional factor,
* 1 is \f$1/z\f$, 2 is \f$1/(1-z)\f$ and 3 is \f$1/z/(1-z)\f$
*/
virtual double invIntegOverP(const double r, const IdList & ids,
unsigned int PDFfactor=0) const;
//@}
public:
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
inline virtual IBPtr clone() const {return new_ptr(*this);}
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
inline virtual IBPtr fullclone() const {return new_ptr(*this);}
//@}
private:
/**
- * The static object used to initialize the description of this class.
- * Indicates that this is an concrete class without persistent data.
- */
- static NoPIOClassDescription<HalfHalfOneSplitFn> initHalfHalfOneSplitFn;
-
- /**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
HalfHalfOneSplitFn & operator=(const HalfHalfOneSplitFn &);
};
}
-#include "ThePEG/Utilities/ClassTraits.h"
-
-namespace ThePEG {
-
-/** @cond TRAITSPECIALIZATIONS */
-
-/** This template specialization informs ThePEG about the
- * base classes of HalfHalfOneSplitFn. */
-template <>
-struct BaseClassTrait<Herwig::HalfHalfOneSplitFn,1> {
- /** Typedef of the first base class of HalfHalfOneSplitFn. */
- typedef Herwig::SplittingFunction NthBase;
-};
-
-/** This template specialization informs ThePEG about the name of
- * the HalfHalfOneSplitFn class and the shared object where it is defined. */
-template <>
-struct ClassTraits<Herwig::HalfHalfOneSplitFn>
- : public ClassTraitsBase<Herwig::HalfHalfOneSplitFn> {
- /** Return a platform-independent class name */
- static string className() { return "Herwig::HalfHalfOneSplitFn"; }
- /**
- * The name of a file containing the dynamic library where the class
- * HalfHalfOneSplitFn is implemented. It may also include several, space-separated,
- * libraries if the class HalfHalfOneSplitFn depends on other classes (base classes
- * excepted). In this case the listed libraries will be dynamically
- * linked in the order they are specified.
- */
- static string library() { return "HwShower.so"; }
-};
-
-/** @endcond */
-
-}
-
#endif /* HERWIG_HalfHalfOneSplitFn_H */
diff --git a/Shower/SplittingFunctions/HalfOneHalfSplitFn.cc b/Shower/SplittingFunctions/HalfOneHalfSplitFn.cc
--- a/Shower/SplittingFunctions/HalfOneHalfSplitFn.cc
+++ b/Shower/SplittingFunctions/HalfOneHalfSplitFn.cc
@@ -1,96 +1,97 @@
// -*- C++ -*-
//
// HalfOneHalfSplitFn.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 HalfOneHalfSplitFn class.
//
#include "HalfOneHalfSplitFn.h"
#include "ThePEG/PDT/ParticleData.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include <cassert>
+#include "ThePEG/Utilities/DescribeClass.h"
using namespace Herwig;
-NoPIOClassDescription<HalfOneHalfSplitFn> HalfOneHalfSplitFn::initHalfOneHalfSplitFn;
-// Definition of the static class description member.
+DescribeNoPIOClass<HalfOneHalfSplitFn,Herwig::SplittingFunction>
+describeHalfOneHalfSplitFn ("Herwig::HalfOneHalfSplitFn","HwShower.so");
void HalfOneHalfSplitFn::Init() {
static ClassDocumentation<HalfOneHalfSplitFn> documentation
("The HalfOneHalfSplitFn class implements the splitting function for q -> g q");
}
double HalfOneHalfSplitFn::P(const double z, const Energy2 t,
const IdList &ids, const bool mass) const {
double val=(2.*(1.-z)+sqr(z))/z;
if(mass) {
Energy m = getParticleData(ids[0])->mass();
val-=2.*sqr(m)/t;
}
return colourFactor()*val;
}
double HalfOneHalfSplitFn::overestimateP(const double z, const IdList &) const {
return 2.*colourFactor()/z;
}
double HalfOneHalfSplitFn::ratioP(const double z, const Energy2 t,
const IdList &ids,const bool mass) const {
double val=2.*(1.-z)+sqr(z);
if(mass) {
Energy m=getParticleData(ids[0])->mass();
val -=2.*sqr(m)*z/t;
}
return 0.5*val;
}
double HalfOneHalfSplitFn::integOverP(const double z, const IdList & ,
unsigned int PDFfactor) const {
switch(PDFfactor) {
case 0:
return 2.*colourFactor()*log(z);
case 1:
return -2.*colourFactor()/z;
case 2:
return 2.*colourFactor()*log(z/(1.-z));
case 3:
default:
throw Exception() << "HalfOneHalfSplitFn::integOverP() invalid PDFfactor = "
<< PDFfactor << Exception::runerror;
}
}
double HalfOneHalfSplitFn::invIntegOverP(const double r, const IdList & ,
unsigned int PDFfactor) const {
switch(PDFfactor) {
case 0:
return exp(0.5*r/colourFactor());
case 1:
return -2.*colourFactor()/r;
case 2:
return 1./(1.+exp(-0.5*r/colourFactor()));
case 3:
default:
throw Exception() << "HalfOneHalfSplitFn::integOverP() invalid PDFfactor = "
<< PDFfactor << Exception::runerror;
}
}
bool HalfOneHalfSplitFn::accept(const IdList &ids) const {
// 3 particles and in and out fermion same
if(ids.size()!=3 || ids[0]!=ids[2]) return false;
tcPDPtr q=getParticleData(ids[0]);
tcPDPtr g=getParticleData(ids[1]);
if(q->iSpin()!=PDT::Spin1Half ||
g->iSpin()!=PDT::Spin1) return false;
return checkColours(ids);
}
diff --git a/Shower/SplittingFunctions/HalfOneHalfSplitFn.h b/Shower/SplittingFunctions/HalfOneHalfSplitFn.h
--- a/Shower/SplittingFunctions/HalfOneHalfSplitFn.h
+++ b/Shower/SplittingFunctions/HalfOneHalfSplitFn.h
@@ -1,193 +1,152 @@
// -*- C++ -*-
//
// HalfOneHalfSplitFn.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_HalfOneHalfSplitFn_H
#define HERWIG_HalfOneHalfSplitFn_H
//
// This is the declaration of the HalfOneHalfSplitFn class.
//
#include "SplittingFunction.h"
namespace Herwig {
using namespace ThePEG;
/** \ingroup Shower
*
* This classs provides the concrete implementation of the exact leading-order
* splitting function for \f$\frac12\to 1\frac12\f$.
*
* In this case the splitting function is given by
* \f[P(z,t) = C\left(\frac{2(1-z)+z^2}{z}-2\frac{m^2_q}t\right),\f]
* where \f$C\f$ is the corresponding colour factor.
* Our choice for the overestimate is
* \f[P_{\rm over}(z) = 2C\frac1z,\f]
* therefore the integral is
* \f[\int P_{\rm over}(z) {\rm d}z = 2C\ln z,\f]
* and its inverse is
* \f[\exp\left(\frac{r}{2C}\right).\f]
*
* @see SplittingFunction
*/
class HalfOneHalfSplitFn: public SplittingFunction {
public:
/**
* The default constructor.
*/
- inline HalfOneHalfSplitFn() : SplittingFunction(1) {}
+ HalfOneHalfSplitFn() : SplittingFunction(1) {}
/**
* Concrete implementation of the method to determine whether this splitting
* function can be used for a given set of particles.
* @param ids The PDG codes for the particles in the splitting.
*/
virtual bool accept(const IdList & ids) const;
/**
* Methods to return the splitting function.
*/
//@{
/**
* The concrete implementation of the splitting function, \f$P(z,t)\f$.
* @param z The energy fraction.
* @param t The scale.
* @param ids The PDG codes for the particles in the splitting.
* @param mass Whether or not to include the mass dependent terms
*/
virtual double P(const double z, const Energy2 t, const IdList & ids,
const bool mass) const;
/**
* The concrete implementation of the overestimate of the splitting function,
* \f$P_{\rm over}\f$.
* @param z The energy fraction.
* @param ids The PDG codes for the particles in the splitting.
*/
virtual double overestimateP(const double z, const IdList & ids) const;
/**
* The concrete implementation of the
* the ratio of the splitting function to the overestimate, i.e.
* \f$P(z,t)/P_{\rm over}(z)\f$.
* @param z The energy fraction.
* @param t The scale.
* @param ids The PDG codes for the particles in the splitting.
* @param mass Whether or not to include the mass dependent terms
*/
virtual double ratioP(const double z, const Energy2 t, const IdList & ids,
const bool mass) const;
/**
* The concrete implementation of the indefinite integral of the
* overestimated splitting function, \f$P_{\rm over}\f$.
* @param z The energy fraction.
* @param ids The PDG codes for the particles in the splitting.
* @param PDFfactor Which additional factor to include for the PDF
* 0 is no additional factor,
* 1 is \f$1/z\f$, 2 is \f$1/(1-z)\f$ and 3 is \f$1/z/(1-z)\f$
*/
virtual double integOverP(const double z, const IdList & ids,
unsigned int PDFfactor=0) const;
/**
* The concrete implementation of the inverse of the indefinite integral.
* @param r Value of the splitting function to be inverted
* @param ids The PDG codes for the particles in the splitting.
* @param PDFfactor Which additional factor to include for the PDF
* 0 is no additional factor,
* 1 is \f$1/z\f$, 2 is \f$1/(1-z)\f$ and 3 is \f$1/z/(1-z)\f$
*/
virtual double invIntegOverP(const double r, const IdList & ids,
unsigned int PDFfactor=0) const;
//@}
public:
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
- inline virtual IBPtr clone() const {return new_ptr(*this);}
+ virtual IBPtr clone() const {return new_ptr(*this);}
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
- inline virtual IBPtr fullclone() const {return new_ptr(*this);}
+ virtual IBPtr fullclone() const {return new_ptr(*this);}
//@}
private:
/**
- * The static object used to initialize the description of this class.
- * Indicates that this is an concrete class without persistent data.
- */
- static NoPIOClassDescription<HalfOneHalfSplitFn> initHalfOneHalfSplitFn;
-
- /**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
HalfOneHalfSplitFn & operator=(const HalfOneHalfSplitFn &);
};
}
-#include "ThePEG/Utilities/ClassTraits.h"
-
-namespace ThePEG {
-
-/** @cond TRAITSPECIALIZATIONS */
-
-/** This template specialization informs ThePEG about the
- * base classes of HalfOneHalfSplitFn. */
-template <>
-struct BaseClassTrait<Herwig::HalfOneHalfSplitFn,1> {
- /** Typedef of the first base class of HalfOneHalfSplitFn. */
- typedef Herwig::SplittingFunction NthBase;
-};
-
-/** This template specialization informs ThePEG about the name of
- * the HalfOneHalfSplitFn class and the shared object where it is defined. */
-template <>
-struct ClassTraits<Herwig::HalfOneHalfSplitFn>
- : public ClassTraitsBase<Herwig::HalfOneHalfSplitFn> {
- /** Return a platform-independent class name */
- static string className() { return "Herwig::HalfOneHalfSplitFn"; }
- /**
- * The name of a file containing the dynamic library where the class
- * HalfOneHalfSplitFn is implemented. It may also include several, space-separated,
- * libraries if the class HalfOneHalfSplitFn depends on other classes (base classes
- * excepted). In this case the listed libraries will be dynamically
- * linked in the order they are specified.
- */
- static string library() { return "HwShower.so"; }
-};
-
-/** @endcond */
-
-}
-
#endif /* HERWIG_HalfOneHalfSplitFn_H */
diff --git a/Shower/SplittingFunctions/OneHalfHalfSplitFn.cc b/Shower/SplittingFunctions/OneHalfHalfSplitFn.cc
--- a/Shower/SplittingFunctions/OneHalfHalfSplitFn.cc
+++ b/Shower/SplittingFunctions/OneHalfHalfSplitFn.cc
@@ -1,99 +1,100 @@
// -*- C++ -*-
//
// OneHalfHalfSplitFn.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 OneHalfHalfSplitFn class.
//
#include "OneHalfHalfSplitFn.h"
#include "ThePEG/PDT/ParticleData.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include <cassert>
+#include "ThePEG/Utilities/DescribeClass.h"
using namespace Herwig;
-NoPIOClassDescription<OneHalfHalfSplitFn> OneHalfHalfSplitFn::initOneHalfHalfSplitFn;
-// Definition of the static class description member.
+DescribeNoPIOClass<OneHalfHalfSplitFn,Herwig::SplittingFunction>
+describeOneHalfHalfSplitFn ("Herwig::OneHalfHalfSplitFn","HwShower.so");
void OneHalfHalfSplitFn::Init() {
static ClassDocumentation<OneHalfHalfSplitFn> documentation
("The OneHalfHalfSplitFn class implements the splitting function for g->q qbar");
}
double OneHalfHalfSplitFn::P(const double z, const Energy2 t,
const IdList &ids, const bool mass) const {
double zz = z*(1.-z);
double val=1.-2.*zz;
if(mass) {
Energy m = getParticleData(ids[1])->mass();
val +=2.*sqr(m)/t;
}
return colourFactor()*val;
}
double OneHalfHalfSplitFn::overestimateP(const double, const IdList &) const {
return colourFactor();
}
double OneHalfHalfSplitFn::ratioP(const double z, const Energy2 t,
const IdList &ids, const bool mass) const {
double zz = z*(1.-z);
double val = 1.-2.*zz;
if(mass) {
Energy m = getParticleData(ids[1])->mass();
val+= 2.*sqr(m)/t;
}
return val;
}
double OneHalfHalfSplitFn::integOverP(const double z, const IdList & ,
unsigned int PDFfactor) const {
switch(PDFfactor) {
case 0:
return colourFactor()*z;
case 1:
return colourFactor()*log(z);
case 2:
return -colourFactor()*log(1.-z);
case 3:
return colourFactor()*log(z/(1.-z));
default:
throw Exception() << "OneHalfHalfSplitFn::integOverP() invalid PDFfactor = "
<< PDFfactor << Exception::runerror;
}
}
double OneHalfHalfSplitFn::invIntegOverP(const double r, const IdList & ,
unsigned int PDFfactor) const {
switch(PDFfactor) {
case 0:
return r/colourFactor();
case 1:
return exp(r/colourFactor());
case 2:
return 1.-exp(-r/colourFactor());
case 3:
return 1./(1.+exp(-r/colourFactor()));
default:
throw Exception() << "OneHalfHalfSplitFn::integOverP() invalid PDFfactor = "
<< PDFfactor << Exception::runerror;
}
}
bool OneHalfHalfSplitFn::accept(const IdList &ids) const {
if(ids.size()!=3) return false;
if(ids[1]!=-ids[2]) return false;
tcPDPtr q=getParticleData(ids[1]);
if(q->iSpin()!=PDT::Spin1Half) return false;
tcPDPtr g=getParticleData(ids[0]);
if(g->iSpin()!=PDT::Spin1) return false;
return checkColours(ids);
}
diff --git a/Shower/SplittingFunctions/OneHalfHalfSplitFn.h b/Shower/SplittingFunctions/OneHalfHalfSplitFn.h
--- a/Shower/SplittingFunctions/OneHalfHalfSplitFn.h
+++ b/Shower/SplittingFunctions/OneHalfHalfSplitFn.h
@@ -1,194 +1,153 @@
// -*- C++ -*-
//
// OneHalfHalfSplitFn.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_OneHalfHalfSplitFn_H
#define HERWIG_OneHalfHalfSplitFn_H
//
// This is the declaration of the OneHalfHalfSplitFn class.
//
#include "SplittingFunction.h"
namespace Herwig {
using namespace ThePEG;
/**\ingroup Shower
*
* This class provides the concrete implementation of the exact leading-order
* splitting function for \f$1\to \frac12\frac12\f$.
*
* In this case the splitting function is given by
* \f[P(z,t) =C\left(1-2z(1-z)+2\frac{m_q^2}{t}\right),\f]
* where \f$C\f$ is the corresponding colour factor
* Our choice for the overestimate is
* \f[P_{\rm over}(z) = C,\f]
* therefore the integral is
* \f[\int P_{\rm over}(z) {\rm d}z =Cz,\f]
* and its inverse is
* \f[\frac{r}{C}\f]
*
* @see \ref OneHalfHalfSplitFnInterfaces "The interfaces"
* defined for OneHalfHalfSplitFn.
*/
class OneHalfHalfSplitFn: public SplittingFunction {
public:
/**
* The default constructor.
*/
inline OneHalfHalfSplitFn() : SplittingFunction(1) {}
/**
* Concrete implementation of the method to determine whether this splitting
* function can be used for a given set of particles.
* @param ids The PDG codes for the particles in the splitting.
*/
virtual bool accept(const IdList & ids) const;
/**
* Methods to return the splitting function.
*/
//@{
/**
* The concrete implementation of the splitting function, \f$P\f$.
* @param z The energy fraction.
* @param t The scale.
* @param ids The PDG codes for the particles in the splitting.
* @param mass Whether or not to include the mass dependent terms
*/
virtual double P(const double z, const Energy2 t, const IdList & ids,
const bool mass) const;
/**
* The concrete implementation of the overestimate of the splitting function,
* \f$P_{\rm over}\f$.
* @param z The energy fraction.
* @param ids The PDG codes for the particles in the splitting.
*/
virtual double overestimateP(const double z, const IdList & ids) const;
/**
* The concrete implementation of the
* the ratio of the splitting function to the overestimate, i.e.
* \f$P(z,\tilde{q}^2)/P_{\rm over}(z)\f$.
* @param z The energy fraction.
* @param t The scale.
* @param ids The PDG codes for the particles in the splitting.
* @param mass Whether or not to include the mass dependent terms
*/
virtual double ratioP(const double z, const Energy2 t, const IdList & ids,
const bool mass) const;
/**
* The concrete implementation of the indefinite integral of the
* overestimated splitting function, \f$P_{\rm over}\f$.
* @param z The energy fraction.
* @param ids The PDG codes for the particles in the splitting.
* @param PDFfactor Which additional factor to include for the PDF
* 0 is no additional factor,
* 1 is \f$1/z\f$, 2 is \f$1/(1-z)\f$ and 3 is \f$1/z/(1-z)\f$
*/
virtual double integOverP(const double z, const IdList & ids,
unsigned int PDFfactor=0) const;
/**
* The concrete implementation of the inverse of the indefinite integral.
* @param r Value of the splitting function to be inverted
* @param ids The PDG codes for the particles in the splitting.
* @param PDFfactor Which additional factor to include for the PDF
* 0 is no additional factor,
* 1 is \f$1/z\f$, 2 is \f$1/(1-z)\f$ and 3 is \f$1/z/(1-z)\f$
*/
virtual double invIntegOverP(const double r, const IdList & ids,
unsigned int PDFfactor=0) const;
//@}
public:
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
inline virtual IBPtr clone() const {return new_ptr(*this);}
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
inline virtual IBPtr fullclone() const {return new_ptr(*this);}
//@}
private:
/**
- * The static object used to initialize the description of this class.
- * Indicates that this is an concrete class without persistent data.
- */
- static NoPIOClassDescription<OneHalfHalfSplitFn> initOneHalfHalfSplitFn;
-
- /**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
OneHalfHalfSplitFn & operator=(const OneHalfHalfSplitFn &);
};
}
-#include "ThePEG/Utilities/ClassTraits.h"
-
-namespace ThePEG {
-
-/** @cond TRAITSPECIALIZATIONS */
-
-/** This template specialization informs ThePEG about the
- * base classes of OneHalfHalfSplitFn. */
-template <>
-struct BaseClassTrait<Herwig::OneHalfHalfSplitFn,1> {
- /** Typedef of the first base class of OneHalfHalfSplitFn. */
- typedef Herwig::SplittingFunction NthBase;
-};
-
-/** This template specialization informs ThePEG about the name of
- * the OneHalfHalfSplitFn class and the shared object where it is defined. */
-template <>
-struct ClassTraits<Herwig::OneHalfHalfSplitFn>
- : public ClassTraitsBase<Herwig::OneHalfHalfSplitFn> {
- /** Return a platform-independent class name */
- static string className() { return "Herwig::OneHalfHalfSplitFn"; }
- /**
- * The name of a file containing the dynamic library where the class
- * OneHalfHalfSplitFn is implemented. It may also include several, space-separated,
- * libraries if the class OneHalfHalfSplitFn depends on other classes (base classes
- * excepted). In this case the listed libraries will be dynamically
- * linked in the order they are specified.
- */
- static string library() { return "HwShower.so"; }
-};
-
-/** @endcond */
-
-}
-
#endif /* HERWIG_OneHalfHalfSplitFn_H */
diff --git a/Shower/SplittingFunctions/OneOneOneSplitFn.cc b/Shower/SplittingFunctions/OneOneOneSplitFn.cc
--- a/Shower/SplittingFunctions/OneOneOneSplitFn.cc
+++ b/Shower/SplittingFunctions/OneOneOneSplitFn.cc
@@ -1,85 +1,86 @@
// -*- C++ -*-
//
// OneOneOneSplitFn.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 OneOneOneSplitFn class.
//
#include "OneOneOneSplitFn.h"
#include "ThePEG/PDT/ParticleData.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include <cassert>
+#include "ThePEG/Utilities/DescribeClass.h"
using namespace Herwig;
-NoPIOClassDescription<OneOneOneSplitFn> OneOneOneSplitFn::initOneOneOneSplitFn;
-// Definition of the static class description member.
+DescribeNoPIOClass<OneOneOneSplitFn,Herwig::SplittingFunction>
+describeOneOneOneSplitFn ("Herwig::OneOneOneSplitFn","HwShower.so");
void OneOneOneSplitFn::Init() {
static ClassDocumentation<OneOneOneSplitFn> documentation
("The OneOneOneSplitFn class implements the g -> gg splitting function");
}
double OneOneOneSplitFn::P(const double z, const Energy2, const IdList &,
const bool)const {
// (this is historically important! the first physics - two years
// after the birth of the project - in the Herwig++ shower! Alberto
// & Stefan, 25/04/2002).
return colourFactor()*sqr(1.-z*(1.-z))/(z*(1.-z));
}
double OneOneOneSplitFn::overestimateP(const double z, const IdList &) const {
return colourFactor()*(1/z + 1/(1.-z));
}
double OneOneOneSplitFn::ratioP(const double z, const Energy2, const IdList &,
const bool) const {
return sqr(1.-z*(1.-z));
}
double OneOneOneSplitFn::invIntegOverP(const double r, const IdList & ,
unsigned int PDFfactor) const {
switch(PDFfactor) {
case 0:
return 1./(1.+exp(-r/colourFactor()));
case 1:
case 2:
case 3:
default:
throw Exception() << "OneOneOneSplitFn::integOverP() invalid PDFfactor = "
<< PDFfactor << Exception::runerror;
}
}
double OneOneOneSplitFn::integOverP(const double z, const IdList & ,
unsigned int PDFfactor) const {
switch(PDFfactor) {
case 0:
return colourFactor()*log(z/(1.-z));
case 1:
case 2:
case 3:
default:
throw Exception() << "OneOneOneSplitFn::integOverP() invalid PDFfactor = "
<< PDFfactor << Exception::runerror;
}
}
bool OneOneOneSplitFn::accept(const IdList & ids) const {
if(ids.size()!=3) return false;
for(unsigned int ix=0;ix<ids.size();++ix) {
tcPDPtr part = getParticleData(ids[ix]);
if(part->iSpin()!=PDT::Spin1) return false;
}
return checkColours(ids);
}
diff --git a/Shower/SplittingFunctions/OneOneOneSplitFn.h b/Shower/SplittingFunctions/OneOneOneSplitFn.h
--- a/Shower/SplittingFunctions/OneOneOneSplitFn.h
+++ b/Shower/SplittingFunctions/OneOneOneSplitFn.h
@@ -1,194 +1,153 @@
// -*- C++ -*-
//
// OneOneOneSplitFn.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_OneOneOneSplitFn_H
#define HERWIG_OneOneOneSplitFn_H
//
// This is the declaration of the OneOneOneSplitFn class.
//
#include "SplittingFunction.h"
namespace Herwig {
using namespace ThePEG;
/** \ingroup Shower
*
* This class provides the concrete implementation of the exact leading-order
* splitting function for \f$1\to 11\f$.
*
* In this case the splitting function is given by
* \f[P(z) =2C*\left(\frac{z}{1-z}+\frac{1-z}{z}+z(1-z)\right),\f]
* where \f$C=\f$ is the corresponding colour factor.
* Our choice for the overestimate is
* \f[P_{\rm over}(z) = 2C\left(\frac1z+\frac1{1-z}\right),\f]
* therefore the integral is
* \f[\int P_{\rm over}(z) {\rm d}z =2C\ln\left(\frac{z}{1-z}\right),\f]
* and its inverse is
* \f[\frac{\exp\left(\frac{r}{2C}\right)}{(1+\exp\left(\frac{r}{2C}\right)}\f]
*
*
* @see \ref OneOneOneSplitFnInterfaces "The interfaces"
* defined for OneOneOneSplitFn.
*/
class OneOneOneSplitFn: public SplittingFunction {
public:
/**
* The default constructor.
*/
inline OneOneOneSplitFn() : SplittingFunction(1) {}
/**
* Concrete implementation of the method to determine whether this splitting
* function can be used for a given set of particles.
* @param ids The PDG codes for the particles in the splitting.
*/
virtual bool accept(const IdList & ids) const;
/**
* Methods to return the splitting function.
*/
//@{
/**
* The concrete implementation of the splitting function, \f$P(z,t)\f$.
* @param z The energy fraction.
* @param t The scale.
* @param ids The PDG codes for the particles in the splitting.
* @param mass Whether or not to include the mass dependent terms
*/
virtual double P(const double z, const Energy2 t, const IdList & ids,
const bool mass) const;
/**
* The concrete implementation of the overestimate of the splitting function,
* \f$P_{\rm over}\f$.
* @param z The energy fraction.
* @param ids The PDG codes for the particles in the splitting.
*/
virtual double overestimateP(const double z, const IdList & ids) const;
/**
* The concrete implementation of the
* the ratio of the splitting function to the overestimate, i.e.
* \f$P(z,t)/P_{\rm over}(z)\f$.
* @param z The energy fraction.
* @param t The scale.
* @param ids The PDG codes for the particles in the splitting.
* @param mass Whether or not to include the mass dependent terms
*/
virtual double ratioP(const double z, const Energy2 t, const IdList & ids,
const bool mass) const;
/**
* The concrete implementation of the indefinite integral of the
* overestimated splitting function, \f$P_{\rm over}\f$.
* @param z The energy fraction.
* @param ids The PDG codes for the particles in the splitting.
* @param PDFfactor Which additional factor to include for the PDF
* 0 is no additional factor,
* 1 is \f$1/z\f$, 2 is \f$1/(1-z)\f$ and 3 is \f$1/z/(1-z)\f$
*/
virtual double integOverP(const double z, const IdList & ids,
unsigned int PDFfactor=0) const;
/**
* The concrete implementation of the inverse of the indefinite integral.
* @param r Value of the splitting function to be inverted
* @param ids The PDG codes for the particles in the splitting.
* @param PDFfactor Which additional factor to include for the PDF
* 0 is no additional factor,
* 1 is \f$1/z\f$, 2 is \f$1/(1-z)\f$ and 3 is \f$1/z/(1-z)\f$
*/
virtual double invIntegOverP(const double r, const IdList & ids,
unsigned int PDFfactor=0) const;
//@}
public:
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
inline virtual IBPtr clone() const {return new_ptr(*this);}
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
inline virtual IBPtr fullclone() const {return new_ptr(*this);}
//@}
private:
/**
- * The static object used to initialize the description of this class.
- * Indicates that this is an concrete class without persistent data.
- */
- static NoPIOClassDescription<OneOneOneSplitFn> initOneOneOneSplitFn;
-
- /**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
OneOneOneSplitFn & operator=(const OneOneOneSplitFn &);
};
}
-#include "ThePEG/Utilities/ClassTraits.h"
-
-namespace ThePEG {
-
-/** @cond TRAITSPECIALIZATIONS */
-
-/** This template specialization informs ThePEG about the
- * base classes of OneOneOneSplitFn. */
-template <>
-struct BaseClassTrait<Herwig::OneOneOneSplitFn,1> {
- /** Typedef of the first base class of OneOneOneSplitFn. */
- typedef Herwig::SplittingFunction NthBase;
-};
-
-/** This template specialization informs ThePEG about the name of
- * the OneOneOneSplitFn class and the shared object where it is defined. */
-template <>
-struct ClassTraits<Herwig::OneOneOneSplitFn>
- : public ClassTraitsBase<Herwig::OneOneOneSplitFn> {
- /** Return a platform-independent class name */
- static string className() { return "Herwig::OneOneOneSplitFn"; }
- /**
- * The name of a file containing the dynamic library where the class
- * OneOneOneSplitFn is implemented. It may also include several, space-separated,
- * libraries if the class OneOneOneSplitFn depends on other classes (base classes
- * excepted). In this case the listed libraries will be dynamically
- * linked in the order they are specified.
- */
- static string library() { return "HwShower.so"; }
-};
-
-/** @endcond */
-
-}
-
#endif /* HERWIG_OneOneOneSplitFn_H */
diff --git a/Shower/SplittingFunctions/SplittingFunction.cc b/Shower/SplittingFunctions/SplittingFunction.cc
--- a/Shower/SplittingFunctions/SplittingFunction.cc
+++ b/Shower/SplittingFunctions/SplittingFunction.cc
@@ -1,610 +1,611 @@
// -*- C++ -*-
//
// SplittingFunction.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 SplittingFunction class.
//
#include "SplittingFunction.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Utilities/EnumIO.h"
#include "Herwig++/Shower/Base/ShowerParticle.h"
+#include "ThePEG/Utilities/DescribeClass.h"
using namespace Herwig;
-AbstractClassDescription<SplittingFunction> SplittingFunction::initSplittingFunction;
-// Definition of the static class description member.
+DescribeAbstractClass<SplittingFunction,Interfaced>
+describeSplittingFunction ("Herwig::SplittingFunction","");
void SplittingFunction::Init() {
static ClassDocumentation<SplittingFunction> documentation
("The SplittingFunction class is the based class for 1->2 splitting functions"
" in Herwig++");
static Switch<SplittingFunction,ColourStructure> interfaceColourStructure
("ColourStructure",
"The colour structure for the splitting function",
&SplittingFunction::_colourStructure, Undefined, false, false);
static SwitchOption interfaceColourStructureTripletTripletOctet
(interfaceColourStructure,
"TripletTripletOctet",
"3 -> 3 8",
TripletTripletOctet);
static SwitchOption interfaceColourStructureOctetOctetOctet
(interfaceColourStructure,
"OctetOctetOctet",
"8 -> 8 8",
OctetOctetOctet);
static SwitchOption interfaceColourStructureOctetTripletTriplet
(interfaceColourStructure,
"OctetTripletTriplet",
"8 -> 3 3bar",
OctetTripletTriplet);
static SwitchOption interfaceColourStructureTripletOctetTriplet
(interfaceColourStructure,
"TripletOctetTriplet",
"3 -> 8 3",
TripletOctetTriplet);
static SwitchOption interfaceColourStructureSextetSextetOctet
(interfaceColourStructure,
"SextetSextetOctet",
"6 -> 6 8",
SextetSextetOctet);
static Switch<SplittingFunction,ShowerInteraction::Type>
interfaceInteractionType
("InteractionType",
"Type of the interaction",
&SplittingFunction::_interactionType,
ShowerInteraction::UNDEFINED, false, false);
static SwitchOption interfaceInteractionTypeQCD
(interfaceInteractionType,
"QCD","QCD",ShowerInteraction::QCD);
static Switch<SplittingFunction,int> interfaceSplittingColourMethod
("SplittingColourMethod",
"Choice of assigning colour in 8->88 splittings.",
&SplittingFunction::_splittingColourMethod, 0, false, false);
static SwitchOption interfaceSplittingColourMethodRandom
(interfaceSplittingColourMethod,
"Random",
"Choose colour assignments randomly.",
0);
static SwitchOption interfaceSplittingColourMethodCorrectLines
(interfaceSplittingColourMethod,
"CorrectLines",
"Choose correct lines for colour.",
1);
static SwitchOption interfaceSplittingColourMethodRandomRecord
(interfaceSplittingColourMethod,
"RandomRecord",
"Choose colour assignments randomly and record the result.",
2);
}
void SplittingFunction::persistentOutput(PersistentOStream & os) const {
using namespace ShowerInteraction;
os << oenum(_interactionType) << _interactionorder
<< oenum(_colourStructure) << _colourFactor
<< _splittingColourMethod;
}
void SplittingFunction::persistentInput(PersistentIStream & is, int) {
using namespace ShowerInteraction;
is >> ienum(_interactionType) >> _interactionorder
>> ienum(_colourStructure) >> _colourFactor
>> _splittingColourMethod;
}
void SplittingFunction::colourConnection(tShowerParticlePtr parent,
tShowerParticlePtr first,
tShowerParticlePtr second,
const bool back) const {
if(_colourStructure==TripletTripletOctet) {
if(!back) {
ColinePair cparent = ColinePair(parent->colourLine(),
parent->antiColourLine());
// ensure input consistency
assert((!cparent.first && cparent.second) ||
( cparent.first && !cparent.second));
// q -> q g
if(cparent.first) {
ColinePtr newline=new_ptr(ColourLine());
cparent.first->addColoured(second);
newline->addColoured ( first);
newline->addAntiColoured (second);
}
// qbar -> qbar g
else {
ColinePtr newline=new_ptr(ColourLine());
cparent.second->addAntiColoured(second);
newline->addColoured(second);
newline->addAntiColoured(first);
}
// Set progenitor
first->setProgenitor(parent->progenitor());
second->setProgenitor(parent->progenitor());
// Random radiation choice
first->setRadiationLine(0);
second->setRadiationLine(0);
}
else {
ColinePair cfirst = ColinePair(first->colourLine(),
first->antiColourLine());
// ensure input consistency
assert(( cfirst.first && !cfirst.second) ||
(!cfirst.first && cfirst.second));
// q -> q g
if(cfirst.first) {
ColinePtr newline=new_ptr(ColourLine());
cfirst.first->addAntiColoured(second);
newline->addColoured(second);
newline->addColoured(parent);
}
// qbar -> qbar g
else {
ColinePtr newline=new_ptr(ColourLine());
cfirst.second->addColoured(second);
newline->addAntiColoured(second);
newline->addAntiColoured(parent);
}
// Set progenitor
parent->setProgenitor(first->progenitor());
second->setProgenitor(first->progenitor());
// Random radiation choice
parent->setRadiationLine(0);
second->setRadiationLine(0);
}
}
else if(_colourStructure==OctetOctetOctet) {
if(!back) {
ColinePair cparent = ColinePair(parent->colourLine(),
parent->antiColourLine());
// ensure input consistency
assert(cparent.first&&cparent.second);
// The choice of colour line is determined by the
// radiation line of the parent.
// If the radiation line is non-zero and the
// scale of the parent is above the second scale of the
// progenitor it will only radiate from the chosen radiation
// line. Otherwise the parent will radiate randomly.
// Initializing radiation lines
first->setRadiationLine(0);
second->setRadiationLine(0);
// Switch to choose random or non-random choice of lines
bool randomchoice = 0;
// Radiation line
int radiationLine = 0;
if (_splittingColourMethod == 1){
// Choose the appropriate colour lines
if ((parent->radiationLine() == 1 || parent->radiationLine() == 2) && parent->progenitor() ) {
if (parent->evolutionScale() > parent->progenitor()->evolutionScale2()){
// Parent has a radiation line, so the line which should
// radiate, and therefore the choice of which colour line
// to pass onto which child, is already determined.
randomchoice = 1;
if(parent->radiationLine() == 2) {
// The anti-colour line is radiating
ColinePtr newline=new_ptr(ColourLine());
cparent.first->addColoured(first);
cparent.second->addAntiColoured(second);
newline->addColoured(second);
newline->addAntiColoured(first);
// Set the radiation line for the children
radiationLine = parent->radiationLine();
}
else {
// The colour line is radiating
ColinePtr newline=new_ptr(ColourLine());
cparent.first->addColoured(second);
cparent.second->addAntiColoured(first);
newline->addColoured(first);
newline->addAntiColoured(second);
// Set the radiation line for the children
radiationLine = parent->radiationLine();
}
}
}
}
if (randomchoice == 0) {
// Randomly decide which of the two gluon products take the
// colour line passing for the colour of the parent gluon
// (the other will take the one passing for the anticolour of
// the parent gluon).
if(UseRandom::rndbool()) {
ColinePtr newline=new_ptr(ColourLine());
cparent.first->addColoured(first);
cparent.second->addAntiColoured(second);
newline->addColoured(second);
newline->addAntiColoured(first);
if (_splittingColourMethod == 1 || _splittingColourMethod == 2){
if (parent->radiationLine() == 1 || parent->radiationLine() == 2){
// Record which line radiates
radiationLine = 2;
}
}
}
else {
ColinePtr newline=new_ptr(ColourLine());
cparent.first->addColoured(second);
cparent.second->addAntiColoured(first);
newline->addColoured(first);
newline->addAntiColoured(second);
if (_splittingColourMethod == 1 || _splittingColourMethod == 2){
if (parent->radiationLine() == 1 || parent->radiationLine() == 2){
// Record which line radiates
radiationLine = 1;
}
}
}
}
if (_splittingColourMethod == 1 || _splittingColourMethod == 2){
if (parent->radiationLine() == 1 || parent->radiationLine() == 2){
// Set the radiation line for the children
first->setRadiationLine(radiationLine);
second->setRadiationLine(0);
// Set the progenitors for the children
first->setProgenitor(parent->progenitor());
second->setProgenitor(parent->progenitor());
}
}
}
else {
ColinePair cfirst = ColinePair(first->colourLine(),
first->antiColourLine());
// ensure input consistency
assert(cfirst.first&&cfirst.second);
// The choice of colour line is determined by the
// radiation line of the parent.
// If the radiation line is non-zero and the
// scale of the parent is above the second scale of the
// progenitor it will only radiate from the chosen radiation
// line. Otherwise the parent will radiate randomly.
// Initializing radiation lines
parent->setRadiationLine(0);
second->setRadiationLine(0);
// Switch to choose random or non-random choice of lines
bool randomchoice = 0;
// Radiation line
int radiationLine = 0;
if (_splittingColourMethod == 1){
// Choose the appropriate colour lines
if ((first->radiationLine() == 1 || first->radiationLine() == 2) && first->progenitor()) {
if (first->evolutionScale() > first->progenitor()->evolutionScale2()){
// Parent has a radiation line, so the line which should
// radiate, and therefore the choice of which colour line
// to pass onto which child, is already determined.
randomchoice = 1;
if (first->radiationLine() == 2) {
// The anti-colour line is radiating
ColinePtr newline=new_ptr(ColourLine());
cfirst.first->addColoured(parent);
cfirst.second->addColoured(second);
newline->addAntiColoured(second);
newline->addAntiColoured(parent);
// Set the radiation line for the children
radiationLine = first->radiationLine();
}
else {
// The colour line is radiating
ColinePtr newline=new_ptr(ColourLine());
cfirst.first->addAntiColoured(second);
cfirst.second->addAntiColoured(parent);
newline->addColoured(parent);
newline->addColoured(second);
// Set the radiation line for the children
radiationLine = first->radiationLine();
}
}
}
}
if (randomchoice == 0) {
// Randomly decide which of the two gluon products take the
// colour line passing for the colour of the parent gluon
// (the other will take the one passing for the anticolour of
// the parent gluon).
if (UseRandom::rndbool()) {
ColinePtr newline=new_ptr(ColourLine());
cfirst.first->addColoured(parent);
cfirst.second->addColoured(second);
newline->addAntiColoured(second);
newline->addAntiColoured(parent);
if (_splittingColourMethod == 1 || _splittingColourMethod == 2){
if (first->radiationLine() == 1 || first->radiationLine() == 2){
// Record which line radiates
radiationLine = 2;
}
}
}
else {
ColinePtr newline=new_ptr(ColourLine());
cfirst.first->addAntiColoured(second);
cfirst.second->addAntiColoured(parent);
newline->addColoured(parent);
newline->addColoured(second);
if (_splittingColourMethod == 1 || _splittingColourMethod == 2){
if (first->radiationLine() == 1 || first->radiationLine() == 2){
// Record which line radiates
radiationLine = 1;
}
}
}
}
if (_splittingColourMethod == 1 || _splittingColourMethod == 2){
if (first->radiationLine() == 1 || first->radiationLine() == 2){
// Set the radiation line for the children
parent->setRadiationLine(radiationLine);
second->setRadiationLine(0);
// Set the progenitors for the children
parent->setProgenitor(first->progenitor());
second->setProgenitor(first->progenitor());
}
}
}
}
else if(_colourStructure == OctetTripletTriplet) {
if(!back) {
ColinePair cparent = ColinePair(parent->colourLine(),
parent->antiColourLine());
// ensure input consistency
assert(cparent.first&&cparent.second);
cparent.first ->addColoured ( first);
cparent.second->addAntiColoured(second);
// Set progenitor
first->setProgenitor(parent->progenitor());
second->setProgenitor(parent->progenitor());
// Random radiation choice
first->setRadiationLine(0);
second->setRadiationLine(0);
}
else {
ColinePair cfirst = ColinePair(first->colourLine(),
first->antiColourLine());
// ensure input consistency
assert(( cfirst.first && !cfirst.second) ||
(!cfirst.first && cfirst.second));
// g -> q qbar
if(cfirst.first) {
ColinePtr newline=new_ptr(ColourLine());
cfirst.first->addColoured(parent);
newline->addAntiColoured(second);
newline->addAntiColoured(parent);
}
// g -> qbar q
else {
ColinePtr newline=new_ptr(ColourLine());
cfirst.second->addAntiColoured(parent);
newline->addColoured(second);
newline->addColoured(parent);
}
// Set progenitor
parent->setProgenitor(first->progenitor());
second->setProgenitor(first->progenitor());
// Random radiation choice
parent->setRadiationLine(0);
second->setRadiationLine(0);
}
}
else if(_colourStructure == TripletOctetTriplet) {
if(!back) {
ColinePair cparent = ColinePair(parent->colourLine(),
parent->antiColourLine());
// ensure input consistency
assert(( cparent.first && !cparent.second) ||
(!cparent.first && cparent.second));
// q -> g q
if(cparent.first) {
ColinePtr newline=new_ptr(ColourLine());
cparent.first->addColoured(first);
newline->addColoured (second);
newline->addAntiColoured( first);
}
// qbar -> g qbar
else {
ColinePtr newline=new_ptr(ColourLine());
cparent.second->addAntiColoured(first);
newline->addColoured ( first);
newline->addAntiColoured(second);
}
// Set progenitor
first->setProgenitor(parent->progenitor());
second->setProgenitor(parent->progenitor());
// Random radiation choice
first->setRadiationLine(0);
second->setRadiationLine(0);
}
else {
ColinePair cfirst = ColinePair(first->colourLine(),
first->antiColourLine());
// ensure input consistency
assert(cfirst.first&&cfirst.second);
// q -> g q
if(parent->id()>0) {
cfirst.first ->addColoured(parent);
cfirst.second->addColoured(second);
}
else {
cfirst.first ->addAntiColoured(second);
cfirst.second->addAntiColoured(parent);
}
// Set progenitor
parent->setProgenitor(first->progenitor());
second->setProgenitor(first->progenitor());
// Random radiation choice
parent->setRadiationLine(0);
second->setRadiationLine(0);
}
}
else if(_colourStructure==SextetSextetOctet) {
//make sure we're not doing backward evolution
assert(!back);
//make sure something sensible
assert(parent->colourLine() || parent->antiColourLine());
//get the colour lines or anti-colour lines
bool isAntiColour=true;
ColinePair cparent;
if(parent->colourLine()) {
cparent = ColinePair(const_ptr_cast<tColinePtr>(parent->colourInfo()->colourLines()[0]),
const_ptr_cast<tColinePtr>(parent->colourInfo()->colourLines()[1]));
isAntiColour=false;
}
else {
cparent = ColinePair(const_ptr_cast<tColinePtr>(parent->colourInfo()->antiColourLines()[0]),
const_ptr_cast<tColinePtr>(parent->colourInfo()->antiColourLines()[1]));
}
//check for sensible input
// assert(cparent.first && cparent.second);
// sextet has 2 colour lines
if(!isAntiColour) {
//pick at random which of the colour topolgies to take
double topology = UseRandom::rnd();
if(topology < 0.25) {
ColinePtr newline=new_ptr(ColourLine());
cparent.first->addColoured(second);
cparent.second->addColoured(first);
newline->addColoured(first);
newline->addAntiColoured(second);
}
else if(topology >=0.25 && topology < 0.5) {
ColinePtr newline=new_ptr(ColourLine());
cparent.first->addColoured(first);
cparent.second->addColoured(second);
newline->addColoured(first);
newline->addAntiColoured(second);
}
else if(topology >= 0.5 && topology < 0.75) {
ColinePtr newline=new_ptr(ColourLine());
cparent.first->addColoured(second);
cparent.second->addColoured(first);
newline->addColoured(first);
newline->addAntiColoured(second);
}
else {
ColinePtr newline=new_ptr(ColourLine());
cparent.first->addColoured(first);
cparent.second->addColoured(second);
newline->addColoured(first);
newline->addAntiColoured(second);
}
}
// sextet has 2 anti-colour lines
else {
double topology = UseRandom::rnd();
if(topology < 0.25){
ColinePtr newline=new_ptr(ColourLine());
cparent.first->addAntiColoured(second);
cparent.second->addAntiColoured(first);
newline->addAntiColoured(first);
newline->addColoured(second);
}
else if(topology >=0.25 && topology < 0.5) {
ColinePtr newline=new_ptr(ColourLine());
cparent.first->addAntiColoured(first);
cparent.second->addAntiColoured(second);
newline->addAntiColoured(first);
newline->addColoured(second);
}
else if(topology >= 0.5 && topology < 0.75) {
ColinePtr newline=new_ptr(ColourLine());
cparent.first->addAntiColoured(second);
cparent.second->addAntiColoured(first);
newline->addAntiColoured(first);
newline->addColoured(second);
}
else {
ColinePtr newline=new_ptr(ColourLine());
cparent.first->addAntiColoured(first);
cparent.second->addAntiColoured(second);
newline->addAntiColoured(first);
newline->addColoured(second);
}
}
}
else {
assert(false);
}
}
void SplittingFunction::doinit() {
Interfaced::doinit();
assert(_interactionType!=ShowerInteraction::UNDEFINED);
if(_colourFactor>0.) return;
// compute the colour factors if need
if(_colourStructure==TripletTripletOctet) {
_colourFactor = 4./3.;
}
else if(_colourStructure==OctetOctetOctet) {
_colourFactor = 3.;
}
else if(_colourStructure==OctetTripletTriplet) {
_colourFactor = 0.5;
}
else if(_colourStructure==TripletOctetTriplet) {
_colourFactor = 4./3.;
}
else if(_colourStructure==SextetSextetOctet) {
_colourFactor = 10./3.;
}
else {
assert(false);
}
}
bool SplittingFunction::checkColours(const IdList & ids) const {
tcPDPtr pd[3]={getParticleData(ids[0]),
getParticleData(ids[1]),
getParticleData(ids[2])};
if(_colourStructure==TripletTripletOctet) {
if(ids[0]!=ids[1]) return false;
if((pd[0]->iColour()==PDT::Colour3||pd[0]->iColour()==PDT::Colour3bar) &&
pd[2]->iColour()==PDT::Colour8) return true;
return false;
}
else if(_colourStructure==OctetOctetOctet) {
for(unsigned int ix=0;ix<3;++ix) {
if(pd[ix]->iColour()!=PDT::Colour8) return false;
}
return true;
}
else if(_colourStructure==OctetTripletTriplet) {
if(pd[0]->iColour()!=PDT::Colour8) return false;
if(pd[1]->iColour()==PDT::Colour3&&pd[2]->iColour()==PDT::Colour3bar)
return true;
if(pd[1]->iColour()==PDT::Colour3bar&&pd[2]->iColour()==PDT::Colour3)
return true;
return false;
}
else if(_colourStructure==TripletOctetTriplet) {
if(ids[0]!=ids[2]) return false;
if((pd[0]->iColour()==PDT::Colour3||pd[0]->iColour()==PDT::Colour3bar) &&
pd[1]->iColour()==PDT::Colour8) return true;
return false;
}
else if(_colourStructure==SextetSextetOctet) {
if(ids[0]!=ids[1]) return false;
if((pd[0]->iColour()==PDT::Colour6 || pd[0]->iColour()==PDT::Colour6bar) &&
pd[2]->iColour()==PDT::Colour8) return true;
return false;
}
else {
assert(false);
}
return false;
}
diff --git a/Shower/SplittingFunctions/SplittingFunction.h b/Shower/SplittingFunctions/SplittingFunction.h
--- a/Shower/SplittingFunctions/SplittingFunction.h
+++ b/Shower/SplittingFunctions/SplittingFunction.h
@@ -1,314 +1,281 @@
// -*- C++ -*-
//
// SplittingFunction.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_SplittingFunction_H
#define HERWIG_SplittingFunction_H
//
// This is the declaration of the SplittingFunction class.
//
#include "ThePEG/Interface/Interfaced.h"
#include "Herwig++/Shower/ShowerConfig.h"
#include "ThePEG/EventRecord/ColourLine.h"
#include "SplittingFunction.fh"
namespace Herwig {
using namespace ThePEG;
/** \ingroup Shower
* Enum to define the possible types of colour structure which can occur in
* the branching.
*/
enum ColourStructure {Undefined=-1,TripletTripletOctet=0,OctetOctetOctet=1,
OctetTripletTriplet=2,TripletOctetTriplet=3,SextetSextetOctet=4};
/** \ingroup Shower
*
* This is an abstract class which defines the common interface
* for all \f$1\to2\f$ splitting functions, for both initial-state
* and final-state radiation.
*
* The SplittingFunction class contains a number of purely virtual members
* which must be implemented in the inheriting classes. The class also stores
* the interaction type of the spltting function.
*
* The inheriting classes need to specific the splitting function
* \f$P(z,2p_j\cdot p_k)\f$, in terms of the energy fraction \f$z\f$ and
* the evolution scale. In order to allow the splitting functions to be used
* with different choices of evolution functions the scale is given by
* \f[2p_j\cdot p_k=(p_j+p_k)^2-m_{jk}^2=Q^2-(p_j+p_k)^2=z(1-z)\tilde{q}^2=
* \frac{p_T^2}{z(1-z)}-m_{jk}^2+\frac{m_j^2}{z}+\frac{m_k^2}{1-z},\f]
* where \f$Q^2\f$ is the virtuality of the branching particle,
* $p_T$ is the relative transverse momentum of the branching products and
* \f$\tilde{q}^2\f$ is the angular variable described in hep-ph/0310083.
*
* In addition an overestimate of the
* splitting function, \f$P_{\rm over}(z)\f$ which only depends upon \f$z\f$,
* the integral, inverse of the integral for this overestimate and
* ratio of the true splitting function to the overestimate must be provided
* as they are necessary for the veto alogrithm used to implement the evolution.
*
* @see \ref SplittingFunctionInterfaces "The interfaces"
* defined for SplittingFunction.
*/
class SplittingFunction: public Interfaced {
public:
/**
* The default constructor.
* @param b All splitting functions must have an interaction order
*/
SplittingFunction(unsigned int b)
: Interfaced(), _interactionType(ShowerInteraction::UNDEFINED),
_interactionorder(b),
_colourStructure(Undefined), _colourFactor(-1.),
_splittingColourMethod(0) {}
public:
/**
* Methods to return the interaction type and order for the splitting function
*/
//@{
/**
* Return the type of the interaction
*/
ShowerInteraction::Type interactionType() const {return _interactionType;}
/**
* Return the order of the splitting function in the interaction
*/
unsigned int interactionOrder() const {return _interactionorder;}
/**
* Return the colour structure
*/
ColourStructure colourStructure() const {return _colourStructure;}
/**
* Return the colour factor
*/
double colourFactor() const {return _colourFactor;}
//@}
/**
* Purely virtual method which should determine whether this splitting
* function can be used for a given set of particles.
* @param ids The PDG codes for the particles in the splitting.
*/
virtual bool accept(const IdList & ids) const = 0;
/**
* Method to check the colours are correct
*/
virtual bool checkColours(const IdList & ids) const;
/**
* Methods to return the splitting function.
*/
//@{
/**
* Purely virtual method which should return the exact value of the splitting function,
* \f$P\f$ evaluated in terms of the energy fraction, \f$z\f$, and the evolution scale
\f$\tilde{q}^2\f$.
* @param z The energy fraction.
* @param t The scale \f$t=2p_j\cdot p_k\f$.
* @param ids The PDG codes for the particles in the splitting.
* @param mass Whether or not to include the mass dependent terms
*/
virtual double P(const double z, const Energy2 t, const IdList & ids,
const bool mass) const = 0;
/**
* Purely virtual method which should return
* an overestimate of the splitting function,
* \f$P_{\rm over}\f$ such that the result \f$P_{\rm over}\geq P\f$. This function
* should be simple enough that it does not depend on the evolution scale.
* @param z The energy fraction.
* @param ids The PDG codes for the particles in the splitting.
*/
virtual double overestimateP(const double z, const IdList & ids) const = 0;
/**
* Purely virtual method which should return
* the ratio of the splitting function to the overestimate, i.e.
* \f$P(z,\tilde{q}^2)/P_{\rm over}(z)\f$.
* @param z The energy fraction.
* @param t The scale \f$t=2p_j\cdot p_k\f$.
* @param ids The PDG codes for the particles in the splitting.
* @param mass Whether or not to include the mass dependent terms
*/
virtual double ratioP(const double z, const Energy2 t, const IdList & ids,
const bool mass) const = 0;
/**
* Purely virtual method which should return the indefinite integral of the
* overestimated splitting function, \f$P_{\rm over}\f$.
* @param z The energy fraction.
* @param ids The PDG codes for the particles in the splitting.
* @param PDFfactor Which additional factor to include for the PDF
* 0 is no additional factor,
* 1 is \f$1/z\f$, 2 is \f$1/(1-z)\f$ and 3 is \f$1/z/(1-z)\f$
*
*/
virtual double integOverP(const double z, const IdList & ids,
unsigned int PDFfactor=0) const = 0;
/**
* Purely virtual method which should return the inverse of the
* indefinite integral of the
* overestimated splitting function, \f$P_{\rm over}\f$ which is used to
* generate the value of \f$z\f$.
* @param r Value of the splitting function to be inverted
* @param ids The PDG codes for the particles in the splitting.
* @param PDFfactor Which additional factor to include for the PDF
* 0 is no additional factor,
* 1 is \f$1/z\f$, 2 is \f$1/(1-z)\f$ and 3 is \f$1/z/(1-z)\f$
*/
virtual double invIntegOverP(const double r, const IdList & ids,
unsigned int PDFfactor=0) const = 0;
//@}
/**
* Purely virtual method which should make the proper colour connection
* between the emitting parent and the branching products.
* @param parent The parent for the branching
* @param first The first branching product
* @param second The second branching product
* @param back Whether this is foward or backward evolution.
*/
virtual void colourConnection(tShowerParticlePtr parent,
tShowerParticlePtr first,
tShowerParticlePtr second,
const bool back) const;
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit();
//@}
protected:
/**
* Set the colour factor
*/
void colourFactor(double in) {_colourFactor=in;}
private:
/**
- * The static object used to initialize the description of this class.
- * Indicates that this is an abstract class without persistent data.
- */
- static AbstractClassDescription<SplittingFunction> initSplittingFunction;
-
- /**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
SplittingFunction & operator=(const SplittingFunction &);
private:
/**
* The interaction type for the splitting function.
*/
ShowerInteraction::Type _interactionType;
/**
* The order of the splitting function in the coupling
*/
unsigned int _interactionorder;
/**
* The colour structure
*/
ColourStructure _colourStructure;
/**
* The colour factor
*/
double _colourFactor;
/**
* The method for assigning colour
* The default, 0, will assign colour lines for octets
* randomly without keeping a record of which lines radiate.
* For option 1 only the "correct" lines will radiate until
* the lowest scale is reached.
* For option 2 there will be random radiation, but the
* line which radiates is recorded
*/
int _splittingColourMethod;
};
}
-#include "ThePEG/Utilities/ClassTraits.h"
-
-namespace ThePEG {
-
-/** @cond TRAITSPECIALIZATIONS */
-
-/** This template specialization informs ThePEG about the
- * base classes of SplittingFunction. */
-template <>
-struct BaseClassTrait<Herwig::SplittingFunction,1> {
- /** Typedef of the first base class of SplittingFunction. */
- typedef Interfaced NthBase;
-};
-
-/** This template specialization informs ThePEG about the name of
- * the SplittingFunction class and the shared object where it is defined. */
-template <>
-struct ClassTraits<Herwig::SplittingFunction>
- : public ClassTraitsBase<Herwig::SplittingFunction> {
- /** Return a platform-independent class name */
- static string className() { return "Herwig::SplittingFunction"; }
-};
-
-/** @endcond */
-
-}
-
#endif /* HERWIG_SplittingFunction_H */
diff --git a/Shower/SplittingFunctions/SplittingGenerator.cc b/Shower/SplittingFunctions/SplittingGenerator.cc
--- a/Shower/SplittingFunctions/SplittingGenerator.cc
+++ b/Shower/SplittingFunctions/SplittingGenerator.cc
@@ -1,341 +1,342 @@
// -*- C++ -*-
//
// SplittingGenerator.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 SplittingGenerator class.
//
#include "SplittingGenerator.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/Command.h"
#include "ThePEG/Utilities/StringUtils.h"
#include "ThePEG/Repository/Repository.h"
#include "Herwig++/Shower/Base/ShowerParticle.h"
#include "Herwig++/Shower/ShowerHandler.h"
#include "ThePEG/Utilities/Rebinder.h"
#include <cassert>
+#include "ThePEG/Utilities/DescribeClass.h"
using namespace Herwig;
+DescribeClass<SplittingGenerator,Interfaced>
+describeSplittingGenerator ("Herwig::SplittingGenerator","");
+
IBPtr SplittingGenerator::clone() const {
return new_ptr(*this);
}
IBPtr SplittingGenerator::fullclone() const {
return new_ptr(*this);
}
void SplittingGenerator::persistentOutput(PersistentOStream & os) const {
os << _isr_Mode << _fsr_Mode << _bbranchings << _fbranchings;
}
void SplittingGenerator::persistentInput(PersistentIStream & is, int) {
is >> _isr_Mode >> _fsr_Mode >> _bbranchings >> _fbranchings;
}
-ClassDescription<SplittingGenerator> SplittingGenerator::initSplittingGenerator;
-// Definition of the static class description member.
-
void SplittingGenerator::Init() {
static ClassDocumentation<SplittingGenerator> documentation
("There class is responsible for initializing the Sudakov form factors ",
"and generating splittings.");
static Switch<SplittingGenerator, bool> interfaceISRMode
("ISR",
"Include initial-state radiation?",
&SplittingGenerator::_isr_Mode, 1, false, false);
static SwitchOption interfaceISRMode0
(interfaceISRMode,"No","ISR (Initial State Radiation) is OFF", 0);
static SwitchOption interfaceISRMode1
(interfaceISRMode,"Yes","ISR (Initial State Radiation) is ON", 1);
static Switch<SplittingGenerator, bool> interfaceFSRMode
("FSR",
"Include final-state radiation?",
&SplittingGenerator::_fsr_Mode, 1, false, false);
static SwitchOption interfaceFSRMode0
(interfaceFSRMode,"No","FSR (Final State Radiation) is OFF", 0);
static SwitchOption interfaceFSRMode1
(interfaceFSRMode,"Yes","FSR (Final State Radiation) is ON", 1);
static Command<SplittingGenerator> interfaceAddSplitting
("AddFinalSplitting",
"Adds another splitting to the list of splittings considered "
"in the shower. Command is a->b,c; Sudakov",
&SplittingGenerator::addFinalSplitting);
static Command<SplittingGenerator> interfaceAddInitialSplitting
("AddInitialSplitting",
"Adds another splitting to the list of initial splittings to consider "
"in the shower. Command is a->b,c; Sudakov. Here the particle a is the "
"particle that is PRODUCED by the splitting. b is the initial state "
"particle that is splitting in the shower.",
&SplittingGenerator::addInitialSplitting);
static Command<SplittingGenerator> interfaceDeleteSplitting
("DeleteFinalSplitting",
"Deletes a splitting from the list of splittings considered "
"in the shower. Command is a->b,c; Sudakov",
&SplittingGenerator::deleteFinalSplitting);
static Command<SplittingGenerator> interfaceDeleteInitialSplitting
("DeleteInitialSplitting",
"Deletes a splitting from the list of initial splittings to consider "
"in the shower. Command is a->b,c; Sudakov. Here the particle a is the "
"particle that is PRODUCED by the splitting. b is the initial state "
"particle that is splitting in the shower.",
&SplittingGenerator::deleteInitialSplitting);
}
string SplittingGenerator::addSplitting(string arg, bool final) {
string partons = StringUtils::car(arg);
string sudakov = StringUtils::cdr(arg);
vector<tPDPtr> products;
string::size_type next = partons.find("->");
if(next == string::npos)
return "Error: Invalid string for splitting " + arg;
if(partons.find(';') == string::npos)
return "Error: Invalid string for splitting " + arg;
tPDPtr parent = Repository::findParticle(partons.substr(0,next));
partons = partons.substr(next+2);
do {
next = min(partons.find(','), partons.find(';'));
tPDPtr pdp = Repository::findParticle(partons.substr(0,next));
partons = partons.substr(next+1);
if(pdp) products.push_back(pdp);
else return "Error: Could not create splitting from " + arg;
} while(partons[0] != ';' && partons.size());
SudakovPtr s;
s = dynamic_ptr_cast<SudakovPtr>(Repository::TraceObject(sudakov));
if(!s) return "Error: Could not load Sudakov " + sudakov + '\n';
IdList ids;
ids.push_back(parent->id());
for(vector<tPDPtr>::iterator it = products.begin(); it!=products.end(); ++it)
ids.push_back((*it)->id());
// check splitting can handle this
if(!s->splittingFn()->accept(ids))
return "Error: Sudakov " + sudakov + "can't handle particles\n";
// add to map
addToMap(ids,s,final);
return "";
}
string SplittingGenerator::deleteSplitting(string arg, bool final) {
string partons = StringUtils::car(arg);
string sudakov = StringUtils::cdr(arg);
vector<tPDPtr> products;
string::size_type next = partons.find("->");
if(next == string::npos)
return "Error: Invalid string for splitting " + arg;
if(partons.find(';') == string::npos)
return "Error: Invalid string for splitting " + arg;
tPDPtr parent = Repository::findParticle(partons.substr(0,next));
partons = partons.substr(next+2);
do {
next = min(partons.find(','), partons.find(';'));
tPDPtr pdp = Repository::findParticle(partons.substr(0,next));
partons = partons.substr(next+1);
if(pdp) products.push_back(pdp);
else return "Error: Could not create splitting from " + arg;
} while(partons[0] != ';' && partons.size());
SudakovPtr s;
s = dynamic_ptr_cast<SudakovPtr>(Repository::TraceObject(sudakov));
if(!s) return "Error: Could not load Sudakov " + sudakov + '\n';
IdList ids;
ids.push_back(parent->id());
for(vector<tPDPtr>::iterator it = products.begin(); it!=products.end(); ++it)
ids.push_back((*it)->id());
// check splitting can handle this
if(!s->splittingFn()->accept(ids))
return "Error: Sudakov " + sudakov + "can't handle particles\n";
// delete from map
deleteFromMap(ids,s,final);
return "";
}
void SplittingGenerator::addToMap(const IdList &ids, const SudakovPtr &s, bool final) {
if(isISRadiationON() && !final) {
_bbranchings.insert(BranchingInsert(ids[1],BranchingElement(s,ids)));
s->addSplitting(ids);
}
if(isFSRadiationON() && final) {
_fbranchings.insert(BranchingInsert(ids[0],BranchingElement(s,ids)));
s->addSplitting(ids);
}
}
void SplittingGenerator::deleteFromMap(const IdList &ids,
const SudakovPtr &s, bool final) {
if(isISRadiationON() && !final) {
pair<BranchingList::iterator,BranchingList::iterator>
range = _bbranchings.equal_range(ids[1]);
for(BranchingList::iterator it=range.first;it!=range.second&&it->first==ids[1];++it) {
if(it->second.first==s&&it->second.second==ids)
_bbranchings.erase(it);
}
s->removeSplitting(ids);
}
if(isFSRadiationON() && final) {
pair<BranchingList::iterator,BranchingList::iterator>
range = _fbranchings.equal_range(ids[0]);
for(BranchingList::iterator it=range.first;it!=range.second&&it->first==ids[0];++it) {
if(it->second.first==s&&it->second.second==ids)
_fbranchings.erase(it);
}
s->removeSplitting(ids);
}
}
Branching SplittingGenerator::chooseForwardBranching(ShowerParticle &particle,
double enhance,
ShowerInteraction::Type type) const {
Energy newQ = ZERO;
ShoKinPtr kinematics = ShoKinPtr();
SudakovPtr sudakov=SudakovPtr();
IdList ids;
// First, find the eventual branching, corresponding to the highest scale.
long index = abs(particle.data().id());
// if no branchings return empty branching struct
if(_fbranchings.find(index) == _fbranchings.end())
return Branching(ShoKinPtr(), IdList(),SudakovPtr());
// otherwise select branching
for(BranchingList::const_iterator cit = _fbranchings.lower_bound(index);
cit != _fbranchings.upper_bound(index); ++cit) {
if(type!=cit->second.first->interactionType()) continue;
// check size of scales beforehand...
ShoKinPtr newKin= cit->second.first->
generateNextTimeBranching(particle.evolutionScale(),
cit->second.second,particle.id()!=cit->first,
enhance);
if(!newKin) continue;
// select highest scale
if(newKin->scale() > newQ &&
newKin->scale() <= particle.evolutionScale()) {
kinematics=newKin;
newQ = newKin->scale();
ids = cit->second.second;
sudakov=cit->second.first;
}
}
// return empty branching if nothing happened
if(!kinematics) return Branching(ShoKinPtr(), IdList(),SudakovPtr());
// If a branching has been selected initialize it
kinematics->initialize(particle,PPtr());
// and return it
return Branching(kinematics, ids,sudakov);
}
Branching SplittingGenerator::
chooseDecayBranching(ShowerParticle &particle, Energy stoppingScale,
Energy minmass, double enhance,
ShowerInteraction::Type type) const {
Energy newQ = Constants::MaxEnergy;
ShoKinPtr kinematics;
SudakovPtr sudakov;
IdList ids;
// First, find the eventual branching, corresponding to the lowest scale.
long index = abs(particle.data().id());
// if no branchings return empty branching struct
if(_fbranchings.find(index) == _fbranchings.end())
return Branching(ShoKinPtr(), IdList(),SudakovPtr());
// otherwise select branching
for(BranchingList::const_iterator cit = _fbranchings.lower_bound(index);
cit != _fbranchings.upper_bound(index); ++cit) {
if(type!=cit->second.first->interactionType()) continue;
ShoKinPtr newKin;
if(particle.evolutionScale() < stoppingScale)
newKin = cit->second.first->
generateNextDecayBranching(particle.evolutionScale(),
stoppingScale,minmass,
cit->second.second,
particle.id()!=cit->first,enhance);
if(!newKin) continue;
if(newKin->scale() < newQ && newKin->scale() > particle.evolutionScale()) {
newQ = newKin->scale();
ids = cit->second.second;
kinematics=newKin;
sudakov=cit->second.first;
}
}
// return empty branching if nothing happened
if(!kinematics) return Branching(ShoKinPtr(), IdList(),SudakovPtr());
// initialize the branching
kinematics->initialize(particle,PPtr());
// and return it
return Branching(kinematics, ids,sudakov);
}
Branching SplittingGenerator::
chooseBackwardBranching(ShowerParticle &particle,PPtr beamparticle,
double enhance,
Ptr<BeamParticleData>::transient_const_pointer beam,
ShowerInteraction::Type type,
tcPDFPtr pdf, Energy freeze) const {
Energy newQ=ZERO;
ShoKinPtr kinematics=ShoKinPtr();
SudakovPtr sudakov;
IdList ids;
// First, find the eventual branching, corresponding to the highest scale.
long index = abs(particle.id());
// if no possible branching return
if(_bbranchings.find(index) == _bbranchings.end())
return Branching(ShoKinPtr(), IdList(),sudakov);
// select the branching
for(BranchingList::const_iterator cit = _bbranchings.lower_bound(index);
cit != _bbranchings.upper_bound(index); ++cit ) {
if(type!=cit->second.first->interactionType()) continue;
cit->second.first->setPDF(pdf,freeze);
ShoKinPtr newKin=cit->second.first->
generateNextSpaceBranching(particle.evolutionScale(),
cit->second.second, particle.x(),
particle.id()!=cit->first,enhance,beam);
if(!newKin) continue;
if(newKin->scale() > newQ) {
newQ = newKin->scale();
kinematics=newKin;
ids = cit->second.second;
sudakov=cit->second.first;
}
}
// return empty branching if nothing happened
if(!kinematics) return Branching(ShoKinPtr(), IdList(),SudakovPtr());
// initialize the ShowerKinematics
// and return it
kinematics->initialize(particle,beamparticle);
// return the answer
return Branching(kinematics, ids,sudakov);
}
void SplittingGenerator::rebind(const TranslationMap & trans)
{
BranchingList::iterator cit;
for(cit=_fbranchings.begin();cit!=_fbranchings.end();++cit)
{(cit->second).first=trans.translate((cit->second).first);}
for(cit=_bbranchings.begin();cit!=_bbranchings.end();++cit)
{(cit->second).first=trans.translate((cit->second).first);}
Interfaced::rebind(trans);
}
IVector SplittingGenerator::getReferences() {
IVector ret = Interfaced::getReferences();
BranchingList::iterator cit;
for(cit=_fbranchings.begin();cit!=_fbranchings.end();++cit)
{ret.push_back((cit->second).first);}
for(cit=_bbranchings.begin();cit!=_bbranchings.end();++cit)
{ret.push_back((cit->second).first);}
return ret;
}
diff --git a/Shower/SplittingFunctions/SplittingGenerator.h b/Shower/SplittingFunctions/SplittingGenerator.h
--- a/Shower/SplittingFunctions/SplittingGenerator.h
+++ b/Shower/SplittingFunctions/SplittingGenerator.h
@@ -1,377 +1,344 @@
// -*- C++ -*-
//
// SplittingGenerator.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_SplittingGenerator_H
#define HERWIG_SplittingGenerator_H
//
// This is the declaration of the SplittingGenerator class.
//
#include "ThePEG/Interface/Interfaced.h"
#include "Herwig++/Shower/Base/Branching.h"
#include "Herwig++/Shower/Base/SudakovFormFactor.h"
#include "SplittingGenerator.fh"
#include "Herwig++/Shower/Base/ShowerKinematics.h"
namespace Herwig {
using namespace ThePEG;
/** \ingroup Shower
*
* This class is responsible for creating, at the beginning of the Run,
* all the SplittingFunction objects and the corresponding
* SudakovFormFactor objects, and then of the generation of splittings
* (radiation emissions) during the event.
* Many switches are defined in this class which allowed the user to turn on/off:
* - each type of interaction (QCD, QED, EWK,...);
* - initial- and final-state radiation for all type of interactions;
* - initial- and final-state radiation for each type of interaction;
* - each type of splitting (\f$u\to ug\f$, \f$d\to dg\f$, \f$\ldots\f$,
* \f$g\to gg\f$, \f$g\to u\bar{u}\f$, \f$\ldots\f$).
*
* These switches are useful mainly for debugging, but eventually can
* also be used for a "quick and dirty" estimation of systematic errors.
*
* In the future it should be possible to implement in this class
*
* - the \f$1\to2\f$ azimuthal correlations for soft emission due to QCD coherence
* using the ShowerParticle object provided in the input.
* - Similarly having the \f$\rho-D\f$ matrix and the SplittingFunction pointer
* it should be possible to implement the spin correlations.
*
* @see SudakovFormFactor
* @see SplitFun
*
* @see \ref SplittingGeneratorInterfaces "The interfaces"
* defined for SplittingGenerator.
*/
class SplittingGenerator: public Interfaced {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
SplittingGenerator() : _isr_Mode(1), _fsr_Mode(1) {}
//@}
public:
/**
* Methods to select the next branching and reconstruct the kinematics
*/
//@{
/**
* Choose a new forward branching for a time-like particle
* The method returns:
* - a pointer to a ShowerKinematics object, which
* contains the information about the new scale and all other
* kinematics variables that need to be generated simultaneously;
* - a pointer to the SudakovFormFactor object associated
* with the chosen emission.
* - The PDG codes of the particles in the branching,
* as a Branching struct.
*
* In the case no branching has been generated, both the returned
* pointers are null ( ShoKinPtr() , tSudakovFFPtr() ).
*
* @param particle The particle to be evolved
* @param enhance The factor by which to ehnace the emission of radiation
* @param type The type of interaction to generate
* @return The Branching struct for the branching
*/
Branching chooseForwardBranching(ShowerParticle & particle,
double enhance,
ShowerInteraction::Type type) const;
/**
* Select the next branching of a particles for the initial-state shower
* in the particle's decay.
* @param particle The particle being showerwed
* @param maxscale The maximum scale
* @param minmass Minimum mass of the particle after the branching
* @param enhance The factor by which to ehnace the emission of radiation
* @param type The type of interaction to generate
* @return The Branching struct for the branching
*/
Branching chooseDecayBranching(ShowerParticle & particle,
Energy maxscale,
Energy minmass,double enhance,
ShowerInteraction::Type type) const;
/**
* Choose a new backward branching for a space-like particle.
* The method returns:
* - a pointer to a ShowerKinematics object, which
* contains the information about the new scale and all other
* kinematics variables that need to be generated simultaneously;
* - a pointer to the SudakovFormFactor object associated
* with the chosen emission.
* - The PDG codes of the particles in the branching,
* as a Branching struct.
*
* In the case no branching has been generated, both the returned
* pointers are null ( ShoKinPtr() , tSudakovFFPtr() ).
*
* @param particle The particle to be evolved
* @param enhance The factor by which to ehnace the emission of radiation
* @param beamparticle The beam particle
* @param beam The BeamParticleData object
* @param type The type of interaction to generate
* @return The Branching struct for the branching
*/
Branching
chooseBackwardBranching(ShowerParticle & particle,
PPtr beamparticle,
double enhance,
Ptr<BeamParticleData>::transient_const_pointer beam,
ShowerInteraction::Type type,
tcPDFPtr , Energy ) const;
//@}
public:
/**
* Access to the switches
*/
//@{
/**
* It returns true/false if the initial-state radiation is on/off.
*/
bool isISRadiationON() const { return _isr_Mode; }
/**
* It returns true/false if the final-state radiation is on/off.
*/
bool isFSRadiationON() const { return _fsr_Mode; }
//@}
/**
* Methods to parse the information from the input files to create the
* branchings
*/
//@{
/**
* Add a final-state splitting
*/
string addFinalSplitting(string arg) { return addSplitting(arg,true); }
/**
* Add an initial-state splitting
*/
string addInitialSplitting(string arg) { return addSplitting(arg,false); }
/**
* Add a final-state splitting
*/
string deleteFinalSplitting(string arg) { return deleteSplitting(arg,true); }
/**
* Add an initial-state splitting
*/
string deleteInitialSplitting(string arg) { return deleteSplitting(arg,false); }
//@}
/**
* Access to the splittings
*/
//@{
/**
* Access the final-state branchings
*/
const BranchingList & finalStateBranchings() const { return _fbranchings; }
/**
* Access the initial-state branchings
*/
const BranchingList & initialStateBranchings() const { return _bbranchings; }
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
virtual IBPtr fullclone() const;
//@}
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Rebind pointer to other Interfaced objects. Called in the setup phase
* after all objects used in an EventGenerator has been cloned so that
* the pointers will refer to the cloned objects afterwards.
* @param trans a TranslationMap relating the original objects to
* their respective clones.
* @throws RebindException if no cloned object was found for a given
* pointer.
*/
virtual void rebind(const TranslationMap & trans)
;
/**
* Return a vector of all pointers to Interfaced objects used in this
* object.
* @return a vector of pointers.
*/
virtual IVector getReferences();
//@}
private:
/**
* Add a branching to the map
* @param ids PDG coeds of the particles in the branching
* @param sudakov The SudakovFormFactor for the branching
* @param final Whether this is an initial- or final-state branching
*/
void addToMap(const IdList & ids, const SudakovPtr & sudakov, bool final);
/**
* Remove a branching to the map
* @param ids PDG coeds of the particles in the branching
* @param sudakov The SudakovFormFactor for the branching
* @param final Whether this is an initial- or final-state branching
*/
void deleteFromMap(const IdList & ids, const SudakovPtr & sudakov, bool final);
/**
* Obtain the reference vectors for a final-state particle
* @param particle The particle
* @param p The p reference vector
* @param n The n reference vector
*/
void finalStateBasisVectors(ShowerParticle particle, Lorentz5Momentum & p,
Lorentz5Momentum & n) const;
/**
* Add a splitting
* @param in string to be parsed
* @param final Whether this is an initial- or final-state branching
*/
string addSplitting(string in ,bool final);
/**
* Delete a splitting
* @param in string to be parsed
* @param final Whether this is an initial- or final-state branching
*/
string deleteSplitting(string in ,bool final);
private:
/**
- * The static object used to initialize the description of this class.
- * Indicates that this is a concrete class with persistent data.
- */
- static ClassDescription<SplittingGenerator> initSplittingGenerator;
-
- /**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
SplittingGenerator & operator=(const SplittingGenerator &);
private:
/**
* Switches to control the radiation
*/
//@{
/**
* Is inqitial-state radiation on/off
*/
bool _isr_Mode;
/**
* Is final-state radiation on/off
*/
bool _fsr_Mode;
//@}
/**
* List of the branchings and the appropriate Sudakovs for forward branchings
*/
BranchingList _fbranchings;
/**
* Lists of the branchings and the appropriate Sudakovs for backward branchings.
*/
BranchingList _bbranchings;
};
}
-#include "ThePEG/Utilities/ClassTraits.h"
-
-namespace ThePEG {
-
-/** @cond TRAITSPECIALIZATIONS */
-
-/** This template specialization informs ThePEG about the
- * base classes of SplittingGenerator. */
-template <>
-struct BaseClassTrait<Herwig::SplittingGenerator,1> {
- /** Typedef of the first base class of SplittingGenerator. */
- typedef Interfaced NthBase;
-};
-
-/** This template specialization informs ThePEG about the name of
- * the SplittingGenerator class and the shared object where it is defined. */
-template <>
-struct ClassTraits<Herwig::SplittingGenerator>
- : public ClassTraitsBase<Herwig::SplittingGenerator> {
- /** Return a platform-independent class name */
- static string className() { return "Herwig::SplittingGenerator"; }
-};
-
-/** @endcond */
-
-}
-
#endif /* HERWIG_SplittingGenerator_H */
diff --git a/Shower/SplittingFunctions/ZeroZeroOneSplitFn.cc b/Shower/SplittingFunctions/ZeroZeroOneSplitFn.cc
--- a/Shower/SplittingFunctions/ZeroZeroOneSplitFn.cc
+++ b/Shower/SplittingFunctions/ZeroZeroOneSplitFn.cc
@@ -1,94 +1,95 @@
// -*- C++ -*-
//
// PhitoPhiGSplitFn.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 ZeroZeroOneSplitFn class.
//
#include "ZeroZeroOneSplitFn.h"
#include "ThePEG/PDT/ParticleData.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include <cassert>
+#include "ThePEG/Utilities/DescribeClass.h"
using namespace Herwig;
-NoPIOClassDescription<ZeroZeroOneSplitFn> ZeroZeroOneSplitFn::initZeroZeroOneSplitFn;
-// Definition of the static class description member.
+DescribeNoPIOClass<ZeroZeroOneSplitFn,Herwig::SplittingFunction>
+describeZeroZeroOneSplitFn ("Herwig::ZeroZeroOneSplitFn","HwShower.so");
void ZeroZeroOneSplitFn::Init() {
static ClassDocumentation<ZeroZeroOneSplitFn> documentation
("The ZeroZeroOneSplitFn class implements the splitting function for the "
"radiation of a gluon by a scalar coloured particle");
}
double ZeroZeroOneSplitFn::P(const double z, const Energy2 t,
const IdList &ids, const bool mass) const {
double val = z/(1.-z);
if(mass) {
Energy m = getParticleData(ids[0])->mass();
val-= sqr(m)/t;
}
return 2.*colourFactor()*val;
}
double ZeroZeroOneSplitFn::overestimateP(const double z, const IdList &) const {
return 2.*colourFactor()/(1.-z);
}
double ZeroZeroOneSplitFn::ratioP(const double z, const Energy2 t,
const IdList &ids,const bool mass) const {
double val = z;
if(mass) {
Energy m = getParticleData(ids[0])->mass();
val-=sqr(m)*(1.-z)/t;
}
return val;
}
double ZeroZeroOneSplitFn::integOverP(const double z, const IdList & ,
unsigned int PDFfactor) const {
switch(PDFfactor) {
case 0:
return -2.*colourFactor()*log(1.-z);
case 1:
case 2:
case 3:
default:
throw Exception() << "ZeroZeroOneSplitFn::integOverP() invalid PDFfactor = "
<< PDFfactor << Exception::runerror;
}
}
double ZeroZeroOneSplitFn::invIntegOverP(const double r, const IdList & ,
unsigned int PDFfactor) const {
switch(PDFfactor) {
case 0:
return 1. - exp(- 0.5*r/colourFactor());
case 1:
case 2:
case 3:
default:
throw Exception() << "ZeroZeroOneSplitFn::integOverP() invalid PDFfactor = "
<< PDFfactor << Exception::runerror;
}
}
bool ZeroZeroOneSplitFn::accept(const IdList &ids) const {
if(ids.size()!=3) return false;
if(ids[0]!=ids[1]) return false;
tcPDPtr q=getParticleData(ids[0]);
tcPDPtr g=getParticleData(ids[2]);
if(q->iSpin()!=PDT::Spin0 ||
g->iSpin()!=PDT::Spin1) return false;
return checkColours(ids);
}
diff --git a/Shower/SplittingFunctions/ZeroZeroOneSplitFn.h b/Shower/SplittingFunctions/ZeroZeroOneSplitFn.h
--- a/Shower/SplittingFunctions/ZeroZeroOneSplitFn.h
+++ b/Shower/SplittingFunctions/ZeroZeroOneSplitFn.h
@@ -1,192 +1,151 @@
// -*- C++ -*-
//
// ZeroZeroOneSplitFn.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_ZeroZeroOneSplitFn_H
#define HERWIG_ZeroZeroOneSplitFn_H
//
// This is the declaration of the ZeroZeroOneSplitFn class.
//
#include "SplittingFunction.h"
namespace Herwig {
using namespace ThePEG;
/** \ingroup Shower
* This class provides the concrete implementation of the exact leading-order
* splitting function for \f$\phi\to \phi g\f$.
*
* In this case the splitting function is given by
* \f[P(z,t) = 2C\left(\frac{z}{1-z}-\frac{m^2_\phi}{t}\right),\f]
* where \f$C\f$ is the corresponding colour factor.
* Our choice for the overestimate is
* \f[P_{\rm over}(z) = \frac{2C}{1-z},\f]
* therefore the integral is
* \f[\int P_{\rm over}(z) {\rm d}z = -2C\ln(1-z),\f]
* and its inverse is
* \f[1-\exp\left(\frac{r}{2C}\right).\f]
*
* @see \ref ZeroZeroOneSplitFnInterfaces "The interfaces"
* defined for ZeroZeroOneSplitFn.
*/
class ZeroZeroOneSplitFn: public SplittingFunction {
public:
/**
* The default constructor.
*/
inline ZeroZeroOneSplitFn() : SplittingFunction(1) {}
/**
* Concrete implementation of the method to determine whether this splitting
* function can be used for a given set of particles.
* @param ids The PDG codes for the particles in the splitting.
*/
virtual bool accept(const IdList & ids) const;
/**
* Methods to return the splitting function.
*/
//@{
/**
* The concrete implementation of the splitting function, \f$P\f$.
* @param z The energy fraction.
* @param t The scale.
* @param ids The PDG codes for the particles in the splitting.
* @param mass Whether or not to include the mass dependent terms
*/
virtual double P(const double z, const Energy2 t, const IdList & ids,
bool mass) const;
/**
* The concrete implementation of the overestimate of the splitting function,
* \f$P_{\rm over}\f$.
* @param z The energy fraction.
* @param ids The PDG codes for the particles in the splitting.
*/
virtual double overestimateP(const double z, const IdList & ids) const;
/**
* The concrete implementation of the
* the ratio of the splitting function to the overestimate, i.e.
* \f$P(z,\tilde{q}^2)/P_{\rm over}(z)\f$.
* @param z The energy fraction.
* @param t The scale.
* @param ids The PDG codes for the particles in the splitting.
* @param mass Whether or not to include the mass dependent terms
*/
virtual double ratioP(const double z, const Energy2 t, const IdList & ids,
bool mass) const;
/**
* The concrete implementation of the indefinite integral of the
* overestimated splitting function, \f$P_{\rm over}\f$.
* @param z The energy fraction.
* @param ids The PDG codes for the particles in the splitting.
* @param PDFfactor Which additional factor to include for the PDF
* 0 is no additional factor,
* 1 is \f$1/z\f$, 2 is \f$1/(1-z)\f$ and 3 is \f$1/z/(1-z)\f$
*/
virtual double integOverP(const double z, const IdList & ids,
unsigned int PDFfactor=0) const;
/**
* The concrete implementation of the inverse of the indefinite integral.
* @param r Value of the splitting function to be inverted
* @param ids The PDG codes for the particles in the splitting.
* @param PDFfactor Which additional factor to include for the PDF
* 0 is no additional factor,
* 1 is \f$1/z\f$, 2 is \f$1/(1-z)\f$ and 3 is \f$1/z/(1-z)\f$
*/
virtual double invIntegOverP(const double r, const IdList & ids,
unsigned int PDFfactor=0) const;
//@}
public:
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
inline virtual IBPtr clone() const {return new_ptr(*this);}
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
inline virtual IBPtr fullclone() const {return new_ptr(*this);}
//@}
private:
/**
- * The static object used to initialize the description of this class.
- * Indicates that this is a concrete class with persistent data.
- */
- static NoPIOClassDescription<ZeroZeroOneSplitFn> initZeroZeroOneSplitFn;
-
- /**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
ZeroZeroOneSplitFn & operator=(const ZeroZeroOneSplitFn &);
};
}
-#include "ThePEG/Utilities/ClassTraits.h"
-
-namespace ThePEG {
-
-/** @cond TRAITSPECIALIZATIONS */
-
-/** This template specialization informs ThePEG about the
- * base classes of ZeroZeroOneSplitFn. */
-template <>
-struct BaseClassTrait<Herwig::ZeroZeroOneSplitFn,1> {
- /** Typedef of the first base class of ZeroZeroOneSplitFn. */
- typedef Herwig::SplittingFunction NthBase;
-};
-
-/** This template specialization informs ThePEG about the name of
- * the ZeroZeroOneSplitFn class and the shared object where it is defined. */
-template <>
-struct ClassTraits<Herwig::ZeroZeroOneSplitFn>
- : public ClassTraitsBase<Herwig::ZeroZeroOneSplitFn> {
- /** Return a platform-independent class name */
- static string className() { return "Herwig::ZeroZeroOneSplitFn"; }
- /**
- * The name of a file containing the dynamic library where the class
- * ZeroZeroOneSplitFn is implemented. It may also include several, space-separated,
- * libraries if the class ZeroZeroOneSplitFn depends on other classes (base classes
- * excepted). In this case the listed libraries will be dynamically
- * linked in the order they are specified.
- */
- static string library() { return "HwShower.so"; }
-};
-
-/** @endcond */
-
-}
-
#endif /* HERWIG_ZeroZeroOneSplitFn_H */
diff --git a/Shower/UEBase.cc b/Shower/UEBase.cc
--- a/Shower/UEBase.cc
+++ b/Shower/UEBase.cc
@@ -1,24 +1,25 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the UEBase class.
//
#include "UEBase.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
+#include "ThePEG/Utilities/DescribeClass.h"
using namespace Herwig;
-AbstractClassDescription<UEBase> UEBase::initUEBase;
-// Definition of the static class description member.
+DescribeAbstractClass<UEBase,Interfaced>
+describeUEBase ("Herwig::UEBase","HwShower.so");
void UEBase::Init() {
static ClassDocumentation<UEBase> documentation
("The UEBase class is an abstract base class used to minimize the"
" dependence between the MPIHandler and all Shower classes");
}
diff --git a/Shower/UEBase.h b/Shower/UEBase.h
--- a/Shower/UEBase.h
+++ b/Shower/UEBase.h
@@ -1,172 +1,131 @@
// -*- C++ -*-
#ifndef HERWIG_UEBase_H
#define HERWIG_UEBase_H
//
// This is the declaration of the UEBase class.
//
#include "ThePEG/Interface/Interfaced.h"
#include "ThePEG/Handlers/StandardXComb.fh"
#include "UEBase.fh"
namespace Herwig {
using namespace ThePEG;
/**
* Abstract base class used to minimize the dependence between
* MPIHandler and all Shower classes.
*
* \author Manuel B\"ahr
*
* @see \ref UEBaseInterfaces "The interfaces"
* defined for UEBase.
*/
class UEBase: public Interfaced {
public:
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
/** @name Virtual functions used for the generation of additional
interactions . */
//@{
/**
* Some initialization code eventually.
*/
virtual void initialize() {}
/**
* Return true or false depending on the generator setup.
*/
virtual bool beamOK() const = 0;
/**
* Return true or false depending on whether soft interactions are enabled.
*/
virtual bool softInt() const {return false;}
/**
* Return the value of the pt cutoff.
*/
virtual Energy Ptmin() const = 0;
/**
* Return the slope of the soft pt spectrum. Only necessary when the
* soft part is modelled.
*/
virtual InvEnergy2 beta() const {return ZERO;}
/**
* Some finalize code eventually.
*/
virtual void finalize() {}
/**
* Clean up method called after each event.
*/
virtual void clean() {}
/**
* Return the number of different hard processes. Use 0 as default to
* not require implementation.
*/
virtual unsigned int additionalHardProcs() const {return 0;}
/**
* return the hard multiplicity of process i. Can't be constant in my
* case because drawing from the probability distribution also
* specifies the soft multiplicity that has to be stored....
*/
virtual unsigned int multiplicity(unsigned int i=0) = 0;
/**
* Generate a additional interaction for ProcessHandler sel. Method
* can't be const because it saves the state of the underlying XComb
* object on it's way.
*/
virtual tStdXCombPtr generate(unsigned int sel=0) = 0;
/**
* Return the type of algorithm.
*/
virtual int Algorithm() const = 0;
/**
* Return the value of the hard Process pt cutoff for vetoing.
*/
virtual Energy PtForVeto() const = 0;
/**
* Return the fraction of colour disrupted subprocesses. Use default 0
* so that it is not required to implement.
*/
virtual double colourDisrupt() const {return 0.0;}
/**
* Return the soft multiplicity. Use 0 as default to not require
* implementation.
*/
virtual unsigned int softMultiplicity() const {return 0;}
//@}
private:
/**
- * The static object used to initialize the description of this class.
- * Indicates that this is an abstract class with persistent data.
- */
- static AbstractClassDescription<UEBase> initUEBase;
-
- /**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
UEBase & operator=(const UEBase &);
};
}
-#include "ThePEG/Utilities/ClassTraits.h"
-
-namespace ThePEG {
-
-/** @cond TRAITSPECIALIZATIONS */
-
-/** This template specialization informs ThePEG about the
- * base classes of UEBase. */
-template <>
-struct BaseClassTrait<Herwig::UEBase,1> {
- /** Typedef of the first base class of UEBase. */
- typedef Interfaced NthBase;
-};
-
-/** This template specialization informs ThePEG about the name of
- * the UEBase class and the shared object where it is defined. */
-template <>
-struct ClassTraits<Herwig::UEBase>
- : public ClassTraitsBase<Herwig::UEBase> {
- /** Return a platform-independent class name */
- static string className() { return "Herwig::UEBase"; }
- /**
- * The name of a file containing the dynamic library where the class
- * UEBase is implemented. It may also include several, space-separated,
- * libraries if the class UEBase depends on other classes (base classes
- * excepted). In this case the listed libraries will be dynamically
- * linked in the order they are specified.
- */
- static string library() { return "HwShower.so"; }
-};
-
-/** @endcond */
-
-}
-
#endif /* HERWIG_UEBase_H */

File Metadata

Mime Type
text/x-diff
Expires
Tue, Jan 21, 2:24 AM (1 d, 17 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4243663
Default Alt Text
(480 KB)

Event Timeline