Page MenuHomeHEPForge

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/MatrixElement/Matchbox/Base/MatchboxAmplitude.h b/MatrixElement/Matchbox/Base/MatchboxAmplitude.h
--- a/MatrixElement/Matchbox/Base/MatchboxAmplitude.h
+++ b/MatrixElement/Matchbox/Base/MatchboxAmplitude.h
@@ -1,641 +1,647 @@
// -*- C++ -*-
//
// MatchboxAmplitude.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_MatchboxAmplitude_H
#define HERWIG_MatchboxAmplitude_H
//
// This is the declaration of the MatchboxAmplitude class.
//
#include "ThePEG/MatrixElement/Amplitude.h"
#include "ThePEG/Handlers/LastXCombInfo.h"
#include "Herwig++/MatrixElement/Matchbox/Utility/ColourBasis.h"
#include "Herwig++/MatrixElement/Matchbox/Utility/SpinCorrelationTensor.h"
#include "Herwig++/MatrixElement/Matchbox/Utility/LastMatchboxXCombInfo.h"
#include "Herwig++/MatrixElement/Matchbox/Utility/MatchboxXComb.h"
#include "Herwig++/MatrixElement/Matchbox/Base/MatchboxMEBase.fh"
#include "Herwig++/MatrixElement/Matchbox/MatchboxFactory.fh"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
namespace Herwig {
using namespace ThePEG;
/**
* \ingroup Matchbox
* \author Simon Platzer
*
* \brief Process information with coupling order
*/
struct Process {
PDVector legs;
unsigned int orderInAlphaS;
unsigned int orderInAlphaEW;
Process()
: orderInAlphaS(0), orderInAlphaEW(0) {}
Process(const PDVector& p,
unsigned int oas,
unsigned int oae)
: legs(p), orderInAlphaS(oas), orderInAlphaEW(oae) {}
bool operator==(const Process& other) const {
return
legs == other.legs &&
orderInAlphaS == other.orderInAlphaS &&
orderInAlphaEW == other.orderInAlphaEW;
}
bool operator<(const Process& other) const {
if ( orderInAlphaS != other.orderInAlphaS )
return orderInAlphaS < other.orderInAlphaS;
if ( orderInAlphaEW != other.orderInAlphaEW )
return orderInAlphaEW < other.orderInAlphaEW;
return legs < other.legs;
}
void persistentOutput(PersistentOStream & os) const {
os << legs << orderInAlphaS << orderInAlphaEW;
}
void persistentInput(PersistentIStream & is) {
is >> legs >> orderInAlphaS >> orderInAlphaEW;
}
};
/**
* \ingroup Matchbox
* \author Simon Platzer
*
* \brief Enumerate the type of calculation required
*/
namespace ProcessType {
enum Types {
treeME2 = 0,
colourCorrelatedME2,
spinColourCorrelatedME2,
oneLoopInterference,
loopInducedME2,
spinCorrelatedME2
};
}
/**
* \ingroup Matchbox
* \author Simon Platzer
*
* \brief MatchboxAmplitude is the base class for amplitude
* implementations inside Matchbox.
*
* @see \ref MatchboxAmplitudeInterfaces "The interfaces"
* defined for MatchboxAmplitude.
*/
class MatchboxAmplitude:
public Amplitude,
public LastXCombInfo<StandardXComb>,
public LastMatchboxXCombInfo {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
MatchboxAmplitude();
/**
* The destructor.
*/
virtual ~MatchboxAmplitude();
//@}
public:
/**
* Return the amplitude. Needs to be implemented from
* ThePEG::Amplitude but is actually ill-defined, as colours of the
* external particles are not specified. To this extent, this
* implementation just asserts.
*/
virtual Complex value(const tcPDVector & particles,
const vector<Lorentz5Momentum> & momenta,
const vector<int> & helicities);
/**
* Return the factory which produced this matrix element
*/
Ptr<MatchboxFactory>::tptr factory() const;
/**
* Set the factory which produced this matrix element
*/
virtual void factory(Ptr<MatchboxFactory>::tptr f);
/** @name Subprocess information */
//@{
/**
* Return true, if this amplitude can handle the given process.
*/
virtual bool canHandle(const PDVector& p,
Ptr<MatchboxFactory>::tptr,
bool) const { return canHandle(p); }
/**
* Return true, if this amplitude can handle the given process.
*/
virtual bool canHandle(const PDVector&) const { return false; }
/**
* Return the number of random numbers required to evaluate this
* amplitude at a fixed phase space point.
*/
virtual int nDimAdditional() const { return 0; }
/**
* Return a ME instance appropriate for this amplitude and the given
* subprocesses
*/
virtual Ptr<MatchboxMEBase>::ptr makeME(const PDVector&) const;
/**
* Set the (tree-level) order in \f$g_S\f$ in which this matrix
* element should be evaluated.
*/
virtual void orderInGs(unsigned int) {}
/**
* Return the (tree-level) order in \f$g_S\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInGs() const = 0;
/**
* Set the (tree-level) order in \f$g_{EM}\f$ in which this matrix
* element should be evaluated.
*/
virtual void orderInGem(unsigned int) {}
/**
* Return the (tree-level) order in \f$g_{EM}\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInGem() const = 0;
/**
* Return the Herwig++ StandardModel object
*/
Ptr<StandardModel>::tcptr standardModel() {
if ( !hwStandardModel() )
hwStandardModel(dynamic_ptr_cast<Ptr<StandardModel>::tcptr>(HandlerBase::standardModel()));
return hwStandardModel();
}
/**
* Return true, if this amplitude already includes averaging over
* incoming parton's quantum numbers.
*/
virtual bool hasInitialAverage() const { return false; }
/**
* Return true, if this amplitude already includes symmetry factors
* for identical outgoing particles.
*/
virtual bool hasFinalStateSymmetry() const { return false; }
/**
* Return true, if this amplitude is handled by a BLHA one-loop provider
*/
virtual bool isOLPTree() const { return false; }
/**
* Return true, if this amplitude is handled by a BLHA one-loop provider
*/
virtual bool isOLPLoop() const { return false; }
/**
* Return true, if colour and spin correlated matrix elements should
* be ordered from the OLP
*/
virtual bool needsOLPCorrelators() const { return true; }
/**
* Write the order file header
*/
virtual void olpOrderFileHeader(ostream&) const;
/**
* Write the order file process list
*/
virtual void olpOrderFileProcesses(ostream&,
const map<pair<Process,int>,int>& procs) const;
/**
* Start the one loop provider, if appropriate, giving order and
* contract files
*/
virtual void signOLP(const string&, const string&) { }
/**
* Start the one loop provider, if appropriate
*/
virtual void startOLP(const string&, int& status) { status = -1; }
/**
* Start the one loop provider, if appropriate. This default
* implementation writes an BLHA 2.0 order file and starts the OLP
*/
virtual bool startOLP(const map<pair<Process,int>,int>& procs);
/**
* Return true, if this amplitude needs to initialize an external
* code.
*/
virtual bool isExternal() const { return false; }
/**
* Initialize this amplitude
*/
virtual bool initializeExternal() { return false; }
/**
* Return a generic process id for the given process
*/
virtual int externalId(const cPDVector&) { return 0; }
//@}
/** @name Colour basis. */
//@{
/**
* Return the colour basis.
*/
virtual Ptr<ColourBasis>::tptr colourBasis() const { return theColourBasis; }
/**
* Return true, if the colour basis is capable of assigning colour
* flows.
*/
virtual bool haveColourFlows() const {
return colourBasis() ? colourBasis()->haveColourFlows() : false;
}
/**
* Return a Selector with possible colour geometries for the selected
* diagram weighted by their relative probabilities.
*/
virtual Selector<const ColourLines *> colourGeometries(tcDiagPtr diag) const;
/**
* Return an ordering identifier for the current subprocess and
* colour absis tensor index.
*/
const string& colourOrderingString(size_t id) const;
/**
* Return an ordering identifier for the current subprocess and
* colour absis tensor index.
*/
const set<vector<size_t> >& colourOrdering(size_t id) const;
//@}
/** @name Phasespace point, crossing and helicities */
//@{
/**
* Set the xcomb object.
*/
virtual void setXComb(tStdXCombPtr xc);
/**
* Return the momentum as crossed appropriate for this amplitude.
*/
Lorentz5Momentum amplitudeMomentum(int) const;
/**
* Perform a normal ordering of external legs and fill the
* crossing information as. This default implementation sorts
* lexicographically in (abs(colour)/spin/abs(charge)), putting pairs
* of particles/anti-particles where possible.
*/
virtual void fillCrossingMap(size_t shift = 0);
/**
* Generate the helicity combinations.
*/
virtual set<vector<int> > generateHelicities() const;
//@}
/** @name Tree-level amplitudes */
//@{
/**
* Calculate the tree level amplitudes for the phasespace point
* stored in lastXComb.
*/
virtual void prepareAmplitudes(Ptr<MatchboxMEBase>::tcptr);
/**
* Return the matrix element squared.
*/
virtual double me2() const;
/**
* Return the largeN matrix element squared.
*/
virtual double largeNME2(Ptr<ColourBasis>::tptr largeNBasis) const;
/**
* Return the colour correlated matrix element.
*/
virtual double colourCorrelatedME2(pair<int,int> ij) const;
/**
* Return the large-N colour correlated matrix element.
*/
virtual double largeNColourCorrelatedME2(pair<int,int> ij,
Ptr<ColourBasis>::tptr largeNBasis) const;
/**
+ * Return true, if this amplitude is capable of consistently filling
+ * the rho matrices for the spin correllations
+ */
+ virtual bool canFillRhoMatrix() const { return false; }
+
+ /**
* Return a positive helicity polarization vector for a gluon of
* momentum p (with reference vector n) to be used when evaluating
* spin correlations.
*/
virtual LorentzVector<Complex> plusPolarization(const Lorentz5Momentum& p,
const Lorentz5Momentum& n,
int id = -1) const;
/**
* Return the colour and spin correlated matrix element.
*/
virtual double spinColourCorrelatedME2(pair<int,int> emitterSpectator,
const SpinCorrelationTensor& c) const;
/**
* Return the spin correlated matrix element.
*/
virtual double spinCorrelatedME2(pair<int,int> emitterSpectator,
const SpinCorrelationTensor& c) const;
/**
* Return true, if tree-level contributions will be evaluated at amplitude level.
*/
virtual bool treeAmplitudes() const { return true; }
/**
* Evaluate the amplitude for the given colour tensor id and
* helicity assignment
*/
virtual Complex evaluate(size_t, const vector<int>&, Complex&) { return 0.; }
//@}
/** @name One-loop amplitudes */
//@{
/**
* Return the one-loop amplitude, if applicable.
*/
virtual Ptr<MatchboxAmplitude>::tptr oneLoopAmplitude() const {
return Ptr<MatchboxAmplitude>::tptr();
}
/**
* Diasble one-loop functionality if not needed.
*/
virtual void disableOneLoop() {}
/**
* Return true, if this amplitude is capable of calculating one-loop
* (QCD) corrections.
*/
virtual bool haveOneLoop() const { return false; }
/**
* Return true, if this amplitude only provides
* one-loop (QCD) corrections.
*/
virtual bool onlyOneLoop() const { return false; }
/**
* Return true, if one-loop contributions will be evaluated at amplitude level.
*/
virtual bool oneLoopAmplitudes() const { return true; }
/**
* Return true, if one loop corrections have been calculated in
* dimensional reduction. Otherwise conventional dimensional
* regularization is assumed. Note that renormalization is always
* assumed to be MSbar.
*/
virtual bool isDR() const { return false; }
/**
* Return true, if the amplitude is DRbar renormalized, otherwise
* MSbar is assumed.
*/
virtual bool isDRbar() const { return true; }
/**
* Return true, if one loop corrections are given in the conventions
* of the integrated dipoles.
*/
virtual bool isCS() const { return false; }
/**
* Return true, if one loop corrections are given in the conventions
* of BDK.
*/
virtual bool isBDK() const { return false; }
/**
* Return true, if one loop corrections are given in the conventions
* of everything expanded.
*/
virtual bool isExpanded() const { return false; }
/**
* Return the value of the dimensional regularization
* parameter. Note that renormalization scale dependence is fully
* restored in DipoleIOperator.
*/
virtual Energy2 mu2() const { return 0.*GeV2; }
/**
* If defined, return the coefficient of the pole in epsilon^2
*/
virtual double oneLoopDoublePole() const { return 0.; }
/**
* If defined, return the coefficient of the pole in epsilon
*/
virtual double oneLoopSinglePole() const { return 0.; }
/**
* Calculate the one-loop amplitudes for the phasespace point
* stored in lastXComb, if provided.
*/
virtual void prepareOneLoopAmplitudes(Ptr<MatchboxMEBase>::tcptr);
/**
* Return the one-loop/tree interference.
*/
virtual double oneLoopInterference() const;
/**
* Evaluate the amplitude for the given colour tensor id and
* helicity assignment
*/
virtual Complex evaluateOneLoop(size_t, const vector<int>&) { return 0.; }
//@}
/** @name Caching and helpers to setup amplitude objects. */
//@{
/**
* Flush all cashes.
*/
virtual void flushCaches() {}
/**
* Clone this amplitude.
*/
Ptr<MatchboxAmplitude>::ptr cloneMe() const {
return dynamic_ptr_cast<Ptr<MatchboxAmplitude>::ptr>(clone());
}
/**
* Clone the dependencies, using a given prefix.
*/
virtual void cloneDependencies(const std::string& prefix = "");
//@}
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();
// 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 factory which produced this matrix element
*/
Ptr<MatchboxFactory>::tptr theFactory;
/**
* Recursively generate helicities
*/
void doGenerateHelicities(set<vector<int> >& res,
vector<int>& current,
size_t pos) const;
/**
* The colour basis implementation to be used.
*/
Ptr<ColourBasis>::ptr theColourBasis;
/**
* The number of points after which helicity combinations wil be
* cleaned up
*/
int theCleanupAfter;
/**
* The number of points that are calculated before a certain
* helicity is excluded. Needed in pp->V
*/
int treeLevelHelicityPoints;
/**
* The number of points that are calculated before a certain
* helicity is excluded. Needed in pp->V
*/
int oneLoopHelicityPoints;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MatchboxAmplitude & operator=(const MatchboxAmplitude &);
};
inline PersistentOStream& operator<<(PersistentOStream& os,
const Process& h) {
h.persistentOutput(os);
return os;
}
inline PersistentIStream& operator>>(PersistentIStream& is,
Process& h) {
h.persistentInput(is);
return is;
}
}
#endif /* HERWIG_MatchboxAmplitude_H */
diff --git a/MatrixElement/Matchbox/Base/MatchboxMEBase.cc b/MatrixElement/Matchbox/Base/MatchboxMEBase.cc
--- a/MatrixElement/Matchbox/Base/MatchboxMEBase.cc
+++ b/MatrixElement/Matchbox/Base/MatchboxMEBase.cc
@@ -1,1618 +1,1629 @@
// -*- C++ -*-
//
// MatchboxMEBase.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 MatchboxMEBase class.
//
#include "MatchboxMEBase.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/RefVector.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDF/PDF.h"
#include "ThePEG/PDT/PDT.h"
#include "ThePEG/StandardModel/StandardModelBase.h"
#include "ThePEG/Cuts/Cuts.h"
#include "ThePEG/Handlers/StdXCombGroup.h"
#include "Herwig++/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h"
#include "Herwig++/MatrixElement/Matchbox/Utility/DiagramDrawer.h"
#include "Herwig++/MatrixElement/Matchbox/MatchboxFactory.h"
#include "Herwig++/Utilities/RunDirectories.h"
#include <iterator>
using std::ostream_iterator;
using namespace Herwig;
MatchboxMEBase::MatchboxMEBase()
: MEBase(),
theOneLoop(false),
theOneLoopNoBorn(false),
theNoCorrelations(false),
theHavePDFs(false,false), checkedPDFs(false),
theDiagramWeightVerboseDown(10000000000000.),
theDiagramWeightVerboseUp(0.) {}
MatchboxMEBase::~MatchboxMEBase() {}
Ptr<MatchboxFactory>::tptr MatchboxMEBase::factory() const { return theFactory; }
void MatchboxMEBase::factory(Ptr<MatchboxFactory>::tptr f) { theFactory = f; }
Ptr<Tree2toNGenerator>::tptr MatchboxMEBase::diagramGenerator() const { return factory()->diagramGenerator(); }
Ptr<ProcessData>::tptr MatchboxMEBase::processData() const { return factory()->processData(); }
unsigned int MatchboxMEBase::getNLight() const { return factory()->nLight(); }
vector<int> MatchboxMEBase::getNLightJetVec() const { return factory()->nLightJetVec(); }
vector<int> MatchboxMEBase::getNHeavyJetVec() const { return factory()->nHeavyJetVec(); }
vector<int> MatchboxMEBase::getNLightProtonVec() const { return factory()->nLightProtonVec(); }
double MatchboxMEBase::factorizationScaleFactor() const { return factory()->factorizationScaleFactor(); }
double MatchboxMEBase::renormalizationScaleFactor() const { return factory()->renormalizationScaleFactor(); }
bool MatchboxMEBase::fixedCouplings() const { return factory()->fixedCouplings(); }
bool MatchboxMEBase::fixedQEDCouplings() const { return factory()->fixedQEDCouplings(); }
bool MatchboxMEBase::checkPoles() const { return factory()->checkPoles(); }
bool MatchboxMEBase::verbose() const { return factory()->verbose(); }
bool MatchboxMEBase::initVerbose() const { return factory()->initVerbose(); }
void MatchboxMEBase::getDiagrams() const {
if ( diagramGenerator() && processData() ) {
vector<Ptr<Tree2toNDiagram>::ptr> diags;
vector<Ptr<Tree2toNDiagram>::ptr>& res =
processData()->diagramMap()[subProcess().legs];
if ( res.empty() ) {
res = diagramGenerator()->generate(subProcess().legs,orderInAlphaS(),orderInAlphaEW());
}
copy(res.begin(),res.end(),back_inserter(diags));
processData()->fillMassGenerators(subProcess().legs);
if ( diags.empty() )
return;
for ( vector<Ptr<Tree2toNDiagram>::ptr>::iterator d = diags.begin();
d != diags.end(); ++d ) {
add(*d);
}
return;
}
throw Exception()
<< "MatchboxMEBase::getDiagrams() expects a Tree2toNGenerator and ProcessData object.\n"
<< "Please check your setup." << Exception::abortnow;
}
Selector<MEBase::DiagramIndex>
MatchboxMEBase::diagrams(const DiagramVector & diags) const {
if ( phasespace() ) {
return phasespace()->selectDiagrams(diags);
}
throw Exception()
<< "MatchboxMEBase::diagrams() expects a MatchboxPhasespace object.\n"
<< "Please check your setup." << Exception::abortnow;
return Selector<MEBase::DiagramIndex>();
}
Selector<const ColourLines *>
MatchboxMEBase::colourGeometries(tcDiagPtr diag) const {
if ( matchboxAmplitude() ) {
if ( matchboxAmplitude()->haveColourFlows() ) {
if ( matchboxAmplitude()->treeAmplitudes() )
matchboxAmplitude()->prepareAmplitudes(this);
return matchboxAmplitude()->colourGeometries(diag);
}
}
Ptr<Tree2toNDiagram>::tcptr tdiag =
dynamic_ptr_cast<Ptr<Tree2toNDiagram>::tcptr>(diag);
assert(diag && processData());
vector<ColourLines*>& flows = processData()->colourFlowMap()[tdiag];
if ( flows.empty() ) {
list<list<list<pair<int,bool> > > > cflows =
ColourBasis::colourFlows(tdiag);
for ( list<list<list<pair<int,bool> > > >::const_iterator fit =
cflows.begin(); fit != cflows.end(); ++fit ) {
flows.push_back(new ColourLines(ColourBasis::cfstring(*fit)));
}
}
Selector<const ColourLines *> res;
for ( vector<ColourLines*>::const_iterator f = flows.begin();
f != flows.end(); ++f )
res.insert(1.0,*f);
return res;
}
+void MatchboxMEBase::constructVertex(tSubProPtr sub, const ColourLines* cl) {
+ if ( canFillRhoMatrix() && factory()->fillRhoMatrices() ) {
+ assert(colourBasis());
+ size_t colourStructureId =
+ colourBasis()->tensorIdFromFlow(lastXComb().lastDiagram(),cl);
+ /*
+ now we can use lastLargeNAmplitudes to get it going
+ */
+ }
+}
+
unsigned int MatchboxMEBase::orderInAlphaS() const {
return subProcess().orderInAlphaS;
}
unsigned int MatchboxMEBase::orderInAlphaEW() const {
return subProcess().orderInAlphaEW;
}
void MatchboxMEBase::setXComb(tStdXCombPtr xc) {
MEBase::setXComb(xc);
lastMatchboxXComb(xc);
if ( phasespace() )
phasespace()->setXComb(xc);
if ( scaleChoice() )
scaleChoice()->setXComb(xc);
if ( matchboxAmplitude() )
matchboxAmplitude()->setXComb(xc);
}
double MatchboxMEBase::generateIncomingPartons(const double* r1, const double* r2) {
// shamelessly stolen from PartonExtractor.cc
Energy2 shmax = lastCuts().sHatMax();
Energy2 shmin = lastCuts().sHatMin();
Energy2 sh = shmin*pow(shmax/shmin, *r1);
double ymax = lastCuts().yHatMax();
double ymin = lastCuts().yHatMin();
double km = log(shmax/shmin);
ymax = min(ymax, log(lastCuts().x1Max()*sqrt(lastS()/sh)));
ymin = max(ymin, -log(lastCuts().x2Max()*sqrt(lastS()/sh)));
double y = ymin + (*r2)*(ymax - ymin);
double x1 = exp(-0.5*log(lastS()/sh) + y);
double x2 = exp(-0.5*log(lastS()/sh) - y);
Lorentz5Momentum P1 = lastParticles().first->momentum();
LorentzMomentum p1 = lightCone((P1.rho() + P1.e())*x1, Energy());
p1.rotateY(P1.theta());
p1.rotateZ(P1.phi());
meMomenta()[0] = p1;
Lorentz5Momentum P2 = lastParticles().second->momentum();
LorentzMomentum p2 = lightCone((P2.rho() + P2.e())*x2, Energy());
p2.rotateY(P2.theta());
p2.rotateZ(P2.phi());
meMomenta()[1] = p2;
lastXCombPtr()->lastX1X2(make_pair(x1,x2));
lastXCombPtr()->lastSHat((meMomenta()[0]+meMomenta()[1]).m2());
return km*(ymax - ymin);
}
bool MatchboxMEBase::generateKinematics(const double * r) {
if ( phasespace() ) {
jacobian(phasespace()->generateKinematics(r,meMomenta()));
if ( jacobian() == 0.0 )
return false;
setScale();
logGenerateKinematics(r);
assert(lastMatchboxXComb());
if ( nDimAmplitude() > 0 ) {
amplitudeRandomNumbers().resize(nDimAmplitude());
copy(r + nDimPhasespace(),
r + nDimPhasespace() + nDimAmplitude(),
amplitudeRandomNumbers().begin());
}
if ( nDimInsertions() > 0 ) {
insertionRandomNumbers().resize(nDimInsertions());
copy(r + nDimPhasespace() + nDimAmplitude(),
r + nDimPhasespace() + nDimAmplitude() + nDimInsertions(),
insertionRandomNumbers().begin());
}
return true;
}
throw Exception()
<< "MatchboxMEBase::generateKinematics() expects a MatchboxPhasespace object.\n"
<< "Please check your setup." << Exception::abortnow;
return false;
}
int MatchboxMEBase::nDim() const {
if ( lastMatchboxXComb() )
return nDimPhasespace() + nDimAmplitude() + nDimInsertions();
int ampAdd = 0;
if ( matchboxAmplitude() ) {
ampAdd = matchboxAmplitude()->nDimAdditional();
}
int insertionAdd = 0;
for ( vector<Ptr<MatchboxInsertionOperator>::ptr>::const_iterator v =
virtuals().begin(); v != virtuals().end(); ++v ) {
insertionAdd = max(insertionAdd,(**v).nDimAdditional());
}
return nDimBorn() + ampAdd + insertionAdd;
}
int MatchboxMEBase::nDimBorn() const {
if ( lastMatchboxXComb() )
return nDimPhasespace();
if ( phasespace() ) {
size_t nout = diagrams().front()->partons().size()-2;
int n = phasespace()->nDim(nout);
if ( phasespace()->useMassGenerators() ) {
for ( cPDVector::const_iterator pd =
diagrams().front()->partons().begin();
pd != diagrams().front()->partons().end(); ++pd ) {
if ( processData()->massGenerator(*pd) ||
(**pd).width() != ZERO ) {
++n;
}
}
}
return n;
}
throw Exception()
<< "MatchboxMEBase::nDim() expects a MatchboxPhasespace object.\n"
<< "Please check your setup." << Exception::abortnow;
return 0;
}
void MatchboxMEBase::setScale() const {
if ( haveX1X2() ) {
lastXCombPtr()->lastSHat((meMomenta()[0]+meMomenta()[1]).m2());
}
Energy2 fcscale = factorizationScale();
Energy2 fscale = fcscale*sqr(factorizationScaleFactor());
Energy2 rscale = renormalizationScale()*sqr(renormalizationScaleFactor());
Energy2 ewrscale = renormalizationScaleQED();
lastXCombPtr()->lastScale(fscale);
lastXCombPtr()->lastCentralScale(fcscale);
if ( !fixedCouplings() ) {
if ( rscale > lastCuts().scaleMin() )
lastXCombPtr()->lastAlphaS(SM().alphaS(rscale));
else
lastXCombPtr()->lastAlphaS(SM().alphaS(lastCuts().scaleMin()));
} else {
lastXCombPtr()->lastAlphaS(SM().alphaS());
}
if ( !fixedQEDCouplings() ) {
lastXCombPtr()->lastAlphaEM(SM().alphaEMME(ewrscale));
} else {
lastXCombPtr()->lastAlphaEM(SM().alphaEMMZ());
}
logSetScale();
}
Energy2 MatchboxMEBase::factorizationScale() const {
if ( scaleChoice() ) {
return scaleChoice()->factorizationScale();
}
throw Exception()
<< "MatchboxMEBase::factorizationScale() expects a MatchboxScaleChoice object.\n"
<< "Please check your setup." << Exception::abortnow;
return ZERO;
}
Energy2 MatchboxMEBase::renormalizationScale() const {
if ( scaleChoice() ) {
return scaleChoice()->renormalizationScale();
}
throw Exception()
<< "MatchboxMEBase::renormalizationScale() expects a MatchboxScaleChoice object.\n"
<< "Please check your setup." << Exception::abortnow;
return ZERO;
}
Energy2 MatchboxMEBase::renormalizationScaleQED() const {
if ( scaleChoice() ) {
return scaleChoice()->renormalizationScaleQED();
}
return renormalizationScale();
}
void MatchboxMEBase::setVetoScales(tSubProPtr) const {}
bool MatchboxMEBase::havePDFWeight1() const {
if ( checkedPDFs )
return theHavePDFs.first;
theHavePDFs.first =
factory()->isIncoming(mePartonData()[0]) &&
lastXCombPtr()->partonBins().first->pdf();
theHavePDFs.second =
factory()->isIncoming(mePartonData()[1]) &&
lastXCombPtr()->partonBins().second->pdf();
checkedPDFs = true;
return theHavePDFs.first;
}
bool MatchboxMEBase::havePDFWeight2() const {
if ( checkedPDFs )
return theHavePDFs.second;
theHavePDFs.first =
factory()->isIncoming(mePartonData()[0]) &&
lastXCombPtr()->partonBins().first->pdf();
theHavePDFs.second =
factory()->isIncoming(mePartonData()[1]) &&
lastXCombPtr()->partonBins().second->pdf();
checkedPDFs = true;
return theHavePDFs.second;
}
void MatchboxMEBase::getPDFWeight(Energy2 factorizationScale) const {
if ( !havePDFWeight1() && !havePDFWeight2() ) {
lastMEPDFWeight(1.0);
logPDFWeight();
return;
}
double w = 1.;
if ( havePDFWeight1() )
w *= pdf1(factorizationScale);
if ( havePDFWeight2() )
w *= pdf2(factorizationScale);
lastMEPDFWeight(w);
logPDFWeight();
}
double MatchboxMEBase::pdf1(Energy2 fscale, double xEx) const {
assert(lastXCombPtr()->partonBins().first->pdf());
if ( xEx < 1. && lastX1() >= xEx ) {
return
( ( 1. - lastX1() ) / ( 1. - xEx ) ) *
lastXCombPtr()->partonBins().first->pdf()->xfx(lastParticles().first->dataPtr(),
lastPartons().first->dataPtr(),
fscale == ZERO ? lastScale() : fscale,
xEx)/xEx;
}
return lastXCombPtr()->partonBins().first->pdf()->xfx(lastParticles().first->dataPtr(),
lastPartons().first->dataPtr(),
fscale == ZERO ? lastScale() : fscale,
lastX1())/lastX1();
}
double MatchboxMEBase::pdf2(Energy2 fscale, double xEx) const {
assert(lastXCombPtr()->partonBins().second->pdf());
if ( xEx < 1. && lastX2() >= xEx ) {
return
( ( 1. - lastX2() ) / ( 1. - xEx ) ) *
lastXCombPtr()->partonBins().second->pdf()->xfx(lastParticles().second->dataPtr(),
lastPartons().second->dataPtr(),
fscale == ZERO ? lastScale() : fscale,
xEx)/xEx;
}
return lastXCombPtr()->partonBins().second->pdf()->xfx(lastParticles().second->dataPtr(),
lastPartons().second->dataPtr(),
fscale == ZERO ? lastScale() : fscale,
lastX2())/lastX2();
}
double MatchboxMEBase::me2() const {
if ( matchboxAmplitude() ) {
if ( matchboxAmplitude()->treeAmplitudes() )
matchboxAmplitude()->prepareAmplitudes(this);
double res =
matchboxAmplitude()->me2()*
me2Norm();
return res;
}
throw Exception()
<< "MatchboxMEBase::me2() expects a MatchboxAmplitude object.\n"
<< "Please check your setup." << Exception::abortnow;
return 0.;
}
double MatchboxMEBase::largeNME2(Ptr<ColourBasis>::tptr largeNBasis) const {
if ( matchboxAmplitude() ) {
largeNBasis->prepare(mePartonData(),false);
if ( matchboxAmplitude()->treeAmplitudes() )
matchboxAmplitude()->prepareAmplitudes(this);
double res =
matchboxAmplitude()->largeNME2(largeNBasis)*
me2Norm();
return res;
}
throw Exception()
<< "MatchboxMEBase::largeNME2() expects a MatchboxAmplitude object.\n"
<< "Please check your setup." << Exception::abortnow;
return 0.;
}
double MatchboxMEBase::finalStateSymmetry() const {
if ( symmetryFactor() > 0.0 )
return symmetryFactor();
double sFactor = 1.;
map<long,int> counts;
cPDVector checkData;
copy(mePartonData().begin()+2,mePartonData().end(),back_inserter(checkData));
cPDVector::iterator p = checkData.begin();
while ( !checkData.empty() ) {
if ( counts.find((**p).id()) != counts.end() ) {
counts[(**p).id()] += 1;
} else {
counts[(**p).id()] = 1;
}
checkData.erase(p);
p = checkData.begin();
continue;
}
for ( map<long,int>::const_iterator c = counts.begin();
c != counts.end(); ++c ) {
if ( c->second == 1 )
continue;
if ( c->second == 2 )
sFactor /= 2.;
else if ( c->second == 3 )
sFactor /= 6.;
else if ( c->second == 4 )
sFactor /= 24.;
}
symmetryFactor(sFactor);
return symmetryFactor();
}
double MatchboxMEBase::me2Norm(unsigned int addAlphaS) const {
// assume that we always have incoming
// spin-1/2 or massless spin-1 particles
double fac = 1./4.;
if ( hasInitialAverage() )
fac = 1.;
double couplings = 1.0;
if ( orderInAlphaS() > 0 || addAlphaS != 0 ) {
fac *= pow(lastAlphaS()/SM().alphaS(),double(orderInAlphaS()+addAlphaS));
couplings *= pow(lastAlphaS(),double(orderInAlphaS()+addAlphaS));
}
if ( orderInAlphaEW() > 0 ) {
fac *= pow(lastAlphaEM()/SM().alphaEMMZ(),double(orderInAlphaEW()));
couplings *= pow(lastAlphaEM(),double(orderInAlphaEW()));
}
lastMECouplings(couplings);
if ( !hasInitialAverage() ) {
if ( mePartonData()[0]->iColour() == PDT::Colour3 ||
mePartonData()[0]->iColour() == PDT::Colour3bar )
fac /= SM().Nc();
else if ( mePartonData()[0]->iColour() == PDT::Colour8 )
fac /= (SM().Nc()*SM().Nc()-1.);
if ( mePartonData()[1]->iColour() == PDT::Colour3 ||
mePartonData()[1]->iColour() == PDT::Colour3bar )
fac /= SM().Nc();
else if ( mePartonData()[1]->iColour() == PDT::Colour8 )
fac /= (SM().Nc()*SM().Nc()-1.);
}
return !hasFinalStateSymmetry() ? finalStateSymmetry()*fac : fac;
}
CrossSection MatchboxMEBase::dSigHatDR() const {
getPDFWeight();
if ( !lastXCombPtr()->willPassCuts() ) {
lastME2(0.0);
lastMECrossSection(ZERO);
return lastMECrossSection();
}
double xme2 = me2();
lastME2(xme2);
if (factory()->verboseDia()){
double diagweightsum = 0.0;
for ( vector<Ptr<DiagramBase>::ptr>::const_iterator d = diagrams().begin();
d != diagrams().end(); ++d ) {
diagweightsum += phasespace()->diagramWeight(dynamic_cast<const Tree2toNDiagram&>(**d));
}
double piWeight = pow(2.*Constants::pi,(int)(3*(meMomenta().size()-2)-4));
double units = pow(lastSHat() / GeV2, mePartonData().size() - 4.);
bookMEoverDiaWeight(log(xme2/(diagweightsum*piWeight*units)));//
}
if ( xme2 == 0. && !oneLoopNoBorn() ) {
lastMECrossSection(ZERO);
return lastMECrossSection();
}
double vme2 = 0.;
if ( oneLoop() )
vme2 = oneLoopInterference();
CrossSection res = ZERO;
if ( !oneLoopNoBorn() )
res +=
(sqr(hbarc)/(2.*lastSHat())) *
jacobian()* lastMEPDFWeight() * xme2;
if ( oneLoop() )
res +=
(sqr(hbarc)/(2.*lastSHat())) *
jacobian()* lastMEPDFWeight() * vme2;
if ( !onlyOneLoop() ) {
for ( vector<Ptr<MatchboxInsertionOperator>::ptr>::const_iterator v =
virtuals().begin(); v != virtuals().end(); ++v ) {
(**v).setXComb(lastXCombPtr());
res += (**v).dSigHatDR();
}
if ( checkPoles() )
logPoles();
}
double weight = 0.0;
bool applied = false;
for ( vector<Ptr<MatchboxReweightBase>::ptr>::const_iterator rw =
theReweights.begin(); rw != theReweights.end(); ++rw ) {
(**rw).setXComb(lastXCombPtr());
if ( !(**rw).apply() )
continue;
weight += (**rw).evaluate();
applied = true;
}
if ( applied )
res *= weight;
lastMECrossSection(res);
return lastMECrossSection();
}
double MatchboxMEBase::oneLoopInterference() const {
if ( matchboxAmplitude() ) {
if ( matchboxAmplitude()->oneLoopAmplitudes() )
matchboxAmplitude()->prepareOneLoopAmplitudes(this);
double res =
matchboxAmplitude()->oneLoopInterference()*
me2Norm(1);
return res;
}
throw Exception()
<< "MatchboxMEBase::oneLoopInterference() expects a MatchboxAmplitude object.\n"
<< "Please check your setup." << Exception::abortnow;
return 0.;
}
MatchboxMEBase::AccuracyHistogram::AccuracyHistogram(double low,
double up,
unsigned int nbins)
: lower(low), upper(up),
sameSign(0), oppositeSign(0), nans(0),
overflow(0), underflow(0) {
double step = (up-low)/nbins;
for ( unsigned int k = 1; k <= nbins; ++k )
bins[lower + k*step] = 0.0;
}
void MatchboxMEBase::AccuracyHistogram::book(double a, double b) {
if ( isnan(a) || isnan(b) ||
isinf(a) || isinf(b) ) {
++nans;
return;
}
if ( a*b >= 0. )
++sameSign;
if ( a*b < 0. )
++oppositeSign;
double r = 1.;
if ( abs(a) != 0.0 )
r = abs(1.-abs(b/a));
else if ( abs(b) != 0.0 )
r = abs(b);
if ( log10(r) < lower || r == 0.0 ) {
++underflow;
return;
}
if ( log10(r) > upper ) {
++overflow;
return;
}
map<double,double>::iterator bin =
bins.upper_bound(log10(r));
if ( bin == bins.end() )
return;
bin->second += 1.;
}
void MatchboxMEBase::AccuracyHistogram::dump(const std::string& folder, const std::string& prefix,
const cPDVector& proc) const {
ostringstream fname("");
for ( cPDVector::const_iterator p = proc.begin();
p != proc.end(); ++p )
fname << (**p).PDGName();
ofstream out((folder+"/"+prefix+fname.str()+".dat").c_str());
out << "# same sign : " << sameSign << " opposite sign : "
<< oppositeSign << " nans : " << nans
<< " overflow : " << overflow
<< " underflow : " << underflow << "\n";
for ( map<double,double>::const_iterator b = bins.begin();
b != bins.end(); ++b ) {
map<double,double>::const_iterator bp = b; --bp;
if ( b->second != 0. ) {
if ( b != bins.begin() )
out << bp->first;
else
out << lower;
out << " " << b->first
<< " " << b->second
<< "\n" << flush;
}
}
ofstream gpout((folder+"/"+prefix+fname.str()+".gp").c_str());
gpout << "set terminal png\n"
<< "set xlabel 'accuracy of pole cancellation [decimal places]'\n"
<< "set ylabel 'counts\n"
<< "set xrange [-20:0]\n"
<< "set output '" << prefix << fname.str() << ".png'\n"
<< "plot '" << prefix << fname.str() << ".dat' using (0.5*($1+$2)):3 with linespoints pt 7 ps 1 not";
}
void MatchboxMEBase::AccuracyHistogram::persistentOutput(PersistentOStream& os) const {
os << lower << upper << bins
<< sameSign << oppositeSign << nans
<< overflow << underflow;
}
void MatchboxMEBase::AccuracyHistogram::persistentInput(PersistentIStream& is) {
is >> lower >> upper >> bins
>> sameSign >> oppositeSign >> nans
>> overflow >> underflow;
}
void MatchboxMEBase::logPoles() const {
double res2me = oneLoopDoublePole();
double res1me = oneLoopSinglePole();
double res2i = 0.;
double res1i = 0.;
for ( vector<Ptr<MatchboxInsertionOperator>::ptr>::const_iterator v =
virtuals().begin(); v != virtuals().end(); ++v ) {
res2i += (**v).oneLoopDoublePole();
res1i += (**v).oneLoopSinglePole();
}
if (res2me != 0.0 || res2i != 0.0) epsilonSquarePoleHistograms[mePartonData()].book(res2me,res2i);
if (res1me != 0.0 || res1i != 0.0) epsilonPoleHistograms[mePartonData()].book(res1me,res1i);
}
bool MatchboxMEBase::haveOneLoop() const {
if ( matchboxAmplitude() )
return matchboxAmplitude()->haveOneLoop();
return false;
}
bool MatchboxMEBase::onlyOneLoop() const {
if ( matchboxAmplitude() )
return matchboxAmplitude()->onlyOneLoop();
return false;
}
bool MatchboxMEBase::isDRbar() const {
if ( matchboxAmplitude() )
return matchboxAmplitude()->isDRbar();
return false;
}
bool MatchboxMEBase::isDR() const {
if ( matchboxAmplitude() )
return matchboxAmplitude()->isDR();
return false;
}
bool MatchboxMEBase::isCS() const {
if ( matchboxAmplitude() )
return matchboxAmplitude()->isCS();
return false;
}
bool MatchboxMEBase::isBDK() const {
if ( matchboxAmplitude() )
return matchboxAmplitude()->isBDK();
return false;
}
bool MatchboxMEBase::isExpanded() const {
if ( matchboxAmplitude() )
return matchboxAmplitude()->isExpanded();
return false;
}
Energy2 MatchboxMEBase::mu2() const {
if ( matchboxAmplitude() )
return matchboxAmplitude()->mu2();
return 0*GeV2;
}
double MatchboxMEBase::oneLoopDoublePole() const {
if ( matchboxAmplitude() ) {
return
matchboxAmplitude()->oneLoopDoublePole()*
me2Norm(1);
}
return 0.;
}
double MatchboxMEBase::oneLoopSinglePole() const {
if ( matchboxAmplitude() ) {
return
matchboxAmplitude()->oneLoopSinglePole()*
me2Norm(1);
}
return 0.;
}
vector<Ptr<SubtractionDipole>::ptr>
MatchboxMEBase::getDipoles(const vector<Ptr<SubtractionDipole>::ptr>& dipoles,
const vector<Ptr<MatchboxMEBase>::ptr>& borns) const {
vector<Ptr<SubtractionDipole>::ptr> res;
// keep track of the dipoles we already did set up
set<pair<pair<pair<int,int>,int>,pair<Ptr<MatchboxMEBase>::tptr,Ptr<SubtractionDipole>::tptr> > > done;
cPDVector rep = diagrams().front()->partons();
int nreal = rep.size();
// now loop over configs
for ( int emitter = 0; emitter < nreal; ++emitter ) {
list<Ptr<SubtractionDipole>::ptr> matchDipoles;
for ( vector<Ptr<SubtractionDipole>::ptr>::const_iterator d =
dipoles.begin(); d != dipoles.end(); ++d ) {
if ( !(**d).canHandleEmitter(rep,emitter) )
continue;
matchDipoles.push_back(*d);
}
if ( matchDipoles.empty() )
continue;
for ( int emission = 2; emission < nreal; ++emission ) {
if ( emission == emitter )
continue;
list<Ptr<SubtractionDipole>::ptr> matchDipoles2;
for ( list<Ptr<SubtractionDipole>::ptr>::const_iterator d =
matchDipoles.begin(); d != matchDipoles.end(); ++d ) {
if ( !(**d).canHandleSplitting(rep,emitter,emission) )
continue;
matchDipoles2.push_back(*d);
}
if ( matchDipoles2.empty() )
continue;
map<Ptr<DiagramBase>::ptr,SubtractionDipole::MergeInfo> mergeInfo;
for ( DiagramVector::const_iterator d = diagrams().begin(); d != diagrams().end(); ++d ) {
Ptr<Tree2toNDiagram>::ptr check(new Tree2toNDiagram(*dynamic_ptr_cast<Ptr<Tree2toNDiagram>::ptr>(*d)));
map<int,int> theMergeLegs;
for ( unsigned int i = 0; i < check->external().size(); ++i )
theMergeLegs[i] = -1;
int theEmitter = check->mergeEmission(emitter,emission,theMergeLegs);
// no underlying Born
if ( theEmitter == -1 )
continue;
SubtractionDipole::MergeInfo info;
info.diagram = check;
info.emitter = theEmitter;
info.mergeLegs = theMergeLegs;
mergeInfo[*d] = info;
}
if ( mergeInfo.empty() )
continue;
for ( int spectator = 0; spectator < nreal; ++spectator ) {
if ( spectator == emitter || spectator == emission )
continue;
list<Ptr<SubtractionDipole>::ptr> matchDipoles3;
for ( list<Ptr<SubtractionDipole>::ptr>::const_iterator d =
matchDipoles2.begin(); d != matchDipoles2.end(); ++d ) {
if ( !(**d).canHandleSpectator(rep,spectator) )
continue;
matchDipoles3.push_back(*d);
}
if ( matchDipoles3.empty() )
continue;
if ( noDipole(emitter,emission,spectator) )
continue;
for ( list<Ptr<SubtractionDipole>::ptr>::const_iterator d =
matchDipoles3.begin(); d != matchDipoles3.end(); ++d ) {
if ( !(**d).canHandle(rep,emitter,emission,spectator) )
continue;
for ( vector<Ptr<MatchboxMEBase>::ptr>::const_iterator b =
borns.begin(); b != borns.end(); ++b ) {
if ( (**b).onlyOneLoop() )
continue;
if ( done.find(make_pair(make_pair(make_pair(emitter,emission),spectator),make_pair(*b,*d)))
!= done.end() )
continue;
// now get to work
(**d).clearBookkeeping();
(**d).factory(factory());
(**d).realEmitter(emitter);
(**d).realEmission(emission);
(**d).realSpectator(spectator);
(**d).realEmissionME(const_cast<MatchboxMEBase*>(this));
(**d).underlyingBornME(*b);
(**d).setupBookkeeping(mergeInfo);
if ( !((**d).empty()) ) {
Ptr<SubtractionDipole>::ptr nDipole = (**d).cloneMe();
res.push_back(nDipole);
done.insert(make_pair(make_pair(make_pair(emitter,emission),spectator),make_pair(*b,*d)));
if ( nDipole->isSymmetric() )
done.insert(make_pair(make_pair(make_pair(emission,emitter),spectator),make_pair(*b,*d)));
ostringstream dname;
dname << fullName() << "." << (**b).name() << "."
<< (**d).name() << ".[("
<< emitter << "," << emission << ")," << spectator << "]";
if ( ! (generator()->preinitRegister(nDipole,dname.str()) ) )
throw InitException() << "Dipole " << dname.str() << " already existing.";
if ( !factory()->reweighters().empty() ) {
for ( vector<ReweightPtr>::const_iterator rw = factory()->reweighters().begin();
rw != factory()->reweighters().end(); ++rw )
nDipole->addReweighter(*rw);
}
if ( !factory()->preweighters().empty() ) {
for ( vector<ReweightPtr>::const_iterator rw = factory()->preweighters().begin();
rw != factory()->preweighters().end(); ++rw )
nDipole->addPreweighter(*rw);
}
nDipole->cloneDependencies(dname.str());
}
}
}
}
}
}
for ( vector<Ptr<SubtractionDipole>::ptr>::iterator d = res.begin();
d != res.end(); ++d )
(**d).partnerDipoles(res);
return res;
}
double MatchboxMEBase::colourCorrelatedME2(pair<int,int> ij) const {
if ( matchboxAmplitude() ) {
if ( matchboxAmplitude()->treeAmplitudes() )
matchboxAmplitude()->prepareAmplitudes(this);
double res =
matchboxAmplitude()->colourCorrelatedME2(ij)*
me2Norm();
return res;
}
throw Exception()
<< "MatchboxMEBase::colourCorrelatedME2() expects a MatchboxAmplitude object.\n"
<< "Please check your setup." << Exception::abortnow;
return 0.;
}
double MatchboxMEBase::largeNColourCorrelatedME2(pair<int,int> ij,
Ptr<ColourBasis>::tptr largeNBasis) const {
if ( matchboxAmplitude() ) {
largeNBasis->prepare(mePartonData(),false);
if ( matchboxAmplitude()->treeAmplitudes() )
matchboxAmplitude()->prepareAmplitudes(this);
double res =
matchboxAmplitude()->largeNColourCorrelatedME2(ij,largeNBasis)*
me2Norm();
return res;
}
throw Exception()
<< "MatchboxMEBase::largeNColourCorrelatedME2() expects a MatchboxAmplitude object.\n"
<< "Please check your setup." << Exception::abortnow;
return 0.;
}
double MatchboxMEBase::spinColourCorrelatedME2(pair<int,int> ij,
const SpinCorrelationTensor& c) const {
if ( matchboxAmplitude() ) {
if ( matchboxAmplitude()->treeAmplitudes() )
matchboxAmplitude()->prepareAmplitudes(this);
double res =
matchboxAmplitude()->spinColourCorrelatedME2(ij,c)*
me2Norm();
return res;
}
throw Exception()
<< "MatchboxMEBase::spinColourCorrelatedME2() expects a MatchboxAmplitude object.\n"
<< "Please check your setup." << Exception::abortnow;
return 0.;
}
double MatchboxMEBase::spinCorrelatedME2(pair<int,int> ij,
const SpinCorrelationTensor& c) const {
if ( matchboxAmplitude() ) {
if ( matchboxAmplitude()->treeAmplitudes() )
matchboxAmplitude()->prepareAmplitudes(this);
double res =
matchboxAmplitude()->spinCorrelatedME2(ij,c)*
me2Norm();
return res;
}
throw Exception()
<< "MatchboxMEBase::spinCorrelatedME2() expects a MatchboxAmplitude object.\n"
<< "Please check your setup." << Exception::abortnow;
return 0.;
}
void MatchboxMEBase::flushCaches() {
MEBase::flushCaches();
if ( matchboxAmplitude() )
matchboxAmplitude()->flushCaches();
for ( vector<Ptr<MatchboxReweightBase>::ptr>::iterator r =
reweights().begin(); r != reweights().end(); ++r ) {
(**r).flushCaches();
}
for ( vector<Ptr<MatchboxInsertionOperator>::ptr>::const_iterator v =
virtuals().begin(); v != virtuals().end(); ++v ) {
(**v).flushCaches();
}
}
void MatchboxMEBase::print(ostream& os) const {
os << "--- MatchboxMEBase setup -------------------------------------------------------\n";
os << " '" << name() << "' for subprocess:\n";
os << " ";
for ( PDVector::const_iterator pp = subProcess().legs.begin();
pp != subProcess().legs.end(); ++pp ) {
os << (**pp).PDGName() << " ";
if ( pp == subProcess().legs.begin() + 1 )
os << "-> ";
}
os << "\n";
os << " including " << (oneLoop() ? "" : "no ") << "virtual corrections";
if ( oneLoopNoBorn() )
os << " without Born contributions";
os << "\n";
if ( oneLoop() && !onlyOneLoop() ) {
os << " using insertion operators\n";
for ( vector<Ptr<MatchboxInsertionOperator>::ptr>::const_iterator v =
virtuals().begin(); v != virtuals().end(); ++v ) {
os << " '" << (**v).name() << "' with "
<< ((**v).isDR() ? "" : "C") << "DR/";
if ( (**v).isCS() )
os << "CS";
if ( (**v).isBDK() )
os << "BDK";
if ( (**v).isExpanded() )
os << "expanded";
os << " conventions\n";
}
}
os << "--------------------------------------------------------------------------------\n";
os << flush;
}
void MatchboxMEBase::printLastEvent(ostream& os) const {
os << "--- MatchboxMEBase last event information --------------------------------------\n";
os << " for matrix element '" << name() << "'\n";
os << " process considered:\n ";
int in = 0;
for ( cPDVector::const_iterator p = mePartonData().begin();
p != mePartonData().end(); ++p ) {
os << (**p).PDGName() << " ";
if ( ++in == 2 )
os << " -> ";
}
os << " kinematic environment as set by the XComb " << lastXCombPtr() << ":\n"
<< " sqrt(shat)/GeV = " << sqrt(lastSHat()/GeV2)
<< " x1 = " << lastX1() << " x2 = " << lastX2()
<< " alphaS = " << lastAlphaS() << "\n";
os << " momenta/GeV generated from random numbers\n ";
copy(lastXComb().lastRandomNumbers().begin(),
lastXComb().lastRandomNumbers().end(),ostream_iterator<double>(os," "));
os << ":\n ";
for ( vector<Lorentz5Momentum>::const_iterator p = meMomenta().begin();
p != meMomenta().end(); ++p ) {
os << (*p/GeV) << "\n ";
}
os << "last cross section/nb calculated was:\n "
<< (lastMECrossSection()/nanobarn) << " (pdf weight " << lastMEPDFWeight() << ")\n";
os << "--------------------------------------------------------------------------------\n";
os << flush;
}
void MatchboxMEBase::logGenerateKinematics(const double * r) const {
if ( !verbose() )
return;
generator()->log() << "'" << name() << "' generated kinematics\nfrom "
<< nDim() << " random numbers:\n";
copy(r,r+nDim(),ostream_iterator<double>(generator()->log()," "));
generator()->log() << "\n";
generator()->log() << "storing phase space information in XComb "
<< lastXCombPtr() << "\n";
generator()->log() << "generated phase space point (in GeV):\n";
vector<Lorentz5Momentum>::const_iterator pit = meMomenta().begin();
cPDVector::const_iterator dit = mePartonData().begin();
for ( ; pit != meMomenta().end() ; ++pit, ++dit )
generator()->log() << (**dit).PDGName() << " : "
<< (*pit/GeV) << "\n";
generator()->log() << "with x1 = " << lastX1() << " x2 = " << lastX2() << "\n"
<< "and Jacobian = " << jacobian() << " sHat/GeV2 = "
<< (lastSHat()/GeV2) << "\n" << flush;
}
void MatchboxMEBase::logSetScale() const {
if ( !verbose() )
return;
generator()->log() << "'" << name() << "' set scales using XComb " << lastXCombPtr() << ":\n"
<< "scale/GeV2 = " << (scale()/GeV2) << " xi_R = "
<< renormalizationScaleFactor() << " xi_F = "
<< factorizationScaleFactor() << "\n"
<< "alpha_s = " << lastAlphaS() << "\n" << flush;
}
void MatchboxMEBase::logPDFWeight() const {
if ( !verbose() )
return;
generator()->log() << "'" << name() << "' calculated pdf weight = "
<< lastMEPDFWeight() << " from XComb "
<< lastXCombPtr() << "\n"
<< "x1 = " << lastX1() << " (" << (mePartonData()[0]->coloured() ? "" : "not ") << "used) "
<< "x2 = " << lastX2() << " (" << (mePartonData()[1]->coloured() ? "" : "not ") << "used)\n"
<< flush;
}
void MatchboxMEBase::logME2() const {
if ( !verbose() )
return;
generator()->log() << "'" << name() << "' evaluated me2 using XComb "
<< lastXCombPtr() << "\n"
<< "and phase space point (in GeV):\n";
vector<Lorentz5Momentum>::const_iterator pit = meMomenta().begin();
cPDVector::const_iterator dit = mePartonData().begin();
for ( ; pit != meMomenta().end() ; ++pit, ++dit )
generator()->log() << (**dit).PDGName() << " : "
<< (*pit/GeV) << "\n";
generator()->log() << "with x1 = " << lastX1() << " x2 = " << lastX2() << "\n"
<< "sHat/GeV2 = " << (lastSHat()/GeV2)
<< " me2 = " << lastME2() << "\n" << flush;
}
void MatchboxMEBase::logDSigHatDR() const {
if ( !verbose() )
return;
generator()->log() << "'" << name() << "' evaluated cross section using XComb "
<< lastXCombPtr() << "\n"
<< "Jacobian = " << jacobian() << " sHat/GeV2 = "
<< (lastSHat()/GeV2) << " dsig/nb = "
<< (lastMECrossSection()/nanobarn) << "\n" << flush;
}
void MatchboxMEBase::cloneDependencies(const std::string& prefix) {
if ( phasespace() ) {
Ptr<MatchboxPhasespace>::ptr myPhasespace = phasespace()->cloneMe();
ostringstream pname;
pname << (prefix == "" ? fullName() : prefix) << "/" << myPhasespace->name();
if ( ! (generator()->preinitRegister(myPhasespace,pname.str()) ) )
throw InitException() << "Phasespace generator " << pname.str() << " already existing.";
myPhasespace->cloneDependencies(pname.str());
phasespace(myPhasespace);
}
theAmplitude = dynamic_ptr_cast<Ptr<MatchboxAmplitude>::ptr>(amplitude());
if ( matchboxAmplitude() ) {
Ptr<MatchboxAmplitude>::ptr myAmplitude = matchboxAmplitude()->cloneMe();
ostringstream pname;
pname << (prefix == "" ? fullName() : prefix) << "/" << myAmplitude->name();
if ( ! (generator()->preinitRegister(myAmplitude,pname.str()) ) )
throw InitException() << "Amplitude " << pname.str() << " already existing.";
myAmplitude->cloneDependencies(pname.str());
matchboxAmplitude(myAmplitude);
amplitude(myAmplitude);
matchboxAmplitude()->orderInGs(orderInAlphaS());
matchboxAmplitude()->orderInGem(orderInAlphaEW());
}
if ( scaleChoice() ) {
Ptr<MatchboxScaleChoice>::ptr myScaleChoice = scaleChoice()->cloneMe();
ostringstream pname;
pname << (prefix == "" ? fullName() : prefix) << "/" << myScaleChoice->name();
if ( ! (generator()->preinitRegister(myScaleChoice,pname.str()) ) )
throw InitException() << "Scale choice " << pname.str() << " already existing.";
scaleChoice(myScaleChoice);
}
for ( vector<Ptr<MatchboxReweightBase>::ptr>::iterator rw =
theReweights.begin(); rw != theReweights.end(); ++rw ) {
Ptr<MatchboxReweightBase>::ptr myReweight = (**rw).cloneMe();
ostringstream pname;
pname << (prefix == "" ? fullName() : prefix) << "/" << (**rw).name();
if ( ! (generator()->preinitRegister(myReweight,pname.str()) ) )
throw InitException() << "Reweight " << pname.str() << " already existing.";
myReweight->cloneDependencies(pname.str());
*rw = myReweight;
}
for ( vector<Ptr<MatchboxInsertionOperator>::ptr>::iterator v =
virtuals().begin(); v != virtuals().end(); ++v ) {
Ptr<MatchboxInsertionOperator>::ptr myIOP = (**v).cloneMe();
ostringstream pname;
pname << (prefix == "" ? fullName() : prefix) << "/" << (**v).name();
if ( ! (generator()->preinitRegister(myIOP,pname.str()) ) )
throw InitException() << "Insertion operator " << pname.str() << " already existing.";
*v = myIOP;
}
}
void MatchboxMEBase::prepareXComb(MatchboxXCombData& xc) const {
// fixme We need to pass on the partons from the xcmob here, not
// assuming one subprocess per matrix element
if ( phasespace() ) {
size_t nout = diagrams().front()->partons().size()-2;
xc.nDimPhasespace(phasespace()->nDim(nout));
}
if ( matchboxAmplitude() ) {
xc.nDimAmplitude(matchboxAmplitude()->nDimAdditional());
if ( matchboxAmplitude()->colourBasis() ) {
size_t cdim =
matchboxAmplitude()->colourBasis()->prepare(diagrams(),noCorrelations());
xc.colourBasisDim(cdim);
}
if ( matchboxAmplitude()->isExternal() ) {
xc.externalId(matchboxAmplitude()->externalId(diagrams().front()->partons()));
}
}
int insertionAdd = 0;
for ( vector<Ptr<MatchboxInsertionOperator>::ptr>::const_iterator v =
virtuals().begin(); v != virtuals().end(); ++v ) {
insertionAdd = max(insertionAdd,(**v).nDimAdditional());
}
xc.nDimInsertions(insertionAdd);
xc.nLight(getNLight());
for (size_t inlv=0; inlv<getNLightJetVec().size(); ++inlv)
xc.nLightJetVec(getNLightJetVec()[inlv]);
for (size_t inhv=0; inhv<getNHeavyJetVec().size(); ++inhv)
xc.nHeavyJetVec(getNHeavyJetVec()[inhv]);
for (size_t inlpv=0; inlpv<getNLightProtonVec().size(); ++inlpv)
xc.nLightProtonVec(getNLightProtonVec()[inlpv]);
xc.olpId(olpProcess());
if ( initVerbose() ) {
string fname = name() + ".diagrams";
ifstream test(fname.c_str());
if ( !test ) {
test.close();
ofstream out(fname.c_str());
for ( vector<Ptr<DiagramBase>::ptr>::const_iterator d = diagrams().begin();
d != diagrams().end(); ++d ) {
DiagramDrawer::drawDiag(out,dynamic_cast<const Tree2toNDiagram&>(**d));
out << "\n";
}
}
}
}
StdXCombPtr MatchboxMEBase::makeXComb(Energy newMaxEnergy, const cPDPair & inc,
tEHPtr newEventHandler,tSubHdlPtr newSubProcessHandler,
tPExtrPtr newExtractor, tCascHdlPtr newCKKW,
const PBPair & newPartonBins, tCutsPtr newCuts,
const DiagramVector & newDiagrams, bool mir,
const PartonPairVec&,
tStdXCombPtr newHead,
tMEPtr newME) {
if ( !newME )
newME = this;
Ptr<MatchboxXComb>::ptr xc =
new_ptr(MatchboxXComb(newMaxEnergy, inc,
newEventHandler, newSubProcessHandler,
newExtractor, newCKKW,
newPartonBins, newCuts, newME,
newDiagrams, mir,
newHead));
prepareXComb(*xc);
return xc;
}
StdXCombPtr MatchboxMEBase::makeXComb(tStdXCombPtr newHead,
const PBPair & newPartonBins,
const DiagramVector & newDiagrams,
tMEPtr newME) {
if ( !newME )
newME = this;
Ptr<MatchboxXComb>::ptr xc =
new_ptr(MatchboxXComb(newHead, newPartonBins, newME, newDiagrams));
prepareXComb(*xc);
return xc;
}
void MatchboxMEBase::persistentOutput(PersistentOStream & os) const {
os << theLastXComb << theFactory << thePhasespace
<< theAmplitude << theScaleChoice << theVirtuals
<< theReweights << theSubprocess << theOneLoop
<< theOneLoopNoBorn
<< epsilonSquarePoleHistograms << epsilonPoleHistograms
<< theOLPProcess << theNoCorrelations
<< theHavePDFs << checkedPDFs<<theDiagramWeightVerboseDown<<theDiagramWeightVerboseUp;
}
void MatchboxMEBase::persistentInput(PersistentIStream & is, int) {
is >> theLastXComb >> theFactory >> thePhasespace
>> theAmplitude >> theScaleChoice >> theVirtuals
>> theReweights >> theSubprocess >> theOneLoop
>> theOneLoopNoBorn
>> epsilonSquarePoleHistograms >> epsilonPoleHistograms
>> theOLPProcess >> theNoCorrelations
>> theHavePDFs >> checkedPDFs>>theDiagramWeightVerboseDown>>theDiagramWeightVerboseUp;
lastMatchboxXComb(theLastXComb);
}
void MatchboxMEBase::Init() {
static ClassDocumentation<MatchboxMEBase> documentation
("MatchboxMEBase is the base class for matrix elements "
"in the context of the matchbox NLO interface.");
}
IBPtr MatchboxMEBase::clone() const {
return new_ptr(*this);
}
IBPtr MatchboxMEBase::fullclone() const {
return new_ptr(*this);
}
void MatchboxMEBase::doinit() {
MEBase::doinit();
if ( !theAmplitude )
theAmplitude = dynamic_ptr_cast<Ptr<MatchboxAmplitude>::ptr>(amplitude());
if ( matchboxAmplitude() )
matchboxAmplitude()->init();
if ( phasespace() ) {
phasespace()->init();
}
if ( scaleChoice() ) {
scaleChoice()->init();
}
for ( vector<Ptr<MatchboxReweightBase>::ptr>::iterator rw =
theReweights.begin(); rw != theReweights.end(); ++rw ) {
(**rw).init();
}
for ( vector<Ptr<MatchboxInsertionOperator>::ptr>::iterator v =
virtuals().begin(); v != virtuals().end(); ++v ) {
(**v).init();
}
}
void MatchboxMEBase::bookMEoverDiaWeight(double x) const {
if (MEoverDiaWeight.size()==0){
theDiagramWeightVerboseDown=min(theDiagramWeightVerboseDown,x*0.9);
theDiagramWeightVerboseUp=max(theDiagramWeightVerboseUp,x*1.1);
}
map<double,double>::iterator bx =MEoverDiaWeight.upper_bound(x);
if ( bx == MEoverDiaWeight.end() ) {
return;
}
bx->second += 1.;
Nevents++;
if (int(Nevents)%1000==0){
ofstream out((RunDirectories::runStorage()+"/"+name()+"-MeoDiaW.dat").c_str());
int i=0;
double m=0.;
for ( map<double,double>::const_iterator bx = MEoverDiaWeight.begin();bx != MEoverDiaWeight.end(); ++bx,i++ ) {
out << " " << bx->first<<" "<<( bx->second/double(Nevents))<<"\n ";
m=max(m,bx->second/double(Nevents));
}
out.close();
ofstream gpout((RunDirectories::runStorage()+"/"+name()+"-MeoDiaW.gp").c_str());
gpout << "set terminal epslatex color solid\n"
<< "set output '" << name()<<"-MeoDiaW"<< "-plot.tex'\n"
<< "#set logscale x\n"
<< "set xrange [" << theDiagramWeightVerboseDown << ":" << theDiagramWeightVerboseUp << "]\n"
<< "set yrange [0.:"<<(m*0.95)<<"]\n"
<< "set xlabel '$log(ME/\\sum DiaW)$'\n"
<< "set size 0.7,0.7\n"
<< "plot 1 w lines lc rgbcolor \"#DDDDDD\" notitle, '" << name()<<"-MeoDiaW"
<< ".dat' with histeps lc rgbcolor \"#00AACC\" t '$"<<name()<<"$'";
gpout.close();
}
}
void MatchboxMEBase::doinitrun() {
MEBase::doinitrun();
if ( matchboxAmplitude() )
matchboxAmplitude()->initrun();
if ( phasespace() ) {
phasespace()->initrun();
}
if ( scaleChoice() ) {
scaleChoice()->initrun();
}
for ( vector<Ptr<MatchboxReweightBase>::ptr>::iterator rw =
theReweights.begin(); rw != theReweights.end(); ++rw ) {
(**rw).initrun();
}
for ( vector<Ptr<MatchboxInsertionOperator>::ptr>::iterator v =
virtuals().begin(); v != virtuals().end(); ++v ) {
(**v).initrun();
}
if ( factory()->verboseDia() ) {
for ( int k = 0; k < factory()->diagramWeightVerboseNBins() ; ++k ) {
MEoverDiaWeight[theDiagramWeightVerboseDown+
double(k)*(theDiagramWeightVerboseUp-
theDiagramWeightVerboseDown)
/double(factory()->diagramWeightVerboseNBins()) ] = 0.;
}
Nevents=0.;
ofstream out("DiagramWeights.sh");
out<<"P=$(pwd)"
<<"\ncd "<<RunDirectories::runStorage()
<<"\nrm -f DiagramWeights.tex"
<<"\n echo \"\\documentclass{article}\" >> DiagramWeights.tex"
<<"\n echo \"\\usepackage{amsmath,amsfonts,amssymb,graphicx,color}\" >> DiagramWeights.tex"
<<"\n echo \"\\usepackage[left=2cm,right=2cm,top=2cm,bottom=2cm]{geometry}\" >> DiagramWeights.tex"
<<"\n echo \"\\begin{document}\" >> DiagramWeights.tex"
<<"\n echo \"\\setlength{\\parindent}{0cm}\" >> DiagramWeights.tex"
<<"\n\n for i in $(ls *.gp | sed s/'\\.gp'//g) ; "
<<"\n do"
<<"\n echo \"\\input{\"\"$i\"-plot\"}\" >> DiagramWeights.tex"
<<"\n done"
<<"\n echo \"\\end{document}\" >> DiagramWeights.tex "
<<"\n for i in *.gp ; do "
<<"\n gnuplot $i "
<<"\n done "
<<"\n pdflatex DiagramWeights.tex \ncp DiagramWeights.pdf $P";
out.close();
}
}
void MatchboxMEBase::dofinish() {
MEBase::dofinish();
for ( map<cPDVector,AccuracyHistogram>::const_iterator
b = epsilonSquarePoleHistograms.begin();
b != epsilonSquarePoleHistograms.end(); ++b ) {
b->second.dump(factory()->poleData(),"epsilonSquarePoles-",b->first);
}
for ( map<cPDVector,AccuracyHistogram>::const_iterator
b = epsilonPoleHistograms.begin();
b != epsilonPoleHistograms.end(); ++b ) {
b->second.dump(factory()->poleData(),"epsilonPoles-",b->first);
}
}
// *** 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<MatchboxMEBase,MEBase>
describeHerwigMatchboxMEBase("Herwig::MatchboxMEBase", "Herwig.so");
diff --git a/MatrixElement/Matchbox/Base/MatchboxMEBase.h b/MatrixElement/Matchbox/Base/MatchboxMEBase.h
--- a/MatrixElement/Matchbox/Base/MatchboxMEBase.h
+++ b/MatrixElement/Matchbox/Base/MatchboxMEBase.h
@@ -1,1082 +1,1097 @@
// -*- C++ -*-
//
// MatchboxMEBase.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_MatchboxMEBase_H
#define HERWIG_MatchboxMEBase_H
//
// This is the declaration of the MatchboxMEBase class.
//
#include "ThePEG/MatrixElement/MEBase.h"
#include "Herwig++/MatrixElement/Matchbox/Utility/SpinCorrelationTensor.h"
#include "Herwig++/MatrixElement/Matchbox/Utility/Tree2toNGenerator.h"
#include "Herwig++/MatrixElement/Matchbox/Utility/MatchboxScaleChoice.h"
#include "Herwig++/MatrixElement/Matchbox/Utility/ProcessData.h"
#include "Herwig++/MatrixElement/Matchbox/Phasespace/MatchboxPhasespace.h"
#include "Herwig++/MatrixElement/Matchbox/Base/MatchboxAmplitude.h"
#include "Herwig++/MatrixElement/Matchbox/Base/MatchboxReweightBase.h"
#include "Herwig++/MatrixElement/Matchbox/Base/MatchboxMEBase.fh"
#include "Herwig++/MatrixElement/Matchbox/Dipoles/SubtractionDipole.fh"
#include "Herwig++/MatrixElement/Matchbox/InsertionOperators/MatchboxInsertionOperator.h"
#include "Herwig++/MatrixElement/Matchbox/MatchboxFactory.fh"
#include "Herwig++/MatrixElement/Matchbox/Utility/LastMatchboxXCombInfo.h"
#include "Herwig++/MatrixElement/Matchbox/Utility/MatchboxXComb.h"
namespace Herwig {
using namespace ThePEG;
/**
* \ingroup Matchbox
* \author Simon Platzer
*
* \brief MatchboxMEBase is the base class for matrix elements
* in the context of the matchbox NLO interface.
*
* @see \ref MatchboxMEBaseInterfaces "The interfaces"
* defined for MatchboxMEBase.
*/
class MatchboxMEBase:
public MEBase, public LastMatchboxXCombInfo {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
MatchboxMEBase();
/**
* The destructor.
*/
virtual ~MatchboxMEBase();
//@}
public:
/**
* Return the factory which produced this matrix element
*/
Ptr<MatchboxFactory>::tptr factory() const;
/**
* Set the factory which produced this matrix element
*/
void factory(Ptr<MatchboxFactory>::tptr f);
/** @name Subprocess and diagram information. */
//@{
/**
* Return the subprocess.
*/
const Process& subProcess() const { return theSubprocess; }
/**
* Access the subprocess.
*/
Process& subProcess() { return theSubprocess; }
/**
* Return the diagram generator.
*/
Ptr<Tree2toNGenerator>::tptr diagramGenerator() const;
/**
* Return the process data.
*/
Ptr<ProcessData>::tptr processData() const;
/**
* Return true, if this matrix element does not want to
* make use of mirroring processes; in this case all
* possible partonic subprocesses with a fixed assignment
* of incoming particles need to be provided through the diagrams
* added with the add(...) method.
*/
virtual bool noMirror () const { return true; }
/**
* Add all possible diagrams with the add() function.
*/
virtual void getDiagrams() const;
using MEBase::getDiagrams;
/**
* With the information previously supplied with the
* setKinematics(...) method, a derived class may optionally
* override this method to weight the given diagrams with their
* (although certainly not physical) relative probabilities.
*/
virtual Selector<DiagramIndex> diagrams(const DiagramVector &) const;
using MEBase::diagrams;
/**
* Return a Selector with possible colour geometries for the selected
* diagram weighted by their relative probabilities.
*/
virtual Selector<const ColourLines *>
colourGeometries(tcDiagPtr diag) const;
/**
+ * Return true, if this amplitude is capable of consistently filling
+ * the rho matrices for the spin correllations
+ */
+ virtual bool canFillRhoMatrix() const {
+ if ( matchboxAmplitude() )
+ return matchboxAmplitude()->canFillRhoMatrix();
+ return false;
+ }
+
+ /**
+ * construct the spin information for the interaction
+ */
+ virtual void constructVertex(tSubProPtr sub, const ColourLines* cl);
+
+ /**
* Return the order in \f$\alpha_S\f$ in which this matrix element
* is given.
*/
virtual unsigned int orderInAlphaS() const;
using MEBase::orderInAlphaS;
/**
* Return the order in \f$\alpha_{EM}\f$ in which this matrix
* element is given. Returns 0.
*/
virtual unsigned int orderInAlphaEW() const;
using MEBase::orderInAlphaEW;
/**
* Return true, if this amplitude already includes averaging over
* incoming parton's quantum numbers.
*/
virtual bool hasInitialAverage() const {
return matchboxAmplitude() ? matchboxAmplitude()->hasInitialAverage() : false;
}
/**
* Return true, if this amplitude already includes symmetry factors
* for identical outgoing particles.
*/
virtual bool hasFinalStateSymmetry() const {
return matchboxAmplitude() ? matchboxAmplitude()->hasFinalStateSymmetry() : false;
}
/**
* Return the number of light flavours, this matrix
* element is calculated for.
*/
virtual unsigned int getNLight() const;
/**
* Return the vector that contains the PDG ids of
* the light flavours, which are contained in the
* jet particle group.
*/
virtual vector<int> getNLightJetVec() const;
/**
* Return the vector that contains the PDG ids of
* the heavy flavours, which are contained in the
* jet particle group.
*/
virtual vector<int> getNHeavyJetVec() const;
/**
* Return the vector that contains the PDG ids of
* the light flavours, which are contained in the
* proton particle group.
*/
virtual vector<int> getNLightProtonVec() const;
/**
* Return true, if this matrix element is handled by a BLHA one-loop provider
*/
virtual bool isOLPTree() const {
return matchboxAmplitude() ? matchboxAmplitude()->isOLPTree() : false;
}
/**
* Return true, if this matrix element is handled by a BLHA one-loop provider
*/
virtual bool isOLPLoop() const {
return matchboxAmplitude() ? matchboxAmplitude()->isOLPLoop() : false;
}
/**
* Return true, if colour and spin correlated matrix elements should
* be ordered from the OLP
*/
virtual bool needsOLPCorrelators() const {
return matchboxAmplitude() ? matchboxAmplitude()->needsOLPCorrelators() : true;
}
/**
* Return the process index, if this is an OLP handled matrix element
*/
const vector<int>& olpProcess() const { return theOLPProcess; }
/**
* Set the process index, if this is an OLP handled matrix element
*/
void olpProcess(int pType, int id) {
if ( theOLPProcess.empty() )
theOLPProcess.resize(5,0);
theOLPProcess[pType] = id;
}
/**
* Return true, if this is a real emission matrix element which does
* not require colour correlators.
*/
bool noCorrelations() const {
return theNoCorrelations;
}
/**
* Indicate that this is a real emission matrix element which does
* not require colour correlators.
*/
void needsNoCorrelations() {
theNoCorrelations = true;
}
/**
* Indicate that this is a virtual matrix element which does
* require colour correlators.
*/
void needsCorrelations() {
theNoCorrelations = false;
}
//@}
/** @name Phasespace generation */
//@{
/**
* Return the phase space generator to be used.
*/
Ptr<MatchboxPhasespace>::tptr phasespace() const { return thePhasespace; }
/**
* Set the phase space generator to be used.
*/
void phasespace(Ptr<MatchboxPhasespace>::ptr ps) { thePhasespace = ps; }
/**
* Set the XComb object to be used in the next call to
* generateKinematics() and dSigHatDR().
*/
virtual void setXComb(tStdXCombPtr xc);
/**
* Return true, if the XComb steering this matrix element
* should keep track of the random numbers used to generate
* the last phase space point
*/
virtual bool keepRandomNumbers() const { return true; }
/**
* Generate incoming parton momenta. This default
* implementation performs the standard mapping
* from x1,x2 -> tau,y making 1/tau flat; incoming
* parton momenta are stored in meMomenta()[0,1],
* only massless partons are supported so far;
* return the Jacobian of the mapping
*/
double generateIncomingPartons(const double* r1, const double* r2);
/**
* Generate internal degrees of freedom given nDim() uniform random
* numbers in the interval ]0,1[. To help the phase space generator,
* the 'dSigHatDR' should be a smooth function of these numbers,
* although this is not strictly necessary. The return value should
* be true of the generation succeeded. If so the generated momenta
* should be stored in the meMomenta() vector. Derived classes
* must call this method once internal degrees of freedom are setup
* and finally return the result of this method.
*/
virtual bool generateKinematics(const double * r);
/**
* The number of internal degreed of freedom used in the matrix
* element.
*/
virtual int nDim() const;
/**
* The number of internal degrees of freedom used in the matrix
* element for generating a Born phase space point
*/
virtual int nDimBorn() const;
/**
* Return true, if this matrix element will generate momenta for the
* incoming partons itself. The matrix element is required to store
* the incoming parton momenta in meMomenta()[0,1]. No mapping in
* tau and y is performed by the PartonExtractor object, if a
* derived class returns true here. The phase space jacobian is to
* include a factor 1/(x1 x2).
*/
virtual bool haveX1X2() const {
return
(phasespace() ? phasespace()->haveX1X2() : false) ||
diagrams().front()->partons().size() == 3;
}
/**
* Return true, if this matrix element expects
* the incoming partons in their center-of-mass system
*/
virtual bool wantCMS() const {
return
(phasespace() ? phasespace()->wantCMS() : true) &&
diagrams().front()->partons().size() != 3; }
/**
* Return the meMomenta as generated at the last
* phase space point.
*/
const vector<Lorentz5Momentum>& lastMEMomenta() const { return meMomenta(); }
/**
* Access the meMomenta.
*/
vector<Lorentz5Momentum>& lastMEMomenta() { return meMomenta(); }
//@}
/** @name Scale choices, couplings and PDFs */
//@{
/**
* Set the scale choice object
*/
void scaleChoice(Ptr<MatchboxScaleChoice>::ptr sc) { theScaleChoice = sc; }
/**
* Return the scale choice object
*/
Ptr<MatchboxScaleChoice>::tptr scaleChoice() const { return theScaleChoice; }
/**
* Set scales and alphaS
*/
void setScale() const;
/**
* Return the scale associated with the phase space point provided
* by the last call to setKinematics().
*/
virtual Energy2 scale() const { return lastScale(); }
/**
* Return the renormalization scale for the last generated phasespace point.
*/
virtual Energy2 factorizationScale() const;
/**
* Get the factorization scale factor
*/
virtual double factorizationScaleFactor() const;
/**
* Return the (QCD) renormalization scale for the last generated phasespace point.
*/
virtual Energy2 renormalizationScale() const;
/**
* Get the renormalization scale factor
*/
virtual double renormalizationScaleFactor() const;
/**
* Return the QED renormalization scale for the last generated phasespace point.
*/
virtual Energy2 renormalizationScaleQED() const;
/**
* Set veto scales on the particles at the given
* SubProcess which has been generated using this
* matrix element.
*/
virtual void setVetoScales(tSubProPtr) const;
/**
* Return true, if fixed couplings are used.
*/
bool fixedCouplings() const;
/**
* Return true, if fixed couplings are used.
*/
bool fixedQEDCouplings() const;
/**
* Return the value of \f$\alpha_S\f$ associated with the phase
* space point provided by the last call to setKinematics(). This
* versions returns SM().alphaS(scale()).
*/
virtual double alphaS() const { return lastAlphaS(); }
/**
* Return the value of \f$\alpha_EM\f$ associated with the phase
* space point provided by the last call to setKinematics(). This
* versions returns SM().alphaEM(scale()).
*/
virtual double alphaEM() const { return lastAlphaEM(); }
/**
* Return true, if this matrix element provides the PDF
* weight for the first incoming parton itself.
*/
virtual bool havePDFWeight1() const;
/**
* Return true, if this matrix element provides the PDF
* weight for the second incoming parton itself.
*/
virtual bool havePDFWeight2() const;
/**
* Set the PDF weight.
*/
void getPDFWeight(Energy2 factorizationScale = ZERO) const;
/**
* Supply the PDF weight for the first incoming parton.
*/
double pdf1(Energy2 factorizationScale = ZERO,
double xEx = 1.) const;
/**
* Supply the PDF weight for the second incoming parton.
*/
double pdf2(Energy2 factorizationScale = ZERO,
double xEx = 1.) const;
//@}
/** @name Amplitude information and matrix element evaluation */
//@{
/**
* Return the amplitude.
*/
Ptr<MatchboxAmplitude>::tptr matchboxAmplitude() const { return theAmplitude; }
/**
* Set the amplitude.
*/
void matchboxAmplitude(Ptr<MatchboxAmplitude>::ptr amp) { theAmplitude = amp; }
/**
* Return the matrix element for the kinematical configuation
* previously provided by the last call to setKinematics(), suitably
* scaled by sHat() to give a dimension-less number.
*/
virtual double me2() const;
/**
* Return the matrix element for the kinematical configuation
* previously provided by the last call to setKinematics(), suitably
* scaled by sHat() to give a dimension-less number.
*/
virtual double largeNME2(Ptr<ColourBasis>::tptr largeNBasis) const;
/**
* Return the symmetry factor for identical final state particles.
*/
virtual double finalStateSymmetry() const;
/**
* Return the normalizing factor for the matrix element averaged
* over quantum numbers and including running couplings.
*/
double me2Norm(unsigned int addAlphaS = 0) const;
/**
* Return the matrix element squared differential in the variables
* given by the last call to generateKinematics().
*/
virtual CrossSection dSigHatDR() const;
//@}
/** @name One-loop corrections */
//@{
/**
* Return the one-loop/tree interference.
*/
virtual double oneLoopInterference() const;
/**
* Return true, if this matrix element is capable of calculating
* one-loop (QCD) corrections.
*/
virtual bool haveOneLoop() const;
/**
* Return true, if this matrix element only provides
* one-loop (QCD) corrections.
*/
virtual bool onlyOneLoop() const;
/**
* Return true, if the amplitude is DRbar renormalized, otherwise
* MSbar is assumed.
*/
virtual bool isDRbar() const;
/**
* Return true, if one loop corrections have been calculated in
* dimensional reduction. Otherwise conventional dimensional
* regularization is assumed. Note that renormalization is always
* assumed to be MSbar.
*/
virtual bool isDR() const;
/**
* Return true, if one loop corrections are given in the conventions
* of the integrated dipoles.
*/
virtual bool isCS() const;
/**
* Return true, if one loop corrections are given in the conventions
* of BDK.
*/
virtual bool isBDK() const;
/**
* Return true, if one loop corrections are given in the conventions
* of everything expanded.
*/
virtual bool isExpanded() const;
/**
* Return the value of the dimensional regularization
* parameter. Note that renormalization scale dependence is fully
* restored in DipoleIOperator.
*/
virtual Energy2 mu2() const;
/**
* If defined, return the coefficient of the pole in epsilon^2
*/
virtual double oneLoopDoublePole() const;
/**
* If defined, return the coefficient of the pole in epsilon
*/
virtual double oneLoopSinglePole() const;
/**
* Return true, if cancellationn of epsilon poles should be checked.
*/
bool checkPoles() const;
/**
* Simple histogram for accuracy checks
*/
struct AccuracyHistogram {
/**
* The lower bound
*/
double lower;
/**
* The upper bound
*/
double upper;
/**
* The bins, indexed by upper bound.
*/
map<double,double> bins;
/**
* The number of points of same sign
*/
unsigned long sameSign;
/**
* The number of points of opposite sign
*/
unsigned long oppositeSign;
/**
* The number of points being nan or inf
*/
unsigned long nans;
/**
* The overflow
*/
unsigned long overflow;
/**
* The underflow
*/
unsigned long underflow;
/**
* Constructor
*/
AccuracyHistogram(double low = -40.,
double up = 0.,
unsigned int nbins = 80);
/**
* Book two values to be checked for numerical compatibility
*/
void book(double a, double b);
/**
* Write to file.
*/
void dump(const std::string& folder, const std::string& prefix,
const cPDVector& proc) const;
/**
* Write to persistent ostream
*/
void persistentOutput(PersistentOStream&) const;
/**
* Read from persistent istream
*/
void persistentInput(PersistentIStream&);
};
/**
* Perform the check of epsilon pole cancellation.
*/
void logPoles() const;
/**
* Return the virtual corrections
*/
const vector<Ptr<MatchboxInsertionOperator>::ptr>& virtuals() const {
return theVirtuals;
}
/**
* Return the virtual corrections
*/
vector<Ptr<MatchboxInsertionOperator>::ptr>& virtuals() {
return theVirtuals;
}
/**
* Instruct this matrix element to include one-loop corrections
*/
void doOneLoop() { theOneLoop = true; }
/**
* Return true, if this matrix element includes one-loop corrections
*/
bool oneLoop() const { return theOneLoop; }
/**
* Instruct this matrix element to include one-loop corrections but
* no Born contributions
*/
void doOneLoopNoBorn() { theOneLoop = true; theOneLoopNoBorn = true; }
/**
* Return true, if this matrix element includes one-loop corrections
* but no Born contributions
*/
bool oneLoopNoBorn() const { return theOneLoopNoBorn || onlyOneLoop(); }
//@}
/** @name Dipole subtraction */
//@{
/**
* If this matrix element is considered a real
* emission matrix element, return all subtraction
* dipoles needed given a set of subtraction terms
* and underlying Born matrix elements to choose
* from.
*/
vector<Ptr<SubtractionDipole>::ptr>
getDipoles(const vector<Ptr<SubtractionDipole>::ptr>&,
const vector<Ptr<MatchboxMEBase>::ptr>&) const;
/**
* If this matrix element is considered a real emission matrix
* element, but actually neglecting a subclass of the contributing
* diagrams, return true if the given emitter-emission-spectator
* configuration should not be considered when setting up
* subtraction dipoles.
*/
virtual bool noDipole(int,int,int) const { return false; }
/**
* If this matrix element is considered an underlying Born matrix
* element in the context of a subtracted real emission, but
* actually neglecting a subclass of the contributing diagrams,
* return true if the given emitter-spectator configuration
* should not be considered when setting up subtraction dipoles.
*/
virtual bool noDipole(int,int) const { return false; }
/**
* Return the colour correlated matrix element squared with
* respect to the given two partons as appearing in mePartonData(),
* suitably scaled by sHat() to give a dimension-less number.
*/
virtual double colourCorrelatedME2(pair<int,int>) const;
/**
* Return the colour correlated matrix element squared in the
* large-N approximation with respect to the given two partons as
* appearing in mePartonData(), suitably scaled by sHat() to give a
* dimension-less number.
*/
virtual double largeNColourCorrelatedME2(pair<int,int> ij,
Ptr<ColourBasis>::tptr largeNBasis) const;
/**
* Return the colour and spin correlated matrix element squared for
* the gluon indexed by the first argument using the given
* correlation tensor.
*/
virtual double spinColourCorrelatedME2(pair<int,int> emitterSpectator,
const SpinCorrelationTensor& c) const;
/**
* Return the spin correlated matrix element squared for
* the vector boson indexed by the first argument using the given
* correlation tensor.
*/
virtual double spinCorrelatedME2(pair<int,int> emitterSpectator,
const SpinCorrelationTensor& c) const;
//@}
/** @name Caching and diagnostic information */
//@{
/**
* Inform this matrix element that a new phase space
* point is about to be generated, so all caches should
* be flushed.
*/
virtual void flushCaches();
/**
* Return true, if verbose
*/
bool verbose() const;
/**
* Return true, if verbose
*/
bool initVerbose() const;
/**
* Dump the setup to an ostream
*/
void print(ostream&) const;
/**
* Print debug information on the last event
*/
virtual void printLastEvent(ostream&) const;
/**
* Write out diagnostic information for
* generateKinematics
*/
void logGenerateKinematics(const double * r) const;
/**
* Write out diagnostic information for
* setting scales
*/
void logSetScale() const;
/**
* Write out diagnostic information for
* pdf evaluation
*/
void logPDFWeight() const;
/**
* Write out diagnostic information for
* me2 evaluation
*/
void logME2() const;
/**
* Write out diagnostic information
* for dsigdr evaluation
*/
void logDSigHatDR() const;
//@}
/** @name Reweight objects */
//@{
/**
* Insert a reweight object
*/
void addReweight(Ptr<MatchboxReweightBase>::ptr rw) { theReweights.push_back(rw); }
/**
* Return the reweights
*/
const vector<Ptr<MatchboxReweightBase>::ptr>& reweights() const { return theReweights; }
/**
* Access the reweights
*/
vector<Ptr<MatchboxReweightBase>::ptr>& reweights() { return theReweights; }
//@}
/** @name Methods used to setup MatchboxMEBase objects */
//@{
/**
* Return true if this object needs to be initialized before all
* other objects (except those for which this function also returns
* true). This default version always returns false, but subclasses
* may override it to return true.
*/
virtual bool preInitialize() const { return true; }
/**
* Clone this matrix element.
*/
Ptr<MatchboxMEBase>::ptr cloneMe() const {
return dynamic_ptr_cast<Ptr<MatchboxMEBase>::ptr>(clone());
}
/**
* Clone the dependencies, using a given prefix.
*/
void cloneDependencies(const std::string& prefix = "");
/**
* Prepare an xcomb
*/
void prepareXComb(MatchboxXCombData&) const;
/**
* For the given event generation setup return a xcomb object
* appropriate to this matrix element.
*/
virtual StdXCombPtr makeXComb(Energy newMaxEnergy, const cPDPair & inc,
tEHPtr newEventHandler,tSubHdlPtr newSubProcessHandler,
tPExtrPtr newExtractor, tCascHdlPtr newCKKW,
const PBPair & newPartonBins, tCutsPtr newCuts,
const DiagramVector & newDiagrams, bool mir,
const PartonPairVec& allPBins,
tStdXCombPtr newHead = tStdXCombPtr(),
tMEPtr newME = tMEPtr());
/**
* For the given event generation setup return a dependent xcomb object
* appropriate to this matrix element.
*/
virtual StdXCombPtr makeXComb(tStdXCombPtr newHead,
const PBPair & newPartonBins,
const DiagramVector & newDiagrams,
tMEPtr newME = tMEPtr());
//@}
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();
/**
* 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 factory which produced this matrix element
*/
Ptr<MatchboxFactory>::tptr theFactory;
/**
* The phase space generator to be used.
*/
Ptr<MatchboxPhasespace>::ptr thePhasespace;
/**
* The amplitude to be used
*/
Ptr<MatchboxAmplitude>::ptr theAmplitude;
/**
* The scale choice object
*/
Ptr<MatchboxScaleChoice>::ptr theScaleChoice;
/**
* The virtual corrections.
*/
vector<Ptr<MatchboxInsertionOperator>::ptr> theVirtuals;
/**
* A vector of reweight objects the sum of which
* should be applied to reweight this matrix element
*/
vector<Ptr<MatchboxReweightBase>::ptr> theReweights;
private:
/**
* The subprocess to be considered.
*/
Process theSubprocess;
/**
* True, if this matrix element includes one-loop corrections
*/
bool theOneLoop;
/**
* True, if this matrix element includes one-loop corrections
* but no Born contributions
*/
bool theOneLoopNoBorn;
/**
* The process index, if this is an OLP handled matrix element
*/
vector<int> theOLPProcess;
/**
* Histograms of epsilon^2 pole cancellation
*/
mutable map<cPDVector,AccuracyHistogram> epsilonSquarePoleHistograms;
/**
* Histograms of epsilon pole cancellation
*/
mutable map<cPDVector,AccuracyHistogram> epsilonPoleHistograms;
/**
* True, if this is a real emission matrix element which does
* not require colour correlators.
*/
bool theNoCorrelations;
/**
* Flag which pdfs should be included.
*/
mutable pair<bool,bool> theHavePDFs;
/**
* True, if already checked for which PDFs to include.
*/
mutable bool checkedPDFs;
/**
* Diagnostic Diagram for TreePhaseSpace
*/
void bookMEoverDiaWeight(double x) const;
mutable map<double,double > MEoverDiaWeight;
mutable int Nevents;
/**
* Range of diagram weight verbosity
*/
mutable double theDiagramWeightVerboseDown, theDiagramWeightVerboseUp;
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MatchboxMEBase & operator=(const MatchboxMEBase &);
};
inline PersistentOStream& operator<<(PersistentOStream& os,
const MatchboxMEBase::AccuracyHistogram& h) {
h.persistentOutput(os);
return os;
}
inline PersistentIStream& operator>>(PersistentIStream& is,
MatchboxMEBase::AccuracyHistogram& h) {
h.persistentInput(is);
return is;
}
}
#endif /* HERWIG_MatchboxMEBase_H */
diff --git a/MatrixElement/Matchbox/Dipoles/SubtractionDipole.cc b/MatrixElement/Matchbox/Dipoles/SubtractionDipole.cc
--- a/MatrixElement/Matchbox/Dipoles/SubtractionDipole.cc
+++ b/MatrixElement/Matchbox/Dipoles/SubtractionDipole.cc
@@ -1,1183 +1,1190 @@
// -*- C++ -*-
//
// SubtractionDipole.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 SubtractionDipole class.
//
#include "SubtractionDipole.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/RefVector.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Repository/Repository.h"
#include "ThePEG/StandardModel/StandardModelBase.h"
#include "ThePEG/Utilities/Rebinder.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDF/PartonBin.h"
#include "ThePEG/PDF/PartonExtractor.h"
#include "Herwig++/MatrixElement/Matchbox/Phasespace/TildeKinematics.h"
#include "Herwig++/MatrixElement/Matchbox/Phasespace/InvertedTildeKinematics.h"
#include "Herwig++/MatrixElement/Matchbox/MatchboxFactory.h"
#include <iterator>
using std::ostream_iterator;
using namespace Herwig;
SubtractionDipole::SubtractionDipole()
: MEBase(), theSplitting(false), theApply(true), theSubtractionTest(false),
theIgnoreCuts(false),
theRealEmitter(-1), theRealEmission(-1), theRealSpectator(-1),
theBornEmitter(-1), theBornSpectator(-1),
theRealShowerSubtraction(false), theVirtualShowerSubtraction(false),
theLoopSimSubtraction(false), theRealEmissionScales(false) {}
SubtractionDipole::~SubtractionDipole() {}
void SubtractionDipole::clearBookkeeping() {
theRealEmitter = -1;
theRealEmission = -1;
theRealSpectator = -1;
theBornEmitter = -1;
theBornSpectator = -1;
theMergingMap.clear();
theSplittingMap.clear();
theIndexMap.clear();
theUnderlyingBornDiagrams.clear();
theRealEmissionDiagrams.clear();
}
void SubtractionDipole::setupBookkeeping(const map<Ptr<DiagramBase>::ptr,SubtractionDipole::MergeInfo>& mergeInfo) {
theMergingMap.clear();
theSplittingMap.clear();
theUnderlyingBornDiagrams.clear();
theRealEmissionDiagrams.clear();
int xemitter = -1;
int xspectator = -1;
map<int,int> mergeLegs;
map<int,int> remapLegs;
map<int,int> realBornMap;
map<int,int> bornRealMap;
for ( map<Ptr<DiagramBase>::ptr,MergeInfo>::const_iterator mit = mergeInfo.begin();
mit != mergeInfo.end(); ++mit ) {
DiagramVector::const_iterator bd =
theUnderlyingBornME->diagrams().end();
map<int,int> theRemapLegs;
for ( DiagramVector::const_iterator b =
theUnderlyingBornME->diagrams().begin();
b != theUnderlyingBornME->diagrams().end(); ++b )
if ( mit->second.diagram->isSame(*b,theRemapLegs) ) {
bd = b; break;
}
// no underlying Born
if ( bd == theUnderlyingBornME->diagrams().end() )
continue;
if ( xemitter == -1 ) {
xemitter = mit->second.emitter;
mergeLegs = mit->second.mergeLegs;
remapLegs = theRemapLegs;
assert(remapLegs.find(xemitter) != remapLegs.end());
xemitter = remapLegs[xemitter];
// work out the leg remapping real -> born
for ( map<int,int>::const_iterator k = mergeLegs.begin();
k != mergeLegs.end(); ++k ) {
assert(remapLegs.find(k->second) != remapLegs.end());
realBornMap[k->first] = remapLegs[k->second];
}
// work out the leg remapping born -> real
for ( map<int,int>::const_iterator k = realBornMap.begin();
k != realBornMap.end(); ++k ) {
bornRealMap[k->second] = k->first;
}
// work out the spectator
assert(mergeLegs.find(realSpectator()) != mergeLegs.end());
assert(remapLegs.find(mergeLegs[realSpectator()]) != remapLegs.end());
xspectator = realBornMap[realSpectator()];
}
RealEmissionKey realKey = realEmissionKey((*mit->first).partons(),realEmitter(),realEmission(),realSpectator());
UnderlyingBornKey bornKey = underlyingBornKey((**bd).partons(),xemitter,xspectator);
if ( theMergingMap.find(realKey) == theMergingMap.end() )
theMergingMap.insert(make_pair(realKey,make_pair(bornKey,realBornMap)));
RealEmissionInfo realInfo = make_pair(realKey,bornRealMap);
bool gotit = false;
typedef multimap<UnderlyingBornKey,RealEmissionInfo>::const_iterator spIterator;
pair<spIterator,spIterator> range = theSplittingMap.equal_range(bornKey);
for ( ; range.first != range.second; ++range.first )
if ( range.first->second == realInfo ) {
gotit = true;
break;
}
if ( !gotit ) {
theSplittingMap.insert(make_pair(bornKey,realInfo));
theUnderlyingBornDiagrams[process(realKey)].push_back(*bd);
theRealEmissionDiagrams[process(bornKey)].push_back(mit->first);
}
}
if ( theSplittingMap.empty() )
return;
theIndexMap.clear();
for ( multimap<UnderlyingBornKey,RealEmissionInfo>::const_iterator s =
theSplittingMap.begin(); s != theSplittingMap.end(); ++s ) {
theIndexMap[process(s->first)] = make_pair(emitter(s->first),spectator(s->first));
}
}
void SubtractionDipole::subtractionBookkeeping() {
/*
if ( theMergingMap.empty() )
setupBookkeeping();
*/
assert(!theMergingMap.empty());
lastRealEmissionKey =
realEmissionKey(lastHeadXComb().mePartonData(),realEmitter(),realEmission(),realSpectator());
map<RealEmissionKey,UnderlyingBornInfo>::const_iterator k =
theMergingMap.find(lastRealEmissionKey);
if ( k == theMergingMap.end() ) {
theApply = false;
return;
}
theApply = true;
lastUnderlyingBornKey = k->second.first;
bornEmitter(emitter(lastUnderlyingBornKey));
bornSpectator(spectator(lastUnderlyingBornKey));
}
void SubtractionDipole::splittingBookkeeping() {
/*
if ( theMergingMap.empty() )
setupBookkeeping();
*/
assert(!theMergingMap.empty());
map<cPDVector,pair<int,int> >::const_iterator esit =
theIndexMap.find(lastHeadXComb().mePartonData());
if ( esit == theIndexMap.end() ) {
theApply = false;
return;
}
theApply = true;
pair<int,int> es = esit->second;
bornEmitter(es.first);
bornSpectator(es.second);
lastUnderlyingBornKey = underlyingBornKey(lastHeadXComb().mePartonData(),bornEmitter(),bornSpectator());
typedef multimap<UnderlyingBornKey,RealEmissionInfo>::const_iterator spit;
pair<spit,spit> kr = theSplittingMap.equal_range(lastUnderlyingBornKey);
assert(kr.first != kr.second);
lastRealEmissionInfo = kr.first;
for ( ; lastRealEmissionInfo != kr.second; ++lastRealEmissionInfo )
if ( process(lastRealEmissionInfo->second.first) == lastXComb().mePartonData() )
break;
assert(lastRealEmissionInfo != kr.second);
lastRealEmissionKey = lastRealEmissionInfo->second.first;
realEmitter(emitter(lastRealEmissionKey));
realEmission(emission(lastRealEmissionKey));
realSpectator(spectator(lastRealEmissionKey));
}
StdXCombPtr SubtractionDipole::makeXComb(Energy newMaxEnergy, const cPDPair & inc,
tEHPtr newEventHandler,tSubHdlPtr newSubProcessHandler,
tPExtrPtr newExtractor, tCascHdlPtr newCKKW,
const PBPair & newPartonBins, tCutsPtr newCuts,
const DiagramVector & newDiagrams, bool mir,
const PartonPairVec& allBins,
tStdXCombPtr newHead,
tMEPtr newME) {
if ( !newME )
newME = this;
if ( !splitting() ) {
return
underlyingBornME()->makeXComb(newMaxEnergy, inc,
newEventHandler, newSubProcessHandler,
newExtractor, newCKKW,
newPartonBins, newCuts,
newDiagrams, mir, allBins,
newHead, newME);
}
return
realEmissionME()->makeXComb(newMaxEnergy, inc,
newEventHandler, newSubProcessHandler,
newExtractor, newCKKW,
newPartonBins, newCuts,
newDiagrams, mir, allBins,
newHead, newME);
}
StdXCombPtr SubtractionDipole::makeXComb(tStdXCombPtr newHead,
const PBPair & newPartonBins,
const DiagramVector & newDiagrams,
tMEPtr newME) {
if ( !newME )
newME = this;
if ( !splitting() ) {
return
underlyingBornME()->makeXComb(newHead, newPartonBins,
newDiagrams, newME);
}
return
realEmissionME()->makeXComb(newHead, newPartonBins,
newDiagrams, newME);
}
StdXCombPtr SubtractionDipole::makeBornXComb(tStdXCombPtr realXC) {
const cPDVector& proc = const_cast<const StandardXComb&>(*realXC).mePartonData();
lastRealEmissionKey =
realEmissionKey(proc,realEmitter(),realEmission(),realSpectator());
map<RealEmissionKey,UnderlyingBornInfo>::const_iterator k =
theMergingMap.find(lastRealEmissionKey);
if ( k == theMergingMap.end() )
return StdXCombPtr();
PartonPairVec pbs = realXC->pExtractor()->getPartons(realXC->maxEnergy(),
realXC->particles(),
*(realXC->cuts()));
DiagramVector bornDiags = underlyingBornDiagrams(proc);
assert(!bornDiags.empty());
PartonPairVec::iterator ppit = pbs.begin();
for ( ; ppit != pbs.end(); ++ppit ) {
if ( ppit->first->parton() == bornDiags.front()->partons()[0] &&
ppit->second->parton() == bornDiags.front()->partons()[1] )
break;
}
assert(ppit != pbs.end());
return
underlyingBornME()->makeXComb(realXC,*ppit,bornDiags,this);
}
vector<StdXCombPtr> SubtractionDipole::makeRealXCombs(tStdXCombPtr bornXC) {
const cPDVector& proc = const_cast<const StandardXComb&>(*bornXC).mePartonData();
map<cPDVector,pair<int,int> >::const_iterator esit = theIndexMap.find(proc);
if ( esit == theIndexMap.end() )
return vector<StdXCombPtr>();
pair<int,int> es = esit->second;
bornEmitter(es.first);
bornSpectator(es.second);
lastUnderlyingBornKey = underlyingBornKey(proc,bornEmitter(),bornSpectator());
if ( theSplittingMap.find(lastUnderlyingBornKey) == theSplittingMap.end() )
return vector<StdXCombPtr>();
PartonPairVec pbs = bornXC->pExtractor()->getPartons(bornXC->maxEnergy(),
bornXC->particles(),
*(bornXC->cuts()));
DiagramVector realDiags = realEmissionDiagrams(proc);
assert(!realDiags.empty());
vector<StdXCombPtr> res;
map<cPDVector,DiagramVector> realProcs;
for ( MEBase::DiagramVector::const_iterator d = realDiags.begin();
d != realDiags.end(); ++d ) {
realProcs[(**d).partons()].push_back(*d);
}
for ( map<cPDVector,DiagramVector>::const_iterator pr =
realProcs.begin(); pr != realProcs.end(); ++pr ) {
PartonPairVec::iterator ppit = pbs.begin();
for ( ; ppit != pbs.end(); ++ppit ) {
if ( ppit->first->parton() == pr->second.front()->partons()[0] &&
ppit->second->parton() == pr->second.front()->partons()[1] )
break;
}
assert(ppit != pbs.end());
StdXCombPtr rxc =
realEmissionME()->makeXComb(bornXC,*ppit,pr->second,this);
res.push_back(rxc);
}
return res;
}
const MEBase::DiagramVector& SubtractionDipole::underlyingBornDiagrams(const cPDVector& real) const {
static DiagramVector empty;
map<cPDVector,DiagramVector>::const_iterator k = theUnderlyingBornDiagrams.find(real);
if (k == theUnderlyingBornDiagrams.end() )
return empty;
return k->second;
}
const MEBase::DiagramVector& SubtractionDipole::realEmissionDiagrams(const cPDVector& born) const {
static DiagramVector empty;
map<cPDVector,DiagramVector>::const_iterator k = theRealEmissionDiagrams.find(born);
if ( k == theRealEmissionDiagrams.end() )
return empty;
return k->second;
}
void SubtractionDipole::getDiagrams() const {
if ( splitting() ) {
realEmissionME()->diagrams();
useDiagrams(realEmissionME());
} else {
underlyingBornME()->diagrams();
useDiagrams(underlyingBornME());
}
}
Selector<MEBase::DiagramIndex> SubtractionDipole::diagrams(const DiagramVector & dv) const {
Ptr<MatchboxMEBase>::tcptr me =
splitting() ?
realEmissionME() :
underlyingBornME();
if ( me->phasespace() ) {
me->phasespace()->setXComb(lastXCombPtr());
me->phasespace()->fillDiagramWeights();
}
return
me->diagrams(dv);
}
Selector<const ColourLines *>
SubtractionDipole::colourGeometries(tcDiagPtr diag) const {
return
splitting() ?
realEmissionME()->colourGeometries(diag) :
underlyingBornME()->colourGeometries(diag);
}
const ColourLines &
SubtractionDipole::selectColourGeometry(tcDiagPtr diag) const {
return
splitting() ?
realEmissionME()->selectColourGeometry(diag) :
underlyingBornME()->selectColourGeometry(diag);
}
void SubtractionDipole::flushCaches() {
theUnderlyingBornME->flushCaches();
theRealEmissionME->flushCaches();
for ( vector<Ptr<MatchboxReweightBase>::ptr>::iterator r =
reweights().begin(); r != reweights().end(); ++r ) {
(**r).flushCaches();
}
}
void SubtractionDipole::setXComb(tStdXCombPtr xc) {
if ( !xc ) {
theApply = false;
return;
} else {
theApply = true;
}
lastMatchboxXComb(xc);
MEBase::setXComb(xc);
if ( splitting() ) {
realEmissionME()->setXComb(xc);
underlyingBornME()->setXComb(xc->head());
splittingBookkeeping();
} else {
realEmissionME()->setXComb(xc->head());
underlyingBornME()->setXComb(xc);
subtractionBookkeeping();
}
if ( !apply() )
return;
}
void SubtractionDipole::setKinematics() {
MEBase::setKinematics();
if ( splitting() )
realEmissionME()->setKinematics();
else
underlyingBornME()->setKinematics();
}
bool SubtractionDipole::generateKinematics(const double * r) {
if ( lastXCombPtr()->kinematicsGenerated() )
return true;
if ( splitting() ) {
if ( !generateRadiationKinematics(r) )
return false;
realEmissionME()->lastXCombPtr()->setIncomingPartons();
realEmissionME()->setScale();
double jac = jacobian();
jac *= pow(underlyingBornME()->lastXComb().lastSHat() / realEmissionME()->lastXComb().lastSHat(),
realEmissionME()->lastXComb().mePartonData().size()-4.);
jacobian(jac);
assert(lastXCombPtr() == realEmissionME()->lastXCombPtr());
lastXCombPtr()->didGenerateKinematics();
return true;
}
if ( !generateTildeKinematics() )
return false;
underlyingBornME()->setScale();
assert(lastXCombPtr() == underlyingBornME()->lastXCombPtr());
underlyingBornME()->lastXCombPtr()->setIncomingPartons();
lastXCombPtr()->didGenerateKinematics();
return true;
}
int SubtractionDipole::nDim() const {
if ( !splitting() )
return underlyingBornME()->nDim();
return underlyingBornME()->nDim() + nDimRadiation();
}
void SubtractionDipole::clearKinematics() {
MEBase::clearKinematics();
if ( splitting() )
realEmissionME()->clearKinematics();
else
underlyingBornME()->clearKinematics();
}
void SubtractionDipole::tildeKinematics(Ptr<TildeKinematics>::tptr tk) {
theTildeKinematics = tk;
}
bool SubtractionDipole::generateTildeKinematics() {
assert(!splitting());
if ( !tildeKinematics() ) {
jacobian(0.0);
return false;
}
theTildeKinematics->prepare(lastHeadXCombPtr(),lastXCombPtr());
if ( !theTildeKinematics->doMap() ) {
jacobian(0.0);
return false;
}
theLastSubtractionScale = theTildeKinematics->lastScale();
theLastSubtractionPt = theTildeKinematics->lastPt();
theLastSubtractionZ = theTildeKinematics->lastZ();
meMomenta().resize(lastHeadXComb().meMomenta().size() - 1);
assert(mergingMap().find(lastRealEmissionKey) != mergingMap().end());
map<int,int>& trans = theMergingMap[lastRealEmissionKey].second;
int n = lastHeadXComb().meMomenta().size();
for ( int k = 0; k < n; ++k ) {
if ( k == realEmitter() || k == realEmission() || k == realSpectator() )
continue;
meMomenta()[trans[k]] = lastHeadXComb().meMomenta()[k];
if ( theTildeKinematics->doesTransform() && k > 1 )
meMomenta()[trans[k]] = theTildeKinematics->transform(meMomenta()[trans[k]]);
}
meMomenta()[bornEmitter()] = tildeKinematics()->bornEmitterMomentum();
meMomenta()[bornSpectator()] = tildeKinematics()->bornSpectatorMomentum();
cPDVector::const_iterator pd = mePartonData().begin();
vector<Lorentz5Momentum>::iterator p = meMomenta().begin();
for ( ; pd != mePartonData().end(); ++pd, ++p ) {
p->setMass((**pd).mass());
p->rescaleRho();
}
jacobian(realEmissionME()->lastXComb().jacobian());
logGenerateTildeKinematics();
return true;
}
void SubtractionDipole::invertedTildeKinematics(Ptr<InvertedTildeKinematics>::tptr itk) {
theInvertedTildeKinematics = itk;
}
int SubtractionDipole::nDimRadiation() const {
return invertedTildeKinematics() ?
invertedTildeKinematics()->nDimRadiation() :
0;
}
bool SubtractionDipole::generateRadiationKinematics(const double * r) {
assert(splitting());
if ( !invertedTildeKinematics() ) {
jacobian(0.0);
return false;
}
theInvertedTildeKinematics->prepare(lastXCombPtr(),lastHeadXCombPtr());
if ( !theInvertedTildeKinematics->doMap(r) ) {
jacobian(0.0);
return false;
}
theLastSplittingScale = theInvertedTildeKinematics->lastScale();
theLastSplittingPt = theInvertedTildeKinematics->lastPt();
theLastSplittingZ = theInvertedTildeKinematics->lastZ();
meMomenta().resize(lastHeadXComb().meMomenta().size() + 1);
assert(splittingMap().find(lastUnderlyingBornKey) != splittingMap().end());
map<int,int>& trans = const_cast<map<int,int>&>(lastRealEmissionInfo->second.second);
int n = lastHeadXComb().meMomenta().size();
for ( int k = 0; k < n; ++k ) {
if ( k == bornEmitter() || k == bornSpectator() )
continue;
meMomenta()[trans[k]] = lastHeadXComb().meMomenta()[k];
if ( invertedTildeKinematics()->doesTransform() && k > 1 )
meMomenta()[trans[k]] = invertedTildeKinematics()->transform(meMomenta()[trans[k]]);
}
meMomenta()[realEmitter()] = invertedTildeKinematics()->realEmitterMomentum();
meMomenta()[realEmission()] = invertedTildeKinematics()->realEmissionMomentum();
meMomenta()[realSpectator()] = invertedTildeKinematics()->realSpectatorMomentum();
cPDVector::const_iterator pd = mePartonData().begin();
vector<Lorentz5Momentum>::iterator p = meMomenta().begin();
for ( ; pd != mePartonData().end(); ++pd, ++p ) {
p->setMass((**pd).mass());
p->rescaleRho();
}
jacobian(underlyingBornME()->lastXComb().jacobian() *
invertedTildeKinematics()->jacobian());
logGenerateRadiationKinematics(r);
return true;
}
void SubtractionDipole::ptCut(Energy cut) {
theInvertedTildeKinematics->ptCut(cut);
}
CrossSection SubtractionDipole::dSigHatDR(Energy2 factorizationScale) const {
double pdfweight = 1.;
double jac = jacobian();
if ( splitting() && jac == 0.0 ) {
lastMECrossSection(ZERO);
lastME2(0.0);
return ZERO;
}
if ( factorizationScale == ZERO ) {
if ( realEmissionScales() )
factorizationScale = realEmissionME()->lastScale();
else
factorizationScale = underlyingBornME()->lastScale();
}
if ( havePDFWeight1() ) {
pdfweight *= realEmissionME()->pdf1(factorizationScale);
}
if ( havePDFWeight2() ) {
pdfweight *= realEmissionME()->pdf2(factorizationScale);
}
lastMEPDFWeight(pdfweight);
bool needTheDipole = true;
CrossSection shower = ZERO;
double lastThetaMu = 1.0;
if ( showerApproximation() ) {
assert(!splitting());
showerApproximation()->setBornXComb(lastXCombPtr());
showerApproximation()->setRealXComb(realEmissionME()->lastXCombPtr());
showerApproximation()->setDipole(this);
if ( !showerApproximation()->isAboveCutoff() ) {
showerApproximation()->wasBelowCutoff();
lastThetaMu = 0.0;
} else {
lastThetaMu = 1.0;;
}
if ( lastThetaMu > 0.0 &&
showerApproximation()->isInShowerPhasespace() ) {
if ( realShowerSubtraction() )
shower = showerApproximation()->dSigHatDR()*lastThetaMu;
if ( virtualShowerSubtraction() || loopSimSubtraction() )
shower = -showerApproximation()->dSigHatDR()*lastThetaMu;
}
if ( realShowerSubtraction() && lastThetaMu == 1.0 )
needTheDipole = false;
if ( virtualShowerSubtraction() && lastThetaMu == 0.0 )
needTheDipole = false;
if ( factory()->loopSimCorrections() ||
factory()->meCorrectionsOnly() )
needTheDipole = false;
}
double xme2 = 0.0;
if ( needTheDipole )
xme2 = me2();
if ( factory()->loopSimCorrections() ||
factory()->meCorrectionsOnly() ) {
assert(showerApproximation());
xme2 = realEmissionME()->me2() * showerApproximation()->channelWeight();
double rws =
pow(underlyingBornME()->lastXComb().lastAlphaS()/
realEmissionME()->lastXComb().lastAlphaS(),
realEmissionME()->orderInAlphaS());
xme2 *= rws;
double rwe =
pow(underlyingBornME()->lastXComb().lastAlphaEM()/
realEmissionME()->lastXComb().lastAlphaEM(),
underlyingBornME()->orderInAlphaEW());
xme2 *= rwe;
}
if ( realShowerSubtraction() )
xme2 *= 1. - lastThetaMu;
if ( virtualShowerSubtraction() || loopSimSubtraction() )
xme2 *= lastThetaMu;
double coupl = lastMECouplings();
coupl *= underlyingBornME()->lastXComb().lastAlphaS();
if ( realEmissionScales() ) {
double rws =
pow(realEmissionME()->lastXComb().lastAlphaS()/
underlyingBornME()->lastXComb().lastAlphaS(),
realEmissionME()->orderInAlphaS());
xme2 *= rws;
coupl *= rws;
double rwe =
pow(realEmissionME()->lastXComb().lastAlphaEM()/
underlyingBornME()->lastXComb().lastAlphaEM(),
underlyingBornME()->orderInAlphaEW());
xme2 *= rwe;
coupl *= rwe;
}
lastMECouplings(coupl);
lastME2(xme2);
CrossSection res =
sqr(hbarc) * jac * pdfweight * xme2 /
(2. * realEmissionME()->lastXComb().lastSHat());
if ( !showerApproximation() && xme2 != 0.0 ) {
double weight = 0.0;
bool applied = false;
for ( vector<Ptr<MatchboxReweightBase>::ptr>::const_iterator rw =
theReweights.begin(); rw != theReweights.end(); ++rw ) {
(**rw).setXComb(theRealEmissionME->lastXCombPtr());
if ( !(**rw).apply() )
continue;
weight += (**rw).evaluate();
applied = true;
}
if ( applied )
res *= weight;
}
lastMECrossSection(-res-shower);
logDSigHatDR(jac);
return lastMECrossSection();
}
void SubtractionDipole::print(ostream& os) const {
os << "--- SubtractionDipole setup ----------------------------------------------------\n";
os << " subtraction '" << name() << "'\n for real emission '"
<< theRealEmissionME->name() << "'\n using underlying Born '"
<< theUnderlyingBornME->name() << "'\n";
os << " tilde kinematics are '"
<< (theTildeKinematics ? theTildeKinematics->name() : "")
<< " '\n inverted tilde kinematics are '"
<< (theInvertedTildeKinematics ? theInvertedTildeKinematics->name() : "") << "'\n";
os << " the following subtraction mappings have been found:\n";
for ( map<RealEmissionKey,UnderlyingBornInfo>::const_iterator m =
theMergingMap.begin(); m != theMergingMap.end(); ++m ) {
os << " " << process(m->second.first)[0]->PDGName() << " "
<< process(m->second.first)[1]->PDGName() << " -> ";
for ( cPDVector::const_iterator p = process(m->second.first).begin() + 2;
p != process(m->second.first).end(); ++p ) {
os << (**p).PDGName() << " ";
}
os << "[" << emitter(m->second.first) << "," << spectator(m->second.first) << "] <=> ";
os << process(m->first)[0]->PDGName() << " "
<< process(m->first)[1]->PDGName() << " -> ";
for ( cPDVector::const_iterator p = process(m->first).begin() + 2;
p != process(m->first).end(); ++p ) {
os << (**p).PDGName() << " ";
}
os << "[(" << emitter(m->first) << "," << emission(m->first) << ")," << spectator(m->first) << "]\n"
<< " non-dipole momenta ( ";
for ( map<int,int>::const_iterator k = m->second.second.begin();
k != m->second.second.end(); ++k ) {
if ( k->first == spectator(m->first) )
continue;
os << k->second << " ";
}
os << ") <=> ( ";
for ( map<int,int>::const_iterator k = m->second.second.begin();
k != m->second.second.end(); ++k ) {
if ( k->first == spectator(m->first) )
continue;
os << k->first << " ";
}
os << ")\n";
}
os << "--------------------------------------------------------------------------------\n";
os << flush;
}
void SubtractionDipole::printLastEvent(ostream& os) const {
os << "--- SubtractionDipole last event information -----------------------------------\n";
os << " for dipole '" << name() << "' applying ["
<< bornEmitter() << "," << bornSpectator() << "] <=> [("
<< realEmitter() << "," << realEmission() << ")," << realSpectator() << "]\n"
<< " evaluated the cross section/nb " << (lastMECrossSection()/nanobarn) << "\n"
<< " with subtraction parameters x[0] = " << subtractionParameters()[0]
<< " x[1] = " << subtractionParameters()[1] << "\n";
os << " the last real emission event was:\n";
realEmissionME()->printLastEvent(os);
os << " the last underlying Born event was:\n";
underlyingBornME()->printLastEvent(os);
os << "--- end SubtractionDipole last event information -------------------------------\n";
os << flush;
}
void SubtractionDipole::logME2() const {
if ( !realEmissionME()->verbose() &&
!underlyingBornME()->verbose() )
return;
tcStdXCombPtr bornxc = splitting() ? lastHeadXCombPtr() : lastXCombPtr();
tcStdXCombPtr realxc = splitting() ? lastXCombPtr() : lastHeadXCombPtr();
generator()->log() << "'" << name() << "' evaluated me2 using\n"
<< "Born XComb " << bornxc << " real XComb " << realxc << "\n";
generator()->log() << "subtraction parameters: ";
copy(subtractionParameters().begin(),subtractionParameters().end(),
ostream_iterator<double>(generator()->log()," "));
generator()->log() << "\n";
generator()->log() << "Born phase space point (in GeV):\n";
vector<Lorentz5Momentum>::const_iterator pit = bornxc->meMomenta().begin();
cPDVector::const_iterator dit = bornxc->mePartonData().begin();
for ( ; pit != bornxc->meMomenta().end() ; ++pit, ++dit )
generator()->log() << (**dit).PDGName() << " : "
<< (*pit/GeV) << "\n";
generator()->log() << "with x1 = " << bornxc->lastX1() << " x2 = " << bornxc->lastX2() << "\n"
<< "sHat/GeV2 = " << (bornxc->lastSHat()/GeV2) << "\n";
generator()->log() << "Real emission phase space point (in GeV):\n";
pit = realxc->meMomenta().begin();
dit = realxc->mePartonData().begin();
for ( ; pit != realxc->meMomenta().end() ; ++pit, ++dit )
generator()->log() << (**dit).PDGName() << " : "
<< (*pit/GeV) << "\n";
generator()->log() << "with x1 = " << realxc->lastX1() << " x2 = " << realxc->lastX2() << "\n"
<< "sHat/GeV2 = " << (realxc->lastSHat()/GeV2) << "\n";
generator()->log() << "me2 = " << lastME2() << "\n" << flush;
}
void SubtractionDipole::logDSigHatDR(double effectiveJac) const {
if ( !realEmissionME()->verbose() &&
!underlyingBornME()->verbose() )
return;
tcStdXCombPtr bornxc = splitting() ? lastHeadXCombPtr() : lastXCombPtr();
tcStdXCombPtr realxc = splitting() ? lastXCombPtr() : lastHeadXCombPtr();
generator()->log() << "'" << name() << "' evaluated cross section using\n"
<< "Born XComb " << bornxc << " real XComb " << realxc << "\n"
<< "Jacobian = " << jacobian()
<< " effective Jacobian = " << effectiveJac << "\n"
<< "Born sHat/GeV2 = " << (bornxc->lastSHat()/GeV2)
<< " real sHat/GeV2 = " << (realxc->lastSHat()/GeV2)
<< " dsig/nb = "
<< (lastMECrossSection()/nanobarn) << "\n" << flush;
}
void SubtractionDipole::logGenerateTildeKinematics() const {
if ( !realEmissionME()->verbose() &&
!underlyingBornME()->verbose() )
return;
generator()->log() << "'" << name() << "' generating tilde kinematics.\n"
<< "configuration: [" << bornEmitter() << ","
<< bornSpectator() << "] => "
<< "[(" << realEmitter() << "," << realEmission() << "),"
<< realSpectator() << "]\n"
<< "with real xcomb " << lastHeadXCombPtr() << " born xcomb "
<< lastXCombPtr() << "\n"
<< "from real emission phase space point:\n";
Lorentz5Momentum rSum;
vector<Lorentz5Momentum>::const_iterator pr = lastHeadXComb().meMomenta().begin();
cPDVector::const_iterator dr = lastHeadXComb().mePartonData().begin();
size_t count = 0;
for ( ; pr != lastHeadXComb().meMomenta().end(); ++pr,++dr ) {
generator()->log() << (**dr).PDGName() << " : "
<< (*pr/GeV) << "\n";
if ( count < 2 ) {
rSum -= *pr;
} else {
rSum += *pr;
}
++count;
}
generator()->log() << "sum : " << (rSum/GeV) << "\n";
generator()->log() << "subtraction parameters: ";
copy(subtractionParameters().begin(),subtractionParameters().end(),
ostream_iterator<double>(generator()->log()," "));
generator()->log() << "\n"
<< "with scale/GeV = " << (theLastSubtractionScale/GeV)
<< "and pt/GeV = " << (theLastSubtractionPt/GeV) << "\n";
generator()->log() << "generated tilde kinematics:\n";
pr = lastXComb().meMomenta().begin();
dr = lastXComb().mePartonData().begin();
count = 0;
Lorentz5Momentum bSum;
for ( ; pr != lastXComb().meMomenta().end(); ++pr,++dr ) {
generator()->log() << (**dr).PDGName() << " : "
<< (*pr/GeV) << "\n";
if ( count < 2 ) {
bSum -= *pr;
} else {
bSum += *pr;
}
++count;
}
generator()->log() << "sum : " << (bSum/GeV) << "\n";
generator()->log() << "Jacobian = " << jacobian() << "\n" << flush;
}
void SubtractionDipole::logGenerateRadiationKinematics(const double * r) const {
if ( !realEmissionME()->verbose() &&
!underlyingBornME()->verbose() )
return;
generator()->log() << "'" << name() << "' generating radiation kinematics.\n"
<< "configuration: [" << bornEmitter() << ","
<< bornSpectator() << "] => "
<< "[(" << realEmitter() << "," << realEmission() << "),"
<< realSpectator() << "]\n"
<< "with born xcomb " << lastHeadXCombPtr() << " real xcomb "
<< lastXCombPtr() << "\n"
<< "from random numbers:\n";
copy(r,r+nDimRadiation(),ostream_iterator<double>(generator()->log()," "));
generator()->log() << "\n";
generator()->log() << "and born phase space point:\n";
vector<Lorentz5Momentum>::const_iterator pr = lastHeadXComb().meMomenta().begin();
cPDVector::const_iterator dr = lastHeadXComb().mePartonData().begin();
for ( ; pr != lastHeadXComb().meMomenta().end(); ++pr,++dr )
generator()->log() << (**dr).PDGName() << " : "
<< (*pr/GeV) << "\n";
generator()->log() << "subtraction parameters: ";
copy(subtractionParameters().begin(),subtractionParameters().end(),
ostream_iterator<double>(generator()->log()," "));
generator()->log() << "\n" << flush;
generator()->log() << "scales: scale/GeV = " << (theLastSplittingScale/GeV)
<< " pt/GeV = " << (theLastSplittingPt/GeV) << "\n" << flush;
generator()->log() << "generated real emission kinematics:\n";
pr = lastXComb().meMomenta().begin();
dr = lastXComb().mePartonData().begin();
for ( ; pr != lastXComb().meMomenta().end(); ++pr,++dr )
generator()->log() << (**dr).PDGName() << " : "
<< (*pr/GeV) << "\n";
generator()->log() << "Jacobian = "
<< jacobian() << " = "
<< underlyingBornME()->lastXComb().jacobian()
<< "|Born * "
<< invertedTildeKinematics()->jacobian()
<< "|Radiation\n" << flush;
}
void SubtractionDipole::doinit() {
MEBase::doinit();
if ( underlyingBornME() ) {
theUnderlyingBornME->init();
}
if ( realEmissionME() ) {
theRealEmissionME->init();
}
if ( tildeKinematics() ) {
theTildeKinematics->init();
}
if ( invertedTildeKinematics() ) {
theInvertedTildeKinematics->init();
}
if ( showerApproximation() ) {
theShowerApproximation->init();
}
for ( vector<Ptr<SubtractionDipole>::ptr>::iterator p = thePartners.begin();
p != thePartners.end(); ++p ) {
(**p).init();
}
for ( vector<Ptr<MatchboxReweightBase>::ptr>::iterator rw =
theReweights.begin(); rw != theReweights.end(); ++rw ) {
(**rw).init();
}
}
void SubtractionDipole::doinitrun() {
MEBase::doinitrun();
if ( underlyingBornME() ) {
theUnderlyingBornME->initrun();
}
if ( realEmissionME() ) {
theRealEmissionME->initrun();
}
if ( tildeKinematics() ) {
theTildeKinematics->initrun();
}
if ( invertedTildeKinematics() ) {
theInvertedTildeKinematics->initrun();
}
if ( showerApproximation() ) {
theShowerApproximation->initrun();
}
for ( vector<Ptr<SubtractionDipole>::ptr>::iterator p = thePartners.begin();
p != thePartners.end(); ++p ) {
(**p).initrun();
}
for ( vector<Ptr<MatchboxReweightBase>::ptr>::iterator rw =
theReweights.begin(); rw != theReweights.end(); ++rw ) {
(**rw).initrun();
}
}
void SubtractionDipole::cloneDependencies(const std::string& prefix) {
if ( underlyingBornME() ) {
Ptr<MatchboxMEBase>::ptr myUnderlyingBornME = underlyingBornME()->cloneMe();
ostringstream pname;
pname << (prefix == "" ? fullName() : prefix) << "/" << myUnderlyingBornME->name();
if ( ! (generator()->preinitRegister(myUnderlyingBornME,pname.str()) ) )
throw InitException() << "Matrix element " << pname.str() << " already existing.";
myUnderlyingBornME->cloneDependencies(pname.str());
underlyingBornME(myUnderlyingBornME);
}
if ( realEmissionME() ) {
Ptr<MatchboxMEBase>::ptr myRealEmissionME = realEmissionME()->cloneMe();
ostringstream pname;
pname << (prefix == "" ? fullName() : prefix) << "/" << myRealEmissionME->name();
if ( ! (generator()->preinitRegister(myRealEmissionME,pname.str()) ) )
throw InitException() << "Matrix element " << pname.str() << " already existing.";
myRealEmissionME->cloneDependencies(pname.str());
realEmissionME(myRealEmissionME);
}
if ( tildeKinematics() ) {
Ptr<TildeKinematics>::ptr myTildeKinematics = tildeKinematics()->cloneMe();
ostringstream pname;
pname << (prefix == "" ? fullName() : prefix) << "/" << myTildeKinematics->name();
if ( ! (generator()->preinitRegister(myTildeKinematics,pname.str()) ) )
throw InitException() << "Tilde kinematics " << pname.str() << " already existing.";
myTildeKinematics->dipole(this);
tildeKinematics(myTildeKinematics);
}
if ( invertedTildeKinematics() ) {
Ptr<InvertedTildeKinematics>::ptr myInvertedTildeKinematics = invertedTildeKinematics()->cloneMe();
ostringstream pname;
pname << (prefix == "" ? fullName() : prefix) << "/" << myInvertedTildeKinematics->name();
if ( ! (generator()->preinitRegister(myInvertedTildeKinematics,pname.str()) ) )
throw InitException() << "Inverted tilde kinematics " << pname.str() << " already existing.";
myInvertedTildeKinematics->dipole(this);
invertedTildeKinematics(myInvertedTildeKinematics);
}
for ( vector<Ptr<MatchboxReweightBase>::ptr>::iterator rw =
theReweights.begin(); rw != theReweights.end(); ++rw ) {
Ptr<MatchboxReweightBase>::ptr myReweight = (**rw).cloneMe();
ostringstream pname;
pname << (prefix == "" ? fullName() : prefix) << "/" << (**rw).name();
if ( ! (generator()->preinitRegister(myReweight,pname.str()) ) )
throw InitException() << "Reweight " << pname.str() << " already existing.";
myReweight->cloneDependencies(pname.str());
*rw = myReweight;
}
}
void SubtractionDipole::constructVertex(tSubProPtr sub) {
if ( splitting() )
realEmissionME()->constructVertex(sub);
else
underlyingBornME()->constructVertex(sub);
}
+void SubtractionDipole::constructVertex(tSubProPtr sub, const ColourLines* cl) {
+ if ( splitting() )
+ realEmissionME()->constructVertex(sub,cl);
+ else
+ underlyingBornME()->constructVertex(sub,cl);
+}
+
void SubtractionDipole::generateSubCollision(SubProcess & sub) {
if ( splitting() )
realEmissionME()->generateSubCollision(sub);
else
underlyingBornME()->generateSubCollision(sub);
}
void SubtractionDipole::persistentOutput(PersistentOStream & os) const {
os << theLastXComb << theSplitting << theApply << theSubtractionTest
<< theIgnoreCuts << theRealEmissionME << theUnderlyingBornME
<< thePartners << theTildeKinematics << theInvertedTildeKinematics
<< theReweights << theRealEmitter << theRealEmission << theRealSpectator
<< theSubtractionParameters << theMergingMap << theSplittingMap
<< theIndexMap << theUnderlyingBornDiagrams << theRealEmissionDiagrams
<< lastRealEmissionKey << lastUnderlyingBornKey
<< theBornEmitter << theBornSpectator << ounit(theLastSubtractionScale,GeV)
<< ounit(theLastSplittingScale,GeV) << ounit(theLastSubtractionPt,GeV)
<< ounit(theLastSplittingPt,GeV) << theLastSubtractionZ
<< theLastSplittingZ << theShowerApproximation
<< theRealShowerSubtraction << theVirtualShowerSubtraction
<< theLoopSimSubtraction << theRealEmissionScales << theFactory;
}
void SubtractionDipole::persistentInput(PersistentIStream & is, int) {
is >> theLastXComb >> theSplitting >> theApply >> theSubtractionTest
>> theIgnoreCuts >> theRealEmissionME >> theUnderlyingBornME
>> thePartners >> theTildeKinematics >> theInvertedTildeKinematics
>> theReweights >> theRealEmitter >> theRealEmission >> theRealSpectator
>> theSubtractionParameters >> theMergingMap >> theSplittingMap
>> theIndexMap >> theUnderlyingBornDiagrams >> theRealEmissionDiagrams
>> lastRealEmissionKey >> lastUnderlyingBornKey
>> theBornEmitter >> theBornSpectator >> iunit(theLastSubtractionScale,GeV)
>> iunit(theLastSplittingScale,GeV) >> iunit(theLastSubtractionPt,GeV)
>> iunit(theLastSplittingPt,GeV) >> theLastSubtractionZ
>> theLastSplittingZ >> theShowerApproximation
>> theRealShowerSubtraction >> theVirtualShowerSubtraction
>> theLoopSimSubtraction >> theRealEmissionScales >> theFactory;
lastMatchboxXComb(theLastXComb);
typedef multimap<UnderlyingBornKey,RealEmissionInfo>::const_iterator spit;
pair<spit,spit> kr = theSplittingMap.equal_range(lastUnderlyingBornKey);
lastRealEmissionInfo = kr.first;
for ( ; lastRealEmissionInfo != kr.second; ++lastRealEmissionInfo )
if ( process(lastRealEmissionInfo->second.first) == lastXComb().mePartonData() )
break;
}
Ptr<MatchboxFactory>::tptr SubtractionDipole::factory() const {
return theFactory;
}
void SubtractionDipole::factory(Ptr<MatchboxFactory>::tptr f) {
theFactory = f;
}
void SubtractionDipole::Init() {
static ClassDocumentation<SubtractionDipole> documentation
("SubtractionDipole represents a dipole subtraction "
"term in the formalism of Catani and Seymour.");
}
// *** 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).
DescribeAbstractClass<SubtractionDipole,MEBase>
describeSubtractionDipole("Herwig::SubtractionDipole", "Herwig.so");
diff --git a/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h b/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h
--- a/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h
+++ b/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h
@@ -1,1119 +1,1124 @@
// -*- C++ -*-
//
// SubtractionDipole.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_SubtractionDipole_H
#define HERWIG_SubtractionDipole_H
//
// This is the declaration of the SubtractionDipole class.
//
#include "Herwig++/MatrixElement/Matchbox/Dipoles/SubtractionDipole.fh"
#include "ThePEG/MatrixElement/MEBase.h"
#include "ThePEG/Handlers/StandardXComb.h"
#include "Herwig++/MatrixElement/Matchbox/Base/MatchboxMEBase.h"
#include "Herwig++/MatrixElement/Matchbox/Matching/ShowerApproximation.h"
#include "Herwig++/MatrixElement/Matchbox/MatchboxFactory.fh"
namespace Herwig {
using namespace ThePEG;
class TildeKinematics;
class InvertedTildeKinematics;
/**
* \ingroup Matchbox
* \author Simon Platzer
*
* \brief SubtractionDipole represents a dipole subtraction
* term in the formalism of Catani and Seymour.
*
*/
class SubtractionDipole:
public MEBase, public LastMatchboxXCombInfo {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
SubtractionDipole();
/**
* The destructor.
*/
virtual ~SubtractionDipole();
//@}
public:
/**
* Return the factory which produced this matrix element
*/
Ptr<MatchboxFactory>::tptr factory() const;
/**
* Set the factory which produced this matrix element
*/
void factory(Ptr<MatchboxFactory>::tptr f);
/** @name Subprocess and diagram information. */
//@{
/**
* A helpre struct to communicate diagram merging and remapping
* information
*/
struct MergeInfo {
/**
* The merged emitter
*/
int emitter;
/**
* The Born diagram
*/
Ptr<Tree2toNDiagram>::ptr diagram;
/**
* The merging map
*/
map<int,int> mergeLegs;
};
/**
* Return true, if this dipole can possibly handle the indicated
* emitter.
*/
virtual bool canHandleEmitter(const cPDVector& partons, int emitter) const = 0;
/**
* Return true, if this dipole can possibly handle the indicated
* splitting.
*/
virtual bool canHandleSplitting(const cPDVector& partons, int emitter, int emission) const = 0;
/**
* Return true, if this dipole can possibly handle the indicated
* spectator.
*/
virtual bool canHandleSpectator(const cPDVector& partons, int spectator) const = 0;
/**
* Return true, if this dipole applies to the selected
* configuration.
*/
virtual bool canHandle(const cPDVector& partons,
int emitter, int emission, int spectator) const = 0;
/**
* Return true, if this dipole is symmetric with respect to emitter
* and emission.
*/
virtual bool isSymmetric() const { return false; }
/**
* If this is a dependent matrix element in a ME group, return true,
* if it applies to the process set in lastXComb()
*/
virtual bool apply() const { return theApply; }
/**
* Clear the bookkeeping
*/
void clearBookkeeping();
/**
* Setup bookkeeping maps.
*/
void setupBookkeeping(const map<Ptr<DiagramBase>::ptr,MergeInfo>& mergeInfo);
/**
* Get bookkeeping information for the given
* real emission diagram
*/
void subtractionBookkeeping();
/**
* Determine bookkeeping information for
* the underlying Born process supplied through
* the lastHeadXComb() object.
*/
void splittingBookkeeping();
/**
* For the given event generation setup return a xcomb object
* appropriate to this matrix element.
*/
virtual StdXCombPtr makeXComb(Energy newMaxEnergy, const cPDPair & inc,
tEHPtr newEventHandler,tSubHdlPtr newSubProcessHandler,
tPExtrPtr newExtractor, tCascHdlPtr newCKKW,
const PBPair & newPartonBins, tCutsPtr newCuts,
const DiagramVector & newDiagrams, bool mir,
const PartonPairVec& allPBins,
tStdXCombPtr newHead = tStdXCombPtr(),
tMEPtr newME = tMEPtr());
/**
* For the given event generation setup return a dependent xcomb object
* appropriate to this matrix element.
*/
virtual StdXCombPtr makeXComb(tStdXCombPtr newHead,
const PBPair & newPartonBins,
const DiagramVector & newDiagrams,
tMEPtr newME = tMEPtr());
/**
* Create a dependent xcomb object for the underlying
* Born process, given a XComb driving the real emission
*/
StdXCombPtr makeBornXComb(tStdXCombPtr realXC);
/**
* Create dependent xcomb objects for the real emission process,
* given a XComb driving the underlying Born
*/
vector<StdXCombPtr> makeRealXCombs(tStdXCombPtr bornXC);
/**
* Return true, if bookkeeping did not find a non-trivial setup.
*/
bool empty() const { return theSplittingMap.empty(); }
/**
* Return the emitter as referred to by the real emission
* matrix element.
*/
int realEmitter() const { return theRealEmitter; }
/**
* Set the emitter as referred to by the real emission
* matrix element.
*/
void realEmitter(int id) { theRealEmitter = id; }
/**
* Return the emission as referred to by the real emission
* matrix element.
*/
int realEmission() const { return theRealEmission; }
/**
* Set the emission as referred to by the real emission
* matrix element.
*/
void realEmission(int id) { theRealEmission = id; }
/**
* Return the spectator as referred to by the real emission
* matrix element.
*/
int realSpectator() const { return theRealSpectator; }
/**
* Set the spectator as referred to by the real emission
* matrix element.
*/
void realSpectator(int id) { theRealSpectator = id; }
/**
* Return the emitter as referred to by the underlying
* Born process.
*/
int bornEmitter() const { return theBornEmitter; }
/**
* Set the emitter as referred to by the underlying
* Born process.
*/
void bornEmitter(int id) { theBornEmitter = id; }
/**
* Return the spectator as referred to by the underlying
* Born process.
*/
int bornSpectator() const { return theBornSpectator; }
/**
* Set the spectator as referred to by the underlying
* Born process.
*/
void bornSpectator(int id) { theBornSpectator = id; }
/**
* Define the real emission key type
*/
typedef pair<pair<cPDVector,int>,pair<int,int> > RealEmissionKey;
/**
* Create a real emission key
*/
static RealEmissionKey realEmissionKey(const cPDVector& proc,
int em, int emm, int sp) {
return make_pair(make_pair(proc,emm),make_pair(em,sp));
}
/**
* Return the diagram of a real emission key
*/
static const cPDVector& process(const RealEmissionKey& key) {
return key.first.first;
}
/**
* Return the emission id of a real emission key
*/
static int emission(const RealEmissionKey& key) {
return key.first.second;
}
/**
* Return the emitter id of a real emission key
*/
static int emitter(const RealEmissionKey& key) {
return key.second.first;
}
/**
* Return the spectator id of a real emission key
*/
static int spectator(const RealEmissionKey& key) {
return key.second.second;
}
/**
* Define the underlying Born key type
*/
typedef pair<cPDVector,pair<int,int> > UnderlyingBornKey;
/**
* Create a underlying Born key
*/
static UnderlyingBornKey underlyingBornKey(const cPDVector& proc,
int em, int sp) {
return make_pair(proc,make_pair(em,sp));
}
/**
* Return the diagram of a underlying Born key
*/
static const cPDVector& process(const UnderlyingBornKey& key) {
return key.first;
}
/**
* Return the emitter id of a underlying Born key
*/
static int emitter(const UnderlyingBornKey& key) {
return key.second.first;
}
/**
* Return the spectator id of a underlying Born key
*/
static int spectator(const UnderlyingBornKey& key) {
return key.second.second;
}
/**
* Define real emission key and index dictionary
* for partons not involved in the given dipole.
*/
typedef pair<RealEmissionKey,map<int,int> > RealEmissionInfo;
/**
* Define underlying Born key and index dictionary
* for partons not involved in the given dipole.
*/
typedef pair<UnderlyingBornKey,map<int,int> > UnderlyingBornInfo;
/**
* Return the merging map
*/
const map<RealEmissionKey,UnderlyingBornInfo>& mergingMap() const { return theMergingMap; }
/**
* Return the splitting map
*/
const multimap<UnderlyingBornKey,RealEmissionInfo>& splittingMap() const { return theSplittingMap; }
/**
* Return the underlying Born diagrams to be considered
* for the given real emission process.
*/
const DiagramVector& underlyingBornDiagrams(const cPDVector& real) const;
/**
* Return the real emission diagrams to be considered
* for the given Born process.
*/
const DiagramVector& realEmissionDiagrams(const cPDVector& born) const;
/**
* Add all possible diagrams with the add() function.
*/
virtual void getDiagrams() const;
/**
* Return true, if this matrix element does not want to
* make use of mirroring processes; in this case all
* possible partonic subprocesses with a fixed assignment
* of incoming particles need to be provided through the diagrams
* added with the add(...) method.
*/
virtual bool noMirror () const { return true; }
/**
* With the information previously supplied with the
* setKinematics(...) method, a derived class may optionally
* override this method to weight the given diagrams with their
* (although certainly not physical) relative probabilities.
*/
virtual Selector<DiagramIndex> diagrams(const DiagramVector & dv) const;
/**
* Return a Selector with possible colour geometries for the selected
* diagram weighted by their relative probabilities.
*/
virtual Selector<const ColourLines *>
colourGeometries(tcDiagPtr diag) const;
/**
* Select a ColpurLines geometry. The default version returns a
* colour geometry selected among the ones returned from
* colourGeometries(tcDiagPtr).
*/
virtual const ColourLines &
selectColourGeometry(tcDiagPtr diag) const;
/**
* Return the order in \f$\alpha_S\f$ in which this matrix element
* is given.
*/
virtual unsigned int orderInAlphaS() const { return realEmissionME()->orderInAlphaS(); }
/**
* Return the order in \f$\alpha_{EM}\f$ in which this matrix
* element is given. Returns 0.
*/
virtual unsigned int orderInAlphaEW() const { return underlyingBornME()->orderInAlphaEW(); }
//@}
/** @name Phasespace generation */
//@{
/**
* Set the XComb object to be used in the next call to
* generateKinematics() and dSigHatDR().
*/
virtual void setXComb(tStdXCombPtr xc);
/**
* Set the typed and momenta of the incoming and outgoing partons to
* be used in subsequent calls to me() and colourGeometries()
* according to the associated XComb object. If the function is
* overridden in a sub class the new function must call the base
* class one first.
*/
virtual void setKinematics();
/**
* Generate internal degrees of freedom given nDim() uniform random
* numbers in the interval ]0,1[. To help the phase space generator,
* the 'dSigHatDR' should be a smooth function of these numbers,
* although this is not strictly necessary. The return value should
* be true of the generation succeeded. If so the generated momenta
* should be stored in the meMomenta() vector.
*/
virtual bool generateKinematics(const double * r);
/**
* The number of internal degreed of freedom used in the matrix
* element. This default version returns 0;
*/
virtual int nDim() const;
/**
* Return true, if this matrix element expects
* the incoming partons in their center-of-mass system
*/
virtual bool wantCMS () const { return realEmissionME()->wantCMS(); }
/**
* Clear the information previously provided by a call to
* setKinematics(...).
*/
virtual void clearKinematics();
/**
* If this is a dependent matrix element in a ME group, return true,
* if cuts should be ignored.
*/
virtual bool ignoreCuts() const { return theIgnoreCuts; }
/**
* Indicate that cuts should be ignored
*/
void doIgnoreCuts(bool is = true) { theIgnoreCuts = is; }
//@}
/** @name Tilde kinematics */
//@{
/**
* Return the TildeKinematics object used
*/
Ptr<TildeKinematics>::tcptr tildeKinematics() const { return theTildeKinematics; }
/**
* Set the TildeKinematics object used
*/
void tildeKinematics(Ptr<TildeKinematics>::tptr);
/**
* Generate the tilde kinematics from real emission
* kinematics accessible through the XComb's
* head object and store it in meMomenta(). This default
* implemenation uses the tildeKinematics() object.
*/
virtual bool generateTildeKinematics();
/**
* Return the InvertedTildeKinematics object used
*/
Ptr<InvertedTildeKinematics>::tcptr invertedTildeKinematics() const { return theInvertedTildeKinematics; }
/**
* Set the InvertedTildeKinematics object used
*/
void invertedTildeKinematics(Ptr<InvertedTildeKinematics>::tptr);
/**
* Return the number of additional random numbers
* needed to generate real emission kinematics off
* the tilde kinematics previously supplied through
* the XComb object. This default implementation
* returns invertedTildeKinematics()->nDimRadiation()
*/
virtual int nDimRadiation() const;
/**
* Generate the real emission kinematics
* off the Born kinematics accessible through the XComb's
* head object and store it in meMomenta(); store
* the single particle phasespace in units of lastHeadXComb()->lastSHat()
* in jacobian(). This default
* implemenation uses the invertedTildeKinematics() object
*/
virtual bool generateRadiationKinematics(const double *);
/**
* Set a pt cut when splitting
*/
void ptCut(Energy cut);
/**
* Return the relevant dipole scale
*/
Energy lastDipoleScale() const {
return splitting() ? theLastSplittingScale : theLastSubtractionScale;
}
/**
* Return the relevant pt
*/
Energy lastPt() const {
return splitting() ? theLastSplittingPt : theLastSubtractionPt;
}
/**
* Return the relevant momentum fractions
*/
double lastZ() const {
return splitting() ? theLastSplittingZ : theLastSubtractionZ;
}
/**
* Return true, if this dipole acts in splitting mode.
*/
bool splitting() const { return theSplitting; }
/**
* Switch on splitting mode for this dipole.
*/
void doSplitting() { theSplitting = true; }
/**
* Switch off splitting mode for this dipole.
*/
void doSubtraction() { theSplitting = false; }
/**
* Return the subtraction parameters.
*/
const vector<double>& subtractionParameters() const { return theSubtractionParameters; }
/**
* Access the subtraction parameters.
*/
vector<double>& subtractionParameters() { return theSubtractionParameters; }
//@}
/** @name Scale choices, couplings and PDFs */
//@{
/**
* Return true, if scales should be calculated from real emission kinematics
*/
bool realEmissionScales() const { return theRealEmissionScales; }
/**
* Switch on or off that scales should be calculated from real emission kinematics
*/
void doRealEmissionScales(bool on = true) { theRealEmissionScales = on; }
/**
* Return the scale associated with the phase space point provided
* by the last call to setKinematics().
*/
virtual Energy2 scale() const {
return realEmissionScales() ?
realEmissionME()->scale() :
underlyingBornME()->scale();
}
/**
* Return the value of \f$\alpha_S\f$ associated with the phase
* space point provided by the last call to setKinematics(). This
* versions returns SM().alphaS(scale()).
*/
virtual double alphaS() const {
return realEmissionScales() ?
realEmissionME()->alphaS() :
underlyingBornME()->alphaS();
}
/**
* Return the value of \f$\alpha_EM\f$ associated with the phase
* space point provided by the last call to setKinematics(). This
* versions returns SM().alphaEM(scale()).
*/
virtual double alphaEM() const {
return realEmissionScales() ?
realEmissionME()->alphaEM() :
underlyingBornME()->alphaEM();
}
/**
* Return true, if this matrix element provides the PDF
* weight for the first incoming parton itself.
*/
virtual bool havePDFWeight1() const { return realEmissionME()->havePDFWeight1(); }
/**
* Return true, if this matrix element provides the PDF
* weight for the second incoming parton itself.
*/
virtual bool havePDFWeight2() const { return realEmissionME()->havePDFWeight2(); }
//@}
/** @name Matrix elements and evaluation */
//@{
/**
* Return the real emission matrix element
*/
Ptr<MatchboxMEBase>::tcptr realEmissionME() const {
return theRealEmissionME;
}
/**
* Return the real emission matrix element
*/
Ptr<MatchboxMEBase>::tptr realEmissionME() {
return theRealEmissionME;
}
/**
* Set the real emission matrix element
*/
void realEmissionME(Ptr<MatchboxMEBase>::tptr me) { theRealEmissionME = me; }
/**
* Return the underlying Born matrix element
*/
Ptr<MatchboxMEBase>::tcptr underlyingBornME() const {
return theUnderlyingBornME;
}
/**
* Return the underlying Born matrix element
*/
Ptr<MatchboxMEBase>::tptr underlyingBornME() {
return theUnderlyingBornME;
}
/**
* Set the underlying Born matrix element
*/
void underlyingBornME(Ptr<MatchboxMEBase>::tptr me) { theUnderlyingBornME = me; }
/**
* Set the dipoles which have been found along with this dipole
*/
void partnerDipoles(const vector<Ptr<SubtractionDipole>::ptr>& p) {
thePartners = p;
}
/**
* Return the dipoles which have been found along with this dipole
*/
const vector<Ptr<SubtractionDipole>::ptr>& partnerDipoles() const {
return thePartners;
}
/**
* Return the matrix element averaged over spin correlations.
*/
virtual double me2Avg(double ccme2) const = 0;
/**
* Return the matrix element squared differential in the variables
* given by the last call to generateKinematics().
*/
virtual CrossSection dSigHatDR(Energy2 factorizationScale) const;
/**
* Return the matrix element squared differential in the variables
* given by the last call to generateKinematics().
*/
virtual CrossSection dSigHatDR() const { return dSigHatDR(ZERO); }
//@}
/** @name Methods relevant to matching */
//@{
/**
* Set the shower approximation.
*/
void showerApproximation(Ptr<ShowerApproximation>::tptr app) {
theShowerApproximation = app;
}
/**
* Return the shower approximation.
*/
Ptr<ShowerApproximation>::tptr showerApproximation() const { return theShowerApproximation; }
/**
* Indicate that the shower real emission contribution should be subtracted.
*/
void doRealShowerSubtraction() { theRealShowerSubtraction = true; }
/**
* Return true, if the shower real emission contribution should be subtracted.
*/
bool realShowerSubtraction() const { return theRealShowerSubtraction; }
/**
* Indicate that the shower virtual contribution should be subtracted.
*/
void doVirtualShowerSubtraction() { theVirtualShowerSubtraction = true; }
/**
* Return true, if the shower virtual contribution should be subtracted.
*/
bool virtualShowerSubtraction() const { return theVirtualShowerSubtraction; }
/**
* Indicate that the loopsim matched virtual contribution should be subtracted.
*/
void doLoopSimSubtraction() { theLoopSimSubtraction = true; }
/**
* Return true, if the loopsim matched virtual contribution should be subtracted.
*/
bool loopSimSubtraction() const { return theLoopSimSubtraction; }
//@}
/** @name Caching and diagnostic information */
//@{
/**
* Inform this matrix element that a new phase space
* point is about to be generated, so all caches should
* be flushed.
*/
virtual void flushCaches();
/**
* Indicate that the subtraction is being tested.
*/
void doTestSubtraction() { theSubtractionTest = true; }
/**
* Return true, if the subtraction is being tested.
*/
bool testSubtraction() const { return theSubtractionTest; }
/**
* Return true, if verbose
*/
bool verbose() const { return realEmissionME()->verbose() || underlyingBornME()->verbose(); }
/**
* Dump the setup to an ostream
*/
void print(ostream&) const;
/**
* Print debug information on the last event
*/
virtual void printLastEvent(ostream&) const;
/**
* Write out diagnostic information for
* generateTildeKinematics
*/
void logGenerateTildeKinematics() const;
/**
* Write out diagnostic information for
* generateRadiationKinematics
*/
void logGenerateRadiationKinematics(const double * r) const;
/**
* Write out diagnostic information for
* me2 evaluation
*/
void logME2() const;
/**
* Write out diagnostic information
* for dsigdr evaluation
*/
void logDSigHatDR(double effectiveJac) const;
//@}
/** @name Reweight objects */
//@{
/**
* Insert a reweight object
*/
void addReweight(Ptr<MatchboxReweightBase>::ptr rw) { theReweights.push_back(rw); }
/**
* Return the reweight objects
*/
const vector<Ptr<MatchboxReweightBase>::ptr>& reweights() const { return theReweights; }
/**
* Access the reweight objects
*/
vector<Ptr<MatchboxReweightBase>::ptr>& reweights() { return theReweights; }
//@}
/** @name Methods used to setup SubtractionDipole objects */
//@{
/**
* Clone this dipole.
*/
Ptr<SubtractionDipole>::ptr cloneMe() const {
return dynamic_ptr_cast<Ptr<SubtractionDipole>::ptr>(clone());
}
/**
* Clone the dependencies, using a given prefix.
*/
void cloneDependencies(const std::string& prefix = "");
//@}
/** @name Methods required to setup the event record */
//@{
/**
* construct the spin information for the interaction
*/
virtual void constructVertex(tSubProPtr sub);
/**
+ * construct the spin information for the interaction
+ */
+ virtual void constructVertex(tSubProPtr sub, const ColourLines* cl);
+
+ /**
* Comlete a SubProcess object using the internal degrees of freedom
* generated in the last generateKinematics() (and possible other
* degrees of freedom which was intergated over in dSigHatDR(). This
* default version does nothing. Will be made purely virtual in the
* future.
*/
virtual void generateSubCollision(SubProcess & sub);
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit();
/**
* Initialize this object. Called in the run phase just before
* a run begins.
*/
virtual void doinitrun();
//@}
private:
/**
* The factory which produced this matrix element
*/
Ptr<MatchboxFactory>::tptr theFactory;
/**
* Wether or not this dipole acts in splitting mode.
*/
bool theSplitting;
/**
* True, if should apply to process in the xcomb.
*/
bool theApply;
/**
* True, if the subtraction is being tested.
*/
bool theSubtractionTest;
/**
* True if cuts should be ignored
*/
bool theIgnoreCuts;
/**
* The real emission matrix element to be considered
*/
Ptr<MatchboxMEBase>::ptr theRealEmissionME;
/**
* The underlying Born matrix element
*/
Ptr<MatchboxMEBase>::ptr theUnderlyingBornME;
/**
* The dipoles which have been found along with this dipole
*/
vector<Ptr<SubtractionDipole>::ptr> thePartners;
/**
* The TildeKinematics to be used.
*/
Ptr<TildeKinematics>::ptr theTildeKinematics;
/**
* The InvertedTildeKinematics to be used.
*/
Ptr<InvertedTildeKinematics>::ptr theInvertedTildeKinematics;
/**
* A vector of reweight objects the sum of which
* should be applied to reweight this dipole
*/
vector<Ptr<MatchboxReweightBase>::ptr> theReweights;
/**
* The emitter as referred to by the real emission
* matrix element.
*/
int theRealEmitter;
/**
* The emission as referred to by the real emission
* matrix element.
*/
int theRealEmission;
/**
* The spectator as referred to by the real emission
* matrix element.
*/
int theRealSpectator;
/**
* The subtraction parameters
*/
vector<double> theSubtractionParameters;
/**
* Map real emission diagrams to underlying Born diagrams
* and tilde emitter/spectator.
*/
map<RealEmissionKey,UnderlyingBornInfo> theMergingMap;
/**
* Map underlying Born diagrams and tilde emitter/spectator
* to real emission diagram containing the splitting.
*/
multimap<UnderlyingBornKey,RealEmissionInfo> theSplittingMap;
/**
* Map underlying Born diagrams to emitter/spectator pairs
*/
map<cPDVector,pair<int,int> > theIndexMap;
/**
* Map real emission processes to Born diagrams
*/
map<cPDVector,DiagramVector> theUnderlyingBornDiagrams;
/**
* Map Born processes to real emission diagrams
*/
map<cPDVector,DiagramVector> theRealEmissionDiagrams;
/**
* The last real emission key encountered
*/
RealEmissionKey lastRealEmissionKey;
/**
* The last underlying Born key encountered
*/
UnderlyingBornKey lastUnderlyingBornKey;
/**
* The last real emission info encountered
*/
multimap<UnderlyingBornKey,RealEmissionInfo>::const_iterator lastRealEmissionInfo;
/**
* The emitter as referred to by the underlying Born
* matrix element.
*/
int theBornEmitter;
/**
* The spectator as referred to by the underlying Born
* matrix element.
*/
int theBornSpectator;
/**
* The last scale as generated from the tilde mapping
*/
Energy theLastSubtractionScale;
/**
* The last scale as generated from the splitting mapping
*/
Energy theLastSplittingScale;
/**
* The last pt as generated from the tilde mapping
*/
Energy theLastSubtractionPt;
/**
* The last pt as generated from the splitting mapping
*/
Energy theLastSplittingPt;
/**
* The last z as generated from the tilde mapping
*/
double theLastSubtractionZ;
/**
* The last z as generated from the splitting mapping
*/
double theLastSplittingZ;
/**
* The shower approximation.
*/
Ptr<ShowerApproximation>::ptr theShowerApproximation;
/**
* True, if the shower real emission contribution should be subtracted.
*/
bool theRealShowerSubtraction;
/**
* True, if the shower virtual contribution should be subtracted.
*/
bool theVirtualShowerSubtraction;
/**
* True, if the loopsim matched virtual contribution should be subtracted.
*/
bool theLoopSimSubtraction;
/**
* True, if scales should be calculated from real emission kinematics
*/
bool theRealEmissionScales;
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
SubtractionDipole & operator=(const SubtractionDipole &);
};
}
#endif /* HERWIG_SubtractionDipole_H */
diff --git a/MatrixElement/Matchbox/External/MadGraph/MadGraphAmplitude.h b/MatrixElement/Matchbox/External/MadGraph/MadGraphAmplitude.h
--- a/MatrixElement/Matchbox/External/MadGraph/MadGraphAmplitude.h
+++ b/MatrixElement/Matchbox/External/MadGraph/MadGraphAmplitude.h
@@ -1,329 +1,335 @@
// -*- C++ -*-
//
// MadGraphAmplitude.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_MadGraphAmplitude_H
#define Herwig_MadGraphAmplitude_H
//
// This is the declaration of the MadGraphAmplitude class.
//
#include "Herwig++/MatrixElement/Matchbox/Base/MatchboxAmplitude.h"
#include "Herwig++/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxCurrents.h"
#include "ThePEG/Utilities/DynamicLoader.h"
namespace Herwig {
using namespace ThePEG;
/**
* \ingroup Matchbox
* \author Johannes Bellm, Simon Platzer
*
* \brief MadGraphAmplitude implements an interface to MadGraph
*/
class MadGraphAmplitude:
public MatchboxAmplitude {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
MadGraphAmplitude();
/**
* The destructor.
*/
virtual ~MadGraphAmplitude();
//@}
public:
/**
* Return true, if this amplitude can handle the given process.
*/
virtual bool canHandle(const PDVector&,
Ptr<MatchboxFactory>::tptr,
bool) const;
/**
* Return true, if this amplitude already includes symmetry factors
* for identical outgoing particles.
*/
virtual bool hasFinalStateSymmetry() const { return false; }
/**
* Set the (tree-level) order in \f$g_S\f$ in which this matrix
* element should be evaluated.
*/
virtual void orderInGs(unsigned int ogs) { theOrderInGs = ogs; }
/**
* Return the (tree-level) order in \f$g_S\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInGs() const { return theOrderInGs; }
/**
* Set the (tree-level) order in \f$g_{EM}\f$ in which this matrix
* element should be evaluated.
*/
virtual void orderInGem(unsigned int oge) { theOrderInGem = oge; }
/**
* Return the (tree-level) order in \f$g_{EM}\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInGem() const { return theOrderInGem; }
/**
* 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);
/**
* Calculate the one-loop amplitudes for the phasespace point
* stored in lastXComb, if provided.
*/
virtual void prepareOneLoopAmplitudes(Ptr<MatchboxMEBase>::tcptr);
/**
* Evaluate the amplitude for the given colour tensor id and
* helicity assignment
*/
virtual Complex evaluate(size_t, const vector<int>&, Complex&);
/**
* Return true, if one-loop contributions will be evaluated at amplitude level.
*/
virtual bool oneLoopAmplitudes() const { return false; }
/**
* Return the one-loop/tree interference.
*/
virtual double oneLoopInterference() const;
void evaloneLoopInterference() const;
/**
* Return true, if one loop corrections are given in the conventions
* of BDK.
*/
virtual bool isCS() const { return false; }
virtual bool isExpanded() const { return true; }
virtual bool isBDK() const { return false; }
virtual bool isDR() const { return false; }
virtual bool isDRbar() const {return false;}
/**
* Return the value of the dimensional regularization
* parameter. Note that renormalization scale dependence is fully
* restored in DipoleIOperator.
*/
virtual Energy2 mu2() const { return sqr(91.18800000000*GeV);}
//virtual Energy2 mu2() const { return lastSHat(); }
virtual LorentzVector<Complex> plusPolarization(const Lorentz5Momentum& p,
const Lorentz5Momentum& n,
int id = -1) const;
/**
* Return the colour and spin correlated matrix element.
*/
virtual double spinColourCorrelatedME2(pair<int,int> emitterSpectator,
const SpinCorrelationTensor& c) const;
/**
* Order process in MadGraph conventions
*/
vector<size_t> gluonsFirst(vector<size_t> i);
/**
* Flush all cashes.
*/
virtual void flushCaches() {
MatchboxAmplitude::flushCaches();
}
/**
* Return true, if this amplitude needs to initialize an external
* code.
*/
virtual bool isExternal() const { return true; }
/**
* Initialize this amplitude
*/
virtual bool initializeExternal();
/**
* Return a generic process id for the given process
*/
virtual int externalId(const cPDVector&);
+ /**
+ * Return true, if this amplitude is capable of consistently filling
+ * the rho matrices for the spin correllations
+ */
+ virtual bool canFillRhoMatrix() const { return true; }
+
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @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();
/**
* The (tree-level) order in \f$g_S\f$ in which this matrix
* element is given.
*/
unsigned int theOrderInGs;
/**
* The (tree-level) order in \f$g_{EM}\f$ in which this matrix
* element is given.
*/
unsigned int theOrderInGem;
/**
* The path for the process libraries.
*/
string theProcessPath;
/**
* The path to generate amplitudes in.
*/
string theMGmodel;
bool keepinputtopmass;
/**
* The process map.
*/
static map<string,int>& processmap();
/**
* Load the process map
*/
void loadProcessMap();
/**
* Initialize the given process
*/
void initProcess(const cPDVector&);
/**
* Storage for Amplitudes
*/
mutable vector<string> BornAmplitudes,VirtAmplitudes;
/**
* Helper for color and crossing handling
*/
mutable vector<int> colourindex, crossing;
/**
* Give this to Madgraph:
*/
mutable double virt[20],momenta[50],pg[4],ng[4],poltmp[8];
mutable int heltmp[10];
/**
* Static Variables to handle initialization.
*/
static bool ranMadGraphInitializeExternal;
static bool initializedMad;
//@}
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MadGraphAmplitude & operator=(const MadGraphAmplitude &);
};
}
#endif /* Herwig_MadGraphAmplitude_H */
diff --git a/MatrixElement/Matchbox/MatchboxFactory.cc b/MatrixElement/Matchbox/MatchboxFactory.cc
--- a/MatrixElement/Matchbox/MatchboxFactory.cc
+++ b/MatrixElement/Matchbox/MatchboxFactory.cc
@@ -1,1735 +1,1761 @@
// -*- C++ -*-
//
// MatchboxFactory.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 MatchboxFactory class.
//
#include "MatchboxFactory.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/RefVector.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Command.h"
#include "ThePEG/Utilities/StringUtils.h"
#include "ThePEG/Repository/Repository.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Handlers/EventHandler.h"
#include "ThePEG/Handlers/SamplerBase.h"
#include "Herwig++/MatrixElement/Matchbox/Base/DipoleRepository.h"
#include "Herwig++/MatrixElement/Matchbox/Utility/SU2Helper.h"
#include "Herwig++/Utilities/RunDirectories.h"
#include <boost/progress.hpp>
#include <boost/filesystem.hpp>
#include <iterator>
using std::ostream_iterator;
using namespace Herwig;
using std::ostream_iterator;
MatchboxFactory::MatchboxFactory()
: SubProcessHandler(), theNLight(0),
theOrderInAlphaS(0), theOrderInAlphaEW(0),
theBornContributions(true), theVirtualContributions(true),
theRealContributions(true), theIndependentVirtuals(false),
theSubProcessGroups(false),
theFactorizationScaleFactor(1.0), theRenormalizationScaleFactor(1.0),
theFixedCouplings(false), theFixedQEDCouplings(false), theVetoScales(false),
theDipoleSet(0), theVerbose(false), theDiagramWeightVerbose(false),
theDiagramWeightVerboseNBins(200),
theInitVerbose(false),
theSubtractionData(""), theSubtractionPlotType(1), theSubtractionScatterPlot(false),
thePoleData(""), theRealEmissionScales(false), theAllProcesses(false),
theMECorrectionsOnly(false), theLoopSimCorrections(false), ranSetup(false),
theFirstPerturbativePDF(true), theSecondPerturbativePDF(true),
- inProductionMode(false) {}
+ inProductionMode(false), theFillRhoMatrices(false) {}
MatchboxFactory::~MatchboxFactory() {}
IBPtr MatchboxFactory::clone() const {
return new_ptr(*this);
}
IBPtr MatchboxFactory::fullclone() const {
return new_ptr(*this);
}
void MatchboxFactory::prepareME(Ptr<MatchboxMEBase>::ptr me) {
Ptr<MatchboxAmplitude>::ptr amp =
dynamic_ptr_cast<Ptr<MatchboxAmplitude>::ptr>((*me).amplitude());
me->matchboxAmplitude(amp);
me->factory(this);
if ( phasespace() && !me->phasespace() )
me->phasespace(phasespace());
if ( scaleChoice() && !me->scaleChoice() )
me->scaleChoice(scaleChoice());
if ( !reweighters().empty() ) {
for ( vector<ReweightPtr>::const_iterator rw = reweighters().begin();
rw != reweighters().end(); ++rw )
me->addReweighter(*rw);
}
if ( !preweighters().empty() ) {
for ( vector<ReweightPtr>::const_iterator rw = preweighters().begin();
rw != preweighters().end(); ++rw )
me->addPreweighter(*rw);
}
}
string pid(const PDVector& key) {
ostringstream res;
res << "[" << key[0]->PDGName() << ","
<< key[1]->PDGName() << "->";
for ( PDVector::const_iterator k =
key.begin() + 2; k != key.end(); ++k )
res << (**k).PDGName() << (k != --key.end() ? "," : "");
res << "]";
return res.str();
}
vector<Ptr<MatchboxMEBase>::ptr> MatchboxFactory::
makeMEs(const vector<string>& proc, unsigned int orderas, bool virt) {
generator()->log() << "determining subprocesses for ";
copy(proc.begin(),proc.end(),ostream_iterator<string>(generator()->log()," "));
generator()->log() << "\n" << flush;
map<Ptr<MatchboxAmplitude>::ptr,set<Process> > ampProcs;
map<Process,set<Ptr<MatchboxAmplitude>::ptr> > procAmps;
set<PDVector> processes = makeSubProcesses(proc);
vector<Ptr<MatchboxAmplitude>::ptr> matchAmplitudes;
unsigned int lowestAsOrder =
allProcesses() ? 0 : orderas;
unsigned int highestAsOrder = orderas;
unsigned int lowestAeOrder =
allProcesses() ? 0 : orderInAlphaEW();
unsigned int highestAeOrder = orderInAlphaEW();
for ( unsigned int oas = lowestAsOrder; oas <= highestAsOrder; ++oas ) {
for ( unsigned int oae = lowestAeOrder; oae <= highestAeOrder; ++oae ) {
for ( vector<Ptr<MatchboxAmplitude>::ptr>::const_iterator amp
= amplitudes().begin(); amp != amplitudes().end(); ++amp ) {
if ( !theSelectedAmplitudes.empty() ) {
if ( find(theSelectedAmplitudes.begin(),theSelectedAmplitudes.end(),*amp)
== theSelectedAmplitudes.end() )
continue;
}
if ( !theDeselectedAmplitudes.empty() ) {
if ( find(theDeselectedAmplitudes.begin(),theDeselectedAmplitudes.end(),*amp)
!= theDeselectedAmplitudes.end() )
continue;
}
(**amp).orderInGs(oas);
(**amp).orderInGem(oae);
if ( (**amp).orderInGs() != oas ||
(**amp).orderInGem() != oae ) {
continue;
}
matchAmplitudes.push_back(*amp);
}
}
}
size_t combinations = processes.size()*matchAmplitudes.size();
size_t procCount = 0;
generator()->log() << "building matrix elements." << flush;
boost::progress_display * progressBar =
new boost::progress_display(combinations,generator()->log());
for ( unsigned int oas = lowestAsOrder; oas <= highestAsOrder; ++oas ) {
for ( unsigned int oae = lowestAeOrder; oae <= highestAeOrder; ++oae ) {
for ( vector<Ptr<MatchboxAmplitude>::ptr>::const_iterator amp
= matchAmplitudes.begin(); amp != matchAmplitudes.end(); ++amp ) {
(**amp).orderInGs(oas);
(**amp).orderInGem(oae);
for ( set<PDVector>::const_iterator p = processes.begin();
p != processes.end(); ++p ) {
++(*progressBar);
if ( !(**amp).canHandle(*p,this,virt) )
continue;
if ( (**amp).isExternal() )
externalAmplitudes().insert(*amp);
++procCount;
Process proc(*p,oas,oae);
ampProcs[*amp].insert(proc);
procAmps[proc].insert(*amp);
}
}
}
}
delete progressBar;
generator()->log() << flush;
bool clash = false;
for ( map<Process,set<Ptr<MatchboxAmplitude>::ptr> >::const_iterator check =
procAmps.begin(); check != procAmps.end(); ++check ) {
if ( check->second.size() > 1 ) {
clash = true;
generator()->log() << "Several different amplitudes have been found for: "
<< check->first.legs[0]->PDGName() << " "
<< check->first.legs[1]->PDGName() << " -> ";
for ( PDVector::const_iterator p = check->first.legs.begin() + 2;
p != check->first.legs.end(); ++p )
generator()->log() << (**p).PDGName() << " ";
generator()->log() << "at alpha_s^" << check->first.orderInAlphaS
<< " and alpha_ew^" << check->first.orderInAlphaEW
<< "\n";
generator()->log() << "The following amplitudes claim responsibility:\n";
for ( set<Ptr<MatchboxAmplitude>::ptr>::const_iterator a = check->second.begin();
a != check->second.end(); ++a ) {
generator()->log() << (**a).name() << " ";
}
generator()->log() << "\n";
}
}
if ( clash ) {
throw InitException()
<< "Ambiguous amplitude setup - please check your input files.\n"
<< "To avoid this problem use the SelectAmplitudes or DeselectAmplitudes interfaces.\n";
}
vector<Ptr<MatchboxMEBase>::ptr> res;
for ( map<Ptr<MatchboxAmplitude>::ptr,set<Process> >::const_iterator
ap = ampProcs.begin(); ap != ampProcs.end(); ++ap ) {
for ( set<Process>::const_iterator m = ap->second.begin();
m != ap->second.end(); ++m ) {
Ptr<MatchboxMEBase>::ptr me = ap->first->makeME(m->legs);
me->subProcess() = *m;
me->amplitude(ap->first);
me->matchboxAmplitude(ap->first);
prepareME(me);
string pname = "ME" + ap->first->name() + pid(m->legs);
if ( ! (generator()->preinitRegister(me,pname) ) )
throw InitException() << "Matrix element " << pname << " already existing.";
if ( me->diagrams().empty() )continue;
res.push_back(me);
if ( theFirstPerturbativePDF )
theIncoming.insert(m->legs[0]->id());
if ( theSecondPerturbativePDF )
theIncoming.insert(m->legs[1]->id());
}
}
generator()->log() << "created "
<< procCount << " subprocesses.\n";
generator()->log() << "--------------------------------------------------------------------------------\n"
<< flush;
return res;
}
int MatchboxFactory::orderOLPProcess(const Process& proc,
Ptr<MatchboxAmplitude>::tptr amp,
int type) {
map<pair<Process,int>,int>& procs =
olpProcesses()[amp];
map<pair<Process,int>,int>::const_iterator it =
procs.find(make_pair(proc,type));
if ( it != procs.end() )
return it->second;
int id = procs.size();
procs[make_pair(proc,type)] = id + 1;
return id + 1;
}
void MatchboxFactory::productionMode() {
if ( inProductionMode )
return;
if ( !bornContributions() && !virtualContributions() && !realContributions() )
throw Exception()
<< "At least one cross section contribution needs to be enabled.\n"
<< "Please check your setup.\n"
<< Exception::abortnow;
bool needTrueVirtuals =
virtualContributions() && !meCorrectionsOnly() && !loopSimCorrections();
for ( vector<Ptr<MatchboxAmplitude>::ptr>::iterator amp
= amplitudes().begin(); amp != amplitudes().end(); ++amp ) {
if ( !needTrueVirtuals && (**amp).oneLoopAmplitude() ) {
Repository::clog() << "One-loop contributions from '"
<< (**amp).name()
<< "' are not required and will be disabled.\n"
<< flush;
(**amp).disableOneLoop();
}
}
if ( showerApproximation() && !virtualContributions() && !realContributions() ) {
Repository::clog() << "Warning: Matching requested for LO run. Matching disabled.\n" << flush;
showerApproximation(Ptr<ShowerApproximation>::tptr());
}
if ( showerApproximation() && (subtractionData() != "" || subProcessGroups()) ) {
Repository::clog() << "Warning: Matching requested for plain NLO run. Matching disabled.\n" << flush;
showerApproximation(Ptr<ShowerApproximation>::tptr());
}
+ if ( showerApproximation() ) {
+ if ( fillRhoMatrices() && !showerApproximation()->hasSpinCorrelations() ) {
+ Repository::clog() << "Warning: Spin correlations have been requested but the matching "
+ << "object is not capable of these. Spin correlations will be turned of.\n"
+ << flush;
+ theFillRhoMatrices = false;
+ }
+ }
+
inProductionMode = true;
}
void MatchboxFactory::setup() {
useMe();
if ( !ranSetup ) {
if ( !inProductionMode )
throw Exception() << "The MatchboxFactory object '"
<< name() << "' has not been switched to production mode.\n"
<< "Did you use 'do "
<< name() << "::ProductionMode' before isolating the event generator?\n"
<< Exception::abortnow;
olpProcesses().clear();
externalAmplitudes().clear();
theHighestVirtualsize = 0;
theIncoming.clear();
bool needTrueVirtuals =
virtualContributions() && !meCorrectionsOnly() && !loopSimCorrections();
for ( vector<Ptr<MatchboxAmplitude>::ptr>::iterator amp
= amplitudes().begin(); amp != amplitudes().end(); ++amp )
(**amp).factory(this);
if ( bornMEs().empty() ) {
if ( particleGroups().find("j") == particleGroups().end() )
throw InitException() << "Could not find a jet particle group named 'j'";
// rebind the particle data objects
for ( map<string,PDVector>::iterator g = particleGroups().begin();
g != particleGroups().end(); ++g )
for ( PDVector::iterator p = g->second.begin();
p != g->second.end(); ++p ) {
#ifndef NDEBUG
long checkid = (**p).id();
#endif
*p = getParticleData((**p).id());
assert((**p).id() == checkid);
}
const PDVector& partons = particleGroups()["j"];
unsigned int nl = 0;
for ( PDVector::const_iterator p = partons.begin();
p != partons.end(); ++p ) {
if ( abs((**p).id()) < 7 && (**p).mass() == ZERO )
++nl;
if ( (**p).id() > 0 && (**p).id() < 7 && (**p).mass() == ZERO )
nLightJetVec( (**p).id() );
if ( (**p).id() > 0 && (**p).id() < 7 && (**p).mass() != ZERO )
nHeavyJetVec( (**p).id() );
}
nLight(nl/2);
const PDVector& partonsInP = particleGroups()["p"];
for ( PDVector::const_iterator pip = partonsInP.begin();
pip != partonsInP.end(); ++pip ) {
if ( (**pip).id() > 0 && (**pip).id() < 7 && (**pip).mass() == ZERO )
nLightProtonVec( (**pip).id() );
}
vector<Ptr<MatchboxMEBase>::ptr> mes;
for ( vector<vector<string> >::const_iterator p = processes.begin();
p != processes.end(); ++p ) {
if( needTrueVirtuals ) {
theHighestVirtualsize = max(theHighestVirtualsize,(int((*p).size())));
}
mes = makeMEs(*p,orderInAlphaS(),needTrueVirtuals);
copy(mes.begin(),mes.end(),back_inserter(bornMEs()));
if ( (realContributions() || meCorrectionsOnly() ||
(showerApproximation() && virtualContributions()) ||
(showerApproximation() && loopSimCorrections()))
&& realEmissionMEs().empty() ) {
if ( realEmissionProcesses.empty() ) {
vector<string> rproc = *p;
rproc.push_back("j");
mes = makeMEs(rproc,orderInAlphaS()+1,false);
copy(mes.begin(),mes.end(),back_inserter(realEmissionMEs()));
}
}
}
if ( (realContributions() || meCorrectionsOnly() ||
(showerApproximation() && virtualContributions()) ||
(showerApproximation() && loopSimCorrections()))
&& realEmissionMEs().empty() ) {
if ( !realEmissionProcesses.empty() ) {
for ( vector<vector<string> >::const_iterator q =
realEmissionProcesses.begin(); q != realEmissionProcesses.end(); ++q ) {
mes = makeMEs(*q,orderInAlphaS()+1,false);
copy(mes.begin(),mes.end(),back_inserter(realEmissionMEs()));
}
}
}
}
if ( loopInducedMEs().empty() ) {
for ( vector<vector<string> >::const_iterator p = loopInducedProcesses.begin();
p != loopInducedProcesses.end(); ++p ) {
vector<Ptr<MatchboxMEBase>::ptr> mes = makeMEs(*p,orderInAlphaS(),false);
copy(mes.begin(),mes.end(),back_inserter(loopInducedMEs()));
}
}
if( bornMEs().empty() && realEmissionMEs().empty() && loopInducedMEs().empty() )
throw InitException() << "No matrix elements have been found.\n\
Please check if your order of Alpha_s and Alpha_ew have the right value.\n";
// check if we have virtual contributions
bool haveVirtuals = true;
// check DR conventions of virtual contributions
bool virtualsAreDR = false;
bool virtualsAreCDR = false;
// check finite term conventions of virtual contributions
bool virtualsAreCS = false;
bool virtualsAreBDK = false;
bool virtualsAreExpanded = false;
// renormalization scheme
bool virtualsAreDRbar = false;
// check and prepare the Born and virtual matrix elements
for ( vector<Ptr<MatchboxMEBase>::ptr>::iterator born
= bornMEs().begin(); born != bornMEs().end(); ++born ) {
prepareME(*born);
haveVirtuals &= (**born).haveOneLoop();
if ( needTrueVirtuals ) {
if ( (**born).haveOneLoop() ) {
virtualsAreDRbar |= (**born).isDRbar();
virtualsAreDR |= (**born).isDR();
virtualsAreCDR |= !(**born).isDR();
virtualsAreCS |= (**born).isCS();
virtualsAreBDK |= (**born).isBDK();
virtualsAreExpanded |= (**born).isExpanded();
}
}
}
// prepare the loop induced matrix elements
for ( vector<Ptr<MatchboxMEBase>::ptr>::iterator looped
= loopInducedMEs().begin(); looped != loopInducedMEs().end(); ++looped ) {
prepareME(*looped);
}
if ( needTrueVirtuals ) {
// check the additional insertion operators
if ( !virtuals().empty() )
haveVirtuals = true;
for ( vector<Ptr<MatchboxInsertionOperator>::ptr>::const_iterator virt
= virtuals().begin(); virt != virtuals().end(); ++virt ) {
virtualsAreDRbar |= (**virt).isDRbar();
virtualsAreDR |= (**virt).isDR();
virtualsAreCDR |= !(**virt).isDR();
virtualsAreCS |= (**virt).isCS();
virtualsAreBDK |= (**virt).isBDK();
virtualsAreExpanded |= (**virt).isExpanded();
}
// check for consistent conventions on virtuals, if we are to include them
if ( virtualContributions() ) {
if ( !haveVirtuals ) {
throw InitException() << "Could not find amplitudes for all virtual contributions needed.\n";
}
if ( virtualsAreDR && virtualsAreCDR ) {
throw InitException() << "Virtual corrections use inconsistent regularization schemes.\n";
}
if ( (virtualsAreCS && virtualsAreBDK) ||
(virtualsAreCS && virtualsAreExpanded) ||
(virtualsAreBDK && virtualsAreExpanded) ||
(!virtualsAreCS && !virtualsAreBDK && !virtualsAreExpanded) ) {
throw InitException() << "Virtual corrections use inconsistent conventions on finite terms.\n";
}
}
// prepare dipole insertion operators
if ( virtualContributions() ) {
for ( vector<Ptr<MatchboxInsertionOperator>::ptr>::const_iterator virt
= DipoleRepository::insertionOperators(dipoleSet()).begin();
virt != DipoleRepository::insertionOperators(dipoleSet()).end(); ++virt ) {
(**virt).factory(this);
if ( virtualsAreDRbar )
(**virt).useDRbar();
if ( virtualsAreDR )
(**virt).useDR();
else
(**virt).useCDR();
if ( virtualsAreCS )
(**virt).useCS();
if ( virtualsAreBDK )
(**virt).useBDK();
if ( virtualsAreExpanded )
(**virt).useExpanded();
}
}
}
// prepare the real emission matrix elements
if ( realContributions() || meCorrectionsOnly() ||
(showerApproximation() && virtualContributions()) ||
(showerApproximation() && loopSimCorrections()) ) {
for ( vector<Ptr<MatchboxMEBase>::ptr>::iterator real
= realEmissionMEs().begin(); real != realEmissionMEs().end(); ++real ) {
prepareME(*real);
}
}
// start creating matrix elements
MEs().clear();
// setup born and virtual contributions
if ( bornContributions() || virtualContributions() ) {
generator()->log() << "preparing Born"
<< (virtualContributions() ? " and virtual" : "")
<< " matrix elements.\n" << flush;
}
if ( (bornContributions() && !virtualContributions()) ||
(bornContributions() && virtualContributions() && independentVirtuals()) ) {
for ( vector<Ptr<MatchboxMEBase>::ptr>::iterator born
= bornMEs().begin(); born != bornMEs().end(); ++born ) {
if ( (**born).onlyOneLoop() )
continue;
Ptr<MatchboxMEBase>::ptr bornme = (**born).cloneMe();
string pname = fullName() + "/" + (**born).name();
if ( independentVirtuals() )
pname += ".Born";
if ( ! (generator()->preinitRegister(bornme,pname) ) )
throw InitException() << "Matrix element " << pname << " already existing.";
if ( bornme->isOLPTree() ) {
int id = orderOLPProcess(bornme->subProcess(),
(**born).matchboxAmplitude(),
ProcessType::treeME2);
bornme->olpProcess(ProcessType::treeME2,id);
}
bornme->needsNoCorrelations();
bornme->cloneDependencies();
MEs().push_back(bornme);
}
}
if ( bornContributions() && !loopInducedMEs().empty() ) {
for ( vector<Ptr<MatchboxMEBase>::ptr>::iterator looped
= loopInducedMEs().begin(); looped != loopInducedMEs().end(); ++looped ) {
Ptr<MatchboxMEBase>::ptr loopme = (**looped).cloneMe();
string pname = fullName() + "/" + (**looped).name() + ".LoopInduced";
if ( ! (generator()->preinitRegister(loopme,pname) ) )
throw InitException() << "Matrix element " << pname << " already existing.";
if ( loopme->isOLPTree() ) {
int id = orderOLPProcess(loopme->subProcess(),
(**looped).matchboxAmplitude(),
ProcessType::loopInducedME2);
loopme->olpProcess(ProcessType::loopInducedME2,id);
}
loopme->needsNoCorrelations();
loopme->cloneDependencies();
MEs().push_back(loopme);
}
}
if ( needTrueVirtuals ) {
bornVirtualMEs().clear();
boost::progress_display * progressBar =
new boost::progress_display(bornMEs().size(),generator()->log());
if ( thePoleData != "" )
if ( thePoleData[thePoleData.size()-1] != '/' )
thePoleData += "/";
for ( vector<Ptr<MatchboxMEBase>::ptr>::iterator born
= bornMEs().begin(); born != bornMEs().end(); ++born ) {
Ptr<MatchboxMEBase>::ptr nlo = (**born).cloneMe();
string pname = fullName() + "/" + (**born).name();
if ( !independentVirtuals() && !(!bornContributions() && virtualContributions()) )
pname += ".BornVirtual";
else
pname += ".Virtual";
if ( ! (generator()->preinitRegister(nlo,pname) ) )
throw InitException() << "NLO ME " << pname << " already existing.";
nlo->virtuals().clear();
if ( !nlo->onlyOneLoop() ) {
for ( vector<Ptr<MatchboxInsertionOperator>::ptr>::const_iterator virt
= virtuals().begin(); virt != virtuals().end(); ++virt ) {
if ( (**virt).apply((**born).diagrams().front()->partons()) )
nlo->virtuals().push_back(*virt);
}
for ( vector<Ptr<MatchboxInsertionOperator>::ptr>::const_iterator virt
= DipoleRepository::insertionOperators(dipoleSet()).begin();
virt != DipoleRepository::insertionOperators(dipoleSet()).end(); ++virt ) {
if ( (**virt).apply((**born).diagrams().front()->partons()) )
nlo->virtuals().push_back(*virt);
}
if ( nlo->virtuals().empty() )
throw InitException() << "No insertion operators have been found for "
<< (**born).name() << "\n";
if ( checkPoles() ) {
if ( !virtualsAreExpanded ) {
throw InitException() << "Cannot check epsilon poles if virtuals are not in `expanded' convention.\n";
}
}
}
if ( !bornContributions() || independentVirtuals() ) {
nlo->doOneLoopNoBorn();
} else {
nlo->doOneLoop();
}
if ( nlo->isOLPLoop() ) {
int id = orderOLPProcess(nlo->subProcess(),
(**born).matchboxAmplitude(),
ProcessType::oneLoopInterference);
nlo->olpProcess(ProcessType::oneLoopInterference,id);
if ( !nlo->onlyOneLoop() && nlo->needsOLPCorrelators() ) {
id = orderOLPProcess(nlo->subProcess(),
(**born).matchboxAmplitude(),
ProcessType::colourCorrelatedME2);
nlo->olpProcess(ProcessType::colourCorrelatedME2,id);
}
}
nlo->needsCorrelations();
nlo->cloneDependencies();
bornVirtualMEs().push_back(nlo);
MEs().push_back(nlo);
++(*progressBar);
}
delete progressBar;
generator()->log() << "--------------------------------------------------------------------------------\n"
<< flush;
}
theSplittingDipoles.clear();
set<cPDVector> bornProcs;
if ( showerApproximation() ) {
if ( showerApproximation()->needsSplittingGenerator() ) {
for ( vector<Ptr<MatchboxMEBase>::ptr>::iterator born
= bornMEs().begin(); born != bornMEs().end(); ++born )
for ( MEBase::DiagramVector::const_iterator d = (**born).diagrams().begin();
d != (**born).diagrams().end(); ++d )
bornProcs.insert((**d).partons());
}
}
if ( realContributions() || meCorrectionsOnly() ||
(showerApproximation() && virtualContributions()) ||
(showerApproximation() && loopSimCorrections()) ) {
generator()->log() << "preparing subtracted matrix elements.\n" << flush;
if ( theSubtractionData != "" )
if ( theSubtractionData[theSubtractionData.size()-1] != '/' )
theSubtractionData += "/";
subtractedMEs().clear();
for ( vector<Ptr<MatchboxMEBase>::ptr>::iterator born
= bornMEs().begin(); born != bornMEs().end(); ++born ) {
if ( (**born).onlyOneLoop() )
continue;
(**born).needsCorrelations();
if ( (**born).isOLPTree() ) {
int id = orderOLPProcess((**born).subProcess(),
(**born).matchboxAmplitude(),
ProcessType::colourCorrelatedME2);
(**born).olpProcess(ProcessType::colourCorrelatedME2,id);
bool haveGluon = false;
for ( PDVector::const_iterator p = (**born).subProcess().legs.begin();
p != (**born).subProcess().legs.end(); ++p )
if ( (**p).id() == 21 ) {
haveGluon = true;
break;
}
if ( haveGluon ) {
id = orderOLPProcess((**born).subProcess(),
(**born).matchboxAmplitude(),
ProcessType::spinColourCorrelatedME2);
(**born).olpProcess(ProcessType::spinColourCorrelatedME2,id);
}
}
}
boost::progress_display * progressBar =
new boost::progress_display(realEmissionMEs().size(),generator()->log());
for ( vector<Ptr<MatchboxMEBase>::ptr>::iterator real
= realEmissionMEs().begin(); real != realEmissionMEs().end(); ++real ) {
Ptr<SubtractedME>::ptr sub = new_ptr(SubtractedME());
string pname = fullName() + "/" + (**real).name() + ".SubtractedReal";
if ( ! (generator()->preinitRegister(sub,pname) ) )
throw InitException() << "Subtracted ME " << pname << " already existing.";
sub->factory(this);
(**real).needsNoCorrelations();
if ( (**real).isOLPTree() ) {
int id = orderOLPProcess((**real).subProcess(),
(**real).matchboxAmplitude(),
ProcessType::treeME2);
(**real).olpProcess(ProcessType::treeME2,id);
}
sub->head(*real);
sub->dependent().clear();
sub->getDipoles();
if ( sub->dependent().empty() && realContributions() ) {
// finite real contribution
Ptr<MatchboxMEBase>::ptr fme =
dynamic_ptr_cast<Ptr<MatchboxMEBase>::ptr>(sub->head())->cloneMe();
string qname = fullName() + "/" + (**real).name() + ".FiniteReal";
if ( ! (generator()->preinitRegister(fme,qname) ) )
throw InitException() << "ME " << qname << " already existing.";
MEs().push_back(fme);
finiteRealMEs().push_back(fme);
sub->head(tMEPtr());
continue;
}
if ( realEmissionScales() )
sub->doRealEmissionScales();
subtractedMEs().push_back(sub);
if ( realContributions() )
if ( !showerApproximation() || (showerApproximation() && showerApproximation()->hasHEvents()) )
MEs().push_back(sub);
if ( showerApproximation() ) {
if ( virtualContributions() && !meCorrectionsOnly() && !loopSimCorrections() ) {
Ptr<SubtractedME>::ptr subv = new_ptr(*sub);
string vname = sub->fullName() + ".SubtractionIntegral";
if ( ! (generator()->preinitRegister(subv,vname) ) )
throw InitException() << "Subtracted ME " << vname << " already existing.";
subv->cloneDependencies(vname);
subv->doVirtualShowerSubtraction();
subtractedMEs().push_back(subv);
MEs().push_back(subv);
}
if ( loopSimCorrections() ) {
Ptr<SubtractedME>::ptr subv = new_ptr(*sub);
string vname = sub->fullName() + ".SubtractionIntegral";
if ( ! (generator()->preinitRegister(subv,vname) ) )
throw InitException() << "Subtracted ME " << vname << " already existing.";
subv->cloneDependencies(vname);
subv->doLoopSimSubtraction();
subtractedMEs().push_back(subv);
MEs().push_back(subv);
}
sub->doRealShowerSubtraction();
if ( showerApproximation()->needsSplittingGenerator() )
for ( set<cPDVector>::const_iterator p = bornProcs.begin();
p != bornProcs.end(); ++p ) {
vector<Ptr<SubtractionDipole>::ptr> sdip = sub->splitDipoles(*p);
set<Ptr<SubtractionDipole>::ptr>& dips = theSplittingDipoles[*p];
copy(sdip.begin(),sdip.end(),inserter(dips,dips.begin()));
}
}
++(*progressBar);
}
delete progressBar;
generator()->log() << "--------------------------------------------------------------------------------\n"
<< flush;
}
if ( !theSplittingDipoles.empty() ) {
map<Ptr<SubtractionDipole>::ptr,Ptr<SubtractionDipole>::ptr> cloneMap;
for ( map<cPDVector,set<Ptr<SubtractionDipole>::ptr> >::const_iterator sd = theSplittingDipoles.begin();
sd != theSplittingDipoles.end(); ++sd ) {
for ( set<Ptr<SubtractionDipole>::ptr>::const_iterator d = sd->second.begin();
d != sd->second.end(); ++d ) {
cloneMap[*d] = Ptr<SubtractionDipole>::ptr();
}
}
for ( map<Ptr<SubtractionDipole>::ptr,Ptr<SubtractionDipole>::ptr>::iterator cd =
cloneMap.begin(); cd != cloneMap.end(); ++cd ) {
Ptr<SubtractionDipole>::ptr cloned = cd->first->cloneMe();
string dname = cd->first->fullName() + ".splitting";
if ( ! (generator()->preinitRegister(cloned,dname)) )
throw InitException() << "Dipole '" << dname << "' already existing.";
cloned->cloneDependencies();
cloned->showerApproximation(Ptr<ShowerApproximation>::tptr());
cloned->doSplitting();
cd->second = cloned;
}
for ( map<cPDVector,set<Ptr<SubtractionDipole>::ptr> >::iterator sd = theSplittingDipoles.begin();
sd != theSplittingDipoles.end(); ++sd ) {
set<Ptr<SubtractionDipole>::ptr> cloned;
for ( set<Ptr<SubtractionDipole>::ptr>::iterator d = sd->second.begin();
d != sd->second.end(); ++d ) {
cloned.insert(cloneMap[*d]);
}
sd->second = cloned;
}
}
if ( !externalAmplitudes().empty() ) {
generator()->log() << "Initializing external amplitudes.\n" << flush;
for ( set<Ptr<MatchboxAmplitude>::tptr>::const_iterator ext =
externalAmplitudes().begin(); ext != externalAmplitudes().end(); ++ext ) {
if ( !(**ext).initializeExternal() ) {
throw InitException()
<< "error: failed to initialize amplitude '" << (**ext).name() << "'\n";
}
}
generator()->log() << "--------------------------------------------------------------------------------\n"
<< flush;
}
if ( !olpProcesses().empty() ) {
generator()->log() << "Initializing one-loop provider(s).\n" << flush;
map<Ptr<MatchboxAmplitude>::tptr,map<pair<Process,int>,int> > olps;
for ( map<Ptr<MatchboxAmplitude>::tptr,map<pair<Process,int>,int> >::const_iterator
oit = olpProcesses().begin(); oit != olpProcesses().end(); ++oit ) {
olps[oit->first] = oit->second;
}
for ( map<Ptr<MatchboxAmplitude>::tptr,map<pair<Process,int>,int> >::const_iterator
olpit = olps.begin(); olpit != olps.end(); ++olpit ) {
if ( !olpit->first->startOLP(olpit->second) ) {
throw InitException()
<< "error: failed to start OLP for amplitude '" << olpit->first->name() << "'\n";
}
}
generator()->log() << "--------------------------------------------------------------------------------\n"
<< flush;
}
generator()->log() << "Process setup finished.\n" << flush;
ranSetup = true;
}
}
void MatchboxFactory::SplittingChannel::print(ostream& os) const {
os << "--- SplittingChannel setup -----------------------------------------------------\n";
os << " Born process ";
const StandardXComb& bxc = *bornXComb;
os << bxc.mePartonData()[0]->PDGName() << " "
<< bxc.mePartonData()[1]->PDGName() << " -> ";
for ( cPDVector::const_iterator p = bxc.mePartonData().begin() + 2;
p != bxc.mePartonData().end(); ++p ) {
os << (**p).PDGName() << " ";
}
os << "\n";
os << " to real emission process ";
const StandardXComb& rxc = *realXComb;
os << rxc.mePartonData()[0]->PDGName() << " "
<< rxc.mePartonData()[1]->PDGName() << " -> ";
for ( cPDVector::const_iterator p = rxc.mePartonData().begin() + 2;
p != rxc.mePartonData().end(); ++p ) {
os << (**p).PDGName() << " ";
}
os << "\n";
os << " with dipole:\n";
dipole->print(os);
os << "--------------------------------------------------------------------------------\n";
os << flush;
}
list<MatchboxFactory::SplittingChannel>
MatchboxFactory::getSplittingChannels(tStdXCombPtr xcptr) const {
if ( xcptr->lastProjector() )
xcptr = xcptr->lastProjector();
const StandardXComb& xc = *xcptr;
cPDVector proc = xc.mePartonData();
map<cPDVector,set<Ptr<SubtractionDipole>::ptr> >::const_iterator splitEntries
= splittingDipoles().find(proc);
list<SplittingChannel> res;
if ( splitEntries == splittingDipoles().end() )
return res;
const set<Ptr<SubtractionDipole>::ptr>& splitDipoles = splitEntries->second;
SplittingChannel channel;
if ( !splitDipoles.empty() ) {
Ptr<MatchboxMEBase>::tptr bornME =
const_ptr_cast<Ptr<MatchboxMEBase>::tptr>((**splitDipoles.begin()).underlyingBornME());
channel.bornXComb =
bornME->makeXComb(xc.maxEnergy(),xc.particles(),xc.eventHandlerPtr(),
const_ptr_cast<tSubHdlPtr>(xc.subProcessHandler()),
xc.pExtractor(),xc.CKKWHandler(),
xc.partonBins(),xc.cuts(),xc.diagrams(),xc.mirror(),
PartonPairVec());
}
for ( set<Ptr<SubtractionDipole>::ptr>::const_iterator sd =
splitDipoles.begin(); sd != splitDipoles.end(); ++sd ) {
channel.dipole = *sd;
vector<StdXCombPtr> realXCombs = (**sd).makeRealXCombs(channel.bornXComb);
for ( vector<StdXCombPtr>::const_iterator rxc = realXCombs.begin();
rxc != realXCombs.end(); ++rxc ) {
channel.realXComb = *rxc;
if ( showerApproximation()->needsTildeXCombs() ) {
channel.tildeXCombs.clear();
assert(!channel.dipole->partnerDipoles().empty());
for ( vector<Ptr<SubtractionDipole>::ptr>::const_iterator p =
channel.dipole->partnerDipoles().begin();
p != channel.dipole->partnerDipoles().end(); ++p ) {
StdXCombPtr txc = channel.dipole->makeBornXComb(channel.realXComb);
if ( txc )
channel.tildeXCombs.push_back(txc);
}
}
res.push_back(channel);
}
}
if ( initVerbose() ) {
generator()->log()
<< "--- MatchboxFactory splitting channels ----------------------------------------------\n";
const StandardXComb& bxc = *xcptr;
generator()->log() << " hard process handled is: ";
generator()->log() << bxc.mePartonData()[0]->PDGName() << " "
<< bxc.mePartonData()[1]->PDGName() << " -> ";
for ( cPDVector::const_iterator p = bxc.mePartonData().begin() + 2;
p != bxc.mePartonData().end(); ++p ) {
generator()->log() << (**p).PDGName() << " ";
}
generator()->log() << "\n";
for ( list<MatchboxFactory::SplittingChannel>::const_iterator sp =
res.begin(); sp != res.end(); ++sp ) {
sp->print(generator()->log());
}
generator()->log()
<< "-------------------------------------------------------------------------------------\n"
<< flush;
}
return res;
}
void MatchboxFactory::print(ostream& os) const {
os << "--- MatchboxFactory setup -----------------------------------------------------------\n";
if ( !amplitudes().empty() ) {
os << " generated Born matrix elements:\n";
for ( vector<Ptr<MatchboxMEBase>::ptr>::const_iterator m = bornMEs().begin();
m != bornMEs().end(); ++m ) {
(**m).print(os);
}
os << flush;
os << " generated real emission matrix elements:\n";
for ( vector<Ptr<MatchboxMEBase>::ptr>::const_iterator m = realEmissionMEs().begin();
m != realEmissionMEs().end(); ++m ) {
(**m).print(os);
}
os << flush;
}
os << " generated Born+virtual matrix elements:\n";
for ( vector<Ptr<MatchboxMEBase>::ptr>::const_iterator bv
= bornVirtualMEs().begin(); bv != bornVirtualMEs().end(); ++bv ) {
(**bv).print(os);
}
os << " generated subtracted matrix elements:\n";
for ( vector<Ptr<SubtractedME>::ptr>::const_iterator sub
= subtractedMEs().begin(); sub != subtractedMEs().end(); ++sub ) {
os << " '" << (**sub).name() << "'\n";
}
os << "--------------------------------------------------------------------------------\n";
os << flush;
}
void MatchboxFactory::doinit() {
if ( RunDirectories::empty() )
RunDirectories::pushRunId(generator()->runName());
setup();
if ( theShowerApproximation )
theShowerApproximation->init();
if ( initVerbose() && !ranSetup )
print(Repository::clog());
Ptr<StandardEventHandler>::tptr eh =
dynamic_ptr_cast<Ptr<StandardEventHandler>::tptr>(generator()->eventHandler());
assert(eh);
SubProcessHandler::doinit();
}
void MatchboxFactory::doinitrun() {
if ( theShowerApproximation )
theShowerApproximation->initrun();
Ptr<StandardEventHandler>::tptr eh =
dynamic_ptr_cast<Ptr<StandardEventHandler>::tptr>(generator()->eventHandler());
assert(eh);
SubProcessHandler::doinitrun();
}
const string& MatchboxFactory::buildStorage() {
return RunDirectories::buildStorage();
}
const string& MatchboxFactory::runStorage() {
return RunDirectories::runStorage();
}
void MatchboxFactory::persistentOutput(PersistentOStream & os) const {
os << theDiagramGenerator << theProcessData
<< theNLight
<< theNLightJetVec << theNHeavyJetVec << theNLightProtonVec
<< theOrderInAlphaS << theOrderInAlphaEW
<< theBornContributions << theVirtualContributions
<< theRealContributions << theIndependentVirtuals << theSubProcessGroups
<< thePhasespace << theScaleChoice
<< theFactorizationScaleFactor << theRenormalizationScaleFactor
<< theFixedCouplings << theFixedQEDCouplings << theVetoScales
<< theAmplitudes
<< theBornMEs << theVirtuals << theRealEmissionMEs << theLoopInducedMEs
<< theBornVirtualMEs << theSubtractedMEs << theFiniteRealMEs
<< theVerbose<<theDiagramWeightVerbose
<<theDiagramWeightVerboseNBins
<< theInitVerbose << theSubtractionData << theSubtractionPlotType
<< theSubtractionScatterPlot << thePoleData
<< theParticleGroups << processes << loopInducedProcesses << realEmissionProcesses
<< theShowerApproximation << theSplittingDipoles
<< theRealEmissionScales << theAllProcesses
<< theOLPProcesses << theExternalAmplitudes
<< theSelectedAmplitudes << theDeselectedAmplitudes
<< theDipoleSet << theReweighters << thePreweighters
<< theMECorrectionsOnly<< theLoopSimCorrections<<theHighestVirtualsize << ranSetup
- << theIncoming << theFirstPerturbativePDF << theSecondPerturbativePDF << inProductionMode;
+ << theIncoming << theFirstPerturbativePDF << theSecondPerturbativePDF
+ << inProductionMode << theFillRhoMatrices;
}
void MatchboxFactory::persistentInput(PersistentIStream & is, int) {
is >> theDiagramGenerator >> theProcessData
>> theNLight
>> theNLightJetVec >> theNHeavyJetVec >> theNLightProtonVec
>> theOrderInAlphaS >> theOrderInAlphaEW
>> theBornContributions >> theVirtualContributions
>> theRealContributions >> theIndependentVirtuals >> theSubProcessGroups
>> thePhasespace >> theScaleChoice
>> theFactorizationScaleFactor >> theRenormalizationScaleFactor
>> theFixedCouplings >> theFixedQEDCouplings >> theVetoScales
>> theAmplitudes
>> theBornMEs >> theVirtuals >> theRealEmissionMEs >> theLoopInducedMEs
>> theBornVirtualMEs >> theSubtractedMEs >> theFiniteRealMEs
>> theVerbose >> theDiagramWeightVerbose
>> theDiagramWeightVerboseNBins
>> theInitVerbose >> theSubtractionData >> theSubtractionPlotType
>> theSubtractionScatterPlot >> thePoleData
>> theParticleGroups >> processes >> loopInducedProcesses >> realEmissionProcesses
>> theShowerApproximation >> theSplittingDipoles
>> theRealEmissionScales >> theAllProcesses
>> theOLPProcesses >> theExternalAmplitudes
>> theSelectedAmplitudes >> theDeselectedAmplitudes
>> theDipoleSet >> theReweighters >> thePreweighters
>> theMECorrectionsOnly>> theLoopSimCorrections>>theHighestVirtualsize >> ranSetup
- >> theIncoming >> theFirstPerturbativePDF >> theSecondPerturbativePDF >> inProductionMode;
+ >> theIncoming >> theFirstPerturbativePDF >> theSecondPerturbativePDF
+ >> inProductionMode >> theFillRhoMatrices;
}
string MatchboxFactory::startParticleGroup(string name) {
particleGroupName = StringUtils::stripws(name);
particleGroup.clear();
return "";
}
string MatchboxFactory::endParticleGroup(string) {
if ( particleGroup.empty() )
throw InitException() << "Empty particle group.";
particleGroups()[particleGroupName] = particleGroup;
particleGroup.clear();
return "";
}
string MatchboxFactory::doProcess(string in) {
vector<string> process = StringUtils::split(in);
if ( process.size() < 3 )
throw InitException() << "Invalid process.";
for ( vector<string>::iterator p = process.begin();
p != process.end(); ++p ) {
*p = StringUtils::stripws(*p);
}
processes.push_back(process);
return "";
}
string MatchboxFactory::doLoopInducedProcess(string in) {
vector<string> loopInducedProcess = StringUtils::split(in);
if ( loopInducedProcess.size() < 3 )
throw InitException() << "Invalid process.";
for ( vector<string>::iterator p = loopInducedProcess.begin();
p != loopInducedProcess.end(); ++p ) {
*p = StringUtils::stripws(*p);
}
loopInducedProcesses.push_back(loopInducedProcess);
return "";
}
string MatchboxFactory::doSingleRealProcess(string in) {
vector<string> realEmissionProcess = StringUtils::split(in);
if ( realEmissionProcess.size() < 3 )
throw InitException() << "Invalid process.";
for ( vector<string>::iterator p = realEmissionProcess.begin();
p != realEmissionProcess.end(); ++p ) {
*p = StringUtils::stripws(*p);
}
realEmissionProcesses.push_back(realEmissionProcess);
return "";
}
struct SortPID {
inline bool operator()(PDPtr a, PDPtr b) const {
return a->id() < b->id();
}
};
set<PDVector> MatchboxFactory::
makeSubProcesses(const vector<string>& proc) const {
if ( proc.empty() )
throw InitException() << "No process specified.";
vector<PDVector> groups;
typedef map<string,PDVector>::const_iterator GroupIterator;
for ( vector<string>::const_iterator gr = proc.begin();
gr != proc.end(); ++gr ) {
GroupIterator git = particleGroups().find(*gr);
if ( git == particleGroups().end() ) {
throw InitException() << "particle group '"
<< *gr << "' not defined.";
}
groups.push_back(git->second);
}
vector<size_t> counts(groups.size(),0);
PDVector proto(groups.size());
set<PDVector> allProcs;
/*
cerr << "using the groups:\n";
for ( size_t k = 0; k < groups.size(); ++k ) {
cerr << k << " : ";
for ( PDVector::const_iterator p = groups[k].begin();
p != groups[k].end(); ++p )
cerr << (**p).PDGName() << " ";
cerr << "\n" << flush;
}
*/
while ( true ) {
for ( size_t k = 0; k < groups.size(); ++k )
proto[k] = groups[k][counts[k]];
/*
cerr << "trying : ";
for ( vector<size_t>::const_iterator c = counts.begin();
c != counts.end(); ++c )
cerr << *c << " ";
cerr << "\n" << flush;
for ( size_t k = 0; k < groups.size(); ++k )
cerr << groups[k][counts[k]]->PDGName() << " ";
cerr << "\n" << flush;
*/
int charge = -proto[0]->iCharge() -proto[1]->iCharge();
for ( size_t k = 2; k < proto.size(); ++k )
charge += proto[k]->iCharge();
if ( charge == 0 ) {
sort(proto.begin()+2,proto.end(),SortPID());
allProcs.insert(proto);
}
vector<size_t>::reverse_iterator c = counts.rbegin();
vector<PDVector>::const_reverse_iterator g = groups.rbegin();
while ( c != counts.rend() ) {
if ( ++(*c) == g->size() ) {
*c = 0;
++c; ++g;
} else {
break;
}
}
if ( c == counts.rend() )
break;
}
return allProcs;
}
void MatchboxFactory::Init() {
static ClassDocumentation<MatchboxFactory> documentation
("MatchboxFactory",
"NLO QCD corrections have been calculated "
"using Matchbox \\cite{Platzer:2011bc}",
"%\\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 Reference<MatchboxFactory,Tree2toNGenerator> interfaceDiagramGenerator
("DiagramGenerator",
"Set the diagram generator.",
&MatchboxFactory::theDiagramGenerator, false, false, true, true, false);
static Reference<MatchboxFactory,ProcessData> interfaceProcessData
("ProcessData",
"Set the process data object to be used.",
&MatchboxFactory::theProcessData, false, false, true, true, false);
static Parameter<MatchboxFactory,unsigned int> interfaceOrderInAlphaS
("OrderInAlphaS",
"The order in alpha_s to consider.",
&MatchboxFactory::theOrderInAlphaS, 0, 0, 0,
false, false, Interface::lowerlim);
static Parameter<MatchboxFactory,unsigned int> interfaceOrderInAlphaEW
("OrderInAlphaEW",
"The order in alpha_EW",
&MatchboxFactory::theOrderInAlphaEW, 2, 0, 0,
false, false, Interface::lowerlim);
static Switch<MatchboxFactory,bool> interfaceBornContributions
("BornContributions",
"Switch on or off the Born contributions.",
&MatchboxFactory::theBornContributions, true, false, false);
static SwitchOption interfaceBornContributionsOn
(interfaceBornContributions,
"On",
"Switch on Born contributions.",
true);
static SwitchOption interfaceBornContributionsOff
(interfaceBornContributions,
"Off",
"Switch off Born contributions.",
false);
static Switch<MatchboxFactory,bool> interfaceVirtualContributions
("VirtualContributions",
"Switch on or off the virtual contributions.",
&MatchboxFactory::theVirtualContributions, true, false, false);
static SwitchOption interfaceVirtualContributionsOn
(interfaceVirtualContributions,
"On",
"Switch on virtual contributions.",
true);
static SwitchOption interfaceVirtualContributionsOff
(interfaceVirtualContributions,
"Off",
"Switch off virtual contributions.",
false);
static Switch<MatchboxFactory,bool> interfaceRealContributions
("RealContributions",
"Switch on or off the real contributions.",
&MatchboxFactory::theRealContributions, true, false, false);
static SwitchOption interfaceRealContributionsOn
(interfaceRealContributions,
"On",
"Switch on real contributions.",
true);
static SwitchOption interfaceRealContributionsOff
(interfaceRealContributions,
"Off",
"Switch off real contributions.",
false);
static Switch<MatchboxFactory,bool> interfaceIndependentVirtuals
("IndependentVirtuals",
"Switch on or off virtual contributions as separate subprocesses.",
&MatchboxFactory::theIndependentVirtuals, true, false, false);
static SwitchOption interfaceIndependentVirtualsOn
(interfaceIndependentVirtuals,
"On",
"Switch on virtual contributions as separate subprocesses.",
true);
static SwitchOption interfaceIndependentVirtualsOff
(interfaceIndependentVirtuals,
"Off",
"Switch off virtual contributions as separate subprocesses.",
false);
static Switch<MatchboxFactory,bool> interfaceSubProcessGroups
("SubProcessGroups",
"Switch on or off production of sub-process groups.",
&MatchboxFactory::theSubProcessGroups, false, false, false);
static SwitchOption interfaceSubProcessGroupsOn
(interfaceSubProcessGroups,
"On",
"On",
true);
static SwitchOption interfaceSubProcessGroupsOff
(interfaceSubProcessGroups,
"Off",
"Off",
false);
static Reference<MatchboxFactory,MatchboxPhasespace> interfacePhasespace
("Phasespace",
"Set the phasespace generator.",
&MatchboxFactory::thePhasespace, false, false, true, true, false);
static Reference<MatchboxFactory,MatchboxScaleChoice> interfaceScaleChoice
("ScaleChoice",
"Set the scale choice object.",
&MatchboxFactory::theScaleChoice, false, false, true, true, false);
static Parameter<MatchboxFactory,double> interfaceFactorizationScaleFactor
("FactorizationScaleFactor",
"The factorization scale factor.",
&MatchboxFactory::theFactorizationScaleFactor, 1.0, 0.0, 0,
false, false, Interface::lowerlim);
static Parameter<MatchboxFactory,double> interfaceRenormalizationScaleFactor
("RenormalizationScaleFactor",
"The renormalization scale factor.",
&MatchboxFactory::theRenormalizationScaleFactor, 1.0, 0.0, 0,
false, false, Interface::lowerlim);
static Switch<MatchboxFactory,bool> interfaceFixedCouplings
("FixedCouplings",
"Switch on or off fixed couplings.",
&MatchboxFactory::theFixedCouplings, true, false, false);
static SwitchOption interfaceFixedCouplingsOn
(interfaceFixedCouplings,
"On",
"On",
true);
static SwitchOption interfaceFixedCouplingsOff
(interfaceFixedCouplings,
"Off",
"Off",
false);
static Switch<MatchboxFactory,bool> interfaceFixedQEDCouplings
("FixedQEDCouplings",
"Switch on or off fixed QED couplings.",
&MatchboxFactory::theFixedQEDCouplings, true, false, false);
static SwitchOption interfaceFixedQEDCouplingsOn
(interfaceFixedQEDCouplings,
"On",
"On",
true);
static SwitchOption interfaceFixedQEDCouplingsOff
(interfaceFixedQEDCouplings,
"Off",
"Off",
false);
static Switch<MatchboxFactory,bool> interfaceVetoScales
("VetoScales",
"Switch on or setting veto scales.",
&MatchboxFactory::theVetoScales, false, false, false);
static SwitchOption interfaceVetoScalesOn
(interfaceVetoScales,
"On",
"On",
true);
static SwitchOption interfaceVetoScalesOff
(interfaceVetoScales,
"Off",
"Off",
false);
static RefVector<MatchboxFactory,MatchboxAmplitude> interfaceAmplitudes
("Amplitudes",
"The amplitude objects.",
&MatchboxFactory::theAmplitudes, -1, false, false, true, true, false);
static RefVector<MatchboxFactory,MatchboxMEBase> interfaceBornMEs
("BornMEs",
"The Born matrix elements to be used",
&MatchboxFactory::theBornMEs, -1, false, false, true, true, false);
static RefVector<MatchboxFactory,MatchboxInsertionOperator> interfaceVirtuals
("Virtuals",
"The virtual corrections to include",
&MatchboxFactory::theVirtuals, -1, false, false, true, true, false);
static RefVector<MatchboxFactory,MatchboxMEBase> interfaceRealEmissionMEs
("RealEmissionMEs",
"The RealEmission matrix elements to be used",
&MatchboxFactory::theRealEmissionMEs, -1, false, false, true, true, false);
static RefVector<MatchboxFactory,MatchboxMEBase> interfaceBornVirtuals
("BornVirtualMEs",
"The generated Born/virtual contributions",
&MatchboxFactory::theBornVirtualMEs, -1, false, true, true, true, false);
static RefVector<MatchboxFactory,SubtractedME> interfaceSubtractedMEs
("SubtractedMEs",
"The generated subtracted real emission contributions",
&MatchboxFactory::theSubtractedMEs, -1, false, true, true, true, false);
static RefVector<MatchboxFactory,MatchboxMEBase> interfaceFiniteRealMEs
("FiniteRealMEs",
"The generated finite real contributions",
&MatchboxFactory::theFiniteRealMEs, -1, false, true, true, true, false);
static Switch<MatchboxFactory,bool> interfaceVerbose
("Verbose",
"Print full infomation on each evaluated phase space point.",
&MatchboxFactory::theVerbose, false, false, false);
static SwitchOption interfaceVerboseOn
(interfaceVerbose,
"On",
"On",
true);
static SwitchOption interfaceVerboseOff
(interfaceVerbose,
"Off",
"Off",
false);
static Switch<MatchboxFactory,bool> interfaceVerboseDia
("DiagramWeightVerbose",
"Print full infomation on each evaluated phase space point.",
&MatchboxFactory::theDiagramWeightVerbose, false, false, false);
static SwitchOption interfaceVerboseDiaOn
(interfaceVerboseDia,
"On",
"On",
true);
static SwitchOption interfaceVerboseDiaOff
(interfaceVerboseDia,
"Off",
"Off",
false);
static Parameter<MatchboxFactory,int> interfaceVerboseDiaNbins
("DiagramWeightVerboseNBins",
"No. of Bins for DiagramWeightVerbose Diagrams.",
&MatchboxFactory::theDiagramWeightVerboseNBins, 200, 0, 0,
false, false, Interface::lowerlim);
static Switch<MatchboxFactory,bool> interfaceInitVerbose
("InitVerbose",
"Print setup information.",
&MatchboxFactory::theInitVerbose, false, false, false);
static SwitchOption interfaceInitVerboseOn
(interfaceInitVerbose,
"On",
"On",
true);
static SwitchOption interfaceInitVerboseOff
(interfaceInitVerbose,
"Off",
"Off",
false);
static Parameter<MatchboxFactory,string> interfaceSubtractionData
("SubtractionData",
"Prefix for subtraction check data.",
&MatchboxFactory::theSubtractionData, "",
false, false);
static Switch<MatchboxFactory,int> interfaceSubtractionPlotType
("SubtractionPlotType",
"Switch for controlling what kind of plot is generated for checking the subtraction",
&MatchboxFactory::theSubtractionPlotType, 1, false, false);
static SwitchOption interfaceSubtractionPlotTypeLinearRatio
(interfaceSubtractionPlotType,
"LinRatio",
"Switch on the linear plot of the ratio",
1);
static SwitchOption interfaceSubtractionPlotTypeLogRelDiff
(interfaceSubtractionPlotType,
"LogRelDiff",
"Switch on the logarithmic plot of the relative difference",
2);
static Switch<MatchboxFactory,bool> interfaceSubtractionScatterPlot
("SubtractionScatterPlot",
"Switch for controlling whether subtraction data should be plotted for each phase space point individually",
&MatchboxFactory::theSubtractionScatterPlot, false, false, false);
static SwitchOption interfaceSubtractionScatterPlotOff
(interfaceSubtractionScatterPlot,
"Off", "Switch off the scatter plot", false);
static SwitchOption interfaceSubtractionScatterPlotOn
(interfaceSubtractionScatterPlot,
"On", "Switch on the scatter plot", true);
static Parameter<MatchboxFactory,string> interfacePoleData
("PoleData",
"Prefix for subtraction check data.",
&MatchboxFactory::thePoleData, "",
false, false);
static RefVector<MatchboxFactory,ParticleData> interfaceParticleGroup
("ParticleGroup",
"The particle group just started.",
&MatchboxFactory::particleGroup, -1, false, false, true, false, false);
static Command<MatchboxFactory> interfaceStartParticleGroup
("StartParticleGroup",
"Start a particle group.",
&MatchboxFactory::startParticleGroup, false);
static Command<MatchboxFactory> interfaceEndParticleGroup
("EndParticleGroup",
"End a particle group.",
&MatchboxFactory::endParticleGroup, false);
static Command<MatchboxFactory> interfaceProcess
("Process",
"Set the process(es) to consider.",
&MatchboxFactory::doProcess, false);
static Command<MatchboxFactory> interfaceLoopInducedProcess
("LoopInducedProcess",
"Set the loop induced process(es) to consider.",
&MatchboxFactory::doLoopInducedProcess, false);
static Command<MatchboxFactory> interfaceSingleRealProcess
("SingleRealProcess",
"Set the real emission process(es) to consider.",
&MatchboxFactory::doSingleRealProcess, false);
static Reference<MatchboxFactory,ShowerApproximation> interfaceShowerApproximation
("ShowerApproximation",
"Set the shower approximation to be considered.",
&MatchboxFactory::theShowerApproximation, false, false, true, true, false);
static Switch<MatchboxFactory,bool> interfaceRealEmissionScales
("RealEmissionScales",
"Switch on or off calculation of subtraction scales from real emission kinematics.",
&MatchboxFactory::theRealEmissionScales, false, false, false);
static SwitchOption interfaceRealEmissionScalesOn
(interfaceRealEmissionScales,
"On",
"On",
true);
static SwitchOption interfaceRealEmissionScalesOff
(interfaceRealEmissionScales,
"Off",
"Off",
false);
static Switch<MatchboxFactory,bool> interfaceAllProcesses
("AllProcesses",
"Consider all processes up to a maximum coupling order specified by the coupling order interfaces.",
&MatchboxFactory::theAllProcesses, false, false, false);
static SwitchOption interfaceAllProcessesYes
(interfaceAllProcesses,
"Yes",
"Include all processes.",
true);
static SwitchOption interfaceAllProcessesNo
(interfaceAllProcesses,
"No",
"Only consider processes matching the exact order in the couplings.",
false);
static RefVector<MatchboxFactory,MatchboxAmplitude> interfaceSelectAmplitudes
("SelectAmplitudes",
"The amplitude objects to be favoured in clashing responsibilities.",
&MatchboxFactory::theSelectedAmplitudes, -1, false, false, true, true, false);
static RefVector<MatchboxFactory,MatchboxAmplitude> interfaceDeselectAmplitudes
("DeselectAmplitudes",
"The amplitude objects to be disfavoured in clashing responsibilities.",
&MatchboxFactory::theDeselectedAmplitudes, -1, false, false, true, true, false);
static Switch<MatchboxFactory,int> interfaceDipoleSet
("DipoleSet",
"The set of subtraction terms to be considered.",
&MatchboxFactory::theDipoleSet, 0, false, false);
static SwitchOption interfaceDipoleSetCataniSeymour
(interfaceDipoleSet,
"CataniSeymour",
"Use default Catani-Seymour dipoles.",
0);
static RefVector<MatchboxFactory,ReweightBase> interfaceReweighters
("Reweighters",
"Reweight objects for matrix elements.",
&MatchboxFactory::theReweighters, -1, false, false, true, false, false);
static RefVector<MatchboxFactory,ReweightBase> interfacePreweighters
("Preweighters",
"Preweight objects for matrix elements.",
&MatchboxFactory::thePreweighters, -1, false, false, true, false, false);
static Switch<MatchboxFactory,bool> interfaceMECorrectionsOnly
("MECorrectionsOnly",
"Prepare only ME corrections, but no NLO calculation.",
&MatchboxFactory::theMECorrectionsOnly, false, false, false);
static SwitchOption interfaceMECorrectionsOnlyYes
(interfaceMECorrectionsOnly,
"Yes",
"Produce only ME corrections.",
true);
static SwitchOption interfaceMECorrectionsOnlyNo
(interfaceMECorrectionsOnly,
"No",
"Produce full NLO.",
false);
static Switch<MatchboxFactory,bool> interfaceLoopSimCorrections
("LoopSimCorrections",
"Prepare LoopSim corrections.",
&MatchboxFactory::theLoopSimCorrections, false, false, false);
static SwitchOption interfaceLoopSimCorrectionsYes
(interfaceLoopSimCorrections,
"Yes",
"Produce loopsim corrections.",
true);
static SwitchOption interfaceLoopSimCorrectionsNo
(interfaceLoopSimCorrections,
"No",
"Produce full NLO.",
false);
static Switch<MatchboxFactory,bool> interfaceFirstPerturbativePDF
("FirstPerturbativePDF",
"",
&MatchboxFactory::theFirstPerturbativePDF, true, false, false);
static SwitchOption interfaceFirstPerturbativePDFYes
(interfaceFirstPerturbativePDF,
"Yes",
"",
true);
static SwitchOption interfaceFirstPerturbativePDFNo
(interfaceFirstPerturbativePDF,
"No",
"",
false);
static Switch<MatchboxFactory,bool> interfaceSecondPerturbativePDF
("SecondPerturbativePDF",
"",
&MatchboxFactory::theSecondPerturbativePDF, true, false, false);
static SwitchOption interfaceSecondPerturbativePDFYes
(interfaceSecondPerturbativePDF,
"Yes",
"",
true);
static SwitchOption interfaceSecondPerturbativePDFNo
(interfaceSecondPerturbativePDF,
"No",
"",
false);
static Command<MatchboxFactory> interfaceProductionMode
("ProductionMode",
"Switch this factory to production mode.",
&MatchboxFactory::doProductionMode, false);
+ static Switch<MatchboxFactory,bool> interfaceFillRhoMatrices
+ ("FillRhoMatrices",
+ "Fill information for the spin correlations, if possible.",
+ &MatchboxFactory::theFillRhoMatrices, false, false, false);
+ static SwitchOption interfaceFillRhoMatricesYes
+ (interfaceFillRhoMatrices,
+ "Yes",
+ "",
+ true);
+ static SwitchOption interfaceFillRhoMatricesNo
+ (interfaceFillRhoMatrices,
+ "No",
+ "",
+ false);
+
}
// *** 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<MatchboxFactory,SubProcessHandler>
describeHerwigMatchboxFactory("Herwig::MatchboxFactory", "Herwig.so");
diff --git a/MatrixElement/Matchbox/MatchboxFactory.h b/MatrixElement/Matchbox/MatchboxFactory.h
--- a/MatrixElement/Matchbox/MatchboxFactory.h
+++ b/MatrixElement/Matchbox/MatchboxFactory.h
@@ -1,1171 +1,1186 @@
// -*- C++ -*-
//
// MatchboxFactory.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_MatchboxFactory_H
#define HERWIG_MatchboxFactory_H
//
// This is the declaration of the MatchboxFactory class.
//
#include "ThePEG/Handlers/SubProcessHandler.h"
#include "Herwig++/MatrixElement/Matchbox/Base/MatchboxAmplitude.h"
#include "Herwig++/MatrixElement/Matchbox/Utility/Tree2toNGenerator.h"
#include "Herwig++/MatrixElement/Matchbox/Utility/ProcessData.h"
#include "Herwig++/MatrixElement/Matchbox/Utility/MatchboxScaleChoice.h"
#include "Herwig++/MatrixElement/Matchbox/Phasespace/MatchboxPhasespace.h"
#include "Herwig++/MatrixElement/Matchbox/Base/MatchboxMEBase.h"
#include "Herwig++/MatrixElement/Matchbox/Base/SubtractedME.h"
#include "Herwig++/MatrixElement/Matchbox/MatchboxFactory.fh"
namespace Herwig {
using namespace ThePEG;
/**
* \ingroup Matchbox
* \author Simon Platzer
*
* \brief MatchboxFactory automatically sets up a NLO
* QCD calculation carried out in dipole subtraction.
*
* @see \ref MatchboxFactoryInterfaces "The interfaces"
* defined for MatchboxFactory.
*/
class MatchboxFactory: public SubProcessHandler {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
MatchboxFactory();
/**
* The destructor.
*/
virtual ~MatchboxFactory();
//@}
public:
/** @name Process and diagram information */
//@{
/**
* Return the diagram generator.
*/
Ptr<Tree2toNGenerator>::tptr diagramGenerator() const { return theDiagramGenerator; }
/**
* Set the diagram generator.
*/
void diagramGenerator(Ptr<Tree2toNGenerator>::ptr dg) { theDiagramGenerator = dg; }
/**
* Return the process data.
*/
Ptr<ProcessData>::tptr processData() const { return theProcessData; }
/**
* Set the process data.
*/
void processData(Ptr<ProcessData>::ptr pd) { theProcessData = pd; }
/**
* Return the number of light flavours, this matrix
* element is calculated for.
*/
unsigned int nLight() const { return theNLight; }
/**
* Set the number of light flavours, this matrix
* element is calculated for.
*/
void nLight(unsigned int n) { theNLight = n; }
/**
* Return the vector that contains the PDG ids of
* the light flavours, which are contained in the
* jet particle group.
*/
vector<int> nLightJetVec() const { return theNLightJetVec; }
/**
* Set the elements of the vector that contains the PDG
* ids of the light flavours, which are contained in the
* jet particle group.
*/
void nLightJetVec(int n) { theNLightJetVec.push_back(n); }
/**
* Return the vector that contains the PDG ids of
* the heavy flavours, which are contained in the
* jet particle group.
*/
vector<int> nHeavyJetVec() const { return theNHeavyJetVec; }
/**
* Set the elements of the vector that contains the PDG
* ids of the heavy flavours, which are contained in the
* jet particle group.
*/
void nHeavyJetVec(int n) { theNHeavyJetVec.push_back(n); }
/**
* Return the vector that contains the PDG ids of
* the light flavours, which are contained in the
* proton particle group.
*/
vector<int> nLightProtonVec() const { return theNLightProtonVec; }
/**
* Set the elements of the vector that contains the PDG
* ids of the light flavours, which are contained in the
* proton particle group.
*/
void nLightProtonVec(int n) { theNLightProtonVec.push_back(n); }
/**
* Return the order in \f$\alpha_S\f$.
*/
unsigned int orderInAlphaS() const { return theOrderInAlphaS; }
/**
* Set the order in \f$\alpha_S\f$.
*/
void orderInAlphaS(unsigned int o) { theOrderInAlphaS = o; }
/**
* Return the order in \f$\alpha_{EM}\f$.
*/
unsigned int orderInAlphaEW() const { return theOrderInAlphaEW; }
/**
* Set the order in \f$\alpha_{EM}\f$.
*/
void orderInAlphaEW(unsigned int o) { theOrderInAlphaEW = o; }
/**
* Return true, if all processes up to a maximum order are considered
*/
bool allProcesses() const { return theAllProcesses; }
/**
* Switch on/off inclusino off all processes up to a maximum order
*/
void setAllProcesses(bool on = true) { theAllProcesses = on; }
/**
* Return true, if Born contributions should be included.
*/
bool bornContributions() const { return theBornContributions; }
/**
* Switch on or off Born contributions
*/
void setBornContributions(bool on = true) { theBornContributions = on; }
/**
* Return true, if virtual contributions should be included.
*/
bool virtualContributions() const { return theVirtualContributions; }
/**
* Switch on or off virtual contributions
*/
void setVirtualContributions(bool on = true) { theVirtualContributions = on; }
/**
* Produce matrix element corrections, but no NLO
*/
bool meCorrectionsOnly() const { return theMECorrectionsOnly; }
/**
* Switch to produce matrix element corrections, but no NLO
*/
void setMECorrectionsOnly(bool on = true) { theMECorrectionsOnly = on; }
/**
* Produce matrix element corrections, with LoopSim NLO
*/
bool loopSimCorrections() const { return theLoopSimCorrections; }
/**
* Switch to produce matrix element corrections, with LoopSim NLO
*/
void setLoopSimCorrections(bool on = true) { theLoopSimCorrections = on; }
/**
* Return true, if subtracted real emission contributions should be included.
*/
bool realContributions() const { return theRealContributions; }
/**
* Switch on or off subtracted real emission contributions
*/
void setRealContributions(bool on = true) { theRealContributions = on; }
/**
* Return true, if virtual contributions should be treated as independent subprocesses
*/
bool independentVirtuals() const { return theIndependentVirtuals; }
/**
* Switch on/off virtual contributions should be treated as independent subprocesses
*/
void setIndependentVirtuals(bool on = true) { theIndependentVirtuals = on; }
/**
* Return true, if SubProcessGroups should be
* setup from this MEGroup. If not, a single SubProcess
* is constructed from the data provided by the
* head matrix element.
*/
bool subProcessGroups() const { return theSubProcessGroups; }
/**
* Switch on or off producing subprocess groups.
*/
void setSubProcessGroups(bool on = true) { theSubProcessGroups = on; }
/**
* Return true, if subtraction scales should be caluclated from real emission kinematics
*/
bool realEmissionScales() const { return theRealEmissionScales; }
/**
* Switch on/off that subtraction scales should be caluclated from real emission kinematics
*/
void setRealEmissionScales(bool on = true) { theRealEmissionScales = on; }
/**
* Set the shower approximation.
*/
void showerApproximation(Ptr<ShowerApproximation>::tptr app) { theShowerApproximation = app; }
/**
* Return the shower approximation.
*/
Ptr<ShowerApproximation>::tptr showerApproximation() const { return theShowerApproximation; }
//@}
/** @name Phasespace generation and scale choice */
//@{
/**
* Return the phase space generator to be used.
*/
Ptr<MatchboxPhasespace>::tptr phasespace() const { return thePhasespace; }
/**
* Set the phase space generator to be used.
*/
void phasespace(Ptr<MatchboxPhasespace>::ptr ps) { thePhasespace = ps; }
/**
* Set the scale choice object
*/
void scaleChoice(Ptr<MatchboxScaleChoice>::ptr sc) { theScaleChoice = sc; }
/**
* Return the scale choice object
*/
Ptr<MatchboxScaleChoice>::tptr scaleChoice() const { return theScaleChoice; }
/**
* Get the factorization scale factor
*/
double factorizationScaleFactor() const { return theFactorizationScaleFactor; }
/**
* Set the factorization scale factor
*/
void factorizationScaleFactor(double f) { theFactorizationScaleFactor = f; }
/**
* Get the renormalization scale factor
*/
double renormalizationScaleFactor() const { return theRenormalizationScaleFactor; }
/**
* Set the renormalization scale factor
*/
void renormalizationScaleFactor(double f) { theRenormalizationScaleFactor = f; }
/**
* Return true, if fixed couplings are used.
*/
bool fixedCouplings() const { return theFixedCouplings; }
/**
* Switch on fixed couplings.
*/
void setFixedCouplings(bool on = true) { theFixedCouplings = on; }
/**
* Return true, if fixed couplings are used.
*/
bool fixedQEDCouplings() const { return theFixedQEDCouplings; }
/**
* Switch on fixed couplings.
*/
void setFixedQEDCouplings(bool on = true) { theFixedQEDCouplings = on; }
/**
* Return true, if veto scales should be set
* for the real emission
*/
bool vetoScales() const { return theVetoScales; }
/**
* Switch on setting veto scales
*/
void doVetoScales() { theVetoScales = true; }
/**
* Switch off setting veto scales
*/
void noVetoScales() { theVetoScales = true; }
//@}
/** @name Amplitudes and caching */
//@{
/**
* Return the amplitudes to be considered
*/
const vector<Ptr<MatchboxAmplitude>::ptr>& amplitudes() const { return theAmplitudes; }
/**
* Access the amplitudes to be considered
*/
vector<Ptr<MatchboxAmplitude>::ptr>& amplitudes() { return theAmplitudes; }
//@}
/** @name Matrix element objects. */
//@{
/**
* Return the Born matrix elements to be considered
*/
const vector<Ptr<MatchboxMEBase>::ptr>& bornMEs() const { return theBornMEs; }
/**
* Access the Born matrix elements to be considered
*/
vector<Ptr<MatchboxMEBase>::ptr>& bornMEs() { return theBornMEs; }
/**
* Return the loop induced matrix elements to be considered
*/
const vector<Ptr<MatchboxMEBase>::ptr>& loopInducedMEs() const { return theLoopInducedMEs; }
/**
* Access the loop induced matrix elements to be considered
*/
vector<Ptr<MatchboxMEBase>::ptr>& loopInducedMEs() { return theLoopInducedMEs; }
/**
* Return the processes to be ordered from an OLP
*/
const map<Ptr<MatchboxAmplitude>::tptr,
map<pair<Process,int>,int> >&
olpProcesses() const { return theOLPProcesses; }
/**
* Access the processes to be ordered from an OLP
*/
map<Ptr<MatchboxAmplitude>::tptr,
map<pair<Process,int>,int> >&
olpProcesses() { return theOLPProcesses; }
/**
* Order an OLP process and return its id
*/
int orderOLPProcess(const Process& p,
Ptr<MatchboxAmplitude>::tptr amp,
int type);
/**
* Return the amplitudes which need external initialization
*/
const set<Ptr<MatchboxAmplitude>::tptr>& externalAmplitudes() const {
return theExternalAmplitudes;
}
/**
* Access the amplitudes which need external initialization
*/
set<Ptr<MatchboxAmplitude>::tptr>& externalAmplitudes() {
return theExternalAmplitudes;
}
/**
* Return the virtual corrections to be considered
*/
const vector<Ptr<MatchboxInsertionOperator>::ptr>& virtuals() const { return theVirtuals; }
/**
* Access the virtual corrections to be considered
*/
vector<Ptr<MatchboxInsertionOperator>::ptr>& virtuals() { return theVirtuals; }
/**
* Return the produced NLO matrix elements
*/
const vector<Ptr<MatchboxMEBase>::ptr>& bornVirtualMEs() const { return theBornVirtualMEs; }
/**
* Access the produced NLO matrix elements
*/
vector<Ptr<MatchboxMEBase>::ptr>& bornVirtualMEs() { return theBornVirtualMEs; }
/**
* Return the real emission matrix elements to be considered
*/
const vector<Ptr<MatchboxMEBase>::ptr>& realEmissionMEs() const { return theRealEmissionMEs; }
/**
* Access the real emission matrix elements to be considered
*/
vector<Ptr<MatchboxMEBase>::ptr>& realEmissionMEs() { return theRealEmissionMEs; }
/**
* Return, which set of dipoles should be considered
*/
int dipoleSet() const { return theDipoleSet; }
/**
* Return, which set of dipoles should be considered
*/
void dipoleSet(int s) { theDipoleSet = s; }
/**
* Return the produced subtracted matrix elements
*/
const vector<Ptr<SubtractedME>::ptr>& subtractedMEs() const { return theSubtractedMEs; }
/**
* Access the produced subtracted matrix elements
*/
vector<Ptr<SubtractedME>::ptr>& subtractedMEs() { return theSubtractedMEs; }
/**
* Return the produced finite real emission matrix elements
*/
const vector<Ptr<MatchboxMEBase>::ptr>& finiteRealMEs() const { return theFiniteRealMEs; }
/**
* Access the produced finite real emission elements
*/
vector<Ptr<MatchboxMEBase>::ptr>& finiteRealMEs() { return theFiniteRealMEs; }
/**
* Return the map of Born processes to splitting dipoles
*/
const map<cPDVector,set<Ptr<SubtractionDipole>::ptr> >& splittingDipoles() const {
return theSplittingDipoles;
}
/**
* Identify a splitting channel
*/
struct SplittingChannel {
/**
* The Born XComb
*/
StdXCombPtr bornXComb;
/**
* The real XComb
*/
StdXCombPtr realXComb;
/**
* The set of tilde XCombs to consider for the real xcomb
*/
vector<StdXCombPtr> tildeXCombs;
/**
* The dipole in charge of the splitting
*/
Ptr<SubtractionDipole>::ptr dipole;
/**
* Dump the setup
*/
void print(ostream&) const;
};
/**
* Generate all splitting channels for the Born process handled by
* the given XComb
*/
list<SplittingChannel> getSplittingChannels(tStdXCombPtr xc) const;
/**
* Return the reweight objects for matrix elements
*/
const vector<ReweightPtr>& reweighters() const { return theReweighters; }
/**
* Access the reweight objects for matrix elements
*/
vector<ReweightPtr>& reweighters() { return theReweighters; }
/**
* Return the preweight objects for matrix elements
*/
const vector<ReweightPtr>& preweighters() const { return thePreweighters; }
/**
* Access the preweight objects for matrix elements
*/
vector<ReweightPtr>& preweighters() { return thePreweighters; }
//@}
/** @name Setup the matrix elements */
//@{
/**
* Return true if this object needs to be initialized before all
* other objects (except those for which this function also returns
* true). This default version always returns false, but subclasses
* may override it to return true.
*/
virtual bool preInitialize() const { return true; }
/**
* Prepare a matrix element.
*/
void prepareME(Ptr<MatchboxMEBase>::ptr);
/**
* Check consistency and switch to porduction mode.
*/
void productionMode();
/**
* Setup everything
*/
virtual void setup();
/**
* The highest multiplicity of legs having virtual contributions.(needed for madgraph)
*/
size_t highestVirt(){return theHighestVirtualsize;}
//@}
/** @name Diagnostic information */
//@{
/**
* Return true, if verbose
*/
bool verbose() const { return theVerbose; }
/**
* Switch on diagnostic information.
*/
void setVerbose(bool on = true) { theVerbose = on; }
/**
* Return true, if diagram weight is verbose
*/
bool verboseDia() const { return theDiagramWeightVerbose; }
/**
* Number of bins for diagram weight verbosity
*/
int diagramWeightVerboseNBins() const {return theDiagramWeightVerboseNBins;}
/**
* Return true, if verbose while initializing
*/
bool initVerbose() const { return theInitVerbose || verbose(); }
/**
* Switch on diagnostic information while initializing
*/
void setInitVerbose(bool on = true) { theInitVerbose = on; }
/**
* Dump the setup
*/
void print(ostream&) const;
/**
* Return the subtraction data prefix.
*/
const string& subtractionData() const { return theSubtractionData; }
/**
* Set the subtraction data prefix.
*/
void subtractionData(const string& s) { theSubtractionData = s; }
/**
* Return the subtraction plot type.
*/
const int& subtractionPlotType() const { return theSubtractionPlotType; }
/**
* Set the subtraction plot type.
*/
void subtractionPlotType(const int& t) { theSubtractionPlotType = t; }
/**
* Return whether subtraction data should be plotted for all phase space points individually
*/
const bool& subtractionScatterPlot() const { return theSubtractionScatterPlot; }
/**
* Set whether subtraction data should be plotted for all phase space points individually
*/
void subtractionScatterPlot(const bool& s) { theSubtractionScatterPlot = s; }
/**
* Return the pole data prefix.
*/
const string& poleData() const { return thePoleData; }
/**
* Set the pole data prefix.
*/
void poleData(const string& s) { thePoleData = s; }
/**
* Return true, if cancellationn of epsilon poles should be checked.
*/
bool checkPoles() const { return poleData() != ""; }
//@}
/** @name Process generation */
//@{
/**
* Return the particle groups.
*/
const map<string,PDVector>& particleGroups() const { return theParticleGroups; }
/**
* Access the particle groups.
*/
map<string,PDVector>& particleGroups() { return theParticleGroups; }
/**
* Return true, if the given particle is incoming
*/
bool isIncoming(cPDPtr p) const {
return theIncoming.find(p->id()) != theIncoming.end();
}
+ /**
+ * Return true, if spin correlation information should be provided, if possible.
+ */
+ bool fillRhoMatrices() const { return theFillRhoMatrices; }
+
+ /**
+ * Indicate that spin correlation information should be provided, if possible.
+ */
+ void setFillRhoMatrices(bool yes) { theFillRhoMatrices = yes; }
+
//@}
/** @name Truncated qtilde shower information */
//@{
/**
* Return the subprocess of the real emission
*/
tSubProPtr hardTreeSubprocess() { return theHardtreeSubprocess; }
/**
* Set the subprocess of the real emission for use in calculating the shower hardtree
*/
void setHardTreeSubprocess(tSubProPtr hardTree) { theHardtreeSubprocess = hardTree; }
/**
* Return the born emitter
*/
int hardTreeEmitter() { return theHardtreeEmitter; }
/**
* Set the born emitter for use in calculating the shower hardtree
*/
void setHardTreeEmitter(int emitter) { theHardtreeEmitter = emitter; }
//@}
/** @name Data handling */
//@{
/**
* Return (and possibly create) a directory to contain amplitude
* information.
*/
const string& buildStorage();
/**
* Return (and possibly create) a directory to contain integration grid
* information.
*/
const string& runStorage();
//@}
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();
/**
* Initialize this object. Called in the run phase just before
* a run begins.
*/
virtual void doinitrun();
//@}
private:
/**
* The diagram generator.
*/
Ptr<Tree2toNGenerator>::ptr theDiagramGenerator;
/**
* The process data object to be used
*/
Ptr<ProcessData>::ptr theProcessData;
/**
* The number of light flavours, this matrix
* element is calculated for.
*/
unsigned int theNLight;
/**
* Vector with the PDG ids of the light quark flavours,
* which are contained in the jet particle group.
*/
vector<int> theNLightJetVec;
/**
* Vector with the PDG ids of the heavy quark flavours,
* which are contained in the jet particle group.
*/
vector<int> theNHeavyJetVec;
/**
* Vector with the PDG ids of the light quark flavours,
* which are contained in the proton particle group.
*/
vector<int> theNLightProtonVec;
/**
* The order in \f$\alpha_S\f$.
*/
unsigned int theOrderInAlphaS;
/**
* The order in \f$\alpha_{EM}\f$.
*/
unsigned int theOrderInAlphaEW;
/**
* Switch on or off Born contributions
*/
bool theBornContributions;
/**
* Switch on or off virtual contributions
*/
bool theVirtualContributions;
/**
* Switch on or off subtracted real emission contributions should be included.
*/
bool theRealContributions;
/**
* True if virtual contributions should be treated as independent subprocesses
*/
bool theIndependentVirtuals;
/**
* True, if SubProcessGroups should be
* setup from this MEGroup. If not, a single SubProcess
* is constructed from the data provided by the
* head matrix element.
*/
bool theSubProcessGroups;
/**
* The phase space generator to be used.
*/
Ptr<MatchboxPhasespace>::ptr thePhasespace;
/**
* The scale choice object
*/
Ptr<MatchboxScaleChoice>::ptr theScaleChoice;
/**
* The factorization scale factor.
*/
double theFactorizationScaleFactor;
/**
* The renormalization scale factor.
*/
double theRenormalizationScaleFactor;
/**
* Use non-running couplings.
*/
bool theFixedCouplings;
/**
* Use non-running couplings.
*/
bool theFixedQEDCouplings;
/**
* True, if veto scales should be set
* for the real emission
*/
bool theVetoScales;
/**
* The amplitudes to be considered
*/
vector<Ptr<MatchboxAmplitude>::ptr> theAmplitudes;
/**
* The Born matrix elements to be considered
*/
vector<Ptr<MatchboxMEBase>::ptr> theBornMEs;
/**
* The loop induced matrix elements to be considered
*/
vector<Ptr<MatchboxMEBase>::ptr> theLoopInducedMEs;
/**
* The virtual corrections to be considered
*/
vector<Ptr<MatchboxInsertionOperator>::ptr> theVirtuals;
/**
* The real emission matrix elements to be considered
*/
vector<Ptr<MatchboxMEBase>::ptr> theRealEmissionMEs;
/**
* The produced NLO matrix elements
*/
vector<Ptr<MatchboxMEBase>::ptr> theBornVirtualMEs;
/**
* The produced subtracted matrix elements
*/
vector<Ptr<SubtractedME>::ptr> theSubtractedMEs;
/**
* The produced finite real emission matrix elements
*/
vector<Ptr<MatchboxMEBase>::ptr> theFiniteRealMEs;
/**
* Which set of dipoles should be considered
*/
int theDipoleSet;
/**
* Switch on or off verbosity
*/
bool theVerbose;
/**
* Switch on or off diagram weight verbosity
*/
bool theDiagramWeightVerbose;
/**
* Number of bins for diagram weight verbosity
*/
int theDiagramWeightVerboseNBins;
/**
* True, if verbose while initializing
*/
bool theInitVerbose;
/**
* Prefix for subtraction data
*/
string theSubtractionData;
/**
* Set the type of plot that is to be generated for subtraction checking
*/
int theSubtractionPlotType;
/**
* Set whether subtraction data should be plotted for all phase space points individually
*/
bool theSubtractionScatterPlot;
/**
* Prefix for pole data.
*/
string thePoleData;
/**
* Command to limit the real emission process to be considered.
*/
string doSingleRealProcess(string);
/**
* The real emission process to be included; if empty, all possible
* ones will be considered.
*/
vector<vector<string> > realEmissionProcesses;
/**
* Particle groups.
*/
map<string,PDVector> theParticleGroups;
/**
* Command to start a particle group.
*/
string startParticleGroup(string);
/**
* The name of the particle group currently edited.
*/
string particleGroupName;
/**
* The particle group currently edited.
*/
PDVector particleGroup;
/**
* Command to end a particle group.
*/
string endParticleGroup(string);
/**
* Command to set the process.
*/
string doProcess(string);
/**
* Command to set the process.
*/
string doLoopInducedProcess(string);
/**
* The process to consider in terms of particle groups.
*/
vector<vector<string> > processes;
/**
* The loop induced process to consider in terms of particle groups.
*/
vector<vector<string> > loopInducedProcesses;
/**
* Generate subprocesses.
*/
set<PDVector> makeSubProcesses(const vector<string>&) const;
/**
* Generate matrix element objects for the given process.
*/
vector<Ptr<MatchboxMEBase>::ptr> makeMEs(const vector<string>&,
unsigned int orderas,
bool virt);
/**
* The shower approximation.
*/
Ptr<ShowerApproximation>::ptr theShowerApproximation;
/**
* The map of Born processes to splitting dipoles
*/
map<cPDVector,set<Ptr<SubtractionDipole>::ptr> > theSplittingDipoles;
/**
* True, if subtraction scales should be caluclated from real emission kinematics
*/
bool theRealEmissionScales;
/**
* Consider all processes with order in couplings specifying the
* maximum order.
*/
bool theAllProcesses;
/**
* The processes to be ordered from an OLP
*/
map<Ptr<MatchboxAmplitude>::tptr,map<pair<Process,int>,int> > theOLPProcesses;
/**
* Amplitudes which need external initialization
*/
set<Ptr<MatchboxAmplitude>::tptr> theExternalAmplitudes;
/**
* Amplitudes to be selected on clashing responsibilities.
*/
vector<Ptr<MatchboxAmplitude>::ptr> theSelectedAmplitudes;
/**
* Amplitudes to be deselected on clashing responsibilities.
*/
vector<Ptr<MatchboxAmplitude>::ptr> theDeselectedAmplitudes;
/**
* Reweight objects for matrix elements
*/
vector<ReweightPtr> theReweighters;
/**
* Preweight objects for matrix elements
*/
vector<ReweightPtr> thePreweighters;
/**
* Produce matrix element corrections, but no NLO
*/
bool theMECorrectionsOnly;
/**
* The highest multiplicity of legs having virtual contributions.(needed for madgraph)
*/
int theHighestVirtualsize;
/**
* Produce matrix element corrections, with LoopSim NLO
*/
bool theLoopSimCorrections;
/**
* True, if the setup has already been run.
*/
bool ranSetup;
/**
* PDG ids of incoming particles
*/
set<long> theIncoming;
/**
* True, if first incoming partons originate from perturbative PDF
*/
bool theFirstPerturbativePDF;
/**
* True, if second incoming partons originate from perturbative PDF
*/
bool theSecondPerturbativePDF;
/**
* True, if this Factory is in production mode.
*/
bool inProductionMode;
/**
* The real emission subprocess used when calculating the hardtree
* in the truncated qtilde shower
*/
tSubProPtr theHardtreeSubprocess;
/**
* The born emitter used when calculating the hardtree in
* the truncated shower
*/
int theHardtreeEmitter;
/**
+ * True, if spin correlation information should be provided, if possible.
+ */
+ bool theFillRhoMatrices;
+
+ /**
* Command for production mode
*/
string doProductionMode(string) {
productionMode(); return "";
}
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MatchboxFactory & operator=(const MatchboxFactory &);
};
}
#endif /* HERWIG_MatchboxFactory_H */
diff --git a/MatrixElement/Matchbox/Matching/ShowerApproximation.h b/MatrixElement/Matchbox/Matching/ShowerApproximation.h
--- a/MatrixElement/Matchbox/Matching/ShowerApproximation.h
+++ b/MatrixElement/Matchbox/Matching/ShowerApproximation.h
@@ -1,605 +1,610 @@
// -*- C++ -*-
//
// ShowerApproximation.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_ShowerApproximation_H
#define Herwig_ShowerApproximation_H
//
// This is the declaration of the ShowerApproximation class.
//
#include "ThePEG/Handlers/HandlerBase.h"
#include "ThePEG/Handlers/StandardXComb.h"
#include "Herwig++/MatrixElement/Matchbox/Dipoles/SubtractionDipole.fh"
#include "Herwig++/MatrixElement/Matchbox/Utility/ColourBasis.h"
namespace Herwig {
using namespace ThePEG;
/**
* \ingroup Matchbox
* \author Simon Platzer
*
* \brief ShowerApproximation describes the shower emission to be used
* in NLO matching.
*
*/
class ShowerApproximation: public HandlerBase {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
ShowerApproximation();
/**
* The destructor.
*/
virtual ~ShowerApproximation();
//@}
public:
/**
* Return true, if this shower approximation will require a
* splitting generator
*/
virtual bool needsSplittingGenerator() const { return false; }
/**
* Return true, if this shower approximation will require
* H events
*/
virtual bool hasHEvents() const { return true; }
/**
* Return true, if this shower approximation will require tilde
* XCombs for the real phase space point generated
*/
virtual bool needsTildeXCombs() const { return false; }
/**
* Return true, if this shower approximation will require
* a truncated parton shower
*/
virtual bool needsTruncatedShower() const { return false; }
public:
/**
* Set the XComb object describing the Born process
*/
void setBornXComb(tStdXCombPtr xc) { theBornXComb = xc; }
/**
* Return the XComb object describing the Born process
*/
tStdXCombPtr bornXComb() const { return theBornXComb; }
/**
* Return the XComb object describing the Born process
*/
tcStdXCombPtr bornCXComb() const { return theBornXComb; }
/**
* Set the XComb object describing the real emission process
*/
void setRealXComb(tStdXCombPtr xc) { theRealXComb = xc; }
/**
* Return the XComb object describing the real emission process
*/
tStdXCombPtr realXComb() const { return theRealXComb; }
/**
* Return the XComb object describing the real emission process
*/
tcStdXCombPtr realCXComb() const { return theRealXComb; }
/**
* Set the tilde xcomb objects associated to the real xcomb
*/
void setTildeXCombs(const vector<StdXCombPtr>& xc) { theTildeXCombs = xc; }
/**
* Return the tilde xcomb objects associated to the real xcomb
*/
const vector<StdXCombPtr>& tildeXCombs() const { return theTildeXCombs; }
/**
* Set the dipole in charge for the emission
*/
void setDipole(Ptr<SubtractionDipole>::tcptr);
/**
* Return the dipole in charge for the emission
*/
Ptr<SubtractionDipole>::tcptr dipole() const;
+ /**
+ * Return true, if this matching is capable of spin correlations.
+ */
+ virtual bool hasSpinCorrelations() const { return false; }
+
public:
/**
* Return true if one of the recently encountered configutations was
* below the infrared cutoff.
*/
bool belowCutoff() const { return theBelowCutoff; }
/**
* Indicate that one of the recently encountered configutations was
* below the infrared cutoff.
*/
void wasBelowCutoff() { theBelowCutoff = true; }
/**
* Reset the below cutoff flag.
*/
void resetBelowCutoff() { theBelowCutoff = false; }
/**
* Return the pt cut to be applied for final-final dipoles.
*/
Energy ffPtCut() const { return theFFPtCut; }
/**
* Return the pt cut to be applied for final-initial dipoles.
*/
Energy fiPtCut() const { return theFIPtCut; }
/**
* Return the pt cut to be applied for initial-initial dipoles.
*/
Energy iiPtCut() const { return theIIPtCut; }
/**
* Return the screening scale to be applied for final-final dipoles.
*/
Energy ffScreeningScale() const { return theFFScreeningScale; }
/**
* Return the screening scale to be applied for final-initial dipoles.
*/
Energy fiScreeningScale() const { return theFIScreeningScale; }
/**
* Return the screening scale to be applied for initial-initial dipoles.
*/
Energy iiScreeningScale() const { return theIIScreeningScale; }
/**
* Return the shower renormalization scale
*/
virtual Energy2 showerEmissionScale() const;
/**
* Return the shower renormalization scale
*/
Energy2 showerRenormalizationScale() const {
return sqr(renormalizationScaleFactor())*showerEmissionScale();
}
/**
* Return the shower factorization scale
*/
Energy2 showerFactorizationScale() const {
return sqr(factorizationScaleFactor())*showerEmissionScale();
}
/**
* Return the Born renormalization scale
*/
Energy2 bornRenormalizationScale() const;
/**
* Return the Born factorization scale
*/
Energy2 bornFactorizationScale() const;
/**
* Return the real emission renormalization scale
*/
Energy2 realRenormalizationScale() const;
/**
* Return the real emission factorization scale
*/
Energy2 realFactorizationScale() const;
/**
* Enumerate possible scale choices
*/
enum ScaleChoices {
bornScale = 0,
/** Use the born scales */
realScale = 1,
/** Use the real scales */
showerScale = 2
/** Use the shower scales */
};
/**
* Return the scale choice in the real emission cross section to be
* used in the matching subtraction.
*/
int realEmissionScaleInSubtraction() const { return theRealEmissionScaleInSubtraction; }
/**
* Return the scale choice in the born cross section to be
* used in the matching subtraction.
*/
int bornScaleInSubtraction() const { return theBornScaleInSubtraction; }
/**
* Return the scale choice in the emission contribution to be
* used in the matching subtraction.
*/
int emissionScaleInSubtraction() const { return theEmissionScaleInSubtraction; }
/**
* Return the scale choice in the real emission cross section to be
* used in the splitting.
*/
int realEmissionScaleInSplitting() const { return theRealEmissionScaleInSplitting; }
/**
* Return the scale choice in the born cross section to be
* used in the splitting.
*/
int bornScaleInSplitting() const { return theBornScaleInSplitting; }
/**
* Return the scale choice in the emission contribution to be
* used in the splitting.
*/
int emissionScaleInSplitting() const { return theEmissionScaleInSplitting; }
/**
* Return the scale weight
*/
double scaleWeight(int rScale, int bScale, int eScale) const;
/**
* Return the scale weight for the matching subtraction
*/
double subtractionScaleWeight() const {
return scaleWeight(realEmissionScaleInSubtraction(),
bornScaleInSubtraction(),
emissionScaleInSubtraction());
}
/**
* Return the scale weight for the splitting
*/
double splittingScaleWeight() const {
return scaleWeight(realEmissionScaleInSplitting(),
bornScaleInSplitting(),
emissionScaleInSplitting());
}
public:
/**
* Return true, if the phase space restrictions of the dipole shower should
* be applied.
*/
bool restrictPhasespace() const { return theRestrictPhasespace; }
/**
* Return true if we are to use profile scales
*/
bool profileScales() const { return theProfileScales; }
/**
* Return the scale factor for the hard scale
*/
double hardScaleFactor() const { return theHardScaleFactor; }
/**
* Set the scale factor for the hard scale
*/
void hardScaleFactor(double f) { theHardScaleFactor = f; }
/**
* Return the relevant hard scale
*/
virtual Energy hardScale() const;
/**
* Return a scale profile towards the hard scale
*/
virtual double hardScaleProfile(Energy hard, Energy soft) const;
/**
* Get the factorization scale factor
*/
double factorizationScaleFactor() const { return theFactorizationScaleFactor; }
/**
* Get the renormalization scale factor
*/
double renormalizationScaleFactor() const { return theRenormalizationScaleFactor; }
/**
* Set the factorization scale factor
*/
void factorizationScaleFactor(double f) { theFactorizationScaleFactor = f; }
/**
* Set the renormalization scale factor
*/
void renormalizationScaleFactor(double f) { theRenormalizationScaleFactor = f; }
/**
* Return true, if the shower was able to generate an emission
* leading from the given Born to the given real emission process.
*/
virtual bool isInShowerPhasespace() const;
/**
* Return true, if the shower emission leading from the given Born
* to the given real emission process would have been generated
* above the shower's infrared cutoff.
*/
virtual bool isAboveCutoff() const;
/**
* Return the shower approximation to the real emission cross
* section for the given pair of Born and real emission
* configurations.
*/
virtual CrossSection dSigHatDR() const = 0;
/**
* Return the shower approximation splitting kernel for the given
* pair of Born and real emission configurations in units of the
* Born center of mass energy squared, and including a weight to
* project onto the splitting given by the dipole used.
*/
virtual double me2() const = 0;
/**
* Return the Born PDF weight
*/
double bornPDFWeight(Energy2 muF) const;
/**
* Return the real emission PDF weight
*/
double realPDFWeight(Energy2 muF) const;
public:
/**
* Generate a weight for the given dipole channel
*/
virtual double channelWeight(int emitter, int emission,
int spectator, int bemitter) const;
/**
* Generate a normalized weight taking into account all channels
*/
virtual double channelWeight() const;
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
// If needed, insert declarations of virtual function defined in the
// InterfacedBase class here (using ThePEG-interfaced-decl in Emacs).
public:
/**
* A large-N colour basis to be used when reproducing the shower
* kernels.
*/
Ptr<ColourBasis>::tptr largeNBasis() const { return theLargeNBasis; }
protected:
/**
* A large-N colour basis to be used when reproducing the shower
* kernels.
*/
Ptr<ColourBasis>::ptr theLargeNBasis;
/**
* Set the large-N basis
*/
void setLargeNBasis();
private:
/**
* The XComb object describing the Born process
*/
tStdXCombPtr theBornXComb;
/**
* The XComb object describing the real emission process
*/
tStdXCombPtr theRealXComb;
/**
* The tilde xcomb objects associated to the real xcomb
*/
vector<StdXCombPtr> theTildeXCombs;
/**
* The dipole in charge for the emission
*/
Ptr<SubtractionDipole>::tcptr theDipole;
/**
* True if one of the recently encountered configutations was below
* the infrared cutoff.
*/
bool theBelowCutoff;
/**
* The pt cut to be applied for final-final dipoles.
*/
Energy theFFPtCut;
/**
* An optional screening scale for final-final dipoles; see
* DipoleSplittingKernel
*/
Energy theFFScreeningScale;
/**
* The pt cut to be applied for final-initial dipoles.
*/
Energy theFIPtCut;
/**
* An optional screening scale for final-initial dipoles; see
* DipoleSplittingKernel
*/
Energy theFIScreeningScale;
/**
* The pt cut to be applied for initial-initial dipoles.
*/
Energy theIIPtCut;
/**
* An optional screening scale for initial-initial dipoles; see
* DipoleSplittingKernel
*/
Energy theIIScreeningScale;
/**
* True, if the phase space restrictions of the dipole shower should
* be applied.
*/
bool theRestrictPhasespace;
/**
* The scale factor for the hard scale
*/
double theHardScaleFactor;
/**
* The scale factor for the renormalization scale
*/
double theRenormalizationScaleFactor;
/**
* The scale factor for the factorization scale
*/
double theFactorizationScaleFactor;
/**
* The x value from which on we extrapolate PDFs for numerically stable ratios.
*/
double theExtrapolationX;
/**
* The scale choice in the real emission cross section to be
* used in the matching subtraction.
*/
int theRealEmissionScaleInSubtraction;
/**
* The scale choice in the born cross section to be
* used in the matching subtraction.
*/
int theBornScaleInSubtraction;
/**
* The scale choice in the emission contribution to be
* used in the matching subtraction.
*/
int theEmissionScaleInSubtraction;
/**
* The scale choice in the real emission cross section to be
* used in the splitting.
*/
int theRealEmissionScaleInSplitting;
/**
* The scale choice in the born cross section to be
* used in the splitting.
*/
int theBornScaleInSplitting;
/**
* The scale choice in the emission contribution to be
* used in the splitting.
*/
int theEmissionScaleInSplitting;
/**
* A freezing value for the renormalization scale
*/
Energy theRenormalizationScaleFreeze;
/**
* A freezing value for the factorization scale
*/
Energy theFactorizationScaleFreeze;
/**
* True if we are to use profile scales
*/
bool theProfileScales;
/**
* The profile scale parameter
*/
double theProfileRho;
/**
* True if maximum pt should be deduced from the factorization scale
*/
bool maxPtIsMuF;
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
ShowerApproximation & operator=(const ShowerApproximation &);
};
}
#endif /* Herwig_ShowerApproximation_H */
diff --git a/MatrixElement/Matchbox/Utility/ColourBasis.cc b/MatrixElement/Matchbox/Utility/ColourBasis.cc
--- a/MatrixElement/Matchbox/Utility/ColourBasis.cc
+++ b/MatrixElement/Matchbox/Utility/ColourBasis.cc
@@ -1,1249 +1,1278 @@
// -*- C++ -*-
//
// ColourBasis.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 ColourBasis class.
//
#include "ColourBasis.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.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/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include <boost/numeric/ublas/io.hpp>
#include <boost/numeric/ublas/matrix_proxy.hpp>
#include <iterator>
using std::ostream_iterator;
#include "DiagramDrawer.h"
using namespace Herwig;
using boost::numeric::ublas::trans;
// default gcc on SLC6 confuses this with std::conj,
// use explicit namespacing in the code instead
//
// using boost::numeric::ublas::conj;
using boost::numeric::ublas::row;
using boost::numeric::ublas::column;
using boost::numeric::ublas::prod;
Ptr<MatchboxFactory>::tptr ColourBasis::factory() const {
return theFactory;
}
void ColourBasis::factory(Ptr<MatchboxFactory>::tptr f) {
theFactory = f;
}
ColourBasis::ColourBasis()
: theLargeN(false), didRead(false), didWrite(false), theSearchPath("") {}
ColourBasis::~ColourBasis() {
for ( map<Ptr<Tree2toNDiagram>::tcptr,vector<ColourLines*> >::iterator cl =
theColourLineMap.begin(); cl != theColourLineMap.end(); ++cl ) {
for ( vector<ColourLines*>::iterator c = cl->second.begin();
c != cl->second.end(); ++c ) {
if ( *c )
delete *c;
}
}
theColourLineMap.clear();
}
void ColourBasis::clear() {
theLargeN = false;
theNormalOrderedLegs.clear();
theIndexMap.clear();
theScalarProducts.clear();
theCharges.clear();
theChargeNonZeros.clear();
theCorrelators.clear();
theFlowMap.clear();
theColourLineMap.clear();
theOrderingStringIdentifiers.clear();
theOrderingIdentifiers.clear();
didRead = false;
didWrite = false;
tmp.clear();
}
// If needed, insert default implementations of virtual function defined
// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs).
bool ColourBasis::colourConnected(const cPDVector& sub,
const vector<PDT::Colour>& basis,
const pair<int,bool>& i,
const pair<int,bool>& j,
size_t a) const {
// translate process to basis ids
map<cPDVector,map<size_t,size_t> >::const_iterator trans
= indexMap().find(sub);
assert(trans != indexMap().end());
int idColoured = i.second ? j.first : i.first;
idColoured = trans->second.find(idColoured)->second;
int idAntiColoured = i.second ? i.first : j.first;
idAntiColoured = trans->second.find(idAntiColoured)->second;
return colourConnected(basis,idColoured,idAntiColoured,a);
}
const string& ColourBasis::orderingString(const cPDVector& sub,
const map<size_t,size_t>& colourToAmplitude,
size_t tensorId) {
map<size_t,string>& tensors = theOrderingStringIdentifiers[sub];
if ( !tensors.empty() ) {
assert(tensors.find(tensorId) != tensors.end());
return tensors[tensorId];
}
const set<vector<size_t> >& xordering = ordering(sub,colourToAmplitude,tensorId);
ostringstream os;
os << "[";
for ( set<vector<size_t> >::const_iterator t = xordering.begin();
t != xordering.end(); ++t ) {
os << "[";
for ( vector<size_t>::const_iterator s = t->begin();
s != t->end(); ++s ) {
os << *s << (s != --t->end() ? "," : "");
}
os << "]" << (t != --xordering.end() ? "," : "");
}
os << "]";
tensors[tensorId] = os.str();
return tensors[tensorId];
}
const set<vector<size_t> >& ColourBasis::ordering(const cPDVector& sub,
const map<size_t,size_t>& colourToAmplitude,
size_t tensorId) {
map<size_t,set<vector<size_t> > >& tensors = theOrderingIdentifiers[sub];
if ( !tensors.empty() ) {
assert(tensors.find(tensorId) != tensors.end());
return tensors[tensorId];
}
const vector<PDT::Colour>& basisId = normalOrderedLegs(sub);
map<size_t,vector<vector<size_t> > > labels = basisList(basisId);
for ( map<size_t,vector<vector<size_t> > >::const_iterator t =
labels.begin(); t != labels.end(); ++t ) {
set<vector<size_t> > xordering;
for ( vector<vector<size_t> >::const_iterator s = t->second.begin();
s != t->second.end(); ++s ) {
vector<size_t> crossed;
for ( vector<size_t>::const_iterator l = s->begin();
l != s->end(); ++l ) {
map<size_t,size_t>::const_iterator trans =
colourToAmplitude.find(*l);
assert(trans != colourToAmplitude.end());
crossed.push_back(trans->second);
}
xordering.insert(crossed);
}
tensors[t->first] = xordering;
}
assert(tensors.find(tensorId) != tensors.end());
return tensors[tensorId];
}
vector<PDT::Colour> ColourBasis::normalOrderMap(const cPDVector& sub) {
vector<PDT::Colour> allLegs = projectColour(sub);
vector<PDT::Colour> legs = normalOrder(allLegs);
if ( allLegs[0] == PDT::Colour3 )
allLegs[0] = PDT::Colour3bar;
else if ( allLegs[0] == PDT::Colour3bar )
allLegs[0] = PDT::Colour3;
if ( allLegs[1] == PDT::Colour3 )
allLegs[1] = PDT::Colour3bar;
else if ( allLegs[1] == PDT::Colour3bar )
allLegs[1] = PDT::Colour3;
if ( theIndexMap.find(sub) == theIndexMap.end() ) {
map<size_t,size_t> trans;
vector<PDT::Colour> checkLegs = legs;
size_t n = checkLegs.size();
for ( size_t i = 0; i < allLegs.size(); ++i ) {
size_t j = 0;
while ( checkLegs[j] != allLegs[i] ) {
++j; if ( j == n ) break;
}
if ( j == n ) continue;
trans[i] = j;
checkLegs[j] = PDT::ColourUndefined;
}
theIndexMap[sub] = trans;
}
return legs;
}
const vector<PDT::Colour>& ColourBasis::normalOrderedLegs(const cPDVector& sub) const {
static vector<PDT::Colour> empty;
map<cPDVector,vector<PDT::Colour> >::const_iterator n =
theNormalOrderedLegs.find(sub);
if ( n != theNormalOrderedLegs.end() )
return n->second;
return empty;
}
size_t ColourBasis::prepare(const cPDVector& sub,
bool noCorrelations) {
vector<PDT::Colour> legs = normalOrderMap(sub);
bool doPrepare = false;
if ( theNormalOrderedLegs.find(sub) == theNormalOrderedLegs.end() )
theNormalOrderedLegs[sub] = legs;
if ( theScalarProducts.find(legs) == theScalarProducts.end() )
doPrepare = true;
if ( doPrepare )
doPrepare = !readBasis(legs);
size_t dim = doPrepare ? prepareBasis(legs) : theScalarProducts[legs].size1();
if ( theCharges.find(legs) != theCharges.end() )
return dim;
if ( !doPrepare && noCorrelations )
return dim;
symmetric_matrix<double,upper>& sp =
theScalarProducts.insert(make_pair(legs,symmetric_matrix<double,upper>(dim,dim))).first->second;
for ( size_t a = 0; a < dim; ++a )
for ( size_t b = a; b < dim; ++b )
sp(a,b) = scalarProduct(a,b,legs);
if ( noCorrelations )
return dim;
vector<PDT::Colour> legsPlus = legs;
legsPlus.push_back(PDT::Colour8);
legsPlus = normalOrder(legsPlus);
bool doPreparePlus = theScalarProducts.find(legsPlus) == theScalarProducts.end();
size_t dimPlus = doPreparePlus ? prepareBasis(legsPlus) : theScalarProducts[legsPlus].size1();
symmetric_matrix<double,upper>& spPlus =
doPreparePlus ?
theScalarProducts.insert(make_pair(legsPlus,symmetric_matrix<double,upper>(dimPlus,dimPlus))).first->second :
theScalarProducts[legsPlus];
if ( doPreparePlus ) {
for ( size_t a = 0; a < dimPlus; ++a )
for ( size_t b = a; b < dimPlus; ++b )
spPlus(a,b) = scalarProduct(a,b,legsPlus);
}
typedef map<size_t,compressed_matrix<double> > cMap;
cMap& cm = theCharges.insert(make_pair(legs,cMap())).first->second;
typedef map<size_t,vector<pair<size_t,size_t> > > ccMap;
ccMap& ccm = theChargeNonZeros.insert(make_pair(legs,ccMap())).first->second;
tmp.resize(dimPlus,dim);
for ( size_t i = 0; i < legs.size(); ++i ) {
size_t nonZero = 0;
vector<pair<size_t,size_t> > nonZeros;
for ( size_t a = 0; a < dimPlus; ++a )
for ( size_t b = 0; b < dim; ++b ) {
tmp(a,b) = tMatrixElement(i,a,b,legsPlus,legs);
if ( tmp(a,b) != 0. ) {
++nonZero;
nonZeros.push_back(make_pair(a,b));
}
}
ccm.insert(make_pair(i,nonZeros));
compressed_matrix<double>& tm =
cm.insert(make_pair(i,compressed_matrix<double>(dimPlus,dim,nonZero))).first->second;
for ( size_t a = 0; a < dimPlus; ++a )
for ( size_t b = 0; b < dim; ++b ) {
if ( tmp(a,b) != 0. )
tm(a,b) = tmp(a,b);
}
}
map<pair<size_t,size_t>,symmetric_matrix<double,upper> >& xm = theCorrelators[legs];
for ( size_t i = 0; i < legs.size(); ++i )
for ( size_t j = i+1; j < legs.size(); ++j ) {
symmetric_matrix<double,upper>& mm =
xm.insert(make_pair(make_pair(i,j),symmetric_matrix<double,upper>(dim,dim))).first->second;
chargeProduct(cm[i],ccm[i],spPlus,cm[j],ccm[j],mm);
}
return dim;
}
void ColourBasis::chargeProduct(const compressed_matrix<double>& ti,
const vector<pair<size_t,size_t> >& tiNonZero,
const symmetric_matrix<double,upper>& X,
const compressed_matrix<double>& tj,
const vector<pair<size_t,size_t> >& tjNonZero,
symmetric_matrix<double,upper>& result) const {
for ( size_t i = 0; i < result.size1(); ++i )
for ( size_t j = i; j < result.size1(); ++j )
result(i,j) = 0.;
for ( vector<pair<size_t,size_t> >::const_iterator i = tiNonZero.begin();
i != tiNonZero.end(); ++i )
for ( vector<pair<size_t,size_t> >::const_iterator j = tjNonZero.begin();
j != tjNonZero.end(); ++j ) {
if ( j->second < i->second )
continue;
result(i->second,j->second) +=
ti(i->first,i->second)*tj(j->first,j->second)*X(i->first,j->first);
}
}
void ColourBasis::chargeProductAdd(const compressed_matrix<double>& ti,
const vector<pair<size_t,size_t> >& tiNonZero,
const matrix<Complex>& X,
const compressed_matrix<double>& tj,
const vector<pair<size_t,size_t> >& tjNonZero,
matrix<Complex>& result,
double factor) const {
for ( vector<pair<size_t,size_t> >::const_iterator i = tiNonZero.begin();
i != tiNonZero.end(); ++i )
for ( vector<pair<size_t,size_t> >::const_iterator j = tjNonZero.begin();
j != tjNonZero.end(); ++j ) {
result(i->first,j->first) += factor*
ti(i->first,i->second)*tj(j->first,j->second)*X(i->second,j->second);
}
}
string ColourBasis::cfstring(const list<list<pair<int,bool> > >& flow) {
ostringstream out("");
for ( list<list<pair<int,bool> > >::const_iterator line =
flow.begin(); line != flow.end(); ++line ) {
for ( list<pair<int,bool> >::const_iterator node =
line->begin(); node != line->end(); ++node ) {
out << (node->second ? "-" : "") << (node->first+1) << " ";
}
if ( line != --(flow.end()) )
out << ", ";
}
return out.str();
}
vector<string> ColourBasis::makeFlows(Ptr<Tree2toNDiagram>::tcptr diag,
size_t dim) const {
vector<string> res(dim);
list<list<list<pair<int,bool> > > > fdata =
colourFlows(diag);
cPDVector ext;
tcPDVector dext = diag->external();
copy(dext.begin(),dext.end(),back_inserter(ext));
vector<PDT::Colour> colouredLegs =
normalOrder(projectColour(ext));
for ( list<list<list<pair<int,bool> > > >::const_iterator flow =
fdata.begin(); flow != fdata.end(); ++flow ) {
for ( size_t i = 0; i < dim; ++i ) {
bool matches = true;
for ( list<list<pair<int,bool> > >::const_iterator line =
flow->begin(); line != flow->end(); ++line ) {
pair<int,bool> front(diag->externalId(line->front().first),line->front().second);
if ( front.first < 2 )
front.second = !front.second;
pair<int,bool> back(diag->externalId(line->back().first),line->back().second);
if ( back.first < 2 )
back.second = !back.second;
if ( !colourConnected(ext,colouredLegs,front,back,i) ) {
matches = false;
break;
}
}
if ( matches ) {
+ assert(res[i] == "" &&
+ "only support colour bases with unique mapping to large-N colour flows");
res[i] = cfstring(*flow);
}
}
}
bool gotone = false;
for ( vector<string>::const_iterator f = res.begin();
f != res.end(); ++f ) {
if ( *f != "" ) {
gotone = true;
break;
}
}
if ( !gotone ) {
generator()->log() << "warning no color flow found for diagram\n";
DiagramDrawer::drawDiag(generator()->log(),*diag);
}
return res;
}
size_t ColourBasis::prepare(const MEBase::DiagramVector& diags,
bool noCorrelations) {
size_t dim = 0;
for ( MEBase::DiagramVector::const_iterator d = diags.begin();
d != diags.end(); ++d ) {
Ptr<Tree2toNDiagram>::tcptr dd = dynamic_ptr_cast<Ptr<Tree2toNDiagram>::ptr>(*d);
assert(dd);
dim = prepare(dd->partons(),noCorrelations);
if ( !haveColourFlows() || theFlowMap.find(dd) != theFlowMap.end() )
continue;
theFlowMap[dd] = makeFlows(dd,dim);
}
return dim;
}
bool matchEnd(int a, pair<int,bool> b,
Ptr<Tree2toNDiagram>::tcptr diag) {
if ( a != b.first )
return false;
if ( b.first != diag->nSpace()-1 ) {
return
!b.second ?
diag->allPartons()[b.first]->hasColour() :
diag->allPartons()[b.first]->hasAntiColour();
} else {
return
!b.second ?
diag->allPartons()[b.first]->hasAntiColour() :
diag->allPartons()[b.first]->hasColour();
}
return false;
}
bool findPath(pair<int,bool> a, pair<int,bool> b,
Ptr<Tree2toNDiagram>::tcptr diag,
list<pair<int,bool> >& path,
bool backward) {
assert(a.first==0 ? !backward : true);
if ( path.empty() )
path.push_back(a);
if ( !backward ) {
if ( diag->children(a.first).first == -1 )
return matchEnd(a.first,b,diag);
pair<int,int> children = diag->children(a.first);
bool cc = (children.first == diag->nSpace()-1);
if ( diag->allPartons()[children.first]->coloured() )
if ( !cc ?
(!a.second ?
diag->allPartons()[children.first]->hasColour() :
diag->allPartons()[children.first]->hasAntiColour()) :
(!a.second ?
diag->allPartons()[children.first]->hasAntiColour() :
diag->allPartons()[children.first]->hasColour()) ) {
pair<int,bool> next(children.first,a.second);
path.push_back(next);
if ( !findPath(next,b,diag,path,false) ) {
path.pop_back();
} else return true;
}
cc = (children.second == diag->nSpace()-1);
if ( diag->allPartons()[children.second]->coloured() )
if ( !cc ?
(!a.second ?
diag->allPartons()[children.second]->hasColour() :
diag->allPartons()[children.second]->hasAntiColour()) :
(!a.second ?
diag->allPartons()[children.second]->hasAntiColour() :
diag->allPartons()[children.second]->hasColour()) ) {
pair<int,bool> next(children.second,a.second);
path.push_back(next);
if ( !findPath(next,b,diag,path,false) ) {
path.pop_back();
} else return true;
}
if ( path.size() == 1 )
path.pop_back();
return false;
} else {
int parent = diag->parent(a.first);
pair<int,int> neighbours = diag->children(parent);
int neighbour = a.first == neighbours.first ? neighbours.second : neighbours.first;
if ( matchEnd(parent,b,diag) ) {
path.push_back(b);
return true;
}
if ( matchEnd(neighbour,b,diag) ) {
path.push_back(b);
return true;
}
if ( diag->allPartons()[neighbour]->coloured() )
if ( a.second ?
diag->allPartons()[neighbour]->hasColour() :
diag->allPartons()[neighbour]->hasAntiColour() ) {
pair<int,bool> next(neighbour,!a.second);
path.push_back(next);
if ( !findPath(next,b,diag,path,false) ) {
path.pop_back();
} else return true;
}
if ( parent == 0 ) {
if ( path.size() == 1 )
path.pop_back();
return false;
}
if ( diag->allPartons()[parent]->coloured() )
if ( !a.second ?
diag->allPartons()[parent]->hasColour() :
diag->allPartons()[parent]->hasAntiColour() ) {
pair<int,bool> next(parent,a.second);
path.push_back(next);
if ( !findPath(next,b,diag,path,true) ) {
path.pop_back();
} else return true;
}
if ( path.size() == 1 )
path.pop_back();
return false;
}
return false;
}
list<pair<int,bool> > ColourBasis::colouredPath(pair<int,bool> a, pair<int,bool> b,
Ptr<Tree2toNDiagram>::tcptr diag) {
list<pair<int,bool> > res;
if ( a.first == b.first )
return res;
bool aIn = (a.first < 2);
bool bIn = (b.first < 2);
if ( (aIn && bIn) || (!aIn && !bIn) )
if ( (a.second && b.second) ||
(!a.second && !b.second) )
return res;
if ( (aIn && !bIn) || (!aIn && bIn) )
if ( (!a.second && b.second) ||
(a.second && !b.second) )
return res;
if ( a.first > b.first )
swap(a,b);
a.first = diag->diagramId(a.first);
b.first = diag->diagramId(b.first);
if ( a.first == diag->nSpace()-1 )
a.second = !a.second;
if ( b.first == diag->nSpace()-1 )
b.second = !b.second;
if ( !findPath(a,b,diag,res,a.first != 0) )
return res;
if ( b.first == diag->nSpace()-1 ) {
res.back().second = !res.back().second;
}
if ( a.first == diag->nSpace()-1 ) {
res.front().second = !res.front().second;
}
return res;
}
list<list<list<pair<int,bool> > > >
ColourBasis::colourFlows(Ptr<Tree2toNDiagram>::tcptr diag) {
vector<pair<int,bool> > connectSource;
vector<pair<int,bool> > connectSink;
for ( size_t i = 0; i != diag->partons().size(); ++i ) {
if ( i < 2 && diag->partons()[i]->hasAntiColour() )
connectSource.push_back(make_pair(i,true));
if ( i < 2 && diag->partons()[i]->hasColour() )
connectSink.push_back(make_pair(i,false));
if ( i > 1 && diag->partons()[i]->hasColour() )
connectSource.push_back(make_pair(i,false));
if ( i > 1 && diag->partons()[i]->hasAntiColour() )
connectSink.push_back(make_pair(i,true));
}
assert(connectSource.size() == connectSink.size());
list<list<list<pair<int,bool> > > > ret;
do {
vector<pair<int,bool> >::iterator source =
connectSource.begin();
vector<pair<int,bool> >::iterator sink =
connectSink.begin();
list<list<pair<int,bool> > > res;
for ( ; source != connectSource.end(); ++source, ++sink ) {
if ( source->first == sink->first ) {
res.clear();
break;
}
list<pair<int,bool> > line =
colouredPath(*source,*sink,diag);
if ( line.empty() ) {
res.clear();
break;
}
res.push_back(line);
}
if ( !res.empty() ) {
// check, if all dressed properly
vector<pair<int,int> > dressed((*diag).allPartons().size(),make_pair(0,0));
for ( size_t p = 0; p < diag->allPartons().size(); ++p ) {
if ( diag->allPartons()[p]->hasColour() &&
!diag->allPartons()[p]->hasAntiColour() )
dressed[p].first = 1;
if ( diag->allPartons()[p]->hasAntiColour() &&
!diag->allPartons()[p]->hasColour() )
dressed[p].second = 1;
if ( diag->allPartons()[p]->hasAntiColour() &&
diag->allPartons()[p]->hasColour() ) {
dressed[p].first = 1; dressed[p].second = 1;
}
}
for ( list<list<pair<int,bool> > >::const_iterator l = res.begin();
l != res.end(); ++l ) {
for ( list<pair<int,bool> >::const_iterator n = l->begin();
n != l->end(); ++n ) {
if ( !(n->second) )
dressed[n->first].first -= 1;
else
dressed[n->first].second -= 1;
}
}
for ( vector<pair<int,int> >::const_iterator d = dressed.begin();
d != dressed.end(); ++d ) {
if ( d->first != 0 || d->second != 0 ) {
res.clear();
break;
}
}
if ( !res.empty() )
ret.push_back(res);
}
} while ( std::next_permutation(connectSink.begin(),connectSink.end()) );
return ret;
}
void ColourBasis::updateColourLines(Ptr<Tree2toNDiagram>::tcptr dd) {
map<Ptr<Tree2toNDiagram>::tcptr,vector<string> >::const_iterator cl =
theFlowMap.find(dd);
assert(cl != theFlowMap.end());
vector<ColourLines*> clines(cl->second.size());
for ( size_t k = 0; k < cl->second.size(); ++k ) {
if ( cl->second[k] == "" ) {
clines[k] = 0;
continue;
}
clines[k] = new ColourLines(cl->second[k]);
}
theColourLineMap[cl->first] = clines;
}
map<Ptr<Tree2toNDiagram>::tcptr,vector<ColourLines*> >&
ColourBasis::colourLineMap() {
if ( !theColourLineMap.empty() )
return theColourLineMap;
for ( map<Ptr<Tree2toNDiagram>::tcptr,vector<string> >::const_iterator cl =
theFlowMap.begin(); cl != theFlowMap.end(); ++cl ) {
vector<ColourLines*> clines(cl->second.size());
for ( size_t k = 0; k < cl->second.size(); ++k ) {
if ( cl->second[k] == "" ) {
clines[k] = 0;
continue;
}
clines[k] = new ColourLines(cl->second[k]);
}
theColourLineMap[cl->first] = clines;
}
return theColourLineMap;
}
Selector<const ColourLines *> ColourBasis::colourGeometries(tcDiagPtr diag,
const map<vector<int>,CVector>& amps) {
Ptr<Tree2toNDiagram>::tcptr dd =
dynamic_ptr_cast<Ptr<Tree2toNDiagram>::tcptr>(diag);
assert(dd && theFlowMap.find(dd) != theFlowMap.end());
map<Ptr<Tree2toNDiagram>::tcptr,vector<ColourLines*> >::const_iterator colit =
colourLineMap().find(dd);
- if ( colit == colourLineMap().end() )
+ if ( colit == colourLineMap().end() ) {
updateColourLines(dd);
- colit = colourLineMap().find(dd);
+ colit = colourLineMap().find(dd);
+ }
const vector<ColourLines*>& cl = colit->second;
Selector<const ColourLines *> sel;
size_t dim = amps.begin()->second.size();
assert(dim == cl.size());
double w = 0.;
for ( size_t i = 0; i < dim; ++i ) {
if ( !cl[i] )
continue;
w = 0.;
for ( map<vector<int>,CVector>::const_iterator a = amps.begin();
a != amps.end(); ++a )
w += real(conj((a->second)(i))*((a->second)(i)));
if ( w > 0. )
sel.insert(w,cl[i]);
}
assert(!sel.empty());
return sel;
}
+size_t ColourBasis::tensorIdFromFlow(tcDiagPtr diag, const ColourLines * flow) const {
+
+ Ptr<Tree2toNDiagram>::tcptr dd =
+ dynamic_ptr_cast<Ptr<Tree2toNDiagram>::tcptr>(diag);
+ assert(dd && theFlowMap.find(dd) != theFlowMap.end());
+ map<Ptr<Tree2toNDiagram>::tcptr,vector<ColourLines*> >::const_iterator colit =
+ colourLineMap().find(dd);
+ if ( colit == colourLineMap().end() ) {
+ updateColourLines(dd);
+ colit = colourLineMap().find(dd);
+ }
+
+ const vector<ColourLines*>& cl = colit->second;
+
+ size_t res = 0;
+ for ( ; res < cl.size(); ++res ) {
+ if ( flow == *cl )
+ break;
+ }
+
+ assert(res < cl.size());
+
+ return res;
+
+}
+
const symmetric_matrix<double,upper>& ColourBasis::scalarProducts(const cPDVector& sub) const {
map<cPDVector,vector<PDT::Colour> >::const_iterator lit =
theNormalOrderedLegs.find(sub);
assert(lit != theNormalOrderedLegs.end());
ScalarProductMap::const_iterator spit =
theScalarProducts.find(lit->second);
assert(spit != theScalarProducts.end());
return spit->second;
}
const compressed_matrix<double>& ColourBasis::charge(const cPDVector& sub, size_t iIn) const {
map<cPDVector,vector<PDT::Colour> >::const_iterator lit =
theNormalOrderedLegs.find(sub);
assert(lit != theNormalOrderedLegs.end());
ChargeMap::const_iterator ct =
theCharges.find(lit->second);
assert(ct != theCharges.end());
map<cPDVector,map<size_t,size_t> >::const_iterator trans
= theIndexMap.find(sub);
assert(trans != theIndexMap.end());
size_t i = trans->second.find(iIn)->second;
map<size_t,compressed_matrix<double> >::const_iterator cit
= ct->second.find(i);
assert(cit != ct->second.end());
return cit->second;
}
const vector<pair<size_t,size_t> >& ColourBasis::chargeNonZero(const cPDVector& sub, size_t iIn) const {
map<cPDVector,vector<PDT::Colour> >::const_iterator lit =
theNormalOrderedLegs.find(sub);
assert(lit != theNormalOrderedLegs.end());
ChargeNonZeroMap::const_iterator ct =
theChargeNonZeros.find(lit->second);
assert(ct != theChargeNonZeros.end());
map<cPDVector,map<size_t,size_t> >::const_iterator trans
= theIndexMap.find(sub);
assert(trans != theIndexMap.end());
size_t i = trans->second.find(iIn)->second;
map<size_t,vector<pair<size_t,size_t> > >::const_iterator cit
= ct->second.find(i);
assert(cit != ct->second.end());
return cit->second;
}
const symmetric_matrix<double,upper>& ColourBasis::correlator(const cPDVector& sub,
const pair<size_t,size_t>& ijIn) const {
map<cPDVector,vector<PDT::Colour> >::const_iterator lit =
theNormalOrderedLegs.find(sub);
assert(lit != theNormalOrderedLegs.end());
CorrelatorMap::const_iterator cit =
theCorrelators.find(lit->second);
assert(cit != theCorrelators.end());
map<cPDVector,map<size_t,size_t> >::const_iterator trans
= theIndexMap.find(sub);
assert(trans != theIndexMap.end());
pair<size_t,size_t> ij(trans->second.find(ijIn.first)->second,
trans->second.find(ijIn.second)->second);
if ( ij.first > ij.second )
swap(ij.first,ij.second);
map<pair<size_t,size_t>,symmetric_matrix<double,upper> >::const_iterator cijit
= cit->second.find(ij);
assert(cijit != cit->second.end());
return cijit->second;
}
double ColourBasis::me2(const cPDVector& sub,
const map<vector<int>,CVector>& amps) const {
const symmetric_matrix<double,upper>& sp = scalarProducts(sub);
double res = 0.;
for ( map<vector<int>,CVector>::const_iterator a = amps.begin();
a != amps.end(); ++a ) {
res += real(inner_prod(boost::numeric::ublas::conj(a->second),prod(sp,a->second)));
}
return res;
}
double ColourBasis::interference(const cPDVector& sub,
const map<vector<int>,CVector>& amps1,
const map<vector<int>,CVector>& amps2) const {
const symmetric_matrix<double,upper>& sp = scalarProducts(sub);
double res = 0.;
map<vector<int>,CVector>::const_iterator a = amps1.begin();
map<vector<int>,CVector>::const_iterator b = amps2.begin();
for ( ; a != amps1.end(); ++a, ++b ) {
assert(a->first == b->first);
res += 2.*real(inner_prod(boost::numeric::ublas::conj(a->second),prod(sp,b->second)));
}
assert(!isnan(res));
return res;
}
double ColourBasis::colourCorrelatedME2(const pair<size_t,size_t>& ij,
const cPDVector& sub,
const map<vector<int>,CVector>& amps) const {
const symmetric_matrix<double,upper>& cij = correlator(sub,ij);
double res = 0.;
for ( map<vector<int>,CVector>::const_iterator a = amps.begin();
a != amps.end(); ++a ) {
res += real(inner_prod(boost::numeric::ublas::conj(a->second),prod(cij,a->second)));
}
return res;
}
Complex ColourBasis::interference(const cPDVector& sub,
const CVector& left,
const CVector& right) const {
const symmetric_matrix<double,upper>& sp = scalarProducts(sub);
return inner_prod(boost::numeric::ublas::conj(left),prod(sp,right));
}
Complex ColourBasis::colourCorrelatedInterference(const pair<size_t,size_t>& ij,
const cPDVector& sub,
const CVector& left,
const CVector& right) const {
const symmetric_matrix<double,upper>& cij = correlator(sub,ij);
return inner_prod(boost::numeric::ublas::conj(left),prod(cij,right));
}
double ColourBasis::me2(const cPDVector& sub,
const matrix<Complex>& amp) const {
const symmetric_matrix<double,upper>& sp = scalarProducts(sub);
double tr = 0;
size_t n = amp.size1();
for ( size_t i = 0; i < n; ++i ) {
tr += real(inner_prod(row(sp,i),column(amp,i)));
}
return tr;
}
double ColourBasis::colourCorrelatedME2(const pair<size_t,size_t>& ij,
const cPDVector& sub,
const matrix<Complex>& amp) const {
const symmetric_matrix<double,upper>& cij = correlator(sub,ij);
double tr = 0;
size_t n = amp.size1();
for ( size_t i = 0; i < n; ++i ) {
tr += real(inner_prod(row(cij,i),column(amp,i)));
}
return tr;
}
struct pickColour {
PDT::Colour operator()(tcPDPtr p) const {
return p->iColour();
}
};
vector<PDT::Colour> ColourBasis::projectColour(const cPDVector& sub) const {
vector<PDT::Colour> res(sub.size());
transform(sub.begin(),sub.end(),res.begin(),pickColour());
return res;
}
vector<PDT::Colour> ColourBasis::normalOrder(const vector<PDT::Colour>& legs) const {
vector<PDT::Colour> crosslegs = legs;
if ( crosslegs[0] == PDT::Colour3 )
crosslegs[0] = PDT::Colour3bar;
else if ( crosslegs[0] == PDT::Colour3bar )
crosslegs[0] = PDT::Colour3;
if ( crosslegs[1] == PDT::Colour3 )
crosslegs[1] = PDT::Colour3bar;
else if ( crosslegs[1] == PDT::Colour3bar )
crosslegs[1] = PDT::Colour3;
int n3 = count_if(crosslegs.begin(),crosslegs.end(),matchRep(PDT::Colour3));
int n8 = count_if(crosslegs.begin(),crosslegs.end(),matchRep(PDT::Colour8));
vector<PDT::Colour> ordered(2*n3+n8,PDT::Colour8);
int i = 0;
while ( i < 2*n3 ) {
ordered[i] = PDT::Colour3;
ordered[i+1] = PDT::Colour3bar;
i+=2;
}
return ordered;
}
string ColourBasis::file(const vector<PDT::Colour>& sub) const {
string res = name() + "-";
for ( vector<PDT::Colour>::const_iterator lit = sub.begin();
lit != sub.end(); ++lit ) {
if ( *lit == PDT::Colour3 )
res += "3";
if ( *lit == PDT::Colour3bar )
res += "3bar";
if ( *lit == PDT::Colour8 )
res += "8";
}
if ( largeN() )
res += "largeN";
return res;
}
void ColourBasis::writeBasis(const string& prefix) const {
if ( didWrite )
return;
set<vector<PDT::Colour> > legs;
for ( map<cPDVector,vector<PDT::Colour> >::const_iterator lit
= theNormalOrderedLegs.begin(); lit != theNormalOrderedLegs.end(); ++lit ) {
legs.insert(lit->second);
}
string searchPath = theSearchPath;
if ( searchPath != "" )
if ( *(--searchPath.end()) != '/' )
searchPath += "/";
for ( set<vector<PDT::Colour> >::const_iterator known = legs.begin();
known != legs.end(); ++known ) {
string fname = searchPath + prefix + file(*known) + ".cdat";
ifstream check(fname.c_str());
if ( check ) continue;
ofstream out(fname.c_str());
if ( !out )
throw Exception() << "ColourBasis failed to open "
<< fname << " for storing colour basis information."
<< Exception::abortnow;
out << setprecision(18);
const symmetric_matrix<double,upper>& sp =
theScalarProducts.find(*known)->second;
write(sp,out);
if ( theCharges.find(*known) != theCharges.end() ) {
out << "#charges\n";
const map<size_t,compressed_matrix<double> >& tm =
theCharges.find(*known)->second;
const map<size_t,vector<pair<size_t,size_t> > >& tc =
theChargeNonZeros.find(*known)->second;
map<size_t,vector<pair<size_t,size_t> > >::const_iterator kc =
tc.begin();
for ( map<size_t,compressed_matrix<double> >::const_iterator k = tm.begin();
k != tm.end(); ++k, ++kc ) {
out << k->first << "\n";
write(k->second,out,kc->second);
}
const map<pair<size_t,size_t>,symmetric_matrix<double,upper> >& cm =
theCorrelators.find(*known)->second;
for ( map<pair<size_t,size_t>,symmetric_matrix<double,upper> >::const_iterator k =
cm.begin(); k != cm.end(); ++k ) {
out << k->first.first << "\n" << k->first.second << "\n";
write(k->second,out);
}
} else {
out << "#nocharges\n";
}
out << flush;
}
didWrite = true;
}
bool ColourBasis::readBasis(const vector<PDT::Colour>& legs) {
string searchPath = theSearchPath;
if ( searchPath != "" )
if ( *(--searchPath.end()) != '/' )
searchPath += "/";
string fname = searchPath + file(legs) + ".cdat";
ifstream in(fname.c_str());
if ( !in )
return false;
read(theScalarProducts[legs],in);
string tag; in >> tag;
if ( tag != "#nocharges" ) {
for ( size_t k = 0; k < legs.size(); ++k ) {
size_t i; in >> i;
read(theCharges[legs][i],in,theChargeNonZeros[legs][i]);
}
for ( size_t k = 0; k < legs.size()*(legs.size()-1)/2; ++k ) {
size_t i,j; in >> i >> j;
read(theCorrelators[legs][make_pair(i,j)],in);
}
}
readBasisDetails(legs);
return true;
}
void ColourBasis::readBasis() {
if ( didRead )
return;
string searchPath = theSearchPath;
if ( searchPath != "" )
if ( *(--searchPath.end()) != '/' )
searchPath += "/";
set<vector<PDT::Colour> > legs;
for ( map<cPDVector,vector<PDT::Colour> >::const_iterator lit
= theNormalOrderedLegs.begin(); lit != theNormalOrderedLegs.end(); ++lit )
legs.insert(lit->second);
for ( set<vector<PDT::Colour> >::const_iterator known = legs.begin();
known != legs.end(); ++known ) {
if ( theScalarProducts.find(*known) != theScalarProducts.end() )
continue;
string fname = searchPath + file(*known) + ".cdat";
if ( !readBasis(*known) )
throw Exception() << "ColourBasis failed to open "
<< fname << " for reading colour basis information."
<< Exception::abortnow;
}
didRead = true;
}
void ColourBasis::write(const symmetric_matrix<double,upper>& m, ostream& os) const {
os << m.size1() << "\n";
for ( size_t i = 0; i < m.size1(); ++i )
for ( size_t j = i; j < m.size1(); ++j )
os << m(i,j) << "\n";
os << flush;
}
void ColourBasis::read(symmetric_matrix<double,upper>& m, istream& is) {
size_t s; is >> s;
m.resize(s);
for ( size_t i = 0; i < m.size1(); ++i )
for ( size_t j = i; j < m.size1(); ++j )
is >> m(i,j);
}
void ColourBasis::write(const compressed_matrix<double>& m, ostream& os,
const vector<pair<size_t,size_t> >& nonZeros) const {
os << nonZeros.size() << "\n"
<< m.size1() << "\n"
<< m.size2() << "\n";
for ( vector<pair<size_t,size_t> >::const_iterator nz = nonZeros.begin();
nz != nonZeros.end(); ++nz )
os << nz->first << "\n" << nz->second << "\n"
<< m(nz->first,nz->second) << "\n";
os << flush;
}
void ColourBasis::read(compressed_matrix<double>& m, istream& is,
vector<pair<size_t,size_t> >& nonZeros) {
size_t nonZero, size1, size2;
is >> nonZero >> size1 >> size2;
nonZeros.resize(nonZero);
m = compressed_matrix<double>(size1,size2,nonZero);
for ( size_t k = 0; k < nonZero; ++k ) {
size_t i,j; double val;
is >> i >> j >> val;
nonZeros[k] = make_pair(i,j);
m(i,j) = val;
}
}
void ColourBasis::doinit() {
HandlerBase::doinit();
if ( theSearchPath.empty() && factory() )
theSearchPath = factory()->buildStorage();
readBasis();
}
void ColourBasis::dofinish() {
HandlerBase::dofinish();
writeBasis();
}
void ColourBasis::doinitrun() {
HandlerBase::doinitrun();
if ( theSearchPath.empty() && factory() )
theSearchPath = factory()->buildStorage();
readBasis();
}
void ColourBasis::persistentOutput(PersistentOStream & os) const {
os << theLargeN << theNormalOrderedLegs
<< theIndexMap << theFlowMap << theOrderingStringIdentifiers
<< theOrderingIdentifiers << theFactory << theSearchPath;
writeBasis();
}
void ColourBasis::persistentInput(PersistentIStream & is, int) {
is >> theLargeN >> theNormalOrderedLegs
>> theIndexMap >> theFlowMap >> theOrderingStringIdentifiers
>> theOrderingIdentifiers >> theFactory >> theSearchPath;
}
// *** 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).
DescribeAbstractClass<ColourBasis,HandlerBase>
describeColourBasis("Herwig::ColourBasis", "Herwig.so");
void ColourBasis::Init() {
static ClassDocumentation<ColourBasis> documentation
("ColourBasis is an interface to a colour basis "
"implementation.");
static Switch<ColourBasis,bool> interfaceLargeN
("LargeN",
"Switch on or off large-N evaluation.",
&ColourBasis::theLargeN, false, false, false);
static SwitchOption interfaceLargeNOn
(interfaceLargeN,
"On",
"Work in N=infinity",
true);
static SwitchOption interfaceLargeNOff
(interfaceLargeN,
"Off",
"Work in N=3",
false);
}
diff --git a/MatrixElement/Matchbox/Utility/ColourBasis.h b/MatrixElement/Matchbox/Utility/ColourBasis.h
--- a/MatrixElement/Matchbox/Utility/ColourBasis.h
+++ b/MatrixElement/Matchbox/Utility/ColourBasis.h
@@ -1,571 +1,576 @@
// -*- C++ -*-
//
// ColourBasis.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_ColourBasis_H
#define HERWIG_ColourBasis_H
//
// This is the declaration of the ColourBasis class.
//
#include "ThePEG/Handlers/HandlerBase.h"
#include "ThePEG/MatrixElement/Tree2toNDiagram.h"
#include "ThePEG/MatrixElement/MEBase.h"
#include "Herwig++/MatrixElement/Matchbox/Utility/MatchboxXComb.h"
#include "Herwig++/MatrixElement/Matchbox/MatchboxFactory.fh"
#include <iterator>
namespace Herwig {
using std::iterator_traits;
using std::distance;
using namespace ThePEG;
using boost::numeric::ublas::matrix;
using boost::numeric::ublas::symmetric_matrix;
using boost::numeric::ublas::compressed_matrix;
using boost::numeric::ublas::upper;
/**
* \ingroup Matchbox
* \author Simon Platzer
*
* \brief ColourBasis is an interface to a colour basis
* implementation.
*
*/
class ColourBasis: public HandlerBase {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
ColourBasis();
/**
* The destructor.
*/
virtual ~ColourBasis();
//@}
public:
/**
* Return the factory which produced this matrix element
*/
Ptr<MatchboxFactory>::tptr factory() const;
/**
* Set the factory which produced this matrix element
*/
void factory(Ptr<MatchboxFactory>::tptr f);
/**
* Clone this colour basis.
*/
Ptr<ColourBasis>::ptr cloneMe() const {
return dynamic_ptr_cast<Ptr<ColourBasis>::ptr>(clone());
}
/**
* Clear this colour basis
*/
virtual void clear();
/**
* Prepare for the given sub process and return the basis
* dimensionality.
*/
size_t prepare(const cPDVector&, bool);
/**
* Prepare for the given diagrams.
*/
size_t prepare(const MEBase::DiagramVector&, bool);
/**
* Return the index map.
*/
const map<cPDVector,map<size_t,size_t> >& indexMap() const { return theIndexMap; }
/**
* Return a map of basis tensor indices to vectors identifying a
* certain ordering corresponding to the given colour structure. May
* not be supported by all colour basis implementations.
*/
virtual map<size_t,vector<vector<size_t> > > basisList(const vector<PDT::Colour>&) const {
return map<size_t,vector<vector<size_t> > >();
}
/**
* Given a physical subprocess, a colour to amplitude label map and
* a basis tensor index, return an identifier of the ordering
* coresponding to the given colour structure. This will only return
* sensible results for colour bases which implement the basisList
* query.
*/
const string& orderingString(const cPDVector& sub,
const map<size_t,size_t>& colourToAmplitude,
size_t tensorId);
/**
* Given a physical subprocess, a colour to amplitude label map and
* a basis tensor index, return an identifier of the ordering
* coresponding to the given colour structure. This will only return
* sensible results for colour bases which implement the basisList
* query.
*/
const set<vector<size_t> >& ordering(const cPDVector& sub,
const map<size_t,size_t>& colourToAmplitude,
size_t tensorId);
/**
* For the given subprocess and amplitude vectors
* calculate the amplitude squared.
*/
double me2(const cPDVector&, const map<vector<int>,CVector>&) const;
/**
* For the given subprocess and amplitude vectors
* calculate the interference.
*/
double interference(const cPDVector&,
const map<vector<int>,CVector>&,
const map<vector<int>,CVector>&) const;
/**
* For the given subprocess and amplitude vector
* calculate the colour correlated amplitude.
*/
double colourCorrelatedME2(const pair<size_t,size_t>&,
const cPDVector&,
const map<vector<int>,CVector>&) const;
/**
* For the given subprocess and amplitude vector
* calculate the amplitude squared.
*/
Complex interference(const cPDVector&,
const CVector&, const CVector&) const;
/**
* For the given subprocess and amplitude vector
* calculate the colour correlated amplitude.
*/
Complex colourCorrelatedInterference(const pair<size_t,size_t>&,
const cPDVector&,
const CVector&, const CVector&) const;
/**
* For the given subprocess and amplitude given as amp amp^\dagger
* calculate the amplitude squared.
*/
double me2(const cPDVector&, const matrix<Complex>&) const;
/**
* For the given subprocess and amplitude given as amp amp^\dagger
* calculate the colour correlated amplitude.
*/
double colourCorrelatedME2(const pair<size_t,size_t>&,
const cPDVector&,
const matrix<Complex>&) const;
/**
* Return the scalar product matrix for the given process.
*/
const symmetric_matrix<double,upper>& scalarProducts(const cPDVector&) const;
/**
* Return the matrix representation of a colour charge.
*/
const compressed_matrix<double>& charge(const cPDVector&, size_t) const;
/**
* Return the non-vanishing elements of a colour charge.
*/
const vector<pair<size_t,size_t> >& chargeNonZero(const cPDVector&, size_t) const;
/**
* Return the correlator matrix for the given process.
*/
const symmetric_matrix<double,upper>& correlator(const cPDVector&,
const pair<size_t,size_t>&) const;
/**
* Return true, if the colour basis is capable of assigning colour
* flows.
*/
virtual bool haveColourFlows() const { return false; }
/**
* Return a Selector with possible colour geometries for the selected
* diagram weighted by their relative probabilities.
*/
Selector<const ColourLines *> colourGeometries(tcDiagPtr diag,
const map<vector<int>,CVector>& amps);
/**
+ * Return the colour tensor used for the selected colour flow
+ */
+ size_t tensorIdFromFlow(tcDiagPtr diag, const ColourLines * cl) const;
+
+ /**
* Match colour representation.
*/
struct matchRep {
PDT::Colour m;
matchRep(PDT::Colour n)
: m(n) {}
bool operator()(PDT::Colour c) const {
return c == m;
}
};
/**
* Return true, if this basis is running in large-N mode
*/
virtual bool largeN() const { return theLargeN; }
/**
* Switch to large n
*/
void doLargeN(bool yes = true) { theLargeN = yes; }
/**
* Convert particle data to colour information
*/
vector<PDT::Colour> projectColour(const cPDVector&) const;
/**
* Perform a normal ordering of the external legs. This default
* implementation assumes normal ordered legs as 3 3bar ... 3 3bar 8 ... 8
* while removing all non-coloured particles.
*/
virtual vector<PDT::Colour> normalOrder(const vector<PDT::Colour>&) const;
/**
* Determine the mapping of process to colour indices and return the
* normal ordered vector of colour indices
*/
vector<PDT::Colour> normalOrderMap(const cPDVector& sub);
/**
* Get the normal ordered legs
*/
const vector<PDT::Colour>& normalOrderedLegs(const cPDVector& sub) const;
/**
* Convert the legs to a string.
*/
string file(const vector<PDT::Colour>&) const;
/**
* Calculate T_i^\dagger X T_j
*/
void chargeProduct(const compressed_matrix<double>& ti,
const vector<pair<size_t,size_t> >& tiNonZero,
const symmetric_matrix<double,upper>& X,
const compressed_matrix<double>& tj,
const vector<pair<size_t,size_t> >& tjNonZero,
symmetric_matrix<double,upper>& result) const;
/**
* Calculate T_i X T_j^\dagger
*/
void chargeProductAdd(const compressed_matrix<double>& ti,
const vector<pair<size_t,size_t> >& tiNonZero,
const matrix<Complex>& X,
const compressed_matrix<double>& tj,
const vector<pair<size_t,size_t> >& tjNonZero,
matrix<Complex>& result,
double factor = 1.) const;
public:
/**
* Find a coloured path from a to b within the given diagram.
*/
static list<pair<int,bool> > colouredPath(pair<int,bool> a, pair<int,bool> b,
Ptr<Tree2toNDiagram>::tcptr);
/**
* Get all colour flows for the given diagram.
*/
static list<list<list<pair<int,bool> > > > colourFlows(Ptr<Tree2toNDiagram>::tcptr);
/**
* Convert a flow to a string representation appropriate for
* ColourLines
*/
static string cfstring(const list<list<pair<int,bool> > >&);
protected:
/**
* Prepare the basis for the normal ordered legs and return the
* dimensionality of the basis.
*/
virtual size_t prepareBasis(const vector<PDT::Colour>&) = 0;
/**
* Return the scalar product of basis tensors labelled a and b in
* the basis used for the given normal ordered legs.
*/
virtual double scalarProduct(size_t a, size_t b,
const vector<PDT::Colour>& abBasis) const = 0;
/**
* Return the matrix element of a colour charge
* <c_{n+1,a}|T_i|c_{n,b}> between basis tensors a and b, with
* respect to aBasis and bBasis
*/
virtual double tMatrixElement(size_t i, size_t a, size_t b,
const vector<PDT::Colour>& aBasis,
const vector<PDT::Colour>& bBasis) const = 0;
/**
* Return true, if a large-N colour connection exists for the
* given external legs and basis tensor.
*/
virtual bool colourConnected(const cPDVector&,
const vector<PDT::Colour>&,
const pair<int,bool>&,
const pair<int,bool>&,
size_t) const;
/**
* Return true, if a large-N colour connection exists for the
* given external legs and basis tensor.
*/
virtual bool colourConnected(const vector<PDT::Colour>&,
int, int, size_t) const {
return false;
}
/**
* Match up colour flows for given diagram to basis tensors.
*/
vector<string> makeFlows(Ptr<Tree2toNDiagram>::tcptr, size_t) const;
/**
* Return the colour line map.
*/
map<Ptr<Tree2toNDiagram>::tcptr,vector<ColourLines*> >&
colourLineMap();
/**
* Update the colour line map for a given diagram.
*/
void updateColourLines(Ptr<Tree2toNDiagram>::tcptr);
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();
// 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 factory which produced this matrix element
*/
Ptr<MatchboxFactory>::tptr theFactory;
typedef map<vector<PDT::Colour>,symmetric_matrix<double,upper> >
ScalarProductMap;
typedef map<vector<PDT::Colour>,map<size_t,compressed_matrix<double> > > ChargeMap;
typedef map<vector<PDT::Colour>,map<size_t,vector<pair<size_t,size_t > > > > ChargeNonZeroMap;
typedef map<vector<PDT::Colour>,map<pair<size_t,size_t>,symmetric_matrix<double,upper> > > CorrelatorMap;
/**
* True, if this basis is running in large-N mode
*/
bool theLargeN;
/**
* Map external legs to normal ordered versions
*/
map<cPDVector,vector<PDT::Colour> > theNormalOrderedLegs;
/**
* Index mappings to normal order from given leg assignments,
* indexed by the original leg assignment.
*/
map<cPDVector,map<size_t,size_t> > theIndexMap;
/**
* The scalar product matrix S_n = <c_{n,a}|c_{n,b}> , indexed
* by normal ordered leg assignments.
*/
ScalarProductMap theScalarProducts;
/**
* The colour charge matrices <c_{n+1,a}|T_i|c_{n,b}> indexed by
* the `n' normal ordered legs and the index i.
*/
ChargeMap theCharges;
/**
* The nonzero elements of the charge matrices.
*/
ChargeNonZeroMap theChargeNonZeros;
/**
* The correlator matrices T_i\cdot T_j -> T_i^\dagger S_{n+1} T_j
* with T_i = <c_{n+1,a}|T_i|c_{n,b}> indexed by the `n' basis
* normal ordered legs and indices i,j
*/
CorrelatorMap theCorrelators;
/**
* Map diagrams to colour flows indexed by basis tensor.
*/
map<Ptr<Tree2toNDiagram>::tcptr,vector<string> > theFlowMap;
/**
* Map diagrams to colour line objects.
*/
map<Ptr<Tree2toNDiagram>::tcptr,vector<ColourLines*> > theColourLineMap;
/**
* Store ordering identifiers
*/
map<cPDVector,map<size_t,string> > theOrderingStringIdentifiers;
/**
* Store ordering identifiers
*/
map<cPDVector,map<size_t,set<vector<size_t> > > > theOrderingIdentifiers;
/**
* Write out yet unknown basis computations.
*/
void writeBasis(const string& prefix = "") const;
/**
* Read in the basis computation which are supposed to be known.
*/
void readBasis();
/**
* Read in the basis computation which are supposed to be known.
*/
bool readBasis(const vector<PDT::Colour>&);
/**
* Gather any implementation dependend details when reading a basis
*/
virtual void readBasisDetails(const vector<PDT::Colour>&) {}
/**
* Write out symmetric matrices.
*/
void write(const symmetric_matrix<double,upper>&, ostream&) const;
/**
* Read in symmetric matrices.
*/
void read(symmetric_matrix<double,upper>&, istream&);
/**
* Write out compressed matrices.
*/
void write(const compressed_matrix<double>&, ostream&,
const vector<pair<size_t,size_t> >&) const;
/**
* Read in compressed matrices.
*/
void read(compressed_matrix<double>&, istream&,
vector<pair<size_t,size_t> >&);
/**
* True, if an attempt to read in basis information has been
* completed.
*/
bool didRead;
/**
* True, if an attempt to write out basis information has been
* completed.
*/
mutable bool didWrite;
/**
* Temporary storage.
*/
matrix<double> tmp;
/**
* The search path
*/
string theSearchPath;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
ColourBasis & operator=(const ColourBasis &);
};
}
#endif /* HERWIG_ColourBasis_H */

File Metadata

Mime Type
text/x-diff
Expires
Sat, Dec 21, 12:53 PM (1 d, 21 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4022835
Default Alt Text
(329 KB)

Event Timeline