Page Menu
Home
HEPForge
Search
Configure Global Search
Log In
Files
F8725617
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
60 KB
Subscribers
None
View Options
diff --git a/Hadronization/Ropewalk.cc b/Hadronization/Ropewalk.cc
--- a/Hadronization/Ropewalk.cc
+++ b/Hadronization/Ropewalk.cc
@@ -1,1207 +1,1207 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the Ropewalk class.
//
#include "Ropewalk.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/EventRecord/Step.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Repository/CurrentGenerator.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/Utilities/Selector.h"
#include "ThePEG/Utilities/SimplePhaseSpace.h"
#include "ThePEG/Utilities/UtilityBase.h"
#include "ThePEG/Utilities/Throw.h"
#include "ThePEG/Handlers/StepHandler.h"
using namespace TheP8I;
Ropewalk::Ropewalk(const vector<ColourSinglet> & singlets, Length width,
Energy scale, double jDP, bool throwaway, bool shoving, double rcIn,
Energy gaIn, double geIn, double ycIn, double dyIn, Length tsIn, Length dtIn,
bool lorentzIn, bool cylinderIn, HistKeeper* hk, bool deb)
: R0(width), m0(scale), junctionDiquarkProb(jDP), rCutOff(rcIn*width), gAmplitude(gaIn),
gExponent(geIn), yCutOff(ycIn), deltay(dyIn), tshove(tsIn), deltat(dtIn), lorentz(lorentzIn),
cylinderShove(cylinderIn), hkPtr(hk), debug(deb), strl0(0.0), strl(0.0), avh(0.0), avp(0.0), avq(0.0) {
for ( int is = 0, Ns = singlets.size(); is < Ns; ++is ){
stringdipoles[cloneToFinal(singlets[is])];
}
getDipoles();
calculateOverlaps(false);
if(throwaway)
doBreakups();
lambdaBefore = lambdaSum();
if ( debug ) CurrentGenerator::log() << singlets.size() << "s "
<< dipoles.size() << "d ";
if(hkPtr){
for(DipoleMap::iterator itr = stringdipoles.begin(); itr!=stringdipoles.end();++itr){
vector<Dipole*> dips = itr->second;
for(int id = 0, Nd = dips.size(); id < Nd; ++id){
Dipole* d = dips[id];
LorentzMomentum mpa = d->pa->momentum();
LorentzMomentum mpc = d->pc->momentum();
LorentzMomentum mpaRot = (d->R)*mpa;
LorentzMomentum mpcRot = (d->R)*mpc;
if(d->pa->id() == 21){
hk->hist("normalGluonPt")->fill(mpa.perp()/GeV,
hk->currentWeight());
hk->hist("normalGluonRestFramePt")->fill(
mpaRot.perp()/GeV,hk->currentWeight());
}
if(abs(d->pa->id()) < 10 ){
hk->hist("normalQuarkPt")->fill(mpa.perp()/GeV,
hk->currentWeight());
hk->hist("normalQuarkRestFramePt")->fill(
mpaRot.perp()/GeV,hk->currentWeight());
}
if(abs(d->pc->id()) < 10 ){
hk->hist("normalQuarkPt")->fill(mpc.perp()/GeV,
hk->currentWeight());
hk->hist("normalQuarkRestFramePt")->fill(
mpcRot.perp()/GeV,hk->currentWeight());
}
if(abs(d->pc->id()) > 100 ){
hk->hist("normalDiQuarkPt")->fill(mpc.perp()/GeV,
hk->currentWeight());
hk->hist("normalDiQuarkRestFramePt")->fill(
mpcRot.perp()/GeV,hk->currentWeight());
}
if(abs(d->pa->id()) > 100 ){
hk->hist("normalDiQuarkPt")->fill(mpa.perp()/GeV,
hk->currentWeight());
hk->hist("normalDiQuarkRestFramePt")->fill(
mpaRot.perp()/GeV,hk->currentWeight());
}
}
}
}
if(shoving){
shoveTheDipoles();
// update color singlets
DipoleMap newStringDipoles;
for(DipoleMap::iterator itr = stringdipoles.begin(); itr != stringdipoles.end(); ++itr){
delete itr->first;
// The old dipoles
vector<Dipole*> oldDipoles = itr->second;
tcParticleSet updatedParticles;
for(int id = 0, Nd = oldDipoles.size(); id < Nd; ++id){
Dipole* d = oldDipoles[id];
const ParticleVector children = d->pa->children();
if(children.empty())
updatedParticles.insert(d->pa);
for(int ic = 0, Nc = children.size(); ic < Nc; ++ic)
updatedParticles.insert(children[ic]);
if(d->pc->id() != 21){
const ParticleVector children = d->pc->children();
if(children.empty())
updatedParticles.insert(d->pc);
for(int ic = 0, Nc = children.size(); ic < Nc; ++ic)
updatedParticles.insert(children[ic]);
}
}
tcPPtr p = *updatedParticles.begin();
if(p->colourLine())
newStringDipoles[new ColourSinglet(p->colourLine(), updatedParticles)];
else if(p->antiColourLine())
newStringDipoles[new ColourSinglet(p->antiColourLine(), updatedParticles)];
else
Throw<ColourException>()
<< "Updating colour singlets after shoving failed."
<< "This is a serious error, please contact the authors."
<< Exception::abortnow;
}
stringdipoles = newStringDipoles;
getDipoles();
if(hkPtr){
for(DipoleMap::iterator itr = stringdipoles.begin(); itr!=stringdipoles.end();++itr){
vector<Dipole*> dips = itr->second;
for(int id = 0, Nd = dips.size(); id < Nd; ++id){
Dipole* d = dips[id];
LorentzMomentum mpa = d->pa->momentum();
LorentzMomentum mpc = d->pc->momentum();
LorentzMomentum mpaRot = (d->R)*mpa;
LorentzMomentum mpcRot = (d->R)*mpc;
if(d->pa->id() == 21){
hk->hist("excitedEndGluonPt")->fill(mpa.perp()/GeV,
hk->currentWeight());
hk->hist("excitedEndGluonRestFramePt")->fill(
mpaRot.perp()/GeV,hk->currentWeight());
}
if(abs(d->pa->id()) < 10 ){
hk->hist("excitedQuarkPt")->fill(mpa.perp()/GeV,
hk->currentWeight());
hk->hist("excitedQuarkRestFramePt")->fill(
mpaRot.perp()/GeV,hk->currentWeight());
}
if(abs(d->pc->id()) < 10 ){
hk->hist("excitedQuarkPt")->fill(mpc.perp()/GeV,
hk->currentWeight());
hk->hist("excitedQuarkRestFramePt")->fill(
mpcRot.perp()/GeV,hk->currentWeight());
}
if(abs(d->pc->id()) > 100 ){
hk->hist("excitedDiQuarkPt")->fill(mpc.perp()/GeV,
hk->currentWeight());
hk->hist("excitedDiQuarkRestFramePt")->fill(
mpcRot.perp()/GeV,hk->currentWeight());
}
if(abs(d->pa->id()) > 100 ){
hk->hist("excitedDiQuarkPt")->fill(mpa.perp()/GeV,
hk->currentWeight());
hk->hist("excitedDiQuarkRestFramePt")->fill(
mpaRot.perp()/GeV,hk->currentWeight());
}
}
}
}
}
}
Ropewalk::~Ropewalk() {
for ( DipoleMap::iterator it = stringdipoles.begin();
it != stringdipoles.end(); ++it ) delete it->first;
}
ColourSinglet * Ropewalk::cloneToFinal(const ColourSinglet & cs) {
tcParticleSet final;
for ( int i = 0, N = cs.partons().size(); i < N; ++i )
final.insert(cs.partons()[i]->final());
tcPPtr p = *final.begin();
if(hkPtr){
hkPtr->hist("nPartons")->fill(final.size(), hkPtr->currentWeight());
}
if ( p->colourLine() ) return new ColourSinglet(p->colourLine(), final);
if ( p->antiColourLine() ) return new ColourSinglet(p->antiColourLine(), final);
Throw<ColourException>()
<< "Cloning ColourSinglets failed in Ropewalk. "
<< "This is a serious error - please contact the authors."
<< Exception::abortnow;
return 0;
}
LorentzPoint Ropewalk::
propagate(const LorentzPoint & b, const LorentzMomentum & p) const {
return b + p/(p.e()*m0/hbarc);
// return b;
}
void Ropewalk::getDipoles() {
dipoles.clear();
// First extract all dipoles from all strings (pieces).
for ( DipoleMap::iterator it = stringdipoles.begin();
it != stringdipoles.end(); ++it ) {
ColourSinglet & string = *it->first;
for ( int isp = 1, Nsp = string.nPieces(); isp <= Nsp; ++isp ) {
const ColourSinglet::StringPiece & sp = string.piece(isp);
if ( sp.size() < 2 ) continue;
bool forward = sp[0]->colourLine() &&
sp[0]->colourLine() == sp[1]->antiColourLine();
for ( int i = 0, N = sp.size(); i < (N - 1); ++i ) {
if ( forward )
dipoles.push_back(Dipole(sp[i], sp[i + 1], string, m0));
else
dipoles.push_back(Dipole(sp[i + 1], sp[i], string, m0));
}
if ( !forward && sp.front()->colourLine() &&
sp.front()->colourLine() == sp.back()->antiColourLine() )
dipoles.push_back(Dipole(sp.front(), sp.back(), string, m0));
else if ( forward && sp.front()->antiColourLine() &&
sp.front()->antiColourLine() == sp.back()->colourLine() )
dipoles.push_back(Dipole(sp.back(), sp.front(), string, m0));
}
}
for ( int i = 0, N = dipoles.size(); i < N; ++i ) {
stringdipoles[dipoles[i].string].push_back(&dipoles[i]);
strl0 += dipoles[i].yspan(1.0*GeV);
}
}
double Ropewalk::limitrap(const LorentzMomentum & p) const {
if ( p.z() == ZERO ) return 0.0;
Energy mt = sqrt(max(p.perp2() + p.m2(), sqr(m0)));
double rap = log((p.t() + abs(p.z()))/mt);
return p.z() > ZERO? rap: -rap;
}
Ropewalk::OverlappingDipole::
OverlappingDipole(const Dipole & d, const LorentzRotation R, const Ropewalk * rw)
: dipole(&d), dir(1) {
// Get the boost to other dipole's rest frame and calculate
// rapidities.
bc = R*rw->propagate(d.pc->vertex(), d.pc->momentum());
ba = R*rw->propagate(d.pa->vertex(), d.pa->momentum());
yc = rw->limitrap(R*d.pc->momentum());
ya = rw->limitrap(R*d.pa->momentum());
if ( yc < ya ) dir = -1;
}
void Ropewalk::calculateOverlaps(bool doPropagate) {
// Then calculate all overlaps between pairs of dipoles.
for ( int i1 = 0, Nd = dipoles.size(); i1 < Nd; ++i1 ) {
Dipole & d1 = dipoles[i1];
d1.clear();
if ( d1.s() <= sqr(m0) ) continue;
// Get the boost to dipoles rest frame and calculate rapidities.
LorentzMomentum pc1 = d1.pc->momentum();
LorentzMomentum pa1 = d1.pa->momentum();
//LorentzRotation R = Utilities::boostToCM(make_pair(&pc1, &pa1));
if(doPropagate){
d1.bc = d1.R*propagate(d1.pc->vertex(), d1.pc->momentum());
d1.ba = d1.R*propagate(d1.pa->vertex(), d1.pa->momentum());
}
else{
d1.bc = d1.pc->vertex();
d1.ba = d1.pa->vertex();
}
double yc1 = limitrap(pc1);
double ya1 = limitrap(pa1);
double n = 0.0;
double m = 0.0;
if ( yc1 <= ya1 ) continue; // don't care about too small strings.
for ( int i2 = 0; i2 < Nd; ++i2 ) {
if ( i1 == i2 ) continue;
// Boost to the rest frame of dipole 1.
if ( dipoles[i2].s() <= sqr(m0) ) continue;
OverlappingDipole od(dipoles[i2], d1.R, this);
// Ignore if not overlapping in rapidity.
if ( min(od.yc, od.ya) > yc1 || max(od.yc, od.ya) < ya1 || od.yc == od.ya )
continue;
// Calculate rapidity overlap.
double yomax = min(max(od.yc, od.ya), yc1);
double yomin = max(min(od.yc, od.ya), ya1);
// Sample a random point in the rapidity overlap region and get
// positions in space and check overlap.
double yfrac = (yomax - yomin)/(yc1 - ya1);
double y = UseRandom::rnd(yomin, yomax);
if ( !od.overlap(y, d1.ba + (d1.bc - d1.ba)*(y - ya1)/(yc1 - ya1), R0) )
yfrac = 0.0;
// Sum overlaps.
if ( od.dir > 0 ) {
n += yfrac;
} else {
m += yfrac;
}
od.yfrac = yfrac*od.dir;
d1.overlaps.push_back(od);
}
d1.n = int(n + UseRandom::rnd());
d1.m = int(m + UseRandom::rnd());
d1.initWeightMultiplet();
avp += d1.p*d1.yspan(1.0*GeV);
avq += d1.q*d1.yspan(1.0*GeV);
}
}
double Ropewalk::Dipole::reinit(double ry, Length R0, Energy m0) {
// First calculate the rapidity in this restframe.
double y = yspan(m0)*(ry - 0.5);
// Then get the position in space of the string at this rapidity.
LorentzPoint b = ba + (bc - ba)*ry;
p = 1;
q = 0;
// Now go through all overlapping dipoles.
for ( int i = 0, N = overlaps.size(); i < N; ++i ) {
if ( overlaps[i].dipole->broken ) continue;
if( overlaps[i].dipole->hadr ) continue;
if ( overlaps[i].overlap(y, b, R0) ) {
if ( overlaps[i].dir > 0 ) ++p;
else ++q;
}
}
return kappaEnhancement();
}
void Ropewalk::Dipole::initMultiplet() {
typedef pair<int,int> Plet;
int ns = 0;
int ms = 0;
while ( ns < n || ms < m ) {
Plet diff;
double octetveto = double(ns + ms + 1 - p - q)/double(ns + ms + 1);
if ( double(n - ns) > UseRandom::rnd()*double(n + m - ns - ms) ) {
Selector<Plet> sel;
sel.insert(multiplicity(p + 1, q), Plet(1, 0));
sel.insert(multiplicity(p, q - 1)*octetveto, Plet(0, -1));
sel.insert(multiplicity(p - 1, q + 1), Plet(-1, 1));
diff = sel[UseRandom::rnd()];
++ns;
} else {
Selector<Plet> sel;
sel.insert(multiplicity(p, q + 1), Plet(0, 1));
sel.insert(multiplicity(p - 1, q)*octetveto, Plet(-1, 0));
sel.insert(multiplicity(p + 1, q - 1), Plet(1, -1));
diff = sel[UseRandom::rnd()];
++ms;
}
if ( diff.first == -diff.second ) nb++;
p += diff.first;
q += diff.second;
}
/* *** ATTENTION *** maybe better if Christian implements this */
}
void Ropewalk::Dipole::initNewMultiplet() {
typedef pair<int,int> Plet;
int ns = 0;
int ms = 0;
for ( int i = 0, N = overlaps.size(); i < N; ++i ) {
if ( abs(overlaps[i].yfrac) < UseRandom::rnd() ) continue;
Plet diff(0,0);
double octetveto = double(ns + ms + 1 - p - q)/double(ns + ms + 1);
if ( overlaps[i].dir > 0 ) {
Selector<Plet> sel;
sel.insert(multiplicity(p + 1, q), Plet(1, 0));
sel.insert(multiplicity(p, q - 1)*octetveto, Plet(0, -1));
sel.insert(multiplicity(p - 1, q + 1), Plet(-1, 1));
diff = sel[UseRandom::rnd()];
++ns;
} else {
Selector<Plet> sel;
sel.insert(multiplicity(p, q + 1), Plet(0, 1));
sel.insert(multiplicity(p - 1, q)*octetveto, Plet(-1, 0));
sel.insert(multiplicity(p + 1, q - 1), Plet(1, -1));
diff = sel[UseRandom::rnd()];
++ms;
}
if ( diff.first == -diff.second ) nb++;
p += diff.first;
q += diff.second;
}
n = ns;
m = ms;
/* *** ATTENTION *** maybe better if Christian implements this */
}
void Ropewalk::Dipole::initWeightMultiplet() {
typedef pair<int,int> Plet;
int ns = 0;
int ms = 0;
double mab = sqrt(s())/GeV;
for ( int i = 0, N = overlaps.size(); i < N; ++i ) {
if ( abs(overlaps[i].yfrac) < UseRandom::rnd() ) continue;
const Dipole * od = overlaps[i].dipole;
double mcd = sqrt(od->s())/GeV;
double w8 = 1.0/sqr(mab*mcd); //The weight for 3 + 3bar -> 8
double w6 = w8; // The weight for 3 + 3 -> 6
Plet diff(0,0);
double octetveto = double(ns + ms + 1 - p - q)/double(ns + ms + 1);
if ( overlaps[i].dir > 0 ) {
double mac = (pc->momentum() + od->pc->momentum()).m()/GeV;
double mbd = (pa->momentum() + od->pa->momentum()).m()/GeV;
double w1 = octetveto/sqr(mac*mbd); // The weight for 3 + 3bar -> 1
double w3 = 1.0/(mab*mcd*mac*mbd); //The weight for 3 + 3 -> 3bar
Selector<Plet> sel;
sel.insert(multiplicity(p + 1, q) +
multiplicity(p, q - 1)*w8/(w8 + w1) +
multiplicity(p - 1, q + 1)*w6/(w6 + w3), Plet(1, 0));
sel.insert(multiplicity(p, q - 1)*w1/(w1 + w8), Plet(0, -1));
sel.insert(multiplicity(p - 1, q + 1)*w3/(w3 + w6), Plet(-1, 1));
diff = sel[UseRandom::rnd()];
++ns;
} else {
double mac = (pa->momentum() + od->pc->momentum()).m()/GeV;
double mbd = (pc->momentum() + od->pa->momentum()).m()/GeV;
if ( mac*mbd <= 0.0 ) {
- q++;
+ ++q; ++ms;
continue;
}
double w1 = octetveto/sqr(mac*mbd); // The weight for 3 + 3bar -> 1
double w3 = 1.0/(mab*mcd*mac*mbd); //The weight for 3 + 3 -> 3bar
Selector<Plet> sel;
sel.insert(multiplicity(p, q + 1) +
multiplicity(p - 1, q)*w8/(w8 + w1) +
multiplicity(p + 1, q - 1)*w6/(w6 + w3), Plet(0, 1));
sel.insert(multiplicity(p - 1, q)*w1/(w1 + w8), Plet(-1, 0));
sel.insert(multiplicity(p + 1, q - 1)*w3/(w3 + w6), Plet(1, -1));
diff = sel[UseRandom::rnd()];
++ms;
}
if ( diff.first == -diff.second ) nb++;
p += diff.first;
q += diff.second;
}
n = ns;
m = ms;
/* *** ATTENTION *** maybe better if Christian implements this */
}
double Ropewalk::getNb(){
double nba = 0;
for ( int i = 0, N = dipoles.size(); i < N; ++i ){
nba += double(dipoles[i].nb);
//cout << dipoles[i].n << " " << dipoles[i].m << " " << dipoles[i].p << " " << dipoles[i].q << endl;
//cout << double(dipoles[i].n + dipoles[i].m + 1 - dipoles[i].p - dipoles[i].q) << endl;
//cout << " --- " << endl;
//nba += double(dipoles[i].n + dipoles[i].m + 1 - dipoles[i].p - dipoles[i].q);
}
// cout << nba << endl;
return nba;
}
double Ropewalk::getkW(){
double kw = 0;
for ( int i = 0, N = dipoles.size(); i < N; ++i )
kw += dipoles[i].kappaEnhancement()*log(dipoles[i].s()/sqr(m0));
return kw;
}
pair<double,double> Ropewalk::getMN(){
pair<double,double> ret = make_pair<double,double>(0,0);
for (int i = 0, N = dipoles.size(); i < N; ++i){
ret.first += dipoles[i].m;
ret.second += dipoles[i].n;
}
return ret;
}
double Ropewalk::lambdaSum(double cutoff){
double ret = 0;
for (int i = 0, N = dipoles.size(); i < N; ++i)
ret += dipoles[i].s() > cutoff*GeV2 ? log(dipoles[i].s()/sqr(m0)) : 0;
return ret;
}
double Ropewalk::Dipole::breakupProbability() const {
if ( !breakable() || n + m <= 0.0 || n + m + 1 == p + q ) return 0.0;
double sum = 0.0;
for (int j = 0, N = overlaps.size(); j < N; ++j )
if ( overlaps[j].dipole->breakable() )
sum += abs(overlaps[j].yfrac);
if ( sum <= 0.0 ) return 1.0;
return double(n + m + 1 - p - q)/(sum + 1.0);
}
Step & Ropewalk::step() const {
return *(CurrentGenerator()->currentStepHandler()->newStep());
}
Step & Ropewalk::Dipole::step() const {
return *(CurrentGenerator()->currentStepHandler()->newStep());
}
// Helper class to describe a pair of excitations
struct Exc {
// The constructor
Exc(double yIn, Energy gmassIn, PPtr p1In, PPtr p2In, Ropewalk::Dipole* dip1In, Ropewalk::Dipole* dip2In) : y(yIn), gluonMass(gmassIn), pp1(p1In), pp2(p2In), dip1(dip1In), dip2(dip2In) {
// Set a sensible starting vertex
pp1->setVertex(dip1->pointAtRap(y));
pp2->setVertex(dip2->pointAtRap(y));
// Set a pointer to the excitation in the dipole
dip1->addExcitation(y, pp1);
dip2->addExcitation(y, pp2);
}
// Give the excitation a kick in the x and y direction,
void shove(Energy dpx, Energy dpy, HistKeeper* hkPtr){
// The old momenta
LorentzMomentum p2 = pp2->momentum();
LorentzMomentum p1 = pp1->momentum();
// The new momenta, after the shove
Energy mt2new = sqrt(sqr(p2.x() - dpx) + sqr(p2.y() - dpy) + sqr(gluonMass));
Energy e2new = mt2new*cosh(y);
Energy p2znew = mt2new*sinh(y);
LorentzMomentum p2new(p2.x() - dpx, p2.y() - dpy, p2znew, e2new);
Energy mt1new = sqrt(sqr(p1.x() + dpx) + sqr(p1.y() + dpy) + sqr(gluonMass));
Energy e1new = mt1new*cosh(y);
Energy p1znew = mt1new*sinh(y);
LorentzMomentum p1new(p1.x() + dpx, p1.y() + dpy, p1znew, e1new);
// The differences between the two
LorentzMomentum deltap1 = p1new - p1;
LorentzMomentum deltap2 = p2new - p2;
// We now want to check if we can add these
// two excitations to the dipoles
if(dip2->recoil(deltap2,true) && dip1->recoil(deltap1,true)){
if(hkPtr){
LorentzMomentum ex2Rot = (dip2->R)*deltap2;
LorentzMomentum ex1Rot = (dip1->R)*deltap1;
hkPtr->hist("shoveInRestFrame")->fill(ex2Rot.perp()/GeV,hkPtr->currentWeight());
hkPtr->hist("shoveInRestFrame")->fill(ex1Rot.perp()/GeV,hkPtr->currentWeight());
}
dip2->recoil(deltap2);
dip1->recoil(deltap1);
pp1->setMomentum(p1new);
pp2->setMomentum(p2new);
}
else if(hkPtr){
LorentzMomentum ex2Rot = (dip2->R)*deltap2;
LorentzMomentum ex1Rot = (dip1->R)*deltap1;
hkPtr->hist("rejectedShoveInRestFrame")->fill(ex2Rot.perp()/GeV,hkPtr->currentWeight());
hkPtr->hist("rejectedShoveInRestFrame")->fill(ex1Rot.perp()/GeV,hkPtr->currentWeight());
}
}
LorentzPoint direction(){
// This gives the push direction
return (pp2->vertex()-pp1->vertex());
}
double y;
Energy gluonMass;
PPtr pp1, pp2;
Ropewalk::Dipole* dip1;
Ropewalk::Dipole* dip2;
};
void Ropewalk::shoveTheDipoles() {
typedef multimap<double, Ropewalk::Dipole *> RMap;
RMap rapDipoles;
// Order the dipoles in maxrapidity and insert new, excited dipole ends
double ymin = 0;
double ymax = 0;
for(int i = 0, N = dipoles.size(); i < N ;++i){
if(dipoles[i].pc->decayed()){
// Set epc to the decay product of pc here
dipoles[i].epc = dipoles[i].pc->children()[0];
}
else{
// Make a new particle
dipoles[i].epc = CurrentGenerator()->getParticle(dipoles[i].pc->id());
dipoles[i].epc->setMomentum(dipoles[i].pc->momentum());
dipoles[i].epc->setVertex(dipoles[i].pc->vertex());
step().addDecayProduct(dipoles[i].pc,dipoles[i].epc, false);
}
if(dipoles[i].pa->decayed()){
// Set epa to the decay product of pa here
dipoles[i].epa = dipoles[i].pa->children()[0];
}
else{
dipoles[i].epa = CurrentGenerator()->getParticle(dipoles[i].pa->id());
dipoles[i].epa->setMomentum(dipoles[i].pa->momentum());
dipoles[i].epa->setVertex(dipoles[i].pa->vertex());
step().addDecayProduct(dipoles[i].pa,dipoles[i].epa, false);
}
// order the dipoles in max rapidity
rapDipoles.insert(make_pair(dipoles[i].maxRapidity(), &dipoles[i]));
// find maximal and minimal rapidity to sample
if(dipoles[i].minRapidity() < ymin)
ymin = dipoles[i].minRapidity();
if(dipoles[i].maxRapidity() > ymax)
ymax = dipoles[i].maxRapidity();
}
vector<double> rapidities;
// cout << rCutOff/femtometer << " " << gAmplitude/GeV << " " << gExponent << " " << yCutOff << " " << deltay << " " << tshove/femtometer << " " << deltat/femtometer << endl;
// We can let the gluon go off-shell between the pushes,
// and on-shell again towards the end
// Not fully implemented yet! Do not toggle this on!
bool gluonMass = false;
// Maybe do better sampling
for(double y = ymin; y < ymax; y+=deltay)
rapidities.push_back(y);
// For each value of ySample, we should have
// an excitation pair per dipole we want to treat
typedef map<double, vector<Exc> > ExMap;
ExMap exPairs;
Energy gMass = 0.001*keV;
for(int i = 0, N = rapidities.size(); i < N; ++i){
// find dipoles that are sampled here
// and store them temporarily
double ySample = rapidities[i];
vector<Ropewalk::Dipole*> tmp;
for(RMap::iterator rItr = rapDipoles.lower_bound(ySample);
rItr != rapDipoles.end(); ++rItr){
if(rItr->second->minRapidity() < ySample)
tmp.push_back(rItr->second);
}
// Construct the excitation particles, one for each sampled dipole
vector<PPtr> eParticles;
// dipoles to erase
vector<int> eraseDipoles;
for(int j = 0, M = tmp.size(); j < M; ++j){
// Test if it is possible to add the small excitation to
// the dipole
Energy pz = gMass*sinh(ySample);
Energy e = gMass*cosh(ySample);
LorentzMomentum ex = LorentzMomentum(0.0*GeV,
0.0*GeV,pz,e);
if(tmp[j]->recoil(ex,true)){
// Add the excitation
tmp[j]->recoil(ex);
eParticles.push_back(CurrentGenerator()->getParticle(21));
eParticles.back()->setMomentum(ex);
}
else{
// if it was not possible, remove the dipole from the list
// but NOT inside the loop
eraseDipoles.push_back(j);
}
}
// Erase dipoles which could not bear an excitation
for(int j = 0, M = eraseDipoles.size(); j < M; ++j){
tmp.erase(tmp.begin() + (eraseDipoles[j]-j) );
}
// Construct all pairs of possible excitations in this slice
exPairs[ySample] = vector<Exc>();
for(int j = 0, M = tmp.size(); j < M; ++j)
for(int k = j + 1; k < M; ++k){
// Both dipoles should span the full rapidity interval
if(tmp[j]->maxRapidity() >= ySample+deltay/2.0 && tmp[k]->maxRapidity() >= ySample+deltay/2.0
&& tmp[j]->minRapidity() <= ySample-deltay/2.0
&& tmp[k]->minRapidity() <= ySample-deltay/2.0){
exPairs[ySample].push_back(Exc(ySample,gMass,eParticles[j],eParticles[k],tmp[j],tmp[k]));
}
}
}
// For all times
int ii = 0;
for(Length t = 0*femtometer; t < tshove; t+=deltat){
++ii;
// For all slices
for(ExMap::iterator slItr = exPairs.begin(); slItr != exPairs.end(); ++slItr)
// For all excitation pairs
for(int i = 0, N = slItr->second.size(); i < N; ++i){
Exc& ep = slItr->second[i];
LorentzPoint direction = ep.direction();
Length dist = direction.perp();
if(hkPtr && ii < 6){
Histogram* hd = hkPtr->hist("dist"+to_string(ii));
hd->fill(dist/femtometer,hkPtr->currentWeight());
}
if(dist < rCutOff){
double gamma = 1.0;
if(lorentz){
LorentzMomentum pp = ep.dip1->momentum() + ep.dip2->momentum();
LorentzMomentum p1 = (ep.dip1->R)*pp;
LorentzMomentum p2 = (ep.dip2->R)*pp;
double gamma1 = sqrt(1 - sqr(p1.perp()/p1.e()));
double gamma2 = sqrt(1 - sqr(p2.perp()/p2.e()));
gamma = min(gamma1,gamma2);
}
Energy gain = 0*GeV;
if(cylinderShove){
if(dist > R0*gExponent){
Length R = R0*gExponent;
Area area = 2*R*R*acos(dist/2/R) - 0.5*dist*sqrt(4*R*R - dist*dist);
Energy inner = gAmplitude*area/M_PI/R/R;
gain = gamma*(sqrt((1*GeV + inner)*(1*GeV + inner)) - 1*GeV);
}
else{
continue;
}
}
else{
gain = gamma*deltay*deltat*gAmplitude/R0/gExponent/sqrt(2*M_PI)*
exp(-dist*dist/2/gExponent/gExponent/R0/R0);
}
Energy dpx = gain*direction.x()/dist;
Energy dpy = gain*direction.y()/dist;
// Print stuff
if(hkPtr && ii < 6){
Histogram* h = hkPtr->hist("shove"+to_string(ii));
h->fill(gain/MeV,hkPtr->currentWeight());
}
ep.shove(dpx,dpy,hkPtr);
}
}
// Propagate the dipoles
for(int i = 0, Nd = dipoles.size(); i < Nd; ++i)
dipoles[i].propagate(deltat, deltay);
}
// Now add the excitations to the dipoles
for(int i = 0, Nd = dipoles.size(); i < Nd; ++i){
if(dipoles[i].excitations.size() > 0)
dipoles[i].excitationsToString(gluonMass, yCutOff, hkPtr);
else{
dipoles[i].epc->antiColourConnect(dipoles[i].epa);
}
}
}
multimap< double, pair<double, double> > Ropewalk::Dipole::getDistPairs(){
// Fill a container with the particle pair rapidities in lab system,
// ordered by their spans
multimap< double, pair<double, double> > distPairs;
DipEx::iterator iplusone = excitations.begin();
++iplusone;
for(DipEx::iterator itr = excitations.begin(); itr != excitations.end(); ++itr,++iplusone){
if(itr == excitations.begin()){
// First -- special
LorentzMomentum p1 = (pa->momentum().rapidity() == minRapidity() ?
pa->momentum() : pc->momentum());
Energy2 s = (p1 + itr->second->momentum()).m2();
double ysep = (s > sqr(m0) ? 0.5*log(s/sqr(m0)) : 0.0);
distPairs.insert(make_pair(ysep, make_pair(minRapidity(),itr->first)) );
}
if(iplusone == excitations.end()){
// Last -- special
LorentzMomentum p1 = (pa->momentum().rapidity() == maxRapidity() ?
pa->momentum() : pc->momentum());
Energy2 s = (p1 + itr->second->momentum()).m2();
double ysep = (s > sqr(m0) ? 0.5*log(s/sqr(m0)) : 0.0);
distPairs.insert(make_pair(ysep, make_pair(itr->first,maxRapidity())) );
}
else{
Energy2 s = (itr->second->momentum() + iplusone->second->momentum()).m2();
double ysep = (s > sqr(m0) ? 0.5*log(s/sqr(m0)) : 0.0);
distPairs.insert(make_pair(ysep, make_pair(itr->first,iplusone->first)));
}
}
return distPairs;
}
void Ropewalk::Dipole::excitationsToString(bool gluonMass, double yCutOff, HistKeeper* hkPtr){
if(gluonMass){
cout << "Oops! Not implemented yet!" << endl;
return;
}
bool clustering = true;
if(clustering){
// Clustering
//
// For all excitation neighbors in the lab-system,
// we calculate their effective rapidity span
// and keep only those above yCutOff
multimap<double, pair<double, double> > distPairs = getDistPairs();
if(hkPtr){
for(auto itr = distPairs.begin(); itr != distPairs.end(); ++itr)
hkPtr->hist("yDistBefore")->fill(itr->first,hkPtr->currentWeight());
}
if(distPairs.begin() != distPairs.end())
while(distPairs.begin()->first < yCutOff){
// There is only one excitation on the string
// The ends will share the momentum provided
// that both distances are small
multimap<double, pair<double, double> >::iterator itr = distPairs.begin();
if(distPairs.size() == 2 && distPairs.rbegin()->first < yCutOff){
DipEx::iterator exP = excitations.find(itr->second.second);
if(exP == excitations.end())
exP = excitations.find(itr->second.first);
LorentzMomentum panew = epa->momentum() +
0.5*exP->second->momentum();
LorentzMomentum pcnew = epc->momentum() +
0.5*exP->second->momentum();
epa->setMomentum(panew);
epc->setMomentum(pcnew);
excitations.erase(exP);
}
// If it is the first piece, put the momentum on the dipole end
else if(itr->second.first == minRapidity()){
LorentzMomentum pnew = (epa->momentum().rapidity() == minRapidity() ?
epa->momentum() : epc->momentum());
pnew+=excitations[itr->second.second]->momentum();
if(epa->momentum().rapidity() == minRapidity())
epa->setMomentum(pnew);
else
epc->setMomentum(pnew);
// Erase the excitation
excitations.erase(itr->second.second);
}
// If it is the last piece ditto...
else if(itr->second.second == maxRapidity()){
LorentzMomentum pnew = (epa->momentum().rapidity() == maxRapidity() ?
epa->momentum() : epc->momentum());
pnew+=excitations[itr->second.first]->momentum();
if(epa->momentum().rapidity() == maxRapidity())
epa->setMomentum(pnew);
else
epc->setMomentum(pnew);
// Erase the excitation
excitations.erase(itr->second.first);
}
else{
LorentzMomentum pnew = excitations[itr->second.first]->momentum() +
excitations[itr->second.second]->momentum();
// update the first
excitations[itr->second.first]->setMomentum(pnew);
// erase the second
excitations.erase(itr->second.second);
}
// We can surely do better than recalculating everything
// each time - lets see if it kills us
if(excitations.empty())
break;
distPairs = getDistPairs();
}
if(hkPtr){
hkPtr->hist("nExcitations")->fill(excitations.size(),hkPtr->currentWeight());
for(auto itr = distPairs.begin(); itr != distPairs.end(); ++itr)
hkPtr->hist("yDistAfter")->fill(itr->first,hkPtr->currentWeight());
}
//
}
// Go through the remaining excitations and sanity check them
for(DipEx::iterator itr = excitations.begin(); itr != excitations.end(); ++itr){
// In the dipole rest frame, we should have pz == 0
//LorentzMomentum ppmom = R*itr->second->momentum();
//LorentzMomentum ppn(ppmom.x(),ppmom.y(),0*GeV,ppmom.t());
//itr->second->setMomentum(R.inverse()*ppn);
LorentzMomentum ppm = itr->second->momentum();
if(fabs(ppm.x()/GeV) < 1e-5 && fabs(ppm.y()/GeV) < 1e-5 && fabs(ppm.z()/GeV) < 1e-5 )
excitations.erase(itr);
else if(hkPtr){
hkPtr->hist("excitationPt")->fill(ppm.perp()/GeV,hkPtr->currentWeight());
LorentzMomentum ppr = R*ppm;
hkPtr->hist("excitationRestFramePt")->fill(ppr.perp()/GeV,hkPtr->currentWeight());
}
}
// If we dont have any excitations, we are done
if(excitations.empty()){
epa->colourConnect(epc);
return;
}
// Flag if we start from the colored parton
bool color = false;
// Link the first excitation to the dipole end with the smallest rapidity
if(minRapidity() == epc->momentum().rapidity()){
epa->colourConnect(excitations.rbegin()->second);
epc->antiColourConnect(excitations.begin()->second);
//excitations.begin()->second->colourConnect(epc);
//excitations.rbegin()->second->antiColourConnect(epa);
step().addDecayProduct(pc,excitations.begin()->second,false);
color = true;
}
else{
epa->colourConnect(excitations.begin()->second);
epc->antiColourConnect(excitations.rbegin()->second);
//excitations.begin()->second->antiColourConnect(epa);
//excitations.rbegin()->second->colourConnect(epc);
step().addDecayProduct(pa,excitations.begin()->second,false);
}
// If we have only one excitation, we are quickly done
if(excitations.size() == 1)
return;
// We have more...
DipEx::iterator iplusone = excitations.begin();
++iplusone;
for(DipEx::iterator itr = excitations.begin(); iplusone != excitations.end(); ++itr,++iplusone){
// Are we halfway through?
bool halfway = double(distance(excitations.begin(),iplusone))/double(excitations.size()) > 0.5;
if(color){
itr->second->antiColourConnect(iplusone->second);
//iplusone->second->colourConnect(itr->second);
step().addDecayProduct((halfway ? pa : pc), iplusone->second,false);
}
else{
itr->second->colourConnect(iplusone->second);
//iplusone->second->antiColourConnect(itr->second);
step().addDecayProduct((halfway ? pc : pa), iplusone->second,false);
}
}
}
void Ropewalk::Dipole::propagate(Length deltat, double deltay){
const Lorentz5Momentum& pcm = epc->momentum();
const Lorentz5Momentum& pam = epa->momentum();
if(pcm.e()/GeV == 0 || pam.e()/GeV == 0)
Throw<ColourException>()
<< "Tried to propagate a dipole end with energy 0; this should never happen."
<< "This is a serious error - please contact the authors."
<< Exception::abortnow;
// Propagate in dipole rest frame
bc = R*(bc + deltat * pcm/(pcm.e()));
ba = R*(ba + deltat * pam/(pam.e()));
// Propagate in the lab frame
LorentzPoint bclab = epc->vertex() + deltat*pcm/pcm.e();
LorentzPoint balab = epa->vertex() + deltat*pam/pam.e();
epc->setVertex(bclab);
epa->setVertex(balab);
//const_cast<ThePEG::Particle& >((*pc)).setVertex(bclab);
//const_cast<ThePEG::Particle& >((*pa)).setVertex(balab);
for(DipEx::iterator eItr = excitations.begin(); eItr != excitations.end(); ++eItr){
const Lorentz5Momentum& em = eItr->second->momentum();
// Propagate excitations only in lab frame
// only if it has been pushed
if(em.e()/GeV > 0){
eItr->second->setVertex(eItr->second->vertex() + deltat*em/(em.perp() + m0*deltay*deltay));
}
else{
eItr->second->setVertex(pointAtRap(eItr->first));
}
}
}
void Ropewalk::doBreakups() {
typedef multimap<double, const Dipole *> BMap;
BMap breakups;
// First order alldipoles in increasing probability of breaking
for ( int i = 0, N = dipoles.size(); i < N; ++i )
breakups.insert(make_pair(dipoles[i].breakupProbability(), &dipoles[i]));
// Then start breaking in reverse order
mspec.clear();
for ( BMap::reverse_iterator it = breakups.rbegin();
it != breakups.rend(); ++it ) {
const Dipole & d = *it->second;
if ( d.breakupProbability() < UseRandom::rnd() ) continue;
mspec.push_back(d.s()/GeV2);
double hinv = 1.0 / d.kappaEnhancement();
// The default parameters should be set
// properly from the outside. Now just Pythia8 defaults
double rho = pow(0.215, hinv);
double x = pow(1.0,hinv);
double y = pow(0.027,hinv);
Selector<int> qsel;
qsel.clear();
if(UseRandom::rnd() < junctionDiquarkProb){
// Take just ordinary quarks
qsel.insert(1.0, ParticleID::ubar);
qsel.insert(1.0, ParticleID::dbar);
qsel.insert(rho, ParticleID::sbar);
}
else {
// Take diquarks
// TODO (Pythia 8.2) Set status code of these diquarks to 74
qsel.insert(1.0, ParticleID::ud_0);
qsel.insert(3.0*y, ParticleID::dd_1);
qsel.insert(3.0*y, ParticleID::ud_1);
qsel.insert(3.0*y, ParticleID::uu_1);
qsel.insert(rho*x, ParticleID::su_0);
qsel.insert(3*x*rho*y, ParticleID::su_1);
qsel.insert(3*y*x*x*rho*rho, ParticleID::ss_1);
qsel.insert(rho*x, ParticleID::sd_0);
qsel.insert(3*x*rho*y, ParticleID::sd_1);
}
int flav = qsel[UseRandom::rnd()];
PPtr dic = CurrentGenerator()->getParticle(flav);
PPtr dia = CurrentGenerator()->getParticle(-flav);
//cout << (dic->momentum() + dia->momentum()).m2() / GeV2 << " " << d.s() / GeV2 << endl;
if((dic->momentum() + dia->momentum()).m2() > d.s()) continue;
// Get boost to dipole rest frame and place the di-quarks there.
LorentzRotation R = Utilities::getBoostFromCM(make_pair(d.pc, d.pa));
SimplePhaseSpace::CMS(dic, dia, d.s(), 1.0, 0.0);
dia->transform(R);
dic->transform(R);
// Add the di-quarks as children to the decayed gluons and split
// the resulting string.
if ( !( step().addDecayProduct(d.pc, dic, true) &&
step().addDecayProduct(d.pa, dia, true) &&
step().addDecayProduct(d.pc, dia, false) &&
step().addDecayProduct(d.pa, dic, false)) )
Throw<ColourException>()
<< "Adding decay products failed in Ropewalk. "
<< "This is a serious error - please contact the authors."
<< Exception::abortnow;
tcParticleSet pset(d.string->partons().begin(), d.string->partons().end());
pset.erase(d.pc);
pset.erase(d.pa);
pset.insert(dic);
pset.insert(dia);
// Reset the neighboring dipoles to point to the new diquarks.
d.broken = true;
ColourSinglet * olds = d.string;
const vector<Dipole *> & oldd = stringdipoles[olds];
for ( int id = 0, Nd = oldd.size(); id < Nd; ++id ) {
if ( oldd[id]->pc == d.pa ) oldd[id]->pc = dia;
if ( oldd[id]->pa == d.pc ) oldd[id]->pa = dic;
}
// remove the old string and insert the new ones fixing the
// pointers from the dipoles.
vector<ColourSinglet> newstrings =
ColourSinglet::getSinglets(pset.begin(), pset.end());
for ( int is = 0, Ns = newstrings.size(); is < Ns; ++is ) {
ColourSinglet * news = new ColourSinglet(newstrings[is]);
tcParticleSet pset(news->partons().begin(), news->partons().end());
vector<Dipole *> & newd = stringdipoles[news];
for ( int id = 0, Nd = oldd.size(); id < Nd; ++id ) {
if ( !oldd[id]->broken && pset.find(oldd[id]->pc) != pset.end() ) {
newd.push_back(oldd[id]);
oldd[id]->string = news;
}
}
sort(newd, news->partons()[0]);
}
stringdipoles.erase(olds);
delete olds;
}
}
vector< pair<ColourSinglet,double> > Ropewalk::getSinglets(double DeltaY) const {
vector< pair<ColourSinglet,double> > ret;
ret.reserve(stringdipoles.size());
double toty = 0.0;
double totyh = 0.0;
double toth = 0.0;
double toth2 = 0.0;
double minh = 10.0;
double maxh = 0.0;
// Calculate the kappa-enhancement of the remaining strings.
for ( DipoleMap::const_iterator it = stringdipoles.begin();
it != stringdipoles.end(); ++it ) {
double sumyh = 0.0;
double sumy = 0.0;
for ( int id = 0, Nd = it->second.size(); id < Nd; ++id ) {
double y = it->second[id]->yspan(m0);
double h = it->second[id]->kappaEnhancement();
avh += h*it->second[id]->yspan(1.0*GeV);
strl += it->second[id]->yspan(1.0*GeV);
if ( DeltaY > 0.0 &&
abs(it->second[id]->pc->eta()) > DeltaY &&
abs(it->second[id]->pa->eta()) > DeltaY ) continue;
sumy += y;
sumyh += y*h;
}
toty += sumy;
totyh += sumyh;
if ( sumy > 0.0 ) {
double h = 0.1*int(10.0*sumyh/sumy + UseRandom::rnd());
ret.push_back(make_pair(*it->first, h));
toth += sumyh/sumy;
toth2 += sqr(sumyh/sumy);
minh = min(minh, sumyh/sumy);
maxh = max(maxh, sumyh/sumy);
} else {
ret.push_back(make_pair(*it->first, 1.0));
toth += 1.0;
toth2 += 1.0;
minh = min(minh, 1.0);
maxh = max(maxh, 1.0);
}
}
if ( debug )
CurrentGenerator::log() << ret.size() << "ns "
<< totyh/max(toty, 0.00001) << "hwa "
<< minh << "<h "
<< toth/ret.size() << "ha "
<< maxh << ">h "
<< sqrt(toth2/ret.size() - sqr(toth/ret.size())) << "hsd " << endl;
if ( avh > 0.0 ) avh /= strl;
if ( avp > 0.0 ) avp /= strl0;
if ( avq > 0.0 ) avq /= strl0;
return ret;
}
double Ropewalk::averageKappaEnhancement(const vector<Dipole *> & dipoles,
double DeltaY) const {
double sumyh = 0.0;
double sumy = 0.0;
for ( int id = 0, Nd = dipoles.size(); id < Nd; ++id ) {
dipoles[id]->reinit(UseRandom::rnd(), R0, m0);
double y = dipoles[id]->yspan(m0);
double h = dipoles[id]->firstKappa();
if ( DeltaY > 0.0 &&
abs(dipoles[id]->pc->eta()) > DeltaY &&
abs(dipoles[id]->pa->eta()) > DeltaY ) continue;
sumy += y;
sumyh += y*h;
}
if ( sumy <= 0.0 ) return 1.0;
return sumyh/sumy;
}
void Ropewalk::sort(vector<Dipole *> & dips, tcPPtr p) {
if ( p->antiColourLine() ) {
map<tcPPtr, Dipole *> dmap;
Dipole * current = 0;
for ( int i = 0, N = dips.size(); i < N; ++i ) {
if ( dips[i]->pa == p ) current = dips[i];
else dmap[dips[i]->pa] = dips[i];
}
dips.clear();
while ( current ) {
dips.push_back(current);
map<tcPPtr, Dipole *>::iterator it = dmap.find(current->pc);
if ( it == dmap.end() ) current = 0;
else {
current = it->second;
dmap.erase(it);
}
}
if ( !dmap.empty() )
Throw<ColourException>()
<< "Failed to sort dipoles in Ropewalk. "
<< "This is a serious error - please contact the authors."
<< Exception::abortnow;
} else {
map<tcPPtr, Dipole *> dmap;
Dipole * current = 0;
for ( int i = 0, N = dips.size(); i < N; ++i ) {
if ( dips[i]->pc == p ) current = dips[i];
else dmap[dips[i]->pc] = dips[i];
}
dips.clear();
while ( current ) {
dips.push_back(current);
map<tcPPtr, Dipole *>::iterator it = dmap.find(current->pa);
if ( it == dmap.end() ) current = 0;
else {
current = it->second;
dmap.erase(it);
}
}
if ( !dmap.empty() )
Throw<ColourException>()
<< "Failed to sort dipoles in Ropewalk. "
<< "This is a serious error - please contact the authors."
<< Exception::abortnow;
}
}
diff --git a/Hadronization/Ropewalk.h b/Hadronization/Ropewalk.h
--- a/Hadronization/Ropewalk.h
+++ b/Hadronization/Ropewalk.h
@@ -1,727 +1,733 @@
// -*- C++ -*-
#ifndef TheP8I_Ropewalk_H
#define TheP8I_Ropewalk_H
//
// This is the declaration of the Ropewalk class.
//
#include "TheP8I/Config/TheP8I.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/EventRecord/ColourSinglet.h"
#include "ThePEG/Utilities/UtilityBase.h"
+#include "ThePEG/Utilities/Throw.h"
#include "HistKeeper.h"
namespace std {
template <>
struct less<ThePEG::ColourSinglet *> :
public binary_function<ThePEG::ColourSinglet *,
ThePEG::ColourSinglet *, bool>
{
/**
* This is the function called when comparing two pointers to
* type_info.
*/
bool operator()(const ThePEG::ColourSinglet * x,
const ThePEG::ColourSinglet * y) const {
if ( x && y ) return x->partons() < y->partons();
return !y;
}
};
}
namespace TheP8I {
using namespace ThePEG;
/**
* Here is the documentation of the Ropewalk class.
*/
class Ropewalk {
public:
double lambdaBefore;
vector<double> mspec;
/**
* Forward declaration of a Dipole.
*/
struct Dipole;
/**
* Container class storing information of a dipole overlapping with another;
*/
struct OverlappingDipole {
/**
* Standard constructor.
*/
OverlappingDipole(const Dipole & d,
const LorentzRotation R, const Ropewalk * rw);
/**
* Check if ovelapping at specific rapidity.
*/
bool overlap(double y, LorentzPoint b1, Length R0) {
if ( y < min(ya, yc) || y > max(ya, yc) ) return false;
LorentzPoint b2 = ba + (bc - ba)*(y - ya)/(yc - ya);
return (b1 - b2).perp() <= R0;
}
LorentzPoint pointAtRap(double y){
return ba + (bc - ba)*(y - ya)/(yc - ya);
}
/**
* Pointer to the dipole.
*/
const Dipole * dipole;
/**
* The boosted rapidities.
*/
double yc, ya;
/**
* The propagated and boosted positions.
*/
LorentzPoint bc, ba;
/**
* Relative direction.
*/
int dir;
/**
* Initially estimated fraction of overlap.
*/
double yfrac;
};
/**
* Container class containing information about overlaps for a dipole.
* *** ATTENTION *** the meaning of pa and pc is reversed: pa is
* always the COLOURED and pc is always the ANTI-COLOURED
*/
struct Dipole {
struct DipoleException : public Exception {};
/**
* Constructor.
*/
Dipole(tcPPtr p1, tcPPtr p2, ColourSinglet & str, Energy m0In)
: pc(p2), pa(p1), string(&str), n(0), m(0), p(1), q(0), nb(0), broken(false), hadr(false), m0(m0In) {
if(pc->colourLine() != pa->antiColourLine())
swap(pc,pa);
LorentzMomentum pcm = pc->momentum();
LorentzMomentum pam = pa->momentum();
//if(pcm.x()/GeV == 0 && pcm.y()/GeV == 0 && pcm.z()/GeV == 0 && pcm.e()/GeV == 0)
//cout << pc->id() << " " << pa->id() << endl;
//cout << pam.x()/GeV << " " << pam.y()/GeV << " " << pam.z()/GeV << " " << pam.e()/GeV << endl;
+ if ( (pcm + pam).m2() < 0.000001*GeV2 )
+ Throw<DipoleException>()
+ << "Ropewalk found a minisculedipole. This should not happen, "
+ << "but hoping it is just a fluke and throwing away the event."
+ << Exception::eventerror;
R = Utilities::boostToCM(make_pair(&pcm,&pam) );
}
/**
* Return true if this dipole is breakable. Only dipoles between
* gluons (not belonging to other dipoles which have broken) and
* which has a mass above 2 GeV can break.
*/
bool breakable() const {
return !broken && pc->id() == ParticleID::g && pa->id() == ParticleID::g &&
!pc->decayed() && !pa->decayed() && s() > 4.0*GeV2;
}
/**
* Calculate the probability that this dipole should break. Taking
* into account the number of negative steps in the colour space
* and the fraction of overlapping dipoles which are able to
* break.
*/
double breakupProbability() const;
void clear(){
overlaps.clear();
n = 0, m = 0, p = 1, q = 0, nb = 0, broken = false, hadr = false;
}
// Propagate the particles and the excitations
void propagate(Length deltat, double deltay);
/**
* The minimal rapidity in the lab system of the excited dipole ends
*/
double minRapidity() const {
//double y1 = 0.5*log(epc->Pplus()/epc->Pminus());
//double y2 = 0.5*log(epa->Pplus()/epa->Pminus());
double y1 = epc->momentum().rapidity();
double y2 = epa->momentum().rapidity();
return min(y1,y2);
}
/**
* The maximal rapidity in the lab system
*/
double maxRapidity() const {
//double y1 = 0.5*log(epc->Pplus()/epc->Pminus());
//double y2 = 0.5*log(epa->Pplus()/epa->Pminus());
double y1 = epc->momentum().rapidity();
double y2 = epa->momentum().rapidity();
return max(y1,y2);
}
/*
* The b-coordinate (in lab frame) of a point
* between the propagated particles, at lab-rapidity yIn
*/
LorentzPoint pointAtRap(double yIn) const {
double ymin = minRapidity();
double ymax = maxRapidity();
LorentzPoint bMin, bMax;
if (pc->momentum().rapidity() == ymin )
bMin = pc->vertex(), bMax = pa->vertex();
else
bMin = pa->vertex(), bMax = pc->vertex();
// We assume that the rapidity fraction stays the same,
// as we cannot calculate yIn in dipole rest frame
return bMin + (bMax - bMin)*(yIn - ymin)/(ymax - ymin);
}
/**
* Recalculate overlaps assuming a position a fraction ry from
* the coloured parton.
*/
double reinit(double ry, Length R0, Energy m0);
/**
* Set and return the effective multiplet.
*/
void initMultiplet();
void initNewMultiplet();
void initWeightMultiplet();
/**
* Calculate the multiplicity given pp and qq;
*/
static double multiplicity(int pp, int qq) {
return ( pp < 0 || qq < 0 || pp + qq == 0 )? 0.0:
0.5*(pp + 1)*(qq + 1)*(pp + qq + 2);
}
/**
* Calculate the average kappa-enhancement.
*/
double kappaEnhancement() const {
// return 1.0;
return 0.25*(p + q + 3 - p*q/double(p + q));
}
/**
* Calculate the kappa-enhancement in the first break-up.
*/
double firstKappa() const {
return 0.25*(2 + 2*p + q);
}
/**
* Calculate boosted kappa-enhancement.
*/
double firstKappa(double alpha) const {
if (alpha > 0)
return alpha*firstKappa();
return firstKappa();
}
/*
LorentzMomentum shoveOverlappers(double dipFrac, double m2Had, Length R0, Lorentz5Momentum pH){
// We first find the b-space point at the breaking point
LorentzPoint thisPoint = ba + (bc - ba)*dipFrac;
double thisy = pa->momentum().rapidity() +
(pc->momentum().rapidity() - pa->momentum().rapidity())*dipFrac;
Energy mp = sqrt(pH.mass2());
Energy mtd = sqrt(s());
Energy mSumH = sqrt(m2Had)*GeV;
double deltay = mp/(mtd - (mSumH - dipFrac*mtd)/(1 - dipFrac) );
// We then go through all dipoles
// overlapping in rapidity
Energy ex = 0*GeV, ey = 0*GeV;
for(int i = 0, N = overlaps.size(); i < N; ++i){
OverlappingDipole& od = overlaps[i];
// Must overlap at the breaking point
if (thisy < min(od.ya, od.yc) ||
thisy > max(od.ya, od.yc))
continue;
LorentzPoint otherPoint = od.pointAtRap(thisy);
LorentzPoint direction = thisPoint - otherPoint;
// The distance between the two dipoles
Length dist = direction.perp();
Energy gain = 2*fabs(deltay)*exp(-dist*dist/4/R0/R0)*GeV;
ex+=gain*direction.x()/dist;
ey+=gain*direction.y()/dist;
od.dipole->recoil(dipFrac,gain,direction);
}
Lorentz5Momentum ret(ex, ey, 0*GeV, 0*GeV);
return ret+pH;
}
*/
/**
* Push a dipole
*/
/*void recoil(double dipFrac, Energy gain, LorentzPoint direction) const {
LorentzMomentum pPush(-gain*direction.x()/direction.perp(), -gain*direction.y()/direction.perp(), 0*GeV, 0*GeV);
(void) pPush;
// We go to the dipole rest frame
// and calculate the push on the ends
//Lorentz5Momentum pcPush = R*pPush + pc->momentum();
//Lorentz5Momentum paPush = R*pPush + pa->momentum();
// const_cast<ThePEG::Particle& >((*pc)).setMomentum(pcPush);
// const_cast<ThePEG::Particle& >((*pa)).setMomentum(paPush);
}
*/
/**
* return the momentum of this dipole
*/
LorentzMomentum momentum() const {
return pc->momentum() + pa->momentum();
}
/**
* Return the squared invariant mass of this dipole.
*/
Energy2 s() const {
return (pc->momentum() + pa->momentum()).m2();
}
/**
* Return the effective rapidityspan of this dipole.
*/
double yspan(Energy m0) const {
return s() > sqr(m0)? 0.5*log(s()/sqr(m0)): 0.0;
}
/**
* The coloured particle.
*/
mutable tcPPtr pc;
/**
* The anti-coloured particle.
*/
mutable tcPPtr pa;
/**
* The coloured, excited particle
*/
PPtr epc;
/**
* The anti-coloured, excited particle
*/
PPtr epa;
/*
* All excitations belonging to this dipole ordered in
* rapidity in lab system
*/
typedef map<double, PPtr> DipEx;
DipEx excitations;
void printExcitations() {
for(DipEx::iterator itr = excitations.begin(); itr != excitations.end(); ++itr){
cout << itr->first << " " << itr->second->rapidity() << " " << itr->second->momentum().perp()/GeV << endl;
}
}
/*
* Recoil the dipole from adding a gluon
* this function will not actually add the gluon, only the
* recoil, if possible, and return true or false if it was
*/
bool recoil(LorentzMomentum& pg, bool dummy = false){
// Keep track of direction
int sign = 1;
if(epc->rapidity() < epa->rapidity())
sign = -1;
// lc momenta after inserting the gluon
Energy pplus = epc->Pplus() + epa->Pplus() - pg.plus();
Energy pminus = epc->Pminus() + epa->Pminus() - pg.minus();
// The new lightcone momenta of the dipole ends
Energy ppa = 0.0*GeV;
Energy ppc = 0.0*GeV;
Energy pma = 0.0*GeV;
Energy pmc = 0.0*GeV;
Energy4 sqarg = sqr(pplus*pminus + epa->mt2() - epc->mt2()) -
4.0*epa->mt2()*pplus*pminus;
// Calculate the new momenta
if(sqarg >= 0.0*GeV*GeV*GeV*GeV){
if(sign > 0){
ppa = (pplus*pminus + epa->mt2() - epc->mt2() +
sqrt(sqarg))*0.5/pminus;
pma = epa->mt2()/ppa;
pmc = pminus - pma;
ppc = epc->mt2()/pmc;
}
else{
pma = (pplus*pminus + epa->mt2() - epc->mt2() +
sqrt(sqarg))*0.5/pplus;
ppa = epa->mt2()/pma;
ppc = pplus - ppa;
pmc = epc->mt2()/ppc;
}
LorentzMomentum shifta = LorentzMomentum(epa->momentum().x(),epa->momentum().y(),
0.5*(ppa - pma),0.5*(ppa + pma));
LorentzMomentum shiftc = LorentzMomentum(epc->momentum().x(), epc->momentum().y(),
0.5*(ppc - pmc), 0.5*(ppc + pmc));
if(shifta.t() / GeV < 0 || shiftc.t() / GeV < 0)
return false;
// Assign the new momenta
if(!dummy){
epa->setMomentum(shifta);
epc->setMomentum(shiftc);
}
return true;
}
// We could not shift the momenta
return false;
}
/*
* Insert an excitation provided that it is not already there
*/
void addExcitation(double ylab, PPtr ex){
auto ret = excitations.equal_range(ylab);
for(auto itr = ret.first; itr != ret.second; ++itr )
if(ex == itr->second){
return;
}
excitations.insert(make_pair(ylab,ex));
}
/*
* Add all excitations to the dipole
*/
void excitationsToString(bool gluonMass, double yCutOff, HistKeeper* hkPtr = NULL);
/*
* Extract the distance between all adjecant excitation pairs on a dipole
*/
multimap< double, pair<double, double> > getDistPairs();
/**
* Return the current step.
*/
Step & step() const;
/**
* The propagated and boosted positions.
*/
LorentzPoint bc, ba;
/**
* The Lorentz rotation taking us to this dipole's rest system
*/
LorentzRotation R;
/**
* The overlapping dipoles with the amount of overlap (negative
* means anti overlap).
*/
vector<OverlappingDipole> overlaps;
/**
* The string to which this Dipole belongs.
*/
ColourSinglet * string;
/**
* The summed parallel (n) and anti-parallel (m) overlaps from
* other dipoles.
*/
int n, m;
/**
* The multiplet.
*/
int p, q;
/**
* The number of baryons from junctions
*/
int nb;
/**
* Indicate that this dipole has been broken.
*/
mutable bool broken;
mutable bool hadr;
/*
* The m0 parameter
*/
Energy m0;
};
/**
* Convenient typedef
*/
typedef map<ColourSinglet *, vector<Dipole *> > DipoleMap;
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
Ropewalk(const vector<ColourSinglet> & singlets, Length width,
Energy scale, double jDC, bool throwaway = true, bool shoving = true, double rcIn = 5.0, Energy gaIn = 1.0*GeV, double geIn = 1.0, double ycIn = 4.0, double dyIn = 0.1, Length tsIn = 1.0*femtometer, Length dtIn = 1.0*femtometer, bool lorentzIn = true, bool cylinderIn = false, HistKeeper* hk = NULL, bool deb = false);
/**
* The destructor.
*/
virtual ~Ropewalk();
//@}
/**
* Return all ColourSinglet objects with their kappa enhancement.
*/
vector< pair<ColourSinglet,double> > getSinglets(double DeltaY = 0.0) const;
/**
* Calculate the average kappa-enhancement for the given colour
* singlet, optionally only taking into account dipoles the
* rapidity interval |y| < deltaY. Note that \a cs must point to a
* object in the stringdipoles map. @return -1 if cs is not found.
*/
double averageKappaEnhancement(ColourSinglet * cs, double deltaY = 0.0) const {
DipoleMap::const_iterator it = stringdipoles.find(cs);
if ( it == stringdipoles.end() ) return -1.0;
return averageKappaEnhancement(it, deltaY);
}
/**
* Calculate the average kappa-enhancement for the given iterator
* pointing into the stringdipoles map, optionally only taking
* into account dipoles the rapidity interval |y| < deltaY. Note
* that \a cs must point to a object in the stringdipoles
* map. @return -1 if something went wrong.
*/
double averageKappaEnhancement(DipoleMap::const_iterator it,
double deltaY = 0.0) const {
return averageKappaEnhancement(it->second, deltaY);
}
/**
* Calculate the average kappa-enhancement the given vector of
* dipoles, optionally only taking into account dipoles the
* rapidity interval |y| < deltaY. @return -1 if something went
* wrong.
*/
double averageKappaEnhancement(const vector<Dipole *> & dipoles,
double deltaY = 0.0) const;
/**
* Propagate a parton a finite time inthe lab-system.
*/
LorentzPoint propagate(const LorentzPoint & b,
const LorentzMomentum & p) const;
/**
/ Get number of juctions
*/
double getNb();
double getkW();
/**
/ Get m,n for all strings
*/
pair<double,double> getMN();
/**
/ Get lambda measure for event
*/
double lambdaSum(double cutoff = 0.1);
/**
* Calculate the rapidity of a Lorentz vector but limit the
* transverse mass to be above m0.
*/
double limitrap(const LorentzMomentum & p) const;
/**
* Sort the given vector of dipoles so that the particle \a p is
* first and the others follows in sequence. If \a p is a
* (anti-)triplet, it will be the pc(pa) of the first dipole, and
* the pc(pa) of the second will be the pa(pc) of the first and so
* on. If \a p is an octet, the direction will be as if it was a
* triplet.
*/
static void sort(vector<Dipole *> & dips, tcPPtr p);
protected:
/**
* Extract all dipoles.
*/
void getDipoles();
/**
* Calculate all overlaps and initialize multiplets in all dipoles.
*/
void calculateOverlaps(bool doPropagate);
/**
* Break dipoles (and strings)
*/
void doBreakups();
/**
* Shove the dipoles away from each other
*/
void shoveTheDipoles();
/**
* Return the current step.
*/
Step & step() const;
/**
* Make a copy of a ColourSinglet making sure all partons are final.
*/
ColourSinglet * cloneToFinal(const ColourSinglet & cs);
public:
DipoleMap::iterator begin() {
return stringdipoles.begin();
}
DipoleMap::iterator end() {
return stringdipoles.end();
}
/**
* Exception class.
*/
struct ColourException: public Exception {};
private:
/**
* The assumed radius of a string.
*/
Length R0;
/**
* The assumed mass for calculating rapidities
*/
Energy m0;
/*
* The junction colour fluctuation parameter
*/
double junctionDiquarkProb;
/*
* Cutoff distance where we no longer consider
* shoving
*/
Length rCutOff;
/*
* Amplitude af shoving function
*/
Energy gAmplitude;
/*
* Shoving function (inverse) multiplier
*/
double gExponent;
/*
* Cutoff in effective rapidity span when clustering
*/
double yCutOff;
/*
* Rapidity slicing for shoving
*/
double deltay;
/*
* Shoving time
*/
Length tshove;
/*
* Shoving time slicing
*/
Length deltat;
/**
* The vector of all Dipoles
*/
vector<Dipole> dipoles;
/**
* All Dipoles in all string
*/
DipoleMap stringdipoles;
/*
* Lorentz contraction of fields
*/
bool lorentz;
bool cylinderShove;
// For analysis
HistKeeper* hkPtr;
/**
* Debug flag.
*/
bool debug;
public:
mutable double strl0;
mutable double strl;
mutable double avh;
mutable double avp;
mutable double avq;
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
Ropewalk & operator=(const Ropewalk &);
double nb;
};
}
#endif /* TheP8I_Ropewalk_H */
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Tue, Jan 21, 2:09 AM (1 d, 14 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4243591
Default Alt Text
(60 KB)
Attached To
rTHEPEGPEIGHTIHG thepegpeightihg
Event Timeline
Log In to Comment