Page MenuHomeHEPForge

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/.hgignore b/.hgignore
--- a/.hgignore
+++ b/.hgignore
@@ -1,98 +1,99 @@
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$
^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/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-scratch$
^src/tests/.*\.(time|mult|Bmult|chisq)$
^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/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.py$
^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/Matchbox/done-all-links$
^src/snippets/done-all-links$
^Utilities/XML/xml_test$
^Utilities/utilities_test$
+^Utilities/versionstring.h$
test\.(log|trs)$
test-suite\.log$
^Config/test-driver$
diff --git a/Analysis/LEPFourJetsAnalysis.h b/Analysis/LEPFourJetsAnalysis.h
--- a/Analysis/LEPFourJetsAnalysis.h
+++ b/Analysis/LEPFourJetsAnalysis.h
@@ -1,265 +1,265 @@
// -*- C++ -*-
//
// LEPFourJetsAnalysis.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_LEPFourJetsAnalysis_H
#define HERWIG_LEPFourJetsAnalysis_H
//
// This is the declaration of the LEPFourJetsAnalysis class.
//
#include "ThePEG/Handlers/AnalysisHandler.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Vectors/Lorentz5Vector.h"
#include "Herwig/Utilities/Histogram.h"
#include "ThePEG/Repository/CurrentGenerator.h"
namespace Herwig {
using namespace ThePEG;
/** \ingroup Analysis
* The LEPFourJetsAnalysis class performs analysis for four jet angles and
* compares them to LEP data.
*
* @see \ref LEPFourJetsAnalysisInterfaces "The interfaces"
* defined for LEPFourJetsAnalysis.
*/
class LEPFourJetsAnalysis: public AnalysisHandler {
public:
/**
* Default constructor
*/
LEPFourJetsAnalysis ()
: _ca34(), _cchiBZ(), _cphiKSW(), _cthNR(),
_charged(true) {}
public:
/** @name Virtual functions required by the AnalysisHandler class. */
//@{
/**
* Analyze a given Event. Note that a fully generated event
* may be presented several times, if it has been manipulated in
* between. The default version of this function will call transform
* to make a lorentz transformation of the whole event, then extract
* all final state particles and call analyze(tPVector) of this
* analysis object and those of all associated analysis objects. The
* default version will not, however, do anything on events which
* have not been fully generated, or have been manipulated in any
* way.
* @param event pointer to the Event to be analyzed.
* @param ieve the event number.
* @param loop the number of times this event has been presented.
* If negative the event is now fully generated.
* @param state a number different from zero if the event has been
* manipulated in some way since it was last presented.
*/
virtual void analyze(tEventPtr event, long ieve, int loop, int state);
//@}
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 compute the four jet angles, assumes the jets are energy ordered
*/
//@{
/**
* Compute \f$\cos\chi_{BZ}\f$
*/
double cosChiBZ(vector<Lorentz5Momentum> p) {
if (p.size() == 4) {
ThreeVector<Energy2> v1 = p[0].vect().cross(p[1].vect());
ThreeVector<Energy2> v2 = p[2].vect().cross(p[3].vect());
return cos(v1.angle(v2));
}
else return 123;
}
/**
* Compute \f$\cos\Phi_{KSW}\f$.
*/
double cosPhiKSW(vector<Lorentz5Momentum> p) {
if (p.size() == 4) {
ThreeVector<Energy2> v1 = p[0].vect().cross(p[3].vect());
ThreeVector<Energy2> v2 = p[1].vect().cross(p[2].vect());
double alpha1 = v1.angle(v2);
v1 = p[0].vect().cross(p[2].vect());
v2 = p[1].vect().cross(p[3].vect());
double alpha2 = v1.angle(v2);
return cos((alpha1+alpha2)/2.);
}
else return 123;
}
/**
* Compute \f$\cos\Theta_{NR}\f$
*/
double cosThetaNR(vector<Lorentz5Momentum> p) {
if (p.size() == 4) {
ThreeVector<Energy> v1 = p[0].vect() - p[1].vect();
ThreeVector<Energy> v2 = p[2].vect() - p[3].vect();
return cos(v1.angle(v2));
}
else return 123;
}
/**
* Compute \f$\cos\alpha_{34}\f$
*/
double cosAlpha34(std::vector<Lorentz5Momentum> p) {
if (p.size() == 4)
return cos(p[2].vect().angle(p[3].vect()));
else
return 123;
}
//@}
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. Called in the run phase just before
* a run begins.
*/
virtual void doinitrun();
/**
* Finalize this object. Called in the run phase just after a
* run has ended. Used eg. to write out statistics.
*/
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<LEPFourJetsAnalysis> initLEPFourJetsAnalysis;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
LEPFourJetsAnalysis & operator=(const LEPFourJetsAnalysis &);
private:
/**
* Histogram for the \f$\cos\alpha_{34}\f$ distribution
*/
HistogramPtr _ca34;
/**
* Histogram for the \f$\cos\chi_{BZ}\f$ distribution
*/
HistogramPtr _cchiBZ;
/**
* Histogram for the \f$\cos\Phi_{KSW}\f$ distribution
*/
HistogramPtr _cphiKSW;
/**
* Histogram for the \f$\cos\Theta_{NR}\f$ distribution
*/
HistogramPtr _cthNR;
/**
* Use charged particles only
*/
bool _charged;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of LEPFourJetsAnalysis. */
template <>
struct BaseClassTrait<Herwig::LEPFourJetsAnalysis,1> {
/** Typedef of the first base class of LEPFourJetsAnalysis. */
typedef AnalysisHandler NthBase;
};
/** This template specialization informs ThePEG about the name of
* the LEPFourJetsAnalysis class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::LEPFourJetsAnalysis>
: public ClassTraitsBase<Herwig::LEPFourJetsAnalysis> {
/** Return a platform-independent class name */
static string className() { return "Herwig::LEPFourJetsAnalysis"; }
/** Return the name(s) of the shared library (or libraries) be loaded to get
* access to the LEPFourJetsAnalysis class and any other class on which it depends
* (except the base class). */
- static string library() { return "libfastjet.so HwLEPJetAnalysis.so"; }
+ static string library() { return "HwLEPJetAnalysis.so"; }
};
/** @endcond */
}
#endif /* HERWIG_LEPFourJetsAnalysis_H */
diff --git a/Analysis/LEPJetAnalysis.h b/Analysis/LEPJetAnalysis.h
--- a/Analysis/LEPJetAnalysis.h
+++ b/Analysis/LEPJetAnalysis.h
@@ -1,282 +1,282 @@
// -*- C++ -*-
//
// LEPJetAnalysis.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_LEPJetAnalysis_H
#define HERWIG_LEPJetAnalysis_H
//
// This is the declaration of the LEPJetAnalysis class.
//
#include "ThePEG/Handlers/AnalysisHandler.h"
#include "Herwig/Utilities/Histogram.h"
namespace Herwig {
using namespace ThePEG;
/** \ingroup Analysis
* The LEPJetAnalysis class compares the results of Heriwg++ with LEP data for
* various jet distributions.
*
* @see \ref LEPJetAnalysisInterfaces "The interfaces"
* defined for LEPJetAnalysis.
*/
class LEPJetAnalysis: public AnalysisHandler {
public:
/// Default constructor
LEPJetAnalysis() : _nevent() {}
/** @name Virtual functions required by the AnalysisHandler class. */
//@{
/**
* Analyze a given Event. Note that a fully generated event
* may be presented several times, if it has been manipulated in
* between. The default version of this function will call transform
* to make a lorentz transformation of the whole event, then extract
* all final state particles and call analyze(tPVector) of this
* analysis object and those of all associated analysis objects. The
* default version will not, however, do anything on events which
* have not been fully generated, or have been manipulated in any
* way.
* @param event pointer to the Event to be analyzed.
* @param ieve the event number.
* @param loop the number of times this event has been presented.
* If negative the event is now fully generated.
* @param state a number different from zero if the event has been
* manipulated in some way since it was last presented.
*/
virtual void analyze(tEventPtr event, long ieve, int loop, int state);
//@}
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.
*/
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. Called in the run phase just before
* a run begins.
*/
virtual void doinitrun();
/**
* Finalize this object. Called in the run phase just after a
* run has ended. Used eg. to write out statistics.
*/
virtual void dofinish();
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is an concrete class without persistent data.
*/
static NoPIOClassDescription<LEPJetAnalysis> initLEPJetAnalysis;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
LEPJetAnalysis & operator=(const LEPJetAnalysis &);
private:
/**
* Histograms ofr the \f$y\f$ distributions
*/
//@{
/**
* \f$y_{23}\f$
*/
HistogramPtr _y23;
/**
* \f$y_{34}\f$
*/
HistogramPtr _y34;
/**
* \f$y_{45}\f$
*/
HistogramPtr _y45;
/**
* \f$y_{56}\f$
*/
HistogramPtr _y56;
//@}
/**
* Bins for the y fractions
*/
vector<double> _yc_frac;
/**
* Points for the y fractions
*/
//@{
/**
* 1 jet
*/
vector<int> _frac1;
/**
* 2 jet
*/
vector<int> _frac2;
/**
* 3 jet
*/
vector<int> _frac3;
/**
* 4 jet
*/
vector<int> _frac4;
/**
* 5 jet
*/
vector<int> _frac5;
/**
* 6 jet
*/
vector<int> _frac6;
//@}
/**
* Number of events analysed
*/
unsigned int _nevent;
/**
* N jet distribution
*/
vector<Statistic> _njet;
/**
* For different jet rates
*/
//@{
/**
* Differential two jet rate
*/
vector<double> _d2dbins;
/**
* Differential three jet rate
*/
vector<double> _d3dbins;
/**
* Differential four jet rate
*/
vector<double> _d4dbins;
/**
* differential 2->2
*/
vector<int> _d2dN2;
/**
* differential 3->2
*/
vector<int> _d3dN2;
/**
* differential 3->2
*/
vector<int> _d3dN3;
/**
* differential 4->2
*/
vector<int> _d4dN2;
/**
* differential 4->3
*/
vector<int> _d4dN3;
/**
* differential 4->4
*/
vector<int> _d4dN4;
//@}
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of LEPJetAnalysis. */
template <>
struct BaseClassTrait<Herwig::LEPJetAnalysis,1> {
/** Typedef of the first base class of LEPJetAnalysis. */
typedef AnalysisHandler NthBase;
};
/** This template specialization informs ThePEG about the name of
* the LEPJetAnalysis class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::LEPJetAnalysis>
: public ClassTraitsBase<Herwig::LEPJetAnalysis> {
/** Return a platform-independent class name */
static string className() { return "Herwig::LEPJetAnalysis"; }
/**
* The name of a file containing the dynamic library where the class
* LEPJetAnalysis is implemented. It may also include several, space-separated,
* libraries if the class LEPJetAnalysis 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 "libfastjet.so HwLEPJetAnalysis.so"; }
+ static string library() { return "HwLEPJetAnalysis.so"; }
};
/** @endcond */
}
#endif /* HERWIG_LEPJetAnalysis_H */
diff --git a/Contrib/Makefile.am b/Contrib/Makefile.am
--- a/Contrib/Makefile.am
+++ b/Contrib/Makefile.am
@@ -1,19 +1,20 @@
EXTRA_DIST = \
AcerDetInterface \
AlpGen \
Analysis2 \
AnomalousHVV \
DecayAnalysis \
+FxFx \
HiggsPair \
HiggsPairOL \
LeptonME \
PGSInterface \
RadiativeZPrime \
TauAnalysis \
MultiWeight
dist-hook:
rm -rf `find $(distdir) -name '.svn' -or -name 'Makefile' -or -name '.hg'`
all:
bash make_makefiles.sh
diff --git a/Contrib/make_makefiles.sh.in b/Contrib/make_makefiles.sh.in
--- a/Contrib/make_makefiles.sh.in
+++ b/Contrib/make_makefiles.sh.in
@@ -1,42 +1,42 @@
#!/bin/bash
# script to put the HERWIG and THEPEG paths into the simple makefiles,
# for everything else the user is on their own!
# loop over all the files
OPENLOOPSPREFIX="@OPENLOOPSPREFIX@"
THEPEGINCLUDE="@THEPEGINCLUDE@"
GSLINCLUDE="@GSLINCLUDE@"
FASTJETINCLUDE="@FASTJETINCLUDE@"
HERWIGINCLUDE=-I@prefix@/include/
HERWIGINSTALL="@prefix@"
FC="@FC@"
FCLIBS="@FCLIBS@"
CXX="@CXX@"
CXXFLAGS="@CXXFLAGS@"
LDFLAGS="@LDFLAGS@"
-SHARED_FLAG="@SHARED_FLAG@"
+SHARED_FLAG="@SHARED_FLAG@ @APPLE_DSO_FLAGS@"
for i in *
do
# if a directory
if [ -d $i ]; then
# check input files exists
file=$i/Makefile.in
if [ -e $file ]; then
file2=`echo $file | sed s!\.in!!`
echo 'Making ' $file2
sed "s!THEPEGINCLUDE *\=!THEPEGINCLUDE=$THEPEGINCLUDE!" < $file | \
sed "s!OPENLOOPSPREFIX *\=!OPENLOOPSPREFIX=$OPENLOOPSPREFIX!" | \
sed "s!FC *\=!FC=$FC!" | \
sed "s!FCLIBS *\=!FCLIBS=$FCLIBS!" | \
sed "s!CXX *\=!CXX=$CXX!" | \
sed "s!SHARED_FLAG *\=!SHARED_FLAG=$SHARED_FLAG!" | \
sed "s!LDFLAGS *\=!LDFLAGS=$LDFLAGS!" | \
sed "s!CXXFLAGS *\=!CXXFLAGS=$CXXFLAGS!" | \
sed "s!HERWIGINCLUDE *\=!HERWIGINCLUDE=$HERWIGINCLUDE!" | \
sed "s!HERWIGINSTALL *\=!HERWIGINSTALL=$HERWIGINSTALL!" | \
sed "s!GSLINCLUDE *\=!GSLINCLUDE=$GSLINCLUDE!" | \
sed "s!FASTJETINCLUDE *\=!FASTJETINCLUDE=$FASTJETINCLUDE!" > $file2
fi
fi
done
diff --git a/DipoleShower/AlphaS/nlo_alpha_s.cc b/DipoleShower/AlphaS/nlo_alpha_s.cc
--- a/DipoleShower/AlphaS/nlo_alpha_s.cc
+++ b/DipoleShower/AlphaS/nlo_alpha_s.cc
@@ -1,111 +1,135 @@
// -*- C++ -*-
// couplings/nlo_alpha_s.cc is part of matchbox
// (C) 2008 Simon Platzer -- sp@particle.uni-karlsruhe.de
#include "nlo_alpha_s.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace matchbox;
nlo_alpha_s::nlo_alpha_s()
- : alpha_s(), freezing_scale_(1.*GeV), exact_evaluation_(true) {
+ : alpha_s(), freezing_scale_(1.*GeV),
+ exact_evaluation_(true), two_largeq_terms_(true) {
}
nlo_alpha_s::~nlo_alpha_s() {}
IBPtr nlo_alpha_s::clone() const {
return new_ptr(*this);
}
IBPtr nlo_alpha_s::fullclone() const {
return new_ptr(*this);
}
void nlo_alpha_s::persistentOutput(PersistentOStream & os) const {
- os << ounit(freezing_scale_,GeV) << exact_evaluation_;
+ os << ounit(freezing_scale_,GeV) << exact_evaluation_
+ << two_largeq_terms_;
}
void nlo_alpha_s::persistentInput(PersistentIStream & is, int) {
- is >> iunit(freezing_scale_,GeV) >> exact_evaluation_;
+ is >> iunit(freezing_scale_,GeV) >> exact_evaluation_
+ >> two_largeq_terms_;
}
ClassDescription<nlo_alpha_s> nlo_alpha_s::initnlo_alpha_s;
// Definition of the static class description member.
void nlo_alpha_s::Init() {
static ClassDocumentation<nlo_alpha_s> documentation
("NLO running alpha_s");
static Parameter<nlo_alpha_s,Energy> interfacefreezing_scale
("freezing_scale",
"Freeze alpha_s below given scale",
&nlo_alpha_s::freezing_scale_, GeV, 1.0*GeV, 0.0*GeV, 0*GeV,
true, false, Interface::lowerlim);
static Switch<nlo_alpha_s,bool> interfaceexact_evaluation
("exact_evaluation",
"Wether to exactly evaluate the running or use running for large scales",
&nlo_alpha_s::exact_evaluation_, true, true, false);
static SwitchOption interfaceexact_evaluationexact
(interfaceexact_evaluation,
"exact",
"Perform exact evaluation",
true);
static SwitchOption interfaceexact_evaluationlarge_scale
(interfaceexact_evaluation,
"large_scale",
"Perform approximate evaluation for large scales",
false);
+ static Switch<nlo_alpha_s,bool> interfacetwo_largeq_terms
+ ("two_largeq_terms",
+ "Include two terms in the large q expansion.",
+ &nlo_alpha_s::two_largeq_terms_, true, false, false);
+ static SwitchOption interfacetwo_largeq_termsYes
+ (interfacetwo_largeq_terms,
+ "Yes",
+ "Include two terms.",
+ true);
+ static SwitchOption interfacetwo_largeq_termsNo
+ (interfacetwo_largeq_terms,
+ "No",
+ "Only include one term.",
+ false);
+
}
double nlo_alpha_s::operator () (Energy2 scale,
Energy2 lambda2,
unsigned int nf) const {
if (scale < sqr(freezing_scale_)) {
scale = sqr(freezing_scale_);
nf = active_flavours(scale);
lambda2 = lambda_squared(nf);
}
double beta0 = (33.-2.*nf)/(12.*Constants::pi);
double beta1 = (153.-19.*nf)/(24.*sqr(Constants::pi));
if (exact_evaluation_) {
rg_solver().f.slog = log(scale/lambda2);
rg_solver().f.nf = nf;
double slog = rg_solver().f.slog;
double center =
(1./(beta0*slog))*
(1. - (beta1/sqr(beta0)) * log(slog)/slog +
sqr(beta1/(sqr(beta0)*slog)) * (sqr(log(slog)-.5) - 5./4.));
return rg_solver().solve(make_pair(.5*center,1.5*center));
} else {
double slog = log(scale/lambda2);
-
- return
+
+ double res =
(1./(beta0*slog))*
- (1. - (beta1/sqr(beta0)) * log(slog)/slog +
- sqr(beta1/(sqr(beta0)*slog)) * (sqr(log(slog)-.5) - 5./4.));
+ (1. - (beta1/sqr(beta0)) * log(slog)/slog);
+
+ if ( two_largeq_terms_ )
+ res +=
+ (1./(beta0*slog))*
+ (sqr(beta1/(sqr(beta0)*slog)) * (sqr(log(slog)-.5) - 5./4.));
+
+ return res;
}
return 0.;
}
diff --git a/DipoleShower/AlphaS/nlo_alpha_s.h b/DipoleShower/AlphaS/nlo_alpha_s.h
--- a/DipoleShower/AlphaS/nlo_alpha_s.h
+++ b/DipoleShower/AlphaS/nlo_alpha_s.h
@@ -1,192 +1,194 @@
// -*- C++ -*-
// couplings/nlo_alpha_s.h is part of matchbox
// (C) 2008 Simon Platzer -- sp@particle.uni-karlsruhe.de
#ifndef matchbox_couplings_nlo_alpha_s_h
#define matchbox_couplings_nlo_alpha_s_h
#include "alpha_s.h"
namespace matchbox {
using namespace ThePEG;
/**
* NLO running alpha_s
*
* @see \ref nlo_alpha_sInterfaces "The interfaces"
* defined for nlo_alpha_s.
*/
class nlo_alpha_s
: public alpha_s {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
nlo_alpha_s();
/**
* The destructor.
*/
virtual ~nlo_alpha_s();
//@}
public:
/// return alpha_s as function of scale, QCD scale
/// and number of active flavours
virtual double operator () (Energy2 scale,
Energy2 lambda2,
unsigned int nf) const;
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @name os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @name is the persistent input stream read from.
* @name 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 inline void doinit() throw(InitException) {
freezing_scale_ *= scale_factor();
alpha_s::doinit();
}
//@}
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 abstract class with persistent data.
*/
static ClassDescription<nlo_alpha_s> initnlo_alpha_s;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
nlo_alpha_s & operator=(const nlo_alpha_s &);
private:
struct rg_solution {
inline double operator () (double alpha) {
double beta0 = (33.-2.*nf)/(12.*Constants::pi);
double beta1 = (153.-19.*nf)/(24.*sqr(Constants::pi));
return ((1./alpha)+(beta1/beta0)*log(alpha/(beta0+beta1*alpha))- beta0*slog);
}
double slog;
unsigned int nf;
};
Energy freezing_scale_;
bool exact_evaluation_;
static rg_solution& rg () {
static rg_solution rg_;
return rg_;
}
static gsl::bisection_root_solver<rg_solution,100>& rg_solver () {
static gsl::bisection_root_solver<rg_solution,100> rg_solver_(rg());
return rg_solver_;
}
+ bool two_largeq_terms_;
+
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of nlo_alpha_s. */
template <>
struct BaseClassTrait<matchbox::nlo_alpha_s,1> {
/** Typedef of the first base class of nlo_alpha_s. */
typedef matchbox::alpha_s NthBase;
};
/** This template specialization informs ThePEG about the name of
* the nlo_alpha_s class and the shared object where it is defined. */
template <>
struct ClassTraits<matchbox::nlo_alpha_s>
: public ClassTraitsBase<matchbox::nlo_alpha_s> {
/** Return a platform-independent class name */
static string className() { return "matchbox::nlo_alpha_s"; }
/**
* The name of a file containing the dynamic library where the class
* nlo_alpha_s is implemented. It may also include several, space-separated,
* libraries if the class nlo_alpha_s 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 "HwDipoleShowerAlphaS.so"; }
};
/** @endcond */
}
#endif /* matchbox_couplings_nlo_alpha_s_h */
diff --git a/DipoleShower/Base/DipoleSplittingGenerator.cc b/DipoleShower/Base/DipoleSplittingGenerator.cc
--- a/DipoleShower/Base/DipoleSplittingGenerator.cc
+++ b/DipoleShower/Base/DipoleSplittingGenerator.cc
@@ -1,577 +1,587 @@
// -*- C++ -*-
//
// DipoleSplittingGenerator.cc is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2007 The Herwig Collaboration
//
// Herwig is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the DipoleSplittingGenerator class.
//
#include <config.h>
#include "DipoleSplittingGenerator.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "Herwig/DipoleShower/DipoleShowerHandler.h"
using namespace Herwig;
DipoleSplittingGenerator::DipoleSplittingGenerator()
: HandlerBase(),
theExponentialGenerator(0), prepared(false), presampling(false),
theDoCompensate(false) {
if ( ShowerHandler::currentHandler() )
setGenerator(ShowerHandler::currentHandler()->generator());
}
DipoleSplittingGenerator::~DipoleSplittingGenerator() {
if ( theExponentialGenerator ) {
delete theExponentialGenerator;
theExponentialGenerator = 0;
}
}
IBPtr DipoleSplittingGenerator::clone() const {
return new_ptr(*this);
}
IBPtr DipoleSplittingGenerator::fullclone() const {
return new_ptr(*this);
}
void DipoleSplittingGenerator::wrap(Ptr<DipoleSplittingGenerator>::ptr other) {
assert(!prepared);
theOtherGenerator = other;
}
void DipoleSplittingGenerator::prepare(const DipoleSplittingInfo& sp) {
generatedSplitting = sp;
generatedSplitting.splittingKinematics(splittingKernel()->splittingKinematics());
generatedSplitting.splittingParameters().resize(splittingKernel()->nDimAdditional());
if ( wrapping() ) {
generatedSplitting.emitterData(theSplittingKernel->emitter(generatedSplitting.index()));
generatedSplitting.spectatorData(theSplittingKernel->spectator(generatedSplitting.index()));
generatedSplitting.emissionData(theSplittingKernel->emission(generatedSplitting.index()));
parameters.resize(theOtherGenerator->nDim());
prepared = true;
return;
}
generatedSplitting.emitterData(splittingKernel()->emitter(generatedSplitting.index()));
generatedSplitting.spectatorData(splittingKernel()->spectator(generatedSplitting.index()));
generatedSplitting.emissionData(splittingKernel()->emission(generatedSplitting.index()));
presampledSplitting = generatedSplitting;
prepared = true;
parameters.resize(nDim());
theExponentialGenerator =
new exsample::exponential_generator<DipoleSplittingGenerator,UseRandom>();
theExponentialGenerator->sampling_parameters().maxtry = maxtry();
theExponentialGenerator->sampling_parameters().presampling_points = presamplingPoints();
theExponentialGenerator->sampling_parameters().freeze_grid = freezeGrid();
theExponentialGenerator->docompensate(theDoCompensate);
theExponentialGenerator->function(this);
theExponentialGenerator->initialize();
}
void DipoleSplittingGenerator::fixParameters(const DipoleSplittingInfo& sp,
Energy optHardPt) {
assert(generator());
assert(!presampling);
assert(prepared);
assert(sp.index() == generatedSplitting.index());
generatedSplitting.scale(sp.scale());
parameters[3] = sp.scale()/generator()->maximumCMEnergy();
generatedSplitting.hardPt(sp.hardPt());
parameters[0] = splittingKinematics()->ptToRandom(optHardPt == ZERO ?
generatedSplitting.hardPt() :
min(generatedSplitting.hardPt(),optHardPt),
sp.scale(),
sp.emitterX(), sp.spectatorX(),
generatedSplitting.index(),
*splittingKernel());
size_t shift = 4;
if ( generatedSplitting.index().emitterPDF().pdf() &&
generatedSplitting.index().spectatorPDF().pdf() ) {
generatedSplitting.emitterX(sp.emitterX());
generatedSplitting.spectatorX(sp.spectatorX());
parameters[4] = sp.emitterX();
parameters[5] = sp.spectatorX();
shift += 2;
}
if ( generatedSplitting.index().emitterPDF().pdf() &&
!generatedSplitting.index().spectatorPDF().pdf() ) {
generatedSplitting.emitterX(sp.emitterX());
parameters[4] = sp.emitterX();
++shift;
}
if ( !generatedSplitting.index().emitterPDF().pdf() &&
generatedSplitting.index().spectatorPDF().pdf() ) {
generatedSplitting.spectatorX(sp.spectatorX());
parameters[4] = sp.spectatorX();
++shift;
}
if ( splittingReweight() ) {
parameters[shift] = splittingReweight()->evaluate(sp);
++shift;
}
if ( splittingKernel()->nDimAdditional() )
copy(sp.lastSplittingParameters().begin(),sp.lastSplittingParameters().end(),parameters.begin()+shift);
if ( sp.emitter() )
generatedSplitting.emitter(sp.emitter());
if ( sp.spectator() )
generatedSplitting.spectator(sp.spectator());
}
int DipoleSplittingGenerator::nDim() const {
assert(!wrapping());
assert(prepared);
int ret = 4; // 0 pt, 1 z, 2 phi, 3 scale, 4/5 xs + parameters
if ( generatedSplitting.index().emitterPDF().pdf() ) {
++ret;
}
if ( generatedSplitting.index().spectatorPDF().pdf() ) {
++ret;
}
if ( splittingReweight() )
++ret;
ret += splittingKernel()->nDimAdditional();
return ret;
}
const vector<bool>& DipoleSplittingGenerator::sampleFlags() {
assert(!wrapping());
if ( !theFlags.empty() )
return theFlags;
theFlags.resize(nDim(),false);
theFlags[0] = true; theFlags[1] = true; theFlags[2] = true; // 0 pt, 1 z, 2 phi
return theFlags;
}
const pair<vector<double>,vector<double> >& DipoleSplittingGenerator::support() {
assert(!wrapping());
if ( !theSupport.first.empty() )
return theSupport;
vector<double> lower(nDim(),0.);
vector<double> upper(nDim(),1.);
pair<double,double> kSupport =
generatedSplitting.splittingKinematics()->kappaSupport(generatedSplitting);
pair<double,double> xSupport =
generatedSplitting.splittingKinematics()->xiSupport(generatedSplitting);
lower[0] = kSupport.first;
lower[1] = xSupport.first;
upper[0] = kSupport.second;
upper[1] = xSupport.second;
if ( splittingReweight() ) {
pair<double,double> bounds = splittingReweight()->reweightBounds(generatedSplitting.index());
int pos = 4;
if ( generatedSplitting.index().emitterPDF().pdf() ) {
++pos;
}
if ( generatedSplitting.index().spectatorPDF().pdf() ) {
++pos;
}
lower[pos] = bounds.first;
upper[pos] = bounds.second;
}
theSupport.first = lower;
theSupport.second = upper;
return theSupport;
}
void DipoleSplittingGenerator::startPresampling() {
assert(!wrapping());
splittingKernel()->startPresampling(generatedSplitting.index());
presampling = true;
}
void DipoleSplittingGenerator::stopPresampling() {
assert(!wrapping());
splittingKernel()->stopPresampling(generatedSplitting.index());
presampling = false;
}
bool DipoleSplittingGenerator::haveOverestimate() const {
assert(!wrapping());
assert(prepared);
return
generatedSplitting.splittingKinematics()->haveOverestimate() &&
splittingKernel()->haveOverestimate(generatedSplitting);
}
bool DipoleSplittingGenerator::overestimate(const vector<double>& point) {
assert(!wrapping());
assert(prepared);
assert(!presampling);
assert(haveOverestimate());
if ( ! generatedSplitting.splittingKinematics()->generateSplitting(point[0],point[1],point[2],
generatedSplitting,
*splittingKernel()) )
return 0.;
generatedSplitting.splittingKinematics()->prepareSplitting(generatedSplitting);
return
( generatedSplitting.splittingKinematics()->jacobianOverestimate() *
splittingKernel()->overestimate(generatedSplitting) *
(splittingReweight() ? splittingReweight()->evaluate(generatedSplitting) : 1.) );
}
double DipoleSplittingGenerator::invertOverestimateIntegral(double value) const {
assert(!wrapping());
assert(prepared);
assert(!presampling);
assert(haveOverestimate());
return
splittingKernel()->invertOverestimateIntegral(generatedSplitting,value);
}
double DipoleSplittingGenerator::evaluate(const vector<double>& point) {
assert(!wrapping());
assert(prepared);
assert(generator());
DipoleSplittingInfo& split =
( !presampling ? generatedSplitting : presampledSplitting );
split.continuesEvolving();
size_t shift = 4;
if ( presampling ) {
split.scale(point[3] * generator()->maximumCMEnergy());
if ( split.index().emitterPDF().pdf() &&
split.index().spectatorPDF().pdf() ) {
split.emitterX(point[4]);
split.spectatorX(point[5]);
shift += 2;
}
if ( split.index().emitterPDF().pdf() &&
!split.index().spectatorPDF().pdf() ) {
split.emitterX(point[4]);
++shift;
}
if ( !split.index().emitterPDF().pdf() &&
split.index().spectatorPDF().pdf() ) {
split.spectatorX(point[4]);
++shift;
}
if ( splittingReweight() )
++shift;
if ( splittingKernel()->nDimAdditional() )
copy(point.begin()+shift,point.end(),split.splittingParameters().begin());
split.hardPt(split.splittingKinematics()->ptMax(split.scale(),
split.emitterX(),
split.spectatorX(),
split.index(),
*splittingKernel()));
}
if ( ! split.splittingKinematics()->generateSplitting(point[0],point[1],point[2],split,*splittingKernel()) ) {
split.lastValue(0.);
return 0.;
}
split.splittingKinematics()->prepareSplitting(split);
if ( split.stoppedEvolving() ) {
split.lastValue(0.);
return 0.;
}
double kernel = splittingKernel()->evaluate(split);
if ( splittingReweight() ) {
if ( !presampling )
kernel *= splittingReweight()->evaluate(split);
else
kernel *= point[shift-1];
}
double jac = split.splittingKinematics()->jacobian();
+ // multiply in the profile scales when relevant
+ assert(ShowerHandler::currentHandler());
+ if ( ShowerHandler::currentHandler()->firstInteraction() &&
+ ShowerHandler::currentHandler()->profileScales() &&
+ !presampling ) {
+ Energy hard = ShowerHandler::currentHandler()->hardScale();
+ if ( hard > ZERO )
+ kernel *= ShowerHandler::currentHandler()->profileScales()->hardScaleProfile(hard,split.lastPt());
+ }
+
split.lastValue( abs(jac) * kernel );
if ( isnan(split.lastValue()) || isinf(split.lastValue()) ) {
generator()->log() << "DipoleSplittingGenerator:evaluate(): problematic splitting kernel encountered for "
<< splittingKernel()->name() << "\n" << flush;
split.lastValue(0.0);
}
if ( kernel < 0. )
return 0.;
return split.lastValue();
}
void DipoleSplittingGenerator::doGenerate(Energy optCutoff) {
assert(!wrapping());
double res = 0.;
Energy startPt = generatedSplitting.hardPt();
double optKappaCutoff = 0.0;
if ( optCutoff > splittingKinematics()->IRCutoff() ) {
optKappaCutoff = splittingKinematics()->ptToRandom(optCutoff,
generatedSplitting.scale(),
generatedSplitting.emitterX(),
generatedSplitting.spectatorX(),
generatedSplitting.index(),
*splittingKernel());
}
while (true) {
try {
if ( optKappaCutoff == 0.0 ) {
res = theExponentialGenerator->generate();
} else {
res = theExponentialGenerator->generate(optKappaCutoff);
}
} catch (exsample::exponential_regenerate&) {
generatedSplitting.hardPt(startPt);
continue;
} catch (exsample::hit_and_miss_maxtry&) {
throw DipoleShowerHandler::RedoShower();
} catch (exsample::selection_maxtry&) {
throw DipoleShowerHandler::RedoShower();
}
break;
}
if ( res == 0. ) {
generatedSplitting.lastPt(0.0*GeV);
generatedSplitting.didStopEvolving();
} else {
generatedSplitting.continuesEvolving();
if ( theMCCheck )
theMCCheck->book(generatedSplitting.emitterX(),
generatedSplitting.spectatorX(),
generatedSplitting.scale(),
startPt,
generatedSplitting.lastPt(),
generatedSplitting.lastZ(),
1.);
}
}
Energy DipoleSplittingGenerator::generate(const DipoleSplittingInfo& split,
Energy optHardPt,
Energy optCutoff) {
fixParameters(split,optHardPt);
if ( wrapping() ) {
return theOtherGenerator->generateWrapped(generatedSplitting,optHardPt,optCutoff);
}
doGenerate(optCutoff);
return generatedSplitting.lastPt();
}
Energy DipoleSplittingGenerator::generateWrapped(DipoleSplittingInfo& split,
Energy optHardPt,
Energy optCutoff) {
assert(!wrapping());
DipoleSplittingInfo backup = generatedSplitting;
generatedSplitting = split;
fixParameters(split,optHardPt);
try {
doGenerate(optCutoff);
} catch (...) {
split = generatedSplitting;
generatedSplitting = backup;
throw;
}
Energy pt = generatedSplitting.lastPt();
split = generatedSplitting;
generatedSplitting = backup;
return pt;
}
void DipoleSplittingGenerator::completeSplitting(DipoleSplittingInfo& sp) const {
pair<bool,bool> conf = sp.configuration();
sp = generatedSplitting;
sp.configuration(conf);
}
Ptr<DipoleSplittingKernel>::tptr DipoleSplittingGenerator::splittingKernel() const {
if ( wrapping() )
return theOtherGenerator->splittingKernel();
return theSplittingKernel;
}
Ptr<DipoleSplittingReweight>::tptr DipoleSplittingGenerator::splittingReweight() const {
if ( wrapping() )
return theOtherGenerator->splittingReweight();
return theSplittingReweight;
}
Ptr<DipoleSplittingKinematics>::tptr DipoleSplittingGenerator::splittingKinematics() const {
if ( wrapping() )
return theOtherGenerator->splittingKinematics();
return theSplittingKernel->splittingKinematics();
}
void DipoleSplittingGenerator::splittingKernel(Ptr<DipoleSplittingKernel>::tptr sp) {
theSplittingKernel = sp;
if ( theSplittingKernel->mcCheck() )
theMCCheck = theSplittingKernel->mcCheck();
}
void DipoleSplittingGenerator::splittingReweight(Ptr<DipoleSplittingReweight>::tptr sp) {
theSplittingReweight = sp;
}
void DipoleSplittingGenerator::debugGenerator(ostream& os) const {
os << "--- DipoleSplittingGenerator ---------------------------------------------------\n";
os << " generating splittings using\n"
<< " splittingKernel = " << splittingKernel()->name()
<< " splittingKinematics = " << generatedSplitting.splittingKinematics()->name() << "\n"
<< " to sample splittings of type:\n";
os << generatedSplitting;
os << "--------------------------------------------------------------------------------\n";
}
void DipoleSplittingGenerator::debugLastEvent(ostream& os) const {
os << "--- DipoleSplittingGenerator ---------------------------------------------------\n";
os << " last generated event:\n";
os << generatedSplitting;
os << "--------------------------------------------------------------------------------\n";
}
// If needed, insert default implementations of virtual function defined
// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs).
void DipoleSplittingGenerator::persistentOutput(PersistentOStream & os) const {
os << theOtherGenerator << theSplittingKernel << theSplittingReweight << theMCCheck << theDoCompensate;
}
void DipoleSplittingGenerator::persistentInput(PersistentIStream & is, int) {
is >> theOtherGenerator >> theSplittingKernel >> theSplittingReweight >> theMCCheck >> theDoCompensate;
}
ClassDescription<DipoleSplittingGenerator> DipoleSplittingGenerator::initDipoleSplittingGenerator;
// Definition of the static class description member.
void DipoleSplittingGenerator::Init() {
static ClassDocumentation<DipoleSplittingGenerator> documentation
("DipoleSplittingGenerator is used by the dipole shower "
"to sample splittings from a given dipole splitting kernel.");
static Reference<DipoleSplittingGenerator,DipoleSplittingKernel> interfaceSplittingKernel
("SplittingKernel",
"Set the splitting kernel to sample from.",
&DipoleSplittingGenerator::theSplittingKernel, false, false, true, false, false);
static Reference<DipoleSplittingGenerator,DipoleSplittingReweight> interfaceSplittingReweight
("SplittingReweight",
"Set the splitting reweight.",
&DipoleSplittingGenerator::theSplittingReweight, false, false, true, true, false);
static Reference<DipoleSplittingGenerator,DipoleMCCheck> interfaceMCCheck
("MCCheck",
"[debug option] MCCheck",
&DipoleSplittingGenerator::theMCCheck, false, false, true, true, false);
interfaceMCCheck.rank(-1);
}
diff --git a/DipoleShower/DipoleShowerHandler.cc b/DipoleShower/DipoleShowerHandler.cc
--- a/DipoleShower/DipoleShowerHandler.cc
+++ b/DipoleShower/DipoleShowerHandler.cc
@@ -1,1110 +1,1098 @@
// -*- C++ -*-
//
// DipoleShowerHandler.cc is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2007 The Herwig Collaboration
//
// Herwig is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the DipoleShowerHandler class.
//
#include <config.h>
#include "DipoleShowerHandler.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/RefVector.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
// include theses to have complete types
#include "Herwig/Shower/Base/Evolver.h"
#include "Herwig/Shower/Base/ShowerParticle.h"
#include "Herwig/PDF/MPIPDF.h"
#include "Herwig/PDF/MinBiasPDF.h"
#include "Herwig/Shower/Base/ShowerTree.h"
#include "Herwig/Shower/Base/KinematicsReconstructor.h"
#include "Herwig/Shower/Base/PartnerFinder.h"
#include "Herwig/PDF/HwRemDecayer.h"
#include "Herwig/DipoleShower/Utility/DipolePartonSplitter.h"
#include "Herwig/MatrixElement/Matchbox/Base/SubtractedME.h"
#include "Herwig/MatrixElement/Matchbox/MatchboxFactory.h"
using namespace Herwig;
bool DipoleShowerHandler::firstWarn = true;
DipoleShowerHandler::DipoleShowerHandler()
: ShowerHandler(), chainOrderVetoScales(true),
nEmissions(0), discardNoEmissions(false), firstMCatNLOEmission(false),
doFSR(true), doISR(true), realignmentScheme(0),
verbosity(0), printEvent(0), nTries(0),
didRadiate(false), didRealign(false),
theRenormalizationScaleFreeze(1.*GeV),
theFactorizationScaleFreeze(2.*GeV),
isMCatNLOSEvent(false),
isMCatNLOHEvent(false), theDoCompensate(false),
theFreezeGrid(500000), maxPt(ZERO),
muPt(ZERO) {}
DipoleShowerHandler::~DipoleShowerHandler() {}
IBPtr DipoleShowerHandler::clone() const {
return new_ptr(*this);
}
IBPtr DipoleShowerHandler::fullclone() const {
return new_ptr(*this);
}
tPPair DipoleShowerHandler::cascade(tSubProPtr sub, XCPtr,
Energy optHardPt, Energy optCutoff) {
useMe();
prepareCascade(sub);
if ( !doFSR && ! doISR )
return sub->incoming();
eventRecord().clear();
eventRecord().prepare(sub,dynamic_ptr_cast<tStdXCombPtr>(lastXCombPtr()),pdfs());
if ( eventRecord().outgoing().empty() && !doISR )
return sub->incoming();
if ( !eventRecord().incoming().first->coloured() &&
!eventRecord().incoming().second->coloured() &&
!doFSR )
return sub->incoming();
nTries = 0;
while ( true ) {
try {
didRadiate = false;
didRealign = false;
isMCatNLOSEvent = false;
isMCatNLOHEvent = false;
if ( eventRecord().xcombPtr() ) {
Ptr<SubtractedME>::tptr subme =
dynamic_ptr_cast<Ptr<SubtractedME>::tptr>(eventRecord().xcombPtr()->matrixElement());
Ptr<MatchboxMEBase>::tptr me =
dynamic_ptr_cast<Ptr<MatchboxMEBase>::tptr>(eventRecord().xcombPtr()->matrixElement());
Ptr<SubtractionDipole>::tptr dipme =
dynamic_ptr_cast<Ptr<SubtractionDipole>::tptr>(eventRecord().xcombPtr()->matrixElement());
if ( subme ) {
if ( subme->showerApproximation() ) {
// don't do this for POWHEG-type corrections
if ( !subme->showerApproximation()->needsSplittingGenerator() ) {
theShowerApproximation = subme->showerApproximation();
if ( subme->realShowerSubtraction() )
isMCatNLOHEvent = true;
else if ( subme->virtualShowerSubtraction() )
isMCatNLOSEvent = true;
}
}
} else if ( me ) {
if ( me->factory()->showerApproximation() ) {
if ( !me->factory()->showerApproximation()->needsSplittingGenerator() ) {
theShowerApproximation = me->factory()->showerApproximation();
isMCatNLOSEvent = true;
}
}
}
string error = "Inconsistent hard emission set-up in DipoleShowerHandler::cascade. ";
if (evolver()->hardEmissionMode()==1 || evolver()->hardEmissionMode()==3 )
throw Exception() << error
<< "Cannot generate POWHEG corrections "
<< "for particle decays using DipoleShowerHandler. "
<< "Check value of Evolver:HardEmissionMode."
<< Exception::runerror;
if ( ( isMCatNLOSEvent || isMCatNLOHEvent ) && evolver()->hardEmissionMode()==2)
throw Exception() << error
<< "Cannot generate POWHEG matching with MC@NLO shower approximation. "
<< "Add 'set Evolver:HardEmissionMode 0' to input file."
<< Exception::runerror;
if (me && me->factory()->showerApproximation()){
if(me->factory()->showerApproximation()->needsTruncatedShower())
throw Exception() << error
<< "No truncated shower needed with DipoleShowerHandler. Add "
<< "'set MEMatching:TruncatedShower No' to input file."
<< Exception::runerror;
if (!( isMCatNLOSEvent || isMCatNLOHEvent ) &&
evolver()->hardEmissionMode()==0 && firstWarn){
firstWarn=false;
throw Exception() << error
<< "Evolver:HardEmissionMode will be set to 'MatchboxPOWHEG'"
<< Exception::warning;
}
}
else if (subme && subme->factory()->showerApproximation()){
if(subme->factory()->showerApproximation()->needsTruncatedShower())
throw Exception() << error
<< "No truncated shower needed with DipoleShowerHandler. Add "
<< "'set MEMatching:TruncatedShower No' to input file."
<< Exception::runerror;
if (!( isMCatNLOSEvent || isMCatNLOHEvent ) &&
evolver()->hardEmissionMode()==0 && firstWarn){
firstWarn=false;
throw Exception() << error
<< "Evolver:HardEmissionMode will be set to 'MatchboxPOWHEG'"
<< Exception::warning;
}
}
else if (dipme && evolver()->hardEmissionMode() == 0 && firstWarn){
firstWarn=false;
throw Exception() << error
<< "Evolver:HardEmissionMode will be set to 'MatchboxPOWHEG'"
<< Exception::warning;
}
else if (!dipme && evolver()->hardEmissionMode()==2 &&
ShowerHandler::currentHandler()->firstInteraction())
throw Exception() << error
<< "POWHEG matching requested for LO events. Include "
<< "'set Factory:ShowerApproximation MEMatching' in input file."
<< Exception::runerror;
}
hardScales(lastXCombPtr()->lastCentralScale());
if ( verbosity > 1 ) {
generator()->log() << "DipoleShowerHandler starting off:\n";
eventRecord().debugLastEvent(generator()->log());
generator()->log() << flush;
}
unsigned int nEmitted = 0;
if ( firstMCatNLOEmission ) {
if ( !isMCatNLOHEvent )
nEmissions = 1;
else
nEmissions = 0;
}
if ( !firstMCatNLOEmission ) {
doCascade(nEmitted,optHardPt,optCutoff);
if ( discardNoEmissions ) {
if ( !didRadiate )
throw Veto();
if ( nEmissions )
if ( nEmissions < nEmitted )
throw Veto();
}
} else {
if ( nEmissions == 1 )
doCascade(nEmitted,optHardPt,optCutoff);
}
if ( intrinsicPtGenerator ) {
if ( eventRecord().incoming().first->coloured() &&
eventRecord().incoming().second->coloured() ) {
SpinOneLorentzRotation rot =
intrinsicPtGenerator->kick(eventRecord().incoming(),
eventRecord().intermediates());
eventRecord().transform(rot);
}
}
didRealign = realign();
constituentReshuffle();
break;
} catch (RedoShower&) {
if ( ++nTries > maxtry() )
throw ShowerTriesVeto(maxtry());
eventRecord().clear();
eventRecord().prepare(sub,dynamic_ptr_cast<tStdXCombPtr>(lastXCombPtr()),pdfs());
continue;
} catch (...) {
throw;
}
}
return eventRecord().fillEventRecord(newStep(),firstInteraction(),didRealign);
}
void DipoleShowerHandler::constituentReshuffle() {
if ( constituentReshuffler ) {
constituentReshuffler->reshuffle(eventRecord().outgoing(),
eventRecord().incoming(),
eventRecord().intermediates());
}
}
void DipoleShowerHandler::hardScales(Energy2 muf) {
maxPt = generator()->maximumCMEnergy();
if ( restrictPhasespace() ) {
if ( !hardScaleIsMuF() || !firstInteraction() ) {
if ( !eventRecord().outgoing().empty() ) {
for ( PList::const_iterator p = eventRecord().outgoing().begin();
p != eventRecord().outgoing().end(); ++p )
maxPt = min(maxPt,(**p).momentum().mt());
} else {
assert(!eventRecord().hard().empty());
Lorentz5Momentum phard(ZERO,ZERO,ZERO,ZERO);
for ( PList::const_iterator p = eventRecord().hard().begin();
p != eventRecord().hard().end(); ++p )
phard += (**p).momentum();
Energy mhard = phard.m();
maxPt = mhard;
}
maxPt *= hardScaleFactor();
} else {
maxPt = hardScaleFactor()*sqrt(muf);
}
muPt = maxPt;
} else {
muPt = hardScaleFactor()*sqrt(muf);
}
for ( list<DipoleChain>::iterator ch = eventRecord().chains().begin();
ch != eventRecord().chains().end(); ++ch ) {
Energy minVetoScale = -1.*GeV;
for ( list<Dipole>::iterator dip = ch->dipoles().begin();
dip != ch->dipoles().end(); ++dip ) {
// max scale per config
Energy maxFirst = 0.0*GeV;
Energy maxSecond = 0.0*GeV;
for ( vector<Ptr<DipoleSplittingKernel>::ptr>::iterator k =
kernels.begin(); k != kernels.end(); ++k ) {
pair<bool,bool> conf = make_pair(true,false);
if ( (**k).canHandle(dip->index(conf)) ) {
Energy scale =
evolutionOrdering()->hardScale(dip->emitter(conf),dip->spectator(conf),
dip->emitterX(conf),dip->spectatorX(conf),
**k,dip->index(conf));
maxFirst = max(maxFirst,scale);
}
conf = make_pair(false,true);
if ( (**k).canHandle(dip->index(conf)) ) {
Energy scale =
evolutionOrdering()->hardScale(dip->emitter(conf),dip->spectator(conf),
dip->emitterX(conf),dip->spectatorX(conf),
**k,dip->index(conf));
maxSecond = max(maxSecond,scale);
}
}
if ( dip->leftParticle()->vetoScale() >= ZERO ) {
maxFirst = min(maxFirst,sqrt(dip->leftParticle()->vetoScale()));
if ( minVetoScale >= ZERO )
minVetoScale = min(minVetoScale,sqrt(dip->leftParticle()->vetoScale()));
else
minVetoScale = sqrt(dip->leftParticle()->vetoScale());
}
if ( dip->rightParticle()->vetoScale() >= ZERO ) {
maxSecond = min(maxSecond,sqrt(dip->rightParticle()->vetoScale()));
if ( minVetoScale >= ZERO )
minVetoScale = min(minVetoScale,sqrt(dip->rightParticle()->vetoScale()));
else
minVetoScale = sqrt(dip->rightParticle()->vetoScale());
}
maxFirst = min(maxPt,maxFirst);
dip->emitterScale(make_pair(true,false),maxFirst);
maxSecond = min(maxPt,maxSecond);
dip->emitterScale(make_pair(false,true),maxSecond);
}
if ( !evolutionOrdering()->independentDipoles() &&
chainOrderVetoScales &&
minVetoScale >= ZERO ) {
for ( list<Dipole>::iterator dip = ch->dipoles().begin();
dip != ch->dipoles().end(); ++dip ) {
dip->leftScale(min(dip->leftScale(),minVetoScale));
dip->rightScale(min(dip->rightScale(),minVetoScale));
}
}
}
}
Energy DipoleShowerHandler::getWinner(DipoleSplittingInfo& winner,
const Dipole& dip,
pair<bool,bool> conf,
Energy optHardPt,
Energy optCutoff) {
return
getWinner(winner,dip.index(conf),
dip.emitterX(conf),dip.spectatorX(conf),
conf,dip.emitter(conf),dip.spectator(conf),
dip.emitterScale(conf),optHardPt,optCutoff);
}
Energy DipoleShowerHandler::getWinner(SubleadingSplittingInfo& winner,
Energy optHardPt,
Energy optCutoff) {
return
getWinner(winner,winner.index(),
winner.emitterX(),winner.spectatorX(),
winner.configuration(),
winner.emitter(),winner.spectator(),
winner.startScale(),optHardPt,optCutoff);
}
Energy DipoleShowerHandler::getWinner(DipoleSplittingInfo& winner,
const DipoleIndex& index,
double emitterX, double spectatorX,
pair<bool,bool> conf,
tPPtr emitter, tPPtr spectator,
Energy startScale,
Energy optHardPt,
Energy optCutoff) {
if ( !index.initialStateEmitter() &&
!doFSR ) {
winner.didStopEvolving();
return 0.0*GeV;
}
if ( index.initialStateEmitter() &&
!doISR ) {
winner.didStopEvolving();
return 0.0*GeV;
}
DipoleSplittingInfo candidate;
candidate.index(index);
candidate.configuration(conf);
candidate.emitterX(emitterX);
candidate.spectatorX(spectatorX);
if ( generators().find(candidate.index()) == generators().end() )
getGenerators(candidate.index());
//
// NOTE -- needs proper fixing at some point
//
// For some very strange reason, equal_range gives back
// key ranges it hasn't been asked for. This particularly
// happens e.g. for FI dipoles of the same kind, but different
// PDF (hard vs MPI PDF). I can't see a reason for this,
// as DipoleIndex properly implements comparison for equality
// and (lexicographic) ordering; for the time being, we
// use equal_range, extented by an explicit check for wether
// the key is indeed what we wanted. See line after (*) comment
// below.
//
pair<GeneratorMap::iterator,GeneratorMap::iterator> gens
= generators().equal_range(candidate.index());
Energy winnerScale = 0.0*GeV;
GeneratorMap::iterator winnerGen = generators().end();
for ( GeneratorMap::iterator gen = gens.first; gen != gens.second; ++gen ) {
// (*) see NOTE above
if ( !(gen->first == candidate.index()) )
continue;
if ( startScale <= gen->second->splittingKinematics()->IRCutoff() )
continue;
Energy dScale =
gen->second->splittingKinematics()->dipoleScale(emitter->momentum(),
spectator->momentum());
// in very exceptional cases happening in DIS
if ( isnan(dScale/GeV ) )
throw RedoShower();
candidate.scale(dScale);
candidate.continuesEvolving();
Energy hardScale = evolutionOrdering()->maxPt(startScale,candidate,*(gen->second->splittingKernel()));
Energy maxPossible =
gen->second->splittingKinematics()->ptMax(candidate.scale(),
candidate.emitterX(), candidate.spectatorX(),
candidate.index(),
*gen->second->splittingKernel());
Energy ircutoff =
optCutoff < gen->second->splittingKinematics()->IRCutoff() ?
gen->second->splittingKinematics()->IRCutoff() :
optCutoff;
if ( maxPossible <= ircutoff ) {
continue;
}
if ( maxPossible >= hardScale )
candidate.hardPt(hardScale);
else {
hardScale = maxPossible;
candidate.hardPt(maxPossible);
}
gen->second->generate(candidate,optHardPt,optCutoff);
Energy nextScale = evolutionOrdering()->evolutionScale(gen->second->lastSplitting(),*(gen->second->splittingKernel()));
- if ( firstInteraction() && profileScales() && nextScale > ircutoff ) {
- while ( UseRandom::rnd() > profileScales()->hardScaleProfile(muPt,nextScale) ) {
- candidate.continuesEvolving();
- Energy nextHardScale = evolutionOrdering()->maxPt(nextScale,candidate,*(gen->second->splittingKernel()));
- candidate.hardPt(nextHardScale);
- gen->second->generate(candidate,optHardPt,optCutoff);
- nextScale = evolutionOrdering()->evolutionScale(gen->second->lastSplitting(),*(gen->second->splittingKernel()));
- if ( nextScale <= ircutoff || candidate.stoppedEvolving() )
- break;
- }
- }
-
if ( nextScale > winnerScale ) {
winner.fill(candidate);
gen->second->completeSplitting(winner);
winnerGen = gen;
winnerScale = nextScale;
}
}
if ( winnerGen == generators().end() ) {
winner.didStopEvolving();
return 0.0*GeV;
}
if ( winner.stoppedEvolving() )
return 0.0*GeV;
return winnerScale;
}
void DipoleShowerHandler::doCascade(unsigned int& emDone,
Energy optHardPt,
Energy optCutoff) {
if ( nEmissions )
if ( emDone == nEmissions )
return;
DipoleSplittingInfo winner;
DipoleSplittingInfo dipoleWinner;
while ( eventRecord().haveChain() ) {
if ( verbosity > 2 ) {
generator()->log() << "DipoleShowerHandler selecting splittings for the chain:\n"
<< eventRecord().currentChain() << flush;
}
list<Dipole>::iterator winnerDip = eventRecord().currentChain().dipoles().end();
Energy winnerScale = 0.0*GeV;
Energy nextLeftScale = 0.0*GeV;
Energy nextRightScale = 0.0*GeV;
for ( list<Dipole>::iterator dip = eventRecord().currentChain().dipoles().begin();
dip != eventRecord().currentChain().dipoles().end(); ++dip ) {
nextLeftScale = getWinner(dipoleWinner,*dip,make_pair(true,false),optHardPt,optCutoff);
if ( nextLeftScale > winnerScale ) {
winnerScale = nextLeftScale;
winner = dipoleWinner;
winnerDip = dip;
}
nextRightScale = getWinner(dipoleWinner,*dip,make_pair(false,true),optHardPt,optCutoff);
if ( nextRightScale > winnerScale ) {
winnerScale = nextRightScale;
winner = dipoleWinner;
winnerDip = dip;
}
if ( evolutionOrdering()->independentDipoles() ) {
Energy dipScale = max(nextLeftScale,nextRightScale);
if ( dip->leftScale() > dipScale )
dip->leftScale(dipScale);
if ( dip->rightScale() > dipScale )
dip->rightScale(dipScale);
}
}
if ( verbosity > 1 ) {
if ( winnerDip != eventRecord().currentChain().dipoles().end() )
generator()->log() << "DipoleShowerHandler selected the splitting:\n"
<< winner << " for the dipole\n"
<< (*winnerDip) << flush;
else
generator()->log() << "DipoleShowerHandler could not select a splitting above the IR cutoff\n"
<< flush;
}
// pop the chain if no dipole did radiate
if ( winnerDip == eventRecord().currentChain().dipoles().end() ) {
if ( theEventReweight ) {
double w = theEventReweight->weightNoEmission(eventRecord().incoming(),
eventRecord().outgoing(),
eventRecord().hard(),theGlobalAlphaS);
Ptr<StandardEventHandler>::tptr eh =
dynamic_ptr_cast<Ptr<StandardEventHandler>::tptr>(eventHandler());
assert(eh);
eh->reweight(w);
}
eventRecord().popChain();
continue;
}
// otherwise perform the splitting
didRadiate = true;
isMCatNLOSEvent = false;
isMCatNLOHEvent = false;
pair<list<Dipole>::iterator,list<Dipole>::iterator> children;
DipoleChain* firstChain = 0;
DipoleChain* secondChain = 0;
eventRecord().split(winnerDip,winner,children,firstChain,secondChain);
assert(firstChain && secondChain);
evolutionOrdering()->setEvolutionScale(winnerScale,winner,*firstChain,children);
if ( !secondChain->dipoles().empty() )
evolutionOrdering()->setEvolutionScale(winnerScale,winner,*secondChain,children);
if ( verbosity > 1 ) {
generator()->log() << "DipoleShowerHandler did split the last selected dipole into:\n"
<< (*children.first) << (*children.second) << flush;
}
if ( verbosity > 2 ) {
generator()->log() << "After splitting the last selected dipole, "
<< "DipoleShowerHandler encountered the following chains:\n"
<< (*firstChain) << (*secondChain) << flush;
}
if ( theEventReweight ) {
double w = theEventReweight->weight(eventRecord().incoming(),
eventRecord().outgoing(),
eventRecord().hard(),theGlobalAlphaS);
Ptr<StandardEventHandler>::tptr eh =
dynamic_ptr_cast<Ptr<StandardEventHandler>::tptr>(eventHandler());
assert(eh);
eh->reweight(w);
}
if ( nEmissions )
if ( ++emDone == nEmissions )
return;
}
}
bool DipoleShowerHandler::realign() {
if ( !didRadiate && !intrinsicPtGenerator )
return false;
if ( eventRecord().incoming().first->coloured() ||
eventRecord().incoming().second->coloured() ) {
if ( eventRecord().incoming().first->momentum().perp2()/GeV2 < 1e-10 &&
eventRecord().incoming().second->momentum().perp2()/GeV2 < 1e-10 )
return false;
pair<Lorentz5Momentum,Lorentz5Momentum> inMomenta
(eventRecord().incoming().first->momentum(),
eventRecord().incoming().second->momentum());
SpinOneLorentzRotation transform((inMomenta.first+inMomenta.second).findBoostToCM());
Axis dir = (transform * inMomenta.first).vect().unit();
Axis rot (-dir.y(),dir.x(),0);
double theta = dir.theta();
if ( lastParticles().first->momentum().z() < ZERO )
theta = -theta;
transform.rotate(-theta,rot);
inMomenta.first = transform*inMomenta.first;
inMomenta.second = transform*inMomenta.second;
assert(inMomenta.first.z() > ZERO &&
inMomenta.second.z() < ZERO);
Energy2 sHat =
(eventRecord().incoming().first->momentum() +
eventRecord().incoming().second->momentum()).m2();
pair<Energy,Energy> masses(eventRecord().incoming().first->mass(),
eventRecord().incoming().second->mass());
pair<Energy,Energy> qs;
if ( !eventRecord().incoming().first->coloured() ) {
assert(masses.second == ZERO);
qs.first = eventRecord().incoming().first->momentum().z();
qs.second = (sHat-sqr(masses.first))/(2.*(qs.first+sqrt(sqr(masses.first)+sqr(qs.first))));
} else if ( !eventRecord().incoming().second->coloured() ) {
assert(masses.first == ZERO);
qs.second = eventRecord().incoming().second->momentum().z();
qs.first = (sHat-sqr(masses.second))/(2.*(qs.second+sqrt(sqr(masses.second)+sqr(qs.second))));
} else {
assert(masses.first == ZERO && masses.second == ZERO);
if ( realignmentScheme == 0 ) {
double yX = eventRecord().pX().rapidity();
double yInt = (transform*eventRecord().pX()).rapidity();
double dy = yX-yInt;
qs.first = (sqrt(sHat)/2.)*exp(dy);
qs.second = (sqrt(sHat)/2.)*exp(-dy);
} else if ( realignmentScheme == 1 ) {
Energy sS = sqrt((lastParticles().first->momentum() +
lastParticles().second->momentum()).m2());
qs.first = eventRecord().fractions().first * sS / 2.;
qs.second = eventRecord().fractions().second * sS / 2.;
}
}
double beta =
(qs.first-qs.second) /
( sqrt(sqr(masses.first)+sqr(qs.first)) +
sqrt(sqr(masses.second)+sqr(qs.second)) );
transform.boostZ(beta);
Lorentz5Momentum tmp;
if ( eventRecord().incoming().first->coloured() ) {
tmp = eventRecord().incoming().first->momentum();
tmp = transform * tmp;
eventRecord().incoming().first->set5Momentum(tmp);
}
if ( eventRecord().incoming().second->coloured() ) {
tmp = eventRecord().incoming().second->momentum();
tmp = transform * tmp;
eventRecord().incoming().second->set5Momentum(tmp);
}
eventRecord().transform(transform);
return true;
}
return false;
}
void DipoleShowerHandler::resetAlphaS(Ptr<AlphaSBase>::tptr as) {
for ( vector<Ptr<DipoleSplittingKernel>::ptr>::iterator k = kernels.begin();
k != kernels.end(); ++k ) {
(**k).alphaS(as);
(**k).renormalizationScaleFreeze(theRenormalizationScaleFreeze);
(**k).factorizationScaleFreeze(theFactorizationScaleFreeze);
}
// clear the generators to be rebuild
// actually, there shouldn't be any generators
// when this happens.
generators().clear();
}
void DipoleShowerHandler::resetReweight(Ptr<DipoleSplittingReweight>::tptr rw) {
for ( GeneratorMap::iterator k = generators().begin();
k != generators().end(); ++k )
k->second->splittingReweight(rw);
}
void DipoleShowerHandler::getGenerators(const DipoleIndex& ind,
Ptr<DipoleSplittingReweight>::tptr rw) {
bool gotone = false;
for ( vector<Ptr<DipoleSplittingKernel>::ptr>::iterator k =
kernels.begin(); k != kernels.end(); ++k ) {
if ( (**k).canHandle(ind) ) {
if ( verbosity > 0 ) {
generator()->log() << "DipoleShowerHandler encountered the dipole configuration\n"
<< ind << " in event number "
<< eventHandler()->currentEvent()->number()
<< "\nwhich can be handled by the splitting kernel '"
<< (**k).name() << "'.\n" << flush;
}
gotone = true;
Ptr<DipoleSplittingGenerator>::ptr nGenerator =
new_ptr(DipoleSplittingGenerator());
nGenerator->doCompensate(theDoCompensate);
nGenerator->splittingKernel(*k);
nGenerator->splittingKernel()->renormalizationScaleFactor(renormalizationScaleFactor());
nGenerator->splittingKernel()->factorizationScaleFactor(factorizationScaleFactor());
nGenerator->splittingKernel()->freezeGrid(theFreezeGrid);
GeneratorMap::const_iterator equivalent = generators().end();
for ( GeneratorMap::const_iterator eq = generators().begin();
eq != generators().end(); ++eq ) {
if ( !eq->second->wrapping() )
if ( (**k).canHandleEquivalent(ind,*(eq->second->splittingKernel()),eq->first) ) {
equivalent = eq;
if ( verbosity > 0 ) {
generator()->log() << "The dipole configuration "
<< ind
<< " can equivalently be handled by the existing\n"
<< "generator for configuration "
<< eq->first << " using the kernel '"
<< eq->second->splittingKernel()->name()
<< "'\n" << flush;
}
break;
}
}
if ( equivalent != generators().end() ) {
nGenerator->wrap(equivalent->second);
}
DipoleSplittingInfo dummy;
dummy.index(ind);
nGenerator->splittingReweight(rw);
nGenerator->prepare(dummy);
generators().insert(make_pair(ind,nGenerator));
}
}
if ( !gotone ) {
generator()->logWarning(Exception()
<< "DipoleShowerHandler could not "
<< "find a splitting kernel which is able "
<< "to handle splittings off the dipole "
<< ind << ".\n"
<< "Please check the input files."
<< Exception::warning);
}
}
// If needed, insert default implementations of virtual function defined
// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs).
void DipoleShowerHandler::doinit() {
ShowerHandler::doinit();
if ( theGlobalAlphaS )
resetAlphaS(theGlobalAlphaS);
}
void DipoleShowerHandler::dofinish() {
ShowerHandler::dofinish();
}
void DipoleShowerHandler::doinitrun() {
ShowerHandler::doinitrun();
}
void DipoleShowerHandler::persistentOutput(PersistentOStream & os) const {
os << kernels << theEvolutionOrdering
<< constituentReshuffler << intrinsicPtGenerator
<< theGlobalAlphaS << chainOrderVetoScales
<< nEmissions << discardNoEmissions << firstMCatNLOEmission << doFSR << doISR
<< realignmentScheme << verbosity << printEvent
<< ounit(theRenormalizationScaleFreeze,GeV)
<< ounit(theFactorizationScaleFreeze,GeV)
<< isMCatNLOSEvent << isMCatNLOHEvent << theShowerApproximation
<< theDoCompensate << theFreezeGrid
<< theEventReweight << ounit(maxPt,GeV)
<< ounit(muPt,GeV);
}
void DipoleShowerHandler::persistentInput(PersistentIStream & is, int) {
is >> kernels >> theEvolutionOrdering
>> constituentReshuffler >> intrinsicPtGenerator
>> theGlobalAlphaS >> chainOrderVetoScales
>> nEmissions >> discardNoEmissions >> firstMCatNLOEmission >> doFSR >> doISR
>> realignmentScheme >> verbosity >> printEvent
>> iunit(theRenormalizationScaleFreeze,GeV)
>> iunit(theFactorizationScaleFreeze,GeV)
>> isMCatNLOSEvent >> isMCatNLOHEvent >> theShowerApproximation
>> theDoCompensate >> theFreezeGrid
>> theEventReweight >> iunit(maxPt,GeV)
>> iunit(muPt,GeV);
}
ClassDescription<DipoleShowerHandler> DipoleShowerHandler::initDipoleShowerHandler;
// Definition of the static class description member.
void DipoleShowerHandler::Init() {
static ClassDocumentation<DipoleShowerHandler> documentation
("The DipoleShowerHandler class manages the showering using "
"the dipole shower algorithm.",
"The shower evolution was performed using the algorithm described in "
"\\cite{Platzer:2009jq} and \\cite{Platzer:2011bc}.",
"%\\cite{Platzer:2009jq}\n"
"\\bibitem{Platzer:2009jq}\n"
"S.~Platzer and S.~Gieseke,\n"
"``Coherent Parton Showers with Local Recoils,''\n"
" JHEP {\\bf 1101}, 024 (2011)\n"
"arXiv:0909.5593 [hep-ph].\n"
"%%CITATION = ARXIV:0909.5593;%%\n"
"%\\cite{Platzer:2011bc}\n"
"\\bibitem{Platzer:2011bc}\n"
"S.~Platzer and S.~Gieseke,\n"
"``Dipole Showers and Automated NLO Matching in Herwig,''\n"
"arXiv:1109.6256 [hep-ph].\n"
"%%CITATION = ARXIV:1109.6256;%%");
static RefVector<DipoleShowerHandler,DipoleSplittingKernel> interfaceKernels
("Kernels",
"Set the splitting kernels to be used by the dipole shower.",
&DipoleShowerHandler::kernels, -1, false, false, true, false, false);
static Reference<DipoleShowerHandler,DipoleEvolutionOrdering> interfaceEvolutionOrdering
("EvolutionOrdering",
"Set the evolution ordering to be used.",
&DipoleShowerHandler::theEvolutionOrdering, false, false, true, false, false);
static Reference<DipoleShowerHandler,ConstituentReshuffler> interfaceConstituentReshuffler
("ConstituentReshuffler",
"The object to be used to reshuffle partons to their constitutent mass shells.",
&DipoleShowerHandler::constituentReshuffler, false, false, true, true, false);
static Reference<DipoleShowerHandler,IntrinsicPtGenerator> interfaceIntrinsicPtGenerator
("IntrinsicPtGenerator",
"Set the object in charge to generate intrinsic pt for incoming partons.",
&DipoleShowerHandler::intrinsicPtGenerator, false, false, true, true, false);
static Reference<DipoleShowerHandler,AlphaSBase> interfaceGlobalAlphaS
("GlobalAlphaS",
"Set a global strong coupling for all splitting kernels.",
&DipoleShowerHandler::theGlobalAlphaS, false, false, true, true, false);
static Switch<DipoleShowerHandler,bool> interfaceDoFSR
("DoFSR",
"Switch on or off final state radiation.",
&DipoleShowerHandler::doFSR, true, false, false);
static SwitchOption interfaceDoFSROn
(interfaceDoFSR,
"On",
"Switch on final state radiation.",
true);
static SwitchOption interfaceDoFSROff
(interfaceDoFSR,
"Off",
"Switch off final state radiation.",
false);
static Switch<DipoleShowerHandler,bool> interfaceDoISR
("DoISR",
"Switch on or off initial state radiation.",
&DipoleShowerHandler::doISR, true, false, false);
static SwitchOption interfaceDoISROn
(interfaceDoISR,
"On",
"Switch on initial state radiation.",
true);
static SwitchOption interfaceDoISROff
(interfaceDoISR,
"Off",
"Switch off initial state radiation.",
false);
static Switch<DipoleShowerHandler,int> interfaceRealignmentScheme
("RealignmentScheme",
"The realignment scheme to use.",
&DipoleShowerHandler::realignmentScheme, 0, false, false);
static SwitchOption interfaceRealignmentSchemePreserveRapidity
(interfaceRealignmentScheme,
"PreserveRapidity",
"Preserve the rapidity of non-coloured outgoing system.",
0);
static SwitchOption interfaceRealignmentSchemeEvolutionFractions
(interfaceRealignmentScheme,
"EvolutionFractions",
"Use momentum fractions as generated by the evolution.",
1);
static SwitchOption interfaceRealignmentSchemeCollisionFrame
(interfaceRealignmentScheme,
"CollisionFrame",
"Determine realignment from collision frame.",
2);
static Switch<DipoleShowerHandler,bool> interfaceChainOrderVetoScales
("ChainOrderVetoScales",
"[experimental] Switch on or off the chain ordering for veto scales.",
&DipoleShowerHandler::chainOrderVetoScales, true, false, false);
static SwitchOption interfaceChainOrderVetoScalesOn
(interfaceChainOrderVetoScales,
"On",
"Switch on chain ordering for veto scales.",
true);
static SwitchOption interfaceChainOrderVetoScalesOff
(interfaceChainOrderVetoScales,
"Off",
"Switch off chain ordering for veto scales.",
false);
interfaceChainOrderVetoScales.rank(-1);
static Parameter<DipoleShowerHandler,unsigned int> interfaceNEmissions
("NEmissions",
"[debug option] Limit the number of emissions to be generated. Zero does not limit the number of emissions.",
&DipoleShowerHandler::nEmissions, 0, 0, 0,
false, false, Interface::lowerlim);
interfaceNEmissions.rank(-1);
static Switch<DipoleShowerHandler,bool> interfaceDiscardNoEmissions
("DiscardNoEmissions",
"[debug option] Discard events without radiation.",
&DipoleShowerHandler::discardNoEmissions, false, false, false);
static SwitchOption interfaceDiscardNoEmissionsOn
(interfaceDiscardNoEmissions,
"On",
"Discard events without radiation.",
true);
static SwitchOption interfaceDiscardNoEmissionsOff
(interfaceDiscardNoEmissions,
"Off",
"Do not discard events without radiation.",
false);
interfaceDiscardNoEmissions.rank(-1);
static Switch<DipoleShowerHandler,bool> interfaceFirstMCatNLOEmission
("FirstMCatNLOEmission",
"[debug option] Only perform the first MC@NLO emission.",
&DipoleShowerHandler::firstMCatNLOEmission, false, false, false);
static SwitchOption interfaceFirstMCatNLOEmissionOn
(interfaceFirstMCatNLOEmission,
"On",
"",
true);
static SwitchOption interfaceFirstMCatNLOEmissionOff
(interfaceFirstMCatNLOEmission,
"Off",
"",
false);
interfaceFirstMCatNLOEmission.rank(-1);
static Parameter<DipoleShowerHandler,int> interfaceVerbosity
("Verbosity",
"[debug option] Set the level of debug information provided.",
&DipoleShowerHandler::verbosity, 0, 0, 0,
false, false, Interface::lowerlim);
interfaceVerbosity.rank(-1);
static Parameter<DipoleShowerHandler,int> interfacePrintEvent
("PrintEvent",
"[debug option] The number of events for which debugging information should be provided.",
&DipoleShowerHandler::printEvent, 0, 0, 0,
false, false, Interface::lowerlim);
interfacePrintEvent.rank(-1);
static Parameter<DipoleShowerHandler,Energy> interfaceRenormalizationScaleFreeze
("RenormalizationScaleFreeze",
"The freezing scale for the renormalization scale.",
&DipoleShowerHandler::theRenormalizationScaleFreeze, GeV, 1.0*GeV, 0.0*GeV, 0*GeV,
false, false, Interface::lowerlim);
static Parameter<DipoleShowerHandler,Energy> interfaceFactorizationScaleFreeze
("FactorizationScaleFreeze",
"The freezing scale for the factorization scale.",
&DipoleShowerHandler::theFactorizationScaleFreeze, GeV, 2.0*GeV, 0.0*GeV, 0*GeV,
false, false, Interface::lowerlim);
static Switch<DipoleShowerHandler,bool> interfaceDoCompensate
("DoCompensate",
"",
&DipoleShowerHandler::theDoCompensate, false, false, false);
static SwitchOption interfaceDoCompensateYes
(interfaceDoCompensate,
"Yes",
"",
true);
static SwitchOption interfaceDoCompensateNo
(interfaceDoCompensate,
"No",
"",
false);
static Parameter<DipoleShowerHandler,unsigned long> interfaceFreezeGrid
("FreezeGrid",
"",
&DipoleShowerHandler::theFreezeGrid, 500000, 1, 0,
false, false, Interface::lowerlim);
static Reference<DipoleShowerHandler,DipoleEventReweight> interfaceEventReweight
("EventReweight",
"",
&DipoleShowerHandler::theEventReweight, false, false, true, true, false);
}
diff --git a/DipoleShower/DipoleShowerHandler.h b/DipoleShower/DipoleShowerHandler.h
--- a/DipoleShower/DipoleShowerHandler.h
+++ b/DipoleShower/DipoleShowerHandler.h
@@ -1,497 +1,504 @@
// -*- C++ -*-
//
// DipoleShowerHandler.h is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2007 The Herwig Collaboration
//
// Herwig is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_DipoleShowerHandler_H
#define HERWIG_DipoleShowerHandler_H
//
// This is the declaration of the DipoleShowerHandler class.
//
#include "Herwig/Shower/ShowerHandler.h"
#include "Herwig/DipoleShower/Base/DipoleSplittingInfo.h"
#include "Herwig/DipoleShower/Base/DipoleSplittingReweight.h"
#include "Herwig/DipoleShower/Kernels/DipoleSplittingKernel.h"
#include "Herwig/DipoleShower/Base/DipoleSplittingGenerator.h"
#include "Herwig/DipoleShower/Base/DipoleEventRecord.h"
#include "Herwig/DipoleShower/Base/DipoleEvolutionOrdering.h"
#include "Herwig/DipoleShower/Base/DipoleEventReweight.h"
#include "Herwig/DipoleShower/Utility/ConstituentReshuffler.h"
#include "Herwig/DipoleShower/Utility/IntrinsicPtGenerator.h"
#include "Herwig/MatrixElement/Matchbox/Matching/ShowerApproximation.h"
namespace Herwig {
using namespace ThePEG;
/**
* \ingroup DipoleShower
* \author Simon Platzer
*
* \brief The DipoleShowerHandler class manages the showering using
* the dipole shower algorithm.
*
* @see \ref DipoleShowerHandlerInterfaces "The interfaces"
* defined for DipoleShowerHandler.
*/
class DipoleShowerHandler: public ShowerHandler {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
DipoleShowerHandler();
/**
* The destructor.
*/
virtual ~DipoleShowerHandler();
//@}
public:
/**
* Indicate a problem in the shower.
*/
struct RedoShower {};
/**
* Insert an additional splitting kernel.
*/
void addSplitting(Ptr<DipoleSplittingKernel>::ptr sp) {
kernels.push_back(sp);
}
/**
* Reset the alpha_s for all splitting kernels.
*/
void resetAlphaS(Ptr<AlphaSBase>::tptr);
/**
* Reset the splitting reweight for all splitting kernels.
*/
void resetReweight(Ptr<DipoleSplittingReweight>::tptr);
/**
* Return true, if the shower handler can generate a truncated
* shower for POWHEG style events generated using Matchbox
*/
virtual bool canHandleMatchboxTrunc() const { return false; }
/**
* Return true, if this cascade handler will perform reshuffling from hard
* process masses.
*/
virtual bool isReshuffling() const { return false; }
+ /**
+ * Return the relevant hard scale to be used in the profile scales
+ */
+ virtual Energy hardScale() const {
+ return muPt;
+ }
+
protected:
typedef multimap<DipoleIndex,Ptr<DipoleSplittingGenerator>::ptr> GeneratorMap;
/**
* The main method which manages the showering of a subprocess.
*/
virtual tPPair cascade(tSubProPtr sub, XCPtr xcomb) {
return cascade(sub,xcomb,ZERO,ZERO);
}
/**
* The main method which manages the showering of a subprocess.
*/
tPPair cascade(tSubProPtr sub, XCPtr xcomb,
Energy optHardPt, Energy optCutoff);
/**
* Build splitting generators for the given
* dipole index.
*/
void getGenerators(const DipoleIndex&,
Ptr<DipoleSplittingReweight>::tptr rw =
Ptr<DipoleSplittingReweight>::tptr());
/**
* Setup the hard scales.
*/
void hardScales(Energy2 scale);
/**
* Return the evolution ordering
*/
Ptr<DipoleEvolutionOrdering>::tptr evolutionOrdering() const { return theEvolutionOrdering; }
/**
* Reshuffle to constituent mass shells
*/
void constituentReshuffle();
/**
* Access the generator map
*/
GeneratorMap& generators() { return theGenerators; }
/**
* Access the event record
*/
DipoleEventRecord& eventRecord() { return theEventRecord; }
/**
* Return the event record
*/
const DipoleEventRecord& eventRecord() const { return theEventRecord; }
/**
* Return the splitting kernels.
*/
const vector<Ptr<DipoleSplittingKernel>::ptr>& splittingKernels() const {
return kernels;
}
/**
* Realign the event such as to have the incoming partons along thre
* beam axes.
*/
bool realign();
private:
/**
* Perform the cascade.
*/
void doCascade(unsigned int& emDone,
Energy optHardPt = ZERO,
Energy optCutoff = ZERO);
/**
* Get the winning splitting for the
* given dipole and configuration.
*/
Energy getWinner(DipoleSplittingInfo& winner,
const Dipole& dip,
pair<bool,bool> conf,
Energy optHardPt = ZERO,
Energy optCutoff = ZERO);
/**
* Get the winning splitting for the
* given dipole and configuration.
*/
Energy getWinner(SubleadingSplittingInfo& winner,
Energy optHardPt = ZERO,
Energy optCutoff = ZERO);
/**
* Get the winning splitting for the
* given dipole and configuration.
*/
Energy getWinner(DipoleSplittingInfo& winner,
const DipoleIndex& index,
double emitterX, double spectatorX,
pair<bool,bool> conf,
tPPtr emitter, tPPtr spectator,
Energy startScale,
Energy optHardPt = ZERO,
Energy optCutoff = ZERO);
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
virtual IBPtr fullclone() const;
//@}
// If needed, insert declarations of virtual function defined in the
// InterfacedBase class here (using ThePEG-interfaced-decl in Emacs).
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();
/**
* Finalize this object. Called in the run phase just after a
* run has ended. Used eg. to write out statistics.
*/
virtual void dofinish();
//@}
private:
/**
* The splitting kernels to be used.
*/
vector<Ptr<DipoleSplittingKernel>::ptr> kernels;
/**
* The evolution ordering considered
*/
Ptr<DipoleEvolutionOrdering>::ptr theEvolutionOrdering;
/**
* The ConstituentReshuffler to be used
*/
Ptr<ConstituentReshuffler>::ptr constituentReshuffler;
/**
* The intrinsic pt generator to be used.
*/
Ptr<IntrinsicPtGenerator>::ptr intrinsicPtGenerator;
/**
* A global alpha_s to be used for all splitting kernels.
*/
Ptr<AlphaSBase>::ptr theGlobalAlphaS;
/**
* Apply chain ordering to events from matrix
* element corrections.
*/
bool chainOrderVetoScales;
/**
* Limit the number of emissions.
* Limit applied if > 0.
*/
unsigned int nEmissions;
/**
* Discard events which did not radiate.
*/
bool discardNoEmissions;
/**
* Perform the first MC@NLO emission only.
*/
bool firstMCatNLOEmission;
/**
* Switch on or off final state radiation.
*/
bool doFSR;
/**
* Switch on or off initial state radiation.
*/
bool doISR;
/**
* The realignment scheme
*/
int realignmentScheme;
private:
/**
* The verbosity level.
* 0 - print no info
* 1 - print diagnostic information on setting up
* splitting generators etc.
* 2 - print detailed event information for up to
* printEvent events.
* 3 - print dipole chains after each splitting.
*/
int verbosity;
/**
* See verbosity.
*/
int printEvent;
private:
/**
* The splitting generators indexed by the dipole
* indices they can work on.
*/
GeneratorMap theGenerators;
/**
* The evnt record used.
*/
DipoleEventRecord theEventRecord;
/**
* The number of shoer tries so far.
*/
unsigned int nTries;
/**
* Whether or not we did radiate anything
*/
bool didRadiate;
/**
* Whether or not we did realign the event
*/
bool didRealign;
private:
/**
* A freezing value for the renormalization scale
*/
Energy theRenormalizationScaleFreeze;
/**
* A freezing value for the factorization scale
*/
Energy theFactorizationScaleFreeze;
/**
* True, if we are showering on a MC@NLO S event
*/
bool isMCatNLOSEvent;
/**
* True, if we are showering on a MC@NLO H event
*/
bool isMCatNLOHEvent;
/**
* The matching subtraction, if appropriate
*/
Ptr<ShowerApproximation>::tptr theShowerApproximation;
/**
* True, if sampler should apply compensation
*/
bool theDoCompensate;
/**
* Return the number of accepted points after which the grid should
* be frozen
*/
unsigned long theFreezeGrid;
/**
* A pointer to the dipole event reweight object
*/
Ptr<DipoleEventReweight>::ptr theEventReweight;
/**
* True if no warnings have been issued yet
*/
static bool firstWarn;
/**
* The shower starting scale for the last event encountered
*/
Energy maxPt;
/**
* The shower hard scale for the last event encountered
*/
Energy muPt;
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<DipoleShowerHandler> initDipoleShowerHandler;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
DipoleShowerHandler & operator=(const DipoleShowerHandler &);
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of DipoleShowerHandler. */
template <>
struct BaseClassTrait<Herwig::DipoleShowerHandler,1> {
/** Typedef of the first base class of DipoleShowerHandler. */
typedef Herwig::ShowerHandler NthBase;
};
/** This template specialization informs ThePEG about the name of
* the DipoleShowerHandler class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::DipoleShowerHandler>
: public ClassTraitsBase<Herwig::DipoleShowerHandler> {
/** Return a platform-independent class name */
static string className() { return "Herwig::DipoleShowerHandler"; }
/**
* The name of a file containing the dynamic library where the class
* DipoleShowerHandler is implemented. It may also include several, space-separated,
* libraries if the class DipoleShowerHandler depends on other classes (base classes
* excepted). In this case the listed libraries will be dynamically
* linked in the order they are specified.
*/
static string library() { return "HwDipoleShower.so"; }
};
/** @endcond */
}
#endif /* HERWIG_DipoleShowerHandler_H */
diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbar.cc b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbar.cc
old mode 100644
new mode 100755
--- a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbar.cc
+++ b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbar.cc
@@ -1,242 +1,241 @@
// -*- C++ -*-
//
// MatchboxAmplitudellbarqqbar.cc is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2012 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 MatchboxAmplitudellbarqqbar class.
//
#include "MatchboxAmplitudellbarqqbar.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/EnumParticles.h"
using namespace Herwig;
MatchboxAmplitudellbarqqbar::MatchboxAmplitudellbarqqbar() {}
MatchboxAmplitudellbarqqbar::~MatchboxAmplitudellbarqqbar() {}
IBPtr MatchboxAmplitudellbarqqbar::clone() const {
return new_ptr(*this);
}
IBPtr MatchboxAmplitudellbarqqbar::fullclone() const {
return new_ptr(*this);
}
void MatchboxAmplitudellbarqqbar::doinit() {
MatchboxZGammaAmplitude::doinit();
MZ = getParticleData(ParticleID::Z0)->hardProcessMass();
GZ = getParticleData(ParticleID::Z0)->hardProcessWidth();
MW = getParticleData(ParticleID::Wplus)->hardProcessMass();
GW = getParticleData(ParticleID::Wplus)->hardProcessWidth();
CA = SM().Nc();
CF = (SM().Nc()*SM().Nc()-1.)/(2.*SM().Nc());
nPoints(4);
}
void MatchboxAmplitudellbarqqbar::doinitrun() {
MatchboxZGammaAmplitude::doinitrun();
MZ = getParticleData(ParticleID::Z0)->hardProcessMass();
GZ = getParticleData(ParticleID::Z0)->hardProcessWidth();
MW = getParticleData(ParticleID::Wplus)->hardProcessMass();
GW = getParticleData(ParticleID::Wplus)->hardProcessWidth();
CA = SM().Nc();
CF = (SM().Nc()*SM().Nc()-1.)/(2.*SM().Nc());
nPoints(4);
}
bool MatchboxAmplitudellbarqqbar::canHandle(const PDVector& proc) const {
if ( proc.size() != 4 )
return false;
PDVector xproc = proc;
if ( xproc[0]->CC() )
xproc[0] = xproc[0]->CC();
if ( xproc[1]->CC() )
xproc[1] = xproc[1]->CC();
PDVector::iterator lepton = xproc.begin();
long leptonId = 0;
for ( ; lepton != xproc.end(); ++lepton )
if ( (**lepton).id() == 11 ||
(**lepton).id() == 13 ||
(**lepton).id() == 15 ) {
break;
}
if ( lepton == xproc.end() )
return false;
leptonId = (**lepton).id();
xproc.erase(lepton);
PDVector::iterator antiLepton = xproc.begin();
for ( ; antiLepton != xproc.end(); ++antiLepton )
if ( (**antiLepton).id() == -leptonId ) {
break;
}
if ( antiLepton == xproc.end() )
return false;
xproc.erase(antiLepton);
+
PDVector::iterator quark = xproc.begin();
long quarkId = 0;
for ( ; quark != xproc.end(); ++quark )
- if ( abs((**quark).id()) < 6 &&
- (**quark).id() > 0 &&
- (**quark).hardProcessMass() == ZERO ) {
+ if ( abs((**quark).id()) < 7 &&
+ (**quark).id() > 0 ) {
break;
}
if ( quark == xproc.end() )
return false;
quarkId = (**quark).id();
xproc.erase(quark);
+
PDVector::iterator antiQuark = xproc.begin();
for ( ; antiQuark != xproc.end(); ++antiQuark )
if ( (**antiQuark).id() == -quarkId ) {
break;
}
if ( antiQuark == xproc.end() )
return false;
xproc.erase(antiQuark);
return xproc.empty();
}
void MatchboxAmplitudellbarqqbar::prepareAmplitudes(Ptr<MatchboxMEBase>::tcptr me) {
if ( !calculateTreeAmplitudes() ) {
MatchboxZGammaAmplitude::prepareAmplitudes(me);
return;
}
amplitudeScale(sqrt(lastSHat()));
setupLeptons(0,amplitudeMomentum(0),
1,amplitudeMomentum(1));
- momentum(2,amplitudeMomentum(2));
- momentum(3,amplitudeMomentum(3));
+ setupQuarks(2,amplitudeMomentum(2),
+ 3,amplitudeMomentum(3));
MatchboxZGammaAmplitude::prepareAmplitudes(me);
}
Complex MatchboxAmplitudellbarqqbar::evaluate(size_t, const vector<int>& hel, Complex& largeN) {
- if ( abs(hel[2]+hel[3]) != 2 ) {
+ if ( abs(hel[2])+abs(hel[3]) != 2 ) {
largeN = 0.;
return 0.;
}
const LorentzVector<Complex>& leptonLeft
- = llbarLeftCurrent(0,hel[0],1,hel[1]);
+ = llbarLeftCurrent(0,hel[0],1,hel[1]);
const LorentzVector<Complex>& leptonRight
- = llbarRightCurrent(0,hel[0],1,hel[1]);
+ = llbarRightCurrent(0,hel[0],1,hel[1]);
- Complex LL =
- hel[2] == 1 ? leptonLeft.dot( qqbarLeftCurrent (2,hel[2],3,hel[3])) : 0.;
- Complex RL =
- hel[2] == 1 ? leptonRight.dot(qqbarLeftCurrent (2,hel[2],3,hel[3])) : 0.;
- Complex LR =
- hel[2] == -1 ? leptonLeft.dot( qqbarRightCurrent(2,hel[2],3,hel[3])) : 0.;
- Complex RR =
- hel[2] == -1 ? leptonRight.dot(qqbarRightCurrent(2,hel[2],3,hel[3])) : 0.;
+ const LorentzVector<Complex>& quarkLeft
+ = qqbarLeftCurrent(2,hel[2],3,hel[3]);
+ const LorentzVector<Complex>& quarkRight
+ = qqbarRightCurrent(2,hel[2],3,hel[3]);
+
+ Complex LL = leptonLeft.dot( quarkLeft );
+ Complex RL = leptonRight.dot( quarkLeft );
+ Complex LR = leptonLeft.dot( quarkRight );
+ Complex RR = leptonRight.dot( quarkRight );
double bProp = (amplitudeMomentum(0)+amplitudeMomentum(1)).m2()/lastSHat();
Complex gamma = 0.0;
if ( includeGamma() )
gamma = Complex(0.,-1.)*(-amplitudePartonData()[2]->iCharge()/3.)*
(LL + RL + LR + RR)/bProp;
bool up = abs(amplitudePartonData()[2]->id()) % 2 == 0;
Complex Z = 0.0;
if ( includeZ() )
Z = Complex(0.,-1.)*
- (standardModel()->le()*(up ? standardModel()->lu() : standardModel()->ld())*LL +
- standardModel()->re()*(up ? standardModel()->lu() : standardModel()->ld())*RL +
- standardModel()->le()*(up ? standardModel()->ru() : standardModel()->rd())*LR +
+ (standardModel()->le()*(up ? standardModel()->lu() : standardModel()->ld())*LL +
+ standardModel()->re()*(up ? standardModel()->lu() : standardModel()->ld())*RL +
+ standardModel()->le()*(up ? standardModel()->ru() : standardModel()->rd())*LR +
standardModel()->re()*(up ? standardModel()->ru() : standardModel()->rd())*RR)/
Complex(bProp-sqr(MZ)/lastSHat(),MZ*GZ/lastSHat());
-
+
Complex res = 4.*Constants::pi*SM().alphaEMMZ()*(gamma+Z);
largeN = res;
return res;
}
Complex MatchboxAmplitudellbarqqbar::evaluateOneLoop(size_t, const vector<int>& hel) {
- if ( abs(hel[2]+hel[3]) != 2 ) {
- return 0.;
- }
+ const LorentzVector<Complex>& leptonLeft
+ = llbarLeftCurrent(0,hel[0],1,hel[1]);
+ const LorentzVector<Complex>& leptonRight
+ = llbarRightCurrent(0,hel[0],1,hel[1]);
- const LorentzVector<Complex>& leptonLeft
- = llbarLeftCurrent(0,hel[0],1,hel[1]);
- const LorentzVector<Complex>& leptonRight
- = llbarRightCurrent(0,hel[0],1,hel[1]);
+ const LorentzVector<Complex>& quarkLeft
+ = qqbarLeftOneLoopCurrent(2,hel[2],3,hel[3]);
+ const LorentzVector<Complex>& quarkRight
+ = qqbarRightOneLoopCurrent(2,hel[2],3,hel[3]);
- Complex LL =
- hel[2] == 1 ? leptonLeft.dot( qqbarLeftOneLoopCurrent (2,hel[2],3,hel[3])) : 0.;
- Complex RL =
- hel[2] == 1 ? leptonRight.dot(qqbarLeftOneLoopCurrent (2,hel[2],3,hel[3])) : 0.;
- Complex LR =
- hel[2] == -1 ? leptonLeft.dot( qqbarRightOneLoopCurrent(2,hel[2],3,hel[3])) : 0.;
- Complex RR =
- hel[2] == -1 ? leptonRight.dot(qqbarRightOneLoopCurrent(2,hel[2],3,hel[3])) : 0.;
+ Complex LL = leptonLeft.dot( quarkLeft );
+ Complex RL = leptonRight.dot( quarkLeft );
+ Complex LR = leptonLeft.dot( quarkRight );
+ Complex RR = leptonRight.dot( quarkRight );
double bProp = (amplitudeMomentum(0)+amplitudeMomentum(1)).m2()/lastSHat();
Complex gamma = 0.0;
if ( includeGamma() )
gamma = Complex(0.,-1.)*(-amplitudePartonData()[2]->iCharge()/3.)*
(LL + RL + LR + RR)/bProp;
bool up = abs(amplitudePartonData()[2]->id()) % 2 == 0;
Complex Z = 0.0;
if ( includeZ() )
Z = Complex(0.,-1.)*
(standardModel()->le()*(up ? standardModel()->lu() : standardModel()->ld())*LL +
standardModel()->re()*(up ? standardModel()->lu() : standardModel()->ld())*RL +
standardModel()->le()*(up ? standardModel()->ru() : standardModel()->rd())*LR +
standardModel()->re()*(up ? standardModel()->ru() : standardModel()->rd())*RR)/
Complex(bProp-sqr(MZ)/lastSHat(),MZ*GZ/lastSHat());
Complex res = (SM().alphaS()/(2.*Constants::pi))*4.*Constants::pi*SM().alphaEMMZ()*(gamma+Z);
return res;
}
// If needed, insert default implementations of virtual function defined
// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs).
void MatchboxAmplitudellbarqqbar::persistentOutput(PersistentOStream &) const {}
void MatchboxAmplitudellbarqqbar::persistentInput(PersistentIStream &, int) {}
// *** Attention *** The following static variable is needed for the type
// description system in ThePEG. Please check that the template arguments
// are correct (the class and its base class), and that the constructor
// arguments are correct (the class name and the name of the dynamically
// loadable library where the class implementation can be found).
DescribeClass<MatchboxAmplitudellbarqqbar,MatchboxZGammaAmplitude>
- describeHerwigMatchboxAmplitudellbarqqbar("Herwig::MatchboxAmplitudellbarqqbar", "HwMatchboxBuiltin.so");
+describeHerwigMatchboxAmplitudellbarqqbar("Herwig::MatchboxAmplitudellbarqqbar", "HwMatchboxBuiltin.so");
void MatchboxAmplitudellbarqqbar::Init() {
static ClassDocumentation<MatchboxAmplitudellbarqqbar> documentation
("MatchboxAmplitudellbarqqbar");
}
diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbar.h b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbar.h
old mode 100644
new mode 100755
--- a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbar.h
+++ b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbar.h
@@ -1,187 +1,186 @@
// -*- C++ -*-
//
// MatchboxAmplitudellbarqqbar.h is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2012 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_MatchboxAmplitudellbarqqbar_H
#define Herwig_MatchboxAmplitudellbarqqbar_H
//
// This is the declaration of the MatchboxAmplitudellbarqqbar class.
//
#include "Herwig/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxZGammaAmplitude.h"
#include "Herwig/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxCurrents.h"
namespace Herwig {
using namespace ThePEG;
/**
* \ingroup Matchbox
* \author Simon Platzer
*
* \brief MatchboxAmplitudellbarqqbar
*/
class MatchboxAmplitudellbarqqbar:
public MatchboxZGammaAmplitude, public MatchboxCurrents {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
MatchboxAmplitudellbarqqbar();
/**
* The destructor.
*/
virtual ~MatchboxAmplitudellbarqqbar();
//@}
public:
/**
* Return true, if this amplitude can handle the given process.
*/
virtual bool canHandle(const PDVector&) const;
/**
* Return the (tree-level) order in \f$g_S\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInGs() const { return 0; }
/**
* Return the (tree-level) order in \f$g_{EM}\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInGem() const { return 2; }
/**
* Return true, if this amplitude is capable of calculating one-loop
* (QCD) corrections.
*/
virtual bool haveOneLoop() const { return true; }
/**
* Calculate the tree level amplitudes for the phasespace point
* stored in lastXComb.
*/
virtual void prepareAmplitudes(Ptr<MatchboxMEBase>::tcptr);
/**
* Evaluate the amplitude for the given colour tensor id and
* helicity assignment
*/
virtual Complex evaluate(size_t, const vector<int>&, Complex&);
/**
* Evaluate the amplitude for the given colour tensor id and
* helicity assignment
*/
virtual Complex evaluateOneLoop(size_t, const vector<int>&);
/**
- * Return true, if one loop corrections are given in the conventions
- * of BDK.
+ * Return true if one loop corrections are given in the conventions of everything expanded - this is currently the only convention available in DipoleMIOperator.cc
*/
- virtual bool isBDK() const { return true; }
+ virtual bool isExpanded() const { return true; }
/**
* Return the value of the dimensional regularization
* parameter. Note that renormalization scale dependence is fully
* restored in DipoleIOperator.
*/
virtual Energy2 mu2() const { return lastSHat(); }
/**
* Flush all cashes.
*/
virtual void flushCaches() {
MatchboxCurrents::reset();
MatchboxZGammaAmplitude::flushCaches();
}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
virtual IBPtr fullclone() const;
//@}
// If needed, insert declarations of virtual function defined in the
// InterfacedBase class here (using ThePEG-interfaced-decl in Emacs).
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();
//@}
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MatchboxAmplitudellbarqqbar & operator=(const MatchboxAmplitudellbarqqbar &);
};
}
#endif /* Herwig_MatchboxAmplitudellbarqqbar_H */
diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbarg.cc b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbarg.cc
old mode 100644
new mode 100755
--- a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbarg.cc
+++ b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbarg.cc
@@ -1,249 +1,255 @@
// -*- C++ -*-
//
// MatchboxAmplitudellbarqqbarg.cc is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2012 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 MatchboxAmplitudellbarqqbarg class.
//
#include "MatchboxAmplitudellbarqqbarg.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/EnumParticles.h"
using namespace Herwig;
MatchboxAmplitudellbarqqbarg::MatchboxAmplitudellbarqqbarg() {}
MatchboxAmplitudellbarqqbarg::~MatchboxAmplitudellbarqqbarg() {}
IBPtr MatchboxAmplitudellbarqqbarg::clone() const {
return new_ptr(*this);
}
IBPtr MatchboxAmplitudellbarqqbarg::fullclone() const {
return new_ptr(*this);
}
void MatchboxAmplitudellbarqqbarg::doinit() {
MatchboxZGammaAmplitude::doinit();
MZ = getParticleData(ParticleID::Z0)->hardProcessMass();
GZ = getParticleData(ParticleID::Z0)->hardProcessWidth();
MW = getParticleData(ParticleID::Wplus)->hardProcessMass();
GW = getParticleData(ParticleID::Wplus)->hardProcessWidth();
CA = SM().Nc();
CF = (SM().Nc()*SM().Nc()-1.)/(2.*SM().Nc());
nPoints(5);
}
void MatchboxAmplitudellbarqqbarg::doinitrun() {
MatchboxZGammaAmplitude::doinitrun();
MZ = getParticleData(ParticleID::Z0)->hardProcessMass();
GZ = getParticleData(ParticleID::Z0)->hardProcessWidth();
MW = getParticleData(ParticleID::Wplus)->hardProcessMass();
GW = getParticleData(ParticleID::Wplus)->hardProcessWidth();
CA = SM().Nc();
CF = (SM().Nc()*SM().Nc()-1.)/(2.*SM().Nc());
nPoints(5);
}
bool MatchboxAmplitudellbarqqbarg::canHandle(const PDVector& proc) const {
if ( proc.size() != 5 )
return false;
PDVector xproc = proc;
if ( xproc[0]->CC() )
xproc[0] = xproc[0]->CC();
if ( xproc[1]->CC() )
xproc[1] = xproc[1]->CC();
PDVector::iterator lepton = xproc.begin();
long leptonId = 0;
for ( ; lepton != xproc.end(); ++lepton )
if ( (**lepton).id() == 11 ||
(**lepton).id() == 13 ||
(**lepton).id() == 15 ) {
break;
}
if ( lepton == xproc.end() )
return false;
leptonId = (**lepton).id();
xproc.erase(lepton);
PDVector::iterator antiLepton = xproc.begin();
for ( ; antiLepton != xproc.end(); ++antiLepton )
if ( (**antiLepton).id() == -leptonId ) {
break;
}
if ( antiLepton == xproc.end() )
return false;
xproc.erase(antiLepton);
+
PDVector::iterator quark = xproc.begin();
long quarkId = 0;
for ( ; quark != xproc.end(); ++quark )
- if ( abs((**quark).id()) < 6 &&
- (**quark).id() > 0 &&
- (**quark).hardProcessMass() == ZERO ) {
+ if ( abs((**quark).id()) < 7 &&
+ (**quark).id() > 0 ) {
break;
}
if ( quark == xproc.end() )
return false;
quarkId = (**quark).id();
xproc.erase(quark);
+
PDVector::iterator antiQuark = xproc.begin();
for ( ; antiQuark != xproc.end(); ++antiQuark )
if ( (**antiQuark).id() == -quarkId ) {
break;
}
if ( antiQuark == xproc.end() )
return false;
xproc.erase(antiQuark);
if ( xproc.size() != 1 )
return false;
return xproc[0]->id() == 21;
}
+
void MatchboxAmplitudellbarqqbarg::prepareAmplitudes(Ptr<MatchboxMEBase>::tcptr me) {
if ( !calculateTreeAmplitudes() ) {
MatchboxZGammaAmplitude::prepareAmplitudes(me);
return;
}
amplitudeScale(sqrt(lastSHat()));
setupLeptons(0,amplitudeMomentum(0),
1,amplitudeMomentum(1));
- momentum(2,amplitudeMomentum(2));
- momentum(3,amplitudeMomentum(3));
+ setupQuarks(2,amplitudeMomentum(2),
+ 3,amplitudeMomentum(3));
+
momentum(4,amplitudeMomentum(4));
MatchboxZGammaAmplitude::prepareAmplitudes(me);
}
+
Complex MatchboxAmplitudellbarqqbarg::evaluate(size_t, const vector<int>& hel, Complex& largeN) {
assert(nPoints() == 5);
- if ( abs(hel[2]+hel[3]) != 2 ) {
+ if ( abs(hel[2])+abs(hel[3]) != 2 ) {
largeN = 0.;
return 0.;
}
const LorentzVector<Complex>& leptonLeft
= llbarLeftCurrent(0,hel[0],1,hel[1]);
const LorentzVector<Complex>& leptonRight
= llbarRightCurrent(0,hel[0],1,hel[1]);
- Complex LL =
- hel[2] == 1 ? leptonLeft.dot( qqbargLeftCurrent (2,hel[2],3,hel[3],4,hel[4])) : 0.;
- Complex RL =
- hel[2] == 1 ? leptonRight.dot(qqbargLeftCurrent (2,hel[2],3,hel[3],4,hel[4])) : 0.;
- Complex LR =
- hel[2] == -1 ? leptonLeft.dot( qqbargRightCurrent(2,hel[2],3,hel[3],4,hel[4])) : 0.;
- Complex RR =
- hel[2] == -1 ? leptonRight.dot(qqbargRightCurrent(2,hel[2],3,hel[3],4,hel[4])) : 0.;
+ const LorentzVector<Complex>& quarkLeft
+ = qqbargLeftCurrent(2,hel[2],3,hel[3],4,hel[4]);
+ const LorentzVector<Complex>& quarkRight
+ = qqbargRightCurrent(2,hel[2],3,hel[3],4,hel[4]);
+
+ Complex LL = leptonLeft.dot( quarkLeft );
+ Complex RL = leptonRight.dot( quarkLeft );
+ Complex LR = leptonLeft.dot( quarkRight );
+ Complex RR = leptonRight.dot( quarkRight );
double bProp = (amplitudeMomentum(0)+amplitudeMomentum(1)).m2()/lastSHat();
Complex gamma = 0.0;
if ( includeGamma() )
gamma = Complex(0.,-1.)*(-amplitudePartonData()[2]->iCharge()/3.)*
(LL + RL + LR + RR)/bProp;
bool up = abs(amplitudePartonData()[2]->id()) % 2 == 0;
Complex Z = 0.0;
if ( includeZ() )
Z = Complex(0.,-1.)*
(standardModel()->le()*(up ? standardModel()->lu() : standardModel()->ld())*LL +
standardModel()->re()*(up ? standardModel()->lu() : standardModel()->ld())*RL +
standardModel()->le()*(up ? standardModel()->ru() : standardModel()->rd())*LR +
standardModel()->re()*(up ? standardModel()->ru() : standardModel()->rd())*RR)/
- Complex(bProp-sqr(MZ)/lastSHat(),MZ*GZ/lastSHat());
+ Complex(bProp-sqr(MZ)/lastSHat(),MZ*GZ/lastSHat());
Complex res = 4.*Constants::pi*SM().alphaEMMZ()*sqrt(4.*Constants::pi*SM().alphaS())*(gamma+Z);
largeN = res;
return res;
}
+
Complex MatchboxAmplitudellbarqqbarg::evaluateOneLoop(size_t, const vector<int>& hel) {
if ( abs(hel[2]+hel[3]) != 2 ) {
return 0.;
}
const LorentzVector<Complex>& leptonLeft
= llbarLeftCurrent(0,hel[0],1,hel[1]);
const LorentzVector<Complex>& leptonRight
= llbarRightCurrent(0,hel[0],1,hel[1]);
Complex LL =
hel[2] == 1 ? leptonLeft.dot( qqbargLeftOneLoopCurrent (2,hel[2],3,hel[3],4,hel[4])) : 0.;
Complex RL =
hel[2] == 1 ? leptonRight.dot(qqbargLeftOneLoopCurrent (2,hel[2],3,hel[3],4,hel[4])) : 0.;
Complex LR =
hel[2] == -1 ? leptonLeft.dot( qqbargRightOneLoopCurrent(2,hel[2],3,hel[3],4,hel[4])) : 0.;
Complex RR =
hel[2] == -1 ? leptonRight.dot(qqbargRightOneLoopCurrent(2,hel[2],3,hel[3],4,hel[4])) : 0.;
double bProp = (amplitudeMomentum(0)+amplitudeMomentum(1)).m2()/lastSHat();
Complex gamma = 0.0;
if ( includeGamma() )
gamma = Complex(0.,-1.)*(-amplitudePartonData()[2]->iCharge()/3.)*
(LL + RL + LR + RR)/bProp;
bool up = abs(amplitudePartonData()[2]->id()) % 2 == 0;
Complex Z = 0.0;
if ( includeZ() )
Z = Complex(0.,-1.)*
(standardModel()->le()*(up ? standardModel()->lu() : standardModel()->ld())*LL +
standardModel()->re()*(up ? standardModel()->lu() : standardModel()->ld())*RL +
standardModel()->le()*(up ? standardModel()->ru() : standardModel()->rd())*LR +
standardModel()->re()*(up ? standardModel()->ru() : standardModel()->rd())*RR)/
Complex(bProp-sqr(MZ)/lastSHat(),MZ*GZ/lastSHat());
Complex res =
(SM().alphaS()/(2.*Constants::pi))*
4.*Constants::pi*SM().alphaEMMZ()*sqrt(4.*Constants::pi*SM().alphaS())*(gamma+Z);
return res;
}
// If needed, insert default implementations of virtual function defined
// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs).
void MatchboxAmplitudellbarqqbarg::persistentOutput(PersistentOStream &) const {}
void MatchboxAmplitudellbarqqbarg::persistentInput(PersistentIStream &, int) {}
// *** Attention *** The following static variable is needed for the type
// description system in ThePEG. Please check that the template arguments
// are correct (the class and its base class), and that the constructor
// arguments are correct (the class name and the name of the dynamically
// loadable library where the class implementation can be found).
DescribeClass<MatchboxAmplitudellbarqqbarg,MatchboxZGammaAmplitude>
describeHerwigMatchboxAmplitudellbarqqbarg("Herwig::MatchboxAmplitudellbarqqbarg", "HwMatchboxBuiltin.so");
void MatchboxAmplitudellbarqqbarg::Init() {
static ClassDocumentation<MatchboxAmplitudellbarqqbarg> documentation
("MatchboxAmplitudellbarqqbarg");
}
diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbarg.h b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbarg.h
old mode 100644
new mode 100755
--- a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbarg.h
+++ b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbarg.h
@@ -1,188 +1,187 @@
// -*- C++ -*-
//
// MatchboxAmplitudellbarqqbarg.h is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2012 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_MatchboxAmplitudellbarqqbarg_H
#define Herwig_MatchboxAmplitudellbarqqbarg_H
//
// This is the declaration of the MatchboxAmplitudellbarqqbarg class.
//
#include "Herwig/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxZGammaAmplitude.h"
#include "Herwig/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxCurrents.h"
namespace Herwig {
using namespace ThePEG;
/**
* \ingroup Matchbox
* \author Simon Platzer
*
* \brief MatchboxAmplitudellbarqqbarg
*/
class MatchboxAmplitudellbarqqbarg:
public MatchboxZGammaAmplitude, public MatchboxCurrents {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
MatchboxAmplitudellbarqqbarg();
/**
* The destructor.
*/
virtual ~MatchboxAmplitudellbarqqbarg();
//@}
public:
/**
* Return true, if this amplitude can handle the given process.
*/
virtual bool canHandle(const PDVector&) const;
/**
* Return the (tree-level) order in \f$g_S\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInGs() const { return 1; }
/**
* Return the (tree-level) order in \f$g_{EM}\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInGem() const { return 2; }
/**
* Return true, if this amplitude is capable of calculating one-loop
* (QCD) corrections.
*/
virtual bool haveOneLoop() const { return true; }
/**
* Calculate the tree level amplitudes for the phasespace point
* stored in lastXComb.
*/
virtual void prepareAmplitudes(Ptr<MatchboxMEBase>::tcptr);
/**
* Evaluate the amplitude for the given colour tensor id and
* helicity assignment
*/
virtual Complex evaluate(size_t, const vector<int>&, Complex&);
/**
* Evaluate the amplitude for the given colour tensor id and
* helicity assignment
*/
virtual Complex evaluateOneLoop(size_t, const vector<int>&);
/**
* Return true, if one loop corrections are given in the conventions
* of BDK.
*/
virtual bool isBDK() const { return true; }
/**
* Return the value of the dimensional regularization
* parameter. Note that renormalization scale dependence is fully
* restored in DipoleIOperator.
*/
virtual Energy2 mu2() const { return lastSHat(); }
- //virtual Energy2 mu2() const { return 10*GeV2; }
/**
* Flush all cashes.
*/
virtual void flushCaches() {
MatchboxCurrents::reset();
MatchboxZGammaAmplitude::flushCaches();
}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
virtual IBPtr fullclone() const;
//@}
// If needed, insert declarations of virtual function defined in the
// InterfacedBase class here (using ThePEG-interfaced-decl in Emacs).
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();
//@}
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MatchboxAmplitudellbarqqbarg & operator=(const MatchboxAmplitudellbarqqbarg &);
};
}
#endif /* Herwig_MatchboxAmplitudellbarqqbarg_H */
diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxCurrents.cc b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxCurrents.cc
old mode 100644
new mode 100755
--- a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxCurrents.cc
+++ b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxCurrents.cc
@@ -1,2582 +1,2861 @@
// - * - C++ - * -
//
// MatchboxCurrents.cc is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2012 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.
//
#include "MatchboxCurrents.h"
#include "Herwig/Utilities/Maths.h"
using namespace Herwig;
+using namespace Herwig::Math;
using Constants::pi;
namespace {
-const static LorentzVector<Complex> czero(0.,0.,0.,0.);
+ const static LorentzVector<Complex> czero(0.,0.,0.,0.);
-inline Complex csqr(const Complex & a) {
- return a * a;
-}
+ inline Complex csqr(const Complex & a) {
+ return a * a;
+ }
-inline double theta(const double x) {
- if ( x >= 0. )
- return 1.;
- return 0.;
-}
+ inline double theta(const double x) {
+ if ( x >= 0. )
+ return 1.;
+ return 0.;
+ }
+ inline double sign(const double x) {
+ if ( x >= 0. )
+ return 1.;
+ return -1.;
+ }
-inline double sign(const double x) {
- if ( x >= 0. )
- return 1.;
- return -1.;
-}
+ // quick'n'dirty fix to template troubles
-// quick'n'dirty fix to template troubles
+ Complex operator * (const Complex& a, const double b) {
+ return Complex(a.real() * b,a.imag() * b);
+ }
-Complex operator * (const Complex& a, const double b) {
- return Complex(a.real() * b,a.imag() * b);
-}
+ Complex operator * (const double b, const Complex& a) {
+ return Complex(a.real() * b,a.imag() * b);
+ }
-Complex operator * (const double b, const Complex& a) {
- return Complex(a.real() * b,a.imag() * b);
-}
+ Complex operator+(const Complex& a, const double b) {
+ return Complex(a.real()+b,a.imag());
+ }
-Complex operator+(const Complex& a, const double b) {
- return Complex(a.real()+b,a.imag());
-}
+ Complex operator+(const double b, const Complex& a) {
+ return Complex(a.real()+b,a.imag());
+ }
-Complex operator+(const double b, const Complex& a) {
- return Complex(a.real()+b,a.imag());
-}
+ Complex operator-(const Complex& a, const double b) {
+ return Complex(a.real()-b,a.imag());
+ }
-Complex operator-(const Complex& a, const double b) {
- return Complex(a.real()-b,a.imag());
-}
+ Complex operator-(const double b, const Complex& a) {
+ return Complex(b-a.real(),-a.imag());
+ }
-Complex operator-(const double b, const Complex& a) {
- return Complex(b-a.real(),-a.imag());
-}
-
-// end fix, needs to be looked at in ThePEG/Config/
+ // end fix, needs to be looked at in ThePEG/Config/
}
+
void MatchboxCurrents::setupLeptons(const int l, const Lorentz5Momentum& pl,
const int lbar, const Lorentz5Momentum& plbar) {
- Lorentz5Momentum plFlat = pl;
- plFlat.setMass(ZERO); plFlat.rescaleEnergy();
+
+ const Energy4 Delta = (sqr(pl*plbar) - (pl*pl)*(plbar*plbar));
+ const Energy2 prod = pl*plbar;
+
+ // Variable to contain the sign of pl*plbar
+ double sgn;
+ if (prod < ZERO ) {sgn = -1;}
+ else if (prod > ZERO) {sgn = 1;}
+ else {sgn = 0;}
+
+ InvEnergy2 fact = 0.5/(sgn*sqrt(Delta));
+
+ Lorentz5Momentum lmassless = ( double(fact*(sgn*sqrt(Delta) + prod))*pl - double(fact*( pl*pl))*plbar );
+ Lorentz5Momentum lbarmassless = ( double(fact*(sgn*sqrt(Delta) + prod))*plbar - double(fact*(plbar*plbar))*pl );
+
+ lmassless.setMass(ZERO); lmassless.rescaleEnergy();
+ lbarmassless.setMass(ZERO); lbarmassless.rescaleEnergy();
+
if ( pl.t() < ZERO )
- plFlat.setT(-plFlat.t());
- momentum(l,plFlat,true,pl.mass());
- Lorentz5Momentum plbarFlat = plbar;
- plbarFlat.setMass(ZERO); plbarFlat.rescaleEnergy();
+ lmassless.setT(-lmassless.t());
+
if ( plbar.t() < ZERO )
- plbarFlat.setT(-plbarFlat.t());
- momentum(lbar,plbarFlat,true,plbar.mass());
+ lbarmassless.setT(-lbarmassless.t());
+
+ momentum(l,lmassless,true,pl.mass());
+ momentum(lbar,lbarmassless,true,plbar.mass());
}
+
+void MatchboxCurrents::setupQuarks(const int q, const Lorentz5Momentum& pq,
+ const int qbar, const Lorentz5Momentum& pqbar) {
+
+ const Energy4 Delta = (sqr(pq*pqbar) - (pq*pq)*(pqbar*pqbar));
+ const Energy2 prod = pq*pqbar;
+
+ // Variable to contain the sign of pq*pqbar
+ double sgn;
+ if (prod < ZERO) {sgn = -1;}
+ else if (prod > ZERO) {sgn = 1;}
+ else {sgn = 0;}
+
+ InvEnergy2 fact = 0.5/(sgn*sqrt(Delta));
+
+ Lorentz5Momentum qmassless = ( double(fact*(sgn*sqrt(Delta) + prod))*pq - double(fact*(pq*pq))*pqbar );
+ Lorentz5Momentum qbarmassless = ( double(fact*(sgn*sqrt(Delta) + prod))*pqbar - double(fact*(pqbar*pqbar))*pq );
+
+ qmassless.setMass(ZERO); qmassless.rescaleEnergy();
+ qbarmassless.setMass(ZERO); qbarmassless.rescaleEnergy();
+
+ if ( pq.t() < ZERO )
+ qmassless.setT(-qmassless.t());
+
+ if ( pqbar.t() < ZERO )
+ qbarmassless.setT(-qbarmassless.t());
+
+ momentum(q,qmassless,true,pq.mass());
+ momentum(qbar,qbarmassless,true,pqbar.mass());
+}
+
+
const LorentzVector<Complex>& MatchboxCurrents::llbarLeftCurrent(const int l, const int lHel,
const int lbar, const int lbarHel) {
if ( getCurrent(hash<0>(1,1,l,lHel,lbar,lbarHel)) ) {
if ( lHel == 1 && lbarHel == 1 )
cacheCurrent(Complex(0.,1.) * minusCurrent(l,lbar));
if ( lHel == 1 && lbarHel == -1 )
cacheCurrent((Complex(0.,2.) * mass(lbar)/plusProduct(l,lbar)) * momentum(l));
if ( lHel == -1 && lbarHel == 1 )
cacheCurrent((Complex(0.,-2.) * mass(l)/minusProduct(l,lbar)) * momentum(lbar));
if ( lHel == -1 && lbarHel == -1 )
cacheCurrent((Complex(0.,1.) * mass(l) * mass(lbar)/invariant(l,lbar)) * minusCurrent(lbar,l));
}
+
return cachedCurrent();
-
}
const LorentzVector<Complex>& MatchboxCurrents::llbarRightCurrent(const int l, const int lHel,
const int lbar, const int lbarHel) {
if ( getCurrent(hash<0>(2,1,l,lHel,lbar,lbarHel)) ) {
if ( lHel == 1 && lbarHel == 1 )
cacheCurrent((Complex(0.,1.) * mass(l) * mass(lbar)/invariant(l,lbar)) * minusCurrent(l,lbar));
if ( lHel == 1 && lbarHel == -1 )
cacheCurrent((Complex(0.,-2.) * mass(l)/plusProduct(l,lbar)) * momentum(lbar));
if ( lHel == -1 && lbarHel == 1 )
cacheCurrent((Complex(0.,2.) * mass(lbar)/minusProduct(l,lbar)) * momentum(l));
if ( lHel == -1 && lbarHel == -1 )
cacheCurrent(Complex(0.,1.) * minusCurrent(lbar,l));
}
+
return cachedCurrent();
+}
-}
const LorentzVector<Complex>& MatchboxCurrents::qqbarLeftCurrent(const int q, const int qHel,
const int qbar, const int qbarHel) {
- if ( qHel != 1 || qbarHel != 1 )
- return czero;
+ if ( getCurrent(hash<1>(1,1,q,qHel,qbar,qbarHel)) ) {
+ if ( qHel == 1 && qbarHel == 1 )
+ cacheCurrent(Complex(0.,1.) * minusCurrent(q,qbar));
+ if ( qHel == 1 && qbarHel == -1 )
+ cacheCurrent((Complex(0.,2.) * mass(qbar)/plusProduct(q,qbar)) * momentum(q));
+ if ( qHel == -1 && qbarHel == 1 )
+ cacheCurrent((Complex(0.,-2.) * mass(q)/minusProduct(q,qbar)) * momentum(qbar));
+ if ( qHel == -1 && qbarHel == -1 )
+ cacheCurrent((Complex(0.,1.) * mass(q) * mass(qbar)/invariant(q,qbar)) * minusCurrent(qbar,q));
+ }
- if ( getCurrent(hash<1>(1,1,q,qHel,qbar,qbarHel)) ) {
- cacheCurrent(Complex(0.,1.) * minusCurrent(q,qbar));
- }
#ifdef CHECK_MatchboxCurrents
checkCurrent("qqbarLeftCurrent",cachedCurrent(),momentum(q)+momentum(qbar));
#endif
+
return cachedCurrent();
-
}
const LorentzVector<Complex>& MatchboxCurrents::qqbarRightCurrent(const int q, const int qHel,
const int qbar, const int qbarHel) {
-
- if ( qHel != -1 || qbarHel != -1 )
- return czero;
-
+
if ( getCurrent(hash<1>(2,1,q,qHel,qbar,qbarHel)) ) {
- cacheCurrent(Complex(0.,1.) * minusCurrent(qbar,q));
+ if ( qHel == 1 && qbarHel == 1 )
+ cacheCurrent((Complex(0.,1.) * mass(q) * mass(qbar)/invariant(q,qbar)) * minusCurrent(q,qbar));
+ if ( qHel == 1 && qbarHel == -1 )
+ cacheCurrent((Complex(0.,-2.) * mass(q)/plusProduct(q,qbar)) * momentum(qbar));
+ if ( qHel == -1 && qbarHel == 1 )
+ cacheCurrent((Complex(0.,2.) * mass(qbar)/minusProduct(q,qbar)) * momentum(q));
+ if ( qHel == -1 && qbarHel == -1 )
+ cacheCurrent(Complex(0.,1.) * minusCurrent(qbar,q));
}
+
#ifdef CHECK_MatchboxCurrents
checkCurrent("qqbarRightCurrent",cachedCurrent(),momentum(q)+momentum(qbar));
#endif
+
return cachedCurrent();
+}
-}
const LorentzVector<Complex>& MatchboxCurrents::qqbargLeftCurrent(const int q, const int qHel,
const int qbar, const int qbarHel,
const int g, const int gHel) {
- if ( qHel != 1 || qbarHel != 1 )
- return czero;
-
if ( gHel == 1 ) {
if ( getCurrent(hash<2>(1,1,q,qHel,qbar,qbarHel,g,gHel)) ) {
- cacheCurrent(Complex(0.,sqrt(2.)) *
- ((minusProduct(q,qbar)/(minusProduct(q,g) * minusProduct(g,qbar))) * minusCurrent(q,qbar)
- +(1./minusProduct(g,qbar)) * minusCurrent(q,g)));
+
+ // Invariant products from propagator denominators
+ const Complex den_i = invariant(q,g) + (sqr(mass(q))/invariant(q,qbar))*invariant(qbar,g);
+ const Complex den_j = invariant(qbar,g) + (sqr(mass(qbar))/invariant(q,qbar))*invariant(q,g);
+
+ // 2*factor from the spinor definition of the negative helicity gluon
+ // Note that the gluon is outgoing so the polarisation vector of the hel=+1 gluon is conjugated to give the hel=-1 vector
+ const Complex cminus = sqrt(2.0) / minusProduct(g,q);
+
+ if ( qHel == 1 && qbarHel == 1 )
+ cacheCurrent( Complex(0.,1.)*cminus*( ((sqr(mass(q))*plusProduct(qbar,g)/(plusProduct(qbar,q)*den_i)) - (minusProduct(qbar,q)*plusProduct(g,qbar)/den_j))*minusCurrent(q, qbar) - (minusProduct(g,q)*plusProduct(g,qbar)/den_j)*minusCurrent(q,g) ) );
+ if ( qHel == 1 && qbarHel == -1 )
+ cacheCurrent( Complex(0.,1.)*cminus*(-mass(qbar)/plusProduct(qbar,q)) * ( ((sqr(mass(q))*plusProduct(qbar,g)/(plusProduct(qbar,q)*den_i)) - (plusProduct(qbar,g)*minusProduct(q,qbar)/den_j))*2*momentum(q) + (invariant(q,g)/den_j)*minusCurrent(q,g) ) );
+ if ( qHel == -1 && qbarHel == 1 )
+ cacheCurrent( Complex(0.,1.)*cminus*(mass(q)/minusProduct(qbar,q)) * ( ((sqr(mass(q))*plusProduct(g,qbar)/(plusProduct(q,qbar)*den_i)) - (plusProduct(g,qbar)*minusProduct(qbar,q)/den_j))*2*momentum(qbar) - (minusProduct(g,q)*plusProduct(g,qbar)/den_j)*minusCurrent(qbar,g) ) );
+ if ( qHel == -1 && qbarHel == -1 )
+ cacheCurrent( Complex(0.,1.)*cminus*(mass(qbar)*mass(q)/(invariant(q,qbar))) * ( ((sqr(mass(q))*plusProduct(g,qbar)/(plusProduct(q,qbar)*den_i)) - (minusProduct(q,qbar)*plusProduct(qbar,g)/den_j))*minusCurrent(qbar,q) + (invariant(q,g)/den_j)*minusCurrent(qbar,g) ) );
}
+
#ifdef CHECK_MatchboxCurrents
- checkCurrent("qqbargLeftCurrent",cachedCurrent(),momentum(q)+momentum(qbar)+momentum(g));
+ checkCurrent("qqbargLeftCurrent",cachedCurrent(),momentum(q)+momentum(qbar)+momentum(g));
#endif
+
return cachedCurrent();
}
if ( gHel == -1 ) {
- if ( getCurrent(hash<2>(1,1,q,qHel,qbar,qbarHel,g,gHel)) ) {
- cacheCurrent(Complex(0.,-sqrt(2.)) *
- ((plusProduct(q,qbar)/(plusProduct(q,g) * plusProduct(g,qbar))) * minusCurrent(q,qbar)
- +(1./plusProduct(q,g)) * minusCurrent(g,qbar)));
+ if ( getCurrent(hash<2>(1,1,q,qHel,qbar,qbarHel,g,gHel)) ) {
+
+ // Invariant products from propagator denominators
+ const Complex den_i = invariant(q,g) + (sqr(mass(q))/invariant(q,qbar))*invariant(qbar,g);
+ const Complex den_j = invariant(qbar,g) + (sqr(mass(qbar))/invariant(q,qbar))*invariant(q,g);
+
+ // 2*factor from the spinor definition of the positive helicity gluon
+ const Complex cplus = sqrt(2.0) / plusProduct(q,g);
+
+ if ( qHel == 1 && qbarHel == 1 )
+ cacheCurrent( Complex(0.,1.)*cplus*( ((sqr(mass(q))*minusProduct(g,qbar)/(minusProduct(q,qbar)*den_i)) - (minusProduct(qbar,g)*plusProduct(q,qbar)/den_j))*minusCurrent(q, qbar) - (invariant(q,g)/den_i)*minusCurrent(g,qbar) ) );
+ if ( qHel == 1 && qbarHel == -1 )
+ cacheCurrent( Complex(0.,1.)*cplus*(-mass(qbar)/plusProduct(qbar,q)) * ( ((sqr(mass(q))*minusProduct(g,qbar)/(minusProduct(q,qbar)*den_i)) - (plusProduct(qbar,q)*minusProduct(g,qbar)/den_j))*2*momentum(q) - (invariant(q,g)/den_i)*minusCurrent(g,q) ) );
+ if ( qHel == -1 && qbarHel == 1 )
+ cacheCurrent( Complex(0.,1.)*cplus*(mass(q)/minusProduct(qbar,q)) * ( ((sqr(mass(q))*minusProduct(qbar,g)/(minusProduct(qbar,q)*den_i)) - (minusProduct(qbar,g)*plusProduct(q,qbar)/den_j))*2*momentum(qbar) + (minusProduct(qbar,g)*plusProduct(q,g)/den_i)*minusCurrent(g,qbar) ) );
+ if ( qHel == -1 && qbarHel == -1 )
+ cacheCurrent( Complex(0.,1.)*cplus*(mass(qbar)*mass(q)/(invariant(q,qbar))) * ( ((sqr(mass(q))*minusProduct(qbar,g)/(minusProduct(qbar,q)*den_i)) - (plusProduct(qbar,q)*minusProduct(g,qbar)/den_j))*minusCurrent(qbar, q) + (minusProduct(qbar,g)*plusProduct(q,g)/den_i)*minusCurrent(g,q) ) );
}
+
#ifdef CHECK_MatchboxCurrents
- checkCurrent("qqbargLeftCurrent",cachedCurrent(),momentum(q)+momentum(qbar)+momentum(g));
+ checkCurrent("qqbargLeftCurrent",cachedCurrent(),momentum(q)+momentum(qbar)+momentum(g));
#endif
+
return cachedCurrent();
}
return czero;
-
}
const LorentzVector<Complex>& MatchboxCurrents::qqbargRightCurrent(const int q, const int qHel,
const int qbar, const int qbarHel,
const int g, const int gHel) {
- if ( qHel != -1 || qbarHel != -1 )
- return czero;
-
if ( gHel == 1 ) {
if ( getCurrent(hash<2>(2,1,q,qHel,qbar,qbarHel,g,gHel)) ) {
- cacheCurrent(Complex(0.,sqrt(2.)) *
- ((minusProduct(q,qbar)/(minusProduct(q,g) * minusProduct(g,qbar))) * minusCurrent(qbar,q)
- +(1./minusProduct(q,g)) * minusCurrent(qbar,g)));
+
+ // Invariant products from propagator denominators
+ const Complex den_i = invariant(q,g) + (sqr(mass(q))/invariant(q,qbar))*invariant(qbar,g);
+ const Complex den_j = invariant(qbar,g) + (sqr(mass(qbar))/invariant(q,qbar))*invariant(q,g);
+
+ // 2*factor from the spinor definition of the positive helicity gluon
+ const Complex cminus = sqrt(2.0) / minusProduct(g,q);
+
+ if ( qHel == 1 && qbarHel == 1 )
+ cacheCurrent( Complex(0.,1.)*cminus*(mass(qbar)*mass(q)/(invariant(q,qbar))) * ( ((sqr(mass(q))*plusProduct(qbar,g)/(plusProduct(qbar,q)*den_i)) - (minusProduct(qbar,q)*plusProduct(g,qbar)/den_j))*plusCurrent(qbar, q) + (plusProduct(qbar,g)*minusProduct(q,g)/den_i)*plusCurrent(g,q) ) );
+ if ( qHel == 1 && qbarHel == -1 )
+ cacheCurrent( Complex(0.,1.)*cminus*(mass(q)/plusProduct(qbar,q)) * ( ((sqr(mass(q))*plusProduct(qbar,g)/(plusProduct(qbar,q)*den_i)) - (plusProduct(qbar,g)*minusProduct(q,qbar)/den_j))*2*momentum(qbar) + (plusProduct(qbar,g)*minusProduct(q,g)/den_i)*plusCurrent(g,qbar) ) );
+ if ( qHel == -1 && qbarHel == 1 )
+ cacheCurrent( Complex(0.,1.)*cminus*(-mass(qbar)/minusProduct(qbar,q)) * ( ((sqr(mass(q))*plusProduct(g,qbar)/(plusProduct(q,qbar)*den_i)) - (minusProduct(qbar,q)*plusProduct(g,qbar)/den_j))*2*momentum(q) - (invariant(q,g)/den_i)*plusCurrent(g,q) ) );
+ if ( qHel == -1 && qbarHel == -1 )
+ cacheCurrent( Complex(0.,1.)*cminus*( ((sqr(mass(q))*plusProduct(g,qbar)/(plusProduct(q,qbar)*den_i)) - (plusProduct(qbar,g)*minusProduct(q,qbar)/den_j))*plusCurrent(q, qbar) - (invariant(q,g)/den_i)*plusCurrent(g,qbar) ) );
}
+
#ifdef CHECK_MatchboxCurrents
- checkCurrent("qqbargRightCurrent",cachedCurrent(),momentum(q)+momentum(qbar)+momentum(g));
+ checkCurrent("qqbargRightCurrent",cachedCurrent(),momentum(q)+momentum(qbar)+momentum(g));
#endif
+
return cachedCurrent();
}
if ( gHel == -1 ) {
if ( getCurrent(hash<2>(2,1,q,qHel,qbar,qbarHel,g,gHel)) ) {
- cacheCurrent(Complex(0.,-sqrt(2.)) *
- ((plusProduct(q,qbar)/(plusProduct(q,g) * plusProduct(g,qbar))) * minusCurrent(qbar,q)
- +(1./plusProduct(g,qbar)) * minusCurrent(g,q)));
+
+ // Invariant products from propagator denominators
+ const Complex den_i = invariant(q,g) + (sqr(mass(q))/invariant(q,qbar))*invariant(qbar,g);
+ const Complex den_j = invariant(qbar,g) + (sqr(mass(qbar))/invariant(q,qbar))*invariant(q,g);
+
+ // 2*factor from the spinor definition of the positive helicity gluon
+ const Complex cplus = sqrt(2.0) / plusProduct(q,g);
+
+ if ( qHel == 1 && qbarHel == 1 )
+ cacheCurrent( Complex(0.,1.)*cplus*(mass(qbar)*mass(q)/(invariant(q,qbar))) * ( ((sqr(mass(q))*minusProduct(g,qbar)/(minusProduct(q,qbar)*den_i)) - (plusProduct(q,qbar)*minusProduct(qbar,g)/den_j))*plusCurrent(qbar, q) + (invariant(q,g)/den_j)*plusCurrent(qbar,g) ) );
+ if ( qHel == 1 && qbarHel == -1 )
+ cacheCurrent( Complex(0.,1.)*cplus*(mass(q)/plusProduct(qbar,q)) * ( ((sqr(mass(q))*minusProduct(g,qbar)/(minusProduct(q,qbar)*den_i)) - (minusProduct(g,qbar)*plusProduct(qbar,q)/den_j))*2*momentum(qbar) - (plusProduct(g,q)*minusProduct(g,qbar)/den_j)*plusCurrent(qbar,g) ) );
+ if ( qHel == -1 && qbarHel == 1 )
+ cacheCurrent( Complex(0.,1.)*cplus*(-mass(qbar)/minusProduct(qbar,q)) * ( ((sqr(mass(q))*minusProduct(qbar,g)/(minusProduct(qbar,q)*den_i)) - (minusProduct(qbar,g)*plusProduct(q,qbar)/den_j))*2*momentum(q) + (invariant(q,g)/den_j)*plusCurrent(q,g) ) );
+ if ( qHel == -1 && qbarHel == -1 )
+ cacheCurrent( Complex(0.,1.)*cplus*( ((sqr(mass(q))*minusProduct(qbar,g)/(minusProduct(qbar,q)*den_i)) - (plusProduct(qbar,q)*minusProduct(g,qbar)/den_j))*plusCurrent(q, qbar) - (plusProduct(g,q)*minusProduct(g,qbar)/den_j)*plusCurrent(q,g) ) );
}
+
#ifdef CHECK_MatchboxCurrents
- checkCurrent("qqbargRightCurrent",cachedCurrent(),momentum(q)+momentum(qbar)+momentum(g));
+ checkCurrent("qqbargRightCurrent",cachedCurrent(),momentum(q)+momentum(qbar)+momentum(g));
#endif
+
return cachedCurrent();
}
return czero;
+}
-}
LorentzVector<Complex> MatchboxCurrents::qqbarggGeneralLeftCurrent(const int i, const int,
const int j, const int,
const int k, const int g1Hel,
const int l, const int g2Hel,
const int n) {
const double ik = invariant(i,k);
const double il = invariant(i,l);
const double jk = invariant(j,k);
const double jl = invariant(j,l);
const double kl = invariant(k,l);
const Complex plusP_ik = plusProduct(i,k);
const Complex plusP_il = plusProduct(i,l);
const Complex plusP_in = plusProduct(i,n);
const Complex plusP_jk = plusProduct(j,k);
const Complex plusP_jl = plusProduct(j,l);
const Complex plusP_jn = plusProduct(j,n);
const Complex plusP_kl = plusProduct(k,l);
const Complex plusP_kn = plusProduct(k,n);
const Complex plusP_ln = plusProduct(l,n);
const Complex minusP_ik = minusProduct(i,k);
const Complex minusP_il = minusProduct(i,l);
const Complex minusP_in = minusProduct(i,n);
const Complex minusP_jk = minusProduct(j,k);
const Complex minusP_jl = minusProduct(j,l);
const Complex minusP_jn = minusProduct(j,n);
const Complex minusP_kl = minusProduct(k,l);
const Complex minusP_kn = minusProduct(k,n);
const Complex minusP_ln = minusProduct(l,n);
const LorentzVector<Complex> & minusC_ij = minusCurrent(i,j);
const LorentzVector<Complex> & minusC_ik = minusCurrent(i,k);
const LorentzVector<Complex> & minusC_il = minusCurrent(i,l);
const LorentzVector<Complex> & minusC_kj = minusCurrent(k,j);
const LorentzVector<Complex> & minusC_kl = minusCurrent(k,l);
const LorentzVector<Complex> & minusC_lj = minusCurrent(l,j);
if ( g1Hel == 1 && g2Hel == 1 ) {
return
(Complex(0,-2) * plusP_jl * plusP_kl * minusC_ik)/
(jl * (jk + jl + kl)) -
(Complex(0,2) * plusP_jl * plusP_kl * minusC_ik)/
(kl * (jk + jl + kl)) -
(Complex(0,2) * plusP_jk * plusP_kl * minusC_il)/
(kl * (jk + jl + kl)) +
(Complex(0,2) * plusP_il * plusP_kl * minusC_ij * minusP_in)/
(kl * (ik + il + kl) * minusP_kn) -
(Complex(0,2) * plusP_ik * plusP_jl * minusC_il * minusP_in)/
(ik * jl * minusP_kn) +
(Complex(0,2) * sqr(plusP_kl) * minusC_kj * minusP_in)/
(kl * (ik + il + kl) * minusP_kn) -
(Complex(0,2) * plusP_jl * plusP_kl * minusC_ij * minusP_jn)/
(jl * (jk + jl + kl) * minusP_kn) -
(Complex(0,2) * plusP_jl * plusP_kl * minusC_ij * minusP_jn)/
(kl * (jk + jl + kl) * minusP_kn) +
(Complex(0,2) * plusP_jk * plusP_jl * minusC_il * minusP_jn)/
(jl * (jk + jl + kl) * minusP_kn) +
(Complex(0,2) * plusP_ik * plusP_kl * minusC_ij * minusP_in)/
(kl * (ik + il + kl) * minusP_ln) -
(Complex(0,2) * sqr(plusP_kl) * minusC_lj * minusP_in)/
(kl * (ik + il + kl) * minusP_ln) -
(Complex(0,2) * plusP_jk * plusP_kl * minusC_ij * minusP_jn)/
(kl * (jk + jl + kl) * minusP_ln) +
(Complex(0,2) * plusP_jk * plusP_jl * minusC_ik * minusP_jn)/
(jl * (jk + jl + kl) * minusP_ln) +
(Complex(0,2) * plusP_ik * plusP_il * minusC_ij * sqr(minusP_in))/
(ik * (ik + il + kl) * minusP_kn * minusP_ln) +
(Complex(0,2) * plusP_ik * plusP_kl * minusC_kj * sqr(minusP_in))/
(ik * (ik + il + kl) * minusP_kn * minusP_ln) -
(Complex(0,2) * plusP_ik * plusP_jl * minusC_ij * minusP_in * minusP_jn)/
(ik * jl * minusP_kn * minusP_ln) +
(Complex(0,2) * plusP_jk * plusP_jl * minusC_ij * sqr(minusP_jn))/
(jl * (jk + jl + kl) * minusP_kn * minusP_ln) -
(Complex(0,2) * plusP_jk * plusP_kl * minusC_ik * minusP_kn)/
(kl * (jk + jl + kl) * minusP_ln) -
(Complex(0,2) * plusP_jl * plusP_kl * minusC_il * minusP_ln)/
(jl * (jk + jl + kl) * minusP_kn) -
(Complex(0,2) * plusP_jl * plusP_kl * minusC_il * minusP_ln)/
(kl * (jk + jl + kl) * minusP_kn);
}
if ( g1Hel == 1 && g2Hel == -1 ) {
return
(Complex(0,-2) * plusP_jk * plusP_jn * minusC_ik * minusP_jl)/
(jl * (jk + jl + kl) * plusP_ln) +
(Complex(0,2) * plusP_jk * plusP_kn * minusC_ik * minusP_kl)/
(kl * (jk + jl + kl) * plusP_ln) -
(Complex(0,2) * plusP_ik * plusP_in * minusC_ij * minusP_il * minusP_in)/
(ik * (ik + il + kl) * plusP_ln * minusP_kn) -
(Complex(0,2) * plusP_ik * plusP_kn * minusC_kj * minusP_il * minusP_in)/
(ik * (ik + il + kl) * plusP_ln * minusP_kn) -
(Complex(0,2) * plusP_ik * minusC_lj * minusP_il * minusP_in)/
(ik * (ik + il + kl) * minusP_kn) +
(Complex(0,2) * plusP_ik * plusP_jn * minusC_ij * minusP_in * minusP_jl)/
(ik * jl * plusP_ln * minusP_kn) -
(Complex(0,2) * plusP_jk * plusP_jn * minusC_ij * minusP_jl * minusP_jn)/
(jl * (jk + jl + kl) * plusP_ln * minusP_kn) -
(Complex(0,2) * plusP_ik * plusP_kn * minusC_ij * minusP_in * minusP_kl)/
(kl * (ik + il + kl) * plusP_ln * minusP_kn) +
(Complex(0,2) * plusP_kl * plusP_kn * minusC_lj * minusP_in * minusP_kl)/
(kl * (ik + il + kl) * plusP_ln * minusP_kn) +
(Complex(0,2) * plusP_jk * plusP_kn * minusC_ij * minusP_jn * minusP_kl)/
(kl * (jk + jl + kl) * plusP_ln * minusP_kn) -
(Complex(0,1) * plusP_ik * plusP_kn * minusC_ij * minusP_ik * minusP_ln)/
(kl * (ik + il + kl) * plusP_ln * minusP_kn) +
(Complex(0,1) * plusP_kl * plusP_kn * minusC_lj * minusP_ik * minusP_ln)/
(kl * (ik + il + kl) * plusP_ln * minusP_kn) -
(Complex(0,2) * plusP_in * plusP_kl * minusC_ij * minusP_il * minusP_ln)/
(kl * (ik + il + kl) * plusP_ln * minusP_kn) +
(Complex(0,1) * plusP_il * plusP_kn * minusC_ij * minusP_il * minusP_ln)/
(kl * (ik + il + kl) * plusP_ln * minusP_kn) -
(Complex(0,1) * plusP_kl * plusP_kn * minusC_kj * minusP_il * minusP_ln)/
(kl * (ik + il + kl) * plusP_ln * minusP_kn) -
(Complex(0,2) * plusP_kl * minusC_lj * minusP_il * minusP_ln)/
(kl * (ik + il + kl) * minusP_kn) +
(Complex(0,1) * plusP_jk * plusP_kn * minusC_ij * minusP_jk * minusP_ln)/
(kl * (jk + jl + kl) * plusP_ln * minusP_kn) +
(Complex(0,2) * plusP_jn * plusP_kl * minusC_ij * minusP_jl * minusP_ln)/
(kl * (jk + jl + kl) * plusP_ln * minusP_kn) -
(Complex(0,1) * plusP_jl * plusP_kn * minusC_ij * minusP_jl * minusP_ln)/
(kl * (jk + jl + kl) * plusP_ln * minusP_kn) -
(Complex(0,2) * plusP_jk * plusP_jn * minusC_il * minusP_jl * minusP_ln)/
(jl * (jk + jl + kl) * plusP_ln * minusP_kn) +
(Complex(0,2) * plusP_jn * plusP_kl * minusC_ik * minusP_kl * minusP_ln)/
(kl * (jk + jl + kl) * plusP_ln * minusP_kn) -
(Complex(0,1) * plusP_jl * plusP_kn * minusC_ik * minusP_kl * minusP_ln)/
(kl * (jk + jl + kl) * plusP_ln * minusP_kn) +
(Complex(0,1) * plusP_jk * plusP_kn * minusC_il * minusP_kl * minusP_ln)/
(kl * (jk + jl + kl) * plusP_ln * minusP_kn);
}
if ( g1Hel == -1 && g2Hel == 1 ) {
return
(Complex(0,2) * plusP_in * plusP_jl * minusC_il * minusP_ik)/
(ik * jl * plusP_kn) +
(Complex(0,2) * plusP_jl * minusC_kl * minusP_ik)/(ik * jl) -
(Complex(0,2) * plusP_jl * plusP_ln * minusC_ij * minusP_jk)/
(jl * (jk + jl + kl) * plusP_kn) +
(Complex(0,2) * plusP_jl * plusP_ln * minusC_il * minusP_kl)/
(jl * (jk + jl + kl) * plusP_kn) +
(Complex(0,2) * plusP_jl * plusP_ln * minusC_il * minusP_kl)/
(kl * (jk + jl + kl) * plusP_kn) -
(Complex(0,2) * plusP_il * plusP_in * minusC_ij * minusP_ik * minusP_in)/
(ik * (ik + il + kl) * plusP_kn * minusP_ln) -
(Complex(0,2) * plusP_in * plusP_kl * minusC_kj * minusP_ik * minusP_in)/
(ik * (ik + il + kl) * plusP_kn * minusP_ln) +
(Complex(0,2) * plusP_in * plusP_jl * minusC_ij * minusP_ik * minusP_jn)/
(ik * jl * plusP_kn * minusP_ln) +
(Complex(0,2) * plusP_jl * minusC_kj * minusP_ik * minusP_jn)/
(ik * jl * minusP_ln) -
(Complex(0,2) * plusP_jl * plusP_jn * minusC_ij * minusP_jk * minusP_jn)/
(jl * (jk + jl + kl) * plusP_kn * minusP_ln) -
(Complex(0,2) * plusP_il * plusP_ln * minusC_ij * minusP_in * minusP_kl)/
(kl * (ik + il + kl) * plusP_kn * minusP_ln) -
(Complex(0,2) * plusP_kl * plusP_ln * minusC_kj * minusP_in * minusP_kl)/
(kl * (ik + il + kl) * plusP_kn * minusP_ln) +
(Complex(0,2) * plusP_jl * plusP_ln * minusC_ij * minusP_jn * minusP_kl)/
(kl * (jk + jl + kl) * plusP_kn * minusP_ln) +
(Complex(0,2) * plusP_jl * plusP_jn * minusC_il * minusP_jn * minusP_kl)/
(jl * (jk + jl + kl) * plusP_kn * minusP_ln) -
(Complex(0,2) * plusP_il * minusC_ij * minusP_ik * minusP_kn)/
(ik * (ik + il + kl) * minusP_ln) -
(Complex(0,2) * plusP_in * plusP_kl * minusC_ij * minusP_ik * minusP_kn)/
(kl * (ik + il + kl) * plusP_kn * minusP_ln) -
(Complex(0,1) * plusP_ik * plusP_ln * minusC_ij * minusP_ik * minusP_kn)/
(kl * (ik + il + kl) * plusP_kn * minusP_ln) -
(Complex(0,2) * plusP_kl * minusC_kj * minusP_ik * minusP_kn)/
(ik * (ik + il + kl) * minusP_ln) -
(Complex(0,2) * plusP_kl * minusC_kj * minusP_ik * minusP_kn)/
(kl * (ik + il + kl) * minusP_ln) -
(Complex(0,1) * plusP_kl * plusP_ln * minusC_lj * minusP_ik * minusP_kn)/
(kl * (ik + il + kl) * plusP_kn * minusP_ln) +
(Complex(0,1) * plusP_il * plusP_ln * minusC_ij * minusP_il * minusP_kn)/
(kl * (ik + il + kl) * plusP_kn * minusP_ln) +
(Complex(0,1) * plusP_kl * plusP_ln * minusC_kj * minusP_il * minusP_kn)/
(kl * (ik + il + kl) * plusP_kn * minusP_ln) +
(Complex(0,2) * plusP_jn * plusP_kl * minusC_ij * minusP_jk * minusP_kn)/
(kl * (jk + jl + kl) * plusP_kn * minusP_ln) +
(Complex(0,1) * plusP_jk * plusP_ln * minusC_ij * minusP_jk * minusP_kn)/
(kl * (jk + jl + kl) * plusP_kn * minusP_ln) -
(Complex(0,1) * plusP_jl * plusP_ln * minusC_ij * minusP_jl * minusP_kn)/
(kl * (jk + jl + kl) * plusP_kn * minusP_ln) +
(Complex(0,1) * plusP_jl * plusP_ln * minusC_ik * minusP_kl * minusP_kn)/
(kl * (jk + jl + kl) * plusP_kn * minusP_ln) -
(Complex(0,2) * plusP_jn * plusP_kl * minusC_il * minusP_kl * minusP_kn)/
(kl * (jk + jl + kl) * plusP_kn * minusP_ln) -
(Complex(0,1) * plusP_jk * plusP_ln * minusC_il * minusP_kl * minusP_kn)/
(kl * (jk + jl + kl) * plusP_kn * minusP_ln);
}
if ( g1Hel == -1 && g2Hel == -1 ) {
return
(Complex(0,2) * sqr(plusP_in) * minusC_ij * minusP_ik * minusP_il)/
(ik * (ik + il + kl) * plusP_kn * plusP_ln) +
(Complex(0,2) * plusP_in * minusC_kj * minusP_ik * minusP_il)/
(ik * (ik + il + kl) * plusP_ln) +
(Complex(0,2) * plusP_in * minusC_lj * minusP_ik * minusP_il)/
(ik * (ik + il + kl) * plusP_kn) -
(Complex(0,2) * plusP_in * plusP_jn * minusC_ij * minusP_ik * minusP_jl)/
(ik * jl * plusP_kn * plusP_ln) -
(Complex(0,2) * plusP_jn * minusC_kj * minusP_ik * minusP_jl)/
(ik * jl * plusP_ln) +
(Complex(0,2) * sqr(plusP_jn) * minusC_ij * minusP_jk * minusP_jl)/
(jl * (jk + jl + kl) * plusP_kn * plusP_ln) +
(Complex(0,2) * plusP_in * minusC_ij * minusP_ik * minusP_kl)/
(ik * (ik + il + kl) * plusP_ln) +
(Complex(0,2) * plusP_in * minusC_ij * minusP_ik * minusP_kl)/
(kl * (ik + il + kl) * plusP_ln) +
(Complex(0,2) * plusP_kn * minusC_kj * minusP_ik * minusP_kl)/
(ik * (ik + il + kl) * plusP_ln) +
(Complex(0,2) * plusP_kn * minusC_kj * minusP_ik * minusP_kl)/
(kl * (ik + il + kl) * plusP_ln) +
(Complex(0,2) * minusC_lj * minusP_ik * minusP_kl)/
(ik * (ik + il + kl)) +
(Complex(0,2) * minusC_lj * minusP_ik * minusP_kl)/
(kl * (ik + il + kl)) +
(Complex(0,2) * plusP_in * minusC_ij * minusP_il * minusP_kl)/
(kl * (ik + il + kl) * plusP_kn) +
(Complex(0,2) * minusC_kj * minusP_il * minusP_kl)/
(kl * (ik + il + kl)) +
(Complex(0,2) * plusP_ln * minusC_lj * minusP_il * minusP_kl)/
(kl * (ik + il + kl) * plusP_kn) -
(Complex(0,2) * plusP_jn * minusC_ij * minusP_jk * minusP_kl)/
(kl * (jk + jl + kl) * plusP_ln) -
(Complex(0,2) * plusP_jn * minusC_ij * minusP_jl * minusP_kl)/
(kl * (jk + jl + kl) * plusP_kn) -
(Complex(0,2) * sqr(plusP_jn) * minusC_il * minusP_jl * minusP_kl)/
(jl * (jk + jl + kl) * plusP_kn * plusP_ln) -
(Complex(0,2) * plusP_jn * minusC_ik * sqr(minusP_kl))/
(kl * (jk + jl + kl) * plusP_kn) +
(Complex(0,2) * plusP_jn * minusC_il * sqr(minusP_kl))/
(kl * (jk + jl + kl) * plusP_ln);
}
return czero;
}
LorentzVector<Complex> MatchboxCurrents::qqbarggFixedLeftCurrent(const int i, const int,
const int j, const int,
const int k, const int g1Hel,
const int l, const int g2Hel) {
const double ik = invariant(i,k);
const double il = invariant(i,l);
const double jk = invariant(j,k);
const double jl = invariant(j,l);
const double kl = invariant(k,l);
const Complex plusP_ij = plusProduct(i,j);
const Complex plusP_ik = plusProduct(i,k);
const Complex plusP_il = plusProduct(i,l);
const Complex plusP_jk = plusProduct(j,k);
const Complex plusP_jl = plusProduct(j,l);
const Complex plusP_kl = plusProduct(k,l);
const Complex minusP_ij = minusProduct(i,j);
const Complex minusP_ik = minusProduct(i,k);
const Complex minusP_il = minusProduct(i,l);
const Complex minusP_jk = minusProduct(j,k);
const Complex minusP_jl = minusProduct(j,l);
const Complex minusP_kl = minusProduct(k,l);
const LorentzVector<Complex> & minusC_ij = minusCurrent(i,j);
const LorentzVector<Complex> & minusC_ik = minusCurrent(i,k);
const LorentzVector<Complex> & minusC_il = minusCurrent(i,l);
const LorentzVector<Complex> & minusC_kj = minusCurrent(k,j);
const LorentzVector<Complex> & minusC_kl = minusCurrent(k,l);
const LorentzVector<Complex> & minusC_lj = minusCurrent(l,j);
if ( g1Hel == 1 && g2Hel == 1 ) {
return
(Complex(0,-2) * plusP_jl * plusP_kl * minusC_ik)/
(jl * (jk + jl + kl)) -
(Complex(0,2) * plusP_jl * plusP_kl * minusC_ik)/
(kl * (jk + jl + kl)) -
(Complex(0,2) * plusP_jk * plusP_kl * minusC_il)/
(kl * (jk + jl + kl)) -
(Complex(0,2) * plusP_jl * plusP_kl * minusC_ij * minusP_ij)/
(jl * (jk + jl + kl) * minusP_ik) -
(Complex(0,2) * plusP_jl * plusP_kl * minusC_ij * minusP_ij)/
(kl * (jk + jl + kl) * minusP_ik) +
(Complex(0,2) * plusP_jk * plusP_jl * minusC_il * minusP_ij)/
(jl * (jk + jl + kl) * minusP_ik) -
(Complex(0,2) * plusP_jk * plusP_kl * minusC_ij * minusP_ij)/
(kl * (jk + jl + kl) * minusP_il) +
(Complex(0,2) * plusP_jk * plusP_jl * minusC_ik * minusP_ij)/
(jl * (jk + jl + kl) * minusP_il) +
(Complex(0,2) * plusP_jk * plusP_jl * minusC_ij * sqr(minusP_ij))/
(jl * (jk + jl + kl) * minusP_ik * minusP_il) -
(Complex(0,2) * plusP_jk * plusP_kl * minusC_ik * minusP_ik)/
(kl * (jk + jl + kl) * minusP_il) -
(Complex(0,2) * plusP_jl * plusP_kl * minusC_il * minusP_il)/
(jl * (jk + jl + kl) * minusP_ik) -
(Complex(0,2) * plusP_jl * plusP_kl * minusC_il * minusP_il)/
(kl * (jk + jl + kl) * minusP_ik);
}
if ( g1Hel == 1 && g2Hel == -1 ) {
return
(Complex(0,-1) * sqr(plusP_ik) * minusC_ij * minusP_il)/
(kl * (ik + il + kl) * plusP_il) +
(Complex(0,1) * plusP_ik * plusP_kl * minusC_lj * minusP_il)/
(kl * (ik + il + kl) * plusP_il) +
(Complex(0,1) * plusP_ik * minusC_ij * sqr(minusP_il))/
(kl * (ik + il + kl) * minusP_ik) -
(Complex(0,1) * plusP_ik * plusP_kl * minusC_kj * sqr(minusP_il))/
(kl * (ik + il + kl) * plusP_il * minusP_ik) -
(Complex(0,2) * plusP_kl * minusC_lj * sqr(minusP_il))/
(kl * (ik + il + kl) * minusP_ik) +
(Complex(0,1) * plusP_ik * plusP_jk * minusC_ij * minusP_il * minusP_jk)/
(kl * (jk + jl + kl) * plusP_il * minusP_ik) -
(Complex(0,2) * plusP_ij * plusP_jk * minusC_ik * minusP_jl)/
(jl * (jk + jl + kl) * plusP_il) -
(Complex(0,2) * plusP_ij * plusP_jk * minusC_ij * minusP_ij * minusP_jl)/
(jl * (jk + jl + kl) * plusP_il * minusP_ik) -
(Complex(0,1) * plusP_ik * plusP_jl * minusC_ij * minusP_il * minusP_jl)/
(kl * (jk + jl + kl) * plusP_il * minusP_ik) +
(Complex(0,2) * plusP_ij * plusP_kl * minusC_ij * minusP_il * minusP_jl)/
(kl * (jk + jl + kl) * plusP_il * minusP_ik) -
(Complex(0,2) * plusP_ij * plusP_jk * minusC_il * minusP_il * minusP_jl)/
(jl * (jk + jl + kl) * plusP_il * minusP_ik) +
(Complex(0,2) * plusP_ik * plusP_jk * minusC_ik * minusP_kl)/
(kl * (jk + jl + kl) * plusP_il) +
(Complex(0,2) * plusP_ik * plusP_jk * minusC_ij * minusP_ij * minusP_kl)/
(kl * (jk + jl + kl) * plusP_il * minusP_ik) -
(Complex(0,1) * plusP_ik * plusP_jl * minusC_ik * minusP_il * minusP_kl)/
(kl * (jk + jl + kl) * plusP_il * minusP_ik) +
(Complex(0,2) * plusP_ij * plusP_kl * minusC_ik * minusP_il * minusP_kl)/
(kl * (jk + jl + kl) * plusP_il * minusP_ik) +
(Complex(0,1) * plusP_ik * plusP_jk * minusC_il * minusP_il * minusP_kl)/
(kl * (jk + jl + kl) * plusP_il * minusP_ik);
}
if ( g1Hel == -1 && g2Hel == 1 ) {
return
(Complex(0,1) * sqr(plusP_il) * minusC_ij * minusP_ik)/
(kl * (ik + il + kl) * plusP_ik) +
(Complex(0,1) * plusP_il * plusP_kl * minusC_kj * minusP_ik)/
(kl * (ik + il + kl) * plusP_ik) +
(Complex(0,2) * plusP_jl * minusC_kl * minusP_ik)/(ik * jl) +
(Complex(0,2) * plusP_jl * minusC_kj * minusP_ij * minusP_ik)/
(ik * jl * minusP_il) -
(Complex(0,2) * plusP_il * minusC_ij * sqr(minusP_ik))/
(ik * (ik + il + kl) * minusP_il) -
(Complex(0,1) * plusP_il * minusC_ij * sqr(minusP_ik))/
(kl * (ik + il + kl) * minusP_il) -
(Complex(0,2) * plusP_kl * minusC_kj * sqr(minusP_ik))/
(ik * (ik + il + kl) * minusP_il) -
(Complex(0,2) * plusP_kl * minusC_kj * sqr(minusP_ik))/
(kl * (ik + il + kl) * minusP_il) -
(Complex(0,1) * plusP_il * plusP_kl * minusC_lj * sqr(minusP_ik))/
(kl * (ik + il + kl) * plusP_ik * minusP_il) -
(Complex(0,2) * plusP_il * plusP_jl * minusC_ij * minusP_jk)/
(jl * (jk + jl + kl) * plusP_ik) -
(Complex(0,2) * plusP_ij * plusP_jl * minusC_ij * minusP_ij * minusP_jk)/
(jl * (jk + jl + kl) * plusP_ik * minusP_il) +
(Complex(0,1) * plusP_il * plusP_jk * minusC_ij * minusP_ik * minusP_jk)/
(kl * (jk + jl + kl) * plusP_ik * minusP_il) +
(Complex(0,2) * plusP_ij * plusP_kl * minusC_ij * minusP_ik * minusP_jk)/
(kl * (jk + jl + kl) * plusP_ik * minusP_il) -
(Complex(0,1) * plusP_il * plusP_jl * minusC_ij * minusP_ik * minusP_jl)/
(kl * (jk + jl + kl) * plusP_ik * minusP_il) +
(Complex(0,2) * plusP_il * plusP_jl * minusC_il * minusP_kl)/
(jl * (jk + jl + kl) * plusP_ik) +
(Complex(0,2) * plusP_il * plusP_jl * minusC_il * minusP_kl)/
(kl * (jk + jl + kl) * plusP_ik) +
(Complex(0,2) * plusP_il * plusP_jl * minusC_ij * minusP_ij * minusP_kl)/
(kl * (jk + jl + kl) * plusP_ik * minusP_il) +
(Complex(0,2) * plusP_ij * plusP_jl * minusC_il * minusP_ij * minusP_kl)/
(jl * (jk + jl + kl) * plusP_ik * minusP_il) +
(Complex(0,1) * plusP_il * plusP_jl * minusC_ik * minusP_ik * minusP_kl)/
(kl * (jk + jl + kl) * plusP_ik * minusP_il) -
(Complex(0,1) * plusP_il * plusP_jk * minusC_il * minusP_ik * minusP_kl)/
(kl * (jk + jl + kl) * plusP_ik * minusP_il) -
(Complex(0,2) * plusP_ij * plusP_kl * minusC_il * minusP_ik * minusP_kl)/
(kl * (jk + jl + kl) * plusP_ik * minusP_il);
}
if ( g1Hel == -1 && g2Hel == -1 ) {
return
(Complex(0,-2) * plusP_ij * minusC_kj * minusP_ik * minusP_jl)/
(ik * jl * plusP_il) +
(Complex(0,2) * sqr(plusP_ij) * minusC_ij * minusP_jk * minusP_jl)/
(jl * (jk + jl + kl) * plusP_ik * plusP_il) +
(Complex(0,2) * plusP_ik * minusC_kj * minusP_ik * minusP_kl)/
(ik * (ik + il + kl) * plusP_il) +
(Complex(0,2) * plusP_ik * minusC_kj * minusP_ik * minusP_kl)/
(kl * (ik + il + kl) * plusP_il) +
(Complex(0,2) * minusC_lj * minusP_ik * minusP_kl)/
(ik * (ik + il + kl)) +
(Complex(0,2) * minusC_lj * minusP_ik * minusP_kl)/
(kl * (ik + il + kl)) +
(Complex(0,2) * minusC_kj * minusP_il * minusP_kl)/
(kl * (ik + il + kl)) +
(Complex(0,2) * plusP_il * minusC_lj * minusP_il * minusP_kl)/
(kl * (ik + il + kl) * plusP_ik) -
(Complex(0,2) * plusP_ij * minusC_ij * minusP_jk * minusP_kl)/
(kl * (jk + jl + kl) * plusP_il) -
(Complex(0,2) * plusP_ij * minusC_ij * minusP_jl * minusP_kl)/
(kl * (jk + jl + kl) * plusP_ik) -
(Complex(0,2) * sqr(plusP_ij) * minusC_il * minusP_jl * minusP_kl)/
(jl * (jk + jl + kl) * plusP_ik * plusP_il) -
(Complex(0,2) * plusP_ij * minusC_ik * sqr(minusP_kl))/
(kl * (jk + jl + kl) * plusP_ik) +
(Complex(0,2) * plusP_ij * minusC_il * sqr(minusP_kl))/
(kl * (jk + jl + kl) * plusP_il);
}
return czero;
}
LorentzVector<Complex> MatchboxCurrents::qqbarggGeneralRightCurrent(const int i, const int,
const int j, const int,
const int k, const int g1Hel,
const int l, const int g2Hel,
const int n) {
const double ik = invariant(i,k);
const double il = invariant(i,l);
const double jk = invariant(j,k);
const double jl = invariant(j,l);
const double kl = invariant(k,l);
const Complex plusP_ik = plusProduct(i,k);
const Complex plusP_il = plusProduct(i,l);
const Complex plusP_in = plusProduct(i,n);
const Complex plusP_jk = plusProduct(j,k);
const Complex plusP_jl = plusProduct(j,l);
const Complex plusP_jn = plusProduct(j,n);
const Complex plusP_kl = plusProduct(k,l);
const Complex plusP_kn = plusProduct(k,n);
const Complex plusP_ln = plusProduct(l,n);
const Complex minusP_ik = minusProduct(i,k);
const Complex minusP_il = minusProduct(i,l);
const Complex minusP_in = minusProduct(i,n);
const Complex minusP_jk = minusProduct(j,k);
const Complex minusP_jl = minusProduct(j,l);
const Complex minusP_jn = minusProduct(j,n);
const Complex minusP_kl = minusProduct(k,l);
const Complex minusP_kn = minusProduct(k,n);
const Complex minusP_ln = minusProduct(l,n);
const LorentzVector<Complex> & minusC_ji = minusCurrent(j,i);
const LorentzVector<Complex> & minusC_jk = minusCurrent(j,k);
const LorentzVector<Complex> & minusC_jl = minusCurrent(j,l);
const LorentzVector<Complex> & minusC_ki = minusCurrent(k,i);
const LorentzVector<Complex> & minusC_li = minusCurrent(l,i);
const LorentzVector<Complex> & minusC_lk = minusCurrent(l,k);
if ( g1Hel == 1 && g2Hel == 1 ) {
return
(Complex(0,2) * plusP_il * plusP_kl * minusC_jk)/
(kl * (ik + il + kl)) +
(Complex(0,2) * plusP_ik * plusP_kl * minusC_jl)/
(ik * (ik + il + kl)) +
(Complex(0,2) * plusP_ik * plusP_kl * minusC_jl)/
(kl * (ik + il + kl)) +
(Complex(0,2) * plusP_il * plusP_kl * minusC_ji * minusP_in)/
(kl * (ik + il + kl) * minusP_kn) +
(Complex(0,2) * plusP_ik * plusP_il * minusC_jl * minusP_in)/
(ik * (ik + il + kl) * minusP_kn) -
(Complex(0,2) * plusP_jl * plusP_kl * minusC_ji * minusP_jn)/
(kl * (jk + jl + kl) * minusP_kn) -
(Complex(0,2) * sqr(plusP_kl) * minusC_ki * minusP_jn)/
(kl * (jk + jl + kl) * minusP_kn) +
(Complex(0,2) * plusP_ik * plusP_kl * minusC_ji * minusP_in)/
(ik * (ik + il + kl) * minusP_ln) +
(Complex(0,2) * plusP_ik * plusP_kl * minusC_ji * minusP_in)/
(kl * (ik + il + kl) * minusP_ln) +
(Complex(0,2) * plusP_ik * plusP_il * minusC_jk * minusP_in)/
(ik * (ik + il + kl) * minusP_ln) -
(Complex(0,2) * plusP_jk * plusP_kl * minusC_ji * minusP_jn)/
(kl * (jk + jl + kl) * minusP_ln) -
(Complex(0,2) * plusP_ik * plusP_jl * minusC_jk * minusP_jn)/
(ik * jl * minusP_ln) +
(Complex(0,2) * sqr(plusP_kl) * minusC_li * minusP_jn)/
(kl * (jk + jl + kl) * minusP_ln) +
(Complex(0,2) * plusP_ik * plusP_il * minusC_ji * sqr(minusP_in))/
(ik * (ik + il + kl) * minusP_kn * minusP_ln) -
(Complex(0,2) * plusP_ik * plusP_jl * minusC_ji * minusP_in * minusP_jn)/
(ik * jl * minusP_kn * minusP_ln) +
(Complex(0,2) * plusP_jk * plusP_jl * minusC_ji * sqr(minusP_jn))/
(jl * (jk + jl + kl) * minusP_kn * minusP_ln) -
(Complex(0,2) * plusP_jl * plusP_kl * minusC_li * sqr(minusP_jn))/
(jl * (jk + jl + kl) * minusP_kn * minusP_ln) +
(Complex(0,2) * plusP_ik * plusP_kl * minusC_jk * minusP_kn)/
(ik * (ik + il + kl) * minusP_ln) +
(Complex(0,2) * plusP_ik * plusP_kl * minusC_jk * minusP_kn)/
(kl * (ik + il + kl) * minusP_ln) +
(Complex(0,2) * plusP_il * plusP_kl * minusC_jl * minusP_ln)/
(kl * (ik + il + kl) * minusP_kn);
}
if ( g1Hel == 1 && g2Hel == -1 ) {
return
(Complex(0,-2) * plusP_ik * plusP_kn * minusC_ji * minusP_il)/
(ik * (ik + il + kl) * plusP_ln) +
(Complex(0,2) * plusP_ik * plusP_jn * minusC_jk * minusP_jl)/
(ik * jl * plusP_ln) +
(Complex(0,2) * plusP_ik * minusC_lk * minusP_jl)/(ik * jl) -
(Complex(0,2) * plusP_ik * plusP_kn * minusC_jk * minusP_kl)/
(ik * (ik + il + kl) * plusP_ln) -
(Complex(0,2) * plusP_ik * plusP_kn * minusC_jk * minusP_kl)/
(kl * (ik + il + kl) * plusP_ln) -
(Complex(0,2) * plusP_ik * plusP_in * minusC_ji * minusP_il * minusP_in)/
(ik * (ik + il + kl) * plusP_ln * minusP_kn) +
(Complex(0,2) * plusP_ik * plusP_jn * minusC_ji * minusP_in * minusP_jl)/
(ik * jl * plusP_ln * minusP_kn) +
(Complex(0,2) * plusP_ik * minusC_li * minusP_in * minusP_jl)/
(ik * jl * minusP_kn) -
(Complex(0,2) * plusP_jk * plusP_jn * minusC_ji * minusP_jl * minusP_jn)/
(jl * (jk + jl + kl) * plusP_ln * minusP_kn) +
(Complex(0,2) * plusP_jn * plusP_kl * minusC_li * minusP_jl * minusP_jn)/
(jl * (jk + jl + kl) * plusP_ln * minusP_kn) -
(Complex(0,2) * plusP_ik * plusP_kn * minusC_ji * minusP_in * minusP_kl)/
(kl * (ik + il + kl) * plusP_ln * minusP_kn) -
(Complex(0,2) * plusP_ik * plusP_in * minusC_jk * minusP_in * minusP_kl)/
(ik * (ik + il + kl) * plusP_ln * minusP_kn) +
(Complex(0,2) * plusP_jk * plusP_kn * minusC_ji * minusP_jn * minusP_kl)/
(kl * (jk + jl + kl) * plusP_ln * minusP_kn) -
(Complex(0,2) * plusP_kl * plusP_kn * minusC_li * minusP_jn * minusP_kl)/
(kl * (jk + jl + kl) * plusP_ln * minusP_kn) -
(Complex(0,1) * plusP_ik * plusP_kn * minusC_ji * minusP_ik * minusP_ln)/
(kl * (ik + il + kl) * plusP_ln * minusP_kn) -
(Complex(0,2) * plusP_in * plusP_kl * minusC_ji * minusP_il * minusP_ln)/
(kl * (ik + il + kl) * plusP_ln * minusP_kn) +
(Complex(0,1) * plusP_il * plusP_kn * minusC_ji * minusP_il * minusP_ln)/
(kl * (ik + il + kl) * plusP_ln * minusP_kn) +
(Complex(0,1) * plusP_jk * plusP_kn * minusC_ji * minusP_jk * minusP_ln)/
(kl * (jk + jl + kl) * plusP_ln * minusP_kn) -
(Complex(0,1) * plusP_kl * plusP_kn * minusC_li * minusP_jk * minusP_ln)/
(kl * (jk + jl + kl) * plusP_ln * minusP_kn) -
(Complex(0,2) * plusP_jk * minusC_ji * minusP_jl * minusP_ln)/
(jl * (jk + jl + kl) * minusP_kn) +
(Complex(0,2) * plusP_jn * plusP_kl * minusC_ji * minusP_jl * minusP_ln)/
(kl * (jk + jl + kl) * plusP_ln * minusP_kn) -
(Complex(0,1) * plusP_jl * plusP_kn * minusC_ji * minusP_jl * minusP_ln)/
(kl * (jk + jl + kl) * plusP_ln * minusP_kn) +
(Complex(0,1) * plusP_kl * plusP_kn * minusC_ki * minusP_jl * minusP_ln)/
(kl * (jk + jl + kl) * plusP_ln * minusP_kn) +
(Complex(0,2) * plusP_kl * minusC_li * minusP_jl * minusP_ln)/
(jl * (jk + jl + kl) * minusP_kn) +
(Complex(0,2) * plusP_kl * minusC_li * minusP_jl * minusP_ln)/
(kl * (jk + jl + kl) * minusP_kn) -
(Complex(0,2) * plusP_in * plusP_kl * minusC_jk * minusP_kl * minusP_ln)/
(kl * (ik + il + kl) * plusP_ln * minusP_kn) +
(Complex(0,1) * plusP_il * plusP_kn * minusC_jk * minusP_kl * minusP_ln)/
(kl * (ik + il + kl) * plusP_ln * minusP_kn) -
(Complex(0,1) * plusP_ik * plusP_kn * minusC_jl * minusP_kl * minusP_ln)/
(kl * (ik + il + kl) * plusP_ln * minusP_kn);
}
if ( g1Hel == -1 && g2Hel == 1 ) {
return
(Complex(0,-2) * plusP_il * plusP_in * minusC_jl * minusP_ik)/
(ik * (ik + il + kl) * plusP_kn) -
(Complex(0,2) * plusP_il * plusP_ln * minusC_jl * minusP_kl)/
(kl * (ik + il + kl) * plusP_kn) -
(Complex(0,2) * plusP_il * plusP_in * minusC_ji * minusP_ik * minusP_in)/
(ik * (ik + il + kl) * plusP_kn * minusP_ln) +
(Complex(0,2) * plusP_in * plusP_jl * minusC_ji * minusP_ik * minusP_jn)/
(ik * jl * plusP_kn * minusP_ln) -
(Complex(0,2) * plusP_jl * plusP_jn * minusC_ji * minusP_jk * minusP_jn)/
(jl * (jk + jl + kl) * plusP_kn * minusP_ln) -
(Complex(0,2) * plusP_jl * minusC_ki * minusP_jk * minusP_jn)/
(jl * (jk + jl + kl) * minusP_ln) -
(Complex(0,2) * plusP_jl * plusP_ln * minusC_li * minusP_jk * minusP_jn)/
(jl * (jk + jl + kl) * plusP_kn * minusP_ln) -
(Complex(0,2) * plusP_il * plusP_ln * minusC_ji * minusP_in * minusP_kl)/
(kl * (ik + il + kl) * plusP_kn * minusP_ln) +
(Complex(0,2) * plusP_jl * plusP_ln * minusC_ji * minusP_jn * minusP_kl)/
(kl * (jk + jl + kl) * plusP_kn * minusP_ln) +
(Complex(0,2) * plusP_kl * plusP_ln * minusC_ki * minusP_jn * minusP_kl)/
(kl * (jk + jl + kl) * plusP_kn * minusP_ln) -
(Complex(0,2) * plusP_in * plusP_kl * minusC_ji * minusP_ik * minusP_kn)/
(kl * (ik + il + kl) * plusP_kn * minusP_ln) -
(Complex(0,1) * plusP_ik * plusP_ln * minusC_ji * minusP_ik * minusP_kn)/
(kl * (ik + il + kl) * plusP_kn * minusP_ln) -
(Complex(0,2) * plusP_il * plusP_in * minusC_jk * minusP_ik * minusP_kn)/
(ik * (ik + il + kl) * plusP_kn * minusP_ln) +
(Complex(0,1) * plusP_il * plusP_ln * minusC_ji * minusP_il * minusP_kn)/
(kl * (ik + il + kl) * plusP_kn * minusP_ln) +
(Complex(0,2) * plusP_jn * plusP_kl * minusC_ji * minusP_jk * minusP_kn)/
(kl * (jk + jl + kl) * plusP_kn * minusP_ln) +
(Complex(0,1) * plusP_jk * plusP_ln * minusC_ji * minusP_jk * minusP_kn)/
(kl * (jk + jl + kl) * plusP_kn * minusP_ln) +
(Complex(0,2) * plusP_kl * minusC_ki * minusP_jk * minusP_kn)/
(kl * (jk + jl + kl) * minusP_ln) +
(Complex(0,1) * plusP_kl * plusP_ln * minusC_li * minusP_jk * minusP_kn)/
(kl * (jk + jl + kl) * plusP_kn * minusP_ln) -
(Complex(0,1) * plusP_jl * plusP_ln * minusC_ji * minusP_jl * minusP_kn)/
(kl * (jk + jl + kl) * plusP_kn * minusP_ln) -
(Complex(0,1) * plusP_kl * plusP_ln * minusC_ki * minusP_jl * minusP_kn)/
(kl * (jk + jl + kl) * plusP_kn * minusP_ln) -
(Complex(0,1) * plusP_il * plusP_ln * minusC_jk * minusP_kl * minusP_kn)/
(kl * (ik + il + kl) * plusP_kn * minusP_ln) +
(Complex(0,2) * plusP_in * plusP_kl * minusC_jl * minusP_kl * minusP_kn)/
(kl * (ik + il + kl) * plusP_kn * minusP_ln) +
(Complex(0,1) * plusP_ik * plusP_ln * minusC_jl * minusP_kl * minusP_kn)/
(kl * (ik + il + kl) * plusP_kn * minusP_ln);
}
if ( g1Hel == -1 && g2Hel == -1 ) {
return
(Complex(0,2) * sqr(plusP_in) * minusC_ji * minusP_ik * minusP_il)/
(ik * (ik + il + kl) * plusP_kn * plusP_ln) -
(Complex(0,2) * plusP_in * plusP_jn * minusC_ji * minusP_ik * minusP_jl)/
(ik * jl * plusP_kn * plusP_ln) -
(Complex(0,2) * plusP_in * minusC_li * minusP_ik * minusP_jl)/
(ik * jl * plusP_kn) +
(Complex(0,2) * sqr(plusP_jn) * minusC_ji * minusP_jk * minusP_jl)/
(jl * (jk + jl + kl) * plusP_kn * plusP_ln) +
(Complex(0,2) * plusP_jn * minusC_ki * minusP_jk * minusP_jl)/
(jl * (jk + jl + kl) * plusP_ln) +
(Complex(0,2) * plusP_jn * minusC_li * minusP_jk * minusP_jl)/
(jl * (jk + jl + kl) * plusP_kn) +
(Complex(0,2) * plusP_in * minusC_ji * minusP_ik * minusP_kl)/
(kl * (ik + il + kl) * plusP_ln) +
(Complex(0,2) * sqr(plusP_in) * minusC_jk * minusP_ik * minusP_kl)/
(ik * (ik + il + kl) * plusP_kn * plusP_ln) +
(Complex(0,2) * plusP_in * minusC_ji * minusP_il * minusP_kl)/
(kl * (ik + il + kl) * plusP_kn) -
(Complex(0,2) * plusP_jn * minusC_ji * minusP_jk * minusP_kl)/
(kl * (jk + jl + kl) * plusP_ln) -
(Complex(0,2) * plusP_kn * minusC_ki * minusP_jk * minusP_kl)/
(kl * (jk + jl + kl) * plusP_ln) -
(Complex(0,2) * minusC_li * minusP_jk * minusP_kl)/
(kl * (jk + jl + kl)) -
(Complex(0,2) * plusP_jn * minusC_ji * minusP_jl * minusP_kl)/
(jl * (jk + jl + kl) * plusP_kn) -
(Complex(0,2) * plusP_jn * minusC_ji * minusP_jl * minusP_kl)/
(kl * (jk + jl + kl) * plusP_kn) -
(Complex(0,2) * minusC_ki * minusP_jl * minusP_kl)/
(jl * (jk + jl + kl)) -
(Complex(0,2) * minusC_ki * minusP_jl * minusP_kl)/
(kl * (jk + jl + kl)) -
(Complex(0,2) * plusP_ln * minusC_li * minusP_jl * minusP_kl)/
(jl * (jk + jl + kl) * plusP_kn) -
(Complex(0,2) * plusP_ln * minusC_li * minusP_jl * minusP_kl)/
(kl * (jk + jl + kl) * plusP_kn) +
(Complex(0,2) * plusP_in * minusC_jk * sqr(minusP_kl))/
(kl * (ik + il + kl) * plusP_kn) -
(Complex(0,2) * plusP_in * minusC_jl * sqr(minusP_kl))/
(kl * (ik + il + kl) * plusP_ln);
}
return czero;
}
LorentzVector<Complex> MatchboxCurrents::qqbarggFixedRightCurrent(const int i, const int,
const int j, const int,
const int k, const int g1Hel,
const int l, const int g2Hel) {
const double ik = invariant(i,k);
const double il = invariant(i,l);
const double jk = invariant(j,k);
const double jl = invariant(j,l);
const double kl = invariant(k,l);
const Complex plusP_ij = plusProduct(i,j);
const Complex plusP_ik = plusProduct(i,k);
const Complex plusP_il = plusProduct(i,l);
const Complex plusP_jk = plusProduct(j,k);
const Complex plusP_jl = plusProduct(j,l);
const Complex plusP_kl = plusProduct(k,l);
const Complex minusP_ij = minusProduct(i,j);
const Complex minusP_ik = minusProduct(i,k);
const Complex minusP_il = minusProduct(i,l);
const Complex minusP_jk = minusProduct(j,k);
const Complex minusP_jl = minusProduct(j,l);
const Complex minusP_kl = minusProduct(k,l);
const LorentzVector<Complex> & minusC_ji = minusCurrent(j,i);
const LorentzVector<Complex> & minusC_jk = minusCurrent(j,k);
const LorentzVector<Complex> & minusC_jl = minusCurrent(j,l);
const LorentzVector<Complex> & minusC_ki = minusCurrent(k,i);
const LorentzVector<Complex> & minusC_li = minusCurrent(l,i);
const LorentzVector<Complex> & minusC_lk = minusCurrent(l,k);
if ( g1Hel == 1 && g2Hel == 1 ) {
return
(Complex(0,2) * plusP_il * plusP_kl * minusC_jk)/
(kl * (ik + il + kl)) +
(Complex(0,2) * plusP_ik * plusP_kl * minusC_jl)/
(ik * (ik + il + kl)) +
(Complex(0,2) * plusP_ik * plusP_kl * minusC_jl)/
(kl * (ik + il + kl)) -
(Complex(0,2) * plusP_jl * plusP_kl * minusC_ji * minusP_ij)/
(kl * (jk + jl + kl) * minusP_ik) -
(Complex(0,2) * sqr(plusP_kl) * minusC_ki * minusP_ij)/
(kl * (jk + jl + kl) * minusP_ik) -
(Complex(0,2) * plusP_jk * plusP_kl * minusC_ji * minusP_ij)/
(kl * (jk + jl + kl) * minusP_il) -
(Complex(0,2) * plusP_ik * plusP_jl * minusC_jk * minusP_ij)/
(ik * jl * minusP_il) +
(Complex(0,2) * sqr(plusP_kl) * minusC_li * minusP_ij)/
(kl * (jk + jl + kl) * minusP_il) +
(Complex(0,2) * plusP_jk * plusP_jl * minusC_ji * sqr(minusP_ij))/
(jl * (jk + jl + kl) * minusP_ik * minusP_il) -
(Complex(0,2) * plusP_jl * plusP_kl * minusC_li * sqr(minusP_ij))/
(jl * (jk + jl + kl) * minusP_ik * minusP_il) +
(Complex(0,2) * plusP_ik * plusP_kl * minusC_jk * minusP_ik)/
(ik * (ik + il + kl) * minusP_il) +
(Complex(0,2) * plusP_ik * plusP_kl * minusC_jk * minusP_ik)/
(kl * (ik + il + kl) * minusP_il) +
(Complex(0,2) * plusP_il * plusP_kl * minusC_jl * minusP_il)/
(kl * (ik + il + kl) * minusP_ik);
}
if ( g1Hel == 1 && g2Hel == -1 ) {
return
(Complex(0,-2) * sqr(plusP_ik) * minusC_ji * minusP_il)/
(ik * (ik + il + kl) * plusP_il) -
(Complex(0,1) * sqr(plusP_ik) * minusC_ji * minusP_il)/
(kl * (ik + il + kl) * plusP_il) +
(Complex(0,1) * plusP_ik * minusC_ji * sqr(minusP_il))/
(kl * (ik + il + kl) * minusP_ik) +
(Complex(0,1) * plusP_ik * plusP_jk * minusC_ji * minusP_il * minusP_jk)/
(kl * (jk + jl + kl) * plusP_il * minusP_ik) -
(Complex(0,1) * plusP_ik * plusP_kl * minusC_li * minusP_il * minusP_jk)/
(kl * (jk + jl + kl) * plusP_il * minusP_ik) +
(Complex(0,2) * plusP_ij * plusP_ik * minusC_jk * minusP_jl)/
(ik * jl * plusP_il) +
(Complex(0,2) * plusP_ik * minusC_lk * minusP_jl)/(ik * jl) -
(Complex(0,2) * plusP_ij * plusP_jk * minusC_ji * minusP_ij * minusP_jl)/
(jl * (jk + jl + kl) * plusP_il * minusP_ik) +
(Complex(0,2) * plusP_ij * plusP_kl * minusC_li * minusP_ij * minusP_jl)/
(jl * (jk + jl + kl) * plusP_il * minusP_ik) -
(Complex(0,2) * plusP_jk * minusC_ji * minusP_il * minusP_jl)/
(jl * (jk + jl + kl) * minusP_ik) -
(Complex(0,1) * plusP_ik * plusP_jl * minusC_ji * minusP_il * minusP_jl)/
(kl * (jk + jl + kl) * plusP_il * minusP_ik) +
(Complex(0,2) * plusP_ij * plusP_kl * minusC_ji * minusP_il * minusP_jl)/
(kl * (jk + jl + kl) * plusP_il * minusP_ik) +
(Complex(0,1) * plusP_ik * plusP_kl * minusC_ki * minusP_il * minusP_jl)/
(kl * (jk + jl + kl) * plusP_il * minusP_ik) +
(Complex(0,2) * plusP_kl * minusC_li * minusP_il * minusP_jl)/
(jl * (jk + jl + kl) * minusP_ik) +
(Complex(0,2) * plusP_kl * minusC_li * minusP_il * minusP_jl)/
(kl * (jk + jl + kl) * minusP_ik) -
(Complex(0,2) * sqr(plusP_ik) * minusC_jk * minusP_kl)/
(ik * (ik + il + kl) * plusP_il) -
(Complex(0,2) * sqr(plusP_ik) * minusC_jk * minusP_kl)/
(kl * (ik + il + kl) * plusP_il) +
(Complex(0,2) * plusP_ik * plusP_jk * minusC_ji * minusP_ij * minusP_kl)/
(kl * (jk + jl + kl) * plusP_il * minusP_ik) -
(Complex(0,2) * plusP_ik * plusP_kl * minusC_li * minusP_ij * minusP_kl)/
(kl * (jk + jl + kl) * plusP_il * minusP_ik) +
(Complex(0,1) * plusP_ik * minusC_jk * minusP_il * minusP_kl)/
(kl * (ik + il + kl) * minusP_ik) -
(Complex(0,1) * sqr(plusP_ik) * minusC_jl * minusP_il * minusP_kl)/
(kl * (ik + il + kl) * plusP_il * minusP_ik);
}
if ( g1Hel == -1 && g2Hel == 1 ) {
return
(Complex(0,1) * sqr(plusP_il) * minusC_ji * minusP_ik)/
(kl * (ik + il + kl) * plusP_ik) -
(Complex(0,1) * plusP_il * minusC_ji * sqr(minusP_ik))/
(kl * (ik + il + kl) * minusP_il) -
(Complex(0,2) * plusP_ij * plusP_jl * minusC_ji * minusP_ij * minusP_jk)/
(jl * (jk + jl + kl) * plusP_ik * minusP_il) -
(Complex(0,2) * plusP_jl * minusC_ki * minusP_ij * minusP_jk)/
(jl * (jk + jl + kl) * minusP_il) -
(Complex(0,2) * plusP_il * plusP_jl * minusC_li * minusP_ij * minusP_jk)/
(jl * (jk + jl + kl) * plusP_ik * minusP_il) +
(Complex(0,1) * plusP_il * plusP_jk * minusC_ji * minusP_ik * minusP_jk)/
(kl * (jk + jl + kl) * plusP_ik * minusP_il) +
(Complex(0,2) * plusP_ij * plusP_kl * minusC_ji * minusP_ik * minusP_jk)/
(kl * (jk + jl + kl) * plusP_ik * minusP_il) +
(Complex(0,2) * plusP_kl * minusC_ki * minusP_ik * minusP_jk)/
(kl * (jk + jl + kl) * minusP_il) +
(Complex(0,1) * plusP_il * plusP_kl * minusC_li * minusP_ik * minusP_jk)/
(kl * (jk + jl + kl) * plusP_ik * minusP_il) -
(Complex(0,1) * plusP_il * plusP_jl * minusC_ji * minusP_ik * minusP_jl)/
(kl * (jk + jl + kl) * plusP_ik * minusP_il) -
(Complex(0,1) * plusP_il * plusP_kl * minusC_ki * minusP_ik * minusP_jl)/
(kl * (jk + jl + kl) * plusP_ik * minusP_il) -
(Complex(0,2) * sqr(plusP_il) * minusC_jl * minusP_kl)/
(kl * (ik + il + kl) * plusP_ik) +
(Complex(0,2) * plusP_il * plusP_jl * minusC_ji * minusP_ij * minusP_kl)/
(kl * (jk + jl + kl) * plusP_ik * minusP_il) +
(Complex(0,2) * plusP_il * plusP_kl * minusC_ki * minusP_ij * minusP_kl)/
(kl * (jk + jl + kl) * plusP_ik * minusP_il) -
(Complex(0,1) * sqr(plusP_il) * minusC_jk * minusP_ik * minusP_kl)/
(kl * (ik + il + kl) * plusP_ik * minusP_il) +
(Complex(0,1) * plusP_il * minusC_jl * minusP_ik * minusP_kl)/
(kl * (ik + il + kl) * minusP_il);
}
if ( g1Hel == -1 && g2Hel == -1 ) {
return
(Complex(0,2) * sqr(plusP_ij) * minusC_ji * minusP_jk * minusP_jl)/
(jl * (jk + jl + kl) * plusP_ik * plusP_il) +
(Complex(0,2) * plusP_ij * minusC_ki * minusP_jk * minusP_jl)/
(jl * (jk + jl + kl) * plusP_il) +
(Complex(0,2) * plusP_ij * minusC_li * minusP_jk * minusP_jl)/
(jl * (jk + jl + kl) * plusP_ik) -
(Complex(0,2) * plusP_ij * minusC_ji * minusP_jk * minusP_kl)/
(kl * (jk + jl + kl) * plusP_il) -
(Complex(0,2) * plusP_ik * minusC_ki * minusP_jk * minusP_kl)/
(kl * (jk + jl + kl) * plusP_il) -
(Complex(0,2) * minusC_li * minusP_jk * minusP_kl)/
(kl * (jk + jl + kl)) -
(Complex(0,2) * plusP_ij * minusC_ji * minusP_jl * minusP_kl)/
(jl * (jk + jl + kl) * plusP_ik) -
(Complex(0,2) * plusP_ij * minusC_ji * minusP_jl * minusP_kl)/
(kl * (jk + jl + kl) * plusP_ik) -
(Complex(0,2) * minusC_ki * minusP_jl * minusP_kl)/
(jl * (jk + jl + kl)) -
(Complex(0,2) * minusC_ki * minusP_jl * minusP_kl)/
(kl * (jk + jl + kl)) -
(Complex(0,2) * plusP_il * minusC_li * minusP_jl * minusP_kl)/
(jl * (jk + jl + kl) * plusP_ik) -
(Complex(0,2) * plusP_il * minusC_li * minusP_jl * minusP_kl)/
(kl * (jk + jl + kl) * plusP_ik);
}
return czero;
}
const LorentzVector<Complex>& MatchboxCurrents::qqbarggLeftCurrent(const int q, const int qHel,
const int qbar, const int qbarHel,
const int g1, const int g1Hel,
const int g2, const int g2Hel) {
if ( qHel != 1 || qbarHel != 1 )
return czero;
if ( getCurrent(hash<3>(1,1,q,qHel,qbar,qbarHel,g1,g1Hel,g2,g2Hel)) ) {
#ifdef CHECK_MatchboxCurrents
LorentzVector<Complex> ni = qqbarggGeneralLeftCurrent(q,qHel,qbar,qbarHel,g1,g1Hel,g2,g2Hel,q);
LorentzVector<Complex> nj = qqbarggGeneralLeftCurrent(q,qHel,qbar,qbarHel,g1,g1Hel,g2,g2Hel,qbar);
LorentzVector<Complex> nl = qqbarggGeneralLeftCurrent(q,qHel,qbar,qbarHel,g1,g1Hel,g2,g2Hel,0);
LorentzVector<Complex> nlbar = qqbarggGeneralLeftCurrent(q,qHel,qbar,qbarHel,g1,g1Hel,g2,g2Hel,1);
LorentzVector<Complex> fixed = qqbarggFixedLeftCurrent(q,qHel,qbar,qbarHel,g1,g1Hel,g2,g2Hel);
LorentzVector<Complex> x1 = fixed - ni;
LorentzVector<Complex> x2 = fixed - nj;
LorentzVector<Complex> x3 = fixed - nl;
LorentzVector<Complex> x4 = fixed - nlbar;
double c1 =
real(x1.t() * conj(x1.t())) + real(x1.x() * conj(x1.x())) + real(x1.y() * conj(x1.y())) + real(x1.z() * conj(x1.z()));
double c2 =
real(x2.t() * conj(x2.t())) + real(x2.x() * conj(x2.x())) + real(x2.y() * conj(x2.y())) + real(x2.z() * conj(x2.z()));
double c3 =
real(x3.t() * conj(x3.t())) + real(x3.x() * conj(x3.x())) + real(x3.y() * conj(x3.y())) + real(x3.z() * conj(x3.z()));
double c4 =
real(x4.t() * conj(x4.t())) + real(x4.x() * conj(x4.x())) + real(x4.y() * conj(x4.y())) + real(x4.z() * conj(x4.z()));
ostream& ncheck = checkStream("qqbarggLeftCurrentNChoice");
ncheck << (c1 != 0. ? log10(abs(c1)) : 0.) << " "
<< (c2 != 0. ? log10(abs(c2)) : 0.) << " "
<< (c3 != 0. ? log10(abs(c3)) : 0.) << " "
<< (c4 != 0. ? log10(abs(c4)) : 0.) << " "
<< "\n" << flush;
#endif
cacheCurrent(qqbarggFixedLeftCurrent(q,qHel,qbar,qbarHel,g1,g1Hel,g2,g2Hel));
}
#ifdef CHECK_MatchboxCurrents
checkCurrent("qqbarggLeftCurrent",cachedCurrent(),momentum(q)+momentum(qbar)+momentum(g1)+momentum(g2));
#endif
return cachedCurrent();
}
const LorentzVector<Complex>& MatchboxCurrents::qqbarggRightCurrent(const int q, const int qHel,
const int qbar, const int qbarHel,
const int g1, const int g1Hel,
const int g2, const int g2Hel) {
if ( qHel != -1 || qbarHel != -1 )
return czero;
if ( getCurrent(hash<3>(2,1,q,qHel,qbar,qbarHel,g1,g1Hel,g2,g2Hel)) ) {
#ifdef CHECK_MatchboxCurrents
LorentzVector<Complex> ni = qqbarggGeneralRightCurrent(q,qHel,qbar,qbarHel,g1,g1Hel,g2,g2Hel,q);
LorentzVector<Complex> nj = qqbarggGeneralRightCurrent(q,qHel,qbar,qbarHel,g1,g1Hel,g2,g2Hel,qbar);
LorentzVector<Complex> nl = qqbarggGeneralRightCurrent(q,qHel,qbar,qbarHel,g1,g1Hel,g2,g2Hel,0);
LorentzVector<Complex> nlbar = qqbarggGeneralRightCurrent(q,qHel,qbar,qbarHel,g1,g1Hel,g2,g2Hel,1);
LorentzVector<Complex> fixed = qqbarggFixedRightCurrent(q,qHel,qbar,qbarHel,g1,g1Hel,g2,g2Hel);
LorentzVector<Complex> x1 = fixed - ni;
LorentzVector<Complex> x2 = fixed - nj;
LorentzVector<Complex> x3 = fixed - nl;
LorentzVector<Complex> x4 = fixed - nlbar;
double c1 =
real(x1.t() * conj(x1.t())) + real(x1.x() * conj(x1.x())) + real(x1.y() * conj(x1.y())) + real(x1.z() * conj(x1.z()));
double c2 =
real(x2.t() * conj(x2.t())) + real(x2.x() * conj(x2.x())) + real(x2.y() * conj(x2.y())) + real(x2.z() * conj(x2.z()));
double c3 =
real(x3.t() * conj(x3.t())) + real(x3.x() * conj(x3.x())) + real(x3.y() * conj(x3.y())) + real(x3.z() * conj(x3.z()));
double c4 =
real(x4.t() * conj(x4.t())) + real(x4.x() * conj(x4.x())) + real(x4.y() * conj(x4.y())) + real(x4.z() * conj(x4.z()));
ostream& ncheck = checkStream("qqbarggRightCurrentNChoice");
ncheck << (c1 != 0. ? log10(abs(c1)) : 0.) << " "
<< (c2 != 0. ? log10(abs(c2)) : 0.) << " "
<< (c3 != 0. ? log10(abs(c3)) : 0.) << " "
<< (c4 != 0. ? log10(abs(c4)) : 0.) << " "
<< "\n" << flush;
#endif
cacheCurrent(qqbarggFixedRightCurrent(q,qHel,qbar,qbarHel,g1,g1Hel,g2,g2Hel));
}
#ifdef CHECK_MatchboxCurrents
checkCurrent("qqbarggRightCurrent",cachedCurrent(),momentum(q)+momentum(qbar)+momentum(g1)+momentum(g2));
#endif
return cachedCurrent();
}
const LorentzVector<Complex>& MatchboxCurrents::qqbarqqbarLeftCurrent(const int q, const int qHel,
const int qbar, const int qbarHel,
const int k, const int kHel,
const int kbar, const int kbarHel) {
if ( qHel != 1 || qbarHel != 1 ||
abs(kHel+kbarHel) != 2 )
return czero;
const int i = q; const int j = qbar; const int l = kbar;
const double ik = invariant(i,k);
const double il = invariant(i,l);
const double jk = invariant(j,k);
const double jl = invariant(j,l);
const double kl = invariant(k,l);
const Complex plusP_ik = plusProduct(i,k);
const Complex plusP_il = plusProduct(i,l);
const Complex plusP_kj = plusProduct(k,j);
const Complex plusP_kl = plusProduct(k,l);
const Complex plusP_lj = plusProduct(l,j);
const Complex plusP_lk = plusProduct(l,k);
const Complex minusP_ik = minusProduct(i,k);
const Complex minusP_il = minusProduct(i,l);
const Complex minusP_jk = minusProduct(j,k);
const Complex minusP_jl = minusProduct(j,l);
const Complex minusP_ki = minusProduct(k,i);
const Complex minusP_kl = minusProduct(k,l);
const Complex minusP_li = minusProduct(l,i);
const Complex minusP_lk = minusProduct(l,k);
const LorentzVector<Complex> & minusC_ij = minusCurrent(i,j);
const LorentzVector<Complex> & minusC_ik = minusCurrent(i,k);
const LorentzVector<Complex> & minusC_il = minusCurrent(i,l);
const LorentzVector<Complex> & minusC_kj = minusCurrent(k,j);
const LorentzVector<Complex> & minusC_lj = minusCurrent(l,j);
if ( kHel == 1 && kbarHel == 1 ) {
if ( getCurrent(hash<4>(1,1,q,qHel,qbar,qbarHel,k,kHel,kbar,kbarHel)) ) {
cacheCurrent((Complex(0.,-2.)/kl)*
((minusP_ki * plusP_il * minusC_ij+
minusP_ik * plusP_lk * minusC_kj)/
(kl+il+ik)-
(minusP_jk * plusP_lj * minusC_ij+
minusP_lk * plusP_lj * minusC_il)/
(kl+jl+jk)));
}
#ifdef CHECK_MatchboxCurrents
- checkCurrent("qqbarqqbarLeftCurrent",cachedCurrent(),momentum(q)+momentum(qbar)+momentum(k)+momentum(kbar));
+ checkCurrent("qqbarqqbarLeftCurrent",cachedCurrent(),momentum(q)+momentum(qbar)+momentum(k)+momentum(kbar));
#endif
return cachedCurrent();
}
if ( kHel == -1 && kbarHel == -1 ) {
if ( getCurrent(hash<4>(1,1,q,qHel,qbar,qbarHel,k,kHel,kbar,kbarHel)) ) {
cacheCurrent((Complex(0.,-2.)/kl)*
((minusP_li * plusP_ik * minusC_ij+
minusP_il * plusP_kl * minusC_lj)/
(kl+il+ik)-
(minusP_jl * plusP_kj * minusC_ij+
minusP_kl * plusP_kj * minusC_ik)/
(kl+jl+jk)));
}
#ifdef CHECK_MatchboxCurrents
- checkCurrent("qqbarqqbarLeftCurrent",cachedCurrent(),momentum(q)+momentum(qbar)+momentum(k)+momentum(kbar));
+ checkCurrent("qqbarqqbarLeftCurrent",cachedCurrent(),momentum(q)+momentum(qbar)+momentum(k)+momentum(kbar));
#endif
return cachedCurrent();
}
return czero;
}
const LorentzVector<Complex>& MatchboxCurrents::qqbarqqbarRightCurrent(const int q, const int qHel,
const int qbar, const int qbarHel,
const int k, const int kHel,
const int kbar, const int kbarHel) {
if ( qHel != -1 || qbarHel != -1 ||
abs(kHel+kbarHel) != 2 )
return czero;
const int i = q; const int j = qbar; const int l = kbar;
const double ik = invariant(i,k);
const double il = invariant(i,l);
const double jk = invariant(j,k);
const double jl = invariant(j,l);
const double kl = invariant(k,l);
const Complex plusP_ik = plusProduct(i,k);
const Complex plusP_il = plusProduct(i,l);
const Complex plusP_ki = plusProduct(k,i);
const Complex plusP_kj = plusProduct(k,j);
const Complex plusP_kl = plusProduct(k,l);
const Complex plusP_li = plusProduct(l,i);
const Complex plusP_lj = plusProduct(l,j);
const Complex plusP_lk = plusProduct(l,k);
const Complex minusP_jk = minusProduct(j,k);
const Complex minusP_jl = minusProduct(j,l);
const Complex minusP_ki = minusProduct(k,i);
const Complex minusP_kl = minusProduct(k,l);
const Complex minusP_li = minusProduct(l,i);
const Complex minusP_lk = minusProduct(l,k);
const LorentzVector<Complex> & minusC_ji = minusCurrent(j,i);
const LorentzVector<Complex> & minusC_jk = minusCurrent(j,k);
const LorentzVector<Complex> & minusC_jl = minusCurrent(j,l);
const LorentzVector<Complex> & minusC_ki = minusCurrent(k,i);
const LorentzVector<Complex> & minusC_li = minusCurrent(l,i);
if ( kHel == 1 && kbarHel == 1 ) {
if ( getCurrent(hash<4>(2,1,q,qHel,qbar,qbarHel,k,kHel,kbar,kbarHel)) ) {
cacheCurrent((Complex(0.,-2.)/kl)*
((minusP_ki * plusP_il * minusC_ji+
minusP_lk * plusP_li * minusC_jl)/
(kl+il+ik)-
(minusP_jk * plusP_lj * minusC_ji+
minusP_jk * plusP_lk * minusC_ki)/
(kl+jl+jk)));
}
#ifdef CHECK_MatchboxCurrents
- checkCurrent("qqbarqqbarRightCurrent",cachedCurrent(),momentum(q)+momentum(qbar)+momentum(k)+momentum(kbar));
+ checkCurrent("qqbarqqbarRightCurrent",cachedCurrent(),momentum(q)+momentum(qbar)+momentum(k)+momentum(kbar));
#endif
return cachedCurrent();
}
if ( kHel == -1 && kbarHel == -1 ) {
if ( getCurrent(hash<4>(2,1,q,qHel,qbar,qbarHel,k,kHel,kbar,kbarHel)) ) {
cacheCurrent((Complex(0.,-2.)/kl)*
((minusP_li * plusP_ik * minusC_ji+
minusP_kl * plusP_ki * minusC_jk)/
(kl+il+ik)-
(minusP_jl * plusP_kj * minusC_ji+
minusP_jl * plusP_kl * minusC_li)/
(kl+jl+jk)));
}
#ifdef CHECK_MatchboxCurrents
- checkCurrent("qqbarqqbarRightCurrent",cachedCurrent(),momentum(q)+momentum(qbar)+momentum(k)+momentum(kbar));
+ checkCurrent("qqbarqqbarRightCurrent",cachedCurrent(),momentum(q)+momentum(qbar)+momentum(k)+momentum(kbar));
#endif
return cachedCurrent();
}
return czero;
}
+// Definition of sqrt to enable calculation of the sqrt of a negative double
+inline Complex sqrt1 (double a) {
+
+ if (a > 0.) { return Complex(sqrt(a), 0.) ;}
+ else if (a < 0.) { return Complex(0., sqrt(abs(a))) ;}
+ else { return Complex(0., 0.); }
+}
+
+// Definition of sqrt to enable calculation of the sqrt of Complex arguments
+inline Complex sqrt1 (Complex a) {
+
+ const double real_part = sqrt(abs(a))*cos(0.5*arg(a));
+ const double imag_part = sqrt(abs(a))*sin(0.5*arg(a));
+ return Complex(real_part, imag_part) ;
+}
+
+// Definition of log to enable continuation of the log of a negative double
+inline Complex log1 (double a) {
+
+ if (a < 0.) { return Complex(log(abs(a)), Constants::pi) ;}
+ else { return Complex(log(a), 0.) ;}
+}
+
+// Definition of log to enable continuation of the log of a Complex argument with a negative real part
+inline Complex log1 (Complex a) {
+
+ return Complex(log(abs(a)), arg(a)) ;
+}
+
+
const LorentzVector<Complex>& MatchboxCurrents::qqbarLeftOneLoopCurrent(const int q, const int qHel,
const int qbar, const int qbarHel) {
+ // Note this cannot currently handle the case of one massive quark and one massless quark
+ assert( (mass(q) == 0 && mass(qbar) == 0) || (mass(q) != 0 && mass(qbar) != 0) );
- if ( qHel != 1 || qbarHel != 1 )
- return czero;
+ // Massless quarks
+ if ( mass(q) == 0 && mass(qbar) == 0 ) {
- const LorentzVector<Complex>& tree = qqbarLeftCurrent(q,qHel,qbar,qbarHel);
- if ( getCurrent(hash<1>(1,2,q,qHel,qbar,qbarHel)) ) {
- cacheCurrent(0.5 * CF * (3. * log(abs(invariant(q,qbar))) - 8.) * tree);
+ if ( qHel != 1 || qbarHel != 1 )
+ return czero;
+
+ const LorentzVector<Complex>& tree = qqbarLeftCurrent(q,qHel,qbar,qbarHel);
+
+ if ( getCurrent(hash<1>(1,2,q,qHel,qbar,qbarHel)) ) {
+ cacheCurrent( 0.5*CF*( -8. - 3.*log1(-1./invariant(q,qbar)) - sqr(log1(-1./invariant(q,qbar))) ) * tree );
+ }
+
+#ifdef CHECK_MatchboxCurrents
+ checkCurrent("qqbarLeftOneLoopCurrent",cachedCurrent(),momentum(q)+momentum(qbar));
+#endif
+
+ return cachedCurrent();
}
+
+ // Massive quarks
+ else {
+ const LorentzVector<Complex>& momQ = momentum(q) + (sqr(mass(q))/invariant(q,qbar))*momentum(qbar);
+ const LorentzVector<Complex>& momQbar = momentum(qbar) + (sqr(mass(qbar))/invariant(q,qbar))*momentum(q);
+
+ const Complex s = (momQ+momQbar).dot(momQ+momQbar);
+ const Complex inv12 = s - sqr(mass(q)) - sqr(mass(qbar));
+
+ // Coefficient of the left-handed born-level current
+ const Complex coeffLeftTree = -1.0*log1(1./sqr(mass(q)))-1.0*log1(1./sqr(mass(qbar)))-4.0 + 0.5*((2.*log1(sqr(mass(q))/sqr(mass(qbar)))*(0.5*inv12+sqr(mass(q))))/(1.*inv12+sqr(mass(q))+sqr(mass(qbar)))-(2.*inv12*Li2(0.5-(0.25*inv12)/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))-(0.5*sqr(mass(qbar)))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))+(2.*inv12*Li2((0.5*(0.5*inv12+sqr(mass(q))+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))-(1.*inv12*log1(-((0.5*inv12+sqr(mass(q))-1.*sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar))))/(1.*inv12+sqr(mass(q))+sqr(mass(qbar)))))*log1(-((1.*inv12+sqr(mass(q))+sqr(mass(qbar)))/(0.5*inv12+sqr(mass(q))+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))+(2.*inv12*log1((2*sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar))))/(1.*inv12+sqr(mass(q))+sqr(mass(qbar))))*log1((-0.5*inv12-1.*sqr(mass(qbar))+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar))))/(0.5*inv12+sqr(mass(q))+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar))))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))+(1.*inv12*log1((1.*inv12+sqr(mass(q))+sqr(mass(qbar)))/(0.5*inv12+sqr(mass(qbar))-1.*sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))*log1((0.5*inv12+sqr(mass(qbar))+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar))))/(1.*inv12+sqr(mass(q))+sqr(mass(qbar)))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))+(0.5*inv12*sqr(log1(-((0.5*inv12+sqr(mass(q))-1.*sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar))))/(1.*inv12+sqr(mass(q))+sqr(mass(qbar)))))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))+(0.5*inv12*sqr(log1((1.*inv12+sqr(mass(q))+sqr(mass(qbar)))/(0.5*inv12+sqr(mass(qbar))-1.*sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))-(0.5*inv12*sqr(log1(-((1.*inv12+sqr(mass(q))+sqr(mass(qbar)))/(0.5*inv12+sqr(mass(q))+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar))))))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))-(0.5*inv12*sqr(log1((0.5*inv12+sqr(mass(qbar))+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar))))/(1.*inv12+sqr(mass(q))+sqr(mass(qbar))))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))+(4*log1((-1.*mass(q)*mass(qbar))/(0.5*inv12+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))*(-0.25*(3+2*log1(1./(1.*inv12+sqr(mass(q))+sqr(mass(qbar)))))*sqr(inv12)+sqr(mass(q))*sqr(mass(qbar))-0.5*inv12*(1.+log1(1./(1.*inv12+sqr(mass(q))+sqr(mass(qbar)))))*(sqr(mass(q))+sqr(mass(qbar)))))/((1.*inv12+sqr(mass(q))+sqr(mass(qbar)))*sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))));
+
+ // Coefficient of the right-handed born-level current
+ const Complex coeffRightTree = (2*log1((-1.*mass(q)*mass(qbar))/(0.5*inv12+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))*mass(q)*mass(qbar))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)));
+
+ const LorentzVector<Complex>& leftTree = qqbarLeftCurrent(q,qHel,qbar,qbarHel);
+ const LorentzVector<Complex>& rightTree = qqbarRightCurrent(q,qHel,qbar,qbarHel);
+
+ if ( getCurrent(hash<1>(1,2,q,qHel,qbar,qbarHel)) ) {
+
+ if ( qHel == 1 && qbarHel == 1 ) {
+ cacheCurrent( 0.5*CF*( coeffLeftTree*leftTree + coeffRightTree*rightTree) );
+ }
+
+ if ( qHel == 1 && qbarHel == -1 ) {
+ // Coefficients of the left and right handed products of massive spinors
+ const LorentzVector<Complex>& coeffLeftProd = ( (mass(qbar)*(-2.*(momQ+momQbar)*(1.*inv12+sqr(mass(q))+sqr(mass(qbar)))+log1(sqr(mass(q))/sqr(mass(qbar)))*(1.*inv12*(2.*momQ+momQbar)+(3.*momQ+2.*momQbar)*sqr(mass(q))+momQ*sqr(mass(qbar)))-(2.*log1((-1.*mass(q)*mass(qbar))/(0.5*inv12+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))*(0.5*(2.*momQ+momQbar)*sqr(inv12)-momQbar*sqr(mass(q))*sqr(mass(qbar))+0.5*inv12*((5.*momQ+2.*momQbar)*sqr(mass(q))+momQ*sqr(mass(qbar)))+(2.*momQ+momQbar)*sqr(sqr(mass(q)))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))/sqr(1.*inv12+sqr(mass(q))+sqr(mass(qbar))) );
+ const LorentzVector<Complex>& coeffRightProd = ( (mass(q)*(2.*(momQ+momQbar)*(1.*inv12+sqr(mass(q))+sqr(mass(qbar)))+log1(sqr(mass(q))/sqr(mass(qbar)))*(1.*inv12*(momQ+2.*momQbar)+momQbar*sqr(mass(q))+(2.*momQ+3.*momQbar)*sqr(mass(qbar)))+(2.*log1((-1.*mass(q)*mass(qbar))/(0.5*inv12+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))*(0.5*(momQ+2.*momQbar)*sqr(inv12)-momQ*sqr(mass(q))*sqr(mass(qbar))+0.5*inv12*(momQbar*sqr(mass(q))+(2.*momQ+5.*momQbar)*sqr(mass(qbar)))+(momQ+2.*momQbar)*sqr(sqr(mass(qbar)))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))/sqr(1.*inv12+sqr(mass(q))+sqr(mass(qbar))) );
+
+ const Complex leftProd = Complex(0.,1.) * minusProduct(q,qbar);
+ const Complex rightProd = Complex(0.,1.) * mass(q)*mass(qbar)/plusProduct(q,qbar);
+
+ cacheCurrent( 0.5*CF*( coeffLeftTree*leftTree + coeffRightTree*rightTree + coeffLeftProd*leftProd + coeffRightProd*rightProd ) );
+ }
+
+ if ( qHel == -1 && qbarHel == 1 ){
+ // Coefficients of the left and right handed products of massive spinors
+ const LorentzVector<Complex>& coeffLeftProd = ( (mass(qbar)*(-2.*(momQ+momQbar)*(1.*inv12+sqr(mass(q))+sqr(mass(qbar)))+log1(sqr(mass(q))/sqr(mass(qbar)))*(1.*inv12*(2.*momQ+momQbar)+(3.*momQ+2.*momQbar)*sqr(mass(q))+momQ*sqr(mass(qbar)))-(2.*log1((-1.*mass(q)*mass(qbar))/(0.5*inv12+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))*(0.5*(2.*momQ+momQbar)*sqr(inv12)-momQbar*sqr(mass(q))*sqr(mass(qbar))+0.5*inv12*((5.*momQ+2.*momQbar)*sqr(mass(q))+momQ*sqr(mass(qbar)))+(2.*momQ+momQbar)*sqr(sqr(mass(q)))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))/sqr(1.*inv12+sqr(mass(q))+sqr(mass(qbar))) );
+ const LorentzVector<Complex>& coeffRightProd = ( (mass(q)*(2.*(momQ+momQbar)*(1.*inv12+sqr(mass(q))+sqr(mass(qbar)))+log1(sqr(mass(q))/sqr(mass(qbar)))*(1.*inv12*(momQ+2.*momQbar)+momQbar*sqr(mass(q))+(2.*momQ+3.*momQbar)*sqr(mass(qbar)))+(2.*log1((-1.*mass(q)*mass(qbar))/(0.5*inv12+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))*(0.5*(momQ+2.*momQbar)*sqr(inv12)-momQ*sqr(mass(q))*sqr(mass(qbar))+0.5*inv12*(momQbar*sqr(mass(q))+(2.*momQ+5.*momQbar)*sqr(mass(qbar)))+(momQ+2.*momQbar)*sqr(sqr(mass(qbar)))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))/sqr(1.*inv12+sqr(mass(q))+sqr(mass(qbar))) );
+
+ const Complex leftProd = Complex(0.,1.) * mass(q)*mass(qbar)/minusProduct(q,qbar);
+ const Complex rightProd = Complex(0.,1.) * plusProduct(q,qbar);
+
+ cacheCurrent( 0.5*CF*( coeffLeftTree*leftTree + coeffRightTree*rightTree + coeffLeftProd*leftProd + coeffRightProd*rightProd ) );
+ }
+
+ if ( qHel == -1 && qbarHel == -1 ){
+ cacheCurrent( 0.5*CF*( coeffLeftTree*leftTree + coeffRightTree*rightTree ) );
+ }
+
+ }
+
#ifdef CHECK_MatchboxCurrents
- checkCurrent("qqbarLeftOneLoopCurrent",cachedCurrent(),momentum(q)+momentum(qbar));
+ checkCurrent("qqbarLeftOneLoopCurrent",cachedCurrent(),momentum(q)+momentum(qbar));
#endif
- return cachedCurrent();
+ return cachedCurrent();
+ }
}
const LorentzVector<Complex>& MatchboxCurrents::qqbarRightOneLoopCurrent(const int q, const int qHel,
- const int qbar, const int qbarHel) {
+ const int qbar, const int qbarHel) {
+ // Note this cannot currently handle the case of one massive quark and one massless quark
+ assert( (mass(q) == 0 && mass(qbar) == 0) || (mass(q) != 0 && mass(qbar) != 0) );
- if ( qHel != -1 || qbarHel != -1 )
- return czero;
+ // Massless quarks
+ if ( mass(q) == 0 && mass(qbar) ==0 ) {
- const LorentzVector<Complex>& tree = qqbarRightCurrent(q,qHel,qbar,qbarHel);
- if ( getCurrent(hash<1>(2,2,q,qHel,qbar,qbarHel)) ) {
- cacheCurrent(0.5 * CF * (3. * log(abs(invariant(q,qbar))) - 8.) * tree);
+ if ( qHel != -1 || qbarHel != -1 )
+ return czero;
+
+ const LorentzVector<Complex>& tree = qqbarRightCurrent(q,qHel,qbar,qbarHel);
+
+ if ( getCurrent(hash<1>(2,2,q,qHel,qbar,qbarHel)) ) {
+ cacheCurrent( 0.5*CF*( -8. - 3.*log1(-1./invariant(q,qbar)) - sqr(log1(-1./invariant(q,qbar))) ) * tree );
+ }
+
+#ifdef CHECK_MatchboxCurrents
+ checkCurrent("qqbarRightOneLoopCurrent",cachedCurrent(),momentum(q)+momentum(qbar));
+#endif
+
+ return cachedCurrent();
}
+
+ // Massive quarks
+ else {
+ const LorentzVector<Complex>& momQ = momentum(q) + (sqr(mass(q))/invariant(q,qbar))*momentum(qbar);
+ const LorentzVector<Complex>& momQbar = momentum(qbar) + (sqr(mass(qbar))/invariant(q,qbar))*momentum(q);
+
+ const Complex s = (momQ+momQbar).dot(momQ+momQbar);
+ const Complex inv12 = s - sqr(mass(q)) - sqr(mass(qbar));
+
+ // Coefficient of the right-handed born-level current
+ const Complex coeffRightTree = -1.0*log1(1./sqr(mass(q)))-1.0*log1(1./sqr(mass(qbar)))-4.0 + 0.5*((2.*log1(sqr(mass(q))/sqr(mass(qbar)))*(0.5*inv12+sqr(mass(q))))/(1.*inv12+sqr(mass(q))+sqr(mass(qbar)))-(2.*inv12*Li2(0.5-(0.25*inv12)/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))-(0.5*sqr(mass(qbar)))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))+(2.*inv12*Li2((0.5*(0.5*inv12+sqr(mass(q))+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))-(1.*inv12*log1(-((0.5*inv12+sqr(mass(q))-1.*sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar))))/(1.*inv12+sqr(mass(q))+sqr(mass(qbar)))))*log1(-((1.*inv12+sqr(mass(q))+sqr(mass(qbar)))/(0.5*inv12+sqr(mass(q))+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))+(2.*inv12*log1((2*sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar))))/(1.*inv12+sqr(mass(q))+sqr(mass(qbar))))*log1((-0.5*inv12-1.*sqr(mass(qbar))+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar))))/(0.5*inv12+sqr(mass(q))+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar))))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))+(1.*inv12*log1((1.*inv12+sqr(mass(q))+sqr(mass(qbar)))/(0.5*inv12+sqr(mass(qbar))-1.*sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))*log1((0.5*inv12+sqr(mass(qbar))+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar))))/(1.*inv12+sqr(mass(q))+sqr(mass(qbar)))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))+(0.5*inv12*sqr(log1(-((0.5*inv12+sqr(mass(q))-1.*sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar))))/(1.*inv12+sqr(mass(q))+sqr(mass(qbar)))))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))+(0.5*inv12*sqr(log1((1.*inv12+sqr(mass(q))+sqr(mass(qbar)))/(0.5*inv12+sqr(mass(qbar))-1.*sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))-(0.5*inv12*sqr(log1(-((1.*inv12+sqr(mass(q))+sqr(mass(qbar)))/(0.5*inv12+sqr(mass(q))+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar))))))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))-(0.5*inv12*sqr(log1((0.5*inv12+sqr(mass(qbar))+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar))))/(1.*inv12+sqr(mass(q))+sqr(mass(qbar))))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))+(4*log1((-1.*mass(q)*mass(qbar))/(0.5*inv12+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))*(-0.25*(3+2*log1(1./(1.*inv12+sqr(mass(q))+sqr(mass(qbar)))))*sqr(inv12)+sqr(mass(q))*sqr(mass(qbar))-0.5*inv12*(1.+log1(1./(1.*inv12+sqr(mass(q))+sqr(mass(qbar)))))*(sqr(mass(q))+sqr(mass(qbar)))))/((1.*inv12+sqr(mass(q))+sqr(mass(qbar)))*sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))));
+
+ // Coefficient of the left-handed born-level current
+ const Complex coeffLeftTree = (2*log1((-1.*mass(q)*mass(qbar))/(0.5*inv12+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))*mass(q)*mass(qbar))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)));
+
+ const LorentzVector<Complex>& leftTree = qqbarLeftCurrent(q,qHel,qbar,qbarHel);
+ const LorentzVector<Complex>& rightTree = qqbarRightCurrent(q,qHel,qbar,qbarHel);
+
+ if ( getCurrent(hash<1>(2,2,q,qHel,qbar,qbarHel)) ) {
+
+ if ( qHel == 1 && qbarHel == 1 ) {
+ cacheCurrent( 0.5*CF*( coeffLeftTree*leftTree + coeffRightTree*rightTree ) );
+ }
+
+ if ( qHel == 1 && qbarHel == -1 ) {
+ // Coefficients of the right and left handed products of massive spinors
+ const LorentzVector<Complex>& coeffRightProd = ( (mass(qbar)*(-2.*(momQ+momQbar)*(1.*inv12+sqr(mass(q))+sqr(mass(qbar)))+log1(sqr(mass(q))/sqr(mass(qbar)))*(1.*inv12*(2.*momQ+momQbar)+(3.*momQ+2.*momQbar)*sqr(mass(q))+momQ*sqr(mass(qbar)))-(2.*log1((-1.*mass(q)*mass(qbar))/(0.5*inv12+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))*(0.5*(2.*momQ+momQbar)*sqr(inv12)-momQbar*sqr(mass(q))*sqr(mass(qbar))+0.5*inv12*((5.*momQ+2.*momQbar)*sqr(mass(q))+momQ*sqr(mass(qbar)))+(2.*momQ+momQbar)*sqr(sqr(mass(q)))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))/sqr(1.*inv12+sqr(mass(q))+sqr(mass(qbar))) );
+ const LorentzVector<Complex>& coeffLeftProd = ( (mass(q)*(2.*(momQ+momQbar)*(1.*inv12+sqr(mass(q))+sqr(mass(qbar)))+log1(sqr(mass(q))/sqr(mass(qbar)))*(1.*inv12*(momQ+2.*momQbar)+momQbar*sqr(mass(q))+(2.*momQ+3.*momQbar)*sqr(mass(qbar)))+(2.*log1((-1.*mass(q)*mass(qbar))/(0.5*inv12+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))*(0.5*(momQ+2.*momQbar)*sqr(inv12)-momQ*sqr(mass(q))*sqr(mass(qbar))+0.5*inv12*(momQbar*sqr(mass(q))+(2.*momQ+5.*momQbar)*sqr(mass(qbar)))+(momQ+2.*momQbar)*sqr(sqr(mass(qbar)))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))/sqr(1.*inv12+sqr(mass(q))+sqr(mass(qbar))) );
+
+ const Complex leftProd = Complex(0.,1.) * minusProduct(q,qbar);
+ const Complex rightProd = Complex(0.,1.) * mass(q)*mass(qbar)/plusProduct(q,qbar);
+
+ cacheCurrent( 0.5*CF*( coeffLeftTree*leftTree + coeffRightTree*rightTree + coeffLeftProd*leftProd + coeffRightProd*rightProd ) );
+ }
+
+ if ( qHel == -1 && qbarHel == 1 ){
+ // Coefficients of the right and left handed products of massive spinors
+ const LorentzVector<Complex>& coeffRightProd = ( (mass(qbar)*(-2.*(momQ+momQbar)*(1.*inv12+sqr(mass(q))+sqr(mass(qbar)))+log1(sqr(mass(q))/sqr(mass(qbar)))*(1.*inv12*(2.*momQ+momQbar)+(3.*momQ+2.*momQbar)*sqr(mass(q))+momQ*sqr(mass(qbar)))-(2.*log1((-1.*mass(q)*mass(qbar))/(0.5*inv12+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))*(0.5*(2.*momQ+momQbar)*sqr(inv12)-momQbar*sqr(mass(q))*sqr(mass(qbar))+0.5*inv12*((5.*momQ+2.*momQbar)*sqr(mass(q))+momQ*sqr(mass(qbar)))+(2.*momQ+momQbar)*sqr(sqr(mass(q)))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))/sqr(1.*inv12+sqr(mass(q))+sqr(mass(qbar))) );
+ const LorentzVector<Complex>& coeffLeftProd = ( (mass(q)*(2.*(momQ+momQbar)*(1.*inv12+sqr(mass(q))+sqr(mass(qbar)))+log1(sqr(mass(q))/sqr(mass(qbar)))*(1.*inv12*(momQ+2.*momQbar)+momQbar*sqr(mass(q))+(2.*momQ+3.*momQbar)*sqr(mass(qbar)))+(2.*log1((-1.*mass(q)*mass(qbar))/(0.5*inv12+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))*(0.5*(momQ+2.*momQbar)*sqr(inv12)-momQ*sqr(mass(q))*sqr(mass(qbar))+0.5*inv12*(momQbar*sqr(mass(q))+(2.*momQ+5.*momQbar)*sqr(mass(qbar)))+(momQ+2.*momQbar)*sqr(sqr(mass(qbar)))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))/sqr(1.*inv12+sqr(mass(q))+sqr(mass(qbar))) );
+
+ const Complex leftProd = Complex(0.,1.) * mass(q)*mass(qbar)/minusProduct(q,qbar);
+ const Complex rightProd = Complex(0.,1.) * plusProduct(q,qbar);
+
+ cacheCurrent( 0.5*CF*( coeffLeftTree*leftTree + coeffRightTree*rightTree + coeffLeftProd*leftProd + coeffRightProd*rightProd ) );
+ }
+
+ if ( qHel == -1 && qbarHel == -1 ){
+ cacheCurrent( 0.5*CF*( coeffLeftTree*leftTree + coeffRightTree*rightTree ) );
+ }
+
+ }
+
#ifdef CHECK_MatchboxCurrents
- checkCurrent("qqbarRightOneLoopCurrent",cachedCurrent(),momentum(q)+momentum(qbar));
+ checkCurrent("qqbarRightOneLoopCurrent",cachedCurrent(),momentum(q)+momentum(qbar));
#endif
- return cachedCurrent();
+ return cachedCurrent();
+ }
}
+
// ln(s(a+i0))
inline Complex log(double s, double a) {
return
s < 0. ?
- Complex(log(abs(a)),-pi * theta(a)) :
+ Complex(log(abs(a)),-pi * theta(a)) :
Complex(log(abs(a)),pi * theta(-a));
}
// ln(s(a+i0)/(b+i0))
inline Complex log(double s, double a, double b) {
return
s < 0. ?
- Complex(log(abs(a/b)),-pi * theta(a/b) * sign(b-a)) :
+ Complex(log(abs(a/b)),-pi * theta(a/b) * sign(b-a)) :
Complex(log(abs(a/b)),pi * theta(-a/b) * sign(b-a));
}
+
// Li2(-(a+i0)/(b+i0))
inline Complex Li2(double a, double b) {
if ( -a/b < 1. )
return Complex(Herwig::Math::ReLi2(-a/b),0.0);
return Complex(Herwig::Math::ReLi2(-a/b),-pi * log(-a/b) * sign(b-a));
}
Complex MatchboxCurrents::box6(const int i, const int j, const int k) {
const double sij = invariant(i,j);
const double sik = invariant(i,k);
const double sjk = invariant(j,k);
return
-( Li2(sik+sjk,sij) + Li2(sik+sij,sjk) + 0.5 * csqr(log(1.,sij,sjk)) + sqr(pi)/6. )/8.;
}
void MatchboxCurrents::qqbargLoopCoefficients(const int i, const int j, const int k) {
// use a dummy cache entry to check if we need to get some work done
static Complex dummy;
if ( getAmplitude(hash<5>(1,2,i,0,j,0,k,0)) ) {
dummy = 0.;
cacheAmplitude(dummy);
cachedAmplitude();
} else {
cachedAmplitude();
return;
}
qqbargLoops.resize(13);
// get the transcendentals
const double ij = invariant(i,j);
const double ij2 = sqr(ij);
const double ij3 = ij2 * ij;
const double ik = invariant(i,k);
const double ik2 = sqr(ik);
//const double ik3 = ik2 * ik;
const double jk = invariant(j,k);
const double jk2 = sqr(jk);
const double jk3 = jk2 * jk;
const double ij_ik = ij + ik;
const double ij_ik_2 = sqr(ij_ik);
const double ij_jk = ij + jk;
const double ij_jk_2 = sqr(ij_jk);
const double ik_jk = ik + jk;
const double ik_jk_2 = sqr(ik_jk);
const double Q2 = ij + ik + jk;
// checked for LEP that virtuals + I operator are mu2 independent
//double xmu2 = 10 * GeV2/sqr(amplitudeScale());
const double xmu2 = 1.;
const Complex Lijk = log(1.,-xmu2/Q2);
const Complex Lij = log(1.,Q2,ij);
const Complex Lik = log(1.,Q2,ik);
const Complex Ljk = log(1.,Q2,jk);
const Complex Box6ijk = box6(i,j,k);
const Complex Box6ikj = box6(i,k,j);
const Complex Box6jik = box6(j,i,k);
// get the coefficients
qqbargLoops[0] = (
- (2 * CF * ij2) -
- (32 * CA * Box6ijk * ij2) +
- (64 * CF * Box6ijk * ij2) -
- (8 * CA * Box6jik * ij2) +
- (16 * CF * Box6jik * ij2) +
- (2 * CA * Lij * ij2) -
- (4 * CF * Lij * ij2) -
- (CA * Lik * ij2) -
- (2 * CF * Lik * ij2) -
- (4 * CF * Ljk * ij2) -
- (16 * CA * Box6ijk * ij3) / ik +
- (32 * CF * Box6ijk * ij3) / ik +
- (CA * Lij * ij3) / ik -
- (2 * CF * Lij * ij3) / ik +
- (2 * CF * ij * ik) -
- (16 * CA * Box6ijk * ij * ik) +
- (32 * CF * Box6ijk * ij * ik) -
- (16 * CA * Box6jik * ij * ik) +
- (32 * CF * Box6jik * ij * ik) +
- (CA * Lij * ij * ik) -
- (2 * CF * Lij * ij * ik) -
- (2 * CA * Lik * ij * ik) -
- (4 * CF * Lik * ij * ik) -
- (4 * CF * Ljk * ij * ik) -
- (8 * CA * Box6jik * ik2) +
- (16 * CF * Box6jik * ik2) -
- (CA * Lik * ik2) -
- (2 * CF * Lik * ik2) -
- (8 * CA * Box6jik * ij3) / jk +
- (16 * CF * Box6jik * ij3) / jk -
- (16 * CA * Box6jik * ij2 * ik) / jk +
- (32 * CF * Box6jik * ij2 * ik) / jk -
- (8 * CA * Box6jik * ij * ik2) / jk +
- (16 * CF * Box6jik * ij * ik2) / jk +
- (2 * CF * ij * jk) -
- (40 * CA * Box6ijk * ij * jk) +
- (80 * CF * Box6ijk * ij * jk) +
- (24 * CA * Box6ikj * ij * jk) +
- (2 * CA * Lij * ij * jk) -
- (4 * CF * Lij * ij * jk) -
- (CA * Lik * ij * jk) -
- (4 * CF * Lik * ij * jk) -
- (12 * CF * Ljk * ij * jk) -
- (8 * CA * Box6ijk * ij3 * jk) / ik2 +
- (16 * CF * Box6ijk * ij3 * jk) / ik2 -
- (32 * CA * Box6ijk * ij2 * jk) / ik +
- (64 * CF * Box6ijk * ij2 * jk) / ik +
- (CA * Lij * ij2 * jk) / ik -
- (2 * CF * Lij * ij2 * jk) / ik +
- (CA * Ljk * ij2 * jk) / ik -
- (2 * CF * Ljk * ij2 * jk) / ik +
- (2 * CF * ik * jk) -
- (16 * CA * Box6ijk * ik * jk) +
- (32 * CF * Box6ijk * ik * jk) +
- (48 * CA * Box6ikj * ik * jk) +
- (CA * Lij * ik * jk) -
- (2 * CF * Lij * ik * jk) -
- (2 * CA * Lik * ik * jk) -
- (8 * CF * Lik * ik * jk) -
- (CA * Ljk * ik * jk) -
- (8 * CF * Ljk * ik * jk) +
- (24 * CA * Box6ikj * ik2 * jk) / ij -
- (CA * Lik * ik2 * jk) / ij -
- (4 * CF * Lik * ik2 * jk) / ij -
- (8 * CA * Box6ijk * jk2) +
- (16 * CF * Box6ijk * jk2) +
- (24 * CA * Box6ikj * jk2) -
- (8 * CF * Ljk * jk2) -
- (8 * CA * Box6ijk * ij2 * jk2) / ik2 +
- (16 * CF * Box6ijk * ij2 * jk2) / ik2 -
- (16 * CA * Box6ijk * ij * jk2) / ik +
- (32 * CF * Box6ijk * ij * jk2) / ik +
- (CA * Ljk * ij * jk2) / ik -
- (2 * CF * Ljk * ij * jk2) / ik +
- (48 * CA * Box6ikj * ik * jk2) / ij -
- (CA * Ljk * ik * jk2) / ij -
- (4 * CF * Ljk * ik * jk2) / ij +
- (24 * CA * Box6ikj * ik2 * jk2) / ij2
- ) / (ij_ik_2 * ij_jk);
+ (2 * CF * ij2) -
+ (32 * CA * Box6ijk * ij2) +
+ (64 * CF * Box6ijk * ij2) -
+ (8 * CA * Box6jik * ij2) +
+ (16 * CF * Box6jik * ij2) +
+ (2 * CA * Lij * ij2) -
+ (4 * CF * Lij * ij2) -
+ (CA * Lik * ij2) -
+ (2 * CF * Lik * ij2) -
+ (4 * CF * Ljk * ij2) -
+ (16 * CA * Box6ijk * ij3) / ik +
+ (32 * CF * Box6ijk * ij3) / ik +
+ (CA * Lij * ij3) / ik -
+ (2 * CF * Lij * ij3) / ik +
+ (2 * CF * ij * ik) -
+ (16 * CA * Box6ijk * ij * ik) +
+ (32 * CF * Box6ijk * ij * ik) -
+ (16 * CA * Box6jik * ij * ik) +
+ (32 * CF * Box6jik * ij * ik) +
+ (CA * Lij * ij * ik) -
+ (2 * CF * Lij * ij * ik) -
+ (2 * CA * Lik * ij * ik) -
+ (4 * CF * Lik * ij * ik) -
+ (4 * CF * Ljk * ij * ik) -
+ (8 * CA * Box6jik * ik2) +
+ (16 * CF * Box6jik * ik2) -
+ (CA * Lik * ik2) -
+ (2 * CF * Lik * ik2) -
+ (8 * CA * Box6jik * ij3) / jk +
+ (16 * CF * Box6jik * ij3) / jk -
+ (16 * CA * Box6jik * ij2 * ik) / jk +
+ (32 * CF * Box6jik * ij2 * ik) / jk -
+ (8 * CA * Box6jik * ij * ik2) / jk +
+ (16 * CF * Box6jik * ij * ik2) / jk +
+ (2 * CF * ij * jk) -
+ (40 * CA * Box6ijk * ij * jk) +
+ (80 * CF * Box6ijk * ij * jk) +
+ (24 * CA * Box6ikj * ij * jk) +
+ (2 * CA * Lij * ij * jk) -
+ (4 * CF * Lij * ij * jk) -
+ (CA * Lik * ij * jk) -
+ (4 * CF * Lik * ij * jk) -
+ (12 * CF * Ljk * ij * jk) -
+ (8 * CA * Box6ijk * ij3 * jk) / ik2 +
+ (16 * CF * Box6ijk * ij3 * jk) / ik2 -
+ (32 * CA * Box6ijk * ij2 * jk) / ik +
+ (64 * CF * Box6ijk * ij2 * jk) / ik +
+ (CA * Lij * ij2 * jk) / ik -
+ (2 * CF * Lij * ij2 * jk) / ik +
+ (CA * Ljk * ij2 * jk) / ik -
+ (2 * CF * Ljk * ij2 * jk) / ik +
+ (2 * CF * ik * jk) -
+ (16 * CA * Box6ijk * ik * jk) +
+ (32 * CF * Box6ijk * ik * jk) +
+ (48 * CA * Box6ikj * ik * jk) +
+ (CA * Lij * ik * jk) -
+ (2 * CF * Lij * ik * jk) -
+ (2 * CA * Lik * ik * jk) -
+ (8 * CF * Lik * ik * jk) -
+ (CA * Ljk * ik * jk) -
+ (8 * CF * Ljk * ik * jk) +
+ (24 * CA * Box6ikj * ik2 * jk) / ij -
+ (CA * Lik * ik2 * jk) / ij -
+ (4 * CF * Lik * ik2 * jk) / ij -
+ (8 * CA * Box6ijk * jk2) +
+ (16 * CF * Box6ijk * jk2) +
+ (24 * CA * Box6ikj * jk2) -
+ (8 * CF * Ljk * jk2) -
+ (8 * CA * Box6ijk * ij2 * jk2) / ik2 +
+ (16 * CF * Box6ijk * ij2 * jk2) / ik2 -
+ (16 * CA * Box6ijk * ij * jk2) / ik +
+ (32 * CF * Box6ijk * ij * jk2) / ik +
+ (CA * Ljk * ij * jk2) / ik -
+ (2 * CF * Ljk * ij * jk2) / ik +
+ (48 * CA * Box6ikj * ik * jk2) / ij -
+ (CA * Ljk * ik * jk2) / ij -
+ (4 * CF * Ljk * ik * jk2) / ij +
+ (24 * CA * Box6ikj * ik2 * jk2) / ij2
+ ) / (ij_ik_2 * ij_jk);
qqbargLoops[1] = (
- (-2 * CF * ij2) +
- (8 * CA * Box6ijk * ij2) -
- (16 * CF * Box6ijk * ij2) +
- (32 * CA * Box6jik * ij2) -
- (64 * CF * Box6jik * ij2) -
- (2 * CA * Lij * ij2) +
- (4 * CF * Lij * ij2) +
- (4 * CF * Lik * ij2) +
- (CA * Ljk * ij2) +
- (2 * CF * Ljk * ij2) +
- (8 * CA * Box6ijk * ij3) / ik -
- (16 * CF * Box6ijk * ij3) / ik -
- (2 * CF * ij * ik) -
- (24 * CA * Box6ikj * ij * ik) +
- (40 * CA * Box6jik * ij * ik) -
- (80 * CF * Box6jik * ij * ik) -
- (2 * CA * Lij * ij * ik) +
- (4 * CF * Lij * ij * ik) +
- (12 * CF * Lik * ij * ik) +
- (CA * Ljk * ij * ik) +
- (4 * CF * Ljk * ij * ik) -
- (24 * CA * Box6ikj * ik2) +
- (8 * CA * Box6jik * ik2) -
- (16 * CF * Box6jik * ik2) +
- (8 * CF * Lik * ik2) +
- (8 * CA * Box6jik * ij3 * ik) / jk2 -
- (16 * CF * Box6jik * ij3 * ik) / jk2 +
- (8 * CA * Box6jik * ij2 * ik2) / jk2 -
- (16 * CF * Box6jik * ij2 * ik2) / jk2 +
- (16 * CA * Box6jik * ij3) / jk -
- (32 * CF * Box6jik * ij3) / jk -
- (CA * Lij * ij3) / jk +
- (2 * CF * Lij * ij3) / jk +
- (32 * CA * Box6jik * ij2 * ik) / jk -
- (64 * CF * Box6jik * ij2 * ik) / jk -
- (CA * Lij * ij2 * ik) / jk +
- (2 * CF * Lij * ij2 * ik) / jk -
- (CA * Lik * ij2 * ik) / jk +
- (2 * CF * Lik * ij2 * ik) / jk +
- (16 * CA * Box6jik * ij * ik2) / jk -
- (32 * CF * Box6jik * ij * ik2) / jk -
- (CA * Lik * ij * ik2) / jk +
- (2 * CF * Lik * ij * ik2) / jk -
- (2 * CF * ij * jk) +
- (16 * CA * Box6ijk * ij * jk) -
- (32 * CF * Box6ijk * ij * jk) +
- (16 * CA * Box6jik * ij * jk) -
- (32 * CF * Box6jik * ij * jk) -
- (CA * Lij * ij * jk) +
- (2 * CF * Lij * ij * jk) +
- (4 * CF * Lik * ij * jk) +
- (2 * CA * Ljk * ij * jk) +
- (4 * CF * Ljk * ij * jk) +
- (16 * CA * Box6ijk * ij2 * jk) / ik -
- (32 * CF * Box6ijk * ij2 * jk) / ik -
- (2 * CF * ik * jk) -
- (48 * CA * Box6ikj * ik * jk) +
- (16 * CA * Box6jik * ik * jk) -
- (32 * CF * Box6jik * ik * jk) -
- (CA * Lij * ik * jk) +
- (2 * CF * Lij * ik * jk) +
- (CA * Lik * ik * jk) +
- (8 * CF * Lik * ik * jk) +
- (2 * CA * Ljk * ik * jk) +
- (8 * CF * Ljk * ik * jk) -
- (48 * CA * Box6ikj * ik2 * jk) / ij +
- (CA * Lik * ik2 * jk) / ij +
- (4 * CF * Lik * ik2 * jk) / ij +
- (8 * CA * Box6ijk * jk2) -
- (16 * CF * Box6ijk * jk2) +
- (CA * Ljk * jk2) +
- (2 * CF * Ljk * jk2) +
- (8 * CA * Box6ijk * ij * jk2) / ik -
- (16 * CF * Box6ijk * ij * jk2) / ik -
- (24 * CA * Box6ikj * ik * jk2) / ij +
- (CA * Ljk * ik * jk2) / ij +
- (4 * CF * Ljk * ik * jk2) / ij -
- (24 * CA * Box6ikj * ik2 * jk2) / ij2
- ) / (ij_ik * ij_jk_2);
+ (-2 * CF * ij2) +
+ (8 * CA * Box6ijk * ij2) -
+ (16 * CF * Box6ijk * ij2) +
+ (32 * CA * Box6jik * ij2) -
+ (64 * CF * Box6jik * ij2) -
+ (2 * CA * Lij * ij2) +
+ (4 * CF * Lij * ij2) +
+ (4 * CF * Lik * ij2) +
+ (CA * Ljk * ij2) +
+ (2 * CF * Ljk * ij2) +
+ (8 * CA * Box6ijk * ij3) / ik -
+ (16 * CF * Box6ijk * ij3) / ik -
+ (2 * CF * ij * ik) -
+ (24 * CA * Box6ikj * ij * ik) +
+ (40 * CA * Box6jik * ij * ik) -
+ (80 * CF * Box6jik * ij * ik) -
+ (2 * CA * Lij * ij * ik) +
+ (4 * CF * Lij * ij * ik) +
+ (12 * CF * Lik * ij * ik) +
+ (CA * Ljk * ij * ik) +
+ (4 * CF * Ljk * ij * ik) -
+ (24 * CA * Box6ikj * ik2) +
+ (8 * CA * Box6jik * ik2) -
+ (16 * CF * Box6jik * ik2) +
+ (8 * CF * Lik * ik2) +
+ (8 * CA * Box6jik * ij3 * ik) / jk2 -
+ (16 * CF * Box6jik * ij3 * ik) / jk2 +
+ (8 * CA * Box6jik * ij2 * ik2) / jk2 -
+ (16 * CF * Box6jik * ij2 * ik2) / jk2 +
+ (16 * CA * Box6jik * ij3) / jk -
+ (32 * CF * Box6jik * ij3) / jk -
+ (CA * Lij * ij3) / jk +
+ (2 * CF * Lij * ij3) / jk +
+ (32 * CA * Box6jik * ij2 * ik) / jk -
+ (64 * CF * Box6jik * ij2 * ik) / jk -
+ (CA * Lij * ij2 * ik) / jk +
+ (2 * CF * Lij * ij2 * ik) / jk -
+ (CA * Lik * ij2 * ik) / jk +
+ (2 * CF * Lik * ij2 * ik) / jk +
+ (16 * CA * Box6jik * ij * ik2) / jk -
+ (32 * CF * Box6jik * ij * ik2) / jk -
+ (CA * Lik * ij * ik2) / jk +
+ (2 * CF * Lik * ij * ik2) / jk -
+ (2 * CF * ij * jk) +
+ (16 * CA * Box6ijk * ij * jk) -
+ (32 * CF * Box6ijk * ij * jk) +
+ (16 * CA * Box6jik * ij * jk) -
+ (32 * CF * Box6jik * ij * jk) -
+ (CA * Lij * ij * jk) +
+ (2 * CF * Lij * ij * jk) +
+ (4 * CF * Lik * ij * jk) +
+ (2 * CA * Ljk * ij * jk) +
+ (4 * CF * Ljk * ij * jk) +
+ (16 * CA * Box6ijk * ij2 * jk) / ik -
+ (32 * CF * Box6ijk * ij2 * jk) / ik -
+ (2 * CF * ik * jk) -
+ (48 * CA * Box6ikj * ik * jk) +
+ (16 * CA * Box6jik * ik * jk) -
+ (32 * CF * Box6jik * ik * jk) -
+ (CA * Lij * ik * jk) +
+ (2 * CF * Lij * ik * jk) +
+ (CA * Lik * ik * jk) +
+ (8 * CF * Lik * ik * jk) +
+ (2 * CA * Ljk * ik * jk) +
+ (8 * CF * Ljk * ik * jk) -
+ (48 * CA * Box6ikj * ik2 * jk) / ij +
+ (CA * Lik * ik2 * jk) / ij +
+ (4 * CF * Lik * ik2 * jk) / ij +
+ (8 * CA * Box6ijk * jk2) -
+ (16 * CF * Box6ijk * jk2) +
+ (CA * Ljk * jk2) +
+ (2 * CF * Ljk * jk2) +
+ (8 * CA * Box6ijk * ij * jk2) / ik -
+ (16 * CF * Box6ijk * ij * jk2) / ik -
+ (24 * CA * Box6ikj * ik * jk2) / ij +
+ (CA * Ljk * ik * jk2) / ij +
+ (4 * CF * Ljk * ik * jk2) / ij -
+ (24 * CA * Box6ikj * ik2 * jk2) / ij2
+ ) / (ij_ik * ij_jk_2);
qqbargLoops[2] = -3 * CF * Lijk + (
- (-4 * CA * Box6jik * ij3) +
- (8 * CF * Box6jik * ij3) +
- (CA * Lij * ij3) / 2. -
- (CF * Lij * ij3) +
- (CA * ij2 * ik) -
- (9 * CF * ij2 * ik) +
- (8 * CA * Box6ijk * ij2 * ik) -
- (16 * CF * Box6ijk * ij2 * ik) -
- (8 * CA * Box6ikj * ij2 * ik) -
- (8 * CA * Box6jik * ij2 * ik) +
- (16 * CF * Box6jik * ij2 * ik) +
- (CA * Lij * ij2 * ik) / 2. -
- (CF * Lij * ij2 * ik) +
- (CA * Lik * ij2 * ik) / 2. -
- (CF * Lik * ij2 * ik) +
- (CA * ij * ik2) -
- (9 * CF * ij * ik2) +
- (8 * CA * Box6ijk * ij * ik2) -
- (16 * CF * Box6ijk * ij * ik2) -
- (8 * CA * Box6ikj * ij * ik2) -
- (4 * CA * Box6jik * ij * ik2) +
- (8 * CF * Box6jik * ij * ik2) +
- (CA * Lik * ij * ik2) / 2. -
- (CF * Lik * ij * ik2) -
- (4 * CA * Box6jik * ij3 * ik) / jk +
- (8 * CF * Box6jik * ij3 * ik) / jk -
- (4 * CA * Box6jik * ij2 * ik2) / jk +
- (8 * CF * Box6jik * ij2 * ik2) / jk +
- (CA * ij2 * jk) -
- (9 * CF * ij2 * jk) +
- (12 * CA * Box6ijk * ij2 * jk) -
- (24 * CF * Box6ijk * ij2 * jk) -
- (8 * CA * Box6ikj * ij2 * jk) -
- (4 * CA * Box6jik * ij2 * jk) +
- (8 * CF * Box6jik * ij2 * jk) +
- (CA * Lik * ij2 * jk) / 2. -
- (CF * Lik * ij2 * jk) -
- (CA * Ljk * ij2 * jk) / 2. +
- (CF * Ljk * ij2 * jk) +
- (4 * CA * Box6ijk * ij3 * jk) / ik -
- (8 * CF * Box6ijk * ij3 * jk) / ik -
- (CA * Lij * ij3 * jk) / (2. * ik) +
- (CF * Lij * ij3 * jk) / ik +
- (2 * CA * ij * ik * jk) -
- (18 * CF * ij * ik * jk) +
- (16 * CA * Box6ijk * ij * ik * jk) -
- (32 * CF * Box6ijk * ij * ik * jk) -
- (28 * CA * Box6ikj * ij * ik * jk) -
- (4 * CA * Box6jik * ij * ik * jk) +
- (8 * CF * Box6jik * ij * ik * jk) +
- (CA * Lij * ij * ik * jk) / 2. -
- (CF * Lij * ij * ik * jk) +
- (CA * Lik * ij * ik * jk) -
- (CF * Lik * ij * ik * jk) -
- (CA * Ljk * ij * ik * jk) / 2. +
- (3 * CF * Ljk * ij * ik * jk) +
- (CA * ik2 * jk) -
- (9 * CF * ik2 * jk) +
- (8 * CA * Box6ijk * ik2 * jk) -
- (16 * CF * Box6ijk * ik2 * jk) -
- (20 * CA * Box6ikj * ik2 * jk) +
- (CA * Lik * ik2 * jk) / 2. +
- (CA * ij * jk2) -
- (9 * CF * ij * jk2) +
- (12 * CA * Box6ijk * ij * jk2) -
- (24 * CF * Box6ijk * ij * jk2) -
- (20 * CA * Box6ikj * ij * jk2) -
- (CA * Lij * ij * jk2) / 2. +
- (CF * Lij * ij * jk2) +
- (CA * Lik * ij * jk2) / 2. -
- (CA * Ljk * ij * jk2) +
- (4 * CF * Ljk * ij * jk2) +
- (4 * CA * Box6ijk * ij3 * jk2) / ik2 -
- (8 * CF * Box6ijk * ij3 * jk2) / ik2 +
- (8 * CA * Box6ijk * ij2 * jk2) / ik -
- (16 * CF * Box6ijk * ij2 * jk2) / ik -
- (CA * Lij * ij2 * jk2) / (2. * ik) +
- (CF * Lij * ij2 * jk2) / ik -
- (CA * Ljk * ij2 * jk2) / (2. * ik) +
- (CF * Ljk * ij2 * jk2) / ik +
- (CA * ik * jk2) -
- (9 * CF * ik * jk2) +
- (8 * CA * Box6ijk * ik * jk2) -
- (16 * CF * Box6ijk * ik * jk2) -
- (32 * CA * Box6ikj * ik * jk2) +
- (CA * Lik * ik * jk2) / 2. -
- (CA * Ljk * ik * jk2) / 2. +
- (3 * CF * Ljk * ik * jk2) -
- (12 * CA * Box6ikj * ik2 * jk2) / ij -
- (12 * CA * Box6ikj * jk3) -
- (CA * Ljk * jk3) / 2. +
- (3 * CF * Ljk * jk3) +
- (4 * CA * Box6ijk * ij2 * jk3) / ik2 -
- (8 * CF * Box6ijk * ij2 * jk3) / ik2 +
- (4 * CA * Box6ijk * ij * jk3) / ik -
- (8 * CF * Box6ijk * ij * jk3) / ik -
- (CA * Ljk * ij * jk3) / (2. * ik) +
- (CF * Ljk * ij * jk3) / ik -
- (12 * CA * Box6ikj * ik * jk3) / ij
- ) / (ij_ik * ij_jk * ik_jk);
+ (-4 * CA * Box6jik * ij3) +
+ (8 * CF * Box6jik * ij3) +
+ (CA * Lij * ij3) / 2. -
+ (CF * Lij * ij3) +
+ (CA * ij2 * ik) -
+ (9 * CF * ij2 * ik) +
+ (8 * CA * Box6ijk * ij2 * ik) -
+ (16 * CF * Box6ijk * ij2 * ik) -
+ (8 * CA * Box6ikj * ij2 * ik) -
+ (8 * CA * Box6jik * ij2 * ik) +
+ (16 * CF * Box6jik * ij2 * ik) +
+ (CA * Lij * ij2 * ik) / 2. -
+ (CF * Lij * ij2 * ik) +
+ (CA * Lik * ij2 * ik) / 2. -
+ (CF * Lik * ij2 * ik) +
+ (CA * ij * ik2) -
+ (9 * CF * ij * ik2) +
+ (8 * CA * Box6ijk * ij * ik2) -
+ (16 * CF * Box6ijk * ij * ik2) -
+ (8 * CA * Box6ikj * ij * ik2) -
+ (4 * CA * Box6jik * ij * ik2) +
+ (8 * CF * Box6jik * ij * ik2) +
+ (CA * Lik * ij * ik2) / 2. -
+ (CF * Lik * ij * ik2) -
+ (4 * CA * Box6jik * ij3 * ik) / jk +
+ (8 * CF * Box6jik * ij3 * ik) / jk -
+ (4 * CA * Box6jik * ij2 * ik2) / jk +
+ (8 * CF * Box6jik * ij2 * ik2) / jk +
+ (CA * ij2 * jk) -
+ (9 * CF * ij2 * jk) +
+ (12 * CA * Box6ijk * ij2 * jk) -
+ (24 * CF * Box6ijk * ij2 * jk) -
+ (8 * CA * Box6ikj * ij2 * jk) -
+ (4 * CA * Box6jik * ij2 * jk) +
+ (8 * CF * Box6jik * ij2 * jk) +
+ (CA * Lik * ij2 * jk) / 2. -
+ (CF * Lik * ij2 * jk) -
+ (CA * Ljk * ij2 * jk) / 2. +
+ (CF * Ljk * ij2 * jk) +
+ (4 * CA * Box6ijk * ij3 * jk) / ik -
+ (8 * CF * Box6ijk * ij3 * jk) / ik -
+ (CA * Lij * ij3 * jk) / (2. * ik) +
+ (CF * Lij * ij3 * jk) / ik +
+ (2 * CA * ij * ik * jk) -
+ (18 * CF * ij * ik * jk) +
+ (16 * CA * Box6ijk * ij * ik * jk) -
+ (32 * CF * Box6ijk * ij * ik * jk) -
+ (28 * CA * Box6ikj * ij * ik * jk) -
+ (4 * CA * Box6jik * ij * ik * jk) +
+ (8 * CF * Box6jik * ij * ik * jk) +
+ (CA * Lij * ij * ik * jk) / 2. -
+ (CF * Lij * ij * ik * jk) +
+ (CA * Lik * ij * ik * jk) -
+ (CF * Lik * ij * ik * jk) -
+ (CA * Ljk * ij * ik * jk) / 2. +
+ (3 * CF * Ljk * ij * ik * jk) +
+ (CA * ik2 * jk) -
+ (9 * CF * ik2 * jk) +
+ (8 * CA * Box6ijk * ik2 * jk) -
+ (16 * CF * Box6ijk * ik2 * jk) -
+ (20 * CA * Box6ikj * ik2 * jk) +
+ (CA * Lik * ik2 * jk) / 2. +
+ (CA * ij * jk2) -
+ (9 * CF * ij * jk2) +
+ (12 * CA * Box6ijk * ij * jk2) -
+ (24 * CF * Box6ijk * ij * jk2) -
+ (20 * CA * Box6ikj * ij * jk2) -
+ (CA * Lij * ij * jk2) / 2. +
+ (CF * Lij * ij * jk2) +
+ (CA * Lik * ij * jk2) / 2. -
+ (CA * Ljk * ij * jk2) +
+ (4 * CF * Ljk * ij * jk2) +
+ (4 * CA * Box6ijk * ij3 * jk2) / ik2 -
+ (8 * CF * Box6ijk * ij3 * jk2) / ik2 +
+ (8 * CA * Box6ijk * ij2 * jk2) / ik -
+ (16 * CF * Box6ijk * ij2 * jk2) / ik -
+ (CA * Lij * ij2 * jk2) / (2. * ik) +
+ (CF * Lij * ij2 * jk2) / ik -
+ (CA * Ljk * ij2 * jk2) / (2. * ik) +
+ (CF * Ljk * ij2 * jk2) / ik +
+ (CA * ik * jk2) -
+ (9 * CF * ik * jk2) +
+ (8 * CA * Box6ijk * ik * jk2) -
+ (16 * CF * Box6ijk * ik * jk2) -
+ (32 * CA * Box6ikj * ik * jk2) +
+ (CA * Lik * ik * jk2) / 2. -
+ (CA * Ljk * ik * jk2) / 2. +
+ (3 * CF * Ljk * ik * jk2) -
+ (12 * CA * Box6ikj * ik2 * jk2) / ij -
+ (12 * CA * Box6ikj * jk3) -
+ (CA * Ljk * jk3) / 2. +
+ (3 * CF * Ljk * jk3) +
+ (4 * CA * Box6ijk * ij2 * jk3) / ik2 -
+ (8 * CF * Box6ijk * ij2 * jk3) / ik2 +
+ (4 * CA * Box6ijk * ij * jk3) / ik -
+ (8 * CF * Box6ijk * ij * jk3) / ik -
+ (CA * Ljk * ij * jk3) / (2. * ik) +
+ (CF * Ljk * ij * jk3) / ik -
+ (12 * CA * Box6ikj * ik * jk3) / ij
+ ) / (ij_ik * ij_jk * ik_jk);
qqbargLoops[3] = 3 * CF * Lijk + (
- (8 * CF * ij2) -
- (8 * CA * Box6ijk * ij2) +
- (16 * CF * Box6ijk * ij2) +
- (8 * CA * Box6ikj * ij2) -
- (8 * CA * Box6jik * ij2) +
- (16 * CF * Box6jik * ij2) +
- (CA * Lij * ij2) / 2. -
- (CF * Lij * ij2) +
- (8 * CF * ij * ik) -
- (8 * CA * Box6ijk * ij * ik) +
- (16 * CF * Box6ijk * ij * ik) +
- (8 * CA * Box6ikj * ij * ik) -
- (12 * CA * Box6jik * ij * ik) +
- (24 * CF * Box6jik * ij * ik) +
- (CA * Lij * ij * ik) / 2. -
- (CF * Lij * ij * ik) +
- (CA * Lik * ij * ik) / 2. -
- (CF * Lik * ij * ik) -
- (4 * CA * Box6jik * ik2) +
- (8 * CF * Box6jik * ik2) +
- (CA * Lik * ik2) / 2. -
- (CF * Lik * ik2) -
- (4 * CA * Box6jik * ij2 * ik) / jk +
- (8 * CF * Box6jik * ij2 * ik) / jk -
- (4 * CA * Box6jik * ij * ik2) / jk +
- (8 * CF * Box6jik * ij * ik2) / jk +
- (8 * CF * ij * jk) -
- (12 * CA * Box6ijk * ij * jk) +
- (24 * CF * Box6ijk * ij * jk) +
- (8 * CA * Box6ikj * ij * jk) -
- (8 * CA * Box6jik * ij * jk) +
- (16 * CF * Box6jik * ij * jk) +
- (CA * Lij * ij * jk) / 2. -
- (CF * Lij * ij * jk) +
- (CA * Ljk * ij * jk) / 2. -
- (CF * Ljk * ij * jk) -
- (4 * CA * Box6ijk * ij2 * jk) / ik +
- (8 * CF * Box6ijk * ij2 * jk) / ik +
- (8 * CF * ik * jk) -
- (8 * CA * Box6ijk * ik * jk) +
- (16 * CF * Box6ijk * ik * jk) -
- (4 * CA * Box6ikj * ik * jk) -
- (8 * CA * Box6jik * ik * jk) +
- (16 * CF * Box6jik * ik * jk) +
- (CA * Lij * ik * jk) / 2. -
- (CF * Lij * ik * jk) +
- (CA * Lik * ik * jk) / 2. +
- (2 * CF * Lik * ik * jk) +
- (CA * Ljk * ik * jk) / 2. +
- (2 * CF * Ljk * ik * jk) -
- (12 * CA * Box6ikj * ik2 * jk) / ij +
- (CA * Lik * ik2 * jk) / (2. * ij) +
- (2 * CF * Lik * ik2 * jk) / ij -
- (4 * CA * Box6ijk * jk2) +
- (8 * CF * Box6ijk * jk2) +
- (CA * Ljk * jk2) / 2. -
- (CF * Ljk * jk2) -
- (4 * CA * Box6ijk * ij * jk2) / ik +
- (8 * CF * Box6ijk * ij * jk2) / ik -
- (12 * CA * Box6ikj * ik * jk2) / ij +
- (CA * Ljk * ik * jk2) / (2. * ij) +
- (2 * CF * Ljk * ik * jk2) / ij -
- (12 * CA * Box6ikj * ik2 * jk2) / ij2
- ) / (ij_ik * ij_jk);
+ (8 * CF * ij2) -
+ (8 * CA * Box6ijk * ij2) +
+ (16 * CF * Box6ijk * ij2) +
+ (8 * CA * Box6ikj * ij2) -
+ (8 * CA * Box6jik * ij2) +
+ (16 * CF * Box6jik * ij2) +
+ (CA * Lij * ij2) / 2. -
+ (CF * Lij * ij2) +
+ (8 * CF * ij * ik) -
+ (8 * CA * Box6ijk * ij * ik) +
+ (16 * CF * Box6ijk * ij * ik) +
+ (8 * CA * Box6ikj * ij * ik) -
+ (12 * CA * Box6jik * ij * ik) +
+ (24 * CF * Box6jik * ij * ik) +
+ (CA * Lij * ij * ik) / 2. -
+ (CF * Lij * ij * ik) +
+ (CA * Lik * ij * ik) / 2. -
+ (CF * Lik * ij * ik) -
+ (4 * CA * Box6jik * ik2) +
+ (8 * CF * Box6jik * ik2) +
+ (CA * Lik * ik2) / 2. -
+ (CF * Lik * ik2) -
+ (4 * CA * Box6jik * ij2 * ik) / jk +
+ (8 * CF * Box6jik * ij2 * ik) / jk -
+ (4 * CA * Box6jik * ij * ik2) / jk +
+ (8 * CF * Box6jik * ij * ik2) / jk +
+ (8 * CF * ij * jk) -
+ (12 * CA * Box6ijk * ij * jk) +
+ (24 * CF * Box6ijk * ij * jk) +
+ (8 * CA * Box6ikj * ij * jk) -
+ (8 * CA * Box6jik * ij * jk) +
+ (16 * CF * Box6jik * ij * jk) +
+ (CA * Lij * ij * jk) / 2. -
+ (CF * Lij * ij * jk) +
+ (CA * Ljk * ij * jk) / 2. -
+ (CF * Ljk * ij * jk) -
+ (4 * CA * Box6ijk * ij2 * jk) / ik +
+ (8 * CF * Box6ijk * ij2 * jk) / ik +
+ (8 * CF * ik * jk) -
+ (8 * CA * Box6ijk * ik * jk) +
+ (16 * CF * Box6ijk * ik * jk) -
+ (4 * CA * Box6ikj * ik * jk) -
+ (8 * CA * Box6jik * ik * jk) +
+ (16 * CF * Box6jik * ik * jk) +
+ (CA * Lij * ik * jk) / 2. -
+ (CF * Lij * ik * jk) +
+ (CA * Lik * ik * jk) / 2. +
+ (2 * CF * Lik * ik * jk) +
+ (CA * Ljk * ik * jk) / 2. +
+ (2 * CF * Ljk * ik * jk) -
+ (12 * CA * Box6ikj * ik2 * jk) / ij +
+ (CA * Lik * ik2 * jk) / (2. * ij) +
+ (2 * CF * Lik * ik2 * jk) / ij -
+ (4 * CA * Box6ijk * jk2) +
+ (8 * CF * Box6ijk * jk2) +
+ (CA * Ljk * jk2) / 2. -
+ (CF * Ljk * jk2) -
+ (4 * CA * Box6ijk * ij * jk2) / ik +
+ (8 * CF * Box6ijk * ij * jk2) / ik -
+ (12 * CA * Box6ikj * ik * jk2) / ij +
+ (CA * Ljk * ik * jk2) / (2. * ij) +
+ (2 * CF * Ljk * ik * jk2) / ij -
+ (12 * CA * Box6ikj * ik2 * jk2) / ij2
+ ) / (ij_ik * ij_jk);
qqbargLoops[4] = -3 * CF * Lijk + (
- (-8 * CF * ij2) +
- (8 * CA * Box6ijk * ij2) -
- (16 * CF * Box6ijk * ij2) -
- (8 * CA * Box6ikj * ij2) +
- (8 * CA * Box6jik * ij2) -
- (16 * CF * Box6jik * ij2) -
- (CA * Lij * ij2) / 2. +
- (CF * Lij * ij2) -
- (8 * CF * ij * ik) +
- (8 * CA * Box6ijk * ij * ik) -
- (16 * CF * Box6ijk * ij * ik) -
- (8 * CA * Box6ikj * ij * ik) +
- (12 * CA * Box6jik * ij * ik) -
- (24 * CF * Box6jik * ij * ik) -
- (CA * Lij * ij * ik) / 2. +
- (CF * Lij * ij * ik) -
- (CA * Lik * ij * ik) / 2. +
- (CF * Lik * ij * ik) +
- (4 * CA * Box6jik * ik2) -
- (8 * CF * Box6jik * ik2) -
- (CA * Lik * ik2) / 2. +
- (CF * Lik * ik2) +
- (4 * CA * Box6jik * ij2 * ik) / jk -
- (8 * CF * Box6jik * ij2 * ik) / jk +
- (4 * CA * Box6jik * ij * ik2) / jk -
- (8 * CF * Box6jik * ij * ik2) / jk -
- (8 * CF * ij * jk) +
- (12 * CA * Box6ijk * ij * jk) -
- (24 * CF * Box6ijk * ij * jk) -
- (8 * CA * Box6ikj * ij * jk) +
- (8 * CA * Box6jik * ij * jk) -
- (16 * CF * Box6jik * ij * jk) -
- (CA * Lij * ij * jk) / 2. +
- (CF * Lij * ij * jk) -
- (CA * Ljk * ij * jk) / 2. +
- (CF * Ljk * ij * jk) +
- (4 * CA * Box6ijk * ij2 * jk) / ik -
- (8 * CF * Box6ijk * ij2 * jk) / ik -
- (8 * CF * ik * jk) +
- (8 * CA * Box6ijk * ik * jk) -
- (16 * CF * Box6ijk * ik * jk) +
- (4 * CA * Box6ikj * ik * jk) +
- (8 * CA * Box6jik * ik * jk) -
- (16 * CF * Box6jik * ik * jk) -
- (CA * Lij * ik * jk) / 2. +
- (CF * Lij * ik * jk) -
- (CA * Lik * ik * jk) / 2. -
- (2 * CF * Lik * ik * jk) -
- (CA * Ljk * ik * jk) / 2. -
- (2 * CF * Ljk * ik * jk) +
- (12 * CA * Box6ikj * ik2 * jk) / ij -
- (CA * Lik * ik2 * jk) / (2. * ij) -
- (2 * CF * Lik * ik2 * jk) / ij +
- (4 * CA * Box6ijk * jk2) -
- (8 * CF * Box6ijk * jk2) -
- (CA * Ljk * jk2) / 2. +
- (CF * Ljk * jk2) +
- (4 * CA * Box6ijk * ij * jk2) / ik -
- (8 * CF * Box6ijk * ij * jk2) / ik +
- (12 * CA * Box6ikj * ik * jk2) / ij -
- (CA * Ljk * ik * jk2) / (2. * ij) -
- (2 * CF * Ljk * ik * jk2) / ij +
- (12 * CA * Box6ikj * ik2 * jk2) / ij2
- ) / (ij_ik * ij_jk);
+ (-8 * CF * ij2) +
+ (8 * CA * Box6ijk * ij2) -
+ (16 * CF * Box6ijk * ij2) -
+ (8 * CA * Box6ikj * ij2) +
+ (8 * CA * Box6jik * ij2) -
+ (16 * CF * Box6jik * ij2) -
+ (CA * Lij * ij2) / 2. +
+ (CF * Lij * ij2) -
+ (8 * CF * ij * ik) +
+ (8 * CA * Box6ijk * ij * ik) -
+ (16 * CF * Box6ijk * ij * ik) -
+ (8 * CA * Box6ikj * ij * ik) +
+ (12 * CA * Box6jik * ij * ik) -
+ (24 * CF * Box6jik * ij * ik) -
+ (CA * Lij * ij * ik) / 2. +
+ (CF * Lij * ij * ik) -
+ (CA * Lik * ij * ik) / 2. +
+ (CF * Lik * ij * ik) +
+ (4 * CA * Box6jik * ik2) -
+ (8 * CF * Box6jik * ik2) -
+ (CA * Lik * ik2) / 2. +
+ (CF * Lik * ik2) +
+ (4 * CA * Box6jik * ij2 * ik) / jk -
+ (8 * CF * Box6jik * ij2 * ik) / jk +
+ (4 * CA * Box6jik * ij * ik2) / jk -
+ (8 * CF * Box6jik * ij * ik2) / jk -
+ (8 * CF * ij * jk) +
+ (12 * CA * Box6ijk * ij * jk) -
+ (24 * CF * Box6ijk * ij * jk) -
+ (8 * CA * Box6ikj * ij * jk) +
+ (8 * CA * Box6jik * ij * jk) -
+ (16 * CF * Box6jik * ij * jk) -
+ (CA * Lij * ij * jk) / 2. +
+ (CF * Lij * ij * jk) -
+ (CA * Ljk * ij * jk) / 2. +
+ (CF * Ljk * ij * jk) +
+ (4 * CA * Box6ijk * ij2 * jk) / ik -
+ (8 * CF * Box6ijk * ij2 * jk) / ik -
+ (8 * CF * ik * jk) +
+ (8 * CA * Box6ijk * ik * jk) -
+ (16 * CF * Box6ijk * ik * jk) +
+ (4 * CA * Box6ikj * ik * jk) +
+ (8 * CA * Box6jik * ik * jk) -
+ (16 * CF * Box6jik * ik * jk) -
+ (CA * Lij * ik * jk) / 2. +
+ (CF * Lij * ik * jk) -
+ (CA * Lik * ik * jk) / 2. -
+ (2 * CF * Lik * ik * jk) -
+ (CA * Ljk * ik * jk) / 2. -
+ (2 * CF * Ljk * ik * jk) +
+ (12 * CA * Box6ikj * ik2 * jk) / ij -
+ (CA * Lik * ik2 * jk) / (2. * ij) -
+ (2 * CF * Lik * ik2 * jk) / ij +
+ (4 * CA * Box6ijk * jk2) -
+ (8 * CF * Box6ijk * jk2) -
+ (CA * Ljk * jk2) / 2. +
+ (CF * Ljk * jk2) +
+ (4 * CA * Box6ijk * ij * jk2) / ik -
+ (8 * CF * Box6ijk * ij * jk2) / ik +
+ (12 * CA * Box6ikj * ik * jk2) / ij -
+ (CA * Ljk * ik * jk2) / (2. * ij) -
+ (2 * CF * Ljk * ik * jk2) / ij +
+ (12 * CA * Box6ikj * ik2 * jk2) / ij2
+ ) / (ij_ik * ij_jk);
qqbargLoops[5] = 3 * CF * Lijk + (
- (-4 * CA * Box6jik * ij2) +
- (8 * CF * Box6jik * ij2) +
- (CA * Lij * ij2) / 2. -
- (CF * Lij * ij2) -
- (CA * ij * ik) +
- (9 * CF * ij * ik) -
- (8 * CA * Box6ijk * ij * ik) +
- (16 * CF * Box6ijk * ij * ik) +
- (8 * CA * Box6ikj * ij * ik) -
- (4 * CA * Box6jik * ij * ik) +
- (8 * CF * Box6jik * ij * ik) +
- (CA * Lij * ij * ik) / 2. -
- (CF * Lij * ij * ik) +
- (CA * Lik * ij * ik) / 2. -
- (CF * Lik * ij * ik) -
- (CA * ik2) +
- (9 * CF * ik2) -
- (8 * CA * Box6ijk * ik2) +
- (16 * CF * Box6ijk * ik2) +
- (8 * CA * Box6ikj * ik2) +
- (CA * Lik * ik2) / 2. -
- (CF * Lik * ik2) -
- (4 * CA * Box6jik * ij2 * ik) / jk +
- (8 * CF * Box6jik * ij2 * ik) / jk -
- (4 * CA * Box6jik * ij * ik2) / jk +
- (8 * CF * Box6jik * ij * ik2) / jk -
- (CA * ij * jk) +
- (9 * CF * ij * jk) -
- (4 * CA * Box6ijk * ij * jk) +
- (8 * CF * Box6ijk * ij * jk) +
- (8 * CA * Box6ikj * ij * jk) -
- (CA * Lij * ij * jk) / 2. +
- (CF * Lij * ij * jk) +
- (CA * Lik * ij * jk) / 2. -
- (CF * Lik * ij * jk) -
- (CA * Ljk * ij * jk) / 2. +
- (CF * Ljk * ij * jk) +
- (4 * CA * Box6ijk * ij2 * jk) / ik -
- (8 * CF * Box6ijk * ij2 * jk) / ik -
- (CA * Lij * ij2 * jk) / (2. * ik) +
- (CF * Lij * ij2 * jk) / ik -
- (CA * ik * jk) +
- (9 * CF * ik * jk) -
- (8 * CA * Box6ijk * ik * jk) +
- (16 * CF * Box6ijk * ik * jk) +
- (20 * CA * Box6ikj * ik * jk) +
- (CA * Lik * ik * jk) / 2. -
- (CF * Lik * ik * jk) -
- (CA * Ljk * ik * jk) / 2. -
- (2 * CF * Ljk * ik * jk) +
- (12 * CA * Box6ikj * ik2 * jk) / ij +
- (12 * CA * Box6ikj * jk2) -
- (CA * Ljk * jk2) / 2. -
- (2 * CF * Ljk * jk2) +
- (4 * CA * Box6ijk * ij2 * jk2) / ik2 -
- (8 * CF * Box6ijk * ij2 * jk2) / ik2 +
- (4 * CA * Box6ijk * ij * jk2) / ik -
- (8 * CF * Box6ijk * ij * jk2) / ik -
- (CA * Ljk * ij * jk2) / (2. * ik) +
- (CF * Ljk * ij * jk2) / ik +
- (12 * CA * Box6ikj * ik * jk2) / ij
- ) / (ij_ik * ik_jk);
+ (-4 * CA * Box6jik * ij2) +
+ (8 * CF * Box6jik * ij2) +
+ (CA * Lij * ij2) / 2. -
+ (CF * Lij * ij2) -
+ (CA * ij * ik) +
+ (9 * CF * ij * ik) -
+ (8 * CA * Box6ijk * ij * ik) +
+ (16 * CF * Box6ijk * ij * ik) +
+ (8 * CA * Box6ikj * ij * ik) -
+ (4 * CA * Box6jik * ij * ik) +
+ (8 * CF * Box6jik * ij * ik) +
+ (CA * Lij * ij * ik) / 2. -
+ (CF * Lij * ij * ik) +
+ (CA * Lik * ij * ik) / 2. -
+ (CF * Lik * ij * ik) -
+ (CA * ik2) +
+ (9 * CF * ik2) -
+ (8 * CA * Box6ijk * ik2) +
+ (16 * CF * Box6ijk * ik2) +
+ (8 * CA * Box6ikj * ik2) +
+ (CA * Lik * ik2) / 2. -
+ (CF * Lik * ik2) -
+ (4 * CA * Box6jik * ij2 * ik) / jk +
+ (8 * CF * Box6jik * ij2 * ik) / jk -
+ (4 * CA * Box6jik * ij * ik2) / jk +
+ (8 * CF * Box6jik * ij * ik2) / jk -
+ (CA * ij * jk) +
+ (9 * CF * ij * jk) -
+ (4 * CA * Box6ijk * ij * jk) +
+ (8 * CF * Box6ijk * ij * jk) +
+ (8 * CA * Box6ikj * ij * jk) -
+ (CA * Lij * ij * jk) / 2. +
+ (CF * Lij * ij * jk) +
+ (CA * Lik * ij * jk) / 2. -
+ (CF * Lik * ij * jk) -
+ (CA * Ljk * ij * jk) / 2. +
+ (CF * Ljk * ij * jk) +
+ (4 * CA * Box6ijk * ij2 * jk) / ik -
+ (8 * CF * Box6ijk * ij2 * jk) / ik -
+ (CA * Lij * ij2 * jk) / (2. * ik) +
+ (CF * Lij * ij2 * jk) / ik -
+ (CA * ik * jk) +
+ (9 * CF * ik * jk) -
+ (8 * CA * Box6ijk * ik * jk) +
+ (16 * CF * Box6ijk * ik * jk) +
+ (20 * CA * Box6ikj * ik * jk) +
+ (CA * Lik * ik * jk) / 2. -
+ (CF * Lik * ik * jk) -
+ (CA * Ljk * ik * jk) / 2. -
+ (2 * CF * Ljk * ik * jk) +
+ (12 * CA * Box6ikj * ik2 * jk) / ij +
+ (12 * CA * Box6ikj * jk2) -
+ (CA * Ljk * jk2) / 2. -
+ (2 * CF * Ljk * jk2) +
+ (4 * CA * Box6ijk * ij2 * jk2) / ik2 -
+ (8 * CF * Box6ijk * ij2 * jk2) / ik2 +
+ (4 * CA * Box6ijk * ij * jk2) / ik -
+ (8 * CF * Box6ijk * ij * jk2) / ik -
+ (CA * Ljk * ij * jk2) / (2. * ik) +
+ (CF * Ljk * ij * jk2) / ik +
+ (12 * CA * Box6ikj * ik * jk2) / ij
+ ) / (ij_ik * ik_jk);
qqbargLoops[6] = (
- (-2 * CF * ij) +
- (32 * CA * Box6ijk * ij) -
- (64 * CF * Box6ijk * ij) -
- (4 * CA * Lij * ij) +
- (8 * CF * Lij * ij) +
- (4 * CF * Ljk * ij) +
- (16 * CA * Box6ijk * ij2) / ik -
- (32 * CF * Box6ijk * ij2) / ik -
- (2 * CA * Lij * ij2) / ik +
- (4 * CF * Lij * ij2) / ik -
- (2 * CF * ik) +
- (16 * CA * Box6ijk * ik) -
- (32 * CF * Box6ijk * ik) -
- (2 * CA * Lij * ik) +
- (4 * CF * Lij * ik) +
- (4 * CF * Ljk * ik) +
- (16 * CA * Box6ijk * jk) -
- (32 * CF * Box6ijk * jk) -
- (2 * CA * Ljk * jk) +
- (6 * CF * Ljk * jk) +
- (16 * CA * Box6ijk * ij2 * jk) / ik2 -
- (32 * CF * Box6ijk * ij2 * jk) / ik2 +
- (32 * CA * Box6ijk * ij * jk) / ik -
- (64 * CF * Box6ijk * ij * jk) / ik -
- (2 * CA * Ljk * ij * jk) / ik +
- (4 * CF * Ljk * ij * jk) / ik
- ) / ij_ik_2;
+ (-2 * CF * ij) +
+ (32 * CA * Box6ijk * ij) -
+ (64 * CF * Box6ijk * ij) -
+ (4 * CA * Lij * ij) +
+ (8 * CF * Lij * ij) +
+ (4 * CF * Ljk * ij) +
+ (16 * CA * Box6ijk * ij2) / ik -
+ (32 * CF * Box6ijk * ij2) / ik -
+ (2 * CA * Lij * ij2) / ik +
+ (4 * CF * Lij * ij2) / ik -
+ (2 * CF * ik) +
+ (16 * CA * Box6ijk * ik) -
+ (32 * CF * Box6ijk * ik) -
+ (2 * CA * Lij * ik) +
+ (4 * CF * Lij * ik) +
+ (4 * CF * Ljk * ik) +
+ (16 * CA * Box6ijk * jk) -
+ (32 * CF * Box6ijk * jk) -
+ (2 * CA * Ljk * jk) +
+ (6 * CF * Ljk * jk) +
+ (16 * CA * Box6ijk * ij2 * jk) / ik2 -
+ (32 * CF * Box6ijk * ij2 * jk) / ik2 +
+ (32 * CA * Box6ijk * ij * jk) / ik -
+ (64 * CF * Box6ijk * ij * jk) / ik -
+ (2 * CA * Ljk * ij * jk) / ik +
+ (4 * CF * Ljk * ij * jk) / ik
+ ) / ij_ik_2;
qqbargLoops[7] = (
- (8 * CA * Box6jik * ij) -
- (16 * CF * Box6jik * ij) +
- (CA * Lij * ij) -
- (2 * CF * Lij * ij) +
- (CA * Lik * ij) +
- (2 * CF * Lik * ij) +
- (CA * Lij * ij2) / ik -
- (2 * CF * Lij * ij2) / ik +
- (8 * CA * Box6jik * ik) -
- (16 * CF * Box6jik * ik) +
- (CA * Lik * ik) +
- (2 * CF * Lik * ik) +
- (8 * CA * Box6jik * ij2) / jk -
- (16 * CF * Box6jik * ij2) / jk +
- (8 * CA * Box6jik * ij * ik) / jk -
- (16 * CF * Box6jik * ij * ik) / jk -
- (24 * CA * Box6ikj * jk) +
- (CA * Lij * jk) -
- (2 * CF * Lij * jk) +
- (CA * Lik * jk) +
- (4 * CF * Lik * jk) +
- (CA * Ljk * jk) +
- (4 * CF * Ljk * jk) -
- (8 * CA * Box6ijk * ij2 * jk) / ik2 +
- (16 * CF * Box6ijk * ij2 * jk) / ik2 -
- (8 * CA * Box6ijk * ij * jk) / ik +
- (16 * CF * Box6ijk * ij * jk) / ik +
- (CA * Lij * ij * jk) / ik -
- (2 * CF * Lij * ij * jk) / ik +
- (CA * Ljk * ij * jk) / ik -
- (2 * CF * Ljk * ij * jk) / ik -
- (24 * CA * Box6ikj * ik * jk) / ij +
- (CA * Lik * ik * jk) / ij +
- (4 * CF * Lik * ik * jk) / ij -
- (24 * CA * Box6ikj * jk2) / ij +
- (CA * Ljk * jk2) / ij +
- (4 * CF * Ljk * jk2) / ij -
- (8 * CA * Box6ijk * ij * jk2) / ik2 +
- (16 * CF * Box6ijk * ij * jk2) / ik2 -
- (8 * CA * Box6ijk * jk2) / ik +
- (16 * CF * Box6ijk * jk2) / ik +
- (CA * Ljk * jk2) / ik -
- (2 * CF * Ljk * jk2) / ik -
- (24 * CA * Box6ikj * ik * jk2) / ij2
- ) / (ij_ik * ij_jk);
+ (8 * CA * Box6jik * ij) -
+ (16 * CF * Box6jik * ij) +
+ (CA * Lij * ij) -
+ (2 * CF * Lij * ij) +
+ (CA * Lik * ij) +
+ (2 * CF * Lik * ij) +
+ (CA * Lij * ij2) / ik -
+ (2 * CF * Lij * ij2) / ik +
+ (8 * CA * Box6jik * ik) -
+ (16 * CF * Box6jik * ik) +
+ (CA * Lik * ik) +
+ (2 * CF * Lik * ik) +
+ (8 * CA * Box6jik * ij2) / jk -
+ (16 * CF * Box6jik * ij2) / jk +
+ (8 * CA * Box6jik * ij * ik) / jk -
+ (16 * CF * Box6jik * ij * ik) / jk -
+ (24 * CA * Box6ikj * jk) +
+ (CA * Lij * jk) -
+ (2 * CF * Lij * jk) +
+ (CA * Lik * jk) +
+ (4 * CF * Lik * jk) +
+ (CA * Ljk * jk) +
+ (4 * CF * Ljk * jk) -
+ (8 * CA * Box6ijk * ij2 * jk) / ik2 +
+ (16 * CF * Box6ijk * ij2 * jk) / ik2 -
+ (8 * CA * Box6ijk * ij * jk) / ik +
+ (16 * CF * Box6ijk * ij * jk) / ik +
+ (CA * Lij * ij * jk) / ik -
+ (2 * CF * Lij * ij * jk) / ik +
+ (CA * Ljk * ij * jk) / ik -
+ (2 * CF * Ljk * ij * jk) / ik -
+ (24 * CA * Box6ikj * ik * jk) / ij +
+ (CA * Lik * ik * jk) / ij +
+ (4 * CF * Lik * ik * jk) / ij -
+ (24 * CA * Box6ikj * jk2) / ij +
+ (CA * Ljk * jk2) / ij +
+ (4 * CF * Ljk * jk2) / ij -
+ (8 * CA * Box6ijk * ij * jk2) / ik2 +
+ (16 * CF * Box6ijk * ij * jk2) / ik2 -
+ (8 * CA * Box6ijk * jk2) / ik +
+ (16 * CF * Box6ijk * jk2) / ik +
+ (CA * Ljk * jk2) / ik -
+ (2 * CF * Ljk * jk2) / ik -
+ (24 * CA * Box6ikj * ik * jk2) / ij2
+ ) / (ij_ik * ij_jk);
qqbargLoops[8] = (
- (-8 * CA * Box6ijk * ij) +
- (16 * CF * Box6ijk * ij) -
- (CA * Lij * ij) +
- (2 * CF * Lij * ij) -
- (CA * Ljk * ij) -
- (2 * CF * Ljk * ij) -
- (8 * CA * Box6ijk * ij2) / ik +
- (16 * CF * Box6ijk * ij2) / ik +
- (24 * CA * Box6ikj * ik) -
- (CA * Lij * ik) +
- (2 * CF * Lij * ik) -
- (CA * Lik * ik) -
- (4 * CF * Lik * ik) -
- (CA * Ljk * ik) -
- (4 * CF * Ljk * ik) +
- (24 * CA * Box6ikj * ik2) / ij -
- (CA * Lik * ik2) / ij -
- (4 * CF * Lik * ik2) / ij +
- (8 * CA * Box6jik * ij2 * ik) / jk2 -
- (16 * CF * Box6jik * ij2 * ik) / jk2 +
- (8 * CA * Box6jik * ij * ik2) / jk2 -
- (16 * CF * Box6jik * ij * ik2) / jk2 -
- (CA * Lij * ij2) / jk +
- (2 * CF * Lij * ij2) / jk +
- (8 * CA * Box6jik * ij * ik) / jk -
- (16 * CF * Box6jik * ij * ik) / jk -
- (CA * Lij * ij * ik) / jk +
- (2 * CF * Lij * ij * ik) / jk -
- (CA * Lik * ij * ik) / jk +
- (2 * CF * Lik * ij * ik) / jk +
- (8 * CA * Box6jik * ik2) / jk -
- (16 * CF * Box6jik * ik2) / jk -
- (CA * Lik * ik2) / jk +
- (2 * CF * Lik * ik2) / jk -
- (8 * CA * Box6ijk * jk) +
- (16 * CF * Box6ijk * jk) -
- (CA * Ljk * jk) -
- (2 * CF * Ljk * jk) -
- (8 * CA * Box6ijk * ij * jk) / ik +
- (16 * CF * Box6ijk * ij * jk) / ik +
- (24 * CA * Box6ikj * ik * jk) / ij -
- (CA * Ljk * ik * jk) / ij -
- (4 * CF * Ljk * ik * jk) / ij +
- (24 * CA * Box6ikj * ik2 * jk) / ij2
- ) / (ij_ik * ij_jk);
+ (-8 * CA * Box6ijk * ij) +
+ (16 * CF * Box6ijk * ij) -
+ (CA * Lij * ij) +
+ (2 * CF * Lij * ij) -
+ (CA * Ljk * ij) -
+ (2 * CF * Ljk * ij) -
+ (8 * CA * Box6ijk * ij2) / ik +
+ (16 * CF * Box6ijk * ij2) / ik +
+ (24 * CA * Box6ikj * ik) -
+ (CA * Lij * ik) +
+ (2 * CF * Lij * ik) -
+ (CA * Lik * ik) -
+ (4 * CF * Lik * ik) -
+ (CA * Ljk * ik) -
+ (4 * CF * Ljk * ik) +
+ (24 * CA * Box6ikj * ik2) / ij -
+ (CA * Lik * ik2) / ij -
+ (4 * CF * Lik * ik2) / ij +
+ (8 * CA * Box6jik * ij2 * ik) / jk2 -
+ (16 * CF * Box6jik * ij2 * ik) / jk2 +
+ (8 * CA * Box6jik * ij * ik2) / jk2 -
+ (16 * CF * Box6jik * ij * ik2) / jk2 -
+ (CA * Lij * ij2) / jk +
+ (2 * CF * Lij * ij2) / jk +
+ (8 * CA * Box6jik * ij * ik) / jk -
+ (16 * CF * Box6jik * ij * ik) / jk -
+ (CA * Lij * ij * ik) / jk +
+ (2 * CF * Lij * ij * ik) / jk -
+ (CA * Lik * ij * ik) / jk +
+ (2 * CF * Lik * ij * ik) / jk +
+ (8 * CA * Box6jik * ik2) / jk -
+ (16 * CF * Box6jik * ik2) / jk -
+ (CA * Lik * ik2) / jk +
+ (2 * CF * Lik * ik2) / jk -
+ (8 * CA * Box6ijk * jk) +
+ (16 * CF * Box6ijk * jk) -
+ (CA * Ljk * jk) -
+ (2 * CF * Ljk * jk) -
+ (8 * CA * Box6ijk * ij * jk) / ik +
+ (16 * CF * Box6ijk * ij * jk) / ik +
+ (24 * CA * Box6ikj * ik * jk) / ij -
+ (CA * Ljk * ik * jk) / ij -
+ (4 * CF * Ljk * ik * jk) / ij +
+ (24 * CA * Box6ikj * ik2 * jk) / ij2
+ ) / (ij_ik * ij_jk);
qqbargLoops[9] = (
- (2 * CF * ij) -
- (32 * CA * Box6jik * ij) +
- (64 * CF * Box6jik * ij) +
- (4 * CA * Lij * ij) -
- (8 * CF * Lij * ij) -
- (4 * CF * Lik * ij) -
- (16 * CA * Box6jik * ik) +
- (32 * CF * Box6jik * ik) +
- (2 * CA * Lik * ik) -
- (6 * CF * Lik * ik) -
- (16 * CA * Box6jik * ij2 * ik) / jk2 +
- (32 * CF * Box6jik * ij2 * ik) / jk2 -
- (16 * CA * Box6jik * ij2) / jk +
- (32 * CF * Box6jik * ij2) / jk +
- (2 * CA * Lij * ij2) / jk -
- (4 * CF * Lij * ij2) / jk -
- (32 * CA * Box6jik * ij * ik) / jk +
- (64 * CF * Box6jik * ij * ik) / jk +
- (2 * CA * Lik * ij * ik) / jk -
- (4 * CF * Lik * ij * ik) / jk +
- (2 * CF * jk) -
- (16 * CA * Box6jik * jk) +
- (32 * CF * Box6jik * jk) +
- (2 * CA * Lij * jk) -
- (4 * CF * Lij * jk) -
- (4 * CF * Lik * jk)
- ) / ij_jk_2;
+ (2 * CF * ij) -
+ (32 * CA * Box6jik * ij) +
+ (64 * CF * Box6jik * ij) +
+ (4 * CA * Lij * ij) -
+ (8 * CF * Lij * ij) -
+ (4 * CF * Lik * ij) -
+ (16 * CA * Box6jik * ik) +
+ (32 * CF * Box6jik * ik) +
+ (2 * CA * Lik * ik) -
+ (6 * CF * Lik * ik) -
+ (16 * CA * Box6jik * ij2 * ik) / jk2 +
+ (32 * CF * Box6jik * ij2 * ik) / jk2 -
+ (16 * CA * Box6jik * ij2) / jk +
+ (32 * CF * Box6jik * ij2) / jk +
+ (2 * CA * Lij * ij2) / jk -
+ (4 * CF * Lij * ij2) / jk -
+ (32 * CA * Box6jik * ij * ik) / jk +
+ (64 * CF * Box6jik * ij * ik) / jk +
+ (2 * CA * Lik * ij * ik) / jk -
+ (4 * CF * Lik * ij * ik) / jk +
+ (2 * CF * jk) -
+ (16 * CA * Box6jik * jk) +
+ (32 * CF * Box6jik * jk) +
+ (2 * CA * Lij * jk) -
+ (4 * CF * Lij * jk) -
+ (4 * CF * Lik * jk)
+ ) / ij_jk_2;
qqbargLoops[10] = (
- (-8 * CA * Box6ijk * ij2 * jk) +
- (16 * CF * Box6ijk * ij2 * jk) +
- (2 * CA * Lij * ij2 * jk) -
- (4 * CF * Lij * ij2 * jk) -
- (CA * ij * ik * jk) +
- (2 * CF * ij * ik * jk) -
- (8 * CA * Box6ijk * ij * ik * jk) +
- (16 * CF * Box6ijk * ij * ik * jk) +
- (3 * CA * Lij * ij * ik * jk) -
- (6 * CF * Lij * ij * ik * jk) +
- (CA * Ljk * ij * ik * jk) -
- (2 * CF * Ljk * ij * ik * jk) -
- (CA * ik2 * jk) +
- (2 * CF * ik2 * jk) +
- (CA * Lij * ik2 * jk) -
- (2 * CF * Lij * ik2 * jk) +
- (CA * Ljk * ik2 * jk) -
- (CF * Ljk * ik2 * jk) -
- (CA * ij * jk2) +
- (2 * CF * ij * jk2) -
- (16 * CA * Box6ijk * ij * jk2) +
- (32 * CF * Box6ijk * ij * jk2) +
- (2 * CA * Lij * ij * jk2) -
- (4 * CF * Lij * ij * jk2) +
- (2 * CA * Ljk * ij * jk2) -
- (4 * CF * Ljk * ij * jk2) -
- (16 * CA * Box6ijk * ij2 * jk2) / ik +
- (32 * CF * Box6ijk * ij2 * jk2) / ik +
- (CA * Lij * ij2 * jk2) / ik -
- (2 * CF * Lij * ij2 * jk2) / ik -
- (CA * ik * jk2) +
- (2 * CF * ik * jk2) +
- (CA * Lij * ik * jk2) -
- (2 * CF * Lij * ik * jk2) +
- (2 * CA * Ljk * ik * jk2) -
- (2 * CF * Ljk * ik * jk2) +
- (CA * Ljk * jk3) -
- (CF * Ljk * jk3) -
- (8 * CA * Box6ijk * ij2 * jk3) / ik2 +
- (16 * CF * Box6ijk * ij2 * jk3) / ik2 -
- (8 * CA * Box6ijk * ij * jk3) / ik +
- (16 * CF * Box6ijk * ij * jk3) / ik +
- (CA * Ljk * ij * jk3) / ik -
- (2 * CF * Ljk * ij * jk3) / ik
- ) / (ij_ik * ik_jk_2);
+ (-8 * CA * Box6ijk * ij2 * jk) +
+ (16 * CF * Box6ijk * ij2 * jk) +
+ (2 * CA * Lij * ij2 * jk) -
+ (4 * CF * Lij * ij2 * jk) -
+ (CA * ij * ik * jk) +
+ (2 * CF * ij * ik * jk) -
+ (8 * CA * Box6ijk * ij * ik * jk) +
+ (16 * CF * Box6ijk * ij * ik * jk) +
+ (3 * CA * Lij * ij * ik * jk) -
+ (6 * CF * Lij * ij * ik * jk) +
+ (CA * Ljk * ij * ik * jk) -
+ (2 * CF * Ljk * ij * ik * jk) -
+ (CA * ik2 * jk) +
+ (2 * CF * ik2 * jk) +
+ (CA * Lij * ik2 * jk) -
+ (2 * CF * Lij * ik2 * jk) +
+ (CA * Ljk * ik2 * jk) -
+ (CF * Ljk * ik2 * jk) -
+ (CA * ij * jk2) +
+ (2 * CF * ij * jk2) -
+ (16 * CA * Box6ijk * ij * jk2) +
+ (32 * CF * Box6ijk * ij * jk2) +
+ (2 * CA * Lij * ij * jk2) -
+ (4 * CF * Lij * ij * jk2) +
+ (2 * CA * Ljk * ij * jk2) -
+ (4 * CF * Ljk * ij * jk2) -
+ (16 * CA * Box6ijk * ij2 * jk2) / ik +
+ (32 * CF * Box6ijk * ij2 * jk2) / ik +
+ (CA * Lij * ij2 * jk2) / ik -
+ (2 * CF * Lij * ij2 * jk2) / ik -
+ (CA * ik * jk2) +
+ (2 * CF * ik * jk2) +
+ (CA * Lij * ik * jk2) -
+ (2 * CF * Lij * ik * jk2) +
+ (2 * CA * Ljk * ik * jk2) -
+ (2 * CF * Ljk * ik * jk2) +
+ (CA * Ljk * jk3) -
+ (CF * Ljk * jk3) -
+ (8 * CA * Box6ijk * ij2 * jk3) / ik2 +
+ (16 * CF * Box6ijk * ij2 * jk3) / ik2 -
+ (8 * CA * Box6ijk * ij * jk3) / ik +
+ (16 * CF * Box6ijk * ij * jk3) / ik +
+ (CA * Ljk * ij * jk3) / ik -
+ (2 * CF * Ljk * ij * jk3) / ik
+ ) / (ij_ik * ik_jk_2);
qqbargLoops[11] = (
- (16 * CA * Box6jik * ij2 * ik) -
- (32 * CF * Box6jik * ij2 * ik) -
- (CA * Lij * ij2 * ik) +
- (2 * CF * Lij * ij2 * ik) +
- (8 * CA * Box6jik * ij * ik2) -
- (16 * CF * Box6jik * ij * ik2) -
- (CA * Lik * ij * ik2) +
- (2 * CF * Lik * ij * ik2) +
- (8 * CA * Box6jik * ij2 * ik2) / jk -
- (16 * CF * Box6jik * ij2 * ik2) / jk +
- (8 * CA * Box6jik * ij2 * jk) -
- (16 * CF * Box6jik * ij2 * jk) -
- (2 * CA * Lij * ij2 * jk) +
- (4 * CF * Lij * ij2 * jk) +
- (CA * ij * ik * jk) -
- (2 * CF * ij * ik * jk) +
- (16 * CA * Box6jik * ij * ik * jk) -
- (32 * CF * Box6jik * ij * ik * jk) -
- (2 * CA * Lij * ij * ik * jk) +
- (4 * CF * Lij * ij * ik * jk) -
- (2 * CA * Lik * ij * ik * jk) +
- (4 * CF * Lik * ij * ik * jk) -
- (CA * Lik * ik2 * jk) +
- (CF * Lik * ik2 * jk) +
- (CA * ij * jk2) -
- (2 * CF * ij * jk2) +
- (8 * CA * Box6jik * ij * jk2) -
- (16 * CF * Box6jik * ij * jk2) -
- (3 * CA * Lij * ij * jk2) +
- (6 * CF * Lij * ij * jk2) -
- (CA * Lik * ij * jk2) +
- (2 * CF * Lik * ij * jk2) +
- (CA * ik * jk2) -
- (2 * CF * ik * jk2) -
- (CA * Lij * ik * jk2) +
- (2 * CF * Lij * ik * jk2) -
- (2 * CA * Lik * ik * jk2) +
- (2 * CF * Lik * ik * jk2) +
- (CA * jk3) -
- (2 * CF * jk3) -
- (CA * Lij * jk3) +
- (2 * CF * Lij * jk3) -
- (CA * Lik * jk3) +
- (CF * Lik * jk3)
- ) / (ij_jk * ik_jk_2);
+ (16 * CA * Box6jik * ij2 * ik) -
+ (32 * CF * Box6jik * ij2 * ik) -
+ (CA * Lij * ij2 * ik) +
+ (2 * CF * Lij * ij2 * ik) +
+ (8 * CA * Box6jik * ij * ik2) -
+ (16 * CF * Box6jik * ij * ik2) -
+ (CA * Lik * ij * ik2) +
+ (2 * CF * Lik * ij * ik2) +
+ (8 * CA * Box6jik * ij2 * ik2) / jk -
+ (16 * CF * Box6jik * ij2 * ik2) / jk +
+ (8 * CA * Box6jik * ij2 * jk) -
+ (16 * CF * Box6jik * ij2 * jk) -
+ (2 * CA * Lij * ij2 * jk) +
+ (4 * CF * Lij * ij2 * jk) +
+ (CA * ij * ik * jk) -
+ (2 * CF * ij * ik * jk) +
+ (16 * CA * Box6jik * ij * ik * jk) -
+ (32 * CF * Box6jik * ij * ik * jk) -
+ (2 * CA * Lij * ij * ik * jk) +
+ (4 * CF * Lij * ij * ik * jk) -
+ (2 * CA * Lik * ij * ik * jk) +
+ (4 * CF * Lik * ij * ik * jk) -
+ (CA * Lik * ik2 * jk) +
+ (CF * Lik * ik2 * jk) +
+ (CA * ij * jk2) -
+ (2 * CF * ij * jk2) +
+ (8 * CA * Box6jik * ij * jk2) -
+ (16 * CF * Box6jik * ij * jk2) -
+ (3 * CA * Lij * ij * jk2) +
+ (6 * CF * Lij * ij * jk2) -
+ (CA * Lik * ij * jk2) +
+ (2 * CF * Lik * ij * jk2) +
+ (CA * ik * jk2) -
+ (2 * CF * ik * jk2) -
+ (CA * Lij * ik * jk2) +
+ (2 * CF * Lij * ik * jk2) -
+ (2 * CA * Lik * ik * jk2) +
+ (2 * CF * Lik * ik * jk2) +
+ (CA * jk3) -
+ (2 * CF * jk3) -
+ (CA * Lij * jk3) +
+ (2 * CF * Lij * jk3) -
+ (CA * Lik * jk3) +
+ (CF * Lik * jk3)
+ ) / (ij_jk * ik_jk_2);
qqbargLoops[12] = -3 * CF * Lijk + (
- (CA * ij2 * ik) -
- (9 * CF * ij2 * ik) +
- (8 * CA * Box6ijk * ij2 * ik) -
- (16 * CF * Box6ijk * ij2 * ik) -
- (8 * CA * Box6ikj * ij2 * ik) +
- (CA * ij * ik2) -
- (9 * CF * ij * ik2) +
- (8 * CA * Box6ijk * ij * ik2) -
- (16 * CF * Box6ijk * ij * ik2) -
- (8 * CA * Box6ikj * ij * ik2) +
- (CA * ij2 * jk) -
- (9 * CF * ij2 * jk) -
- (8 * CA * Box6ikj * ij2 * jk) +
- (8 * CA * Box6jik * ij2 * jk) -
- (16 * CF * Box6jik * ij2 * jk) +
- (2 * CA * ij * ik * jk) -
- (18 * CF * ij * ik * jk) +
- (8 * CA * Box6ijk * ij * ik * jk) -
- (16 * CF * Box6ijk * ij * ik * jk) -
- (40 * CA * Box6ikj * ij * ik * jk) +
- (8 * CA * Box6jik * ij * ik * jk) -
- (16 * CF * Box6jik * ij * ik * jk) +
- (3 * CF * Lik * ij * ik * jk) +
- (3 * CF * Ljk * ij * ik * jk) +
- (CA * ik2 * jk) -
- (9 * CF * ik2 * jk) +
- (8 * CA * Box6ijk * ik2 * jk) -
- (16 * CF * Box6ijk * ik2 * jk) -
- (32 * CA * Box6ikj * ik2 * jk) +
- (3 * CF * Lik * ik2 * jk) +
- (CA * ij * jk2) -
- (9 * CF * ij * jk2) -
- (8 * CA * Box6ikj * ij * jk2) +
- (8 * CA * Box6jik * ij * jk2) -
- (16 * CF * Box6jik * ij * jk2) +
- (CA * ik * jk2) -
- (9 * CF * ik * jk2) -
- (32 * CA * Box6ikj * ik * jk2) +
- (8 * CA * Box6jik * ik * jk2) -
- (16 * CF * Box6jik * ik * jk2) +
- (3 * CF * Ljk * ik * jk2) -
- (24 * CA * Box6ikj * ik2 * jk2) / ij
- ) / (ij_ik * ij_jk * ik_jk);
+ (CA * ij2 * ik) -
+ (9 * CF * ij2 * ik) +
+ (8 * CA * Box6ijk * ij2 * ik) -
+ (16 * CF * Box6ijk * ij2 * ik) -
+ (8 * CA * Box6ikj * ij2 * ik) +
+ (CA * ij * ik2) -
+ (9 * CF * ij * ik2) +
+ (8 * CA * Box6ijk * ij * ik2) -
+ (16 * CF * Box6ijk * ij * ik2) -
+ (8 * CA * Box6ikj * ij * ik2) +
+ (CA * ij2 * jk) -
+ (9 * CF * ij2 * jk) -
+ (8 * CA * Box6ikj * ij2 * jk) +
+ (8 * CA * Box6jik * ij2 * jk) -
+ (16 * CF * Box6jik * ij2 * jk) +
+ (2 * CA * ij * ik * jk) -
+ (18 * CF * ij * ik * jk) +
+ (8 * CA * Box6ijk * ij * ik * jk) -
+ (16 * CF * Box6ijk * ij * ik * jk) -
+ (40 * CA * Box6ikj * ij * ik * jk) +
+ (8 * CA * Box6jik * ij * ik * jk) -
+ (16 * CF * Box6jik * ij * ik * jk) +
+ (3 * CF * Lik * ij * ik * jk) +
+ (3 * CF * Ljk * ij * ik * jk) +
+ (CA * ik2 * jk) -
+ (9 * CF * ik2 * jk) +
+ (8 * CA * Box6ijk * ik2 * jk) -
+ (16 * CF * Box6ijk * ik2 * jk) -
+ (32 * CA * Box6ikj * ik2 * jk) +
+ (3 * CF * Lik * ik2 * jk) +
+ (CA * ij * jk2) -
+ (9 * CF * ij * jk2) -
+ (8 * CA * Box6ikj * ij * jk2) +
+ (8 * CA * Box6jik * ij * jk2) -
+ (16 * CF * Box6jik * ij * jk2) +
+ (CA * ik * jk2) -
+ (9 * CF * ik * jk2) -
+ (32 * CA * Box6ikj * ik * jk2) +
+ (8 * CA * Box6jik * ik * jk2) -
+ (16 * CF * Box6jik * ik * jk2) +
+ (3 * CF * Ljk * ik * jk2) -
+ (24 * CA * Box6ikj * ik2 * jk2) / ij
+ ) / (ij_ik * ij_jk * ik_jk);
/* // idendities implied by gauge invariance and current conservation; checked analytically and numerically
- Complex c1 = qqbargLoops[0] + qqbargLoops[6] + qqbargLoops[7];
- Complex c2 = qqbargLoops[1] + qqbargLoops[8] + qqbargLoops[9];
- Complex c3 = qqbargLoops[3] + qqbargLoops[4];
- Complex c4 = qqbargLoops[2] + qqbargLoops[5] + qqbargLoops[10] + qqbargLoops[11];
- Complex c5 =
- 2. * qqbargLoops[3]/ik +
- 2. * qqbargLoops[5]/jk +
- qqbargLoops[6] * (1.+ij/ik) +
- qqbargLoops[8] * (jk+ij)/ik +
- 2. * qqbargLoops[10] * (1./ik+1./jk) +
- 2. * qqbargLoops[12] * (1./ik+1./jk);
- Complex c6 =
- 2. * qqbargLoops[4]/jk +
- 2. * qqbargLoops[5]/jk +
- qqbargLoops[7] * (ik+ij)/jk +
- qqbargLoops[9] * (1.+ij/jk) +
- 2. * qqbargLoops[11] * (ik/jk2+1./jk);
- Complex c7 =
- 0.5 * qqbargLoops[0] * (ij+ik) +
- 0.5 * qqbargLoops[1] * (ij+jk) +
- qqbargLoops[2] * (1.+ik/jk) -
- qqbargLoops[12] * (1.+ik/jk);
+ Complex c1 = qqbargLoops[0] + qqbargLoops[6] + qqbargLoops[7];
+ Complex c2 = qqbargLoops[1] + qqbargLoops[8] + qqbargLoops[9];
+ Complex c3 = qqbargLoops[3] + qqbargLoops[4];
+ Complex c4 = qqbargLoops[2] + qqbargLoops[5] + qqbargLoops[10] + qqbargLoops[11];
+ Complex c5 =
+ 2. * qqbargLoops[3]/ik +
+ 2. * qqbargLoops[5]/jk +
+ qqbargLoops[6] * (1.+ij/ik) +
+ qqbargLoops[8] * (jk+ij)/ik +
+ 2. * qqbargLoops[10] * (1./ik+1./jk) +
+ 2. * qqbargLoops[12] * (1./ik+1./jk);
+ Complex c6 =
+ 2. * qqbargLoops[4]/jk +
+ 2. * qqbargLoops[5]/jk +
+ qqbargLoops[7] * (ik+ij)/jk +
+ qqbargLoops[9] * (1.+ij/jk) +
+ 2. * qqbargLoops[11] * (ik/jk2+1./jk);
+ Complex c7 =
+ 0.5 * qqbargLoops[0] * (ij+ik) +
+ 0.5 * qqbargLoops[1] * (ij+jk) +
+ qqbargLoops[2] * (1.+ik/jk) -
+ qqbargLoops[12] * (1.+ik/jk);
- double x1 = c1 != 0. ? log(abs(real(c1 * conj(c1)))) : 0.;
- double x2 = c2 != 0. ? log(abs(real(c2 * conj(c2)))) : 0.;
- double x3 = c3 != 0. ? log(abs(real(c3 * conj(c3)))) : 0.;
- double x4 = c4 != 0. ? log(abs(real(c4 * conj(c4)))) : 0.;
- double x5 = c5 != 0. ? log(abs(real(c5 * conj(c5)))) : 0.;
- double x6 = c6 != 0. ? log(abs(real(c6 * conj(c6)))) : 0.;
- double x7 = c7 != 0. ? log(abs(real(c7 * conj(c7)))) : 0.;
+ double x1 = c1 != 0. ? log(abs(real(c1 * conj(c1)))) : 0.;
+ double x2 = c2 != 0. ? log(abs(real(c2 * conj(c2)))) : 0.;
+ double x3 = c3 != 0. ? log(abs(real(c3 * conj(c3)))) : 0.;
+ double x4 = c4 != 0. ? log(abs(real(c4 * conj(c4)))) : 0.;
+ double x5 = c5 != 0. ? log(abs(real(c5 * conj(c5)))) : 0.;
+ double x6 = c6 != 0. ? log(abs(real(c6 * conj(c6)))) : 0.;
+ double x7 = c7 != 0. ? log(abs(real(c7 * conj(c7)))) : 0.;
- cerr << x1 << " " << x2 << " " << x3 << " " << x4 << " "
- << x5 << " " << x6 << " " << x7 << "\n";
+ cerr << x1 << " " << x2 << " " << x3 << " " << x4 << " "
+ << x5 << " " << x6 << " " << x7 << "\n";
*/
}
LorentzVector<Complex> MatchboxCurrents::qqbargGeneralLeftLoopCurrent(const int i, const int,
const int j, const int,
const int k, const int gHel,
const int n) {
qqbargLoopCoefficients(i,j,k);
const double ik = invariant(i,k);
const double jk = invariant(j,k);
const Complex plusP_ik = plusProduct(i,k);
const Complex plusP_in = plusProduct(i,n);
const Complex plusP_jk = plusProduct(j,k);
const Complex plusP_jn = plusProduct(j,n);
const Complex plusP_kn = plusProduct(k,n);
const Complex minusP_ik = minusProduct(i,k);
const Complex minusP_in = minusProduct(i,n);
const Complex minusP_jk = minusProduct(j,k);
const Complex minusP_jn = minusProduct(j,n);
const Complex minusP_kn = minusProduct(k,n);
const LorentzVector<Complex> & minusC_ij = minusCurrent(i,j);
const LorentzVector<Complex> & minusC_nk = minusCurrent(n,k);
const LorentzVector<Complex> & minusC_kj = minusCurrent(k,j);
const LorentzVector<Complex> & minusC_kn = minusCurrent(k,n);
Complex c1 = qqbargLoops[0]; Complex c2 = qqbargLoops[1]; Complex c3 = qqbargLoops[2];
Complex c4 = qqbargLoops[3]; Complex c5 = qqbargLoops[4]; Complex c6 = qqbargLoops[5];
Complex c7 = qqbargLoops[6]; Complex c8 = qqbargLoops[7]; Complex c9 = qqbargLoops[8];
Complex c10 = qqbargLoops[9]; Complex c11 = qqbargLoops[10]; Complex c12 = qqbargLoops[11];
Complex c13 = qqbargLoops[12];
if ( gHel == 1 ) {
return
(sqrt(2) * c6 * plusP_jk * minusC_nk * minusP_ik)/(jk * minusP_kn) +
(sqrt(2) * c1 * plusP_jk * momentum(i) * minusP_in)/minusP_kn +
(sqrt(2) * c2 * plusP_jk * momentum(j) * minusP_in)/minusP_kn +
(2 * sqrt(2) * c3 * plusP_jk * momentum(k) * minusP_in)/(jk * minusP_kn) +
(sqrt(2) * c4 * plusP_ik * minusC_ij * minusP_in)/(ik * minusP_kn) -
(sqrt(2) * c7 * plusP_ik * plusP_jk * momentum(i) * minusP_ik * minusP_in)/(ik * minusP_kn) -
(sqrt(2) * c9 * plusP_ik * plusP_jk * momentum(j) * minusP_ik * minusP_in)/(ik * minusP_kn) -
(2 * sqrt(2) * c11 * plusP_ik * plusP_jk * momentum(k) * minusP_ik * minusP_in)/(ik * jk * minusP_kn) +
(sqrt(2) * c5 * plusP_jk * minusC_ij * minusP_jn)/(jk * minusP_kn) -
(sqrt(2) * c8 * sqr(plusP_jk) * momentum(i) * minusP_ik * minusP_jn)/(jk * minusP_kn) -
(sqrt(2) * c10 * sqr(plusP_jk) * momentum(j) * minusP_ik * minusP_jn)/(jk * minusP_kn) -
(2 * sqrt(2) * c12 * sqr(plusP_jk) * momentum(k) * minusP_ik * minusP_jn)/(sqr(jk) * minusP_kn);
}
if ( gHel == -1 ) {
return
-((sqrt(2) * c1 * plusP_jn * momentum(i) * minusP_ik)/plusP_kn) -
(sqrt(2) * c2 * plusP_jn * momentum(j) * minusP_ik)/plusP_kn -
(2 * sqrt(2) * c3 * plusP_jn * momentum(k) * minusP_ik)/(jk * plusP_kn) -
(sqrt(2) * c4 * plusP_in * minusC_ij * minusP_ik)/(ik * plusP_kn) +
(sqrt(2) * c13 * minusC_kj * minusP_ik)/ik + (sqrt(2) * c13 * minusC_kj * minusP_ik)/jk -
(sqrt(2) * c6 * plusP_jk * minusC_kn * minusP_ik)/(jk * plusP_kn) +
(sqrt(2) * c7 * plusP_in * plusP_jk * momentum(i) * sqr(minusP_ik))/(ik * plusP_kn) +
(sqrt(2) * c9 * plusP_in * plusP_jk * momentum(j) * sqr(minusP_ik))/(ik * plusP_kn) +
(2 * sqrt(2) * c11 * plusP_in * plusP_jk * momentum(k) * sqr(minusP_ik))/(ik * jk * plusP_kn) -
(sqrt(2) * c5 * plusP_jn * minusC_ij * minusP_jk)/(jk * plusP_kn) +
(sqrt(2) * c8 * plusP_jk * plusP_jn * momentum(i) * minusP_ik * minusP_jk)/(jk * plusP_kn) +
(sqrt(2) * c10 * plusP_jk * plusP_jn * momentum(j) * minusP_ik * minusP_jk)/(jk * plusP_kn) +
(2 * sqrt(2) * c12 * plusP_jk * plusP_jn * momentum(k) * minusP_ik * minusP_jk)/(sqr(jk) * plusP_kn);
}
return czero;
}
LorentzVector<Complex> MatchboxCurrents::qqbargFixedLeftLoopCurrent(const int i, const int,
const int j, const int,
const int k, const int gHel) {
qqbargLoopCoefficients(i,j,k);
const double ik = invariant(i,k);
const double jk = invariant(j,k);
const Complex plusP_ij = plusProduct(i,j);
const Complex plusP_jk = plusProduct(j,k);
const Complex minusP_ij = minusProduct(i,j);
const Complex minusP_ik = minusProduct(i,k);
const LorentzVector<Complex> & minusC_ij = minusCurrent(i,j);
const LorentzVector<Complex> & minusC_ik = minusCurrent(i,k);
const LorentzVector<Complex> & minusC_kj = minusCurrent(k,j);
//Complex c1 = qqbargLoops[0]; Complex c2 = qqbargLoops[1]; Complex c3 = qqbargLoops[2];
Complex c4 = qqbargLoops[3]; Complex c5 = qqbargLoops[4]; Complex c6 = qqbargLoops[5];
Complex c7 = qqbargLoops[6]; Complex c8 = qqbargLoops[7]; Complex c9 = qqbargLoops[8];
Complex c10 = qqbargLoops[9]; Complex c11 = qqbargLoops[10]; Complex c12 = qqbargLoops[11];
Complex c13 = qqbargLoops[12];
if ( gHel == 1 ) {
return
-((sqrt(2) * c6 * plusP_jk * minusC_ik)/jk)
- (sqrt(2) * c8 * sqr(plusP_jk) * momentum(i) * minusP_ij)/jk -
(sqrt(2) * c10 * sqr(plusP_jk) * momentum(j) * minusP_ij)/jk -
(2 * sqrt(2) * c12 * sqr(plusP_jk) * momentum(k) * minusP_ij)/sqr(jk) +
(sqrt(2) * c5 * plusP_jk * minusC_ij * minusP_ij)/(jk * minusP_ik);
}
if ( gHel == -1 ) {
return
(sqrt(2) * c4 * plusP_ij * minusC_ij * minusP_ik)/(ik * plusP_jk) +
(sqrt(2) * c13 * minusC_kj * minusP_ik)/ik + (sqrt(2) * c13 * minusC_kj * minusP_ik)/jk +
(sqrt(2) * c6 * minusC_kj * minusP_ik)/jk - (sqrt(2) * c7 * plusP_ij * momentum(i)*
- sqr(minusP_ik))/ik -
+ sqr(minusP_ik))/ik -
(sqrt(2) * c9 * plusP_ij * momentum(j) * sqr(minusP_ik))/ik -
(2 * sqrt(2) * c11 * plusP_ij * momentum(k) * sqr(minusP_ik))/(ik * jk);
}
return czero;
}
LorentzVector<Complex> MatchboxCurrents::qqbargGeneralRightLoopCurrent(const int i, const int,
const int j, const int,
const int k, const int gHel,
const int n) {
qqbargLoopCoefficients(i,j,k);
const double ik = invariant(i,k);
const double jk = invariant(j,k);
const Complex plusP_ik = plusProduct(i,k);
const Complex plusP_in = plusProduct(i,n);
const Complex plusP_jk = plusProduct(j,k);
const Complex plusP_jn = plusProduct(j,n);
const Complex plusP_kn = plusProduct(k,n);
const Complex minusP_ik = minusProduct(i,k);
const Complex minusP_in = minusProduct(i,n);
const Complex minusP_jk = minusProduct(j,k);
const Complex minusP_jn = minusProduct(j,n);
const Complex minusP_kn = minusProduct(k,n);
const LorentzVector<Complex> & minusC_ji = minusCurrent(j,i);
const LorentzVector<Complex> & minusC_jk = minusCurrent(j,k);
const LorentzVector<Complex> & minusC_nk = minusCurrent(n,k);
const LorentzVector<Complex> & minusC_kn = minusCurrent(k,n);
Complex c1 = qqbargLoops[0]; Complex c2 = qqbargLoops[1]; Complex c3 = qqbargLoops[2];
Complex c4 = qqbargLoops[3]; Complex c5 = qqbargLoops[4]; Complex c6 = qqbargLoops[5];
Complex c7 = qqbargLoops[6]; Complex c8 = qqbargLoops[7]; Complex c9 = qqbargLoops[8];
Complex c10 = qqbargLoops[9]; Complex c11 = qqbargLoops[10]; Complex c12 = qqbargLoops[11];
Complex c13 = qqbargLoops[12];
if ( gHel == 1 ) {
return
-((sqrt(2) * c13 * plusP_ik * minusC_jk)/ik) - (sqrt(2) * c13 * plusP_ik * minusC_jk)/jk +
(sqrt(2) * c4 * plusP_ik * minusC_ji * minusP_in)/(ik * minusP_kn) +
(sqrt(2) * c6 * plusP_ik * minusC_nk * minusP_jk)/(jk * minusP_kn) -
(sqrt(2) * c7 * sqr(plusP_ik) * momentum(i) * minusP_in * minusP_jk)/(ik * minusP_kn) -
(sqrt(2) * c9 * sqr(plusP_ik) * momentum(j) * minusP_in * minusP_jk)/(ik * minusP_kn) -
(2 * sqrt(2) * c11 * sqr(plusP_ik) * momentum(k) * minusP_in * minusP_jk)/(ik * jk * minusP_kn) +
(sqrt(2) * c1 * plusP_ik * momentum(i) * minusP_jn)/minusP_kn +
(sqrt(2) * c2 * plusP_ik * momentum(j) * minusP_jn)/minusP_kn +
(2 * sqrt(2) * c3 * plusP_ik * momentum(k) * minusP_jn)/(jk * minusP_kn) +
(sqrt(2) * c5 * plusP_jk * minusC_ji * minusP_jn)/(jk * minusP_kn) -
(sqrt(2) * c8 * plusP_ik * plusP_jk * momentum(i) * minusP_jk * minusP_jn)/(jk * minusP_kn) -
(sqrt(2) * c10 * plusP_ik * plusP_jk * momentum(j) * minusP_jk * minusP_jn)/(jk * minusP_kn) -
(2 * sqrt(2) * c12 * plusP_ik * plusP_jk * momentum(k) * minusP_jk * minusP_jn)/(sqr(jk) * minusP_kn);
}
if ( gHel == -1 ) {
return
-((sqrt(2) * c4 * plusP_in * minusC_ji * minusP_ik)/(ik * plusP_kn)) -
(sqrt(2) * c1 * plusP_in * momentum(i) * minusP_jk)/plusP_kn -
(sqrt(2) * c2 * plusP_in * momentum(j) * minusP_jk)/plusP_kn -
(2 * sqrt(2) * c3 * plusP_in * momentum(k) * minusP_jk)/(jk * plusP_kn) -
(sqrt(2) * c5 * plusP_jn * minusC_ji * minusP_jk)/(jk * plusP_kn) -
(sqrt(2) * c6 * plusP_ik * minusC_kn * minusP_jk)/(jk * plusP_kn) +
(sqrt(2) * c7 * plusP_ik * plusP_in * momentum(i) * minusP_ik * minusP_jk)/(ik * plusP_kn) +
(sqrt(2) * c9 * plusP_ik * plusP_in * momentum(j) * minusP_ik * minusP_jk)/(ik * plusP_kn) +
(2 * sqrt(2) * c11 * plusP_ik * plusP_in * momentum(k) * minusP_ik * minusP_jk)/
(ik * jk * plusP_kn) +
(sqrt(2) * c8 * plusP_ik * plusP_jn * momentum(i) * sqr(minusP_jk))/(jk * plusP_kn) +
(sqrt(2) * c10 * plusP_ik * plusP_jn * momentum(j) * sqr(minusP_jk))/(jk * plusP_kn) +
(2 * sqrt(2) * c12 * plusP_ik * plusP_jn * momentum(k) * sqr(minusP_jk))/(sqr(jk) * plusP_kn);
}
return czero;
}
LorentzVector<Complex> MatchboxCurrents::qqbargFixedRightLoopCurrent(const int i, const int,
const int j, const int,
const int k, const int gHel) {
qqbargLoopCoefficients(i,j,k);
const double ik = invariant(i,k);
const double jk = invariant(j,k);
const Complex plusP_ij = plusProduct(i,j);
const Complex plusP_ik = plusProduct(i,k);
const Complex minusP_ij = minusProduct(i,j);
const Complex minusP_jk = minusProduct(j,k);
const LorentzVector<Complex> & minusC_ji = minusCurrent(j,i);
const LorentzVector<Complex> & minusC_jk = minusCurrent(j,k);
const LorentzVector<Complex> & minusC_ki = minusCurrent(k,i);
//Complex c1 = qqbargLoops[0]; Complex c2 = qqbargLoops[1]; Complex c3 = qqbargLoops[2];
Complex c4 = qqbargLoops[3]; Complex c5 = qqbargLoops[4]; Complex c6 = qqbargLoops[5];
Complex c7 = qqbargLoops[6]; Complex c8 = qqbargLoops[7]; Complex c9 = qqbargLoops[8];
Complex c10 = qqbargLoops[9]; Complex c11 = qqbargLoops[10]; Complex c12 = qqbargLoops[11];
Complex c13 = qqbargLoops[12];
if ( gHel == 1 ) {
return
-((sqrt(2) * c13 * plusP_ik * minusC_jk)/ik) -
(sqrt(2) * c13 * plusP_ik * minusC_jk)/jk -
(sqrt(2) * c6 * plusP_ik * minusC_jk)/jk +
(sqrt(2) * c7 * sqr(plusP_ik) * momentum(i) * minusP_ij)/ik +
(sqrt(2) * c9 * sqr(plusP_ik) * momentum(j) * minusP_ij)/ik +
(2 * sqrt(2) * c11 * sqr(plusP_ik) * momentum(k) * minusP_ij)/(ik * jk) -
(sqrt(2) * c4 * plusP_ik * minusC_ji * minusP_ij)/(ik * minusP_jk);
}
if ( gHel == -1 ) {
return
-((sqrt(2) * c5 * plusP_ij * minusC_ji * minusP_jk)/(jk * plusP_ik)) +
(sqrt(2) * c6 * minusC_ki * minusP_jk)/jk +
(sqrt(2) * c8 * plusP_ij * momentum(i) * sqr(minusP_jk))/jk +
(sqrt(2) * c10 * plusP_ij * momentum(j) * sqr(minusP_jk))/jk +
(2 * sqrt(2) * c12 * plusP_ij * momentum(k) * sqr(minusP_jk))/sqr(jk);
}
return czero;
}
const LorentzVector<Complex>& MatchboxCurrents::qqbargLeftOneLoopCurrent(const int q, const int qHel,
const int qbar, const int qbarHel,
const int g1, const int g1Hel) {
if ( qHel != 1 || qbarHel != 1 )
return czero;
if ( getCurrent(hash<2>(1,2,q,qHel,qbar,qbarHel,g1,g1Hel)) ) {
#ifdef CHECK_MatchboxCurrents
LorentzVector<Complex> ni = Complex(0.,0.5) * qqbargGeneralLeftLoopCurrent(q,qHel,qbar,qbarHel,g1,g1Hel,q);
LorentzVector<Complex> nj = Complex(0.,0.5) * qqbargGeneralLeftLoopCurrent(q,qHel,qbar,qbarHel,g1,g1Hel,qbar);
LorentzVector<Complex> nl = Complex(0.,0.5) * qqbargGeneralLeftLoopCurrent(q,qHel,qbar,qbarHel,g1,g1Hel,0);
LorentzVector<Complex> nlbar = Complex(0.,0.5) * qqbargGeneralLeftLoopCurrent(q,qHel,qbar,qbarHel,g1,g1Hel,1);
LorentzVector<Complex> fixed = Complex(0.,0.5) * qqbargFixedLeftLoopCurrent(q,qHel,qbar,qbarHel,g1,g1Hel);
LorentzVector<Complex> x1 = fixed - ni;
LorentzVector<Complex> x2 = fixed - nj;
LorentzVector<Complex> x3 = fixed - nl;
LorentzVector<Complex> x4 = fixed - nlbar;
double c1 =
real(x1.t() * conj(x1.t())) + real(x1.x() * conj(x1.x())) + real(x1.y() * conj(x1.y())) + real(x1.z() * conj(x1.z()));
double c2 =
real(x2.t() * conj(x2.t())) + real(x2.x() * conj(x2.x())) + real(x2.y() * conj(x2.y())) + real(x2.z() * conj(x2.z()));
double c3 =
real(x3.t() * conj(x3.t())) + real(x3.x() * conj(x3.x())) + real(x3.y() * conj(x3.y())) + real(x3.z() * conj(x3.z()));
double c4 =
real(x4.t() * conj(x4.t())) + real(x4.x() * conj(x4.x())) + real(x4.y() * conj(x4.y())) + real(x4.z() * conj(x4.z()));
ostream& ncheck = checkStream("qqbargLeftLoopCurrentNChoice");
ncheck << (c1 != 0. ? log10(abs(c1)) : 0.) << " "
<< (c2 != 0. ? log10(abs(c2)) : 0.) << " "
<< (c3 != 0. ? log10(abs(c3)) : 0.) << " "
<< (c4 != 0. ? log10(abs(c4)) : 0.) << " "
<< "\n" << flush;
#endif
cacheCurrent(Complex(0.,0.5) * qqbargFixedLeftLoopCurrent(q,qHel,qbar,qbarHel,g1,g1Hel));
}
#ifdef CHECK_MatchboxCurrents
checkCurrent("qqbargLeftLoopCurrent",cachedCurrent(),momentum(q)+momentum(qbar)+momentum(g1));
#endif
return cachedCurrent();
}
const LorentzVector<Complex>& MatchboxCurrents::qqbargRightOneLoopCurrent(const int q, const int qHel,
const int qbar, const int qbarHel,
const int g1, const int g1Hel) {
if ( qHel != -1 || qbarHel != -1 )
return czero;
if ( getCurrent(hash<2>(2,2,q,qHel,qbar,qbarHel,g1,g1Hel)) ) {
#ifdef CHECK_MatchboxCurrents
LorentzVector<Complex> ni = Complex(0.,0.5) * qqbargGeneralRightLoopCurrent(q,qHel,qbar,qbarHel,g1,g1Hel,q);
LorentzVector<Complex> nj = Complex(0.,0.5) * qqbargGeneralRightLoopCurrent(q,qHel,qbar,qbarHel,g1,g1Hel,qbar);
LorentzVector<Complex> nl = Complex(0.,0.5) * qqbargGeneralRightLoopCurrent(q,qHel,qbar,qbarHel,g1,g1Hel,0);
LorentzVector<Complex> nlbar = Complex(0.,0.5) * qqbargGeneralRightLoopCurrent(q,qHel,qbar,qbarHel,g1,g1Hel,1);
LorentzVector<Complex> fixed = Complex(0.,0.5) * qqbargFixedRightLoopCurrent(q,qHel,qbar,qbarHel,g1,g1Hel);
LorentzVector<Complex> x1 = fixed - ni;
LorentzVector<Complex> x2 = fixed - nj;
LorentzVector<Complex> x3 = fixed - nl;
LorentzVector<Complex> x4 = fixed - nlbar;
double c1 =
real(x1.t() * conj(x1.t())) + real(x1.x() * conj(x1.x())) + real(x1.y() * conj(x1.y())) + real(x1.z() * conj(x1.z()));
double c2 =
real(x2.t() * conj(x2.t())) + real(x2.x() * conj(x2.x())) + real(x2.y() * conj(x2.y())) + real(x2.z() * conj(x2.z()));
double c3 =
real(x3.t() * conj(x3.t())) + real(x3.x() * conj(x3.x())) + real(x3.y() * conj(x3.y())) + real(x3.z() * conj(x3.z()));
double c4 =
real(x4.t() * conj(x4.t())) + real(x4.x() * conj(x4.x())) + real(x4.y() * conj(x4.y())) + real(x4.z() * conj(x4.z()));
ostream& ncheck = checkStream("qqbargRightLoopCurrentNChoice");
ncheck << (c1 != 0. ? log10(abs(c1)) : 0.) << " "
<< (c2 != 0. ? log10(abs(c2)) : 0.) << " "
<< (c3 != 0. ? log10(abs(c3)) : 0.) << " "
<< (c4 != 0. ? log10(abs(c4)) : 0.) << " "
<< "\n" << flush;
#endif
cacheCurrent(Complex(0.,0.5) * qqbargFixedRightLoopCurrent(q,qHel,qbar,qbarHel,g1,g1Hel));
}
#ifdef CHECK_MatchboxCurrents
checkCurrent("qqbargRightLoopCurrent",cachedCurrent(),momentum(q)+momentum(qbar)+momentum(g1));
#endif
return cachedCurrent();
}
#ifdef CHECK_MatchboxCurrents
map<string,ofstream * >& MatchboxCurrents::checkStreams() {
static map<string,ofstream * > theMap;
return theMap;
}
ostream& MatchboxCurrents::checkStream(const string& id) {
map<string,ofstream * >::iterator ret = checkStreams().find(id);
if ( ret == checkStreams().end() ) {
checkStreams()[id] = new ofstream(id.c_str());
ret = checkStreams().find(id);
}
return *(ret->second);
}
void MatchboxCurrents::checkCurrent(const string& id,
const LorentzVector<Complex>& current,
const LorentzVector<double>& q) {
Complex c = current.dot(q);
double ac = abs(real(conj(c) * c));
if ( isnan(ac) || isinf(ac) ) {
cerr << "ooops ... nan encountered in current conservation\n" << flush;
return;
}
checkStream(id) << (ac > 0. ? log10(ac) : 0.) << "\n";
}
#endif // CHECK_MatchboxCurrents
diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxCurrents.h b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxCurrents.h
old mode 100644
new mode 100755
--- a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxCurrents.h
+++ b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxCurrents.h
@@ -1,314 +1,320 @@
-// -*- C++ -*-
+// -*- C++ -*-
//
// MatchboxCurrents.h is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2012 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_MatchboxCurrents_H
#define Herwig_MatchboxCurrents_H
//
// This is the declaration of the MatchboxCurrents class.
//
#include "Herwig/MatrixElement/Matchbox/Utility/AmplitudeCache.h"
#include "Herwig/MatrixElement/Matchbox/Utility/SpinorHelicity.h"
#include "Herwig/Models/StandardModel/StandardCKM.h"
#include "ThePEG/StandardModel/StandardModelBase.h"
namespace Herwig {
using namespace ThePEG;
using namespace SpinorHelicity;
/**
* \ingroup Matchbox
* \author Simon Platzer
*
* \brief MatchboxCurrents
*/
struct MatchboxCurrents
: public AmplitudeCache<pair<size_t,size_t> > {
/**
* The Herwig StandardCKM object
*/
Ptr<StandardCKM>::tcptr theStandardCKM;
/**
* Return the Herwig StandardCKM object
*/
Ptr<StandardCKM>::tcptr standardCKM(const StandardModelBase& SM) {
if ( !theStandardCKM )
theStandardCKM = dynamic_ptr_cast<Ptr<StandardCKM>::tcptr>(SM.CKM());
assert(theStandardCKM);
return theStandardCKM;
}
/**
* The Z mass
*/
Energy MZ;
/**
* The Z width
*/
Energy GZ;
/**
* The W mass
*/
Energy MW;
/**
* The W width
*/
Energy GW;
/**
* CA
*/
double CA;
/**
* CF
*/
double CF;
/**
* Generate a hash value for the current;
* second member of the pair reserved for combinations
*/
template<size_t slot>
pair<size_t,size_t> hash(const int ct, const int tl,
const int p1, const int h1,
const int p2, const int h2,
const int p3 = -1, const int h3 = -2,
const int p4 = -1, const int h4 = -2) const {
return
pair<size_t,size_t>(slot,
(p4 + 1)*1 + (h4 + 2)*10 +
(p3 + 1)*100 + (h3 + 2)*1000 +
(p2 + 1)*10000 + (h2 + 2)*100000 +
(p1 + 1)*1000000 + (h1 + 2)*10000000 +
(ct + 1)*100000000 + (tl + 1)*1000000000);
}
/**
* Setup the lepton reference momenta
*/
void setupLeptons(const int l, const Lorentz5Momentum& pl,
const int lbar, const Lorentz5Momentum& plbar);
/**
+ * Setup the quark reference momenta
+ */
+ void setupQuarks(const int q, const Lorentz5Momentum& pq,
+ const int qbar, const Lorentz5Momentum& pqbar);
+
+ /**
* Tree level left-handed llbar current
*/
const LorentzVector<Complex>& llbarLeftCurrent(const int l, const int lHel,
const int lbar, const int lbarHel);
/**
* Tree level right-handed llbar current
*/
const LorentzVector<Complex>& llbarRightCurrent(const int l, const int lHel,
const int lbar, const int lbarHel);
/**
* Tree level left-handed qqbar current
*/
const LorentzVector<Complex>& qqbarLeftCurrent(const int q, const int qHel,
const int qbar, const int qbarHel);
/**
* Tree level right-handed qqbar current
*/
const LorentzVector<Complex>& qqbarRightCurrent(const int q, const int qHel,
const int qbar, const int qbarHel);
/**
* Tree level left-handed qqbarg current
*/
const LorentzVector<Complex>& qqbargLeftCurrent(const int q, const int qHel,
const int qbar, const int qbarHel,
const int g, const int gHel);
/**
* Tree level right-handed qqbarg current
*/
const LorentzVector<Complex>& qqbargRightCurrent(const int q, const int qHel,
const int qbar, const int qbarHel,
const int g, const int gHel);
/**
* Tree level left-handed qqbargg current
*/
const LorentzVector<Complex>& qqbarggLeftCurrent(const int q, const int qHel,
const int qbar, const int qbarHel,
const int g1, const int g1Hel,
const int g2, const int g2Hel);
/**
* Tree level right-handed qqbargg current
*/
const LorentzVector<Complex>& qqbarggRightCurrent(const int q, const int qHel,
const int qbar, const int qbarHel,
const int g1, const int g1Hel,
const int g2, const int g2Hel);
/**
* Tree level left-handed qqbarkkbar current
*/
const LorentzVector<Complex>& qqbarqqbarLeftCurrent(const int q, const int qHel,
const int qbar, const int qbarHel,
const int k, const int kHel,
const int kbar, const int kbarHel);
/**
* Tree level right-handed qqbarkkbar current
*/
const LorentzVector<Complex>& qqbarqqbarRightCurrent(const int q, const int qHel,
const int qbar, const int qbarHel,
const int k, const int kHel,
const int kbar, const int kbarHel);
/**
* One-loop left-handed qqbar current
*/
const LorentzVector<Complex>& qqbarLeftOneLoopCurrent(const int q, const int qHel,
const int qbar, const int qbarHel);
/**
* One-loop right-handed qqbar current
*/
const LorentzVector<Complex>& qqbarRightOneLoopCurrent(const int q, const int qHel,
const int qbar, const int qbarHel);
/**
* One-loop left-handed qqbarg current
*/
const LorentzVector<Complex>& qqbargLeftOneLoopCurrent(const int q, const int qHel,
const int qbar, const int qbarHel,
const int g, const int gHel);
/**
* One-loop right-handed qqbarg current
*/
const LorentzVector<Complex>& qqbargRightOneLoopCurrent(const int q, const int qHel,
const int qbar, const int qbarHel,
const int g, const int gHel);
private:
/**
* Tree level left-handed qqbargg current, full reference vector dependence
*/
LorentzVector<Complex> qqbarggGeneralLeftCurrent(const int q, const int qHel,
const int qbar, const int qbarHel,
const int g1, const int g1Hel,
const int g2, const int g2Hel,
const int n);
/**
* Tree level left-handed qqbargg current, fixed reference vector choice
*/
LorentzVector<Complex> qqbarggFixedLeftCurrent(const int q, const int qHel,
const int qbar, const int qbarHel,
const int g1, const int g1Hel,
const int g2, const int g2Hel);
/**
* Tree level left-handed qqbargg current, full reference vector dependence
*/
LorentzVector<Complex> qqbarggGeneralRightCurrent(const int q, const int qHel,
const int qbar, const int qbarHel,
const int g1, const int g1Hel,
const int g2, const int g2Hel,
const int n);
/**
* Tree level left-handed qqbargg current, fixed reference vector choice
*/
LorentzVector<Complex> qqbarggFixedRightCurrent(const int q, const int qHel,
const int qbar, const int qbarHel,
const int g1, const int g1Hel,
const int g2, const int g2Hel);
/**
* Container for the coefficients of the standard matrix elements for the
* one-loop qqbarg currents.
*/
vector<Complex> qqbargLoops;
/**
* Work out the coefficients of the standard matrix elements for the
* one-loop qqbarg currents.
*/
void qqbargLoopCoefficients(const int q, const int qbar, const int g);
/**
* Evaluate the six-dimensional box
*/
Complex box6(const int i, const int j, const int k);
/**
* One-loop left-handed qqbarg current, full reference vector dependence
*/
LorentzVector<Complex> qqbargGeneralLeftLoopCurrent(const int q, const int qHel,
const int qbar, const int qbarHel,
const int g, const int gHel,
const int n);
/**
* One-loop left-handed qqbarg current, fixed reference vector choice
*/
LorentzVector<Complex> qqbargFixedLeftLoopCurrent(const int q, const int qHel,
const int qbar, const int qbarHel,
const int g, const int gHel);
/**
* One-loop left-handed qqbarg current, full reference vector dependence
*/
LorentzVector<Complex> qqbargGeneralRightLoopCurrent(const int q, const int qHel,
const int qbar, const int qbarHel,
const int g, const int gHel,
const int n);
/**
* One-loop left-handed qqbarg current, fixed reference vector choice
*/
LorentzVector<Complex> qqbargFixedRightLoopCurrent(const int q, const int qHel,
const int qbar, const int qbarHel,
const int g, const int gHel);
//#define CHECK_MatchboxCurrents
#ifdef CHECK_MatchboxCurrents
private:
/**
* Ostreams to write precision data to
*/
static map<string,ofstream*>& checkStreams();
/**
* Return check stream for given name
*/
static ostream& checkStream(const string&);
/**
* Check if the given current is conserved
*/
void checkCurrent(const string& id,
const LorentzVector<Complex>& current,
const LorentzVector<double>& q);
#endif // CHECK_MatchboxCurrents
};
}
#endif // Herwig_MatchboxCurrents_H
diff --git a/MatrixElement/Matchbox/External/MadGraph/MadGraphAmplitude.cc b/MatrixElement/Matchbox/External/MadGraph/MadGraphAmplitude.cc
--- a/MatrixElement/Matchbox/External/MadGraph/MadGraphAmplitude.cc
+++ b/MatrixElement/Matchbox/External/MadGraph/MadGraphAmplitude.cc
@@ -1,842 +1,843 @@
// -*- C++ -*-
//
// MadGraphAmplitude.cc is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2012 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 MadGraphAmplitude class.
//
#include "MadGraphAmplitude.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "Herwig/MatrixElement/Matchbox/MatchboxFactory.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/EnumParticles.h"
#include <boost/lexical_cast.hpp>
#include <boost/filesystem.hpp>
#include <cstdlib>
#include <dlfcn.h>
#include <errno.h>
#include <sstream>
using namespace Herwig;
#ifndef HERWIG_BINDIR
#error Makefile.am needs to define HERWIG_BINDIR
#endif
#ifndef HERWIG_PKGDATADIR
#error Makefile.am needs to define HERWIG_PKGDATADIR
#endif
#ifndef MADGRAPH_PREFIX
#error Makefile.am needs to define MADGRAPH_PREFIX
#endif
extern "C" void mginitproc_(char *i,int);
extern "C" void MG_Calculate_wavefunctions_virt(int* proc,double*,double*);
extern "C" void MG_Calculate_wavefunctions_born(int* proc,double*, int*);
extern "C" void MG_Jamp (int* proc,int*, double*);
extern "C" void MG_LNJamp (int* proc,int*, double*);
extern "C" void MG_Virt (int* proc,double*);
extern "C" void MG_NCol (int* proc,int*);
extern "C" void MG_vxxxxx (double* p,double* n,int* inc,double* );
extern "C" void MG_Colour (int* proc,int* i,int* j ,int* color);
MadGraphAmplitude::MadGraphAmplitude()
: theMGmodel("loop_sm"),keepinputtopmass(false),
bindir_(HERWIG_BINDIR), includedir_(HERWIG_INCLUDEDIR), pkgdatadir_(HERWIG_PKGDATADIR), madgraphPrefix_(MADGRAPH_PREFIX)
{}
MadGraphAmplitude::~MadGraphAmplitude() {
}
IBPtr MadGraphAmplitude::clone() const {
return new_ptr(*this);
}
IBPtr MadGraphAmplitude::fullclone() const {
return new_ptr(*this);
}
bool MadGraphAmplitude::initializedMad=false;
vector<string> MadGraphAmplitude::BornAmplitudes=vector<string>();
vector<string> MadGraphAmplitude::VirtAmplitudes=vector<string>();
void MadGraphAmplitude::initProcess(const cPDVector& ) {
if ( lastMatchboxXComb()->initialized() )
return;
if ( !DynamicLoader::load(mgProcLibPath()+"InterfaceMadGraph.so") )
throw Exception() << "MadGraphAmplitude: Failed to load MadGraph amplitudes\n"
<< DynamicLoader::lastErrorMessage
<< Exception::runerror;
if (!initializedMad){
string mstr=(factory()->runStorage()+"MadGraphAmplitudes"+"/param_card"+((theMGmodel=="loop_sm")?"":("_"+theMGmodel))+".dat");
+ if( theMGmodel[0]=='/')mstr="param_card.dat";
size_t len = mstr.size();
mginitproc_(const_cast<char*>(mstr.c_str()),len);
initializedMad=true;
}
lastMatchboxXComb()->isInitialized();
}
bool MadGraphAmplitude::writeAmplitudesDat(){
bool res=false;
string born= mgProcLibPath()+"BornAmplitudes.dat";
if ( !boost::filesystem::exists(born) ) {
ofstream borns(born.c_str());
for (vector<string>::iterator amps=BornAmplitudes.begin();amps!=BornAmplitudes.end();amps++)
borns<<*amps<<endl;
borns.close();
res=true;
}
string virt= mgProcLibPath()+"VirtAmplitudes.dat";
if ( !boost::filesystem::exists(virt) ) {
ofstream virts(virt.c_str());
for (vector<string>::iterator amps=VirtAmplitudes.begin();amps!=VirtAmplitudes.end();amps++)
virts<<*amps<<endl;
virts.flush();
virts.close();
res=true;
}
return res;
}
bool MadGraphAmplitude::checkAmplitudes(){
string born= mgProcLibPath()+"BornAmplitudes.dat";
string virt= mgProcLibPath()+"VirtAmplitudes.dat";
assert ( boost::filesystem::exists(born)|| boost::filesystem::exists(virt));
bool foundallborns=true;
for (vector<string>::iterator amps=BornAmplitudes.begin();amps!=BornAmplitudes.end();amps++){
ifstream borns(born.c_str());
string line;
bool foundthisborn=false;
while (std::getline(borns, line)) {
if(line==*amps)foundthisborn=true;
}
foundallborns&=foundthisborn;
}
bool foundallvirts=true;
for (vector<string>::iterator amps=VirtAmplitudes.begin();amps!=VirtAmplitudes.end();amps++){
ifstream virts(virt.c_str());
string line;
bool foundthisvirt=false;
while (std::getline(virts, line)) {
if(line==*amps)foundthisvirt=true;
}
foundallvirts&=foundthisvirt;
}
if (!foundallborns||!foundallvirts)
throw Exception() << "MadGraphAmplitude: One amplitude has no externalId. Please remove the MadGraphAmplitude-folder and rebuild.\n" << Exception::runerror;
return foundallborns && foundallvirts;
}
string MadGraphAmplitude::mgProcLibPath(){
string res=theProcessPath == "" ? factory()->buildStorage()+"MadGraphAmplitudes" : theProcessPath;
if (res.at(res.length()-1) != '/') res.append("/");
return res;
}
bool MadGraphAmplitude::initializeExternal() {
if ( boost::filesystem::exists(mgProcLibPath()) ) {
if ( !boost::filesystem::is_directory(mgProcLibPath()) )
throw Exception() << "MadGraphAmplitude: MadGraph amplitude storage '"
<< mgProcLibPath() << "' existing but not a directory."
<< Exception::runerror;
} else {
boost::filesystem::create_directories(mgProcLibPath());
}
string runAmplitudes = factory()->runStorage() + "/MadGraphAmplitudes";
if ( boost::filesystem::exists(runAmplitudes) ) {
if ( !boost::filesystem::is_directory(runAmplitudes) )
throw Exception() << "MadGraphAmplitude: MadGraph amplitude storage '"
<< runAmplitudes << "' existing but not a directory."
<< Exception::runerror;
} else {
boost::filesystem::create_directories(runAmplitudes);
}
//EW-consistency check:
Energy MW=getParticleData(ParticleID::Wplus)->hardProcessMass();
Energy MZ=getParticleData(ParticleID::Z0)->hardProcessMass();
if( MW!= sqrt(MZ*MZ/2.0+sqrt(MZ*MZ*MZ*MZ/4.0-Constants::pi*SM().alphaEMMZ()*MZ*MZ/ sqrt(2.0)/SM().fermiConstant()))){
generator()->log()<<"\n\n-----!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!-----";
generator()->log() << "\nYou are using a EW scheme which is inconsistent with the MadGraph parametisation:\n\n"
<<MW/GeV<< " GeV==MW!= sqrt(MZ^2/2+sqrt(MZ^4/4.0-pi*alphaEMMZ*MZ^2/ sqrt(2)/G_f))=="<<
sqrt(MZ*MZ/2.0+sqrt(MZ*MZ*MZ*MZ/4.0-Constants::pi*SM().alphaEMMZ()*MZ*MZ/ sqrt(2.0)/SM().fermiConstant()))/GeV
<<" GeV\n\n-----!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!-----\n";
}
string para= factory()->runStorage()+"/MadGraphAmplitudes"+"/MG-Parameter.dat";
ofstream params(para.c_str());
params<<"$WZ$ " <<std::setiosflags(ios::scientific) <<getParticleData(ParticleID::Z0)->hardProcessWidth() /GeV;
params<<"\n$WW$ " <<std::setiosflags(ios::scientific) <<getParticleData(ParticleID::Wplus)->hardProcessWidth()/GeV;
params<<"\n$alphas$ " <<std::setiosflags(ios::scientific) <<SM().alphaS();
params<<"\n$GF$ " <<std::setiosflags(ios::scientific) <<SM().fermiConstant()*GeV2 ;
params<<"\n$alphaMZ$ " <<std::setiosflags(ios::scientific) <<1/SM().alphaEMMZ();
params<<"\n$MZ$ " <<std::setiosflags(ios::scientific) <<getParticleData(ParticleID::Z0)->hardProcessMass() /GeV<<flush;
params<<"\n$MW$ " <<std::setiosflags(ios::scientific) <<getParticleData(ParticleID::Wplus)->hardProcessMass() /GeV<<flush;
params<<"\n$sw2$ " <<std::setiosflags(ios::scientific) << SM().sin2ThetaW() <<flush;
if(theMGmodel=="heft"&&!keepinputtopmass){
if ( factory()->initVerbose() ) {
generator()->log()<<"\n---------------------------------------------------------------";
generator()->log()<<"\n---------------------------------------------------------------";
generator()->log()<<"\nNote: You are using the Higgs Effective model (heft) in ";
generator()->log()<<"\n Madgraph. We assume you try to calculate NLO with ";
generator()->log()<<"\n the GoSam virtual amplitudes. To match the models we ";
generator()->log()<<"\n therefore set the topmass to 10000000 GeV.";
generator()->log()<<"\n\n For more information see the \\tau parameter in:";
generator()->log()<<"\n https://cp3.irmp.ucl.ac.be/projects/madgraph/wiki/Models/HiggsEffective";
generator()->log()<<"\n\n The Effective Higgs model in Gosam is using mT=infinity";
generator()->log()<<"\n\n\n If you want to use the LO matrixelements of MadGraph with finite' topmass you need to add: ";
generator()->log()<<"\n\n set Madgraph:KeepInputTopMass True";
generator()->log()<<"\n\n to your input file.";
generator()->log()<<"\n---------------------------------------------------------------";
generator()->log()<<"\n---------------------------------------------------------------\n";
}
params<<"\n$MT$ 10000000." <<flush;
}else{
params<<"\n$MT$ " <<std::setiosflags(ios::scientific) << getParticleData(ParticleID::t)->hardProcessMass() /GeV <<flush;
}
params<<"\n$WT$ " <<std::setiosflags(ios::scientific) << getParticleData(ParticleID::t)->hardProcessWidth() /GeV <<flush;
params<<"\n$MB$ " <<std::setiosflags(ios::scientific) << getParticleData(ParticleID::b)->hardProcessMass() /GeV <<flush;
params<<"\n$MH$ " <<std::setiosflags(ios::scientific) << getParticleData(ParticleID::h0)->hardProcessMass() /GeV <<flush;
params<<"\n$WH$ " <<std::setiosflags(ios::scientific) << getParticleData(ParticleID::h0)->hardProcessWidth() /GeV <<flush;
params<<"\n$MTA$ " <<std::setiosflags(ios::scientific) << getParticleData(ParticleID::tauplus)->hardProcessMass() /GeV <<flush;
string cmd = "python " + bindir_ + "/mg2herwig ";
cmd +=" --buildpath "+mgProcLibPath();
cmd +=" --model "+theMGmodel;
cmd +=" --runpath "+factory()->runStorage()+"/MadGraphAmplitudes ";
cmd +=" --datadir "+pkgdatadir_;
cmd +=" --includedir "+includedir_;
std::stringstream as,aem;
as << factory()->orderInAlphaS();
cmd +=" --orderas "+as.str() ;
aem <<factory()->orderInAlphaEW();
cmd +=" --orderew "+aem.str();
// TODO move to boost::system
writeAmplitudesDat();
if (boost::filesystem::exists(mgProcLibPath()+"InterfaceMadGraph.so") ){
//set the parameters
checkAmplitudes();
std::system(cmd.c_str());
ranMadGraphInitializeExternal = true;
return true;
}
char cwd[1024];
if ( !getcwd(cwd,sizeof(cwd)) )
throw Exception() << "MadGraphAmplitude: failed to determine current working directory\n"
<< Exception::runerror;
cmd +=" --madgraph " + madgraphPrefix_ + "/bin " ;
cmd +="--build > ";
cmd += mgProcLibPath()+"MG.log 2>&1";
generator()->log() << "\n>>> Compiling MadGraph amplitudes. This may take some time -- please be patient.\n"
<< ">>> In case of problems see " << mgProcLibPath() << "MG.log for details.\n\n"
<< flush;
std::system(cmd.c_str());
cmd = "python " + bindir_ + "/mg2herwig ";
cmd +=" --buildpath "+mgProcLibPath();
cmd +=" --model "+theMGmodel;
cmd +=" --runpath "+factory()->runStorage()+"/MadGraphAmplitudes ";
cmd +=" --datadir "+pkgdatadir_;
as.clear();
aem.clear();
as << factory()->orderInAlphaS();
cmd +=" --orderas "+as.str() ;
aem <<factory()->orderInAlphaEW();
cmd +=" --orderew "+aem.str();
std::system(cmd.c_str());
ranMadGraphInitializeExternal = true;
return boost::filesystem::exists(mgProcLibPath()+"InterfaceMadGraph.so");
}
int MadGraphAmplitude::externalId(const cPDVector& proc) {
for (int i=0;i<100;i++){
colourindex.push_back(-2);
}
assert(!BornAmplitudes.empty()||!VirtAmplitudes.empty());
writeAmplitudesDat();
int res=0;
string amp="";
int k=0;
for (cPDVector::const_iterator it=proc.begin();it!=proc.end();it++,k++){
amp+=boost::lexical_cast<string>( (*it)->id())+" ";if (k==1)amp+=" > ";
}
string born= mgProcLibPath()+"BornAmplitudes.dat";
string virt= mgProcLibPath()+"VirtAmplitudes.dat";
assert ( boost::filesystem::exists(born)|| boost::filesystem::exists(virt));
ifstream borns(born.c_str());
string line;
while (std::getline(borns, line)) {
res+=1;
if(line==amp)return res;
}
ifstream virts(virt.c_str());
while (std::getline(virts, line)) {
res+=1;
if(line==amp)return res;
}
throw Exception() << "MadGraphAmplitude: One amplitude has no externalId. Please remove the MadGraphAmplitude-folder and rebuild.\n" << Exception::runerror;
return res;
}
bool MadGraphAmplitude::ranMadGraphInitializeExternal = false;
void MadGraphAmplitude::doinit() {
if ( !ranMadGraphInitializeExternal ) {
initializeExternal();
}
MatchboxAmplitude::doinit();
}
void MadGraphAmplitude::doinitrun() {
if ( !ranMadGraphInitializeExternal ) {
initializeExternal();
}
MatchboxAmplitude::doinitrun();
}
bool MadGraphAmplitude::canHandle(const PDVector& p,
Ptr<MatchboxFactory>::tptr factory,
bool virt) const {
if ( factory->processData()->diagramMap().find(p) !=
factory->processData()->diagramMap().end() )
return true;
vector<Ptr<Tree2toNDiagram>::ptr> diags =
factory->diagramGenerator()->generate(p,orderInGs(),orderInGem());
if ( diags.empty() )
return false;
factory->processData()->diagramMap()[p] = diags;
string amp="";
int k=0;
for (PDVector::const_iterator it=p.begin();it!=p.end();it++,k++){
amp+=boost::lexical_cast<string>( (*it)->id())+" ";if (k==1)amp+=" > ";
}
if (virt && factory->highestVirt()>=p.size()){
VirtAmplitudes.push_back(amp);
}else{
BornAmplitudes.push_back(amp);
}
return true;
}
void MadGraphAmplitude::prepareAmplitudes(Ptr<MatchboxMEBase>::tcptr me) {
useMe();
if ( !calculateTreeAmplitudes() ) {
MatchboxAmplitude::prepareAmplitudes(me);
return;
}
if (colourindex.empty()) {
for (int i=0;i<100;i++){
colourindex.push_back(-2);
}
}
lastMatchboxXComb()->clearheljamp();
lastMatchboxXComb()->clearhelLNjamp();
initProcess(mePartonData());
MatchboxAmplitude::prepareAmplitudes(me);
}
Complex MadGraphAmplitude::evaluate(size_t i, const vector<int>& hel, Complex& largeN) {
//find the colourline:
int ii = -1;
int xx=lastMatchboxXComb()->externalId();
if (colourindex.size()<=i) {
colourindex.clear();
for (size_t l=0;l<=i+10;l++){
colourindex.push_back(-2);
}
}
if(colourindex[i]!=-2){
ii = colourindex[i];
if (ii==-1) {
largeN = Complex(0.0);
return Complex(0.0);
}
} else {
set<vector<size_t> > a = colourOrdering(i);
int ncol=-1;
MG_NCol(&xx,&ncol);
assert(ncol!=-1);
for( int it = 0; it < ncol; it++ ){
int n = 0;
for ( cPDVector::const_iterator nx = mePartonData().begin();
nx != mePartonData().end(); nx++ )
if ( (*nx)->coloured() ) n++;
set<vector<size_t> > tmpset;
vector<size_t> tmpvek;
for ( int it2 = 0; it2 < n; it2++ ) {
int ret=-2;
MG_Colour(&xx,&it,&it2,&ret);
assert(ret !=-2);
if (ret== -1)
break;
if ( ret == 0 ) {
n++;
tmpset.insert(tmpvek);
tmpvek.clear();
} else {
tmpvek.push_back(ret-1);
}
if( it2 == n-1 ) tmpset.insert(tmpvek);
}
bool found_all = true;
for ( set<vector<size_t> >::iterator it3 = a.begin(); it3 != a.end(); it3++ ) {
bool found_it3=false;
for ( set<vector<size_t> >::iterator it4 = tmpset.begin(); it4 != tmpset.end(); it4++ ) {
vector<size_t> it3tmp = gluonsFirst(*it3);
vector<size_t> it4tmp = (*it4);
if ( it3tmp.size() != it4tmp.size() ) continue;
if ( it3tmp == it4tmp ) found_it3 = true;
}
found_all = found_all && found_it3;
}
if ( found_all ) {
colourindex[i]=it;
ii=it;
}
}
}
if ( ii == -1 ){
colourindex[i]=ii;
largeN = Complex(0.0);
return Complex(0.0);
}
const map<vector<int>,vector < complex<double> > >& tmp = lastMatchboxXComb()->heljamp();
const map<vector<int>,vector < complex<double> > >& tmpLN = lastMatchboxXComb()->helLNjamp();
if( tmp.find(hel) != tmp.end()) {
largeN = tmpLN.find(hel)->second[ii];
return tmp.find(hel)->second[ii];;
}
double units = pow(sqrt(lastSHat())/GeV,int(hel.size())-4);
int heltmp[10];
for(size_t j=0;j<hel.size();j++){
int cross=crossingMap()[j];
if( (cross>1&&j<=1)||(cross<=1&&j>1)){
heltmp[cross]=-1*hel[j];}
else{heltmp[cross]=hel[j];}
}
vector<Lorentz5Momentum> reshuffled = meMomenta();
if ( !reshuffleMasses().empty() && reshuffled.size() > 3 ) {
const cPDVector& pdata = mePartonData();
const map<long,Energy>& masses = reshuffleMasses();
lastMatchboxXComb()->reshuffle(reshuffled,pdata,masses);
}
double momenta[50];
size_t j=0;
for (size_t i=0;i<mePartonData().size();i++){
momenta[j]=abs(reshuffled[i].e()/GeV)<1.e-13?0.:double(reshuffled[i].e()/GeV);
momenta[j+1]=abs(reshuffled[i].x()/GeV)<1.e-13?0.:double(reshuffled[i].x()/GeV);
momenta[j+2]=abs(reshuffled[i].y()/GeV)<1.e-13?0.:double(reshuffled[i].y()/GeV);
momenta[j+3]=abs(reshuffled[i].z()/GeV)<1.e-13?0.:double(reshuffled[i].z()/GeV);
if(momenta[j ] == 0. && momenta[j+1] == 0. &&
momenta[j+2] == 0. && momenta[j+3] == 0. )
return 0.;
j+=4;
}
MG_Calculate_wavefunctions_born(&xx, &momenta[0], &heltmp[0]);
int ncol=-1;
MG_NCol(&xx,&ncol);
Complex res;
Complex resLN;
for( int it = 0; it < ncol; it++ ){
double dd[2];
MG_Jamp(&xx,&it,&dd[0]);
Complex d(dd[0],dd[1]);
if(it==ii)res=d*units;
lastMatchboxXComb()->pushheljamp(hel,d*units);
double ddLN[2];
MG_LNJamp(&xx,&it,&ddLN[0]);
Complex dLN(ddLN[0],ddLN[1]);
if(it==ii)resLN=dLN*units;
lastMatchboxXComb()->pushhelLNjamp(hel,dLN*units);
}
largeN = resLN;
return res;
}
vector<unsigned int> MadGraphAmplitude::physicalHelicities(const vector<int>& hel) const {
vector<unsigned int> res(hel.size(),0);
for ( size_t j = 0; j < hel.size(); ++j ) {
int cross = crossingMap()[j];
int xhel = 0;
if ( (cross > 1 && j <= 1) || (cross <= 1 && j > 1) )
xhel = -1*hel[j];
else
xhel = hel[j];
if ( mePartonData()[cross]->iSpin() == PDT::Spin1Half )
res[cross] = (xhel == -1 ? 0 : 1);
else if ( mePartonData()[cross]->iSpin() == PDT::Spin1 )
res[cross] = (unsigned int)(xhel + 1);
else if ( mePartonData()[cross]->iSpin() == PDT::Spin0 )
res[cross] = 0;
else assert(false);
}
return res;
}
LorentzVector<Complex> MadGraphAmplitude::plusPolarization(const Lorentz5Momentum& p,
const Lorentz5Momentum& n,
int i) const {
int tmp=i;
double pg[4],ng[4],poltmp[8];
pg[0]=p.e()/GeV;pg[1]=p.x()/GeV;pg[2]=p.y()/GeV;pg[3]=p.z()/GeV;
ng[0]=n.e()/GeV;ng[1]=n.x()/GeV;ng[2]=n.y()/GeV;ng[3]=n.z()/GeV;
MG_vxxxxx(&pg[0],&ng[0],&tmp,&poltmp[0]);
complex<double> pol[6];
pol[0]=Complex(poltmp[0],poltmp[1]);
pol[1]=Complex(poltmp[2],poltmp[3]);
pol[2]=Complex(poltmp[4],poltmp[5]);
pol[3]=Complex(poltmp[6],poltmp[7]);
LorentzVector<Complex> polarization(pol[1],pol[2],pol[3],pol[0]);
return polarization;
}
bool equalsModulo(unsigned int i, const vector<int>& a, const vector<int>& b) {
assert(a.size()==b.size());
if ( a[i] == b[i] )
return false;
for ( unsigned int k = 0; k < a.size(); ++k ) {
if ( k == i )
continue;
if ( a[k] != b[k] )
return false;
}
return true;
}
vector<size_t> MadGraphAmplitude::gluonsFirst(vector<size_t> vec) {
vector<size_t> vecout;
for(vector<size_t>::iterator it= vec.begin();it!= vec.end();++it)
if ( mePartonData()[crossingMap()[*it]]->id()==21)
vecout.push_back(crossingMap()[*it]);
for(vector<size_t>::iterator it= vec.begin();it!= vec.end();++it)
if ( mePartonData()[crossingMap()[*it]]->id()!=21)
vecout.push_back(crossingMap()[*it]);
return vecout;
}
double MadGraphAmplitude::spinColourCorrelatedME2(pair<int,int> ij,
const SpinCorrelationTensor& c) const {
vector<Lorentz5Momentum> reshuffled = meMomenta();
if ( !reshuffleMasses().empty() && reshuffled.size() > 3 ) {
const cPDVector& pdata = mePartonData();
const map<long,Energy>& masses = reshuffleMasses();
lastMatchboxXComb()->reshuffle(reshuffled,pdata,masses);
}
Lorentz5Momentum p = reshuffled[ij.first];
Lorentz5Momentum n = reshuffled[ij.second];
LorentzVector<Complex> polarization = plusPolarization(p,n,ij.first<2?-1:1);
int iCrossed = -1;
for ( unsigned int k = 0; k < crossingMap().size(); ++k )
if ( crossingMap()[k] == ij.first ) {
iCrossed = k;
break;
}
assert(iCrossed!=-1);
if(ij.first>1) polarization =polarization.conjugate();
if(iCrossed<2) polarization =polarization.conjugate();
Complex pFactor = (polarization*c.momentum())/sqrt(abs(c.scale()));
double avg =
colourCorrelatedME2(ij)*(-c.diagonal()+ (c.scale() > ZERO ? 1. : -1.)*norm(pFactor));
Complex csCorr = 0.0;
if ( calculateColourSpinCorrelator(ij) ) {
set<const CVector*> done;
for ( AmplitudeConstIterator a = lastAmplitudes().begin();
a != lastAmplitudes().end(); ++a ) {
if ( done.find(&(a->second)) != done.end() )
continue;
AmplitudeConstIterator b = lastAmplitudes().begin();
while ( !equalsModulo(iCrossed,a->first,b->first) )
if ( ++b == lastAmplitudes().end() )
break;
if ( b == lastAmplitudes().end() || done.find(&(b->second)) != done.end() )
continue;
done.insert(&(a->second)); done.insert(&(b->second));
if ( a->first[iCrossed] == 1 )
swap(a,b);
csCorr -= colourBasis()->colourCorrelatedInterference(ij,mePartonData(),a->second,b->second);
}
lastColourSpinCorrelator(ij,csCorr);
} else {
csCorr = lastColourSpinCorrelator(ij);
}
double corr =
2.*real(csCorr*sqr(pFactor));
double Nc = generator()->standardModel()->Nc();
double cfac = 1.;
if ( mePartonData()[ij.first]->iColour() == PDT::Colour8 ) {
cfac = Nc;
} else if ( mePartonData()[ij.first]->iColour() == PDT::Colour3 ||
mePartonData()[ij.first]->iColour() == PDT::Colour3bar ) {
cfac = (sqr(Nc)-1.)/(2.*Nc);
} else assert(false);
return
( avg +(c.scale() > ZERO ? 1. : -1.)*corr/cfac);
}
void MadGraphAmplitude::prepareOneLoopAmplitudes(Ptr<MatchboxMEBase>::tcptr ){
assert(false);
}
double MadGraphAmplitude::oneLoopInterference() const {
if ( !calculateOneLoopInterference() )
return lastOneLoopInterference();
evaloneLoopInterference();
return lastOneLoopInterference();
}
void MadGraphAmplitude::evaloneLoopInterference() const {
double units = pow(lastSHat()/GeV2,int(mePartonData().size())-4);
vector<Lorentz5Momentum> reshuffled = meMomenta();
if ( !reshuffleMasses().empty() && reshuffled.size() > 3 ) {
const cPDVector& pdata = mePartonData();
const map<long,Energy>& masses = reshuffleMasses();
lastMatchboxXComb()->reshuffle(reshuffled,pdata,masses);
}
double virt[20];
double momenta[50];
size_t j=0;
for (size_t i=0;i<mePartonData().size();i++){
momenta[j]=abs(reshuffled[i].e()/GeV)<1.e-13?0.:double(reshuffled[i].e()/GeV);
momenta[j+1]=abs(reshuffled[i].x()/GeV)<1.e-13?0.:double(reshuffled[i].x()/GeV);
momenta[j+2]=abs(reshuffled[i].y()/GeV)<1.e-13?0.:double(reshuffled[i].y()/GeV);
momenta[j+3]=abs(reshuffled[i].z()/GeV)<1.e-13?0.:double(reshuffled[i].z()/GeV);
j+=4;
}
int xx=lastMatchboxXComb()->externalId();
MG_Calculate_wavefunctions_virt(&xx,&momenta[0],&virt[0]);
double ifact = 1.;
ifact = 1./4.;
if (lastMatchboxXComb()->matchboxME()->mePartonData()[0]->iColour() == PDT::Colour3 ||
lastMatchboxXComb()->matchboxME()->mePartonData()[0]->iColour() == PDT::Colour3bar )
ifact /= SM().Nc();
else if ( lastMatchboxXComb()->matchboxME()->mePartonData()[0]->iColour() == PDT::Colour8 )
ifact /= (SM().Nc()*SM().Nc()-1.);
if ( lastMatchboxXComb()->matchboxME()->mePartonData()[1]->iColour() == PDT::Colour3 ||
lastMatchboxXComb()->matchboxME()->mePartonData()[1]->iColour() == PDT::Colour3bar )
ifact /= SM().Nc();
else if ( mePartonData()[1]->iColour() == PDT::Colour8 )
ifact /= (SM().Nc()*SM().Nc()-1.);
ifact *= lastMatchboxXComb()->matchboxME()->finalStateSymmetry();
lastOneLoopInterference(virt[1]/ifact*units);
lastOneLoopPoles(pair<double, double>(virt[2]/ifact*units,virt[3]/ifact*units));
}
void MadGraphAmplitude::persistentOutput(PersistentOStream & os) const {
os << theOrderInGs << theOrderInGem << BornAmplitudes << VirtAmplitudes
<< colourindex<<crossing << theProcessPath << theMGmodel << bindir_
<< pkgdatadir_ << madgraphPrefix_;
}
void MadGraphAmplitude::persistentInput(PersistentIStream & is, int) {
is >> theOrderInGs >> theOrderInGem >> BornAmplitudes >> VirtAmplitudes
>> colourindex>>crossing >> theProcessPath >> theMGmodel >> bindir_
>> pkgdatadir_ >> madgraphPrefix_;
}
// *** Attention *** The following static variable is needed for the type
// description system in ThePEG. Please check that the template arguments
// are correct (the class and its base class), and that the constructor
// arguments are correct (the class name and the name of the dynamically
// loadable library where the class implementation can be found).
DescribeClass<MadGraphAmplitude,MatchboxAmplitude>
describeHerwigMadGraphAmplitude("Herwig::MadGraphAmplitude", "HwMatchboxMadGraph.so");
void MadGraphAmplitude::Init() {
static ClassDocumentation<MadGraphAmplitude>
documentation("MadGraphAmplitude",
"Matrix elements have been calculated using MadGraph5 \\cite{Alwall:2011uj}",
"%\\cite{Alwall:2011uj}\n"
"\\bibitem{Alwall:2011uj}\n"
"J. Alwall et al.,\n"
"``MadGraph 5 : Going Beyond,''\n"
"arXiv:1106.0522 [hep-ph].\n"
"%%CITATION = ARXIV:1106.0522;%%");
static Parameter<MadGraphAmplitude,string> interfaceProcessPath
("ProcessPath",
"The Process Path.",
&MadGraphAmplitude::theProcessPath, "",false, false);
static Parameter<MadGraphAmplitude,string> interfaceModel
("Model",
"The MadGraph-Model.",
&MadGraphAmplitude::theMGmodel, "loop_sm",false, false);
static Switch<MadGraphAmplitude,bool> interfacekeepinputtopmass
("KeepInputTopMass",
"Switch On/Off formopt",
&MadGraphAmplitude::keepinputtopmass, false, false, false);
static SwitchOption interfacekeepinputtopmassTrue
(interfacekeepinputtopmass,
"On",
"On",
true);
static SwitchOption interfacekeepinputtopmassFalse
(interfacekeepinputtopmass,
"Off",
"Off",
false);
static Parameter<MadGraphAmplitude,string> interfaceBinDir
("BinDir",
"The location for the installed executable",
&MadGraphAmplitude::bindir_, string(HERWIG_BINDIR),
false, false);
static Parameter<MadGraphAmplitude,string> interfacePKGDATADIR
("DataDir",
"The location for the installed Herwig data files",
&MadGraphAmplitude::pkgdatadir_, string(HERWIG_PKGDATADIR),
false, false);
static Parameter<MadGraphAmplitude,string> interfaceMadgraphPrefix
("MadgraphPrefix",
"The prefix for the location of MadGraph",
&MadGraphAmplitude::madgraphPrefix_, string(MADGRAPH_PREFIX),
false, false);
}
diff --git a/MatrixElement/Matchbox/External/MadGraph/mg2herwig.py.in b/MatrixElement/Matchbox/External/MadGraph/mg2herwig.py.in
--- a/MatrixElement/Matchbox/External/MadGraph/mg2herwig.py.in
+++ b/MatrixElement/Matchbox/External/MadGraph/mg2herwig.py.in
@@ -1,376 +1,382 @@
#! /usr/bin/env python
import os,sys,glob,errno,shutil,time,fnmatch #argparse
from optparse import OptionParser
# helper to replace all sourceText in fileName with replaceText
def replacetext(fileName, sourceText, replaceText):
file = open(fileName, "r")
text = file.read()
file.close()
file = open(fileName, "w")
file.write(text.replace(sourceText, replaceText))
file.close()
# helper to build recursivly path
def mkdir_p(path):
try:
os.makedirs(path)
except OSError as exc: # Python >2.5
if exc.errno == errno.EEXIST and os.path.isdir(path):
pass
else: raise
# helper to find all files of with name in path
def find(name, path):
for root, dirs, files in os.walk(path):
if name in files:
return os.path.join(root, name)
# helper to find all file paths which contain file names matching filepattern
def finddirs(filepattern, path):
founddirs = []
for root, dirs, files in os.walk(path):
if fnmatch.filter(files, filepattern):
founddirs.append(root)
return founddirs
# fill the proc.dat file from BornAmplitudes.dat and VirtAmplitudes.dat.
def fillprocs(model,oras,orew):
bornlist=[]
virtlist=[]
fileproc=open("proc.dat","w")
fileproc.write("set fortran_compiler @FC@ --no_save\n")
fileproc.write("import model "+model+"\n")
borns="BornAmplitudes.dat"
virts="VirtAmplitudes.dat"
first=True
procnr=0
virtlines=""
bornlines=""
minlegs=100
legs=0
for i in [borns, virts]:
file = open(i, "r")
for line in file:
if (len(line.split(" "))<minlegs):
minlegs=len(line.split(" "))
for it in line.split(" "):
if it.replace("-","").isdigit():
legs+=1
file.close()
#conversion for heft model to go from (2QCD+1QED)->1HIG for each FS HIGGS.
HIG=0
if (model=="heft"):
HIG=(int(oras)+int(orew)-legs+2)/2
if (int(oras)+int(orew)-legs+2)%2!=0:
print "Warning: No possible coupling power:(int(oras)+int(orew)-legs+2)%2!=0 "
exit()
return
file = open(borns, "r")
for line in file:
#this assumes extra QCD emmissions
addalphas=len(line.split(" "))-minlegs
linetmp=line.rstrip()
procnr+=1
bornlist+=[str(procnr)]
if first:
if HIG ==0 :
bornlines+="generate "+linetmp+" QCD="+str(int(oras)+addalphas)+" QED="+str(orew)+" @"+str(procnr)+"\n"
else:
bornlines+="generate "+linetmp+" HIG="+str(HIG)+" QCD="+str(int(oras)+addalphas-2*HIG)+" QED="+str(int(orew)-HIG)+" @"+str(procnr)+"\n"
first=False
else:
if HIG ==0 :
bornlines+="add process "+linetmp+" QCD="+str(int(oras)+addalphas)+" QED="+str(orew)+" @"+str(procnr)+"\n"
else:
bornlines+="add process "+linetmp+" HIG="+str(HIG)+" QCD="+str(int(oras)+addalphas-2*HIG)+" QED="+str(int(orew)-HIG)+" @"+str(procnr)+"\n"
file.close()
first=True
file = open(virts, "r")
for line in file:
addalphas=len(line.split(" "))-minlegs
- linetmp=line.rstrip()+" QED="+str(int(orew))+" [ virt=QCD ]"
+ linetmp=line.rstrip()+" QCD="+str(int(oras)+addalphas)+" QED="+str(int(orew))+" [ virt=QCD ]"
procnr+=1
virtlist+=[str(procnr)]
if first:
virtlines+="generate "+linetmp+" @"+str(procnr)+"\n"
first=False
else:
virtlines+="add process "+linetmp+" @"+str(procnr)+"\n"
file.close()
fileproc.write(bornlines)
if virtlines!="" and bornlines!="":
fileproc.write("output matchbox MG5 --postpone_model\n")
fileproc.write(virtlines)
fileproc.write("output matchbox MG5 -f\n")
fileproc.close()
return bornlist,virtlist
def build_matchbox_tmp(pwd,buildpath):
cwd=os.getcwd()
os.chdir(pwd)
mkdir_p(pwd+"/Herwig-scratch/MG_tmp/")
if not buildpath.startswith("/"):
buildpath=pwd+"/"+buildpath.lstrip("./")
resources=glob.glob(buildpath +"/MG5/SubProcesses/MadLoop5_resources/*")
resources+=glob.glob(buildpath +"/MG5/Cards/*")
resources+=glob.glob(buildpath +"/MG5/Cards/SubProcesses/*")
for i in resources:
if not os.path.isfile( pwd+"/Herwig-scratch/MG_tmp/"+os.path.basename(i)) \
and not os.path.islink( pwd+"/Herwig-scratch/MG_tmp/"+os.path.basename(i)):
os.symlink(i, pwd+"/Herwig-scratch/MG_tmp/"+os.path.basename(i))
os.chdir(cwd)
parser = OptionParser()
parser.add_option("-a", "--buildpath", dest="buildpath",help="Do not use this script. Only for Herwig internal use. ")
parser.add_option("-b", "--build", action="store_true", dest="build", default=True,help="Do not use this script. Only for Herwig internal use.")
parser.add_option("-c", "--madgraph", dest="madgraph",help="Do not use this script. Only for Herwig internal use.")
parser.add_option("-d", "--runpath", dest="runpath",help="Do not use this script. Only for Herwig internal use.")
parser.add_option("-e", "--model", dest="model",help="Do not use this script. Only for Herwig internal use.")
parser.add_option("-f", "--orderas", dest="orderas",help="Do not use this script. Only for Herwig internal use.")
parser.add_option("-g", "--orderew", dest="orderew",help="Do not use this script. Only for Herwig internal use.")
parser.add_option("-i", "--datadir",dest="datadir",help="Do not use this script. Only for Herwig internal use.")
parser.add_option("-I", "--includedir",dest="includedir",help="Do not use this script. Only for Herwig internal use.")
(options, args) = parser.parse_args()
#parser = argparse.ArgumentParser()
#parser.add_argument('--buildpath', help='installpath')
#parser.add_argument('--build', help='build', action="store_true")
#parser.add_argument('--madgraph', help='madgraph_installpath')
#parser.add_argument('--runpath', help='runpath')
#parser.add_argument('--model', help='model')
#parser.add_argument('--orderas', help='orderas')
#parser.add_argument('--orderew', help='orderew')
#parser.add_argument('--datadir', help='datadir')
#args = parser.parse_args()
pwd=os.getcwd()
param_card=""
mkdir_p(pwd+"/Herwig-scratch/MG_tmp/")
if options.model=="loop_sm" or options.model=="heft":
if options.model=="loop_sm":
param_card="param_card.dat"
else:
param_card="param_card_"+options.model+".dat"
file = open("%s/MadGraphInterface/%s.in" % (options.datadir,param_card) , "r")
paramcard = file.read()
file.close()
file = open(options.runpath+"/"+param_card, "w")
params=open(options.runpath+"/MG-Parameter.dat", "r")
for line in params:
a=line.split()
paramcard=paramcard.replace(a[0],a[1])
params.close()
file.write(paramcard)
file.close()
+elif options.model.startswith("/"):
+
+ os.system("python %s/write_param_card.py " % options.model)
+
+
+
else:
print "---------------------------------------------------------------"
print "---------------------------------------------------------------"
print "Warning: The model set for the MadGraph Interface "
print " needs a parameter setting by hand."
print " Please fill the param_card_"+options.model+".dat"
print " with your favourite assumptions."
print " And make sure Herwig uses the same parameters."
print "---------------------------------------------------------------"
print "---------------------------------------------------------------"
if os.path.isfile(options.buildpath +"/MG5/Cards/param_card.dat") and not os.path.isfile(options.runpath+"/"+"param_card_"+options.model+".dat"):
shutil.copyfile(options.buildpath +"/MG5/Cards/param_card.dat", options.runpath+"/"+"param_card_"+options.model+".dat")
time.sleep(1)
if not os.path.isdir(options.buildpath):
print "The MadGraph Install path was not existend. It has been created for you."
print "Just start Herwig read again.."
mkdir_p(options.buildpath)
exit()
os.chdir(options.buildpath)
if os.path.isfile("InterfaceMadGraph.so"):
build_matchbox_tmp(pwd,options.buildpath)
exit()
Bornlist,Virtlist=fillprocs(options.model,options.orderas,options.orderew)
if not options.madgraph and not os.path.isfile("InterfaceMadGraph.so"):
print "*** warning *** MadGraph build failed, check logfile for details"
exit()
os.system("python "+options.madgraph+"/mg5_aMC proc.dat")
routines=[["","BORN(momenta,hel)"],
["","SLOOPMATRIX(momenta,virt)"],
["","GET_JAMP(color,Jamp)"],
["","GET_LNJAMP(color,Jamp)"],
["","GET_NCOL(color)"],
["","GET_NCOLOR(i,j,color)"]]
for routine in routines:
for i in Bornlist + list(set(Virtlist) - set(Bornlist)):
if routine[1]=="Virt(amp)" or routine[1]=="SLOOPMATRIX(momenta,virt)" and i not in Virtlist:
continue
if routine[0]=="":
routine[0]+=" SELECT CASE (proc) \n"
routine[0]+=" CASE("+i+") \n CALL "
routine[0]+= "MG5_"+i+"_"+routine[1]+"\n"
else:
routine[0]+=" CASE("+i+") \n"\
" CALL "
routine[0]+= "MG5_"+i+"_"+routine[1]+"\n"
if routine[0]!="":
routine[0]+=" CASE DEFAULT\n"
routine[0]+=" WRITE(*,*) '##W02A WARNING No id found '\n"
routine[0]+=" END SELECT \n"
shutil.copyfile("%s/MadGraphInterface/InterfaceMadGraph.f.in" % options.datadir, "InterfaceMadGraph.f")
replacetext("InterfaceMadGraph.f","MG_CalculateBORNtxt",routines[0][0])
replacetext("InterfaceMadGraph.f","MG_CalculateVIRTtxt",routines[1][0])
replacetext("InterfaceMadGraph.f","MG_Jamptxt", routines[2][0])
replacetext("InterfaceMadGraph.f","MG_LNJamptxt", routines[3][0])
replacetext("InterfaceMadGraph.f","MG_NColtxt", routines[4][0])
replacetext("InterfaceMadGraph.f","MG_ColourMattxt",routines[5][0])
MG_vxxxxxtxt=""
if routines[1][0]!="":
MG_vxxxxxtxt=""" subroutine MG_vxxxxx(p, n,inc,VC)
$ bind(c, name='MG_vxxxxx')
IMPLICIT NONE
double precision p(0:3)
double precision n(0:3)
INTEGER inc
double precision VC(0:7)
double complex VCtmp(8)
call vxxxxx(p, 0d0,1,inc ,VCtmp)
VC(0)= real(VCtmp(5))
VC(1)=aimag(VCtmp(5))
VC(2)= real(VCtmp(6))
VC(3)=aimag(VCtmp(6))
VC(4)= real(VCtmp(7))
VC(5)=aimag(VCtmp(7))
VC(6)= real(VCtmp(8))
VC(7)=aimag(VCtmp(8))
END"""
else:
MG_vxxxxxtxt=""" subroutine MG_vxxxxx(p, n,inc,VC)
$ bind(c, name='MG_vxxxxx')
IMPLICIT NONE
double precision p(0:3)
double precision n(0:3)
INTEGER inc
double precision VC(0:7)
double complex VCtmp(6)
call vxxxxx(p, 0d0,1,inc ,VCtmp)
VC(0)= real(VCtmp(3))
VC(1)=aimag(VCtmp(3))
VC(2)= real(VCtmp(4))
VC(3)=aimag(VCtmp(4))
VC(4)= real(VCtmp(5))
VC(5)=aimag(VCtmp(5))
VC(6)= real(VCtmp(6))
VC(7)=aimag(VCtmp(6))
END"""
replacetext("InterfaceMadGraph.f","MG_vxxxxxtxt",MG_vxxxxxtxt)
make=" "
fortanfiles=glob.glob('*/*/*.f')+glob.glob('*/*/*/*.f')
for i in fortanfiles:
if "check_sa" not in i:
if not os.path.islink(i):
make += " "+i+"\\\n "
incfiles=glob.glob('*/*/*.inc')+glob.glob('*/*/*/*.inc')
coefdir=""
for i in incfiles:
if "nexternal.inc" in i:
coefdir+=" -I"+i.replace("nexternal.inc"," ")
file=open("makefile","w")
file.write("include MG5/Source/make_opts ")
if Virtlist!=[]:
file.write("\nLIBDIR = MG5/lib\nLINKLIBS = -L$(LIBDIR) -lcts -liregi -L$(LIBDIR)/golem95_lib -lgolem")
file.write("\nLIBS = $(LIBDIR)libcts.$(libext) $(LIBDIR)libgolem.$(libext) $(LIBDIR)libiregi.$(libext)")
file.write("\nPROCESS= InterfaceMadGraph.f "+make+"\n\nall: \n\t @FC@ @FFLAGS@ -w -fbounds-check -ffixed-line-length-132 -fPIC -fno-f2c -shared -s -o InterfaceMadGraph.so -IMG5/SubProcesses/" )
if Virtlist!=[]:
file.write(" -IMG5/lib/golem95_include ")
# Find all .mod files also in /usr/include if golem was build there.
# There can be an error message in the MadGraph output to add the golem include path to the makefiles.
# Usually MadGraph finds the path if its Golem was build in an separate dictionary.
# Our bootstrap script installs golem with gosam beside boost. Here MadGraph creates a link (->errormessage).
# If we can find the modfiles easily the user doesn't need to change the makefiles.
moddirs=finddirs('*.mod',options.includedir)
for moddir in moddirs:
file.write(" -I%s " % moddir)
if os.path.isdir("/usr/include"):
moddirs=finddirs('*.mod',"/usr/include")
for moddir in moddirs:
file.write(" -I%s " % moddir)
if coefdir != "":
file.write(coefdir)
file.write(" $(PROCESS) $(LINKLIBS) ")
file.close()
os.chdir(pwd)
os.chdir(options.buildpath)
replacetext("MG5/Source/MODEL/lha_read.f", "ident_card.dat","Herwig-scratch/MG_tmp/ident_card.dat")
replacetext("MG5/Source/MODEL/lha_read.f", "param.log","Herwig-scratch/MG_tmp/param.log")
if Virtlist!=[]:
replacetext("MG5/SubProcesses/MadLoopCommons.f", "PREFIX='./'","PREFIX='./Herwig-scratch/MG_tmp/'")
os.system("make")
build_matchbox_tmp(pwd,options.buildpath)
diff --git a/MatrixElement/Matchbox/Scales/MatchboxScale.cc.in b/MatrixElement/Matchbox/Scales/MatchboxScale.cc.in
--- a/MatrixElement/Matchbox/Scales/MatchboxScale.cc.in
+++ b/MatrixElement/Matchbox/Scales/MatchboxScale.cc.in
@@ -1,172 +1,183 @@
// -*- C++ -*-
//
// MatchboxScale.cc is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2012 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 MatchboxScale class.
//
#include "MatchboxScale.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/Repository/Repository.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Interface/Command.h"
#include "ThePEG/Utilities/DynamicLoader.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace Herwig;
//external function which will be filled in doFunktion(..)
Energy2 renScale(vector<Lorentz5Momentum> jet, vector<Lorentz5Momentum> lepton, vector<Lorentz5Momentum> boson);
MatchboxScale::MatchboxScale()
{}
MatchboxScale::~MatchboxScale() {}
IBPtr MatchboxScale::clone() const {
return new_ptr(*this);
}
IBPtr MatchboxScale::fullclone() const {
return new_ptr(*this);
}
string MatchboxScale::doFunction(string in) {
string cmd = "Makefile";
ofstream makeFile(cmd.c_str());
cmd = "Scale.cc";
ofstream scaleFile(cmd.c_str());
scaleFile<< "#include \"Herwig/MatrixElement/Matchbox/Scales/MatchboxScale.h\"\n" ;
scaleFile<< "using namespace Herwig ;\n" ;
scaleFile<< "Energy2 renScale(vector<Lorentz5Momentum> jet, vector<Lorentz5Momentum> lepton, vector<Lorentz5Momentum> boson){\n" ;
scaleFile<< "return \n"<< in.c_str();
scaleFile<< ";}\n" ;
scaleFile<< flush ;
makeFile<< "THEPEG=@THEPEGPATH@\n" ;
makeFile<< "HERWIG=@prefix@\n" ;
makeFile<< "INCLUDE=-I $(THEPEG)/include -I $(HERWIG)/include\n" ;
makeFile<< "LIBPATH=@THEPEGLDFLAGS@\n" ;
+ makeFile<< "SHARED_FLAG=@SHARED_FLAG@ @APPLE_DSO_FLAGS@ \n";
makeFile<< "all: \n" ;
- makeFile<< "\tg++ --shared -g3 -fPIC -o "<<scalePath<<"Scale.so $(INCLUDE) $(LIBPATH) @THEPEGLIB@ Scale.cc\n" ;
+ makeFile<< "\tg++ $(SHARED_FLAG) -g3 -fPIC -o "<<scalePath<<"Scale.so $(INCLUDE) $(LIBPATH) @THEPEGLIB@ Scale.cc\n" ;
makeFile<< flush ;
cmd = "make";
int st = std::system(cmd.c_str());
Repository::clog() << "scale compilation returned " << st << "\n";
return "";
}
+struct PtLargerMB {
+ inline bool operator()(const LorentzMomentum& a,
+ const LorentzMomentum& b) const {
+ return a.perp() > b.perp();
+ }
+};
+
+
bool loadlib=false;
Energy2 MatchboxScale::renormalizationScale() const {
tcPDVector pd (mePartonData().begin() + 2, mePartonData().end());
vector<LorentzMomentum> p (meMomenta().begin() + 2, meMomenta().end());
tcPDPtr t1 = mePartonData()[0];
tcPDPtr t2 = mePartonData()[1];
tcCutsPtr cuts = lastCutsPtr();
theJetFinder->cluster(pd, p, cuts, t1, t2);
vector<Lorentz5Momentum> jet;
vector<Lorentz5Momentum> lepton;
vector<Lorentz5Momentum> boson;
-
-
tcPDVector::const_iterator itpd = pd.begin();
for (vector<LorentzMomentum>::const_iterator itp = p.begin() ;
itp != p.end(); ++itp, ++itpd ) {
if ( (**itpd).coloured() ) {
jet.push_back(*itp);
}
if ( abs((**itpd).id())>=22&&abs((**itpd).id())<=25 ) {
boson.push_back(*itp);
}
if ( abs((**itpd).id())> 10&&abs((**itpd).id())< 17 ) {
lepton.push_back(*itp);
}
}
+
+ std::sort(jet.begin(),jet.end(),PtLargerMB());
+
+
if (!loadlib)
- if ( !DynamicLoader::load(scalePath+"/Scale.so") ) assert(0);
+ if ( !DynamicLoader::load(scalePath+"Scale.so") ) assert(0);
return renScale(jet,lepton,boson);
}
Energy2 MatchboxScale::factorizationScale() const {
return renormalizationScale();
}
// If needed, insert default implementations of virtual function defined
// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs).
void MatchboxScale::persistentOutput(PersistentOStream & os) const {
os << theJetFinder << scalePath;
}
void MatchboxScale::persistentInput(PersistentIStream & is, int) {
is >> theJetFinder >> scalePath ;
}
// *** Attention *** The following static variable is needed for the type
// description system in ThePEG. Please check that the template arguments
// are correct (the class and its base class), and that the constructor
// arguments are correct (the class name and the name of the dynamically
// loadable library where the class implementation can be found).
DescribeClass<MatchboxScale,MatchboxScaleChoice>
describeHerwigMatchboxScale("Herwig::MatchboxScale", "HwMatchboxScales.so");
void MatchboxScale::Init() {
static ClassDocumentation<MatchboxScale> documentation
("MatchboxScale implements scale choices related to transverse momenta.");
static Reference<MatchboxScale,JetFinder> interfaceJetFinder
("JetFinder",
"A reference to the jet finder.",
&MatchboxScale::theJetFinder, false, false, true, false, false);
static Command<MatchboxScale> interfaceFunction
("Function",
"Set the scale function.",
&MatchboxScale::doFunction, false);
static Parameter<MatchboxScale,string> interfaceScalePath
("ScalePath",
"Prefix for the scalepath.",
&MatchboxScale::scalePath, "",
false, false);
}
diff --git a/Models/Feynrules/python/ufo2herwig b/Models/Feynrules/python/ufo2herwig
--- a/Models/Feynrules/python/ufo2herwig
+++ b/Models/Feynrules/python/ufo2herwig
@@ -1,667 +1,702 @@
#! /usr/bin/env python
from __future__ import division
import os, sys, pprint, argparse, re
from string import strip, Template
# add path to the ufo conversion modules
modulepath = os.path.join("@PKGLIBDIR@",'python')
sys.path.append(modulepath)
from ufo2peg import *
# set up the option parser for command line input
parser = argparse.ArgumentParser(
description='Create Herwig model files from Feynrules UFO input.'
)
parser.add_argument(
'ufodir',
metavar='UFO_directory',
help='the UFO model directory'
)
parser.add_argument(
'-v', '--verbose',
action="store_true",
help="print verbose output"
)
parser.add_argument(
'-n','--name',
default="FRModel",
help="set custom nametag for the model"
)
parser.add_argument(
'--ignore-skipped',
action="store_true",
help="ignore skipped vertices and produce output anyway"
)
parser.add_argument(
'--split-model',
action="store_true",
help="Split the model file into pieces to improve compilation for models with many parameters"
)
parser.add_argument(
'--no-generic-loop-vertices',
action="store_true",
help="Don't include the automatically generated generic loop vertices for h->gg and h->gamma gamma"
)
vertex_skipped = False
args = parser.parse_args()
def should_print():
return not vertex_skipped or args.ignore_skipped
import imp
path,mod = os.path.split(os.path.abspath(args.ufodir))
FR = imp.load_module(mod,*imp.find_module(mod,[path]))
##################################################
##################################################
# get the Model name from the arguments
modelname = args.name
libname = modelname + '.so'
# define arrays and variables
#allplist = ""
parmdecls = []
parmgetters = []
parmconstr = []
doinit = []
paramstoreplace_ = []
paramstoreplace_expressions_ = []
# get external parameters for printing
parmsubs = dict( [ (p.name, p.value)
for p in FR.all_parameters
if p.nature == 'external' ] )
# evaluate python cmath
def evaluate(x):
import cmath
return eval(x,
{'cmath':cmath,
'complexconjugate':FR.function_library.complexconjugate},
parmsubs)
## get internal params into arrays
internal = ( p for p in FR.all_parameters
if p.nature == 'internal' )
#paramstoreplaceEW_ = []
#paramstoreplaceEW_expressions_ = []
# calculate internal parameters
for p in internal:
parmsubs.update( { p.name : evaluate(p.value) } )
# if 'aS' in p.value and p.name != 'aS':
# paramstoreplace_.append(p.name)
# paramstoreplace_expressions_.append(p.value)
# if 'aEWM1' in p.value and p.name != 'aEWM1':
# paramstoreplaceEW_.append(p.name)
# paramstoreplaceEW_expressions_.append(p.value)
# more arrays used for substitution in templates
paramsforstream = []
parmmodelconstr = []
# loop over parameters and fill in template stuff according to internal/external and complex/real
# WARNING: Complex external parameter input not tested!
if args.verbose:
print 'verbose mode on: printing all parameters'
print '-'*60
paramsstuff = ('name', 'expression', 'default value', 'nature')
pprint.pprint(paramsstuff)
interfacedecl_T = """\
static Parameter<{modelname}, {type}> interface{pname}
("{pname}",
"The interface for parameter {pname}",
&{modelname}::{pname}_, {value}, 0, 0,
false, false, Interface::nolimits);
"""
+massnames = {}
+widthnames = {}
+
+for particle in FR.all_particles:
+ if particle.mass != 'ZERO':
+ massnames[particle.mass] = abs(particle.pdg_code)
+
+ if particle.width != 'ZERO':
+ widthnames[particle.width] = abs(particle.pdg_code)
+
interfaceDecls = []
modelparameters = {}
for p in FR.all_parameters:
value = parmsubs[p.name]
if p.type == 'real':
assert( value.imag < 1.0e-16 )
value = value.real
if p.nature == 'external':
- interfaceDecls.append(
- interfacedecl_T.format(modelname=modelname,
- pname=p.name,
- value=value,
- type=typemap(p.type))
- )
+ if p.name not in massnames and p.name not in widthnames:
+ interfaceDecls.append(
+ interfacedecl_T.format(modelname=modelname,
+ pname=p.name,
+ value=value,
+ type=typemap(p.type))
+ )
+ else:
+ interfaceDecls.append('\n// no interface for %s. Use particle definition instead.\n' % p.name)
if hasattr(p,'lhablock'):
lhalabel = '{lhablock}_{lhacode}'.format( lhablock=p.lhablock, lhacode='_'.join(map(str,p.lhacode)) )
- parmmodelconstr.append('set %s:%s ${%s}' % (modelname, p.name, lhalabel))
+ if p.name not in massnames and p.name not in widthnames:
+ parmmodelconstr.append('set %s:%s ${%s}' % (modelname, p.name, lhalabel))
+ else:
+ parmmodelconstr.append('# %s is taken from the particle setup' % p.name)
modelparameters[lhalabel] = value
parmsubs[p.name] = lhalabel
else:
- parmmodelconstr.append('set %s:%s %s' % (modelname, p.name, value))
+ if p.name not in massnames and p.name not in widthnames:
+ parmmodelconstr.append('set %s:%s %s' % (modelname, p.name, value))
+ else:
+ parmmodelconstr.append('# %s is taken from the particle setup' % p.name)
parmsubs[p.name] = value
- parmconstr.append('%s_(%s)' % (p.name, value))
+ if p.name not in massnames and p.name not in widthnames:
+ parmconstr.append('%s_(%s)' % (p.name, value))
+ else:
+ parmconstr.append('%s_()' % p.name)
else :
parmconstr.append('%s_()' % p.name)
parmsubs[p.name] = value
elif p.type == 'complex':
value = complex(value)
if p.nature == 'external':
#
# TODO: WE DO NOT HAVE COMPLEX INTERFACES IN THEPEG (yet?)
#
# interfaceDecls.append(
# interfacedecl_T.format(modelname=modelname,
# pname=p.name,
# value='Complex(%s,%s)'%(value.real,value.imag),
# type=typemap(p.type))
# )
#
# parmmodelconstr.append('set %s:%s (%s,%s)' % (modelname, p.name, value.real, value.imag))
parmconstr.append('%s_(%s,%s)' % (p.name, value.real, value.imag))
else :
parmconstr.append('%s_(%s,%s)' % (p.name, 0.,0.))
parmsubs[p.name] = value
else:
raise Exception('Unknown data type "%s".' % p.type)
parmdecls.append(' %s %s_;' % (typemap(p.type), p.name))
parmgetters.append(' %s %s() const { return %s_; }' % (typemap(p.type),p.name, p.name))
paramsforstream.append('%s_' % p.name)
expression, symbols = 'return %s_' % p.name, None
if p.nature != 'external':
expression, symbols = py2cpp(p.value)
text = add_brackets(expression, symbols)
text=text.replace('()()','()')
- #parmgetters.append(' %s %s() const { return %s; }' % (typemap(p.type),p.name, text))
doinit.append(' %s_ = %s;' % (p.name, text) )
+ if p.name in massnames:
+ doinit.append(' getParticleData(%s)->mass(%s_ * GeV);' % (massnames[p.name], p.name) )
+ elif p.name in widthnames:
+ doinit.append(' getParticleData(%s)->width(%s_ * GeV);' % (widthnames[p.name], p.name) )
+ doinit.append(' getParticleData(%s)->cTau (%s_ == 0.0 ? ZERO : hbarc/(%s_*GeV));' % (widthnames[p.name], p.name, p.name) )
+ doinit.append(' getParticleData(%s)->widthCut(10. * %s_ * GeV);' % (widthnames[p.name], p.name) )
+
+
+ elif p.nature == 'external':
+ if p.name in massnames:
+ doinit.append(' %s_ = getParticleData(%s)->mass() / GeV;' % (p.name, massnames[p.name]) )
+ elif p.name in widthnames:
+ doinit.append(' %s_ = getParticleData(%s)->width() / GeV;' % (p.name, widthnames[p.name]) )
+
+ if args.verbose:
+ pprint.pprint((p.name,p.value, value, p.nature))
+
+pcwriter = ParamCardWriter(FR.all_parameters)
+paramcard_output = '\n'.join(pcwriter.output)
### special treatment
# if p.name == 'aS':
# expression = '0.25 * sqr(strongCoupling(q2)) / Constants::pi'
# elif p.name == 'aEWM1':
# expression = '4.0 * Constants::pi / sqr(electroMagneticCoupling(q2))'
# elif p.name == 'Gf':
# expression = 'generator()->standardModel()->fermiConstant() * GeV2'
-# elif p.name == 'MZ':
-# expression = 'getParticleData(ThePEG::ParticleID::Z0)->mass() / GeV'
-
-
- if args.verbose:
- pprint.pprint((p.name,p.value, value, p.nature))
paramconstructor=': '
for ncount in range(0,len(parmconstr)) :
paramconstructor += parmconstr[ncount]
if(ncount != len(parmconstr) -1) :
paramconstructor += ','
if(ncount%5 == 0 ) :
paramconstructor += "\n"
paramout=""
paramin =""
for ncount in range(0,len(paramsforstream)) :
if(ncount !=0 ) :
paramout += "<< " + paramsforstream[ncount]
paramin += ">> " + paramsforstream[ncount]
else :
paramout += paramsforstream[ncount]
paramin += paramsforstream[ncount]
if(ncount%5 == 0 ) :
paramout += "\n"
paramin += "\n"
parmtextsubs = { 'parmgetters' : '\n'.join(parmgetters),
'parmdecls' : '\n'.join(parmdecls),
'parmconstr' : paramconstructor,
'getters' : '',
'decls' : '',
'addVertex' : '',
'doinit' : '\n'.join(doinit),
'ostream' : paramout,
'istream' : paramin ,
'refs' : '',
'parmextinter': ''.join(interfaceDecls),
'ModelName': modelname,
- 'calcfunctions': ''
+ 'calcfunctions': '',
+ 'param_card_data': paramcard_output
}
##################################################
##################################################
##################################################
# get vertex template
VERTEX = getTemplate('Vertex.cc')
VERTEXCLASS = getTemplate('Vertex_class')
VERTEXHEADER = """\
#include "ThePEG/Helicity/Vertex/{spindirectory}/{lorentztag}Vertex.h"
"""
def write_vertex_file(subs):
newname = '%s_Vertices_%03d.cc' % (subs['ModelName'],subs['vertexnumber'])
writeFile( newname, VERTEX.substitute(subs) )
if args.verbose:
print 'verbose mode on: printing all vertices'
print '-'*60
labels = ('vertex', 'particles', 'Lorentz', 'C_L', 'C_R', 'norm')
pprint.pprint(labels)
### initial pass to find global sign
def global_sign():
return 1.0
for v in FR.all_vertices:
pids = sorted([ p.pdg_code for p in v.particles ])
if pids != [-11,11,22]: continue
coup = v.couplings
assert( len(coup) == 1 )
val = coup.values()[0].value
val = evaluate(val)
assert( val.real == 0 )
return 1 if val.imag > 0 else -1
vertexclasses, vertexheaders = [], set()
ONE_EACH = True
if ONE_EACH:
all_vertices = FR.all_vertices
else:
all_vertices = collapse_vertices(FR.all_vertices)
globalsign = global_sign()
for vertexnumber,vertex in enumerate(all_vertices,1):
lorentztag = unique_lorentztag(vertex)
vertex.herwig_skip_vertex = False
# remove vertices involving ghost fields
if 'U' in lorentztag:
vertex.herwig_skip_vertex = True
continue
gsnames = ['goldstone',
'goldstoneboson',
'GoldstoneBoson']
for p in vertex.particles:
def gstest(name):
try:
return getattr(p,name)
except AttributeError:
return False
if any(map(gstest, gsnames)):
vertex.herwig_skip_vertex = True
break
if vertex.herwig_skip_vertex:
continue
lfactors = {
'FFV' : '-complex(0,1)', # ok
'VVV' : 'complex(0,1)', # changed to fix ttbar
'VVVV' : 'complex(0,1)',
'VVS' : '-complex(0,1)',
'VSS' : '-complex(0,1)', # changed to minus to fix dL ->x1 W- d
'SSS' : '-complex(0,1)', # ok
'VVSS' : '-complex(0,1)', # ok
'VVT' : 'complex(0,2)',
'VVVT' : '-complex(0,2)',
'SSSS' : '-complex(0,1)', # ok
'FFS' : '-complex(0,1)', # ok
'SST' : 'complex(0,2)',
'FFT' : '-complex(0,8)',
'FFVT' : '-complex(0,4)',
}
try:
lf = lfactors[lorentztag]
except KeyError:
msg = 'Warning: Lorentz structure {tag} ( {ps} ) in {name} ' \
'is not supported.\n'.format(tag=lorentztag, name=vertex.name,
ps=' '.join(map(str,vertex.particles)))
sys.stderr.write(msg)
vertex.herwig_skip_vertex = True
vertex_skipped = True
continue
### Particle ids
if ONE_EACH:
plistarray = [ ','.join([ str(p.pdg_code) for p in vertex.particles ]) ]
else:
plistarray = [ ','.join([ str(p.pdg_code) for p in pl ])
for pl in vertex.particles_list ]
try:
L,pos = colors(vertex)
cf = colorfactor(vertex,L,pos)
except SkipThisVertex:
vertex.herwig_skip_vertex = True
vertex_skipped = True
continue
### classname
classname = 'V_%s' % vertex.name
### parse couplings
unique_qcd = CheckUnique()
unique_qed = CheckUnique()
coup_left = []
coup_right = []
coup_norm = []
if ONE_EACH:
items = vertex.couplings.iteritems()
else:
items = vertex.couplings
try:
for (color_idx,lorentz_idx),coupling in items:
qcd, qed = qcd_qed_orders(vertex, coupling)
unique_qcd( qcd )
unique_qed( qed )
L = vertex.lorentz[lorentz_idx]
prefactors = '(%s) * (%s) * (%s)' \
% (globalsign**(len(lorentztag)-2),lf,cf[color_idx])
ordering = ''
if lorentztag in ['FFS','FFV']:
left,right = parse_lorentz(L.structure)
if left:
coup_left.append('(%s) * (%s) * (%s)' % (prefactors,left,coupling.value))
if right:
coup_right.append('(%s) * (%s) * (%s)' % (prefactors,right,coupling.value))
if lorentztag == 'FFV':
ordering = ('if(p1->id()!=%s) {Complex ltemp=left(), rtemp=right(); left(-rtemp); right(-ltemp);}'
% vertex.particles[0].pdg_code)
elif 'T' in lorentztag :
all_coup, left_coup, right_coup, ordering = \
tensorCouplings(vertex,coupling,prefactors,L,lorentztag,pos)
coup_norm += all_coup
coup_left += left_coup
coup_right += right_coup
else:
if lorentztag == 'VSS':
if L.structure == 'P(1,3) - P(1,2)':
prefactors += ' * (-1)'
ordering = 'if(p2->id()!=%s){norm(-norm());}' \
% vertex.particles[1].pdg_code
elif lorentztag == 'VVVV':
if qcd==2:
ordering = 'setType(1);\nsetOrder(0,1,2,3);'
else:
ordering, factor = EWVVVVCouplings(vertex,L)
prefactors += ' * (%s)' % factor
elif lorentztag == 'VVV':
if len(pos[8]) != 3:
ordering = VVVordering(vertex)
if type(coupling) is not list:
value = coupling.value
else:
value = "("
for coup in coupling :
value += '+(%s)' % coup.value
value +=")"
coup_norm.append('(%s) * (%s)' % (prefactors,value))
#print 'Colour :',vertex.color[color_idx]
#print 'Lorentz %s:'%L.name, L.spins, L.structure
#print 'Coupling %s:'%C.name, C.value, '\nQED=%s'%qed, 'QCD=%s'%qcd
#print '---------------'
except SkipThisVertex:
vertex.herwig_skip_vertex = True
vertex_skipped = True
continue
leftcontent = ' + '.join(coup_left) if coup_left else '0'
rightcontent = ' + '.join(coup_right) if coup_right else '0'
normcontent = ' + '.join(coup_norm) if coup_norm else '1'
# #print 'Left:',leftcontent
# #print 'Right:',rightcontent
# #print 'Norm:',normcontent
# #print '---------------'
# ### do we need left/right?
symbols = set()
if 'FF' in lorentztag and lorentztag != "FFT":
# leftcalc = aStoStrongCoup(py2cpp(leftcontent)[0], paramstoreplace_, paramstoreplace_expressions_)
# rightcalc = aStoStrongCoup(py2cpp(rightcontent)[0], paramstoreplace_, paramstoreplace_expressions_)
leftcalc, sym = py2cpp(leftcontent)
symbols |= sym
rightcalc, sym = py2cpp(rightcontent)
symbols |= sym
left = 'left(' + leftcalc + ');'
right = 'right(' + rightcalc + ');'
else:
left = ''
right = ''
leftcalc = ''
rightcalc = ''
# normcalc = aStoStrongCoup(py2cpp(normcontent)[0], paramstoreplace_, paramstoreplace_expressions_)
normcalc, sym = py2cpp(normcontent)
symbols |= sym
# UFO is GeV by default (?)
if lorentztag in ['VVS','SSS']:
normcalc = '(%s) * GeV / UnitRemoval::E' % normcalc
elif lorentztag in ['FFT','VVT', 'SST', 'FFVT', 'VVVT' ]:
normcalc = 'Complex((%s) / GeV * UnitRemoval::E)' % normcalc
norm = 'norm(' + normcalc + ');'
# define unkown symbols from the model
symboldefs = [ def_from_model(FR,s) for s in symbols ]
couplingptrs = [',tcPDPtr']*len(lorentztag)
if lorentztag == 'VSS':
couplingptrs[1] += ' p2'
elif lorentztag == 'FFV':
couplingptrs[0] += ' p1'
elif lorentztag == 'VVV' and ordering != '':
couplingptrs[0] += ' p1'
couplingptrs[1] += ' p2'
couplingptrs[2] += ' p3'
elif lorentztag == 'VVVT' and ordering != '':
couplingptrs[0] += ' p1'
couplingptrs[1] += ' p2'
couplingptrs[2] += ' p3'
elif lorentztag == 'VVVV' and qcd != 2:
couplingptrs[0] += ' p1'
couplingptrs[1] += ' p2'
couplingptrs[2] += ' p3'
couplingptrs[3] += ' p4'
### assemble dictionary and fill template
subs = { 'lorentztag' : lorentztag, # ok
'classname' : classname, # ok
'symbolrefs' : '\n '.join(symboldefs),
'left' : left, # doesn't always exist in base
'right' : right, # doesn't always exist in base
'norm' : norm, # needs norm, too
#################### need survey which different setter methods exist in base classes
'addToPlist' : '\n'.join([ 'addToList(%s);'%s for s in plistarray]),
'parameters' : '',
'setCouplings' : '',
'qedorder' : qed,
'qcdorder' : qcd,
'couplingptrs' : ''.join(couplingptrs),
'spindirectory' : spindirectory(lorentztag),
'ModelName' : modelname,
'ordering' : ordering,
} # ok
if args.verbose:
print '-'*60
pprint.pprint(( classname, plistarray, leftcalc, rightcalc, normcalc ))
vertexclasses.append(VERTEXCLASS.substitute(subs))
vertexheaders.add(VERTEXHEADER.format(**subs))
WRAP = 25
if vertexnumber % WRAP == 0:
write_vertex_file({'classname':classname,
'vertexnumber' : vertexnumber//WRAP,
'vertexclasses' : '\n'.join(vertexclasses),
'vertexheaders' : ''.join(vertexheaders),
'ModelName' : modelname})
vertexclasses = []
vertexheaders = set()
if not should_print():
sys.stderr.write(
"""
Error: The conversion was unsuccessful, some vertices could not be
generated. If you think the missing vertices are not important
and want to go ahead anyway, use --ignore-skipped.
Herwig may not give correct results, though.
"""
)
sys.exit(1)
if vertexclasses:
write_vertex_file({'classname':classname,
'vertexnumber' : vertexnumber//WRAP + 1,
'vertexclasses' : '\n'.join(vertexclasses),
'vertexheaders' : ''.join(vertexheaders),
'ModelName' : modelname})
print '='*60
##################################################
##################################################
##################################################
vertexline = """\
create Herwig::{modelname}V_{vname} /Herwig/{modelname}/V_{vname}
insert {modelname}:ExtraVertices 0 /Herwig/{modelname}/V_{vname}
"""
def get_vertices():
vlist = ['library %s\n' % libname]
for v in all_vertices:
if v.herwig_skip_vertex: continue
vlist.append( vertexline.format(modelname=modelname, vname=v.name) )
if( not args.no_generic_loop_vertices) :
vlist.append('insert {modelname}:ExtraVertices 0 /Herwig/{modelname}/V_GenericHPP\n'.format(modelname=modelname) )
vlist.append('insert {modelname}:ExtraVertices 0 /Herwig/{modelname}/V_GenericHGG\n'.format(modelname=modelname) )
return ''.join(vlist)
plist, names = thepeg_particles(FR,parmsubs,modelname,modelparameters)
particlelist = [
"# insert HPConstructor:Outgoing 0 /Herwig/{n}/Particles/{p}".format(n=modelname,p=p)
for p in names
]
# make the first one active to have something runnable in the example .in file
particlelist[0] = particlelist[0][2:]
particlelist = '\n'.join(particlelist)
modelfilesubs = { 'plist' : plist,
'vlist' : get_vertices(),
'setcouplings': '\n'.join(parmmodelconstr),
'ModelName': modelname
}
# write the files from templates according to the above subs
if should_print():
MODEL_HWIN = getTemplate('LHC-FR.in')
if(not args.split_model) :
MODEL_CC = [getTemplate('Model.cc')]
else :
MODEL_EXTRA_CC=getTemplate('Model6.cc')
extra_names=[]
extra_calcs=[]
parmtextsubs['doinit']=""
for i in range(0,len(doinit)) :
if( i%20 == 0 ) :
function_name = "initCalc" +str(int(i/20))
parmtextsubs['doinit'] += function_name +"();\n"
parmtextsubs['calcfunctions'] += "void " + function_name + "();\n"
extra_names.append(function_name)
extra_calcs.append("")
extra_calcs[-1] += doinit[i] + "\n"
for i in range(0,len(extra_names)) :
ccname = '%s_extra_%s.cc' % (modelname,i)
writeFile( ccname, MODEL_EXTRA_CC.substitute({'ModelName' : modelname,
'functionName' : extra_names[i],
'functionCalcs' : extra_calcs[i] }) )
MODEL_CC = [getTemplate('Model1.cc'),getTemplate('Model2.cc'),getTemplate('Model3.cc'),
getTemplate('Model4.cc'),getTemplate('Model5.cc')]
MODEL_H = getTemplate('Model.h')
print 'LENGTH',len(MODEL_CC)
MODELINFILE = getTemplate('FR.model')
writeFile( 'LHC-%s.in' % modelname,
MODEL_HWIN.substitute({ 'ModelName' : modelname,
'Particles' : particlelist })
)
modeltemplate = Template( MODELINFILE.substitute(modelfilesubs) )
writeFile( '%s.h' % modelname, MODEL_H.substitute(parmtextsubs) )
for i in range(0,len(MODEL_CC)) :
if(len(MODEL_CC)==1) :
ccname = '%s.cc' % modelname
else :
ccname = '%s.cc' % (modelname + str(i))
writeFile( ccname, MODEL_CC[i].substitute(parmtextsubs) )
writeFile( modelname +'.template', modeltemplate.template )
writeFile( modelname +'.model', modeltemplate.substitute( modelparameters ) )
# copy the Makefile-FR to current directory,
# replace with the modelname for compilation
with open(os.path.join(modulepath,'Makefile-FR'),'r') as orig:
with open('Makefile','w') as dest:
dest.write(orig.read().replace("FeynrulesModel.so", libname))
print 'finished generating model:\t', modelname
print 'model directory:\t\t', args.ufodir
print 'generated:\t\t\t', len(FR.all_vertices), 'vertices'
print '='*60
print 'library:\t\t\t', libname
print 'input file:\t\t\t', 'LHC-' + modelname +'.in'
print 'model file:\t\t\t', modelname +'.model'
print '='*60
print """\
To complete the installation, compile by typing "make".
An example input file is provided as LHC-FRModel.in,
you'll need to change the required particles in there.
"""
print 'DONE!'
print '='*60
diff --git a/Models/Feynrules/python/ufo2peg/Model.cc.template b/Models/Feynrules/python/ufo2peg/Model.cc.template
--- a/Models/Feynrules/python/ufo2peg/Model.cc.template
+++ b/Models/Feynrules/python/ufo2peg/Model.cc.template
@@ -1,72 +1,93 @@
// -*- C++ -*-
//
// ${ModelName}.cc is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2007 The Herwig Collaboration
//
// Herwig is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the ${ModelName} class.
//
#include "${ModelName}.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Helicity/Vertex/VertexBase.h"
#include "ThePEG/Utilities/DescribeClass.h"
+#include <fstream>
//#include "Herwig/Models/General/ModelGenerator.h"
using namespace ThePEG;
using namespace Herwig;
${ModelName}::${ModelName}()
${parmconstr}
{}
IBPtr ${ModelName}::clone() const {
return new_ptr(*this);
}
IBPtr ${ModelName}::fullclone() const {
return new_ptr(*this);
}
void ${ModelName}::doinit() {
${doinit}
BSMModel::doinit();
${addVertex}
+ writeParamCard();
+}
+void ${ModelName}::doinitrun() {
+ BSMModel::doinitrun();
+ writeParamCard();
}
void ${ModelName}::persistentOutput(PersistentOStream & os) const {
os << ${ostream} ;
}
void ${ModelName}::persistentInput(PersistentIStream & is, int) {
is >> ${istream} ;
}
+void ${ModelName}::writeParamCard() const {
+ ofstream card("param_card.dat");
+
+ card
+ << "#####################################################\n"
+ << "## DO NOT EDIT - GENERATED BY HERWIG UFO CONVERTER ##\n"
+ << "#####################################################\n\n";
+
+ card
+ ${param_card_data}
+ << '\n';
+
+ card.close();
+}
+
// Static variable needed for the type description system in ThePEG.
DescribeClass<${ModelName},BSMModel>
describeThePEG${ModelName}("Herwig::${ModelName}", "${ModelName}.so");
void ${ModelName}::Init() {
${refs}
static ClassDocumentation<${ModelName}> documentation
("The ${ModelName} class inherits from BSMModel"
"and supplies additional couplings and access to the ${ModelName}"
"vertices for helicity amplitude calculations" );
${parmextinter}
}
diff --git a/Models/Feynrules/python/ufo2peg/Model.h.template b/Models/Feynrules/python/ufo2peg/Model.h.template
--- a/Models/Feynrules/python/ufo2peg/Model.h.template
+++ b/Models/Feynrules/python/ufo2peg/Model.h.template
@@ -1,137 +1,148 @@
// -*- C++ -*-
//
// ${ModelName}.h is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2013 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_${ModelName}_H
#define HERWIG_${ModelName}_H
// This is the declaration of the ${ModelName} class.
#include "Herwig/Models/General/BSMModel.h"
namespace Herwig {
using namespace ThePEG;
using ThePEG::Constants::pi;
const Complex ii = Complex(0,1);
/** \ingroup Models
*
* This is the Herwig ${ModelName} class which inherits from ThePEG
* FeynRules Model class and implements additional FeynRules Model couplings,
* access to vertices for helicity amplitude calculations etc.
*
* @see BSMModel
*/
class ${ModelName}: public BSMModel {
public:
/// Default constructor
${ModelName}();
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);
//@}
-
+
+ /**
+ * Write out a UFO param_card.dat that matches the configured values
+ */
+ void writeParamCard() const;
+
/**
* Standard Init function used to initialize the interfaces.
*/
static void Init();
protected:
virtual bool registerDefaultVertices() const { return false; }
public:
/**
* Pointers to the objects handling the vertices.
*/
//@{
${getters}
${parmgetters}
//@}
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
virtual IBPtr fullclone() const;
//@}
protected:
/**
* Initialize this object after the setup phase before saving and
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit();
+
+ /**
+ * Initialize this object. Called in the run phase just before
+ * a run begins.
+ */
+ virtual void doinitrun();
//@}
private:
/**
* Private and non-existent assignment operator.
*/
${ModelName} & operator=(const ${ModelName} &);
private:
/**
* Helper functions for doinit
*/
//@{
${calcfunctions}
//@}
private:
/**
* Pointers to the vertices for ${ModelName} Model helicity amplitude
* calculations.
*/
//@{
${decls}
${parmdecls}
//@}
};
}
namespace ThePEG {
ThePEG_DECLARE_POINTERS(Herwig::${ModelName},Hw${ModelName}Ptr);
}
#endif /* HERWIG_${ModelName}_H */
diff --git a/Models/Feynrules/python/ufo2peg/Model2.cc.template b/Models/Feynrules/python/ufo2peg/Model2.cc.template
--- a/Models/Feynrules/python/ufo2peg/Model2.cc.template
+++ b/Models/Feynrules/python/ufo2peg/Model2.cc.template
@@ -1,33 +1,55 @@
// -*- C++ -*-
//
// ${ModelName}.cc is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2007 The Herwig Collaboration
//
// Herwig is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the ${ModelName} class.
//
#include "${ModelName}.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Helicity/Vertex/VertexBase.h"
#include "ThePEG/Utilities/DescribeClass.h"
+#include <fstream>
//#include "Herwig/Models/General/ModelGenerator.h"
using namespace ThePEG;
using namespace Herwig;
void ${ModelName}::doinit() {
${doinit}
BSMModel::doinit();
${addVertex}
+ writeParamCard();
+}
+void ${ModelName}::doinitrun() {
+ BSMModel::doinitrun();
+ writeParamCard();
}
+
+
+void ${ModelName}::writeParamCard() const {
+ ofstream card("param_card.dat");
+
+ card
+ << "#####################################################\n"
+ << "## DO NOT EDIT - GENERATED BY HERWIG UFO CONVERTER ##\n"
+ << "#####################################################\n\n";
+
+ card
+ ${param_card_data}
+ << '\n';
+
+ card.close();
+}
diff --git a/Models/Feynrules/python/ufo2peg/__init__.py b/Models/Feynrules/python/ufo2peg/__init__.py
--- a/Models/Feynrules/python/ufo2peg/__init__.py
+++ b/Models/Feynrules/python/ufo2peg/__init__.py
@@ -1,11 +1,13 @@
from .particles import thepeg_particles
from .helpers import CheckUnique, getTemplate, writeFile, def_from_model
from .helpers import unique_lorentztag, colors, colorfactor, SkipThisVertex
from .helpers import spindirectory, add_brackets, typemap,VVVordering
from .helpers import tensorCouplings,EWVVVVCouplings, qcd_qed_orders
from .converter import py2cpp
from .lorentzparser import parse_lorentz
from .collapse_vertices import collapse_vertices
+
+from .write_paramcard import ParamCardWriter
diff --git a/Models/Feynrules/python/ufo2peg/particles.py b/Models/Feynrules/python/ufo2peg/particles.py
--- a/Models/Feynrules/python/ufo2peg/particles.py
+++ b/Models/Feynrules/python/ufo2peg/particles.py
@@ -1,200 +1,202 @@
from string import Template
# ignore these, they're in Hw++ already # TODO reset Hw++ settings instead
SMPARTICLES = {
1:'d',
2:'u',
3:'s',
4:'c',
5:'b',
6:'t', # think about this one later
11:'e-',
12:'nu_e',
13:'mu-',
14:'nu_mu',
15:'tau-',
16:'nu_tau',
21:'g',
22:'gamma',
23:'Z0',
24:'W+',
-1:'dbar',
-2:'ubar',
-3:'sbar',
-4:'cbar',
-5:'bbar',
-6:'tbar',
-11:'e+',
-12:'nu_ebar',
-13:'mu+',
-14:'nu_mubar',
-15:'tau+',
-16:'nu_taubar',
-24:'W-',
}
particleT = Template(
"""
create ThePEG::ParticleData $name
+# values set to 999999 are recalculated later from other model parameters
setup $name $pdg_code $name $mass $width $wcut $ctau $charge $color $spin 0
"""
)
class ParticleConverter:
'Convert a FR particle to extract the information ThePEG needs.'
def __init__(self,p,parmsubs,modelparameters):
self.name = p.name
self.pdg_code = p.pdg_code
self.spin = p.spin
self.color = p.color
if self.color == 1:
self.color = 0
self.selfconjugate = 0
self.mass = parmsubs[str(p.mass)]
if type(self.mass) == str:
value = modelparameters[self.mass]
try:
value = value.real
except:
pass
newname = '%s_ABS' % self.mass
self.mass = '${%s}' % newname
modelparameters[newname] = abs(value)
else:
try:
self.mass = self.mass.real
except:
pass
- self.mass = abs(self.mass)
+ self.mass = 999999. # abs(self.mass)
hbarc = 197.3269631e-15 # GeV mm (I hope ;-) )
self.width = parmsubs[str(p.width)]
if type(self.width) == str:
width = modelparameters[self.width]
ctau = (hbarc / width) if width != 0 else 0
newname = '%s_CTAU' % self.width
self.ctau = '${%s}' % newname
modelparameters[newname] = ctau
wcut = 10 * width
newname = '%s_WCUT' % self.width
self.wcut = '${%s}' % newname
modelparameters[newname] = wcut
self.width = '${%s}' % self.width
else:
- self.ctau = (hbarc / self.width) if self.width != 0 else 0
- self.wcut = 10.0 * self.width
+ self.ctau = 999999. # (hbarc / self.width) if self.width != 0 else 0
+ self.wcut = 999999. #10.0 * self.width
+ self.width = 999999. # was blank line before
self.charge = int(3 * p.charge)
def subs(self):
return self.__dict__
def thepeg_particles(FR,parameters,modelname,modelparameters):
plist = []
antis = {}
names = []
for p in FR.all_particles:
if p.spin == -1:
continue
gsnames = ['goldstone',
'goldstoneboson',
'GoldstoneBoson']
def gstest(name):
try:
return getattr(p,name)
except AttributeError:
return False
if any(map(gstest, gsnames)):
continue
if p.pdg_code in SMPARTICLES:
continue
if p.pdg_code == 25:
plist.append(
"""
set /Herwig/Particles/h0:Mass_generator NULL
set /Herwig/Particles/h0:Width_generator NULL
rm /Herwig/Masses/HiggsMass
rm /Herwig/Widths/hWidth
"""
)
subs = ParticleConverter(p,parameters,modelparameters).subs()
plist.append( particleT.substitute(subs) )
pdg, name = subs['pdg_code'], subs['name']
names.append(name)
if -pdg in antis:
plist.append( 'makeanti %s %s\n' % (antis[-pdg], name) )
else:
plist.append( 'insert /Herwig/NewPhysics/NewModel:DecayParticles 0 %s\n' % name )
plist.append( 'insert /Herwig/Shower/ShowerHandler:DecayInShower 0 %s # %s' % (pdg, name) )
antis[pdg] = name
selfconjugate = 1
class SkipMe(Exception):
pass
def spin_name(s):
spins = { 1 : 'Zero',
2 : 'Half',
3 : 'One' }
if s not in spins:
raise SkipMe()
else:
return spins[s]
def col_name(c):
cols = { 3 : 'Triplet',
6 : 'Sextet',
8 : 'Octet' }
return cols[c]
try:
if p.color in [3,6,8]: # which colors?
splitname = '{name}SplitFn'.format(name=p.name)
sudname = '{name}Sudakov'.format(name=p.name)
plist.append(
"""
create Herwig::{s}{s}OneSplitFn {name}
set {name}:InteractionType QCD
set {name}:ColourStructure {c}{c}Octet
cp /Herwig/Shower/SudakovCommon {sudname}
set {sudname}:SplittingFunction {name}
do /Herwig/Shower/SplittingGenerator:AddFinalSplitting {pname}->{pname},g; {sudname}
""".format(s=spin_name(p.spin), name=splitname,
c=col_name(p.color), pname=p.name, sudname=sudname)
)
except SkipMe:
pass
if p.charge == 0 and p.color == 1 and p.spin == 1:
plist.append(
"""
insert /Herwig/{ModelName}/V_GenericHPP:Bosons 0 {pname}
insert /Herwig/{ModelName}/V_GenericHGG:Bosons 0 {pname}
""".format(pname=p.name, ModelName=modelname)
)
return ''.join(plist), names
diff --git a/Models/Feynrules/python/ufo2peg/write_paramcard.py b/Models/Feynrules/python/ufo2peg/write_paramcard.py
new file mode 100644
--- /dev/null
+++ b/Models/Feynrules/python/ufo2peg/write_paramcard.py
@@ -0,0 +1,41 @@
+# modified from the UFO version
+
+class ParamCardWriter(object):
+
+ def __init__(self, all_parameters):
+ """write a valid param_card.dat"""
+
+ list_of_parameters = [
+ param
+ for param in all_parameters
+ if param.nature=='external'
+ ]
+
+ self.output = []
+
+ self.write_card(list_of_parameters)
+
+ def write_card(self, all_ext_param):
+ # list all lhablock
+ all_lhablock = set([param.lhablock for param in all_ext_param])
+
+ # ordonate lhablock alphabeticaly
+ list(all_lhablock).sort()
+
+ for lhablock in all_lhablock:
+ self.write_block(lhablock)
+ [self.write_param(param, lhablock) for param in all_ext_param if \
+ param.lhablock == lhablock]
+ def write_block(self, name):
+ """ write a comment for a block"""
+ if name!='DECAY':
+ self.output.append('<< "Block %s\\n"' % name)
+
+ def write_param(self, param, lhablock):
+
+ lhacode=' '.join(['%3s' % key for key in param.lhacode])
+ if lhablock != 'DECAY':
+ text = '<< " %s " << %s() << " # %s\\n"' % (lhacode, param.name, param.name )
+ else:
+ text = '<< "DECAY %s " << %s() << "\\n"' % (lhacode, param.name)
+ self.output.append(text)
diff --git a/NEWS b/NEWS
--- a/NEWS
+++ b/NEWS
@@ -1,1466 +1,1470 @@
Herwig News -*- outline -*-
================================================================================
+* ATTENTION TODO No entries on NEWS between
+** 64ad0a62f6f4 (tagged Herwig 7.0.0) and
+** 30c7c5d7bf8b on herwig-7-0
+
* Herwig 7.0.0 (Herwig++ 3.0.0) release: 2015-12-04
** Major new release
A major new release of the Monte Carlo event generator Herwig++ (version
3.0) is now available. This release marks the end of distinguishing
Herwig++ and HERWIG development and therefore constitutes the first major
release of version 7 of the Herwig event generator family. The new version
features a number of significant improvements to the event simulation,
including: built-in NLO hard process calculation for all Standard Model
processes, with matching to both angular ordered and dipole shower modules
via variants of both subtractive (MC@NLO-type) and multiplicative
(Powheg-type) algorithms; QED radiation and spin correlations in the
angular ordered shower; a consistent treatment of perturbative
uncertainties within the hard process and parton showering, as well as a
vastly improved documentation. This version includes (for a more detailed
overview and further references please see the release note
arXiv:1512.01178):
** A long list of improvements and fixes for the Matchbox module
*** includes MC@NLO and Powheg matching to both showers with truncated showering
** A long list of improvements and fixes for both of the shower modules
*** includes improvements of numerics issues relevant to 100 TeV pp collisions
** NLO event simulation and Matchbox development
*** Interfaces to a number of external libraries
*** A new workflow for event generation
*** Electroweak corrections to VV production
** Parton shower development
*** QED radiation in the angular ordered shower
*** Spin correlations in the angular ordered shower
*** New scale choices in gluon branchings
** Improvements to event generation workflow
*** Re-organized and streamlined input files for the new NLO development
*** A unified treatment of shower and matching uncertainties
*** New integrator modules featuring parallel integration
** New default tunes for both shower modules
** New contrib modules
*** Electroweak Higgs plus jets production
*** FxFx merging support
*** Higgs boson pair production
* Herwig++-2.7.1 release: 2014-07-07
** New shower switches to select schemes for momentum reconstruction
*** QTildeReconstructor:FinalStateReconOption
has the following options:
*** Default
All momenta are rescaled in the rest frame.
*** MostOffShell
Put all particles on the new-mass shell and the most off-shell and
recoiling system are rescaled to ensure 4-momentum is conserved.
*** Recursive
Recursively put the most off-shell particle which hasn't yet been
rescaled on-shell by rescaling the particles and the recoiling
system.
*** RestMostOffShell
The most off-shell is put on shell by rescaling it and the
recoiling system, the recoiling system is then put on-shell in its
rest frame.
*** RestRecursive
As above, but recursively treat the currently most-off shell
(only makes a difference for more than 3 partons)
** Ticket #378: Hadronization of baryon number violating clusters involving diquarks
Fixed by only considering non-diquarks to be combined in the
ClusterFinder.
** UFO converter can now parse SLHA files for parameter settings
The UFO converter code can now use SLHA files for modifying
parameters. The first pass "ufo2herwig" produces the model to be
compiled. For each parameter card, run "slha2herwig" to get the
matching input file.
** Fix for systems using lib64
The repository is now initialized correctly on systems using lib64
as the library location.
** Efficiency optimization
Better allocation of internal vector variables for a noticeable
speed increase of 10-20% with LHC events.
* Herwig++-2.7.0 release: 2013-10-28
** UFO interface to Feynman rules generators
Herwig++ now includes "ufo2herwig", a tool that automatically
creates all required files to run a BSM model from a UFO
directory. The conversion has been extensively tested against
Feynrules models MSSM, NMSSM, RS, Technicolor,
and less extensively with most of the
other models in the Feynrules model database.
We expect that following this release there will be no further
hard-coded new physics models added to Herwig++ and that future
models will be included using the UFO interface.
** Shower uncertainties
A first set of scaling parameters to estimate shower uncertainties
is provided for both the angular ordered as well as the dipole
shower; they are Evolver:HardScaleFactor and ShowerAlphaQCD:
RenormalizationScaleFactor.
** Rewrite of Matchbox NLO matching
The NLO matching implementation has been rewritten and is now more
flexible and consistent. Profile scales are provided for the
hardest emission both for the dipole shower and matrix element
correction matching.
** BLHA2 Interface and new processes
Matchbox now features a generic BLHA2 interface to one-loop
amplitude codes and now also includes W and W+jet production as
well as Higss production in gluon fusion as builtin processes.
** Impoved dipole shower kinematics parametrization
The kinematics parametrization for emissions in the dipole shower
has been made more efficient.
** W and Z Powheg decays
Decays of W and Z bosons now use the Powheg decayers by default.
** Improved treatment of beam remnants
The handling of beam remnants has been improved in multiple
contexts, leading to a much lower error rate at p+/p- collisions.
An additional value "VeryHard" for ClusterFissioner:RemnantOption
can be used to disable any special treatment of beam remnant
clusters.
** New underlying event tune
Herwig++ now uses tune UE-EE-5-MRST by default. Other related tunes
can be obtained from the Herwig++ tunes page
** Improvements in BSM code
The UFO development identified many sign fixes in rarely used BSM
vertices; many improvements were made to general decayers, allowing
four-body decays in BSM for the first time; Powheg is enabled in
General two-body decayers; and the handling of colour
sextets has been improved.
** A new HiggsPair matrix element in Contrib.
** A new matrix element for single top production.
** The Higgs mass is now set to 125.9 GeV (from PDG 2013 update).
** C++-11 testing
To help with the coming transition to C++-11, we provide the new
--enable-stdcxx11 configure flag. Please try to test builds with
this flag enabled and let us know any problems, but do not use this
in production code yet. In future releases, this flag will be on by
default.
** Other changes
*** Many new Rivet analyses have been included in the Tests directory.
*** Cleaned Shower header structure; grouped shower parameters into one struct.
*** The boolean Powheg flag in HwMEBase changed to an enumeration.
* Herwig++-2.6.3 release: 2013-02-22
** Decay vertex positioning in HepMC output
Pseudo-vertices that Herwig++ inserts for technical reasons will
now not contribute to the Lorentz positions of downstream vertices.
Thanks to ATLAS for the bug report!
** Updated Rivet tests
Herwig's library of Rivet test runs has been brought up-to-date
with new analyses that were recently published by the Rivet
collaboration.
* Herwig++-2.6.2 release: 2013-01-30
** Fixes for PDF and scale choices in POWHEG events
Scale settings for MPI and the regular shower are now correct in
POWHEG events. This should fix reported anomalies in POWHEG jet rates.
NLO PDFs are now also set consistently in the example input files.
** Ticket #373: Branching ratio factors in cross-section
If any decay modes are selectively disabled, setting the following
post-handler will cause all reported cross-sections to include the
branching ratio factor(s) from the previous stages correctly:
create Herwig::BranchingRatioReweighter BRreweight
insert LHCGenerator:EventHandler:PostDecayHandlers 0 BRreweight
** Anomalous vertices now possible in MEfftoVH
** Interactive shell does not quit on error
** Better warning messages for events from inconsistent LHEF files
** Possible division by zero error fixed in BSM branching ratio calculations
** Decayer and ME changes to improve checkpointing
The checkpointing changes in ThePEG 1.8.2 are implemented here, too. Regular
dump files are consistent now.
* Herwig++-2.6.1 release: 2012-10-16
** Configure switches
The various switches to turn off compilation of BSM models have
been unified into a single '--disable-models'. A new flag
'--disable-dipole' can be used to turn off the compilation of the
Dipole and Matchbox codes.
** Ticket #348: Search path for repository 'read' command
The search path for the 'read' command is configurable on the
command line with the -i and -I switches. By default, the
installation location is now included in the search path, so that
'Herwig++ read LEP.in' will work in an empty directory. The current
working directory will always be searched first.
The rarely used "Herwig++ init" command has been made consistent
with 'read' and 'run' and should now be used without the '-i' flag.
** Width treatment in BSM
The width treatment in BSM decay chains has been greatly improved
and is now switched on by default in the .model files. To get the
old behaviour, use
set /Herwig/NewPhysics/NewModel:WhichOffshell Selected
** New BSM models
Little Higgs models with and without T-parity are now available.
** Resonance photon lifetime
A lifetime bug affecting decays of pi0 to e+e-X was fixed. The
virtual photon is not part of the event record anymore.
** Ticket #371: Hard diffraction FPE
Herwig++ 2.6.0 introduced a bug into the diffraction code which
would abort any runs. This is now fixed.
** O2AlphaS
Support for setting quark masses different from the particle data
objects as introduced in ThePEG 1.8.1 has been enabled.
** Matchbox
Several improvements and bug fixes are included for
Matchbox. Amplitudes relevant to pp -> Z+jet and crossed processes
at NLO are now available, and various scale choices have been added
in a more flexible way. All subtraction dipoles for massive quarks
are now included.
** Dipole shower
Parameters to perform scale variations in the shower have been
added to estimate uncertainties. A bug in showering off gg -> h has
been fixed.
** Minor fixes
*** Two broken colour structures in GeneralHardME
*** Susy Higgs mixing matrix
*** BaryonFactorizedDecayer out-of-bounds access
*** Mass values in SimpleLHCAnalysis
* Herwig++-2.6.0 release: 2012-05-21 (tagged at SVN r7407)
** New NLO framework
Matchbox, a flexible and very general framework for performing NLO
calculations at fixed order or matched to parton showers is
provided with this release.
** Dipole shower algorithm
A first implementation of the coherent dipole shower algorithm by
Plätzer and Gieseke (arXiv:0909.5593 and arXiv:1109.6256) is
available.
** Alternative samplers and the ExSample library
The ExSample library by Plätzer (arXiv:1108.6182) is shipped along
with Herwig++ in an extended version. The extended version provides
SamplerBase objects which can be used alternatively to the default
ACDCSampler.
** New BSM models
*** New colour sextet diquark model
A colour sextet diquark model has been included, as described in
Richardson and Winn (arXiv:1108.6154).
*** Models reproducing the CDF t-tbar asymmetry
Four models that can reproduce the reported t-tbar asymmetry have
been included.
*** Zprime
A simple standard model extension by one additional heavy neutral
vector boson.
** Interface to AlpGen, with MLM merging
The Contrib directory contains a new interface to the AlpGen matrix
element generator. AlpGen events must be preprocessed with the
provided AlpGenToLH.exe tool before they can be used. More
information can be found in the Herwig++ 2.6 release note.
** HiggsVBF Powheg
Higgs boson production by vector boson fusion is available at NLO
in the POWHEG scheme, as described in d'Errico, Richardson
(arXiv:1106.2983). The Powheg DIS processes were available in
Herwig++-2.5.2 already.
** Statistical colour reconnection
Alternative mechanisms to minimize the colour length Sum(m_clu)
before the hadronization stage, based on Metropolis and annealing
algorithms.
** Energy extrapolation of underlying-event tunes
To describe underlying-event data at different c.m. energies, the
energy-dependent parameter pT_min will now be adjusted
automatically, following a power-law. The new tune parameters are
the value at 7000 GeV "MPIHandler:pTmin0", and MPIHandler:Power.
** Ticket #239: Reporting of minimum-bias cross-section
When simulating minimum-bias events using the MEMinBias matrix
element, the correct unitarized cross section can now be reported
via the standard facilities; it is no longer necessary to extract
it from the .log file of the run. The corresponding functionality
is enabled by inserting a MPIXSecReweighter object as a
post-subprocess handler:
create Herwig::MPIXSecReweighter MPIXSecReweighter
insert LHCHandler:PostSubProcessHandlers 0 MPIXSecReweighter
** Dependency on 'boost'
Herwig++ now requires the boost headers to build; if not detected
in standard locations, specify with the --with-boost configure
option.
** Tests directory
The Tests directory now contains input cards for almost all Rivet
analyses. A full comparison run can be initiated with 'make tests'.
** Minor changes
*** Default LHC energy now 8 TeV
All LHC-based defaults have now been updated to use 8 TeV as the
center-of-mass energy.
*** Herwig::ExtraParticleID -> ThePEG::ParticleID
The namespace for additional particles has been unified into
ThePEG::ParticleID
*** MEee2VectorMeson
The e+e- -> vector meson matrix element has moved from Contrib into
HwMELepton.so
*** SUSY numerics fixes
Better handling of rare numerical instabilities.
*** YODA output for Rivet
The built-in histogramming handler can now output data in the YODA
format used by Rivet.
*** Consistency checks in SLHA file reader
Better warnings for inconsistent SusyLHA files
*** better colour flow checking for development
** Bug fixes
*** Extremely offshell W from top decay
Numerical improvements for very off-shell W bosons coming from top
decays.
*** Ticket #367: problems in using SUSY + LHE
Susy events from Les Houches event files are now handled better.
*** Infinite loop in remnant decayer
The remnant decayer will now abort after 100 tries.
*** Fix to HiggsVBF LO diagrams
The diagram structure of HiggsVBF LO matrix elements has been fixed.
*** LEP thrust fix
The calculation of the transverse momentum of a branching from the
evolution variable in final-state radiation can now be
changed. While formally a sub-leading choice this enables a better
description of the thrust distribution in e+e- collisions at
small values of the thrust. Currently the default behaviour, where
the cut-off masses are used in the calculation, remains the same
as previous versions.
* Herwig++-2.5.2 release: 2011-11-01 (tagged at SVN r6928)
** Optional new jet vetoing model
The jet vetoing model by Schofield and Seymour (arXiv:1103.4811) is
available via Evolver:ColourEvolutionMethod,
PartnerFinder:PartnerMethod and SplittingFunction:SplittingColourMethod.
The default behaviour is unchanged.
** MPI tune
Version 3 of the MPI tunes is now the default. Please note that the
pT parameter is energy-dependent and needs to be modified when an
LHC run is not at 7 TeV.
The latest tunes are always available at
http://projects.hepforge.org/herwig/trac/wiki/MB_UE_tunes
** MPI PDFs
MPI PDFs can now be controlled independently.
** Initialization time speedup
A new BSMModel base class was introduced between StandardModel and
the BSM model classes. Together with a restructured decay mode
initialization, this offers significantly faster startup times for
BSM runs. ThreeBodyDecays can now always be switched on without a
large speed penalty.
** Decay mode file
Decay mode files in the SLHA format can now be read separately in
any BSM model with 'set Model:DecayFileName filename'
** Powheg DIS
Charged- and neutral-current DIS processes implementing the POWHEG
method are now available.
** Diffraction models
Xi cut implemented in PomeronFlux
** Ticket #352: Colour reconnection fixed in DIS
** Ticket #353: Improved numerical stability in chargino decays
** Ticket #358: Infinite loop in top events with pT cut in shower
** Ticket #361: Problem with duplicate 2-body modes in BSM
** Tickets #362 / #363: Crashes with baryon number violating models
Particle decays in SUSY models with RPV now work correctly in the
colour 8 -> 3,3,3 case. Colour reshuffling now works for RPV
clusters.
** Improved Fastjet detection
The configure step uses fastjet-config to make sure all header file
paths are seen.
** Darwin 11 / OS X Lion
A configure bug was fixed which prevented 'make check' from
succeeding on OS X Lion.
** Vertex classes
The specification of QED / QCD orders has been moved to the vertex
constructors, to allow ThePEG consistency checks. WWHH vertices in
MSSM and NMSSM were fixed. Some Leptoquark and UED vertices fixed.
** Hadronization
Cleanup of obsolete code.
* Herwig++-2.5.1 release: 2011-06-24 (tagged at SVN r6609)
** Example input files at 7 TeV
All our example input files for LHC now have their beam energy set
to 7 TeV instead of 14 TeV.
** Colour reconnection on by default
The colour reconnection tunes are now the default setup. Version 2
of the tunes replaces the *-1 tunes, which had a problem with LEP
event shapes.
** Run name tags
Aded possibility to add a tag to the run name when running with the
'-t' option. One run file can thus be run with different seeds and
results stored in different output files.
** Floating point exceptions
The new command line option -D enables floating point error checking.
** General improvements to WeakCurrent decays
** Remnant decayer
Hardwired gluon mass was removed.
** WeakCurrentDecayConstructor
Instead of specifying separate Particle1...Particle5 vectors for
the decay modes, the new interface DecayModes can be filled with
decay tags in the standard syntax.
** BSM: improvements to handling of vertex and model initialisation
** Powheg Higgs
Option to use pT or mT as the scale in alphaS and for the
factorization scale in the PDFs
** Ticket #337: Tau polarization wrong in charged Higgs decay
** Ticket #339: Colour flows in GeneralThreeBody Decayers for 3bar -> 8 3bar 1
** Ticket #340: Crash for resonant zero-width particles
** Ticket #341: Varying scale for BSM processes
The scale used is now ResonantProcessConstructor:ScaleFactor or
TwoToTwoProcessConstructor:ScaleFactor multiplied by sHat.
** Ticket #346: Chargino decays
Chargino decayers now automatically switch between the mesonic
decays for mass differences less than 2 GeV and the normal partonic
decays above 2 GeV.
** Ticket #349: Stop by default on input file errors
The '--exitonerror' flag is now the default behaviour for the
Herwig++ binary. To switch back to the old behaviour,
'--noexitonerror' is required.
** Ticket #351: Four-body stop decays
** Tested with gcc-4.6
* Herwig++-2.5.0 release: 2011-02-08 (tagged at SVN r6274)
** Uses ThePEG-1.7.0
Herwig++ 2.5.0 requires ThePEG 1.7.0 to benefit from various
improvements, particularly: handling of diffractive processes;
respecting LD_LIBRARY_PATH when loading dynamic libraries,
including LHAPDF; improvements to repository commands for decay
modes. See ThePEG's NEWS file for more details.
** POWHEG improvements
*** New POWHEG processes
Simulation at NLO accuracy using the POWHEG method is now
available for hadronic diboson production (pp to WW,WZ,ZZ), Higgs
decays to heavy quarks, and e+e- to two jets or ttbar, including
full mass dependence.
*** Input file changes
The input files for setting up POWHEG process simulation have been
simplified. See the example files LHC-Powheg.in and TVT-Powheg.in
for the improved command list.
*** Structural changes
The POWHEG backend in the shower code has been restructured to
make future additions easier: PowhegEvolver has merged with
Evolver; both the matrix element corrections and real corrections
in the POWHEG scheme are implemented directly in the ME or Decayer
classes.
** New processes at leading order
*** Photon initiated processes
We have added a matrix element for dijet production in gamma
hadron collisions.
*** Bottom and charm in heavy quark ME
The option of bottom and charm quarks is now supported for heavy
quark production in MEHeavyQuark.
** Colour reconnection
The cluster hadronization model has been extended by an option to
reconnect coloured constituents between clusters with a given
probability. This new model is different from the colour
reconnection model used in FORTRAN HERWIG, and improves the
description of minimum bias and underlying event data.
** Diffractive Processes
Both single and double diffractive processes are now supported in
Herwig++. The Pomeron PDF is implemented using a fit to HERA data,
and a pion PDF can be used to model reggeon flux.
** BSM physics
*** New models
We have added new BSM models, particularly ADD-type extra
dimension models and the next-to-minimal supersymmetric standard
model (NMSSM). Effects of leptoquarks can as well be simulated.
*** Vertex additions
We have added flavour changing stop interactions (stop -
neutralino - charm) and gravitino interactions with particular
emphasis on numerical stability for very light gravitinos.
Tri-linear Higgs and Higgs-Higgs/Vector-Vector four-vertices are
available as well.
*** Input file changes
The SUSY model can now also extract the SLHA information from the
header of a Les Houches event file: replace the SLHA file name
in the example input files with the LH file name.
*** Structure
The backend structure of the HardProcessConstructor has changed,
to allow easier inclusion of new process constructors. Some 2->3
BSM scattering processes involving neutral higgs bosons are now
included. The spin handling has been improved in the background.
** Shower splitting code reorganized
The selection of spin structures has been decoupled from the choice
of colour structure. This gives more flexibility in implementing
new splittings. Selected splittings can be disabled in the input
files.
** B mixing
B mixing, and indirect CP violation in the B meson system are
included now.
** Looptools
The Looptools directory has been updated to reflect T.Hahn's
Looptools 2.6.
** Contrib changes
The ROOT interface has been removed as deprecated. The MCPWNLO code
has temporarily been removed from the Contrib directory as a major
review of this code is required. Additionally, there are various
fixes to all other codes shipped in Contrib.
** DIS improvements
The momentum reshuffling in DIS events has been improved.
** mu and nu beams
mu, nu_e and nu_mu and their antiparticles are now available as
beam particles. They are all supported in the DIS matrix
elements. mu+ mu- collisions are supported in the general
matrix element code for BSM models, but not yet in the hard-coded
matrix elements for lepton-lepton scattering.
** Structural changes
*** Inline code
Inline code has been merged into the header files, .icc files were
removed.
*** Silent build
By default, Herwig++ now builds with silent build rules. To get
the old behaviour, run 'make V=1'.
*** Debug level
The debug level on the command line will now always have priority.
*** Event counter
The event counter has been simplified.
*** Interpolator persistency
Interpolators can now be written persistently.
** Ticket #307: Momentum violation check in BasicConsistency
Added parameters AbsoluteMomentumTolerance and
RelativeMomentumTolerance
** Example POWHEG input files
The example input files for Powheg processes now set the NLO
alpha_S correctly, and are run as part of 'make check'.
** Truncated shower
A problem which lead to the truncated shower not being applied in
some cases has been fixed.
** Fixes to numerical problems
Minor problems with values close to zero were fixed in several
locations.
** Remove duplicated calculation of event shapes
An accidental duplication in the calculation of event shapes was
removed, they are now only calculated once per event. Several other
minor issues in the event shape calculations have also been fixed.
** MRST PDFs fixed
An initialization problem in the internal MRST PDFs was fixed.
** Vertex scale choice
The scale in the Vertex classes can now be zero where
possible.
** Treatment of -N flag
The Herwig++ main program now correctly treats the -N flag
as optional.
** Numerical stability improved
The numerical stability in the 'RunningMass' and
'QTildeReconstructor' classes has been improved. The
stability of the boosts in the SOPTHY code for the
simulation of QED radiation has been improved.
The accuracy of boosts in the z-direction has been improved to
fix problems with extremely high p_T partons.
** Bugfix in initial state splittings
A bug in the implementation of the PDF weight in initial-state
qbar -> qbar g splittings has been fixed.
** Bugfix in chargino neutralino vertices
A bug in the 'chi+- chi0 W-+' and charged
Higgs-sfermions vertices has been fixed.
** Remove uninitialized variables written to repository
A number of uninitialised variables which were written to the
repository have been initialised to zero to avoid problems on some
systems.
** Fix to QED radiation in hadronic collisions
The longitudinal boost of the centre-of-mass frame in hadronic
collisions is correctly accounted for now in the generation of QED
radiation.
** Fix to numerical problems in two-body decays
Numerical problems have been fixed, which appeared in the rare case
that the three-momenta of the decay products in two-body decays are
zero in the rest frame of the decay particle.
** A problem with forced splittings in the Remnant was fixed.
** ME correction for W+- decays applied properly
The matrix element correction for QCD radiation in W+- decays
which was not being applied is now correctly used.
** Top quark decays from SLHA file
The presence of top quark decay modes in SLHA files is now handled
correctly.
** Exceptional shower reconstruction kinematics
Additional protection against problems due to the shower
reconstruction leading to partons with x>1 has been added.
** Ordering of particles in BSM processes
Changes have been made to allow arbitrary ordering of the outgoing
particles in BSM processes.
** Bugfixes in tau decays
Two bugs involving tau decays have been fixed. The wrong masses
were used in the 'KPiCurrent' class for the scalar form factors
and a mistake in the selection of decay products lead to
tau- --> pi0 K- being generated instead of tau- --> eta K-.
** Avoid crashes in baryon number violating processes.
To avoid crashes, better protection has been introduced for the
case where diquarks cannot be formed from the quarks in a
baryon-number violating process. In addition, the parents of the
baryon-number violating clusters have been changed to avoid
problems with the conversion of the events to HepMC.
** QED radiation in W- decays
A bug in the 'QEDRadiationHandler' class which resulted
in no QED radiation being generated in W- decays has been fixed.
** A number of minor fixes to the SUSY models have been made.
** Partial width calculations in BSM models
A fix for the direction of the incoming particle in the calculation
of two-body partial widths in BSM models has been made.
** LoopTools improvements
The LoopTools cache is now cleared more frequently to
reduce the amount of memory used by the particle.
** Negative gluino masses are now correctly handled.
** A problem with mixing matrices which are not square has been fixed.
** Removed duplicate diagram
The 'MEee2gZ2ll' class has been fixed to only include the
photon exchange diagram once rather than twice as previously.
** Fix for duplicate particles in DecayConstructor
A problem has been fixed which occurred if the same particle was
included in the list of DecayConstructor:DecayParticles.
** Fixes for UED model vertices
A number of minor problems in the vertices for the UED model have
been fixed.
** Include missing symmetry factor
The missing identical-particle symmetry factor in
'MEPP2GammaGamma' has been included.
** Fix floating point problem in top decays
A floating point problem in the matrix element correction for top
decays has been fixed.
* Herwig++-2.4.2 release: 2009-12-11 (tagged at SVN r5022)
** Ticket #292: Tau decay numerical instability
The momentum assignment in tau decays contained numerical
instabilities which have been fixed by postponing the tau decay
until after the parton shower. A new interface setting
DecayHandler:Excluded is available to prevent decays in the shower
step. This is enabled by default for tau only.
** Ticket #290: Missing MSSM colour structure
The missing colour structure for gluino -> gluon neutralino was added.
** Ticket #294: Zero momentum in some decays
Some rare phase space points lead to zero momentum in two-body
decays. This has been fixed.
** Ticket #295: Stability of QED radiation for lepton collider processes
The numerical stability of QED radiation momenta was improved
further.
** Ticket #296: K0 oscillation vertex was wrong
The oscillation from K0 to K0_L/S now takes place at the production
vertex of K0.
** Ticket #289: Undefined variables in repository
On some system configurations, undefined variables were written to
the repository. These have been fixed.
** Fixed QED radiation for hadron processes
The longitudinal boost of the centre-of-mass frame in hadronic
collisions is correctly accounted for now.
** Numerical stability fixes
Small fixes in RunningMass and QTildeReconstructor.
** Powheg example input files
The example input files for Powheg processes now set the NLO
alpha_S correctly, and are run as part of 'make check'.
** OS X builds for Snow Leopard
Snow Leopard machines will now be recognized as a 64bit
architecture.
* Herwig++-2.4.1 release: 2009-11-19 (tagged at SVN r4932)
** Uses ThePEG-1.6.0
Herwig++ now requires ThePEG-1.6.0 to benefit from the improved
helicity code there. If you have self-written vertex classes, see
ThePEG's NEWS file for conversion instructions.
** Vertex improvements
ThePEG's new helicity code allowed major simplification of the vertex
implementations for all Standard Model and BSM physics models.
** New Transplanckian scattering model
An example configuration is in LHC-TRP.in
** BSM ModelGenerator as branching ratio calculator
The BSM ModelGenerator has a new switch to output the branching
ratios for a given SLHA file in SLHA format, which can then be used
elsewhere.
** BSM debugging: HardProcessConstructor
New interface 'Excluded' to exclude certain particles from
intermediate lines.
** Chargino-Neutralino-W vertex fixed
** Spin correlations
are now switched on by default for all perturbative decays.
** Ticket #276: Scale choice in BSM models' HardProcessConstructor
New interface 'ScaleChoice' to choose process scale between
- sHat (default for colour neutral intermediates) and
- transverse mass (default for all other processes).
** Ticket #287: Powheg process scale choice
The default choice is now the mass of the colour-singlet system.
** Ticket #278: QED radiation for BSM
Soft QED radiation is now enabled in BSM decays and all
perturbative decays by default.
** Ticket #279: Full 1-loop QED radiation for Z decays
Soft QED radiation in Z decays is now fully 1-loop by default.
** Ticket #280: Redirect all files to stdout
This is now implemented globally. The files previously ending in
-UE.out and -BSMinfo.out are now appended to the log file. They now
also obey the EventGenerator:UseStdout flag.
** Ticket #270: LaTeX output updated
After each run, a LaTeX file is produced that contains the full
list of citations. Please include the relevant ones in publications.
** Ticket #256: Mac OS X problems
An initialization problem that affected only some configurations has
been identified and fixed.
** Tests directory added
This contains many .in files, to exercise most matrix
elements.
** Minor fixes
*** Prevent rare x>1 partons in shower reconstruction.
*** SUSY-LHA parameter EXTPAR can be used to set tan beta
*** Improved Fastjet detection at configure time
* Herwig++-2.4.0 release: 2009-09-01 (tagged at SVN r4616)
** New matrix elements
We have added a built-in implementation of several new matrix elements:
PP --> WW / WZ / ZZ
PP --> W gamma / Z gamma
PP --> VBF Higgs
PP --> Higgs tt / Higgs bb
e+e- --> WW / ZZ
gamma gamma --> ff / WW
** Base code improvements
*** Ticket #257: Remnant handling
A problem with forced splittings in the Remnant was fixed.
*** Ticket #264: Soft matrix element correction
A problem with emissions form antiquarks was fixed.
** PDF sets
*** New default set
MRST LO** is the new default PDF set. LO* is also available built-in.
*** Shower PDFs can be set separately from the hard process
Use the 'ShowerHandler:PDF' interface.
** Parameter tunes
Shower, hadronization and underlying event parameters were retuned
against LEP and Tevatron data respectively.
** BSM module improvements
*** Ticket #259: read error for some UED models
Arbitrary ordering of outgoing lines in the process description is now
possible.
*** Ticket #266: branching ratio sums
The warning threshold for branching ratios not summing to 1 has
been relaxed. It is now a user interface parameter.
*** Ticket #267: Top decay modes
Top decay modes listed in SLHA files are now handled correctly.
** QED radiation
*** Ticket #241: Soft QED radiation is now enabled by default
*** Ticket #265: Radiation off W+ and W- is now handled correctly
** Interfaces
*** Ticket #243: Fastjet
Fastjet is now the only supported jet finder code. All example
analyses have been converted to use Fastjet.
*** KtJet and CLHEP interfaces have been removed.
*** New interfaces to AcerDet and PGS available in Contrib
*** MCPWnlo distributed in Contrib
*** HepMC and Rivet interfaces moved to ThePEG
** Ticket #239: Inelastic cross-section for MinBias
This information is now available in the ...-UE.out files.
** Technical changes
*** Ticket #186
Configure now looks for ThePEG in the --prefix location first.
*** Configure information
Important configuration information is listed at the end of the
'configure' run and in the file 'config.thepeg'. Please provide
this file in any bug reports.
*** New ZERO object
The ZERO object can be used to set any dimensionful quantity to
zero. This avoids explicit constructs like 0.0*GeV.
*** Exception specifiers removed
Client code changes are needed in doinit() etc., simply remove the
exception specifier after the function name.
*** Ticket #263: Tau polarizations can be forced in TauDecayer
* Herwig++-2.3.2 release: 2009-05-08 (tagged at SVN r4249)
** SUSY enhancements
*** Ticket #245: Select inclusive / exclusive production
Using the new 'HardProcessConstructor:Processes' switch options
'SingleParticleInclusive', 'TwoParticleInclusive' or 'Exclusive'
*** Improved three-body decay generation
Several problems were fixed, incl. tickets #249 #250 #251
Thanks to J.Tattersall and K.Rolbiecki for the stress-testing!
*** Looptools fix
Release 2.3.1 had broken the Looptools initialization.
*** Improved warning message texts
** Ticket #237:
Values of q2last can now be zero where possible.
** Ticket #240:
The Herwig++ main program now correctly treats the -N flag as optional.
** Ticket #246:
Extreme pT partons fixed by improving accuracy of z boosts.
** DIS
Improved parton shower momentum reshuffling.
** Minimum Bias events
The zero-momentum interacting particle used for
bookkeeping is now labelled as a pomeron.
** User Makefile
Makefile-UserModules does not enable -pedantic anymore. User's ROOT
code will not compile otherwise.
** Build system
Small fixes in the build system.
* Herwig++-2.3.1 release: 2009-03-31 (tagged at SVN r4140)
** Initial state showers
The PDF veto was wrongly applied to qbar->qbar g splittings.
** User interaction
The Makefile-UserModules now includes the Herwig version number.
The -N flag to 'Herwig++ run' is optional now, as was always intended.
** Contrib
The contrib directory is now included in the tarball. The omission
was accidental.
** Numerical accuracy
Minor problems with values close to zero were fixed in several
locations.
** LEP event shapes
An accidental duplication was removed, they are now only calculated
once per event.
** MRST PDF code
Initialization problem fixed.
** Mac OS X
The configure script was improved to detect libraries better.
** Libtool
Updated to version 2.2.6
* Herwig++-2.3.0 release: 2008-12-02 (tagged at SVN r3939)
** Major release, with many new features and bug fixes
** Extension to lepton-hadron collisions
** Inclusion of several processes accurate at next-to-leading order
in the POsitive Weight Hardest Emission Generator (POWHEG) scheme
** Inclusion of three-body decays and finite-width effects
in BSM processes
** New procedure for reconstructing kinematics of the parton shower
based on the colour structure of the hard scattering process
** New model for baryon decays including excited baryon multiplets
** Addition of a soft component to the multiple scattering model
of the underlying event and the option to choose more than one hard
scattering explicitly
** New matrix elements for DIS and e+e- processes
** New /Contrib directory added
containing external modules that will hopefully be of use to some
users but are not expected to be needed by most users and are not
supported at the same level as the main Herwig++ code
** Minor changes to improve the physics simulation:
*** IncomingPhotonEvolver added
to allow the simulation of partonic processes with incoming photons
in hadron collisions
*** KTRapidityCut added
to allow cuts on the p_T and rapidity, rather than just the p_T and
pseudorapidity used in SimpleKTCut. This is now used by default for
cuts on massive particles such as the $W^\pm$, $Z^0$ and Higgs
bosons and the top quark
*** Several changes to the decayers of B mesons
both to resolve problems with the modelling of partonic decays and
improve agreement with $\Upsilon(4s)$ data
*** Changes to allow values other than transverse mass of final-state particles as maximum transverse momentum for radiation in parton shower
either SCALUP for Les Houches events or the scale of the hard
process for internally generated hard processes
*** Changed defaults for intrinsic transverse momentum in hadron collisions
to 1.9GeV, 2.1GeV and 2.2GeV for the Tevatron and LHC at 10 TeV and
14 TeV, respectively
*** Pdfinfo object is now created in the HepMC interface
However in order to support all versions of HepMC containing this
feature the PDF set is not specified as not all versions contain
this information
*** New option of only decaying particles with lifetimes below user specified value
*** New options for the cut-off in the shower
and some obsolete parameters removed
*** Added option of switching off certain decay modes in BSM models
*** Added a Matcher for Higgs boson
to allow cuts to be placed on it
*** Diffractive particles deleted from default input files
they were not previously used
** Technical changes:
*** Some AnalysisHandler classes comparing to LEP data have been renamed
e.g. MultiplicityCount becomes LEPMultiplicityCount to avoid
confusion with those supplied in /Contrib for observables at the
Upsilon(4s) resonance
*** Reorganisation to remove the majority of the .icc files
by moving inlined functions to headers in an effort to improve
compile time
*** Restructured the decay libraries to reduce the amount of memory allocation
and de-allocation which improves run-time performance
*** The switch to turn off LoopTools has been removed
because LoopTools is now used by several core modules. As LoopTools
does not work on 64-bit platforms with g77 this build option is not
supported
*** Removed support for obsolete version of HepMC supplied with CLHEP
and improved the support for different units options with HepMC
*** EvtGen interface has been removed until it is more stable
*** Support for ROOT has been removed
it was not previously used
*** CKKW infrastructure has been removed from the release
until a concrete implementation is available
*** Default optimisation has been increased from -O2 to -O3
*** Handling of the fortran compiler has been improved
mainly due to improvements in the autotools
*** Use of FixedAllocator for Particle objects in ThePEG has been removed
as it had no performance benefits
** Bugs fixed:
*** Problems with the mother/daughter relations in the hard process
and diagram selection in W+- and Z0 production in association with a
hard jet
*** In general matrix element code for fermion-vector to fermion-scalar
where the outgoing fermion is coloured and the scalar neutral
*** In the selection of diagrams in some associated squark gaugino processes
*** h0->mu+mu- was being generated when h0->tau+tau-
*** Normalisation in the Histogram class for non unit-weight events
*** Protection against negative PDF values has been improved
these can occur when using NLO PDF sets
*** Lifetime for BSM particles is now automatically calculated
at the same time as the width
*** Hadrons containing a top quark now treated like hadrons containing BSM particles
in order to support this possibility
*** Several ambiguous uses of unsigned int
*** Several variables that may have been used undefined
*** Several memory leaks at initialisation
*** The configuration now aborts if no fortran compiler is found
as this is required to compile Looptools
*** Several minor floating point errors that did not affect results
* Herwig++-2.2.1 release: 2008-07-09 (tagged at SVN r3434)
** Ticket #181: BSM shower with a decay close to threshold
Now fixed.
** Ticket #191: Split SUSY crash
Improved error message.
** Ticket #192: using SCALUP as the pT veto in the shower
Now implemented.
** Ticket #194: production processes of ~chi_1(2)-
Fixed bug in the diagram creation.
** Removed unused particles
DiffractiveParticles.in was removed, they were never produced.
** Hadronization
Top quark clusters now possible, handled as 'exotic' clusters.
** Improved handling of decay modes
See ThePEG-1.3.0. 'defaultparticle' command is now obsolete.
** Multi-Parton interactions
Increased phase space sampling to have less than 1% uncertainty on
average multiplicity.
** New libtool version
gfortran is now used as default if it is available. Set FC=g77 to
override this.
** Fixed several memory leaks
** Memory allocation
Now using plain 'new' and 'delete'.
* Herwig++-2.2.0 release: 2008-04-18 (tagged at SVN r3195)
** Major release: now as stand-alone library
Herwig++ is now a stand-alone dlopen() plugin to ThePEG.
No compile-time linking to Herwig code is required. The Herwig++
binary is a simple executable steering ThePEG, which can
be replaced by other frontends (such as setupThePEG / runThePEG).
** New matrix elements
p p -> W + jet / Z + jet / W + higgs / Z + higgs
e+ e- -> Z + higgs
** Looptools
Updated to version 2.2.
** Ticket #141: segfault from using 'run' command
Fixed by using default allocators in Herwig++, and the
Repository::cleanup() method in ThePEG 1.2.0.
** Ticket #157: broken gsl library path on some 64bit systems
Paths with lib64 are correctly identified now.
** Ticket #159: p_t spectrum of ttbar pair
Fixed identical particle multiplier in Sudakov form factor.
** Ticket #161: glibc segfault
Rare segfault in MPI handler fixed.
** Ticket #165: rare infinite loop in four-body decay
All 4-body decays without dedicated decayers now use the Mambo algorithm.
A loop guard has been introduced to 3-body decays to avoid infinite retries.
** Ticket #166: rare infinite loop in top ME correction
These very rare events (O(1) in 10^7) close to mass threshold
now are discarded.
** Higgs width fixes
** SatPDF
Optionally, the PDF extrapolation behaviour outside a given range
can now be specified.
** gcc 4.3
Herwig++-2.2 compiles cleanly with the new gcc 4.3 series.
* Herwig++-2.1.4 release: 2008-03-03 (tagged at SVN r3024)
** Ticket #152: Vertex positions
All vertex positions of unphysical particles are set to zero until
a fix for the previous nonsensical values can be implemented.
* Herwig++-2.1.3 release: 2008-02-25 (tagged at SVN r2957)
** Ticket #129: Baryon decays
Fix for baryon decay modes.
** Ticket #131: HepMC
Check if IO_GenEvent exists
** Ticket #134: Hadronization
Smearing of hadron directions in cluster decay fixed.
** Ticket #137: HepMC
HepMC conversion allows specification of energy and length units to
be used.
** Ticket #139: Neutral kaons
Ratio K_L / K_S corrected.
** Ticket #140 / #141: Crash on shutdown
Event generation from the 'read' stage or an interface now shuts
down cleanly. Fixes a crash bug introduced in 2.1.1 which affected
external APIs to ThePEG / Herwig.
** Ticket #146: BSM models can be disabled
To save build time, some or all of the BSM models can be disabled
using the '--enable-models' configure switch.
** Reorganised .model files
The .model files now include the model-specific particles, too.
** Re-tune
Re-tuned hadronization parameters to LEP data.
** Other fixes in
QSPAC implementation in Shower; Multi-parton interaction tuning;
MRST initialization
* Herwig++-2.1.2 release: 2008-01-05 (tagged at SVN r2694)
** Ticket #127
Thanks to a patch submitted by Fred Stober, HepMCFile now can
output event files in all supported formats.
** Ticket #128
Fixed incorrect value of pi in histogram limits.
** Other fixes in
CKKW Qtilde clusterers, BSM width cut, SUSY mixing matrices.
* Herwig++-2.1.1 release: 2007-12-08 (tagged at SVN r2589)
** Bug #123
Fixed a bug with particle lifetimes which resulted in nan for some
vertex positions.
** Secondary scatters
Fixed bug which gave intrinsic pT to secondary scatters.
** gcc abs bug detection
configure now checks for and works around
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34130
** CKKW reweighting
Fixed wrong check for top quarks.
** MPIHandler
Fixed call order ambiguity.
* Herwig++-2.1.0 release: 2007-11-20 (tagged at SVN r2542)
** Major new release
Herwig++-2.1 includes significant improvements, including
multi-parton interactions, BSM physics and a new hadronic decay
model, tuned to LEP data.
For an overview of the changes, please see the release note
arXiv:0711.3137
* Herwig++-2.0.3 release: 2007-08-21 (tagged at SVN r2101)
** Bug #90
nan in top decay ME corrections fixed.
** unlisted
Colour flow fix in LightClusterDecayer
** unlisted
Updated version of MultiplicityCount analysis handler.
* Herwig++-2.0.2 release: 2007-07-06 (tagged at SVN r1716)
** Bug #80
Separation of HepMC from CLHEP is handled properly now.
** Bug #83
Workaround for OS X header problem
** unlisted
Veto on very hard emissions from Shower.
** unlisted
Detailed documentation in .in files
* Herwig++-2.0.1 release: 2006-12-05 (tagged at SVN r1195)
** Bug #54
ClusterFissioner vertex calculation fixed.
** Bug #57
Crash when showering W+jet events supplied by Les Houches interface.
** Bug #59
Fix for #57 applied to LHC events.
** Bug #60
Segfault when PDF is set to NoPDF.
** Bug #61
Missing weight factor for I=0 mesons
** Bug #62
Spinor vertex calculations broken when spinor rep is not default rep.
** Bug #63
Top decay never produces tau.
** Bug #69
TTbar and HiggsJet analysis handlers fixed.
** unlisted
Reorganization of Hadronization module gives 30% speedup.
Thanks to Vincenzo Innocente at CMS for his profiling work!
** unlisted
cleaner automake files in include/ and src/
** unlisted
Hw64 hadron selection algorithm 'abortnow' fixed.
** unlisted
Top/LeptonDalitzAnalysis removed (only worked with modified code).
** unlisted
removed f'_0 from particle list, decays were not handled
* Herwig++-2.0.0 release: 2006-09-28 (tagged at SVN r1066)
** Full simulation of hadron collisions
diff --git a/Shower/Base/Evolver.cc b/Shower/Base/Evolver.cc
--- a/Shower/Base/Evolver.cc
+++ b/Shower/Base/Evolver.cc
@@ -1,3184 +1,3222 @@
// -*- C++ -*-
//
// Evolver.cc is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the Evolver class.
//
#include "Evolver.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/RefVector.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "Herwig/Shower/Base/ShowerParticle.h"
#include "ThePEG/Utilities/EnumIO.h"
#include "ShowerKinematics.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Handlers/EventHandler.h"
#include "ThePEG/Utilities/Throw.h"
#include "ShowerTree.h"
#include "ShowerProgenitor.h"
#include "KinematicsReconstructor.h"
#include "PartnerFinder.h"
#include "ThePEG/Handlers/StandardXComb.h"
#include "ThePEG/PDT/DecayMode.h"
#include "Herwig/Shower/ShowerHandler.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ShowerVertex.h"
#include "ThePEG/Repository/CurrentGenerator.h"
#include "Herwig/MatrixElement/Matchbox/Base/SubtractedME.h"
#include "Herwig/MatrixElement/Matchbox/MatchboxFactory.h"
#include "ThePEG/Handlers/StandardXComb.h"
using namespace Herwig;
namespace {
/**
* A struct to order the particles in the same way as in the DecayMode's
*/
struct ParticleOrdering {
/**
* Operator for the ordering
* @param p1 The first ParticleData object
* @param p2 The second ParticleData object
*/
bool operator() (tcPDPtr p1, tcPDPtr p2) {
return abs(p1->id()) > abs(p2->id()) ||
( abs(p1->id()) == abs(p2->id()) && p1->id() > p2->id() ) ||
( p1->id() == p2->id() && p1->fullName() > p2->fullName() );
}
};
typedef multiset<tcPDPtr,ParticleOrdering> OrderedParticles;
/**
* Cached lookup of decay modes.
* Generator::findDecayMode() is not efficient.
*/
tDMPtr findDecayMode(const string & tag) {
static map<string,DMPtr> cache;
map<string,DMPtr>::const_iterator pos = cache.find(tag);
if ( pos != cache.end() )
return pos->second;
tDMPtr dm = CurrentGenerator::current().findDecayMode(tag);
cache[tag] = dm;
return dm;
}
}
DescribeClass<Evolver,Interfaced>
describeEvolver ("Herwig::Evolver","HwShower.so");
bool Evolver::_hardEmissionModeWarn = true;
bool Evolver::_missingTruncWarn = true;
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 << _spinOpt << _softOpt << _hardPOWHEG
<< ounit(_iptrms,GeV) << _beta << ounit(_gamma,GeV) << ounit(_iptmax,GeV)
<< _vetoes << _trunc_Mode << _hardEmissionMode << _reconOpt
<< _massVetoOption << isMCatNLOSEvent << isMCatNLOHEvent
<< isPowhegSEvent << isPowhegHEvent
- << theFactorizationScaleFactor << theRenormalizationScaleFactor
- << interaction_<< interactions_.size();
+ << theFactorizationScaleFactor << theRenormalizationScaleFactor << ounit(muPt,GeV)
+ << interaction_ << _maxTryFSR << _maxFailFSR << _fracFSR << interactions_.size();
for(unsigned int ix=0;ix<interactions_.size();++ix)
os << oenum(interactions_[ix]);
}
void Evolver::persistentInput(PersistentIStream & is, int) {
unsigned int isize;
is >> _model >> _splittingGenerator >> _maxtry
>> _meCorrMode >> _hardVetoMode >> _hardVetoRead >> _hardVetoReadOption
>> _limitEmissions >> _spinOpt >> _softOpt >> _hardPOWHEG
>> iunit(_iptrms,GeV) >> _beta >> iunit(_gamma,GeV) >> iunit(_iptmax,GeV)
>> _vetoes >> _trunc_Mode >> _hardEmissionMode >> _reconOpt
>> _massVetoOption >> isMCatNLOSEvent >> isMCatNLOHEvent
>> isPowhegSEvent >> isPowhegHEvent
- >> theFactorizationScaleFactor >> theRenormalizationScaleFactor
- >> interaction_ >> isize;
+ >> theFactorizationScaleFactor >> theRenormalizationScaleFactor >> iunit(muPt,GeV)
+ >> interaction_ >> _maxTryFSR >> _maxFailFSR >> _fracFSR >> isize;
interactions_.resize(isize);
for(unsigned int ix=0;ix<interactions_.size();++ix)
is >> ienum(interactions_[ix]);
}
void Evolver::doinit() {
Interfaced::doinit();
// interactions may have been changed through a setup file so we
// clear it up here
interactions_.clear();
if(interaction_==0) {
interactions_.push_back(ShowerInteraction::QCD);
interactions_.push_back(ShowerInteraction::QED);
}
else if(interaction_==1) {
interactions_.push_back(ShowerInteraction::QCD);
}
else if(interaction_==2) {
interactions_.push_back(ShowerInteraction::QED);
interactions_.push_back(ShowerInteraction::QCD);
}
else if(interaction_==3) {
interactions_.push_back(ShowerInteraction::QED);
}
else if(interaction_==4) {
interactions_.push_back(ShowerInteraction::Both);
}
+ // calculate max no of FSR vetos
+ _maxFailFSR = max(int(_maxFailFSR), int(_fracFSR*double(generator()->N())));
}
void Evolver::Init() {
static ClassDocumentation<Evolver> documentation
("This class is responsible for carrying out the showering,",
"including the kinematics reconstruction, in a given scale range,"
"including the option of the POWHEG approach to simulated next-to-leading order"
" radiation\\cite{Nason:2004rx}.",
"%\\cite{Nason:2004rx}\n"
"\\bibitem{Nason:2004rx}\n"
" P.~Nason,\n"
" ``A new method for combining NLO QCD with shower Monte Carlo algorithms,''\n"
" JHEP {\\bf 0411} (2004) 040\n"
" [arXiv:hep-ph/0409146].\n"
" %%CITATION = JHEPA,0411,040;%%\n");
static Reference<Evolver,SplittingGenerator>
interfaceSplitGen("SplittingGenerator",
"A reference to the SplittingGenerator object",
&Herwig::Evolver::_splittingGenerator,
false, false, true, false);
static Reference<Evolver,ShowerModel> interfaceShowerModel
("ShowerModel",
"The pointer to the object which defines the shower evolution model.",
&Evolver::_model, false, false, true, false, false);
static Parameter<Evolver,unsigned int> interfaceMaxTry
("MaxTry",
"The maximum number of attempts to generate the shower from a"
" particular ShowerTree",
&Evolver::_maxtry, 100, 1, 1000,
false, false, Interface::limited);
static Switch<Evolver, unsigned int> ifaceMECorrMode
("MECorrMode",
"Choice of the ME Correction Mode",
&Evolver::_meCorrMode, 1, false, false);
static SwitchOption off
(ifaceMECorrMode,"No","MECorrections off", 0);
static SwitchOption on
(ifaceMECorrMode,"Yes","hard+soft on", 1);
static SwitchOption hard
(ifaceMECorrMode,"Hard","only hard on", 2);
static SwitchOption soft
(ifaceMECorrMode,"Soft","only soft on", 3);
static Switch<Evolver, unsigned int> ifaceHardVetoMode
("HardVetoMode",
"Choice of the Hard Veto Mode",
&Evolver::_hardVetoMode, 1, false, false);
static SwitchOption HVoff
(ifaceHardVetoMode,"No","hard vetos off", 0);
static SwitchOption HVon
(ifaceHardVetoMode,"Yes","hard vetos on", 1);
static SwitchOption HVIS
(ifaceHardVetoMode,"Initial", "only IS emissions vetoed", 2);
static SwitchOption HVFS
(ifaceHardVetoMode,"Final","only FS emissions vetoed", 3);
static Switch<Evolver, unsigned int> ifaceHardVetoRead
("HardVetoScaleSource",
"If hard veto scale is to be read",
&Evolver::_hardVetoRead, 0, false, false);
static SwitchOption HVRcalc
(ifaceHardVetoRead,"Calculate","Calculate from hard process", 0);
static SwitchOption HVRread
(ifaceHardVetoRead,"Read","Read from XComb->lastScale", 1);
static Switch<Evolver, bool> ifaceHardVetoReadOption
("HardVetoReadOption",
"Apply read-in scale veto to all collisions or just the primary one?",
&Evolver::_hardVetoReadOption, false, false, false);
static SwitchOption AllCollisions
(ifaceHardVetoReadOption,
"AllCollisions",
"Read-in pT veto applied to primary and secondary collisions.",
false);
static SwitchOption PrimaryCollision
(ifaceHardVetoReadOption,
"PrimaryCollision",
"Read-in pT veto applied to primary but not secondary collisions.",
true);
static Parameter<Evolver, Energy> ifaceiptrms
("IntrinsicPtGaussian",
"RMS of intrinsic pT of Gaussian distribution:\n"
"2*(1-Beta)*exp(-sqr(intrinsicpT/RMS))/sqr(RMS)",
&Evolver::_iptrms, GeV, ZERO, ZERO, 1000000.0*GeV,
false, false, Interface::limited);
static Parameter<Evolver, double> ifacebeta
("IntrinsicPtBeta",
"Proportion of inverse quadratic distribution in generating intrinsic pT.\n"
"(1-Beta) is the proportion of Gaussian distribution",
&Evolver::_beta, 0, 0, 1,
false, false, Interface::limited);
static Parameter<Evolver, Energy> ifacegamma
("IntrinsicPtGamma",
"Parameter for inverse quadratic:\n"
"2*Beta*Gamma/(sqr(Gamma)+sqr(intrinsicpT))",
&Evolver::_gamma,GeV, ZERO, ZERO, 100000.0*GeV,
false, false, Interface::limited);
static Parameter<Evolver, Energy> ifaceiptmax
("IntrinsicPtIptmax",
"Upper bound on intrinsic pT for inverse quadratic",
&Evolver::_iptmax,GeV, ZERO, ZERO, 100000.0*GeV,
false, false, Interface::limited);
static RefVector<Evolver,ShowerVeto> ifaceVetoes
("Vetoes",
"The vetoes to be checked during showering",
&Evolver::_vetoes, -1,
false,false,true,true,false);
static Switch<Evolver,unsigned int> interfaceLimitEmissions
("LimitEmissions",
"Limit the number and type of emissions for testing",
&Evolver::_limitEmissions, 0, false, false);
static SwitchOption interfaceLimitEmissionsNoLimit
(interfaceLimitEmissions,
"NoLimit",
"Allow an arbitrary number of emissions",
0);
static SwitchOption interfaceLimitEmissionsOneInitialStateEmission
(interfaceLimitEmissions,
"OneInitialStateEmission",
"Allow one emission in the initial state and none in the final state",
1);
static SwitchOption interfaceLimitEmissionsOneFinalStateEmission
(interfaceLimitEmissions,
"OneFinalStateEmission",
"Allow one emission in the final state and none in the initial state",
2);
static SwitchOption interfaceLimitEmissionsHardOnly
(interfaceLimitEmissions,
"HardOnly",
"Only allow radiation from the hard ME correction",
3);
static SwitchOption interfaceLimitEmissionsOneEmission
(interfaceLimitEmissions,
"OneEmission",
"Allow one emission in either the final state or initial state, but not both",
4);
static Switch<Evolver,bool> interfaceTruncMode
("TruncatedShower", "Include the truncated shower?",
&Evolver::_trunc_Mode, 1, false, false);
static SwitchOption interfaceTruncMode0
(interfaceTruncMode,"No","Truncated Shower is OFF", 0);
static SwitchOption interfaceTruncMode1
(interfaceTruncMode,"Yes","Truncated Shower is ON", 1);
static Switch<Evolver,int> interfaceHardEmissionMode
("HardEmissionMode",
"Whether to use ME corrections or POWHEG for the hardest emission",
&Evolver::_hardEmissionMode, 0, false, false);
static SwitchOption interfaceHardEmissionModeDecayMECorrection
(interfaceHardEmissionMode,
"DecayMECorrection",
"Old fashioned ME correction for decays only",
-1);
static SwitchOption interfaceHardEmissionModeMECorrection
(interfaceHardEmissionMode,
"MECorrection",
"Old fashioned ME correction",
0);
static SwitchOption interfaceHardEmissionModePOWHEG
(interfaceHardEmissionMode,
"POWHEG",
"Powheg style hard emission using internal matrix elements",
1);
static SwitchOption interfaceHardEmissionModeMatchboxPOWHEG
(interfaceHardEmissionMode,
"MatchboxPOWHEG",
"Powheg style emission for the hard process using Matchbox",
2);
static SwitchOption interfaceHardEmissionModeFullPOWHEG
(interfaceHardEmissionMode,
"FullPOWHEG",
"Powheg style emission for the hard process using Matchbox "
"and decays using internal matrix elements",
3);
static Switch<Evolver,unsigned int > interfaceInteractions
("Interactions",
"The interactions to be used in the shower",
&Evolver::interaction_, 1, false, false);
static SwitchOption interfaceInteractionsQCDFirst
(interfaceInteractions,
"QCDFirst",
"QCD first then QED",
0);
static SwitchOption interfaceInteractionsQCDOnly
(interfaceInteractions,
"QCDOnly",
"Only QCD",
1);
static SwitchOption interfaceInteractionsQEDFirst
(interfaceInteractions,
"QEDFirst",
"QED first then QCD",
2);
static SwitchOption interfaceInteractionsQEDOnly
(interfaceInteractions,
"QEDOnly",
"Only QED",
3);
static SwitchOption interfaceInteractionsBothAtOnce
(interfaceInteractions,
"BothAtOnce",
"Generate both at the same time",
4);
static Switch<Evolver,unsigned int> interfaceReconstructionOption
("ReconstructionOption",
"Treatment of the reconstruction of the transverse momentum of "
"a branching from the evolution scale.",
&Evolver::_reconOpt, 0, false, false);
static SwitchOption interfaceReconstructionOptionCutOff
(interfaceReconstructionOption,
"CutOff",
"Use the cut-off masses in the calculation",
0);
static SwitchOption interfaceReconstructionOptionOffShell
(interfaceReconstructionOption,
"OffShell",
"Use the off-shell masses in the calculation",
1);
static SwitchOption interfaceReconstructionOptionOffShell2
(interfaceReconstructionOption,
"OffShell2",
"Use the off-shell masses in the calculation but only locally for each branching",
2);
static Switch<Evolver,unsigned int> interfaceMassVetoOption
("MassVetoOption",
"Option for the handling of the mass vetos",
&Evolver::_massVetoOption, 1, false, false);
static SwitchOption interfaceMassVetoOptionReset
(interfaceMassVetoOption,
"Reset",
"Try another branching without resetting the starting scale",
0);
static SwitchOption interfaceMassVetoOptionInclude
(interfaceMassVetoOption,
"Include",
"Include the veto in the scale generation via the veto algorithm",
1);
static Switch<Evolver,unsigned int> interfaceSpinCorrelations
("SpinCorrelations",
"Treatment of spin correlations in the parton shower",
&Evolver::_spinOpt, 1, false, false);
static SwitchOption interfaceSpinCorrelationsOff
(interfaceSpinCorrelations,
"No",
"No spin correlations",
0);
static SwitchOption interfaceSpinCorrelationsSpin
(interfaceSpinCorrelations,
"Yes",
"Include the azimuthal spin correlations only",
1);
static Switch<Evolver,unsigned int> interfaceSoftCorrelations
("SoftCorrelations",
"Option for the treatment of soft correlations in the parton shower",
&Evolver::_softOpt, 2, false, false);
static SwitchOption interfaceSoftCorrelationsNone
(interfaceSoftCorrelations,
"No",
"No soft correlations",
0);
static SwitchOption interfaceSoftCorrelationsFull
(interfaceSoftCorrelations,
"Full",
"Use the full eikonal",
1);
static SwitchOption interfaceSoftCorrelationsSingular
(interfaceSoftCorrelations,
"Singular",
"Use original Webber-Marchisini form",
2);
static Switch<Evolver,bool> interfaceHardPOWHEG
("HardPOWHEG",
"Treatment of powheg emissions which are too hard to have a shower interpretation",
&Evolver::_hardPOWHEG, false, false, false);
static SwitchOption interfaceHardPOWHEGAsShower
(interfaceHardPOWHEG,
"AsShower",
"Still interpret as shower emissions",
false);
static SwitchOption interfaceHardPOWHEGRealEmission
(interfaceHardPOWHEG,
"RealEmission",
"Generate shower from the real emmission configuration",
true);
+ static Parameter<Evolver,unsigned int> interfaceMaxTryFSR
+ ("MaxTryFSR",
+ "The maximum number of attempted FSR emissions in"
+ " the generation of the FSR",
+ &Evolver::_maxTryFSR, 100000, 10, 100000000,
+ false, false, Interface::limited);
+
+ static Parameter<Evolver,unsigned int> interfaceMaxFailFSR
+ ("MaxFailFSR",
+ "Maximum number of failures generating the FSR",
+ &Evolver::_maxFailFSR, 100, 1, 100000000,
+ false, false, Interface::limited);
+
+
+ static Parameter<Evolver,double> interfaceFSRFailureFraction
+ ("FSRFailureFraction",
+ "Maximum fraction of events allowed to fail due to too many FSR emissions",
+ &Evolver::_fracFSR, 0.001, 1e-10, 1,
+ false, false, Interface::limited);
}
void Evolver::generateIntrinsicpT(vector<ShowerProgenitorPtr> particlesToShower) {
_intrinsic.clear();
if ( !ipTon() || !isISRadiationON() ) return;
// don't do anything for the moment for secondary scatters
if( !ShowerHandler::currentHandler()->firstInteraction() ) return;
// generate intrinsic pT
for(unsigned int ix=0;ix<particlesToShower.size();++ix) {
// only consider initial-state particles
if(particlesToShower[ix]->progenitor()->isFinalState()) continue;
if(!particlesToShower[ix]->progenitor()->dataPtr()->coloured()) continue;
Energy ipt;
if(UseRandom::rnd() > _beta) {
ipt=_iptrms*sqrt(-log(UseRandom::rnd()));
}
else {
ipt=_gamma*sqrt(pow(1.+sqr(_iptmax/_gamma), UseRandom::rnd())-1.);
}
pair<Energy,double> pt = make_pair(ipt,UseRandom::rnd(Constants::twopi));
_intrinsic[particlesToShower[ix]] = pt;
}
}
void Evolver::setupMaximumScales(const vector<ShowerProgenitorPtr> & p,
XCPtr xcomb) {
// let POWHEG events radiate freely
if(_hardEmissionMode>0&&hardTree()) {
vector<ShowerProgenitorPtr>::const_iterator ckt = p.begin();
for (; ckt != p.end(); ckt++) (*ckt)->maxHardPt(Constants::MaxEnergy);
return;
}
// return if no vetos
if (!hardVetoOn()) return;
// find out if hard partonic subprocess.
bool isPartonic(false);
map<ShowerProgenitorPtr,ShowerParticlePtr>::const_iterator
cit = _currenttree->incomingLines().begin();
Lorentz5Momentum pcm;
for(; cit!=currentTree()->incomingLines().end(); ++cit) {
pcm += cit->first->progenitor()->momentum();
isPartonic |= cit->first->progenitor()->coloured();
}
// find minimum 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 = generator()->maximumCMEnergy();
// general case calculate the scale
if (!hardVetoXComb()||
(hardVetoReadOption()&&
!ShowerHandler::currentHandler()->firstInteraction())) {
// scattering process
if(currentTree()->isHard()) {
assert(xcomb);
// coloured incoming particles
if (isPartonic) {
map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator
cjt = currentTree()->outgoingLines().begin();
for(; cjt!=currentTree()->outgoingLines().end(); ++cjt) {
if (cjt->first->progenitor()->coloured())
ptmax = min(ptmax,cjt->first->progenitor()->momentum().mt());
}
}
if (ptmax == generator()->maximumCMEnergy() ) ptmax = pcm.m();
if(hardVetoXComb()&&hardVetoReadOption()&&
!ShowerHandler::currentHandler()->firstInteraction()) {
ptmax=min(ptmax,sqrt(xcomb->lastCentralScale()));
}
}
// decay, incoming() is the decaying particle.
else {
ptmax = currentTree()->incomingLines().begin()->first
->progenitor()->momentum().mass();
}
}
// hepeup.SCALUP is written into the lastXComb by the
// LesHouchesReader itself - use this by user's choice.
// Can be more general than this.
else {
if(currentTree()->isHard()) {
assert(xcomb);
ptmax = sqrt( xcomb->lastCentralScale() );
}
else {
ptmax = currentTree()->incomingLines().begin()->first
->progenitor()->momentum().mass();
}
}
ptmax *= ShowerHandler::currentHandler()->hardScaleFactor();
// set maxHardPt for all progenitors. For partonic processes this
// is now the max pt in the FS, for non-partonic processes or
// processes with no coloured FS the invariant mass of the IS
vector<ShowerProgenitorPtr>::const_iterator ckt = p.begin();
for (; ckt != p.end(); ckt++) (*ckt)->maxHardPt(ptmax);
}
void Evolver::setupHardScales(const vector<ShowerProgenitorPtr> & p,
XCPtr xcomb) {
if ( hardVetoXComb() &&
(!hardVetoReadOption() ||
ShowerHandler::currentHandler()->firstInteraction()) ) {
Energy hardScale = ZERO;
if(currentTree()->isHard()) {
assert(xcomb);
hardScale = sqrt( xcomb->lastCentralScale() );
}
else {
hardScale = currentTree()->incomingLines().begin()->first
->progenitor()->momentum().mass();
}
hardScale *= ShowerHandler::currentHandler()->hardScaleFactor();
vector<ShowerProgenitorPtr>::const_iterator ckt = p.begin();
for (; ckt != p.end(); ckt++) (*ckt)->hardScale(hardScale);
+ muPt = hardScale;
}
}
void Evolver::showerHardProcess(ShowerTreePtr hard, XCPtr xcomb) {
isMCatNLOSEvent = false;
isMCatNLOHEvent = false;
isPowhegSEvent = false;
isPowhegHEvent = false;
Ptr<SubtractedME>::tptr subme;
Ptr<MatchboxMEBase>::tptr me;
Ptr<SubtractionDipole>::tptr dipme;
Ptr<StandardXComb>::ptr sxc = dynamic_ptr_cast<Ptr<StandardXComb>::ptr>(xcomb);
if ( sxc ) {
subme = dynamic_ptr_cast<Ptr<SubtractedME>::tptr>(sxc->matrixElement());
me = dynamic_ptr_cast<Ptr<MatchboxMEBase>::tptr>(sxc->matrixElement());
dipme = dynamic_ptr_cast<Ptr<SubtractionDipole>::tptr>(sxc->matrixElement());
}
if ( subme ) {
if ( subme->showerApproximation() ) {
theShowerApproximation = subme->showerApproximation();
// separate MCatNLO and POWHEG-type corrections
if ( !subme->showerApproximation()->needsSplittingGenerator() ) {
if ( subme->realShowerSubtraction() )
isMCatNLOHEvent = true;
else if ( subme->virtualShowerSubtraction() )
isMCatNLOSEvent = true;
}
else {
if ( subme->realShowerSubtraction() )
isPowhegHEvent = true;
else if ( subme->virtualShowerSubtraction() || subme->loopSimSubtraction() )
isPowhegSEvent = true;
}
}
} else if ( me ) {
if ( me->factory()->showerApproximation() ) {
theShowerApproximation = me->factory()->showerApproximation();
if ( !me->factory()->showerApproximation()->needsSplittingGenerator() )
isMCatNLOSEvent = true;
else
isPowhegSEvent = true;
}
}
string error = "Inconsistent hard emission set-up in Evolver::showerHardProcess(). ";
if ( ( isMCatNLOSEvent || isMCatNLOHEvent ) ){
if (_hardEmissionMode > 1)
throw Exception() << error
<< "Cannot generate POWHEG matching with MC@NLO shower "
<< "approximation. Add 'set Evolver:HardEmissionMode 0' to input file."
<< Exception::runerror;
if ( ShowerHandler::currentHandler()->canHandleMatchboxTrunc())
throw Exception() << error
<< "Cannot use truncated qtilde shower with MC@NLO shower "
<< "approximation. Set LHCGenerator:EventHandler"
<< ":CascadeHandler to '/Herwig/Shower/ShowerHandler' or "
<< "'/Herwig/DipoleShower/DipoleShowerHandler'."
<< Exception::runerror;
}
else if ( ((isPowhegSEvent || isPowhegHEvent) || dipme) &&
_hardEmissionMode < 2){
if ( ShowerHandler::currentHandler()->canHandleMatchboxTrunc())
throw Exception() << error
<< "Unmatched events requested for POWHEG shower "
<< "approximation. Set Evolver:HardEmissionMode to "
<< "'MatchboxPOWHEG' or 'FullPOWHEG'."
<< Exception::runerror;
else if (_hardEmissionModeWarn){
_hardEmissionModeWarn = false;
_hardEmissionMode+=2;
throw Exception() << error
<< "Unmatched events requested for POWHEG shower "
<< "approximation. Changing Evolver:HardEmissionMode from "
<< _hardEmissionMode-2 << " to " << _hardEmissionMode
<< Exception::warning;
}
}
if ( isPowhegSEvent || isPowhegHEvent) {
if (theShowerApproximation->needsTruncatedShower() &&
!ShowerHandler::currentHandler()->canHandleMatchboxTrunc() )
throw Exception() << error
<< "Current shower handler cannot generate truncated shower. "
<< "Set Generator:EventHandler:CascadeHandler to "
<< "'/Herwig/Shower/PowhegShowerHandler'."
<< Exception::runerror;
}
else if ( dipme && _missingTruncWarn){
_missingTruncWarn=false;
throw Exception() << "Warning: POWHEG shower approximation used without "
<< "truncated shower. Set Generator:EventHandler:"
<< "CascadeHandler to '/Herwig/Shower/PowhegShowerHandler' and "
<< "'MEMatching:TruncatedShower Yes'."
<< Exception::warning;
}
else if ( !dipme && _hardEmissionMode > 1 &&
ShowerHandler::currentHandler()->firstInteraction())
throw Exception() << error
<< "POWHEG matching requested for LO events. Include "
<< "'set Factory:ShowerApproximation MEMatching' in input file."
<< Exception::runerror;
_hardme = HwMEBasePtr();
// extract the matrix element
tStdXCombPtr lastXC = dynamic_ptr_cast<tStdXCombPtr>(xcomb);
if(lastXC) {
_hardme = dynamic_ptr_cast<HwMEBasePtr>(lastXC->matrixElement());
}
_decayme = HwDecayerBasePtr();
// set the current tree
currentTree(hard);
hardTree(HardTreePtr());
// number of attempts if more than one interaction switched on
unsigned int interactionTry=0;
do {
try {
// generate the showering
doShowering(true,xcomb);
// if no vetos return
return;
}
catch (InteractionVeto) {
currentTree()->clear();
++interactionTry;
}
}
while(interactionTry<=5);
throw Exception() << "Too many tries for shower in "
<< "Evolver::showerHardProcess()"
<< Exception::eventerror;
}
void Evolver::hardMatrixElementCorrection(bool hard) {
// set the initial enhancement factors for the soft correction
_initialenhance = 1.;
_finalenhance = 1.;
// if hard matrix element switched off return
if(!MECOn(hard)) 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(hard))
_hardme->applyHardMatrixElementCorrection(_currenttree);
}
}
else {
if(_decayme&&_decayme->hasMECorrection()) {
_decayme->initializeMECorrection(_currenttree,
_initialenhance,_finalenhance);
if(hardMEC(hard))
_decayme->applyHardMatrixElementCorrection(_currenttree);
}
}
}
Branching Evolver::selectTimeLikeBranching(tShowerParticlePtr particle,
ShowerInteraction::Type type) {
Branching fb;
while (true) {
fb=_splittingGenerator->chooseForwardBranching(*particle,_finalenhance,type);
// no emission return
if(!fb.kinematics) return fb;
// if emission OK break
if(!timeLikeVetoed(fb,particle)) break;
// otherwise reset scale and continue - SO IS involved in veto algorithm
particle->vetoEmission(fb.type,fb.kinematics->scale());
if(particle->spinInfo()) particle->spinInfo()->decayVertex(VertexPtr());
}
return fb;
}
ShowerParticleVector Evolver::createTimeLikeChildren(tShowerParticlePtr particle, IdList ids) {
// 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(ids[ix+1]);
if(particle->id()!=ids[0]) {
for(unsigned int ix=0;ix<2;++ix) {
tPDPtr cc(pdata[ix]->CC());
if(cc) pdata[ix]=cc;
}
}
ShowerParticleVector children;
for(unsigned int ix=0;ix<2;++ix) {
children.push_back(new_ptr(ShowerParticle(pdata[ix],true)));
if(children[ix]->id()==_progenitor->id()&&!pdata[ix]->stable())
children[ix]->set5Momentum(Lorentz5Momentum(_progenitor->progenitor()->mass()));
else
children[ix]->set5Momentum(Lorentz5Momentum(pdata[ix]->mass()));
}
return children;
}
bool Evolver::timeLikeShower(tShowerParticlePtr particle,
ShowerInteraction::Type type,
Branching fb, bool first) {
// don't do anything if not needed
if(_limitEmissions == 1 || hardOnly() ||
( _limitEmissions == 2 && _nfs != 0) ||
( _limitEmissions == 4 && _nfs + _nis != 0) ) {
if(particle->spinInfo()) particle->spinInfo()->develop();
return false;
}
+ // too many tries
+ if(_nFSR>=_maxTryFSR) {
+ ++_nFailedFSR;
+ // too many failed events
+ if(_nFailedFSR>=_maxFailFSR)
+ throw Exception() << "Too many events have failed due to too many shower emissions, in\n"
+ << "Evolver::timeLikeShower(). Terminating run\n"
+ << Exception::runerror;
+ throw Exception() << "Too many attempted emissions in Evolver::timeLikeShower()\n"
+ << Exception::eventerror;
+ }
+ // generate the emission
ShowerParticleVector children;
int ntry=0;
while (ntry<50) {
++ntry;
// generate the emission
if(!fb.kinematics)
fb = selectTimeLikeBranching(particle,type);
// no emission, return
if(!fb.kinematics) {
if(particle->spinInfo()) particle->spinInfo()->develop();
return false;
}
// has emitted
// Assign the shower kinematics to the emitting particle.
+ ++_nFSR;
particle->showerKinematics(fb.kinematics);
// generate phi
fb.kinematics->phi(fb.sudakov->generatePhiForward(*particle,fb.ids,fb.kinematics));
// check highest pT
if(fb.kinematics->pT()>progenitor()->highestpT())
progenitor()->highestpT(fb.kinematics->pT());
// create the children
children = createTimeLikeChildren(particle,fb.ids);
// update the children
particle->showerKinematics()->
updateChildren(particle, children,fb.type);
// update number of emissions
++_nfs;
if(_limitEmissions!=0) {
if(children[0]->spinInfo()) children[0]->spinInfo()->develop();
if(children[1]->spinInfo()) children[1]->spinInfo()->develop();
if(particle->spinInfo()) particle->spinInfo()->develop();
return true;
}
// select branchings for children
Branching fc[2] = {selectTimeLikeBranching(children[0],type),
selectTimeLikeBranching(children[1],type)};
// old recon option
if(_reconOpt==0) {
// shower the first particle
if(fc[0].kinematics) timeLikeShower(children[0],type,fc[0],false);
if(children[0]->spinInfo()) children[0]->spinInfo()->develop();
// shower the second particle
if(fc[1].kinematics) timeLikeShower(children[1],type,fc[1],false);
if(children[1]->spinInfo()) children[1]->spinInfo()->develop();
}
else if(_reconOpt==1) {
// shower the first particle
if(fc[0].kinematics) timeLikeShower(children[0],type,fc[0],false);
if(children[0]->spinInfo()) children[0]->spinInfo()->develop();
// shower the second particle
if(fc[1].kinematics) timeLikeShower(children[1],type,fc[1],false);
if(children[1]->spinInfo()) children[1]->spinInfo()->develop();
// branching has happened
particle->showerKinematics()->
updateParent(particle, children,fb.type);
// clean up the vetoed emission
if(particle->virtualMass()==ZERO) {
particle->showerKinematics(ShoKinPtr());
for(unsigned int ix=0;ix<children.size();++ix)
particle->abandonChild(children[ix]);
children.clear();
if(particle->spinInfo()) particle->spinInfo()->decayVertex(VertexPtr());
if(_massVetoOption==1) particle->vetoEmission(fb.type,fb.kinematics->scale());
fb = Branching();
continue;
}
}
else if(_reconOpt==2) {
// cut-off masses for the branching
const vector<Energy> & virtualMasses = fb.sudakov->virtualMasses(fb.ids);
// compute the masses of the children
Energy masses[3];
for(unsigned int ix=0;ix<2;++ix) {
if(fc[ix].kinematics) {
const vector<Energy> & vm = fc[ix].sudakov->virtualMasses(fc[ix].ids);
Energy2 q2 =
fc[ix].kinematics->z()*(1.-fc[ix].kinematics->z())*sqr(fc[ix].kinematics->scale());
if(fc[ix].ids[0]!=ParticleID::g) q2 += sqr(vm[0]);
masses[ix+1] = sqrt(q2);
}
else {
masses[ix+1] = virtualMasses[ix+1];
}
}
masses[0] = fb.ids[0]!=ParticleID::g ? virtualMasses[0] : ZERO;
double z = fb.kinematics->z();
Energy2 pt2 = z*(1.-z)*(z*(1.-z)*sqr(fb.kinematics->scale())
+sqr(masses[0]))
- sqr(masses[1])*(1.-z) - sqr(masses[2])*z;
if(pt2>=ZERO) {
// branching has happened
particle->showerKinematics()->
updateParent(particle, children,fb.type);
// shower the first particle
if(fc[0].kinematics) timeLikeShower(children[0],type,fc[0],false);
if(children[0]->spinInfo()) children[0]->spinInfo()->develop();
// shower the second particle
if(fc[1].kinematics) timeLikeShower(children[1],type,fc[1],false);
if(children[1]->spinInfo()) children[1]->spinInfo()->develop();
}
else {
particle->showerKinematics(ShoKinPtr());
for(unsigned int ix=0;ix<children.size();++ix)
particle->abandonChild(children[ix]);
children.clear();
if(_massVetoOption==1) particle->vetoEmission(fb.type,fb.kinematics->scale());
if(particle->spinInfo()) particle->spinInfo()->decayVertex(VertexPtr());
fb = Branching();
continue;
}
}
break;
};
if(first&&!children.empty())
particle->showerKinematics()->resetChildren(particle,children);
if(particle->spinInfo()) particle->spinInfo()->develop();
return true;
}
bool
Evolver::spaceLikeShower(tShowerParticlePtr particle, PPtr beam,
ShowerInteraction::Type type) {
//using the pdf's associated with the ShowerHandler assures, that
//modified pdf's are used for the secondary interactions via
//CascadeHandler::resetPDFs(...)
tcPDFPtr pdf;
if(ShowerHandler::currentHandler()->firstPDF().particle() == _beam)
pdf = ShowerHandler::currentHandler()->firstPDF().pdf();
if(ShowerHandler::currentHandler()->secondPDF().particle() == _beam)
pdf = ShowerHandler::currentHandler()->secondPDF().pdf();
Energy freeze = ShowerHandler::currentHandler()->pdfFreezingScale();
// don't do anything if not needed
if(_limitEmissions == 2 || hardOnly() ||
( _limitEmissions == 1 && _nis != 0 ) ||
( _limitEmissions == 4 && _nis + _nfs != 0 ) ) {
if(particle->spinInfo()) particle->spinInfo()->develop();
return false;
}
Branching bb;
// generate branching
while (true) {
bb=_splittingGenerator->chooseBackwardBranching(*particle,beam,
_initialenhance,
_beam,type,
pdf,freeze);
// return if no emission
if(!bb.kinematics) {
if(particle->spinInfo()) particle->spinInfo()->develop();
return false;
}
// if not vetoed break
if(!spaceLikeVetoed(bb,particle)) break;
// otherwise reset scale and continue
particle->vetoEmission(bb.type,bb.kinematics->scale());
if(particle->spinInfo()) particle->spinInfo()->decayVertex(VertexPtr());
}
// assign the splitting function and shower kinematics
particle->showerKinematics(bb.kinematics);
if(bb.kinematics->pT()>progenitor()->highestpT())
progenitor()->highestpT(bb.kinematics->pT());
// For the time being we are considering only 1->2 branching
// particles as in Sudakov form factor
tcPDPtr part[2]={getParticleData(bb.ids[0]),
getParticleData(bb.ids[2])};
if(particle->id()!=bb.ids[1]) {
if(part[0]->CC()) part[0]=part[0]->CC();
if(part[1]->CC()) part[1]=part[1]->CC();
}
// Now create the actual particles, make the otherChild a final state
// particle, while the newParent is not
ShowerParticlePtr newParent=new_ptr(ShowerParticle(part[0],false));
ShowerParticlePtr otherChild = new_ptr(ShowerParticle(part[1],true,true));
ShowerParticleVector theChildren;
theChildren.push_back(particle);
theChildren.push_back(otherChild);
//this updates the evolution scale
particle->showerKinematics()->
updateParent(newParent, theChildren,bb.type);
// update the history if needed
_currenttree->updateInitialStateShowerProduct(_progenitor,newParent);
_currenttree->addInitialStateBranching(particle,newParent,otherChild);
// for the reconstruction of kinematics, parent/child
// relationships are according to the branching process:
// now continue the shower
++_nis;
bool emitted = _limitEmissions==0 ?
spaceLikeShower(newParent,beam,type) : false;
if(newParent->spinInfo()) newParent->spinInfo()->develop();
// now reconstruct the momentum
if(!emitted) {
if(_intrinsic.find(_progenitor)==_intrinsic.end()) {
bb.kinematics->updateLast(newParent,ZERO,ZERO);
}
else {
pair<Energy,double> kt=_intrinsic[_progenitor];
bb.kinematics->updateLast(newParent,
kt.first*cos(kt.second),
kt.first*sin(kt.second));
}
}
particle->showerKinematics()->
updateChildren(newParent, theChildren,bb.type);
if(_limitEmissions!=0) {
if(particle->spinInfo()) particle->spinInfo()->develop();
return true;
}
// perform the shower of the final-state particle
timeLikeShower(otherChild,type,Branching(),true);
updateHistory(otherChild);
if(theChildren[1]->spinInfo()) theChildren[1]->spinInfo()->develop();
// return the emitted
if(particle->spinInfo()) particle->spinInfo()->develop();
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()
+ "->";
OrderedParticles outgoing;
for(map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator
it=decay->outgoingLines().begin();it!=decay->outgoingLines().end();++it) {
if(abs(decay->incomingLines().begin()->first->original()->id()) == ParticleID::t &&
abs(it->first->original()->id())==ParticleID::Wplus &&
decay->treelinks().size() == 1) {
ShowerTreePtr Wtree = decay->treelinks().begin()->first;
for(map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator
it2=Wtree->outgoingLines().begin();it2!=Wtree->outgoingLines().end();++it2) {
outgoing.insert(it2->first->original()->dataPtr());
}
}
else {
outgoing.insert(it->first->original()->dataPtr());
}
}
for(OrderedParticles::const_iterator it=outgoing.begin(); it!=outgoing.end();++it) {
if(it!=outgoing.begin()) tag += ",";
tag +=(**it).name();
}
tag += ";";
dm = findDecayMode(tag);
}
if(dm) _decayme = dynamic_ptr_cast<HwDecayerBasePtr>(dm->decayer());
// set the ShowerTree to be showered
currentTree(decay);
decay->applyTransforms();
hardTree(HardTreePtr());
unsigned int interactionTry=0;
do {
try {
// generate the showering
doShowering(false,XCPtr());
// if no vetos
// force calculation of spin correlations
SpinPtr spInfo = decay->incomingLines().begin()->first->progenitor()->spinInfo();
if(spInfo) {
if(!spInfo->developed()) spInfo->needsUpdate();
spInfo->develop();
}
// and then return
return;
}
catch (InteractionVeto) {
currentTree()->clear();
++interactionTry;
}
}
while(interactionTry<=5);
throw Exception() << "Too many tries for QED shower in Evolver::showerDecay()"
<< Exception::eventerror;
}
bool Evolver::spaceLikeDecayShower(tShowerParticlePtr particle,
const ShowerParticle::EvolutionScales & maxScales,
Energy minmass,ShowerInteraction::Type type) {
Branching fb;
while (true) {
fb=_splittingGenerator->chooseDecayBranching(*particle,maxScales,minmass,
_initialenhance,type);
// return if no radiation
if(!fb.kinematics) return false;
// if not vetoed break
if(!spaceLikeDecayVetoed(fb,particle)) break;
// otherwise reset scale and continue
particle->vetoEmission(fb.type,fb.kinematics->scale());
}
// has emitted
// Assign the shower kinematics to the emitting particle.
particle->showerKinematics(fb.kinematics);
if(fb.kinematics->pT()>progenitor()->highestpT())
progenitor()->highestpT(fb.kinematics->pT());
// 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;
for(unsigned int ix=0;ix<2;++ix) {
theChildren.push_back(new_ptr(ShowerParticle(pdata[ix],true)));
if(theChildren[ix]->id()==_progenitor->id()&&!pdata[ix]->stable())
theChildren[ix]->set5Momentum(Lorentz5Momentum(_progenitor->progenitor()->mass()));
else
theChildren[ix]->set5Momentum(Lorentz5Momentum(pdata[ix]->mass()));
}
// some code moved to updateChildren
particle->showerKinematics()->
updateChildren(particle, theChildren, fb.type);
// In the case of splittings which involves coloured particles,
// set properly the colour flow of the branching.
// update the history if needed
_currenttree->updateInitialStateShowerProduct(_progenitor,theChildren[0]);
_currenttree->addInitialStateBranching(particle,theChildren[0],theChildren[1]);
// shower the first particle
spaceLikeDecayShower(theChildren[0],maxScales,minmass,type);
// shower the second particle
timeLikeShower(theChildren[1],type,Branching(),true);
updateHistory(theChildren[1]);
// branching has happened
return true;
}
vector<ShowerProgenitorPtr> Evolver::setupShower(bool hard) {
// generate POWHEG hard emission if needed
if(_hardEmissionMode>0) hardestEmission(hard);
ShowerInteraction::Type inter = interactions_[0];
if(_hardtree&&inter!=ShowerInteraction::Both) {
inter = _hardtree->interaction();
}
// set the initial colour partners
setEvolutionPartners(hard,inter,false);
// generate hard me if needed
if(_hardEmissionMode==0 ||
(!hard && _hardEmissionMode==-1)) hardMatrixElementCorrection(hard);
// get the particles to be showered
vector<ShowerProgenitorPtr> particlesToShower =
currentTree()->extractProgenitors();
// remake the colour partners if needed
if(_currenttree->hardMatrixElementCorrection()) {
setEvolutionPartners(hard,interactions_[0],true);
_currenttree->resetShowerProducts();
}
// return the answer
return particlesToShower;
}
void Evolver::setEvolutionPartners(bool hard,ShowerInteraction::Type type,
bool clear) {
// match the particles in the ShowerTree and hardTree
if(hardTree() && !hardTree()->connect(currentTree()))
throw Exception() << "Can't match trees in "
<< "Evolver::setEvolutionPartners()"
<< Exception::eventerror;
// extract the progenitors
vector<ShowerParticlePtr> particles =
currentTree()->extractProgenitorParticles();
// clear the partners if needed
if(clear) {
for(unsigned int ix=0;ix<particles.size();++ix) {
particles[ix]->partner(ShowerParticlePtr());
particles[ix]->clearPartners();
}
}
// sort out the colour partners
if(hardTree()) {
// find the partner
for(unsigned int ix=0;ix<particles.size();++ix) {
tHardBranchingPtr partner =
hardTree()->particles()[particles[ix]]->colourPartner();
if(!partner) continue;
for(map<ShowerParticlePtr,tHardBranchingPtr>::const_iterator
it=hardTree()->particles().begin();
it!=hardTree()->particles().end();++it) {
if(it->second==partner) particles[ix]->partner(it->first);
}
if(!particles[ix]->partner())
throw Exception() << "Can't match partners in "
<< "Evolver::setEvolutionPartners()"
<< Exception::eventerror;
}
}
// Set the initial evolution scales
showerModel()->partnerFinder()->
setInitialEvolutionScales(particles,!hard,type,!_hardtree);
if(hardTree() && _hardPOWHEG) {
bool tooHard=false;
map<ShowerParticlePtr,tHardBranchingPtr>::const_iterator
eit=hardTree()->particles().end();
for(unsigned int ix=0;ix<particles.size();++ix) {
map<ShowerParticlePtr,tHardBranchingPtr>::const_iterator
mit = hardTree()->particles().find(particles[ix]);
Energy hardScale(ZERO);
ShowerPartnerType::Type type(ShowerPartnerType::Undefined);
// final-state
if(particles[ix]->isFinalState()) {
if(mit!= eit && !mit->second->children().empty()) {
hardScale = mit->second->scale();
type = mit->second->type();
}
}
// initial-state
else {
if(mit!= eit && mit->second->parent()) {
hardScale = mit->second->parent()->scale();
type = mit->second->parent()->type();
}
}
if(type!=ShowerPartnerType::Undefined) {
if(type==ShowerPartnerType::QED) {
tooHard |= particles[ix]->scales().QED_noAO<hardScale;
}
else if(type==ShowerPartnerType::QCDColourLine) {
tooHard |= particles[ix]->scales().QCD_c_noAO<hardScale;
}
else if(type==ShowerPartnerType::QCDAntiColourLine) {
tooHard |= particles[ix]->scales().QCD_ac_noAO<hardScale;
}
}
}
if(tooHard) convertHardTree(hard,type);
}
}
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) {
+ _nFSR = 0;
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,true);
if(output) updateHistory(progenitor()->progenitor());
return output;
}
}
bool output = hardOnly() ? false :
timeLikeShower(progenitor()->progenitor() ,type,Branching(),true) ;
if(output) updateHistory(progenitor()->progenitor());
return output;
}
bool Evolver::startSpaceLikeShower(PPtr parent, ShowerInteraction::Type type) {
if(hardTree()) {
map<ShowerParticlePtr,tHardBranchingPtr>::const_iterator
eit =hardTree()->particles().end(),
mit = hardTree()->particles().find(progenitor()->progenitor());
if( mit != eit && mit->second->parent() ) {
return truncatedSpaceLikeShower( progenitor()->progenitor(),
parent, mit->second->parent(), type );
}
}
return hardOnly() ? false :
spaceLikeShower(progenitor()->progenitor(),parent,type);
}
bool Evolver::
startSpaceLikeDecayShower(const ShowerParticle::EvolutionScales & maxScales,
Energy minimumMass,ShowerInteraction::Type type) {
if(hardTree()) {
map<ShowerParticlePtr,tHardBranchingPtr>::const_iterator
eit =hardTree()->particles().end(),
mit = hardTree()->particles().find(progenitor()->progenitor());
if( mit != eit && mit->second->parent() ) {
HardBranchingPtr branch=mit->second;
while(branch->parent()) branch=branch->parent();
return truncatedSpaceLikeDecayShower(progenitor()->progenitor(),maxScales,
minimumMass, branch ,type);
}
}
return hardOnly() ? false :
spaceLikeDecayShower(progenitor()->progenitor(),maxScales,minimumMass,type);
}
bool Evolver::timeLikeVetoed(const Branching & fb,
ShowerParticlePtr particle) {
// work out type of interaction
ShowerInteraction::Type type = fb.type==ShowerPartnerType::QED ?
ShowerInteraction::QED : ShowerInteraction::QCD;
// check whether emission was harder than largest pt of hard subprocess
if ( hardVetoFS() && fb.kinematics->pT() > _progenitor->maxHardPt() )
return true;
// soft matrix element correction veto
if( softMEC()) {
if(_hardme && _hardme->hasMECorrection()) {
if(_hardme->softMatrixElementVeto(_progenitor,particle,fb))
return true;
}
else if(_decayme && _decayme->hasMECorrection()) {
if(_decayme->softMatrixElementVeto(_progenitor,particle,fb))
return true;
}
}
// veto on maximum pt
if(fb.kinematics->pT()>_progenitor->maximumpT(type)) return true;
// general vetos
if (fb.kinematics && !_vetoes.empty()) {
bool vetoed=false;
for (vector<ShowerVetoPtr>::iterator v = _vetoes.begin();
v != _vetoes.end(); ++v) {
bool test = (**v).vetoTimeLike(_progenitor,particle,fb);
switch((**v).vetoType()) {
case ShowerVeto::Emission:
vetoed |= test;
break;
case ShowerVeto::Shower:
if(test) throw VetoShower();
break;
case ShowerVeto::Event:
if(test) throw Veto();
break;
}
}
if(vetoed) return true;
}
if ( ShowerHandler::currentHandler()->firstInteraction() &&
ShowerHandler::currentHandler()->profileScales() ) {
double weight =
ShowerHandler::currentHandler()->profileScales()->
hardScaleProfile(_progenitor->hardScale(),fb.kinematics->pT());
if ( UseRandom::rnd() > weight )
return true;
}
return false;
}
bool Evolver::spaceLikeVetoed(const Branching & bb,
ShowerParticlePtr particle) {
// work out type of interaction
ShowerInteraction::Type type = bb.type==ShowerPartnerType::QED ?
ShowerInteraction::QED : ShowerInteraction::QCD;
// check whether emission was harder than largest pt of hard subprocess
if (hardVetoIS() && bb.kinematics->pT() > _progenitor->maxHardPt())
return true;
// apply the soft correction
if( softMEC() && _hardme && _hardme->hasMECorrection() ) {
if(_hardme->softMatrixElementVeto(_progenitor,particle,bb))
return true;
}
// the more general vetos
// check vs max pt for the shower
if(bb.kinematics->pT()>_progenitor->maximumpT(type)) return true;
if (!_vetoes.empty()) {
bool vetoed=false;
for (vector<ShowerVetoPtr>::iterator v = _vetoes.begin();
v != _vetoes.end(); ++v) {
bool test = (**v).vetoSpaceLike(_progenitor,particle,bb);
switch ((**v).vetoType()) {
case ShowerVeto::Emission:
vetoed |= test;
break;
case ShowerVeto::Shower:
if(test) throw VetoShower();
break;
case ShowerVeto::Event:
if(test) throw Veto();
break;
}
}
if (vetoed) return true;
}
if ( ShowerHandler::currentHandler()->firstInteraction() &&
ShowerHandler::currentHandler()->profileScales() ) {
double weight =
ShowerHandler::currentHandler()->profileScales()->
hardScaleProfile(_progenitor->hardScale(),bb.kinematics->pT());
if ( UseRandom::rnd() > weight )
return true;
}
return false;
}
bool Evolver::spaceLikeDecayVetoed( const Branching & fb,
ShowerParticlePtr particle) {
// work out type of interaction
ShowerInteraction::Type type = fb.type==ShowerPartnerType::QED ?
ShowerInteraction::QED : ShowerInteraction::QCD;
// apply the soft correction
if( softMEC() && _decayme && _decayme->hasMECorrection() ) {
if(_decayme->softMatrixElementVeto(_progenitor,particle,fb))
return true;
}
// veto on hardest pt in the shower
if(fb.kinematics->pT()> _progenitor->maximumpT(type)) return true;
// general vetos
if (!_vetoes.empty()) {
bool vetoed=false;
for (vector<ShowerVetoPtr>::iterator v = _vetoes.begin();
v != _vetoes.end(); ++v) {
bool test = (**v).vetoSpaceLike(_progenitor,particle,fb);
switch((**v).vetoType()) {
case ShowerVeto::Emission:
vetoed |= test;
break;
case ShowerVeto::Shower:
if(test) throw VetoShower();
break;
case ShowerVeto::Event:
if(test) throw Veto();
break;
}
if (vetoed) return true;
}
}
return false;
}
void Evolver::hardestEmission(bool hard) {
HardTreePtr ISRTree;
if( ( _hardme && _hardme->hasPOWHEGCorrection()!=0 && _hardEmissionMode< 2) ||
( _decayme && _decayme->hasPOWHEGCorrection()!=0 && _hardEmissionMode!=2) ) {
if(_hardme) {
assert(hard);
if(interaction_==4) {
vector<ShowerInteraction::Type> inter(2);
inter[0] = ShowerInteraction::QCD;
inter[1] = ShowerInteraction::QED;
_hardtree = _hardme->generateHardest( currentTree(),inter );
}
else {
_hardtree = _hardme->generateHardest( currentTree(),interactions_ );
}
}
else {
assert(!hard);
_hardtree = _decayme->generateHardest( currentTree() );
}
// store initial state POWHEG radiation
if(_hardtree && _hardme && _hardme->hasPOWHEGCorrection()==1)
ISRTree=_hardtree;
}
else if (_hardEmissionMode>1 && hard) {
// Get minimum pT cutoff used in shower approximation
Energy maxpt = 1.*GeV;
int colouredIn = 0;
int colouredOut = 0;
for( map< ShowerProgenitorPtr, tShowerParticlePtr >::iterator it
= currentTree()->outgoingLines().begin();
it != currentTree()->outgoingLines().end(); ++it ) {
if( it->second->coloured() ) colouredOut+=1;
}
for( map< ShowerProgenitorPtr, ShowerParticlePtr >::iterator it
= currentTree()->incomingLines().begin();
it != currentTree()->incomingLines().end(); ++it ) {
if( ! it->second->coloured() ) colouredIn+=1;
}
if ( theShowerApproximation ){
if ( theShowerApproximation->ffPtCut() == theShowerApproximation->fiPtCut() &&
theShowerApproximation->ffPtCut() == theShowerApproximation->iiPtCut() )
maxpt = theShowerApproximation->ffPtCut();
else if ( colouredIn == 2 && colouredOut == 0 )
maxpt = theShowerApproximation->iiPtCut();
else if ( colouredIn == 0 && colouredOut > 1 )
maxpt = theShowerApproximation->ffPtCut();
else if ( colouredIn == 2 && colouredOut == 1 )
maxpt = min(theShowerApproximation->iiPtCut(), theShowerApproximation->fiPtCut());
else if ( colouredIn == 1 && colouredOut > 1 )
maxpt = min(theShowerApproximation->ffPtCut(), theShowerApproximation->fiPtCut());
else
maxpt = min(min(theShowerApproximation->iiPtCut(), theShowerApproximation->fiPtCut()),
theShowerApproximation->ffPtCut());
}
// Generate hardtree from born and real emission subprocesses
_hardtree = ShowerHandler::currentHandler()->generateCKKW(currentTree());
// Find transverse momentum of hardest emission
if (_hardtree){
for(set<HardBranchingPtr>::iterator it=_hardtree->branchings().begin();
it!=_hardtree->branchings().end();++it) {
if ((*it)->parent() && (*it)->status()==HardBranching::Incoming)
maxpt=(*it)->branchingParticle()->momentum().perp();
if ((*it)->children().size()==2 && (*it)->status()==HardBranching::Outgoing){
if ((*it)->branchingParticle()->id()!=21 &&
abs((*it)->branchingParticle()->id())>5 ){
if ((*it)->children()[0]->branchingParticle()->id()==21 ||
abs((*it)->children()[0]->branchingParticle()->id())<6)
maxpt=(*it)->children()[0]->branchingParticle()->momentum().perp();
else if ((*it)->children()[1]->branchingParticle()->id()==21 ||
abs((*it)->children()[1]->branchingParticle()->id())<6)
maxpt=(*it)->children()[1]->branchingParticle()->momentum().perp();
}
else {
if ( abs((*it)->branchingParticle()->id())<6){
if (abs((*it)->children()[0]->branchingParticle()->id())<6)
maxpt = (*it)->children()[1]->branchingParticle()->momentum().perp();
else
maxpt = (*it)->children()[0]->branchingParticle()->momentum().perp();
}
else maxpt = (*it)->children()[1]->branchingParticle()->momentum().perp();
}
}
}
}
// Hardest (pt) emission should be the first powheg emission.
maxpt=min(sqrt(ShowerHandler::currentHandler()->lastXCombPtr()->lastCentralScale()),maxpt);
// Set maxpt to pT of emission when showering POWHEG real-emission subprocesses
if (!isPowhegSEvent && !isPowhegHEvent){
vector<int> outGluon;
vector<int> outQuark;
map< ShowerProgenitorPtr, tShowerParticlePtr >::iterator it;
for( it = currentTree()->outgoingLines().begin();
it != currentTree()->outgoingLines().end(); ++it ) {
if ( abs(it->second->id())< 6) outQuark.push_back(it->second->id());
if ( it->second->id()==21 ) outGluon.push_back(it->second->id());
}
if (outGluon.size() + outQuark.size() == 1){
for( it = currentTree()->outgoingLines().begin();
it != currentTree()->outgoingLines().end(); ++it ) {
if ( abs(it->second->id())< 6 || it->second->id()==21 )
maxpt = it->second->momentum().perp();
}
}
else if (outGluon.size() + outQuark.size() > 1){
// assume qqbar pair from a Z/gamma
if (outGluon.size()==1 && outQuark.size() == 2 && outQuark[0]==-outQuark[1]){
for( it = currentTree()->outgoingLines().begin();
it != currentTree()->outgoingLines().end(); ++it ) {
if ( it->second->id()==21 )
maxpt = it->second->momentum().perp();
}
}
// otherwise take the lowest pT avoiding born DY events
else {
maxpt = generator()->maximumCMEnergy();
for( it = currentTree()->outgoingLines().begin();
it != currentTree()->outgoingLines().end(); ++it ) {
if ( abs(it->second->id())< 6 || it->second->id()==21 )
maxpt = min(maxpt,it->second->momentum().perp());
}
}
}
}
// set maximum pT for subsequent emissions from S events
if ( isPowhegSEvent || (!isPowhegSEvent && !isPowhegHEvent)){
for( map< ShowerProgenitorPtr, tShowerParticlePtr >::iterator it
= currentTree()->outgoingLines().begin();
it != currentTree()->outgoingLines().end(); ++it ) {
if( ! it->second->coloured() ) continue;
it->first->maximumpT(maxpt, ShowerInteraction::QCD );
}
for( map< ShowerProgenitorPtr, ShowerParticlePtr >::iterator it
= currentTree()->incomingLines().begin();
it != currentTree()->incomingLines().end(); ++it ) {
if( ! it->second->coloured() ) continue;
it->first->maximumpT(maxpt, ShowerInteraction::QCD );
}
}
}
else
_hardtree = ShowerHandler::currentHandler()->generateCKKW(currentTree());
// if hard me doesn't have a FSR powheg
// correction use decay powheg correction
if (_hardme && _hardme->hasPOWHEGCorrection()<2) {
// check for intermediate colour singlet resonance
const ParticleVector inter = _hardme->subProcess()->intermediates();
if (inter.size()!=1 ||
inter[0]->momentum().m2()/GeV2 < 0 ||
inter[0]->dataPtr()->iColour()!=PDT::Colour0){
if(_hardtree) connectTrees(currentTree(),_hardtree,hard);
return;
}
map<ShowerProgenitorPtr, tShowerParticlePtr > out = currentTree()->outgoingLines();
// ignore cases where outgoing particles are not coloured
if (out.size()!=2 ||
out. begin()->second->dataPtr()->iColour()==PDT::Colour0 ||
out.rbegin()->second->dataPtr()->iColour()==PDT::Colour0) {
if(_hardtree) connectTrees(currentTree(),_hardtree,hard);
return;
}
// look up decay mode
tDMPtr dm;
string tag;
string inParticle = inter[0]->dataPtr()->name() + "->";
vector<string> outParticles;
outParticles.push_back(out.begin ()->first->progenitor()->dataPtr()->name());
outParticles.push_back(out.rbegin()->first->progenitor()->dataPtr()->name());
for (int it=0; it<2; ++it){
tag = inParticle + outParticles[it] + "," + outParticles[(it+1)%2] + ";";
dm = generator()->findDecayMode(tag);
if(dm) break;
}
// get the decayer
HwDecayerBasePtr decayer;
if(dm) decayer = dynamic_ptr_cast<HwDecayerBasePtr>(dm->decayer());
// check if decayer has a FSR POWHEG correction
if (!decayer || decayer->hasPOWHEGCorrection()<2){
if(_hardtree) connectTrees(currentTree(),_hardtree,hard);
return;
}
// generate the hardest emission
ShowerDecayMap decay;
PPtr in = new_ptr(*inter[0]);
ShowerTreePtr decayTree = new_ptr(ShowerTree(in, decay));
HardTreePtr FSRTree = decayer->generateHardest(decayTree);
if (!FSRTree) {
if(_hardtree) connectTrees(currentTree(),_hardtree,hard);
return;
}
// if there is no ISRTree make _hardtree from FSRTree
if (!ISRTree){
vector<HardBranchingPtr> inBranch,hardBranch;
for(map<ShowerProgenitorPtr,ShowerParticlePtr>::const_iterator
cit =currentTree()->incomingLines().begin();
cit!=currentTree()->incomingLines().end();++cit ) {
inBranch.push_back(new_ptr(HardBranching(cit->second,SudakovPtr(),
HardBranchingPtr(),
HardBranching::Incoming)));
inBranch.back()->beam(cit->first->original()->parents()[0]);
hardBranch.push_back(inBranch.back());
}
if(inBranch[0]->branchingParticle()->dataPtr()->coloured()) {
inBranch[0]->colourPartner(inBranch[1]);
inBranch[1]->colourPartner(inBranch[0]);
}
for(set<HardBranchingPtr>::iterator it=FSRTree->branchings().begin();
it!=FSRTree->branchings().end();++it) {
if((**it).branchingParticle()->id()!=in->id())
hardBranch.push_back(*it);
}
hardBranch[2]->colourPartner(hardBranch[3]);
hardBranch[3]->colourPartner(hardBranch[2]);
HardTreePtr newTree = new_ptr(HardTree(hardBranch,inBranch,
ShowerInteraction::QCD));
_hardtree = newTree;
}
// Otherwise modify the ISRTree to include the emission in FSRTree
else {
vector<tShowerParticlePtr> FSROut, ISROut;
set<HardBranchingPtr>::iterator itFSR, itISR;
// get outgoing particles
for(itFSR =FSRTree->branchings().begin();
itFSR!=FSRTree->branchings().end();++itFSR){
if ((**itFSR).status()==HardBranching::Outgoing)
FSROut.push_back((*itFSR)->branchingParticle());
}
for(itISR =ISRTree->branchings().begin();
itISR!=ISRTree->branchings().end();++itISR){
if ((**itISR).status()==HardBranching::Outgoing)
ISROut.push_back((*itISR)->branchingParticle());
}
// find COM frame formed by outgoing particles
LorentzRotation eventFrameFSR, eventFrameISR;
eventFrameFSR = ((FSROut[0]->momentum()+FSROut[1]->momentum()).findBoostToCM());
eventFrameISR = ((ISROut[0]->momentum()+ISROut[1]->momentum()).findBoostToCM());
// find rotation between ISR and FSR frames
int j=0;
if (ISROut[0]->id()!=FSROut[0]->id()) j=1;
eventFrameISR.rotateZ( (eventFrameFSR*FSROut[0]->momentum()).phi()-
(eventFrameISR*ISROut[j]->momentum()).phi() );
eventFrameISR.rotateY( (eventFrameFSR*FSROut[0]->momentum()).theta()-
(eventFrameISR*ISROut[j]->momentum()).theta() );
eventFrameISR.invert();
for (itFSR=FSRTree->branchings().begin();
itFSR!=FSRTree->branchings().end();++itFSR){
if ((**itFSR).branchingParticle()->id()==in->id()) continue;
for (itISR =ISRTree->branchings().begin();
itISR!=ISRTree->branchings().end();++itISR){
if ((**itISR).status()==HardBranching::Incoming) continue;
if ((**itFSR).branchingParticle()->id()==
(**itISR).branchingParticle()->id()){
// rotate FSRTree particle to ISRTree event frame
(**itISR).branchingParticle()->setMomentum(eventFrameISR*
eventFrameFSR*
(**itFSR).branchingParticle()->momentum());
(**itISR).branchingParticle()->rescaleMass();
// add the children of the FSRTree particles to the ISRTree
if(!(**itFSR).children().empty()){
(**itISR).addChild((**itFSR).children()[0]);
(**itISR).addChild((**itFSR).children()[1]);
// rotate momenta to ISRTree event frame
(**itISR).children()[0]->branchingParticle()->setMomentum(eventFrameISR*
eventFrameFSR*
(**itFSR).children()[0]->branchingParticle()->momentum());
(**itISR).children()[1]->branchingParticle()->setMomentum(eventFrameISR*
eventFrameFSR*
(**itFSR).children()[1]->branchingParticle()->momentum());
}
}
}
}
_hardtree = ISRTree;
}
}
if(_hardtree){
connectTrees(currentTree(),_hardtree,hard);
}
}
bool Evolver::truncatedTimeLikeShower(tShowerParticlePtr particle,
HardBranchingPtr branch,
ShowerInteraction::Type type,bool first) {
int ntry=0;
do {
++ntry;
Branching fb;
unsigned int iout=0;
tcPDPtr pdata[2];
while (true) {
// no truncated shower break
if(!isTruncatedShowerON()||hardOnly()) break;
// generate emission
fb=splittingGenerator()->chooseForwardBranching(*particle,1.,type);
// no emission break
if(!fb.kinematics) break;
// check haven't evolved too far
if(fb.kinematics->scale() < branch->scale()) {
fb=Branching();
break;
}
// get the particle data objects
for(unsigned int ix=0;ix<2;++ix) pdata[ix]=getParticleData(fb.ids[ix+1]);
if(particle->id()!=fb.ids[0]) {
for(unsigned int ix=0;ix<2;++ix) {
tPDPtr cc(pdata[ix]->CC());
if(cc) pdata[ix]=cc;
}
}
// find the truncated line
iout=0;
if(pdata[0]->id()!=pdata[1]->id()) {
if(pdata[0]->id()==particle->id()) iout=1;
else if (pdata[1]->id()==particle->id()) iout=2;
}
else if(pdata[0]->id()==particle->id()) {
if(fb.kinematics->z()>0.5) iout=1;
else iout=2;
}
// apply the vetos for the truncated shower
// no flavour changing branchings
if(iout==0) {
particle->vetoEmission(fb.type,fb.kinematics->scale());
continue;
}
double zsplit = iout==1 ? fb.kinematics->z() : 1-fb.kinematics->z();
// only if same interaction for forced branching
ShowerInteraction::Type type2 = fb.type==ShowerPartnerType::QED ?
ShowerInteraction::QED : ShowerInteraction::QCD;
// and evolution
if(type2==branch->sudakov()->interactionType()) {
if(zsplit < 0.5 || // hardest line veto
fb.kinematics->scale()*zsplit < branch->scale() ) { // angular ordering veto
particle->vetoEmission(fb.type,fb.kinematics->scale());
continue;
}
}
// pt veto
if(fb.kinematics->pT() > progenitor()->maximumpT(type2)) {
particle->vetoEmission(fb.type,fb.kinematics->scale());
continue;
}
// should do base class vetos as well
if(timeLikeVetoed(fb,particle)) {
particle->vetoEmission(fb.type,fb.kinematics->scale());
continue;
}
break;
}
// if no branching force truncated emission
if(!fb.kinematics) {
// construct the kinematics for the hard emission
ShoKinPtr showerKin=
branch->sudakov()->createFinalStateBranching(branch->scale(),
branch->children()[0]->z(),
branch->phi(),
branch->children()[0]->pT());
showerKin->initialize( *particle,PPtr() );
IdList idlist(3);
idlist[0] = particle->id();
idlist[1] = branch->children()[0]->branchingParticle()->id();
idlist[2] = branch->children()[1]->branchingParticle()->id();
fb = Branching( showerKin, idlist, branch->sudakov(),branch->type() );
// Assign the shower kinematics to the emitting particle.
+ ++_nFSR;
particle->showerKinematics( fb.kinematics );
if(fb.kinematics->pT()>progenitor()->highestpT())
progenitor()->highestpT(fb.kinematics->pT());
// 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;
for(unsigned int ix=0;ix<2;++ix) {
theChildren.push_back(new_ptr(ShowerParticle(branch->children()[ix]->
branchingParticle()->dataPtr(),true)));
if(theChildren[ix]->id()==_progenitor->id()&&!theChildren[ix]->dataPtr()->stable())
theChildren[ix]->set5Momentum(Lorentz5Momentum(_progenitor->progenitor()->mass()));
else
theChildren[ix]->set5Momentum(Lorentz5Momentum(theChildren[ix]->dataPtr()->mass()));
}
particle->showerKinematics()->
updateChildren(particle, theChildren,fb.type);
for(unsigned int ix=0;ix<2;++ix) {
theChildren[ix]->scales().QED = min(theChildren[ix]->scales().QED ,particle->scales().QED );
theChildren[ix]->scales().QED_noAO = min(theChildren[ix]->scales().QED_noAO ,particle->scales().QED_noAO );
theChildren[ix]->scales().QCD_c = min(theChildren[ix]->scales().QCD_c ,particle->scales().QCD_c );
theChildren[ix]->scales().QCD_c_noAO = min(theChildren[ix]->scales().QCD_c_noAO ,particle->scales().QCD_c_noAO );
theChildren[ix]->scales().QCD_ac = min(theChildren[ix]->scales().QCD_ac ,particle->scales().QCD_ac );
theChildren[ix]->scales().QCD_ac_noAO = min(theChildren[ix]->scales().QCD_ac_noAO,particle->scales().QCD_ac_noAO);
}
// shower the first particle
if( branch->children()[0]->children().empty() ) {
if( ! hardOnly() )
timeLikeShower(theChildren[0],type,Branching(),false);
}
else {
truncatedTimeLikeShower( theChildren[0],branch->children()[0],type,false);
}
// shower the second particle
if( branch->children()[1]->children().empty() ) {
if( ! hardOnly() )
timeLikeShower( theChildren[1] , type,Branching(),false);
}
else {
truncatedTimeLikeShower( theChildren[1],branch->children()[1] ,type,false);
}
// that's if for old approach
if(_reconOpt==0) return true;
// branching has happened
particle->showerKinematics()->updateParent(particle, theChildren,fb.type);
// clean up the vetoed emission
if(particle->virtualMass()==ZERO) {
particle->showerKinematics(ShoKinPtr());
for(unsigned int ix=0;ix<theChildren.size();++ix)
particle->abandonChild(theChildren[ix]);
theChildren.clear();
continue;
}
else {
if(first&&!theChildren.empty())
particle->showerKinematics()->resetChildren(particle,theChildren);
if(particle->spinInfo()) particle->spinInfo()->develop();
return true;
}
}
// has emitted
// Assign the shower kinematics to the emitting particle.
+ ++_nFSR;
particle->showerKinematics(fb.kinematics);
if(fb.kinematics->pT()>progenitor()->highestpT())
progenitor()->highestpT(fb.kinematics->pT());
// 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;
for(unsigned int ix=0;ix<2;++ix) {
theChildren.push_back( new_ptr( ShowerParticle( pdata[ix], true ) ) );
if(theChildren[ix]->id()==_progenitor->id()&&!pdata[ix]->stable())
theChildren[ix]->set5Momentum(Lorentz5Momentum(_progenitor->progenitor()->mass()));
else
theChildren[ix]->set5Momentum(Lorentz5Momentum(pdata[ix]->mass()));
}
particle->showerKinematics()->
updateChildren( particle, theChildren , fb.type);
// shower the first particle
if( iout == 1 ) truncatedTimeLikeShower( theChildren[0], branch , type ,false);
else timeLikeShower( theChildren[0] , type,Branching(),false);
// shower the second particle
if( iout == 2 ) truncatedTimeLikeShower( theChildren[1], branch , type ,false);
else timeLikeShower( theChildren[1] , type,Branching(),false);
// that's if for old approach
if(_reconOpt==0) return true;
// branching has happened
particle->showerKinematics()->updateParent(particle, theChildren,fb.type);
// clean up the vetoed emission
if(particle->virtualMass()==ZERO) {
particle->showerKinematics(ShoKinPtr());
for(unsigned int ix=0;ix<theChildren.size();++ix)
particle->abandonChild(theChildren[ix]);
theChildren.clear();
}
else {
if(first&&!theChildren.empty())
particle->showerKinematics()->resetChildren(particle,theChildren);
if(particle->spinInfo()) particle->spinInfo()->develop();
return true;
}
}
while(ntry<50);
return false;
}
bool Evolver::truncatedSpaceLikeShower(tShowerParticlePtr particle, PPtr beam,
HardBranchingPtr branch,
ShowerInteraction::Type type) {
tcPDFPtr pdf;
if(ShowerHandler::currentHandler()->firstPDF().particle() == beamParticle())
pdf = ShowerHandler::currentHandler()->firstPDF().pdf();
if(ShowerHandler::currentHandler()->secondPDF().particle() == beamParticle())
pdf = ShowerHandler::currentHandler()->secondPDF().pdf();
Energy freeze = ShowerHandler::currentHandler()->pdfFreezingScale();
Branching bb;
// parameters of the force branching
double z(0.);
HardBranchingPtr timelike;
for( unsigned int ix = 0; ix < branch->children().size(); ++ix ) {
if( branch->children()[ix]->status() ==HardBranching::Outgoing) {
timelike = branch->children()[ix];
}
if( branch->children()[ix]->status() ==HardBranching::Incoming )
z = branch->children()[ix]->z();
}
// generate truncated branching
tcPDPtr part[2];
if(z>=0.&&z<=1.) {
while (true) {
if( !isTruncatedShowerON() || hardOnly() ) break;
bb = splittingGenerator()->chooseBackwardBranching( *particle,
beam, 1., beamParticle(),
type , pdf,freeze);
if( !bb.kinematics || bb.kinematics->scale() < branch->scale() ) {
bb = Branching();
break;
}
// particles as in Sudakov form factor
part[0] = getParticleData( bb.ids[0] );
part[1] = getParticleData( bb.ids[2] );
//is emitter anti-particle
if( particle->id() != bb.ids[1]) {
if( part[0]->CC() ) part[0] = part[0]->CC();
if( part[1]->CC() ) part[1] = part[1]->CC();
}
double zsplit = bb.kinematics->z();
// apply the vetos for the truncated shower
// if doesn't carry most of momentum
ShowerInteraction::Type type2 = bb.type==ShowerPartnerType::QED ?
ShowerInteraction::QED : ShowerInteraction::QCD;
if(type2==branch->sudakov()->interactionType() &&
zsplit < 0.5) {
particle->vetoEmission(bb.type,bb.kinematics->scale());
continue;
}
// others
if( part[0]->id() != particle->id() || // if particle changes type
bb.kinematics->pT() > progenitor()->maximumpT(type2) || // pt veto
bb.kinematics->scale() < branch->scale()) { // angular ordering veto
particle->vetoEmission(bb.type,bb.kinematics->scale());
continue;
}
// and those from the base class
if(spaceLikeVetoed(bb,particle)) {
particle->vetoEmission(bb.type,bb.kinematics->scale());
continue;
}
break;
}
}
if( !bb.kinematics ) {
//do the hard emission
ShoKinPtr kinematics =
branch->sudakov()->createInitialStateBranching( branch->scale(), z, branch->phi(),
branch->children()[0]->pT() );
kinematics->initialize( *particle, beam );
// assign the splitting function and shower kinematics
particle->showerKinematics( kinematics );
if(kinematics->pT()>progenitor()->highestpT())
progenitor()->highestpT(kinematics->pT());
// For the time being we are considering only 1->2 branching
// Now create the actual particles, make the otherChild a final state
// particle, while the newParent is not
ShowerParticlePtr newParent =
new_ptr( ShowerParticle( branch->branchingParticle()->dataPtr(), false ) );
ShowerParticlePtr otherChild =
new_ptr( ShowerParticle( timelike->branchingParticle()->dataPtr(),
true, true ) );
ShowerParticleVector theChildren;
theChildren.push_back( particle );
theChildren.push_back( otherChild );
particle->showerKinematics()->
updateParent( newParent, theChildren, branch->type());
// update the history if needed
currentTree()->updateInitialStateShowerProduct( progenitor(), newParent );
currentTree()->addInitialStateBranching( particle, newParent, otherChild );
// for the reconstruction of kinematics, parent/child
// relationships are according to the branching process:
// now continue the shower
bool emitted=false;
if(!hardOnly()) {
if( branch->parent() ) {
emitted = truncatedSpaceLikeShower( newParent, beam, branch->parent() , type);
}
else {
emitted = spaceLikeShower( newParent, beam , type);
}
}
if( !emitted ) {
if( intrinsicpT().find( progenitor() ) == intrinsicpT().end() ) {
kinematics->updateLast( newParent, ZERO, ZERO );
}
else {
pair<Energy,double> kt = intrinsicpT()[progenitor()];
kinematics->updateLast( newParent,
kt.first*cos( kt.second ),
kt.first*sin( kt.second ) );
}
}
particle->showerKinematics()->
updateChildren( newParent, theChildren,bb.type);
if(hardOnly()) return true;
// perform the shower of the final-state particle
if( timelike->children().empty() ) {
timeLikeShower( otherChild , type,Branching(),true);
}
else {
truncatedTimeLikeShower( otherChild, timelike , type,true);
}
updateHistory(otherChild);
// return the emitted
return true;
}
// assign the splitting function and shower kinematics
particle->showerKinematics( bb.kinematics );
if(bb.kinematics->pT()>progenitor()->highestpT())
progenitor()->highestpT(bb.kinematics->pT());
// For the time being we are considering only 1->2 branching
// Now create the actual particles, make the otherChild a final state
// particle, while the newParent is not
ShowerParticlePtr newParent = new_ptr( ShowerParticle( part[0], false ) );
ShowerParticlePtr otherChild = new_ptr( ShowerParticle( part[1], true, true ) );
ShowerParticleVector theChildren;
theChildren.push_back( particle );
theChildren.push_back( otherChild );
particle->showerKinematics()->
updateParent( newParent, theChildren, bb.type);
// update the history if needed
currentTree()->updateInitialStateShowerProduct( progenitor(), newParent );
currentTree()->addInitialStateBranching( particle, newParent, otherChild );
// for the reconstruction of kinematics, parent/child
// relationships are according to the branching process:
// now continue the shower
bool emitted = truncatedSpaceLikeShower( newParent, beam, branch,type);
// now reconstruct the momentum
if( !emitted ) {
if( intrinsicpT().find( progenitor() ) == intrinsicpT().end() ) {
bb.kinematics->updateLast( newParent, ZERO, ZERO );
}
else {
pair<Energy,double> kt = intrinsicpT()[ progenitor() ];
bb.kinematics->updateLast( newParent,
kt.first*cos( kt.second ),
kt.first*sin( kt.second ) );
}
}
particle->showerKinematics()->
updateChildren( newParent, theChildren, bb.type);
// perform the shower of the final-state particle
timeLikeShower( otherChild , type,Branching(),true);
updateHistory(otherChild);
// return the emitted
return true;
}
bool Evolver::
truncatedSpaceLikeDecayShower(tShowerParticlePtr particle,
const ShowerParticle::EvolutionScales & maxScales,
Energy minmass, HardBranchingPtr branch,
ShowerInteraction::Type type) {
Branching fb;
unsigned int iout=0;
tcPDPtr pdata[2];
while (true) {
// no truncated shower break
if(!isTruncatedShowerON()||hardOnly()) break;
fb=splittingGenerator()->chooseDecayBranching(*particle,maxScales,minmass,1.,type);
// return if no radiation
if(!fb.kinematics) break;
// check haven't evolved too far
if(fb.kinematics->scale() < branch->scale()) {
fb=Branching();
break;
}
// get the particle data objects
for(unsigned int ix=0;ix<2;++ix) pdata[ix]=getParticleData(fb.ids[ix+1]);
if(particle->id()!=fb.ids[0]) {
for(unsigned int ix=0;ix<2;++ix) {
tPDPtr cc(pdata[ix]->CC());
if(cc) pdata[ix]=cc;
}
}
// find the truncated line
iout=0;
if(pdata[0]->id()!=pdata[1]->id()) {
if(pdata[0]->id()==particle->id()) iout=1;
else if (pdata[1]->id()==particle->id()) iout=2;
}
else if(pdata[0]->id()==particle->id()) {
if(fb.kinematics->z()>0.5) iout=1;
else iout=2;
}
// apply the vetos for the truncated shower
// no flavour changing branchings
if(iout==0) {
particle->vetoEmission(fb.type,fb.kinematics->scale());
continue;
}
ShowerInteraction::Type type2 = fb.type==ShowerPartnerType::QED ?
ShowerInteraction::QED : ShowerInteraction::QCD;
double zsplit = iout==1 ? fb.kinematics->z() : 1-fb.kinematics->z();
if(type2==branch->sudakov()->interactionType()) {
if(zsplit < 0.5 || // hardest line veto
fb.kinematics->scale()*zsplit < branch->scale() ) { // angular ordering veto
particle->vetoEmission(fb.type,fb.kinematics->scale());
continue;
}
}
// pt veto
if(fb.kinematics->pT() > progenitor()->maximumpT(type2)) {
particle->vetoEmission(fb.type,fb.kinematics->scale());
continue;
}
// should do base class vetos as well
// if not vetoed break
if(!spaceLikeDecayVetoed(fb,particle)) break;
// otherwise reset scale and continue
particle->vetoEmission(fb.type,fb.kinematics->scale());
}
// this may not be currently used but in principle could be
// and should be included
if (!fb.kinematics) {
// construct the kinematics for the hard emission
ShoKinPtr showerKin=
branch->sudakov()->createDecayBranching(branch->scale(),
branch->children()[0]->z(),
branch->phi(),
branch->children()[0]->pT());
showerKin->initialize( *particle,PPtr() );
IdList idlist(3);
idlist[0] = particle->id();
idlist[1] = branch->children()[0]->branchingParticle()->id();
idlist[2] = branch->children()[1]->branchingParticle()->id();
// create the branching
fb = Branching( showerKin, idlist, branch->sudakov(),ShowerPartnerType::QCDColourLine );
// Assign the shower kinematics to the emitting particle.
particle->showerKinematics( fb.kinematics );
if(fb.kinematics->pT()>progenitor()->highestpT())
progenitor()->highestpT(fb.kinematics->pT());
// Assign the splitting function to the emitting particle.
// For the time being we are considering only 1->2 branching
// Create the ShowerParticle objects for the two children of
// the emitting particle; set the parent/child relationship
// if same as definition create particles, otherwise create cc
ShowerParticleVector theChildren;
theChildren.push_back(new_ptr(ShowerParticle(branch->children()[0]->
branchingParticle()->dataPtr(),true)));
theChildren.push_back(new_ptr(ShowerParticle(branch->children()[1]->
branchingParticle()->dataPtr(),true)));
particle->showerKinematics()->
updateChildren(particle, theChildren,fb.type);
if(theChildren[0]->id()==particle->id()) {
// update the history if needed
currentTree()->updateInitialStateShowerProduct(progenitor(),theChildren[0]);
currentTree()->addInitialStateBranching(particle,theChildren[0],theChildren[1]);
// shower the space-like particle
if( branch->children()[0]->children().empty() ) {
if( ! hardOnly() ) spaceLikeDecayShower(theChildren[0],maxScales,minmass,type);
}
else {
truncatedSpaceLikeDecayShower( theChildren[0],maxScales,minmass,
branch->children()[0],type);
}
// shower the second particle
if( branch->children()[1]->children().empty() ) {
if( ! hardOnly() ) timeLikeShower( theChildren[1] , type,Branching(), true);
}
else {
truncatedTimeLikeShower( theChildren[1],branch->children()[1] ,type,true);
}
updateHistory(theChildren[1]);
}
else {
// update the history if needed
currentTree()->updateInitialStateShowerProduct(progenitor(),theChildren[1]);
currentTree()->addInitialStateBranching(particle,theChildren[0],theChildren[1]);
// shower the space-like particle
if( branch->children()[1]->children().empty() ) {
if( ! hardOnly() ) spaceLikeDecayShower(theChildren[1],maxScales,minmass,type);
}
else {
truncatedSpaceLikeDecayShower( theChildren[1],maxScales,minmass,
branch->children()[1],type);
}
// shower the second particle
if( branch->children()[0]->children().empty() ) {
if( ! hardOnly() ) timeLikeShower( theChildren[0] , type, Branching(),true);
}
else {
truncatedTimeLikeShower( theChildren[0],branch->children()[0] ,type,true);
}
updateHistory(theChildren[0]);
}
return true;
}
// has emitted
// Assign the shower kinematics to the emitting particle.
particle->showerKinematics(fb.kinematics);
if(fb.kinematics->pT()>progenitor()->highestpT())
progenitor()->highestpT(fb.kinematics->pT());
// For the time being we are considering only 1->2 branching
// Create the ShowerParticle objects for the two children of
// the emitting particle; set the parent/child relationship
// if same as definition create particles, otherwise create cc
ShowerParticleVector theChildren;
theChildren.push_back(new_ptr(ShowerParticle(pdata[0],true)));
theChildren.push_back(new_ptr(ShowerParticle(pdata[1],true)));
particle->showerKinematics()->updateChildren(particle, theChildren,fb.type);
// In the case of splittings which involves coloured particles,
// set properly the colour flow of the branching.
// update the history if needed
currentTree()->updateInitialStateShowerProduct(progenitor(),theChildren[0]);
currentTree()->addInitialStateBranching(particle,theChildren[0],theChildren[1]);
// shower the first particle
truncatedSpaceLikeDecayShower(theChildren[0],maxScales,minmass,branch,type);
// shower the second particle
timeLikeShower(theChildren[1],type,Branching(),true);
updateHistory(theChildren[1]);
// branching has happened
return true;
}
bool Evolver::constructDecayTree(vector<ShowerProgenitorPtr> & particlesToShower,
ShowerInteraction::Type inter) {
Energy ptmax(-GeV);
// get the maximum pt is all ready a hard tree
if(hardTree()) {
for(unsigned int ix=0;ix<particlesToShower.size();++ix) {
if(particlesToShower[ix]->maximumpT(inter)>ptmax&&
particlesToShower[ix]->progenitor()->isFinalState())
ptmax = particlesToShower[ix]->maximumpT(inter);
}
}
vector<HardBranchingPtr> spaceBranchings,allBranchings;
for(unsigned int ix=0;ix<particlesToShower.size();++ix) {
if(particlesToShower[ix]->progenitor()->isFinalState()) {
HardBranchingPtr newBranch;
if(particlesToShower[ix]->hasEmitted()) {
newBranch =
new_ptr(HardBranching(particlesToShower[ix]->progenitor(),
particlesToShower[ix]->progenitor()->
showerKinematics()->SudakovFormFactor(),
HardBranchingPtr(),HardBranching::Outgoing));
constructTimeLikeLine(newBranch,particlesToShower[ix]->progenitor());
}
else {
newBranch =
new_ptr(HardBranching(particlesToShower[ix]->progenitor(),
SudakovPtr(),HardBranchingPtr(),
HardBranching::Outgoing));
}
allBranchings.push_back(newBranch);
}
else {
HardBranchingPtr newBranch;
if(particlesToShower[ix]->hasEmitted()) {
newBranch =
new_ptr(HardBranching(particlesToShower[ix]->progenitor(),
particlesToShower[ix]->progenitor()->
showerKinematics()->SudakovFormFactor(),
HardBranchingPtr(),HardBranching::Decay));
constructTimeLikeLine(newBranch,particlesToShower[ix]->progenitor());
HardBranchingPtr last=newBranch;
do {
for(unsigned int ix=0;ix<last->children().size();++ix) {
if(last->children()[ix]->branchingParticle()->id()==
particlesToShower[ix]->id()) {
last = last->children()[ix];
continue;
}
}
}
while(!last->children().empty());
last->status(HardBranching::Incoming);
spaceBranchings.push_back(newBranch);
allBranchings .push_back(last);
}
else {
newBranch =
new_ptr(HardBranching(particlesToShower[ix]->progenitor(),
SudakovPtr(),HardBranchingPtr(),
HardBranching::Incoming));
spaceBranchings.push_back(newBranch);
allBranchings .push_back(newBranch);
}
}
}
HardTreePtr QCDTree = new_ptr(HardTree(allBranchings,spaceBranchings,inter));
// set the charge partners
ShowerParticleVector particles;
particles.push_back(spaceBranchings.back()->branchingParticle());
for(set<HardBranchingPtr>::iterator cit=QCDTree->branchings().begin();
cit!=QCDTree->branchings().end();++cit) {
if((*cit)->status()==HardBranching::Outgoing)
particles.push_back((*cit)->branchingParticle());
}
// get the partners
showerModel()->partnerFinder()->setInitialEvolutionScales(particles,true,inter,true);
// do the inverse recon
if(!showerModel()->kinematicsReconstructor()->
deconstructDecayJets(QCDTree,this,inter)) {
return false;
}
// clear the old shower
currentTree()->clear();
// set the hard tree
hardTree(QCDTree);
// set the charge partners
setEvolutionPartners(false,inter,false);
// get the particles to be showered
map<ShowerProgenitorPtr,ShowerParticlePtr>::const_iterator cit;
map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator cjt;
particlesToShower.clear();
// incoming particles
for(cit=currentTree()->incomingLines().begin();
cit!=currentTree()->incomingLines().end();++cit)
particlesToShower.push_back(((*cit).first));
assert(particlesToShower.size()==1);
// outgoing particles
for(cjt=currentTree()->outgoingLines().begin();
cjt!=currentTree()->outgoingLines().end();++cjt) {
particlesToShower.push_back(((*cjt).first));
if(ptmax>ZERO) particlesToShower.back()->maximumpT(ptmax,inter);
}
for(unsigned int ix=0;ix<particlesToShower.size();++ix) {
map<ShowerParticlePtr,tHardBranchingPtr>::const_iterator
eit=hardTree()->particles().end(),
mit = hardTree()->particles().find(particlesToShower[ix]->progenitor());
if( mit != eit) {
if(mit->second->status()==HardBranching::Outgoing)
particlesToShower[ix]->progenitor()->set5Momentum(mit->second->pVector());
}
}
return true;
}
bool Evolver::constructHardTree(vector<ShowerProgenitorPtr> & particlesToShower,
ShowerInteraction::Type inter) {
bool noEmission = true;
vector<HardBranchingPtr> spaceBranchings,allBranchings;
for(unsigned int ix=0;ix<particlesToShower.size();++ix) {
if(particlesToShower[ix]->progenitor()->isFinalState()) {
HardBranchingPtr newBranch;
if(particlesToShower[ix]->hasEmitted()) {
noEmission = false;
newBranch =
new_ptr(HardBranching(particlesToShower[ix]->progenitor(),
particlesToShower[ix]->progenitor()->
showerKinematics()->SudakovFormFactor(),
HardBranchingPtr(),HardBranching::Outgoing));
constructTimeLikeLine(newBranch,particlesToShower[ix]->progenitor());
}
else {
newBranch =
new_ptr(HardBranching(particlesToShower[ix]->progenitor(),
SudakovPtr(),HardBranchingPtr(),
HardBranching::Outgoing));
}
allBranchings.push_back(newBranch);
}
else {
HardBranchingPtr first,last;
if(!particlesToShower[ix]->progenitor()->parents().empty()) {
noEmission = false;
constructSpaceLikeLine(particlesToShower[ix]->progenitor(),
first,last,SudakovPtr(),
particlesToShower[ix]->original()->parents()[0]);
}
else {
first = new_ptr(HardBranching(particlesToShower[ix]->progenitor(),
SudakovPtr(),HardBranchingPtr(),
HardBranching::Incoming));
if(particlesToShower[ix]->original()->parents().empty())
first->beam(particlesToShower[ix]->original());
else
first->beam(particlesToShower[ix]->original()->parents()[0]);
last = first;
}
spaceBranchings.push_back(first);
allBranchings.push_back(last);
}
}
if(!noEmission) {
HardTreePtr QCDTree = new_ptr(HardTree(allBranchings,spaceBranchings,
inter));
// set the charge partners
ShowerParticleVector particles;
for(set<HardBranchingPtr>::iterator cit=QCDTree->branchings().begin();
cit!=QCDTree->branchings().end();++cit) {
particles.push_back((*cit)->branchingParticle());
}
// get the partners
showerModel()->partnerFinder()->setInitialEvolutionScales(particles,false,
inter,true);
// do the inverse recon
if(!showerModel()->kinematicsReconstructor()->
deconstructHardJets(QCDTree,this,inter))
throw Exception() << "Can't to shower deconstruction for QED shower in"
<< "QEDEvolver::showerHard" << Exception::eventerror;
// set the hard tree
hardTree(QCDTree);
}
// clear the old shower
currentTree()->clear();
// set the charge partners
setEvolutionPartners(true,inter,false);
// get the particles to be showered
particlesToShower = currentTree()->extractProgenitors();
// reset momenta
if(hardTree()) {
for(unsigned int ix=0;ix<particlesToShower.size();++ix) {
map<ShowerParticlePtr,tHardBranchingPtr>::const_iterator
eit=hardTree()->particles().end(),
mit = hardTree()->particles().find(particlesToShower[ix]->progenitor());
if( mit != eit) {
particlesToShower[ix]->progenitor()->set5Momentum(mit->second->showerMomentum());
}
}
}
return true;
}
void Evolver::constructTimeLikeLine(tHardBranchingPtr branch,
tShowerParticlePtr particle) {
for(unsigned int ix=0;ix<particle->children().size();++ix) {
HardBranching::Status status = branch->status();
tShowerParticlePtr child =
dynamic_ptr_cast<ShowerParticlePtr>(particle->children()[ix]);
if(child->children().empty()) {
HardBranchingPtr newBranch =
new_ptr(HardBranching(child,SudakovPtr(),branch,status));
branch->addChild(newBranch);
}
else {
HardBranchingPtr newBranch =
new_ptr(HardBranching(child,child->showerKinematics()->SudakovFormFactor(),
branch,status));
constructTimeLikeLine(newBranch,child);
branch->addChild(newBranch);
}
}
// sort out the type of interaction
if(!branch->children().empty()) {
if(branch->branchingParticle()->id()==ParticleID::gamma ||
branch->children()[0]->branchingParticle()->id()==ParticleID::gamma ||
branch->children()[1]->branchingParticle()->id()==ParticleID::gamma)
branch->type(ShowerPartnerType::QED);
else {
if(branch->branchingParticle()->id()==
branch->children()[0]->branchingParticle()->id()) {
if(branch->branchingParticle()->dataPtr()->iColour()==PDT::Colour8) {
tShowerParticlePtr emittor =
branch->branchingParticle()->showerKinematics()->z()>0.5 ?
branch->children()[0]->branchingParticle() :
branch->children()[1]->branchingParticle();
if(branch->branchingParticle()->colourLine()==emittor->colourLine())
branch->type(ShowerPartnerType::QCDAntiColourLine);
else if(branch->branchingParticle()->antiColourLine()==emittor->antiColourLine())
branch->type(ShowerPartnerType::QCDColourLine);
else
assert(false);
}
else if(branch->branchingParticle()->colourLine()) {
branch->type(ShowerPartnerType::QCDColourLine);
}
else if(branch->branchingParticle()->antiColourLine()) {
branch->type(ShowerPartnerType::QCDAntiColourLine);
}
else
assert(false);
}
else if(branch->branchingParticle()->id()==ParticleID::g &&
branch->children()[0]->branchingParticle()->id()==
-branch->children()[1]->branchingParticle()->id()) {
if(branch->branchingParticle()->showerKinematics()->z()>0.5)
branch->type(ShowerPartnerType::QCDAntiColourLine);
else
branch->type(ShowerPartnerType::QCDColourLine);
}
else
assert(false);
}
}
}
void Evolver::constructSpaceLikeLine(tShowerParticlePtr particle,
HardBranchingPtr & first,
HardBranchingPtr & last,
SudakovPtr sud,PPtr beam) {
if(!particle) return;
if(!particle->parents().empty()) {
tShowerParticlePtr parent =
dynamic_ptr_cast<ShowerParticlePtr>(particle->parents()[0]);
SudakovPtr newSud=particle->showerKinematics()->SudakovFormFactor();
constructSpaceLikeLine(parent,first,last,newSud,beam);
}
HardBranchingPtr newBranch =
new_ptr(HardBranching(particle,sud,last,HardBranching::Incoming));
newBranch->beam(beam);
if(!first) {
first=newBranch;
last =newBranch;
return;
}
last->addChild(newBranch);
tShowerParticlePtr timeChild =
dynamic_ptr_cast<ShowerParticlePtr>(particle->parents()[0]->children()[1]);
HardBranchingPtr timeBranch;
if(!timeChild->children().empty()) {
timeBranch =
new_ptr(HardBranching(timeChild,
timeChild->showerKinematics()->SudakovFormFactor(),
last,HardBranching::Outgoing));
constructTimeLikeLine(timeBranch,timeChild);
}
else {
timeBranch =
new_ptr(HardBranching(timeChild,SudakovPtr(),last,HardBranching::Outgoing));
}
last->addChild(timeBranch);
// sort out the type
if(last->branchingParticle() ->id() == ParticleID::gamma ||
newBranch->branchingParticle() ->id() == ParticleID::gamma ||
timeBranch->branchingParticle()->id() == ParticleID::gamma) {
last->type(ShowerPartnerType::QED);
}
else if(last->branchingParticle()->id()==newBranch->branchingParticle()->id()) {
if(last->branchingParticle()->id()==ParticleID::g) {
if(last->branchingParticle()->colourLine()==
newBranch->branchingParticle()->colourLine()) {
last->type(ShowerPartnerType::QCDAntiColourLine);
}
else {
last->type(ShowerPartnerType::QCDColourLine);
}
}
else if(last->branchingParticle()->hasColour()) {
last->type(ShowerPartnerType::QCDColourLine);
}
else if(last->branchingParticle()->hasAntiColour()) {
last->type(ShowerPartnerType::QCDAntiColourLine);
}
else
assert(false);
}
else if(newBranch->branchingParticle()->id()==ParticleID::g) {
if(last->branchingParticle()->hasColour()) {
last->type(ShowerPartnerType::QCDAntiColourLine);
}
else if(last->branchingParticle()->hasAntiColour()) {
last->type(ShowerPartnerType::QCDColourLine);
}
else
assert(false);
}
else if(newBranch->branchingParticle()->hasColour()) {
last->type(ShowerPartnerType::QCDColourLine);
}
else if(newBranch->branchingParticle()->hasAntiColour()) {
last->type(ShowerPartnerType::QCDAntiColourLine);
}
else {
assert(false);
}
last=newBranch;
}
void Evolver::connectTrees(ShowerTreePtr showerTree,
HardTreePtr hardTree, bool hard ) {
ShowerParticleVector particles;
// find the Sudakovs
for(set<HardBranchingPtr>::iterator cit=hardTree->branchings().begin();
cit!=hardTree->branchings().end();++cit) {
// Sudakovs for ISR
if((**cit).parent()&&(**cit).status()==HardBranching::Incoming) {
++_nis;
IdList br(3);
br[0] = (**cit).parent()->branchingParticle()->id();
br[1] = (**cit). branchingParticle()->id();
br[2] = (**cit).parent()->children()[0]==*cit ?
(**cit).parent()->children()[1]->branchingParticle()->id() :
(**cit).parent()->children()[0]->branchingParticle()->id();
BranchingList branchings = splittingGenerator()->initialStateBranchings();
if(br[1]<0&&br[0]==br[1]) {
br[0] = abs(br[0]);
br[1] = abs(br[1]);
}
else if(br[1]<0) {
br[1] = -br[1];
br[2] = -br[2];
}
long index = abs(br[1]);
SudakovPtr sudakov;
for(BranchingList::const_iterator cjt = branchings.lower_bound(index);
cjt != branchings.upper_bound(index); ++cjt ) {
IdList ids = cjt->second.second;
if(ids[0]==br[0]&&ids[1]==br[1]&&ids[2]==br[2]) {
sudakov=cjt->second.first;
break;
}
}
if(!sudakov) throw Exception() << "Can't find Sudakov for the hard emission in "
<< "Evolver::connectTrees() for ISR"
<< Exception::runerror;
(**cit).parent()->sudakov(sudakov);
}
// Sudakovs for FSR
else if(!(**cit).children().empty()) {
++_nfs;
IdList br(3);
br[0] = (**cit) .branchingParticle()->id();
br[1] = (**cit).children()[0]->branchingParticle()->id();
br[2] = (**cit).children()[1]->branchingParticle()->id();
BranchingList branchings = splittingGenerator()->finalStateBranchings();
if(br[0]<0) {
br[0] = abs(br[0]);
br[1] = abs(br[1]);
br[2] = abs(br[2]);
}
long index = br[0];
SudakovPtr sudakov;
for(BranchingList::const_iterator cjt = branchings.lower_bound(index);
cjt != branchings.upper_bound(index); ++cjt ) {
IdList ids = cjt->second.second;
if(ids[0]==br[0]&&ids[1]==br[1]&&ids[2]==br[2]) {
sudakov=cjt->second.first;
break;
}
}
if(!sudakov) throw Exception() << "Can't find Sudakov for the hard emission in "
<< "Evolver::connectTrees()"
<< Exception::runerror;
(**cit).sudakov(sudakov);
}
}
// calculate the evolution scale
for(set<HardBranchingPtr>::iterator cit=hardTree->branchings().begin();
cit!=hardTree->branchings().end();++cit) {
particles.push_back((*cit)->branchingParticle());
}
showerModel()->partnerFinder()->
setInitialEvolutionScales(particles,!hard,hardTree->interaction(),
!hardTree->partnersSet());
hardTree->partnersSet(true);
// inverse reconstruction
if(hard) {
showerModel()->kinematicsReconstructor()->
deconstructHardJets(hardTree,ShowerHandler::currentHandler()->evolver(),
hardTree->interaction());
}
else
showerModel()->kinematicsReconstructor()->
deconstructDecayJets(hardTree,ShowerHandler::currentHandler()->evolver(),
hardTree->interaction());
// now reset the momenta of the showering particles
vector<ShowerProgenitorPtr> particlesToShower;
for(map<ShowerProgenitorPtr,ShowerParticlePtr>::const_iterator
cit=showerTree->incomingLines().begin();
cit!=showerTree->incomingLines().end();++cit )
particlesToShower.push_back(cit->first);
// extract the showering particles
for(map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator
cit=showerTree->outgoingLines().begin();
cit!=showerTree->outgoingLines().end();++cit )
particlesToShower.push_back(cit->first);
// match them
map<ShowerProgenitorPtr,HardBranchingPtr> partners;
for(set<HardBranchingPtr>::const_iterator bit=hardTree->branchings().begin();
bit!=hardTree->branchings().end();++bit) {
Energy2 dmin( 1e30*GeV2 );
ShowerProgenitorPtr partner;
for(vector<ShowerProgenitorPtr>::const_iterator pit=particlesToShower.begin();
pit!=particlesToShower.end();++pit) {
if(partners.find(*pit)!=partners.end()) continue;
if( (**bit).branchingParticle()->id() != (**pit).progenitor()->id() ) continue;
if( (**bit).branchingParticle()->isFinalState() !=
(**pit).progenitor()->isFinalState() ) continue;
if( (**pit).progenitor()->isFinalState() ) {
Energy2 dtest =
sqr( (**pit).progenitor()->momentum().x() - (**bit).showerMomentum().x() ) +
sqr( (**pit).progenitor()->momentum().y() - (**bit).showerMomentum().y() ) +
sqr( (**pit).progenitor()->momentum().z() - (**bit).showerMomentum().z() ) +
sqr( (**pit).progenitor()->momentum().t() - (**bit).showerMomentum().t() );
// add mass difference for identical particles (e.g. Z0 Z0 production)
dtest += 1e10*sqr((**pit).progenitor()->momentum().m()-(**bit).showerMomentum().m());
if( dtest < dmin ) {
partner = *pit;
dmin = dtest;
}
}
else {
// ensure directions are right
if((**pit).progenitor()->momentum().z()/(**bit).showerMomentum().z()>ZERO) {
partner = *pit;
break;
}
}
}
if(!partner) throw Exception() << "Failed to match shower and hard trees in Evolver::hardestEmission"
<< Exception::eventerror;
partners[partner] = *bit;
}
for(vector<ShowerProgenitorPtr>::const_iterator pit=particlesToShower.begin();
pit!=particlesToShower.end();++pit) {
HardBranchingPtr partner = partners[*pit];
if((**pit).progenitor()->dataPtr()->stable()) {
(**pit).progenitor()->set5Momentum(partner->showerMomentum());
(**pit).copy()->set5Momentum(partner->showerMomentum());
}
else {
Lorentz5Momentum oldMomentum = (**pit).progenitor()->momentum();
Lorentz5Momentum newMomentum = partner->showerMomentum();
LorentzRotation boost( oldMomentum.findBoostToCM(),oldMomentum.e()/oldMomentum.mass());
(**pit).progenitor()->transform(boost);
(**pit).copy() ->transform(boost);
boost = LorentzRotation(-newMomentum.findBoostToCM(),newMomentum.e()/newMomentum.mass());
(**pit).progenitor()->transform(boost);
(**pit).copy() ->transform(boost);
}
}
// 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());
decayTree->transform(boost,true);
boost = LorentzRotation(-newMomentum.findBoostToCM(),newMomentum.e()/newMomentum.mass());
decayTree->transform(boost,true);
}
}
void Evolver::doShowering(bool hard,XCPtr xcomb) {
// order of the interactions
bool showerOrder(true);
// zero number of emissions
_nis = _nfs = 0;
// if MC@NLO H event and limited emissions
// indicate both final and initial state emission
if ( isMCatNLOHEvent && _limitEmissions != 0 ) {
_nis = _nfs = 1;
}
// extract particles to shower
vector<ShowerProgenitorPtr> particlesToShower(setupShower(hard));
// setup the maximum scales for the shower
if (hardVetoOn()) setupMaximumScales(particlesToShower,xcomb);
// set the hard scales for the profiles
setupHardScales(particlesToShower,xcomb);
// specific stuff for hard processes and decays
Energy minmass(ZERO), mIn(ZERO);
// hard process generate the intrinsic p_T once and for all
if(hard) {
generateIntrinsicpT(particlesToShower);
}
// decay compute the minimum mass of the final-state
else {
for(unsigned int ix=0;ix<particlesToShower.size();++ix) {
if(particlesToShower[ix]->progenitor()->isFinalState()) {
if(particlesToShower[ix]->progenitor()->dataPtr()->stable())
minmass += particlesToShower[ix]->progenitor()->dataPtr()->constituentMass();
else
minmass += particlesToShower[ix]->progenitor()->mass();
}
else {
mIn = particlesToShower[ix]->progenitor()->mass();
}
}
// throw exception if decay can't happen
if ( minmass > mIn ) {
throw Exception() << "Evolver.cc: Mass of decaying particle is "
<< "below constituent masses of decay products."
<< Exception::eventerror;
}
}
// check if interactions in right order
if(hardTree() && interaction_!=4 &&
hardTree()->interaction()!=interactions_[0]) {
assert(interactions_.size()==2);
showerOrder = false;
swap(interactions_[0],interactions_[1]);
}
// loop over possible interactions
for(unsigned int inter=0;inter<interactions_.size();++inter) {
// set up for second pass if required
if(inter!=0) {
// zero intrinsic pt so only added first time round
intrinsicpT().clear();
// construct the tree and throw veto if not possible
if(!(hard ?
constructHardTree (particlesToShower,interactions_[inter]) :
constructDecayTree(particlesToShower,interactions_[inter])))
throw InteractionVeto();
}
// create random particle vector (only need to do once)
vector<ShowerProgenitorPtr> tmp;
unsigned int nColouredIncoming = 0;
while(particlesToShower.size()>0){
unsigned int xx=UseRandom::irnd(particlesToShower.size());
tmp.push_back(particlesToShower[xx]);
particlesToShower.erase(particlesToShower.begin()+xx);
}
particlesToShower=tmp;
for(unsigned int ix=0;ix<particlesToShower.size();++ix) {
if(!particlesToShower[ix]->progenitor()->isFinalState() &&
particlesToShower[ix]->progenitor()->coloured()) ++nColouredIncoming;
}
bool switchRecon = hard && nColouredIncoming !=1;
// main shower loop
unsigned int ntry(0);
bool reconstructed = false;
do {
// clear results of last attempt if needed
if(ntry!=0) {
currentTree()->clear();
setEvolutionPartners(hard,interactions_[inter],true);
_nis = _nfs = 0;
// if MC@NLO H event and limited emissions
// indicate both final and initial state emission
if ( isMCatNLOHEvent && _limitEmissions != 0 ) {
_nis = _nfs = 1;
}
for(unsigned int ix=0; ix<particlesToShower.size();++ix) {
SpinPtr spin = particlesToShower[ix]->progenitor()->spinInfo();
if(spin && spin->decayVertex() &&
dynamic_ptr_cast<tcSVertexPtr>(spin->decayVertex())) {
spin->decayVertex(VertexPtr());
}
}
}
// loop over particles
for(unsigned int ix=0;ix<particlesToShower.size();++ix) {
// extract the progenitor
progenitor(particlesToShower[ix]);
// final-state radiation
if(progenitor()->progenitor()->isFinalState()) {
if(!isFSRadiationON()) continue;
// perform shower
progenitor()->hasEmitted(startTimeLikeShower(interactions_[inter]));
}
// initial-state radiation
else {
if(!isISRadiationON()) continue;
// hard process
if(hard) {
// get the PDF
setBeamParticle(_progenitor->beam());
assert(beamParticle());
// perform the shower
// set the beam particle
tPPtr beamparticle=progenitor()->original();
if(!beamparticle->parents().empty())
beamparticle=beamparticle->parents()[0];
// generate the shower
progenitor()->hasEmitted(startSpaceLikeShower(beamparticle,
interactions_[inter]));
}
// decay
else {
// skip colour and electrically neutral particles
if(!progenitor()->progenitor()->dataPtr()->coloured() &&
!progenitor()->progenitor()->dataPtr()->charged()) {
progenitor()->hasEmitted(false);
continue;
}
// perform shower
// set the scales correctly. The current scale is the maximum scale for
// emission not the starting scale
ShowerParticle::EvolutionScales maxScales(progenitor()->progenitor()->scales());
progenitor()->progenitor()->scales() = ShowerParticle::EvolutionScales();
if(progenitor()->progenitor()->dataPtr()->charged()) {
progenitor()->progenitor()->scales().QED = progenitor()->progenitor()->mass();
progenitor()->progenitor()->scales().QED_noAO = progenitor()->progenitor()->mass();
}
if(progenitor()->progenitor()->hasColour()) {
progenitor()->progenitor()->scales().QCD_c = progenitor()->progenitor()->mass();
progenitor()->progenitor()->scales().QCD_c_noAO = progenitor()->progenitor()->mass();
}
if(progenitor()->progenitor()->hasAntiColour()) {
progenitor()->progenitor()->scales().QCD_ac = progenitor()->progenitor()->mass();
progenitor()->progenitor()->scales().QCD_ac_noAO = progenitor()->progenitor()->mass();
}
// perform the shower
progenitor()->hasEmitted(startSpaceLikeDecayShower(maxScales,minmass,
interactions_[inter]));
}
}
}
// do the kinematic reconstruction, checking if it worked
reconstructed = hard ?
showerModel()->kinematicsReconstructor()->
reconstructHardJets (currentTree(),intrinsicpT(),interactions_[inter],
switchRecon && ntry>maximumTries()/2) :
showerModel()->kinematicsReconstructor()->
reconstructDecayJets(currentTree(),interactions_[inter]);
}
while(!reconstructed&&maximumTries()>++ntry);
// check if failed to generate the shower
if(ntry==maximumTries()) {
if(hard)
throw ShowerHandler::ShowerTriesVeto(ntry);
else
throw Exception() << "Failed to generate the shower after "
<< ntry << " attempts in Evolver::showerDecay()"
<< Exception::eventerror;
}
}
// tree has now showered
_currenttree->hasShowered(true);
if(!showerOrder) swap(interactions_[0],interactions_[1]);
hardTree(HardTreePtr());
}
void Evolver:: convertHardTree(bool hard,ShowerInteraction::Type type) {
map<ColinePtr,ColinePtr> cmap;
// incoming particles
for(map<ShowerProgenitorPtr,ShowerParticlePtr>::const_iterator
cit=currentTree()->incomingLines().begin();cit!=currentTree()->incomingLines().end();++cit) {
map<ShowerParticlePtr,tHardBranchingPtr>::const_iterator
mit = hardTree()->particles().find(cit->first->progenitor());
// put the colour lines in the map
ShowerParticlePtr oldParticle = cit->first->progenitor();
ShowerParticlePtr newParticle = mit->second->branchingParticle();
ColinePtr cLine = oldParticle-> colourLine();
ColinePtr aLine = oldParticle->antiColourLine();
if(newParticle->colourLine() &&
cmap.find(newParticle-> colourLine())==cmap.end())
cmap[newParticle-> colourLine()] = cLine;
if(newParticle->antiColourLine() &&
cmap.find(newParticle->antiColourLine())==cmap.end())
cmap[newParticle->antiColourLine()] = aLine;
// check whether or not particle emits
bool emission = mit->second->parent();
if(emission) {
if(newParticle->colourLine()) {
ColinePtr ctemp = newParticle-> colourLine();
ctemp->removeColoured(newParticle);
}
if(newParticle->antiColourLine()) {
ColinePtr ctemp = newParticle->antiColourLine();
ctemp->removeAntiColoured(newParticle);
}
newParticle = mit->second->parent()->branchingParticle();
}
// get the new colour lines
ColinePtr newCLine,newALine;
// sort out colour lines
if(newParticle->colourLine()) {
ColinePtr ctemp = newParticle-> colourLine();
ctemp->removeColoured(newParticle);
if(cmap.find(ctemp)!=cmap.end()) {
newCLine = cmap[ctemp];
}
else {
newCLine = new_ptr(ColourLine());
cmap[ctemp] = newCLine;
}
}
// and anticolour lines
if(newParticle->antiColourLine()) {
ColinePtr ctemp = newParticle->antiColourLine();
ctemp->removeAntiColoured(newParticle);
if(cmap.find(ctemp)!=cmap.end()) {
newALine = cmap[ctemp];
}
else {
newALine = new_ptr(ColourLine());
cmap[ctemp] = newALine;
}
}
// remove colour lines from old particle
if(aLine) {
aLine->removeAntiColoured(cit->first->copy());
aLine->removeAntiColoured(cit->first->progenitor());
}
if(cLine) {
cLine->removeColoured(cit->first->copy());
cLine->removeColoured(cit->first->progenitor());
}
// add particle to colour lines
if(newCLine) newCLine->addColoured (newParticle);
if(newALine) newALine->addAntiColoured(newParticle);
// insert new particles
cit->first->copy(newParticle);
ShowerParticlePtr sp(new_ptr(ShowerParticle(*newParticle,1,false)));
cit->first->progenitor(sp);
currentTree()->incomingLines()[cit->first]=sp;
cit->first->perturbative(!emission);
// and the emitted particle if needed
if(emission) {
ShowerParticlePtr newOut = mit->second->parent()->children()[1]->branchingParticle();
if(newOut->colourLine()) {
ColinePtr ctemp = newOut-> colourLine();
ctemp->removeColoured(newOut);
assert(cmap.find(ctemp)!=cmap.end());
cmap[ctemp]->addColoured (newOut);
}
if(newOut->antiColourLine()) {
ColinePtr ctemp = newOut->antiColourLine();
ctemp->removeAntiColoured(newOut);
assert(cmap.find(ctemp)!=cmap.end());
cmap[ctemp]->addAntiColoured(newOut);
}
ShowerParticlePtr sout=new_ptr(ShowerParticle(*newOut,1,true));
ShowerProgenitorPtr out=new_ptr(ShowerProgenitor(cit->first->original(),newOut,sout));
out->perturbative(false);
currentTree()->outgoingLines().insert(make_pair(out,sout));
}
if(hard) {
// sort out the value of x
if(mit->second->beam()->momentum().z()>ZERO) {
sp->x(newParticle->momentum(). plus()/mit->second->beam()->momentum(). plus());
}
else {
sp->x(newParticle->momentum().minus()/mit->second->beam()->momentum().minus());
}
}
}
// outgoing particles
for(map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator
cit=currentTree()->outgoingLines().begin();cit!=currentTree()->outgoingLines().end();++cit) {
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==cit->first->progenitor())
break;
}
map<ShowerParticlePtr,tHardBranchingPtr>::const_iterator
mit = hardTree()->particles().find(cit->first->progenitor());
if(mit==hardTree()->particles().end()) continue;
// put the colour lines in the map
ShowerParticlePtr oldParticle = cit->first->progenitor();
ShowerParticlePtr newParticle = mit->second->branchingParticle();
ShowerParticlePtr newOut;
ColinePtr cLine = oldParticle-> colourLine();
ColinePtr aLine = oldParticle->antiColourLine();
if(newParticle->colourLine() &&
cmap.find(newParticle-> colourLine())==cmap.end())
cmap[newParticle-> colourLine()] = cLine;
if(newParticle->antiColourLine() &&
cmap.find(newParticle->antiColourLine())==cmap.end())
cmap[newParticle->antiColourLine()] = aLine;
// check whether or not particle emits
bool emission = !mit->second->children().empty();
if(emission) {
if(newParticle->colourLine()) {
ColinePtr ctemp = newParticle-> colourLine();
ctemp->removeColoured(newParticle);
}
if(newParticle->antiColourLine()) {
ColinePtr ctemp = newParticle->antiColourLine();
ctemp->removeAntiColoured(newParticle);
}
newParticle = mit->second->children()[0]->branchingParticle();
newOut = mit->second->children()[1]->branchingParticle();
if(newParticle->id()!=oldParticle->id()&&newParticle->id()==newOut->id())
swap(newParticle,newOut);
}
// get the new colour lines
ColinePtr newCLine,newALine;
// sort out colour lines
if(newParticle->colourLine()) {
ColinePtr ctemp = newParticle-> colourLine();
ctemp->removeColoured(newParticle);
if(cmap.find(ctemp)!=cmap.end()) {
newCLine = cmap[ctemp];
}
else {
newCLine = new_ptr(ColourLine());
cmap[ctemp] = newCLine;
}
}
// and anticolour lines
if(newParticle->antiColourLine()) {
ColinePtr ctemp = newParticle->antiColourLine();
ctemp->removeAntiColoured(newParticle);
if(cmap.find(ctemp)!=cmap.end()) {
newALine = cmap[ctemp];
}
else {
newALine = new_ptr(ColourLine());
cmap[ctemp] = newALine;
}
}
// remove colour lines from old particle
if(aLine) {
aLine->removeAntiColoured(cit->first->copy());
aLine->removeAntiColoured(cit->first->progenitor());
}
if(cLine) {
cLine->removeColoured(cit->first->copy());
cLine->removeColoured(cit->first->progenitor());
}
// special for unstable particles
if(newParticle->id()==oldParticle->id() &&
(tit!=currentTree()->treelinks().end()||!oldParticle->dataPtr()->stable())) {
Lorentz5Momentum oldMomentum = oldParticle->momentum();
Lorentz5Momentum newMomentum = newParticle->momentum();
LorentzRotation boost( oldMomentum.findBoostToCM(),oldMomentum.e()/oldMomentum.mass());
if(tit!=currentTree()->treelinks().end()) tit->first->transform(boost,false);
oldParticle->transform(boost);
boost = LorentzRotation(-newMomentum.findBoostToCM(),newMomentum.e()/newMomentum.mass());
oldParticle->transform(boost);
if(tit!=currentTree()->treelinks().end()) tit->first->transform(boost,false);
newParticle=oldParticle;
}
// add particle to colour lines
if(newCLine) newCLine->addColoured (newParticle);
if(newALine) newALine->addAntiColoured(newParticle);
// insert new particles
cit->first->copy(newParticle);
ShowerParticlePtr sp(new_ptr(ShowerParticle(*newParticle,1,true)));
cit->first->progenitor(sp);
currentTree()->outgoingLines()[cit->first]=sp;
cit->first->perturbative(!emission);
// and the emitted particle if needed
if(emission) {
if(newOut->colourLine()) {
ColinePtr ctemp = newOut-> colourLine();
ctemp->removeColoured(newOut);
assert(cmap.find(ctemp)!=cmap.end());
cmap[ctemp]->addColoured (newOut);
}
if(newOut->antiColourLine()) {
ColinePtr ctemp = newOut->antiColourLine();
ctemp->removeAntiColoured(newOut);
assert(cmap.find(ctemp)!=cmap.end());
cmap[ctemp]->addAntiColoured(newOut);
}
ShowerParticlePtr sout=new_ptr(ShowerParticle(*newOut,1,true));
ShowerProgenitorPtr out=new_ptr(ShowerProgenitor(cit->first->original(),newOut,sout));
out->perturbative(false);
currentTree()->outgoingLines().insert(make_pair(out,sout));
}
// update any decay products
if(tit!=currentTree()->treelinks().end())
currentTree()->updateLink(tit->first,make_pair(cit->first,sp));
}
// reset the tree
currentTree()->resetShowerProducts();
// reextract the particles and set the colour partners
vector<ShowerParticlePtr> particles =
currentTree()->extractProgenitorParticles();
// clear the partners
for(unsigned int ix=0;ix<particles.size();++ix) {
particles[ix]->partner(ShowerParticlePtr());
particles[ix]->clearPartners();
}
// clear the tree
hardTree(HardTreePtr());
// Set the initial evolution scales
showerModel()->partnerFinder()->
setInitialEvolutionScales(particles,!hard,type,!_hardtree);
}
diff --git a/Shower/Base/Evolver.h b/Shower/Base/Evolver.h
--- a/Shower/Base/Evolver.h
+++ b/Shower/Base/Evolver.h
@@ -1,908 +1,946 @@
// -*- 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"
#include "Herwig/MatrixElement/Matchbox/Matching/ShowerApproximation.h"
namespace Herwig {
using namespace ThePEG;
/**\ingroup Shower
* Exception class
* used to communicate failure of QED shower
*/
struct InteractionVeto {};
/** \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),
_massVetoOption(1), _hardVetoReadOption(false),
_iptrms(ZERO), _beta(0.), _gamma(ZERO), _iptmax(),
_limitEmissions(0), _initialenhance(1.), _finalenhance(1.),
interaction_(1), _trunc_Mode(true), _hardEmissionMode(0),
_spinOpt(1), _softOpt(2), _hardPOWHEG(false),
theFactorizationScaleFactor(1.0),
- theRenormalizationScaleFactor(1.0)
+ theRenormalizationScaleFactor(1.0), muPt(ZERO),
+ _maxTryFSR(100000),_maxFailFSR(100),_fracFSR(0.001),
+ _nFSR(0), _nFailedFSR(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; }
/**
* Mode for hard emissions
*/
int hardEmissionMode() const {return _hardEmissionMode;}
/**
* Switch on or off hard vetoes
*/
void restrictPhasespace(bool yes) {
if ( yes )
_hardVetoMode = 1;
else
_hardVetoMode = 0;
}
/**
* Switch on or off hard veto scale from muF
*/
void hardScaleIsMuF(bool yes) {
if ( yes )
_hardVetoRead = 1;
else
_hardVetoRead = 0;
}
//@}
/**
* Connect the Hard and Shower trees
*/
virtual void connectTrees(ShowerTreePtr showerTree, HardTreePtr hardTree, bool hard );
/**
* Access to switches for spin correlations
*/
//@{
/**
* Spin Correlations
*/
unsigned int spinCorrelations() const {
return _spinOpt;
}
/**
* Soft correlations
*/
unsigned int softCorrelations() const {
return _softOpt;
}
/**
* Any correlations
*/
bool correlations() const {
return _spinOpt!=0||_softOpt!=0;
}
//@}
/**
* Set the factorization scale factor
*/
void factorizationScaleFactor(double f) {
if ( f == theFactorizationScaleFactor )
return;
theFactorizationScaleFactor = f;
splittingGenerator()->factorizationScaleFactor(f);
}
/**
* Set the renormalization scale factor
*/
void renormalizationScaleFactor(double f) {
if ( f == theRenormalizationScaleFactor )
return;
theRenormalizationScaleFactor = f;
splittingGenerator()->renormalizationScaleFactor(f);
}
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:
/**
* Perform the shower
*/
void doShowering(bool hard,XCPtr);
/**
* 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,
bool clear);
/**
* Methods to perform the evolution of an individual particle, including
* recursive calling on the products
*/
//@{
/**
* It does the forward evolution of the time-like input particle
* (and recursively for all its radiation products).
* accepting only emissions which conforms to the showerVariables
* and soft matrix element correction.
* If at least one emission has occurred then the method returns true.
* @param particle The particle to be showered
*/
virtual bool timeLikeShower(tShowerParticlePtr particle, ShowerInteraction::Type,
Branching fb, bool first);
/**
* It does the backward evolution of the space-like input particle
* (and recursively for all its time-like radiation products).
* accepting only emissions which conforms to the showerVariables.
* If at least one emission has occurred then the method returns true
* @param particle The particle to be showered
* @param beam The beam particle
*/
virtual bool spaceLikeShower(tShowerParticlePtr particle,PPtr beam,
ShowerInteraction::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,
const ShowerParticle::EvolutionScales & maxScales,
Energy minimumMass,ShowerInteraction::Type);
/**
* Truncated shower from a time-like particle
*/
virtual bool truncatedTimeLikeShower(tShowerParticlePtr particle,
HardBranchingPtr branch,
ShowerInteraction::Type type, bool first);
/**
* 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,
const ShowerParticle::EvolutionScales & maxScales,
Energy minimumMass, HardBranchingPtr branch,
ShowerInteraction::Type type);
//@}
/**
* Switches for matrix element corrections
*/
//@{
/**
* Any ME correction?
*/
bool MECOn(bool hard) const {
return ( _hardEmissionMode == 0 ||
(!hard && _hardEmissionMode ==-1) ) &&
_meCorrMode > 0;
}
/**
* Any hard ME correction?
*/
bool hardMEC(bool hard) const {
return ( _hardEmissionMode == 0 ||
(!hard && _hardEmissionMode ==-1) ) &&
(_meCorrMode == 1 || _meCorrMode == 2);
}
/**
* Any soft ME correction?
*/
bool softMEC() const {
return ( _hardEmissionMode == 0 ||
(_currenttree->isDecay() && _hardEmissionMode ==-1) ) &&
(_meCorrMode == 1 || _meCorrMode > 2);
}
//@}
/**
* Is the truncated shower on?
*/
bool isTruncatedShowerON() const {return _trunc_Mode;}
/**
* Switch for intrinsic pT
*/
//@{
/**
* Any intrinsic pT?
*/
bool ipTon() const {
return _iptrms != ZERO || ( _beta == 1.0 && _gamma != ZERO && _iptmax !=ZERO );
}
//@}
/**@name Additional shower vetoes */
//@{
/**
* Insert a veto.
*/
void addVeto (ShowerVetoPtr v) { _vetoes.push_back(v); }
/**
* Remove a veto.
*/
void removeVeto (ShowerVetoPtr v) {
vector<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(const vector<ShowerProgenitorPtr> &,XCPtr);
/**
* find the relevant hard scales for profile scales.
*/
void setupHardScales(const vector<ShowerProgenitorPtr> &,XCPtr);
/**
+ * Return the relevant hard scale to be used in the profile scales
+ */
+ Energy hardScale() const {
+ return muPt;
+ }
+
+ /**
* Convert the HardTree into an extra shower emission
*/
void convertHardTree(bool hard,ShowerInteraction::Type type);
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(const ShowerParticle::EvolutionScales & maxScales,
Energy minimumMass,ShowerInteraction::Type);
/**
* Select the branching for the next time-like emission
*/
Branching selectTimeLikeBranching(tShowerParticlePtr particle,
ShowerInteraction::Type type);
/**
* Create the timelike child of a branching
*/
ShowerParticleVector createTimeLikeChildren(tShowerParticlePtr particle,
IdList ids);
/**
* Vetos for the timelike shower
*/
virtual bool timeLikeVetoed(const Branching &,ShowerParticlePtr);
/**
* Vetos for the spacelike shower
*/
virtual bool spaceLikeVetoed(const Branching &,ShowerParticlePtr);
/**
* Vetos for the spacelike shower
*/
virtual bool spaceLikeDecayVetoed(const Branching &,ShowerParticlePtr);
/**
* Only generate the hard emission, for testing only.
*/
bool hardOnly() const {return _limitEmissions==3;}
/**
* Members to construct the HardTree from the shower if needed
*/
//@{
/**
* Construct the tree for a scattering process
*/
bool constructHardTree(vector<ShowerProgenitorPtr> & particlesToShower,
ShowerInteraction::Type inter);
/**
* Construct the tree for a decay process
*/
bool constructDecayTree(vector<ShowerProgenitorPtr> & particlesToShower,
ShowerInteraction::Type inter);
/**
* Construct a time-like line
*/
void constructTimeLikeLine(tHardBranchingPtr branch,tShowerParticlePtr particle);
/**
* Construct a space-like line
*/
void constructSpaceLikeLine(tShowerParticlePtr particle,
HardBranchingPtr & first, HardBranchingPtr & last,
SudakovPtr sud,PPtr beam);
//@}
public:
/** @name MC@NLO diagnostics */
//@{
/**
* True, if Matchbox MC@NLO S-event
*/
bool wasMCatNLOSEvent() const { return isMCatNLOSEvent; }
/**
* True, if matchbox MC@NLO H-event
*/
bool wasMCatNLOHEvent() const { return isMCatNLOHEvent; }
//@}
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:
/**
* 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;
/**
* Option for inclusion of mass veto
*/
unsigned int _massVetoOption;
/**
* 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;
/**
* The option for wqhich interactions to use
*/
unsigned int interaction_;
/**
* Interactions allowed in the shower
*/
vector<ShowerInteraction::Type> interactions_;
/**
* Truncated shower switch
*/
bool _trunc_Mode;
/**
* Count of the number of truncated emissions
*/
unsigned int _truncEmissions;
/**
* Mode for the hard emissions
*/
int _hardEmissionMode;
/**
* Option to include spin correlations
*/
unsigned int _spinOpt;
/**
* Option for the kernal for soft correlations
*/
unsigned int _softOpt;
/**
* Option for hard radiation in POWHEG events
*/
bool _hardPOWHEG;
/**
* True, if Matchbox MC@NLO S-event
*/
bool isMCatNLOSEvent;
/**
* True, if matchbox MC@NLO H-event
*/
bool isMCatNLOHEvent;
/**
* True, if Matchbox Powheg S-event
*/
bool isPowhegSEvent;
/**
* True, if matchbox Powheg H-event
*/
bool isPowhegHEvent;
/**
* The shower approximation to provide the hard scale profile
*/
Ptr<ShowerApproximation>::tptr theShowerApproximation;
/**
* The factorization scale factor.
*/
double theFactorizationScaleFactor;
/**
* The renormalization scale factor.
*/
double theRenormalizationScaleFactor;
/**
* True if no warnings about incorrect hard emission
* mode setting have been issued yet
*/
static bool _hardEmissionModeWarn;
/**
* True if no warnings about missing truncated shower
* have been issued yet
*/
static bool _missingTruncWarn;
+ /**
+ * The relevant hard scale to be used in the profile scales
+ */
+ Energy muPt;
+
+ /**
+ * Maximum number of emission attempts for FSR
+ */
+ unsigned int _maxTryFSR;
+
+ /**
+ * Maximum number of failures for FSR generation
+ */
+ unsigned int _maxFailFSR;
+
+ /**
+ * Failure fraction for FSR generation
+ */
+ double _fracFSR;
+
+ /**
+ * Counter for number of FSR emissions
+ */
+ unsigned int _nFSR;
+
+ /**
+ * Counter for the number of failed events due to FSR emissions
+ */
+ unsigned int _nFailedFSR;
};
}
#endif /* HERWIG_Evolver_H */
diff --git a/Shower/Base/ShowerTree.cc b/Shower/Base/ShowerTree.cc
--- a/Shower/Base/ShowerTree.cc
+++ b/Shower/Base/ShowerTree.cc
@@ -1,1471 +1,1477 @@
// -*- C++ -*-
//
// ShowerTree.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.
//
#include "ShowerProgenitor.h"
#include "ThePEG/EventRecord/MultiColour.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ShowerTree.h"
#include "Herwig/Shower/Base/ShowerParticle.h"
#include "Herwig/Shower/ShowerHandler.h"
#include "ThePEG/PDT/DecayMode.h"
#include "ThePEG/Handlers/EventHandler.h"
#include "ThePEG/Handlers/XComb.h"
#include "KinematicsReconstructor.h"
#include <cassert>
#include "ThePEG/Repository/CurrentGenerator.h"
#include "ThePEG/PDT/StandardMatchers.h"
using namespace Herwig;
using namespace ThePEG;
set<long> ShowerTree::_decayInShower = set<long>();
bool ShowerTree::_spaceTime = false;
Energy2 ShowerTree::_vmin2 = 0.1*GeV2;
namespace {
void findBeam(tPPtr & beam, PPtr incoming) {
while(!beam->children().empty()) {
bool found=false;
for(unsigned int ix=0;ix<beam->children().size();++ix) {
if(beam->children()[ix]==incoming) {
found = true;
break;
}
}
if(found) break;
beam = beam->children()[0];
}
}
}
// constructor from hard process
ShowerTree::ShowerTree(const PPair incoming, const ParticleVector & out,
ShowerDecayMap& decay)
: _hardMECorrection(false), _wasHard(true),
_parent(), _hasShowered(false) {
tPPair beam = CurrentGenerator::current().currentEvent()->incoming();
findBeam(beam.first ,incoming.first );
findBeam(beam.second,incoming.second);
_incoming = incoming;
double x1(_incoming.first ->momentum().rho()/beam.first ->momentum().rho());
double x2(_incoming.second->momentum().rho()/beam.second->momentum().rho());
// must have two incoming particles
assert(_incoming.first && _incoming.second);
// set the parent tree
_parent=ShowerTreePtr();
// temporary vectors to contain all the particles before insertion into
// the data structure
vector<PPtr> original,copy;
vector<ShowerParticlePtr> shower;
// create copies of ThePEG particles for the incoming particles
original.push_back(_incoming.first);
copy.push_back(new_ptr(Particle(*_incoming.first)));
original.push_back(_incoming.second);
copy.push_back(new_ptr(Particle(*_incoming.second)));
// and same for outgoing
map<PPtr,ShowerTreePtr> trees;
for (ParticleVector::const_iterator it = out.begin();
it != out.end(); ++it) {
// if decayed or should be decayed in shower make the tree
PPtr orig = *it;
bool radiates = false;
if(!orig->children().empty()) {
// remove d,u,s,c,b quarks and leptons other than on-shell taus
if(StandardQCDPartonMatcher::Check(orig->id())||
(LeptonMatcher::Check(orig->id())&& !(abs(orig->id())==ParticleID::tauminus && abs(orig->mass()-orig->dataPtr()->mass())<MeV))) {
radiates = true;
}
else {
bool foundParticle(false),foundGauge(false);
for(unsigned int iy=0;iy<orig->children().size();++iy) {
if(orig->children()[iy]->id()==orig->id()) {
foundParticle = true;
}
else if(orig->children()[iy]->id()==ParticleID::g ||
orig->children()[iy]->id()==ParticleID::gamma) {
foundGauge = true;
}
}
radiates = foundParticle && foundGauge;
}
}
if(radiates) {
findDecayProducts(orig,original,copy,decay,trees);
}
else if(!orig->children().empty()||
(decaysInShower(orig->id())&&!orig->dataPtr()->stable())) {
ShowerTreePtr newtree=new_ptr(ShowerTree(orig,decay));
newtree->setParents();
trees.insert(make_pair(orig,newtree));
Energy width=orig->dataPtr()->generateWidth(orig->mass());
decay.insert(make_pair(width,newtree));
original.push_back(orig);
copy.push_back(new_ptr(Particle(*orig)));
}
else {
original.push_back(orig);
copy.push_back(new_ptr(Particle(*orig)));
}
}
// colour isolate the hard process
colourIsolate(original,copy);
// now create the Shower particles
// create ShowerParticles for the incoming particles
assert(original.size() == copy.size());
for(unsigned int ix=0;ix<original.size();++ix) {
ShowerParticlePtr temp=new_ptr(ShowerParticle(*copy[ix],1,ix>=2));
fixColour(temp);
// incoming
if(ix<2) {
temp->x(ix==0 ? x1 : x2);
_incomingLines.insert(make_pair(new_ptr(ShowerProgenitor(original[ix],
copy[ix],temp)),temp));
_backward.insert(temp);
}
// outgoing
else {
_outgoingLines.insert(make_pair(new_ptr(ShowerProgenitor(original[ix],
copy[ix],temp)),temp));
_forward.insert(temp);
}
}
// set up the map of daughter trees
map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator mit;
for(mit=_outgoingLines.begin();mit!=_outgoingLines.end();++mit) {
map<PPtr,ShowerTreePtr>::const_iterator tit=trees.find(mit->first->original());
if(tit!=trees.end())
_treelinks.insert(make_pair(tit->second,
make_pair(mit->first,mit->first->progenitor())));
}
}
void ShowerTree::findDecayProducts(PPtr in, vector<PPtr> & original, vector<PPtr> & copy,
ShowerDecayMap& decay, map<PPtr,ShowerTreePtr> & trees) {
ParticleVector children=in->children();
for(unsigned int ix=0;ix<children.size();++ix) {
// if decayed or should be decayed in shower make the tree
PPtr orig=children[ix];
// in->abandonChild(orig);
bool radiates = false;
if(!orig->children().empty()) {
// remove d,u,s,c,b quarks and leptons other than on-shell taus
if(StandardQCDPartonMatcher::Check(orig->id())||
(LeptonMatcher::Check(orig->id())&& !(abs(orig->id())==ParticleID::tauminus && abs(orig->mass()-orig->dataPtr()->mass())<MeV))) {
radiates = true;
}
else {
bool foundParticle(false),foundGauge(false);
for(unsigned int iy=0;iy<orig->children().size();++iy) {
if(orig->children()[iy]->id()==orig->id()) {
foundParticle = true;
}
else if(orig->children()[iy]->id()==ParticleID::g ||
orig->children()[iy]->id()==ParticleID::gamma) {
foundGauge = true;
}
}
radiates = foundParticle && foundGauge;
}
}
if(radiates) {
findDecayProducts(orig,original,copy,decay,trees);
}
else if(!orig->children().empty()||
(decaysInShower(orig->id())&&!orig->dataPtr()->stable())) {
ShowerTreePtr newtree=new_ptr(ShowerTree(orig,decay));
trees.insert(make_pair(orig,newtree));
Energy width=orig->dataPtr()->generateWidth(orig->mass());
decay.insert(make_pair(width,newtree));
newtree->setParents();
newtree->_parent=this;
original.push_back(orig);
copy.push_back(new_ptr(Particle(*orig)));
}
else {
original.push_back(orig);
copy.push_back(new_ptr(Particle(*orig)));
}
}
}
ShowerTree::ShowerTree(PPtr in,
ShowerDecayMap& decay)
: _hardMECorrection(false), _wasHard(false), _hasShowered(false) {
// there must be an incoming particle
assert(in);
// temporary vectors to contain all the particles before insertion into
// the data structure
vector<PPtr> original,copy;
// insert place holder for incoming particle
original.push_back(in);
copy.push_back(PPtr());
// we need to deal with the decay products if decayed
map<PPtr,ShowerTreePtr> trees;
if(!in->children().empty()) {
ParticleVector children=in->children();
for(unsigned int ix=0;ix<children.size();++ix) {
// if decayed or should be decayed in shower make the tree
PPtr orig=children[ix];
in->abandonChild(orig);
bool radiates = false;
if(!orig->children().empty()) {
if(StandardQCDPartonMatcher::Check(orig->id())||
(LeptonMatcher::Check(orig->id())&& !(abs(orig->id())==ParticleID::tauminus && abs(orig->mass()-orig->dataPtr()->mass())<MeV))) {
radiates = true;
}
else {
bool foundParticle(false),foundGauge(false);
for(unsigned int iy=0;iy<orig->children().size();++iy) {
if(orig->children()[iy]->id()==orig->id()) {
foundParticle = true;
}
else if(orig->children()[iy]->id()==ParticleID::g ||
orig->children()[iy]->id()==ParticleID::gamma) {
foundGauge = true;
}
}
radiates = foundParticle && foundGauge;
}
// finally assume all non-decaying particles are in this class
if(!radiates) {
radiates = !decaysInShower(orig->id());
}
}
if(radiates) {
findDecayProducts(orig,original,copy,decay,trees);
}
else if(!orig->children().empty()||
(decaysInShower(orig->id())&&!orig->dataPtr()->stable())) {
ShowerTreePtr newtree=new_ptr(ShowerTree(orig,decay));
trees.insert(make_pair(orig,newtree));
Energy width=orig->dataPtr()->generateWidth(orig->mass());
decay.insert(make_pair(width,newtree));
newtree->setParents();
newtree->_parent=this;
original.push_back(orig);
copy.push_back(new_ptr(Particle(*orig)));
}
else {
original.push_back(orig);
copy.push_back(new_ptr(Particle(*orig)));
}
}
}
// create the incoming particle
copy[0] = new_ptr(Particle(*in));
// isolate the colour
colourIsolate(original,copy);
// create the parent
ShowerParticlePtr sparent(new_ptr(ShowerParticle(*copy[0],2,false)));
fixColour(sparent);
_incomingLines.insert(make_pair(new_ptr(ShowerProgenitor(original[0],copy[0],sparent))
,sparent));
// return if not decayed
if(original.size()==1) return;
// create the children
assert(copy.size() == original.size());
for (unsigned int ix=1;ix<original.size();++ix) {
ShowerParticlePtr stemp= new_ptr(ShowerParticle(*copy[ix],2,true));
fixColour(stemp);
_outgoingLines.insert(make_pair(new_ptr(ShowerProgenitor(original[ix],copy[ix],
stemp)),
stemp));
_forward.insert(stemp);
}
// set up the map of daughter trees
map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator mit;
for(mit=_outgoingLines.begin();mit!=_outgoingLines.end();++mit) {
map<PPtr,ShowerTreePtr>::const_iterator tit=trees.find(mit->first->original());
if(tit!=trees.end())
_treelinks.insert(make_pair(tit->second,
make_pair(mit->first,mit->first->progenitor())));
}
}
void ShowerTree::updateFinalStateShowerProduct(ShowerProgenitorPtr progenitor,
ShowerParticlePtr parent,
const ShowerParticleVector & children) {
assert(children.size()==2);
bool matches[2];
for(unsigned int ix=0;ix<2;++ix) {
matches[ix] = children[ix]->id()==progenitor->id();
}
ShowerParticlePtr newpart;
if(matches[0]&&matches[1]) {
if(parent->showerKinematics()->z()>0.5) newpart=children[0];
else newpart=children[1];
}
else if(matches[0]) newpart=children[0];
else if(matches[1]) newpart=children[1];
_outgoingLines[progenitor]=newpart;
}
void ShowerTree::updateInitialStateShowerProduct(ShowerProgenitorPtr progenitor,
ShowerParticlePtr newParent) {
_incomingLines[progenitor]=newParent;
}
void ShowerTree::isolateLine(vector<PPair>::const_iterator cit,
vector<PPair> & particles,
tcColinePtr oldline,
tColinePtr newline) {
// loop over particles
for(vector<PPair>::const_iterator cjt=particles.begin();
cjt!=particles.end();++cjt) {
if(cjt==cit) continue;
// if particle has colour line
if((*cjt).second->colourLine()) {
// if only one check if current line and reset
if(int((*cjt).second->colourInfo()->colourLines().size())==1) {
if((*cjt).second->colourLine()==oldline)
newline->addColoured((*cjt).first);
}
// if more than one check if each line current line and reset
else {
Ptr<MultiColour>::pointer colour1 =
dynamic_ptr_cast<Ptr<MultiColour>::pointer>
((*cjt).second->colourInfo());
Ptr<MultiColour>::pointer colour2 =
dynamic_ptr_cast<Ptr<MultiColour>::pointer>
((*cjt).first ->colourInfo());
for(unsigned int ix=0;ix<colour1->colourLines().size();++ix) {
if(colour1->colourLines()[ix]==oldline)
colour2->colourLine(newline,int(ix)+1);
}
}
}
// if particle has anticolour line
if((*cjt).second->antiColourLine()) {
// if only one check if current line and reset
if(int((*cjt).second->colourInfo()->antiColourLines().size())==1) {
if((*cjt).second->antiColourLine()==oldline)
newline->addColoured((*cjt).first,true);
}
// if more than one check if each line current line and reset
else {
Ptr<MultiColour>::pointer colour1 =
dynamic_ptr_cast<Ptr<MultiColour>::pointer>
((*cjt).second->colourInfo());
Ptr<MultiColour>::pointer colour2 =
dynamic_ptr_cast<Ptr<MultiColour>::pointer>
((*cjt).first ->colourInfo());
for(unsigned int ix=0;ix<colour1->antiColourLines().size();++ix) {
if(colour1->antiColourLines()[ix]==oldline)
colour2->antiColourLine(newline, int(ix)+1);
}
}
}
}
}
void ShowerTree::colourIsolate(const vector<PPtr> & original,
const vector<PPtr> & copy) {
// vectors must have same size
assert(original.size()==copy.size());
// create a temporary map with all the particles to make looping easier
vector<PPair> particles;
particles.reserve(original.size());
for(unsigned int ix=0;ix<original.size();++ix)
particles.push_back(make_pair(copy[ix],original[ix]));
// reset the colour of the copies
vector<PPair>::const_iterator cit;
// make the colour connections of the copies
for(cit=particles.begin();cit!=particles.end();++cit) {
if((*cit).first->colourInfo()) {
if((*cit).first->dataPtr()->iColour() == PDT::Colour6 ||
(*cit).first->dataPtr()->iColour() == PDT::Colour6bar)
(*cit).first->colourInfo(new_ptr(MultiColour()));
else
(*cit).first->colourInfo(new_ptr(ColourBase()));
}
}
map<tcColinePtr,tColinePtr> cmap;
// make the colour connections of the copies
// loop over the particles
for(cit=particles.begin();cit!=particles.end();++cit) {
// if particle has at least one colour line
if((*cit).second->colourLine()) {
// one and only one line
if(int((*cit).second->colourInfo()->colourLines().size())==1) {
// if not already change
if(!(*cit).first->colourLine()) {
// make new line
tcColinePtr oldline=(*cit).second->colourLine();
ColinePtr newline=ColourLine::create((*cit).first);
cmap[oldline]=newline;
isolateLine(cit,particles,oldline,newline);
}
}
// more than one line
else {
Ptr<MultiColour>::pointer colour1 =
dynamic_ptr_cast<Ptr<MultiColour>::pointer>
((*cit).second->colourInfo());
vector<tcColinePtr> lines1 = colour1->colourLines();
Ptr<MultiColour>::pointer colour2 =
dynamic_ptr_cast<Ptr<MultiColour>::pointer>
((*cit).first->colourInfo());
vector<tcColinePtr> lines2 = colour2->colourLines();
// loop over lines
for(unsigned int ix=0;ix<lines1.size();++ix) {
if( (lines2.size()>ix && !lines2[ix]) ||
lines2.size()<=ix) {
tcColinePtr oldline = lines1[ix];
ColinePtr newline = new_ptr(ColourLine());
cmap[oldline]=newline;
colour2->colourLine(newline, int(ix)+1);
isolateLine(cit,particles,oldline,newline);
}
}
}
}
// if anticolour line
if((*cit).second->antiColourLine()) {
// one and only one line
if(int((*cit).second->colourInfo()->antiColourLines().size())==1) {
// if not already change
if(!(*cit).first->antiColourLine()) {
// make new line
tcColinePtr oldline=(*cit).second->antiColourLine();
ColinePtr newline=ColourLine::create((*cit).first, true);
cmap[oldline]=newline;
isolateLine(cit,particles,oldline,newline);
}
}
// more than one line
else {
Ptr<MultiColour>::pointer colour1 =
dynamic_ptr_cast<Ptr<MultiColour>::pointer>
((*cit).second->colourInfo());
vector<tcColinePtr> lines1 = colour1->antiColourLines();
Ptr<MultiColour>::pointer colour2 =
dynamic_ptr_cast<Ptr<MultiColour>::pointer>
((*cit).first->colourInfo());
vector<tcColinePtr> lines2 = colour2->antiColourLines();
// loop over lines
for(unsigned int ix=0;ix<lines1.size();++ix) {
if( (lines2.size()>ix && !lines2[ix]) ||
lines2.size()<=ix) {
tcColinePtr oldline = lines1[ix];
ColinePtr newline = new_ptr(ColourLine());
cmap[oldline]=newline;
colour2->antiColourLine(newline, int(ix)+1);
isolateLine(cit,particles,oldline,newline);
}
}
}
}
}
// sort out sinks and sources
for(cit=particles.begin();cit!=particles.end();++cit) {
tColinePtr cline[2];
tColinePair cpair;
for(unsigned int ix=0;ix<4;++ix) {
cline[0] = ix<2 ? cit->second->colourLine() : cit->second->antiColourLine();
cline[1] = ix<2 ? cit->first ->colourLine() : cit->first ->antiColourLine();
if(cline[0]) {
switch (ix) {
case 0: case 2:
cpair = cline[0]->sinkNeighbours();
break;
case 1: case 3:
cpair = cline[0]->sourceNeighbours();
break;
};
}
else {
cpair = make_pair(tColinePtr(),tColinePtr());
}
if(cline[0]&&cpair.first) {
map<tcColinePtr,tColinePtr>::const_iterator
mit[2] = {cmap.find(cpair.first),cmap.find(cpair.second)};
if(mit[0]!=cmap.end()&&mit[1]!=cmap.end()) {
if(ix==0||ix==2) {
cline[1]->setSinkNeighbours(mit[0]->second,mit[1]->second);
}
else {
cline[1]->setSourceNeighbours(mit[0]->second,mit[1]->second);
}
}
}
}
}
}
void ShowerTree::mapColour(PPtr original,
PPtr copy) {
// has colour line
if(copy->colourLine()) {
// one and only one
if(copy->colourInfo()->colourLines().size()==1) {
_colour.insert(make_pair(copy->colourLine(),
original->colourLine()));
}
// more than one
else {
Ptr<MultiColour>::pointer colour1 =
dynamic_ptr_cast<Ptr<MultiColour>::pointer>(copy->colourInfo());
vector<tcColinePtr> lines1 = colour1->colourLines();
Ptr<MultiColour>::pointer colour2 =
dynamic_ptr_cast<Ptr<MultiColour>::pointer>(original->colourInfo());
vector<tcColinePtr> lines2 = colour2->colourLines();
for(unsigned int ix=0;ix<lines1.size();++ix)
_colour.insert(make_pair(const_ptr_cast<ColinePtr>(lines1[ix]),
const_ptr_cast<ColinePtr>(lines2[ix])));
}
}
// has anticolour line
if(copy->antiColourLine()) {
// one and only one
if(copy->colourInfo()->antiColourLines().size()==1) {
_colour.insert(make_pair(copy->antiColourLine(),
original->antiColourLine()));
}
// more than one
else {
Ptr<MultiColour>::pointer colour1 =
dynamic_ptr_cast<Ptr<MultiColour>::pointer>(copy->colourInfo());
vector<tcColinePtr> lines1 = colour1->antiColourLines();
Ptr<MultiColour>::pointer colour2 =
dynamic_ptr_cast<Ptr<MultiColour>::pointer>(original->colourInfo());
vector<tcColinePtr> lines2 = colour2->antiColourLines();
for(unsigned int ix=0;ix<lines1.size();++ix)
_colour.insert(make_pair(const_ptr_cast<ColinePtr>(lines1[ix]),
const_ptr_cast<ColinePtr>(lines2[ix])));
}
}
}
void ShowerTree::insertHard(StepPtr pstep, bool ISR, bool) {
assert(_incomingLines.size()==2);
_colour.clear();
map<ShowerProgenitorPtr,ShowerParticlePtr>::const_iterator cit;
// construct the map of colour lines for hard process
for(cit=_incomingLines.begin();cit!=_incomingLines.end();++cit) {
if(!cit->first->perturbative()) continue;
mapColour(cit->first->original(),cit->first->copy());
}
map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator cjt;
for(cjt=_outgoingLines.begin();cjt!=_outgoingLines.end();++cjt) {
if(!cjt->first->perturbative()) continue;
mapColour(cjt->first->original(),cjt->first->copy());
}
// initial-state radiation
if(ISR) {
for(cit=incomingLines().begin();cit!=incomingLines().end();++cit) {
ShowerParticlePtr init=(*cit).first->progenitor();
assert(init->thePEGBase());
PPtr original = (*cit).first->original();
if(original->parents().empty()) continue;
PPtr hadron= original->parents()[0];
assert(!original->children().empty());
PPtr copy=cit->first->copy();
ParticleVector intermediates=original->children();
for(unsigned int ix=0;ix<intermediates.size();++ix) {
init->abandonChild(intermediates[ix]);
copy->abandonChild(intermediates[ix]);
}
// if not from a matrix element correction
if(cit->first->perturbative()) {
// break mother/daugther relations
init->addChild(original);
hadron->abandonChild(original);
// if particle showers add shower
if(cit->first->hasEmitted()) {
addInitialStateShower(init,hadron,pstep,false);
}
// no showering for this particle
else {
updateColour(init);
hadron->addChild(init);
pstep->addIntermediate(init);
init->setLifeLength(Lorentz5Distance());
init->setVertex(LorentzPoint());
}
}
// from matrix element correction
else {
// break mother/daugther relations
hadron->abandonChild(original);
copy->addChild(original);
updateColour(copy);
init->addChild(copy);
pstep->addIntermediate(copy);
copy->setLifeLength(Lorentz5Distance());
copy->setVertex(LorentzPoint());
// if particle showers add shower
if(cit->first->hasEmitted()) {
addInitialStateShower(init,hadron,pstep,false);
}
// no showering for this particle
else {
updateColour(init);
hadron->addChild(init);
pstep->addIntermediate(init);
init->setLifeLength(Lorentz5Distance());
init->setVertex(LorentzPoint());
}
}
}
}
else {
for(cit=incomingLines().begin();cit!=incomingLines().end();++cit) {
ShowerParticlePtr init=(*cit).first->progenitor();
assert(init->thePEGBase());
PPtr original = (*cit).first->original();
if(original->parents().empty()) continue;
PPtr hadron= original->parents()[0];
assert(!original->children().empty());
PPtr copy=cit->first->copy();
ParticleVector intermediates=original->children();
for(unsigned int ix=0;ix<intermediates.size();++ix) {
init->abandonChild(intermediates[ix]);
copy->abandonChild(intermediates[ix]);
}
// break mother/daugther relations
init->addChild(original);
hadron->abandonChild(original);
// no showering for this particle
updateColour(init);
hadron->addChild(init);
pstep->addIntermediate(init);
init->setLifeLength(Lorentz5Distance());
init->setVertex(LorentzPoint());
original->setLifeLength(Lorentz5Distance());
original->setVertex(LorentzPoint());
}
}
// final-state radiation
for(cjt=outgoingLines().begin();cjt!=outgoingLines().end();++cjt) {
ShowerParticlePtr init=(*cjt).first->progenitor();
assert(init->thePEGBase());
// ZERO the distance of original
(*cjt).first->original()->setLifeLength(Lorentz5Distance());
(*cjt).first->original()->setVertex(LorentzPoint());
// if not from a matrix element correction
if(cjt->first->perturbative()) {
// register the shower particle as a
// copy of the one from the hard process
tParticleVector parents=init->parents();
for(unsigned int ix=0;ix<parents.size();++ix)
parents[ix]->abandonChild(init);
(*cjt).first->original()->addChild(init);
pstep->addDecayProduct(init);
}
// from a matrix element correction
else {
if(cjt->first->original()==_incoming.first||
cjt->first->original()==_incoming.second) {
updateColour((*cjt).first->copy());
(*cjt).first->original()->parents()[0]->
addChild((*cjt).first->copy());
pstep->addDecayProduct((*cjt).first->copy());
(*cjt).first->copy()->addChild(init);
pstep->addDecayProduct(init);
}
else {
updateColour((*cjt).first->copy());
(*cjt).first->original()->addChild((*cjt).first->copy());
pstep->addDecayProduct((*cjt).first->copy());
(*cjt).first->copy()->addChild(init);
pstep->addDecayProduct(init);
}
// ZERO the distance of copy ??? \todo change if add space-time
(*cjt).first->copy()->setLifeLength(Lorentz5Distance());
(*cjt).first->copy()->setVertex(LorentzPoint());
}
// copy so travels no distance
init->setLifeLength(Lorentz5Distance());
init->setVertex(init->parents()[0]->decayVertex());
// sort out the colour
updateColour(init);
// insert shower products
addFinalStateShower(init,pstep);
}
_colour.clear();
}
void ShowerTree::addFinalStateShower(PPtr p, StepPtr s) {
// if endpoint assume doesn't travel
if(p->children().empty()) {
- p->setLifeLength(Lorentz5Distance());
+ if(p->dataPtr()->stable()||decaysInShower(p->id()))
+ p->setLifeLength(Lorentz5Distance());
+ else {
+ Length ctau = p->dataPtr()->generateLifeTime(p->mass(), p->dataPtr()->width());
+ Lorentz5Distance lifeLength(ctau,p->momentum().vect()*(ctau/p->mass()));
+ p->setLifeLength(lifeLength);
+ }
return;
}
// set the space-time distance
else {
p->setLifeLength(spaceTimeDistance(p));
}
ParticleVector::const_iterator child;
for(child=p->children().begin(); child != p->children().end(); ++child) {
updateColour(*child);
s->addDecayProduct(*child);
(**child).setVertex(p->decayVertex());
addFinalStateShower(*child,s);
}
}
void ShowerTree::updateColour(PPtr particle) {
// if attached to a colour line
if(particle->colourLine()) {
// one and only one
if(particle->colourInfo()->colourLines().size()==1) {
bool reset=false;
// if colour line from hard process reconnect
ColinePtr c1=particle->colourLine();
if(_colour.find(c1)!=_colour.end()) {
c1->removeColoured(particle);
_colour[c1]->addColoured(particle);
reset=true;
}
// ensure properly connected to the line
if(!reset) {
ColinePtr c1=particle->colourLine();
c1->removeColoured(particle);
c1->addColoured(particle);
}
}
else {
Ptr<MultiColour>::pointer colour =
dynamic_ptr_cast<Ptr<MultiColour>::pointer>(particle->colourInfo());
vector<tcColinePtr> lines = colour->colourLines();
for(unsigned int ix=0;ix<lines.size();++ix) {
ColinePtr c1 = const_ptr_cast<ColinePtr>(lines[ix]);
if(_colour.find(c1)!=_colour.end()) {
colour->colourLine(_colour[c1],int(ix)+1);
c1->removeColoured(particle);
}
}
}
}
// if attached to an anticolour line
if(particle->antiColourLine()) {
bool reset=false;
// one and only one
if(particle->colourInfo()->antiColourLines().size()==1) {
// if anti colour line from hard process reconnect
ColinePtr c1=particle->antiColourLine();
if(_colour.find(c1)!=_colour.end()) {
c1->removeColoured(particle,true);
_colour[c1]->addColoured(particle,true);
reset=true;
}
if(!reset) {
ColinePtr c1=particle->antiColourLine();
c1->removeColoured(particle,true);
c1->addColoured(particle,true);
}
}
else {
Ptr<MultiColour>::pointer colour =
dynamic_ptr_cast<Ptr<MultiColour>::pointer>(particle->colourInfo());
vector<tcColinePtr> lines = colour->antiColourLines();
for(unsigned int ix=0;ix<lines.size();++ix) {
ColinePtr c1 = const_ptr_cast<ColinePtr>(lines[ix]);
if(_colour.find(c1)!=_colour.end()) {
colour->antiColourLine(_colour[c1],int(ix)+1);
c1->removeColoured(particle,true);
}
}
}
}
}
void ShowerTree::addInitialStateShower(PPtr p, PPtr hadron,
StepPtr s, bool addchildren) {
// Each parton here should only have one parent
if(!p->parents().empty()) {
if(p->parents().size()!=1)
throw Exception() << "Particle must only have one parent in ShowerTree"
<< "::addInitialStateShower" << Exception::runerror;
// set the space-time distances
if(addchildren) {
p->setLifeLength(spaceTimeDistance(p));
p->setVertex(p->children()[0]->vertex()-p->lifeLength());
}
else {
p->setLifeLength(spaceTimeDistance(p));
p->setVertex(-p->lifeLength());
}
// recurse
addInitialStateShower(p->parents()[0],hadron,s);
}
else {
hadron->addChild(p);
s->addIntermediate(p);
p->setVertex(p->children()[0]->vertex());
p->setLifeLength(Lorentz5Distance());
}
updateColour(p);
// if not adding children return
if(!addchildren) return;
// add children
ParticleVector::const_iterator child;
for(child = p->children().begin(); child != p->children().end(); ++child) {
// if a final-state particle update the colour
ShowerParticlePtr schild =
dynamic_ptr_cast<ShowerParticlePtr>(*child);
(**child).setVertex(p->decayVertex());
if(schild && schild->isFinalState()) updateColour(*child);
// if there are grandchildren of p
if(!(*child)->children().empty()) {
// Add child as intermediate
s->addIntermediate(*child);
// If child is shower particle and final-state, add children
if(schild && schild->isFinalState()) addFinalStateShower(schild,s);
}
else
s->addDecayProduct(*child);
}
}
void ShowerTree::decay(ShowerDecayMap & decay) {
// must be one incoming particle
assert(_incomingLines.size()==1);
// otherwise decay it
applyTransforms();
// if already decayed return
if(!_outgoingLines.empty()) return;
// now we need to replace the particle with a new copy after the shower
// find particle after the shower
ShowerParticlePtr newparent=_parent->_treelinks[this].second;
// now make the new progenitor
vector<PPtr> original,copy;
original.push_back(newparent);
copy.push_back(new_ptr(Particle(*newparent)));
// reisolate the colour
colourIsolate(original,copy);
// make the new progenitor
ShowerParticlePtr stemp=new_ptr(ShowerParticle(*copy[0],2,false));
fixColour(stemp);
ShowerProgenitorPtr newprog=new_ptr(ShowerProgenitor(original[0],copy[0],stemp));
_incomingLines.clear();
_incomingLines.insert(make_pair(newprog,stemp));
// now we need to decay the copy
PPtr parent=copy[0];
if(parent->spinInfo()) parent->spinInfo()->decay(true);
unsigned int ntry = 0;
while (true) {
// exit if fails
if (++ntry>=200)
throw Exception() << "Failed to perform decay in ShowerTree::decay()"
<< " after " << 200
<< " attempts for " << parent->PDGName()
<< Exception::eventerror;
// select decay mode
tDMPtr dm(parent->data().selectMode(*parent));
if(!dm)
throw Exception() << "Failed to select decay mode in ShowerTree::decay()"
<< "for " << newparent->PDGName()
<< Exception::eventerror;
if(!dm->decayer())
throw Exception() << "No Decayer for selected decay mode "
<< " in ShowerTree::decay()"
<< Exception::runerror;
// start of try block
try {
ParticleVector children = dm->decayer()->decay(*dm, *parent);
// if no children have another go
if(children.empty()) continue;
// set up parent
parent->decayMode(dm);
// add children
for (unsigned int i = 0, N = children.size(); i < N; ++i ) {
children[i]->setLabVertex(parent->labDecayVertex());
parent->addChild(children[i]);
parent->scale(ZERO);
}
// if succeeded break out of loop
break;
}
catch(KinematicsReconstructionVeto) {}
}
// insert the trees from the children
ParticleVector children=parent->children();
map<PPtr,ShowerTreePtr> trees;
for(unsigned int ix=0;ix<children.size();++ix) {
PPtr orig=children[ix];
parent->abandonChild(orig);
// if particle has children or decays in shower
if(!orig->children().empty()||
(decaysInShower(orig->id())&&!orig->dataPtr()->stable())) {
ShowerTreePtr newtree=new_ptr(ShowerTree(orig,decay));
trees.insert(make_pair(orig,newtree));
Energy width=orig->dataPtr()->generateWidth(orig->mass());
decay.insert(make_pair(width,newtree));
}
// now create the shower progenitors
PPtr ncopy=new_ptr(Particle(*orig));
//copy[0]->addChild(ncopy);
ShowerParticlePtr nshow=new_ptr(ShowerParticle(*ncopy,2,true));
fixColour(nshow);
ShowerProgenitorPtr prog=new_ptr(ShowerProgenitor(children[ix],
ncopy,nshow));
_outgoingLines.insert(make_pair(prog,nshow));
}
// set up the map of daughter trees
map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator mit;
for(mit=_outgoingLines.begin();mit!=_outgoingLines.end();++mit) {
map<PPtr,ShowerTreePtr>::const_iterator tit=trees.find(mit->first->original());
if(tit!=trees.end()) {
_treelinks.insert(make_pair(tit->second,
make_pair(mit->first,
mit->first->progenitor())));
tit->second->_parent=this;
}
}
}
void ShowerTree::insertDecay(StepPtr pstep,bool ISR, bool) {
assert(_incomingLines.size()==1);
_colour.clear();
// find final particle from previous tree
PPtr final;
if(_parent&&!_parent->_treelinks.empty())
final = _parent->_treelinks[this].second;
else
final=_incomingLines.begin()->first->original();
// construct the map of colour lines
PPtr copy=_incomingLines.begin()->first->copy();
mapColour(final,copy);
// now this is the ONE instance of the particle which should have a life length
// \todo change if space-time picture added
// set the lifelength, need this so that still in right direction after
// any ISR recoils
Length ctau = copy->lifeTime();
Lorentz5Distance lifeLength(ctau,final->momentum().vect()*(ctau/final->mass()));
final->setLifeLength(lifeLength);
// initial-state radiation
if(ISR&&!_incomingLines.begin()->first->progenitor()->children().empty()) {
ShowerParticlePtr init=_incomingLines.begin()->first->progenitor();
updateColour(init);
final->addChild(init);
pstep->addDecayProduct(init);
// just a copy doesn't travel
init->setLifeLength(Lorentz5Distance());
init->setVertex(final->decayVertex());
// insert shower products
addFinalStateShower(init,pstep);
// sort out colour
final=_incomingLines.begin()->second;
_colour.clear();
mapColour(final,copy);
}
// get the decaying particles
// make the copy
tColinePair cline=make_pair(copy->colourLine(),copy->antiColourLine());
updateColour(copy);
// sort out sinks and sources if needed
if(cline.first) {
if(cline.first->sourceNeighbours().first) {
copy->colourLine()->setSourceNeighbours(cline.first->sourceNeighbours().first,
cline.first->sourceNeighbours().second);
}
else if (cline.first->sinkNeighbours().first) {
copy->colourLine()->setSinkNeighbours(cline.first->sinkNeighbours().first,
cline.first->sinkNeighbours().second);
}
}
if(cline.second) {
if(cline.second->sourceNeighbours().first) {
copy->antiColourLine()->setSourceNeighbours(cline.second->sourceNeighbours().first,
cline.second->sourceNeighbours().second);
}
else if (cline.second->sinkNeighbours().first) {
copy->antiColourLine()->setSinkNeighbours(cline.second->sinkNeighbours().first,
cline.second->sinkNeighbours().second);
}
}
// copy of the one from the hard process
tParticleVector dpar=copy->parents();
for(unsigned int ix=0;ix<dpar.size();++ix) dpar[ix]->abandonChild(copy);
final->addChild(copy);
pstep->addDecayProduct(copy);
// just a copy does not move
copy->setLifeLength(Lorentz5Distance());
copy->setVertex(final->decayVertex());
// final-state radiation
map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator cit;
for(cit=outgoingLines().begin();cit!=outgoingLines().end();++cit) {
ShowerParticlePtr init=cit->first->progenitor();
// ZERO the distance
init->setLifeLength(Lorentz5Distance());
if(!init->thePEGBase())
throw Exception() << "Final-state particle must have a ThePEGBase"
<< " in ShowerTree::insertDecay()"
<< Exception::runerror;
// if not from matrix element correction
if(cit->first->perturbative()) {
// add the child
updateColour(cit->first->copy());
PPtr orig=cit->first->original();
orig->setLifeLength(Lorentz5Distance());
orig->setVertex(copy->decayVertex());
copy->addChild(orig);
pstep->addDecayProduct(orig);
orig->addChild(cit->first->copy());
pstep->addDecayProduct(cit->first->copy());
// register the shower particle as a
// copy of the one from the hard process
tParticleVector parents=init->parents();
for(unsigned int ix=0;ix<parents.size();++ix)
{parents[ix]->abandonChild(init);}
(*cit).first->copy()->addChild(init);
pstep->addDecayProduct(init);
updateColour(init);
}
// from a matrix element correction
else {
if(copy->children().end()==
find(copy->children().begin(),copy->children().end(),
cit->first->original())) {
updateColour(cit->first->original());
copy->addChild(cit->first->original());
pstep->addDecayProduct(cit->first->original());
}
updateColour(cit->first->copy());
cit->first->original()->addChild(cit->first->copy());
pstep->addDecayProduct(cit->first->copy());
// register the shower particle as a
// copy of the one from the hard process
tParticleVector parents=init->parents();
for(unsigned int ix=0;ix<parents.size();++ix)
{parents[ix]->abandonChild(init);}
(*cit).first->copy()->addChild(init);
pstep->addDecayProduct(init);
updateColour(init);
}
// ZERO the distances as just copies
cit->first->copy()->setLifeLength(Lorentz5Distance());
init->setLifeLength(Lorentz5Distance());
cit->first->copy()->setVertex(copy->decayVertex());
init->setVertex(copy->decayVertex());
// insert shower products
addFinalStateShower(init,pstep);
}
_colour.clear();
}
void ShowerTree::clear() {
// reset the has showered flag
_hasShowered=false;
// clear the colour map
_colour.clear();
map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator cit;
map<ShowerProgenitorPtr, ShowerParticlePtr>::const_iterator cjt;
// abandon the children of the outgoing particles
for(cit=_outgoingLines.begin();cit!=_outgoingLines.end();++cit) {
ShowerParticlePtr orig=cit->first->progenitor();
orig->set5Momentum(cit->first->copy()->momentum());
ParticleVector children=orig->children();
for(unsigned int ix=0;ix<children.size();++ix) orig->abandonChild(children[ix]);
_outgoingLines[cit->first]=orig;
cit->first->hasEmitted(false);
cit->first->reconstructed(ShowerProgenitor::notReconstructed);
}
// forward products
_forward.clear();
for(cit=_outgoingLines.begin();cit!=_outgoingLines.end();++cit)
_forward.insert(cit->first->progenitor());
// if a decay
if(!_wasHard) {
ShowerParticlePtr orig=_incomingLines.begin()->first->progenitor();
orig->set5Momentum(_incomingLines.begin()->first->copy()->momentum());
ParticleVector children=orig->children();
for(unsigned int ix=0;ix<children.size();++ix) orig->abandonChild(children[ix]);
_incomingLines.begin()->first->reconstructed(ShowerProgenitor::notReconstructed);
}
// if a hard process
else {
for(cjt=_incomingLines.begin();cjt!=_incomingLines.end();++cjt) {
tPPtr parent = cjt->first->original()->parents().empty() ?
tPPtr() : cjt->first->original()->parents()[0];
ShowerParticlePtr temp=
new_ptr(ShowerParticle(*cjt->first->copy(),
cjt->first->progenitor()->perturbative(),
cjt->first->progenitor()->isFinalState()));
fixColour(temp);
temp->x(cjt->first->progenitor()->x());
cjt->first->hasEmitted(false);
if(!(cjt->first->progenitor()==cjt->second)&&cjt->second&&parent)
parent->abandonChild(cjt->second);
cjt->first->progenitor(temp);
_incomingLines[cjt->first]=temp;
cjt->first->reconstructed(ShowerProgenitor::notReconstructed);
}
}
// reset the particles at the end of the shower
_backward.clear();
// if hard process backward products
if(_wasHard)
for(cjt=_incomingLines.begin();cjt!=_incomingLines.end();++cjt)
_backward.insert(cjt->first->progenitor());
clearTransforms();
}
void ShowerTree::resetShowerProducts() {
map<ShowerProgenitorPtr, ShowerParticlePtr>::const_iterator cit;
map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator cjt;
_backward.clear();
_forward.clear();
for(cit=_incomingLines.begin();cit!=_incomingLines.end();++cit)
_backward.insert(cit->second);
for(cjt=_outgoingLines.begin();cjt!=_outgoingLines.end();++cjt)
_forward.insert(cjt->second);
}
void ShowerTree::updateAfterShower(ShowerDecayMap & decay) {
// update the links
map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator mit;
map<tShowerTreePtr,pair<tShowerProgenitorPtr,tShowerParticlePtr> >::iterator tit;
for(tit=_treelinks.begin();tit!=_treelinks.end();++tit) {
if(tit->second.first) {
mit=_outgoingLines.find(tit->second.first);
if(mit!=_outgoingLines.end()) tit->second.second=mit->second;
}
}
// get the particles coming from those in the hard process
set<tShowerParticlePtr> hard;
for(mit=_outgoingLines.begin();mit!=_outgoingLines.end();++mit)
hard.insert(mit->second);
// find the shower particles which should be decayed in the
// shower but didn't come from the hard process
set<tShowerParticlePtr>::const_iterator cit;
for(cit=_forward.begin();cit!=_forward.end();++cit) {
if((decaysInShower((**cit).id())&&!(**cit).dataPtr()->stable())&&
hard.find(*cit)==hard.end()) {
ShowerTreePtr newtree=new_ptr(ShowerTree(*cit,decay));
newtree->setParents();
newtree->_parent=this;
Energy width=(**cit).dataPtr()->generateWidth((**cit).mass());
decay.insert(make_pair(width,newtree));
_treelinks.insert(make_pair(newtree,
make_pair(tShowerProgenitorPtr(),*cit)));
}
}
}
void ShowerTree::addFinalStateBranching(ShowerParticlePtr parent,
const ShowerParticleVector & children) {
assert(children.size()==2);
_forward.erase(parent);
for(unsigned int ix=0; ix<children.size(); ++ix) {
_forward.insert(children[ix]);
}
}
void ShowerTree::addInitialStateBranching(ShowerParticlePtr oldParent,
ShowerParticlePtr newParent,
ShowerParticlePtr otherChild) {
_backward.erase(oldParent);
_backward.insert(newParent);
_forward.insert(otherChild);
}
void ShowerTree::setParents() {
// set the parent tree of the children
map<tShowerTreePtr,pair<tShowerProgenitorPtr,tShowerParticlePtr> >::const_iterator tit;
for(tit=_treelinks.begin();tit!=_treelinks.end();++tit)
tit->first->_parent=this;
}
vector<ShowerProgenitorPtr> ShowerTree::extractProgenitors() {
// extract the particles from the ShowerTree
map<ShowerProgenitorPtr,ShowerParticlePtr>::const_iterator mit;
vector<ShowerProgenitorPtr> ShowerHardJets;
for(mit=incomingLines().begin();mit!=incomingLines().end();++mit)
ShowerHardJets.push_back((*mit).first);
map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator mjt;
for(mjt=outgoingLines().begin();mjt!=outgoingLines().end();++mjt)
ShowerHardJets.push_back((*mjt).first);
return ShowerHardJets;
}
void ShowerTree::transform(const LorentzRotation & boost, bool applyNow) {
if(applyNow) {
// now boost all the particles
map<ShowerProgenitorPtr,ShowerParticlePtr>::const_iterator cit;
// incoming
for(cit=_incomingLines.begin();cit!=_incomingLines.end();++cit) {
cit->first->progenitor()->deepTransform(boost);
cit->first->copy()->deepTransform(boost);
}
// outgoing
map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator cjt;
for(cjt=_outgoingLines.begin();cjt!=_outgoingLines.end();++cjt) {
cjt->first->progenitor()->deepTransform(boost);
cjt->first->copy()->deepTransform(boost);
}
}
else {
_transforms.transform(boost);
}
// child trees
for(map<tShowerTreePtr,pair<tShowerProgenitorPtr,tShowerParticlePtr> >::const_iterator
tit=_treelinks.begin();tit!=_treelinks.end();++tit)
tit->first->transform(boost,applyNow);
}
void ShowerTree::applyTransforms() {
// now boost all the particles
map<ShowerProgenitorPtr,ShowerParticlePtr>::const_iterator cit;
// incoming
for(cit=_incomingLines.begin();cit!=_incomingLines.end();++cit) {
cit->first->progenitor()->deepTransform(_transforms);
cit->first->copy()->deepTransform(_transforms);
}
// outgoing
map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator cjt;
for(cjt=_outgoingLines.begin();cjt!=_outgoingLines.end();++cjt) {
cjt->first->progenitor()->deepTransform(_transforms);
cjt->first->copy()->deepTransform(_transforms);
}
// child trees
for(map<tShowerTreePtr,pair<tShowerProgenitorPtr,tShowerParticlePtr> >::const_iterator
tit=_treelinks.begin();tit!=_treelinks.end();++tit)
tit->first->applyTransforms();
_transforms = LorentzRotation();
}
void ShowerTree::clearTransforms() {
_transforms = LorentzRotation();
// // child trees
// for(map<tShowerTreePtr,pair<tShowerProgenitorPtr,tShowerParticlePtr> >::const_iterator
// tit=_treelinks.begin();tit!=_treelinks.end();++tit)
// tit->first->clearTransforms();
}
void ShowerTree::fixColour(tShowerParticlePtr part) {
if(!part->colourInfo()->colourLines().empty()) {
if(part->colourInfo()->colourLines().size()==1) {
ColinePtr line=part->colourLine();
if(line) {
line->removeColoured(part);
line->addColoured(part);
}
}
else {
Ptr<MultiColour>::pointer colour =
dynamic_ptr_cast<Ptr<MultiColour>::pointer>(part->colourInfo());
vector<tcColinePtr> lines = colour->colourLines();
for(unsigned int ix=0;ix<lines.size();++ix) {
ColinePtr line = const_ptr_cast<ColinePtr>(lines[ix]);
if(line) {
line->removeColoured(part);
line->addColoured(part);
}
}
}
}
if(!part->colourInfo()->antiColourLines().empty()) {
if(part->colourInfo()->antiColourLines().size()==1) {
ColinePtr line=part->antiColourLine();
if(line) {
line->removeAntiColoured(part);
line->addAntiColoured(part);
}
}
else {
Ptr<MultiColour>::pointer colour =
dynamic_ptr_cast<Ptr<MultiColour>::pointer>(part->colourInfo());
vector<tcColinePtr> lines = colour->antiColourLines();
for(unsigned int ix=0;ix<lines.size();++ix) {
ColinePtr line = const_ptr_cast<ColinePtr>(lines[ix]);
if(line) {
line->removeAntiColoured(part);
line->addAntiColoured(part);
}
}
}
}
}
vector<ShowerParticlePtr> ShowerTree::extractProgenitorParticles() {
vector<ShowerParticlePtr> particles;
// incoming particles
for(map<ShowerProgenitorPtr, ShowerParticlePtr>::const_iterator
cit=incomingLines().begin(); cit!=incomingLines().end();++cit)
particles.push_back(cit->first->progenitor());
// outgoing particles
for(map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator
cjt=outgoingLines().begin(); cjt!=outgoingLines().end();++cjt)
particles.push_back(cjt->first->progenitor());
return particles;
}
Lorentz5Distance ShowerTree::spaceTimeDistance(tPPtr particle) {
if(!_spaceTime) return Lorentz5Distance();
Energy2 q2 = particle->mass() > ZERO ? sqr(particle->mass()) : -sqr(particle->mass());
const tcPDPtr data = particle->dataPtr();
// calculate width imposing min value
Energy conMass = max(data->constituentMass(),200*MeV);
Energy width = max(data->generateWidth(particle->mass()),_vmin2/conMass);
// offshellness
Energy2 offShell = q2-sqr(data->constituentMass());
if(abs(offShell)<1e-10*GeV2) offShell = ZERO;
InvEnergy2 fact = UseRandom::rndExp(1./sqrt((sqr(offShell)+sqr(q2*width/conMass))));
Lorentz5Distance output = (hbarc*fact)*particle->momentum();
return output;
}
namespace {
bool decayProduct(tSubProPtr subProcess,
tPPtr particle) {
// must be time-like and not incoming
if(particle->momentum().m2()<=ZERO||
particle == subProcess->incoming().first||
particle == subProcess->incoming().second) return false;
// if only 1 outgoing and this is it
if(subProcess->outgoing().size()==1 &&
subProcess->outgoing()[0]==particle) return true;
// must not be the s-channel intermediate otherwise
if(find(subProcess->incoming().first->children().begin(),
subProcess->incoming().first->children().end(),particle)!=
subProcess->incoming().first->children().end()&&
find(subProcess->incoming().second->children().begin(),
subProcess->incoming().second->children().end(),particle)!=
subProcess->incoming().second->children().end()&&
subProcess->incoming().first ->children().size()==1&&
subProcess->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;
}
PPtr findParent(PPtr original, bool & isHard,
set<PPtr> outgoingset,
tSubProPtr subProcess) {
PPtr parent=original;
isHard |=(outgoingset.find(original) != outgoingset.end());
if(!original->parents().empty()) {
PPtr orig=original->parents()[0];
if(CurrentGenerator::current().currentEventHandler()->currentStep()->
find(orig)&&decayProduct(subProcess,orig)) {
parent=findParent(orig,isHard,outgoingset,subProcess);
}
}
return parent;
}
}
void ShowerTree::constructTrees(tSubProPtr subProcess, ShowerTreePtr & hard,
ShowerDecayMap & decay, tPVector tagged,
bool splitTrees) {
// temporary storage of the particles
set<PPtr> hardParticles;
// loop over the tagged particles
bool isHard=false;
set<PPtr> outgoingset(tagged.begin(),tagged.end());
for (tParticleVector::const_iterator taggedP = tagged.begin();
taggedP != tagged.end(); ++taggedP) {
// if a remnant don't consider
if(CurrentGenerator::current().currentEventHandler()->currentCollision()->isRemnant(*taggedP))
continue;
// find the parent and whether its a colourless s-channel resonance
bool isDecayProd=false;
// check if hard
isHard |=(outgoingset.find(*taggedP) != outgoingset.end());
if(splitTrees) {
tPPtr parent = *taggedP;
// check if from s channel decaying colourless particle
while(parent&&!parent->parents().empty()&&!isDecayProd) {
parent = parent->parents()[0];
if(parent == subProcess->incoming().first ||
parent == subProcess->incoming().second ) break;
isDecayProd = decayProduct(subProcess,parent);
}
if (isDecayProd)
hardParticles.insert(findParent(parent,isHard,outgoingset,subProcess));
}
if (!isDecayProd)
hardParticles.insert(*taggedP);
}
// there must be something to shower
if(hardParticles.empty())
throw Exception() << "No particles to shower in "
<< "ShowerTree::constructTrees()"
<< Exception::eventerror;
if(!isHard)
throw Exception() << "Starting on decay not yet implemented in "
<< "ShowerTree::constructTrees()"
<< Exception::runerror;
// create the hard process ShowerTree
ParticleVector out(hardParticles.begin(),hardParticles.end());
hard=new_ptr(ShowerTree(subProcess->incoming(),out, decay));
hard->setParents();
}
namespace {
Lorentz5Momentum sumMomenta(tPPtr particle) {
if(particle->children().empty())
return particle->momentum();
Lorentz5Momentum output;
for(unsigned int ix=0;ix<particle->children().size();++ix) {
output += sumMomenta(particle->children()[ix]);
}
return output;
}
}
void ShowerTree::checkMomenta() {
vector<Lorentz5Momentum> pin;
for(map<ShowerProgenitorPtr,ShowerParticlePtr>::const_iterator it=_incomingLines.begin();
it!=_incomingLines.end();++it) {
if(isDecay()) {
tPPtr parent = it->first->progenitor();
pin.push_back(parent->momentum());
while(!parent->children().empty()) {
pin.back() -= sumMomenta(parent->children()[1]);
parent = parent->children()[0];
}
}
else {
tPPtr parent = it->second;
pin.push_back(parent->momentum());
while(!parent->children().empty()&&parent->children().size()==2) {
pin.back() -= sumMomenta(parent->children()[1]);
parent = parent->children()[0];
if(parent==it->first->progenitor()) break;
}
}
}
vector<Lorentz5Momentum> pout;
for(map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator it= _outgoingLines.begin();
it!=_outgoingLines.end();++it) {
pout.push_back(sumMomenta(it->first->progenitor()));
}
Lorentz5Momentum psum;
for(unsigned int ix=0;ix< pin.size();++ix) {
CurrentGenerator::log() << "pin " << ix << pin[ix]/GeV << "\n";
psum +=pin[ix];
}
CurrentGenerator::log() << "In total " << psum/GeV << " " << psum.m()/GeV << "\n";
Lorentz5Momentum psum2;
for(unsigned int ix=0;ix< pout.size();++ix) {
CurrentGenerator::log() << "pout " << ix << pout[ix]/GeV << "\n";
psum2 +=pout[ix];
}
CurrentGenerator::log() << "Out total " << psum2/GeV << " " << psum2.m()/GeV << "\n";
CurrentGenerator::log() << "Total " << (psum-psum2)/GeV << "\n";
}
diff --git a/Shower/Couplings/ShowerAlphaQCD.cc b/Shower/Couplings/ShowerAlphaQCD.cc
--- a/Shower/Couplings/ShowerAlphaQCD.cc
+++ b/Shower/Couplings/ShowerAlphaQCD.cc
@@ -1,372 +1,434 @@
// -*- 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/ParticleData.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Parameter.h"
+#include "ThePEG/Interface/ParVector.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"
#include "ThePEG/Config/Constants.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);
+ << ounit(_thresholds,GeV) << ounit(_lambda,GeV)
+ << ounit(_optInputScale,GeV) << ounit(_quarkMasses,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);
+ >> iunit(_thresholds,GeV) >> iunit(_lambda,GeV)
+ >> iunit(_optInputScale,GeV) >> iunit(_quarkMasses,GeV);
}
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);
+ static Command<ShowerAlphaQCD> interfacecheck
+ ("check",
+ "check",
+ &ShowerAlphaQCD::check, false);
+
+ static Parameter<ShowerAlphaQCD,Energy> interfaceInputScale
+ ("InputScale",
+ "An optional input scale. MZ will be used if not set.",
+ &ShowerAlphaQCD::_optInputScale, GeV, ZERO, ZERO, 0*GeV,
+ false, false, Interface::lowerlim);
+
+ static ParVector<ShowerAlphaQCD,Energy> interfaceQuarkMasses
+ ("QuarkMasses",
+ "The quark masses to be used instead of the masses set in the particle data.",
+ &ShowerAlphaQCD::_quarkMasses, GeV, -1, 0.0*GeV, 0.0*GeV, 0*GeV,
+ false, false, Interface::lowerlim);
+
}
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);
+ _lambda[2]=computeLambda(_optInputScale == ZERO ?
+ getParticleData(ParticleID::Z0)->mass() :
+ _optInputScale,
+ _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();
+ if ( _quarkMasses.empty() ) {
+ if(_thresopt)
+ _thresholds[ix]=getParticleData(ix+3)->mass();
+ else
+ _thresholds[ix]=getParticleData(ix+3)->constituentMass();
+ } else {
+ // starting at zero rather than one, cf the other alphas's
+ _thresholds[ix] = _quarkMasses[ix+2];
+ }
}
// 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;
}
+string ShowerAlphaQCD::check(string args) {
+
+ doinit();
+
+ istringstream argin(args);
+
+ double Q_low, Q_high;
+ long n_steps;
+
+ argin >> Q_low >> Q_high >> n_steps;
+
+ string fname;
+ argin >> fname;
+
+ cout << "checking alpha_s in range [" << Q_low << "," << Q_high << "] GeV in "
+ << n_steps << " steps.\nResults are written to " << fname << "\n";
+
+ double step_width = (Q_high-Q_low)/n_steps;
+
+ ofstream out (fname.c_str());
+
+ for (long k = 0; k <= n_steps; ++k) {
+
+ Energy Q = Q_low*GeV + k*step_width*GeV;
+
+ out << (Q/GeV) << " " << value(Q*Q) << "\n";
+
+ }
+
+ return "alpha_s check finished";
+
+}
+
+
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);
Energy newLambda = match/exp(0.5*xtest);
lamtest = newLambda<match ? newLambda : 0.5*(lamtest+match);
}
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,278 +1,304 @@
// -*- 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"
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.) {}
+ _maxtry(100),_alphamin(0.), _optInputScale(ZERO) {}
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);
+ /**
+ * Match thresholds and write alpha_s
+ * specified file; arguments are
+ * Q_low/GeV Q_high/GeV n_steps filename
+ */
+ string check(string args);
+
//@}
/**
* 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];
}
+ /**
+ * Return the quark masses to be used; if not empty these masses
+ * should be considered instead of the ones set in the particle data
+ * objects.
+ */
+ const vector<Energy>& quarkMasses() const { return _quarkMasses; }
+
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 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;
+ /**
+ * An optional input scale to be used for the input alphas; if zero MZ will
+ * be used out of the particle data object.
+ */
+ Energy _optInputScale;
+
+ /**
+ * The quark masses to be used; if not empty these masses should be
+ * considered instead of the ones set in the particle data objects.
+ */
+ vector<Energy> _quarkMasses;
+
};
}
#endif /* HERWIG_ShowerAlphaQCD_H */
diff --git a/Shower/ShowerHandler.cc b/Shower/ShowerHandler.cc
--- a/Shower/ShowerHandler.cc
+++ b/Shower/ShowerHandler.cc
@@ -1,813 +1,817 @@
// -*- 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
if ( particlesDecayInShower_.empty() )
particlesDecayInShower_.insert(inputparticlesDecayInShower_.begin(),
inputparticlesDecayInShower_.end());
ShowerTree::_decayInShower = particlesDecayInShower_;
ShowerTree::_vmin2 = vMin_;
ShowerTree::_spaceTime = includeSpaceTime_;
}
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),
includeSpaceTime_(false), vMin_(0.1*GeV2), subProcess_(),
factorizationScaleFactor_(1.0),
renormalizationScaleFactor_(1.0),
hardScaleFactor_(1.0), scaleFactorOption_(0),
restrictPhasespace_(true), maxPtIsMuF_(false),
splitHardProcess_(true) {
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());
}
ShowerTree::_decayInShower = particlesDecayInShower_;
ShowerTree::_vmin2 = vMin_;
ShowerTree::_spaceTime = includeSpaceTime_;
}
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_
<< PDFARemnant_ << PDFBRemnant_
<< includeSpaceTime_ << ounit(vMin_,GeV2)
<< factorizationScaleFactor_ << renormalizationScaleFactor_
<< hardScaleFactor_ << scaleFactorOption_
<< restrictPhasespace_ << maxPtIsMuF_ << hardScaleProfile_
<< splitHardProcess_;
}
void ShowerHandler::persistentInput(PersistentIStream & is, int) {
is >> evolver_ >> remDec_ >> iunit(pdfFreezingScale_,GeV) >> maxtry_
>> maxtryMPI_ >> maxtryDP_ >> inputparticlesDecayInShower_
>> particlesDecayInShower_ >> MPIHandler_ >> PDFA_ >> PDFB_
>> PDFARemnant_ >> PDFBRemnant_
>> includeSpaceTime_ >> iunit(vMin_,GeV2)
>> factorizationScaleFactor_ >> renormalizationScaleFactor_
>> hardScaleFactor_ >> scaleFactorOption_
>> restrictPhasespace_ >> maxPtIsMuF_ >> hardScaleProfile_
>> splitHardProcess_;
}
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."
"By default used for both the shower and forced splitting in the remnant",
&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."
"By default used for both the shower and forced splitting in the remnant",
&ShowerHandler::PDFB_, false, false, true, true, false);
static Reference<ShowerHandler,PDFBase> interfacePDFARemnant
("PDFARemnant",
"The PDF for beam particle A used to generate forced splittings of the remnant."
" This overrides both the particle's own PDF setting and the value set by PDFA if used.",
&ShowerHandler::PDFARemnant_, false, false, true, true, false);
static Reference<ShowerHandler,PDFBase> interfacePDFBRemnant
("PDFBRemnant",
"The PDF for beam particle B used to generate forced splittings of the remnant."
" This overrides both the particle's own PDF setting and the value set by PDFB if used.",
&ShowerHandler::PDFBRemnant_, false, false, true, true, false);
static Switch<ShowerHandler,bool> interfaceIncludeSpaceTime
("IncludeSpaceTime",
"Whether to include the model for the calculation of space-time distances",
&ShowerHandler::includeSpaceTime_, false, false, false);
static SwitchOption interfaceIncludeSpaceTimeYes
(interfaceIncludeSpaceTime,
"Yes",
"Include the model",
true);
static SwitchOption interfaceIncludeSpaceTimeNo
(interfaceIncludeSpaceTime,
"No",
"Only include the displacement from the particle-s lifetime for decaying particles",
false);
static Parameter<ShowerHandler,Energy2> interfaceMinimumVirtuality
("MinimumVirtuality",
"The minimum virtuality for the space-time model",
&ShowerHandler::vMin_, GeV2, 0.1*GeV2, 0.0*GeV2, 1000.0*GeV2,
false, false, Interface::limited);
static Parameter<ShowerHandler,double> interfaceFactorizationScaleFactor
("FactorizationScaleFactor",
"The factorization scale factor.",
&ShowerHandler::factorizationScaleFactor_, 1.0, 0.0, 0,
false, false, Interface::lowerlim);
static Parameter<ShowerHandler,double> interfaceRenormalizationScaleFactor
("RenormalizationScaleFactor",
"The renormalization scale factor.",
&ShowerHandler::renormalizationScaleFactor_, 1.0, 0.0, 0,
false, false, Interface::lowerlim);
static Parameter<ShowerHandler,double> interfaceHardScaleFactor
("HardScaleFactor",
"The hard scale factor.",
&ShowerHandler::hardScaleFactor_, 1.0, 0.0, 0,
false, false, Interface::lowerlim);
static Switch<ShowerHandler,int> interfaceScaleFactorOption
("ScaleFactorOption",
"Where to apply scale factors.",
&ShowerHandler::scaleFactorOption_, 0, false, false);
static SwitchOption interfaceScaleFactorOptionAll
(interfaceScaleFactorOption,
"All",
"Apply in first and secondary scatterings.",
0);
static SwitchOption interfaceScaleFactorOptionHard
(interfaceScaleFactorOption,
"Hard",
"Only apply for the hard process.",
1);
static SwitchOption interfaceScaleFactorOptionSecondary
(interfaceScaleFactorOption,
"Secondary",
"Only apply to secondary scatterings.",
2);
static Reference<ShowerHandler,HardScaleProfile> interfaceHardScaleProfile
("HardScaleProfile",
"The hard scale profile to use.",
&ShowerHandler::hardScaleProfile_, false, false, true, true, false);
static Switch<ShowerHandler,bool> interfaceMaxPtIsMuF
("MaxPtIsMuF",
"",
&ShowerHandler::maxPtIsMuF_, false, false, false);
static SwitchOption interfaceMaxPtIsMuFYes
(interfaceMaxPtIsMuF,
"Yes",
"",
true);
static SwitchOption interfaceMaxPtIsMuFNo
(interfaceMaxPtIsMuF,
"No",
"",
false);
static Switch<ShowerHandler,bool> interfaceRestrictPhasespace
("RestrictPhasespace",
"Switch on or off phasespace restrictions",
&ShowerHandler::restrictPhasespace_, true, false, false);
static SwitchOption interfaceRestrictPhasespaceOn
(interfaceRestrictPhasespace,
"On",
"Perform phasespace restrictions",
true);
static SwitchOption interfaceRestrictPhasespaceOff
(interfaceRestrictPhasespace,
"Off",
"Do not perform phasespace restrictions",
false);
static Switch<ShowerHandler,bool> interfaceSplitHardProcess
("SplitHardProcess",
"Whether or not to try and split the hard process into production and decay processes",
&ShowerHandler::splitHardProcess_, true, false, false);
static SwitchOption interfaceSplitHardProcessYes
(interfaceSplitHardProcess,
"Yes",
"Split the hard process",
true);
static SwitchOption interfaceSplitHardProcessNo
(interfaceSplitHardProcess,
"No",
"Don't split the hard process",
false);
}
+Energy ShowerHandler::hardScale() const {
+ return evolver_->hardScale();
+}
+
void ShowerHandler::cascade() {
tcPDFPtr first = firstPDF().pdf();
tcPDFPtr second = secondPDF().pdf();
if ( PDFA_ ) first = PDFA_;
if ( PDFB_ ) second = PDFB_;
resetPDFs(make_pair(first,second));
if( ! rempdfs_.first)
rempdfs_.first = PDFARemnant_ ? PDFPtr(PDFARemnant_) : const_ptr_cast<PDFPtr>(first);
if( ! rempdfs_.second)
rempdfs_.second = PDFBRemnant_ ? PDFPtr(PDFBRemnant_) : const_ptr_cast<PDFPtr>(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(rempdfs_.first,rempdfs_.second), 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(remmpipdfs_.first,remmpipdfs_.second), 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(remmpipdfs_.first,remmpipdfs_.second), 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::prepareCascade(tSubProPtr sub) {
current_ = currentStep();
subProcess_ = sub;
}
tPPair ShowerHandler::cascade(tSubProPtr sub,
XCPtr xcomb) {
prepareCascade(sub);
// set the scale variation factors; needs to go after prepareCascade
// to trigger possible different variations for hard and secondary
// scatters
evolver()->renormalizationScaleFactor(renormalizationScaleFactor());
evolver()->factorizationScaleFactor(factorizationScaleFactor());
evolver()->restrictPhasespace(restrictPhasespace());
evolver()->hardScaleIsMuF(hardScaleIsMuF());
// start of the try block for the whole showering process
unsigned int countFailures=0;
while (countFailures<maxtry_) {
try {
decay_.clear();
done_.clear();
ShowerTree::constructTrees(currentSubProcess(),hard_,decay_,
firstInteraction() ? tagged() :
tPVector(currentSubProcess()->outgoing().begin(),
currentSubProcess()->outgoing().end()),
splitHardProcess_);
// 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));
}
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
// ATTENTION Broken here for very strange configuration
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);
}
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()));
}
if( !remmpipdfs_.first ) {
tcMinBiasPDFPtr first = dynamic_ptr_cast<tcMinBiasPDFPtr>(rempdfs_.first);
if(first)
remmpipdfs_.first = new_ptr(MPIPDF(first->originalPDF()));
else
remmpipdfs_.first = new_ptr(MPIPDF(rempdfs_.first));
}
if( !remmpipdfs_.second ) {
tcMinBiasPDFPtr second = dynamic_ptr_cast<tcMinBiasPDFPtr>(rempdfs_.second);
if(second)
remmpipdfs_.second = new_ptr(MPIPDF(second->originalPDF()));
else
remmpipdfs_.second = new_ptr(MPIPDF(rempdfs_.second));
}
// 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,576 +1,581 @@
// -*- 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"
#include "Herwig/MatrixElement/Matchbox/Matching/HardScaleProfile.h"
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; };
/**
* Return true, if this cascade handler will perform reshuffling from hard
* process masses.
*/
virtual bool isReshuffling() const { return true; }
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;
/**
* Return true, if the shower handler can generate a truncated
* shower for POWHEG style events generated using Matchbox
*/
virtual bool canHandleMatchboxTrunc() const { return false; }
/**
* The factorization scale factor.
*/
double factorizationScaleFactor() const {
if ( scaleFactorOption_ == 0 || !subProcess_ )
return factorizationScaleFactor_;
if ( scaleFactorOption_ == 1 )
return firstInteraction() ? factorizationScaleFactor_ : 1.0;
if ( scaleFactorOption_ == 2 )
return !firstInteraction() ? factorizationScaleFactor_ : 1.0;
return 1.0;
}
/**
* The renormalization scale factor.
*/
double renormalizationScaleFactor() const {
if ( scaleFactorOption_ == 0 || !subProcess_ )
return renormalizationScaleFactor_;
if ( scaleFactorOption_ == 1 )
return firstInteraction() ? renormalizationScaleFactor_ : 1.0;
if ( scaleFactorOption_ == 2 )
return !firstInteraction() ? renormalizationScaleFactor_ : 1.0;
return 1.0;
}
/**
* The scale factor for the hard scale
*/
double hardScaleFactor() const {
if ( scaleFactorOption_ == 0 || !subProcess_ )
return hardScaleFactor_;
if ( scaleFactorOption_ == 1 )
return firstInteraction() ? hardScaleFactor_ : 1.0;
if ( scaleFactorOption_ == 2 )
return !firstInteraction() ? hardScaleFactor_ : 1.0;
return 1.0;
}
/**
* The option on when to apply the scale factors
*/
int scaleFactorOption() const { return scaleFactorOption_; }
/**
* Return true, if the phase space restrictions of the dipole shower should
* be applied.
*/
bool restrictPhasespace() const { return restrictPhasespace_; }
/**
* Return profile scales
*/
Ptr<HardScaleProfile>::tptr profileScales() const { return hardScaleProfile_; }
/**
+ * Return the relevant hard scale to be used in the profile scales
+ */
+ virtual Energy hardScale() const;
+
+ /**
* Return true if maximum pt should be deduced from the factorization scale
*/
bool hardScaleIsMuF() const { return maxPtIsMuF_; }
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();
/**
* 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();
/**
* 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 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 for beam particle A for remnant splitting. Overrides the particle's own PDF setting.
*/
PDFPtr PDFARemnant_;
/**
* The PDF for beam particle B for remnant splitting. Overrides the particle's own PDF setting.
*/
PDFPtr PDFBRemnant_;
/**
* 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_;
/**
* Whether or not to include spa-cetime distances in the shower
*/
bool includeSpaceTime_;
/**
* The minimum virtuality for the space-time model
*/
Energy2 vMin_;
/**
* 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_;
/**
* The MPI PDF's to be used for secondary scatters.
*/
pair <PDFPtr, PDFPtr> rempdfs_;
/**
* The MPI PDF's to be used for secondary scatters.
*/
pair <PDFPtr, PDFPtr> remmpipdfs_;
/**
* The factorization scale factor.
*/
double factorizationScaleFactor_;
/**
* The renormalization scale factor.
*/
double renormalizationScaleFactor_;
/**
* The scale factor for the hard scale
*/
double hardScaleFactor_;
/**
* The option on when to apply the scale factors
*/
int scaleFactorOption_;
/**
* True, if the phase space restrictions of the dipole shower should
* be applied.
*/
bool restrictPhasespace_;
/**
* True if maximum pt should be deduced from the factorization scale
*/
bool maxPtIsMuF_;
/**
* The profile scales
*/
Ptr<HardScaleProfile>::ptr hardScaleProfile_;
/**
* Whether or not to split into hard and decay trees
*/
bool splitHardProcess_;
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;
}
};
}
#endif /* HERWIG_ShowerHandler_H */
diff --git a/src/Herwig.cc b/src/Herwig.cc
--- a/src/Herwig.cc
+++ b/src/Herwig.cc
@@ -1,288 +1,292 @@
// -*- C++ -*-
//
// Herwig.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.
//
#include "Herwig.h"
#include "HerwigUI.h"
#include <ThePEG/Persistency/PersistentIStream.h>
#include <ThePEG/Repository/EventGenerator.h>
#include <ThePEG/Utilities/DynamicLoader.h>
#include <ThePEG/Utilities/Debug.h>
#include <ThePEG/Repository/Repository.h>
#include <ThePEG/Handlers/SamplerBase.h>
#include <ThePEG/Handlers/StandardEventHandler.h>
#include <iostream>
#include <sstream>
#include <unistd.h>
#include <sys/wait.h>
#include <boost/filesystem.hpp>
#include "Herwig/Utilities/RunDirectories.h"
using namespace ThePEG;
namespace {
/**
* Search paths for Repository read
*
* You can pass two string vectors with directories which Herwig will use to look in for files.
* A vector with directories which will be prepended and a vector with directories which will be appended.
* Both vectors are optional.
*/
void setSearchPaths(const Herwig::HerwigUI & ui,
bool usePWD = true);
void HerwigGenericRead(const Herwig::HerwigUI & ui);
void HerwigGenericRun(const Herwig::HerwigUI & ui);
}
namespace Herwig {
namespace API {
void init(const HerwigUI & ui) {
setSearchPaths(ui, false);
SamplerBase::setRunLevel(SamplerBase::InitMode);
string infile = ui.inputfile();
// If status is INIT, we need an infile name / runname
if (infile.empty())
infile = "HerwigDefaults.in";
breakThePEG();
{
# ifdef HERWIG_PKGLIBDIR
DynamicLoader::appendPath(HERWIG_PKGLIBDIR);
# endif
# ifdef THEPEG_PKGLIBDIR
DynamicLoader::appendPath(THEPEG_PKGLIBDIR);
# endif
HoldFlag<> setup(InterfaceBase::NoReadOnly);
string msg = Repository::read(infile, cout);
if ( ! msg.empty() ) cerr << msg << '\n';
Repository::update();
}
Repository::save(ui.repository());
}
void read(const HerwigUI & ui) {
setSearchPaths(ui);
SamplerBase::setRunLevel(SamplerBase::ReadMode);
HerwigGenericRead(ui);
}
void build(const HerwigUI & ui) {
setSearchPaths(ui);
SamplerBase::setRunLevel(SamplerBase::BuildMode);
HerwigGenericRead(ui);
}
void integrate(const HerwigUI & ui) {
setSearchPaths(ui);
SamplerBase::setRunLevel(SamplerBase::IntegrationMode);
HerwigGenericRun(ui);
}
void run(const HerwigUI & ui) {
setSearchPaths(ui);
SamplerBase::setRunLevel(SamplerBase::RunMode);
HerwigGenericRun(ui);
}
}
}
namespace {
void setSearchPaths(const Herwig::HerwigUI & ui,
bool usePWD) {
// Search path for read command uses CWD first
if ( usePWD ) {
string cwd = boost::filesystem::current_path().string();
Repository::prependReadDir( cwd );
}
// append command line choices for directories from which Herwig will read.
Repository::appendReadDir(ui.appendReadDirectories());
Repository::prependReadDir(ui.prependReadDirectories());
}
//void HerwigGenericRead(string reponame, string runname, const gengetopt_args_info & args_info)
void HerwigGenericRead(const Herwig::HerwigUI & ui) {
string reponame = ui.repository();
#ifdef HERWIG_PKGDATADIR
ifstream test(reponame.c_str());
if ( !test ) {
reponame = string(HERWIG_PKGDATADIR) + '/' + reponame;
}
test.close();
#endif
string msg = Repository::load(reponame);
if ( ! msg.empty() ) cerr << msg << '\n';
// Repeated invocation of setSearchPaths is necessary since Repository::load revokes all setted paths.
setSearchPaths(ui);
breakThePEG();
if ( !ui.inputfile().empty() && ui.inputfile() != "-" ) {
string msg = Repository::read(ui.inputfile(), std::cout);
if ( ! msg.empty() ) cerr << msg << '\n';
}
else {
Repository::exitOnError() = 0;
Repository::read(std::cin, std::cout, "Herwig> ");
}
}
void HerwigGenericRun(const Herwig::HerwigUI & ui) {
// If runMode is integration or run, we need a runname
const string runname = ui.inputfile();
if (runname.empty() ) {
std::cerr << "Error: You need to supply a runfile name.\n";
ui.quitWithHelp();
}
if ( ui.integrationJob() && ui.jobs() > 1 ) {
std::cerr << "parallel event generation is not applicable to integrate\n";
ui.quit();
}
PersistentIStream is(runname);
ThePEG::EGPtr eg;
is >> eg;
// debugging breakpoint
breakThePEG();
if ( !eg ) {
std::cerr << "Herwig: EventGenerator not available.\n"
<< "Check if '" << runname << "' is a valid run file.\n";
ui.quit();
}
Herwig::RunDirectories::pushRunId(eg->runName());
if ( !ui.setupfile().empty() )
Herwig::RunDirectories::pushRunId(ui.setupfile());
if ( !ui.tag().empty() )
Herwig::RunDirectories::pushRunId(ui.tag());
if ( !ui.integrationList().empty() )
Herwig::RunDirectories::pushRunId(ui.integrationList());
if ( ui.seed() > 0 ) {
ostringstream sseed;
sseed << ui.seed();
Herwig::RunDirectories::pushRunId(sseed.str());
}
if ( ui.seed() > 0 ) eg->setSeed(ui.seed());
if ( !ui.setupfile().empty() ) eg->addTag("-" + ui.setupfile());
if ( !ui.tag().empty() ) eg->addTag("-" + ui.tag());
if ( ui.integrationJob() ) {
Ptr<StandardEventHandler>::tptr eh =
dynamic_ptr_cast<Ptr<StandardEventHandler>::tptr>(eg->eventHandler());
if ( !eh ) {
std::cerr << "Herwig: Cannot set integration mode for a non-standard EventHandler.\n";
ui.quit();
}
if ( !ui.integrationList().empty() )
eh->sampler()->integrationList(ui.integrationList());
}
if ( ! ui.setupfile().empty() ) {
SamplerBase::setupFileUsed();
string msg = Repository::modifyEventGenerator(*eg, ui.setupfile(), cout, true);
if ( ! msg.empty() ) cerr << msg << '\n';
if ( ui.integrationJob() )
return;
}
if ( ui.integrationJob() ) {
Repository::resetEventGenerator(*eg);
return;
}
if (ui.jobs() <= 1) {
eg->go( ui.resume() ? -1 : 1, ui.N(), ui.tics() );
if ( ui.tics() ) std::cout << '\n';
}
else { // forked jobs
- pid_t pid;
+ pid_t pid = 0;
const int maxlen = log10(ui.jobs()) + 1;
+ // make sure the parent got initialized once so e.g. grid combination is
+ // working
+ eg->initialize(true);
+
for (int n=0; n<ui.jobs(); n++) {
ostringstream tmp;
tmp << std::setfill('0') << std::setw(maxlen) << n+1;
const string nstr = tmp.str();
pid = fork();
if (pid == -1) { // fork failed
std::perror("Herwig: fork");
ui.quit();
}
else if ( pid == 0 ) { // we're the child
if ( ui.tics() ) std::cout << "Forked child " << n << ", PID " << getpid() << std::endl;
eg->setSeed( ui.seed() + n );
eg->addTag( "-" + nstr );
Herwig::RunDirectories::pushRunId( nstr );
eg->go( ui.resume() ? -1 : 1, ui.N() / ui.jobs(), false );
break; // avoid sub-forks
}
// nothing to do here if we're the parent
}
// children have nothing else to do
if (pid == 0) return;
if ( ui.tics() ) std::cout << "Waiting for forked jobs." << std::endl;
int status;
pid_t child;
bool cleanrun = true;
while (true) {
child = wait(&status);
if (child == -1) {
if (errno == ECHILD) {
if ( ui.tics() ) std::cout << "No more forked jobs." << std::endl;
break;
}
else {
std::perror("Herwig: waitpid");
ui.quit();
}
}
if (WIFEXITED(status)) {
if (WEXITSTATUS(status) != 0)
cleanrun = false;
if ( ui.tics() ) std::cout << "PID " << child
<< " exited, status=" << WEXITSTATUS(status)
<< std::endl;
} else if (WIFSIGNALED(status)) {
// a clean SIGTERM is handled in the child
// and will count as exit above, so...
cleanrun = false;
if ( ui.tics() ) std::cout << "PID " << child
<< " killed by signal " << WTERMSIG(status)
<< std::endl;
}
}
if (! cleanrun) {
ui.quit();
}
}
}
}
diff --git a/src/Matchbox/MCatNLO-Dipole-HardAlphaSTune.in b/src/Matchbox/MCatNLO-Dipole-HardAlphaSTune.in
--- a/src/Matchbox/MCatNLO-Dipole-HardAlphaSTune.in
+++ b/src/Matchbox/MCatNLO-Dipole-HardAlphaSTune.in
@@ -1,115 +1,115 @@
# -*- ThePEG-repository -*-
# tune where the world average perutbative alphaS is used for the hard me
# and matching and the shower alpha_S tuned seperately
##################################################
## special scale choices
##################################################
cd /Herwig/DipoleShower/Kernels
set FFgx2ddxDipoleKernel:VirtualitySplittingScale Yes
set FFgx2uuxDipoleKernel:VirtualitySplittingScale Yes
set FFgx2ccxDipoleKernel:VirtualitySplittingScale Yes
set FFgx2ssxDipoleKernel:VirtualitySplittingScale Yes
set FFgx2bbxDipoleKernel:VirtualitySplittingScale Yes
set FIgx2ddxDipoleKernel:VirtualitySplittingScale Yes
set FIgx2uuxDipoleKernel:VirtualitySplittingScale Yes
set FIgx2ccxDipoleKernel:VirtualitySplittingScale Yes
set FIgx2ssxDipoleKernel:VirtualitySplittingScale Yes
set FIgx2bbxDipoleKernel:VirtualitySplittingScale Yes
set IFgx2ggxDipoleKernel:VirtualitySplittingScale Yes
set IFqx2gqxDipoleKernel:VirtualitySplittingScale Yes
set IIgx2ggxDipoleKernel:VirtualitySplittingScale Yes
set IIqx2gqxDipoleKernel:VirtualitySplittingScale Yes
set FFMgx2ddxDipoleKernel:VirtualitySplittingScale Yes
set FFMgx2uuxDipoleKernel:VirtualitySplittingScale Yes
set FFMgx2ccxDipoleKernel:VirtualitySplittingScale Yes
set FFMgx2ssxDipoleKernel:VirtualitySplittingScale Yes
set FFMgx2bbxDipoleKernel:VirtualitySplittingScale Yes
-set FIMgx2ddxDipoleKernel:VirtualitySplittingScale Yes
-set FIMgx2uuxDipoleKernel:VirtualitySplittingScale Yes
-set FIMgx2ccxDipoleKernel:VirtualitySplittingScale Yes
-set FIMgx2ssxDipoleKernel:VirtualitySplittingScale Yes
-set FIMgx2bbxDipoleKernel:VirtualitySplittingScale Yes
+# set FIMgx2ddxDipoleKernel:VirtualitySplittingScale Yes
+# set FIMgx2uuxDipoleKernel:VirtualitySplittingScale Yes
+# set FIMgx2ccxDipoleKernel:VirtualitySplittingScale Yes
+# set FIMgx2ssxDipoleKernel:VirtualitySplittingScale Yes
+# set FIMgx2bbxDipoleKernel:VirtualitySplittingScale Yes
-set IFMgx2ggxDipoleKernel:VirtualitySplittingScale Yes
-set IFMqx2gqxDipoleKernel:VirtualitySplittingScale Yes
+# set IFMgx2ggxDipoleKernel:VirtualitySplittingScale Yes
+# set IFMqx2gqxDipoleKernel:VirtualitySplittingScale Yes
##################################################
## intrinsic pt
##################################################
set /Herwig/DipoleShower/IntrinsicPtGenerator:ValenceIntrinsicPtScale 2.0*GeV
set /Herwig/DipoleShower/IntrinsicPtGenerator:SeaIntrinsicPtScale 2.0*GeV
##################################################
## Dipole shower tune settings
##################################################
set /Herwig/Particles/g:ConstituentMass 0.7899848*GeV
##################################################
## (two-loop) alpha_s
##################################################
set /Herwig/DipoleShower/NLOAlphaS:input_alpha_s 0.125
set /Herwig/DipoleShower/NLOAlphaS:input_scale 91.18*GeV
##################################################
## cutoffs
##################################################
set /Herwig/DipoleShower/Kinematics/FFLightKinematics:IRCutoff 0.45*GeV
set /Herwig/DipoleShower/Kinematics/FFMassiveKinematics:IRCutoff 0.45*GeV
set /Herwig/DipoleShower/Kinematics/FILightKinematics:IRCutoff 0.45*GeV
set /Herwig/DipoleShower/Kinematics/FIMassiveKinematics:IRCutoff 0.45*GeV
set /Herwig/DipoleShower/Kinematics/IFLightKinematics:IRCutoff 0.45*GeV
set /Herwig/DipoleShower/Kinematics/IFMassiveKinematics:IRCutoff 0.45*GeV
set /Herwig/DipoleShower/Kinematics/IILightKinematics:IRCutoff 0.45*GeV
## needs to be synchronized with settings above
set /Herwig/MatrixElements/Matchbox/DipoleMatching:FFPtCut 0.45*GeV
set /Herwig/MatrixElements/Matchbox/DipoleMatching:FIPtCut 0.45*GeV
set /Herwig/MatrixElements/Matchbox/DipoleMatching:IIPtCut 0.45*GeV
##################################################
## hadronization parameters -- complete?
##################################################
cd /Herwig/Hadronization
set ClusterFissioner:ClMaxLight 3.30
set ClusterFissioner:ClPowLight 2.50
set ClusterFissioner:PSplitLight 1.29
set ClusterDecayer:ClDirLight 1
set ClusterDecayer:ClSmrLight 3.118342
set ClusterFissioner:ClMaxCharm 3.11*GeV
set ClusterFissioner:ClPowCharm 1.62
set ClusterFissioner:PSplitCharm 2.54
set ClusterDecayer:ClDirCharm 1
set ClusterDecayer:ClSmrCharm 0.
set LightClusterDecayer:SingleHadronLimitCharm 0.0
set ClusterFissioner:ClMaxBottom 1.38*GeV
set ClusterFissioner:ClPowBottom 0.62
set ClusterFissioner:PSplitBottom 0.20
set ClusterDecayer:ClDirBottom 1
set ClusterDecayer:ClSmrBottom 0.
set LightClusterDecayer:SingleHadronLimitBottom 0.12
set HadronSelector:PwtUquark 1.0
set HadronSelector:PwtDquark 1.0
set HadronSelector:PwtSquark 1.09
set HadronSelector:PwtCquark 1.0
set HadronSelector:PwtBquark 1.0
set HadronSelector:PwtDIquark 0.66
set HadronSelector:SngWt 1.0
set HadronSelector:DecWt 1.0
cd /
diff --git a/src/Matchbox/MCatNLO-Dipole-ShowerAlphaSTune.in b/src/Matchbox/MCatNLO-Dipole-ShowerAlphaSTune.in
--- a/src/Matchbox/MCatNLO-Dipole-ShowerAlphaSTune.in
+++ b/src/Matchbox/MCatNLO-Dipole-ShowerAlphaSTune.in
@@ -1,117 +1,117 @@
# -*- ThePEG-repository -*-
# tune wherre the alphaS used for the hard me
# and matching and the shower alpha_S are the same
##################################################
## special scale choices
##################################################
cd /Herwig/DipoleShower/Kernels
set FFgx2ddxDipoleKernel:VirtualitySplittingScale Yes
set FFgx2uuxDipoleKernel:VirtualitySplittingScale Yes
set FFgx2ccxDipoleKernel:VirtualitySplittingScale Yes
set FFgx2ssxDipoleKernel:VirtualitySplittingScale Yes
set FFgx2bbxDipoleKernel:VirtualitySplittingScale Yes
set FIgx2ddxDipoleKernel:VirtualitySplittingScale Yes
set FIgx2uuxDipoleKernel:VirtualitySplittingScale Yes
set FIgx2ccxDipoleKernel:VirtualitySplittingScale Yes
set FIgx2ssxDipoleKernel:VirtualitySplittingScale Yes
set FIgx2bbxDipoleKernel:VirtualitySplittingScale Yes
set IFgx2ggxDipoleKernel:VirtualitySplittingScale Yes
set IFqx2gqxDipoleKernel:VirtualitySplittingScale Yes
set IIgx2ggxDipoleKernel:VirtualitySplittingScale Yes
set IIqx2gqxDipoleKernel:VirtualitySplittingScale Yes
set FFMgx2ddxDipoleKernel:VirtualitySplittingScale Yes
set FFMgx2uuxDipoleKernel:VirtualitySplittingScale Yes
set FFMgx2ccxDipoleKernel:VirtualitySplittingScale Yes
set FFMgx2ssxDipoleKernel:VirtualitySplittingScale Yes
set FFMgx2bbxDipoleKernel:VirtualitySplittingScale Yes
-set FIMgx2ddxDipoleKernel:VirtualitySplittingScale Yes
-set FIMgx2uuxDipoleKernel:VirtualitySplittingScale Yes
-set FIMgx2ccxDipoleKernel:VirtualitySplittingScale Yes
-set FIMgx2ssxDipoleKernel:VirtualitySplittingScale Yes
-set FIMgx2bbxDipoleKernel:VirtualitySplittingScale Yes
+# set FIMgx2ddxDipoleKernel:VirtualitySplittingScale Yes
+# set FIMgx2uuxDipoleKernel:VirtualitySplittingScale Yes
+# set FIMgx2ccxDipoleKernel:VirtualitySplittingScale Yes
+# set FIMgx2ssxDipoleKernel:VirtualitySplittingScale Yes
+# set FIMgx2bbxDipoleKernel:VirtualitySplittingScale Yes
-set IFMgx2ggxDipoleKernel:VirtualitySplittingScale Yes
-set IFMqx2gqxDipoleKernel:VirtualitySplittingScale Yes
+# set IFMgx2ggxDipoleKernel:VirtualitySplittingScale Yes
+# set IFMqx2gqxDipoleKernel:VirtualitySplittingScale Yes
##################################################
## intrinsic pt
##################################################
set /Herwig/DipoleShower/IntrinsicPtGenerator:ValenceIntrinsicPtScale 2.0*GeV
set /Herwig/DipoleShower/IntrinsicPtGenerator:SeaIntrinsicPtScale 2.0*GeV
##################################################
## Dipole shower tune settings
##################################################
set /Herwig/Particles/g:ConstituentMass 0.7899848*GeV
##################################################
## (two-loop) alpha_s
##################################################
set /Herwig/DipoleShower/NLOAlphaS:input_alpha_s 0.139
set /Herwig/DipoleShower/NLOAlphaS:input_scale 91.18*GeV
set /Herwig/Couplings/NLOAlphaS:input_alpha_s 0.139
set /Herwig/Couplings/NLOAlphaS:input_scale 91.18*GeV
##################################################
## cutoffs
##################################################
set /Herwig/DipoleShower/Kinematics/FFLightKinematics:IRCutoff 1.12*GeV
set /Herwig/DipoleShower/Kinematics/FFMassiveKinematics:IRCutoff 1.12*GeV
set /Herwig/DipoleShower/Kinematics/FILightKinematics:IRCutoff 1.12*GeV
set /Herwig/DipoleShower/Kinematics/FIMassiveKinematics:IRCutoff 1.12*GeV
set /Herwig/DipoleShower/Kinematics/IFLightKinematics:IRCutoff 1.12*GeV
set /Herwig/DipoleShower/Kinematics/IFMassiveKinematics:IRCutoff 1.12*GeV
set /Herwig/DipoleShower/Kinematics/IILightKinematics:IRCutoff 1.12*GeV
## needs to be synchronized with settings above
set /Herwig/MatrixElements/Matchbox/DipoleMatching:FFPtCut 1.12*GeV
set /Herwig/MatrixElements/Matchbox/DipoleMatching:FIPtCut 1.12*GeV
set /Herwig/MatrixElements/Matchbox/DipoleMatching:IIPtCut 1.12*GeV
##################################################
## hadronization parameters -- complete?
##################################################
cd /Herwig/Hadronization
set ClusterFissioner:ClMaxLight 3.03
set ClusterFissioner:ClPowLight 0.92
set ClusterFissioner:PSplitLight 0.57
set ClusterDecayer:ClDirLight 1
set ClusterDecayer:ClSmrLight 3.118342
set ClusterFissioner:ClMaxCharm 3.58*GeV
set ClusterFissioner:ClPowCharm 2.36
set ClusterFissioner:PSplitCharm 1.08
set ClusterDecayer:ClDirCharm 1
set ClusterDecayer:ClSmrCharm 0.
set LightClusterDecayer:SingleHadronLimitCharm 0.0
set ClusterFissioner:ClMaxBottom 2.03*GeV
set ClusterFissioner:ClPowBottom 0.67
set ClusterFissioner:PSplitBottom 0.01
set ClusterDecayer:ClDirBottom 1
set ClusterDecayer:ClSmrBottom 0.
set LightClusterDecayer:SingleHadronLimitBottom 0.12
set HadronSelector:PwtUquark 1.0
set HadronSelector:PwtDquark 1.0
set HadronSelector:PwtSquark 0.61
set HadronSelector:PwtCquark 1.0
set HadronSelector:PwtBquark 1.0
set HadronSelector:PwtDIquark 0.46
set HadronSelector:SngWt 1.0
set HadronSelector:DecWt 1.0
cd /

File Metadata

Mime Type
text/x-diff
Expires
Tue, Nov 19, 9:13 PM (23 h, 1 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3789852
Default Alt Text
(722 KB)

Event Timeline