Page Menu
Home
HEPForge
Search
Configure Global Search
Log In
Files
F7879811
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
61 KB
Subscribers
None
View Options
diff --git a/.hgignore b/.hgignore
--- a/.hgignore
+++ b/.hgignore
@@ -1,113 +1,114 @@
Makefile$
Makefile\.in$
\.deps$
\.libs$
\.l[ao]$
\.so$
\.so\.
\.o$
~$
\.pyc$
\.codereplace$
\.orig$
\.tar\.(gz|bz2)$
^autom4te.cache$
^config.herwig$
^config.log$
^config.status$
^configure$
^include/Herwig$
^Config/config.guess$
^Config/config.h$
^Config/config.h.in$
^Config/config.sub$
^Config/depcomp$
^Config/compile$
^Config/install-sh$
^Config/missing$
^Config/stamp-h1$
^Config/ar-lib$
^Contrib/make_makefiles.sh$
^Contrib/.*/.*\.(log|out|tex|run)$
^Utilities/hgstamp.inc$
^Doc/HerwigDefaults.in$
^Doc/refman-html$
^Doc/fixinterfaces.pl$
^Doc/refman.conf$
^Doc/refman.h$
^Doc/AllInterfaces.h$
^Doc/HerwigDefaults.rpo$
^Doc/Herwig-refman.tag$
^Doc/tagfileThePEG.tag$
^Doc/.*\.log$
^INSTALL$
^aclocal.m4$
^confdefs.h$
^conftest.c$
^conftest.err$
^include/done-all-links$
^libtool$
\.dirstamp$
^src/hgstamp.inc$
^src/herwigopts.h$
^src/herwigopts.c$
^src/defaults/Analysis.in$
^src/defaults/Decays.in$
^src/defaults/decayers.in$
^src/herwig-config$
^src/.*\.(run|tex|out|log|rpo|spc|top|dump|dot|aux|pdf|ps|png|svg|hepmc|dvi)$
^src/Makefile-UserModules$
^lib/done-all-links$
^lib/apple-fixes$
^src/defaults/PDF.in$
^src/defaults/done-all-links$
^src/tune$
^src/Herwig$
^src/Herwig-cache$
^src/tests/.*\.(time|mult|Bmult|chisq)$
^src/Merging/test/*yoda
^src/Merging/test/Herwig*
^src/Merging/test/L*
^src/Merging/test/done-all-links
^src/Merging/done-all-links
^Tests/.*/.*\.(top|ps|pyc|info|dat|pdf|png)$
^Tests/.*\.(top|ps|pyc|info|dat|pdf|png|log|out)$
^Tests/.*\.(top|run|tex|mult|Bmult|aida|yoda)$
^Tests/Rivet-.*$
^Tests/.cache$
^Tests/Rivet/(LEP|DIS|LHC|TVT|Star|BFactory|ISR|SppS)-.*\.in$
^Tests/plots$
^Tests/Herwig$
^Tests/.*index.html$
^Herwig\-
^Models/Feynrules/python/Makefile-FR$
^MatrixElement/Matchbox/External/MadGraph/mg2herwig$
^MatrixElement/Matchbox/Scales/MatchboxScale.cc$
^Utilities/Statistics/herwig-combinedistributions$
^Utilities/Statistics/herwig-combineruns$
^Utilities/Statistics/herwig-makedistributions$
^src/defaults/MatchboxDefaults.in$
^src/defaults/setup.gosam.in$
^src/Matchbox/LO-DefaultShower.in$
^src/Matchbox/LO-DipoleShower.in$
^src/Matchbox/LO-NoShower.in$
^src/Matchbox/MCatLO-DefaultShower.in$
^src/Matchbox/MCatLO-DipoleShower.in$
^src/Matchbox/MCatNLO-DefaultShower.in$
^src/Matchbox/MCatNLO-DipoleShower.in$
^src/Matchbox/NLO-NoShower.in$
^src/Matchbox/Powheg-DefaultShower.in$
^src/Matchbox/Powheg-DipoleShower.in$
^src/defaults/MatchboxMergingDefaults.in
^src/Matchbox/done-all-links$
^src/snippets/done-all-links$
^Utilities/XML/xml_test$
^Utilities/utilities_test$
^Utilities/versionstring.h$
^MatrixElement/Matchbox/External/MadGraph/mg2herwig.py$
test\.(log|trs)$
test-suite\.log$
^Config/test-driver$
param_card\.dat$
__all.cc$
.ccR$
+^tmp/*
diff --git a/Shower/Dipole/Merging/Merger.cc b/Shower/Dipole/Merging/Merger.cc
--- a/Shower/Dipole/Merging/Merger.cc
+++ b/Shower/Dipole/Merging/Merger.cc
@@ -1,1622 +1,1627 @@
// -*- C++ -*-
//
// Merger.cc is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2017 The Herwig Collaboration
//
// Herwig is licenced under version 3 of the GPL , see COPYING for details.
// Please respect the MCnet academic guidelines , see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined , non-templated member
// functions of the Merger class.
//
#include "Merger.h"
#include "Node.h"
#include "MergingFactory.h"
// other includes when needed below.
using namespace Herwig;
IBPtr Merger::clone() const {
return new_ptr( *this );
}
IBPtr Merger::fullclone() const {
return new_ptr( *this );
}
namespace {
double decideClustering(const NodePtr sub,const NodePtr head,bool& pro){
if( sub != head ){// at least one history step -> unitarisation
if ( UseRandom::rndbool() ){ pro = true; return -2.; }
else{ pro = false; return 2.; }
} // no ordered history -> no projection
else{ pro = false; return 1.; }
}
}
CrossSection Merger::MergingDSigDRBornStandard( ){
// get the history for the process
const NodePtr productionNode =
currentNode()-> getHistory( true, DSH()->hardScaleFactor() );
// decide if to cluster
weight = decideClustering(productionNode, currentNode(), projected);
// check if we only want to calculate the current multiplicity.
if(notOnlyMulti()) return ZERO;
// Check for cuts on the production proces.
if ( !productionNode->xcomb()->willPassCuts() ) return ZERO;
// calculate the staring scale for the production node
Energy startscale = CKKW_StartScale( productionNode );
// fill history with caluclation of sudakov supression
fillHistory( startscale , productionNode , currentNode() );
// fill the projector -> return the scale of the last splitting
currentNode()->runningPt( fillProjector( projected ? 1 : 0 ) );
// the weight has three components to get shower history weight
weight *= history.back().weight* // Sudakov suppression
alphaReweight()* // alpha_s reweight
pdfReweight(); // pdf reweight
// If weight is zero return.
if( weight == ZERO ) return ZERO;
//calculate the cross section
return weight*TreedSigDR( startscale , 1. );
}
CrossSection Merger::MergingDSigDRVirtualStandard( ){
// get the history for the process
const NodePtr productionNode = currentNode()-> getHistory( true , DSH()->hardScaleFactor() );
// decide if to cluster
weight = decideClustering(productionNode,currentNode(),projected);
// Check for cuts on the production proces.
if ( !productionNode->xcomb()->willPassCuts() )return ZERO;
// calculate the staring scale
Energy startscale = CKKW_StartScale( productionNode );
// fill history with caluclation of sudakov supression
fillHistory( startscale , productionNode , currentNode() );
// fill the projector -> return the scale of the last splitting
currentNode()->runningPt( fillProjector( projected ? 1 : 0 ) );
// the weight has three components to get shower history weight
double ww1 = history.back().weight;
double ww2 = alphaReweight(true);
double ww3 = pdfReweight();
weight *= ww1*ww2*ww3;
// If weight is zero return.
if( weight == 0. )return ZERO;
// calculate the cross section for virtual contribution
// and various insertion operators.
CrossSection matrixElement = LoopdSigDR( startscale );
// Now calculate the expansion of the shower history.
// first: the born contibution:
CrossSection bornWeight = currentME()->dSigHatDRB();
// second: expansion of pdf ,alpha_s-ratio and sudakov suppression.
double w1 = -sumPdfReweightExpansion();
double w2 = -sumAlphaSReweightExpansion();
double w3 = -sumFillHistoryExpansion();
// put together the expansion weights.
CrossSection expansionweight =
bornWeight*SM().alphaS()/( 2.*ThePEG::Constants::pi );
if (theShowerExpansionWeights == 0){
expansionweight *=0.;
}else if ( theShowerExpansionWeights == 1 ){
expansionweight *=w1+w2+w3;
}else if ( theShowerExpansionWeights == 2 ){
expansionweight *=w1+w2+w3*pow(as( startscale*DSH()->renFac() )/SM().alphaS(),currentME()->orderInAlphaS())/ww2;
}else if ( theShowerExpansionWeights == 3 ){
expansionweight *=(w1+w2+w3)*pow(as( startscale*DSH()->renFac() )/SM().alphaS(),currentME()->orderInAlphaS())/ww2;
}else if ( theShowerExpansionWeights == 4 ){
expansionweight *= w1+w3+w2*pow(as( startscale*DSH()->renFac() )/SM().alphaS(),currentME()->orderInAlphaS())/ww2;
}else assert(false && theShowerExpansionWeights);
// [ DEBUG ]
if ( currentNode()->legsize() == 5 && Debug::level > 2 )
debugVirt(weight,w1,w2,w3,matrixElement,ww1,ww2,ww3,productionNode,bornWeight);
// return with correction that ME was calculated with fixed alpha_s
return weight* as( startscale*DSH()->renFac() )/
SM().alphaS()* ( matrixElement+expansionweight );
}
CrossSection Merger::MergingDSigDRRealStandard(){
if ( currentNode()->children().empty() ) {
throw Exception()
<< "Real emission contribution without underlying born."
<< "These are finite contibutions already handled in LO merging."
<< Exception::abortnow;
}
// check for IR Safe Cutoff
if( !currentNode()->allAbove( theIRSafePT ) )return ZERO;
auto inOutPair = currentNode()->getInOut();
NodePtr randomChild = currentNode()->randomChild();
bool meRegion =matrixElementRegion(
inOutPair.first ,
inOutPair.second ,
randomChild->pT() ,
theMergePt );
if ( meRegion )return MergingDSigDRRealAllAbove( );
if ( UseRandom::rndbool() )
return 2.*MergingDSigDRRealBelowSubReal( );
return 2.*MergingDSigDRRealBelowSubInt( );
}
CrossSection Merger::MergingDSigDRRealAllAbove( ){
//If all dipoles pts are above , we cluster to this dipole.
NodePtr CLNode = currentNode()->randomChild();
// Check if phase space poing is in ME region--> else rm PSP
if ( !CLNode->children().empty() ) {
auto inOutPair = CLNode->getInOut();
NodePtr randomChild = CLNode->randomChild();
if( !matrixElementRegion( inOutPair.first ,
inOutPair.second ,
randomChild->pT() ,
theMergePt ) )return ZERO;
}
// first find the history for the acctual Node
NodePtr productionNode = currentNode()-> getHistory( true , DSH()->hardScaleFactor() );
// If CLNode is not part of the history , dont calculate the Real contribution
// else multiply the real contribution with N ( number of children ).
// this returns the sudakov suppression according to
// the clustering of the born parts.
bool inhist = CLNode->isInHistoryOf( productionNode );
if(productionNode== currentNode())assert(!inhist);
// get the history for the clustered Node.
productionNode = CLNode-> getHistory( false , DSH()->hardScaleFactor() );
// decide if to cluster
weight = decideClustering(productionNode,CLNode,projected);
// Check for cuts on the production process.
if ( !productionNode->xcomb()->willPassCuts() )return ZERO;
// calculate the staring scale
Energy startscale = CKKW_StartScale( productionNode );
// fill history with caluclation of sudakov supression
fillHistory( startscale , productionNode , CLNode );
// fill the projector -> return the scale of the last splitting
currentNode()->runningPt( fillProjector( projected ? 2 : 1 ) );
// the weight has three components to get shower history weight
weight *= history.back().weight*alphaReweight(true)*pdfReweight();
if( weight == 0. )return ZERO;
// The inhist flag produces the correct cluster density.
CrossSection me = ( inhist?TreedSigDR( startscale ):ZERO );
// calculate the dipole
CrossSection dip = CLNode->calcDip( startscale* currentME()->renFac() );
CrossSection res = weight*as( startscale*DSH()->renFac() )/SM().alphaS()*
currentNode()->children().size()*
( me - dip );
// [ DEBUG ]
if ( currentNode()->legsize() == 6&&Debug::level > 2 )
debugReal("RAA",weight,me,dip);
return res;
}
CrossSection Merger::MergingDSigDRRealBelowSubReal( ){
// Choose a random child to produce history from.
NodePtr HistNode = currentNode()->randomChild();
// Check that this subleading point is in ME region.
if ( !HistNode->children().empty() ) {
auto inOutPair = HistNode->getInOut();
NodePtr randomChild = HistNode->randomChild(); // Here we make sure that clustering and splitting are invertible
if( !matrixElementRegion( inOutPair.first , inOutPair.second , randomChild->pT() , theMergePt ) )return ZERO;
}
// As the HistNode is now in ME region, we can cluster according to LO merging.
// In this clustering we do not require a orering for the last step to the currentNode.
const NodePtr productionNode = HistNode-> getHistory( false , DSH()->hardScaleFactor() );
// If the real emission contribution should be unitarised, we decide here if we cluster.
// This applies to NLO corrections for the first emission w.r.t. the production process the first time.
weight = decideClustering(productionNode,HistNode,projected);
// The production node needs to fulfill the cut criterion of the production process.
if ( !productionNode->xcomb()->willPassCuts() && !currentNode()->xcomb()->willPassCuts() )return ZERO;
// Calculate the starting scale w.r.t. the production process.
Energy startscale = CKKW_StartScale( productionNode );
// If the production process does not fullfill the cut criterion use the real emission point (DEBUG)
if (!productionNode->xcomb()->willPassCuts()) startscale = CKKW_StartScale( currentNode() );
// DEBUG trial
//currentNode()->xcomb()->lastProjector( productionNode->xcomb());
// Calculate the sudakov weights starting from the production node to the histNode
fillHistory( startscale , productionNode , HistNode );
// Set the running Pt of the process as it is used in the vetoed parton shower.
currentNode()->runningPt( fillProjector( projected ? 1 : 0 ) );
currentNode()->runningPt(max(HistNode->pT(),theMergePt));
// Calculate the alpha_S ratios and pdf ratios.
weight *= history.back().weight*alphaReweight(true)*pdfReweight();
if( weight == 0. )return ZERO;
// Start calculation of subtraction contribution.
CrossSection sumPS = ZERO;
// Iterate over all subtraction contributions.
for( auto const & child : currentNode()->children() ){
if ( child->allAbove( mergePt() ) && child->xcomb()->willPassCuts() ){
Energy relevantScale=child->children().empty()?CKKW_StartScale( child ):child->maxChildPt();
if( ( child )->pT()>mergePt()/theRealSubtractionRatio ){
if( child ->pT()<relevantScale&&(child->inShowerPS(relevantScale))){ //DEBUG: CKKW_StartScale( child);????
sumPS += child->calcPs( startscale* currentME()->renFac() );
}
}else{
if( child ->pT()<relevantScale){
sumPS += child->calcDip( startscale* currentME()->renFac() );
}
}
}
}
CrossSection me = ZERO;
if(currentNode()->xcomb()->willPassCuts()){
me = TreedSigDR( startscale );
}
// [ DEBUG ]
if ( currentNode()->legsize() == 6&&Debug::level > 2 )
debugReal("RBSR",weight,me,sumPS);
//Here we subtract the PS ( and below the dynamical cutoff the Dip )
return weight*as( startscale*DSH()->renFac() )/SM().alphaS()*
( me-sumPS );
}
CrossSection Merger::MergingDSigDRRealBelowSubInt( ){
if( currentNode()->children().empty() )return ZERO;
NodePtr CLNode = currentNode()->randomChild();
if( CLNode->pT()<mergePt()/theRealSubtractionRatio )return ZERO;
if ( !CLNode->children().empty() ) {
auto inOutPair = CLNode->getInOut( );
NodePtr randomChild = CLNode->randomChild(); // Here we make sure that clustering and splitting are invertible
if( !matrixElementRegion( inOutPair.first , inOutPair.second , randomChild->pT() , theMergePt ) )return ZERO;
}
const NodePtr productionNode = CLNode-> getHistory( false , DSH()->hardScaleFactor() );
weight = decideClustering(productionNode,CLNode,projected);
if ( !CLNode->allAbove( mergePt() ) )return ZERO;
if ( !productionNode->xcomb()->willPassCuts() )return ZERO;
Energy startscale = CKKW_StartScale( productionNode );
fillHistory( startscale , productionNode , CLNode );
currentNode()->runningPt( fillProjector( projected ? 2 : 1 ) );
weight *= history.back().weight*alphaReweight(true)*pdfReweight();
if( weight == 0. )return ZERO;
pair<CrossSection , CrossSection> DipAndPs =
CLNode->calcDipandPS( startscale* currentME()->renFac() );
// [ DEBUG ]
if ( currentNode()->legsize() == 6&&Debug::level > 2 )
debugReal("RBSI",weight,DipAndPs.second,DipAndPs.first);
Energy relevantScale=CLNode->children().empty()?CKKW_StartScale( CLNode ):CLNode->maxChildPt();
bool calcPScontribution=CLNode->pT()<relevantScale&&(CLNode->inShowerPS(relevantScale));
//Here we add the PS and subtrac the Dip ( only above the dynamical cutoff )
return weight*as( startscale*DSH()->renFac() )/SM().alphaS()*
currentNode()->children().size()*( (calcPScontribution?DipAndPs.second:ZERO)-DipAndPs.first );
}
CrossSection Merger::MergingDSigDRBornGamma( ){
double weightCL = 0.;
weight = 1.;
if ( !currentNode()->children().empty() ) {
auto const inOutPair = currentNode()->getInOut();
// Here we make sure that clustering and splitting are invertible.
NodePtr randomChild = currentNode()->randomChild();
// Check if point is part of the ME region.
if( !matrixElementRegion( inOutPair.first ,
inOutPair.second ,
randomChild->pT() ,
theMergePt ) )weight *= 0.;
}
const NodePtr productionNode = currentNode()->getHistory( true , DSH()->hardScaleFactor() );
NodePtr CLNode;
NodePtr BornCL;
if( !currentNode()->children().empty() ){
if ( UseRandom::rndbool() ){
CLNode = currentNode()->randomChild();
bool inhist = CLNode->isInHistoryOf( productionNode );
weight *= inhist?( -2.*int( currentNode()->children().size() ) ):0.;
projected = true;
weightCL = 2.*int( currentNode()->children().size() );
BornCL = CLNode-> getHistory( false , DSH()->hardScaleFactor() );
}else{
weight = 2.;
projected = false;
}
}else{
weight = 1.;
projected = false;
}
if ( treefactory()->onlymulti() != -1&&
treefactory()->onlymulti() !=
int( currentNode()->legsize()-(projected ? 1 : 0) ) )
return ZERO;
if( !currentNode()->allAbove( mergePt()*(1.-1e-6) ) )weight = 0.;
if( CLNode&&!CLNode->allAbove( mergePt()*(1.-1e-6) ) )weightCL = 0.;
if ( !productionNode->xcomb()->willPassCuts() ){
return ZERO;
}
CrossSection res = ZERO;
bool maxMulti = currentNode()->legsize() == int( maxLegsLO() );
if( weight != 0. ){
Energy startscale = CKKW_StartScale( productionNode );
fillHistory( startscale , productionNode , currentNode() );
currentNode()->runningPt( fillProjector( (projected ? 1 : 0) ) );
weight *= history.back().weight*alphaReweight()*pdfReweight();
if( weight == 0.&&weightCL == 0. )return ZERO;
res += weight*TreedSigDR( startscale , ( !maxMulti&&!projected )?theGamma:1. );
}
if( CLNode&&theGamma != 1. ){
Energy startscale = CKKW_StartScale( BornCL );
fillHistory( startscale , BornCL , CLNode );
currentNode()->runningPt( fillProjector( projected ? 1 : 0 ) );
weightCL *= history.back().weight*alphaReweight()*pdfReweight();
CrossSection diff = ZERO;
currentME()->factory()->setAlphaParameter( 1. );
diff -= weightCL*CLNode->dipole()->dSigHatDR( sqr( startscale* currentME()->renFac() ) );
currentME()->factory()->setAlphaParameter( theGamma );
string alp = ( CLNode->dipole()->aboveAlpha()?"Above":"Below" );
diff += weightCL*CLNode->dipole()->dSigHatDR( sqr( startscale* currentME()->renFac() ) );
currentME()->factory()->setAlphaParameter( 1. );
res += diff;
}
return res;
}
CrossSection Merger::TreedSigDR( Energy startscale , double diffAlpha ){
currentME()->setScale( sqr( startscale ) , sqr( startscale ) );
CrossSection res = currentME()->dSigHatDRB();
/*bool useDipolesForME=false;
if (useDipolesForME && !currentNode()->children().empty()){
res=ZERO;
for (auto const & child : currentNode()->children() )
res-=child->dipole()->dSigHatDR(sqr( startscale ));
}
*/
if ( projected && emitDipoleMEDiff ) {
CrossSection resDip=ZERO;
for (auto const & child : currentNode()->children() )
resDip-=child->dipole()->dSigHatDR(sqr( startscale ));
setEmissionProbability(1.-min(resDip/res,res/resDip));
}else{
setEmissionProbability(0.);
}
if ( diffAlpha != 1. ) {
res += currentME()->dSigHatDRAlphaDiff( diffAlpha );
}
if( std::isnan( double( res/nanobarn ) ) ){
generator()->logWarning(Exception()
<< "Merger: TreedSigDR is nan"
<< Exception::warning);
res = ZERO;};
return res;
}
CrossSection Merger::LoopdSigDR( Energy startscale ){
currentME()->setScale( sqr( startscale ) , sqr( startscale ) );
currentME()->doOneLoopNoBorn();
CrossSection res = currentME()->dSigHatDRV()+
currentME()->dSigHatDRI();
currentME()->noOneLoopNoBorn();
return res;
}
Energy Merger::fillProjector( int pjs ){
// in the shower handler the scale is multiplied
// by DSH()->hardScaleFactor() so here we need
// to devide by the factor.
double xiQSh = history.begin()->node->legsize() == N0()?DSH()->hardScaleFactor():1.;
if( pjs == 0 ){
return ( history.size() == 1?1.:( 1./xiQSh ) )*history.back().scale;
}
for( auto const & hs : history )
if ( isProjectorStage( hs.node , pjs )&&pjs != 0 ){
currentNode()->xcomb()->lastProjector( hs.node->xcomb() );
return ( hs.node == history[0].node?1.:( 1./xiQSh ) )*hs.scale;
}
throw Exception() << "Could not fill projector." << Exception::abortnow;
return ZERO;
}
double Merger::pdfReweight(){ // TODO factorization scale inside
double res = 1.;
// consider both sides.
for( int side : {0 , 1} ){
// The side scale defines the scale that the leg is changig thou the history.
// We start reweighting at the seed process.
// We only need to calculate the pdf if the emission whould change the leg,
// otherwise the leg remains the same.
// If no emission is prduced from this leg the pdf ratios from this leg are always 1.
Energy sidescale=history[0].scale*(
history[0].node->legsize() == N0() ?
currentME()->facFac():
DSH()->facFac());
bool sidechanged=false;
// only if the incoming parton is coloured.
if( history[0].node->xcomb()->mePartonData()[side]->coloured() ){
// go though the history.
for ( auto const & hs : history ){
//pdf-ratio only to the last step
if ( !hs.node->parent() ) continue;
if ( hs.node == history.back().node ) continue;
if ( !hs.node->dipole() ){
throw Exception()
<< "\nMerger: pdfReweight: history step has no dipol. "
<< Exception::abortnow;
return 0.;
}
// if the emitter is the side the emission changes the momentum fraction.
if(!(hs.node->dipole()->bornEmitter()==side||
// II dipoles dont change the momentum fraction of the spectator only FI
( hs.node->dipole()->bornSpectator()==side && hs.node->dipole()->bornEmitter()>1)))
continue;
const bool fromIsME = false;
const bool toIsME = history[0].node == hs.node;
res *= pdfratio( hs.node,
//numerator
sidescale,
// denominator
DSH()->facFac()*hs.node->pT(),
side,
fromIsME,
toIsME);
sidescale= DSH()->facFac()*hs.node->pT();
sidechanged=true;
}
const bool fromIsME = true;
const bool toIsME = !sidechanged && history[0].node->legsize() == N0();
res *= pdfratio( history.back().node,
sidescale,
history[0].scale * currentME()->facFac(),
side,
fromIsME,
toIsME );
}
}
if ( std::isnan( res ) )
generator()->logWarning(Exception()
<< "Merger: pdfReweight is nan."
<< Exception::warning);
return res;
}
double Merger::cmwAlphaS(Energy q)const{
using Constants::pi;
// No cmw-scheme
if (theCMWScheme==0)
return as( q );
// Linear cmw-scheme
else if(theCMWScheme==1){
double als=as( q );
return als *
(1.+(3.*(67./18.-1./6.*sqr(pi))
-5./9.*Nf(q))* als/2./pi);
}
// cmw-scheme as factor in argument.
else if(theCMWScheme==2){
double kg=exp(-(67.-3.*sqr(pi)-10/3*Nf(q))
/( 2. *(33.-2.*Nf(q))));
//Note factor 2 since we here dealing with Energy
return as(max(kg*q,1_GeV));
}else{
throw Exception()
<< "This CMW-Scheme is not implemented."
<< Exception::abortnow;
}
return -1;
}
double Merger::alphaReweight(bool nocmw){
double res = 1.;
Energy Q_R = ( history[0].node->legsize() == N0()?
currentME()->renFac():
DSH()->renFac() )*
history[0].scale;
using Constants::pi;
const auto Q_qed=history[0].node->nodeME()->factory()->scaleChoice()->renormalizationScaleQED();
const auto Oew=history[0].node->nodeME()->orderInAlphaEW();
const auto Oqcd=history[0].node->nodeME()->orderInAlphaS();
if (!history[0].node->children().empty()) {
assert(Oqcd!=0);
}
res *= pow( SM().alphaEMME( Q_qed )/ SM().alphaEMMZ() , Oew );
res *= pow( (nocmw?as(Q_R):cmwAlphaS(Q_R)) / SM().alphaS() , Oqcd );
for ( auto const & hs : history )
if ( hs.node!= history.back().node ){
Energy q_i = DSH()->renFac()* hs.node->pT();
res *= cmwAlphaS(q_i) / SM().alphaS();
}
if ( std::isnan( res ) )
generator()->logWarning(Exception()
<< "Merger: alphaReweight is nan. "<< Exception::warning);
return res;
}
void Merger::fillHistory( Energy scale , NodePtr begin , NodePtr endNode ){
history.clear();
double sudakov0_n = 1.;
history.push_back( {begin , sudakov0_n , scale} );
double xiQSh = history.begin()->node->legsize() == N0()?
DSH()->hardScaleFactor():1.;
scale *= xiQSh;
if ( begin->parent()||!isUnitarized ) {
while ( begin->parent() && ( begin != endNode ) ) {
if ( !dosudakov( begin , scale , begin->pT() , sudakov0_n ) ){
history.push_back( { begin->parent() , 0. , scale } );
}
if ( std::isnan( sudakov0_n ) )
generator()->logWarning(Exception()
<< "Merger: sudakov"<<scale/GeV<<" "
<<begin->pT()/GeV<<"0_n is nan. "
<< Exception::warning);
scale = begin->pT();
history.push_back( { begin->parent() , sudakov0_n , begin->pT() } );
begin = begin->parent();
}
Energy notunirunning = scale;
if ( !isUnitarized&&N()+N0() > int( currentNode()->legsize() ) ) {
if ( !dosudakov( begin , notunirunning , mergePt() , sudakov0_n ) ){
history.back().weight = 0.;
}else{
history.back().weight = sudakov0_n;
}
}
}
if( history.size() == 1 )scale /= DSH()->hardScaleFactor();
}
double Merger::sumPdfReweightExpansion()const{
double res = 0.;
Energy beam1Scale = history[0].scale*
( history[0].node->legsize() == N0()?
currentME()->facFac():
DSH()->facFac() );
Energy beam2Scale = history[0].scale*
( history[0].node->legsize() == N0()?
currentME()->facFac():
DSH()->facFac() );
for ( auto const & hs : history ){
//pdf expansion only to the last step
if( !hs.node->parent() )continue;
if( hs.node->xcomb()->mePartonData()[0]->coloured()&&
hs.node->nodeME()->lastX1()>0.99 )return 0.;
if( hs.node->xcomb()->mePartonData()[1]->coloured()&&
hs.node->nodeME()->lastX2()>0.99 )return 0.;
if( hs.node->nodeME()->lastX1()<0.00001 )return 0.;
if( hs.node->nodeME()->lastX2()<0.00001 )return 0.;
if ( hs.node->dipole()->bornEmitter() == 0 ){
res += pdfExpansion( hs.node , 0 ,
beam1Scale ,
( hs.node->pT() ) ,
hs.node->nodeME()->lastX1() ,
Nf( history[0].scale ) ,
history[0].scale );
beam1Scale = ( hs.node->pT() )*DSH()->facFac();
}
else if ( hs.node->dipole()->bornEmitter() == 1 ){
res += pdfExpansion( hs.node , 1 ,
beam2Scale ,
( hs.node->pT() ) ,
hs.node->nodeME()->lastX2() ,
Nf( history[0].scale ) ,
history[0].scale );
beam2Scale = ( hs.node->pT() )*DSH()->facFac();
}
// if we're here we know hs.node->dipole()->bornEmitter() > 1
// works only in collinear scheme
else if ( hs.node->dipole()->bornSpectator() == 0 ){
res += pdfExpansion( hs.node , 0 ,
beam1Scale ,
( hs.node->pT() ) ,
hs.node->nodeME()->lastX1() ,
Nf( history[0].scale ) ,
history[0].scale );
beam1Scale = ( hs.node->pT() )*DSH()->facFac();
}
else if ( hs.node->dipole()->bornSpectator() == 1 ){
res += pdfExpansion( hs.node , 1 ,
beam2Scale ,
( hs.node->pT() ) ,
hs.node->nodeME()->lastX2() ,
Nf( history[0].scale ) ,
history[0].scale );
beam2Scale = ( hs.node->pT() )*DSH()->facFac();
}
}
if ( currentNode()->xcomb()->mePartonData()[0]->coloured() ){
res += pdfExpansion( history.back().node , 0 ,
beam1Scale ,
history[0].scale* currentME()->facFac() ,
( history.back() ).node->nodeME()->lastX1() ,
Nf( history[0].scale ) ,
history[0].scale );
}
if ( currentNode()->xcomb()->mePartonData()[1]->coloured() ) {
res += pdfExpansion( history.back().node , 1 ,
beam2Scale ,
history[0].scale* currentME()->facFac() ,
( history.back() ).node->nodeME()->lastX2() ,
Nf( history[0].scale ) ,
history[0].scale );
}
return res;
}
#include "Herwig/MatrixElement/Matchbox/Phasespace/RandomHelpers.h"
double Merger::pdfExpansion( NodePtr node ,
int side , Energy running ,
Energy next , double x ,
int nlp , Energy fixedScale ) const {
tcPDPtr particle , parton;
tcPDFPtr pdf;
if ( side == 0 ) {
particle = node->nodeME()->lastParticles().first->dataPtr();
parton = node->nodeME()->lastPartons().first->dataPtr();
pdf = node->xcomb()->partonBins().first->pdf();
}else{
assert( side == 1 );
particle = node->nodeME()->lastParticles().second->dataPtr();
parton = node->nodeME()->lastPartons().second->dataPtr();
pdf = node->xcomb()->partonBins().second->pdf();
}
//copied from PKOperator
double res = 0.;
int number = 10;
for ( int nr = 0;nr<number;nr++ ){
double restmp = 0;
using namespace RandomHelpers;
double r = UseRandom::rnd();
double eps = 1e-3;
pair<double , double> zw =
generate( ( piecewise() ,
flat( 0.0 , x ) ,
match( inverse( 0.0 , x , 1.0 ) +
inverse( 1.0+eps , x , 1.0 ) ) ) , r );
double z = zw.first;
double mapz = zw.second;
double PDFxparton = pdf->xfx( particle , parton , sqr( fixedScale ) , x )/x;
double CA = SM().Nc();
double CF = ( SM().Nc()*SM().Nc()-1.0 )/( 2.*SM().Nc() );
if ( abs( parton->id() ) < 7 ) {
double PDFxByzgluon = pdf->xfx( particle ,
getParticleData( ParticleID::g ) ,
sqr( fixedScale ) , x/z )*z/x;
double PDFxByzparton = pdf->xfx( particle , parton ,
sqr( fixedScale ) , x/z )*z/x;
assert( abs( parton->id() ) < 7 );
restmp += CF*( 3./2.+2.*log( 1.-x ) ) * PDFxparton;
if ( z > x ) {
restmp += 0.5 * ( sqr( z ) + sqr( 1.-z ) ) * PDFxByzgluon / z;
restmp += CF*2.*( PDFxByzparton - z*PDFxparton )/( z*( 1.-z ) );
restmp -= CF*PDFxByzparton * ( 1.+z )/z;
}
}else{
assert( parton->id() == ParticleID::g );
double PDFxByzgluon = pdf->xfx( particle ,
getParticleData( ParticleID::g ) ,
sqr( fixedScale ) , x/z )*z/x;
// Pqg
if ( z > x ){
double factor = CF * ( 1. + sqr( 1.-z ) ) / sqr( z );
for ( int f = -nlp; f <= nlp; ++f ) {
if ( f == 0 )
continue;
restmp += pdf->xfx( particle , getParticleData( f ) ,
sqr( fixedScale ) , x/z )*z/x*factor;
}
}
// Pgg
restmp += ( ( 11./6. ) * CA
- ( 1./3. )*Nf( history[0].scale )
+ 2.*CA*log( 1.-x ) ) *PDFxparton;
if ( z > x ) {
restmp += 2. * CA * ( PDFxByzgluon - z*PDFxparton ) / ( z*( 1.-z ) );
restmp += 2.* CA *( ( 1.-z )/z - 1. + z*( 1.-z ) ) * PDFxByzgluon / z;
}
}
if ( PDFxparton<1e-8 )
restmp = 0.;
else
res += 1*restmp*log( sqr( running/next ) )/PDFxparton*mapz;
}
return res/number;
}
double Merger::sumAlphaSReweightExpansion()const{
double res = 0.;
const auto Oqcd=history[0].node->nodeME()->orderInAlphaS();
res += alphasExpansion( history[0].scale* DSH()->renFac() ,
history[0].scale* currentME()->renFac() )*
Oqcd;
// dsig is calculated with fixed alpha_s
for ( auto const & hs : history ){
//expansion only to the last step
if( !hs.node->parent() )continue;
res += alphasExpansion( hs.node->pT()*DSH()->renFac() ,currentME()->renFac()*history[0].scale );
}
return res;
}
double Merger::sumFillHistoryExpansion(){
double res = 0.;
double xiQSh = history[0].node->legsize() == N0()?DSH()->hardScaleFactor():1.;
for ( auto const & hs : history ){
if( !hs.node->parent() )continue;
doHistExpansion( hs.node , ( hs.node == history[0].node?xiQSh:1. )*hs.scale ,
hs.node->pT() , history[0].scale , res );
}
return res;
}
MergingFactoryPtr Merger::treefactory()const{return theTreeFactory;}
void Merger::doinit(){
if ( !DSH()->hardScaleIsMuF() ) {
throw Exception()
<< "Merger: Merging is currently only sensible "
<< "if we are using the hardScale as MuF."
<< Exception::abortnow;
}
}
namespace{
void setXCombScales(StdXCombPtr xc,Energy2 scale){
xc->lastShowerScale ( scale );
xc->partonBinInstances().first->scale ( scale );
xc->partonBinInstances().second->scale ( scale );
}
}
CrossSection Merger::MergingDSigDR() {
history.clear();
assert(currentNode()==theFirstNodeMap[ currentME()]);
if(DSH()->doesSplitHardProcess()){
throw Exception()
<< "Merger: The splithardprocess option is currently not supported."
<< Exception::abortnow;
}
//get the PDF's (from ShowerHandler.cc)
if (!DSH()->getPDFA()||!DSH()->firstPDF().particle()){
tSubProPtr sub = currentNode()->xcomb()->construct();
const auto pb=currentNode()->xcomb()->partonBins();
tcPDFPtr first = DSH()->getPDFA() ?
tcPDFPtr(DSH()->getPDFA()) : DSH()->firstPDF().pdf();
tcPDFPtr second = DSH()->getPDFB() ?
tcPDFPtr(DSH()->getPDFB()) : DSH()->secondPDF().pdf();
DSH()->resetPDFs( {first,second },pb );
}
DSH()->eventHandler( generator()->eventHandler() );
CrossSection res = ZERO;
if( currentNode()->subtractedReal() ){
res = MergingDSigDRRealStandard();
theCurrentMaxLegs = maxLegsNLO();
}else if( currentNode()->virtualContribution() ){
res = MergingDSigDRVirtualStandard();
theCurrentMaxLegs = maxLegsNLO();
}else if( theGamma!= 1. ){
res = MergingDSigDRBornGamma();
theCurrentMaxLegs = maxLegsLO();
}else{
res = MergingDSigDRBornStandard();
theCurrentMaxLegs = maxLegsLO();
}
auto lxc= currentME()->lastXCombPtr();
setXCombScales(lxc,sqr( currentNode()->runningPt()));
auto lp= currentME()->lastXCombPtr()->lastProjector();
if( lp )
setXCombScales( lp, sqr( currentNode()->runningPt()));
if ( res == ZERO ){
history.clear();
return ZERO;
}
cleanup( currentNode() );
lxc->subProcess( SubProPtr() );
history.clear();
if( !std::isfinite( double( res/nanobarn ) ) ){
generator()->logWarning(Exception()
<< "Merger weight is " << res/nanobarn<< " -> setting to 0"
<< Exception::warning);
return ZERO;
}
return res;
}
#include "Herwig/PDF/HwRemDecayer.h"
void Merger::CKKW_PrepareSudakov( NodePtr node , Energy running ){
tSubProPtr sub = node->xcomb()->construct();
const auto pb=node->xcomb()->partonBins();
DSH()->setCurrentHandler();
DSH()->currentHandler()->generator()->currentEventHandler(currentNode()->xcomb()->eventHandlerPtr() );
DSH()->currentHandler()->remnantDecayer()->setHadronContent( currentNode()->xcomb()->lastParticles() );
DSH()->eventRecord().clear();
DSH()->eventRecord().slimprepare( sub , dynamic_ptr_cast<tStdXCombPtr>( node->xcomb() ) , DSH()->pdfs() ,
currentNode()->xcomb()->lastParticles(), DSH()->offShellPartons() );
DSH()->hardScales( sqr( running ) );
}
Energy Merger::CKKW_StartScale( NodePtr node ) const {
Energy res = generator()->maximumCMEnergy();
const int N=node->legsize();
const auto & data=node->nodeME()->mePartonData();
const auto & momenta=node->nodeME()->lastMEMomenta();
if( !node->children().empty() ){
for ( int i = 0; i<N ; i++ ){ if ( !data[i]->coloured() )continue;
for ( int j = 2; j<N ; j++ ){ if ( i == j||!data[j]->coloured() )continue;
for ( int k = 0; k<N ; k++ ){ if ( !data[k]->coloured() || i == k || j == k )continue;
if(i<2){
if(k<2) {
res = min( res , IILTK->lastPt( momenta[i] , momenta[j] , momenta[k] ));
}
else {
res = min( res ,
(data[k]->mass()+data[j]->mass()+data[i]->mass()>ZERO)?
IFMTK->lastPt( momenta[i] , momenta[j] , momenta[k] ):
IFLTK->lastPt( momenta[i] , momenta[j] , momenta[k] ));
}
}else{
if(k<2) {
res = min( res ,
(data[k]->mass()+data[j]->mass()+data[i]->mass()>ZERO)?
FIMTK->lastPt( momenta[i] , momenta[j] , momenta[k] ):
FILTK->lastPt( momenta[i] , momenta[j] , momenta[k] ));
}
else {
res = min( res ,
(data[k]->mass()+data[j]->mass()+data[i]->mass()>ZERO)?
FFMTK->lastPt( momenta[i] , momenta[j] , momenta[k] ):
FFLTK->lastPt( momenta[i] , momenta[j] , momenta[k] ));
}
}
}
}
}
}else{
node->nodeME()->factory()->scaleChoice()->setXComb( node->xcomb() );
res = sqrt( node->nodeME()->factory()->scaleChoice()->renormalizationScale() );
}
node->nodeME()->factory()->scaleChoice()->setXComb( node->xcomb() );
res = max( res , sqrt( node->nodeME()->factory()->scaleChoice()->renormalizationScale() ) );
return res;
}
double Merger::alphasExpansion( Energy next , Energy fixedScale ) const {
double betaZero = ( 11./6. )*SM().Nc() - ( 1./3. )*Nf( history[0].scale );
double K=3.*( 67./18.-1./6.*sqr(Constants::pi) ) -5./9.*Nf( history[0].scale);
return ( betaZero*log( sqr( fixedScale/next ) ) )+( theCMWScheme>0?K:0. );
}
double Merger::pdfratio( NodePtr node ,
Energy numerator_scale ,
Energy denominator_scale ,
int side ,
bool fromIsME,
bool toIsME ){
StdXCombPtr bXc = node->xcomb();
if( !bXc->mePartonData()[side]->coloured() )
throw Exception()
<< "Merger: pdf-ratio required for non-coloured particle."
<< Exception::abortnow;
double from = 1.;
double to = 1.;
if ( side == 0 ){
if ( denominator_scale == numerator_scale && fromIsME==toIsME ) {
return 1.;
}
if (fromIsME) {
from = node->nodeME()->pdf1( sqr( denominator_scale ) );
}else{
from = DSH()->firstPDF().xfx(node->xcomb()->lastPartons().first->dataPtr(),
sqr( denominator_scale ),
node->xcomb()->lastX1())/node->xcomb()->lastX1();
}
if (toIsME) {
to = node->nodeME()->pdf1( sqr( numerator_scale ) );
}else{
to = DSH()->firstPDF().xfx(node->xcomb()->lastPartons().first->dataPtr(),
sqr( numerator_scale ),
node->xcomb()->lastX1())/node->xcomb()->lastX1();
}
if ( ( to < 1e-8||from < 1e-8 )&&( to/from>10000000. ) ){
generator()->logWarning(Exception()
<< "Merger: pdfratio to = " << to << " from = " << from
<< Exception::warning);
return 0.;
}
}
else{
if ( denominator_scale == numerator_scale && fromIsME==toIsME ) {
return 1.;
}
if (fromIsME) {
from = node->nodeME()->pdf2( sqr( denominator_scale ) );
}else{
from =DSH()->secondPDF().xfx(node->xcomb()->lastPartons().second->dataPtr(),
sqr( denominator_scale ),
node->xcomb()->lastX2())/node->xcomb()->lastX2();
}
if (toIsME) {
to = node->nodeME()->pdf2( sqr( numerator_scale ) );
}else{
to = DSH()->secondPDF().xfx(node->xcomb()->lastPartons().second->dataPtr(),
sqr( numerator_scale ),
node->xcomb()->lastX2())/node->xcomb()->lastX2();
}
if ( ( to < 1e-8||from < 1e-8 )&&( to/from>10000000. ) ){
generator()->logWarning(Exception()
<< "Merger: pdfratio to = "
<< to << " from = " << from
<< Exception::warning);
return 0.;}
}
return to/from;
}
bool Merger::dosudakov( NodePtr node , Energy running , Energy next , double& sudakov0_n ) {
CKKW_PrepareSudakov( node , running );
for( DipoleChain const & chain : DSH()->eventRecord().chains() ){
for( Dipole const & dip : chain.dipoles() ){
sudakov0_n *= singlesudakov( dip , next , running , { true , false } );
sudakov0_n *= singlesudakov( dip , next , running , { false , true } );
if ( sudakov0_n == 0.0 ){
cleanup( node );
return false;
}
}
}
cleanup( node );
return true;
}
bool Merger::doHistExpansion( NodePtr node , Energy running , Energy next , Energy fixedScale , double& histExpansion ) {
CKKW_PrepareSudakov( node , running );
for( DipoleChain const & chain : DSH()->eventRecord().chains() ){
for( Dipole const & dip : chain.dipoles() ){
histExpansion += singleHistExpansion( dip , next , running , fixedScale , { true , false } );;
histExpansion += singleHistExpansion( dip , next , running , fixedScale , { false , true } );
}
}
cleanup( node );
return true;
}
bool Merger::isProjectorStage( NodePtr node , int pjs )const{
return ( pjs == int( ( currentNode()->legsize() - node->legsize() ) ) );
}
void Merger::cleanup( NodePtr node ) {
DSH()->eventRecord().clear();
if( !node->xcomb()->subProcess() )return;
ParticleVector vecfirst = node->xcomb()->subProcess()->incoming().first->children();
for( auto const & particle : vecfirst )
node->xcomb()->subProcess()->incoming().first->abandonChild( particle );
ParticleVector vecsecond = node->xcomb()->subProcess()->incoming().second->children();
for( auto const & particle : vecsecond )
node->xcomb()->subProcess()->incoming().second->abandonChild( particle );
node->xcomb()->subProcess( SubProPtr() );
}
double Merger::singlesudakov( Dipole dip , Energy next , Energy running , pair<bool , bool> conf ){
double res = 1.;
tPPtr emitter = dip.emitter( conf );
tPPtr spectator = dip.spectator( conf );
DipoleSplittingInfo candidate( dip.index( conf ) , conf ,
dip.emitterX( conf ) ,
dip.spectatorX( conf ) ,
emitter , spectator );
if ( DSH()->generators().find( candidate.index() ) == DSH()->generators().end() ) DSH()->getGenerators( candidate.index() );
auto const & gens = DSH()->generators().equal_range( candidate.index() );
for ( auto gen = gens.first; gen != gens.second; ++gen ) {
if ( !( gen->first == candidate.index() ) )
continue;
Energy dScale = gen->second->splittingKinematics()->dipoleScale( emitter->momentum() , spectator->momentum() );
candidate.scale( dScale );
candidate.continuesEvolving();
- Energy ptMax = gen->second->splittingKinematics()->ptMax( candidate.scale() , candidate.emitterX() , candidate.spectatorX() ,
- candidate.index() , *gen->second->splittingKernel() );
+
+ Energy ptMax = gen->second->splittingKinematics()->ptMax(
+ candidate.scale() ,
+ candidate.emitterX() ,
+ candidate.spectatorX() ,
+ candidate ,
+ *gen->second->splittingKernel() );
candidate.hardPt( min( running , ptMax ) );
if ( candidate.hardPt()>next ){
res *= gen->second->sudakov( candidate , next );
}
}
return res;
}
double Merger::singleHistExpansion( Dipole dip , Energy next , Energy running , Energy fixedScale , pair<bool , bool> conf ){
double res = 0.;
tPPtr emitter = dip.emitter( conf );
tPPtr spectator = dip.spectator( conf );
DipoleSplittingInfo candidate( dip.index( conf ) ,
conf , dip.emitterX( conf ) ,
dip.spectatorX( conf ) ,
emitter , spectator );
if ( DSH()->generators().find( candidate.index() ) ==
DSH()->generators().end() )
DSH()->getGenerators( candidate.index() );
auto const & gens = DSH()->generators().equal_range( candidate.index() );
for ( auto gen = gens.first; gen != gens.second; ++gen ) {
if ( !( gen->first == candidate.index() ) )
continue;
Energy dScale = gen->second->splittingKinematics()->dipoleScale(
emitter->momentum() , spectator->momentum() );
candidate.scale( dScale );
candidate.continuesEvolving();
Energy ptMax = gen->second->
splittingKinematics()->ptMax(
candidate.scale() , candidate.emitterX() ,
candidate.spectatorX() , candidate.index() ,
*gen->second->splittingKernel() );
candidate.hardPt( min( running , ptMax ) );
if ( candidate.hardPt()>next ){
res += gen->second->sudakovExpansion( candidate , next , fixedScale );
}
}
return res;
}
void Merger::firstNodeMap( MatchboxMEBasePtr a , NodePtr b ){
theFirstNodeMap.insert( { a , b } );
}
map<MatchboxMEBasePtr , NodePtr> Merger::firstNodeMap()const{return theFirstNodeMap;}
void Merger::setXComb( tStdXCombPtr xc ){
currentNode()->setXComb( xc );
}
void Merger::setKinematics( ){
currentNode()->setKinematics();
}
void Merger::clearKinematics( ){
currentNode()->clearKinematics();
}
void Merger::flushCaches(){
if (currentNode()&¤tNode()->xcomb()->lastParticles().first) {
currentNode()->flushCaches();
}
}
bool Merger::generateKinematics( const double * r ){
return currentNode()->firstgenerateKinematics( r , ! currentNode()->subtractedReal() );
}
bool Merger::matrixElementRegion( PVector incoming , PVector outgoing , Energy winnerScale , Energy cutscale )const{
Energy ptx = Constants::MaxEnergy;
bool foundwinnerpt = false;
using namespace boost;
//FF
for( auto const & em : outgoing ){ if ( ! em->coloured() ) continue;
for( auto const & emm : outgoing ){ if ( !emm->coloured() ) continue; if ( em == emm ) continue;
for( auto const & spe : outgoing ){ if ( !spe->coloured() ) continue; if ( em == spe||emm == spe ) continue;
if ( !( em->id() == -emm->id()||emm->id()>6 ) )continue;
Energy pt = ZERO;
if ( em->momentum().m()<= 10_MeV &&
emm->momentum().m()<= 10_MeV &&
spe->momentum().m()<= 10_MeV ) {
pt = FFLTK->lastPt( em->momentum() , emm->momentum() , spe->momentum() );
}else{
pt = FFMTK->lastPt( em->momentum() , emm->momentum() , spe->momentum() );
}
if ( abs( pt-winnerScale ) < 10_MeV ) {
foundwinnerpt = true;
}
ptx = min( ptx , pt );
}
}
}
//FI
for( auto const & spe : incoming ){ if ( ! spe->coloured() ) continue;
for( auto const & emm : outgoing ){ if ( ! emm->coloured() ) continue;
for( auto const & em : outgoing ){ if ( ! em->coloured() ) continue; if ( em == emm ) continue;
if ( !( em->id() == -emm->id() || emm->id()>6 ) )continue;
Energy pt = ZERO;
if ( em->momentum().m()<= 10_MeV &&
emm->momentum().m()<= 10_MeV &&
spe->momentum().m()<= 10_MeV ) {
pt = FILTK->lastPt( em->momentum() , emm->momentum() , spe->momentum() );
}else{
pt = FIMTK->lastPt( em->momentum() , emm->momentum() , spe->momentum() );
}
if ( abs( pt-winnerScale )<10_MeV ) {
foundwinnerpt = true;
}
if( pt > ZERO )
ptx = min( ptx , pt );
}
}
}
//IF
for( auto const & em : incoming ){ if ( ! em->coloured() ) continue;
for( auto const & emm : outgoing ){ if ( ! emm->coloured() ) continue;
for( auto const & spe : outgoing ){ if ( ! spe->coloured() ) continue; if ( emm == spe ) continue;
if ( !( em->id()>6|| em->id() == emm->id() ||emm->id()>6 ) )continue;
Energy pt = ZERO;
if ( em->momentum().m()<= 10_MeV &&
emm->momentum().m()<= 10_MeV &&
spe->momentum().m()<= 10_MeV ) {
//massless
pt = IFLTK->lastPt( em->momentum() , emm->momentum() , spe->momentum() );
}else{
//massiv
pt = IFMTK->lastPt( em->momentum() , emm->momentum() , spe->momentum() );
}
if ( abs( pt-winnerScale )< 10_MeV ) {
foundwinnerpt = true;
}
ptx = min( ptx , pt );
}
}
}
//II
for( auto const & em : incoming ){ if ( ! em->coloured() ) continue;
for( auto const & spe : incoming ){ if ( ! spe->coloured() ) continue; if ( em == spe ) continue;
for( auto const & emm : outgoing ){ if ( ! emm->coloured() ) continue;
if ( !( em->id()>6||em->id() == emm->id() ||emm->id()>6 ) )continue;
Energy pt = IILTK->lastPt( em->momentum() , emm->momentum() , spe->momentum() );
if ( abs( pt-winnerScale )< 10_MeV ) {
foundwinnerpt = true;
}
ptx = min( ptx , pt );
}
}
}
if( !foundwinnerpt ){
generator()->logWarning( Exception()
<< "Merger: Could not find winner with pt."
<< "Run with -d3 to get phase space points. "
<< Exception::warning );
if( Debug::level > 2 ) {
generator()->log() << "\nWarning: could not find winner with pt: " << winnerScale/GeV;
for( auto const & emm : incoming ){
generator()->log() << "\n" << emm->id() << " " << emm->momentum()/GeV << " " << emm->momentum().m()/GeV << flush;
}
for( auto const & emm : outgoing ){
generator()->log() <<"\n" << emm->id() << " " << emm->momentum()/GeV << " " << emm->momentum().m()/GeV << flush;
}
}
}
return ( ptx>cutscale ) ;
}
bool Merger::notOnlyMulti() const {
return ( treefactory()->onlymulti() != -1&&
treefactory()->onlymulti() !=
int( currentNode()->legsize()-( projected ? 1 : 0 ) ) );
}
int Merger::M()const{return theTreeFactory->M();}
int Merger::N()const{return theTreeFactory->N();}
void Merger::debugVirt(double weight,double w1,double w2,double w3,
CrossSection matrixElement,double ww1,double ww2,
double ww3, NodePtr node,CrossSection bornWeight)const{
Energy minPT = Constants::MaxEnergy;
for( auto const & no :currentNode()->children() )minPT = min( no->pT() , minPT );
generator()->log() << "\nVIRT " << minPT/GeV << " " << weight << " " << w1;
generator()->log() << " " << w2;
generator()->log() << " " << w3;
generator()->log() << " " << ( matrixElement/nanobarn ) << " " << ww1 << " " << ww2 << " " << ww3 << " " << node->pT()/GeV << " " << node->nodeME()->mePartonData()[3]->mass()/GeV << " " << ( bornWeight*SM().alphaS()/( 2.*ThePEG::Constants::pi )/nanobarn );
}
void Merger::debugReal(string realstr, double weight,
CrossSection me, CrossSection dip)const {
Energy minPT = Constants::MaxEnergy;
for( auto const & no :currentNode()->children() )minPT = min( no->pT() , minPT );
generator()->log() << "\n"<<realstr <<" "<< minPT/GeV << " " << weight << " " << ( me-dip )/nanobarn << " " << me/nanobarn << " " << dip/nanobarn;
}
// If needed , insert default implementations of virtual function defined
// in the InterfacedBase class here ( using ThePEG-interfaced-impl in Emacs ).
#include "ThePEG/Persistency/PersistentOStream.h"
void Merger::persistentOutput( PersistentOStream & os ) const {
os << theShowerExpansionWeights << theCMWScheme << projected <<
isUnitarized << isNLOUnitarized <<
theOpenZBoundaries << theChooseHistory <<
theN0 << theOnlyN << weight <<
theGamma << theSmearing << ounit( theIRSafePT , GeV ) <<
ounit( theMergePt , GeV ) << ounit( theCentralMergePt , GeV )
<< theLargeNBasis << FFLTK << FILTK <<
IFLTK << IILTK << FFMTK << FIMTK << IFMTK <<
theDipoleShowerHandler << theTreeFactory <<
theFirstNodeMap<<theRealSubtractionRatio << emitDipoleMEDiff;
}
#include "ThePEG/Persistency/PersistentIStream.h"
void Merger::persistentInput( PersistentIStream & is , int ) {
is >> theShowerExpansionWeights >> theCMWScheme >> projected >>
isUnitarized >> isNLOUnitarized >>
theOpenZBoundaries >>
theChooseHistory >> theN0 >> theOnlyN >>
weight >>
theGamma >> theSmearing >> iunit( theIRSafePT , GeV ) >>
iunit( theMergePt , GeV ) >>
iunit( theCentralMergePt , GeV ) >> theLargeNBasis >>
FFLTK >> FILTK >> IFLTK >>
IILTK >> FFMTK >> FIMTK >>
IFMTK >> theDipoleShowerHandler >> theTreeFactory >>
theFirstNodeMap >> theRealSubtractionRatio >> emitDipoleMEDiff;
}
// *** Attention *** The following static variable is needed for the type
// description system in ThePEG. Please check that the template arguments
// are correct ( the class and its base class ) , and that the constructor
// arguments are correct ( the class name and the name of the dynamically
// loadable library where the class implementation can be found ).
#include "ThePEG/Utilities/DescribeClass.h"
DescribeClass<Merger , Herwig::MergerBase>
describeHerwigMerger( "Herwig::Merger" , "HwDipoleShower.so" );
//ClassDescription<Merger> Merger::initMerger;
// Definition of the static class description member.
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/Switch.h"
void Merger::Init() {
static ClassDocumentation<Merger> documentation
( "The Merger class takes care of merging multiple LO & NLO cross sections." );
//////////////////////////////////////////////////
static Switch<Merger , unsigned int>
interfaceShowerExpansionWeights
( "ShowerExpansionWeights" ,
"Calculate the expansions of the shower history to be NLO accurate, in different schemes." ,
&Merger::theShowerExpansionWeights ,
3 , false , false );
static SwitchOption
interfaceShowerExpansionWeightsScheme0
( interfaceShowerExpansionWeights ,
"NoWeights" ,
"Switch off the expansion." ,
0 );
static SwitchOption
interfaceShowerExpansionWeightsScheme1
( interfaceShowerExpansionWeights ,
"FlatAndHistoryReweighted" ,
"Sum alphaS expansion and weight with same Historyweight as LO." ,
1 );
static SwitchOption
interfaceShowerExpansionWeightsScheme2
( interfaceShowerExpansionWeights ,
"NoAlphaSReweightForSudakovExpansion" ,
"Switch off the expansion." ,
2 );
static SwitchOption
interfaceShowerExpansionWeightsScheme3
( interfaceShowerExpansionWeights ,
"NoAlphaSReweightForAllExpansions" ,
"Switch off the expansion." ,
3 );
static SwitchOption
interfaceShowerExpansionWeightsScheme4
( interfaceShowerExpansionWeights ,
"NoAlphaSReweightForAlphaSExpansion" ,
"Switch off the expansion." ,
4 );
/////////////////////////////////////////////////////////////////////7
static Switch<Merger , unsigned int>
interfacetheCMWScheme
( "CMWScheme" ,
"Use CMW-Scheme to calculate the alpha_s for the shower expressions." ,
&Merger::theCMWScheme ,
0 ,
false , false );
static SwitchOption interfacetheCMWSchemeNo
(interfacetheCMWScheme,
"No",
"No CMW-Scheme",
0);
static SwitchOption interfacetheCMWSchemeLinear
(interfacetheCMWScheme,
"Linear",
"Linear CMW multiplication: alpha_s(q) -> alpha_s(q)(1+K_g*alpha_s(q)/2pi )",
1);
static SwitchOption interfacetheCMWSchemeFactor
(interfacetheCMWScheme,
"Factor",
"Use factor in alpha_s argument: alpha_s(q) -> alpha_s(fac*q) with fac=exp(-(67-3pi^2-10/3*Nf)/(33-2Nf)) ",
2);
static Parameter<Merger , Energy> interfaceMergerScale
( "MergingScale" , "The MergingScale." ,
&Merger::theCentralMergePt ,
GeV , 20.0*GeV , 0.0*GeV , 0*GeV ,
false , false , Interface::lowerlim );
static Parameter<Merger , double> interfacegamma
( "gamma" ,
"gamma parameter." ,
&Merger::theGamma , 1.0 , 0.0 , 0 ,
false , false , Interface::lowerlim );
interfacegamma.rank(-1);
static Switch<Merger,int> interfaceOpenZBoundariesM
("OpenZBoundaries", "",
&Merger::theOpenZBoundaries, 0, false, false);
static SwitchOption interfaceOpenZBoundariesMhardScale
(interfaceOpenZBoundariesM, "Hard", "", 0);
static SwitchOption interfaceOpenZBoundariesMfull
(interfaceOpenZBoundariesM, "Full", "", 1);
static SwitchOption interfaceOpenZBoundariesMDipoleScale
(interfaceOpenZBoundariesM, "DipoleScale", "", 2);
static Switch<Merger , bool>
interfaceemitDipoleMEDiff
( "emitDipoleMEDiff" ,
"Allow emissions of the unitarisation contribution with prob. 1-min(B_n/sum Dip_n,sum Dip_n/B_n)" ,
&Merger::emitDipoleMEDiff , false , false , false );
static SwitchOption interfaceemitDipoleMEDiffYes
( interfaceemitDipoleMEDiff , "Yes" , "" , true );
static SwitchOption interfaceemitDipoleMEDiffNo
( interfaceemitDipoleMEDiff , "No" , "" , false );
interfaceemitDipoleMEDiff.rank(-1);
static Parameter<Merger , Energy> interfaceIRSafePT
( "IRSafePT" ,
"Set the pt for which a matrixelement should be treated as IR-safe." ,
&Merger::theIRSafePT ,
GeV , 0.0 * GeV , ZERO , Constants::MaxEnergy ,
true , false , Interface::limited );
interfaceIRSafePT.setHasDefault( false );
static Parameter<Merger , double> interfacemergePtsmearing(
"MergingScaleSmearing" ,
"Set the percentage the merging pt should be smeared." ,
&Merger::theSmearing ,
0. , 0. , 0.0 , 0.5 ,
true , false , Interface::limited );
static Parameter<Merger , int> interfacechooseHistory(
"chooseHistory" ,
"Various ways of choosing the history weights: 0(default):dipole xs, 1:dipole/born, 2:flat, 3: 1/pt_dip" ,
&Merger::theChooseHistory ,
3 , -1 , 0 ,
false , false , Interface::lowerlim );
static Parameter<Merger , double> interfacetheRealSubtractionRatio(
"RealSubtractionRatio" ,
"If the pt of the Dipole divided by the merging scale is lower than the ratio, the dipole is used to subtract the real emission. Otherwise the shower approximation is used, " ,
&Merger::theRealSubtractionRatio , 0. , 0. ,
1. , 10.0 ,
true , false , Interface::limited );
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Tue, Nov 19, 9:07 PM (1 d, 24 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3806203
Default Alt Text
(61 KB)
Attached To
rHERWIGHG herwighg
Event Timeline
Log In to Comment