Page Menu
Home
HEPForge
Search
Configure Global Search
Log In
Files
F7879104
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
82 KB
Subscribers
None
View Options
diff --git a/DIPSY/Emitter.cc b/DIPSY/Emitter.cc
--- a/DIPSY/Emitter.cc
+++ b/DIPSY/Emitter.cc
@@ -1,942 +1,942 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the Emitter class.
//
//Commented
#include "Emitter.h"
#include "Parton.h"
#include "ShadowParton.h"
#include "Dipole.h"
#include "DipoleState.h"
#include "EffectiveParton.h"
#include "ThePEG/Utilities/Current.h"
#include "DipoleEventHandler.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Utilities/Throw.h"
#include "ThePEG/Utilities/DebugItem.h"
#include <iostream>
#ifdef ThePEG_TEMPLATES_IN_CC_FILE
// #include "Emitter.tcc"
#endif
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "gsl/gsl_sf_bessel.h"
using namespace DIPSY;
Emitter::~Emitter() {}
/*
* Just a shortcut to access the input parameter from the Current handler.
*/
InvEnergy Emitter::rMax() const {
return theRMax > 0.0*InvGeV? theRMax: Current<DipoleEventHandler>()->rMax();
}
/*
* Shortcut to access running alpha from the Current handler.
*/
double Emitter::alphaS(InvEnergy r) const {
return Current<DipoleEventHandler>()->alphaS(r);
}
/*
* The veto check for the overestimates done previously.
* This calculates the overestimated emission probability, and checks the
* actual probability it should have been in this point, and then returns
* true or false randomly depending on the ratio.
* Note that this is not the final distribution, as there are still more
* vetos done later.
*/
bool Emitter::OEVeto(DipolePtr dip, double y0, Parton::Point p) const {
//set up dipole sizes.
InvEnergy R13 = (dip->effectivePartons().first->position() - p).pt();
InvEnergy R23 = (dip->effectivePartons().second->position() - p).pt();
InvEnergy R12 = dip->size();
//Too large dipoles messes up the bessel functions, and will not make it
//through the p- veto anyways, so can be vetoed already now, to avoid
//errors from the bessel function.
if(R13*GeV > 100.0) return true;
if(R23*GeV > 100.0) return true;
if(R12*GeV > 100.0) return false;
//some more set up.
double bess13 = gsl_sf_bessel_K1(R13/rMax());
double bess23 = gsl_sf_bessel_K1(R23/rMax());
//this is the correct probability distribution used in the paper.
Energy2 correctDist = alphaBar(min(min(R13,R23),R12))/(M_PI*2.0*sqr(rMax()))*
(sqr(bess13) + sqr(bess23) - (sqr(R13) + sqr(R23) - sqr(R12))/
(R13*R23)*bess13*bess23);
// If we create dipoles which are larger than the original, the
// original partons will be distributed as dpt2/pt4. Here we may
// include an extra fudge factor to emulate a matrix element
// correction.
if ( R13 > R12 && R23 > R12 && Current<DipoleEventHandler>()->fudgeME() )
correctDist *= 1.0 - 1.0/(1.0 + cosh(dip->partons().first->y() -
dip->partons().second->y()));
//Now calculate the overestimated distribution in the same way as it is done in gerateY() and generateXT().
double Coe = alphaBar(R12/2.0)/M_PI*
sqr(gsl_sf_bessel_K1(R12/(2.0*rMax())))*
sqr(R12/(2.0*rMax()))*
(R12/(2.0*theRScale)+2.0);
if(R12>2.0*rMax()) //double check that this is ok!!!!
Coe *= sqrt(R12/(2.0*rMax()))*
exp(R12/(rMax())-2.0);
//this is the overestime
Energy2 overestimate = Coe*(1.0/(sqr(R13)*(R13/theRScale+2.0)) +
1.0/(sqr(R23)*(R23/theRScale+2.0)));
//if the overestimate is ok, this should never happen.
if( correctDist/overestimate > 1.0 )
Throw<EmitterException>()
<< "In DIPSY::Emitter " << name() << ": XT keep prob is " << correctDist/overestimate
<< " (r12 = " << R12*GeV << ", Rr13 = " << R13*GeV << ", r23 = " << R23*GeV << ")"
<< Exception::warning;
//generate a random number and check if veto or not.
if(correctDist/overestimate>UseRandom::rnd())
return false;
else
return true;
}
/*
* The veto check for the overestimates done previously using shadows.
* This calculates the overestimated emission probability, and checks the
* actual probability it should have been in this point, and then returns
* true or false randomly depending on the ratio.
* Note that this is not the final distribution, as there are still more
* vetos done later.
*/
bool Emitter::OEVeto(DipolePtr dip, tSPartonPtr sp1, tSPartonPtr sp2,
double y0, Parton::Point p) const {
//set up dipole sizes.
InvEnergy R13 = (dip->partons().first->position() - p).pt();
InvEnergy R23 = (dip->partons().second->position() - p).pt();
InvEnergy R12 = dip->size();
//Too large dipoles messes up the bessel functions, and will not make it
//through the p- veto anyways, so can be vetoed already now, to avoid
//errors from the bessel function.
if ( R13*GeV > 100.0 || R23*GeV > 100.0 ) return true;
if ( R12*GeV > 100.0 ) return false;
//some more set up.
double bess13 = gsl_sf_bessel_K1(R13/rMax());
double bess23 = gsl_sf_bessel_K1(R23/rMax());
//this is the correct probability distribution used in the paper.
Energy2 correctDist = alphaBar(min(min(R13,R23),R12))/(M_PI*2.0*sqr(rMax()))*
(sqr(bess13) + sqr(bess23) - (sqr(R13) + sqr(R23) - sqr(R12))/
(R13*R23)*bess13*bess23);
// If we create dipoles which are larger than the original, the
// original partons will be distributed as dpt2/pt4. Here we may
// include an extra fudge factor to emulate a matrix element
// correction.
if ( R13 > R12 && R23 > R12 && Current<DipoleEventHandler>()->fudgeME() )
correctDist *= 1.0 - 1.0/(1.0 + cosh(dip->partons().first->y() -
dip->partons().second->y()));
//Now calculate the overestimated distribution in the same way as it is done in gerateY() and generateXT().
double Coe = alphaBar(R12/2.0)/M_PI*
sqr(gsl_sf_bessel_K1(R12/(2.0*rMax())))*
sqr(R12/(2.0*rMax()))*
(R12/(2.0*theRScale)+2.0);
if(R12>2.0*rMax()) //double check that this is ok!!!!
Coe *= sqrt(R12/(2.0*rMax()))*
exp(R12/(rMax())-2.0);
//this is the overestime
Energy2 overestimate = Coe*(1.0/(sqr(R13)*(R13/theRScale+2.0)) +
1.0/(sqr(R23)*(R23/theRScale+2.0)));
//if the overestimate is ok, this should never happen.
//TODO: write a proper error message.
if ( correctDist/overestimate > 1.0 )
Throw<EmitterException>()
<< "In DIPSY::Emitter " << name() << ": XT keep prob is " << correctDist/overestimate
<< " (r12 = " << R12*GeV << ", Rr13 = " << R13*GeV << ", r23 = " << R23*GeV << ")"
<< Exception::warning;
//generate a random number and check if veto or not.
return !UseRandom::rndbool(correctDist/overestimate);
}
/*
* This corrects the overestimated emission probability in Y used in generateY().
* The correct emission rate is calculated for the rapidity in question and
* compared to the overestimate rate used in generateY().
* Note that this is not the final correct y-distribution, as there are still several
* vetos to be checked, it is just a step closer to the correct distribution.
*/
bool Emitter::YVeto(double y,DipolePtr dip, double Coe, double rateOE) const {
tEffectivePartonPtr p1 = dip->effectivePartons().first;
tEffectivePartonPtr p2 = dip->effectivePartons().second;
//calculate the correct rate at the rapidity y in question.
//TODO: member calculating cutoff, interface before/after recoil.
//Before recoil corresponds to order wrt propagator, after wrt final gluon.
InvEnergy cutoff = 0.99*0.5*
min(pTScale()/(p1->plus()*exp(y) + p1->pT().pt()/2.0),
min(pTScale()/(p2->plus()*exp(y) + p2->pT().pt()/2.0),
dip->size()/4.0)); //if ordered AFTER recoil
// InvEnergy cutoff = 0.99*
// min(2.0/3.0*pTScale()*exp(-y)/p1->plus(),
// min(2.0/3.0*pTScale()*exp(-y)/p2->plus(),
// dip->size()/4.0)); //if ordered BEFORE recoil
//calculate overestimated rate according the what is used in generateY().
double rate = 2.0*M_PI*Coe*log(1.0 + 2.0*theRScale/cutoff);
//generate rnd() and veto.
if(rate/rateOE > UseRandom::rnd()) //if exp(-...) big enough
return false; //keep
else
return true; //else veto
}
/*
* This corrects the overestimated emission probability in Y used in generateY().
* The correct emission rate is calculated for the rapidity in question and
* compared to the overestimate rate used in generateY().
* Note that this is not the final correct y-distribution, as there are still several
* vetos to be checked, it is just a step closer to the correct distribution.
*/
bool Emitter::YVeto(double y, DipolePtr dip, tSPartonPtr sp1, tSPartonPtr sp2,
double Coe, double rateOE) const {
//calculate the correct rate at the rapidity y in question.
//TODO: member calculating cutoff, interface before/after recoil.
//Before recoil corresponds to order wrt propagator, after wrt final gluon.
InvEnergy cutoff = 0.99*0.5*
- min(pTScale()/(sp1->plus()*exp(y) + sp1->pT().pt()/2.0),
- min(pTScale()/(sp2->plus()*exp(y) + sp2->pT().pt()/2.0),
+ min(pTScale()/(sp1->plus0()*exp(y) + sp1->pT0().pt()/2.0),
+ min(pTScale()/(sp2->plus0()*exp(y) + sp2->pT0().pt()/2.0),
dip->size()/4.0));
//calculate overestimated rate according the what is used in generateY().
double rate = 2.0*M_PI*Coe*log(1.0 + 2.0*theRScale/cutoff);
return !UseRandom::rndbool(rate/rateOE);
}
/*
* Generates a rapidity for the next emission.
* The distribution f(y) in this member is using is an overestimate, and will be
* vetoed down to correct distribution in the checks of the x_T distribution.
*
* Already the overestimate f(y) is too messy to generate directly though,
* so it has to be done through a further overestimate g(y) > f(y) which is
* then vetoed (only depending on y) down to f(y) with YVeto().
* Look at the writeup for more details on f() and g().
*/
double Emitter::
generateY(DipolePtr dip, double ymin, double ymax) const {
//set up shorter names.
tEffectivePartonPtr p1 = dip->effectivePartons().first;
tEffectivePartonPtr p2 = dip->effectivePartons().second;
InvEnergy r = dip->size();
//To large dipoles will mess up the bessel function, so just shut them
// off by emitting after the maximum y.
if ( r*GeV > 100.0 ) return ymax + 1.0;
//Calculate the cutoff in transverse distance. See writeup for details.
InvEnergy cutoff = 0.99*0.5*
min(pTScale()/(p1->plus()*exp(ymin) + p1->pT().pt()/2.0),
min(pTScale()/(p2->plus()*exp(ymin) + p2->pT().pt()/2.0),
dip->size()/4.0)); //if ordered AFTER recoil
// InvEnergy cutoff = 0.99*
// min(2.0/3.0*pTScale()*exp(-ymin)/p1->plus(),
// min(2.0/3.0*pTScale()*exp(-ymin)/p2->plus(),
// dip->size()/4.0)); //if ordered BEFORE recoil
//Calculate the overestimated coefficient. See writeup for details.
double Coe = alphaBar(r/2.0)/M_PI*
sqr(gsl_sf_bessel_K1(r/(2.0*rMax())))*
sqr(r/(2.0*rMax()))*
(r/(2.0*theRScale)+2.0);
//For assymptotically large dipoles, the overestimated emission rate grows
//faster than Coe, so add an extra factor for large dipoles.
//this will have to be removed in the veto.
if(r>2.0*rMax()) //double check that this is ok!!!
Coe *= sqrt(r/(2.0*rMax()))*
exp(r/(rMax())-2.0);
//calculate the overestimated rate of emission (per unit rapidity).
double rateOE = 2.0*M_PI*Coe*log(1.0 + 2.0*theRScale/cutoff);
//generate the rapidity. (see writeup for details.)
double y = ymin + log(1.0-log(UseRandom::rnd())/rateOE);
//veto to get to correct distribution, recur if vetoed.
if(YVeto(y,dip,Coe,rateOE*exp(y-ymin)) && y < ymax)
return generateY(dip, y, ymax);
else{
return y;
}
}
/*
* Generates a rapidity for the next emission using shadows.
* The distribution f(y) in this member is using is an overestimate, and will be
* vetoed down to correct distribution in the checks of the x_T distribution.
*
* Already the overestimate f(y) is too messy to generate directly though,
* so it has to be done through a further overestimate g(y) > f(y) which is
* then vetoed (only depending on y) down to f(y) with YVeto().
* Look at the writeup for more details on f() and g().
*/
double Emitter::generateY(DipolePtr dip, tSPartonPtr sp1, tSPartonPtr sp2,
double ymin, double ymax) const {
//set up shorter names.
InvEnergy r = dip->size();
//To large dipoles will mess up the bessel function, so just shut them
// off by emitting after the maximum y.
if ( r*GeV > 100.0 ) return ymax + 1.0;
//Calculate the cutoff in transverse distance. See writeup for details.
InvEnergy cutoff = 0.99*0.5*
- min(pTScale()/(sp1->plus()*exp(ymin) + sp1->pT().pt()/2.0),
- min(pTScale()/(sp2->plus()*exp(ymin) + sp2->pT().pt()/2.0), r/4.0));
+ min(pTScale()/(sp1->plus0()*exp(ymin) + sp1->pT0().pt()/2.0),
+ min(pTScale()/(sp2->plus0()*exp(ymin) + sp2->pT0().pt()/2.0), r/4.0));
//Calculate the overestimated coefficient. See writeup for details.
double Coe = alphaBar(r/2.0)/M_PI*
sqr(gsl_sf_bessel_K1(r/(2.0*rMax())))*
sqr(r/(2.0*rMax()))*
(r/(2.0*theRScale)+2.0);
//For assymptotically large dipoles, the overestimated emission rate grows
//faster than Coe, so add an extra factor for large dipoles.
//this will have to be removed in the veto.
if(r>2.0*rMax()) //double check that this is ok!!!
Coe *= sqrt(r/(2.0*rMax()))*
exp(r/(rMax())-2.0);
//calculate the overestimated rate of emission (per unit rapidity).
double rateOE = 2.0*M_PI*Coe*log(1.0 + 2.0*theRScale/cutoff);
//generate the rapidity. (see writeup for details.)
double y = ymin + log(1.0-log(UseRandom::rnd())/rateOE);
//veto to get to correct distribution, recur if vetoed.
if( YVeto(y, dip, sp1, sp2, Coe, rateOE*exp(y-ymin)) && y < ymax )
return generateY(dip, sp1, sp2, y, ymax);
return y;
}
/*
* Generate the transverse position. First generate the distance r
* larger than the cutoff used in generateY(), then decide around which
* parton, and then the angle. Distributions found in writeup.
*/
Parton::Point Emitter::generateXT(DipolePtr dip, double y0) const {
//set up
tEffectivePartonPtr p1 = dip->effectivePartons().first;
tEffectivePartonPtr p2 = dip->effectivePartons().second;
//Calculate the cutoff.
//TODO: make cutoff member, taking dipole and y as arguments.
InvEnergy cutoff = 0.99*0.5*
min(pTScale()/(p1->plus()*exp(y0) + p1->pT().pt()/2.0),
min(pTScale()/(p2->plus()*exp(y0) + p2->pT().pt()/2.0),
dip->size()/4.0)); //if ordered AFTER recoil
// InvEnergy cutoff = 0.99*
// min(2.0/3.0*pTScale()*exp(-y0)/p1->plus(),
// min(2.0/3.0*pTScale()*exp(-y0)/p2->plus(),
// dip->size()/4.0)); //if ordered BEFORE recoil
//The normalisation. See writeup for details.
double C2 = 2.0/log(1.0+2.0*theRScale/cutoff); //normalises g(z)
//Generate the distance.
InvEnergy r = 2.0*theRScale/(exp(2.0*UseRandom::rnd()/C2)-1.0);
//tested to give correct distribution C2/(r^3/theRScale+2r^2)
//generate the angle.
double phi = 2.0*M_PI*UseRandom::rnd();
//decide which parton, and create the Point to be returned.
if(UseRandom::rnd()>0.5)
return Parton::Point(p1->position().first + cos(phi)*r,
p1->position().second + sin(phi)*r);
else
return Parton::Point(p2->position().first + cos(phi)*r,
p2->position().second + sin(phi)*r);
}
/*
* Generate the transverse position. First generate the distance r
* larger than the cutoff used in generateY(), then decide around which
* parton, and then the angle. Distributions found in writeup.
*/
Parton::Point
Emitter::generateXT(DipolePtr dip, tSPartonPtr sp1, tSPartonPtr sp2, double y0) const {
//Calculate the cutoff.
//TODO: make cutoff member, taking dipole and y as arguments.
InvEnergy cutoff = 0.99*0.5*
- min(pTScale()/(sp1->plus()*exp(y0) + sp1->pT().pt()/2.0),
- min(pTScale()/(sp2->plus()*exp(y0) + sp2->pT().pt()/2.0),
+ min(pTScale()/(sp1->plus0()*exp(y0) + sp1->pT0().pt()/2.0),
+ min(pTScale()/(sp2->plus0()*exp(y0) + sp2->pT0().pt()/2.0),
dip->size()/4.0)); //if ordered AFTER recoil
//The normalisation. See writeup for details.
double C2 = 2.0/log(1.0 + 2.0*theRScale/cutoff); //normalises g(z)
//Generate the distance.
InvEnergy r = 2.0*theRScale/(exp(2.0*UseRandom::rnd()/C2)-1.0);
//tested to give correct distribution C2/(r^3/theRScale+2r^2)
//generate the angle.
double phi = 2.0*M_PI*UseRandom::rnd();
//decide which parton, and create the Point to be returned.
tPartonPtr pp =
UseRandom::rndbool()? dip->partons().first: dip->partons().second;
return Point(pp->position().first + cos(phi)*r,
pp->position().second + sin(phi)*r);
}
/*
* the main function to be called from outside. Other functions are mainly to help
* this one. To get the emission right, several layers of overestimates and vetoes
* are used.
*/
void Emitter::generate(Dipole & dip, double ymin, double ymax) const {
if ( dip.partons().first->shadow() ) {
generateWithShadows(dip, ymin, ymax);
return;
}
//Lowest allowed emission rapidity. Not before any of the partons
//in the dipole, and not before the supplied ymin.
double y0 = max(ymin,max(dip.partons().first->y(),dip.partons().second->y()));
//define the resolved effective partons, as function of the dipole size.
//Later, when the transverse position is decided, this will have to
//be recalculated with the actual resolution ranges.
//This is an overestimate, as later lowering the range can only
//decrease the allowed phase space through less p+, and increased p_T.
dip.effectivePartons(EffectiveParton::create(*(dip.partons().first),
dip.size()/2.0),
EffectiveParton::create(*(dip.partons().second),
dip.size()/2.0));
//Some renaming to save space later.
tEffectivePartonPtr p1 = dip.effectivePartons().first;
tEffectivePartonPtr p2 = dip.effectivePartons().second;
//We will go through the while loop until something passes all the vetoes
//or pass the maximum allowed rapidity ymax. However, put a limit
//on the number of trials not to get stuck. So define the count to keep
//track. Possibly a for loop would be more appropriate at this point...
while ( true ) {
//reset the range to the overestimate, as we do not know
//what x_T will eb chosen this trial.
p1->setRange( dip.size()/2.0 );
p2->setRange( dip.size()/2.0 );
//generate a rapidity, according to an overestimate.
y0 = generateY(& dip, y0, ymax);
//if the generated rapidity is above the limit, return an empty pointer
if ( y0 > ymax ) {
dip.generatedGluon(new_ptr(Parton()));
dip.generatedY(y0);
break;
}
//generate a transverse position, using an overestimated
//phase space.
Parton::Point p = generateXT(& dip, y0);
//Bring down the overestimate in the distribution
//to get the right amplitude. After this, only phase space limitations
//left.
if(OEVeto(& dip,y0,p)) {
continue;
}
//Set up notation.
InvEnergy r13 = (p1->position() - p).pt();
InvEnergy r23 = (p2->position() - p).pt();
InvEnergy r12 = dip.size();
//this is to what extent the first parent emitted, and to what extent the
//second one. Here, it is some kind of superposition where they are emitting
//together, so both parents recoil a bit, etc.
double P1 = sqr(r23)/(sqr(r23) + sqr(r13));
double P2 = sqr(r13)/(sqr(r13) + sqr(r23));
//check how much is actually resolved, small emissions resolve more
if ( Current<DipoleEventHandler>()->emitter().rangeMode() != 1 ) {
if ( r13 < r12/2.0 )
p1->setRange( r13 );
if ( r23 < r12/2.0 )
p2->setRange( r23 );
}
//The transverse momentum of the new parton from the parents.
TransverseMomentum v1 = pTScale()*(p - p1->position())/sqr(r13);
TransverseMomentum v2 = pTScale()*(p - p2->position())/sqr(r23);
//calculate the 4-momentum of the emitted gluon.
TransverseMomentum pt = v1 + v2;
Energy pplus = pt.pt()*exp(-y0);
Energy pminus = pt.pt2()/pplus;
//check that there's enough p+
if ( p1->plus() - P1*pplus <= 0.0*GeV ){
continue;
}
if ( p2->plus() - P2*pplus <= 0.0*GeV ){
continue;
}
//calculate the new 4-momenta of the recoiled parents.
TransverseMomentum pt1 = p1->pT() - v1;
TransverseMomentum pt2 = p2->pT() - v2;
Energy plus1 = p1->plus() - P1*pplus;
Energy plus2 = p2->plus() - P2*pplus;
double y1 = log(pt1.pt()/plus1);
double y2 = log(pt2.pt()/plus2);
Energy minus1 = pt1.pt2()/plus1;
Energy minus2 = pt2.pt2()/plus2;
//this option use the p- ordering of the non-effective parton,
//so p- should be calculated from the non-effective parton.
if ( theMinusOrderingMode == 1 ) {
minus1 = pt1.pt()*exp(dip.partons().first->y());
minus2 = pt2.pt()*exp(dip.partons().second->y());
}
//in the first option, p- is required to be fully ordered with both parents.
//in the second option, the parton has to be ordered mainly to the parton that
//emitted it most, so it is allowed to be unordered by a factor P1 and P2.
//PSInflation is a plain factor that the emission is allowed to be unordered by.
if ( bothOrderedEvo() ) {
if ( pminus*thePSInflation < max(minus1, minus2)*thePMinusOrdering ) continue;
}
else {
if ( pminus*thePSInflation < max(P1*minus1, P2*minus2)*thePMinusOrdering ) continue;
}
//check rapidity ordered with the two recoiled parents.
if ( y1 > y0 ) {
continue;
}
if ( y2 > y0 ) {
continue;
}
//check that none of the internal partons recoiled over ymax.
if ( p1->recoilsOverYMax( v1, P1*pplus, ymax ) ) {
continue;
}
if ( p2->recoilsOverYMax( v2, P2*pplus, ymax ) ) {
continue;
}
//This is a self-consistency check.
//If things are donw correctly, then emissions at the limit of the
//cutoff in x_T used in generateXT() and generateY() should all be vetoed.
//if emissions at the limit go through, it means that we are missing part of
//the phase space just within the cutoff, which is bad.
//
//to check this, the cutoff is decreased by a factor 0.99 in generateY() etc above,
//to create the occasional emission in a region that should always be vetoed if the
//overestimates are fair. This is a check at the end so that none of these emission
//between 1 and 0.99 of the cutoff went through.
//TODO: match this with cutoff above
//TODO: proper error message.
if ( min(r13, r23) < min(2.0/3.0*pTScale()/(p1->plus()*exp(y0)),
min(2.0/3.0*pTScale()/(p2->plus()*exp(y0)),
dip.size()/4.0)) )
Throw<EmitterException>()
<< "In DIPSY::Emitter " << name() << ": Emission below r-cutoff passed vetos!"
<< " (r12 = " << ounit(r12, InvGeV) << ", r13 = " << ounit(r13, InvGeV)
<< ", r23 = " << ounit(r23, InvGeV)
<< "v1/pt = " << double(min(v1.pt(), v2.pt())/pt.pt()) << ")"
<< Exception::warning;
// passed. Set up a new parton for the dipole with the information of the emission.
PartonPtr gluon = new_ptr(Parton());
gluon->position(p);
dip.generatedGluon(gluon);
dip.generatedY(y0);
//leave the while loop.
break;
}
}
/*
* the main function to be called from outside when using
* shadows. Other functions are mainly to help this one. To get the
* emission right, several layers of overestimates and vetoes are used.
*/
void Emitter::generateWithShadows(Dipole & dip, double ymin, double ymax) const {
static DebugItem trace("DIPSY::Trace", 9);
if ( trace ) cerr << "Gen " << dip.tag() << endl;
// Handy pointers to the partons.
tPartonPtr p1 = dip.partons().first;
tPartonPtr p2 = dip.partons().second;
//First check how far down the history we must consider previous shadows.
tSPartonPtr sp1 =
dip.partons().first->shadow()->resolve(dip.size2()/4.0, dip.partons().second);
tSPartonPtr sp2 =
dip.partons().second->shadow()->resolve(dip.size2()/4.0, dip.partons().first);
//Lowest allowed emission rapidity. Not before any of the partons
//in the dipole, and not before the supplied ymin.
double y0 = max(ymin, max(p1->y(), p2->y()));
//We will go through the while loop until something passes all the vetoes
//or pass the maximum allowed rapidity ymax. However, put a limit
//on the number of trials not to get stuck. So define the count to keep
//track. Possibly a for loop would be more appropriate at this point...
while ( true ) {
//generate a rapidity, according to an overestimate.
y0 = generateY(&dip, sp1, sp2, y0, ymax);
//if the generated rapidity is above the limit, return an empty pointer
if ( y0 > ymax ) {
dip.generatedGluon(new_ptr(Parton()));
dip.generatedY(y0);
return;
}
//generate a transverse position, using an overestimated
//phase space.
Parton::Point p = generateXT(&dip, sp1, sp2, y0);
//Bring down the overestimate in the distribution
//to get the right amplitude. After this, only phase space limitations
//left.
if ( OEVeto(&dip, sp1, sp2, y0, p) ) {
continue;
}
//Set up notation.
InvEnergy2 r13 = (p1->position() - p).pt2();
InvEnergy2 r23 = (p2->position() - p).pt2();
InvEnergy2 r12 = dip.size2();
// We need to already here decide which parton is emitting.
bool firstsplit = UseRandom::rndbool(r23/(r23 + r13));
tPartonPtr pe = firstsplit? p1: p2;
tPartonPtr pr = firstsplit? p2: p1;
tSPartonPtr spe = firstsplit? sp1: sp2;
InvEnergy2 re3 = firstsplit? r13: r23;
// The emitting parton may be further resolved by the emission.
tSPartonPtr spre = re3 < r12/4.0? pe->shadow()->resolve(re3, pr): spe;
//The transverse momentum of the new parton from the emitter.
TransverseMomentum pt = pTScale()*(p - pe->position())/re3;
Energy pplus = pt.pt()*exp(-y0);
Energy pminus = pt.pt2()/pplus;
//check that there's enough p+
- if ( pplus > spre->plus() ) continue;
+ if ( pplus > spre->plus0() ) continue;
//calculate the new 4-momenta of the recoiled parents.
TransverseMomentum pte = spre->pT() - pt;
- Energy pluse = spre->plus() - pplus;
+ Energy pluse = spre->plus0() - pplus;
double ye = log(pte.pt()/pluse);
Energy minuse = pte.pt2()/pluse;
if ( theMinusOrderingMode == 2 ) {
ShadowParton::Propagator prop =
spre->propagator(min(re3, r12/4.0), pr, -1);
if ( prop.fail ) continue;
pluse = prop.p.plus() - pplus;
if ( pluse <= ZERO ) continue;
pte = TransverseMomentum(prop.p) - pt;
ye = log(pte.pt()/pluse);
minuse = pte.pt2()/pluse;
// *** TODO *** fix masses!
}
else if ( theMinusOrderingMode == 1 )
minuse = pte.pt()*exp(pe->y());
// Ensure approximate minus ordering.
if ( pminus*thePSInflation < minuse*thePMinusOrdering ) continue;
//check rapidity ordered with the two recoiled parents.
if ( ye > y0 ) continue;
// passed. Set up a new parton for the dipole with the information of the emission.
PartonPtr gluon = new_ptr(Parton());
gluon->position(p);
gluon->mainParent(pe);
dip.generatedGluon(gluon);
dip.generatedY(y0);
// And we're done!
return;
}
}
/*
* Maked the dipole actually emit the dipole prepared in generate(), setting up
* parents, children, changing 4-momenta etc.
*/
void Emitter::emit(Dipole & d) const {
//some notation.
if ( d.partons().first->shadow() ) {
emitWithShadows(d);
return;
}
PartonPtr p = d.generatedGluon();
InvEnergy r13 = (d.partons().first->position() - p->position()).pt();
InvEnergy r23 = (d.partons().second->position() - p->position()).pt();
//The recoils.
//TODO: use recoil().
TransverseMomentum v1 = pTScale()*(p->position() - d.partons().first->position())/sqr(r13);
TransverseMomentum v2 = pTScale()*(p->position() - d.partons().second->position())/sqr(r23);
//the ratio each parent emitted the gluon with.
double P1 = sqr(r23)/(sqr(r13) + sqr(r23));
double P2 = 1.0 - P1;
//set 4-momenta for emission.
p->pT(v1 + v2);
p->y(d.generatedY());
p->plus(p->pT().pt()*exp(-d.generatedY()));
p->minus(p->pT().pt()*exp(d.generatedY()));
p->oY(p->y());
//change the dipole structure, generate new colour etc.
d.splitDipole(P2);
//perform the recoil on the effective partons.
//the resolution ranges should be set since the generation of the emission.
d.effectivePartons().first->recoil( v1, P1*p->plus() );
d.effectivePartons().second->recoil( v2, P2*p->plus() );
}
void Emitter::emitWithShadows(Dipole & d) const {
static DebugItem trace("DIPSY::Trace", 9);
if ( trace ) cerr << "Emit " << d.tag();
//some notation.
PartonPtr p = d.generatedGluon();
// Decide which parton is the emitter.
bool em1 = ( p->mainParent() == d.partons().first );
tPartonPtr emitter = em1? d.partons().first: d.partons().second;
tPartonPtr recoiler = em1? d.partons().second: d.partons().first;
InvEnergy2 res = emitter->dist2(*p);
tSPartonPtr sem = emitter->shadow()->resolve(min(res, d.size2()/4.0), recoiler);
TransverseMomentum rec =
pTScale()*(p->position() - emitter->position())/res;
//change the dipole structure, generate new colour etc.
d.splitDipole(em1? 0.0: 1.0);
//set 4-momenta for emission.
p->pT(rec);
p->y(d.generatedY());
p->plus(p->pT().pt()*exp(-d.generatedY()));
p->minus(p->pT().pt()*exp(d.generatedY()));
p->oY(p->y());
if ( theMinusOrderingMode == 2 ) {
ShadowParton::Propagator prop =
sem->propagator(min(res, d.size2()/4.0), recoiler, -1);
emitter->pT(TransverseMomentum(prop.p) - rec);
emitter->plus(prop.p.plus() - p->plus());
emitter->y(log(emitter->mt()/emitter->plus()));
emitter->minus(emitter->mt2()/emitter->plus());
} else {
emitter->pT(sem->pT() - rec);
emitter->plus(sem->plus() - p->plus());
emitter->y(log(emitter->pT().pt()/emitter->plus()));
emitter->minus(emitter->mt2()/emitter->plus());
}
emitter->shadow()->setupEmission(*emitter, *p, *recoiler);
if ( trace ) cerr << " -> " << d.children().first->tag()
<< " + " << d.children().second->tag() << endl;
}
void Emitter::persistentOutput(PersistentOStream & os) const {
os << ounit(thePSInflation, 1.0)
<< ounit(thePMinusOrdering, 1.0)
<< ounit(theRScale, InvGeV)
<< ounit(theRMax, InvGeV)
<< ounit(thePTScale, 1.0)
<< ounit(theBothOrderedEvo, true)
<< ounit(theBothOrderedInt, true)
<< ounit(theBothOrderedFS, true)
<< ounit(theRangeMode, 1)
<< ounit(theMinusOrderingMode, 1);
}
void Emitter::persistentInput(PersistentIStream & is, int) {
is >> iunit(thePSInflation, 1.0)
>> iunit(thePMinusOrdering, 1.0)
>> iunit(theRScale, InvGeV)
>> iunit(theRMax, InvGeV)
>> iunit(thePTScale, 1.0)
>> iunit(theBothOrderedEvo, true)
>> iunit(theBothOrderedInt, true)
>> iunit(theBothOrderedFS, true)
>> iunit(theRangeMode, 1)
>> iunit(theMinusOrderingMode, 1);
}
// Static variable needed for the type description system in ThePEG.
#include "ThePEG/Utilities/DescribeClass.h"
DescribeClass<Emitter,HandlerBase>
describeDIPSYEmitter("DIPSY::Emitter", "libAriadne5.so libDIPSY.so");
void Emitter::Init() {
static ClassDocumentation<Emitter> documentation
("The Emitter class is responsible for generating and performing "
"emissions from dipoles. This base class does the default emission "
"strategy.");
static Parameter<Emitter,InvEnergy> interfaceRScale
("RScale",
"Constant used in overestimate of emission probability.",
&Emitter::theRScale, InvGeV, 1.0*InvGeV, 0.0*InvGeV, 0.0*InvGeV,
true, false, Interface::lowerlim);
static Parameter<Emitter,double> interfacePSInflation
("PSInflation",
"How much p+- ordering should be enforced. 1 is normal ordering, high numbers "
"are no ordering(energy must still be conserved though), "
"low number demands stronger ordering",
&Emitter::thePSInflation, 1.0, 1.0, 0.0, 0.0,
true, false, Interface::lowerlim);
static Parameter<Emitter,double> interfacePMinusOrdering
("PMinusOrdering",
"An extra factor strengthening the p- ordering on top of the PSInflation."
"A large value will suppress large dipoles more.",
&Emitter::thePMinusOrdering, 1.0, 1.0, 0.0, 0.0,
true, false, Interface::lowerlim);
static Parameter<Emitter,double> interfacePTScale
("PTScale",
"If pT is 1/r or 2/r.",
&Emitter::thePTScale, 1.0, 1.0, 0.0, 0.0,
true, false, Interface::lowerlim);
static Parameter<Emitter,InvEnergy> interfaceRMax
("RMax",
"The confinement scale (in iverse GeV). If set to zero, "
"the value of <interface>DipoleEventHandler::RMax</interface> of the "
"controlling event handler will be used.",
&Emitter::theRMax, InvGeV, 0.0*InvGeV, 0.0*InvGeV, 0*InvGeV,
true, false, Interface::lowerlim);
static Switch<Emitter,bool> interfaceBothOrderedEvo
("BothOrderedEvo",
"If an emission should be fully ordered with both its parents."
"otherwise it will be weighted according to how close they are.",
&Emitter::theBothOrderedEvo, false, true, false);
static SwitchOption interfaceBothOrderedEvoTrue
(interfaceBothOrderedEvo,"True","both parents fully ordered.",true);
static SwitchOption interfaceBothOrderedEvoFalse
(interfaceBothOrderedEvo,"False","weighted by distance.",false);
static Switch<Emitter,bool> interfaceBothOrderedInt
("BothOrderedInt",
"If an emission should be fully ordered with both its parents."
"otherwise it will be weighted according to how close they are.",
&Emitter::theBothOrderedInt, false, true, false);
static SwitchOption interfaceBothOrderedIntTrue
(interfaceBothOrderedInt,"True","both parents fully ordered.",true);
static SwitchOption interfaceBothOrderedIntFalse
(interfaceBothOrderedInt,"False","weighted by distance.",false);
static Switch<Emitter,bool> interfaceBothOrderedFS
("BothOrderedFS",
"If an emission should be fully ordered with both its parents."
"otherwise it will be weighted according to how close they are.",
&Emitter::theBothOrderedFS, false, true, false);
static SwitchOption interfaceBothOrderedFSTrue
(interfaceBothOrderedFS,"True","both parents fully ordered.",true);
static SwitchOption interfaceBothOrderedFSFalse
(interfaceBothOrderedFS,"False","weighted by distance.",false);
static Switch<Emitter,int> interfaceRangeMode
("RangeMode",
"How the range of coherenent emissions is determined.",
&Emitter::theRangeMode, 0, true, false);
static SwitchOption interfaceRangeModeMin
(interfaceRangeMode,
"Min",
"minimum of half mother dipole and distance to emission. Default.",
0);
static SwitchOption interfaceRangeModeMax
(interfaceRangeMode,
"Mother",
"Half distance of mother dipole, no matter how close the emission is.",
1);
static Switch<Emitter,int> interfaceMinusOrderingMode
("MinusOrderingMode",
"Sets how the ordering in p- is done in the virtual cascade, in relation to effective partons mainly.",
&Emitter::theMinusOrderingMode, 0, true, false);
static SwitchOption interfaceMinusOrderingModeEffectiveParton
(interfaceMinusOrderingMode,
"EffectiveParton",
"Uses the momentum of the effective parton to order, both plus and pt.",
0);
static SwitchOption interfaceMinusOrderingModeEffectivePT
(interfaceMinusOrderingMode,
"EffectivePT",
"Uses the pt of the effective parton, but the rapidity of the single emitting parton.",
1);
static SwitchOption interfaceMinusOrderingModeTrueShadow
(interfaceMinusOrderingMode,
"TrueShadow",
"Use the full shadow mechanism for resolved emissions to get the "
"incoming propagator.",
2);
}
diff --git a/DIPSY/ShadowParton.cc b/DIPSY/ShadowParton.cc
--- a/DIPSY/ShadowParton.cc
+++ b/DIPSY/ShadowParton.cc
@@ -1,676 +1,669 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the ShadowParton class.
//
#include "ShadowParton.h"
#include "Parton.h"
#include "DipoleState.h"
#include "DipoleEventHandler.h"
#include "Dipole.h"
#include "ImpactParameters.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/Repository/CurrentGenerator.h"
#include "ThePEG/Utilities/Debug.h"
#include "ThePEG/Utilities/Throw.h"
#include "ThePEG/Utilities/EnumIO.h"
#include "ThePEG/Utilities/Current.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Utilities/DebugItem.h"
using namespace DIPSY;
ShadowParton::ShadowParton(Parton & p)
- : theOriginal(&p), thePosition(p.position()), thePlus(p.plus()),
+ : theOriginal(&p), thePlus(p.plus()),
thePT(p.pT()), thePT0(p.pT()), theMass(p.mass()), theMinus(p.minus()),
theY(p.y()), theY0(p.y()), theFlavour(p.flavour()),
- theDifference(first), theDipoles(p.dipoles()), theEmissionFactor(ZERO),
+ theDipoles(p.dipoles()), theEmissionFactor(ZERO),
theRes(ZERO), isLocked(false), hasInteracted(false), isOnShell(false),
isValence(p.valence()), memememe(false) {}
ShadowParton::~ShadowParton() {}
void ShadowParton::setupParton() {
if ( tSPartonPtr sp = original()->shadow() ) {
sp->theNext = this;
thePrevious = sp;
}
original()->shadow(this);
}
SPartonPtr ShadowParton::createValence(Parton & p) {
SPartonPtr sp = new_ptr(ShadowParton(p));
sp->setupParton();
sp->isValence = true;
return sp;
}
void ShadowParton::setupSwing(Parton & pa1, Parton & pa2, Parton & pb1, Parton & pb2) {
// SPartonPtr sa1 = new_ptr(ShadowParton(pa1));
// sa1->setupParton();
// SPartonPtr sa2 = new_ptr(ShadowParton(pa2));
// sa2->setupParton();
// SPartonPtr sb1 = new_ptr(ShadowParton(pb1));
// sb1->setupParton();
// SPartonPtr sb2 = new_ptr(ShadowParton(pb2));
// sb2->setupParton();
- // sa1->theDifference = sa2->theDifference = sb1->theDifference = sb2->theDifference = swing;
// sa1->setupNeighbors();
// sa2->setupNeighbors();
// sb1->setupNeighbors();
// sb2->setupNeighbors();
}
void ShadowParton::setupEmission(Parton & emitter, Parton & produced, Parton & recoiler) {
SPartonPtr se = new_ptr(ShadowParton(emitter));
se->setupParton();
SPartonPtr sp = new_ptr(ShadowParton(produced));
sp->setupParton();
// SPartonPtr sr = new_ptr(ShadowParton(recoiler));
// sr->setupParton();
- se->theDifference = emission;
se->theSibling = sp;
se->setupNeighbors();
- sp->theDifference = emission;
sp->theParent = this;
sp->theSibling = se;
theChild = sp;
sp->setupNeighbors();
- // sr->theDifference = recoil;
// sr->setupNeighbors();
InvEnergy2 d2 = se->theRes = sp->theRes = se->dist2(*sp);
se->theEmissionFactor = sp->theEmissionFactor = alphaS(d2)*d2/UseRandom::rnd();
- se->pT0(sp->pT0());
- se->y0(sp->y0());
+ // se->pT0(sp->pT0());
+ // se->y0(sp->y0());
}
void ShadowParton::setupNeighbors() {
if ( dipoles().first )
theNeighbors.first = dipoles().first->partons().first->shadow();
if ( dipoles().second )
theNeighbors.second = dipoles().second->partons().second->shadow();
}
void ShadowParton::lock() {
if ( mother() ) mother()->lock();
isLocked = true;
}
void ShadowParton::unlock() {
if ( mother() && locked() ) mother()->unlock();
isLocked = false;
}
tSPartonPtr ShadowParton::last() {
if ( next() ) return next();
return this;
}
tSPartonPtr ShadowParton::initial() {
if ( previous() ) return previous();
return this;
}
tSPartonPtr ShadowParton::valenceMother() {
if ( mother() ) return mother()->valenceMother();
return this;
}
tcSPartonPtr ShadowParton::last() const {
if ( next() ) return next();
return this;
}
double ShadowParton::alphaS(InvEnergy2 r2) {
return Current<DipoleEventHandler>()->alphaS(sqrt(r2));
}
// tcSPartonPtr ShadowParton::resolve(InvEnergy2 r2, tPartonPtr stopp) const {
// if ( resolved(r2, stopp) || !mother() ) return this;
// return mother()->resolve(r2, stopp);
// }
tSPartonPtr ShadowParton::resolve(InvEnergy2 r2) {
if ( resolved(r2) || !mother() ) return this;
return mother()->resolve(r2);
}
tSPartonPtr ShadowParton::resolveInteraction(InvEnergy2 r2) {
if ( resolved(r2)
|| !mother()
|| forceEmission()
|| onShell()
|| ( sibling() && sibling()->interacted() ) ) return this;
return mother()->resolveInteraction(r2);
}
// void ShadowParton::flagOnShell(InvEnergy2 r2, tPartonPtr stopp) {
// tSPartonPtr resolved = resolve(r2, stopp);
// if ( resolved->onShell() ) return;
// resolved->onShell(true);
// if ( resolved->sibling() ) {
// r2 = resolved->res();
// resolved->sibling()->onShell(true);
// }
// if ( resolved->mother() ) resolved->mother()->flagOnShell(r2, stopp);
// // *** TODO *** probably the whole function should be deleted
// // else dipoleState().flagShadowsOnShell();
// }
void ShadowParton::pTplus(const TransverseMomentum & qt, Energy qp) {
pT(qt);
plus(qp);
minus(mt2()/plus());
y(log(mt()/plus()));
}
void ShadowParton::setOnShell(int mode) {
if ( mode < 0 ) return;
onShell(true);
if ( mode <= 0 ) return;
original()->plus(plus());
original()->pT(pT());
original()->minus(original()->mt2()/plus());
original()->y(log(original()->mt()/original()->plus()));
original()->onShell(true);
}
void ShadowParton::unsetOnShell() {
if ( onShell() ) {
original()->onShell(false);
onShell(false);
}
}
void ShadowParton::interact() {
if ( interacted() ) return;
hasInteracted = true;
if ( mother() ) mother()->interact();
}
void ShadowParton::resetInteracted() {
if ( !mother() ) {
pT(pT0());
y(y0());
plus(mt()*exp(-y()));
minus(mt()*exp(y()));
}
hasInteracted = false;
theInteractions.clear();
onShell(false);
if ( next() ) next()->resetInteracted();
if ( child() ) child()->resetInteracted();
}
void ShadowParton::reset() {
if ( !mother() ) {
pT(pT0());
y(y0());
plus(mt()*exp(-y()));
minus(mt()*exp(y()));
}
onShell(false);
theInteractions.clear();
hasInteracted = false;
theInteractionRoots.clear();
if ( next() ) next()->reset();
if ( child() ) child()->reset();
}
void ShadowParton::insertInteraction(int i) {
// If this parton has been set on-shell by a previous interaction we
// do not have to look further. Similarly if the sibling has
// interacted.
if ( onShell()
|| ( sibling() && sibling()->interacted() )
|| !mother() ) {
interactionRoot(i);
}
// Otherwise we try with the mother instead.
else mother()->insertInteraction(i);
}
void ShadowParton::rejectInteraction(int i) {
if ( hasInteractionRoot(i) ) theInteractionRoots.erase(i);
else mother()->rejectInteraction(i);
}
void ShadowParton::acceptInteraction(int i) {
hasInteracted = true;
if ( !hasInteractionRoot(i) ) mother()->acceptInteraction(i);
}
void ShadowParton::makeIncoming() {
if ( interacted() && onShell() ) onShell(false);
else if ( mother() ) mother()->makeIncoming();
}
bool ShadowParton::setEmissionMomenta(const LorentzMomentum & p,
bool forced) {
// *** TODO *** Think this through! If the emission unresolved but
// anyway should be done because a valence need to be put on shell,
// or a subsequent emission needs it, the generated pt is ignored
// and the emitted parton and the continuing propagator will share
// the incoming pt, while the generated rapidity of the emission
// remains untouched.
- TransverseMomentum qT = pT0();
+ TransverseMomentum qT = parent()? pT0(): sibling()->pT0();
if ( forced ) qT = TransverseMomentum(-p.x()/2.0, -p.y()/2.0);
if ( parent() ) {
// If this parton was emitted, pretend it was actually he emitter
// and continues as a propagator. It will retain its original
// rapidity, but will get the transverse momentum of the incoming
// propagator.
pT(TransverseMomentum(p.x(), p.y()) + qT);
plus(mt0()*exp(y0()));
y(y0());
// The sibling will get minus the original transverse momentum and
// what ever is left of the positive light-cone momenta. (return
// false if not enough to put on shell).
sibling()->pT(-qT);
sibling()->plus(p.plus() - mt()*exp(-y()));
if ( sibling()->plus() <= ZERO ) return false;
sibling()->minus(mt2()/sibling()->plus());
sibling()->y(log(sibling()->mt()/sibling()->plus()));
// The propagators negative light-cone momentum is trivial,
minus(p.minus() - sibling()->minus());
} else {
// If this parton was assumed in the evolution, life is simpler.
sibling()->pT(-qT);
- sibling()->plus(sibling()->mt()*exp(-y0()));
+ sibling()->plus(sibling()->mt()*exp(-sibling()->y0()));
sibling()->minus(sibling()->mt2()/sibling()->plus());
- sibling()->y(y0());
+ sibling()->y(sibling()->y0());
pT(TransverseMomentum(p.x(), p.y()) + qT);
plus(p.plus() - sibling()->plus());
if ( plus() <= ZERO ) return false;
minus(mt2()/plus());
y(log(mt()/plus()));
}
return true;
}
// ShadowParton::Propagator ShadowParton::
// oldpropagator(InvEnergy2 r2, tPartonPtr stopp, int mode) {
// // If we reach a parton that has been set on shell, we will simply
// // return its momentum and set it off-shell.
// if ( onShell() ) {
// if ( mode >= 0 ) unsetOnShell();
// return momentum();
// }
// // If this was a valence, ask the DipoleState about its momentum.
// if ( !mother() ) return dipoleState().incomingMomentum(this, mode);
// // Now, if this emission was not resolved then simply return the
// // propagator of the mother. However, if the emission is needed for
// // subsequent interactions or if the emitted parton was a valence,
// // we need to force it. with a special procedure.
// bool forced = forceEmission();
// bool unresolved = !resolved(r2, stopp);
// if ( unresolved && !forced )
// return setMomentum(mother()->propagator(r2, stopp, mode));
// // Get the propagator of the mother with the new resolution
// // scale. But don't put anything on-shell yet in case the emission
// // is rejected later.
// Propagator prop = mother()->propagator(res(), stopp, -1);
// // If it is not possible to set the emitted parton on shell, flag
// // the propagator as failed.
// if ( !setEmissionMomenta(prop.p, false) ) {
// prop.fail = true;
// // If the emitted parton is necessary for a subsequent
// // interaction, return the failed propagator.
// if ( forced ) return prop;
// // Otherwise just ignore the emission.
// return setMomentum(mother()->propagator(r2, stopp, mode));
// }
// // Now depending on the colour line of the emitted parton, it must
// // be ordered in light-cone momenta with previous partons on the
// // same side except if it partakes in a subsequent interaction.
// if ( colourSibling() ) {
// if ( sibling()->interactionRoot() ) {
// prop.colpos = Constants::MaxEnergy;
// prop.colneg = ZERO;
// } else {
// // Check if a resolved emission was not ordered, in that case
// // flag it unresolved.
// if ( sibling()->plus() > prop.colpos ||
// sibling()->minus() < prop.colneg )
// unresolved = true;
// else {
// prop.colpos = sibling()->plus();
// prop.colneg = sibling()->minus();
// }
// }
// } else {
// if ( sibling()->interactionRoot() ) {
// prop.acopos = Constants::MaxEnergy;
// prop.aconeg = ZERO;
// } else {
// if ( sibling()->plus() > prop.acopos ||
// sibling()->minus() < prop.aconeg )
// unresolved = true;
// else {
// prop.acopos = sibling()->plus();
// prop.aconeg = sibling()->minus();
// }
// }
// }
// // If the emission was found to be unresolved we need to recalculate
// // the incoming momentum.
// if ( unresolved ) {
// prop = mother()->propagator(r2, stopp, mode);
// // If the unresolved emission was a valence we need to emit it
// // anyway with a special treatment.
// if ( forced ) {
// if ( !setEmissionMomenta(prop.p, true) ) {
// prop.fail = true;
// return prop;
// }
// } else
// return setMomentum(prop);
// }
// // In any case we need to redo the incoming momentum to mark it final.
// if ( mode >= 0 ) prop = mother()->propagator(res(), stopp, mode);
// // Now we are done. Depending on the mode we will put the emitted
// // parton on shell.
// sibling()->setOnShell(mode);
// prop.p -= sibling()->momentum();
// return prop;
// }
ShadowParton::Propagator ShadowParton::
propagator(InvEnergy2 r2, int mode) {
static DebugItem unorderlock("DIPSY::UnorderLock", 6);
Propagator prop;
// If we reach a parton that has been set on shell, we will simply
// return its momentum and set it off-shell.
if ( onShell() ) {
if ( mode >= 0 ) unsetOnShell();
return momentum();
}
// If this was a valence, ask the DipoleState about its momentum.
if ( !mother() ) return dipoleState().incomingMomentum(this, mode);
// Now, if this emission was not resolved then simply return the
// propagator of the mother. However, if the emission is needed for
// subsequent interactions or if the emitted parton was a valence,
// we need to force it. with a special procedure.
bool forced = forceEmission();
bool unresolved = !resolved(r2);
// First we check if a resolved emission is possible.
if ( !unresolved ) {
// Get the propagator of the mother with the new resolution
// scale. But don't put anything on-shell yet in case the emission
// is rejected later.
prop = mother()->propagator(res(), -1);
// First check that it was at all kinematically possible perform
// the emission.
if ( setEmissionMomenta(prop.p, false) ) {
// OK. That seemed to work, but we must also check the ordering.
// Now depending on the colour line of the emitted parton, it
// must be ordered in light-cone momenta with previous partons
// on the same side. If that is not the case, te emissionis
// marked unresolved.
if ( ! ( unorderlock && sibling() && sibling()->locked() ) ) {
if ( colourSibling() ) {
if ( sibling()->plus() > prop.colpos ||
sibling()->minus() < prop.colneg )
unresolved = true;
} else{
if ( sibling()->plus() > prop.acopos ||
sibling()->minus() < prop.aconeg )
unresolved = true;
}
}
} else {
// Since the emission could not be performed, we flaf it
// unresolved.
unresolved = true;
}
}
// If the emission was really resolved, we get the incoming
// propagator again, but this time put stuff on-shell. Then we
// return the outgoing propagator, after setting the ordering for
// the subsequent emissions, and we're done.
if ( !unresolved ) {
if ( mode >= 0 ) prop = mother()->propagator(res(), mode);
if ( colourSibling() ) {
prop.colpos = sibling()->plus();
prop.colneg = sibling()->minus();
} else {
prop.acopos = sibling()->plus();
prop.aconeg = sibling()->minus();
}
sibling()->setOnShell(mode);
prop.p -= sibling()->momentum();
return prop;
}
// OK, so it was unresolved. Get the incoming propagator with the
// previous resolution scale. If it was not forced, then let it go.
prop = mother()->propagator(r2, mode);
if ( !forced ) return prop;
// However, if we have to force it we need to check that it really
if ( !setEmissionMomenta(prop.p, true) ) {
// If it doesn't work, just give up the whole thing and fail the
// whole propagator chain.
prop.fail = true;
return prop;
}
// If it does work we set things on-shell, return the propagator and
// we're done.
sibling()->setOnShell(mode);
prop.p -= sibling()->momentum();
return prop;
}
tSPartonPtr ShadowParton::findFirstOnShell() {
if ( original()->onShell() ) return this;
if ( !next() ) return tSPartonPtr();
if ( next()->colourSibling() ) {
tSPartonPtr ch = child()->findFirstOnShell();
if ( ch ) return ch;
}
return next()->findFirstOnShell();
}
tSPartonPtr ShadowParton::findSecondOnShell() {
if ( original()->onShell() ) return this;
if ( !next() ) return tSPartonPtr();
if ( !next()->colourSibling() ) {
tSPartonPtr ch = child()->findSecondOnShell();
if ( ch ) return ch;
}
return next()->findSecondOnShell();
}
Ariadne5::ClonePtr ShadowParton::clone() const {
return new_ptr(*this);
}
-void ShadowParton::mirror(double y0) {
- y(2.0*y0 - y());
+void ShadowParton::mirror(double yf) {
+ y(2.0*yf - y());
swap(thePlus, theMinus);
- if ( next() ) next()->mirror(y0);
- if ( child() ) child()->mirror(y0);
+ if ( next() ) next()->mirror(yf);
+ if ( child() ) child()->mirror(yf);
}
void ShadowParton::translate(const ImpactParameters & b) {
- thePosition = b.translate(thePosition);
thePT = b.rotatePT(thePT);
if ( next() ) next()->translate(b);
if ( child() ) child()->translate(b);
}
void ShadowParton::propagateShadowMomenta() {
if ( onShell() ) {
original()->plus(plus());
original()->pT(pT());
original()->y(log(original()->mt()/original()->plus()));
original()->onShell(true);
}
if ( next() ) next()->propagateShadowMomenta();
if ( child() ) child()->propagateShadowMomenta();
}
void ShadowParton::rebind(const TranslationMap & trans) {
thePrevious = trans.translate(thePrevious);
theParent = trans.translate(theParent);
theSibling = trans.translate(theSibling);
theNext = trans.translate(theNext);
theChild = trans.translate(theChild);
theDipoles.first = trans.translate(theDipoles.first);
theDipoles.second = trans.translate(theDipoles.second);
theNeighbors.first = trans.translate(theNeighbors.first);
theNeighbors.second = trans.translate(theNeighbors.second);
}
DipoleState& ShadowParton::dipoleState() const {
if ( dipoles().first ) return dipoles().first->dipoleState();
else return dipoles().second->dipoleState();
}
double ShadowParton::pTScale() const {
- return dipoleState().handler().emitter().pTScale();
+ return Current<DipoleEventHandler>()->emitter().pTScale();
}
Energy ShadowParton::mass() const {
if ( theMass < ZERO )
theMass = CurrentGenerator::current().getParticleData(flavour())->mass();
return theMass;
}
bool ShadowParton::partonOnShell() const {
return onShell() || ( previous() && previous()->partonOnShell() );
}
void ShadowParton::debugme() {
// cout << "data for ShadowParton " << this << endl;
// cout << "thePosition1: " << thePosition.first*GeV
// << ", thePosition2: " << thePosition.second*GeV
// << ", thePlus: " << thePlus/GeV
// << ", thePT: " << thePT.pt()/GeV
// << ", theMinus: " << theMinus/GeV
// << ", theY: " << theY
// << ", theFlavour: " << theFlavour
// << ", theDipoles1: " << theDipoles.first
// << ", theDipoles2: " << theDipoles.second
// << ", hasInteracted: " << hasInteracted
// << ", isOnShell: " << isOnShell
// << ", isValence: " << isValence
// << ", theMass: " << theMass/GeV << endl;
memememe = true;
valenceMother()->debugTree("");
memememe = false;
}
void ShadowParton::debugTree(string indent) {
- // if ( mother() && diff() != emission && next() ) {
- // next()->debugTree(indent);
- // return;
- // }
cerr << indent << (memememe? "==": "--")
<< (valence()? "v": "-") << (locked()? "%": "-");
if ( interactionRoot() ) {
set<int>::iterator i = theInteractionRoots.begin();
cerr << "{" << *i;
while ( ++i != theInteractionRoots.end() )
cerr << "," << *i;
cerr << "}";
}
cerr << (interacted()? "+": "-");
if ( interacting() ) {
set<int>::iterator i = theInteractions.begin();
cerr << "[" << *i;
while ( ++i != theInteractions.end() )
cerr << "," << *i;
cerr << "]";
}
cerr << (onShell()? "*": "-") << (memememe? "=>": "->");
if ( onShell() )
cerr << "[" << pT().x()/GeV << ", "
<< pT().y()/GeV << ", "
<< plus()/GeV << "]";
else if ( interacted() )
cerr << "(" << pT().x()/GeV << ", "
<< pT().y()/GeV << ", "
<< plus()/GeV << ")";
cerr << endl;
if ( indent.size() > 1 && indent[indent.size() - 1] == '\\' )
indent[indent.size() - 1] = ' ';
if ( next() && child() ) {
if ( child()->interacted() ) next()->debugTree(indent + " +");
else next()->debugTree(indent + " |");
}
if ( next() && !child() ) next()->debugTree(indent + " ");
if ( child() ) child()->debugTree(indent + " \\");
}
/*
----->
|---->
| |---->
| \---->
| |---->
| \---->
\---->
*/
void ShadowParton::persistentOutput(PersistentOStream & os) const {
- os << theOriginal << ounit(thePosition, InvGeV) << ounit(thePlus, GeV)
- << ounit(thePT, GeV) << ounit(theMass, GeV) << ounit(theMinus, GeV)
- << theY << theFlavour << thePrevious << theParent << theSibling
+ os << theOriginal << ounit(thePlus, GeV)
+ << ounit(thePT, GeV) << ounit(thePT0, GeV) << ounit(theMass, GeV)
+ << ounit(theMinus, GeV) << theY << theY0 << theFlavour
+ << thePrevious << theParent << theSibling
<< theNext << theChild << theDipoles << theNeighbors
<< ounit(theEmissionFactor, 1.0/GeV2) << ounit(theRes, 1.0/GeV2)
- << hasInteracted << isOnShell << isValence << oenum(theDifference);
+ << hasInteracted << isOnShell << isValence;
}
void ShadowParton::persistentInput(PersistentIStream & is, int) {
- is >> theOriginal >> iunit(thePosition, InvGeV) >> iunit(thePlus, GeV)
- >> iunit(thePT, GeV) >> iunit(theMass, GeV)>> iunit(theMinus, GeV)
- >> theY >> theFlavour >> thePrevious >> theParent >> theSibling
+ is >> theOriginal >> iunit(thePlus, GeV)
+ >> iunit(thePT, GeV) >> iunit(thePT0, GeV) >> iunit(theMass, GeV)
+ >> iunit(theMinus, GeV) >> theY >> theY0 >> theFlavour
+ >> thePrevious >> theParent >> theSibling
>> theNext >> theChild >> theDipoles >> theNeighbors
>> iunit(theEmissionFactor, 1.0/GeV2) >> iunit(theRes, 1.0/GeV2)
- >> hasInteracted >> isOnShell >> isValence >> ienum(theDifference);
+ >> hasInteracted >> isOnShell >> isValence;
}
DescribeClass<ShadowParton,Ariadne5::CloneBase>
describeDIPSYShadowParton("DIPSY::ShadowParton", "libAriadne5.so libDIPSY.so");
// Definition of the static class description member.
void ShadowParton::Init() {}
diff --git a/DIPSY/ShadowParton.h b/DIPSY/ShadowParton.h
--- a/DIPSY/ShadowParton.h
+++ b/DIPSY/ShadowParton.h
@@ -1,1038 +1,1003 @@
// -*- C++ -*-
#ifndef DIPSY_ShadowParton_H
#define DIPSY_ShadowParton_H
//
// This is the declaration of the ShadowParton class.
//
#include "ThePEG/Config/ThePEG.h"
#include "ThePEG/Vectors/Transverse.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/Repository/UseRandom.h"
#include "Ariadne/Config/CloneBase.h"
#include "ShadowParton.fh"
#include "Parton.h"
#include "Dipole.fh"
#include "DipoleXSec.fh"
namespace DIPSY {
using namespace ThePEG;
class ImpactParameters;
/**
* Here is the documentation of the ShadowParton class.
*/
class ShadowParton: public Ariadne5::CloneBase {
public:
/**
* Typedef for position in transverse coordinate space.
*/
typedef Transverse<InvEnergy> Point;
/**
* A pair of partons.
*/
typedef pair<tSPartonPtr,tSPartonPtr> tSPartonPair;
/**
* A pair of dipoles.
*/
typedef pair<tDipolePtr,tDipolePtr> tDipolePair;
/**
* The Dipole is a friend.
*/
friend class Dipole;
/**
- * Enum difference from the previous version of the same parton.
- */
- enum Difference {
- first = 0, /**< No difference - this is the first instance. */
- emission = 1, /**< The previous instance emitted. */
- recoil = 2, /**< The previous received a recoil from a neighboring emission */
- swing = 3, /**< The previous underwent a swing. */
- interactn = 4 /**< The previous underwent an interaction */
- };
-
- /**
* Helper class for traversing along a propagator to an interaction
*/
struct Propagator {
/**
* Constructor.
*/
Propagator(): colpos(Constants::MaxEnergy), colneg(ZERO),
acopos(Constants::MaxEnergy), aconeg(ZERO), fail(false) {}
/**
* Construct from momentum.
*/
Propagator(const LorentzMomentum & mom)
: p(mom), colpos(Constants::MaxEnergy), colneg(ZERO),
acopos(Constants::MaxEnergy), aconeg(ZERO), fail(false) {}
/**
* The Momentum of the propagator.
*/
LorentzMomentum p;
/**
* The positive light-cone momentum of the previous emission on the colour line.
*/
Energy colpos;
/**
* Thenegative light-cone momentum of the previous emission on the colour line.
*/
Energy colneg;
/**
* The positive light-cone momentum of the previous emission on
* the anti-colour line.
*/
Energy acopos;
/**
* Thenegative light-cone momentum of the previous emission on the
* anti-colour line.
*/
Energy aconeg;
/**
* Indicate that the propagator has failed.
*/
bool fail;
};
/**
* Helper class to temporarily protect a propagator.
*/
struct Lock {
/**
* The only constructor. Locking the propagator to a given parton.
*/
Lock(tPartonPtr p): sp(p->shadow()) {
sp->lock();
}
/**
* The destructor, unlocking the propagator.
*/
~Lock() {
sp->unlock();
}
/**
* The parton to which the propagator should be locked.
*/
tSPartonPtr sp;
};
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
inline ShadowParton()
- : thePosition(Point()), thePlus(ZERO), theMass(-1*GeV), theMinus(0*GeV),
- theY(0), theY0(0), theFlavour(ParticleID::g), theDifference(first),
+ : thePlus(ZERO), theMass(-1*GeV), theMinus(0*GeV),
+ theY(0), theY0(0), theFlavour(ParticleID::g),
theEmissionFactor(ZERO), theRes(ZERO), isLocked(false),
hasInteracted(false), isOnShell(false), isValence(false), memememe(false) {}
/**
* Construct from ordinary parton.
*/
ShadowParton(Parton & p);
/**
* The destructor.
*/
virtual ~ShadowParton();
/**
* Create a valence shadow parton from a given ordinary parton.
*/
static SPartonPtr createValence(Parton & p);
/**
* Easy access to alphaS.
*/
static double alphaS(InvEnergy2 r2);
/**
* Setup shadow partons in an emission.
*/
void setupEmission(Parton & emitter, Parton & produced, Parton & recoiler);
/**
* Setup shadow partons in a swing.
*/
static void setupSwing(Parton & pa1, Parton & pa2, Parton & pb1, Parton & pb2);
/**
* Setup pointers to and from neighboring partons.
*/
void setupParton();
/**
* Setup neighboring shadow partons.
*/
void setupNeighbors();
//@}
protected:
/** @name The virtual functions to be overridden in sub-classes. */
//@{
/**
* Return a simple clone of this object. Should be implemented as
* <code>return new_ptr(*this);</code> by a derived class.
*/
virtual Ariadne5::ClonePtr clone() const;
/**
* Rebind pointers to other CloneBase objects. Called after a number
* of interconnected CloneBase objects have been cloned, so that
* the cloned objects will refer to the cloned copies afterwards.
*
* @param trans a TranslationMap relating the original objects to
* their respective clones.
*/
virtual void rebind(const TranslationMap & trans);
//@}
public:
/**
* Return the DipoleState to which this parton belongs. If it was
* originally belonged to one state which was subsequently merged
* into another, the parton will belong to the latter state.
*/
DipoleState & dipoleState() const;
/**
* finds the pTscale through the dipolestates emitter.
*/
double pTScale() const;
/**
* Calculate the squared transverse distance to the given parton.
*/
inline InvEnergy2 dist2(const ShadowParton & p) const {
return (position() - p.position()).pt2();
}
/**
* Calculate the transverse distance to the given parton.
*/
inline InvEnergy dist(const ShadowParton & p) const {
return sqrt(dist2(p));
}
/**
* Produce a ThePEG::Particle corresponding to this parton.
*/
PPtr produceParticle() const;
/**
* The mass of this parton.
*/
Energy mass() const;
/**
* The transverse momentum squared of this parton.
*/
Energy2 pt2() const {
return pT().pt2();
}
/**
* The transverse mass squared of this parton.
*/
Energy2 mt2() const {
return pt2() + sqr(mass());
}
/**
* The transverse mass of this parton in the emission.
*/
Energy2 mt02() const {
return pT0().pt2() + sqr(mass());
}
/**
* The transverse mass of this parton in the emission.
*/
Energy mt0() const {
return sqrt(mt02());
}
/**
* The transverse momentum of this parton.
*/
Energy pt() const {
return sqrt(pt2());
}
/**
* The transverse momentum of this parton.
*/
Energy mt() const {
return sqrt(mt2());
}
/**
* The final-state momentum of this particle.
*/
LorentzMomentum momentum() const {
return lightCone(plus(), mt2()/plus(), pT());
}
/** @name Simple access functions. */
//@{
/**
* Get the position in impact parameter space.
*/
inline const Point & position() const {
- return thePosition;
+ return original()->position();
}
/**
* Get the positive light-cone momentum.
*/
inline Energy plus() const {
return thePlus;
}
/**
* Get the original positive light-cone momentum.
*/
inline Energy plus0() const {
return pT0().pt()*exp(-y0());
}
/**
* Get the transverse momentum.
*/
inline TransverseMomentum pT() const {
return thePT;
}
/**
* Get the transverse momentum.
*/
inline TransverseMomentum pT0() const {
return thePT0;
}
/**
* Get the accumulated negative light-cone momentum deficit.
*/
inline Energy minus() const {
return theMinus;
}
/**
* Get the rapidity.
*/
inline double y() const {
return theY;
}
/**
* Get the rapidity generated in the emission.
*/
inline double y0() const {
return theY0;
}
/**
* Get the flavour of this parton.
*/
inline long flavour() const {
return theFlavour;
}
/**
- * Indicate what happened to the previous instance of this parton.
- */
- Difference diff() const {
- return theDifference;
- }
-
- /**
* Get the original DIPSY parton.
*/
tPartonPtr original() const {
return theOriginal;
}
/**
* Get the previous instance of this parton befor it was emitted or
* swinged.
*/
inline tSPartonPtr previous() const {
return thePrevious;
}
/**
* Get the parent parton if this was emitted.
*/
inline tSPartonPtr parent() const {
return theParent;
}
/**
* Get the sibling of this parton if any.
*/
inline tSPartonPtr sibling() const {
return theSibling;
}
/**
* Get the next version of this parton if emitted or swinged.
*/
inline tSPartonPtr next() const {
return theNext;
}
/**
* Get the first version of this parton if emitted or swinged.
*/
tSPartonPtr initial();
/**
* Get the first (grand)mother of this parton.
*/
tSPartonPtr valenceMother();
/**
* Get the last version of this parton if emitted or swinged.
*/
tSPartonPtr last();
/**
* Get the last version of this parton if emitted or swinged.
*/
tcSPartonPtr last() const;
/**
* Get the parton this has emitted if any.
*/
inline tSPartonPtr child() const {
return theChild;
}
/**
* Get the mother parton, either previous() or parent().
*/
inline tSPartonPtr mother() const {
return parent()? parent(): previous();
}
/**
* Get the connecting dipoles.
*/
inline tDipolePair dipoles() const {
return theDipoles;
}
/**
* Indicate that the corresponding emission is on a protected
* propagator. Any other propagator must assume that this emission
* must be resolved.
*/
inline bool locked() const {
return isLocked;
}
/**
* Indicate that the propagator leading up to this parton is protected.
*/
void lock();
/**
* Indicate that the propagator leading up to thi parton is no
* longer protected.
*/
void unlock();
/**
* Indicate if this parton has interacted.
*/
inline bool interacted() const {
return hasInteracted;
}
/**
* Return true if the sibling is on the colour side of this parton.
*/
inline bool colourSibling() const {
return sibling() == theNeighbors.first;
}
/**
* Return if this shadow was the root of an interacting propagator.
*/
inline bool interactionRoot() const {
return theInteractionRoots.size() > 0;
}
/**
* Return if this shadow was the root of an interacting propagator.
*/
inline bool hasInteractionRoot(int i) const {
return theInteractionRoots.find(i) != theInteractionRoots.end();
}
/**
* Return if this shadow was directly involved in the interaction.
*/
inline int interacting() const {
return theInteractions.size() > 0;
}
/**
* Return if this parton is on shell.
*/
inline bool onShell() const {
return isOnShell;
}
/**
* Return true if the actual parton should be put on-shell;
*/
bool partonOnShell() const;
/**
* Set if this parton is on shell.
*/
inline void onShell(bool b) {
isOnShell = b;
}
/**
* Indicate that this parton is the root of an interaction.
*/
inline void interactionRoot(int i) {
theInteractionRoots.insert(i);
}
/**
* Set if this shadow is directly involved in an interaction.
*/
inline void interacting(int i) {
theInteractions.insert(i);
}
/**
* Return if this parton is a valence parton.
*/
inline bool valence() const {
return isValence;
}
/**
* Set if this parton is a valence parton.
*/
inline void valence(bool b) {
isValence = b;
}
/**
- * Set the position in impact parameter space.
- */
- inline void position(const Point & x) {
- thePosition = x;
- }
-
- /**
* Set the positive light-cone momentum.
*/
inline void plus(Energy x) {
thePlus = x;
}
/**
* Set the transverse momentum.
*/
inline void pT(const TransverseMomentum & x) {
thePT = x;
}
/**
* Set the momentum using transverse momentum and positive
* light-cone momentum. Set also other components assuming real.
*/
void pTplus(const TransverseMomentum & qt, Energy qp);
/**
* Set the transverse momentum.
*/
inline void pT0(const TransverseMomentum & x) {
thePT0 = x;
}
/**
* Set the accumulated negative light-cone momentum deficit.
*/
inline void minus(Energy x) {
theMinus = x;
}
/**
* Set the rapidity.
*/
inline void y(double x) {
theY = x;
}
/**
* Set the rapidity.
*/
inline void y0(double x) {
theY0 = x;
}
/**
* Set the flavour of this parton.
*/
inline void flavour(long x) {
theFlavour = (x == 0? ParticleID::g: x);
}
/**
* Set the parent parton.
*/
inline void parent(tSPartonPtr p) {
theParent = p;
}
/**
* Set the connecting dipoles.
*/
inline void dipoles(tDipolePair x) {
theDipoles = x;
}
/**
* Indicate that this parton has interacted and mark all parent and
* original partons if needed.
*/
void interact();
/**
* The emission factor for this parton if emitted or emitter.
*/
InvEnergy2 emissionFactor() const {
return theEmissionFactor;
}
/**
* The resolusion scale factor for this parton if emitted or emitter.
*/
InvEnergy2 res() const {
return theRes;
}
/**
* Return true if this parton and its sibling are resolved.
*/
bool resolved(InvEnergy2 r2) const {
return ( ( sibling() && ( sibling()->locked()
|| emissionFactor() > alphaS(r2)*r2 ) ) );
}
/**
* Return true if this parton and its sibling are resolved. An
* emission involving \a stopp is always resolved.
*/
// bool resolved(InvEnergy2 r2, tPartonPtr stopp) const {
// return ( ( sibling() && ( sibling()->original() == stopp
// || sibling()->locked()
// || emissionFactor() > alphaS(r2)*r2 ) ) );
// }
/**
* Return true if the sibling must be put on-shell even if it was not
* resolved, because it will partake in a subsequent interaction or is
* a valence.
*/
bool forceEmission() const {
return sibling() && ( sibling()->valence()
|| sibling()->interactionRoot() );
}
/**
* Go back in the history of this shadow parton and find the
* original parton which would be resolved at a given size or would
* be the interaction root. Always resolve emissions involving \a
* stopp.
*/
tSPartonPtr resolveInteraction(InvEnergy2 r2, tPartonPtr stopp) {
Lock safeguard(stopp);
return resolveInteraction(r2);
}
/**
* Go back in the history of this shadow parton and find the
* original parton which would be resolved at a given size or would
* be the interaction root.
*/
tSPartonPtr resolveInteraction(InvEnergy2 r2);
/**
* Go back in the history of this shadow parton and find the
* original parton which would be resolved at a given size. Always
* resolve emissions involving \a stopp.
*/
tSPartonPtr resolve(InvEnergy2 r2, tPartonPtr stopp) {
Lock safeguard(stopp);
return resolve(r2);
}
/**
* Go back in the history of this shadow parton and find the
* original parton which would be resolved at a given size. Always
* resolve emissions involving \a stopp. (const version).
*/
// tcSPartonPtr resolve(InvEnergy2 r2, tPartonPtr stopp) const;
/**
* Go back in the history and flag all partons which are resoved by
* the given size to be set on-shell. Always
* resolve emissions involving \a stopp.
*/
// void flagOnShell(InvEnergy2 r2, tPartonPtr stopp);
/**
* If this parton is not on shell, find an emitted parton
* with the same colour lines (modulo swing) that is.
*/
tSPartonPtr findFirstOnShell();
/**
* If this parton is not on shell, find an emitted parton
* with the same colour lines (modulo swing) that is.
*/
tSPartonPtr findSecondOnShell();
/**
* Flag on-shell if \a mode >= 0 and copy to original parton if \a
* mode > 0.
*/
void setOnShell(int mode);
/**
* If prevoíously set on-shell, clear the flag.
*/
void unsetOnShell();
/**
* Go forward in the evolution and reset all interaction flags.
*/
void reset();
/**
* Go forward in the evolution and reset all interacted flags.
*/
void resetInteracted();
/**
* Set the momenta in an emission, assuming the incoming momentum \a p.
*/
bool setEmissionMomenta(const LorentzMomentum & p, bool valencefix);
protected:
/**
* Go back in the history of this shadow parton and find the
* original parton which would be resolved at a given size. Always
* resolve emissions involving \a stopp.
*/
tSPartonPtr resolve(InvEnergy2 r2);
public:
/**
* Go back in the history and find the momentum of this incoming
* parton. Always resolve emissions involving \a stopp. If \a mode
* >= 0 flag partons which would be put on shell. if \a mode > 0
* also propagate the momentum to the original() parton.
*/
Propagator oldpropagator(InvEnergy2 r2, tPartonPtr stopp, int mode);
Propagator propagator(InvEnergy2 r2, tPartonPtr stopp, int mode) {
Lock safeguard(stopp);
return propagator(r2, mode);
}
Propagator propagator(InvEnergy2 r2, int mode);
Propagator setMomentum(const Propagator & prop) {
plus(prop.p.plus());
pT(TransverseMomentum(prop.p.x(), prop.p.y()));
return prop;
}
/**
* Recursively tell all this and any offspring to propagate their
* momentum to the original partons if set on shell.
*/
void propagateShadowMomenta();
/**
* Indicate that this parton should be tested for an
* interaction. Insert the corresponding interaction object at the
* correct place in the chain. The primary interaction is always at
* one of the incoming shadows. Secondary interactions are inserted
* at a parton which has been or should be made real by a previous
* emission. If this parton already had an interaction, simply leave
* it as it is.
*/
void insertInteraction(int i);
/**
* Indicate that a previously tested interaction is accepted. This
* is done by marking all propagators interacted() in the chain down
* to the one where the interaction was found.
*/
void acceptInteraction(int i);
/**
* Make this and all its anceseters incoming.
*/
void makeIncoming();
/**
* Indicate that the interaction that has been tested was rejected
* by simply removing the interaction root inserted by
* insertInteraction().
*/
void rejectInteraction(int i);
/**
* Change direction before producing collision.
*/
void mirror(double yframe);
/**
* Translate according to the impagt parameter.
*/
void translate(const ImpactParameters & b);
/**
* Prints all the member variables to cerr.
*/
void debugme();
/**
* Debug the structure of the shadow tree.
*/
void debugTree(string indent);
//@}
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();
private:
/**
* The original DIPSY parton
*/
tPartonPtr theOriginal;
/**
- * The position in impact parameter space.
- */
- Point thePosition;
-
- /**
* The positive light-cone momentum.
*/
Energy thePlus;
/**
* The transverse momentum.
*/
TransverseMomentum thePT;
/**
* The transverse momentum generated in the emission.
*/
TransverseMomentum thePT0;
/**
* The mass of this parton.
*/
mutable Energy theMass;
/**
* The accumulated negative light-cone momentum deficit.
*/
Energy theMinus;
/**
* The rapidity.
*/
double theY;
/**
* The rapidity generated in the emission.
*/
double theY0;
/**
* The flavour of this parton.
*/
long theFlavour;
/**
- * Indicate what happened to the previous instance of this parton.
- */
- Difference theDifference;
-
- /**
* The state of this parton, if any, before the swing or the emission of this
* parton's sibling. Is aways null if theParent exists.
*/
tSPartonPtr thePrevious;
/**
* The parent parton if this has emitted or swinged. Is aways null if
* thePrevious exists.
*/
tSPartonPtr theParent;
/**
* The sibling of this parton if any.
*/
tSPartonPtr theSibling;
/**
* The state of this parton after the emission of the child. Is null
* if this parton has not emitted.
*/
SPartonPtr theNext;
/**
* The child this parton has emitted, if any.
*/
SPartonPtr theChild;
/**
* The dipoles connected to this parton.
*/
tDipolePair theDipoles;
/**
* The partons connected to this.
*/
tSPartonPair theNeighbors;
/**
* The emission factor for this parton if emitted or emitter.
*/
InvEnergy2 theEmissionFactor;
/**
* The resolution factor for this parton if emitted or emitter.
*/
InvEnergy2 theRes;
/**
* Indicate that the corresponding emission is on a protected
* propagator. Any other propagator must assume that this emission
* must be resolved.
*/
bool isLocked;
/**
* Indicate if this parton has interacted.
*/
bool hasInteracted;
/**
* Indicate if this parton is on shell, that is if it has
* been supplied with the neccesary p+ or p- for left or rightmoving
* particles respectively.
*/
bool isOnShell;
/**
* This is root of an interaction chain.
*/
set<int> theInteractionRoots;
/**
* The interactions this was directly involved with.
*/
set<int> theInteractions;
/**
* Indicate if this parton is a valence parton.
*/
bool isValence;
protected:
/**
* Exception class for bad kinematics.
*/
struct ShadowPartonKinematicsException: public Exception {};
public:
bool memememe;
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
ShadowParton & operator=(const ShadowParton &);
};
}
#endif /* DIPSY_ShadowParton_H */
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Tue, Nov 19, 7:35 PM (1 d, 10 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3805850
Default Alt Text
(82 KB)
Attached To
rTHEPEGARIADNEHG thepegariadnehg
Event Timeline
Log In to Comment