Page Menu
Home
HEPForge
Search
Configure Global Search
Log In
Files
F7877905
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
141 KB
Subscribers
None
View Options
diff --git a/Cuts/Cuts.cc b/Cuts/Cuts.cc
--- a/Cuts/Cuts.cc
+++ b/Cuts/Cuts.cc
@@ -1,578 +1,615 @@
// -*- C++ -*-
//
// Cuts.cc is a part of ThePEG - Toolkit for HEP Event Generation
// Copyright (C) 1999-2011 Leif Lonnblad
//
// ThePEG 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 Cuts class.
//
#include "Cuts.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/RefVector.h"
#include "ThePEG/PDT/ParticleData.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/EventRecord/SubProcess.h"
#include "ThePEG/EventRecord/Collision.h"
#include "ThePEG/EventRecord/TmpTransform.h"
#include "ThePEG/Utilities/UtilityBase.h"
#include "ThePEG/Utilities/HoldFlag.h"
#include "ThePEG/Utilities/Debug.h"
#include "ThePEG/Repository/CurrentGenerator.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Config/algorithm.h"
using namespace ThePEG;
Cuts::Cuts(Energy MhatMin)
: theSMax(ZERO), theY(0), theCurrentSHat(-1.0*GeV2),
theCurrentYHat(0), theMHatMin(MhatMin), theMHatMax(Constants::MaxEnergy),
theYHatMin(-Constants::MaxRapidity), theYHatMax(Constants::MaxRapidity),
theX1Min(0.0), theX1Max(1.0), theX2Min(0.0), theX2Max(1.0),
theScaleMin(ZERO), theScaleMax(Constants::MaxEnergy2),
- theSubMirror(false) {}
+ theSubMirror(false), theCutWeight(1.0), theLastCutWeight(1.0) {}
Cuts::~Cuts() {}
IBPtr Cuts::clone() const {
return new_ptr(*this);
}
IBPtr Cuts::fullclone() const {
return new_ptr(*this);
}
void Cuts::doinitrun() {
Interfaced::doinitrun();
if ( Debug::level ) {
describe();
for_each(theOneCuts, mem_fun(&OneCutBase::describe));
for_each(theTwoCuts, mem_fun(&TwoCutBase::describe));
for_each(theMultiCuts, mem_fun(&MultiCutBase::describe));
}
}
void Cuts::describe() const {
CurrentGenerator::log()
<< fullName() << ":\n"
<< "MHat = " << theMHatMin/GeV << " .. " << theMHatMax/GeV << " GeV\n"
<< "Scale = " << theScaleMin/GeV2 << " .. " << theScaleMax/GeV2 << " GeV2\n"
<< "YHat = " << theYHatMin << " .. " << theYHatMax << '\n'
<< "X1 = " << theX1Min << " .. " << theX1Max << '\n'
<< "X2 = " << theX2Min << " .. " << theX2Max << "\n\n";
}
void Cuts::initialize(Energy2 smax, double Y) {
theSMax = smax;
theMHatMax = min(theMHatMax, sqrt(smax));
theY = Y;
theSubMirror = false;
}
void Cuts::initEvent() {
theCurrentSHat = -1.0*GeV2;
theCurrentYHat = 0.0;
theSubMirror = false;
}
bool Cuts::initSubProcess(Energy2 shat, double yhat, bool mirror) const {
+ theCutWeight = 1.0;
+ theLastCutWeight = 1.0;
theSubMirror = mirror;
theCurrentSHat = shat;
theCurrentYHat = yhat;
if ( shat <= sHatMin() || shat > sHatMax()*(1.0 + 1000.0*Constants::epsilon) ) return false;
if ( yhat <= yHatMin() || yhat >= yHatMax() ) return false;
double x1 = min(1.0, sqrt(shat/SMax())*exp(yhat));
if ( x1 <= x1Min() || x1 > x1Max() ) return false;
double x2 = min(1.0, sqrt(shat/SMax())*exp(-yhat));
if ( x2 <= x2Min() || x2 > x2Max() ) return false;
return true;
}
bool Cuts::passCuts(const tcPDVector & ptype, const vector<LorentzMomentum> & p,
tcPDPtr t1, tcPDPtr t2) const {
if ( subMirror() ) {
vector<LorentzMomentum> pmir = p;
for ( int i = 0, N = pmir.size(); i < N; ++i ) pmir[i].setZ(-pmir[i].z());
swap(t1,t2);
HoldFlag<> nomir(theSubMirror, false);
return passCuts(ptype, pmir, t1, t2);
}
+ bool pass = true;
+ theCutWeight = 1.0;
+ theLastCutWeight = 1.0;
+
+ // ATTENTION fuzzy jet finding
if ( jetFinder() )
if ( ptype.size() > jetFinder()->minOutgoing() ) {
vector<LorentzMomentum> jets = p;
tcPDVector jettype = ptype;
if ( jetFinder()->cluster(jettype,jets,this,t1,t2) ){
return passCuts(jettype,jets,t1,t2);
}
}
for ( int i = 0, N = p.size(); i < N; ++i )
- for ( int j = 0, M = theOneCuts.size(); j < M; ++j )
- if ( !theOneCuts[j]->passCuts(this, ptype[i], p[i]) ) return false;
+ for ( int j = 0, M = theOneCuts.size(); j < M; ++j ) {
+ pass &= theOneCuts[j]->passCuts(this, ptype[i], p[i]);
+ theCutWeight *= theLastCutWeight;
+ theLastCutWeight = 1.0;
+ if ( !pass )
+ return false;
+ }
for ( int i1 = 0, N1 = p.size() - 1; i1 < N1; ++i1 )
for ( int i2 = i1 + 1, N2 = p.size(); i2 < N2; ++i2 )
- for ( int j = 0, M = theTwoCuts.size(); j < M; ++j )
- if ( !theTwoCuts[j]->passCuts(this, ptype[i1], ptype[i2],
- p[i1], p[i2]) ) return false;
- for ( int j = 0, M = theMultiCuts.size(); j < M; ++j )
- if ( !theMultiCuts[j]->passCuts(this, ptype, p) ) return false;
+ for ( int j = 0, M = theTwoCuts.size(); j < M; ++j ) {
+ pass &= theTwoCuts[j]->passCuts(this, ptype[i1], ptype[i2],
+ p[i1], p[i2]);
+ theCutWeight *= theLastCutWeight;
+ theLastCutWeight = 1.0;
+ if ( !pass )
+ return false;
+ }
+
+ for ( int j = 0, M = theMultiCuts.size(); j < M; ++j ) {
+ pass &= theMultiCuts[j]->passCuts(this, ptype, p);
+ theCutWeight *= theLastCutWeight;
+ theLastCutWeight = 1.0;
+ if ( !pass )
+ return false;
+ }
+
if ( t1 ) {
LorentzMomentum p1(ZERO, ZERO, 0.5*sqrt(currentSHat()),
0.5*sqrt(currentSHat()));
for ( int i = 0, N = p.size(); i < N; ++i )
- for ( int j = 0, M = theTwoCuts.size(); j < M; ++j )
- if ( !theTwoCuts[j]->passCuts(this, t1, ptype[i], p1, p[i],
- true, false) )
+ for ( int j = 0, M = theTwoCuts.size(); j < M; ++j ) {
+ pass &= theTwoCuts[j]->passCuts(this, t1, ptype[i], p1, p[i],
+ true, false);
+ theCutWeight *= theLastCutWeight;
+ theLastCutWeight = 1.0;
+ if ( !pass )
return false;
+ }
}
+
if ( t2 ) {
LorentzMomentum p2(ZERO, ZERO,
-0.5*sqrt(currentSHat()), 0.5*sqrt(currentSHat()));
for ( int i = 0, N = p.size(); i < N; ++i )
- for ( int j = 0, M = theTwoCuts.size(); j < M; ++j )
- if ( !theTwoCuts[j]->passCuts(this, ptype[i], t2, p[i], p2,
- false, true) )
+ for ( int j = 0, M = theTwoCuts.size(); j < M; ++j ) {
+ pass &= theTwoCuts[j]->passCuts(this, ptype[i], t2, p[i], p2,
+ false, true);
+ theCutWeight *= theLastCutWeight;
+ theLastCutWeight = 1.0;
+ if ( !pass )
return false;
+ }
}
- return true;
+
+ return pass;
+
}
bool Cuts::passCuts(const tcPVector & p, tcPDPtr t1, tcPDPtr t2) const {
tcPDVector ptype(p.size());
vector<LorentzMomentum> mom(p.size());
for ( int i = 0, N = p.size(); i < N; ++i ) {
ptype[i] = p[i]->dataPtr();
mom[i] = p[i]->momentum();
}
return passCuts(ptype, mom, t1, t2);
}
bool Cuts::passCuts(const SubProcess & sub) const {
if ( !passCuts(tcPVector(sub.outgoing().begin(), sub.outgoing().end()),
sub.incoming().first->dataPtr(),
sub.incoming().second->dataPtr()) ) return false;
return true;
}
bool Cuts::passCuts(const Collision & coll) const {
tSubProPtr sub = coll.primarySubProcess();
LorentzMomentum phat = sub->incoming().first->momentum() +
sub->incoming().second->momentum();
if ( !initSubProcess(phat.m2(), phat.rapidity()) ) return false;
TmpTransform<tSubProPtr> tmp(sub, Utilities::getBoostToCM(sub->incoming()));
if ( !passCuts(*sub) ) return false;
return true;
}
Energy2 Cuts::minS(const tcPDVector & pv) const {
Energy2 mins = ZERO;
for ( int i = 0, N = theMultiCuts.size(); i < N; ++i )
mins = max(mins, theMultiCuts[i]->minS(pv));
return mins;
}
Energy2 Cuts::maxS(const tcPDVector & pv) const {
Energy2 maxs = SMax();
for ( int i = 0, N = theMultiCuts.size(); i < N; ++i )
maxs = min(maxs, theMultiCuts[i]->maxS(pv));
return maxs;
}
Energy2 Cuts::minSij(tcPDPtr pi, tcPDPtr pj) const {
Energy2 mins = ZERO;
for ( int i = 0, N = theTwoCuts.size(); i < N; ++i )
mins = max(mins, theTwoCuts[i]->minSij(pi, pj));
if ( mins > ZERO ) return mins;
mins = sqr(pi->massMin() + pj->massMin());
mins = max(mins, sqr(minKTClus(pi, pj))/4.0);
mins = max(mins, minDurham(pi, pj)*currentSHat()/2.0);
mins = max(mins, minKT(pi)*minKT(pj)*minDeltaR(pi, pj)/4.0);
return mins;
}
Energy2 Cuts::minTij(tcPDPtr pi, tcPDPtr po) const {
Energy2 mint = ZERO;
for ( int i = 0, N = theTwoCuts.size(); i < N; ++i )
mint = max(mint, theTwoCuts[i]->minTij(pi, po));
if ( mint > ZERO ) return mint;
mint = max(mint, sqr(minKT(po)));
return mint;
}
double Cuts::minDeltaR(tcPDPtr pi, tcPDPtr pj) const {
double mindr = 0.0;
for ( int i = 0, N = theTwoCuts.size(); i < N; ++i )
mindr = max(mindr, theTwoCuts[i]->minDeltaR(pi, pj));
return mindr;
}
Energy Cuts::minKTClus(tcPDPtr pi, tcPDPtr pj) const {
Energy minkt = ZERO;
for ( int i = 0, N = theTwoCuts.size(); i < N; ++i )
minkt = max(minkt, theTwoCuts[i]->minKTClus(pi, pj));
return minkt;
}
double Cuts::minDurham(tcPDPtr pi, tcPDPtr pj) const {
double y = 0.0;
for ( int i = 0, N = theTwoCuts.size(); i < N; ++i )
y = max(y, theTwoCuts[i]->minDurham(pi, pj));
return y;
}
Energy Cuts::minKT(tcPDPtr p) const {
Energy minkt = ZERO;
for ( int i = 0, N = theOneCuts.size(); i < N; ++i )
minkt = max(minkt, theOneCuts[i]->minKT(p));
if ( minkt > ZERO ) return minkt;
minkt = minKTClus(p, tcPDPtr());
return minkt;
}
double Cuts::minEta(tcPDPtr p) const {
double mineta = -Constants::MaxRapidity;
for ( int i = 0, N = theOneCuts.size(); i < N; ++i )
mineta = max(mineta, theOneCuts[i]->minEta(p));
return mineta;
}
double Cuts::maxEta(tcPDPtr p) const {
double maxeta = Constants::MaxRapidity;
for ( int i = 0, N = theOneCuts.size(); i < N; ++i )
maxeta = min(maxeta, theOneCuts[i]->maxEta(p));
return maxeta;
}
double Cuts::minYStar(tcPDPtr p) const {
if ( currentSHat() < ZERO ) return -Constants::MaxRapidity;
if ( subMirror() ) {
HoldFlag<> nomir(theSubMirror, false);
return -maxYStar(p);
}
double etamin = minEta(p);
double ytot = Y() + currentYHat();
if ( etamin > 0.0 ) {
Energy minkt = minKT(p);
Energy maxm = p->massMax();
return asinh(minkt*sinh(etamin)/sqrt(sqr(minkt) + sqr(maxm))) - ytot;
} else {
return etamin - ytot;
}
}
double Cuts::maxYStar(tcPDPtr p) const {
if ( currentSHat() < ZERO ) return Constants::MaxRapidity;
if ( subMirror() ) {
HoldFlag<> nomir(theSubMirror, false);
return -minYStar(p);
}
double etamax = maxEta(p);
double ytot = Y() + currentYHat();
if ( etamax > 0.0 ) {
return etamax - ytot;
} else {
Energy minkt = minKT(p);
Energy maxm = p->massMax();
return asinh(minkt*sinh(etamax)/sqrt(sqr(minkt) + sqr(maxm))) - ytot;
}
}
double Cuts::minRapidityMax(tcPDPtr p) const {
double minRapidityMax = -Constants::MaxRapidity;
for ( int i = 0, N = theOneCuts.size(); i < N; ++i )
minRapidityMax = max(minRapidityMax, theOneCuts[i]->minRapidityMax(p));
return minRapidityMax;
}
double Cuts::maxRapidityMin(tcPDPtr p) const {
double maxRapidityMin = Constants::MaxRapidity;
for ( int i = 0, N = theOneCuts.size(); i < N; ++i )
maxRapidityMin = min(maxRapidityMin, theOneCuts[i]->maxRapidityMin(p));
return maxRapidityMin;
}
void Cuts::persistentOutput(PersistentOStream & os) const {
os << ounit(theSMax, GeV2) << theY << ounit(theCurrentSHat, GeV2)
<< theCurrentYHat << ounit(theMHatMin, GeV) << ounit(theMHatMax, GeV)
<< theYHatMin << theYHatMax
<< theX1Min << theX1Max << theX2Min << theX2Max << ounit(theScaleMin, GeV2)
<< ounit(theScaleMax, GeV2) << theOneCuts << theTwoCuts << theMultiCuts
- << theJetFinder << theSubMirror;
+ << theJetFinder << theSubMirror
+ << theCutWeight << theLastCutWeight;
}
void Cuts::persistentInput(PersistentIStream & is, int) {
is >> iunit(theSMax, GeV2) >> theY >> iunit(theCurrentSHat, GeV2)
>> theCurrentYHat >> iunit(theMHatMin, GeV) >> iunit(theMHatMax, GeV)
>> theYHatMin >> theYHatMax
>> theX1Min >> theX1Max >> theX2Min >> theX2Max >> iunit(theScaleMin, GeV2)
>> iunit(theScaleMax, GeV2) >> theOneCuts >> theTwoCuts >> theMultiCuts
- >> theJetFinder >> theSubMirror;
+ >> theJetFinder >> theSubMirror
+ >> theCutWeight >> theLastCutWeight;
}
ClassDescription<Cuts> Cuts::initCuts;
// Definition of the static class description member.
Energy Cuts::maxMHatMin() const {
return theMHatMax;
}
Energy Cuts::minMHatMax() const {
return theMHatMin;
}
Energy2 Cuts::maxScaleMin() const {
return theScaleMax;
}
Energy2 Cuts::minScaleMax() const {
return theScaleMin;
}
double Cuts::maxYHatMin() const {
return theYHatMax;
}
double Cuts::minYHatMax() const {
return theYHatMin;
}
double Cuts::maxX1Min() const {
return theX1Max;
}
double Cuts::minX1Max() const {
return theX1Min;
}
double Cuts::maxX2Min() const {
return theX2Max;
}
double Cuts::minX2Max() const {
return theX2Min;
}
void Cuts::Init() {
typedef double (ThePEG::Cuts::*IGFN)() const;
typedef void (ThePEG::Cuts::*ISFN)(double);
static ClassDocumentation<Cuts> documentation
("Cuts is a class for implementing kinematical cuts in ThePEG. The "
"class itself only implements cuts on the total momentum of the hard "
"sub-process, implemented as minimum and maximum values of \\f$x_1\\f$ "
"and \\f$x_2\\f$ (or \\f$\\hat{s}\\f$ and \\f$\\hat{y}\\f$. Further cuts "
"can be implemented either by inheriting from this base class, in which "
"the virtual cut() function should be overridden, or by assigning "
"objects of class OneCutBase, TwoCutBase and MultiCutBase defining "
"cuts on single particles, pairs of particles and groups of "
"particles respectively.");
static Parameter<Cuts,Energy> interfaceMHatMin
("MHatMin",
"The minimum allowed value of \\f$\\sqrt{\\hat{s}}\\f$.",
&Cuts::theMHatMin, GeV, 2.0*GeV, ZERO, Constants::MaxEnergy,
true, false, Interface::limited,
0, 0, 0, &Cuts::maxMHatMin, 0);
interfaceMHatMin.setHasDefault(false);
static Parameter<Cuts,Energy> interfaceMHatMax
("MHatMax",
"The maximum allowed value of \\f$\\sqrt{\\hat{s}}\\f$.",
&Cuts::theMHatMax, GeV, 100.0*GeV, ZERO, ZERO,
true, false, Interface::lowerlim,
0, 0,
&Cuts::minMHatMax, 0, 0);
interfaceMHatMax.setHasDefault(false);
static Parameter<Cuts,Energy2> interfaceScaleMin
("ScaleMin",
"The minimum allowed value of the scale to be used in PDFs and "
"coupling constants.",
&Cuts::theScaleMin, GeV2, ZERO, ZERO, Constants::MaxEnergy2,
true, false, Interface::limited,
0, 0, 0, &Cuts::maxScaleMin, 0);
interfaceScaleMin.setHasDefault(false);
static Parameter<Cuts,Energy2> interfaceScaleMax
("ScaleMax",
"The maximum allowed value of the scale to be used in PDFs and "
"coupling constants.",
&Cuts::theScaleMax, GeV2, 10000.0*GeV2, ZERO, ZERO,
true, false, Interface::lowerlim,
0, 0,
&Cuts::minScaleMax, 0, 0);
interfaceScaleMax.setHasDefault(false);
static Parameter<Cuts,double> interfaceYHatMin
("YHatMin",
"The minimum value of the rapidity of the hard sub-process "
"(wrt. the rest system of the colliding particles).",
&Cuts::theYHatMin, -10.0, 0.0, Constants::MaxRapidity,
true, false, Interface::upperlim,
(ISFN)0, (IGFN)0, (IGFN)0, &Cuts::maxYHatMin, (IGFN)0);
interfaceYHatMin.setHasDefault(false);
static Parameter<Cuts,double> interfaceYHatMax
("YHatMax",
"The maximum value of the rapidity of the hard sub-process "
"(wrt. the rest system of the colliding particles).",
&Cuts::theYHatMax, 10.0, -Constants::MaxRapidity, 0.0,
true, false, Interface::lowerlim,
(ISFN)0, (IGFN)0, &Cuts::minYHatMax, (IGFN)0, (IGFN)0);
interfaceYHatMax.setHasDefault(false);
static Parameter<Cuts,double> interfaceX1Min
("X1Min",
"The minimum value of the positive light-cone fraction of the hard "
"sub-process.",
&Cuts::theX1Min, 0.0, 0.0, 1.0,
true, false, Interface::limited,
(ISFN)0, (IGFN)0, (IGFN)0, &Cuts::maxX1Min, (IGFN)0);
interfaceX1Min.setHasDefault(false);
static Parameter<Cuts,double> interfaceX1Max
("X1Max",
"The maximum value of the positive light-cone fraction of the hard "
"sub-process.",
&Cuts::theX1Max, 0.0, 0.0, 1.0,
true, false, Interface::limited,
(ISFN)0, (IGFN)0, &Cuts::minX1Max, (IGFN)0, (IGFN)0);
interfaceX1Max.setHasDefault(false);
static Parameter<Cuts,double> interfaceX2Min
("X2Min",
"The minimum value of the negative light-cone fraction of the hard "
"sub-process.",
&Cuts::theX2Min, 0.0, 0.0, 1.0,
true, false, Interface::limited,
(ISFN)0, (IGFN)0, (IGFN)0, &Cuts::maxX2Min, (IGFN)0);
interfaceX2Min.setHasDefault(false);
static Parameter<Cuts,double> interfaceX2Max
("X2Max",
"The maximum value of the negative light-cone fraction of the hard "
"sub-process.",
&Cuts::theX2Max, 0.0, 0.0, 1.0,
true, false, Interface::limited,
(ISFN)0, (IGFN)0, &Cuts::minX2Max, (IGFN)0, (IGFN)0);
interfaceX2Max.setHasDefault(false);
static RefVector<Cuts,OneCutBase> interfaceOneCuts
("OneCuts",
"The objects defining cuts on single outgoing partons from the "
"hard sub-process.",
&Cuts::theOneCuts, -1, true, false, true, false, false);
static RefVector<Cuts,TwoCutBase> interfaceTwoCuts
("TwoCuts",
"The objects defining cuts on pairs of particles in the "
"hard sub-process.",
&Cuts::theTwoCuts, -1, true, false, true, false, false);
static RefVector<Cuts,MultiCutBase> interfaceMultiCuts
("MultiCuts",
"The objects defining cuts on sets of outgoing particles from the "
"hard sub-process.",
&Cuts::theMultiCuts, -1, true, false, true, false, false);
static Reference<Cuts,JetFinder> interfaceJetFinder
("JetFinder",
"Set a JetFinder object used to define cuts on the"
"level of reconstructed jets as needed for higher order corrections.",
&Cuts::theJetFinder, false, false, true, true, false);
interfaceX1Min.rank(10);
interfaceX1Max.rank(9);
interfaceX2Min.rank(8);
interfaceX2Max.rank(7);
interfaceMHatMin.rank(6);
interfaceMHatMax.rank(5);
interfaceYHatMin.rank(4);
interfaceYHatMax.rank(3);
interfaceOneCuts.rank(2);
interfaceTwoCuts.rank(1);
}
double Cuts::yHatMin() const {
return theX1Min > 0.0 && theX2Max > 0.0?
max(theYHatMin, 0.5*log(theX1Min/theX2Max)): theYHatMin;
}
double Cuts::yHatMax() const {
return theX1Max > 0.0 && theX2Min > 0.0?
min(theYHatMax, 0.5*log(theX1Max/theX2Min)): theYHatMax;
}
bool Cuts::yHat(double y) const {
return y > yHatMin() && y < yHatMax();
}
double Cuts::x1Min() const {
return max(theX1Min, (theMHatMin/sqrt(SMax()))*exp(theYHatMin));
}
double Cuts::x1Max() const {
return min(theX1Max, (theMHatMax/sqrt(SMax()))*exp(theYHatMax));
}
bool Cuts::x1(double x) const {
return x > x1Min() && x <= x1Max();
}
double Cuts::x2Min() const {
return max(theX2Min, (theMHatMin/sqrt(SMax()))/exp(theYHatMax));
}
double Cuts::x2Max() const {
return min(theX2Max, (theMHatMax/sqrt(SMax()))/exp(theYHatMin));
}
bool Cuts::x2(double x) const {
return x > x2Min() && x <= x2Max();
}
template <typename T>
vector<typename Ptr<T>::transient_const_pointer>
Cuts::oneCutObjects() const {
typedef typename Ptr<T>::transient_const_pointer tcPtr;
vector<tcPtr> ret;
for ( int i = 0, N = theOneCuts.size(); i < N; ++i )
if ( dynamic_ptr_cast<tcPtr>(theOneCuts[i]) )
ret.push_back(dynamic_ptr_cast<tcPtr>(theOneCuts[i]));
return ret;
}
template <typename T>
vector<typename Ptr<T>::transient_const_pointer>
Cuts::twoCutObjects() const {
typedef typename Ptr<T>::transient_const_pointer tcPtr;
vector<tcPtr> ret;
for ( int i = 0, N = theTwoCuts.size(); i < N; ++i )
if ( dynamic_ptr_cast<tcPtr>(theTwoCuts[i]) )
ret.push_back(dynamic_ptr_cast<tcPtr>(theTwoCuts[i]));
return ret;
}
template <typename T>
vector<typename Ptr<T>::transient_const_pointer>
Cuts::multiCutObjects() const {
typedef typename Ptr<T>::transient_const_pointer tcPtr;
vector<tcPtr> ret;
for ( int i = 0, N = theMultiCuts.size(); i < N; ++i )
if ( dynamic_ptr_cast<tcPtr>(theMultiCuts[i]) )
ret.push_back(dynamic_ptr_cast<tcPtr>(theMultiCuts[i]));
return ret;
}
diff --git a/Cuts/Cuts.h b/Cuts/Cuts.h
--- a/Cuts/Cuts.h
+++ b/Cuts/Cuts.h
@@ -1,763 +1,785 @@
// -*- C++ -*-
//
// Cuts.h is a part of ThePEG - Toolkit for HEP Event Generation
// Copyright (C) 1999-2011 Leif Lonnblad
//
// ThePEG is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef THEPEG_Cuts_H
#define THEPEG_Cuts_H
//
// This is the declaration of the Cuts class.
//
#include "ThePEG/Interface/Interfaced.h"
#include "Cuts.fh"
#include "OneCutBase.h"
#include "TwoCutBase.h"
#include "MultiCutBase.h"
#include "JetFinder.h"
namespace ThePEG {
/**
* Cuts is a class for implementing kinematical cuts in ThePEG. The
* class itself only implements cuts on the total momentum of the hard
* sub-process, implemented as minimum and maximum values of \f$x_1\f$
* and \f$x_2\f$ (or \f$\hat{s}=x_1x_2S_{tot}\f$ and
* \f$\hat{y}=\log(x_1/x_2)/2\f$. Further cuts can be implemented
* either by inheriting from this base class, in which the virtual
* cut() function should be overridden, or by assigning objects of
* class OneCutBase, TwoCutBase and MultiCutBase defining cuts on
* single particles, pairs of particles and groups of particles in the
* hard sub-process respectively.
*
* The Cuts object must be initialized specifying the overall
* laboratory frame, giving the total squared invariant mass, \f$S\f$,
* and the rapidity, \f$Y\f$, of the colliding particles in this
* frame. The colliding particles are thus assumed to be directed
* along the \f$z\f$-axis.
*
* For each event, the Cuts object must also be initialized giving the
* squared invarint mass, \f$\hat{s}\f$, and the total rapidity,
* \f$\hat{y}\f$, of the hard sub-process in the center-of-mass frame
* of the colliding particles. Note that this means that the
* transformation between the lab frame and the rest frame of the hard
* sub-process is assumed to be a simple boost along the z-axis.
*
* @see \ref CutsInterfaces "The interfaces"
* defined for Cuts.
*/
class Cuts: public Interfaced {
public:
/**
* A vector of OneCutBase pointers.
*/
typedef vector<OneCutPtr> OneCutVector;
/**
* A vector of TwoCutBase pointers.
*/
typedef vector<TwoCutPtr> TwoCutVector;
/**
* A vector of MultiCutBase pointers.
*/
typedef vector<MultiCutPtr> MultiCutVector;
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
Cuts(Energy MhatMin=2*GeV);
/**
* The destructor.
*/
virtual ~Cuts();
//@}
public:
/** @name Initialization functions. */
//@{
/**
* Initialize this object specifying the maximum total invariant
* mass squared, \a smax, and the total rapidity, \a Y, of the
* colliding particles (for the maximum invariant mass). A sub-class
* overriding this function must make sure the base-class function
* is called. This function should be called once in the beginning
* of a run.
*/
virtual void initialize(Energy2 smax, double Y);
/**
* Initialize this object for a new event. A sub-class overriding
* this function must make sure the base-class function is called.
* This function is called before the generation of a new
* sub-process, before the incoming partons have been generated.
*/
virtual void initEvent();
/**
* Set information about the invariant mass squared, \a shat, and
* rapidity, \a yhat, of the hard sub-process. The rapidity should
* be given wrt. the center of mass of the colliding particles. A
* sub-class overriding this function must make sure the base-class
* function is called. This function is called before the generation
* of a new sub-process, after the incoming partons have been
* generated. If \a mirror is true any questions regarding cuts on
* the sub-process in the functions minYStar(tcPDPtr),
* maxYStar(tcPDPtr p), passCuts(const tcPDVector &, const
* vector<LorentzMomentum> &, tcPDPtr, tcPDPtr) and passCuts(const
* tcPVector &, tcPDPtr t1, tcPDPtr) will assume that the z-axis is
* reversed in the sub-process rest frame. Returns false if the
* given values were outside of the cuts.
*/
virtual bool
initSubProcess(Energy2 shat, double yhat, bool mirror = false) const;
//@}
/** @name Check functions to see if a state has passed the cuts or not. */
//@{
/**
* Check if the outgoing particles, with the given types and
* momenta, from a sub-process passes the cuts. The particles must
* be given in the rest frame of tha hard sub-process, and the
* initSubProcess must have been called before. Also the types of
* the incoming partons, \a t1 and \a t2, may be given if availible.
*/
virtual bool passCuts(const tcPDVector & ptype, const vector<LorentzMomentum> & p,
tcPDPtr t1 = tcPDPtr(), tcPDPtr t2 = tcPDPtr()) const;
/**
* Check if the outgoing particles from a sub-process passes the
* cuts. The particles must be given in the rest frame of tha hard
* sub-process, and the initSubProcess must have been called
* before. Also the types of the incoming partons, \a t1 and \a t2,
* may be given if availible.
*/
bool passCuts(const tcPVector & p,
tcPDPtr t1 = tcPDPtr(), tcPDPtr t2 = tcPDPtr()) const;
/**
* Check if the incoming and outgoing particles in the given
* sub-process passes the cuts. The sub-process must be given in its
* rest frame, and the initSubProcess must have been called before.
*/
bool passCuts(const SubProcess & sub) const;
/**
* Check if the given collision passes the cuts. The collision must
* be given in its rest frame.
*/
bool passCuts(const Collision & coll) const;
//@}
/** @name Access to cuts of the underlying cut objects. */
//@{
/**
* Return the minimum allowed squared invariant mass of two outgoing
* partons of type \a pi and \a pj. This function first determines
* the minimum from the corresponding function from in TwoCutBase
* objects. If no minimum was found, one is derived from
* minKTClus(), minDurham(), minKT() and minDeltaR(), if possible.
*/
Energy2 minSij(tcPDPtr pi, tcPDPtr pj) const;
/**
* Return the minimum allowed value of the negative of the squared
* invariant mass of an incoming parton of type \a pi and an
* outgoing parton of type \a po. This function first determines the
* minimum from the corresponding function from in TwoCutBase
* objects. If no minimum was found, one is derived from minKT(), if
* possible.
*/
Energy2 minTij(tcPDPtr pi, tcPDPtr po) const;
/**
* Return the minimum allowed value of \f$\Delta
* R_{ij}=\sqrt{\Delta\eta_{ij}^2+\Delta\phi_{ij}^2}\f$ of two
* outgoing partons of type \a pi and \a pj. Simply returns the
* maximum of the results from calling the corresponding function in
* the TwoCutBase objects.
*/
double minDeltaR(tcPDPtr pi, tcPDPtr pj) const;
/**
* Return the minimum allowed value of the longitudinally invariant
* \f$k_\perp\f$-algorithms distance measure. This is defined as
* \f$\min(p_{\perp i}, p_{\perp
* j})\sqrt{\Delta\eta_{ij}^2+\Delta\phi_{ij}^2}\f$ for two outgoing
* partons, or simply \f$p_{\perp i}\f$ or \f$p_{\perp j}\f$ for a
* single outgoing parton. Returns 0 if both partons are incoming. A
* null pointer indicates an incoming parton, hence the type of the
* incoming parton is irrelevant. Simply returns the maximum of the
* results from calling the corresponding function in the TwoCutBase
* objects.
*/
Energy minKTClus(tcPDPtr pi, tcPDPtr pj) const;
/**
* Return the minimum allowed value of the Durham
* \f$k_\perp\f$-algorithms distance measure. This is defined as
* \f$2\min(E_j^2, E_j^2)(1-\cos\theta_{ij})/\hat{s}\f$ for two
* outgoing partons. Simply returns the maximum of the results from
* calling the corresponding function in the TwoCutBase objects.
*/
double minDurham(tcPDPtr pi, tcPDPtr pj) const;
/**
* Return the minimum allowed value of the transverse momentum of an
* outgoing parton. This function first determines the minimum from
* the corresponding function from in OneCutBase objects. If no
* minimum was found, one is derived from minKTClus(), if possible.
*/
Energy minKT(tcPDPtr p) const;
/**
* Return the minimum allowed pseudo-rapidity of an outgoing parton
* of the given type. The pseudo-rapidity is measured in the lab
* system. Simply returns the maximum of the results from calling
* the corresponding function in the OneCutBase objects.
*/
double minEta(tcPDPtr p) const;
/**
* Return the maximum allowed pseudo-rapidity of an outgoing parton
* of the given type. The pseudo-rapidity is measured in the lab
* system. Simply returns the minimum of the results from calling
* the corresponding function in the OneCutBase objects.
*/
double maxEta(tcPDPtr p) const;
/**
* Return the minimum allowed rapidity of an outgoing parton
* of the given type. The rapidity is measured in the lab
* system. Simply returns the maximum of the results from calling
* the corresponding function in the OneCutBase objects.
*/
double minRapidityMax(tcPDPtr p) const;
/**
* Return the maximum allowed rapidity of an outgoing parton
* of the given type. The rapidity is measured in the lab
* system. Simply returns the minimum of the results from calling
* the corresponding function in the OneCutBase objects.
*/
double maxRapidityMin(tcPDPtr p) const;
/**
* Return the minimum allowed rapidity of an outgoing parton of the
* given type in the center-of-mass system of the hard sub-process.
* Only available after initSubProcess() has been called.
*/
double minYStar(tcPDPtr p) const;
/**
* Return the minimum allowed rapidity of an outgoing parton of the
* given type in the center-of-mass system of the hard sub-process.
* Only available after initSubProcess() has been called.
*/
double maxYStar(tcPDPtr p) const;
/**
* Return the minimum allowed value of the squared invariant mass of
* a set of outgoing partons of the given types. Typically used to
* cut off the tails of the mass of a resonance for
* efficiency. Simply returns the maximum of the results from
* calling the corresponding function in the MultiCutBase objects.
*/
Energy2 minS(const tcPDVector & pv) const;
/**
* Return the maximum allowed value of the squared invariant mass of
* a set of outgoing partons of the given types. Typically used to
* cut off the tails of the mass of a resonance for
* efficiency. Simply returns the minimum of the results from
* calling the corresponding function in the MultiCutBase objects.
*/
Energy2 maxS(const tcPDVector & pv) const;
//@}
/** @name Direct access to underlying cut objects. */
//@{
/**
* Return a vector of pointers to objects of the given class (with
* base class OneCutBase).
*/
template <typename T>
vector<typename Ptr<T>::transient_const_pointer>
oneCutObjects() const;
/**
* Return a vector of pointers to objects of the given class (with
* base class TwoCutBase).
*/
template <typename T>
vector<typename Ptr<T>::transient_const_pointer>
twoCutObjects() const;
/**
* Return a vector of pointers to objects of the given class (with
* base class MultiCutBase).
*/
template <typename T>
vector<typename Ptr<T>::transient_const_pointer>
multiCutObjects() const;
/**
* Return the objects defining cuts on single outgoing partons from the
* hard sub-process.
*/
const OneCutVector& oneCuts() const { return theOneCuts; }
/**
* Return the objects defining cuts on pairs of particles in the hard
* sub-process.
*/
const TwoCutVector& twoCuts() const { return theTwoCuts; }
/**
* Return the objects defining cuts on sets of outgoing particles from the
* hard sub-process.
*/
const MultiCutVector& multiCuts() const { return theMultiCuts; }
/**
* Return the jet finder
*/
Ptr<JetFinder>::tptr jetFinder() const { return theJetFinder; }
/**
* Add a OneCutBase object.
*/
void add(tOneCutPtr c) { theOneCuts.push_back(c); }
/**
* Add a TwoCutBase object.
*/
void add(tTwoCutPtr c) { theTwoCuts.push_back(c); }
/**
* Add a MultiCutBase object.
*/
void add(tMultiCutPtr c) { theMultiCuts.push_back(c); }
//@}
public:
/** @name Simple access functions. */
//@{
/**
* The maximum allowed total invariant mass squared allowed for
* events to be considered.
*/
Energy2 SMax() const { return theSMax; }
/**
* The total rapidity of the colliding particles corresponding to
* the maximum invariant mass squared, SMax().
*/
double Y() const { return theY; }
/**
* The invariant mass squared of the hard sub-process of the event
* being considered.
*/
Energy2 currentSHat() const { return theCurrentSHat; }
/**
* The total rapidity of hard sub-process (wrt. the rest system of
* the colliding particles so that currentYHat() + Y() gives the
* true rapidity) of the event being considered.
*/
double currentYHat() const { return theCurrentYHat; }
//@}
/** @name Functions to inquire about specific cuts. */
//@{
/**
* The minimum allowed value of \f$\hat{s}\f$.
*/
Energy2 sHatMin() const { return max(sqr(theMHatMin), theX1Min*theX2Min*SMax()); }
/**
* The maximum allowed value of \f$\hat{s}\f$.
*/
Energy2 sHatMax() const { return min(sqr(theMHatMax), theX1Max*theX2Max*SMax()); }
/**
* Check if the given \f$\hat{s}\f$ is within the cuts.
*/
bool sHat(Energy2 sh) const {
return sh > sHatMin() && sh <= sHatMax()*(1.0 + 1000.0*Constants::epsilon);
}
/**
* The minimum allowed value of \f$\sqrt{\hat{s}}\f$.
*/
Energy mHatMin() const { return max(theMHatMin, sqrt(theX1Min*theX2Min*SMax())); }
/**
* The maximum allowed value of \f$\sqrt{\hat{s}}\f$.
*/
Energy mHatMax() const { return min(theMHatMax, sqrt(theX1Max*theX2Max*SMax())); }
/**
* The minimum value of the rapidity of the hard sub-process
* (wrt. the rest system of the colliding particles).
*/
double yHatMin() const;
/**
* The maximum value of the rapidity of the hard sub-process
* (wrt. the rest system of the colliding particles).
*/
double yHatMax() const;
/**
* Check if the given \f$\hat{y}\f$ is within the cuts.
*/
bool yHat(double y) const;
/**
* The minimum value of the positive light-cone fraction of the hard
* sub-process.
*/
double x1Min() const;
/**
* The maximum value of the positive light-cone fraction of the hard
* sub-process.
*/
double x1Max() const;
/**
* Check if the given \f$x_1\f$ is within the cuts.
*/
bool x1(double x) const;
/**
* The minimum value of the negative light-cone fraction of the hard
* sub-process.
*/
double x2Min() const;
/**
* The maximum value of the negative light-cone fraction of the hard
* sub-process.
*/
double x2Max() const;
/**
* Check if the given \f$x_2\f$ is within the cuts.
*/
bool x2(double x) const;
/**
* The minimum allowed value of the scale to be used in PDF's and
* coupling constants.
*/
Energy2 scaleMin() const { return theScaleMin; }
/**
* The maximum allowed value of the scale to be used in PDF's and
* coupling constants.
*/
Energy2 scaleMax() const { return theScaleMax; }
/**
* Check if the given scale is within the cuts.
*/
bool scale(Energy2 Q2) const { return Q2 > scaleMin() && Q2 < scaleMax(); }
/**
* Set true if a matrix element is should be using this cut and is
* mirrored along the z-axis .
*/
bool subMirror() const { return theSubMirror; }
+
+ /**
+ * Return the overall cut weight
+ */
+ double cutWeight() const { return theCutWeight; }
+
+ /**
+ * Set the cut weight as appropriate from the call to the last n-cut
+ * object.
+ */
+ void lastCutWeight(double w) const { theLastCutWeight = w; }
//@}
public:
/**
* Describe the currently active cuts in the log file.
*/
virtual void describe() const;
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object. Called in the run phase just before
* a run begins.
*/
virtual void doinitrun();
//@}
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;
//@}
private:
/**
* Helper function used by the interface.
*/
Energy maxMHatMin() const;
/**
* Helper function used by the interface.
*/
Energy minMHatMax() const;
/**
* Helper function used by the interface.
*/
double maxYHatMin() const;
/**
* Helper function used by the interface.
*/
double minYHatMax() const;
/**
* Helper function used by the interface.
*/
double maxX1Min() const;
/**
* Helper function used by the interface.
*/
double minX1Max() const;
/**
* Helper function used by the interface.
*/
double maxX2Min() const;
/**
* Helper function used by the interface.
*/
double minX2Max() const;
/**
* Helper function used by the interface.
*/
Energy2 maxScaleMin() const;
/**
* Helper function used by the interface.
*/
Energy2 minScaleMax() const;
private:
/**
* The maximum allowed total invariant mass squared allowed for
* events to be considered.
*/
Energy2 theSMax;
/**
* The total rapidity of the colliding particles corresponding to
* the maximum invariant mass squared, SMax().
*/
double theY;
/**
* The invariant mass squared of the hard sub-process of the event
* being considered.
*/
mutable Energy2 theCurrentSHat;
/**
* The total rapidity of hard sub-process (wrt. the rest system of
* the colliding particles so that currentYHat() + Y() gives the
* true rapidity) of the event being considered.
*/
mutable double theCurrentYHat;
/**
* The minimum allowed value of \f$\sqrt{\hat{s}}\f$.
*/
Energy theMHatMin;
/**
* The maximum allowed value of \f$\sqrt{\hat{s}}\f$.
*/
Energy theMHatMax;
/**
* The minimum value of the rapidity of the hard sub-process
* (wrt. the rest system of the colliding particles).
*/
double theYHatMin;
/**
* The maximum value of the rapidity of the hard sub-process
* (wrt. the rest system of the colliding particles).
*/
double theYHatMax;
/**
* The minimum value of the positive light-cone fraction of the hard
* sub-process.
*/
double theX1Min;
/**
* The maximum value of the positive light-cone fraction of the hard
* sub-process.
*/
double theX1Max;
/**
* The minimum value of the negative light-cone fraction of the hard
* sub-process.
*/
double theX2Min;
/**
* The maximum value of the negative light-cone fraction of the hard
* sub-process.
*/
double theX2Max;
/**
* The minimum allowed value of the scale to be used in PDF's and
* coupling constants.
*/
Energy2 theScaleMin;
/**
* The maximum allowed value of the scale to be used in PDF's and
* coupling constants.
*/
Energy2 theScaleMax;
/**
* The objects defining cuts on single outgoing partons from the
* hard sub-process.
*/
OneCutVector theOneCuts;
/**
* The objects defining cuts on pairs of particles in the hard
* sub-process.
*/
TwoCutVector theTwoCuts;
/**
* The objects defining cuts on sets of outgoing particles from the
* hard sub-process.
*/
MultiCutVector theMultiCuts;
/**
* An optional jet finder used to define cuts on the level of
* reconstructed jets.
*/
Ptr<JetFinder>::ptr theJetFinder;
/**
* Set to true if a matrix element is should be using this cut and is
* mirrored along the z-axis .
*/
mutable bool theSubMirror;
+ /**
+ * The overall cut weight
+ */
+ mutable double theCutWeight;
+
+ /**
+ * The cut weight as appropriate from the call to the last n-cut
+ * object.
+ */
+ mutable double theLastCutWeight;
+
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<Cuts> initCuts;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
Cuts & operator=(const Cuts &);
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of Cuts. */
template <>
struct BaseClassTrait<Cuts,1> {
/** Typedef of the first base class of Cuts. */
typedef Interfaced NthBase;
};
/** This template specialization informs ThePEG about the name of
* the Cuts class and the shared object where it is defined. */
template <>
struct ClassTraits<Cuts>
: public ClassTraitsBase<Cuts> {
/** Return a platform-independent class name */
static string className() { return "ThePEG::Cuts"; }
};
/** @endcond */
}
#endif /* THEPEG_Cuts_H */
diff --git a/Cuts/JetCuts.cc b/Cuts/JetCuts.cc
--- a/Cuts/JetCuts.cc
+++ b/Cuts/JetCuts.cc
@@ -1,205 +1,232 @@
// -*- C++ -*-
//
// JetCuts.cc is a part of ThePEG - Toolkit for HEP Event Generation
// Copyright (C) 1999-2011 Leif Lonnblad
// Copyright (C) 2009-2012 Simon Platzer
//
// ThePEG 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 JetCuts class.
//
#include "JetCuts.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/RefVector.h"
#include "ThePEG/PDT/ParticleData.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Repository/CurrentGenerator.h"
using namespace ThePEG;
JetCuts::JetCuts()
: theOrdering(orderPt) {}
JetCuts::~JetCuts() {}
void JetCuts::describe() const {
CurrentGenerator::log() << name() << " cutting on jets ordered in "
<< (ordering() == orderPt ? "pt " : "y ")
<< " with regions:\n";
for ( vector<Ptr<JetRegion>::ptr>::const_iterator r = jetRegions().begin();
r != jetRegions().end(); ++r )
(**r).describe();
if ( !jetPairRegions().empty() ) {
CurrentGenerator::log() << "and jet pair cuts:\n";
for ( vector<Ptr<JetPairRegion>::ptr>::const_iterator r = jetPairRegions().begin();
r != jetPairRegions().end(); ++r )
(**r).describe();
for ( vector<Ptr<MultiJetRegion>::ptr>::const_iterator r = multiJetRegions().begin();
r != multiJetRegions().end(); ++r )
(**r).describe();
}
if ( !jetVetoRegions().empty() ) {
CurrentGenerator::log() << "vetoing jets inside:\n";
for ( vector<Ptr<JetRegion>::ptr>::const_iterator r = jetVetoRegions().begin();
r != jetVetoRegions().end(); ++r )
(**r).describe();
}
+ CurrentGenerator::log() << "\n";
}
IBPtr JetCuts::clone() const {
return new_ptr(*this);
}
IBPtr JetCuts::fullclone() const {
return new_ptr(*this);
}
void JetCuts::persistentOutput(PersistentOStream & os) const {
os << theUnresolvedMatcher
<< theJetRegions << theJetVetoRegions
- << theJetPairRegions << theMultiJetRegions << theOrdering;
+ << theJetPairRegions << theMultiJetRegions
+ << theOrdering;
}
void JetCuts::persistentInput(PersistentIStream & is, int) {
is >> theUnresolvedMatcher
>> theJetRegions >> theJetVetoRegions
- >> theJetPairRegions >> theMultiJetRegions >> theOrdering;
+ >> theJetPairRegions >> theMultiJetRegions
+ >> theOrdering;
}
struct PtLarger {
inline bool operator()(const LorentzMomentum& a,
const LorentzMomentum& b) const {
return a.perp() > b.perp();
}
};
struct YLess {
inline bool operator()(const LorentzMomentum& a,
const LorentzMomentum& b) const {
return a.rapidity() < b.rapidity();
}
};
bool JetCuts::passCuts(tcCutsPtr parent, const tcPDVector & ptype,
const vector<LorentzMomentum> & p) const {
vector<LorentzMomentum> jets;
tcPDVector::const_iterator ptypeit = ptype.begin();
vector<LorentzMomentum>::const_iterator pit = p.begin();
for ( ; ptypeit != ptype.end(); ++ptypeit, ++pit )
if ( unresolvedMatcher()->check(**ptypeit) )
jets.push_back(*pit);
if ( ordering() == orderPt ) {
sort(jets.begin(),jets.end(),PtLarger());
} else if ( ordering() == orderY ) {
sort(jets.begin(),jets.end(),YLess());
} else assert(false);
for ( vector<Ptr<JetRegion>::ptr>::const_iterator r = jetRegions().begin();
r != jetRegions().end(); ++r )
(**r).reset();
set<int> matchedJets;
for ( size_t k = 0; k < jets.size(); ++k ) {
for ( vector<Ptr<JetRegion>::ptr>::const_iterator r = jetRegions().begin();
r != jetRegions().end(); ++r ) {
if ( (**r).matches(parent,k+1,jets[k]) ) {
matchedJets.insert(k+1);
break;
}
}
}
+ double cutWeight = 1.0;
+ bool pass = true;
+
for ( vector<Ptr<JetRegion>::ptr>::const_iterator r = jetRegions().begin();
- r != jetRegions().end(); ++r )
- if ( !(**r).didMatch() )
+ r != jetRegions().end(); ++r ) {
+ pass &= (**r).didMatch();
+ cutWeight *= (**r).cutWeight();
+ if ( !pass ) {
+ parent->lastCutWeight(cutWeight);
return false;
+ }
+ }
for ( vector<Ptr<JetPairRegion>::ptr>::const_iterator r = jetPairRegions().begin();
- r != jetPairRegions().end(); ++r )
- if ( !(**r).matches(parent) )
+ r != jetPairRegions().end(); ++r ) {
+ pass &= (**r).matches(parent);
+ cutWeight *= (**r).cutWeight();
+ if ( !pass ) {
+ parent->lastCutWeight(cutWeight);
return false;
+ }
+ }
for ( vector<Ptr<MultiJetRegion>::ptr>::const_iterator r = multiJetRegions().begin();
- r != multiJetRegions().end(); ++r )
- if ( !(**r).matches() )
+ r != multiJetRegions().end(); ++r ) {
+ pass &= (**r).matches();
+ cutWeight *= (**r).cutWeight();
+ if ( !pass ) {
+ parent->lastCutWeight(cutWeight);
return false;
+ }
+ }
if ( !jetVetoRegions().empty() ) {
for ( size_t k = 0; k < jets.size(); ++k ) {
if ( matchedJets.find(k+1) != matchedJets.end() )
continue;
for ( vector<Ptr<JetRegion>::ptr>::const_iterator r = jetVetoRegions().begin();
r != jetVetoRegions().end(); ++r ) {
- if ( (**r).matches(parent,k+1,jets[k]) )
+ pass &= !(**r).matches(parent,k+1,jets[k]);
+ cutWeight *= 1. - (**r).cutWeight();
+ if ( !pass ) {
+ parent->lastCutWeight(cutWeight);
return false;
+ }
}
}
}
- return true;
+ parent->lastCutWeight(cutWeight);
+
+ return pass;
}
ClassDescription<JetCuts> JetCuts::initJetCuts;
// Definition of the static class description member.
void JetCuts::Init() {
static ClassDocumentation<JetCuts> documentation
("JetCuts combines various JetRegion and JetPairRegion objects into a "
"cut object.");
static Reference<JetCuts,MatcherBase> interfaceUnresolvedMatcher
("UnresolvedMatcher",
"A matcher identifying unresolved partons",
&JetCuts::theUnresolvedMatcher, false, false, true, false, false);
static RefVector<JetCuts,JetRegion> interfaceJetRegions
("JetRegions",
"The jet regions to be used.",
&JetCuts::theJetRegions, -1, false, false, true, false, false);
static RefVector<JetCuts,JetRegion> interfaceJetVetoRegions
("JetVetoRegions",
"The jet veto regions to be used.",
&JetCuts::theJetVetoRegions, -1, false, false, true, false, false);
static RefVector<JetCuts,JetPairRegion> interfaceJetPairRegions
("JetPairRegions",
"The jet pair regions to be used.",
&JetCuts::theJetPairRegions, -1, false, false, true, false, false);
static RefVector<JetCuts,MultiJetRegion> interfaceMultiJetRegions
("MultiJetRegions",
"The multi jet regions to be used.",
&JetCuts::theMultiJetRegions, -1, false, false, true, false, false);
static Switch<JetCuts,int> interfaceOrdering
("Ordering",
"The ordering to apply on jets.",
&JetCuts::theOrdering, orderPt, false, false);
static SwitchOption interfaceOrderingOrderPt
(interfaceOrdering,
"OrderPt",
"Order in decreasing transverse momentum.",
orderPt);
static SwitchOption interfaceOrderingOrderY
(interfaceOrdering,
"OrderY",
"Order in rapidity.",
orderY);
}
diff --git a/Cuts/JetPairRegion.cc b/Cuts/JetPairRegion.cc
--- a/Cuts/JetPairRegion.cc
+++ b/Cuts/JetPairRegion.cc
@@ -1,190 +1,199 @@
// -*- C++ -*-
//
// JetPairRegion.cc is a part of ThePEG - Toolkit for HEP Event Generation
// Copyright (C) 1999-2007 Leif Lonnblad
// Copyright (C) 2009-2012 Simon Platzer
//
// ThePEG 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 JetPairRegion class.
//
#include "JetPairRegion.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Reference.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 "ThePEG/Repository/CurrentGenerator.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace ThePEG;
JetPairRegion::JetPairRegion()
: theMassMin(0.*GeV), theMassMax(Constants::MaxEnergy),
theDeltaRMin(0.0), theDeltaRMax(Constants::MaxRapidity),
theDeltaYMin(0.0), theDeltaYMax(Constants::MaxRapidity),
- theOppositeHemispheres(false) {}
+ theOppositeHemispheres(false), theCutWeight(1.0) {}
JetPairRegion::~JetPairRegion() {}
IBPtr JetPairRegion::clone() const {
return new_ptr(*this);
}
IBPtr JetPairRegion::fullclone() const {
return new_ptr(*this);
}
void JetPairRegion::describe() const {
CurrentGenerator::log()
<< "JetPairRegion '" << name() << "' matching "
<< " JetRegions '" << firstRegion()->name()
<< "' and '" << secondRegion()->name() << "' with\n";
CurrentGenerator::log()
<< "m = " << massMin()/GeV << " .. " << massMax()/GeV << " GeV\n"
<< "dR = " << deltaRMin() << " .. " << deltaRMax() << "\n"
<< "dy = " << deltaYMin() << " .. " << deltaYMax() << "\n";
}
-bool JetPairRegion::matches(tcCutsPtr parent) const {
+bool JetPairRegion::matches(tcCutsPtr parent) {
if ( !firstRegion()->didMatch() ||
- !secondRegion()->didMatch() )
+ !secondRegion()->didMatch() ) {
+ theCutWeight = 0.0;
return false;
+ }
+
+ theCutWeight = 1.0;
const LorentzMomentum& pi = firstRegion()->lastMomentum();
const LorentzMomentum& pj = secondRegion()->lastMomentum();
Energy m = (pi+pj).m();
- if ( m < massMin() || m > massMax() )
+ if ( !(firstRegion()->lessThanEnergy(massMin(),m,theCutWeight) &&
+ firstRegion()->lessThanEnergy(m,massMax(),theCutWeight)) )
return false;
double dy = abs(pi.rapidity() - pj.rapidity());
- if ( dy < deltaYMin() || dy > deltaYMax() )
+ if ( !(firstRegion()->lessThanRapidity(deltaYMin(),dy,theCutWeight) &&
+ firstRegion()->lessThanRapidity(dy,deltaYMax(),theCutWeight)) )
return false;
double dphi = abs(pi.phi() - pj.phi());
if ( dphi > Constants::pi ) dphi = 2.0*Constants::pi - dphi;
double dR = sqrt(sqr(dy)+sqr(dphi));
- if ( dR < deltaRMin() || dR > deltaRMax() )
+ if ( !(firstRegion()->lessThanRapidity(deltaRMin(),dR,theCutWeight) &&
+ firstRegion()->lessThanRapidity(dR,deltaRMax(),theCutWeight)) )
return false;
double py =
(pi.rapidity() + parent->currentYHat()) *
(pj.rapidity() + parent->currentYHat());
- if ( theOppositeHemispheres && py > 0.0 )
+ if ( theOppositeHemispheres &&
+ !firstRegion()->lessThanRapidity(py,0.0,theCutWeight) )
return false;
return true;
}
// If needed, insert default implementations of virtual function defined
// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs).
void JetPairRegion::persistentOutput(PersistentOStream & os) const {
os << theFirstRegion << theSecondRegion
<< ounit(theMassMin,GeV) << ounit(theMassMax,GeV)
<< theDeltaRMin << theDeltaRMax
<< theDeltaYMin << theDeltaYMax
- << theOppositeHemispheres;
+ << theOppositeHemispheres << theCutWeight;
}
void JetPairRegion::persistentInput(PersistentIStream & is, int) {
is >> theFirstRegion >> theSecondRegion
>> iunit(theMassMin,GeV) >> iunit(theMassMax,GeV)
>> theDeltaRMin >> theDeltaRMax
>> theDeltaYMin >> theDeltaYMax
- >> theOppositeHemispheres;
+ >> theOppositeHemispheres >> theCutWeight;
}
// *** 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<JetPairRegion,HandlerBase>
describeThePEGJetPairRegion("ThePEG::JetPairRegion", "JetCuts.so");
void JetPairRegion::Init() {
static ClassDocumentation<JetPairRegion> documentation
("JetPairRegion implements constraints on jets matching two jet regions.");
static Reference<JetPairRegion,JetRegion> interfaceFirstRegion
("FirstRegion",
"The first region to act on.",
&JetPairRegion::theFirstRegion, false, false, true, false, false);
static Reference<JetPairRegion,JetRegion> interfaceSecondRegion
("SecondRegion",
"The second region to act on.",
&JetPairRegion::theSecondRegion, false, false, true, false, false);
static Parameter<JetPairRegion,Energy> interfaceMassMin
("MassMin",
"The minimum jet-jet invariant mass.",
&JetPairRegion::theMassMin, GeV, 0.0*GeV, 0.0*GeV, 0*GeV,
false, false, Interface::lowerlim);
static Parameter<JetPairRegion,Energy> interfaceMassMax
("MassMax",
"The maximum jet-jet invariant mass.",
&JetPairRegion::theMassMax, GeV, Constants::MaxEnergy, 0.0*GeV, 0*GeV,
false, false, Interface::lowerlim);
static Parameter<JetPairRegion,double> interfaceDeltaRMin
("DeltaRMin",
"The minimum jet-jet lego-plot separation.",
&JetPairRegion::theDeltaRMin, 0.0, 0.0, 0,
false, false, Interface::lowerlim);
static Parameter<JetPairRegion,double> interfaceDeltaRMax
("DeltaRMax",
"The maximum jet-jet lego-plot separation.",
&JetPairRegion::theDeltaRMax, Constants::MaxRapidity, 0, 0,
false, false, Interface::lowerlim);
static Parameter<JetPairRegion,double> interfaceDeltaYMin
("DeltaYMin",
"The minimum jet-jet rapidity separation.",
&JetPairRegion::theDeltaYMin, 0.0, 0.0, 0,
false, false, Interface::lowerlim);
static Parameter<JetPairRegion,double> interfaceDeltaYMax
("DeltaYMax",
"The maximum jet-jet rapidity separation.",
&JetPairRegion::theDeltaYMax, Constants::MaxRapidity, 0, 0,
false, false, Interface::lowerlim);
static Switch<JetPairRegion,bool> interfaceOppositeHemispheres
("OppositeHemispheres",
"Should the jets go into opposite detector hemispheres?",
&JetPairRegion::theOppositeHemispheres, false, true, false);
static SwitchOption interfaceOppositeHemispheresTrue
(interfaceOppositeHemispheres,
"True",
"Require jets to be in different hemispheres",
true);
static SwitchOption interfaceOppositeHemispheresFalse
(interfaceOppositeHemispheres,
"False",
"Do not require jets to be in different hemispheres",
false);
+
}
diff --git a/Cuts/JetPairRegion.h b/Cuts/JetPairRegion.h
--- a/Cuts/JetPairRegion.h
+++ b/Cuts/JetPairRegion.h
@@ -1,205 +1,215 @@
// -*- C++ -*-
//
// JetPairRegion.h is a part of ThePEG - Toolkit for HEP Event Generation
// Copyright (C) 1999-2007 Leif Lonnblad
// Copyright (C) 2009-2012 Simon Platzer
//
// ThePEG is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef ThePEG_JetPairRegion_H
#define ThePEG_JetPairRegion_H
//
// This is the declaration of the JetPairRegion class.
//
#include "ThePEG/Cuts/JetRegion.h"
namespace ThePEG {
/**
* JetPairRegion implements constraints on jets matching two jet regions.
*
* @see JetRegion
* @see JetCuts
*
* @see \ref JetPairRegionInterfaces "The interfaces"
* defined for JetPairRegion.
*/
class JetPairRegion: public HandlerBase {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
JetPairRegion();
/**
* The destructor.
*/
virtual ~JetPairRegion();
//@}
public:
/**
* Return the first jet region to act on.
*/
Ptr<JetRegion>::tptr firstRegion() const { return theFirstRegion; }
/**
* Return the second jet region to act on.
*/
Ptr<JetRegion>::tptr secondRegion() const { return theSecondRegion; }
/**
* Return the minimum jet-jet invariant mass.
*/
Energy massMin() const { return theMassMin; }
/**
* Return the maximum jet-jet invariant mass.
*/
Energy massMax() const { return theMassMax; }
/**
* Return the minimum jet-jet lego-plot separation.
*/
double deltaRMin() const { return theDeltaRMin; }
/**
* Return the maximum jet-jet lego-plot separation.
*/
double deltaRMax() const { return theDeltaRMax; }
/**
* Return the minimum jet-jet rapidity separation.
*/
double deltaYMin() const { return theDeltaYMin; }
/**
* Return the maximum jet-jet rapidity separation.
*/
double deltaYMax() const { return theDeltaYMax; }
+ /**
+ * Return the cut weight encountered from the last call to matches()
+ */
+ double cutWeight() const { return theCutWeight; }
+
public:
/**
* Describe the currently active cuts in the log file.
*/
virtual void describe() const;
/**
* Return true, if the requirements on the jet regions are fullfilled.
*/
- virtual bool matches(tcCutsPtr parent) const;
+ virtual bool matches(tcCutsPtr parent);
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).
private:
/**
* The first jet region to act on.
*/
Ptr<JetRegion>::ptr theFirstRegion;
/**
* The second jet region to act on.
*/
Ptr<JetRegion>::ptr theSecondRegion;
/**
* The minimum jet-jet invariant mass.
*/
Energy theMassMin;
/**
* The maximum jet-jet invariant mass.
*/
Energy theMassMax;
/**
* The minimum jet-jet lego-plot separation.
*/
double theDeltaRMin;
/**
* The maximum jet-jet lego-plot separation.
*/
double theDeltaRMax;
/**
* The minimum jet-jet rapidity separation.
*/
double theDeltaYMin;
/**
* The maximum jet-jet rapidity separation.
*/
double theDeltaYMax;
/**
* Should the jets go into opposite detector hemispheres?
*/
bool theOppositeHemispheres;
/**
+ * The cut weight encountered from the last call to matches()
+ */
+ double theCutWeight;
+
+ /**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
JetPairRegion & operator=(const JetPairRegion &);
};
}
#endif /* ThePEG_JetPairRegion_H */
diff --git a/Cuts/JetRegion.cc b/Cuts/JetRegion.cc
--- a/Cuts/JetRegion.cc
+++ b/Cuts/JetRegion.cc
@@ -1,168 +1,252 @@
// -*- C++ -*-
//
// JetRegion.cc is a part of ThePEG - Toolkit for HEP Event Generation
// Copyright (C) 1999-2007 Leif Lonnblad
// Copyright (C) 2009-2012 Simon Platzer
//
// ThePEG 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 JetRegion class.
//
#include "JetRegion.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Command.h"
+#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/ParVector.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Repository/CurrentGenerator.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace ThePEG;
JetRegion::JetRegion()
: thePtMin(0.*GeV), thePtMax(Constants::MaxEnergy),
- theDidMatch(false), theLastNumber(0) {}
+ theDidMatch(false), theLastNumber(0),
+ theFuzzy(false), theCutWeight(1.0),
+ theEnergyCutWidth(1.0*GeV), theRapidityCutWidth(0.1) {}
JetRegion::~JetRegion() {}
IBPtr JetRegion::clone() const {
return new_ptr(*this);
}
IBPtr JetRegion::fullclone() const {
return new_ptr(*this);
}
string JetRegion::doYRange(string in) {
istringstream ins(in);
double first, second;
ins >> first >> second;
if ( first > second )
swap(first,second);
theYRanges.push_back(make_pair(first,second));
return "";
}
void JetRegion::describe() const {
CurrentGenerator::log()
<< "JetRegion '" << name() << "' matching ";
if ( accepts().empty() )
CurrentGenerator::log() << "any jets ";
else {
CurrentGenerator::log() << "jets ";
for ( vector<int>::const_iterator k = accepts().begin();
k != accepts().end(); ++k ) {
CurrentGenerator::log() << "#" << *k;
if ( k != --accepts().end() )
CurrentGenerator::log() << ", ";
else
CurrentGenerator::log() << " ";
}
}
CurrentGenerator::log() << " within:\n";
CurrentGenerator::log()
<< "pt = " << ptMin()/GeV << " .. " << ptMax()/GeV << " GeV\n";
for ( vector<pair<double,double> >::const_iterator r = yRanges().begin();
r != yRanges().end(); ++r ) {
CurrentGenerator::log() << "y = " << r->first << " .. " << r->second << "\n";
}
}
+double step(double r) {
+ if ( r < -0.5 )
+ return 0.0;
+ if ( r > 0.5 )
+ return 1.0;
+ return r+0.5;
+}
+
+bool JetRegion::lessThanEnergy(Energy a, Energy b, double& weight) const {
+ if ( !fuzzy() ) {
+ if ( a < b ) {
+ weight = 1.0;
+ return true;
+ }
+ weight = 0.0;
+ return false;
+ }
+ double w = step((b-a)/theEnergyCutWidth);
+ if ( w == 0.0 ) {
+ weight = 0.0;
+ return false;
+ }
+ weight *= w;
+ return true;
+}
+
+bool JetRegion::lessThanRapidity(double a, double b, double& weight) const {
+ if ( !fuzzy() ) {
+ if ( a < b ) {
+ weight = 1.0;
+ return true;
+ }
+ weight = 0.0;
+ return false;
+ }
+ double w = step((b-a)/theRapidityCutWidth);
+ if ( w == 0.0 ) {
+ weight = 0.0;
+ return false;
+ }
+ weight *= w;
+ return true;
+}
+
bool JetRegion::matches(tcCutsPtr parent, int n, const LorentzMomentum& p) {
// one jet region can only contain one jet
if ( didMatch() )
return false;
if ( !accepts().empty() && find(accepts().begin(),accepts().end(),n) == accepts().end() )
return false;
- if ( p.perp() < ptMin() || p.perp() > ptMax() )
+ theCutWeight = 1.0;
+
+ if ( !(lessThanEnergy(ptMin(),p.perp(),theCutWeight) &&
+ lessThanEnergy(p.perp(),ptMax(),theCutWeight)) )
return false;
bool inRange = false || yRanges().empty();
for ( vector<pair<double,double> >::const_iterator r = yRanges().begin();
r != yRanges().end(); ++r ) {
- if ( p.rapidity() + parent->currentYHat() > r->first && p.rapidity() + parent->currentYHat() < r->second ) {
+ double rangeWeight = 1.0;
+ if ( lessThanRapidity(r->first,p.rapidity() + parent->currentYHat(),rangeWeight) &&
+ lessThanRapidity(p.rapidity() + parent->currentYHat(),r->second,rangeWeight) ) {
+ theCutWeight *= rangeWeight;
inRange = true;
break;
}
}
- if ( !inRange )
+ if ( !inRange ) {
+ theCutWeight = 0.0;
return false;
+ }
theDidMatch = true;
theLastNumber = n;
theLastMomentum = p;
return true;
}
// If needed, insert default implementations of virtual function defined
// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs).
void JetRegion::persistentOutput(PersistentOStream & os) const {
os << ounit(thePtMin,GeV) << ounit(thePtMax,GeV)
- << theYRanges << theAccepts;
+ << theYRanges << theAccepts << theFuzzy << theCutWeight
+ << ounit(theEnergyCutWidth,GeV) << theRapidityCutWidth;
}
void JetRegion::persistentInput(PersistentIStream & is, int) {
is >> iunit(thePtMin,GeV) >> iunit(thePtMax,GeV)
- >> theYRanges >> theAccepts;
+ >> theYRanges >> theAccepts >> theFuzzy >> theCutWeight
+ >> iunit(theEnergyCutWidth,GeV) >> theRapidityCutWidth;
}
// *** 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<JetRegion,HandlerBase>
describeThePEGJetRegion("ThePEG::JetRegion", "JetCuts.so");
void JetRegion::Init() {
static ClassDocumentation<JetRegion> documentation
("JetRegion implements the requirement of finding a jet inside a "
"given range of transverse momenta, and (pseudo-)rapidity.");
static Parameter<JetRegion,Energy> interfacePtMin
("PtMin",
"The minimum pt required.",
&JetRegion::thePtMin, GeV, 0.0*GeV, 0.0*GeV, 0*GeV,
false, false, Interface::lowerlim);
static Parameter<JetRegion,Energy> interfacePtMax
("PtMax",
"The maximum pt allowed.",
&JetRegion::thePtMax, GeV, Constants::MaxEnergy, 0.0*GeV, 0*GeV,
false, false, Interface::lowerlim);
static Command<JetRegion> interfaceYRange
("YRange",
"Insert a rapidity range.",
&JetRegion::doYRange, false);
static ParVector<JetRegion,int> interfaceAccepts
("Accepts",
"The jet numbers accepted. If empty, any jets are accepted.",
&JetRegion::theAccepts, -1, 1, 1, 10,
false, false, Interface::upperlim);
+ static Switch<JetRegion,bool> interfaceFuzzy
+ ("Fuzzy",
+ "Make this jet region a fuzzy cut",
+ &JetRegion::theFuzzy, false, false, false);
+ static SwitchOption interfaceFuzzyOn
+ (interfaceFuzzy,
+ "Yes",
+ "",
+ true);
+ static SwitchOption interfaceFuzzyOff
+ (interfaceFuzzy,
+ "No",
+ "",
+ false);
+
+ static Parameter<JetRegion,Energy> interfaceEnergyCutWidth
+ ("EnergyCutWidth",
+ "The pt cut smearing.",
+ &JetRegion::theEnergyCutWidth, GeV, 1.0*GeV, 0.0*GeV, 0*GeV,
+ false, false, Interface::lowerlim);
+
+ static Parameter<JetRegion,double> interfaceRapidityCutWidth
+ ("RapidityCutWidth",
+ "The rapidity cut smearing.",
+ &JetRegion::theRapidityCutWidth, 0.1, 0.0, 0,
+ false, false, Interface::lowerlim);
+
}
diff --git a/Cuts/JetRegion.h b/Cuts/JetRegion.h
--- a/Cuts/JetRegion.h
+++ b/Cuts/JetRegion.h
@@ -1,207 +1,247 @@
// -*- C++ -*-
//
// JetRegion.h is a part of ThePEG - Toolkit for HEP Event Generation
// Copyright (C) 1999-2007 Leif Lonnblad
// Copyright (C) 2009-2012 Simon Platzer
//
// ThePEG is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef ThePEG_JetRegion_H
#define ThePEG_JetRegion_H
//
// This is the declaration of the JetRegion class.
//
#include "ThePEG/Handlers/HandlerBase.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/Cuts/Cuts.h"
namespace ThePEG {
/**
* JetRegion implements the requirement of finding a jet inside a
* given range of transverse momenta, and (pseudo-)rapidity.
*
* @see JetPairRegion
* @see JetCuts
*
* @see \ref JetRegionInterfaces "The interfaces"
* defined for JetRegion.
*/
class JetRegion: public HandlerBase {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
JetRegion();
/**
* The destructor.
*/
virtual ~JetRegion();
//@}
public:
/**
* Return the minimum pt.
*/
Energy ptMin() const { return thePtMin; }
/**
* Return the maximum pt.
*/
Energy ptMax() const { return thePtMax; }
/**
* Return the rapidity ranges.
*/
const vector<pair<double,double> >& yRanges() const { return theYRanges; }
/**
* Return the jets accepted by this region (with respect to the
* ordering imposed by the JetCuts object). If empty, any jet will
* be accepted.
*/
const vector<int>& accepts() const { return theAccepts; }
+ /**
+ * Return true, if this jet region is fuzzy
+ */
+ bool fuzzy() const { return theFuzzy; }
+
+ /**
+ * Return the cut weight encountered from the last call to matches()
+ */
+ double cutWeight() const { return theCutWeight; }
+
+ /**
+ * Perform a (potentially) fuzzy check on energy-type quantities
+ */
+ bool lessThanEnergy(Energy a, Energy b, double& weight) const;
+
+ /**
+ * Perform a (potentially) fuzzy check on angular-type quantities
+ */
+ bool lessThanRapidity(double a, double b, double& weight) const;
+
public:
/**
* Describe the currently active cuts in the log file.
*/
virtual void describe() const;
/**
* Return true, if the given jet matches this region.
*/
virtual bool matches(tcCutsPtr parent, int n, const LorentzMomentum& p);
/**
* Return true, if this region matched a jet in the last call to matches().
*/
bool didMatch() { return theDidMatch; }
/**
* Reset this region to act on a new event.
*/
virtual void reset() { theDidMatch = false; }
/**
* Return the number of the last jet matching this region.
*/
int lastNumber() const { return theLastNumber; }
/**
* Return the momentum of the last jet matching this region.
*/
const LorentzMomentum& lastMomentum() const { return theLastMomentum; }
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).
private:
/**
* Command to insert a rapidity range
*/
string doYRange(string);
/**
* The minimum pt.
*/
Energy thePtMin;
/**
* The maximum pt.
*/
Energy thePtMax;
/**
* The rapidity ranges.
*/
vector<pair<double,double> > theYRanges;
/**
* The jets accepted by this region (with respect to the ordering
* imposed by the JetCuts object). If empty, any jet will be
* accepted.
*/
vector<int> theAccepts;
/**
* True, if this region matched a jet in the last call to matches().
*/
bool theDidMatch;
/**
* The number of the last jet matching this region.
*/
int theLastNumber;
/**
* Return the momentum of the last jet matching this region.
*/
LorentzMomentum theLastMomentum;
/**
+ * True if this region is fuzzy
+ */
+ bool theFuzzy;
+
+ /**
+ * The cut weight encountered from the last call to matches()
+ */
+ double theCutWeight;
+
+ /**
+ * The smearing width for the pt or mass cuts, if fuzzy
+ */
+ Energy theEnergyCutWidth;
+
+ /**
+ * The smearing width for the rapidity cut, if fuzzy
+ */
+ double theRapidityCutWidth;
+
+ /**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
JetRegion & operator=(const JetRegion &);
};
}
#endif /* ThePEG_JetRegion_H */
diff --git a/Cuts/MultiJetRegion.cc b/Cuts/MultiJetRegion.cc
--- a/Cuts/MultiJetRegion.cc
+++ b/Cuts/MultiJetRegion.cc
@@ -1,182 +1,190 @@
// -*- C++ -*-
//
// MultiJetRegion.cc is a part of ThePEG - Toolkit for HEP Event Generation
// Copyright (C) 1999-2007 Leif Lonnblad
// Copyright (C) 2009-2012 Simon Platzer
//
// ThePEG 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 MultiJetRegion class.
//
#include "MultiJetRegion.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/RefVector.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Repository/CurrentGenerator.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace ThePEG;
MultiJetRegion::MultiJetRegion()
: theMassMin(0.*GeV), theMassMax(Constants::MaxEnergy),
theDeltaRMin(0.0), theDeltaRMax(Constants::MaxRapidity),
- theDeltaYMin(0.0), theDeltaYMax(Constants::MaxRapidity) {}
+ theDeltaYMin(0.0), theDeltaYMax(Constants::MaxRapidity),
+ theCutWeight(1.0) {}
MultiJetRegion::~MultiJetRegion() {}
IBPtr MultiJetRegion::clone() const {
return new_ptr(*this);
}
IBPtr MultiJetRegion::fullclone() const {
return new_ptr(*this);
}
void MultiJetRegion::describe() const {
CurrentGenerator::log()
<< "MultiJetRegion '" << name() << "' matching JetRegions:\n";
for ( vector<Ptr<JetRegion>::ptr>::const_iterator r = regions().begin();
r != regions().end(); ++r ) {
CurrentGenerator::log()
<< "'" << (**r).name() << "'\n";
}
CurrentGenerator::log() << "with\n";
CurrentGenerator::log()
<< "m = " << massMin()/GeV << " .. " << massMax()/GeV << " GeV\n"
<< "dR = " << deltaRMin() << " .. " << deltaRMax() << "\n"
<< "dy = " << deltaYMin() << " .. " << deltaYMax() << "\n";
}
-bool MultiJetRegion::matches() const {
+bool MultiJetRegion::matches() {
int n = regions().size();
for ( int i = 0; i < n; ++i )
for ( int j = i+1; j < n; ++j )
if ( !matches(i,j) )
return false;
return true;
}
-bool MultiJetRegion::matches(int i, int j) const {
+bool MultiJetRegion::matches(int i, int j) {
if ( !regions()[i]->didMatch() ||
- !regions()[j]->didMatch() )
+ !regions()[j]->didMatch() ) {
+ theCutWeight = 0.0;
return false;
+ }
+
+ theCutWeight = 1.0;
const LorentzMomentum& pi = regions()[i]->lastMomentum();
const LorentzMomentum& pj = regions()[j]->lastMomentum();
Energy m = (pi+pj).m();
- if ( m < massMin() || m > massMax() )
+ if ( !(regions()[i]->lessThanEnergy(massMin(),m,theCutWeight) &&
+ regions()[i]->lessThanEnergy(m,massMax(),theCutWeight)) )
return false;
double dy = abs(pi.rapidity() - pj.rapidity());
- if ( dy < deltaYMin() || dy > deltaYMax() )
+ if ( !(regions()[i]->lessThanRapidity(deltaYMin(),dy,theCutWeight) &&
+ regions()[i]->lessThanRapidity(dy,deltaYMax(),theCutWeight)) )
return false;
double dphi = abs(pi.phi() - pj.phi());
if ( dphi > Constants::pi ) dphi = 2.0*Constants::pi - dphi;
double dR = sqrt(sqr(dy)+sqr(dphi));
- if ( dR < deltaRMin() || dR > deltaRMax() )
+ if ( !(regions()[i]->lessThanRapidity(deltaRMin(),dR,theCutWeight) &&
+ regions()[i]->lessThanRapidity(dR,deltaRMax(),theCutWeight)) )
return false;
return true;
}
// If needed, insert default implementations of virtual function defined
// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs).
void MultiJetRegion::persistentOutput(PersistentOStream & os) const {
os << theRegions
<< ounit(theMassMin,GeV) << ounit(theMassMax,GeV)
<< theDeltaRMin << theDeltaRMax
- << theDeltaYMin << theDeltaYMax;
+ << theDeltaYMin << theDeltaYMax << theCutWeight;
}
void MultiJetRegion::persistentInput(PersistentIStream & is, int) {
is >> theRegions
>> iunit(theMassMin,GeV) >> iunit(theMassMax,GeV)
>> theDeltaRMin >> theDeltaRMax
- >> theDeltaYMin >> theDeltaYMax;
+ >> theDeltaYMin >> theDeltaYMax >> theCutWeight;
}
// *** 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<MultiJetRegion,HandlerBase>
describeThePEGMultiJetRegion("ThePEG::MultiJetRegion", "JetCuts.so");
void MultiJetRegion::Init() {
static ClassDocumentation<MultiJetRegion> documentation
("MultiJetRegion implements pairwise constraints on jets matching several jet regions.");
static RefVector<MultiJetRegion,JetRegion> interfaceRegions
("Regions",
"The jet regions to act on.",
&MultiJetRegion::theRegions, -1, false, false, true, false, false);
static Parameter<MultiJetRegion,Energy> interfaceMassMin
("MassMin",
"The minimum jet-jet invariant mass.",
&MultiJetRegion::theMassMin, GeV, 0.0*GeV, 0.0*GeV, 0*GeV,
false, false, Interface::lowerlim);
static Parameter<MultiJetRegion,Energy> interfaceMassMax
("MassMax",
"The maximum jet-jet invariant mass.",
&MultiJetRegion::theMassMax, GeV, Constants::MaxEnergy, 0.0*GeV, 0*GeV,
false, false, Interface::lowerlim);
static Parameter<MultiJetRegion,double> interfaceDeltaRMin
("DeltaRMin",
"The minimum jet-jet lego-plot separation.",
&MultiJetRegion::theDeltaRMin, 0.0, 0.0, 0,
false, false, Interface::lowerlim);
static Parameter<MultiJetRegion,double> interfaceDeltaRMax
("DeltaRMax",
"The maximum jet-jet lego-plot separation.",
&MultiJetRegion::theDeltaRMax, Constants::MaxRapidity, 0, 0,
false, false, Interface::lowerlim);
static Parameter<MultiJetRegion,double> interfaceDeltaYMin
("DeltaYMin",
"The minimum jet-jet rapidity separation.",
&MultiJetRegion::theDeltaYMin, 0.0, 0.0, 0,
false, false, Interface::lowerlim);
static Parameter<MultiJetRegion,double> interfaceDeltaYMax
("DeltaYMax",
"The maximum jet-jet rapidity separation.",
&MultiJetRegion::theDeltaYMax, Constants::MaxRapidity, 0, 0,
false, false, Interface::lowerlim);
}
diff --git a/Cuts/MultiJetRegion.h b/Cuts/MultiJetRegion.h
--- a/Cuts/MultiJetRegion.h
+++ b/Cuts/MultiJetRegion.h
@@ -1,195 +1,205 @@
// -*- C++ -*-
//
// MultiJetRegion.h is a part of ThePEG - Toolkit for HEP Event Generation
// Copyright (C) 1999-2007 Leif Lonnblad
// Copyright (C) 2009-2012 Simon Platzer
//
// ThePEG is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef ThePEG_MultiJetRegion_H
#define ThePEG_MultiJetRegion_H
//
// This is the declaration of the MultiJetRegion class.
//
#include "ThePEG/Cuts/JetRegion.h"
namespace ThePEG {
/**
* MultiJetRegion implements pairwise constraints on jets matching several jet regions.
*
* @see JetRegion
* @see JetCuts
*
* @see \ref MultiJetRegionInterfaces "The interfaces"
* defined for MultiJetRegion.
*/
class MultiJetRegion: public HandlerBase {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
MultiJetRegion();
/**
* The destructor.
*/
virtual ~MultiJetRegion();
//@}
public:
/**
* Return the jet regions to act on.
*/
const vector<Ptr<JetRegion>::ptr>& regions() const { return theRegions; }
/**
* Return the minimum jet-jet invariant mass.
*/
Energy massMin() const { return theMassMin; }
/**
* Return the maximum jet-jet invariant mass.
*/
Energy massMax() const { return theMassMax; }
/**
* Return the minimum jet-jet lego-plot separation.
*/
double deltaRMin() const { return theDeltaRMin; }
/**
* Return the maximum jet-jet lego-plot separation.
*/
double deltaRMax() const { return theDeltaRMax; }
/**
* Return the minimum jet-jet rapidity separation.
*/
double deltaYMin() const { return theDeltaYMin; }
/**
* Return the maximum jet-jet rapidity separation.
*/
double deltaYMax() const { return theDeltaYMax; }
+ /**
+ * Return the cut weight encountered from the last call to matches()
+ */
+ double cutWeight() const { return theCutWeight; }
+
public:
/**
* Describe the currently active cuts in the log file.
*/
virtual void describe() const;
/**
* Return true, if the requirements on the jet regions are fullfilled.
*/
- virtual bool matches() const;
+ virtual bool matches();
/**
* Return true, if the requirements on two jet regions are fullfilled.
*/
- virtual bool matches(int i, int j) const;
+ virtual bool matches(int i, int j);
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).
private:
/**
* The jet regions to act on.
*/
vector<Ptr<JetRegion>::ptr> theRegions;
/**
* The minimum jet-jet invariant mass.
*/
Energy theMassMin;
/**
* The maximum jet-jet invariant mass.
*/
Energy theMassMax;
/**
* The minimum jet-jet lego-plot separation.
*/
double theDeltaRMin;
/**
* The maximum jet-jet lego-plot separation.
*/
double theDeltaRMax;
/**
* The minimum jet-jet rapidity separation.
*/
double theDeltaYMin;
/**
* The maximum jet-jet rapidity separation.
*/
double theDeltaYMax;
/**
+ * The cut weight encountered from the last call to matches()
+ */
+ double theCutWeight;
+
+ /**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MultiJetRegion & operator=(const MultiJetRegion &);
};
}
#endif /* ThePEG_MultiJetRegion_H */
diff --git a/Handlers/StandardXComb.cc b/Handlers/StandardXComb.cc
--- a/Handlers/StandardXComb.cc
+++ b/Handlers/StandardXComb.cc
@@ -1,677 +1,691 @@
// -*- C++ -*-
//
// StandardXComb.cc is a part of ThePEG - Toolkit for HEP Event Generation
// Copyright (C) 1999-2011 Leif Lonnblad
// Copyright (C) 2009-2011 Simon Platzer
//
// ThePEG 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 StandardXComb class.
//
#include "StandardXComb.h"
#include "StdXCombGroup.h"
#include "ThePEG/Handlers/StandardEventHandler.h"
#include "ThePEG/Handlers/SubProcessHandler.h"
#include "ThePEG/Cuts/Cuts.h"
#include "ThePEG/PDF/PartonExtractor.h"
#include "ThePEG/Utilities/Debug.h"
#include "ThePEG/Utilities/Maths.h"
#include "ThePEG/PDT/ParticleData.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Utilities/SimplePhaseSpace.h"
#include "ThePEG/Utilities/UtilityBase.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/EventRecord/SubProcessGroup.h"
#include "ThePEG/Vectors/LorentzRotation.h"
#include "ThePEG/MatrixElement/MEBase.h"
#include "ThePEG/MatrixElement/ColourLines.h"
#include "ThePEG/Handlers/LuminosityFunction.h"
#include "ThePEG/Handlers/CascadeHandler.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/EventRecord/TmpTransform.h"
#ifdef ThePEG_TEMPLATES_IN_CC_FILE
#include "StandardXComb.tcc"
#endif
using namespace ThePEG;
StandardXComb::StandardXComb()
: XComb(), isMirror(false), theNDim(0),
partonDims(make_pair(0, 0)), theKinematicsGenerated(false),
theLastDiagramIndex(0), theLastPDFWeight(0.0),
theLastCrossSection(ZERO), theLastJacobian(1.0), theLastME2(-1.0),
theLastMECrossSection(ZERO), theLastMEPDFWeight(1.0),
- checkedCuts(false), passedCuts(false) {}
+ checkedCuts(false), passedCuts(false), theCutWeight(1.0) {}
StandardXComb::
StandardXComb(Energy newMaxEnergy, const cPDPair & inc,
tEHPtr newEventHandler, tSubHdlPtr newSubProcessHandler,
tPExtrPtr newExtractor, tCascHdlPtr newCKKW,
const PBPair & newPartonBins, tCutsPtr newCuts,
tMEPtr newME, const DiagramVector & newDiagrams, bool mir,
tStdXCombPtr newHead)
: XComb(newMaxEnergy, inc, newEventHandler,
newExtractor, newCKKW, newPartonBins, newCuts),
theSubProcessHandler(newSubProcessHandler), theME(newME),
theDiagrams(newDiagrams), isMirror(mir), theKinematicsGenerated(false),
theLastDiagramIndex(0), theLastPDFWeight(0.0),
theLastCrossSection(ZERO), theLastME2(-1.0), theLastMECrossSection(ZERO),
theLastMEPDFWeight(1.0), theHead(newHead),
checkedCuts(false), passedCuts(false) {
partonDims = pExtractor()->nDims(partonBins());
if ( matrixElement()->haveX1X2() ) {
partonDims.first = 0;
partonDims.second = 0;
}
theNDim = matrixElement()->nDim() + partonDims.first + partonDims.second;
mePartonData() = lastDiagram()->partons();
}
StandardXComb::StandardXComb(tMEPtr me, const tPVector & parts,
DiagramIndex indx)
: theME(me), isMirror(false), theNDim(0), partonDims(make_pair(0, 0)),
theKinematicsGenerated(false),
theLastDiagramIndex(0), theLastPDFWeight(0.0), theLastCrossSection(ZERO),
theLastME2(-1.0), theLastMECrossSection(ZERO), theLastMEPDFWeight(1.0),
checkedCuts(false), passedCuts(false) {
subProcess(new_ptr(SubProcess(make_pair(parts[0], parts[1]),
tCollPtr(), me)));
for ( int i = 0, N = parts.size(); i < N; ++i ) {
subProcess()->addOutgoing(parts[i], false);
theMEPartonData.push_back(parts[i]->dataPtr());
theMEMomenta.push_back(parts[i]->momentum());
}
lastSHat((meMomenta()[0] + meMomenta()[1]).m2());
string tag = me->diagrams()[indx]->getTag();
for ( int i = 0, N = me->diagrams().size(); i < N; ++i )
if ( me->diagrams()[i]->getTag() == tag )
theDiagrams.push_back(me->diagrams()[i]);
}
StandardXComb::StandardXComb(tStdXCombPtr newHead,
const PBPair & newPartonBins, tMEPtr newME,
const DiagramVector & newDiagrams)
: XComb(newHead->maxEnergy(), newHead->particles(),
newHead->eventHandlerPtr(), newHead->pExtractor(),
newHead->CKKWHandler(), newPartonBins, newHead->cuts()),
theSubProcessHandler(const_ptr_cast<tSubHdlPtr>(newHead->subProcessHandler())),
theME(newME), theDiagrams(newDiagrams), isMirror(newHead->mirror()),
theKinematicsGenerated(false), theLastDiagramIndex(0), theLastPDFWeight(0.0),
theLastCrossSection(ZERO), theLastME2(-1.0), theLastMECrossSection(ZERO),
theLastMEPDFWeight(1.0), theHead(newHead),
checkedCuts(false), passedCuts(false) {
partonDims = pExtractor()->nDims(partonBins());
if ( matrixElement()->haveX1X2() ) {
partonDims.first = 0;
partonDims.second = 0;
}
theNDim = matrixElement()->nDim() + partonDims.first + partonDims.second;
mePartonData() = lastDiagram()->partons();
/* // wait for C++11
StandardXComb(newHead->maxEnergy(),newHead->particles(),
newHead->eventHandlerPtr(),
const_ptr_cast<tSubHdlPtr>(newHead->subProcessHandler()),
newHead->pExtractor(),newHead->CKKWHandler(),
newPartonBins,newHead->cuts(),newME,newDiagrams,newHead->mirror(),
newHead);
*/
}
StandardXComb::~StandardXComb() {}
void StandardXComb::recreatePartonBinInstances(Energy2 scale) {
PBIPair newBins;
Direction<0> dir(true);
newBins.first =
new_ptr(PartonBinInstance(lastPartons().first,partonBins().first,scale));
dir.reverse();
newBins.second =
new_ptr(PartonBinInstance(lastPartons().second,partonBins().second,scale));
resetPartonBinInstances(newBins);
setPartonBinInfo();
lastPartons().first->scale(partonBinInstances().first->scale());
lastPartons().second->scale(partonBinInstances().second->scale());
}
void StandardXComb::refillPartonBinInstances(const double* r) {
pExtractor()->select(this);
pExtractor()->updatePartonBinInstances(partonBinInstances());
pExtractor()->generateSHat(lastS(), partonBinInstances(),
r, r + nDim() - partonDims.second,true);
}
void StandardXComb::setIncomingPartons(tStdXCombPtr labHead) {
if ( lastPartons().first )
return;
if ( !labHead )
labHead = head();
createPartonBinInstances();
lastParticles(labHead->lastParticles());
setPartonBinInfo();
lastPartons(make_pair(mePartonData()[0]->produceParticle(Lorentz5Momentum()),
mePartonData()[1]->produceParticle(Lorentz5Momentum())));
Lorentz5Momentum pFirst = meMomenta()[0];
Lorentz5Momentum pSecond = meMomenta()[1];
if ( labHead->matrixElement()->wantCMS() ) {
Boost toLab = (labHead->lastPartons().first->momentum() +
labHead->lastPartons().second->momentum()).boostVector();
if ( toLab.mag2() > Constants::epsilon ) {
pFirst.boost(toLab);
pSecond.boost(toLab);
}
}
lastPartons().first->set5Momentum(pFirst);
lastPartons().second->set5Momentum(pSecond);
partonBinInstances().first->parton(lastPartons().first);
partonBinInstances().second->parton(lastPartons().second);
lastS((lastParticles().first->momentum() +
lastParticles().second->momentum()).m2());
lastSHat((lastPartons().first->momentum() +
lastPartons().second->momentum()).m2());
lastP1P2(make_pair(labHead->lastP1(),labHead->lastP2()));
double x1 =
lastPartons().first->momentum().plus()/
lastParticles().first->momentum().plus();
double x2 =
lastPartons().second->momentum().minus()/
lastParticles().second->momentum().minus();
lastX1X2(make_pair(x1,x2));
lastY((lastPartons().first->momentum()+
lastPartons().second->momentum()).rapidity());
}
void StandardXComb::fill(const PPair& newParticles,
const PPair& newPartons,
const vector<Lorentz5Momentum>& newMEMomenta,
const DVector& newLastRandomNumbers) {
lastParticles(newParticles);
lastP1P2(make_pair(0.0, 0.0));
lastS((lastParticles().first->momentum() +
lastParticles().second->momentum()).m2());
lastPartons(newPartons);
lastSHat((lastPartons().first->momentum() +
lastPartons().second->momentum()).m2());
lastX1X2(make_pair(lastPartons().first->momentum().plus()/
lastParticles().first->momentum().plus(),
lastPartons().second->momentum().minus()/
lastParticles().second->momentum().minus()));
lastY((lastPartons().first->momentum() +
lastPartons().second->momentum()).rapidity());
meMomenta().resize(newMEMomenta.size());
copy(newMEMomenta.begin(),newMEMomenta.end(),
meMomenta().begin());
lastRandomNumbers().resize(newLastRandomNumbers.size());
copy(newLastRandomNumbers.begin(),newLastRandomNumbers.end(),
lastRandomNumbers().begin());
}
bool StandardXComb::checkInit() {
Energy summin = ZERO;
for ( int i = 2, N = mePartonData().size(); i < N; ++i ) {
summin += mePartonData()[i]->massMin();
}
return ( summin < min(maxEnergy(), cuts()->mHatMax()) );
}
bool StandardXComb::willPassCuts() {
if ( checkedCuts )
return passedCuts;
checkedCuts = true;
if ( !head() ) {
if ( !cuts()->initSubProcess(lastSHat(), lastY(), mirror()) ) {
passedCuts = false;
+ theCutWeight = 0.0;
return false;
}
} else {
cuts()->initSubProcess(lastSHat(), lastY(), mirror());
}
tcPDVector outdata(mePartonData().begin()+2,mePartonData().end());
vector<LorentzMomentum> outmomenta(meMomenta().begin()+2,meMomenta().end());
Boost tocm = (meMomenta()[0]+meMomenta()[1]).findBoostToCM();
if ( tocm.mag2() > Constants::epsilon ) {
for ( vector<LorentzMomentum>::iterator p = outmomenta.begin();
p != outmomenta.end(); ++p ) {
p->boost(tocm);
}
}
if ( !cuts()->passCuts(outdata,outmomenta,mePartonData()[0],mePartonData()[1]) ) {
+ theCutWeight = cuts()->cutWeight();
passedCuts = false;
return false;
}
+ theCutWeight = cuts()->cutWeight();
passedCuts = true;
return true;
}
void StandardXComb::clean() {
XComb::clean();
theLastPDFWeight = 0.0;
theLastCrossSection = ZERO;
theLastJacobian = 0.0;
theLastME2 = 0.0;
theLastMECrossSection = ZERO;
theLastMEPDFWeight = 0.0;
theProjectors.clear();
theProjector = StdXCombPtr();
theKinematicsGenerated = false;
checkedCuts = false;
passedCuts = false;
+ theCutWeight = 1.0;
matrixElement()->flushCaches();
}
CrossSection StandardXComb::dSigDR(const double * r) {
matrixElement()->flushCaches();
matrixElement()->setXComb(this);
if ( !matrixElement()->apply() ) {
subProcess(SubProPtr());
lastCrossSection(ZERO);
return ZERO;
}
meMomenta().resize(mePartonData().size());
if ( !matrixElement()->generateKinematics(r) ) {
subProcess(SubProPtr());
lastCrossSection(ZERO);
return ZERO;
}
setIncomingPartons();
lastScale(matrixElement()->scale());
lastAlphaS(matrixElement()->alphaS());
lastAlphaEM(matrixElement()->alphaEM());
if ( (!willPassCuts() &&
!matrixElement()->headCuts() &&
!matrixElement()->ignoreCuts()) ||
!matrixElement()->apply() ) {
subProcess(SubProPtr());
lastCrossSection(ZERO);
return ZERO;
}
lastPDFWeight(head()->lastPDFWeight());
matrixElement()->setKinematics();
+
CrossSection xsec = matrixElement()->dSigHatDR() * lastPDFWeight();
+ xsec *= cutWeight();
+
subProcess(SubProPtr());
lastCrossSection(xsec);
return xsec;
}
CrossSection StandardXComb::
dSigDR(const pair<double,double> ll, int nr, const double * r) {
matrixElement()->flushCaches();
if ( matrixElement()->keepRandomNumbers() ) {
lastRandomNumbers().resize(nDim());
copy(r,r+nDim(),lastRandomNumbers().begin());
}
pExtractor()->select(this);
setPartonBinInfo();
lastP1P2(ll);
lastS(sqr(maxEnergy())/exp(lastP1() + lastP2()));
meMomenta().resize(mePartonData().size());
matrixElement()->setXComb(this);
PPair partons;
if ( !matrixElement()->haveX1X2() ) {
if ( !pExtractor()->generateL(partonBinInstances(),
r, r + nr - partonDims.second) ) {
lastCrossSection(ZERO);
return ZERO;
}
partons = make_pair(partonBinInstances().first->parton(),
partonBinInstances().second->parton());
lastSHat(lastS()/exp(partonBinInstances().first->l() +
partonBinInstances().second->l()));
meMomenta()[0] = partons.first->momentum();
meMomenta()[1] = partons.second->momentum();
} else {
if ( !matrixElement()->generateKinematics(r + partonDims.first) ) {
lastCrossSection(ZERO);
return ZERO;
}
lastSHat((meMomenta()[0]+meMomenta()[1]).m2());
matrixElement()->setKinematics();
lastScale(matrixElement()->scale());
partons.first = mePartonData()[0]->produceParticle(meMomenta()[0]);
partons.second = mePartonData()[1]->produceParticle(meMomenta()[1]);
Direction<0> dir(true);
partonBinInstances().first =
new_ptr(PartonBinInstance(lastParticles().first,partons.first,
partonBins().first,lastScale()));
dir.reverse();
partonBinInstances().second =
new_ptr(PartonBinInstance(lastParticles().second,partons.second,
partonBins().second,lastScale()));
}
lastPartons(partons);
if ( lastSHat() < cuts()->sHatMin() ) {
lastCrossSection(ZERO);
return ZERO;
}
lastY(0.5*(partonBinInstances().second->l() -
partonBinInstances().first->l()));
if ( !cuts()->initSubProcess(lastSHat(), lastY(), mirror()) ) {
lastCrossSection(ZERO);
return ZERO;
}
if ( mirror() ) swap(meMomenta()[0], meMomenta()[1]);
if ( matrixElement()->wantCMS() &&
!matrixElement()->haveX1X2() )
SimplePhaseSpace::CMS(meMomenta()[0], meMomenta()[1], lastSHat());
Energy summ = ZERO;
if ( meMomenta().size() == 3 ) {
if ( !matrixElement()->haveX1X2() )
meMomenta()[2] = Lorentz5Momentum(sqrt(lastSHat()));
} else {
for ( int i = 2, N = meMomenta().size(); i < N; ++i ) {
if ( !matrixElement()->haveX1X2() )
meMomenta()[i] = Lorentz5Momentum(mePartonData()[i]->mass());
summ += mePartonData()[i]->massMin();
}
if ( sqr(summ) >= lastSHat() ) {
lastCrossSection(ZERO);
return ZERO;
}
}
matrixElement()->setXComb(this);
if ( !matrixElement()->haveX1X2() )
lastScale(max(lastSHat()/4.0, cuts()->scaleMin()));
lastSHat(pExtractor()->generateSHat(lastS(), partonBinInstances(),
r, r + nr - partonDims.second,
matrixElement()->haveX1X2()));
if ( !cuts()->sHat(lastSHat()) ) {
lastCrossSection(ZERO);
return ZERO;
}
r += partonDims.first;
lastX1X2(make_pair(lastPartons().first->momentum().plus()/
lastParticles().first->momentum().plus(),
lastPartons().second->momentum().minus()/
lastParticles().second->momentum().minus()));
if ( !cuts()->x1(lastX1()) || !cuts()->x2(lastX2()) ) {
lastCrossSection(ZERO);
return ZERO;
}
lastY((lastPartons().first->momentum() +
lastPartons().second->momentum()).rapidity());
if ( !cuts()->yHat(lastY()) ) {
lastCrossSection(ZERO);
return ZERO;
}
+
if ( !cuts()->initSubProcess(lastSHat(), lastY(), mirror()) ) {
lastCrossSection(ZERO);
return ZERO;
}
meMomenta()[0] = lastPartons().first->momentum();
meMomenta()[1] = lastPartons().second->momentum();
if ( mirror() ) swap(meMomenta()[0], meMomenta()[1]);
if ( matrixElement()->wantCMS() &&
!matrixElement()->haveX1X2() )
SimplePhaseSpace::CMS(meMomenta()[0], meMomenta()[1], lastSHat());
if ( meMomenta().size() == 3 ) {
if ( !matrixElement()->haveX1X2() )
meMomenta()[2] = Lorentz5Momentum(sqrt(lastSHat()));
} else {
if ( sqr(summ) >= lastSHat() ) {
lastCrossSection(ZERO);
return ZERO;
}
}
matrixElement()->setXComb(this);
if ( !matrixElement()->haveX1X2() ) {
if ( !matrixElement()->generateKinematics(r) ) {
lastCrossSection(ZERO);
return ZERO;
}
}
+
lastScale(matrixElement()->scale());
if ( !cuts()->scale(lastScale()) ) {
lastCrossSection(ZERO);
return ZERO;
}
+ // get information on cuts; we don't take this into account here for
+ // reasons of backward compatibility but this will change eventually
+ willPassCuts();
+
pair<bool,bool> evalPDFS =
make_pair(matrixElement()->havePDFWeight1(),
matrixElement()->havePDFWeight2());
if ( mirror() )
swap(evalPDFS.first,evalPDFS.second);
lastPDFWeight(pExtractor()->fullFn(partonBinInstances(), lastScale(),
evalPDFS));
if ( lastPDFWeight() == 0.0 ) {
lastCrossSection(ZERO);
return ZERO;
}
matrixElement()->setKinematics();
CrossSection xsec = matrixElement()->dSigHatDR() * lastPDFWeight();
if ( xsec == ZERO ) {
lastCrossSection(ZERO);
return ZERO;
}
+ xsec *= cutWeight();
+
lastAlphaS (matrixElement()->orderInAlphaS () >0 ?
matrixElement()->alphaS() : -1.);
lastAlphaEM(matrixElement()->orderInAlphaEW() >0 ?
matrixElement()->alphaEM() : -1.);
matrixElement()->fillProjectors();
if ( !projectors().empty() ) {
lastProjector(projectors().select(UseRandom::rnd()));
}
subProcess(SubProPtr());
if ( CKKWHandler() && matrixElement()->maxMultCKKW() > 0 &&
matrixElement()->maxMultCKKW() > matrixElement()->minMultCKKW() ) {
newSubProcess();
CKKWHandler()->setXComb(this);
xsec *= CKKWHandler()->reweightCKKW(matrixElement()->minMultCKKW(),
matrixElement()->maxMultCKKW());
}
if ( matrixElement()->reweighted() ) {
newSubProcess();
xsec *= matrixElement()->reWeight() * matrixElement()->preWeight();
}
lastCrossSection(xsec);
return xsec;
}
void StandardXComb::newSubProcess(bool group) {
if ( subProcess() ) return;
if ( head() ) {
// first get the meMomenta in their CMS, as this may
// not be the case
Boost cm = (meMomenta()[0] + meMomenta()[1]).findBoostToCM();
if ( cm.mag2() > Constants::epsilon ) {
for ( vector<Lorentz5Momentum>::iterator m = meMomenta().begin();
m != meMomenta().end(); ++m ) {
*m = m->boost(cm);
}
}
}
if ( !lastProjector() ) {
if ( !group )
subProcess(new_ptr(SubProcess(lastPartons(), tCollPtr(), matrixElement())));
else
subProcess(new_ptr(SubProcessGroup(lastPartons(), tCollPtr(), matrixElement())));
lastDiagramIndex(matrixElement()->diagram(diagrams()));
const ColourLines & cl = matrixElement()->selectColourGeometry(lastDiagram());
Lorentz5Momentum p1 = lastPartons().first->momentum();
Lorentz5Momentum p2 = lastPartons().second->momentum();
tPPair inc = lastPartons();
if ( mirror() ) swap(inc.first, inc.second);
if ( matrixElement()->wantCMS() &&
!matrixElement()->haveX1X2() ) {
LorentzRotation r = Utilities::boostToCM(inc);
lastDiagram()->construct(subProcess(), *this, cl);
subProcess()->transform(r.inverse());
lastPartons().first->set5Momentum(p1);
lastPartons().second->set5Momentum(p2);
} else {
lastDiagram()->construct(subProcess(), *this, cl);
}
lastPartons().first ->scale(partonBinInstances().first ->scale());
lastPartons().second->scale(partonBinInstances().second->scale());
for ( int i = 0, N = subProcess()->outgoing().size(); i < N; ++i )
subProcess()->outgoing()[i]->scale(lastScale());
// construct the spin information for the interaction
matrixElement()->constructVertex(subProcess());
// set veto scales
matrixElement()->setVetoScales(subProcess());
} else {
lastProjector()->newSubProcess();
subProcess(lastProjector()->subProcess());
lastPartons(lastProjector()->lastPartons());
lastSHat((lastPartons().first->momentum() +
lastPartons().second->momentum()).m2());
lastX1X2(make_pair(lastPartons().first->momentum().plus()/
lastParticles().first->momentum().plus(),
lastPartons().second->momentum().minus()/
lastParticles().second->momentum().minus()));
lastY(log(lastX1()/lastX2())*0.5);
partonBinInstances().first->parton(lastPartons().first);
partonBinInstances().second->parton(lastPartons().second);
if ( !matrixElement()->keepRandomNumbers() )
throw Exception() << "Matrix element needs to request random number storage "
<< "for creating projected subprocesses."
<< Exception::runerror;
const double * r = &lastRandomNumbers()[0];
pExtractor()->generateSHat(lastS(), partonBinInstances(),
r, r + nDim() - partonDims.second,true);
pExtractor()->updatePartonBinInstances(partonBinInstances());
}
}
tSubProPtr StandardXComb::construct() {
matrixElement()->setXComb(this);
if ( !head() ) {
if ( !cuts()->initSubProcess(lastSHat(), lastY()) ) throw Veto();
} else {
cuts()->initSubProcess(lastSHat(), lastY());
}
-
if ( head() )
if ( !matrixElement()->apply() )
return tSubProPtr();
setPartonBinInfo();
matrixElement()->setKinematics();
newSubProcess();
TmpTransform<tSubProPtr>
tmp(subProcess(), Utilities::getBoostToCM(subProcess()->incoming()));
if ( !cuts()->passCuts(*subProcess()) ) throw Veto();
if ( head() ) {
subProcess()->head(head()->subProcess());
subProcess()->groupWeight(lastCrossSection()/head()->lastCrossSection());
}
return subProcess();
}
void StandardXComb::Init() {}
void StandardXComb::persistentOutput(PersistentOStream & os) const {
os << theSubProcessHandler << theME << theStats
<< theDiagrams << isMirror << theNDim << partonDims
<< theLastDiagramIndex << theMEInfo << theLastRandomNumbers << theMEPartonData
<< theLastPDFWeight << ounit(theLastCrossSection,nanobarn) << theLastJacobian
<< theLastME2 << ounit(theLastMECrossSection,nanobarn) << theLastMEPDFWeight
<< theHead << theProjectors << theProjector << theKinematicsGenerated
- << checkedCuts << passedCuts;
+ << checkedCuts << passedCuts << theCutWeight;
}
void StandardXComb::persistentInput(PersistentIStream & is, int) {
is >> theSubProcessHandler >> theME >> theStats
>> theDiagrams >> isMirror >> theNDim >> partonDims
>> theLastDiagramIndex >> theMEInfo >> theLastRandomNumbers >> theMEPartonData
>> theLastPDFWeight >> iunit(theLastCrossSection,nanobarn) >> theLastJacobian
>> theLastME2 >> iunit(theLastMECrossSection,nanobarn) >> theLastMEPDFWeight
>> theHead >> theProjectors >> theProjector >> theKinematicsGenerated
- >> checkedCuts >> passedCuts;
+ >> checkedCuts >> passedCuts >> theCutWeight;
}
ClassDescription<StandardXComb> StandardXComb::initStandardXComb;
diff --git a/Handlers/StandardXComb.h b/Handlers/StandardXComb.h
--- a/Handlers/StandardXComb.h
+++ b/Handlers/StandardXComb.h
@@ -1,671 +1,681 @@
// -*- C++ -*-
//
// StandardXComb.h is a part of ThePEG - Toolkit for HEP Event Generation
// Copyright (C) 1999-2011 Leif Lonnblad
// Copyright (C) 2009-2011 Simon Platzer
//
// ThePEG is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef ThePEG_StandardXComb_H
#define ThePEG_StandardXComb_H
// This is the declaration of the StandardXComb class.
#include "ThePEG/Config/ThePEG.h"
#include "SubProcessHandler.fh"
#include "ThePEG/PDF/PartonExtractor.fh"
#include "ThePEG/PDF/PartonBin.h"
#include "ThePEG/PDF/PartonBinInstance.h"
#include "ThePEG/Utilities/VSelector.h"
#include "ThePEG/Utilities/ClassDescription.h"
#include "ThePEG/Utilities/Maths.h"
#include "ThePEG/Utilities/XSecStat.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/MatrixElement/MEBase.h"
#include "ThePEG/Handlers/XComb.h"
#include "ThePEG/Handlers/StandardEventHandler.h"
#include "ThePEG/Handlers/SubProcessHandler.fh"
#include "StandardXComb.fh"
namespace ThePEG {
/**
* The StandardXComb class inherits from the more general XComb class
* which stores all information about the generation of a hard
* sub-proces for a given pair of incoming particles, a pair of
* extracted partons, etc. This class stores more information related
* to thestandard process generation scheme in ThePEG, such as the
* PartonExtractor and MEBase object used. It also does some of the
* administration of the process generation.
*
* The main function is dSigDR() which returns the differential cross
* section w.r.t. a given vector of random numbers in the interval
* ]0,1[. In the initialization this is used to pre-sample the phase
* space. In the generation phase it is used to give the cross section
* for a phase space point, and if this StandardXComb is chosen the
* construct() function is called to generate the actual sub-process.
*
* @see ParonExtractor
* @see MEBase
* @see Cuts
* @see StdXCombGroup
*/
class StandardXComb: public XComb {
public:
/** A vector of DiagramBase objects. */
typedef MEBase::DiagramVector DiagramVector;
/** A vector of indices. */
typedef MEBase::DiagramIndex DiagramIndex;
/** MEBase needs to be a friend. */
friend class MEBase;
public:
/** @name Standard constructors and destructors. */
//@{
/**
* Standard constructor.
*/
StandardXComb(Energy newMaxEnergy, const cPDPair & inc,
tEHPtr newEventHandler,tSubHdlPtr newSubProcessHandler,
tPExtrPtr newExtractor, tCascHdlPtr newCKKW,
const PBPair & newPartonBins, tCutsPtr newCuts, tMEPtr newME,
const DiagramVector & newDiagrams, bool mir,
tStdXCombPtr newHead = tStdXCombPtr());
/**
* Constructor given a head xcomb.
*/
StandardXComb(tStdXCombPtr newHead,
const PBPair & newPartonBins, tMEPtr newME,
const DiagramVector & newDiagrams);
/**
* Default constructor.
*/
StandardXComb();
/**
* Destructor.
*/
virtual ~StandardXComb();
/**
* Constructor used by MEBase to create a temporary object to store info.
*/
StandardXComb(tMEPtr me, const tPVector & parts, DiagramIndex i);
//@}
/** @name Utilities for incoming partons. */
//@{
/**
* Properly setup the PartonBinInstance objects provided a sub
* process has been constructed using this XComb.
*/
void recreatePartonBinInstances(Energy2 scale);
/**
* Fill the variables needed to generate remnants; momenta will be
* used from the partons set in this xcomb, but random numbers need
* to be provided to (re)generate variables not fixed by the
* incoming partons.
*/
void refillPartonBinInstances(const double* r);
/**
* Setup information on incoming partons depending
* on the information previously supplied through the
* choice of diagram and incoming momenta in the first
* two entries of meMomenta(). Partons are not actually
* extracted from the incoming particles, though a subprocess
* detached from the current Event may be created.
*/
void setIncomingPartons(tStdXCombPtr labHead = tStdXCombPtr());
/**
* Fill phase space information as far as possible
*/
void fill(const PPair& newParticles,
const PPair& newPartons,
const vector<Lorentz5Momentum>& newMEMomenta,
const DVector& newLastRandomNumbers = DVector());
//@}
/** @name Access the assigned objects used in the generation. */
//@{
/**
* Return a pointer to the corresponding sub-process handler. May be
* null if the standard process generation in ThePEG was not used.
*/
tcSubHdlPtr subProcessHandler() const { return theSubProcessHandler; }
/**
* The matrix element to be used.
*/
tMEPtr matrixElement() const { return theME; }
/**
* Return a pointer to the head XComb this XComb
* depends on. May return NULL, if this is not a
* member of a XComb group.
*/
tStdXCombPtr head() const { return theHead; }
/**
* Set the head XComb pointer.
*/
void head(tStdXCombPtr headXC) { theHead = headXC; }
/**
* Return a selector object of xcombs to choose subprocesses
* different than the one currently integrated.
*/
Selector<tStdXCombPtr>& projectors() { return theProjectors; }
/**
* Return a selector object of xcombs to choose subprocesses
* different than the one currently integrated.
*/
const Selector<tStdXCombPtr>& projectors() const { return theProjectors; }
/**
* Return a pointer to a projector xcomb which will generate a subprocess
* different from the one just integrated.
*/
tStdXCombPtr lastProjector() const { return theProjector; }
/**
* Set a pointer to a projector xcomb which will generate a subprocess
* different from the one just integrated.
*/
void lastProjector(tStdXCombPtr pxc) { theProjector = pxc; }
//@}
/** @name Main functions used for the generation. */
//@{
/**
* Try to determine if this subprocess is at all possible.
*/
virtual bool checkInit();
/**
* The number of dimensions of the phase space used to generate this
* process.
*/
int nDim() const { return theNDim; }
/**
* Return the parton extraction dimensions
*/
const pair<int,int>& partonDimensions() const { return partonDims; }
/**
* Return true, if the current configuration will pass the cuts
*/
bool willPassCuts();
/**
+ * Return the cut weight encountered from fuzzy cuts
+ */
+ double cutWeight() const { return theCutWeight; }
+
+ /**
* Reset all saved data about last generated phasespace point;
*/
virtual void clean();
/**
* Return true, if kinematics have already been generated
*/
bool kinematicsGenerated() const { return theKinematicsGenerated; }
/**
* Indicate that kinematics have been generated
*/
void didGenerateKinematics() { theKinematicsGenerated = true; }
/**
* Generate a phase space point from a vector \a r of \a nr numbers
* in the interval ]0,1[ and return the corresponding differential
* cross section.
*/
virtual CrossSection dSigDR(const pair<double,double> ll, int nr, const double * r);
/**
* If this XComb has a head XComb, return the cross section
* differential in the variables previously supplied. The PDF weight
* is taken from the lastPDFWeight supplied by the head XComb
* object.
*/
CrossSection dSigDR(const double * r);
/**
* Return the PDF weight used in the last call to dSigDR
*/
double lastPDFWeight() const { return theLastPDFWeight; }
/**
* Return the cross section calculated in the last call to dSigDR
*/
CrossSection lastCrossSection() const { return theLastCrossSection; }
/**
* Construct a sub-process object from the information available.
*/
virtual tSubProPtr construct();
//@}
/** @name Functions used for collecting statistics. */
//@{
/**
* The statistics object for this XComb.
*/
virtual const XSecStat & stats() const { return theStats; }
/**
* Select the current event. It will later be rejected with a
* probability given by \a weight.
*/
virtual void select(double weight) { theStats.select(weight); }
/**
* Accept the current event assuming it was previously selcted.
*/
virtual void accept() { theStats.accept(); }
/**
* Reweight a selected and accepted event.
*/
void reweight(double oldWeight, double newWeight) {
theStats.reweight(oldWeight,newWeight);
}
/**
* Reject the current event assuming it was previously accepted. If
* weighted events are produced, the \a weight should be the same as
* the previous call to select(double).
*/
virtual void reject(double weight = 1.0) { theStats.reject(weight); }
/**
* Reset statistics.
*/
virtual void reset() { theStats.reset(); }
//@}
/** @name Access information used by the MEBase object. */
//@{
/**
* The diagrams used by the matrix element.
*/
const DiagramVector & diagrams() const { return theDiagrams; }
/**
* True if the TreeDiagram's for this matrix element should in fact
* be mirrored before used to create an actual sub-rocess.
*/
bool mirror() const { return isMirror; }
/**
* Return the momenta of the partons to be used by the matrix
* element object, in the order specified by the TreeDiagram objects
* given by the matrix element.
*/
const vector<Lorentz5Momentum> & meMomenta() const { return theMEMomenta; }
/**
* Return the last selected diagram.
*/
tcDiagPtr lastDiagram() const { return diagrams()[lastDiagramIndex()]; }
/**
* Return the parton types to be used by the matrix element object,
* in the order specified by the TreeDiagram objects given by the
* matrix element.
*/
const cPDVector & mePartonData() const { return theMEPartonData; }
/**
* Return the index of the last selected diagram.
*/
DiagramIndex lastDiagramIndex() const { return theLastDiagramIndex; }
/**
* Get information saved by the matrix element in the calculation of
* the cross section to be used later when selecting diagrams and
* colour flow.
*/
const DVector & meInfo() const { return theMEInfo; }
/**
* Set information saved by the matrix element in the calculation of
* the cross section to be used later when selecting diagrams and
* colour flow.
*/
void meInfo(const DVector & info) { theMEInfo = info; }
/**
* Return the random numbers used to generate the
* last phase space point, if the matrix element
* requested so.
*/
const DVector& lastRandomNumbers() const { return theLastRandomNumbers; }
/**
* Get the last jacobian obtained when generating the kinematics
* for the call to dSigHatDR.
*/
double jacobian() const { return theLastJacobian; }
/**
* Return the matrix element squared as calculated
* for the last phase space point. This may optionally
* be used by a matrix element for caching.
*/
double lastME2() const { return theLastME2; }
/**
* Return the partonic cross section as calculated
* for the last phase space point. This may optionally
* be used by a matrix element for caching.
*/
CrossSection lastMECrossSection() const { return theLastMECrossSection; }
/**
* Return the PDF weight as calculated
* for the last phase space point, if the matrix
* element does supply PDF weights. This may optionally
* be used by a matrix element for caching.
*/
double lastMEPDFWeight() const { return theLastMEPDFWeight; }
//@}
protected:
/**
* Construct the corresponding SubProcess object if it hasn't been
* done before.
*/
virtual void newSubProcess(bool group = false);
/**
* Return the momenta of the partons to be used by the matrix
* element object, in the order specified by the TreeDiagram objects
* given by the matrix element.
*/
vector<Lorentz5Momentum> & meMomenta() { return theMEMomenta; }
/**
* Access the random numbers used to generate the
* last phase space point, if the matrix element
* requested so.
*/
DVector& lastRandomNumbers() { return theLastRandomNumbers; }
/**
* Return the parton types to be used by the matrix element object,
* in the order specified by the TreeDiagram objects given by the
* matrix element.
*/
cPDVector & mePartonData() { return theMEPartonData; }
/**
* Set the last selected diagram.
*/
void lastDiagramIndex(DiagramIndex i) { theLastDiagramIndex = i; }
/**
* Set the PDF weight used in the last call to dSigDR
*/
void lastPDFWeight(double w) { theLastPDFWeight = w; }
/**
* Set the cross section calculated in the last call to dSigDR
*/
void lastCrossSection(CrossSection s) { theLastCrossSection = s; }
/**
* Set the last jacobian obtained when generating the kinematics for
* the call to dSigHatDR.
*/
void jacobian(double j) { theLastJacobian = j; }
/**
* Set the matrix element squared as calculated
* for the last phase space point. This may optionally
* be used by a matrix element for caching.
*/
void lastME2(double v) { theLastME2 = v; }
/**
* Set the partonic cross section as calculated
* for the last phase space point. This may optionally
* be used by a matrix element for caching.
*/
void lastMECrossSection(CrossSection v) { theLastMECrossSection = v; }
/**
* Set the PDF weight as calculated
* for the last phase space point, if the matrix
* element does supply PDF weights. This may optionally
* be used by a matrix element for caching.
*/
void lastMEPDFWeight(double v) { theLastMEPDFWeight = v; }
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);
//@}
/**
* Standard Init function used to initialize the interface.
*/
static void Init();
private:
/**
* The corresponding sub-process handler
*/
tSubHdlPtr theSubProcessHandler;
/**
* The matrix element to be used.
*/
tMEPtr theME;
/**
* Statistics gathering for this XComb.
*/
XSecStat theStats;
/**
* The diagrams used by the matrix element.
*/
DiagramVector theDiagrams;
/**
* True if the TreeDiagram's for this matrix element should in fact
* be mirrored before used to create an actual sub-rocess.
*/
bool isMirror;
/**
* The number of dimensions of the phase space used to generate this
* process.
*/
int theNDim;
protected:
/**
* The number of dimensions of the phase space used for each of the
* incoming partons.
*/
pair<int,int> partonDims;
private:
/**
* True, if kinematics have already been generated
*/
bool theKinematicsGenerated;
/**
* The momenta of the partons to be used by the matrix element
* object, in the order specified by the TreeDiagram objects given
* by the matrix element.
*/
vector<Lorentz5Momentum> theMEMomenta;
/**
* The parton types to be used by the matrix element object, in the
* order specified by the TreeDiagram objects given by the matrix
* element.
*/
cPDVector theMEPartonData;
/**
* The last selected tree diagram.
*/
DiagramIndex theLastDiagramIndex;
/**
* Information saved by the matrix element in the calculation of the
* cross section to be used later when selecting diagrams and colour
* flow.
*/
DVector theMEInfo;
/**
* The random numbers used to generate the
* last phase space point, if the matrix element
* requested so.
*/
DVector theLastRandomNumbers;
/**
* The PDF weight used in the last call to dSigDR
*/
double theLastPDFWeight;
/**
* The cross section calculated in the last call to dSigDR
*/
CrossSection theLastCrossSection;
/**
* Save the last jacobian obtained when generating the kinematics for
* the call to dSigHatDR.
*/
double theLastJacobian;
/**
* The matrix element squared as calculated
* for the last phase space point. This may optionally
* be used by a matrix element for caching.
*/
double theLastME2;
/**
* The partonic cross section as calculated
* for the last phase space point. This may optionally
* be used by a matrix element for caching.
*/
CrossSection theLastMECrossSection;
/**
* The PDF weight as calculated
* for the last phase space point, if the matrix
* element does supply PDF weights. This may optionally
* be used by a matrix element for caching.
*/
double theLastMEPDFWeight;
/**
* A pointer to the head XComb this XComb
* depends on. May return NULL, if this is not a
* member of a XComb group.
*/
tStdXCombPtr theHead;
/**
* A selector object of xcombs to choose subprocesses
* different than the one currently integrated.
*/
Selector<tStdXCombPtr> theProjectors;
/**
* A pointer to a projector xcomb which will generate a subprocess
* different from the one just integrated.
*/
tStdXCombPtr theProjector;
/**
* True, if cuts have already been checked
*/
bool checkedCuts;
/**
* The result of the last call to willPassCuts
*/
bool passedCuts;
+ /**
+ * The cut weight encountered from fuzzy cuts
+ */
+ double theCutWeight;
+
private:
/**
* Describe a concrete class with persistent data.
*/
static ClassDescription<StandardXComb> initStandardXComb;
/**
* Private and non-existent assignment operator.
*/
StandardXComb & operator=(const StandardXComb &);
};
/** @cond TRAITSPECIALIZATIONS */
/**
* This template specialization informs ThePEG about the base class of
* StandardXComb.
*/
template <>
struct BaseClassTrait<StandardXComb,1>: public ClassTraitsType {
/** Typedef of the base class of StandardXComb. */
typedef XComb NthBase;
};
/**
* This template specialization informs ThePEG about the name of the
* StandardXComb class.
*/
template <>
struct ClassTraits<StandardXComb>:
public ClassTraitsBase<StandardXComb> {
/** Return the class name. */
static string className() { return "ThePEG::StandardXComb"; }
};
/** @endcond */
}
#endif /* ThePEG_StandardXComb_H */
diff --git a/Handlers/StdXCombGroup.cc b/Handlers/StdXCombGroup.cc
--- a/Handlers/StdXCombGroup.cc
+++ b/Handlers/StdXCombGroup.cc
@@ -1,391 +1,400 @@
// -*- C++ -*-
//
// StdXCombGroup.cc is a part of ThePEG - Toolkit for HEP Event Generation
// Copyright (C) 1999-2007 Leif Lonnblad
// Copyright (C) 2009-2010 Simon Platzer
//
// ThePEG 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 StdXCombGroup class.
//
#include "StdXCombGroup.h"
#include "ThePEG/MatrixElement/MEGroup.h"
#include "ThePEG/Handlers/StandardEventHandler.h"
#include "ThePEG/Handlers/SubProcessHandler.h"
#include "ThePEG/Cuts/Cuts.h"
#include "ThePEG/PDF/PartonExtractor.h"
#include "ThePEG/Utilities/Debug.h"
#include "ThePEG/Utilities/Maths.h"
#include "ThePEG/PDT/ParticleData.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Utilities/SimplePhaseSpace.h"
#include "ThePEG/Utilities/UtilityBase.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/EventRecord/SubProcessGroup.h"
#include "ThePEG/Vectors/LorentzRotation.h"
#include "ThePEG/MatrixElement/MEBase.h"
#include "ThePEG/MatrixElement/ColourLines.h"
#include "ThePEG/Handlers/LuminosityFunction.h"
#include "ThePEG/Handlers/CascadeHandler.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/EventRecord/TmpTransform.h"
using namespace ThePEG;
StdXCombGroup::StdXCombGroup(Energy newMaxEnergy, const cPDPair & inc,
tEHPtr newEventHandler,tSubHdlPtr newSubProcessHandler,
tPExtrPtr newExtractor, tCascHdlPtr newCKKW,
const PBPair & newPartonBins, tCutsPtr newCuts, tMEGroupPtr newME,
const DiagramVector & newDiagrams, bool mir, tStdXCombPtr newHead)
: StandardXComb(newMaxEnergy,inc,newEventHandler,newSubProcessHandler,
newExtractor, newCKKW, newPartonBins, newCuts,
newME, newDiagrams, mir, newHead),
theMEGroup(newME), theDependent(), theLastHeadCrossSection(ZERO) {}
StdXCombGroup::StdXCombGroup()
: StandardXComb(), theDependent() {}
void StdXCombGroup::build(const PartonPairVec& allPBins) {
for ( MEVector::const_iterator me = theMEGroup->dependent().begin();
me != theMEGroup->dependent().end(); ++me ) {
vector<StdXCombPtr> dep =
theMEGroup->makeDependentXCombs(this,diagrams().front()->partons(),*me,allPBins);
copy(dep.begin(),dep.end(),back_inserter(theDependent));
}
}
StdXCombGroup::~StdXCombGroup() { }
void StdXCombGroup::clean() {
StandardXComb::clean();
theLastHeadCrossSection = ZERO;
for ( vector<StdXCombPtr>::const_iterator dep = theDependent.begin();
dep != theDependent.end(); ++dep )
(**dep).clean();
}
CrossSection StdXCombGroup::dSigDR(const pair<double,double> ll, int nr, const double * r) {
matrixElement()->flushCaches();
if ( matrixElement()->keepRandomNumbers() ) {
lastRandomNumbers().resize(nDim());
copy(r,r+nDim(),lastRandomNumbers().begin());
}
pExtractor()->select(this);
setPartonBinInfo();
lastP1P2(ll);
lastS(sqr(maxEnergy())/exp(lastP1() + lastP2()));
meMomenta().resize(mePartonData().size());
matrixElement()->setXComb(this);
PPair partons;
if ( !matrixElement()->haveX1X2() ) {
if ( !pExtractor()->generateL(partonBinInstances(),
r, r + nr - partonDims.second) ) {
lastCrossSection(ZERO);
return ZERO;
}
partons = make_pair(partonBinInstances().first->parton(),
partonBinInstances().second->parton());
lastSHat(lastS()/exp(partonBinInstances().first->l() +
partonBinInstances().second->l()));
meMomenta()[0] = partons.first->momentum();
meMomenta()[1] = partons.second->momentum();
} else {
if ( !matrixElement()->generateKinematics(r + partonDims.first) ) {
lastCrossSection(ZERO);
return ZERO;
}
lastSHat((meMomenta()[0]+meMomenta()[1]).m2());
matrixElement()->setKinematics();
lastScale(matrixElement()->scale());
partons.first = mePartonData()[0]->produceParticle(meMomenta()[0]);
partons.second = mePartonData()[1]->produceParticle(meMomenta()[1]);
Direction<0> dir(true);
partonBinInstances().first =
new_ptr(PartonBinInstance(lastParticles().first,partons.first,
partonBins().first,lastScale()));
dir.reverse();
partonBinInstances().second =
new_ptr(PartonBinInstance(lastParticles().second,partons.second,
partonBins().second,lastScale()));
}
lastPartons(partons);
if ( lastSHat() < cuts()->sHatMin() ) {
lastCrossSection(ZERO);
return ZERO;
}
lastY(0.5*(partonBinInstances().second->l() -
partonBinInstances().first->l()));
if ( !cuts()->initSubProcess(lastSHat(), lastY(), mirror()) ) {
lastCrossSection(ZERO);
return ZERO;
}
if ( mirror() ) swap(meMomenta()[0], meMomenta()[1]);
if ( matrixElement()->wantCMS() &&
!matrixElement()->haveX1X2() )
SimplePhaseSpace::CMS(meMomenta()[0], meMomenta()[1], lastSHat());
Energy summ = ZERO;
if ( meMomenta().size() == 3 ) {
if ( !matrixElement()->haveX1X2() )
meMomenta()[2] = Lorentz5Momentum(sqrt(lastSHat()));
} else {
for ( int i = 2, N = meMomenta().size(); i < N; ++i ) {
if ( !matrixElement()->haveX1X2() )
meMomenta()[i] = Lorentz5Momentum(mePartonData()[i]->mass());
summ += mePartonData()[i]->massMin();
}
if ( sqr(summ) >= lastSHat() ) {
lastCrossSection(ZERO);
return ZERO;
}
}
matrixElement()->setXComb(this);
if ( !matrixElement()->haveX1X2() )
lastScale(max(lastSHat()/4.0, cuts()->scaleMin()));
lastSHat(pExtractor()->generateSHat(lastS(), partonBinInstances(),
r, r + nr - partonDims.second,
matrixElement()->haveX1X2()));
if ( !cuts()->sHat(lastSHat()) ) {
lastCrossSection(ZERO);
return ZERO;
}
r += partonDims.first;
lastX1X2(make_pair(lastPartons().first->momentum().plus()/
lastParticles().first->momentum().plus(),
lastPartons().second->momentum().minus()/
lastParticles().second->momentum().minus()));
if ( !cuts()->x1(lastX1()) || !cuts()->x2(lastX2()) ) {
lastCrossSection(ZERO);
return ZERO;
}
lastY((lastPartons().first->momentum() +
lastPartons().second->momentum()).rapidity());
if ( !cuts()->yHat(lastY()) ) {
lastCrossSection(ZERO);
return ZERO;
}
if ( !cuts()->initSubProcess(lastSHat(), lastY(), mirror()) ) {
lastCrossSection(ZERO);
return ZERO;
}
meMomenta()[0] = lastPartons().first->momentum();
meMomenta()[1] = lastPartons().second->momentum();
if ( mirror() ) swap(meMomenta()[0], meMomenta()[1]);
if ( matrixElement()->wantCMS() &&
!matrixElement()->haveX1X2() )
SimplePhaseSpace::CMS(meMomenta()[0], meMomenta()[1], lastSHat());
if ( meMomenta().size() == 3 ) {
if ( !matrixElement()->haveX1X2() )
meMomenta()[2] = Lorentz5Momentum(sqrt(lastSHat()));
} else {
if ( sqr(summ) >= lastSHat() ) {
lastCrossSection(ZERO);
return ZERO;
}
}
matrixElement()->setXComb(this);
if ( !matrixElement()->haveX1X2() ) {
if ( !matrixElement()->generateKinematics(r) ) {
lastCrossSection(ZERO);
return ZERO;
}
}
lastScale(matrixElement()->scale());
if ( !cuts()->scale(lastScale()) ) {
lastCrossSection(ZERO);
return ZERO;
}
pair<bool,bool> evalPDFS =
make_pair(matrixElement()->havePDFWeight1(),
matrixElement()->havePDFWeight2());
if ( mirror() )
swap(evalPDFS.first,evalPDFS.second);
lastPDFWeight(pExtractor()->fullFn(partonBinInstances(), lastScale(),
evalPDFS));
if ( lastPDFWeight() == 0.0 ) {
lastCrossSection(ZERO);
return ZERO;
}
matrixElement()->setKinematics();
CrossSection xsec = matrixElement()->dSigHatDR() * lastPDFWeight();
bool noHeadPass = !willPassCuts() || xsec == ZERO;
if ( noHeadPass ) {
xsec = ZERO;
lastCrossSection(ZERO);
}
+ xsec *= cutWeight();
+
lastAlphaS(matrixElement()->alphaS());
lastAlphaEM(matrixElement()->alphaEM());
lastHeadCrossSection(xsec);
CrossSection depxsec = ZERO;
vector<tStdXCombPtr> activeXCombs;
if ( !theMEGroup->mcSumDependent() ) {
for ( vector<StdXCombPtr>::const_iterator dep = theDependent.begin();
dep != theDependent.end(); ++dep ) {
if ( noHeadPass && (**dep).matrixElement()->headCuts() )
continue;
depxsec += (**dep).dSigDR(r + theMEGroup->dependentOffset((**dep).matrixElement()));
if ( theMEGroup->groupReweighted() )
activeXCombs.push_back(*dep);
}
} else {
if ( theMEGroup->lastDependentXComb() ) {
tStdXCombPtr dxc = theMEGroup->lastDependentXComb();
if ( !(noHeadPass && dxc->matrixElement()->headCuts()) )
depxsec = theDependent.size()*
dxc->dSigDR(r + theMEGroup->dependentOffset(dxc->matrixElement()));
if ( theMEGroup->groupReweighted() )
activeXCombs.push_back(dxc);
}
}
- if ( xsec != ZERO ) {
- double rw = 1.0 + depxsec/xsec;
- xsec *= rw;
- } else {
+ if ( xsec != ZERO &&
+ depxsec != ZERO ) {
+ if ( abs(xsec) < abs(depxsec) ) {
+ volatile double rw = (1.+depxsec/xsec);
+ xsec = xsec*rw;
+ } else {
+ volatile double rw = (1.+xsec/depxsec);
+ xsec = depxsec*rw;
+ }
+ } else if ( xsec == ZERO &&
+ depxsec != ZERO ) {
xsec = depxsec;
}
lastCrossSection(xsec);
if ( xsec != ZERO )
theMEGroup->lastEventStatistics();
matrixElement()->fillProjectors();
if ( !projectors().empty() ) {
lastProjector(projectors().select(UseRandom::rnd()));
}
if ( theMEGroup->groupReweighted() && !activeXCombs.empty() ) {
xsec = theMEGroup->reweightHead(activeXCombs)*lastHeadCrossSection();
depxsec = ZERO;
for ( vector<tStdXCombPtr>::const_iterator dep = activeXCombs.begin();
dep != activeXCombs.end(); ++dep ) {
depxsec += theMEGroup->reweightDependent(*dep,activeXCombs)*(**dep).lastCrossSection();
}
if ( xsec != ZERO ) {
double rw = 1.0 + depxsec/xsec;
xsec *= rw;
} else {
xsec = depxsec;
}
}
subProcess(SubProPtr());
if ( CKKWHandler() && matrixElement()->maxMultCKKW() > 0 &&
matrixElement()->maxMultCKKW() > matrixElement()->minMultCKKW() ) {
newSubProcess(theMEGroup->subProcessGroups());
CKKWHandler()->setXComb(this);
xsec *= CKKWHandler()->reweightCKKW(matrixElement()->minMultCKKW(),
matrixElement()->maxMultCKKW());
}
if ( matrixElement()->reweighted() ) {
newSubProcess(theMEGroup->subProcessGroups());
xsec *= matrixElement()->reWeight() * matrixElement()->preWeight();
}
return xsec;
}
void StdXCombGroup::newSubProcess(bool) {
StandardXComb::newSubProcess(theMEGroup->subProcessGroups());
if ( !theMEGroup->subProcessGroups() )
return;
subProcess()->groupWeight(lastHeadCrossSection()/lastCrossSection());
Ptr<SubProcessGroup>::tptr group =
dynamic_ptr_cast<Ptr<SubProcessGroup>::tptr>(subProcess());
assert(group);
for ( vector<StdXCombPtr>::iterator dep = theDependent.begin();
dep != theDependent.end(); ++dep ) {
if ( (**dep).lastCrossSection() == ZERO )
continue;
tSubProPtr ds;
try {
ds = (**dep).construct();
} catch(Veto&) {
throw Exception() << "A veto was encountered while constructing a dependent sub process.\n"
<< "This situation should not have happened. Will veto the event."
<< Exception::eventerror;
}
if ( ds )
group->add(ds);
}
}
tSubProPtr StdXCombGroup::construct() {
matrixElement()->setXComb(this);
setPartonBinInfo();
matrixElement()->setKinematics();
newSubProcess(theMEGroup->subProcessGroups());
if ( !theMEGroup->subProcessGroups() ) {
if ( !cuts()->initSubProcess(lastSHat(), lastY()) ) throw Veto();
TmpTransform<tSubProPtr>
tmp(subProcess(), Utilities::getBoostToCM(subProcess()->incoming()));
if ( !cuts()->passCuts(*subProcess()) ) throw Veto();
}
return subProcess();
}
void StdXCombGroup::Init() {}
void StdXCombGroup::persistentOutput(PersistentOStream & os) const {
os << theDependent << theMEGroup << ounit(theLastHeadCrossSection,nanobarn);
}
void StdXCombGroup::persistentInput(PersistentIStream & is, int) {
is >> theDependent >> theMEGroup >> iunit(theLastHeadCrossSection,nanobarn);
}
ClassDescription<StdXCombGroup> StdXCombGroup::initStdXCombGroup;
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Tue, Nov 19, 4:42 PM (1 d, 9 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3805209
Default Alt Text
(141 KB)
Attached To
rTHEPEGHG thepeghg
Event Timeline
Log In to Comment