Page Menu
Home
HEPForge
Search
Configure Global Search
Log In
Files
F8725611
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
33 KB
Subscribers
None
View Options
diff --git a/MatrixElement/Matchbox/Phasespace/MatchboxPhasespace.cc b/MatrixElement/Matchbox/Phasespace/MatchboxPhasespace.cc
--- a/MatrixElement/Matchbox/Phasespace/MatchboxPhasespace.cc
+++ b/MatrixElement/Matchbox/Phasespace/MatchboxPhasespace.cc
@@ -1,145 +1,157 @@
// -*- C++ -*-
//
// MatchboxPhasespace.cc is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2012 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the MatchboxPhasespace class.
//
#include "MatchboxPhasespace.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Utilities/DescribeClass.h"
using namespace Herwig;
MatchboxPhasespace::MatchboxPhasespace() {}
MatchboxPhasespace::~MatchboxPhasespace() {}
void MatchboxPhasespace::cloneDependencies(const std::string&) {
}
void MatchboxPhasespace::dumpInfo(const string& prefix) const {
generator()->log() << prefix << fullName()
<< " [" << this << "]\n";
generator()->log() << prefix << " | XComb " << lastXCombPtr()
<< " for ";
if ( lastXCombPtr() ) {
for ( cPDVector::const_iterator p = lastXComb().mePartonData().begin();
p != lastXComb().mePartonData().end(); ++p ) {
generator()->log() << (**p).PDGName() << " ";
}
}
generator()->log() << "\n";
}
pair<double,Lorentz5Momentum>
MatchboxPhasespace::timeLikeWeight(const Tree2toNDiagram& diag,
- int branch) const {
+ int branch, double flatCut) const {
pair<int,int> children = diag.children(branch);
if ( children.first == -1 ) {
return make_pair(1.,meMomenta()[diag.externalId(branch)]);
}
pair<double,Lorentz5Momentum> res
- = timeLikeWeight(diag,children.first);
+ = timeLikeWeight(diag,children.first,flatCut);
pair<double,Lorentz5Momentum> other
- = timeLikeWeight(diag,children.second);
+ = timeLikeWeight(diag,children.second,flatCut);
res.first *= other.first;
res.second += other.second;
Energy2 mass2 = sqr(diag.allPartons()[branch]->mass());
Energy2 width2 = sqr(diag.allPartons()[branch]->width());
- res.first /=
- sqr((res.second.m2()-mass2)/lastSHat()) +
- mass2*width2/sqr(lastSHat());
+ if ( width2 == ZERO ) {
+ if ( abs((res.second.m2()-mass2)/lastSHat()) > flatCut )
+ res.first /=
+ abs((res.second.m2()-mass2)/lastSHat());
+ } else {
+ res.first /=
+ sqr((res.second.m2()-mass2)/lastSHat()) +
+ mass2*width2/sqr(lastSHat());
+ }
return res;
}
double MatchboxPhasespace::spaceLikeWeight(const Tree2toNDiagram& diag,
const Lorentz5Momentum& incoming,
- int branch) const {
+ int branch, double flatCut) const {
if ( branch == -1 )
return 1.;
pair<int,int> children = diag.children(branch);
pair<double,Lorentz5Momentum> res =
- timeLikeWeight(diag,children.second);
+ timeLikeWeight(diag,children.second,flatCut);
if ( children.first == diag.nSpace() - 1 ) {
return res.first;
}
res.second = incoming - res.second;
Energy2 mass2 = sqr(diag.allPartons()[branch]->mass());
Energy2 width2 = sqr(diag.allPartons()[branch]->width());
- res.first /=
- sqr((res.second.m2()-mass2)/lastSHat()) +
- mass2*width2/sqr(lastSHat());
+ if ( width2 == ZERO ) {
+ if ( abs((res.second.m2()-mass2)/lastSHat()) > flatCut )
+ res.first /=
+ abs((res.second.m2()-mass2)/lastSHat());
+ } else {
+ res.first /=
+ sqr((res.second.m2()-mass2)/lastSHat()) +
+ mass2*width2/sqr(lastSHat());
+ }
return
- res.first * spaceLikeWeight(diag,res.second,children.first);
+ res.first * spaceLikeWeight(diag,res.second,children.first,flatCut);
}
-void MatchboxPhasespace::fillDiagramWeights() {
+void MatchboxPhasespace::fillDiagramWeights(double flatCut) {
diagramWeights.clear();
for ( StandardXComb::DiagramVector::const_iterator d =
lastXComb().diagrams().begin(); d != lastXComb().diagrams().end(); ++d ) {
diagramWeights[(**d).id()] =
- spaceLikeWeight(dynamic_cast<const Tree2toNDiagram&>(**d),meMomenta()[0],0);
+ spaceLikeWeight(dynamic_cast<const Tree2toNDiagram&>(**d),meMomenta()[0],0,flatCut);
}
}
Selector<MEBase::DiagramIndex>
MatchboxPhasespace::selectDiagrams(const MEBase::DiagramVector& diags) const {
Selector<MEBase::DiagramIndex> ret;
for ( MEBase::DiagramIndex d = 0; d < diags.size(); ++d ) {
ret.insert(diagramWeight(dynamic_cast<const Tree2toNDiagram&>(*diags[d])),d);
}
return ret;
}
// If needed, insert default implementations of virtual function defined
// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs).
// *** 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).
DescribeAbstractNoPIOClass<MatchboxPhasespace,HandlerBase>
describeMatchboxPhasespace("Herwig::MatchboxPhasespace", "HwMatchbox.so");
void MatchboxPhasespace::Init() {
static ClassDocumentation<MatchboxPhasespace> documentation
("MatchboxPhasespace defines an abstract interface to a phase "
"space generator.");
}
diff --git a/MatrixElement/Matchbox/Phasespace/MatchboxPhasespace.h b/MatrixElement/Matchbox/Phasespace/MatchboxPhasespace.h
--- a/MatrixElement/Matchbox/Phasespace/MatchboxPhasespace.h
+++ b/MatrixElement/Matchbox/Phasespace/MatchboxPhasespace.h
@@ -1,206 +1,206 @@
// -*- C++ -*-
//
// MatchboxPhasespace.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2012 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_MatchboxPhasespace_H
#define HERWIG_MatchboxPhasespace_H
//
// This is the declaration of the MatchboxPhasespace class.
//
#include "ThePEG/Handlers/StandardXComb.h"
#include "ThePEG/Handlers/HandlerBase.h"
#include "ThePEG/MatrixElement/Tree2toNDiagram.h"
namespace Herwig {
using namespace ThePEG;
/**
* \ingroup Matchbox
* \author Simon Platzer
*
* \brief Wrap around a vector of random numbers to behave as a stream
* of those.
*/
struct StreamingRnd {
/**
* The random numbers
*/
const double* numbers;
/**
* The number of random numbers available.
*/
size_t nRnd;
/**
* Default constructor.
*/
StreamingRnd()
: numbers(0), nRnd(0) {}
/**
* Construct from random numbers.
*/
explicit StreamingRnd(const double* newNumbers,
size_t n)
: numbers(newNumbers), nRnd(n) {}
/**
* Return next random number
*/
inline double operator()() {
assert(numbers && nRnd > 0);
const double ret = numbers[0];
++numbers; --nRnd;
return ret;
}
};
/**
* \ingroup Matchbox
* \author Simon Platzer
*
* \brief MatchboxPhasespace defines an abstract interface to a phase
* space generator.
*
*/
class MatchboxPhasespace:
public HandlerBase, public LastXCombInfo<StandardXComb> {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
MatchboxPhasespace();
/**
* The destructor.
*/
virtual ~MatchboxPhasespace();
//@}
public:
/**
* Prepare a phase space generator for the given xcomb object.
*/
virtual void prepare(tStdXCombPtr, bool verbose = false) = 0;
/**
* Generate a phase space point and return its weight.
*/
virtual double generateKinematics(const double*,
vector<Lorentz5Momentum>& momenta) = 0;
/**
* Return the number of random numbers required to produce a given
* multiplicity final state.
*/
virtual int nDim(int nFinal) const = 0;
/**
* Return true, if this phasespace generator will generate incoming
* partons itself.
*/
virtual bool haveX1X2() const { return false; }
/**
* Return true, if this phase space generator expects
* the incoming partons in their center-of-mass system
*/
virtual bool wantCMS() const { return true; }
/**
* Fill a diagram selector for the last phase space point.
*/
virtual Selector<MEBase::DiagramIndex> selectDiagrams(const MEBase::DiagramVector&) const;
/**
* Return the momentum and weight appropriate to the given timelike
* branch of the diagram.
*/
pair<double,Lorentz5Momentum> timeLikeWeight(const Tree2toNDiagram& diag,
- int branch) const;
+ int branch, double flatCut) const;
/**
* Return the weight appropriate to the given spacelike branch of
* the diagram.
*/
double spaceLikeWeight(const Tree2toNDiagram& diag,
const Lorentz5Momentum& incoming,
- int branch) const;
+ int branch, double flatCut) const;
/**
* Return the weight appropriate to the given diagram.
*/
double diagramWeight(const Tree2toNDiagram& diag) const {
assert( !diagramWeights.empty() );
return diagramWeights.find(diag.id())->second;
}
/**
* Fill the diagram weights.
*/
- void fillDiagramWeights();
+ void fillDiagramWeights(double flatCut = 0.0);
/**
* Clone this phase space generator.
*/
Ptr<MatchboxPhasespace>::ptr cloneMe() const {
return dynamic_ptr_cast<Ptr<MatchboxPhasespace>::ptr>(clone());
}
/**
* Clone the dependencies, using a given prefix.
*/
virtual void cloneDependencies(const std::string& prefix = "");
/**
* Dump xcomb hierarchies.
*/
void dumpInfo(const string& prefix = "") const;
public:
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
// If needed, insert declarations of virtual function defined in the
// InterfacedBase class here (using ThePEG-interfaced-decl in Emacs).
private:
/**
* The diagram weights indexed by diagram id.
*/
map<int,double> diagramWeights;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MatchboxPhasespace & operator=(const MatchboxPhasespace &);
};
}
#endif /* HERWIG_MatchboxPhasespace_H */
diff --git a/MatrixElement/Matchbox/Phasespace/PhasespaceHelpers.cc b/MatrixElement/Matchbox/Phasespace/PhasespaceHelpers.cc
--- a/MatrixElement/Matchbox/Phasespace/PhasespaceHelpers.cc
+++ b/MatrixElement/Matchbox/Phasespace/PhasespaceHelpers.cc
@@ -1,514 +1,516 @@
// -*- C++ -*-
//
// PhasespaceHelpers.cc is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2012 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#include "PhasespaceHelpers.h"
#include "Herwig++/MatrixElement/Matchbox/Phasespace/RandomHelpers.h"
using namespace Herwig;
using namespace Herwig::PhasespaceHelpers;
using namespace Herwig::RandomHelpers;
Energy PhasespaceInfo::generateMass(tcPDPtr data,
const pair<Energy,Energy>& range) {
double xlow = sqr(range.first)/sHat;
if ( range.first < ZERO )
xlow = -xlow;
double xup = sqr(range.second)/sHat;
if ( range.second < ZERO )
xup = -xup;
double mu = sqr(data->mass())/sHat;
double gamma = sqr(data->width())/sHat;
double r = rnd();
pair<double,double> event;
if ( gamma == 0. ) {
if ( mu < xlow || mu > xup ) {
if ( abs(xlow-mu) < xc )
xlow = mu;
if ( abs(xup-mu) < xc )
xup = mu;
}
if ( mu < xlow || mu > xup ) {
event =
generate(inverse(mu,xlow,xup),r);
} else {
pair<double,double> pLeft(xlow,xlow < mu-x0 ? mu-x0 : xlow);
pair<double,double> pRight(xup > mu+x0 ? mu+x0 : xup,xup);
pair<double,double> fLeft(pLeft.second < mu-x0 ? mu-x0 : pLeft.second,mu-xc);
if ( fLeft.first >= fLeft.second )
fLeft.first = fLeft.second;
pair<double,double> fRight(mu+xc,pRight.first > mu+x0 ? mu+x0 : pRight.first);
if ( fRight.first >= fRight.second )
fRight.second = fRight.first;
if ( pLeft.first != pLeft.second &&
fLeft.first != fLeft.second &&
fRight.first != fRight.second &&
pRight.first != pRight.second ) {
event =
generate((piecewise(),
inverse(mu,pLeft.first,pLeft.second),
match(flat(fLeft.first,fLeft.second))) +
match((piecewise(),
flat(fRight.first,fRight.second),
match(inverse(mu,pRight.first,pRight.second)))),
r);
} else if ( pLeft.first == pLeft.second &&
fLeft.first != fLeft.second &&
fRight.first != fRight.second &&
pRight.first != pRight.second ) {
event =
generate(flat(fLeft.first,fLeft.second) +
match((piecewise(),
flat(fRight.first,fRight.second),
match(inverse(mu,pRight.first,pRight.second)))),
r);
} else if ( pLeft.first != pLeft.second &&
fLeft.first != fLeft.second &&
fRight.first != fRight.second &&
pRight.first == pRight.second ) {
event =
generate((piecewise(),
inverse(mu,pLeft.first,pLeft.second),
match(flat(fLeft.first,fLeft.second))) +
match(flat(fRight.first,fRight.second)),
r);
} else if ( pLeft.first == pLeft.second &&
fLeft.first == fLeft.second &&
fRight.first != fRight.second &&
pRight.first != pRight.second ) {
event =
generate((piecewise(),
flat(fRight.first,fRight.second),
match(inverse(mu,pRight.first,pRight.second))),
r);
} else if ( pLeft.first != pLeft.second &&
fLeft.first != fLeft.second &&
fRight.first == fRight.second &&
pRight.first == pRight.second ) {
event =
generate((piecewise(),
inverse(mu,pLeft.first,pLeft.second),
match(flat(fLeft.first,fLeft.second))),
r);
} else if ( pLeft.first == pLeft.second &&
fLeft.first != fLeft.second &&
fRight.first != fRight.second &&
pRight.first == pRight.second ) {
event =
generate(flat(fLeft.first,fLeft.second) +
match(flat(fRight.first,fRight.second)),
r);
} else if ( pLeft.first == pLeft.second &&
fLeft.first == fLeft.second &&
fRight.first != fRight.second &&
pRight.first == pRight.second ) {
event =
generate(flat(fRight.first,fRight.second),
r);
} else if ( pLeft.first == pLeft.second &&
fLeft.first != fLeft.second &&
fRight.first == fRight.second &&
pRight.first == pRight.second ) {
event =
generate(flat(fLeft.first,fLeft.second),
r);
} else if ( pLeft.first == pLeft.second &&
fLeft.first == fLeft.second &&
fRight.first == fRight.second &&
pRight.first == pRight.second ) {
throw Veto();
} else assert(false);
}
} else {
event = generate(breitWigner(mu,gamma,xlow,xup),r);
}
weight *= event.second;
Energy res = sqrt(abs(event.first)*sHat);
if ( event.first < 0. )
res = -res;
return res;
}
Lorentz5Momentum PhasespaceInfo::generateKt(const Lorentz5Momentum& p1,
const Lorentz5Momentum& p2,
Energy pt) {
- if ( (p1+p2).m2() <= ZERO ) {
- cerr << "cannot boost ... " << ((p1+p2).m2()/GeV2) << "\n";
- throw Veto();
- }
- Boost beta = (p1+p2).findBoostToCM();
-
- Lorentz5Momentum p1c = p1;
+ double phi = 2.*Constants::pi*rnd();
- if (beta.mag2() > Constants::epsilon) {
- p1c.boost(beta);
- }
-
- Lorentz5Momentum k (0.*GeV,0.*GeV,0.*GeV,0.*GeV);
-
- double ct = p1c.vect().unit().z();
- double st = sqrt(1.-ct*ct);
-
- double phi = 2.*Constants::pi*rnd();
- weight *= 2.*Constants::pi;
- double cphi = cos(phi);
- double sphi = sqrt(1.-cphi*cphi);
- if (phi > Constants::pi) sphi = -sphi;
-
- // adding an output somewhere around here results in the correct behaviour
- // when compiling with g++-4.6.1 -O3
- // cerr << "bla\n" << flush;
- if (st > Constants::epsilon) {
- double cchi = p1c.vect().unit().x()/st;
- double schi = p1c.vect().unit().y()/st;
- k.setX((cphi*cchi*ct-sphi*schi)*pt);
- k.setY((cphi*schi*ct+sphi*cchi)*pt);
- k.setZ(-cphi*st*pt);
- } else {
- k.setX(pt*cphi);
- k.setY(pt*sphi);
- k.setZ(0.*GeV);
- }
-
- if (beta.mag2() > Constants::epsilon)
- k.boost(-beta);
-
- return k;
+ Lorentz5Momentum P = p1 + p2;
+
+ Energy2 Q2 = abs(P.m2());
+
+ Lorentz5Momentum Q =
+ Lorentz5Momentum(ZERO,ZERO,ZERO,sqrt(Q2),sqrt(Q2));
+
+ bool boost =
+ abs((P-Q).vect().mag2()/GeV2) > 1e-10 ||
+ abs((P-Q).t()/GeV) > 1e-5;
+
+ Lorentz5Momentum inFrame1;
+ if ( boost )
+ inFrame1 = p1 + ((P*p1-Q*p1)/(P*Q-Q.mass2()))*(P-Q);
+ else
+ inFrame1 = p1;
+
+ Energy ptx = inFrame1.x();
+ Energy pty = inFrame1.y();
+ Energy q = 2.*inFrame1.z();
+
+ Energy Qp = sqrt(4.*(sqr(ptx)+sqr(pty))+sqr(q));
+ Energy Qy = sqrt(4.*sqr(pty)+sqr(q));
+
+ double cPhi = cos(phi);
+ double sPhi = sqrt(1.-sqr(cPhi));
+ if ( phi > Constants::pi )
+ sPhi = -sPhi;
+
+ Lorentz5Momentum kt;
+
+ kt.setT(ZERO);
+ kt.setX(pt*Qy*cPhi/Qp);
+ kt.setY(-pt*(4*ptx*pty*cPhi/Qp+q*sPhi)/Qy);
+ kt.setZ(2.*pt*(-ptx*q*cPhi/Qp + pty*sPhi)/Qy);
+
+ if ( boost )
+ kt = kt + ((P*kt-Q*kt)/(P*Q-Q.mass2()))*(P-Q);
+ kt.setMass(-pt);
+ kt.rescaleRho();
+
+ return kt;
}
void PhasespaceTree::setup(const Tree2toNDiagram& diag,
int pos) {
pair<int,int> dchildren =
diag.children(pos);
data = diag.allPartons()[pos];
spacelike = pos < diag.nSpace();
if ( pos == 0 )
externalId = 0;
if ( dchildren.first == -1 ) {
externalId = diag.externalId(pos);
leafs.insert(externalId);
return;
}
children.push_back(PhasespaceTree());
children.back().setup(diag,dchildren.first);
children.push_back(PhasespaceTree());
children.back().setup(diag,dchildren.second);
if ( !children[0].children.empty() &&
children[1].children.empty() &&
!spacelike )
swap(children[0],children[1]);
if ( spacelike &&
!children[0].spacelike )
swap(children[0],children[1]);
copy(children[0].leafs.begin(),children[0].leafs.end(),
inserter(leafs,leafs.begin()));
copy(children[1].leafs.begin(),children[1].leafs.end(),
inserter(leafs,leafs.begin()));
}
void PhasespaceTree::init(const vector<Lorentz5Momentum>& meMomenta) {
if ( children.empty() ) {
massRange.first = meMomenta[externalId].mass();
massRange.second = massRange.first;
momentum.setMass(meMomenta[externalId].mass());
if ( externalId == 1 )
momentum = meMomenta[1];
return;
}
children[0].init(meMomenta);
children[1].init(meMomenta);
if ( !children[0].spacelike &&
!children[1].spacelike ) {
massRange.first =
children[0].massRange.first +
children[1].massRange.first;
}
}
void PhasespaceTree::generateKinematics(PhasespaceInfo& info,
vector<Lorentz5Momentum>& meMomenta) {
if ( externalId == 0 ) {
init(meMomenta);
momentum = meMomenta[0];
}
if ( children.empty() ) {
if ( externalId != 1 )
meMomenta[externalId] = momentum;
return;
}
// s-channel
if ( externalId == 0 &&
children[0].externalId == 1 ) {
children[1].momentum = meMomenta[0] + meMomenta[1];
children[1].momentum.setMass(info.sqrtSHat);
children[1].momentum.rescaleEnergy();
children[1].generateKinematics(info,meMomenta);
return;
}
if ( !spacelike ) {
Energy mij = momentum.mass();
Energy mi,mj;
// work out the mass for the first child
if ( !children[0].children.empty() ) {
Energy sumOthers = ZERO;
for ( size_t k = 2; k < meMomenta.size(); ++k )
if ( children[1].leafs.find(k) != children[1].leafs.end() )
sumOthers += meMomenta[k].mass();
children[0].massRange.second = momentum.mass() - sumOthers;
if ( children[0].massRange.second < children[0].massRange.first )
throw Veto();
if ( children[0].massRange.second > momentum.mass() )
throw Veto();
mi = info.generateMass(children[0].data,children[0].massRange);
children[0].momentum.setMass(mi);
} else {
mi = children[0].momentum.mass();
}
// work out the mass for the second child
if ( !children[1].children.empty() ) {
children[1].massRange.second = momentum.mass()-children[0].momentum.mass();
if ( children[1].massRange.second < children[1].massRange.first )
throw Veto();
mj = info.generateMass(children[1].data,children[1].massRange);
children[1].momentum.setMass(mj);
} else {
mj = children[1].momentum.mass();
}
Energy2 mij2 = sqr(mij);
Energy2 mi2 = sqr(mi);
Energy2 mj2 = sqr(mj);
// perform the decay
Energy4 lambda2 = sqr(mij2-mi2-mj2)-4.*mi2*mj2;
if ( lambda2 < ZERO )
throw Veto();
Energy2 lambda = sqrt(lambda2);
double phi = 2.*Constants::pi*info.rnd();
double cosPhi = cos(phi);
double sinPhi = sqrt(1.-sqr(cosPhi));
if ( phi > Constants::pi )
sinPhi = -sinPhi;
info.weight *= Constants::pi*lambda/(2.*mij2);
double cosTheta = 2.*info.rnd() - 1.;
double sinTheta = sqrt(1.-sqr(cosTheta));
Energy p = lambda/(2.*mij);
children[0].momentum.setX(p*cosPhi*sinTheta);
children[0].momentum.setY(p*sinPhi*sinTheta);
children[0].momentum.setZ(p*cosTheta);
children[0].momentum.rescaleEnergy();
if ( momentum.m2() <= ZERO ) {
cerr << "cannot boost in decay ... " << (momentum.m2()/GeV2) << "\n";
throw Veto();
}
Boost out = momentum.boostVector();
if ( out.mag2() > Constants::epsilon ) {
children[0].momentum.boost(out);
}
children[1].momentum = momentum - children[0].momentum;
children[1].momentum.setMass(mj);
children[1].momentum.rescaleEnergy();
// go on with next branchings
children[0].generateKinematics(info,meMomenta);
children[1].generateKinematics(info,meMomenta);
return;
}
// get the minimum mass of the `W' system
Energy Wmin = ZERO;
PhasespaceTree* current = &children[0];
while ( !(current->children.empty()) ) {
Wmin += current->children[1].massRange.first;
current = &(current->children[0]);
}
// get the CM energy avaialble
Energy2 s = (momentum+meMomenta[1]).m2();
if ( s <= ZERO )
throw Veto();
// generate a mass for the timelike child
Energy mi;
if ( !children[1].children.empty() ) {
children[1].massRange.second = sqrt(s)-Wmin;
if ( children[1].massRange.second < children[1].massRange.first )
throw Veto();
mi = info.generateMass(children[1].data,children[1].massRange);
children[1].momentum.setMass(mi);
} else {
mi = children[1].momentum.mass();
}
Energy2 mi2 = sqr(mi);
// wether or not this is the last 2->2 scatter
bool lastScatter
= children[0].children[0].children.empty();
// `W' mass relevant for the other boundaries
Energy MW = Wmin;
// generate a mass for second outgoing leg, if needed
if ( lastScatter )
if ( !children[0].children[1].children.empty() ) {
// get the maximum `W' mass
Energy Wmax = sqrt(s)-children[1].momentum.mass();
children[0].children[1].massRange.second = Wmax;
if ( children[0].children[1].massRange.second <
children[0].children[1].massRange.first )
throw Veto();
MW = info.generateMass(children[0].children[1].data,
children[0].children[1].massRange);
children[0].children[1].momentum.setMass(MW);
}
Energy2 MW2 = sqr(MW);
Energy ma = momentum.mass();
Energy2 ma2 = sqr(ma);
if ( ma < ZERO )
ma2 = -ma2;
Energy mb = meMomenta[1].mass();
Energy2 mb2 = sqr(mb);
// pick the ys variable
Energy2 ys = ZERO;
if ( !lastScatter ) {
ys = info.rnd()*(sqr(sqrt(s)-mi)-MW2);
info.weight *= (sqr(sqrt(s)-mi)-MW2)/info.sHat;
}
Energy4 lambda2 = sqr(s-ma2-mb2)-4.*ma2*mb2;
if ( lambda2 <= ZERO ) {
throw Veto();
}
Energy2 lambda = sqrt(lambda2);
info.weight *= info.sHat/(4.*lambda);
// get the boundaries on the momentum transfer
Energy4 rho2 = sqr(s-ys-MW2-mi2)-4.*mi2*(ys+MW2);
if ( rho2 < ZERO )
throw Veto();
Energy2 rho = sqrt(rho2);
Energy4 tau2 =
ys*(ma2-mb2+s)
- sqr(s)+s*(ma2+mb2+mi2+MW2)-(mi2-MW2)*(ma2-mb2);
pair<Energy2,Energy2> tBounds
((tau2-rho*lambda)/(2.*s),(tau2+rho*lambda)/(2.*s));
children[0].massRange.first = sqrt(abs(tBounds.first));
if ( tBounds.first < ZERO )
children[0].massRange.first = -children[0].massRange.first;
children[0].massRange.second = sqrt(abs(tBounds.second));
if ( tBounds.second < ZERO )
children[0].massRange.second = -children[0].massRange.second;
// generate a momentum transfer
Energy mai = info.generateMass(children[0].data,children[0].massRange);
children[0].momentum.setMass(mai);
Energy2 t = sqr(mai);
if ( mai < ZERO )
t = -t;
Energy2 u = -s -t + ys + ma2 + mb2 + mi2 + MW2;
Energy2 st = s - ma2 - mb2;
Energy2 tt = t - mi2 - ma2;
Energy2 ut = u - mi2 - mb2;
// get the timelike momentum
double xa = (-st*ut+2.*mb2*tt)/lambda2;
double xb = (-st*tt+2.*ma2*ut)/lambda2;
Energy2 pt2 = (st*tt*ut-ma2*sqr(ut)-mb2*sqr(tt)-mi2*sqr(st)+4.*ma2*mb2*mi2)/lambda2;
if ( pt2 < ZERO )
throw Veto();
Energy pt = sqrt(pt2);
children[1].momentum =
xa*momentum + xb*meMomenta[1] + info.generateKt(momentum,meMomenta[1],pt);
children[1].momentum.setMass(mi);
children[1].momentum.rescaleEnergy();
children[0].momentum =
momentum - children[1].momentum;
children[0].momentum.setMass(mai);
bool changeSign = false;
if ( children[0].momentum.t() < ZERO && mai > ZERO ) changeSign = true;
if ( mai < ZERO )
children[0].momentum.rescaleRho();
else
children[0].momentum.rescaleEnergy();
if ( changeSign ) children[0].momentum.setT(-children[0].momentum.t());
children[1].generateKinematics(info,meMomenta);
if ( !lastScatter ) {
children[0].generateKinematics(info,meMomenta);
} else {
children[0].children[1].momentum =
meMomenta[1] + children[0].momentum;
children[0].children[1].momentum.setMass(MW);
children[0].children[1].momentum.rescaleEnergy();
children[0].children[1].generateKinematics(info,meMomenta);
}
}
void PhasespaceTree::put(PersistentOStream& os) const {
os << children.size();
if ( !children.empty() ) {
children[0].put(os);
children[1].put(os);
}
os << data << externalId << leafs << spacelike;
}
void PhasespaceTree::get(PersistentIStream& is) {
size_t nc; is >> nc;
assert(nc == 0 || nc == 2);
if ( nc == 2 ) {
children.resize(2,PhasespaceTree());
children[0].get(is);
children[1].get(is);
}
is >> data >> externalId >> leafs >> spacelike;
}
diff --git a/MatrixElement/Matchbox/Phasespace/TreePhasespace.cc b/MatrixElement/Matchbox/Phasespace/TreePhasespace.cc
--- a/MatrixElement/Matchbox/Phasespace/TreePhasespace.cc
+++ b/MatrixElement/Matchbox/Phasespace/TreePhasespace.cc
@@ -1,170 +1,170 @@
// -*- C++ -*-
//
// TreePhasespace.cc is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2012 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the TreePhasespace class.
//
#include "TreePhasespace.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace Herwig;
using namespace Herwig::PhasespaceHelpers;
TreePhasespace::TreePhasespace()
: x0(0.01), xc(1e-4) {
lastPhasespaceInfo.x0 = x0;
lastPhasespaceInfo.xc = xc;
}
TreePhasespace::~TreePhasespace() {}
IBPtr TreePhasespace::clone() const {
return new_ptr(*this);
}
IBPtr TreePhasespace::fullclone() const {
return new_ptr(*this);
}
void TreePhasespace::prepare(tStdXCombPtr xco, bool) {
theLastXComb = xco;
lastChannelsIterator = channelMap().find(lastXCombPtr());
if ( lastChannelsIterator == channelMap().end() ) {
map<Ptr<Tree2toNDiagram>::ptr,PhasespaceTree> channels;
for ( StandardXComb::DiagramVector::const_iterator d =
lastXComb().diagrams().begin(); d != lastXComb().diagrams().end(); ++d ) {
PhasespaceTree tree;
Ptr<Tree2toNDiagram>::ptr diag =
dynamic_ptr_cast<Ptr<Tree2toNDiagram>::ptr>(*d);
tree.setup(*diag);
channels[diag] = tree;
}
channelMap()[lastXCombPtr()] = channels;
lastChannelsIterator = channelMap().find(lastXCombPtr());
}
lastPhasespaceInfo.sHat = lastXComb().lastSHat();
lastPhasespaceInfo.sqrtSHat = sqrt(lastXComb().lastSHat());
lastPhasespaceInfo.weight = 1.;
}
double TreePhasespace::generateKinematics(const double* random,
vector<Lorentz5Momentum>& momenta) {
size_t nchannels = lastXComb().diagrams().size();
map<Ptr<Tree2toNDiagram>::ptr,PhasespaceHelpers::PhasespaceTree>::iterator ds =
lastChannels().begin();
advance(ds,(size_t)(random[0]*nchannels));
Ptr<Tree2toNDiagram>::ptr channel = ds->first;
++random;
lastPhasespaceInfo.rnd.numbers = random;
lastPhasespaceInfo.rnd.nRnd = 3*momenta.size() - 10;
cPDVector::const_iterator pd = mePartonData().begin();
vector<Lorentz5Momentum>::iterator p = momenta.begin();
for ( ; pd != mePartonData().end(); ++pd, ++p )
p->setMass((**pd).mass());
try {
lastChannels()[channel].generateKinematics(lastPhasespaceInfo,momenta);
} catch (Veto) {
return 0.;
}
- fillDiagramWeights();
+ fillDiagramWeights(x0);
double sum = 0.;
for ( map<Ptr<Tree2toNDiagram>::ptr,PhasespaceHelpers::PhasespaceTree>::const_iterator d
= lastChannels().begin(); d != lastChannels().end(); ++d )
sum += diagramWeight(*(d->first));
double piWeight = pow(2.*Constants::pi,(double)(3*(momenta.size()-2)-4));
return nchannels*lastPhasespaceInfo.weight*diagramWeight(*channel)/(sum*piWeight);
}
// If needed, insert default implementations of virtual function defined
// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs).
void TreePhasespace::doinit() {
MatchboxPhasespace::doinit();
lastPhasespaceInfo.x0 = x0;
lastPhasespaceInfo.xc = xc;
}
void TreePhasespace::doinitrun() {
MatchboxPhasespace::doinitrun();
lastPhasespaceInfo.x0 = x0;
lastPhasespaceInfo.xc = xc;
}
void TreePhasespace::persistentOutput(PersistentOStream & os) const {
os << theChannelMap << x0 << xc;
}
void TreePhasespace::persistentInput(PersistentIStream & is, int) {
is >> theChannelMap >> x0 >> xc;
}
// *** 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<TreePhasespace,MatchboxPhasespace>
describeHerwigTreePhasespace("Herwig::TreePhasespace", "HwMatchbox.so");
void TreePhasespace::Init() {
static ClassDocumentation<TreePhasespace> documentation
("TreePhasespace is a multichannel phasespace generator "
"adapting to singularity structures as determined from the matrix "
"elements diagrams.");
static Reference<TreePhasespace,TreePhasespaceChannels> interfaceChannelMap
("ChannelMap",
"Set the object storing the channels.",
&TreePhasespace::theChannelMap, false, false, true, false, false);
static Parameter<TreePhasespace,double> interfaceX0
("X0",
"Set the cut below which flat virtuality sampling is imposed.",
&TreePhasespace::x0, 0.01, 0.0, 0,
false, false, Interface::lowerlim);
static Parameter<TreePhasespace,double> interfaceXC
("XC",
"Set the cut below which no virtualities are generated.",
&TreePhasespace::xc, 1e-4, 0.0, 0,
false, false, Interface::lowerlim);
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Tue, Jan 21, 2:07 AM (1 d, 17 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4206525
Default Alt Text
(33 KB)
Attached To
rHERWIGHG herwighg
Event Timeline
Log In to Comment