Page MenuHomeHEPForge

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/.hgignore b/.hgignore
--- a/.hgignore
+++ b/.hgignore
@@ -1,83 +1,95 @@
.*/Makefile
.*/Makefile\.in
.*/\.deps
.*/\.libs
.*/.*\.l[ao]
.*/.*\.so\.*
.*/.*\.o
.*~
.*/done-all-links
lib/AriadneDefaults.rpo
(DIPSY|src)/.*\.(run|tex|out|log|rpo|spc|top|dump|dot|aux|pdf|ps|png|svg|hepmc|dat|aida|rz|eps|root|tuple|gp|exe)
src/done-all-links
autom4te.cache
aclocal.m4
libtool
Makefile
Makefile.in
config.log
config.status
configure
Config/config.h
Config/config.h.in
Config/config.sub
Config/depcomp
Config/install-sh
Config/missing
Config/stamp-h.
Config/config.guess
include/done-all-links
include/Ariadne
DIPSY/NuclearDistribution-1.C
DIPSY/NuclearDistribution.C
DIPSY/plots
src/plots
src/.*\.prof
src/3jet.lhe.gz
src/MadGraph_DIS
src/mgdis.in
src/runThePEG
DIPSY/runThePEG
lib/Ariadne5Defaults.rpo
DIPSY/fsswing.txt
DIPSY/rphi.pl
DIPSY1991
DIPSY/mcnetRivetbin
DIPSY/pythia8
DIPSY/exps
DIPSY/temp.*
DIPSY/95
DIPSY/.*\.yoda
src/.*\.yoda
DIPSY/.*\.info
DIPSY/.*\.plot
DIPSY/bugtest.in
DIPSY/PPTune/.*\.prof
# added by aHg on Tue Oct 8 16:20:34 2013
syntax: glob
DIPSY/TestRemnants.in
# added by aHg on Tue Oct 8 16:21:11 2013
syntax: glob
src/MTuneLEP.prof/ipol/profipol_quadratic_a3d80e6417a4670a4a51a4dbc59e222b.pkl
# added by aHg on Tue Nov 5 17:09:03 2013
syntax: glob
src/used_params
# added by aHg on Tue Nov 26 09:38:47 2013
syntax: glob
DIPSY/dummy.pl
# added by aHg on Fri Feb 7 15:50:55 2014
syntax: glob
DIPSY/PPTune.in
# added by aHg on Fri Feb 7 15:51:31 2014
syntax: glob
DIPSY/PPTune/PPTune.in
# added by aHg on Fri Feb 7 15:51:42 2014
syntax: glob
DIPSY/PPTune/runThePEG
+
+# added by aHg on Thu Feb 13 15:30:42 2014
+syntax: glob
+DIPSY/PPTune/plots
+
+# added by aHg on Thu Feb 13 15:31:13 2014
+syntax: glob
+lib/DIPSYDefaults.rpo
+
+# added by aHg on Thu Feb 13 15:31:23 2014
+syntax: glob
+DIPSY/PPTune/refs/refs
diff --git a/Cascade/AriadneHandler.cc b/Cascade/AriadneHandler.cc
--- a/Cascade/AriadneHandler.cc
+++ b/Cascade/AriadneHandler.cc
@@ -1,822 +1,822 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the AriadneHandler class.
//
#include "AriadneHandler.h"
#include "ConsistencyChecker.h"
#include "QCDDipoleFinder.h"
#include "EMDipoleFinder.h"
#include "ReweightBase.h"
#include "DipoleState.h"
#include "EmitterBase.h"
#include "BornCheckerBase.h"
#include "ScaleSetter.h"
#include "DISFinder.h"
#include "ResonanceFinder.h"
#include "Ariadne/Cascade/Models/RemnantModel.h"
#include "Ariadne/Cascade/Models/ColourResonanceModel.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/RefVector.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/EventRecord/Collision.h"
#include "ThePEG/EventRecord/SubProcess.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/Handlers/EventHandler.h"
#include "ThePEG/Handlers/Hint.h"
#include "ThePEG/Handlers/XComb.h"
#include "ThePEG/Utilities/UtilityBase.h"
#include "ThePEG/Utilities/DescriptionList.h"
#include "ThePEG/Utilities/Throw.h"
#include "ThePEG/Cuts/Cuts.h"
#include "ThePEG/Utilities/EnumIO.h"
#include "ThePEG/Utilities/Current.h"
#include "ThePEG/Repository/CurrentGenerator.h"
#include "ThePEG/Utilities/DebugItem.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/StandardModel/StandardModelBase.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "Models/FSGluonEmission.h"
#include "Models/FSQQEmission.h"
#include "Models/DipoleSwing.h"
#include "ThePEG/Analysis/FactoryBase.h"
#ifndef LWH_AIAnalysisFactory_H
#ifndef LWH
#define LWH ThePEGLWH
#endif
#include "ThePEG/Analysis/LWH/AnalysisFactory.h"
#endif
using namespace Ariadne5;
AriadneHandler::AriadneHandler()
: theRunningCoupling(simpleRunning), theAlpha0(0.2), theLambdaQCD(0.22*GeV),
scaleFactor(1.0), thePTCut(0.6*GeV), theAlphaEM0(1.0/137.0),
thePTCutEM(0.6*GeV), theNCol(8), theNFlav(5), thePhotonEmissions(false),
theSoftMu(0.6*GeV), theSoftAlpha(1.0), theHardAlpha(-1.0), theBeta(2.0),
theMaxEmissions(0), suspendConsistencyChecks(false), thePurgeStrategy(neverpurge),
thePurgeFactor(0.0) {}
AriadneHandler::~AriadneHandler() {}
IBPtr AriadneHandler::clone() const {
return new_ptr(*this);
}
IBPtr AriadneHandler::fullclone() const {
return new_ptr(*this);
}
bool AriadneHandler::preInitialize() const {
if ( CascadeHandler::preInitialize() ) return true;
return runningCoupling() == internalRunning && !internalAlphaS();
}
void AriadneHandler::doinit() throw(InitException) {
CascadeHandler::doinit();
if ( runningCoupling() != internalRunning || internalAlphaS() ) return;
theInternalAlphaS = dynamic_ptr_cast<Ptr<AlphaSBase>::pointer>
(generator()->preinitCreate("ThePEG::O1AlphaS", fullName() + "/AlphaS",
"O1AlphaS.so"));
ostringstream os;
os << ounit(lambdaQCD(), GeV);
generator()->preinitInterface(theInternalAlphaS,
"LambdaQCD", "set", os.str());
generator()->preinitInterface(theInternalAlphaS, "LambdaFlav", "set", "5");
theInternalAlphaS->update();
// Remove duplicate emitters.
vector<EmitterPtr> cleaned;
set<const ClassDescriptionBase *> cleanset;
for ( int i = 0, N = emitters().size(); i < N; ++i ) {
const ClassDescriptionBase * cd =
DescriptionList::find(typeid(*emitters()[i]));
if ( cleanset.find(cd) != cleanset.end() ) continue;
cleaned.push_back(emitters()[i]);
cleanset.insert(cd);
}
theEmitters.swap(cleaned);
}
void AriadneHandler::doinitrun() {
static DebugItem histem("Ariadne5::HistEm", 6);
CascadeHandler::doinitrun();
theFlavourThresholds.clear();
vector<Energy2> thrsh;
switch ( runningCoupling() ) {
case noRunning:
return;
case simpleRunning:
case externalRunning:
thrsh = SM().alphaSPtr()->flavourThresholds();
break;
case internalRunning:
thrsh = internalAlphaS()->flavourThresholds();
}
for ( int i = 0, N = thrsh.size(); i < N; ++i ) thrsh[i] /= scaleFactor;
theFlavourThresholds.insert(thrsh.begin(), thrsh.end());
if ( histem ) {
generator()->histogramFactory()->initrun();
generator()->histogramFactory()->registerClient(this);
generator()->histogramFactory()->mkdir("/Ariadne5Debug");
histall = generator()->histogramFactory()->createHistogram1D
("/Ariadne5Debug/All", 100, -1.0, 9.0);
histswing = generator()->histogramFactory()->createHistogram1D
("/Ariadne5Debug/Swings", 100, -1.0, 9.0);
histglue = generator()->histogramFactory()->createHistogram1D
("/Ariadne5Debug/Glue", 100, -1.0, 9.0);
histqq = generator()->histogramFactory()->createHistogram1D
("/Ariadne5Debug/QQ", 100, -1.0, 9.0);
histlam = generator()->histogramFactory()->createHistogram1D
("/Ariadne5Debug/Lambda", 100, -1.0, 9.0);
}
}
void AriadneHandler::cascade() {
static DebugItem histem("Ariadne5::HistEm", 6);
- static DebugItem tupleswing("Ariadne::SwingTuple", 6);
+ static DebugItem tupleswing("Ariadne5::SwingTuple", 6);
static ofstream swingtuple;
if ( tupleswing ) {
static bool isopen = false;
if ( !isopen ) {
string filename = CurrentGenerator::current().filename() + "-swing.tuple";
swingtuple.open(filename.c_str());
isopen = true;
}
}
Current<AriadneHandler> current(this);
DipoleStatePtr state;
tSubProPtr sub;
tPVector final;
Energy rhomax = ZERO;
// Energy rhomin = pTCut();
Energy rhomin = ZERO;
bool perf = false;
int emnbr = 0;
// Check if the state has already been generated in reweightCKKW
if ( theCKKWMap.count(lastXCombPtr()) ){
CKKWState ckkw = theCKKWMap[lastXCombPtr()];
sub = subProcess();
state = ckkw.history->state();
checkState(*state);
rhomax = startingScale(*state);
while ( emnbr == 0 &&
( rhomax = state->select(rhomin, rhomax) ) > rhomin ) {
SaveDipoleState backup(state);
if ( state->perform() ) {
if ( !ckkw.maxMult && checkTreeState(*state) && passCuts(state) ) {
theCKKWMap.clear();
throw Veto();
}
perf = true;
emnbr++;
} else {
state = backup.revert();
state->selected()->dipole->touch();
}
}
}
else {
tCollPtr coll = eventHandler()->currentCollision();
state = new_ptr(DipoleState(coll->incoming()));
sub = coll->primarySubProcess();
if ( sub->decayed() ) sub = tSubProPtr();
// Decide whether we are cascadeing a whole sub-process or if we
// only need to deal with final-state shower.
if ( ( hint().tagged() || !sub ) && !tagged().empty() ) {
final = tagged();
}
else if ( sub ) {
state->setup(*sub);
}
else
return;
if ( !final.empty() ) {
state->setup(set<tPPtr>(final.begin(), final.end()));
}
checkState(*state);
if ( !state->checkIntegrity() )
Throw<Exception>()
<< "Ariadne failed to setup dipole system. This is a serious error,"
<< "Please inform the author." << Exception::runerror;
rhomax = startingScale(*state);
}
theCKKWMap.clear();
if ( tupleswing ) {
swingtuple << "# " << setw(4) << CurrentGenerator::current().currentEventNumber()
<< setw(8) << "rho"
<< setw(14) << "lam/dip"
<< setw(14) << "lambda"
<< setw(6) << "cross"
<< setw(6) << "below"
<< setw(14) << "folding"
<< setw(6) << "geno"
<< setw(6) << "emno" << endl;
pair<double,int> lam = state->lambdaMeasure(sqr(pTCut()));
int cross = state->crossings();
swingtuple << setw(14) << log10(rhomax/GeV)
<< setw(14) << lam.first/lam.second
<< setw(14) << lam.first
<< setw(6) << cross
<< setw(6) << state->gluonsBelow()
<< setw(14) << state->folding() << endl;
}
if ( purgeStrategy() == onlybefore || purgeStrategy() > neverpurge )
state->purgeGluons(pTCut()*purgeFactor());
if ( tupleswing ) {
pair<double,int> lam = state->lambdaMeasure(sqr(pTCut()));
int cross = state->crossings();
swingtuple << setw(14) << log10(rhomax/GeV)
<< setw(14) << lam.first/lam.second
<< setw(14) << lam.first
<< setw(6) << cross
<< setw(6) << state->gluonsBelow()
<< setw(14) << state->folding() << endl;
}
while ( ( rhomax = state->select(rhomin, rhomax) ) > rhomin &&
( maxEmissions() == 0 || emnbr < maxEmissions() ) ) {
SaveDipoleState backup(state);
if ( state->perform() ) {
perf = true;
emnbr++;
if ( tupleswing ) {
double lrho = log10(state->selected()->rho/GeV);
pair<double,int> lam = state->lambdaMeasure(sqr(pTCut()));
int cross = state->crossings();
swingtuple << setw(14) << lrho
<< setw(14) << lam.first/lam.second
<< setw(14) << lam.first
<< setw(6) << cross
<< setw(6) << state->gluonsBelow()
<< setw(14) << state->folding()
<< setw(6) << state->selected()->geno
<< setw(6) << state->selected()->emno;
if ( DipoleSwing * em = dynamic_cast<DipoleSwing*>((Emission*)(state->selected())) ) {
swingtuple << "s" << setw(6) << state->index(em->dipoles.first) << setw(6)
<< state->index(em->dipoles.second);
}
else if ( dynamic_cast<FSGluonEmission*>((Emission*)(state->selected())) )
swingtuple << "g" << setw(6)<< state->index(state->selected()->dipole);
else if ( dynamic_cast<FSQQEmission*>((Emission*)(state->selected())) )
swingtuple << "q" << setw(6) << state->index(state->selected()->dipole);
swingtuple << endl;
}
if ( histem ) {
double w = 1.0/double(state->activeDipoles().size());
double lrho = log10(state->selected()->rho/GeV);
histall->fill(lrho, w);
histlam->fill(lrho, state->lambdaMeasure().first);
if ( dynamic_cast<DipoleSwing*>((Emission*)(state->selected())) )
histswing->fill(lrho, w);
else if ( dynamic_cast<FSGluonEmission*>((Emission*)(state->selected())) )
histglue->fill(lrho, w);
else if ( dynamic_cast<FSQQEmission*>((Emission*)(state->selected())) )
histqq->fill(lrho, w);
else
state->selected()->debug();
}
if ( purgeStrategy() == everystep ) state->purgeGluons(pTCut()*purgeFactor());
} else {
state = backup.revert();
state->selected()->dipole->touch();
}
if ( !state->checkIntegrity() ) {
throw IntegretyException() << "AriadneHandler::cascade "
<< "The dipole state is not self consistent."
<< Exception::eventerror;
}
}
if ( perf && ( purgeStrategy() == onlyafter || purgeStrategy() == beforeandafter ) )
state->purgeGluons(pTCut()*purgeFactor());
if ( tupleswing ) {
pair<double,int> lam = state->lambdaMeasure(sqr(pTCut()));
int cross = state->crossings();
swingtuple << setw(14) << log10(pTCut()/GeV)
<< setw(14) << lam.first/lam.second
<< setw(14) << lam.first
<< setw(6) << cross
<< setw(6) << state->gluonsBelow()
<< setw(14) << state->folding() << endl;
}
if ( final.empty() ) {
if ( perf ) state->fill(*newStep());
sub->decayed(true);
} else {
if ( perf ) state->fill(*newStep());
}
}
double AriadneHandler::reweightCKKW(int minMult, int maxMult) {
if(minMult == maxMult){
return 1.0;
}
CKKWState ckkw;
DipoleStatePtr state = new_ptr(DipoleState());
tXCPtr lastXC = lastXCombPtr();
int outgoing = lastXC->subProcess()->outgoing().size();
if ( outgoing < minMult || outgoing > maxMult ) {
throw CKKWMultiplicityException()
- << "Ariadne::CascadeHandler::reweightCKKW "
+ << "Ariadne5::CascadeHandler::reweightCKKW "
<< "Number of outgoing particles out of range."
<< Exception::eventerror;
}
int steps = outgoing - minMult;
ckkw.maxMult = (outgoing == maxMult);
state->setup(*(lastXC->subProcess()));
checkState(*state);
if ( !state->checkIntegrity() )
Throw<Exception>()
<< "Ariadne failed to setup dipole system. This is a serious error,"
<< "Please inform the author." << Exception::runerror;
ckkw.history = HistoryPtr(new History(steps, state));
if ( !ckkw.history->select() ) return 0.0;
double w = ckkw.history->weight(lastXC->lastAlphaS(), lastXC->lastScale());
if ( w > 0.0 ) theCKKWMap[lastXC] = ckkw;
return w;
}
bool AriadneHandler::passCuts(tcDipoleStatePtr state) {
/* *** ATTENTION ***
tCutsPtr cuts = lastCutsPtr();
Lorentz5Momentum ph = state->hardFS().momentum();
cuts->initSubProcess(ph.mass2(), ph.rapidity());
tcPDVector pdata;
vector< LorentzMomentum > p;
typedef HardSubSys::PartonSet PartonSet;
const PartonSet & active = state->hardSubSys().coloured();
const PartonSet & produced = state->hardSubSys().produced();
for(PartonSet::const_iterator it = active.begin(); it != active.end();
it++){
pdata.push_back((*it)->dataPtr());
p.push_back((*it)->momentum());
}
for(PartonSet::const_iterator it = produced.begin(); it != produced.end();
it++){
pdata.push_back((*it)->dataPtr());
p.push_back((*it)->momentum());
}
LorentzRotation R(0.0, 0.0, - ph.z()/ph.e());
Utilities::transform(p, R);
return cuts->passCuts(pdata, p, state->particles().first->dataPtr(),
state->particles().second->dataPtr());
*/ return false;
}
double AriadneHandler::alphaS(Energy2 scale) const {
scale *= scaleFactor;
int Nf = SM().Nf(scale);
switch ( runningCoupling() ) {
case noRunning:
return alpha0();
case simpleRunning:
return 12.0*Constants::pi/
((33.0 - 2.0*min(int(SM().Nf(scale)),5))*log(scale/sqr(lambdaQCD())));
case internalRunning:
return internalAlphaS()->value(scale, SM());
case externalRunning:
return SM().alphaS(scale);
}
return ZERO*Nf;
}
Energy AriadneHandler::checkBornState(const DipoleState & ds) const {
Energy scale = ZERO;
for ( int i = 0, N = theBornCheckers.size(); i < N; ++i ) {
Energy mu = theBornCheckers[i]->check(ds);
if ( mu > ZERO ) return mu;
if ( scale == ZERO ) scale = mu;
}
if ( scale == ZERO )
Throw<CKKWBornException>()
<< "Could not reconstruct the given event in the CKKW-L algorithm. "
<< *(eventHandler()->currentEvent()) << Exception::runerror;
return scale;
}
bool AriadneHandler::checkTreeState(const DipoleState & ds) const {
for ( int i = 0, N = theBornCheckers.size(); i < N; ++i )
if ( theBornCheckers[i]->checkTree(ds) ) return true;
return false;
}
vector<tQCDPtr> AriadneHandler::findQCDDipoles(DipoleState & state) const {
return theQCDFinder->findDipoles(state);
}
vector<tEMDipPtr> AriadneHandler::findEMDipoles(DipoleState & state) const {
return theEMFinder? theEMFinder->findDipoles(state): vector<tEMDipPtr>();
}
Energy AriadneHandler::startingScale(const DipoleState & state) const {
return theScaleSetter->scale(state);
}
bool AriadneHandler::checkState(DipoleState & state, tcEmPtr e) {
if ( !consistency ) return true;
if ( !e ) suspendConsistencyChecks = false;
else if ( suspendConsistencyChecks ) return true;
if ( consistency->check(state, e) ) return true;
if ( !e ) suspendConsistencyChecks = true;
return false;
}
pair<tRemParPtr,tRemParPtr>
AriadneHandler::findDISLeptons(SubProcess & sub, DipoleState & state) const {
return theDISFinder? theDISFinder->findDISLeptons(sub, state):
pair<tRemParPtr,tRemParPtr>();
}
pair<tRemParPtr,tRemParPtr>
AriadneHandler::findDISQuarks(pair<tRemParPtr,tRemParPtr> leptons,
SubProcess & sub, DipoleState & state) const {
return theDISFinder? theDISFinder->findDISQuarks(leptons, sub, state):
pair<tRemParPtr,tRemParPtr>();
}
tPVector AriadneHandler::resonances(SubProcess & sub) const {
return theResonanceFinder->resonances(sub);
}
void AriadneHandler::persistentOutput(PersistentOStream & os) const {
os << oenum(theRunningCoupling) << theAlpha0 << ounit(theLambdaQCD, GeV)
<< theInternalAlphaS << scaleFactor << theFlavourThresholds.size()
<< ounit(thePTCut, GeV) << theAlphaEM0 << ounit(thePTCutEM, GeV)
<< theNCol << theNFlav << thePhotonEmissions << ounit(theSoftMu, GeV)
<< theSoftAlpha << theHardAlpha << theBeta << theReweighters
<< theMaxEmissions << theEmitters << theBornCheckers << theScaleSetter
<< theDISFinder << theResonanceFinder << theQCDFinder << theEMFinder
<< theColourResonanceModel << theRemnantModel
<< consistency << suspendConsistencyChecks << oenum(thePurgeStrategy) << thePurgeFactor;
for ( set<Energy2>::const_iterator it = theFlavourThresholds.begin();
it != theFlavourThresholds.end(); ++it ) os << ounit(*it, GeV2);
}
void AriadneHandler::persistentInput(PersistentIStream & is, int) {
int size = 0;
is >> ienum(theRunningCoupling) >> theAlpha0 >> iunit(theLambdaQCD, GeV)
>> theInternalAlphaS >> scaleFactor >> size
>> iunit(thePTCut, GeV) >> theAlphaEM0 >> iunit(thePTCutEM, GeV)
>> theNCol >> theNFlav >> thePhotonEmissions >> iunit(theSoftMu, GeV)
>> theSoftAlpha >> theHardAlpha >> theBeta >> theReweighters
>> theMaxEmissions >> theEmitters >> theBornCheckers >> theScaleSetter
>> theDISFinder >> theResonanceFinder >> theQCDFinder >> theEMFinder
>> theColourResonanceModel >> theRemnantModel
>> consistency >> suspendConsistencyChecks >> ienum(thePurgeStrategy) >> thePurgeFactor;
theFlavourThresholds.clear();
Energy2 t = ZERO;
for ( int i = 0; i < size; ++i ) {
is >> iunit(t, GeV2);
theFlavourThresholds.insert(t);
}
}
DescribeClass<AriadneHandler,ThePEG::CascadeHandler>
describeAriadne5("Ariadne5::AriadneHandler", "libAriadne5.so");
Energy AriadneHandler::minPTCut() const {
return ( runningCoupling() == simpleRunning ||
( runningCoupling() == internalRunning && !theInternalAlphaS ) )?
lambdaQCD()/sqrt(scaleFactor): 0.0*GeV;
}
Energy AriadneHandler::maxLambdaQCD() const {
return ( runningCoupling() == simpleRunning ||
( runningCoupling() == internalRunning && !theInternalAlphaS ) )?
pTCut()*sqrt(scaleFactor): Constants::MaxEnergy;
}
void AriadneHandler::Init() {
static ClassDocumentation<AriadneHandler> documentation
("The AriadneHandler class administers the Ariadne dipole "
"cascade.",
"Parton cascades performed by Ariadne\\cite{Lav05} according to the "
"Dipole Cascade Model\\cite{Gustafson:1986db,Gustafson:1988rq,"
"Andersson:1989gp,Andersson:1990ki}.",
"\\bibitem{Lav05}"
"Nils Lavesson and Leif L\\\"onnblad, Preprint in preparation.\n"
"\\bibitem{Gustafson:1986db}"
"G\\\"osta Gustafson, Phys.~Lett.~{\\bf B175} (1986) 453.\n"
"\\bibitem{Gustafson:1988rq}"
"G\\\"osta Gustafson and Ulf Pettersson, "
"Nucl.~Phys.~{\\bf B306} (1988) 746.\n"
"\\bibitem{Andersson:1989gp}"
"Bo Andersson, et al., Z.~Phys.~{\\bf C43} (1989) 625.\n"
"\\bibitem{Andersson:1990ki}"
"Bo Andersson, et al., Nucl.~Phys.~{\\bf B339} (1990) 393.");
static Switch<AriadneHandler,RunningOption> interfaceRunningCoupling
("RunningCoupling",
"Strategy for handling \\f$\\alpha_S\\f$.",
&AriadneHandler::theRunningCoupling, simpleRunning, true, false);
static SwitchOption interfaceRunningCouplingSimpleRunning
(interfaceRunningCoupling,
"SimpleRunning",
"Use a one loop running coupling with \\f$\\Lambda_{QCD}\\f$ given "
"by <interface>LambdaQCD</interface>.",
simpleRunning);
static SwitchOption interfaceRunningCouplingConstant
(interfaceRunningCoupling,
"Constant",
"Use a constant coupling given by <interface>Alpha0</interface>.",
noRunning);
static SwitchOption interfaceRunningCouplingExternalRunning
(interfaceRunningCoupling,
"ExternalRunning",
"Use whatever coupling is specified by the current StandardModelBase "
"object.",
externalRunning);
static SwitchOption interfaceRunningCouplingInternalRUnning
(interfaceRunningCoupling,
"InternalRunning",
"Use the coupling specified by <interface>InternalAlphaS</interface>.",
internalRunning);
static Parameter<AriadneHandler,double> interfaceAlpha0
("Alpha0",
"The constant \\f$\\alpha_S\\f$ to use if "
"<interface>RunningCoupling</interface> is set to Constant.",
&AriadneHandler::theAlpha0, 0.2, 0.0, 0,
true, false, Interface::lowerlim);
static Parameter<AriadneHandler,double> interfaceAlphaEM0
("AlphaEM0",
"The constant \\f$\\alpha_{EM}\\f$ to use. If zero, use whatever "
"is specified in the current StandardModelBase object.",
&AriadneHandler::theAlphaEM0, 1.0/137.0, 0.0, 0,
true, false, Interface::lowerlim);
static Parameter<AriadneHandler,Energy> interfaceLambdaQCD
("LambdaQCD",
"The \\f$\\Lambda_{QCD}\\f$ to use in the one loop running "
"\\f$\\alpha_S\\f$ if <interface>RunningCoupling</interface> "
"is set to Running.",
&AriadneHandler::theLambdaQCD, GeV, 0.22*GeV, 0.0*GeV,
Constants::MaxEnergy,
true, false, Interface::limited,
0, 0, 0, &AriadneHandler::maxLambdaQCD, 0);
static Parameter<AriadneHandler,double> interfaceScaleFactor
("ScaleFactor",
"Scale factor used to multiply the emission scales in the argument of "
"\\f$\alpha_S\\f$.",
&AriadneHandler::scaleFactor, 1.0, 0.0, 0,
true, false, Interface::lowerlim);
static Parameter<AriadneHandler,Energy> interfacePTCut
("PTCut",
"The cutoff in invariant transverse momentum for QCD emissions.",
&AriadneHandler::thePTCut, GeV, 0.6*GeV, 0.0*GeV, 0*GeV,
true, false, Interface::lowerlim,
0, 0, &AriadneHandler::minPTCut, 0, 0);
static Parameter<AriadneHandler,Energy> interfacePTCutEM
("PTCutEM",
"The cutoff in invariant transverse momentum for QED emissions.",
&AriadneHandler::thePTCutEM, GeV, 0.6*GeV, 0.0*GeV, 0*GeV,
true, false, Interface::lowerlim);
static Parameter<AriadneHandler,int> interfaceDipoleColours
("DipoleColours",
"The number of differently coloured dipoles possible. This should "
"normally be 8, but may be varied to check the effects of colour "
"reconnections.",
&AriadneHandler::theNCol, 8, 3, 0,
true, false, Interface::lowerlim);
static Parameter<AriadneHandler,int> interfaceNFlav
("NFlav",
"The number of possible flavours in a \f$g\to q\bar{q}\f$ splitting.",
&AriadneHandler::theNFlav, 5, 0, 8,
true, false, Interface::lowerlim);
static Switch<AriadneHandler,bool> interfacePhotonEmissions
("PhotonEmissions",
"Switches photon emission in the cascade on and off.",
&AriadneHandler::thePhotonEmissions, false, true, false);
static SwitchOption interfacePhotonEmissionsOn
(interfacePhotonEmissions,
"On",
"Switch photon emission on",
true);
static SwitchOption interfacePhotonEmissionsOff
(interfacePhotonEmissions,
"Off",
"Switch photon emission off.",
false);
static Parameter<AriadneHandler,Energy> interfaceSoftMu
("SoftMu",
"The inverse extension of a hadron remnant used in the soft "
"suppression mechanism. See also <interface>SoftAlphs</interface> and "
"<interface>Beta</interface>",
&AriadneHandler::theSoftMu, GeV, 0.6*GeV, 0.0*GeV, 0*GeV,
true, false, Interface::lowerlim);
static Parameter<AriadneHandler,double> interfaceSoftAlpha
("SoftAlpha",
"The dimension of the extension of a hadron remnant used in the "
"soft-suppression mechanism. See also <interface>SoftMu</interface> "
"and <interface>Beta</interface>.",
&AriadneHandler::theSoftAlpha, 1.0, 0.0, 0,
true, false, Interface::lowerlim);
static Parameter<AriadneHandler,double> interfaceHardAlpha
("HardAlpha",
"The dimension of the extension of a hard remnant used in the "
"soft-suppression mechanism for radiation off a scattered quark in "
"DIS at small \\f$Q^2\\f$. If set negative, the value of "
"<interface>SoftAlpha</interface> will be used instead. See also "
"<interface>Beta</interface>.",
&AriadneHandler::theHardAlpha, -1.0, -1.0, 0,
true, false, Interface::lowerlim);
static Parameter<AriadneHandler,double> interfaceBeta
("Beta",
"The power in the suppression of radiation from extended dipoles. "
"The original soft suppression model used a sharp cutoff in the "
"transverse-momentum--rapidity space of an emitted gluon. This parameter "
"is used to allow emissions with larger transverse momentum according to "
"\\f$P(p_\\perp^2>p_{\\perp cut}^2="
"\\left(\\frac{p_{\\perp cut}^2}{p_\\perp^2}\\right)^\\beta\\f$. if "
"negative, the sharp cutoff is retained.",
&AriadneHandler::theBeta, 2.0, -1.0, 0,
true, false, Interface::lowerlim);
static RefVector<AriadneHandler,Ariadne5::ReweightBase> interfaceReweighters
("Reweighters",
"A vector of objects implementing reweightings of basic dipole "
"emissions. Each dipole emission will be reweighted.",
&AriadneHandler::theReweighters, -1, true, false, true, false, false);
static Parameter<AriadneHandler,int> interfaceMaxEmissions
("MaxEmissions",
"This number specifies the maximum number of emissions from the "
"cascade. If it is set to zero an unlimited number is allowed. "
"This parameter should only be used for debugging purposes.",
&AriadneHandler::theMaxEmissions, 0, 0, 0,
true, false, Interface::lowerlim);
static Reference<AriadneHandler,AlphaSBase> interfaceInternalAlphaS
("InternalAlphaS",
"An internal AlphaSBase object to be used if "
"<interface>RunningCoupling</interface> is set to InternalRunning. "
"If no such object is given, A O1AlphaS object will be created and "
"assigned in the initialization with <interface>LambdaQCD</interface> "
"used as lambda for five flavours.",
&AriadneHandler::theInternalAlphaS, true, false, true, true, false);
static RefVector<AriadneHandler,EmitterBase> interfaceEmitters
("Emitters",
"The vector of EmittorBase objects responsible for generatong and "
"performing emissions according to the Dipole Cascade Model and its "
"extentions. For each dipole, all Emitters are tried in turn if to see "
"if they are able to model emissions. Only one EmittorBase object of "
"each SubClass will be used (earlier ones will override later ones "
"in the vector).",
&AriadneHandler::theEmitters, -1, true, false, true, false, false);
static RefVector<AriadneHandler,BornCheckerBase> interfaceBornCheckers
("BornCheckers",
" A vector of BornCheckerBase objects which are used in the CKKW-L "
"algorithm to check if a reclustered dipole state corresponds to a "
"reasonable Born-level state (the lowest jet-multiplicity state in a "
"CKKW-L merging). At least one object must be assigned in order for "
"the CKKW-L algorithm to work.",
&AriadneHandler::theBornCheckers, -1, true, false, true, false, false);
static Reference<AriadneHandler,ScaleSetter> interfaceScaleSetter
("ScaleSetter",
"The object responsible for choosing the starting scale of the "
"Ariadne dipole shower.",
&AriadneHandler::theScaleSetter, true, false, true, false, true);
static Reference<AriadneHandler,DISFinder> interfaceDISFinder
("DISFinder",
"The object responsible for identifying DIS-like event.",
&AriadneHandler::theDISFinder, true, false, true, true, false);
static Reference<AriadneHandler,ResonanceFinder> interfaceResonanceFinder
("ResonanceFinder",
"The object responsible for identifying DIS-like event.",
&AriadneHandler::theResonanceFinder, true, false, true, false, false);
static Reference<AriadneHandler,QCDDipoleFinder> interfaceQCDFinder
("QCDFinder",
"The Object responsible for identifying QCD Diploles.",
&AriadneHandler::theQCDFinder, true, false, true, false, false);
static Reference<AriadneHandler,EMDipoleFinder> interfaceEMFinder
("EMFinder",
"The Object responsible for identifying electro-magnetic Diploles. "
"If null, all electro-magnetic radiation will be switched off.",
&AriadneHandler::theEMFinder, true, false, true, true, false);
static Reference<AriadneHandler,ColourResonanceModel>
interfaceColourResonanceModel
("ColourResonanceModel",
"The object responsible for radiating from decay products from "
"coloured resonances.",
&AriadneHandler::theColourResonanceModel, true, false, true, true, false);
static Reference<AriadneHandler,RemnantModel> interfaceRemnantModel
("RemnantModel",
"The object responsible for radiating from remnants.",
&AriadneHandler::theRemnantModel, true, false, true, false, false);
static Reference<AriadneHandler,ConsistencyChecker> interfaceConsistencyChecker
("ConsistencyChecker",
"The object responsible for checking the consistency of a DipoleState.",
&AriadneHandler::consistency, true, false, true, true, false);
static Switch<AriadneHandler,PurgeStrategy> interfacePurgeStrategy
("PurgeStrategy",
"The strategy for purging gluons with transverse momentum less than a factor <interface>PurgeFactor</interface> times the cutoff.",
&AriadneHandler::thePurgeStrategy, neverpurge, true, false);
static SwitchOption interfacePurgeStrategyOnlyBefore
(interfacePurgeStrategy,
"OnlyBefore",
"Gluons are only purged before the cascade.",
onlybefore);
static SwitchOption interfacePurgeStrategyOnlyAfter
(interfacePurgeStrategy,
"OnlyAfter",
"Gluons are only purged after the cascade.",
onlyafter);
static SwitchOption interfacePurgeStrategyNever
(interfacePurgeStrategy,
"Never",
"Gluon purging is switched off.",
neverpurge);
static SwitchOption interfacePurgeStrategyBeforeAndAfter
(interfacePurgeStrategy,
"BeforeAndAfter",
"Gluons are purged before and after the cascade.",
beforeandafter);
static SwitchOption interfacePurgeStrategyEveryStep
(interfacePurgeStrategy,
"EveryStep",
"Gluons are purged before (and after) each step of the cascade.",
everystep);
static Parameter<AriadneHandler,double> interfacePurgeFactor
("PurgeFactor",
"The factor used to determine how far below the cutoff a gluon may be before "
"it is purged. If the transverse momentum of a gluon is less than this factor "
"times the cutoff it will be purged. Cf. <interface>PurgeStrategy</interface>.",
&AriadneHandler::thePurgeFactor, 0.0, 0.0, 0,
true, false, Interface::lowerlim);
interfacePTCut.rank(10);
interfaceLambdaQCD.rank(9);
interfaceNFlav.rank(8);
interfaceSoftMu.rank(7);
interfaceSoftAlpha.rank(6);
interfaceHardAlpha.rank(5);
interfaceBeta.rank(4);
}
diff --git a/Cascade/CascadeBase.h b/Cascade/CascadeBase.h
--- a/Cascade/CascadeBase.h
+++ b/Cascade/CascadeBase.h
@@ -1,175 +1,172 @@
// -*- C++ -*-
#ifndef Ariadne5_CascadeBase_H
#define Ariadne5_CascadeBase_H
//
// This is the declaration of the CascadeBase class.
//
#include "Ariadne/Config/Ariadne5.h"
#include "Ariadne/Config/CloneBase.h"
#include "CascadeBase.fh"
#include "DipoleState.fh"
#include "AriadneHandler.fh"
#include "ThePEG/Utilities/Current.h"
namespace Ariadne5 {
-using Ariadne::CloneBase;
-using Ariadne::ClonePtr;
-
/**
* CascadeBase is the base class of all Partons, Dipoles and
* DipoleState classes in the Ariadne dipole cascade classes. It keeps
* track of the DioleState to which an object belongs.
*/
class CascadeBase: public CloneBase {
public:
/**
* The DipoleState is a friend.
*/
friend class DipoleState;
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor has an optional pointer to the
* CascadeHandler in charge as argument.
*/
inline CascadeBase(): isTouched(true) {}
/**
* The destructor.
*/
inline virtual ~CascadeBase() {}
//@}
public:
/** @name Functions relating to the DipoleState and CascadeHandler
* to which this belongs. */
//@{
/**
* Get the Ariadne::AriadneHandler in charge of the current generation.
*/
inline tHandlerPtr handler() const {
return Current<AriadneHandler>::ptr();
}
/**
* Get the DipoleState to which this Object belongs.
*/
inline tDipoleStatePtr state() const {
return theState;
}
protected:
/**
* Set the DipoleState to which this Dipole belongs.
*/
inline void state(tDipoleStatePtr ds) {
theState= ds;
}
/**
* Fill the provided set with all pointers to CloneBase objects used
* in this object.
*/
virtual void fillReferences(CloneSet &) 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:
/** @name Functions determining if the object has been changed since
the last generation. */
//@{
/**
* If true, this object has been modified since the last round of
* generating emissions.
*/
inline bool touched() const {
return isTouched;
}
/**
* Signal that this object has been modified.
*/
inline void touch() {
isTouched = true;
}
/**
* Signal that all possible emissions involving this object has been
* generated.
*/
inline void untouch() {
isTouched = false;
}
//@}
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 DipoleState to which this Dipole belongs.
*/
tDipoleStatePtr theState;
/**
* If true, this object has been modified since the last round of
* generating emissions.
*/
bool isTouched;
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
CascadeBase & operator=(const CascadeBase &);
};
}
#endif /* Ariadne5_CascadeBase_H */
diff --git a/Cascade/EMDipole.cc b/Cascade/EMDipole.cc
--- a/Cascade/EMDipole.cc
+++ b/Cascade/EMDipole.cc
@@ -1,59 +1,59 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the EMDipole class.
//
#include "EMDipole.h"
#include "Parton.h"
#include "AriadneHandler.h"
#include "ThePEG/Utilities/Current.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Utilities/DescribeClass.h"
using namespace Ariadne5;
EMDipole::EMDipole()
: theSystem(0) {
theRhoCut = Current<AriadneHandler>()->pTCutEM();
}
ClonePtr EMDipole::clone() const {
return new_ptr(*this);
}
Energy2 EMDipole::sdip() const {
return (iPart()->momentum() + oPart()->momentum()).m2();
}
void EMDipole::fillReferences(CloneSet & cset) const {
DipoleBase::fillReferences(cset);
cset.insert(oPart());
cset.insert(iPart());
}
void EMDipole::rebind(const TranslationMap & trans) {
DipoleBase::rebind(trans);
oPart(trans.translate(oPart()));
iPart(trans.translate(iPart()));
}
void EMDipole::persistentOutput(PersistentOStream & os) const {
os << theIPart << theOPart << theSystem;
}
void EMDipole::persistentInput(PersistentIStream & is, int) {
is >> theIPart >> theOPart >> theSystem;
}
DescribeClass<EMDipole,DipoleBase>
-describeAriadne5EMDipole("Ariadne::EMDipole", "libAriadne.so");
+describeAriadne5EMDipole("Ariadne5::EMDipole", "libAriadne5.so");
void EMDipole::Init() {}
void EMDipole::debugme() const {
DipoleBase::debugme();
}
diff --git a/Cascade/Emission.cc b/Cascade/Emission.cc
--- a/Cascade/Emission.cc
+++ b/Cascade/Emission.cc
@@ -1,119 +1,119 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the Emission class.
//
#include "Emission.h"
#include "EmitterBase.h"
#include "Parton.h"
#include "DipoleState.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Utilities/UnitIO.h"
#include "ThePEG/Utilities/EnumIO.h"
#include "ThePEG/Utilities/StringUtils.h"
#include "Ariadne/Config/UnitFO.h"
using namespace Ariadne5;
void Emission::fillReferences(CloneSet & cset) const {}
void Emission::rebind(const TranslationMap & trans) {
dipole = trans.translate(dipole);
cdipole = trans.translate(cdipole);
vector<tParPtr> rold;
rold.swap(radiators);
trans.translate(inserter(radiators), rold.begin(), rold.end());
vector<tParPtr> parold;
parold.swap(partons);
trans.translate(inserter(partons), parold.begin(), parold.end());
vector<tParPtr> aold;
aold.swap(affected);
trans.translate(inserter(affected), aold.begin(), aold.end());
colourParent = trans.translate(colourParent);
antiColourParent = trans.translate(antiColourParent);
mainParent = trans.translate(mainParent);
}
bool Emission::perform() const {
state = performed;
if ( !model->perform(*this) ) return false;
if ( model->finalVeto(*this) ) return false;
return true;
}
void Emission::revert() const {
model->revert(*this);
state = reverted;
}
void Emission::persistentOutput(PersistentOStream & os) const {
os << oenum(state) << emno << geno
<< ounit(pold.first, GeV) << ounit(pold.second, GeV)
<< ounit(rho, GeV) << y << ounit(genmom.first, GeV)
<< ounit(genmom.second, GeV) << ounit(genmom.third, GeV)
<< ymax << orderAlphaS << orderAlphaEW
<< dipole << cdipole << radiators << partons << affected << prob
<< weightPDF << reversible << failsafe << colourParent << antiColourParent
<< mainParent;
}
void Emission::persistentInput(PersistentIStream & is, int) {
is >> ienum(state) >> emno >> geno
>> iunit(pold.first, GeV) >> iunit(pold.second, GeV)
>> iunit(rho, GeV) >> y >> iunit(genmom.first, GeV)
>> iunit(genmom.second, GeV) >> iunit(genmom.third, GeV)
>> ymax >> orderAlphaS >> orderAlphaEW
>> dipole >> cdipole >> radiators >> partons >> affected >> prob
>> weightPDF >> reversible >> failsafe >> colourParent >> antiColourParent
>> mainParent;
}
DescribeAbstractClass<Emission,CloneBase>
-describeAriadne5Emission("Ariadne5::Emission", "libAriadne.so");
+describeAriadne5Emission("Ariadne5::Emission", "libAriadne5.so");
void Emission::Init() {}
void Emission::debugme() const {
LorentzMomentum diff = genmom.first + genmom.second + genmom.third
- pold.first - pold.second;
cerr << endl
<< "Emission type: " << StringUtils::typeName(typeid(*this)) << endl
<< " Emitter type: " << StringUtils::typeName(typeid(*model)) << endl
<< "Generation no: " << geno << endl
<< " Emission no: " << emno << endl
<< " State: ";
switch ( state ) {
case generated:
cerr << "generated";
break;
case performed:
cerr << "performed";
break;
case reverted:
cerr << "reverted";
}
if ( failsafe ) cerr << " (failsafe)";
cerr << endl
<< " scale: " << rho/GeV << endl
<< " pold: " << founit(pold.first, GeV, 10, 4) << endl
<< " " << founit(pold.second, GeV, 10, 4) << endl
<< " genmom: " << founit(genmom.first, GeV, 10, 4) << endl
<< " " << founit(genmom.second, GeV, 10, 4) << endl
<< " " << founit(genmom.third, GeV, 10, 4) << endl
<< " diff: " << founit(diff, GeV, 10, 1, ios::scientific) << endl
<< " dipole: " << cdipole->state()->index(cdipole) << endl
<< " partons:";
for ( unsigned i = 0; i < radiators.size(); ++i )
cerr << (radiators[i] == mainParent? " *": " ")
<< cdipole->state()->index(radiators[i]);
cerr << " ->";
for ( unsigned i = 0; i < partons.size(); ++i )
cerr << " " << cdipole->state()->index(partons[i]);
cerr << endl;
}
diff --git a/Cascade/Emission.h b/Cascade/Emission.h
--- a/Cascade/Emission.h
+++ b/Cascade/Emission.h
@@ -1,311 +1,308 @@
// -*- C++ -*-
#ifndef Ariadne5_Emission_H
#define Ariadne5_Emission_H
//
// This is the declaration of the Emission class.
//
#include "Ariadne/Config/Ariadne5.h"
#include "Ariadne/Config/CloneBase.h"
#include "Emission.fh"
#include "EmitterBase.fh"
#include "DipoleBase.fh"
#include "Parton.fh"
#include "ThePEG/Utilities/Triplet.h"
namespace Ariadne5 {
-using Ariadne::CloneBase;
-using Ariadne::ClonePtr;
-
/**
* Emission is the base class to be used by all sub-classes of
* EmissionModel to specify a generated emission for an Emitter.
*/
class Emission: public CloneBase {
public:
/** Convenient typedef. */
typedef Triplet<Lorentz5Momentum,Lorentz5Momentum,Lorentz5Momentum> Trip;
/**
* Enum giving the state of this Emission.
*/
enum State {
generated, /**< This Emission has been created but not yet performed. */
performed, /**< This Emission has been performed. */
reverted /**< This Emission has been performed but then reverted. */
};
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The only relevant constructor.
*/
Emission(const EmitterBase & inmodel, const DipoleBase & indipole)
: state(generated), emno(0), geno(0), model(&inmodel), cdipole(&indipole),
rho(ZERO), y(0.0), ymax(-1.0),
orderAlphaS(1), orderAlphaEW(0), prob(-1.0), weightPDF(-1.0),
reversible(true), failsafe(false) {}
/**
* The deault constructor should not normally be used.
*/
Emission(): state(generated), emno(0), geno(0), rho(ZERO), y(0.0), ymax(-1.0),
orderAlphaS(0), orderAlphaEW(0), prob(-1.0), weightPDF(-1.0),
reversible(false), failsafe(false) {}
/**
* The destructor.
*/
virtual ~Emission() {}
//@}
public:
/** @name Functions relating to the DipoleState and CascadeHandler
* to which this belongs. */
//@{
/**
* Fill the provided set with all pointers to CloneBase objects used
* in this object.
*/
virtual void fillReferences(CloneSet &) 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:
/**
* Perform this emission.
*/
bool perform() const;
/**
* Revert this emission if it for some reason failed.
*/
void revert() const;
/**
* The State of this Emission
*/
mutable State state;
/**
* The emission number
*/
mutable int emno;
/**
* The generation number
*/
mutable int geno;
/**
* The emission model.
*/
tcEmitterPtr model;
/**
* The unmutable dipole, available during the generation.
*/
tcDBPtr cdipole;
/**
* The dipole. Is only set after the full emission has been generated.
*/
tDBPtr dipole;
/**
* The momentum of the original partons.
*/
mutable pair<Lorentz5Momentum,Lorentz5Momentum> pold;
/**
* The evolution scale of the generated emission.
*/
Energy rho;
/**
*The invariant rapidity of the generated emission.
*/
double y;
/**
* The generated mometa.
*/
mutable Trip genmom;
/**
* The approximate maximum invariant rapidity possible for the
* given scale (typically given by log(S/pt^2)/2. Is negative if
* no such value is given.
*/
double ymax;
/**
* The order in \f$\alpha_S\f$ of this emission. If this is a
* pre-generated emission (e.g. a decay given already in the hard
* sub-process) it should be set to the negative.
*/
int orderAlphaS;
/**
* The order in \f$\alpha_{EW}\f$ of this emission. If this is
* a pre-generated emission (e.g. a decay given already in the
* hard sub-process) it shoule be set to the negative.
*/
int orderAlphaEW;
/**
* The partons responsible for the emission (if any). Typically the
* two partons spanning a dipole.
*/
vector<tParPtr> radiators;
/**
* The parent which was the incoming (coloured) parton in the
* original dipole.
*/
tParPtr colourParent;
/**
* The parent which was the outgoing (anti-coloured) parton in the
* original dipole.
*/
tParPtr antiColourParent;
/**
* The parent from which the main particle was most likely emitted.
*/
tParPtr mainParent;
/**
* The list of emitted partons
*/
mutable vector<tParPtr> partons;
/**
* The list of partons which are affected by this emission.
*/
mutable vector<tParPtr> affected;
/**
* The splitting probability for this (inverse) emission given in
* units of 1/GeV.
*/
double prob;
/**
* The PDF ratio weight for this (inverse) emission.
*/
double weightPDF;
/**
* Can the emitter model revert this Emission so that the
* DipoleSystem can be completely restored?
*/
bool reversible;
/**
* Can the emitter model guarantee that this Emission is failsafe?
*/
bool failsafe;
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();
/**
* Standard debug function to be called from within a debugger.
*/
void debugme() const;
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
Emission & operator=(const Emission &);
};
/**
* Special container class to help selecting the emission with largest scale.
*/
class EmSel {
public:
/**
* The only constructor requires an Energy variable where the
* largest scale so far is modified.
*/
EmSel(Energy & rhom): rhomax(rhom) {}
/**
* Conditionally assing the given Emission if it is the largest
* scale so far.
*/
EmSel & operator=(EmPtr e) {
if ( !sel || ( e && e->rho > sel->rho ) ) sel = e;
if ( sel ) rhomax = max(sel->rho, rhomax);
return *this;
}
operator EmPtr () {
return sel;
}
private:
/**
* The selected Emission.
*/
EmPtr sel;
/**
* The Energy variable keeping track of the highest scale so far.
*/
Energy & rhomax;
};
}
#endif /* Ariadne5_Emission_H */
diff --git a/Cascade/EmitterBase.cc b/Cascade/EmitterBase.cc
--- a/Cascade/EmitterBase.cc
+++ b/Cascade/EmitterBase.cc
@@ -1,368 +1,368 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the EmitterBase class.
//
#include "EmitterBase.h"
#include "Emission.h"
#include "QCDDipole.h"
#include "Parton.h"
#include "Junction.h"
#include "RemnantParton.h"
#include "ResonanceParton.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/RefVector.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/StandardModel/StandardModelBase.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Utilities/Current.h"
#include "ThePEG/Utilities/Throw.h"
#include "ThePEG/Utilities/SimplePhaseSpace.h"
#include "ThePEG/Utilities/UtilityBase.h"
#include "ThePEG/Repository/UseRandom.h"
#include "AriadneHandler.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace Ariadne5;
/*
We will assume that an external alphas is of second order where the
first order is
alphas_s(mu)=1/(b0 x) [with x = log(mu^2/Lambda^2)]
giving the second order
alpha_s(mu)= 1/(b0 x){1 - (b1/(b0**2))*(log(x)/x) +
((b1**2)*(log(x)**2-log(x)-1) + b0*b2)/(b0*x)**2}
with
b0 = (33-2*nf)/(12*pi)
b1 = (153-19*nf)/(24*pi**2)
b2 = (2857 - 5033*nf/9 + 325*(nf**2)/27)/(128*pi**3)
the second order effects are approximated by a shift in Lambda and a factor
alpha1_s(mu)=C/(b0*(x-shift))
as2(x1)==C/(b0*(x1-shift))
as2(x2)==C//b0*(x2-shift))
as2(x1)/as2(x2)==(x1-shift)/(x2-shift)
*/
Energy EmitterBase::rhoCut() const {
return Current<AriadneHandler>()->pTCut();
}
bool EmitterBase::touched(const DipoleBase & dipole) const {
if ( dipole.touched() ) return true;
if ( tcQCDPtr d = dynamic_ptr_cast<tcQCDPtr>(&dipole) )
if ( d->iPart()->touched() || d->oPart()->touched() ) return true;
return false;
}
Energy2 EmitterBase::rndsud(double C, Energy2 pt2max, Energy2 pt2min) {
if ( Current<AriadneHandler>()->runningCoupling() !=
AriadneHandler::noRunning ) return runrndsud(C, pt2max, pt2min);
double CN = 1.0/(C*Current<AriadneHandler>()->alpha0());
double R = UseRandom::rnd();
return CN*log(R) < log(pt2min/pt2max)? -1.0*GeV2: pt2max*pow(R, CN);
}
Energy2 EmitterBase::
runrndsud(double C, Energy2 pt2max, Energy2 pt2min) {
// Check which flavour thresholds we are between.
set<Energy2>::iterator fit =
Current<AriadneHandler>()->flavourThresholds().lower_bound(pt2max);
Energy2 pt2cut = pt2min;
if ( fit != Current<AriadneHandler>()->flavourThresholds().begin() )
pt2cut = max(*(--fit), pt2min);
Energy2 pt2m = sqrt(pt2max*pt2cut);
Energy2 pt2u = sqrt(pt2max*pt2m);
Energy2 pt2l = sqrt(pt2cut*pt2m);
// Sample alpha0 away from flavour thresholds to be on the safe side.
double aup = Current<AriadneHandler>()->alphaS(pt2u);
double alo = Current<AriadneHandler>()->alphaS(pt2l);
if ( abs(aup - alo) < 1.0e-12 ) {
pt2u *= 2.0;
aup = Current<AriadneHandler>()->alphaS(pt2u);
}
double a0 = aup*alo*log(pt2l/pt2u)/(aup - alo);
Energy2 Lam2 = pt2u/exp(a0/aup);
// Add a little margin to the derived alpha0 to avoid rounding errors.
double CN = 0.9/(C*a0);
double logpt2min = log(pt2min/Lam2);
while ( true ) {
double RtoCN = pow(UseRandom::rnd(), CN);
if ( RtoCN <= logpt2min/log(pt2max/Lam2) )
pt2max = ZERO;
else
pt2max = Lam2*pow(pt2max/Lam2, RtoCN);
if ( pt2max < pt2cut )
return pt2cut > pt2min? runrndsud(C, pt2cut, pt2min): pt2max;
double weight = Current<AriadneHandler>()->alphaS(pt2max)*
log(pt2max/Lam2)*0.9/a0;
if ( weight > 1.0 )
Throw<WeightException>()
- << "The Ariadne::CascadeHandler '"
+ << "The Ariadne5::CascadeHandler '"
<< Current<AriadneHandler>()->name()
<< "' failed to overestimate the alpha_S specified by the StandardModel "
<< "object. If this hapens too often you should contact the authors."
<< Exception::warning;
if ( UseRandom::rnd() < weight ) return pt2max;
}
}
bool EmitterBase::
check(double x1, double x3, double y1, double y2, double y3) {
double x2 = 2.0 - x1 - x3;
if ( x1 < 0.0 || x2 < 0.0 || x3 < 0.0 ) return false;
double pp1 = sqr(0.5*x1) - y1;
double pp2 = sqr(0.5*x2) - y2;
double pp3 = sqr(0.5*x3) - y3;
if ( pp1 < 0.0 || pp2 < 0.0 || pp3 < 0.0 ||
2.0*(pp1*pp2 + pp2*pp3 + pp3*pp1) <= sqr(pp1) + sqr(pp2) + sqr(pp3) )
return false;
return true;
}
double EmitterBase::
preweight(const Emission & emission) const {
double w = 1.0;
for ( int i = 0, N = theReweighters.size(); i < N; ++i )
w *= theReweighters[i]->preweight(emission);
const vector<DipoleRWPtr> & auxw =
Current<AriadneHandler>()->reweighters();
for ( int i = 0, N = auxw.size(); i < N; ++i )
w *= auxw[i]->preweight(emission);
return w;
}
double EmitterBase::
reweight(const Emission & emission) const {
double w = 1.0;
for ( int i = 0, N = theReweighters.size(); i < N; ++i )
w *= theReweighters[i]->reweight(emission);
const vector<DipoleRWPtr> & auxw =
Current<AriadneHandler>()->reweighters();
for ( int i = 0, N = auxw.size(); i < N; ++i )
w *= auxw[i]->reweight(emission);
return w;
}
bool EmitterBase::hasFinalVeto() const {
for ( int i = 0, N = theReweighters.size(); i < N; ++i )
if ( theReweighters[i]->hasFinalVeto() ) return true;
const vector<DipoleRWPtr> & auxw =
Current<AriadneHandler>()->reweighters();
for ( int i = 0, N = auxw.size(); i < N; ++i )
if ( auxw[i]->hasFinalVeto() ) return true;
return false;
}
bool EmitterBase::
finalVeto(const Emission & emission) const {
for ( int i = 0, N = theReweighters.size(); i < N; ++i )
if ( theReweighters[i]->hasFinalVeto() &&
theReweighters[i]->finalVeto(emission) ) return true;
const vector<DipoleRWPtr> & auxw =
Current<AriadneHandler>()->reweighters();
for ( int i = 0, N = auxw.size(); i < N; ++i )
if ( auxw[i]->hasFinalVeto() &&
auxw[i]->finalVeto(emission) ) return true;
return false;
}
Energy2 EmitterBase::invPT2(tcParPtr p1, tcParPtr p2, tcParPtr p3) {
Energy2 s123 = (p1->momentum() + p2->momentum() + p3->momentum()).m2();
Energy2 s12 = (p1->momentum() + p2->momentum()).m2();
Energy2 s23 = (p2->momentum() + p3->momentum()).m2();
Energy m1 = p1->momentum().mass();
Energy m2 = p2->momentum().mass();
Energy m3 = p3->momentum().mass();
return (s12 - sqr(m1 + m2)) * (s23 - sqr(m2 + m3)) / s123;
}
double EmitterBase::invY(tcParPtr p1, tcParPtr p2, tcParPtr p3) {
Energy2 s12 = (p1->momentum() + p2->momentum()).m2();
Energy2 s23 = (p1->momentum() + p2->momentum()).m2();
Energy m1 = p1->momentum().mass();
Energy m2 = p2->momentum().mass();
Energy m3 = p3->momentum().mass();
return 0.5*log((s12 - sqr(m1 + m2))/(s23 - sqr(m2 + m3)));
}
Triplet<Lorentz5Momentum,Lorentz5Momentum,Lorentz5Momentum>
EmitterBase::getMomenta(Energy2 s, double x1, double x3,
Energy m1, Energy m2, Energy m3,
bool nr1, bool nr3, bool userho) {
Trip p =
Trip(Lorentz5Momentum(m1), Lorentz5Momentum(m2), Lorentz5Momentum(m3));
SimplePhaseSpace::CMS(p.first, p.second, p.third, s, x1, x3, 0.0, 0.0, 0.0);
double Psi = Constants::pi - p.third.theta();
double beta = 0.0;
if ( userho ) {
x1 = p.first.rho()/sqrt(s);
x3 = p.third.rho()/sqrt(s);
}
if ( nr1 && nr3 ) beta = Psi*sqr(x3)/(sqr(x1) + sqr(x3)); // minimize pt
else if ( nr3 ) beta = Psi;
else if ( !nr1 && sqr(x3) > UseRandom::rnd()*(sqr(x1) + sqr(x3)) )
beta = Psi;
LorentzRotation R;
R.rotateY(-beta);
p.first.transform(R);
p.second.transform(R);
p.third.transform(R);
return p;
}
Triplet<Lorentz5Momentum,Lorentz5Momentum,Lorentz5Momentum>
EmitterBase::getMomenta(Energy2 s, double x1, double x3,
Energy m1, Energy m2, Energy m3,
bool nr1, bool nr3, double phi, bool userho) {
Trip p =
Trip(Lorentz5Momentum(m1), Lorentz5Momentum(m2), Lorentz5Momentum(m3));
SimplePhaseSpace::CMS(p.first, p.second, p.third, s, x1, x3, 0.0, 0.0, 0.0);
double Psi = Constants::pi - p.third.theta();
double beta = 0.0;
if ( userho ) {
x1 = p.first.rho()/sqrt(s);
x3 = p.third.rho()/sqrt(s);
}
if ( nr1 && nr3 ) beta = Psi*sqr(x3)/(sqr(x1) + sqr(x3)); // minimize pt
else if ( nr3 ) beta = Psi;
else if ( !nr1 && sqr(x3) > UseRandom::rnd()*(sqr(x1) + sqr(x3)) )
beta = Psi;
LorentzRotation R;
R.rotateY(-beta);
R.rotateZ(phi);
p.first.transform(R);
p.second.transform(R);
p.third.transform(R);
return p;
}
Triplet<Lorentz5Momentum,Lorentz5Momentum,Lorentz5Momentum>
EmitterBase::
getMomenta(Energy2 s, double x1, double x3,
Energy m1, Energy m2, Energy m3, bool nr1, bool nr3, double phi,
const Lorentz5Momentum & p1, const Lorentz5Momentum & p3,
bool userho) {
Trip p =
Trip(Lorentz5Momentum(m1), Lorentz5Momentum(m2), Lorentz5Momentum(m3));
SimplePhaseSpace::CMS(p.first, p.second, p.third, s, x1, x3, 0.0, 0.0, 0.0);
double Psi = Constants::pi - p.third.theta();
double beta = 0.0;
if ( userho ) {
x1 = p.first.rho()/sqrt(s);
x3 = p.third.rho()/sqrt(s);
}
if ( nr1 && nr3 ) beta = Psi*sqr(x3)/(sqr(x1) + sqr(x3)); // minimize pt
else if ( nr3 ) beta = Psi;
else if ( !nr1 && sqr(x3) > UseRandom::rnd()*(sqr(x1) + sqr(x3)) ) beta = Psi;
LorentzRotation R;
R.rotateY(-beta);
R.rotateZ(phi);
R.transform(Utilities::getBoostFromCM(make_pair(p1, p3)));
p.first.transform(R);
p.second.transform(R);
p.third.transform(R);
return p;
}
void EmitterBase::revert(const Emission & emission) const {
Throw<Exception>()
<< "The emitter model " << fullName()
<< " has not implemented a revert() method even though it reports "
<< "that e performed emission was reversible. Please contact the author "
<< "to have this error corrected." << Exception::runerror;
}
vector<EmPtr> EmitterBase::inverseEmissions(const DipoleState &) const {
vector<EmPtr> ret;
return ret;
}
bool EmitterBase::overrideInverse(const Emission &) const {
return false;
}
bool EmitterBase::performInverse(const Emission &, DipoleState &) const {
return false;
}
// If needed, insert default implementations of virtual function defined
// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs).
void EmitterBase::persistentOutput(PersistentOStream & os) const {
os << theReweighters << canReconstruct << willReconstruct;
}
void EmitterBase::persistentInput(PersistentIStream & is, int) {
is >> theReweighters >> canReconstruct >> willReconstruct;
}
void EmitterBase::setReconstruct(bool t) {
if ( t && ! canReconstruct )
Throw<InterfaceException>()
<< name() << " cannot be used to reconstruct emissions."
<< Exception::warning;
willReconstruct = t;
}
bool EmitterBase::defReconstruct() const {
return canReconstruct;
}
DescribeAbstractClass<EmitterBase,HandlerBase>
-describeAriadne5EmitterBase("Ariadne5::EmitterBase", "libAriadne.so");
+describeAriadne5EmitterBase("Ariadne5::EmitterBase", "libAriadne5.so");
void EmitterBase::Init() {
static ClassDocumentation<EmitterBase> documentation
("EmitterBase is the base class of all Ariadne classes implementing "
"a specific model for emission from different kinds of dipoles. A "
"sub-class must implement a sub-class of Emission to store the "
"result of an emission.");
static RefVector<EmitterBase,Ariadne5::ReweightBase> interfaceReweighters
("Reweighters",
"A vector of objects implementing reweightings of basic dipole "
"emissions. Each emission modelled by this emission model "
"will be reweighted. Also global reweightors given in the "
- "Ariadne::CascadeHandler will be included.",
+ "Ariadne5::CascadeHandler will be included.",
&EmitterBase::theReweighters, -1, true, false, true, false, false);
static Switch<EmitterBase,bool> interfaceReconstruct
("Reconstruct",
"Determines whether this emitter will be used to reconstruct emissions in the CKKW-L algorithm. May not be possible for all emitters.",
&EmitterBase::willReconstruct, false, true, false,
&EmitterBase::setReconstruct,
(bool(EmitterBase::*)()const)(0), &EmitterBase::defReconstruct);
static SwitchOption interfaceReconstructon
(interfaceReconstruct,
"on",
"This emitter will be used for CKKW-L reconstruction.",
true);
static SwitchOption interfaceReconstructOff
(interfaceReconstruct,
"Off",
"This emitter will not be used for CKKW-L reconstruction.",
false);
}
diff --git a/Cascade/Makefile.am b/Cascade/Makefile.am
--- a/Cascade/Makefile.am
+++ b/Cascade/Makefile.am
@@ -1,47 +1,47 @@
SUBDIRS = Models
mySOURCES = CascadeBase.cc DipoleBase.cc Parton.cc QCDDipole.cc ColourIndex.cc \
EMDipole.cc AriadneHandler.cc ReweightBase.cc \
Emission.cc EmitterBase.cc DipoleState.cc \
EmissionGenerator.cc RemnantParton.cc \
History.cc BornCheckerBase.cc ScaleSetter.cc \
ResonanceFinder.cc Junction.cc ResonanceParton.cc \
QCDDipoleFinder.cc EMDipoleFinder.cc Resonance.cc \
DISFinder.cc ConsistencyChecker.cc StateDipole.cc
DOCFILES = CascadeBase.h DipoleBase.h Parton.h QCDDipole.h ColourIndex.h \
EMDipole.h AriadneHandler.h ReweightBase.h Emission.h \
EmitterBase.h DipoleState.h PartonTraits.h \
EmissionGenerator.h RemnantParton.h \
History.h BornCheckerBase.h ScaleSetter.h ResonanceFinder.h \
Junction.h ResonanceParton.h QCDDipoleFinder.h \
EMDipoleFinder.h Resonance.h DISFinder.h ConsistencyChecker.h \
StateDipole.h
INCLUDEFILES = $(DOCFILES) CascadeBase.fh DipoleState.fh AriadneHandler.fh \
DipoleBase.fh Parton.fh QCDDipole.fh Emission.fh \
EMDipole.fh ReweightBase.fh EmitterBase.fh RemnantParton.fh \
History.fh BornCheckerBase.fh \
ScaleSetter.fh ResonanceFinder.fh Junction.fh \
ResonanceParton.fh QCDDipoleFinder.fh \
EMDipoleFinder.fh Resonance.fh DISFinder.fh ConsistencyChecker.fh \
StateDipole.fh
pkglib_LTLIBRARIES = libAriadne5.la MinPTScale.la MaxPTScale.la
# Version info should be updated if any interface or persistent I/O
# function is changed
libAriadne5_la_LDFLAGS = -module -version-info 1:0:0
libAriadne5_la_SOURCES = $(mySOURCES) $(INCLUDEFILES)
-libAriadne5_la_LIBADD = Models/libAriadne5Models.la
+libAriadne5_la_LIBADD = Models/libAriadne5Models.la ../Config/libAriadne5Config.la
MinPTScale_la_SOURCES = MinPTScale.cc MinPTScale.h
MinPTScale_la_LDFLAGS = -module -version-info 1:0:0
MaxPTScale_la_SOURCES = MaxPTScale.cc MaxPTScale.h
MaxPTScale_la_LDFLAGS = -module -version-info 1:0:0
include $(top_srcdir)/Config/Makefile.aminclude
..check:
cd ..; make check
diff --git a/Cascade/Models/DipoleSwinger.cc b/Cascade/Models/DipoleSwinger.cc
--- a/Cascade/Models/DipoleSwinger.cc
+++ b/Cascade/Models/DipoleSwinger.cc
@@ -1,549 +1,552 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the DipoleSwinger class.
//
#include "FSGluonEmission.h"
#include "DipoleSwinger.h"
#include "Ariadne/Cascade/QCDDipole.h"
#include "Ariadne/Cascade/StateDipole.h"
#include "Ariadne/Cascade/DipoleState.h"
#include "Ariadne/Cascade/AriadneHandler.h"
#include "ThePEG/Utilities/SimplePhaseSpace.h"
#include "ThePEG/Utilities/UtilityBase.h"
#include "ThePEG/Utilities/Throw.h"
#include "ThePEG/Utilities/DebugItem.h"
#include "ThePEG/Utilities/MaxCmp.h"
#include "ThePEG/Utilities/EnumIO.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Command.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Repository/CurrentGenerator.h"
#include "ThePEG/Utilities/EnumIO.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "../../DIPSY/CPUTimer.h"
using namespace Ariadne5;
DipoleSwinger::DipoleSwinger():
lambda(1.0), Rmax(3.5*InvGeV*hbarc), linear(false), sizeOpt(0),
theRhoCut(-1.0*GeV), stringMassCut(ZERO), disallowedrho(0.0*GeV) {}
DipoleSwinger::~DipoleSwinger() {}
IBPtr DipoleSwinger::clone() const {
return new_ptr(*this);
}
IBPtr DipoleSwinger::fullclone() const {
return new_ptr(*this);
}
void DipoleSwinger::TauRatio::plot(Time dt1, Time dt2, int N) const {
double rmax = maximum(dt1, dt2);
for ( int i = 0; i < N; ++i ) {
Time dt = dt1 + (i + 0.5)*(dt2 - dt1)/double(N);
cerr << dt/femtometer << '\t'
<< rat(dt)/rmax << '\t'
<< ounit(sqrt(d1tau2(dt)), femtometer) << '\t'
<< ounit(sqrt(d2tau2(dt)), femtometer) << '\t'
<< ounit(sqrt(r1tau2(dt)), femtometer) << '\t'
<< ounit(sqrt(r2tau2(dt)), femtometer) << endl;
}
}
void DipoleSwinger::TauRatio::debug() const {
cerr << sqrt(-d1tau2.dx2)/femtometer << '\t' << sqrt(-d2tau2.dx2)/femtometer << endl;
cerr << sqrt(-r1tau2.dx2)/femtometer << '\t' << sqrt(-r2tau2.dx2)/femtometer << endl;
cerr << " inf " << rat(ZERO) << '\t' << chris(ZERO) << endl;
cerr << "100.00 " << rat(hbarc/(100.0*GeV)) << '\t' << chris(hbarc/(100.0*GeV)) << endl;
cerr << " 10.00 " << rat(hbarc/(10.0*GeV)) << '\t' << chris(hbarc/(10.0*GeV)) << endl;
cerr << " 1.00 " << rat(hbarc/(1.0*GeV)) << '\t' << chris(hbarc/(1.0*GeV)) << endl;
cerr << " 0.10 " << rat(hbarc/(0.1*GeV)) << '\t' << chris(hbarc/(0.1*GeV)) << endl;
cerr << " 0.01 " << rat(hbarc/(0.01*GeV)) << '\t' << chris(hbarc/(0.01*GeV)) << endl;
cerr << " 0.00 " << rat(hbarc/(0.000001*GeV)) << '\t' << chris(hbarc/(0.000001*GeV)) << endl;
cerr << " " << srat << endl;
cerr << sqrt(s12)/GeV << '\t' << sqrt(s34)/GeV << endl;
cerr << sqrt(s14)/GeV << '\t' << sqrt(s32)/GeV << endl;
}
DipoleSwinger::TauRatio::TauRatio(const QCDDipole & d1, const QCDDipole & d2,
Length Rmaxin, int optin)
: d1tau2(d1.iPart(), d1.oPart(), optin, Rmaxin),
d2tau2(d2.iPart(), d2.oPart(), optin, Rmaxin),
r1tau2(d1.iPart(), d2.oPart(), optin, Rmaxin),
r2tau2(d2.iPart(), d1.oPart(), optin, Rmaxin),
Rmax(Rmaxin), sizeOpt(optin) {
s12 = (d1.iPart()->momentum() + d1.oPart()->momentum()).m2();
s34 = (d2.iPart()->momentum() + d2.oPart()->momentum()).m2();
s14 = (d1.iPart()->momentum() + d2.oPart()->momentum()).m2();
s32 = (d2.iPart()->momentum() + d1.oPart()->momentum()).m2();
srat = (s12*s34)/(s14*s32);
// LorentzMomentum ptot = d1.iPart()->momentum() + d1.oPart()->momentum() +
// d2.iPart()->momentum() + d2.oPart()->momentum();
}
double DipoleSwinger::TauRatio::rat(Time dt) const {
if ( Rmax == ZERO )
return d1tau2(dt)*d2tau2(dt)/(r1tau2(dt)*r2tau2(dt));
if ( sizeOpt == 0 )
return sqr((exp(sqrt(d1tau2(dt))/abs(Rmax)) - 1.0)*(exp(sqrt(d2tau2(dt))/abs(Rmax)) - 1.0)/
((exp(sqrt(r1tau2(dt))/abs(Rmax)) - 1.0)*(exp(sqrt(r2tau2(dt))/abs(Rmax)) - 1.0)));
else if ( Rmax > ZERO )
return exp((sqr(d1tau2.db()) + sqr(d2tau2.db()) - sqr(r1tau2.db()) - sqr(r2tau2.db()))/sqr(Rmax))*
(d1tau2(dt)*d2tau2(dt))/(r1tau2(dt)*r2tau2(dt));
else
return exp(-(d1tau2.db() + d2tau2.db() - r1tau2.db() - r2tau2.db())/Rmax)*
(d1tau2(dt)*d2tau2(dt))/(r1tau2(dt)*r2tau2(dt));
}
double DipoleSwinger::TauRatio::maximum(Time dt1, Time dt2) const {
// return d1tau2.minmax(dt1, dt2).second*d2tau2.minmax(dt1, dt2).second/
// (r1tau2.minmax(dt1, dt2).first*r2tau2.minmax(dt1, dt2).first);
double rmax = max(rat(dt1), rat(dt2));
if ( sizeOpt == 1 ) return 1.01*rmax;
double rmax2 = max(rat(r1tau2.extreme(dt1, dt2)), rat(r2tau2.extreme(dt1, dt2)));
if ( rmax2 > rmax ) rmax = rmax2;
return 1.1*rmax;
}
bool DipoleSwinger::canHandle(const DipoleBase & e) const {
tcStateDipPtr d = dynamic_ptr_cast<tcStateDipPtr>(&e);
if ( !d ) return false;
return true;
}
bool DipoleSwinger::overrides(const EmitterBase &, DipoleBase &) const {
return false;
}
bool DipoleSwinger::touched(const DipoleBase & dipole) const {
return dipole.state()->touched() || dipole.touched() ||
dipole.state() != lastState || dipole.state()->uniqueId != lastStateId;
}
Energy DipoleSwinger::rhoCut() const {
return theRhoCut > ZERO? theRhoCut: EmitterBase::rhoCut();
}
EmPtr DipoleSwinger::
generate(const DipoleBase & dipole, Energy rhomin, Energy rhomax) const {
static DebugItem logme("Ariadne5::DipoleSwinger", 6);
static DebugItem swinglast("Ariadne5::SwingLast", 60);
static CPUClock cpuclock("Ariadne5::DipoleSwinger::generate");
static CPUClock cpuclock1("Ariadne5::DipoleSwinger::generate1");
static CPUClock cpuclock2("Ariadne5::DipoleSwinger::generate2");
static CPUClock cpuclock3("Ariadne5::DipoleSwinger::generate3");
CPUTimer timer(cpuclock);
// Only for debugging.
if ( swinglast && rhomax > 1.0*GeV ) return EmPtr();
// Some swings results in too small strings and are rejected, these
// should be disallowed in the following generations. All such
// dipole pairs are collected in disallowed set until an accepted
// emission (one which lowers the rhomax) is found.
if ( rhomax != disallowedrho ) disallowed.clear();
if ( lastSelected && lastSelected->state == Emission::reverted ) {
disallowed.insert(lastSelected->dipoles);
disallowedrho = rhomax;
}
// Here we collect all dipoes which may swing in different sets
// depending on their colour index. Touched dipoles are alse stored
// in a separate set.
const set<tDBPtr> & activeset = dipole.state()->activeDipoles();
map<ColourIndex, vector<tQCDPtr> > cactive;
map<ColourIndex, vector<tQCDPtr> > ctouched;
for ( set<tDBPtr>::const_iterator it = activeset.begin();
it != activeset.end(); ++it )
if ( tQCDPtr dp = dynamic_ptr_cast<tQCDPtr>(*it) ) {
cactive[dp->colourIndex()].push_back(dp);
if ( dp->touched() || dp->iPart()->touched() || dp->oPart()->touched() )
ctouched[dp->colourIndex()].push_back(dp);
}
CPUTimer timer1(cpuclock1);
// Collect initial values in time (inverse scale) variables.
Time dtmax = hbarc/rhomin;
Time dtmin = hbarc/rhomax;
Time dtmaxcut = hbarc/rhoCut();
Time t0 = hbarc/Current<AriadneHandler>()->pTCut();
// Now check how much we need to redo since last time.
bool redoFull = false;
// If the previous emission was a forced swing of a tiny string, we
// need to redo everything, because everything was not considered
// last time.
if ( lastSelected && lastSelected->state == Emission::performed && lastSelected->forced )
redoFull = true;
// If this is a new dipole state we clearly have to redo everything.
if ( redoFull || dipole.state() != lastState || dipole.state()->uniqueId != lastStateId ) {
redoFull = true;
lastState = dipole.state();
lastStateId = dipole.state()->uniqueId;
cache.clear();
findTinyStrings();
lastSelected = DipSwPtr();
}
// If the state dipole was touched it means the lastSelected swing was performed.
if ( redoFull || dipole.touched() ) lastSelected = DipSwPtr();
// If either dipole in the previous generation was touched can't use the last generated swing.
if ( lastSelected && ( lastSelected->dipoles.first->touched() ||
lastSelected->dipoles.second->touched() ) )
lastSelected = DipSwPtr();
// Just for debugging.
if ( logme && redoFull )
generator()->log() << "DipoleSwinger: Starting new event." << endl;
if ( logme ) generator()->log()
<< "DipoleSwinger: Starting new swing search." << endl;
bool forceTiny = !tinyString.empty();
for ( map<ColourIndex, vector<tQCDPtr> >::iterator ciit = cactive.begin();
ciit != cactive.end(); ++ciit ) {
const vector<tQCDPtr> & active = ciit->second;
if ( active.empty() ) continue;
const vector<tQCDPtr> & touched = ctouched[active[0]->colourIndex()];
int ti1 = touched.empty()? -1: 0;
for ( int i1 = 0, N = active.size(); i1 < N; ++i1 ) {
CPUTimer timer2(cpuclock2);
if ( ti1 >= 0 && touched[ti1] == active[i1] ) ++ti1;
QCDDipole & d1 = *active[i1];
bool inTiny = false;
if ( forceTiny ) inTiny = member(tinyString, &d1);
tcQCDPtr nextnext = tcQCDPtr();
if ( stringMassCut > ZERO && d1.next() && d1.next()->sdip() < sqr(stringMassCut) )
nextnext = d1.next()->next();
tcQCDPtr prevprev = tcQCDPtr();
if ( stringMassCut > ZERO && d1.prev() && d1.prev()->sdip() < sqr(stringMassCut) )
prevprev = d1.prev()->prev();
bool redo = redoFull || d1.touched() ||
d1.iPart()->touched() || d1.oPart()->touched();
pair<CacheMap::iterator,bool> cit = cache.insert(make_pair(&d1, DipSwPtr()));
if ( redo ) cit.first->second = DipSwPtr();
DipSwPtr sel = cit.first->second;
if ( !sel || ( sel->dipoles.second->touched() ||
sel->dipoles.second->iPart()->touched() ||
sel->dipoles.second->oPart()->touched() ||
sel->dipoles.second->colourIndex() != d1.colourIndex() ||
sel->dipoles.second == nextnext ||
sel->dipoles.second == prevprev ) ) {
redo = true;
sel = cit.first->second = DipSwPtr();
}
if ( !redo && sel && disallowed.find(sel->dipoles) != disallowed.end() ) {
redo = true;
sel = cit.first->second = DipSwPtr();
}
const vector<tQCDPtr> * secondp = &active;
int i2 = i1 + 1;
if ( !redo ) {
if ( ti1 < 0 ) {
select(sel);
continue;
}
secondp = &touched;
i2 = ti1;
}
const vector<tQCDPtr> & second = *secondp;
CPUTimer timer3(cpuclock3);
for ( int N2 = second.size(); i2 < N2; ++i2 ) {
if ( second[i2] == nextnext || second[i2] == prevprev ) continue;
if ( disallowed.find(make_pair(active[i1], second[i2])) != disallowed.end() ) continue;
QCDDipole & d2 = *second[i2];
if ( d1.iPart() == d2.oPart() || d2.iPart() == d1.oPart() ) {
cerr << "Bullocks! Try to swing a gluon into colour singlet!" << endl;
}
// If we are forcing a swing on a tiny string we should only
// consider swings where one dipole is in the tyny string and
// the other is not.
if ( forceTiny && inTiny == member(tinyString, &d2) ) continue;
TauRatio tauRatio(d1, d2, Rmax, sizeOpt);
// LorentzMomentum ptot = d1.iPart()->momentum() + d1.oPart()->momentum() +
// d2.iPart()->momentum() + d2.oPart()->momentum();
double ratmax = tauRatio.maximum(dtmin, dtmax);
double Cinv = -1.0/(lambda*ratmax);
Time dt = dtmin;
Time dtcut = dtmax;
if ( sel ) dtcut = min(dtcut, hbarc/sel->rho);
do {
double logR = log(UseRandom::rnd());
if ( linear )
dt += logR*Cinv*t0;
else {
if ( logR*Cinv > log(2.0*dtmaxcut/dt) ) dt = dtmaxcut*2.0;
else dt *= exp(logR*Cinv);
}
if ( dt >= dtcut ) break;
if ( tauRatio(dt) > ratmax ) {
cerr << "Ooops failed to overestimate swing probability: "
<< tauRatio(dt)/ratmax << endl;
}
} while ( dt < dtcut && tauRatio(dt) < UseRandom::rnd()*ratmax );
if ( !sel ) sel = new_ptr(DipoleSwing(*this, dipole, d1, d2, dt));
else if ( dt < dtcut ) sel->setup(d1, d2, dt);
}
select(cit.first->second = sel);
}
}
if ( lastSelected && forceTiny ) {
lastSelected->rho = rhomax;
lastSelected->forced = true;
}
if ( lastSelected && lastSelected->rho < rhomin ) lastSelected = DipSwPtr();
return lastSelected;
}
void DipoleSwinger::findTinyStrings() const {
tinyString.clear();
if ( stringMassCut <= ZERO ) return;
MinCmp<Energy> cut(stringMassCut);
set<tDBPtr> tdipoles = lastState->activeDipoles();
set<tcDBPtr> dipoles(tdipoles.begin(), tdipoles.end());
while ( !dipoles.empty() ) {
set<tcDBPtr> currentstring;
if ( tcQCDPtr d = dynamic_ptr_cast<tcQCDPtr>(*dipoles.begin()) ) {
dipoles.erase(d);
pair<tcQCDPtr,tcQCDPtr> range = DipoleState::StringEnds(d);
tParPtr p1 = range.first->iPart();
tParPtr p2 = range.second->oPart();
LorentzMomentum psum;
while ( range.first ) {
currentstring.insert(range.first);
psum += range.first->iPart()->momentum();
if ( range.first == range.second )
range.first = tcQCDPtr();
else
range.first = range.first->next();
}
if ( p1 != p2 ) psum += p2->momentum();
if ( cut(psum.m()) ) {
tinyString = currentstring;
}
} else {
dipoles.erase(dipoles.begin());
}
}
}
void DipoleSwinger::swing(tQCDPtr d1, tQCDPtr d2) {
// Swing the o-partons.
tParPtr tmp = d1->oPart();
d1->oPart(d2->oPart());
d2->oPart(tmp);
// The new o-partons inhreits the previous colour line.
tColinePtr cltmp = d1->oPart()->origICol();
d1->oPart()->origICol(d2->oPart()->origICol());
d2->oPart()->origICol(cltmp);
// Fix pointers to neighboring dipoles.
tQCDPtr dtmp = d1->next();
d1->next(d2->next());
d2->next(dtmp);
if ( d1->next() ) d1->next()->prev(d1);
if ( d2->next() ) d2->next()->prev(d2);
}
bool DipoleSwinger::
perform(const Emission & emission) const {
static DebugItem stat("Ariadne5::DipoleSwinger::Statistics", 6);
static double sum = 0.0;
static CPUClock cpuclock("Ariadne5::DipoleSwinger::perform");
CPUTimer timer(cpuclock);
const DipoleSwing & e = dynamic_cast<const DipoleSwing &>(emission);
if ( e.dipoles.first->colourIndex() != e.dipoles.second->colourIndex() )
cerr << "Ooops, tried to swing dipoles of diferent colours!" << endl;
double lam0 = 0.0;
Energy2 s12 = ZERO;
Energy2 s34 = ZERO;
if ( stat ) {
lam0 = log(e.dipoles.first->sdip()/GeV2) + log(e.dipoles.second->sdip()/GeV2);
TauRatio tauRatio(*e.dipoles.first, *e.dipoles.second, Rmax, sizeOpt);
cerr << "ratio " << tauRatio(hbarc/e.rho);
s12 = e.dipoles.first->sdip();
s34 = e.dipoles.second->sdip();
}
swing(e.dipoles.first, e.dipoles.second);
if ( stringMassCut > ZERO && !e.forced ) {
if ( Utilities::sumMomentum(e.dipoles.first->string()).m() < stringMassCut ) return false;
if ( Utilities::sumMomentum(e.dipoles.second->string()).m() < stringMassCut ) return false;
}
if ( stat ) {
double lam = log(e.dipoles.first->sdip()/GeV2) + log(e.dipoles.second->sdip()/GeV2);
cerr << " (" << s12*s34/(e.dipoles.first->sdip()*e.dipoles.second->sdip())
<< "), swing diff " << lam - lam0
<< " (total " << (sum += lam - lam0) << ")" << endl;
}
e.dipoles.first->touch();
e.dipoles.second->touch();
e.dipole->touch();
return true;
}
void DipoleSwinger::revert(const Emission & emission) const {
static CPUClock cpuclock("Ariadne5::DipoleSwinger::revert");
CPUTimer timer(cpuclock);
const DipoleSwing & e = dynamic_cast<const DipoleSwing &>(emission);
swing(e.dipoles.first, e.dipoles.second);
e.dipoles.second->untouch();
e.dipole->untouch();
}
// If needed, insert default implementations of virtual function defined
// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs).
void DipoleSwinger::persistentOutput(PersistentOStream & os) const {
- os << lambda << ounit(Rmax, femtometer) << oenum(linear) << sizeOpt << ounit(theRhoCut, GeV)
- << ounit(stringMassCut, GeV) << tinyString << cache << lastState << lastStateId
+ os << lambda << ounit(Rmax, femtometer) << oenum(linear) << sizeOpt
+ << ounit(theRhoCut, GeV) << ounit(stringMassCut, GeV) << tinyString
<< lastSelected;
}
void DipoleSwinger::persistentInput(PersistentIStream & is, int) {
- is >> lambda >> iunit(Rmax, femtometer) >> ienum(linear) >> sizeOpt >> iunit(theRhoCut, GeV)
- >> iunit(stringMassCut, GeV) >> tinyString >> cache >> lastState >> lastStateId
+ is >> lambda >> iunit(Rmax, femtometer) >> ienum(linear) >> sizeOpt
+ >> iunit(theRhoCut, GeV) >> iunit(stringMassCut, GeV) >> tinyString
>> lastSelected;
+ cache.clear();
+ lastState = tDipoleStatePtr();
+ lastStateId = 0;
}
string DipoleSwinger::setRmax(string cmd) {
istringstream is(cmd);
double x;
is >> x;
Rmax = x*InvGeV*hbarc;
return "";
}
DescribeClass<DipoleSwinger,EmitterBase>
describeAriadne5DipoleSwinger("Ariadne5::DipoleSwinger", "libAriadne5.so");
void DipoleSwinger::Init() {
static ClassDocumentation<DipoleSwinger> documentation
("The DipoleSwinger class implements the final-state swing method"
"for colour reconnections.");
static Parameter<DipoleSwinger,double> interfaceLambda
("Lambda",
"The frequency of the swings.",
&DipoleSwinger::lambda, 1.0, 1.0, 0.0, 0.0,
true, false, Interface::lowerlim);
static Parameter<DipoleSwinger,Length> interfaceRmax
("Rmax",
"The typical hadronic size used to regularize large dipoles in the swing.",
&DipoleSwinger::Rmax, femtometer, 3.5*InvGeV*hbarc, 0.0*femtometer, 0.0*femtometer,
true, false, Interface::nolimits);
static Command<DipoleSwinger> interfaceSetRmax
("SetRmax",
"Set the value of <interface>Rmax</interface> with a value given in units of inverse GeV.",
&DipoleSwinger::setRmax, true);
static Switch<DipoleSwinger,bool> interfaceLinear
("Linear",
"Normally we use logarithmic evolution in time. With this switch we can instead use linear evolution.",
&DipoleSwinger::linear, false, true, false);
static SwitchOption interfaceLinearLogarithmic
(interfaceLinear,
"Logarithmic",
"Use logarithmic evolution in time.",
false);
static SwitchOption interfaceLinearLinear
(interfaceLinear,
"Linear",
"Use linear evolution in time.",
true);
static Switch<DipoleSwinger,int> interfaceSizeOpt
("SizeOpt",
"Different options for how to define dipole size is the swing.",
&DipoleSwinger::sizeOpt, 0, true, false);
static SwitchOption interfaceSizeOptNaive
(interfaceSizeOpt,
"Naive",
"Assuming a global time given by the inverse transverse momentum, use the "
"Lorentz-invariant actual distance.",
0);
static SwitchOption interfaceSizeOptInvariantMass
(interfaceSizeOpt,
"InvariantMass",
"Use only the invariant mass of the dipoles.",
1);
static SwitchOption interfaceSizeOptInvariantMassR
(interfaceSizeOpt,
"NaiveR",
"As for Naive but Rmax limit only applied to original vertex positions.",
-1);
static Parameter<DipoleSwinger,Energy> interfaceRhoCut
("RhoCut",
"Cutoff in the evolution variable. If zero or less, use the global QCD shower cutoff.",
&DipoleSwinger::theRhoCut, GeV, -1.0*GeV, -1.0*GeV, 0*GeV,
true, false, Interface::lowerlim);
static Parameter<DipoleSwinger,Energy> interfaceStringMassCut
("StringMassCut",
"Cutoff against too small string. No swing is allowed to produce strings with invarint "
"mass below this value.",
&DipoleSwinger::stringMassCut, GeV, 0.0*GeV, 0.0*GeV, 0*GeV,
true, false, Interface::lowerlim);
}
diff --git a/Cascade/QCDDipole.cc b/Cascade/QCDDipole.cc
--- a/Cascade/QCDDipole.cc
+++ b/Cascade/QCDDipole.cc
@@ -1,151 +1,151 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the QCDDipole class.
//
#include "QCDDipole.h"
#include "Junction.h"
#include "RemnantParton.h"
#include "ResonanceParton.h"
#include "DipoleState.h"
#include "AriadneHandler.h"
#include "Emission.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Utilities/Current.h"
#include "ThePEG/Utilities/Throw.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/EventRecord/Particle.h"
using namespace Ariadne5;
QCDDipole::QCDDipole() {
theRhoCut = Current<AriadneHandler>()->pTCut();
}
ClonePtr QCDDipole::clone() const {
return new_ptr(*this);
}
ColinePtr QCDDipole::colourLine() const {
tJunctionPtr ji = dynamic_ptr_cast<tJunctionPtr>(iPart());
tJunctionPtr jo = dynamic_ptr_cast<tJunctionPtr>(oPart());
// If both partons are junctions then we have no colour line to report.
if ( ji && jo ) return ColinePtr();
// First check if we are attached to an original colour line.
ColinePtr cl;
// This must always be the case if we have a juction.
if ( ji || jo ) {
if ( ji ) cl = oPart()->origICol();
if ( jo ) cl = iPart()->origOCol();
if ( !cl )
Throw<Exception>()
<< "Could not find colour line of Junction in Ariadne. This is a "
<< "serious error, please contact the author." << Exception::runerror;
return cl;
} else {
// Now simply check the partons and see if there is already a colour line
cl = iPart()->origOCol();
if ( oPart()->origICol() ) {
if ( cl && oPart()->origICol() != cl )
Throw<Exception>()
<< "Found Conflicting colour lines in Ariadne. This is a "
<< "serious error, please contact the author." << Exception::runerror;
cl = oPart()->origICol();
}
// If no colour line was found we may create one.
if ( !cl ) cl = new_ptr(ColourLine());
// Now connect the produced particles.
tRemParPtr ri = dynamic_ptr_cast<tRemParPtr>(iPart());
if ( ri && ri->hard() ) ri = tRemParPtr();
tRemParPtr ro = dynamic_ptr_cast<tRemParPtr>(oPart());
if ( ro && ro->hard() ) ro = tRemParPtr();
if ( ri ) cl->addAntiColoured(ri->extracted());
else if ( !ji ) cl->addColoured(iPart()->particle());
if ( ro ) cl->addColoured(ro->extracted());
else if ( !jo ) cl->addAntiColoured(oPart()->particle());
}
return cl;
}
Energy2 QCDDipole::sdip() const {
return (iPart()->momentum() + oPart()->momentum()).m2();
}
void QCDDipole::generateColourIndex() {
theColourIndex.generate(next()? next()->colourIndex(): ColourIndex(),
prev()? prev()->colourIndex(): ColourIndex());
}
vector<tParPtr> QCDDipole::string() const {
vector<tParPtr> ret;
pair<tcQCDPtr,tcQCDPtr> range = DipoleState::StringEnds(this);
tParPtr p1 = range.first->iPart();
tParPtr p2 = range.second->oPart();
while ( range.first ) {
ret.push_back(range.first->iPart());
if ( range.first == range.second )
range.first = tcQCDPtr();
else
range.first = range.first->next();
}
if ( p1 != p2 ) ret.push_back(p2);
return ret;
}
void QCDDipole::fillReferences(CloneSet & cset) const {
DipoleBase::fillReferences(cset);
cset.insert(oPart());
cset.insert(iPart());
}
void QCDDipole::rebind(const TranslationMap & trans) {
DipoleBase::rebind(trans);
theOPart = trans.translate(oPart());
theIPart = trans.translate(iPart());
theNext = trans.translate(theNext);
thePrev = trans.translate(thePrev);
}
void QCDDipole::persistentOutput(PersistentOStream & os) const {
os << theIPart << theOPart << theNext << thePrev
<< theColourIndex << theResonance;
}
void QCDDipole::persistentInput(PersistentIStream & is, int) {
is >> theIPart >> theOPart >> theNext >> thePrev
>> theColourIndex >> theResonance;
}
DescribeClass<QCDDipole,DipoleBase>
-describeAriadne5QCDDipole("Ariadne::QCDDipole", "libAriadne5.so");
+describeAriadne5QCDDipole("Ariadne5::QCDDipole", "libAriadne5.so");
void QCDDipole::Init() {}
void QCDDipole::debugme() const {
DipoleBase::debugme();
cerr << "D"
<< setw(3) << state()->index(this) << " "
<< setw(3) << state()->index(iPart()) << " "
<< setw(3) << state()->index(oPart())
<< setw(10) << setprecision(3)
<< (touched()? " *": " ")
<< "[" << colourIndex() << "]";
}
bool QCDDipole::checkIntegrity() {
if ( oPart()->origICol() && iPart()->origOCol() &&
oPart()->origICol() != iPart()->origOCol() )
return false;
return DipoleBase::checkIntegrity() &&
iPart() && (!next() || next()->prev() == this) &&
oPart() && (!prev() || prev()->next() == this);
}
diff --git a/Cascade/ReweightBase.h b/Cascade/ReweightBase.h
--- a/Cascade/ReweightBase.h
+++ b/Cascade/ReweightBase.h
@@ -1,135 +1,135 @@
// -*- C++ -*-
#ifndef Ariadne5_ReweightBase_H
#define Ariadne5_ReweightBase_H
//
// This is the declaration of the ReweightBase class.
//
#include "ThePEG/Handlers/HandlerBase.h"
#include "ReweightBase.fh"
#include "DipoleBase.fh"
#include "Parton.fh"
#include "Emission.fh"
namespace Ariadne5 {
using namespace ThePEG;
/**
* ReweightBase is the base class for implementing different ways of
* reweighting the dipole emissions in Ariadne. There are three
* virtual functions which may be overridden in concrete sub-classes:
* preweight() should return a factor multiplying the standard dipole
* emission before reweighting and reweight() should return the actual
* reweight. Alternatively the finalVeto() function can be used to
* accept/reject an already performed dipole emission. Object of a
* concrete sub-class can inserted to a list in
- * Ariadne::CascadeHandler and will then be applied to all dipole
+ * Ariadne5::CascadeHandler and will then be applied to all dipole
* emissions. The object could possibly be used for several different
* dipoles, and should therefore not store any information in the
* preweigth() function to be used in the subsequent reweigth() and
* finalVeto() calls.
*
* @see \ref ReweightBaseInterfaces "The interfaces"
* defined for ReweightBase.
*/
class ReweightBase: public HandlerBase {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor. \a mayveto must be set to true by
* subclasses which implements the finalVeto function.
*/
ReweightBase(bool mayveto = false) : mayVeto(mayveto) {};
/**
* The destructor.
*/
virtual ~ReweightBase();
//@}
public:
/** @name Virtual functions to be overridden in sub-classes. */
//@{
/**
* Return a factor to multiply the basic emission emission
* probability for a given \a emission to ensure that a subsequent
* call to reweight() will give a number less than unity.
*/
virtual double preweight(const Emission & emission) const;
/**
* Return the weight associated with an \a emission. Must return a
* number between zero and one.
*/
virtual double reweight(const Emission & emission) const;
/**
* In addition to the reweight function a final hit/miss veto may be
* given after the \a emission has been performed. Will only be
* called if hasFinalVeto() returns true.
*/
virtual bool finalVeto(const Emission & emission) const;
/**
* Indicate that this object may veto a performed emission.
*/
bool hasFinalVeto() const {
return mayVeto;
}
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
// If needed, insert declarations of virtual function defined in the
// InterfacedBase class here (using ThePEG-interfaced-decl in Emacs).
private:
/**
* Indicate that this object may veto a performed emission.
*/
bool mayVeto;
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
ReweightBase & operator=(const ReweightBase &);
};
}
#endif /* Ariadne5_ReweightBase_H */
diff --git a/Cascade/StateDipole.cc b/Cascade/StateDipole.cc
--- a/Cascade/StateDipole.cc
+++ b/Cascade/StateDipole.cc
@@ -1,37 +1,37 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the StateDipole class.
//
#include "StateDipole.h"
#include "AriadneHandler.h"
#include "ThePEG/Utilities/Current.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Utilities/DescribeClass.h"
using namespace Ariadne5;
StateDipole::StateDipole() {
theRhoCut = Current<AriadneHandler>()->pTCut();
}
ClonePtr StateDipole::clone() const {
return new_ptr(*this);
}
void StateDipole::fillReferences(CloneSet & cset) const {
DipoleBase::fillReferences(cset);
}
void StateDipole::rebind(const TranslationMap & trans) {
DipoleBase::rebind(trans);
}
DescribeNoPIOClass<StateDipole,DipoleBase>
-describeAriadne5StateDipole("Ariadne::StateDipole", "libAriadne.so");
+describeAriadne5StateDipole("Ariadne5::StateDipole", "libAriadne5.so");
void StateDipole::Init() {}
diff --git a/Config/Ariadne5.h b/Config/Ariadne5.h
--- a/Config/Ariadne5.h
+++ b/Config/Ariadne5.h
@@ -1,92 +1,101 @@
// -*- C++ -*-
#ifndef Ariadne5_H
#define Ariadne5_H
// This is the main config header file for Ariande.
-#include "Ariadne/Config/Ariadne.h"
+#include "ThePEG/Config/ThePEG.h"
+#include "ThePEG/Vectors/Lorentz5Vector.h"
namespace Ariadne5 {
using namespace ThePEG;
+/** Create a LorentzVector given mass, pt, rapidity, and azimuth
+ * angle. */
+inline LorentzMomentum
+ptRapidity(Energy mass, Energy pt, double y = 0.0, double phi = 0.0) {
+ Energy mt = sqrt( sqr(mass) + sqr(pt) );
+ return lightCone(mt*exp(y), mt*exp(-y), pt*cos(phi), pt*sin(phi));
+}
+
/**
* This is a fail-safe version of LorentzMomentum::rapidity().
*/
inline double rapidity(const LorentzMomentum & p,
double ymax = Constants::MaxRapidity) {
if ( p.e() > abs(p.z()) ) return p.rapidity();
return p.z() > ZERO? ymax: ( p.z() < ZERO? -ymax: 0.0 );
}
/** Create a Lorentz5Vector giving its light-cone and transverse
* components. */
template <typename Value>
inline Lorentz5Vector<Value>
lightCone5(Value plus, Value minus, Value x, Value y) {
Lorentz5Vector<Value> r(x, y, 0.5*(plus-minus), 0.5*(plus+minus));
return r;
}
/** Create a Lorentz5Vector giving its light-cone and transverse
* components and a possibly inconsistent mass. */
template <typename Value>
inline Lorentz5Vector<Value>
lightCone5(Value plus, Value minus, Value x, Value y, Value m) {
Lorentz5Vector<Value> r(x, y, 0.5*(plus-minus), 0.5*(plus+minus), m);
return r;
}
/** Create a Lorentz5Vector giving its light-cone components. */
template <typename Value>
inline Lorentz5Vector<Value>
lightCone5(Value plus, Value minus) {
Lorentz5Vector<Value> r(ZERO, ZERO, 0.5*(plus-minus), 0.5*(plus+minus));
return r;
}
/** Create a Lorentz5Vector giving its light-cone and transverse
* components. */
template <typename Value>
inline Lorentz5Vector<Value>
lightCone5(Value plus, Value minus, Transverse<Value> pt) {
Lorentz5Vector<Value> r(pt.x(), pt.y(), 0.5*(plus-minus), 0.5*(plus+minus));
return r;
}
/** Create a Lorentz5Vector giving its light-cone and transverse
* components and a possibly inconsistent mass. */
template <typename Value>
inline Lorentz5Vector<Value>
lightCone5(Value plus, Value minus, Transverse<Value> pt, Value m) {
Lorentz5Vector<Value> r(pt.x(), pt.y(), 0.5*(plus-minus), 0.5*(plus+minus), m);
return r;
}
/** Create a Lorentz5Vector giving its light-cone and transverse
* components. If the current Direction<0> is reversed, so is the
* z-component. */
template <typename Value>
inline Lorentz5Vector<Value>
lightCone5Dir(Value plus, Value minus,
Value x = Value(), Value y = Value()) {
Lorentz5Vector<Value> r(x, y, Direction<0>::dir()*0.5*(plus - minus),
0.5*(plus + minus));
return r;
}
/** Create a Lorentz5Vector giving its light-cone and transverse
* components. If the current Direction<0> is reversed, so is the
* z-component. */
template <typename Value>
inline Lorentz5Vector<Value>
lightCone5Dir(Value plus, Value minus, Transverse<Value> pt) {
Lorentz5Vector<Value> r(pt.x(), pt.y(), Direction<0>::dir()*0.5*(plus - minus),
0.5*(plus + minus));
return r;
}
}
#endif /* Ariadne5_H */
diff --git a/Config/CloneBase.cc b/Config/CloneBase.cc
new file mode 100644
--- /dev/null
+++ b/Config/CloneBase.cc
@@ -0,0 +1,22 @@
+// -*- C++ -*-
+//
+// This is the implementation of the non-inlined, non-templated member
+// functions of the CloneBase class.
+//
+
+#include "CloneBase.h"
+#include "ThePEG/Utilities/DescribeClass.h"
+
+using namespace Ariadne5;
+
+CloneBase::~CloneBase() {}
+
+void CloneBase::fillReferences(CloneSet &) const {}
+
+void CloneBase::rebind(const TranslationMap & trans) {}
+
+// Definition of the static class description member.
+DescribeAbstractNoPIOClass<CloneBase,PersistentBase>
+describeAriadne5CloneBase("Ariadne5::CloneBase", "libAriadne5.so");
+
+void CloneBase::Init() {}
diff --git a/Config/CloneBase.fh b/Config/CloneBase.fh
--- a/Config/CloneBase.fh
+++ b/Config/CloneBase.fh
@@ -1,17 +1,17 @@
// -*- C++ -*-
//
// This is the forward declaration of the CloneBase class.
//
#ifndef ARIADNE_CloneBase_FH
#define ARIADNE_CloneBase_FH
#include "ThePEG/Config/Pointers.h"
-namespace Ariadne {
+namespace Ariadne5 {
class CloneBase;
ThePEG_DECLARE_POINTERS(CloneBase,ClonePtr);
}
#endif
diff --git a/Config/CloneBase.h b/Config/CloneBase.h
--- a/Config/CloneBase.h
+++ b/Config/CloneBase.h
@@ -1,147 +1,108 @@
// -*- C++ -*-
-#ifndef ARIADNE_CloneBase_H
-#define ARIADNE_CloneBase_H
+#ifndef ARIADNE5_CloneBase_H
+#define ARIADNE5_CloneBase_H
//
// This is the declaration of the CloneBase class.
//
-#include "Ariadne.h"
+#include "Ariadne5.h"
#include "ThePEG/Utilities/Rebinder.h"
#include "ThePEG/Utilities/ClassDescription.h"
#include "CloneBase.fh"
#include "Ariadne/DIPSY/DipoleState.fh"
-#include "Ariadne/DipoleCascade/DipoleState.fh"
#include "Ariadne/Cascade/DipoleState.fh"
-namespace Ariadne {
+namespace Ariadne5 {
/**
* CloneBase is used as base class for most of the classes in the
* Ariadne dipole cascade. It defines the basic clone and rebind
* methods which are used when cloning a whole dipole state. Maybe
* this class is general enough to be a part of ThePEG base
* classes.
*/
class CloneBase: public PersistentBase {
public:
/**
* A set of pointers to CloneBase objects.
*/
typedef set<cClonePtr> CloneSet;
/**
* The Rebinder class for CloneBase objects.
*/
typedef Rebinder<CloneBase> TranslationMap;
/**
*
*/
friend class ::Ariadne5::DipoleState;
- friend class ::Ariadne::DipoleState;
friend class ::DIPSY::DipoleState;
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
- inline CloneBase();
-
- /**
- * The copy constructor.
- */
- inline CloneBase(const CloneBase &);
+ inline CloneBase() {}
/**
* The destructor.
*/
- inline virtual ~CloneBase();
+ virtual ~CloneBase();
//@}
+ /**
+ * The standard Init function used to initialize the interfaces.
+ * Called exactly once for each class by the class description system
+ * before the main function starts or
+ * when this class is dynamically loaded.
+ */
+ static void Init();
+
protected:
/** @name 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 ClonePtr clone() const = 0;
/**
* Fill the provided set with all pointers to CloneBase objects used
* in this object.
*/
virtual void fillReferences(CloneSet &) 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);
//@}
private:
/**
- * The static object used to initialize the description of this class.
- * Indicates that this is an abstract class without persistent data.
- */
- static AbstractNoPIOClassDescription<CloneBase> initCloneBase;
-
- /**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
CloneBase & operator=(const CloneBase &);
};
}
#include "ThePEG/Utilities/ClassTraits.h"
-namespace ThePEG {
-
-/** @cond TRAITSPECIALIZATIONS */
-
-/** This template specialization informs ThePEG about the
- * base classes of CloneBase. */
-template <>
-struct BaseClassTrait<Ariadne::CloneBase,1> {
- /** Typedef of the first base class of CloneBase. */
- typedef PersistentBase NthBase;
-};
-
-/** This template specialization informs ThePEG about the name of
- * the CloneBase class and the shared object where it is defined. */
-template <>
-struct ClassTraits<Ariadne::CloneBase>
- : public ClassTraitsBase<Ariadne::CloneBase> {
- /** Return a platform-independent class name */
- static string className() { return "Ariadne::CloneBase"; }
- /** Return the name of the shared library be loaded to get
- * access to the CloneBase class and every other class it uses
- * (except the base class). */
- static string library() { return "libAriadne.so"; }
-};
-
-/** @endcond */
-
-}
-
-#include "CloneBase.icc"
-#ifndef ThePEG_TEMPLATES_IN_CC_FILE
-// #include "CloneBase.tcc"
-#endif
-
-#endif /* ARIADNE_CloneBase_H */
+#endif /* ARIADNE5_CloneBase_H */
diff --git a/Config/Makefile.am b/Config/Makefile.am
--- a/Config/Makefile.am
+++ b/Config/Makefile.am
@@ -1,6 +1,13 @@
-DOCFILES = Ariadne.h Ariadne5.h CloneBase.h UnitFO.h
+mySOURCES = CloneBase.cc
+
+DOCFILES = Ariadne5.h CloneBase.h UnitFO.h
INCLUDEFILES = $(DOCFILES) config.h CloneBase.fh CloneBase.icc
EXTRA_DIST = $(INCLUDEFILES)
+noinst_LTLIBRARIES = libAriadne5Config.la
+
+libAriadne5Config_la_SOURCES = $(mySOURCES) $(INCLUDEFILES)
+
+include $(top_srcdir)/Config/Makefile.aminclude
diff --git a/DIPSY/DiffractiveEventFiller.cc b/DIPSY/DiffractiveEventFiller.cc
--- a/DIPSY/DiffractiveEventFiller.cc
+++ b/DIPSY/DiffractiveEventFiller.cc
@@ -1,1369 +1,1369 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the DiffractiveEventFiller class.
//
#include "DipoleEventHandler.h"
#include "EventFiller.h"
#include "DiffractiveEventFiller.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Repository/CurrentGenerator.h"
#include "ThePEG/Utilities/Current.h"
#include "ThePEG/Utilities/Throw.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Repository/CurrentGenerator.h"
#include "ThePEG/EventRecord/Step.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/EventRecord/SubProcess.h"
#include "RealPartonState.h"
#include "ThePEG/Utilities/Debug.h"
#include "ThePEG/Utilities/DebugItem.h"
#include "ThePEG/Utilities/UtilityBase.h"
#include "ThePEG/Utilities/SimplePhaseSpace.h"
#include "ThePEG/Handlers/LuminosityFunction.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include <iostream>
#include <fstream>
using namespace DIPSY;
DiffractiveEventFiller::DiffractiveEventFiller()
{}
DiffractiveEventFiller::~DiffractiveEventFiller() {}
IBPtr DiffractiveEventFiller::clone() const {
return new_ptr(*this);
}
IBPtr DiffractiveEventFiller::fullclone() const {
return new_ptr(*this);
}
/*
* Fills the step with a diffractive event.
*/
double DiffractiveEventFiller::fill(Step & step, DipoleEventHandler & eh, tPPair inc,
DipoleState & dr, DipoleState & de,
const ImpactParameters & b) const {
//Some debugging set up.
static DebugItem printsteps("DIPSY::PrintSteps", 6);
static DebugItem printstepdetails("DIPSY::PrintStepDetails", 6);
//Sets debugging output.
//TODO: interface
// bool printstepdetails = true;
if ( printstepdetails ) cout << setprecision(6);
if ( printstepdetails ) cout << "entered fill()" << endl;
//evolve the valence state to maximum allowed rapidity for the excited state.
//turn swing of for this. then revert for the virtual cascades later.
double lambda = eh.swingPtr()->lambda();
//TODO: can this be set to 0?
eh.swingPtr()->lambda(0.0000000000001);
dr.evolve(dr.lowestY(), maxY());
eh.swingPtr()->lambda(lambda);
if ( printstepdetails ) cout << "evolved real state" << endl;
//to get the correct weight for the real cascade (specially the absence of
//a "no more emissions after this" term for the real cascade), we need to
//return an event for every subcascade. Or equivalently, and avoiding correlations
//between the final states, returning one random subcascade weighted by the number
//of subcascades.
//
//The selectionProbability is only used when running with nInteractions == -1,
//and should be set to about 1/(the largest number of subcascades you expect in a
//real cascade). Too low means that it will run through a lot of real cascades before
//picking one (not too bad), and too high will give occasional events with very high
//weight (potentially making the result untrustworthy).
double selectionProbability = 1;
//the weight the event receives in association with the choice of subcascade.
double choiceWeight = 0.0;
//this choice runs with any number of interactions. While producing an exact result,
//it converges incredibly slowly, as the cross section will be dominated by a very small
//fraction of the events (namely the ones with a single interacting large dipole).
if ( nInteractions() < 0 ) {
choiceWeight = selectSubcascade(dr, selectionProbability);
}
//No interacting dipoles means an elastic event.
else if ( nInteractions() == 0 ) {
pickSubcascade(dr, 0);
increaseNSubCascades(1.0);
choiceWeight = 1.0;
}
//A single interacting dipole.
else if ( nInteractions() == 1 ) {
choiceWeight = selectSingleSubcascade(dr);
}
//a fix number of interaction larger than 1.
else if ( nInteractions() > 1 ) {
choiceWeight = selectNSubcascade(dr, nInteractions());
}
//if no subcascade chosen, start over.
if ( choiceWeight == 0.0 ) {
if ( printstepdetails ) cout << "choiceweight is 0, return 0 and start over." << endl;
return 0.0;
}
double weight = choiceWeight;
//identify the ends of the chains. These are treated differently than the rest in the
//amplitude, so it is easier to identify them one time for all here. These are the circled
//partons in fig 15 in the diffractive paper.
vector<PartonPtr> chainCaps = childlessChildren(&dr);
if ( printstepdetails ) cout << "found chaincaps " << chainCaps.size() << endl;
//We now clean up the subcascade into a proper real finalstate.
//Ie, do all the things you have to do to a virtual cascade to make it real,
//like reweight the pt maxima, double check ordering etc.
makeReal(dr, chainCaps, de);
//The cleaning can mess up the interacting partons, although it shouldn't be very frequent.
//but better to recheck and avoid troubles later on.
chainCaps = childlessChildren(&dr);
//check that the number of chaincaps (ie, interactions) in the real state is still the correct one.
//they may go away if some interacting parton was not ordered etc.
//if we run all numbers of interaction (-1 or -2), then it doesn't matter and we should always continue.
if ( int(chainCaps.size()) != nInteractions() && nInteractions() > -1 ) {
if ( printstepdetails ) cout << "got " << chainCaps.size() << " chainCaps, veto." << endl;
return 0.0;
}
//if the subcascade doesnt reach up to minimum y (too low M_X^2), start over.
if ( dr.highestY() < minY() ) {
if ( printstepdetails ) cout << "too low highestY, return 0 and start over. needed "
<< minY() << ", got " << dr.highestY() << endl;
return 0.0;
}
//estimate the amplitude and veto/reweight accordingly
//this is to avoid running through all the elastic cascade for all excited states
//that will get a very low amplitude anyways.
//
//I have some doubts on this method, as if the estimate is not accurate for all cascades
//it may throw away high-amplitude cascade often, and give some events with very high weight.
//However, tests has shown that the weight distribution looks a bit better with reweighting
//like this, so I left it in. But keep track on the weight distribution and consider
//switching this off (-2 interactions) if it gets worse.
double estimate = reweightCascade(dr, chainCaps);
if ( nInteractions() != -2 ) {
if ( estimate == 0.0 ) {
if ( printstepdetails ) cout << "estimated amplitude 0, probably not good." << endl;
return 0.0;
}
//to estimate weight, we need to square the estimate of the amplitude.
double passProb = sqr(estimate);
//to tone down the reweighting a bit (specially to avoid spikes to high weights)
//the square root of the estimated weight is used.
passProb = sqrt(passProb);
//throw away most of the cascades that seems to have low amplitude, but increase the weight
//of the ones we do decide to run.
if ( UseRandom::rnd() > passProb ) {
return 0.0;
}
else weight /= passProb;
//TODO: proper error message
if ( isnan(weight) ) cout << "weight is not a number after interaction estimate." << endl;
}
//calculate the amplitude for this real cascade, by summing over virtual cascades.
double amp = amplitude(dr, chainCaps, b);
//probability is proportional to the square of the amplitude.
weight *= sqr(amp);
//TODO: proper error message
if ( isnan(weight) ) cout << "weight is not a number after amplitude." << endl;
if ( printstepdetails ) cout << "calculated amp^2 " << sqr(amp) << endl;
if ( printstepdetails ) cout << "weight is now " << weight << endl;
if ( printstepdetails ) cout << "number of gluons: " << dr.getPartons().size() << endl;
//balance momenta by taking some energy from the elastic state to put
//the excited state on shell. If this fails (usually due to not enough energy),
//then throw the event away.
if ( !balanceMomenta(&dr, &de) ) {
if ( printstepdetails ) cout << "failed to balance momenta" << endl;
return 0.0;
}
//add finalstate swing
double yrange = FSSwingTime();
double ystep = FSSwingTimeStep();
for ( double y = 0.0; y < yrange; y += ystep ) {
dr.swingFS(y, y + ystep);
}
//extract strings from the excited state.
vector<String> strings = dr.strings();
//mirrer elastic state to make it move in the opposite direction of the
//excited state and turn it into a proton
//This is will obviously have to be changed if diffracting on something
//else than a proton.
de.mirror(0.0);
DipoleState::String protonString = makeProton(& de);
//add elastic particle to the strings.
strings.push_back(protonString);
//fill step. Scrap event if something doesn't work.
if ( strings.empty() || ! fillStep(step, inc, strings) ) {
weight = 0.0;
currentWeight = 0.0;
//TODO: proper error message
if ( printstepdetails ) cout << "empty string or failed fillstep, return 0" << endl;
return weight;
}
if ( printstepdetails ) dr.diagnosis(true);
//For really long runs, one could imagine that the elastic cascades should be
//regenerated to reduce the error. Due to limited RAM on the computer
//one cannot increase the number of elastic events to eb stored over a certain
//number. Didn't turn out to really be needed yet though, thus commented out.
// int CEN = generator()->currentEventNumber();
// int NEC = nElasticCascades();
// if ( double(CEN/NEC) == double(CEN)/double(NEC) ) {
// cout << "generating new elastic cascades" << endl;
// DipoleEventHandlerPtr eh = Current<DipoleEventHandler>().ptr();
// DipoleStatePtr dummyState = eh->WFR().generate(*eh, 1000.0*GeV);
// Energy W = dummyState->handler().lumiFn().maximumCMEnergy();
// Energy2 a = eh->WFR().m2() - eh->WFL().m2() + sqr(W);
// Energy PR = (a + sqrt(sqr(a) - 4.0*eh->WFR().m2()*sqr(W)))*0.5/W;
// initialiseVirtualCascades(*eh, eh->WFR(), PR, -maxY());
// cout << "done generating new elastic cascades" << endl;
// }
if ( printstepdetails ) cout << "done in DiffractiveEventFiller::fill(...), leaving." << endl;
return weight;
}
/*
* Some comments on this in the writeup. It is based on the version in the ND collisions.
*/
bool DiffractiveEventFiller::balanceMomenta(DipoleStatePtr excited, DipoleStatePtr elastic) const {
//First calculate the p+ and p- of the excited state.
Energy intPlus1 = ZERO;
Energy intMinus1 = -excited->minus();
list<PartonPtr> partons = excited->getPartons();
for ( list<PartonPtr>::iterator it = partons.begin(); it != partons.end(); it++) {
intPlus1 += (*it)->plus();
intMinus1 += (*it)->minus();
}
//The p+ and p- of the elastic state. Reverse the + and -, due to not being mirrored yet, ie, both
//the excited and elastic states have large p+ and low p- right now.
Energy intPlus2 = -elastic->minus();
//TODO: should it really be "excited" here, not "elastic"? Compare to ND.
Energy intMinus2 = excited->plus();
//solve the equation for:
//x is the fraction of the p+ the excited state has to give to the elastic state.
//y is the fraction of p- that it has to give to the excited state. Note however, that the elastic
//state is not yet mirrored, so the roles of p+ and p- should be reversed.
//Just set up some paramaters that apear in the solution.
Energy2 A = intPlus1*intMinus2;
Energy2 B = intPlus1*(intMinus1 - intMinus2) - intPlus2*intMinus2;
Energy2 C = intPlus2*intMinus2;
//This is what we have to take the square root of, so check it is positive. If not enough
//energy, there will be no real solutions to get on shell.
//TODO: proper error message.
if ( sqr(B/(2*A)) - C/A < 0.0 ) {
return false;
}
//The solution we are ineterested in. It is a 2:nd degree eq, but I am pretty sure this is the
//solution we want. The other solution will make the two states bounce out almost the way they came
//rather than just glancing of, as they should do (low-x, etc). The other has "- sqrt" instead.
double y = -B/(2*A) + sqrt(sqr(B/(2*A)) - C/A);
double x = 1.0 - intPlus2/(y*intPlus1);
//this should not happen, but...
if ( isnan(x) || isnan(y) || x <= 0.0 || y <= 0.0 ) {
//TODO: proper error message.
cout << "found negative or nan boosts in DifractiveEventFiller." << endl;
return false;
}
//With x and y found, change the 4-momenta.
for ( list<PartonPtr>::iterator it = partons.begin(); it != partons.end(); it++) {
(*it)->plus(x*(*it)->plus());
(*it)->updateYMinus();
}
//Again, elastic state not mirrored yet.
elastic->plus(y*elastic->plus());
elastic->minus(elastic->minus()/y);
return true;
}
/*
* Had this in to calculate the inclusive cross section but I guess it should be called from
* somewhere else.
* TODO: is this done somewhere else? Comment if needed.
*/
void DiffractiveEventFiller::calculateInclusive(DipoleStatePtr real, CrossSection weight,
const ImpactParameters & b) const {
DipoleEventHandlerPtr eh = Current<DipoleEventHandler>().ptr();
double prob = 0.0;
for (int i = 0; i < int(virtualCascades.size()); i++ ) {
double F = eh->xSecFn().sumf(*real, *virtualCascades[i], b);
prob += eh->xSecFn().unitarize(F);
}
prob /= double(virtualCascades.size());
totalXSec += weight*sqr(prob);
totalSqr += sqr(weight*sqr(prob));
neve++;
}
/*
*
*/
double DiffractiveEventFiller::selectSubcascade(DipoleState & dr,
double selectionProbability) const {
static DebugItem printstepdetails("DIPSY::PrintStepDetails", 6);
if ( printstepdetails ) cout << "entering DiffractiveEventFiller::selectSubcascade(...)" << endl;
//count the elastic subcascade this many times extra
int elasticBoost = 10; //interface! tested that results do not depend on this variable
//which gives that many extra subcascades effectively
int nSub = nSubcascades(dr) + elasticBoost;
if ( printstepdetails ) cout << "number of subcascade choices: " << nSub << endl;
//choose if using this cascade, nsub*selProb
double weight = nSub*selectionProbability;
if ( printstepdetails ) cout << "weight is " << weight << endl;
if ( isnan(weight) ) cout << "weight is not a number after cascade selection." << endl;
double R = UseRandom::rnd();
if ( R > weight ) {
if ( printstepdetails ) cout << "veto, try again with another real cascade" << endl;
return 0.0;
}
//if passed veto with a 1 or less prob, set prob to 1
//larger probability than 1 has to go into the returned weight
if ( weight < 1.0 ) weight = 1.0;
if ( weight > 1.0 ) R *= weight;
if ( printstepdetails ) cout << "passed selection veto, weight set to " << weight << endl;
//select which subcascade using an integer between 0 and nSub
int choice = int(R/selectionProbability);
if ( printstepdetails ) cout << "pick subcascade no " << choice << endl;
//identify it and modify dr accordingly
//first check if it was one of the elastic ones, otherwise choose one normally
//note that a choice of 0 corresponds to the elastic cascade
if ( choice < elasticBoost + 1 ) {
choice = 0;
weight /= double(elasticBoost) + 1.0;
if ( printstepdetails ) cout << "pick elastic, weight divided by " << double(elasticBoost) + 1.0 << ", now " << weight << endl;
}
else choice -= elasticBoost;
if ( printstepdetails ) cout << "choice is " << choice << endl;
if ( isnan(weight) ) cout << "weight is not a number after elastic boost" << endl;
weight *= pickSubcascade(dr, choice);
return weight;
}
void DiffractiveEventFiller::addPartonsToSet(DipolePtr d, set<PartonPtr> x) const {
x.insert(d->partons().first);
x.insert(d->partons().second);
}
double DiffractiveEventFiller::addRandomChain(DipoleState & dr) const {
static DebugItem printstepdetails("DIPSY::PrintStepDetails", 6);
if ( printstepdetails ) cout << "entering DiffractiveEventFiller::selectSubcascade(...)" << endl;
//first find the old partons and dipoles in a set
list<PartonPtr> partons = dr.getPartons();
set<PartonPtr> oldP;
for ( list<PartonPtr>::iterator it = partons.begin();
it != partons.end(); it++ )
oldP.insert(*it);
//find the set of all partons
set<PartonPtr> allP;
set<DipolePtr> allD = dr.getAllDipoles();
for ( set<DipolePtr>::iterator it = allD.begin();
it != allD.end(); it++ )
addPartonsToSet(*it, allP);
//remove the old partons
for ( set<PartonPtr>::iterator it = oldP.begin();
it != oldP.end(); it++ )
allP.erase(*it);
set<PartonPtr> newP = allP;
if ( newP.empty() ) return 0.0;
//pick one of the leftover partons as the new chain end (ie interaction)
int choice = UseRandom::rnd()*newP.size();
set<PartonPtr>::iterator it = newP.begin();
while (choice > 0 ) {
it++;
choice--;
}
// addChainFromInteraction(dr,*it);
return 0.0;
}
double DiffractiveEventFiller::selectSingleSubcascade(DipoleState & dr) const {
static DebugItem printstepdetails("DIPSY::PrintStepDetails", 6);
if ( printstepdetails ) cout << "entering DiffractiveEventFiller::selectSubcascade(...)" << endl;
list<PartonPtr> partons = dr.getPartons();
int nSub = countSingleStates(dr);
if ( nSub == 0 ) return 0.0;
if ( printstepdetails ) cout << "number of subcascade choices: " << nSub << endl;
//count the number of possible subcascades.
increaseNSubCascades(double(nSub));
//first find the valence partons
vector<DipolePtr> dips = dr.initialDipoles();
set<PartonPtr> valP;
for ( int i = 0; i < int(dips.size());i++) {
valP.insert(dips[i]->partons().first);
valP.insert(dips[i]->partons().second);
}
//remove the valence partons from the set of partons
for ( list<PartonPtr>::iterator it = partons.begin(); it != partons.end(); it++ ) {
PartonPtr p = *it;
if ( valP.find(p) != valP.end() ) {
it = partons.erase(it);
it--;
}
}
//pick one of the partons as the last emission (ie interaction)
int choice = UseRandom::rnd()*partons.size();
list<PartonPtr>::iterator it = partons.begin();
while (choice > 0 ) {
it++;
choice--;
}
pickSubcascadeFromInteraction(dr,*it);
return nSub;
}
double DiffractiveEventFiller::selectNSubcascade(DipoleState & dr, int N) const {
static DebugItem printstepdetails("DIPSY::PrintStepDetails", 6);
if ( printstepdetails ) cout << "entering DiffractiveEventFiller::selectSubcascade(...)" << endl;
if ( N < 1 ) cerr << "DiffractiveEventFiller::selectNSubcascade called with less than one interaction" << endl;
double ret = selectSingleSubcascade(dr);
int n = 1;
while ( n < N ) {
ret*= addRandomChain(dr);
}
//count the number of possible subcascades.
increaseNSubCascades(double(ret));
return ret;
}
int DiffractiveEventFiller::countSingleStates(DipoleState & dr) const {
list<PartonPtr> partons = dr.getPartons();
//count the valence partons
vector<DipolePtr> dips = dr.initialDipoles();
set<PartonPtr> valP;
for ( int i = 0; i < int(dips.size());i++) {
valP.insert(dips[i]->partons().first);
valP.insert(dips[i]->partons().second);
}
//return the number of excited states (partons - valP)
return partons.size() - valP.size();
}
int DiffractiveEventFiller::nSubcascades(DipoleState & dl) const {
static DebugItem printstepdetails("DIPSY::PrintStepDetails", 6);
if ( printstepdetails ) cout << "entering DiffractiveEventFiller::nSubcascades(...)" << endl;
int ret = 1;
//iterate through valence dipoles and multiply number of combinations
vector<DipolePtr> valDips = dl.initialDipoles();
if ( printstepdetails ) cout << "looking for subcascades of state:" << endl;
// dl.plotState(true);
for ( int i = 0; i < int(valDips.size()); i++ ) {
ret *= nSubcascades(valDips[i]);
}
if ( printstepdetails ) cout << "found " << ret << " subcascsades" << endl;
return ret;
}
int DiffractiveEventFiller::nSubcascades(DipolePtr dip) const {
static DebugItem printstepdetails("DIPSY::PrintStepDetails", 6);
//a = 1 + b*c if 2 kids
//a = b if one kid
//a = 1 if no kids
if ( dip->children().first && !dip->children().second ) {
if ( printstepdetails ) cout << "found swung dipole in nsubcascades..." << endl;
return nSubcascades(dip->children().first);
}
else if ( !dip->children().first && dip->children().second ) {
return nSubcascades(dip->children().second);
}
else if ( dip->children().first && dip->children().second ) {
return 1 + nSubcascades(dip->children().second)*nSubcascades(dip->children().first);
}
else {
return 1;
}
}
double DiffractiveEventFiller::pickSubcascade(DipoleState & dr, int choice) const {
static DebugItem printstepdetails("DIPSY::PrintStepDetails", 6);
int configuration = choice;
double weight = 1.0;
//set all partons off shell
setOffShell(dr);
//mark the ones in the subcascade as on shell, by looping over the valence dips
//this MAY have to be corrected with a swing.
vector<DipolePtr> valDips = dr.initialDipoles();
for ( int i = 0; i < int(valDips.size()); i++ ) {
//valence dips always real
setPartonsOnShell(valDips[i]);
//find the configuration number for this valence dipole
//note that the max configuration number is the product of
//the number of combinations in each valence dipole
int N = nSubcascades(valDips[i]);
int subconfiguration = configuration % N;
//the remaining valence dips can choose between the config/N combinations.
configuration /= N;
if ( printstepdetails ) cout << "for this valence dip, use subconfiguration " << subconfiguration
<< " out of " << N << endl;
//now look at this valence dipole.
weight *= pickSubcascade(valDips[i], subconfiguration);
}
if ( printstepdetails ) cout << "done tagging onshells. now remove virtuals" << endl;
// dr.plotState(true);
//remove the off-shell ones
removeVirtuals(& dr);
if ( printstepdetails ) cout << "removed virtuals" << endl;
//fix the parent structure that may get broken (REALLY?) when removing the virtuals
//this is so that the real state will not run into troubles
// updateParentStructure(&dr);
return weight;
}
void DiffractiveEventFiller::pickSubcascadeFromInteraction(DipoleState & dr, PartonPtr p) const {
static DebugItem printstepdetails("DIPSY::PrintStepDetails", 6);
//set all partons off shell
setOffShell(dr);
setValenceOnShell(dr);
recursiveSetOnShell(p);
//remove the off-shell ones
removeVirtuals(& dr);
if ( printstepdetails ) cout << "removed virtuals" << endl;
//fix the parent structure that may get broken (REALLY?) when removing the virtuals
//this is so that the real state will not run into troubles
// updateParentStructure(&dr);
}
void DiffractiveEventFiller::recursiveSetOnShell(PartonPtr p) const {
p->onShell(true);
if ( p->parents().first ) recursiveSetOnShell(p->parents().first);
if ( p->parents().second ) recursiveSetOnShell(p->parents().second);
}
double DiffractiveEventFiller::reweightCascade(DipoleState & dr,
vector<PartonPtr> chainCaps) const {
static DebugItem printstepdetails("DIPSY::PrintStepDetails", 6);
if ( dr.getDipoles().size() == dr.initialDipoles().size() )
return min(1.0, estimateF(&dr));
vector<DipoleStatePtr> realI = extractI(chainCaps);
vector<DipoleStatePtr> realH = extractH(chainCaps);
double ret = 1.0;
for ( int i = 0; i < int(realI.size()); i++ ) {
double Fi = estimateF(realI[i]);
double Gi = estimateF(realH[i]);
//cout << ", (fi,Gi): (" << Fi << ", " << Gi << ")";
ret *= Fi-Gi;
}
//cout << endl;
return min(1.0, ret);
}
double DiffractiveEventFiller::estimateF(DipoleStatePtr I) const {
InvEnergy scale = 3.0/GeV;
list<DipolePtr> dips = I->getDipoles();
double ret = 0.0;
for ( list<DipolePtr>::iterator it = dips.begin(); it != dips.end(); it++ ) {
DipolePtr dip = *it;
ret += min(1.0, sqr(dip->size()/scale));
}
return ret;
}
void DiffractiveEventFiller::setOffShell(DipoleState & dr) const {
list<PartonPtr> partons = dr.getPartons();
for ( list<PartonPtr>::iterator it = partons.begin(); it != partons.end(); it++) {
tPartonPtr p = *it;
p->onShell(false);
}
}
void DiffractiveEventFiller::setValenceOnShell(DipoleState & dr) const {
vector<DipolePtr> dips = dr.initialDipoles();
for ( int i = 0; i < int(dips.size()); i++) {
tPartonPtr p1 = dips[i]->partons().first;
tPartonPtr p2 = dips[i]->partons().second;
p1->onShell(true);
p2->onShell(true);
}
}
void DiffractiveEventFiller::setPartonsOnShell(DipolePtr dip) const {
dip->partons().first->onShell(true);
dip->partons().second->onShell(true);
}
double DiffractiveEventFiller::pickSubcascade(DipolePtr dip, int choice) const {
static DebugItem printstepdetails("DIPSY::PrintStepDetails", 6);
//this dipole is always on shell.
setPartonsOnShell(dip);
int configuration = choice;
//find out how many subcascades come from first child
int firstN = dip->children().first? nSubcascades(dip->children().first):0;
// int secondN = dip->children().second? nSubcascades(dip->children().second):0;
//how much the no emissions case is boosted. INTERFACE!!
//1 means default no emission, 2 means double probability.
//double noEmBo = 1.0 + double(firstN*secondN)/3.0;
//double noEmBo = 1.0;
//as the no emission weights are changed, but the average weight has
//to be maintained, a renormalisation is necessary
//double weightNorm = (noEmBo + double(firstN*secondN))/
//(1.0+double(firstN*secondN));
// cout << "weightnorm: " << weightNorm << " options: "
// << firstN*secondN << endl;
if ( printstepdetails )
cout << "entering picksubcascade for a dipole with configuration number " << choice << endl;
//configuration 0 is the one with no more emissions.
if ( configuration == 0 ) {
if ( printstepdetails ) cout << "this dipole has no further emissions" << endl;
//reduce weight, as this option is more probable, see below
// cout << "no emission 0, returning weight " << weightNorm/noEmBo << endl;
//return weightNorm/noEmBo;
return 1.0;
}
if ( !dip->children().first || !dip->children().second ) {
Throw<DiffractiveCombinatorics>()
<< "Found a non-zero configuration number, but no children!! Will pretend configuration number is zero... :(" << Exception::warning;
//return weightNorm/noEmBo;
return 1.0;
}
//sometimes chose no emission anyways.
//compensate this by reducing weight a factor 2 if that happens.
//if ( UseRandom::rnd() < noEmBo/(noEmBo + double(firstN*secondN)) ) {
// cout << "no emission 1, returning weight " << weightNorm/noEmBo << endl;
//return weightNorm/noEmBo;
//}
// cout << "yes emission, emission options " << firstN*secondN << endl;
//since no emission is excluded, remove 1 so that configuration is
//between 0 and firstN*secondN
configuration -= 1;
if ( printstepdetails ) cout << "this dipole has (reduced) config number " << configuration << endl;
//split up the configuration number into two independent numbers
//one between 0 and firstN and one between 0 and secondN
int firstConfiguration = configuration % firstN;
int secondConfiguration = configuration/firstN;
if ( printstepdetails ) cout << "split up into firstconf " << firstConfiguration << " (out of " << firstN << ")"
<< ", and second conf "<< secondConfiguration << " (out of "
<< nSubcascades(dip->children().second) << ")" << endl;
//recur to each child with their respective configuration numbers
//double weight = weightNorm;
double weight = 1.0;
weight *= pickSubcascade(dip->children().first, firstConfiguration);
weight *= pickSubcascade(dip->children().second, secondConfiguration);
// cout << "returning emitted weight " << weight << endl;
//return weight;
return 1.0;
}
void DiffractiveEventFiller::updateParentStructure(DipoleStatePtr dr) const {
list<PartonPtr> partons = dr->getPartons();
for ( list<PartonPtr>::iterator it = partons.begin(); it != partons.end(); it++) {
tPartonPtr p = *it;
//dont bother with the offshell ones
if ( !p->onShell() ) continue;
//if the parent is off shell, take the grandparent as new parent
while ( p->parents().first && !p->parents().first->onShell() )
p->parents(make_pair(p->parents().first->parents().first,
p->parents().second));
while ( p->parents().second && !p->parents().second->onShell() )
p->parents(make_pair(p->parents().first,
p->parents().second->parents().second));
}
}
//checks through all partons, and returns the ones without children.
vector<PartonPtr> DiffractiveEventFiller::childlessChildren(DipoleStatePtr dr) const {
static DebugItem printstepdetails("DIPSY::PrintStepDetails", 6);
list<PartonPtr> partons = dr->getPartons();
list<PartonPtr> childless = partons;
//start with in the list, and remove the parents.
//this is necessary as the partons do not remember their kids.
while ( !partons.empty() ) {
list<PartonPtr> offShells;
for ( list<PartonPtr>::iterator it = partons.begin(); it != partons.end(); it++) {
tPartonPtr p = *it;
//remove parents from childless
if ( p->parents().first ) {
childless.remove(p->parents().first);
}
if ( p->parents().second ) {
childless.remove(p->parents().second);
}
//save the off shell parents, as their parents in turn should not be counted as childless
if ( p->parents().first && !p->parents().first->onShell() ) {
offShells.push_back(p->parents().first);
if ( printstepdetails )
cout << "found off shell at oy " << p->parents().first->oY() << endl;
}
if ( p->parents().second && !p->parents().second->onShell() ) {
offShells.push_back(p->parents().second);
if ( printstepdetails ) cout << "found off shell at oy " << p->parents().second->oY() << endl;
}
}
partons = offShells;
if ( printstepdetails ) cout << "found " << partons.size() << " off shell parents." << endl;
}
vector<PartonPtr> ret;
for ( list<PartonPtr>::iterator it = childless.begin(); it != childless.end(); it++) {
//first check that we don't add things without parents (ie valence)
if ( !((*it)->parents().first) && !((*it)->parents().second) ) continue;
ret.push_back(*it);
}
return ret;
}
//removes all valence partons in the vector
void DiffractiveEventFiller::removeValence(vector<PartonPtr> partons) const {
for ( vector<PartonPtr>::iterator it = partons.begin(); it != partons.end(); it++ ) {
if ( (*it)->valence() ) {
it = partons.erase(it);
it--;
}
}
}
void DiffractiveEventFiller::makeReal(DipoleState & dr, vector<PartonPtr> chainCaps,
DipoleState & de) const {
static DebugItem printstepdetails("DIPSY::PrintStepDetails", 6);
//prepare by setting all partons off shell, they will then be set on shell
//if they make it through the machinery
setOffShell(dr);
//create the real state
RealPartonStatePtr rs = new_ptr(RealPartonState());
rs->addValence(dr);
//run dr through a real state reweighting, with no interaction recoils
//set interaction scale to that of the "interacting" dipoles
for ( int i = 0; i < int(chainCaps.size()); i++ ) {
if ( printstepdetails ) cout << "adding chainCap no " << i << endl;
PartonPtr p = chainCaps[i];
//if already on-shell, nothing has to be done
if ( p->onShell() ) continue;
DipolePtr d1 = p->dipoles().first;
DipolePtr d2 = p->dipoles().second;
//first find the scale of the cap no i from the smallest connected dipole
//this will set the pt scale the chain starts the non-DGLAP suppression from.
Energy iScale = ZERO;
if ( d1 && d2 )
iScale = p->pTScale()/min(d1->size(), d2->size());
else if ( d1 && !d2 )
iScale = p->pTScale()/d1->size();
else if ( !d1 && d2 )
iScale = p->pTScale()/d2->size();
else Throw<DiffractiveCombinatorics>()
<< "Found (childless) parton without dipoles in DiffractiveEventFiller::makeReal"
<< Exception::warning;
//then run the machinery for reweighting and ordering
if ( d1 )
rs->fullControlEvolution(d1, DipolePtr(), true, true, iScale, iScale);
if ( d2 )
rs->fullControlEvolution(d2, DipolePtr(), true, true, iScale, iScale);
//set the partons on shell
if ( d1 )
rs->setOnShell(d1);
if ( d2 )
rs->setOnShell(d2);
}
for ( RealParton::RealPartonSet::iterator it = rs->valence.begin();
it != rs->valence.end(); it++ ) {
(*it)->setOnShell();
}
//balance p- (and pt if overall recoil done) using dr
//this then has to be inserted into the returned elastic particle
RealPartonStatePtr ers = new_ptr(RealPartonState());
ers->addValence(de);
fixBoost(rs, ers);
if ( printstepdetails ) cout << "balanced p+-" << endl;
//remove the virtuals in the dipole states
rs->mergeVirtuals();
rs->saveState();
removeVirtuals(&dr);
ers->saveState();
}
double DiffractiveEventFiller::amplitude(DipoleState & dr, vector<PartonPtr> chainCaps,
const ImpactParameters & b) const {
static DebugItem printstepdetails("DIPSY::PrintStepDetails", 6);
if ( printstepdetails ) cout << setprecision(10);
//make sure dr is in a state to be evolved and interact.
//the state gets a bit messed up by reabsorbtion
list<DipolePtr> dips = dr.getDipoles();
for ( list<DipolePtr>::const_iterator it = dips.begin(); it != dips.end(); it++ ) {
DipolePtr d = *it;
d->reset();
if ( d->neighbors().first && d->neighbors().first->colour() == d->colour() )
dr.generateColourIndex(d);
if ( d->neighbors().second && d->neighbors().second->colour() == d->colour() )
dr.generateColourIndex(d);
}
DipoleEventHandlerPtr eh = Current<DipoleEventHandler>().ptr();
// cout << "entering amplitude calculation for real state with " << chainCaps.size()
// << " interactions" << endl;
//first check if the state is the valence one, if so return the elastic amplitude. otherwise do the diffractive excitation amplitude
if ( dr.getDipoles().size() == dr.initialDipoles().size() )
return elasticAmplitude(dr, b);
//create one non-cap dipolestate (C) (these are the parents in the paper)
DipoleStatePtr realC = steriliseCaps(&dr);
//and for each cap:
//one state of the two last dipoles (I_i) and one state of the second last dipole (X_i).
vector<DipoleStatePtr> realI = extractI(chainCaps);
vector<DipoleStatePtr> realH = extractH(chainCaps);
//and the rapidities at which the caps were emitted.
vector<double> intY = extractIntY(chainCaps);
//loop over virtual cascades from these real subcascades, pair each with a stored
//virtual cascades from the elastic side, and calculate the averages of
//cascadeNonInt (e^{F_U})
//hiddenInt: 1 - exp(-F_X_i) (for each i)
//interactingInt: 1 - exp(-F_W_i) (for each i)
double cascadeNonInt = 0.0;
vector<double> hiddenInt(realI.size(), 0.0);
vector<double> interactingInt(realI.size(), 0.0);
vector<double> hiddenInthalf(realI.size(), 0.0);
vector<double> interactingInthalf(realI.size(), 0.0);
// cout << "vectors set up, starting loop" << endl;
for (int i = 0; i < int(virtualCascades.size()); i++ ) {
DipoleStatePtr virtU = realC->clone();
virtU->makeOriginal();
virtU->evolve(virtU->lowestY(), maxY());
double FU = eh->xSecFn().sumf(*virtU, *virtualCascades[i], b);
cascadeNonInt += exp(-FU);
for ( int j = 0; j < int(realI.size()); j++ ) {
DipoleStatePtr virtW = realI[j]->clone();
virtW->makeOriginal();
virtW->evolve(intY[j], maxY());
double FWi = eh->xSecFn().sumf(*virtW, *virtualCascades[i], b);
DipoleStatePtr virtX = realH[j]->clone();
virtX->makeOriginal();
virtX->evolve(intY[j], maxY());
double FXi = eh->xSecFn().sumf(*virtX, *virtualCascades[i], b);
hiddenInt[j] += eh->xSecFn().unitarize(FXi);
interactingInt[j] += eh->xSecFn().unitarize(FWi);
if ( double(i) < double(virtualCascades.size())/2.0 ) {
hiddenInthalf[j] += eh->xSecFn().unitarize(FXi);
interactingInthalf[j] += eh->xSecFn().unitarize(FWi);
}
}
}
//normalise
cascadeNonInt /= virtualCascades.size();
for ( int j = 0; j < int(realI.size()); j++ ) {
hiddenInt[j] /= virtualCascades.size();
interactingInt[j] /= virtualCascades.size();
// cout << setprecision(10);
// cout << "hidden: " << hiddenInt[j] << ", last: " << interactingInt[j]
// << ", diff: " << interactingInt[j] - hiddenInt[j] << ", relative error: "
// << (2.0*(interactingInthalf[j] - hiddenInthalf[j])/virtualCascades.size() - (interactingInt[j] - hiddenInt[j]))/(interactingInt[j] - hiddenInt[j])
// << ", parents: " << cascadeNonInt << endl;
}
//the final amplitude then is CascadeNonInt*hiddenNonInt*prod_i(interactingInti)
double amp = cascadeNonInt;
// cout << "cascade sudakov = " << cascadeNonInt;
for ( int j = 0; j < int(realI.size()); j++ ) {
// cout << ", interacting amplitude = " << interactingInt[j]
// << ", hidden amplitude = " << hiddenInt[j] << endl;
amp *= interactingInt[j] - hiddenInt[j];
}
// cout << "returning amp " << amp << endl;
return amp;
}
double DiffractiveEventFiller::elasticAmplitude(DipoleState & dr, const ImpactParameters & b) const {
static DebugItem printstepdetails("DIPSY::PrintStepDetails", 6);
if ( printstepdetails ) cout << setprecision(10);
cout << "elastic state. calculate elastic amplitude. dips: "
<< dr.getDipoles().size() << ", partons: " << dr.getPartons().size() << endl;
DipoleEventHandlerPtr eh = Current<DipoleEventHandler>().ptr();
// //testing
// DipoleStatePtr newState = eh->WFR().generate(*eh, 200.0*GeV);
// cout << "A completely new state:" << endl;
// newState->coutData();
double amp = 0.0;
double amphalf = 0.0;
for (int i = 0; i < int(virtualCascades.size()); i++ ) {
DipoleStatePtr virt = dr.clone();
virt->makeOriginal();
//DipoleStatePtr virt = copyActiveState(&dr);
// DipoleStatePtr virtNew = eh->WFR().generate(*eh, 200.0*GeV);
// set<DipolePtr> dipset = dr.allDipoles;
// for ( set<DipolePtr>::const_iterator it = allDipoles.begin();
// it != allDipoles.end(); it++ ) {
// }
list<DipolePtr> newdips = virt->getDipoles();
// cout << "copied unevolved dips:" << endl;
// for ( list<DipolePtr>::const_iterator it = newdips.begin(); it != newdips.end(); it++ ) {
// DipolePtr d = *it;
// cout << "address: " << d
// << ", y1: " << d->partons().first->y()
// << ", y2: " << d->partons().first->y()
// << ", effective Parton 1: " << d->effectivePartons().first
// << ", effective Parton 2: " << d->effectivePartons().second
// << ", colour: " << d->colour() << endl;
// }
// newdips = virtNew->getDipoles();
// cout << "new dips:" << endl;
// for ( list<DipolePtr>::const_iterator it = newdips.begin(); it != newdips.end(); it++ ) {
// DipolePtr d = *it;
// cout << "address: " << d
// << ", y1: " << d->partons().first->y()
// << ", child1: " << d->children().first
// << ", child2: " << d->children().second
// << ", generated gluon: " << d->generatedGluon()
// << ", generatedy: " << d->generatedY()
// << ", swingdip: " << d->swingDipole()
// << ", colour: " << d->colour() << endl;
// }
if ( printstepdetails ) cout << "evolve from " << virt->lowestY() << " to " << maxY() << endl;
virt->evolve(virt->lowestY(), maxY());
// cout << "copied state has " << virt->getPartons().size() << " partons." << endl;
// virtNew->evolve(virtNew->lowestY(), maxY());
// cout << "new state has " << virtNew->getPartons().size() << " partons." << endl;
double F = eh->xSecFn().sumf(*virt, *virtualCascades[i], b);
F = eh->xSecFn().unitarize(F);
if ( printstepdetails )
cout << "for elastic cascade " << i << ", elastic amp is = " << F << endl;
amp += F;
if ( double(i) < double(virtualCascades.size())/2.0 ) {
amphalf += F;
}
}
amp /= double(virtualCascades.size());
double relError = abs(2.0*amphalf/virtualCascades.size() - amp)/amp;
double correctionFactor = 1.0/sqrt(1.0+sqr(relError));
//cout << "elastic amp: " << amp << ", relative error: "
// << relError << ", correction factor: " << correctionFactor << endl;
return amp*correctionFactor;
}
// DipoleStatePtr DiffractiveEventFiller::copyActiveState(DipoleStatePtr dr) const {
// DipoleStatePtr copy = DipoleState(*dr);
// list<DipolePtr> dips = dr->getDipoles();
// list<PartonPtr> ps = dr->getPartons();
// vector<PartonPtr> newPs;
// for ( list<DipolePtr>::const_iterator it = dips.begin();
// it != dips.end(); it++ ) {
// }
// }
//removes the chain caps from the state dr.
DipoleStatePtr DiffractiveEventFiller::steriliseCaps(DipoleStatePtr dr) const {
DipoleStatePtr state = dr->clone();
vector<PartonPtr> caps = childlessChildren(state);
removeValence(caps);
list<DipolePtr> parents = state->getDipoles();
// cout << "entering sterilisecaps, dipoles before: " << parents.size()
// << ", caps: " << caps.size() << endl;
for ( int i = 0; i < int(caps.size()); i++ ) {
parents.remove(caps[i]->dipoles().first);
parents.remove(caps[i]->dipoles().second);
}
// cout << "dipoles after: " << parents.size() << endl;
if ( parents.size() == 0 ) {
DipoleStatePtr ret = new_ptr(DipoleState());
ret->handler(Current<DipoleEventHandler>().ptr());
return ret;
}
DipolePtr parent = *parents.begin();
// cout << "parent dipole is " << parent << endl;
for ( int i = 0; i < int(caps.size()); i++ ) {
DipolePtr d1 = caps[i]->dipoles().first;
DipolePtr d2 = caps[i]->dipoles().second;
d1->children().second = d2;
d2->children().second = d1;
PartonPtr p1 = d1->partons().first;
PartonPtr p2 = d2->partons().second;
// cout << "cap: " << caps[i]->oY();
// cout << ", p1: " << p1->oY();
// cout << ", p2: " << p2->oY() << endl;
p1->removeChild(caps[i]);
p2->removeChild(caps[i]);
d1->turnOff();
d2->turnOff();
}
return state;
}
vector<DipoleStatePtr> DiffractiveEventFiller::extractI(vector<PartonPtr> chainCaps) const {
static DebugItem printstepdetails("DIPSY::PrintStepDetails", 6);
if ( printstepdetails ) cout << "entering extract I" << endl;
vector<DipoleStatePtr> ret;
for ( int i = 0; i < int(chainCaps.size()); i++ ) {
PartonPtr c = chainCaps[i];
if ( printstepdetails ) cout << "set up cap" << endl;
if ( !c->dipoles().first || !c->dipoles().second )
cerr << "quark chaincap in DEF::extractI!!!! :o" << endl; //make proper error message
else {
PartonPtr c1 = c->dipoles().first->partons().first;
PartonPtr c2 = c->dipoles().second->partons().second;
if ( printstepdetails ) cout << "create state, partons and dipoles" << endl;
DipoleStatePtr state = new_ptr(DipoleState());
state->handler(Current<DipoleEventHandler>().ptr());
PartonPtr p = new_ptr(Parton());
PartonPtr p1 = new_ptr(Parton());
PartonPtr p2 = new_ptr(Parton());
DipolePtr d1 = state->createDipole();
DipolePtr d2 = state->createDipole();
d1->partons(make_pair(p1, p));
d2->partons(make_pair(p, p2));
d1->neighbors(make_pair(DipolePtr(), d2));
d2->neighbors(make_pair(d1, DipolePtr()));
d1->colour(c->dipoles().first->colour());
d2->colour(c->dipoles().second->colour());
p->plus(c->plus());
p->pT(c->pT());
p->updateYMinus();
p->oY(p->y());
p->position(c->position());
p->dipoles(make_pair(d1, d2));
p1->plus(c1->plus());
p1->pT(c1->pT());
p1->updateYMinus();
p1->oY(p1->y());
p1->position(c1->position());
p1->dipoles(make_pair(DipolePtr(), d1));
p2->plus(c2->plus());
p2->pT(c2->pT());
p2->updateYMinus();
p2->oY(p2->y());
p2->position(c2->position());
p2->dipoles(make_pair(d2, DipolePtr()));
state->addDipole(*d1);
state->addDipole(*d2);
// cout << "L dip sizes: " << d1->size()*GeV << ", "
// << d2->size()*GeV;
if ( printstepdetails ) cout << "extracted I" << endl;
// state->plotState(true);
ret.push_back(state);
}
}
return ret;
}
vector<DipoleStatePtr> DiffractiveEventFiller::extractH(vector<PartonPtr> chainCaps) const {
static DebugItem printstepdetails("DIPSY::PrintStepDetails", 6);
vector<DipoleStatePtr> ret;
for ( int i = 0; i < int(chainCaps.size()); i++ ) {
PartonPtr c = chainCaps[i];
if ( !c->dipoles().first || !c->dipoles().second )
cerr << "quark chaincap in DEF::extractH!!!! :o" << endl; //make proper error message
else {
PartonPtr c1 = c->dipoles().first->partons().first;
PartonPtr c2 = c->dipoles().second->partons().second;
DipoleStatePtr state = new_ptr(DipoleState());
state->handler(Current<DipoleEventHandler>().ptr());
PartonPtr p1 = new_ptr(Parton());
PartonPtr p2 = new_ptr(Parton());
DipolePtr d = state->createDipole();
d->partons(make_pair(p1, p2));
d->neighbors(make_pair(DipolePtr(), DipolePtr()));
InvEnergy r1 = (c->position() - c1->position()).pt();
InvEnergy r2 = (c->position() - c2->position()).pt();
double P1 = sqr(r2)/(sqr(r1) + sqr(r2));
double P2 = 1.0 - P1;
if ( P1 > 0.5 )
d->colour(c->dipoles().first->colour());
else
d->colour(c->dipoles().second->colour());
p1->plus(c1->plus() + P1*c->plus());
p1->pT(c1->pT() + P1*c->pT());
p1->updateYMinus();
p1->oY(p1->y());
p1->position(c1->position());
p1->dipoles(make_pair(DipolePtr(), d));
p2->plus(c2->plus() + P2*c->plus());
p2->pT(c2->pT() + P2*c->pT());
p2->updateYMinus();
p2->oY(p2->y());
p2->position(c2->position());
p2->dipoles(make_pair(d, DipolePtr()));
state->addDipole(*d);
// cout << ", H dip sizes: " << d->size()*GeV << endl;
if ( printstepdetails ) cout << "extracted H" << endl;
// state->plotState(true);
ret.push_back(state);
}
}
return ret;
}
vector<double> DiffractiveEventFiller::extractIntY(vector<PartonPtr> chainCaps) const {
vector<double> ret;
for ( int i = 0; i < int(chainCaps.size()); i++ ) {
ret.push_back(chainCaps[i]->oY());
// cout << "intY is " << chainCaps[i]->oY() << ", ";
}
return ret;
}
DipoleState::String DiffractiveEventFiller::makeProton(DipoleStatePtr state) const {
DipoleState::String ret;
PartonPtr proton = new_ptr(Parton());
proton->plus(state->plus());
proton->minus(state->minus());
proton->pT(TransverseMomentum());
ret.push_back(proton);
proton->flavour(ParticleID::pplus);
return ret;
}
// If needed, insert default implementations of virtual function defined
// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs).
void DiffractiveEventFiller::doinit() throw(InitException) {
EventFiller::doinit();
totalXSec = ZERO;
totalSqr = ZERO;
neve = 0;
}
void DiffractiveEventFiller::dofinish() {
EventFiller::dofinish();
totalXSec /= double(neve);
totalSqr /= double(neve);
CrossSection err = sqrt(totalSqr - sqr(totalXSec))/double(neve);
generator()->log()
<< "inclusive elastic plus SD (up to this y) cross section is "
<< ouniterr(totalXSec, err, nanobarn) << " nb." << endl;
generator()->log()
<< "total number of subcascades encountered: " << nSubCascades() << endl;
}
void DiffractiveEventFiller::doinitrun() {
EventFiller::doinitrun();
static DebugItem printstepdetails("DIPSY::PrintStepDetails", 6);
if ( printstepdetails ) cout << "entering DiffractiveEventHandler doinitrun" << endl;
DipoleEventHandlerPtr eh = Current<DipoleEventHandler>().ptr();
DipoleStatePtr dummyState = eh->WFR().generate(*eh, 1000.0*GeV);
Energy W = dummyState->handler().lumiFn().maximumCMEnergy();
Energy2 a = eh->WFR().m2() - eh->WFL().m2() + sqr(W);
Energy PR = (a + sqrt(sqr(a) - 4.0*eh->WFR().m2()*sqr(W)))*0.5/W;
double elasticY = log(PR/sqrt(eh->WFR().m2()));
maxY(elasticY - minRapGap());
minY(elasticY - maxRapGap());
initialiseVirtualCascades(*eh, eh->WFR(), PR, -maxY());
}
void DiffractiveEventFiller::persistentOutput(PersistentOStream & os) const {
os << theNElasticCascades << theMinRapGap << theMaxRapGap << theMinY << theMaxY << theNInteractions;
}
void DiffractiveEventFiller::persistentInput(PersistentIStream & is, int) {
is >> theNElasticCascades >> theMinRapGap >> theMaxRapGap >> theMinY >> theMaxY >> theNInteractions;
}
DescribeClass<DiffractiveEventFiller,EventFiller>
-describeDIPSYDiffractiveEventFiller("DIPSY::DiffractiveEventFiller", "libDIPSY.so");
+describeDIPSYDiffractiveEventFiller("DIPSY::DiffractiveEventFiller", "libAriadne5.so libDIPSY.so");
void DiffractiveEventFiller::Init() {
static ClassDocumentation<DiffractiveEventFiller> documentation
("The DiffractiveEventFiller class is able to produce an initial ThePEG::Step "
"from two colliding DipoleStates.");
static Parameter<DiffractiveEventFiller,int> interfaceNElasticCascades
("NElasticCascades",
"How many pregenerated elastic cascades should be used in the average over virtual cascades.",
&DiffractiveEventFiller::theNElasticCascades, 0, 1, 0,
true, false, Interface::lowerlim);
static Parameter<DiffractiveEventFiller,double> interfaceMinRapGap
("MinRapGap",
"The minimum rapidity gap in the generated (gluonic) events. There may be some leak due to "
"FSR and hadronisation",
&DiffractiveEventFiller::theMinRapGap, 3.0, 0.0, 0,
true, false, Interface::lowerlim);
static Parameter<DiffractiveEventFiller,double> interfaceMaxRapGap
("MaxRapGap",
"The maximum rapidity gap in the generated (gluonic) events. There may be some leak due to "
"FSR and hadronisation",
&DiffractiveEventFiller::theMaxRapGap, 5.0, 0.0, 0,
true, false, Interface::lowerlim);
static Parameter<DiffractiveEventFiller, int> interfaceNInteractions
("NInteractions",
"The number of interactions in the events being sampled."
"0 is elastic"
"-1 is the old algorithm with reweighting (seems to converge a bit faster)"
"-2 is the old algorithm without reweighting (slower for the tested runs, but "
"may be better for other runs.",
&DiffractiveEventFiller::theNInteractions, -2, 0, 0,
true, false, Interface::lowerlim);
}
//ymax should be the M_x limit, and the real state should be evolved to meet the virtuals
void DiffractiveEventFiller::initialiseVirtualCascades
(DipoleEventHandler & eh, WaveFunction & WFR, Energy E, double ymax) {
static DebugItem printstepdetails("DIPSY::PrintStepDetails", 6);
if ( printstepdetails ) cout << "entering initialise virtual cascades" << endl;
virtualCascades.clear();
int virtualSamples = nElasticCascades();
generator()->log() << "evolving elastic from "
<< -eh.WFR().generate(eh, E)->lowestY()
<< " to " << -ymax << endl;
for ( int i = 0; i < virtualSamples; i ++ ) {
DipoleStatePtr virt = eh.WFR().generate(eh, E);
virt->evolve(virt->lowestY(), ymax);
virtualCascades.push_back(virt);
// if ( printstepdetails ) cout << "done virtual state no " << i << endl;
// virt->plotState(true);
}
}
diff --git a/DIPSY/Dipole.cc b/DIPSY/Dipole.cc
--- a/DIPSY/Dipole.cc
+++ b/DIPSY/Dipole.cc
@@ -1,321 +1,321 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the Dipole class.
//
#include "Dipole.h"
#include "DipoleState.h"
#include "DipoleEventHandler.h"
#include "ThePEG/Utilities/Current.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Utilities/Throw.h"
#include "ThePEG/Repository/UseRandom.h"
using namespace DIPSY;
Dipole::~Dipole() {
if ( effmap ) delete effmap;
}
-Ariadne::ClonePtr Dipole::clone() const {
+Ariadne5::ClonePtr Dipole::clone() const {
return new_ptr(*this);
}
void Dipole::fillReferences(CloneSet & cs) const {
cs.insert(thePartons.first);
cs.insert(thePartons.second);
cs.insert(theGeneratedGluon);
}
void Dipole::rebind(const TranslationMap & trans) {
thePartons.first = trans.translate(thePartons.first);
thePartons.second = trans.translate(thePartons.second);
theNeighbors.first = trans.translate(theNeighbors.first);
theNeighbors.second = trans.translate(theNeighbors.second);
theChildren.first = trans.translate(theChildren.first);
theChildren.second = trans.translate(theChildren.second);
theGeneratedGluon = trans.translate(theGeneratedGluon);
theSwingDipole = trans.translate(theSwingDipole);
}
void Dipole::interact(Dipole & x) {
theInteracted = &x;
if ( partons().first ) partons().first->interact();
if ( partons().second ) partons().second->interact();
}
pair <InvEnergy, InvEnergy> Dipole::interactionLengths() const {
if ( !interacted() ) return make_pair( 0.0/GeV, 0.0/GeV );
return make_pair( sqrt(partons().first->dist2
(*(interacted()->partons().second))),
sqrt(partons().second->dist2
(*(interacted()->partons().first))) );
}
InvEnergy Dipole::rMax() const {
return theDipoleState->handler().rMax();
}
void Dipole::reset() {
theGeneratedGluon = PartonPtr();
theSwingDipole = tDipolePtr();
theGeneratedY = Constants::MaxRapidity;
swingCache = -1.0/GeV2;
if ( effmap ) delete effmap;
effmap = 0;
}
void Dipole::colExtract(vector< vector<tDipolePtr> > & colvec) {
if ( children().first ) children().first->colExtract(colvec);
if ( children().second ) children().second->colExtract(colvec);
if ( !children().first && !children().second )
forceAt(colvec, colour()).push_back(this);
}
tDipolePtr Dipole::getFSSwinger(double miny, double maxy) {
// *** TODO *** Check if dead-end before recursion
if ( children().first && children().second ) {
tDipolePtr em1 = children().first->getFSSwinger(miny, maxy);
tDipolePtr em2 = children().second->getFSSwinger(miny, maxy);
return em1->generatedY() < em2->generatedY()? em1: em2;
} else if ( children().first ) {
return children().first->getFSSwinger(miny, maxy);
} else if ( children().second ) { //dead end??
// return children().second->getFSSwinger(miny, maxy);
}
generateFSRec(miny, maxy);
return this;
}
void Dipole::generateFSRec(double miny, double maxy) {
if ( dipoleState().handler().swingPtr() && participating() &&
!children().second )
dipoleState().handler().swinger().generateFS(*this, miny, maxy);
}
tDipolePtr Dipole::getEmitter(double miny, double maxy) {
if ( !isOn ) return DipolePtr();
if ( children().first && children().second ) {
tDipolePtr em1 = children().first->getEmitter(miny, maxy);
tDipolePtr em2 = children().second->getEmitter(miny, maxy);
if ( !em1 ) return em2? em2:em1;
else if ( !em2 ) return em1;
return em1->generatedY() < em2->generatedY()? em1: em2;
} else if ( children().first ) {
return children().first->getEmitter(miny, maxy);
} else if ( children().second ) {
return DipolePtr();
}
if ( !hasGen() || effectivePartonsChanged() ) {
generate(miny, maxy);
}
else {
generateRec(miny, min(generatedY(), maxy), false);
}
return this;
}
void Dipole::generate(double miny, double maxy) {
reset();
dipoleState().handler().emitter().generate(*this, miny, maxy);
generateRec(miny, min(generatedY(), maxy), true);
}
void Dipole::generateRec(double miny, double maxy, bool force) {
if ( dipoleState().handler().swingPtr() )
dipoleState().handler().swinger().generate(*this, miny, maxy, force);
}
bool Dipole::forceGenerateRec(double ymax) {
return dipoleState().handler().swingPtr()?
dipoleState().handler().swinger().forceGenerate(*this, ymax): false;
}
void Dipole::recombine() {
if ( dipoleState().handler().swingPtr() )
dipoleState().handler().swinger().recombine(*this);
}
void Dipole::absorb() {
PartonPtr p = new_ptr(Parton());
PartonPtr p1 = partons().first;
PartonPtr p2 = partons().second;
DipolePtr d1 = neighbors().first;
DipolePtr d2 = neighbors().second;
p->pT( p1->pT() + p2->pT() );
p->plus( p1->plus() + p2->plus() );
p->y( log(p->pT().pt()/p->plus()) );
p->minus( p->pT().pt()*exp(p->y()) );
d1->neighbors( make_pair( d1->neighbors().first, d2 ) );
d2->neighbors( make_pair( d1, d2->neighbors().second ) );
d1->partons( make_pair( d1->partons().first, p ) );
d2->partons( make_pair( p, d2->partons().second ) );
p->dipoles( make_pair( d1, d2 ) );
theChildren.second = d2;
}
void Dipole::emit() {
if ( swingDipole() ) {
recombine();
return;
}
dipoleState().handler().emitter().emit(*this);
// splitDipole();
// *** ATTENTION *** implement this.
}
void Dipole::splitDipole(double colsel) {
if ( !generatedGluon() )
Throw<NothingGenerated>()
<< "Tried to perform an emission where none was generated."
<< Exception::abortnow;
theChildren = make_pair(dipoleState().createDipole(),
dipoleState().createDipole());
thePartons.first->theChildren.insert(generatedGluon());
thePartons.second->theChildren.insert(generatedGluon());
if ( neighbors().first ) {
children().first->theNeighbors.first = neighbors().first;
neighbors().first->theNeighbors.second = children().first;
neighbors().first->reset();
neighbors().first->touch();
}
children().first->theNeighbors.second = children().second;
children().second->theNeighbors.first = children().first;
partons().first->theDipoles.second = children().first;
partons().second->theDipoles.first = children().second;
if ( neighbors().second ) {
children().second->theNeighbors.second = neighbors().second;
neighbors().second->theNeighbors.first = children().second;
neighbors().second->reset();
neighbors().second->touch();
}
children().first->partons(make_pair(partons().first,generatedGluon()));
children().second->partons(make_pair(generatedGluon(),partons().second));
generatedGluon()->parents(partons());
generatedGluon()->dipoles(children());
generatedGluon()->rightMoving( partons().first->rightMoving() );
if ( UseRandom::rndbool(colsel) ) {
children().first->theColour = theColour;
dipoleState().generateColourIndex(children().second);
} else {
children().second->theColour = theColour;
dipoleState().generateColourIndex(children().first);
}
}
int Dipole::colourSystem() const {
return colour()/Current<DipoleEventHandler>()->nColours();
}
void Dipole::colourSystem(int sys) {
colour(colour()%Current<DipoleEventHandler>()->nColours() +
sys*Current<DipoleEventHandler>()->nColours());
}
tEffectivePartonPtr Dipole::getEff(tPartonPtr p, InvEnergy range) const {
tEffectivePartonPtr ret;
if ( Current<DipoleEventHandler>()->effectivePartonMode() == 3 ) {
if ( p == partons().first ) {
effectivePartons().first->setRange(range);
return effectivePartons().first;
}
if ( p == partons().second ) {
effectivePartons().second->setRange(range);
return effectivePartons().second;
}
}
if ( !effmap ) buildEffMap();
if ( p == partons().first ) {
EffMap::const_iterator it = effmap->first.begin();
ret = it->second;
while ( ++it != effmap->first.end() && it->first < range ) ret = it->second;
}
if ( p == partons().second ) {
EffMap::const_iterator it = effmap->second.begin();
ret = it->second;
while ( ++it != effmap->second.end() && it->first < range ) ret = it->second;
}
return ret;
}
void Dipole::buildEffMap() const {
if ( effmap ) delete effmap;
effmap = new pair<EffMap,EffMap>();
// First take the first partonand create the largest one immaginable.
EffectivePartonPtr ep =
EffectiveParton::create(*partons().first, size()/2.0);
// Then we loop through the included partons in order and create all
// sub effective partons.
set<tPartonPtr> intp = ep->internalPartons();
set<InvEnergy> dists;
if ( intp.empty() ) {
const vector<tPartonPtr> & intp = ep->cachedPartons();
for ( vector<tPartonPtr>::const_iterator it = intp.begin();
it != intp.end(); ++it )
dists.insert(sqrt(ep->originalParton()->dist2(**it)));
} else {
for ( set<tPartonPtr>::iterator it = intp.begin(); it != intp.end(); ++it )
dists.insert(sqrt(ep->originalParton()->dist2(**it)));
}
effmap->first.resize(intp.size());
for ( set<InvEnergy>::iterator it = dists.begin();
it != dists.end(); ++it ) {
effmap->first.push_back
(make_pair(*it, EffectiveParton::create(*partons().first, *it)));
}
// Then do the same for the second
ep = EffectiveParton::create(*partons().second, size()/2.0);
// Then we loop through the included partons in order and create all
// sub effective partons.
intp = ep->internalPartons();
dists.clear();
if ( intp.empty() ) {
const vector<tPartonPtr> & intp = ep->cachedPartons();
for ( vector<tPartonPtr>::const_iterator it = intp.begin();
it != intp.end(); ++it )
dists.insert(sqrt(ep->originalParton()->dist2(**it)));
} else {
for ( set<tPartonPtr>::iterator it = intp.begin(); it != intp.end(); ++it )
dists.insert(sqrt(ep->originalParton()->dist2(**it)));
}
effmap->second.reserve(intp.size());
for ( set<InvEnergy>::iterator it = dists.begin(); it != dists.end(); ++it ) {
effmap->second.push_back
(make_pair(*it, EffectiveParton::create(*partons().second, *it)));
}
}
void Dipole::persistentOutput(PersistentOStream & os) const {
os << theDipoleState << thePartons << theNeighbors << theChildren
<< theGeneratedGluon << theSwingDipole << theGeneratedY << theColour
<< theInteracted << isParticipating << isRecoilSwing << isTouched
<< isOn << ounit(swingCache, 1.0/GeV2);
}
void Dipole::persistentInput(PersistentIStream & is, int) {
if ( effmap ) delete effmap;
is >> theDipoleState >> thePartons >> theNeighbors >> theChildren
>> theGeneratedGluon >> theSwingDipole >> theGeneratedY >> theColour
>> theInteracted >> isParticipating >> isRecoilSwing >> isTouched
>> isOn >> iunit(swingCache, 1.0/GeV2);
}
// Static variable needed for the type description system in ThePEG.
#include "ThePEG/Utilities/DescribeClass.h"
DescribeClass<Dipole,PersistentBase>
- describeDIPSYDipole("DIPSY::Dipole", "libDIPSY.so");
+ describeDIPSYDipole("DIPSY::Dipole", "libAriadne5.so libDIPSY.so");
void Dipole::Init() {}
diff --git a/DIPSY/Dipole.h b/DIPSY/Dipole.h
--- a/DIPSY/Dipole.h
+++ b/DIPSY/Dipole.h
@@ -1,561 +1,561 @@
// -*- C++ -*-
#ifndef DIPSY_Dipole_H
#define DIPSY_Dipole_H
//
// This is the declaration of the Dipole class.
//
#include "ThePEG/Config/ThePEG.h"
#include "Ariadne/Config/CloneBase.h"
#include "Dipole.fh"
#include "Parton.h"
#include "EffectiveParton.h"
#include "DipoleState.fh"
namespace DIPSY {
using namespace ThePEG;
/**
* Here is the documentation of the Dipole class.
*/
-class Dipole: public Ariadne::CloneBase {
+class Dipole: public Ariadne5::CloneBase {
public:
/**
* A pair of dipoles
*/
typedef pair<tDipolePtr,tDipolePtr> tDipolePair;
/**
* A pair of partons.
*/
typedef pair<PartonPtr,PartonPtr> PartonPair;
/**
* The DipoleState is a friend.
*/
friend class DipoleState;
/**
* A map for stoing effective partons.
*/
typedef vector< pair<InvEnergy,EffectivePartonPtr> > EffMap;
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
inline Dipole();
/**
* The copy constructor.
*/
inline Dipole(const Dipole &);
/**
* The destructor.
*/
virtual ~Dipole();
//@}
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 Ariadne::ClonePtr clone() const;
+ virtual Ariadne5::ClonePtr clone() const;
/**
* Fill the provided set with all pointers to CloneBase objects used
* in this object.
*/
virtual void fillReferences(CloneSet &) 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:
/** @name Simple access functions. */
//@{
/**
* rMax for the dipoles handler.
*/
InvEnergy rMax() const;
/**
* The DipoleState to which this Dipole belongs.
*/
inline DipoleState & dipoleState() const;
/**
* Set the DipoleState to which this Dipole belongs.
* added by CF to access from emitter.
*/
inline void dipoleState(tDipoleStatePtr);
/**
*/
inline const PartonPair & partons() const;
/**
* Get the effective parton.
*/
inline const pair< EffectivePartonPtr, EffectivePartonPtr > &
effectivePartons() const;
/**
* Get an effective parton corresponding to one of the partons in
* the original dipole given a range.
*/
tEffectivePartonPtr getEff(tPartonPtr p, InvEnergy range) const;
/**
* Set the effective parton.
*/
inline void effectivePartons( tEffectivePartonPtr, tEffectivePartonPtr );
/**
* controls if any of the effective partons have been changed by emissions.
*/
inline const bool effectivePartonsChanged() const;
/**
* Set the neighboring dipoles.
*/
inline const tDipolePair & neighbors() const;
/**
* Get the child dipoles.
*/
inline const tDipolePair & children() const;
/**
* Get the child dipoles.
*/
inline tDipolePair & children();
/**
* Get the generated gluon to be emitted. Returns null if none has
* been generated.
*/
inline tPartonPtr generatedGluon() const;
/**
* Set the generated gluon to be emitted.
* Added by CF to get access from emitter.
*/
inline void generatedGluon(tPartonPtr);
/**
* Get the dipole to swing with. Return null if no swing has been
* generated.
*/
inline tDipolePtr swingDipole() const;
/**
* Set the dipole to swing with.
* Aded by CF
*/
inline void swingDipole(tDipolePtr);
/**
* Return true if this dipole has generated an emission or a swing.
*/
inline bool hasGen();
/**
* The rapidity of the generated emission or swing.
*/
inline double generatedY() const;
/**
* Set the rapidity of the generated emission or swing.
* Added by CF to access from emitter.
*/
inline void generatedY(double);
/**
* Get a pointer to a Dipole in another DipoleState with which this
* Dipole has interacted. @return null if Dipole has not interacted.
*/
inline tDipolePtr interacted() const;
/**
* Returns the lengths that the new dipoles will have when it has
* swinged with the interacted() dipole. returns 0 if not interacting.
*/
pair <InvEnergy, InvEnergy> interactionLengths() const;
/**
* Set the partons.
*/
inline void partons(PartonPair);
/**
* Set the neighboring dipoles.
*/
inline void neighbors(tDipolePair);
/**
* Set the neighboring dipole.
*/
inline void firstNeighbor(tDipolePtr);
/**
* Set the neighboring dipole.
*/
inline void secondNeighbor(tDipolePtr);
/**
* Get the colour.
*/
inline int colour() const;
/**
* Set the colour.
*/
inline void colour(int c, int sys = 0);
/**
* Get the colour system.
*/
int colourSystem() const;
/**
* Set the colour system.
*/
void colourSystem(int sys);
/**
* says if the dipole is part of a DGLAP chain, and thus should not be absorbed.
*/
inline bool DGLAPsafe();
/**
* Sets if the dipole is part of a DGLAP chain or not.
*/
inline void DGLAPsafe(bool);
/**
* says if the (initial) dipole is participating in the interaction.
*/
inline bool participating();
/**
* Sets if the (initial) dipole is participating in the interaction.
*/
inline void participating(bool);
/**
* gets if the generated swing is a gluon exchange.
*/
inline bool recoilSwing() const {
return isRecoilSwing;
}
/**
* sets if the generated swing is a gluon exchange.
*/
inline void recoilSwing(bool recoil) {
isRecoilSwing = recoil;
}
/**
* Indicate that the Dipole has interacted with the given Dipole in
* another DipoleState.
*/
void interact(Dipole &);
/**
* Get the squared transverse size of this Dipole.
*/
inline InvEnergy2 size2() const;
/**
* Get the transverse size of this Dipole.
*/
inline InvEnergy size() const;
//@}
/** @name Functions for extracting final dipoles. */
//@{
/**
* Given an output iterator fill the corresponding container with
* final, undecayed dipoles. This is done recursively, ie. if this
* dipole has decayed, the extract methods of the two children are
* called instead.
*/
template <typename OutputIterator>
void extract(OutputIterator it);
/**
* Extract all undecayed dipoles into the vector according to colour
* index.
*/
void colExtract(vector< vector<tDipolePtr> > &);
//@}
/**
* Recursively find the dipole which is next to swing in final state.
*/
tDipolePtr getFSSwinger(double miny, double maxy);
/**
* Generate a possible emission or a swing from this Dipole in the
* given rapidity interval [\a miny,\a maxy].
*/
void generateFSRec(double miny, double maxy);
/** @name Functions for shower generation. */
//@{
/**
* Recursively find the dipole which is next to emit or swing in the
* given rapidity interval [\a miny,\a maxy].
*/
tDipolePtr getEmitter(double miny, double maxy);
/**
* Generate a possible emission or a swing from this Dipole in the
* given rapidity interval [\a miny,\a maxy].
*/
void generate(double miny, double maxy);
/**
* Generate a swing for this Dipole in the given rapidity interval
* [\a miny,\a maxy]. If \a force is true, always generate a swing,
* otherwise only check if a swing is possible with dipoles which
* are new or has changed.
*/
void generateRec(double miny, double maxy, bool force);
/**
* Try really hard to generates a swing, but not with higher rapdity step
* than /a ymax. /a ymax = 0 means no limit.
* If no swing found, return false.
*/
bool forceGenerateRec(double ymax);
/**
* Perform a recombination previously generated by generateRec().
*/
void recombine();
/**
* absorb the dipole, replacing it with a single parton.
*/
void absorb();
/**
* Perform the emission previously generated for this \a dipole. If
* no emission has been generated a runtime_error is thrown.
*/
void emit();
//@}
public:
/**
* Split this dipole by emitting the generated gluon. \a colsel
* gives the probability that the first child dipole inherits the
* colour index of the mother.
*/
void splitDipole(double colsel);
/**
* Reset any emission or swong generated for this dipole.
*/
void reset();
/**
* Check if conditions for this dipole has changed since last
* generated emission or swing.
*/
bool touched() const {
return isTouched;
}
/**
* Flag that conditions for this dipole has changed since last
* generated emission or swing.
*/
void touch() {
isTouched = true;
}
/**
* Flag that this dipole no has generated emission or swing.
*/
void untouch() {
isTouched = false;
}
/**
* Flag that this dipole should no longer emit.
*/
void turnOff() {
isOn = false;
}
protected:
struct NothingGenerated: public Exception {};
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 DipoleState to which this Dipole belongs.
*/
tDipoleStatePtr theDipoleState;
/**
* The partons.
*/
PartonPair thePartons;
/**
* The neighboring dipoles.
*/
tDipolePair theNeighbors;
/**
* The child dipoles.
*/
tDipolePair theChildren;
/**
* The generated gluon to be emitted. Null if none has been generated.
*/
PartonPtr theGeneratedGluon;
/**
* the effective partons.
*/
pair< EffectivePartonPtr, EffectivePartonPtr > theEffectivePartons;
/**
* The dipole to swing with. Null if no swing has been generated.
*/
tDipolePtr theSwingDipole;
/**
* The rapidity of the generated emission or swing.
*/
double theGeneratedY;
/**
* The colour index of this Dipole.
*/
int theColour;
/**
* If non-null, pointer to a Dipole in another DipoleState with which
* this Dipole has interacted.
*/
tDipolePtr theInteracted;
/**
* If the dipole is part of a DGLAP chain or not in the final state.
*/
bool theGLAPsafe;
/**
* if the (initial) dipole is part of a participating nucleon in a
* heavy ion collision.
*/
bool isParticipating;
/**
* If the generated swing is gluon exchange or quadrupole swing.
*/
bool isRecoilSwing;
/**
* Indicate if conditions for this dipole has changed since last
* generated emission or swing.
*/
bool isTouched;
/**
* This can be set to false to manually turn a dipole of, ie disallow
* emissions or swings.
**/
bool isOn;
public:
/**
* Cache values needed for (FS) swing.
*/
mutable InvEnergy2 swingCache;
/**
* A pair of maps where the effective partons are stored.
*/
mutable pair<EffMap,EffMap> * effmap;
/**
* Build the map of effective partons.
*/
void buildEffMap() const;
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
Dipole & operator=(const Dipole &);
};
}
#include "Dipole.icc"
#endif /* DIPSY_Dipole_H */
diff --git a/DIPSY/DipoleAbsorber.cc b/DIPSY/DipoleAbsorber.cc
--- a/DIPSY/DipoleAbsorber.cc
+++ b/DIPSY/DipoleAbsorber.cc
@@ -1,209 +1,209 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the DipoleAbsorber class.
//
#include "DipoleAbsorber.h"
#include "Ariadne/DIPSY/DipoleState.h"
#include "Ariadne/DIPSY/Parton.h"
#include "Ariadne/DIPSY/Dipole.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Utilities/Throw.h"
#include "ThePEG/Utilities/Current.h"
#include "DipoleEventHandler.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace DIPSY;
DipoleAbsorber::DipoleAbsorber() {}
DipoleAbsorber::~DipoleAbsorber() {}
bool rapSorty(tcPartonPtr part1, tcPartonPtr part2) {
return (part1->y() >= part2->y());
}
void DipoleAbsorber::removeParton(tPartonPtr p) const {
DipolePtr d1 = p->dipoles().first;
DipolePtr d2 = p->dipoles().second;
//if a quark (ie only one colour line out), then just remove
//the parton and the connected dipole.
if ( !d1 ) {
PartonPtr g = d2->partons().second;
if ( !g->dipoles().first ) return;
d2->neighbors().second->firstNeighbor(d1);
g->dipoles(make_pair(d1, d2->neighbors().second));
d2->children().second = d2->neighbors().second;
g->flavour(p->flavour());
return;
}
if ( !d2 ) {
PartonPtr g = d1->partons().first;
if ( !g->dipoles().second ) return;
d1->neighbors().first->secondNeighbor(d2);
g->dipoles(make_pair(d1->neighbors().first, d2));
d1->children().second = d1->neighbors().first;
g->flavour(p->flavour());
return;
}
PartonPtr p1 = d1->partons().first;
PartonPtr p2 = d2->partons().second;
if ( p1->dipoles().second->partons().second == p2 ) return;
d2->children().second = d1;
p2->dipoles(make_pair(d1,p2->dipoles().second));
d1->partons(make_pair(p1,p2));
d1->secondNeighbor(d2->neighbors().second);
if ( d1->neighbors().second ) d1->neighbors().second->firstNeighbor(d1);
if ( d1->size()/(d1->size()+d2->size()) < UseRandom::rnd() )
d1->colour(d2->colour());
}
void DipoleAbsorber::absorbVirtualPartons( DipoleState & state ) const {
list<PartonPtr> virtualPartons = state.virtualPartons();
virtualPartons.sort(rapSorty);
while ( !(virtualPartons.empty()) ) {
virtualPartons.sort(rapSorty);
absorbParton( virtualPartons.front(), state );
virtualPartons.pop_front();
}
}
bool DipoleAbsorber::swing( DipolePtr d1, DipolePtr d2 ) const {
if ( d1->neighbors().second == d2 ) return false;
if ( d2->neighbors().second == d1 ) return false;
if (d1 == d2) Throw<Exception>()
<< "lol, swinging with itself?? >_>" << Exception::abortnow;
if (d2->children().second || d2->children().first)
Throw<Exception>()
<< "swinging with someone thats emitted already" << Exception::abortnow;
PartonPtr p11 = d1->partons().first;
PartonPtr p12 = d1->partons().second;
PartonPtr p21 = d2->partons().first;
PartonPtr p22 = d2->partons().second;
d1->partons(make_pair(p11, p22));
d1->neighbors(make_pair(p11->dipoles().first, p22->dipoles().second));
if ( d1->neighbors().second ) d1->neighbors().second->firstNeighbor(d1);
d2->partons(make_pair(p21, p12));
d2->neighbors(make_pair(p21->dipoles().first, p12->dipoles().second));
if ( d2->neighbors().second ) d2->neighbors().second->firstNeighbor(d2);
p12->dipoles(make_pair(d2, p12->dipoles().second));
p22->dipoles(make_pair(d1, p22->dipoles().second));
return true;
}
void DipoleAbsorber::isolateNonParticipating( DipoleState & state ) const {
for( int i = 0; i < int(state.initialDipoles().size()); i++ ) {
DipolePtr d = state.initialDipoles()[i];
if ( !(d->participating()) ) {
if ( d->partons().first->dipoles().second != d->partons().second->dipoles().first )
swing( d->partons().first->dipoles().second, d->partons().second->dipoles().first );
d->partons().first->dipoles().second->participating( false );
}
}
}
void DipoleAbsorber::swingLoop( DipolePtr d, DipoleState & state ) const {
//make a list of the partons and dipoles in the loop.
list<PartonPtr> partons;
list<DipolePtr> dipoles;
PartonPtr p = d->partons().second;
partons.push_back(p);
dipoles.push_back(d);
bool forward = true;
while ( p != d->partons().first && (forward || p->dipoles().first) ) {
if ( !(p->dipoles().second) ) {
cout << "found a quark in SmallDipoleAbsorber::absorbLoop!!!!!!!" << endl;
state.diagnosis(true);
p = d->partons().first;
partons.push_back(p);
forward = false;
continue;
}
if ( forward ) {
p = p->dipoles().second->partons().second;
dipoles.push_back(p->dipoles().first);
}
else {
p = p->dipoles().first->partons().first;
dipoles.push_back(p->dipoles().second);
}
partons.push_back(p);
}
//find and perform a probable swing. Don't bother with colours...
list<DipolePtr> otherDips = d->dipoleState().getDipoles();
for ( list<DipolePtr>::iterator i = dipoles.begin(); i != dipoles.end(); i++ ) {
for ( list<DipolePtr>::iterator j = otherDips.begin(); j != otherDips.end(); j++ ) {
if ( *i == *j )
j = otherDips.erase(j)--;
}
}
DipolePtr d1, d2;
double maxy = 0.0;
for ( list<DipolePtr>::iterator i = dipoles.begin(); i != dipoles.end(); i++ ) {
for ( list<DipolePtr>::iterator j = otherDips.begin(); j != otherDips.end(); j++ ) {
double R = log( UseRandom::rnd() );
InvEnergy2 a = (*i)->partons().first->dist2(*(*i)->partons().second);
InvEnergy2 b = (*j)->partons().first->dist2(*(*j)->partons().second);
InvEnergy2 c = (*i)->partons().second->dist2(*(*j)->partons().first);
InvEnergy2 d = (*i)->partons().first->dist2(*(*j)->partons().second);
a = sqr(Current<DipoleEventHandler>()->rMax())/
(Current<DipoleEventHandler>()->alphaS(sqrt(a)))*
sqr(exp(sqrt(a)/Current<DipoleEventHandler>()->rMax()) - 1.0);
b = sqr(Current<DipoleEventHandler>()->rMax())/
(Current<DipoleEventHandler>()->alphaS(sqrt(b)))*
sqr(exp(sqrt(b)/Current<DipoleEventHandler>()->rMax()) - 1.0);
c = sqr(Current<DipoleEventHandler>()->rMax())/
(Current<DipoleEventHandler>()->alphaS(sqrt(c)))*
sqr(exp(sqrt(c)/Current<DipoleEventHandler>()->rMax()) - 1.0);
d = sqr(Current<DipoleEventHandler>()->rMax())/
(Current<DipoleEventHandler>()->alphaS(sqrt(d)))*
sqr(exp(sqrt(d)/Current<DipoleEventHandler>()->rMax()) - 1.0);
double A = c*d/(a*b);
double y = R*A;
if ( y < maxy || maxy == 0.0 ) {
maxy = y;
d1 = *i;
d2 = *j;
}
}
}
swing(d1, d2);
}
// If needed, insert default implementations of virtual function defined
// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs).
// Static variable needed for the type description system in ThePEG.
#include "ThePEG/Utilities/DescribeClass.h"
DescribeAbstractNoPIOClass<DipoleAbsorber,HandlerBase>
- describeDIPSYDipoleAbsorber("DIPSY::DipoleAbsorber", "libDIPSY.so");
+ describeDIPSYDipoleAbsorber("DIPSY::DipoleAbsorber", "libAriadne5.so libDIPSY.so");
void DipoleAbsorber::Init() {
static ClassDocumentation<DipoleAbsorber> documentation
("DipoleAbsorber is a base class to be used for models describing how "
"non-interacted dipoles will be reabsorbed.");
}
diff --git a/DIPSY/DipoleAnalysisHandler.cc b/DIPSY/DipoleAnalysisHandler.cc
--- a/DIPSY/DipoleAnalysisHandler.cc
+++ b/DIPSY/DipoleAnalysisHandler.cc
@@ -1,58 +1,58 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the DipoleAnalysisHandler class.
//
#include "DipoleAnalysisHandler.h"
#include "ThePEG/Interface/ClassDocumentation.h"
using namespace DIPSY;
DipoleAnalysisHandler::DipoleAnalysisHandler() {}
DipoleAnalysisHandler::~DipoleAnalysisHandler() {}
void DipoleAnalysisHandler::analyze(const DipoleState &, const DipoleState &,
const ImpactParameters &, const DipoleXSec &,
double, CrossSection) {}
void DipoleAnalysisHandler::analyze(const vector<DipoleStatePtr> &,
const vector<DipoleStatePtr> &,
const vector<ImpactParameters> &, const DipoleXSec &,
const Vec3D & probs, double) {}
ostream & DipoleAnalysisHandler::stub(string text) const {
generator()->log().setf(ios::left, ios::adjustfield);
generator()->log() << setw(50) << name() +text;
return generator()->log();
}
// If needed, insert default implementations of virtual function defined
// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs).
// Static variable needed for the type description system in ThePEG.
#include "ThePEG/Utilities/DescribeClass.h"
DescribeAbstractNoPIOClass<DipoleAnalysisHandler,HandlerBase>
describeDIPSYDipoleAnalysisHandler("DIPSY::DipoleAnalysisHandler",
- "libDIPSY.so");
+ "libAriadne5.so libDIPSY.so");
void DipoleAnalysisHandler::Init() {
static ClassDocumentation<DipoleAnalysisHandler> documentation
("The DipoleAnalysisHandler class can be used as a base class for "
"sub-classes which can be used in the initialization of a "
"DipoleEventHandler, where statistics on, eg. total and elastic "
"cross sections, can be collected during the presampling phase.");
}
diff --git a/DIPSY/DipoleEventHandler.cc b/DIPSY/DipoleEventHandler.cc
--- a/DIPSY/DipoleEventHandler.cc
+++ b/DIPSY/DipoleEventHandler.cc
@@ -1,817 +1,818 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the DipoleEventHandler class.
//
#include "DipoleEventHandler.h"
#include "SimpleProtonState.h"
#include "PhotonDipoleState.h"
#include "Parton.h"
#include "OldStyleEmitter.h"
#include "ThePEG/Interface/Switch.h"
#include "PT1DEmitter.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Repository/CurrentGenerator.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Handlers/LuminosityFunction.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/RefVector.h"
#include "ThePEG/Config/algorithm.h"
#include "gsl/gsl_sf_bessel.h"
#include "ThePEG/Utilities/Current.h"
#include "ThePEG/Cuts/Cuts.h"
#include "ThePEG/PDF/PartonExtractor.h"
#include "ThePEG/Utilities/Debug.h"
#include "ThePEG/Utilities/DebugItem.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "CPUTimer.h"
#include <iostream>
#include <fstream>
using namespace DIPSY;
DipoleEventHandler::DipoleEventHandler()
: EventHandler(false), theNColours(9), theRMax(3.5*InvGeV),
theBaryonSize(0.0*InvGeV),
theCoherenceRange(0.5*InvGeV), theEffectivePartonMode(0), theCollisionType(0),
doShowHistory(false), theLambdaQCD(0.22*GeV), theNF(0),
theFixedAlphaS(0.0), theExternalAlphaS(ASPtr()),
theWFR(WaveFunctionPtr()), theWFL(WaveFunctionPtr()),
theBGen(ImpactParameterGeneratorPtr()), theYFrame(0.5),
thePreSamples(1000), thePreSampleL(1), thePreSampleR(1), thePreSampleB(1),
theXSecFn(DipoleXSecPtr()), theEmitter(EmitterPtr()),
theSwinger(SwingerPtr()) {}
DipoleEventHandler::~DipoleEventHandler() {}
IBPtr DipoleEventHandler::clone() const {
return new_ptr(*this);
}
IBPtr DipoleEventHandler::fullclone() const {
return new_ptr(*this);
}
double DipoleEventHandler::elapsed() {
static long last = 0;
long el = clock() - last;
last += el;
return double(el)*0.000001;
}
void DipoleEventHandler::presample() {
//redirect diffractive runs, as the cross section calculation
//then requires more than a single loop over collisions.
if ( collisionType() == 1 ) return diffractivePresample();
//Set up before the loop
Current<DipoleEventHandler> current(this);
for_each(analyses, mem_fun(&DipoleAnalysisHandler::initialize));
CrossSection xmax = 0.0*picobarn;
CrossSection xnmax = 0.0*picobarn;
elapsed();
generator()->log()
<< endl << "Starting DIPSY run at CoM energy "
<< lumiFn().maximumCMEnergy()/GeV << " GeV" << endl;
//Loop over collisions
for ( int i = 0, N = preSamples(); i < N; ++i ) {
//Setup before collision. Energy, jacobian, luminosity.
Energy W = lumiFn().maximumCMEnergy();
double jac = 1.0;
pair<double,double> ll(1.0, 1.0);
if ( int ndim = lumiFn().nDim(make_pair(WFL().particle(), WFR().particle())) ) {
vector<double> r = UseRandom::rndvec(ndim);
ll = lumiFn().generateLL(&(r[0]), jac);
W *= exp(-0.5*(ll.first + ll.second));
}
//Find the p+ (or p-) of each state.
Energy2 a = WFL().m2() - WFR().m2() + sqr(W);
Energy PL = (a + sqrt(sqr(a) - WFL().m2()*sqr(W)))*0.5/W;
a = WFR().m2() - WFL().m2() + sqr(W);
Energy PR = (a + sqrt(sqr(a) - WFR().m2()*sqr(W)))*0.5/W;
//Create the dipole states and impact parameters.
vector<DipoleStatePtr> vl(preSampleL());
vector<DipoleStatePtr> vr(preSampleR());
vector<ImpactParameters> vb(preSampleB());
vector< vector< vector<double> > >
probs(preSampleL(),
vector< vector<double> >(preSampleR(), vector<double>(preSampleB(), 0.0)));
// Setup a number of left- and right-moving states
double highYL = 0.0;
for ( int il = 0; il < preSampleL(); ++il ) {
DipoleStatePtr dl = WFL().generate(*this, PL);
vl[il] = dl;
dl->collidingEnergy(PR);
highYL += dl->highestY();
}
double highYR = 0.0;
for ( int ir = 0; ir < preSampleR(); ++ir ) {
DipoleStatePtr dr = WFR().generate(*this, PR);
vr[ir] = dr;
dr->collidingEnergy(PL);
highYR += dr->highestY();
}
// Evolve the states
double y0 = interactionFrame(highYL/double(preSampleL()), -highYR/double(preSampleR()));
for ( int il = 0; il < preSampleL(); ++il ) {
vl[il]->evolve(vl[il]->lowestY(), y0);
vl[il]->unifyColourSystems();
}
for ( int ir = 0; ir < preSampleR(); ++ir ) {
vr[ir]->evolve(vr[ir]->lowestY(), -y0);
vr[ir]->unifyColourSystems();
}
for ( int ib = 0; ib < preSampleB(); ++ib ) {
ImpactParameters b = bGen().generate();
vb[ib] = b;
}
for ( int il = 0; il < preSampleL(); ++il )
for ( int ir = 0; ir < preSampleR(); ++ir )
for ( int ib = 0; ib < preSampleB(); ++ib ) {
DipoleStatePtr dl =vl[il];
DipoleStatePtr dr =vr[ir];
ImpactParameters b = vb[ib];
//Calculate interaction probability, and apply all the weights
double prob = xSecFn().sumf(*dr, *dl, b);
probs[il][ir][ib] = prob;
CrossSection weight = sqr(hbarc)*dr->weight()*dl->weight()*b.weight()*jac;
//This is the contribution to the non-diffractive
//cross section 1 - exp(-2(amp)^2)
CrossSection x = weight*xSecFn().unitarize(2.0*prob);
if ( x > xmax ) {
xnmax = xmax;
xmax = x;
} else
xnmax = max(x, xnmax);
//Call the analysis (which calculates cross sections)
for ( int i = 0, N = analyses.size(); i < N; ++i )
analyses[i]->analyze(*dr, *dl, b, xSecFn(), prob, weight);
}
// Call the analysis (which calculates cross sections) for all
// systems and impact parameters.
for ( int i = 0, N = analyses.size(); i < N; ++i )
analyses[i]->analyze(vr, vl, vb, xSecFn(), probs, jac);
}
//Write output (also from the called analyses) to log file.
if ( preSamples() > 0 ) {
generator()->log()
<< "Presampled " << preSamples() << " collisions ("
<< elapsed()/max(preSamples(),0) << " seconds per collisions)" << endl
<< "Maximum cross section: "
<< ouniterr(xmax, xmax-xnmax, nanobarn) << " nb." <<endl;
for_each(analyses,
bind2nd(mem_fun(&DipoleAnalysisHandler::finalize),
preSamples()*preSampleL()*preSampleR()*preSampleB()));
generator()->log() << endl;
}
stats = XSecStat(xmax > 0.0*nanobarn? xmax: 1.0*millibarn);
}
void DipoleEventHandler::diffractivePresample() {
//Setup before
Current<DipoleEventHandler> current(this);
for_each(analyses, mem_fun(&DipoleAnalysisHandler::initialize));
CrossSection xmax = 0.0*picobarn;
CrossSection xnmax = 0.0*picobarn;
elapsed();
generator()->log()
<< endl << "Starting Diffractive DIPSY run at CoM energy "
<< lumiFn().maximumCMEnergy()/GeV << " GeV" << endl;
Energy W = lumiFn().maximumCMEnergy();
double jac = 1.0;
pair<double,double> ll(1.0, 1.0);
//Create the starting states from their wavefunction.
if ( int ndim = lumiFn().nDim(make_pair(WFL().particle(), WFR().particle())) ) {
vector<double> r = UseRandom::rndvec(ndim);
ll = lumiFn().generateLL(&(r[0]), jac);
W *= exp(-0.5*(ll.first + ll.second));
}
//Calculate the energy of each incoming state in this frame.
Energy2 a = WFL().m2() - WFR().m2() + sqr(W);
Energy PL = (a + sqrt(sqr(a) - WFL().m2()*sqr(W)))*0.5/W;
a = WFR().m2() - WFL().m2() + sqr(W);
Energy PR = (a + sqrt(sqr(a) - WFR().m2()*sqr(W)))*0.5/W;
//Set up rapidity intervals to evolve over.
double y0 = interactionFrame(-log(PL/sqrt(abs(WFL().m2()))), log(PR/sqrt(abs(WFR().m2()))));
//Pre-generate the virtual cascade, ie the ones from the
//elastic side (right side by default).
vector<DipoleStatePtr> virtualCascades;
for ( int i = 0, N = preSamples(); i < N; i ++ ) {
DipoleStatePtr virt = WFR().generate(*this, PR);
virt->collidingEnergy(PL);
virt->evolve(virt->lowestY(), -y0);
virtualCascades.push_back(virt);
}
CrossSection sigmaSD = ZERO;
QTY<4,0,0>::Type sigmaSD2 = ZERO;
//Now run main loop over the real (excited in final state) cascades.
for ( int i = 0, N = preSamples(); i < N; ++i ) {
DipoleStatePtr dl = WFL().generate(*this, PL);
dl->collidingEnergy(PR);
dl->evolve(dl->lowestY(), y0);
ImpactParameters b = bGen().generate();
double sum = 0.0;
double sumWeights = 0.0;
//Loop over the pregenerated virtual elastic
for ( int j = 0; j < N; j ++ ) {
double amp = xSecFn().unitarize(xSecFn().sumf(*virtualCascades[j], *dl, b));
sum += amp*virtualCascades[j]->weight();
sumWeights += virtualCascades[j]->weight();
}
double average = sum/sumWeights;
//Take statistics on inclusive single diffractive cross section.
CrossSection weight = sqr(hbarc)*dl->weight()*b.weight()*jac;
CrossSection x = weight*average;
sigmaSD += weight*sqr(average);
sigmaSD2 += sqr(weight*sqr(average));
if ( x > xmax ) {
xnmax = xmax;
xmax = x;
} else
xnmax = max(x, xnmax);
//Pass on to analysers.
for ( int j = 0, M = analyses.size(); j < M; ++j )
analyses[j]->analyze(*WFR().generate(*this, PR), *dl, b, xSecFn(), average, weight);
}
//Output results to log file.
if ( preSamples() > 0 ) {
sigmaSD /= preSamples();
sigmaSD2 /= preSamples();
//Estimate error from the fluctuations.
CrossSection err = sqrt((sigmaSD2 - sqr(sigmaSD))/preSamples());
generator()->log()
<< "Presampled " << preSamples() << " real cascades, collided with "
<< preSamples() << " virtual cascades ("
<< elapsed()/max(preSamples(),0) << " seconds per real cascade)" << endl
<< "Maximum cross section: "
<< ouniterr(xmax, xmax-xnmax, nanobarn) << " nb." <<endl
<< "Integrated single diffractive cross section up to y = " << y0
<< " is " << ouniterr(sigmaSD, err, nanobarn) << " nb." <<endl;
for_each(analyses,
bind2nd(mem_fun(&DipoleAnalysisHandler::finalize), preSamples()));
generator()->log() << endl;
}
stats = XSecStat(xmax > 0.0*nanobarn? xmax: 1.0*millibarn);
}
void DipoleEventHandler::initialize() {
Current<DipoleEventHandler> current(this);
theWFL->initialize(*this);
theWFR->initialize(*this);
}
EventPtr DipoleEventHandler::generateEvent() {
//Redirect diffractive events.
if ( collisionType() == 1 ) return generateDiffractiveEvent();
while ( true ) {
Current<DipoleEventHandler> current(this);
//Set up energy, jacobians and wavefunctions.
Energy W = lumiFn().maximumCMEnergy();
double jac = 1.0;
pair<double,double> ll(1.0, 1.0);
if ( int ndim = lumiFn().nDim(make_pair(WFL().particle(), WFR().particle())) ) {
vector<double> r = UseRandom::rndvec(ndim);
ll = lumiFn().generateLL(&(r[0]), jac);
}
//Find lightcone momenta.
Energy2 a = WFL().m2() - WFR().m2() + sqr(W);
Energy PL = (a + sqrt(sqr(a) - 4.0*WFL().m2()*sqr(W)))*0.5/W;
a = WFR().m2() - WFL().m2() + sqr(W);
Energy PR = (a + sqrt(sqr(a) - 4.0*WFR().m2()*sqr(W)))*0.5/W;
PPair inc(WFL().particle()->produceParticle(lightCone(PL, WFL().m2()/PL)),
WFR().particle()->produceParticle(lightCone(WFR().m2()/PR, PR)));
LorentzRotation cmboost =
lumiFn().getBoost()*LorentzRotation(0.0, 0.0, tanh(0.5*(ll.second - ll.first)));
inc.first->transform(cmboost);
inc.second->transform(cmboost);
//Create dipole states.
DipoleStatePtr dr = WFR().generate(*this, PR);
DipoleStatePtr dl = WFL().generate(*this, PL);
//in some settings, the states need to know about the
//energy of the other state.
dr->collidingEnergy(PL);
dl->collidingEnergy(PR);
double y0 = interactionFrame(dl->highestY(), -dr->highestY());
dr->evolve(dr->lowestY(), -y0);
dr->unifyColourSystems();
dl->evolve(dl->lowestY(), y0);
dl->unifyColourSystems();
// This generates the impact parameter depending on the position
//of the partons. Intention was to generate high-pt events more
//often by selecting a b such that two partons would end up
//very close to each other more often. Should work in theory, but
//didn't make as big difference as hoped, maybe due to too many
//of the high pTs coming from the cascade.
// vector<pair<Parton::Point, InvEnergy> > points1 = dl->points();
// vector<pair<Parton::Point, InvEnergy> > points2 = dr->points();
// ImpactParameters b = bGen().generateDynamic(points1, points2);
//Standard impact parameter generation.
ImpactParameters b = bGen().generate();
inc.first->setVertex
(LorentzPoint(hbarc*b.bVec().x()/2, hbarc*b.bVec().y()/2, ZERO, ZERO));
inc.second->setVertex
(LorentzPoint(-hbarc*b.bVec().x()/2, -hbarc*b.bVec().y()/2, ZERO, ZERO));
currentEvent(new_ptr(Event(inc, this, generator()->runName(),
generator()->currentEventNumber(), 1.0)));
currentCollision(new_ptr(Collision(inc, currentEvent(), this)));
if ( currentEvent() ) currentEvent()->addCollision(currentCollision());
currentStep(new_ptr(Step(currentCollision())));
currentCollision()->addStep(currentStep());
double genweight = sqr(hbarc)*dr->weight()*dl->weight()*b.weight()*jac/
stats.maxXSec();
//Pass to filler. This is where the final state is decided.
double prob = eventFiller().fill(*currentStep(), *this, inc, *dl, *dr, b);
double weight = prob*genweight;
stats.select(weight);
currentEvent()->weight(weight);
if ( weight <= 0.0 ) continue;
stats.accept();
try {
initGroups();
continueCollision();
return currentEvent();
}
catch (Veto) {
stats.reject(weight);
}
catch (Stop) {
break;
}
catch (Exception &) {
stats.reject(weight);
throw;
}
}
return currentEvent();
}
EventPtr DipoleEventHandler::generateDiffractiveEvent() {
//Very similar to generateEvent.
while ( true ) {
//Same setup as in the non-diffractive case.
Current<DipoleEventHandler> current(this);
Energy W = lumiFn().maximumCMEnergy();
double jac = 1.0;
pair<double,double> ll(1.0, 1.0);
if ( int ndim = lumiFn().nDim(make_pair(WFL().particle(), WFR().particle())) ) {
vector<double> r = UseRandom::rndvec(ndim);
ll = lumiFn().generateLL(&(r[0]), jac);
}
Energy2 a = WFL().m2() - WFR().m2() + sqr(W);
Energy PL = (a + sqrt(sqr(a) - 4.0*WFL().m2()*sqr(W)))*0.5/W;
a = WFR().m2() - WFL().m2() + sqr(W);
Energy PR = (a + sqrt(sqr(a) - 4.0*WFR().m2()*sqr(W)))*0.5/W;
PPair inc(WFL().particle()->produceParticle(lightCone(PL, WFL().m2()/PL)),
WFR().particle()->produceParticle(lightCone(WFL().m2()/PR, PR)));
LorentzRotation cmboost =
lumiFn().getBoost()*LorentzRotation(0.0, 0.0, tanh(0.5*(ll.second - ll.first)));
inc.first->transform(cmboost);
inc.second->transform(cmboost);
//create real excited valence. Evolution is done in diffFill.
DipoleStatePtr dr = WFL().generate(*this, PL);
//create elastic
DipoleStatePtr de = WFR().generate(*this, PR);
ImpactParameters b = bGen().generate();
inc.first->setVertex
(LorentzPoint(hbarc*b.bVec().x()/2, hbarc*b.bVec().y()/2, ZERO, ZERO));
inc.second->setVertex
(LorentzPoint(-hbarc*b.bVec().x()/2, -hbarc*b.bVec().y()/2, ZERO, ZERO));
currentEvent(new_ptr(Event(inc, this, generator()->runName(),
generator()->currentEventNumber(), 1.0)));
currentCollision(new_ptr(Collision(inc, currentEvent(), this)));
if ( currentEvent() ) currentEvent()->addCollision(currentCollision());
currentStep(new_ptr(Step(currentCollision())));
currentCollision()->addStep(currentStep());
double genweight = sqr(hbarc)*dr->weight()*de->weight()*b.weight()*jac/
stats.maxXSec();
//Call filler, which will be redirected to diffractive version.
double prob = eventFiller().fill(*currentStep(), *this, inc, *dr, *de, b);
double weight = prob*genweight;
if ( weight <= 0.0 ) continue;
if ( isnan(weight) ) {
continue;
}
stats.select(weight);
currentEvent()->weight(weight);
stats.accept();
try {
initGroups();
continueCollision();
return currentEvent();
}
catch (Veto) {
stats.reject(weight);
}
catch (Stop) {
break;
}
catch (Exception &) {
stats.reject(weight);
throw;
}
}
return currentEvent();
}
CrossSection DipoleEventHandler::integratedXSec() const {
return stats.xSec();
}
CrossSection DipoleEventHandler::integratedXSecErr() const {
return stats.xSecErr();
}
CrossSection DipoleEventHandler::maxXSec() const {
return stats.maxXSec();
}
CrossSection DipoleEventHandler::histogramScale() const {
return stats.xSec()/stats.sumWeights();
}
void DipoleEventHandler::statistics(ostream & os) const {
string line = "======================================="
"=======================================\n";
if ( stats.accepted() <= 0 ) {
os << line << "No events generated by event handler '" << name() << "'."
<< endl;
return;
}
os << line << "Statistics for event handler \'" << name() << "\':\n"
<< " "
<< "generated number of Cross-section\n"
<< " "
<< " events attempts (nb)\n";
os << line << "Total:" << setw(42) << stats.accepted() << setw(13)
<< stats.attempts() << setw(17)
<< ouniterr(stats.xSec(), stats.xSecErr(), nanobarn)
<< endl << line;
}
void DipoleEventHandler::doinit() throw(InitException) {
Current<DipoleEventHandler> current(this);
EventHandler::doinit();
}
void DipoleEventHandler::dofinish() {
generator()->log() << endl << "Ending DIPSY run at CoM energy "
<< lumiFn().maximumCMEnergy()/GeV << " GeV" << endl;
theEventFiller->finish();
EventHandler::dofinish();
CPUClock::dump(generator()->log());
}
void DipoleEventHandler::doinitrun() {
Current<DipoleEventHandler> current(this);
EventHandler::doinitrun();
theNErr = 0;
for_each(analyses, mem_fun(&DipoleAnalysisHandler::initrun));
if ( theSwinger ) theSwinger->initrun();
theEmitter->initrun();
theBGen->initrun();
theXSecFn->initrun();
theEventFiller->initrun();
theWFL->initrun();
theWFR->initrun();
if ( externalAlphaS() ) externalAlphaS()->initrun();
presample();
// Fix up a dummy XComb object
Energy emax = lumiFn().maximumCMEnergy();
cuts()->initialize(sqr(emax), 0.0);
cPDPair incoming = make_pair(WFL().particle(), WFR().particle());
PartonPairVec bins = partonExtractor()->getPartons(emax, incoming, *cuts());
theLastXComb = new_ptr(XComb(emax, incoming, this, partonExtractor(),
tCascHdlPtr(), bins[0], cuts()));
theLastXComb->lastSHat(sqr(emax));
theLastXComb->lastY(0.0);
theLastXComb->lastP1P2(make_pair(0.0, 0.0));
theLastXComb->lastL1L2(make_pair(0.0, 0.0));
theLastXComb->lastX1X2(make_pair(1.0, 1.0));
theLastXComb->lastScale(sqr(emax));
theLastXComb->lastAlphaS(1.0);
theLastXComb->lastAlphaEM(1.0/137.0);
}
void DipoleEventHandler::rebind(const TranslationMap & trans) throw(RebindException) {
// dummy = trans.translate(dummy);
EventHandler::rebind(trans);
}
IVector DipoleEventHandler::getReferences() {
IVector ret = EventHandler::getReferences();
// ret.push_back(dummy);
return ret;
}
double DipoleEventHandler::alphaS(InvEnergy r) const {
if ( fixedAlphaS() > 0.0 )
return fixedAlphaS();
else if ( LambdaQCD() > 0.0*GeV && LambdaQCD() < 2.0/rMax() )
return 6.0*Constants::pi/((33.0 - 2.0*nF())*
log(2.0/(min(r,rMax())*LambdaQCD())));
else if ( externalAlphaS() )
return externalAlphaS()->value(sqr(2.0/min(r,rMax())), SM());
else
return SM().alphaS(sqr(2.0/min(r,rMax())));
}
double DipoleEventHandler::interactionFrame(double ymin, double ymax) const {
double y0 = ymin + yFrame()*(ymax - ymin);
if ( y0 > ymax ) y0 = max(ymin, ymax + (1.0 - yFrame()));
else if ( y0 < ymin ) y0 = min(ymax, ymin + yFrame());
return y0;
}
void DipoleEventHandler::persistentOutput(PersistentOStream & os) const {
os << theNColours << ounit(theRMax, InvGeV) << ounit(theBaryonSize, InvGeV)
<< ounit(theCoherenceRange, InvGeV)
<< theEffectivePartonMode << theCollisionType << doShowHistory
<< ounit(theLambdaQCD, GeV) << theNF << theFixedAlphaS << theExternalAlphaS
<< theWFR << theWFL << theBGen << theYFrame << thePreSamples << thePreSampleL
<< thePreSampleR << thePreSampleB << theXSecFn << theEmitter << theSwinger
<< theEventFiller << analyses << stats;
}
void DipoleEventHandler::persistentInput(PersistentIStream & is, int) {
is >> theNColours >> iunit(theRMax, InvGeV) >> iunit(theBaryonSize, InvGeV)
>> iunit(theCoherenceRange, InvGeV)
>> theEffectivePartonMode >> theCollisionType >> doShowHistory
>> iunit(theLambdaQCD, GeV) >> theNF >> theFixedAlphaS >> theExternalAlphaS
>> theWFR >> theWFL >> theBGen >> theYFrame >> thePreSamples >> thePreSampleL
>> thePreSampleR >> thePreSampleB >> theXSecFn >> theEmitter >> theSwinger
>> theEventFiller >> analyses >> stats;
}
// Static variable needed for the type description system in ThePEG.
#include "ThePEG/Utilities/DescribeClass.h"
DescribeClass<DipoleEventHandler,EventHandler>
- describeDIPSYDipoleEventHandler("DIPSY::DipoleEventHandler", "libDIPSY.so");
+ describeDIPSYDipoleEventHandler("DIPSY::DipoleEventHandler",
+ "libAriadne5.so libDIPSY.so");
void DipoleEventHandler::Init() {
static ClassDocumentation<DipoleEventHandler> documentation
("The DipoleEventHandler is a special EventHandler capable of generating "
"minimum-bias events using the Lund version of the Mueller dipole model.");
static Parameter<DipoleEventHandler,int> interfaceNColours
("NColours",
"The number of different colour indices in the swing mechanism. Should be "
"\\f$N_c^2\\f$ but can be varied to investigate swing effects.",
&DipoleEventHandler::theNColours, 9, 3, 0,
true, false, Interface::lowerlim);
static Parameter<DipoleEventHandler,InvEnergy> interfaceRMax
("RMax",
"The general hadronic size in units of inverse GeV.",
&DipoleEventHandler::theRMax, InvGeV, 3.5*InvGeV, 0.0*InvGeV, 0*InvGeV,
true, false, Interface::lowerlim);
static Parameter<DipoleEventHandler,InvEnergy> interfaceCoherenceRange
("CoherenceRange",
"The maximum range at which partons are allowed to emit coherently."
"This is also used as maximum range in the DGLAP suppression",
&DipoleEventHandler::theCoherenceRange, InvGeV, 0.5*InvGeV, 0.0*InvGeV, 0*InvGeV,
true, false, Interface::lowerlim);
static Switch<DipoleEventHandler,int> interfaceEffectivePartonMode
("EffectivePartonMode",
"How the partons are grouped inteo effective partons.",
&DipoleEventHandler::theEffectivePartonMode, 0, true, false);
static SwitchOption interfaceEffectivePartonModeColours
(interfaceEffectivePartonMode,
"Colours",
"Groups with colour neighbours. Makes more sence since the "
"colour flow determines how the emissions are made, but the "
"swing makes this mode not always group up recoiling partons, "
"which can mess up availible phase space and ordering. "
"This is default.",
0);
static SwitchOption interfaceEffectivePartonModeFastColours
(interfaceEffectivePartonMode,
"FastColours",
"Groups with colour neighbours as for the \"Colour\" option, "
"but speed up the generation by caching different ranges for "
"the same parton.",
2);
static SwitchOption interfaceEffectivePartonModeFastColours2
(interfaceEffectivePartonMode,
"FastColours2",
"Groups with colour neighbours as for the \"FastColour\" option, "
"but speed up the generation by caching different ranges for "
"the same parton.",
3);
static SwitchOption interfaceEffectivePartonModeRelatives
(interfaceEffectivePartonMode,
"Relatives",
"Groups with parents and childs. Always pairs up with the "
"recoiling pt, and should get the phase space and ordering "
"correct, but makes the emissions depend on the history"
", not only current state.",
1);
static Switch<DipoleEventHandler,int> interfaceCollisionType
("CollisionType",
"What type of collison.",
&DipoleEventHandler::theCollisionType, 0, true, false);
static SwitchOption interfaceCollisionTypeNonDiffractive
(interfaceCollisionType,
"NonDiffractive",
"Should be self explanatory. :P",
0);
static SwitchOption interfaceTypeSingleDiffractive
(interfaceCollisionType,
"SingleDiffractive",
"Should be self explanatory. :P",
1);
static Parameter<DipoleEventHandler,bool> interfaceShowHistory
("ShowHistory",
"If the history of every event should be studied manually."
"Note that only final state events get studied, not the presamples.",
&DipoleEventHandler::doShowHistory, false, false, false,
true, false, Interface::lowerlim);
static Parameter<DipoleEventHandler,Energy> interfaceLambdaQCD
("LambdaQCD",
"The value of \\f$\\Lambda_{QCD}\\f$ to be used in the running coupling. "
"If zero, the <interface>AlphaS</interface> object will be used for the "
"coupling instead.",
&DipoleEventHandler::theLambdaQCD, GeV, 0.22*GeV, 0.0*GeV, 0*GeV,
true, false, Interface::lowerlim);
static Parameter<DipoleEventHandler,double> interfaceFixedAlphaS
("FixedAlphaS",
"The value of the constant coupling. If zero, a running coupling is "
"assumed.",
&DipoleEventHandler::theFixedAlphaS, 0.0, 0.0, 0,
true, false, Interface::lowerlim);
static Reference<DipoleEventHandler,AlphaSBase> interfaceExternalAlphaS
("ExternalAlphaS",
"An external \\f$\\alpha_S\\f$ object to be used if "
"<interface>LambdaQCD</interface> is zero. If null the object "
"specified in the overall StandardModel object will be used insted.",
&DipoleEventHandler::theExternalAlphaS, true, false, true, true, false);
static Parameter<DipoleEventHandler,int> interfaceNF
("NF",
"The number of flavours to be used in the running coupling. Not active "
"if an external running coupling (<interface>ExternalAlphaS</interface> "
"is used.",
&DipoleEventHandler::theNF, 3, 1, 0,
true, false, Interface::lowerlim);
static Reference<DipoleEventHandler,WaveFunction> interfaceWFR
("WFR",
"The wave function of the incoming particle along the positive z-axis.",
&DipoleEventHandler::theWFR, true, false, true, false, false);
static Reference<DipoleEventHandler,WaveFunction> interfaceWFL
("WFL",
"The wave function of the incoming particle along the negative z-axis.",
&DipoleEventHandler::theWFL, true, false, true, false, false);
static Parameter<DipoleEventHandler,double> interfaceYFrame
("YFrametest",
"Indicate in which frame the dipole systems should collide. A value of "
"0.5 means that both systems will be evolved an equal rapidity distance. "
"0.0 (1.0) means that the right(left)-moving system will not be evolved "
"at all while the left(right)-moving system will be evolved as much as "
"possible. A value larger than 1.0 (less than 0.0) means the right-(left-)moving "
"system will be evolved a fixed rapidity interval YFrametest - 1 (-YFrametest)",
&DipoleEventHandler::theYFrame, 0.5, 0.0, 1.0,
true, false, Interface::nolimits);
static Parameter<DipoleEventHandler,int> interfacePreSamples
("PreSamples",
"The number of collisions to analyze in the presampling.",
&DipoleEventHandler::thePreSamples, 1000, 0, 0,
true, false, Interface::lowerlim);
static Parameter<DipoleEventHandler,int> interfacePreSampleL
("PreSampleL",
"The number of left-moving systems to generate for each presample.",
&DipoleEventHandler::thePreSampleL, 1, 1, 0,
true, false, Interface::lowerlim);
static Parameter<DipoleEventHandler,int> interfacePreSampleR
("PreSampleR",
"The number of right-moving systems to generate for each presample.",
&DipoleEventHandler::thePreSampleR, 1, 1, 0,
true, false, Interface::lowerlim);
static Parameter<DipoleEventHandler,int> interfacePreSampleB
("PreSampleB",
"The number ofimpact parameters to generate for each presample.",
&DipoleEventHandler::thePreSampleB, 1, 1, 0,
true, false, Interface::lowerlim);
static Reference<DipoleEventHandler,DipoleXSec> interfaceXSecFn
("XSecFn",
"The object responsible for calculating the cross section for two "
"colliding dipole systems.",
&DipoleEventHandler::theXSecFn, true, false, true, false, false);
static Reference<DipoleEventHandler,ImpactParameterGenerator> interfaceBGen
("BGen",
"The object responsible for generating the impact parameters.",
&DipoleEventHandler::theBGen, true, false, true, false, false);
static Reference<DipoleEventHandler,Emitter> interfaceEmitter
("Emitter",
"The object responsible for generating and performing dipole emissions "
"of gluons.",
&DipoleEventHandler::theEmitter, true, false, true, false, false);
static Reference<DipoleEventHandler,Swinger> interfaceSwinger
("Swinger",
"The object responsible for generating and performing dipole swings.",
&DipoleEventHandler::theSwinger, true, false, true, true, false);
static Reference<DipoleEventHandler,EventFiller> interfaceEventFiller
("EventFiller",
"The object responsible for filling an event with final state gluons.",
&DipoleEventHandler::theEventFiller, true, false, true, false, false);
static RefVector<DipoleEventHandler,DipoleAnalysisHandler>
interfaceAnalysisHandlers
("AnalysisHandlers",
"A list of analysis to be performed in the presample phase.",
&DipoleEventHandler::analyses, -1, true, false, true, false, false);
static Parameter<DipoleEventHandler,InvEnergy> interfaceBaryonSize
("BaryonSize",
"The typical size of a baryon to be used by wave functions not "
"defining their own. If zero, <interface>RMax</interface> will "
"be used instead.",
&DipoleEventHandler::theBaryonSize, InvGeV, 0.0*InvGeV, 0.0*InvGeV, 0*InvGeV,
true, false, Interface::lowerlim);
}
diff --git a/DIPSY/DipoleState.cc b/DIPSY/DipoleState.cc
--- a/DIPSY/DipoleState.cc
+++ b/DIPSY/DipoleState.cc
@@ -1,1411 +1,1415 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the DipoleState class.
//
#include "DipoleState.h"
#include "DipoleEventHandler.h"
#include "EventFiller.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Repository/CurrentGenerator.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Utilities/Current.h"
#include "ThePEG/Utilities/Throw.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Utilities/Debug.h"
#include "ThePEG/Utilities/MaxCmp.h"
#include "ThePEG/Utilities/ObjectIndexer.h"
#include "ThePEG/Utilities/UtilityBase.h"
#include "ThePEG/Utilities/SimplePhaseSpace.h"
#include "ParticleInfo.h"
#include "CPUTimer.h"
#include <stdio.h>
#include <iostream>
#include <fstream>
using namespace DIPSY;
DipoleState::DipoleState(const DipoleState & x)
: thePlus(x.thePlus), theMinus(x.theMinus), theMinusDeficit(x.theMinusDeficit),
theHandler(x.theHandler), theInitialDipoles(x.theInitialDipoles),
theSwingCandidates(x.theSwingCandidates),
theTouchedSwingCandidates(x.theTouchedSwingCandidates),
theWFInfo(x.theWFInfo),
theWeight(x.theWeight), doTakeHistory(x.doTakeHistory), theYmax(x.theYmax),
theCollidingEnergy(x.theCollidingEnergy), theHistory(x.theHistory),
allDipoles(x.allDipoles), theIncoming(x.theIncoming), theProducedParticles(x.theProducedParticles) {
for ( set<DipolePtr>::iterator it = allDipoles.begin();
it != allDipoles.end(); ++it )
(**it).theDipoleState = this;
}
DipoleState::~DipoleState() {}
DipoleStatePtr DipoleState::clone() {
DipoleStatePtr copy = new_ptr(*this);
for ( set<DipolePtr>::iterator it = allDipoles.begin();
it != allDipoles.end(); ++it )
(**it).theDipoleState = this;
Dipole::CloneSet toclone;
for ( set<DipolePtr>::iterator it = allDipoles.begin();
it != allDipoles.end(); ++it ) {
toclone.insert(*it);
(**it).fillReferences(toclone);
}
Dipole::TranslationMap trans;
- vector<Ariadne::ClonePtr> clones;
+ vector<Ariadne5::ClonePtr> clones;
for ( Dipole::CloneSet::iterator it = toclone.begin();
it != toclone.end(); ++it )
if ( *it ) clones.push_back(trans[*it] = (**it).clone());
for ( int i = 0, N = clones.size(); i < N; ++i ) {
clones[i]->rebind(trans);
if ( tDipolePtr d = dynamic_ptr_cast<tDipolePtr>(clones[i]) ) {
d->theDipoleState = copy;
}
}
copy->allDipoles.clear();
trans.translate(inserter(copy->allDipoles),
allDipoles.begin(), allDipoles.end());
copy->theInitialDipoles.clear();
trans.translate(inserter(copy->theInitialDipoles),
theInitialDipoles.begin(), theInitialDipoles.end());
for ( int i = 0, N = theSwingCandidates.size(); i < N; ++i ) {
copy->theSwingCandidates =
vector< vector<tDipolePtr> >(theSwingCandidates.size());
trans.translate(inserter(copy->theSwingCandidates[i]),
theSwingCandidates[i].begin(), theSwingCandidates[i].end());
}
for ( int i = 0, N = theTouchedSwingCandidates.size(); i < N; ++i ) {
copy->theTouchedSwingCandidates =
vector< vector<tDipolePtr> >(theTouchedSwingCandidates.size());
trans.translate(inserter(copy->theTouchedSwingCandidates[i]),
theTouchedSwingCandidates[i].begin(),
theTouchedSwingCandidates[i].end());
}
return copy;
}
void DipoleState::sortDipolesFS() {
theSwingCandidates.clear();
theTouchedSwingCandidates.clear();
theSwingCandidates.resize(Current<DipoleEventHandler>()->nColours());
theTouchedSwingCandidates.resize(Current<DipoleEventHandler>()->nColours());
list<DipolePtr> dips = getDipoles();
for ( list<DipolePtr>::const_iterator it = dips.begin(); it != dips.end(); it++ ) {
sortDipoleFS(**it);
}
}
void dummycollect(const Dipole & d, int & ndip, Energy & sump, Energy & summ,
TransverseMomentum & sumpt, set<tcDipolePtr> & dips) {
if ( d.children().first && d.children().second ) {
dummycollect(*d.children().first, ndip, sump, summ, sumpt, dips);
dummycollect(*d.children().second, ndip, sump, summ, sumpt, dips);
} else if ( d.children().first ) {
dummycollect(*d.children().first, ndip, sump, summ, sumpt, dips);
} else if ( d.children().second ) { //dead end??
// dummycollect(*d.children().second, ndip, sump, summ, sumpt, dips);
} else {
++ndip;
dips.insert(&d);
if ( d.partons().first->flavour() == ParticleID::g ) {
sumpt += d.partons().first->pT()/2.0;
sump += d.partons().first->plus()/2.0;
summ += d.partons().first->minus()/2.0;
} else {
sumpt += d.partons().first->pT();
sump += d.partons().first->plus();
summ += d.partons().first->minus();
}
if ( d.partons().second->flavour() == ParticleID::g ) {
sumpt += d.partons().second->pT()/2.0;
sump += d.partons().second->plus()/2.0;
summ += d.partons().second->minus()/2.0;
} else {
sumpt += d.partons().second->pT();
sump += d.partons().second->plus();
summ += d.partons().second->minus();
}
}
}
pair<double,int> DipoleState::lambdaMeasure(Energy2 scale,
FactoryBase::tH1DPtr histlength,
FactoryBase::tH1DPtr histmass) const {
pair<double,int> lam (0.0, 0);
for ( set<DipolePtr>::const_iterator it = allDipoles.begin();
it != allDipoles.end(); it++ ) {
Dipole & d = **it;
if ( !d.children().first && !d.children().second && d.participating() ) {
Energy2 m2 = (d.partons().first->momentum() +
d.partons().second->momentum()).m2();
if ( m2 > ZERO ) lam.first += log(m2/scale);
++lam.second;
if ( histmass && m2 >= ZERO ) histmass->fill(sqrt(m2/GeV2));
if ( histlength )
histlength->fill((d.partons().first->position() -
d.partons().second->position()).pt()*GeV);
}
}
return lam;
}
void DipoleState::sortFSDipoles() {
theSwingCandidates.clear();
theSwingCandidates.resize(Current<DipoleEventHandler>()->nColours());
for ( set<DipolePtr>::const_iterator it = allDipoles.begin();
it != allDipoles.end(); it++ ) {
Dipole & d = **it;
if ( !d.children().first && !d.children().second && d.participating() ) {
if ( ( d.neighbors().first &&
d.neighbors().first->colour() == d.colour() ) ||
( d.neighbors().second &&
d.neighbors().second->colour() == d.colour() ) )
generateColourIndex(&d);
forceAt(theSwingCandidates, (**it).colour()).push_back(*it);
}
}
if ( theSwingCandidates.size() != 0 ) return;
set<tcDipolePtr> dipset1;
TransverseMomentum sumpt;
Energy sump = ZERO;
Energy summ = ZERO;
int ndip = 0;
for ( int ic = 0, Nc = theSwingCandidates.size(); ic < Nc; ++ ic )
for ( int i = 0, N = theSwingCandidates[ic].size(); i < N; ++i ) {
const Dipole & d = *theSwingCandidates[ic][i];
dipset1.insert(&d);
++ndip;
if ( d.partons().first->flavour() == ParticleID::g ) {
sumpt += d.partons().first->pT()/2.0;
sump += d.partons().first->plus()/2.0;
summ += d.partons().first->minus()/2.0;
} else {
sumpt += d.partons().first->pT();
sump += d.partons().first->plus();
summ += d.partons().first->minus();
}
if ( d.partons().second->flavour() == ParticleID::g ) {
sumpt += d.partons().second->pT()/2.0;
sump += d.partons().second->plus()/2.0;
summ += d.partons().second->minus()/2.0;
} else {
sumpt += d.partons().second->pT();
sump += d.partons().second->plus();
summ += d.partons().second->minus();
}
}
cerr << "<DIPSY> total momentum in sortFSDipoles." << endl
<< " Plus: " << sump/GeV << endl
<< " Minus: " << summ/GeV << endl
<< " x: " << sumpt.x()/GeV << endl
<< " y: " << sumpt.y()/GeV << endl
<< " Ndip: " << ndip << " (" << dipset1.size() << ")" << endl;
sump = ZERO;
summ = ZERO;
sumpt = TransverseMomentum();
ndip = 0;
set<tcDipolePtr> dipset2;
for ( int i = 0, N = initialDipoles().size(); i < N; ++i )
dummycollect(*initialDipoles()[i], ndip, sump, summ, sumpt, dipset2);
cerr << "<DIPSY> total momentum in getFSSwinger." << endl
<< " Plus: " << sump/GeV << endl
<< " Minus: " << summ/GeV << endl
<< " x: " << sumpt.x()/GeV << endl
<< " y: " << sumpt.y()/GeV << endl
<< " Ndip: " << ndip << " (" << dipset2.size() << ")" << endl;
set<tcDipolePtr> diffset;
set_difference(dipset1.begin(), dipset1.end(), dipset2.begin(), dipset2.end(),
inserter(diffset));
cerr << " " << diffset.size()
<< " dipoles are in sortFSDipoles but not in getFSSwinger" << endl;
diffset.clear();
set_difference(dipset2.begin(), dipset2.end(), dipset1.begin(), dipset1.end(),
inserter(diffset));
cerr << " " << diffset.size()
<< " dipoles are in getFSSwinger but not in sortFSDipoles" << endl;
}
void DipoleState::sortDipoleFS(Dipole & d){
if(d.children().second && d.children().first) {
sortDipole(*(d.children().first));
sortDipole(*(d.children().second)); }
else if(d.children().first)
sortDipole(*(d.children().first));
else if ( d.children().second );
else if ( !(d.participating()) );
else forceAt(theSwingCandidates, d.colour()).push_back(&d);
}
void DipoleState::sortDipoles() {
theSwingCandidates.clear();
theSwingCandidates.resize(Current<DipoleEventHandler>()->nColours());
theTouchedSwingCandidates.clear();
theTouchedSwingCandidates.resize(Current<DipoleEventHandler>()->nColours());
for ( int i = 0, N = theInitialDipoles.size(); i < N; ++i ) {
sortDipole(*(theInitialDipoles[i]));
}
}
void DipoleState::sortDipole(Dipole & d){
if(d.children().second && d.children().first) {
sortDipole(*(d.children().first));
sortDipole(*(d.children().second)); }
else if(d.children().first)
sortDipole(*(d.children().first));
else if ( d.children().second );
else if ( d.interacted() );
else if ( !(d.participating()) );
else if ( !(d.isOn) );
else {
forceAt(theSwingCandidates, d.colour()).push_back(& d);
if ( !d.hasGen() )
forceAt(theTouchedSwingCandidates, d.colour()).push_back(& d);
}
}
void DipoleState::evolve(double ymin, double ymax) {
save();
for ( set<DipolePtr>::const_iterator it = allDipoles.begin(); it != allDipoles.end(); it++ ) {
(*it)->reset();
(*it)->touch();
}
while ( true ) {
sortDipoles();
tDipolePtr sel = tDipolePtr();
for ( int i = 0, N = initialDipoles().size(); i < N; ++i ) {
tDipolePtr si = initialDipoles()[i]->getEmitter(ymin, ymax);
if ( si && si->generatedY() < ymax && si->hasGen() &&
( !sel || si->generatedY() < sel->generatedY() ))
sel = si;
}
if ( sel ) {
ymin = sel->generatedY();
sel->emit();
save();
continue;
}
break;
}
theYmax = ymax;
}
void DipoleState::swingFS(double ymin, double ymax) {
if ( !handler().swingPtr() ) return;
const Swinger & swinger = handler().swinger();
for ( set<DipolePtr>::const_iterator it = allDipoles.begin();
it != allDipoles.end(); it++ ) {
(*it)->reset();
(*it)->touch();
}
sortFSDipoles();
double miny = ymin;
int lastcol = -1;
while ( true ) {
MinCmp<double, Dipole *> sel;
for ( int ic = 0, Nc = theSwingCandidates.size(); ic < Nc; ++ic ) {
const vector<tDipolePtr> & candidates = swingCandidates(ic);
if ( lastcol < 0 || lastcol == ic )
for ( int i = 0, N = candidates.size(); i < N; ++i ) {
Dipole & d = *candidates[i];
InvEnergy2 saver = d.swingCache;
if ( saver < ZERO )
saver = swinger.swingDistanceFS(*d.partons().first,
*d.partons().second, ymin/GeV2);
if ( d.swingDipole() && d.swingDipole()->touched() ) d.reset();
d.swingCache = saver;
}
for ( int i = 0, N = candidates.size(); i < N - 1; ++i ) {
Dipole & d1 = *candidates[i];
bool safe = d1.hasGen();
if ( lastcol < 0 || lastcol == ic )
for ( int j = i + 1; j < N; ++j ) {
Dipole & d2 = *candidates[j];
if ( safe && !d2.touched() ) continue;
InvEnergy2 c =
swinger.swingDistanceFS(*d1.partons().first,
*d2.partons().second, ymin/GeV2);
InvEnergy2 d =
swinger.swingDistanceFS(*d2.partons().first,
*d1.partons().second, ymin/GeV2);
double R = -log( UseRandom::rnd() );
double amp = swinger.swingAmpFS(d1.swingCache, d2.swingCache, c, d);
double yi = Constants::MaxRapidity;
if ( miny*amp + R < Constants::MaxRapidity*amp ) yi = miny + R/amp;
if ( yi < d1.generatedY() || !d1.hasGen() ) {
d1.swingDipole(&d2);
d1.generatedY(yi);
d1.recoilSwing(false);
}
}
sel(d1.generatedY(), &d1);
d1.untouch();
}
if ( candidates.size() ) candidates.back()->untouch();
}
if ( !sel.index() || sel > ymax ) break;
miny = sel;
lastcol = sel.index()->colour();
swinger.recombineFS(*sel.index());
static DebugItem tupleswing("DIPSY::SwingTuple", 6);
static ofstream swingtuple;
static bool isopen = false;
static long lastevent = 0;
if ( tupleswing ) {
if ( !isopen ) {
string filename = CurrentGenerator::current().filename() + "-swing.tuple";
swingtuple.open(filename.c_str());
isopen = true;
}
if ( lastevent != CurrentGenerator::current().currentEventNumber() ) {
lastevent = CurrentGenerator::current().currentEventNumber();
swingtuple << "# " << lastevent << endl;
}
double lrho = -log10(sqrt(miny));
pair<double,int> lam = lambdaMeasure(0.36*GeV2);
swingtuple << lrho << '\t' << lam.first/lam.second << '\t' << lam.first << endl;
}
}
theYmax = ymax;
}
void DipoleState::restoreNonparticipants() {
for ( int i = 0; i < int(theInitialDipoles.size()); i++ ) {
tPartonPtr p1 = theInitialDipoles[i]->partons().first;
tPartonPtr p2 = theInitialDipoles[i]->partons().second;
tPartonPtr p3;
if ( i != int(theInitialDipoles.size())-1 &&
theInitialDipoles[i+1]->partons().first == p2 )
p3 = theInitialDipoles[i+1]->partons().second;
else if ( i != int(theInitialDipoles.size())-1 &&
theInitialDipoles[i+1]->partons().second == p1 )
p3 = theInitialDipoles[i+1]->partons().first;
else if ( i != 0 && theInitialDipoles[i-1]->partons().first == p2 )
p3 = theInitialDipoles[i-1]->partons().second;
else if ( i != 0 && theInitialDipoles[i-1]->partons().second == p1 )
p3 = theInitialDipoles[i-1]->partons().first;
if ( !(p1->interacted()) &&
!(p2->interacted()) &&
!( p3 && p3->interacted() ) ) {
theInitialDipoles[i]->participating(false);
restoreDipole(p1, p2);
}
else
theInitialDipoles[i]->participating(true);
}
}
bool DipoleState::restoreDipole(PartonPtr p1, PartonPtr p2) {
//there must be dipoles to reconnect.
if ( !p1->dipoles().second || !p2->dipoles().first ) return false;
//if already connect, do nothing
if ( p1->dipoles().second == p2->dipoles().first ) return true;
//if p1 and p2 are connected to different partons, just swing.
if ( p1->dipoles().second->partons().second != p2->dipoles().first->partons().first ) {
p1->dipoles().second->swingDipole(p2->dipoles().first);
p1->dipoles().second->recombine();
return true;
}
//if p1 and p2 are separated by only one parton, then first swing away one of
//the dipoles, then repeat.
else {
sortDipoles();
//if no swing can be found, then leave it.
if ( !forceSwing(p1->dipoles().second->partons().second, 0.0, 0.0) ) return false;
//otherwise go ahead and reconnect the dipoles.
p1->dipoles().second->swingDipole(p2->dipoles().first);
p1->dipoles().second->recombine();
return true;
}
}
void DipoleState::normaliseValenceCharge(int mode) {
if ( mode == 0 ) return;
if ( double(int(theInitialDipoles.size())/3) != double(theInitialDipoles.size())/3.0 ) {
return;
}
if ( mode == 1 ) {
set<pair<tPartonPtr, tPartonPtr> > valencePartons;
for ( int i = 0; i < int(theInitialDipoles.size()); i++) {
tPartonPtr p1 = theInitialDipoles[i]->partons().first;
tPartonPtr p2 = theInitialDipoles[i]->partons().second;
//if there are no dipoles to swing, do nothing
if ( !p1->dipoles().second || !p2->dipoles().first )
continue;
//if already connected, do nothing.
if ( p1->dipoles().second->partons().second == p2 )
continue;
//if connected to the same parton, do nothing.
if ( p1->dipoles().second->partons().second == p2->dipoles().first->partons().first )
continue;
//otherwise swing with 50% prob
if ( UseRandom::rnd() > 0.5 ) {
p1->dipoles().second->swingDipole(p2->dipoles().first);
p1->dipoles().second->recombine();
}
}
}
}
void DipoleState::generateColourIndex(tDipolePtr d) {
int isys = -1;
if ( d->neighbors().first )
isys = d->neighbors().first->colourSystem();
if ( d->neighbors().second ) {
int isys2 = d->neighbors().second->colourSystem();
if ( isys >= 0 && isys2 != isys )
cerr << "Dipole bewteen different colour systems!" << endl;
isys = isys2;
}
do {
d->colour(UseRandom::irnd(handler().nColours()), isys);
} while ( ( d->neighbors().first &&
d->colour() == d->neighbors().first->colour() ) ||
( d->neighbors().second &&
d->colour() == d->neighbors().second->colour() ) );
}
const list<PartonPtr> DipoleState::virtualPartons() const {
list<PartonPtr> partons;
for ( set<DipolePtr>::const_iterator it = allDipoles.begin() ; it != allDipoles.end(); it++ ) {
if ( (*it)->children().first || (*it)->children().second ) continue;
if ( !((*it)->neighbors().first) && !((*it)->partons().first->interacted()) )
if ( !((*it)->partons().first->valence()) )
partons.push_back((*it)->partons().first);
if ( !((*it)->partons().second->interacted()) && !((*it)->partons().second->valence()) )
partons.push_back((*it)->partons().second);
}
return partons;
}
const set< list<PartonPtr> > DipoleState::loops() const {
list<PartonPtr> partonsList = getPartons();
set<PartonPtr> partons;
set< list<PartonPtr> > ret;
for( list<PartonPtr>::const_iterator it = partonsList.begin();
it != partonsList.end(); it++ ) {
partons.insert(*it);
}
//go through all partons and add them to colour chains.
while ( !partons.empty() ) {
list<PartonPtr> loop;
PartonPtr head = *partons.begin();
bool forward = true;
PartonPtr p = head;
//follow the colour flow first in forward direction from head until it comes back to the start
//if a quark is hit, then continue in other direction.
do {
//add at end/start of list depending of if we are moving forward or beckwards in colour
if ( forward ) {
loop.push_back(p);
}
else {
loop.push_front(p);
}
//remove from partons, so we know its added.
//could potentially be better to do this without destroy the dipoleState...
- partons.erase(p);
+ if ( !partons.erase(p) ) {
+ Throw<DipoleConnectionException>()
+ << "DIPSY found inconsistent DipoleState when extracting "
+ "colour singlets!" << Exception::eventerror;
+ }
//move forward in colour if there are more partons, otherwise turn around
if ( forward ) {
if ( p->dipoles().second ) {
p = p->dipoles().second->partons().second;
if ( Debug::level > 5 ) cout << " continue forward to " << p->y() << endl;
}
else {
if ( head->dipoles().first ) {
//continue at other side, going in other direction
p = head->dipoles().first->partons().first;
}
else {
//want to turn around, but "head" is at the other end, so we are done.
p = head;
}
forward = false;
}
}
else {
if ( p->dipoles().first ) {
p = p->dipoles().first->partons().first;
}
else {
break;
}
}
} while ( p!= head );
ret.insert(loop);
}
return ret;
}
const double DipoleState::highestY() const {
MaxCmp<double> ret;
list< PartonPtr > partons = getPartons();
for ( list<PartonPtr>::const_iterator it = partons.begin();
it != partons.end(); it++ ) {
ret((*it)->y());
ret((*it)->y());
}
return ret;
}
const double DipoleState::lowestY() const {
MinCmp<double> ret;
list< PartonPtr > partons = getPartons();
for ( list<PartonPtr>::const_iterator it = partons.begin();
it != partons.end(); it++ ) {
ret((*it)->y());
ret((*it)->y());
}
return ret;
}
const double DipoleState::ymax() const {
return theYmax;
}
const Energy DipoleState::collidingEnergy() const {
return theCollidingEnergy;
}
void DipoleState::collidingEnergy(Energy E) {
theCollidingEnergy = E;
}
bool DipoleState::diagnosis(bool print) const {
bool ok = true;
int activeDipoles = 0;
int partons = 0;
int interactingDips = 0;
Energy plus = 0.0*GeV;
Energy minus = 0.0*GeV;
Energy plusNeeded = 0.0*GeV;
Energy minusNeeded = 0.0*GeV;
Energy plusMissing = 0.0*GeV;
Energy minusMissing = 0.0*GeV;
bool hasQuark = false;
TransverseMomentum totalpT;
Energy maxpT = 0.0*GeV;
InvEnergy dipSize = ZERO;
for(set< DipolePtr >::iterator it = allDipoles.begin();
it != allDipoles.end(); it++) {
if( ((*it)->children().first || (*it)->children().second) )
continue;
activeDipoles++;
dipSize += (*it)->size();
if ( (*it)->DGLAPsafe() ) {
if ( (*it)->neighbors().first &&
(*it)->neighbors().first->size() > (*it)->size() &&
!((*it)->neighbors().first->DGLAPsafe()) )
Throw<DipoleDGLAPSafeException>()
<< "DIPSY found broken DGLAPchain!" << Exception::eventerror;
if ( (*it)->neighbors().second &&
(*it)->neighbors().second->size() > (*it)->size() &&
!((*it)->neighbors().second->DGLAPsafe()) )
Throw<DipoleDGLAPSafeException>()
<< "DIPSY found broken DGLAPchain!" << Exception::eventerror;
}
if ( (*it)->interacted() ) interactingDips++;
if ( ((*it)->neighbors().first &&
(*it)->neighbors().first->children().first) ||
((*it)->neighbors().first &&
(*it)->neighbors().first->children().second) )
Throw<DipoleConnectionException>()
<< "DIPSY found dipole where negiboring dipole has decayed!"
<< Exception::eventerror;
if( (*it)->partons().first->dipoles().second != (*it) )
Throw<DipoleConnectionException>()
<< "DIPSY found dipole where first parton "
<< "doesn't point back at the dipole!" << Exception::eventerror;
if( (*it)->partons().second->dipoles().first != (*it) )
Throw<DipoleConnectionException>()
<< "DIPSY found dipole where second parton "
<< "doesn't point back at the dipole!" << Exception::eventerror;
if ( (*it)->neighbors().first &&
(*it)->neighbors().first->neighbors().second != (*it) )
Throw<DipoleConnectionException>()
<< "DIPSY found dipole where neighbouring dipole "
<< "doesn't point back at the dipole!" << Exception::eventerror;
if ( (*it)->neighbors().second &&
(*it)->neighbors().second->neighbors().first != (*it) )
Throw<DipoleConnectionException>()
<< "DIPSY found dipole where neighbouring dipole "
<< "doesn't point back at the dipole!" << Exception::eventerror;
if ( (*it)->partons().first == (*it)->partons().second )
Throw<DipoleConnectionException>()
<< "DIPSY found dipole looping back to itself!" << Exception::eventerror;
PartonPtr p = (*it)->partons().first;
partons++;
if ( p->dipoles().first && p->dipoles().first->partons().second != p )
Throw<DipoleConnectionException>()
<< "DIPSY found parton where first dipole "
<< "doesn't point back at the parton!" << Exception::eventerror;
if ( p->dipoles().second && p->dipoles().second->partons().first != p )
Throw<DipoleConnectionException>()
<< "DIPSY found parton where second dipole "
<< "doesn't point back at the parton!" << Exception::eventerror;
if ( p->dipoles().first && p->dipoles().second &&
p->dipoles().first == p->dipoles().second )
Throw<DipoleConnectionException>()
<< "DIPSY found parton colour connected to itself!"
<< Exception::eventerror;
if ( p->dipoles().first && (p->dipoles().first->children().first ||
p->dipoles().first->children().second) )
Throw<DipoleConnectionException>()
<< "DIPSY found parton where first dipole has decayed!"
<< Exception::eventerror;
if ( p->dipoles().second && (p->dipoles().second->children().first ||
p->dipoles().second->children().second) )
Throw<DipoleConnectionException>()
<< "DIPSY found parton where second dipole has decayed!"
<< Exception::eventerror;
if ( p->y() < -100.0 || p->y() > 100.0 )
Throw<DipoleKinematicsException>()
<< "DIPSY found parton impossible rapidity!" << Exception::eventerror;
if ( p->plus() < ZERO )
Throw<DipoleKinematicsException>()
<< "DIPSY found parton at oY " << p->oY() << " has negative plus "
<< p->plus()/GeV << "!" << Exception::eventerror;
if ( p->minus() < ZERO )
Throw<DipoleKinematicsException>()
<< "DIPSY found parton at oY " << p->oY() << " has negative minus "
<< p->minus()/GeV << "!" << Exception::eventerror;
totalpT += p->pT();
if ( p->pT().pt() > maxpT ) {
maxpT = p->pT().pt();
if ( maxpT > 1000.0*GeV )
Throw<DipoleKinematicsException>()
<< "DIPSY found parton with very large transverse momentum: "
<< maxpT/GeV << " (p+ = " << p->plus()/GeV << ", p- = "
<< p->minus()/GeV << ", y = " << p->y() << ")" << Exception::warning;
}
if( abs((p->plus()*p->minus() - sqr(p->pT().pt()))/sqr(GeV)) >
0.001*sqr(p->pT().pt())/sqr(GeV) ) {
Throw<DipoleKinematicsException>()
<< "DIPSY found off-shell parton with invariant mass square "
<< (p->plus()*p->minus() - sqr(p->pT().pt()))/sqr(GeV)
<< "!" << Exception::eventerror;
ok = false;
}
if( p->rightMoving() ) {
plus += p->plus();
minusMissing += p->minus();
minusNeeded += p->pT().pt()*exp( p->y() );
}
else {
minus += p->minus();
plusMissing += p->plus();
plusNeeded += p->pT().pt()*exp( -p->y() );
}
if( !((*it)->neighbors().second) ) {
hasQuark = true;
p = (*it)->partons().second;
partons++;
totalpT += p->pT();
if( p->rightMoving() ) {
plus += p->plus();
minusMissing += p->minus();
minusNeeded += p->pT().pt()*exp( p->y() );
}
else {
minus += p->minus();
plusMissing += p->plus();
plusNeeded += p->pT().pt()*exp( -p->y() );
}
}
}
if( totalpT.pt() > 0.00000001*GeV ) {
Throw<DipoleKinematicsException>()
<< "DIPSY found transverse momentum imbalance: " << totalpT.pt()/GeV
<< Exception::warning;
ok = false;
}
Energy acceptableError = 0.1*GeV;
if ( handler().eventFiller().mode() == 1 )
acceptableError = 0.000001*GeV;
if ( abs(plus - thePlus) > 2.0*acceptableError &&
abs(plus + minus + minusMissing + plusMissing - thePlus - theMinus) >
2.0*acceptableError ) {
Throw<DipoleKinematicsException>()
<< "DIPSY found energy non-conservation: "
<< (plus + minus + minusMissing + plusMissing
- thePlus - theMinus)/GeV/2.0 << " GeV" << Exception::warning;
ok = false;
}
if ( isnan(plus/GeV) || isnan(minus/GeV) )
Throw<DipoleKinematicsException>()
<< "DIPSY found parton with nan kinematics!" << Exception::runerror;
if ( print ) {
cout << "------------------ state " << this << " ------------------------------\n";
if (!ok )
cout << "| NOT OK!!!" << endl;
cout << setprecision(10);
cout <<
"| original plus = " << thePlus/GeV << endl <<
"| originl minus = " << theMinus/GeV << endl <<
"| plus = " << plus/GeV << endl <<
"| minus = " << minus/GeV << endl <<
"| missing minus = " << minusMissing/GeV << endl <<
"| needed minus = " << minusNeeded/GeV << endl <<
"| missing plus = " << plusMissing/GeV << endl <<
"| needed plus = " << plusNeeded/GeV << endl <<
"| total plus = " << (plus + plusNeeded - plusMissing)/GeV << endl <<
"| total minus = " << (minus + minusNeeded - minusMissing)/GeV << endl <<
"| total pT = " << "( "<<totalpT.x()/GeV<<", "<<totalpT.y()/GeV<<" )" << endl <<
"| originl enrgy = " << (thePlus + theMinus)/GeV/2.0 << endl <<
"| total energy = " << (plus + minus + minusMissing + plusMissing)/GeV/2.0 << endl <<
"| missing enrgy = " << (plus+minus+minusMissing+plusMissing-thePlus-theMinus)/GeV/2.0 << endl <<
"| allDipoles has " << allDipoles.size() << " dipoles." << endl <<
"| number of active dipoles: " << activeDipoles << endl <<
"| number of partons " << partons << endl <<
"| hasQuark: " << hasQuark << endl <<
"| number of interacting dipoles: " << interactingDips << endl <<
"| max pT : " << maxpT/GeV << endl <<
"| average dipole size: " << GeV*dipSize/double(activeDipoles) << endl;
cout << "----------------------------------------------------------------------\n";
if (ok ) cout << "| Found no errors! :)\n";
else cout << "| STATE NOT OK!! :o\n";
cout << "----------------------------------------------------------------------\n";
}
return ok;
}
bool DipoleState::forceSwing(PartonPtr p, double ymax1, double ymax2) {
DipolePtr d1 = p->dipoles().first;
DipolePtr d2 = p->dipoles().second;
if ( !d1 || !d2 )
cout << "forcing a swing for a parton that doesnt have 2 dipoles!" << endl;
//check for swings of same colour up to ymax1
d1->reset();
d1->touch();
bool foundFirstDipole = d1->forceGenerateRec(ymax1);
d2->reset();
d2->touch();
bool foundSecondDipole = d2->forceGenerateRec(ymax1);
if( foundFirstDipole || foundSecondDipole ) {
if ( !foundFirstDipole )
d2->recombine();
else if ( !foundSecondDipole )
d1->recombine();
else {
if ( d1->generatedY() < d2->generatedY() )
d1->recombine();
else
d2->recombine();
}
return true;
}
//check for swings of other colours up to ymax2
int trueColour = d1->colour();
int trueSys = d1->colourSystem();
for ( int c=0;c < Current<DipoleEventHandler>()->nColours();c++ ) {
d1->colour(c, trueSys);
d1->forceGenerateRec(ymax2);
}
d1->colour(trueColour);
foundFirstDipole = d1->swingDipole();
trueColour = d2->colour();
trueSys = d2->colourSystem();
for ( int c=0;c < Current<DipoleEventHandler>()->nColours();c++ ) {
d2->colour(c, trueSys);
d2->forceGenerateRec(ymax2);
}
d2->colour(trueColour);
foundSecondDipole = d2->swingDipole();
if( foundFirstDipole || foundSecondDipole ) {
if ( !foundFirstDipole )
d2->recombine();
else if ( !foundSecondDipole )
d1->recombine();
else {
if ( d1->generatedY() < d2->generatedY() )
d1->recombine();
else
d2->recombine();
return true;
}
}
return false;
}
DipoleStatePtr DipoleState::merge(DipoleStatePtr otherState) {
//reasign all other dipoles to belong to this state.
for( set< DipolePtr >::iterator it = otherState->allDipoles.begin();
it != otherState->allDipoles.end(); it++ ) {
(*it)->dipoleState(this);
}
//fill up initialDipoles and allDipoles with the other state.
theInitialDipoles.insert(theInitialDipoles.begin(),
otherState->initialDipoles().begin(),
otherState->initialDipoles().end());
theIncoming.insert(otherState->incoming().begin(), otherState->incoming().end());
allDipoles.insert(otherState->allDipoles.begin(),otherState->allDipoles.end());
theProducedParticles.insert(otherState->theProducedParticles.begin(),
otherState->theProducedParticles.end());
//add up the original particles momenta
thePlus += otherState->thePlus;
theMinus += otherState->theMinus;
return this;
}
DipoleStatePtr DipoleState::collide( DipoleStatePtr otherState,
const vector<FList::const_iterator> & sel,
const ImpactParameters & b ) {
//mirror the other state in y
otherState->mirror(0.0);
//move the other state according to the impact parameter
otherState->translate(b);
//reasign all other dipoles to belong to this state.
for( set< DipolePtr >::iterator it = otherState->allDipoles.begin();
it != otherState->allDipoles.end(); it++ ) {
(*it)->dipoleState(this);
}
//fill up initialDipoles and allDipoles with the other state.
theInitialDipoles.insert(theInitialDipoles.begin(),
otherState->initialDipoles().begin(),
otherState->initialDipoles().end());
allDipoles.insert(otherState->allDipoles.begin(),otherState->allDipoles.end());
//decide if each collision in sel is elastic or not, and recouple the non-elastic ones
for( vector< FList::const_iterator>::const_iterator it = sel.begin();
it != sel.end(); it++ ) {
if( (*it)->first.second < 2.0*UseRandom::rnd() ) {
(*it)->second.first->swingDipole( (*it)->second.second );
(*it)->second.first->recombine();
}
}
return this;
}
void DipoleState::mirror(double y0) {
for ( set< DipolePtr >::iterator it = allDipoles.begin();
it != allDipoles.end(); it++) {
if ( !((*it)->children().first || (*it)->children().second) ) {
PartonPtr p = (*it)->partons().first;
p->y( 2.0*y0 - p->y() );
Energy plus = p->plus();
p->plus( p->minus() );
p->minus( plus );
p->rightMoving( !(p->rightMoving()) );
if ( !((*it)->neighbors().second) ) {
PartonPtr p2 = (*it)->partons().second;
p2->y( 2.0*y0 - p2->y() );
p2->plus( p2->pT().pt()*exp(-p2->y()) );
p2->minus( p2->pT().pt()*exp(p2->y()) );
p->rightMoving( !(p->rightMoving()) );
}
}
}
Energy x = thePlus;
thePlus = theMinus;
theMinus = x;
for ( map<PPtr, vector<PartonPtr> >::iterator it = theIncoming.begin();
it != theIncoming.end(); ++it )
it->first->setMomentum(lightCone(it->first->momentum().minus(),
it->first->momentum().plus()));
}
void DipoleState::translate(const ImpactParameters & b) {
for(set< DipolePtr >::iterator it = allDipoles.begin();
it != allDipoles.end(); it++) {
if( !((*it)->children().first || (*it)->children().second) ) {
(*it)->partons().first->position( Parton::Point
((*it)->partons().first->position().x()*cos(b.phi()) +
(*it)->partons().first->position().y()*sin(b.phi()) + b.bVec().x() ,
(*it)->partons().first->position().y()*cos(b.phi()) -
(*it)->partons().first->position().x()*sin(b.phi()) + b.bVec().y() ) );
(*it)->partons().first->pT( b.rotatePT((*it)->partons().first->pT()));
if( !((*it)->neighbors().second) ) {
(*it)->partons().second->position( Parton::Point
((*it)->partons().second->position().x()*cos(b.phi()) +
(*it)->partons().second->position().y()*sin(b.phi()) + b.bVec().x() ,
(*it)->partons().second->position().y()*cos(b.phi()) -
(*it)->partons().second->position().x()*sin(b.phi()) + b.bVec().y() ) );
(*it)->partons().second->pT( b.rotatePT((*it)->partons().second->pT()));
}
}
}
}
void DipoleState::fixValence(Step & step) const {
for ( map<PPtr, vector<PartonPtr> >::const_iterator it = theIncoming.begin();
it != theIncoming.end(); ++it ) {
tcWFInfoPtr wfi = WFInfo::getWFInfo(*it->first);
if ( !wfi ) continue;
PVector valence;
for ( int i = 0, N = it->second.size(); i < N; ++i ) {
valence.push_back(getParticle(it->second[i], true));
if ( !valence.back() ) valence.pop_back();
}
wfi->wf().fixValence(step, it->first, valence);
}
LorentzRotation Rshift = Utilities::boostToCM(step.collision()->incoming());
Utilities::transform(step.particles(), Rshift);
}
LorentzMomentum DipoleState::changeMass(LorentzMomentum p, Energy m, LorentzMomentum ref,
LorentzRotation * Rshift) {
Energy2 s = (p + ref).m2();
LorentzRotation R(0.0, 0.0, -(p.z() + ref.z())/(p.e() + ref.e()));
Energy z = Math::sign(SimplePhaseSpace::getMagnitude(s, ref.mt(), sqrt(sqr(m) + p.perp2())), (R*p).z());
LorentzMomentum pnew(p.x(), p.y(), z, sqrt(sqr(m) + sqr(z) + p.perp2()));
LorentzMomentum refnew(ref.x(), ref.y(), -z, sqrt(sqr(z) + ref.mt2()));
s = (pnew + refnew).m2();
LorentzRotation shift = LorentzRotation(0.0, 0.0, ref.z()/ref.e())*
LorentzRotation(0.0, 0.0, -refnew.z()/refnew.e());
pnew *= shift;
refnew *= shift;
if ( Rshift ) *Rshift = R.boostZ((pnew.z() + ref.z())/(pnew.e() + ref.e()));
return pnew;
}
vector<pair<Parton::Point, InvEnergy> > DipoleState::points() {
list< PartonPtr > partons = getPartons();
vector<pair<Parton::Point, InvEnergy> > ret;
for ( list<PartonPtr>::iterator it = partons.begin(); it != partons.end(); it++) {
InvEnergy r = max((*it)->dipoles().first->size(), (*it)->dipoles().first->size());
ret.push_back(make_pair((*it)->position(), r));
}
return ret;
}
list< PartonPtr > DipoleState::getPartons() const {
list<PartonPtr> partons;
for ( set<DipolePtr>::const_iterator it = allDipoles.begin() ; it != allDipoles.end(); it++ ) {
if ( (*it)->children().first || (*it)->children().second ) continue;
partons.push_back((*it)->partons().first);
if ( !((*it)->neighbors().second) ) //end of chain --> add also right parton
partons.push_back((*it)->partons().second);
}
return partons;
}
list< DipolePtr > DipoleState::getDipoles() const {
list<DipolePtr> dipoles;
for ( set<DipolePtr>::const_iterator it = allDipoles.begin() ; it != allDipoles.end(); it++ ) {
if ( (*it)->children().first || (*it)->children().second ) continue;
dipoles.push_back(*it);
}
return dipoles;
}
void DipoleState::makeOriginal() {
//clear the original dipoles
theInitialDipoles.clear(); //owns the dipoles
theSwingCandidates.clear(); //trancient
theTouchedSwingCandidates.clear(); //trancient
//go through allDipoles and set them to on or off.
for ( set<DipolePtr>::iterator it = allDipoles.begin();
it != allDipoles.end(); it++ ) {
DipolePtr d = *it;
if ( d->children().first || d->children().second ) d->isOn = false;
else d->isOn = true;
}
//go through allDipoles again
for ( set<DipolePtr>::iterator it = allDipoles.begin();
it != allDipoles.end(); it++ ) {
DipolePtr d = *it;
//remove neighbors that are off, both from dipole and parton
if ( d->isOn ) {
if ( d->neighbors().first && !d->neighbors().first->isOn ) {
d->neighbors(make_pair(DipolePtr(), d->neighbors().second));
d->partons().first->dipoles(make_pair(DipolePtr(), d->partons().first->dipoles().second) );
}
if ( d->neighbors().second && !d->neighbors().second->isOn ) {
d->neighbors(make_pair(d->neighbors().first, DipolePtr()));
d->partons().second->dipoles(make_pair(d->partons().second->dipoles().first, DipolePtr()) );
}
}
}
//go through allDipoles again
for ( set<DipolePtr>::iterator it = allDipoles.begin();
it != allDipoles.end(); ) {
DipolePtr d = *it;
//remove all pointers to off dipoles (not needed, as transient pointers)
//insert in original dipoles if the dipole is on.
if ( d->isOn ) {
theInitialDipoles.push_back(d);
d->partons().first->parents() = make_pair(PartonPtr(), PartonPtr());
d->partons().second->parents() = make_pair(PartonPtr(), PartonPtr());
d->partons().first->removeAllChildren();
d->partons().second->removeAllChildren();
d->reset();
it++;
}
//remove the dipole from allDipoles if it is off.
if ( !d->isOn ) {
set<DipolePtr>::iterator jt = it;
it++;
allDipoles.erase(jt);
}
}
//set parton data as if they were valence partons
list<PartonPtr> partons = getPartons();
int i = 0;
for( list<PartonPtr>::iterator it = partons.begin();
it != partons.end(); it++ ) {
PartonPtr p = *it;
p->number(i);
p->ordered(true);
p->valencePlus(p->plus());
p->valencePT(p->pT());
p->oY(p->y());
p->parents(make_pair(PartonPtr(), PartonPtr()));
i++;
}
}
vector<DipoleState::String> DipoleState::strings() {
set< list<PartonPtr> > colourLoops = loops();
vector<DipoleState::String> ret;
for ( set< list<PartonPtr> >::const_iterator loop = colourLoops.begin();
loop != colourLoops.end(); loop++ ) {
DipoleState::String s;
for ( list<PartonPtr>::const_iterator p = (*loop).begin(); p != (*loop).end(); p++ ) {
s.push_back( *p );
}
if ( Debug::level > 5 ) cout << "new string of size " << s.size() << endl;
ret.push_back( s );
}
return ret;
}
//Assume incoming particles massless for now. Valid as long higest pT
//is much larger than the mass.
void DipoleState::balanceMomenta() {
//Sum up how much p-/p+ is needed on the left/right side.
//Assumes that no particles got pushed over to the other side during reabsorbtion.
Energy PlmMissing = 0.0*GeV;
Energy PlmNeeded = 0.0*GeV;
Energy PrpMissing = 0.0*GeV;
Energy PrpNeeded = 0.0*GeV;
Energy Plp = 0.0*GeV;
Energy Prm = 0.0*GeV;
PartonPtr p;
for(set< DipolePtr >::iterator it = allDipoles.begin();
it != allDipoles.end(); it++) {
if( ((*it)->children().first || (*it)->children().second) )
continue;
//Do first parton always
p = (*it)->partons().first;
if( p->rightMoving() ) {
PlmMissing += p->minus();
PlmNeeded += p->pT().pt()*exp( p->y() );
Plp += p->plus();
}
else {
Prm += p->minus();
PrpMissing += p->plus();
PrpNeeded += p->pT().pt()*exp( -p->y() );
}
if( !((*it)->neighbors().second) ) {
//do second parton as well if at the end of a chain
p = (*it)->partons().second;
if( p->rightMoving() ) {
PlmMissing += p->minus();
PlmNeeded += p->pT().pt()*exp( p->y() );
Plp += p->plus();
}
else {
Prm += p->minus();
PrpMissing += p->plus();
PrpNeeded += p->pT().pt()*exp( -p->y() );
}
}
}
Energy PpShuffled = PrpNeeded - PrpMissing;
Energy PmShuffled = PlmNeeded - PlmMissing;
double a = -(1 + PmShuffled/Prm);
double b = -PlmNeeded/Prm;
double c = -(1 + PpShuffled/Plp);
double d = -PrpNeeded/Plp;
double e = (b - d)/c + a;
//how much p+/p- has to be scaled down on left/right side.
double q2 = - e/2 + sqrt( sqr(e)/4 + d*a/c );
double q1 = (d - c*q2)/q2;
if( max(abs(log(q1)),abs(log(q2))) > 0.1 ) {
cout << "yl shifted " << log(q2) << endl <<
"yr shifted " << log(q1) << endl;
}
if ( PlmMissing > Prm ) {
cout << "not enough p- in right state! VETO!" << endl;
}
else if ( PrpMissing > Plp ) {
cout << "not enough p+ in left state! VETO!" << endl;
}
//now shift all the partons in rapidity with ln q1 or ln q2 on left/right side.
for(set< DipolePtr >::iterator it = allDipoles.begin();
it != allDipoles.end(); it++) {
if( ((*it)->children().first || (*it)->children().second) )
continue;
//Do first parton always
p = (*it)->partons().first;
if( p->rightMoving() ) {
p->plus( p->plus()*q1 );
p->y( log(p->pT().pt()/p->plus() ) );
p->minus( p->pT().pt()*exp( p->y() ) );
}
else {
p->minus( p->minus()*q2 );
p->y( log( p->minus()/p->pT().pt() ) );
p->plus( p->pT().pt()*exp( -p->y() ) );
}
if( !((*it)->neighbors().second) ) {
//do second parton as well if at the end of a chain
p = (*it)->partons().second;
if( p->rightMoving() ) {
p->plus( p->plus()*q1 );
p->y( log(p->pT().pt()/p->plus() ) );
p->minus( p->pT().pt()*exp( p->y() ) );
}
else {
p->minus( p->minus()*q2 );
p->y( log( p->minus()/p->pT().pt() ) );
p->plus( p->pT().pt()*exp( -p->y() ) );
}
}
}
}
void DipoleState::saveGluonsToFile(double weight) const {
EventPtr event = handler().currentEvent();
string filename = handler().generator()->filename();
//set up outfile
ostringstream os;
PPair incoming = event->incoming();
LorentzPoint p1 = incoming.first->vertex();
LorentzPoint p2 = incoming.second->vertex();
double bx = (p1-p2).x()/femtometer;
double by = (p1-p2).y()/femtometer;
//TODO: interface!
os << "/home/christoffer/DIPSYevents/" << filename << "/event" << event->number() << ".dat";
// os << "/scratch/parton/christof/DIPSY/events/" << filename << "/event" << weight << ".dat";
weight = 2.0*int(sqrt(sqr(bx)+sqr(by))) + 1.0;
ofstream outfile (os.str().c_str());
//general information
outfile << "Generated with DIPSY 1.1" << endl;
outfile << "These are the real gluons only. No FSR or hadronisation has been done." << endl;
//print weight and impact parameter.
outfile << endl << "eventweight: " << weight << endl << endl;
outfile << "impact_parameter(fm):" << " " << bx << " " << by << endl;
vector<PartonPtr> partonVector;
int n = 0;
for(set< DipolePtr >::iterator it = allDipoles.begin();
it != allDipoles.end(); it++) {
if( ((*it)->children().first || (*it)->children().second) )
continue;
PartonPtr p = (*it)->partons().first;
if ( p->y() < -3 || p->y() > 3 ) continue;
partonVector.push_back(p);
p->number(n);
n++;
}
outfile << "number_of_particles:" << " " << partonVector.size() << endl;
outfile << "number of spectating nucleons: " << numberOfSpectators() << endl << endl;
//print gluons
outfile << "particle_number" << " "
<< "transverse_position_x(fm)" << " "
<< "transverse_position_y(fm)" << " "
<< "transverse_momentum_x(GeV)" << " "
<< "transverse_momentum_y(GeV)" << " "
<< "rapidity" << " "
<< "colour_neighbour_number" << " "
<< "anticolour_neighbour_number" << endl << endl;
for(int i = 0; i < int(partonVector.size()); i++) {
PartonPtr p = partonVector[i];
outfile << p->number() << " "
<< p->position().x()*hbarc/femtometer << " "
<< p->position().y()*hbarc/femtometer << " "
<< p->pT().x()/GeV << " "
<< p->pT().y()/GeV << " "
<< p->y() << " ";
if ( p->dipoles().first )
outfile << p->dipoles().first->partons().first->number() << " ";
else outfile << -1 << " ";
if ( p->dipoles().second )
outfile << p->dipoles().second->partons().second->number() << " ";
else outfile << -1 << " ";
outfile << endl;
}
outfile.close();
cout << "printed gluons to file " << os.str().c_str() << endl;
}
int DipoleState::numberOfSpectators() const {
int nSpectators = 0;
for ( int i = 0; i < int(theInitialDipoles.size()); i++ ) {
tPartonPtr p1 = theInitialDipoles[i]->partons().first;
tPartonPtr p2 = theInitialDipoles[i]->partons().second;
tPartonPtr p3;
if ( i != int(theInitialDipoles.size())-1 &&
theInitialDipoles[i+1]->partons().first == p2 )
p3 = theInitialDipoles[i+1]->partons().second;
else if ( i != int(theInitialDipoles.size())-1 &&
theInitialDipoles[i+1]->partons().second == p1 )
p3 = theInitialDipoles[i+1]->partons().first;
else if ( i != 0 && theInitialDipoles[i-1]->partons().first == p2 )
p3 = theInitialDipoles[i-1]->partons().second;
else if ( i != 0 && theInitialDipoles[i-1]->partons().second == p1 )
p3 = theInitialDipoles[i-1]->partons().first;
if ( !(p1->interacted()) &&
!(p2->interacted()) &&
!( p3 && p3->interacted() ) ) {
nSpectators++;
}
}
return nSpectators/3;
}
void DipoleState::unifyColourSystems(int sys) {
for ( set<DipolePtr>::iterator it = allDipoles.begin();
it != allDipoles.end(); ++it ) (**it).colourSystem(sys);
}
tPPtr DipoleState::getParticle(tcPartonPtr parton, bool nocreate) const {
map<tcPartonPtr,PPtr>::iterator pit = theProducedParticles.find(parton);
if ( pit != theProducedParticles.end() ) return pit->second;
if ( nocreate ) return tPPtr();
if( parton->plus() <= 0.0*GeV ) cout << "p+ is not positive :(" << endl <<
"p+ = " << parton->plus()/GeV << endl <<
"p- = " << parton->minus()/GeV << endl <<
"pt = " << parton->pT().pt()/GeV << endl <<
"y = " << parton->y() << endl;
PPtr p = CurrentGenerator::current().getParticle(parton->flavour());
p->setMomentum(parton->momentum());
p->setVertex(LorentzPoint(parton->position().x()*hbarc, parton->position().y()*hbarc,
ZERO, ZERO));
p->getInfo().push_back(new_ptr(ParticleInfo(parton)));
theProducedParticles[parton] = p;
return p;
}
void DipoleState::persistentOutput(PersistentOStream & os) const {
os << ounit(thePlus, GeV) << ounit(theMinus, GeV)
<< ounit(theMinusDeficit, GeV) << theHandler << theInitialDipoles
<< theSwingCandidates << theTouchedSwingCandidates
<< theWFInfo << theWeight << doTakeHistory
<< theYmax << ounit(theCollidingEnergy, GeV) << allDipoles << theIncoming
<< theProducedParticles;
}
void DipoleState::persistentInput(PersistentIStream & is, int) {
is >> iunit(thePlus, GeV)>> iunit(theMinus, GeV)
>> iunit(theMinusDeficit, GeV) >> theHandler >> theInitialDipoles
>> theSwingCandidates >> theTouchedSwingCandidates
>> theWFInfo >> theWeight >> doTakeHistory
>> theYmax >> iunit(theCollidingEnergy, GeV) >> allDipoles >> theIncoming
>> theProducedParticles;
}
// Static variable needed for the type description system in ThePEG.
#include "ThePEG/Utilities/DescribeClass.h"
DescribeClass<DipoleState,PersistentBase>
- describeDIPSYDipoleState("DIPSY::DipoleState", "libDIPSY.so");
+ describeDIPSYDipoleState("DIPSY::DipoleState", "libAriadne5.so libDIPSY.so");
void DipoleState::Init() {}
diff --git a/DIPSY/DipoleXSec.cc b/DIPSY/DipoleXSec.cc
--- a/DIPSY/DipoleXSec.cc
+++ b/DIPSY/DipoleXSec.cc
@@ -1,1504 +1,1504 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the DipoleXSec class.
//
#include "DipoleXSec.h"
#include "Dipole.h"
#include "DipoleState.h"
#include "Parton.h"
#include "DipoleEventHandler.h"
#include "RealParton.h"
#include "RealPartonState.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Utilities/Current.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Repository/CurrentGenerator.h"
#include "ThePEG/Utilities/Debug.h"
#include "ThePEG/Utilities/DebugItem.h"
#include "ThePEG/Utilities/Throw.h"
#ifdef ThePEG_TEMPLATES_IN_CC_FILE
// #include "DipoleXSec.tcc"
#endif
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "gsl/gsl_sf_bessel.h"
using namespace ThePEG;
using namespace DIPSY;
DipoleXSec::~DipoleXSec() {}
InvEnergy DipoleXSec::rMax() const {
return theRMax > 0.0*InvGeV? theRMax: Current<DipoleEventHandler>()->rMax();
}
double DipoleXSec::
fij(const pair<tPartonPtr, tPartonPtr> left,
const pair<tPartonPtr, tPartonPtr> right,
const ImpactParameters & b, bool veto) const {
Nfij++;
tcPartonPtr p11 = left.first;
tcPartonPtr p12 = left.second;
tcPartonPtr p21 = right.first;
tcPartonPtr p22 = right.second;
//TODO: keep only interaction 0, as that is the only one supported anyway
if ( theInteraction == 0 || theInteraction == 1 || theInteraction == 3 || theInteraction == 4 ) {
InvEnergy2 rr11 = b.dist2(*p11, *p21);
InvEnergy2 rr21 = b.dist2(*p12, *p21);
InvEnergy2 rr12 = b.dist2(*p11, *p22);
InvEnergy2 rr22 = b.dist2(*p12, *p22);
if ( veto && kinematicsVeto(left, right, b) ) {
return 0.0;
}
TransverseMomentum pt;
double pTScale = Current<DipoleEventHandler>()->emitter().pTScale();
InvEnergy rscale = sqrt(min(min(min(rr12, rr21),min(rr11, rr22)),
min(p11->dist2(*p12), p21->dist2(*p22))));
if ( theInteraction == 0 ) {
pair<bool, bool> ints;
ints = int0Partons(p11, p12, p21, p22, b);
Parton::Point r1 = b.difference((ints.first ? p11->position():p12->position()),
(ints.second ? p21->position():p22->position()));
pt = pTScale*r1/sqr(r1.pt());
rscale = sqrt(min(min(sqr(r1.pt()),p11->dist2(*p12)), p21->dist2(*p22)));
}
if ( theInteraction == 1 ) { //4 parton distance
Parton::Point r1 = b.difference(p11->position(), p21->position());
Parton::Point r2 = b.difference(p11->position(), p22->position());
Parton::Point r3 = b.difference(p12->position(), p21->position());
Parton::Point r4 = b.difference(p12->position(), p22->position());
pt = pTScale*(r1/sqr(r1.pt()) + r2/sqr(r2.pt()) +
r3/sqr(r3.pt()) + r4/sqr(r4.pt()))*0.35;
}
if ( theInteraction == 3 ) { //2 parton distance
Parton::Point r1 = b.difference(p11->position(), p22->position());
Parton::Point r2 = b.difference(p12->position(), p21->position());
pt = pTScale*(r1/sqr(r1.pt()) + r2/sqr(r2.pt()))*0.6;
}
Parton::Point rho1 = (p12->position() - p11->position())/2.0;
Parton::Point rho2 = (p22->position() - p21->position())/2.0;
double s1 = pt.x()*rho1.x() + pt.y()*rho1.y();
double s2 = pt.x()*rho2.x() + pt.y()*rho2.y();
return 8.0*sqr(Current<DipoleEventHandler>()->alphaS(rscale))*
sqr(sin(s1)*sin(s2))*
sqr(sqr(pt.pt()))/sqr(sqr(pt.pt()) + sqr(pTScale/rMax()));
}
return 0.0;
}
double DipoleXSec::
fij(const Dipole & dleft, const Dipole & dright,
const ImpactParameters & b, bool veto) const {
pair<tPartonPtr, tPartonPtr> left = dleft.partons();
pair<tPartonPtr, tPartonPtr> right = dright.partons();
pair<bool, bool> ints;
Nfij++;
tcPartonPtr p11 = left.first;
tcPartonPtr p12 = left.second;
tcPartonPtr p21 = right.first;
tcPartonPtr p22 = right.second;
ints = int0Partons(p11, p12, p21, p22, b);
//TODO: keep only interaction 0, as that is the only one supported anyway
if ( theInteraction == 0 || theInteraction == 1 || theInteraction == 3 || theInteraction == 4 ) {
InvEnergy2 rr11 = b.dist2(*p11, *p21);
InvEnergy2 rr21 = b.dist2(*p12, *p21);
InvEnergy2 rr12 = b.dist2(*p11, *p22);
InvEnergy2 rr22 = b.dist2(*p12, *p22);
if ( veto && kinematicsVeto(dleft, dright, b, ints) ) {
return 0.0;
}
TransverseMomentum pt;
double pTScale = Current<DipoleEventHandler>()->emitter().pTScale();
InvEnergy rscale = sqrt(min(min(min(rr12, rr21),min(rr11, rr22)),
min(p11->dist2(*p12), p21->dist2(*p22))));
if ( theInteraction == 0 ) {
Parton::Point r1 = b.difference((ints.first ? p11->position():p12->position()),
(ints.second ? p21->position():p22->position()));
pt = pTScale*r1/sqr(r1.pt());
rscale = sqrt(min(min(sqr(r1.pt()),p11->dist2(*p12)), p21->dist2(*p22)));
}
if ( theInteraction == 1 ) { //4 parton distance
Parton::Point r1 = b.difference(p11->position(), p21->position());
Parton::Point r2 = b.difference(p11->position(), p22->position());
Parton::Point r3 = b.difference(p12->position(), p21->position());
Parton::Point r4 = b.difference(p12->position(), p22->position());
pt = pTScale*(r1/sqr(r1.pt()) + r2/sqr(r2.pt()) +
r3/sqr(r3.pt()) + r4/sqr(r4.pt()))*0.35;
}
if ( theInteraction == 3 ) { //2 parton distance
Parton::Point r1 = b.difference(p11->position(), p22->position());
Parton::Point r2 = b.difference(p12->position(), p21->position());
pt = pTScale*(r1/sqr(r1.pt()) + r2/sqr(r2.pt()))*0.6;
}
Parton::Point rho1 = (p12->position() - p11->position())/2.0;
Parton::Point rho2 = (p22->position() - p21->position())/2.0;
double s1 = pt.x()*rho1.x() + pt.y()*rho1.y();
double s2 = pt.x()*rho2.x() + pt.y()*rho2.y();
return 8.0*sqr(Current<DipoleEventHandler>()->alphaS(rscale))*
sqr(sin(s1)*sin(s2))*
sqr(sqr(pt.pt()))/sqr(sqr(pt.pt()) + sqr(pTScale/rMax()));
}
return 0.0;
}
bool DipoleXSec::kinematicsVeto(const pair<tPartonPtr, tPartonPtr> left,
const pair<tPartonPtr, tPartonPtr> right,
const ImpactParameters & b) const {
pair<pair<bool, bool>, pair<bool, bool> > ints = doesInt(left, right, b);
InteractionRecoil recs = recoil(left, right, b, ints);
if ( theInteraction == 0 ) {
//the key partons for f_ij
pair<bool, bool> ints0 = int0Partons(left.first, left.second, right.first, right.second, b);
//first set up effective partons with range etc
tPartonPtr p1 = (ints0.first ? left.first:left.second);
tPartonPtr p2 = (ints0.second ? right.first:right.second);
//there MAY be secondary partons in the interaction, decided by ints.
tPartonPtr p1sec, p2sec;
if ( ints.first.first && ints.first.second )
p1sec = (ints0.first ? left.second:left.first);
if ( ints.second.first && ints.second.second )
p2sec = (ints0.second ? right.second:right.first);
//only distance between key partons will affect range (reasonable?)
InvEnergy range1 = sqrt(min(left.first->dist2(*left.second)/4.0, b.dist2(*p1, *p2)));
InvEnergy range2 = sqrt(min(right.first->dist2(*right.second)/4.0, b.dist2(*p1, *p2)));
if ( Current<DipoleEventHandler>()->emitter().rangeMode() == 1 ) {
range1 = sqrt(left.first->dist2(*left.second)/4.0);
range2 = sqrt(right.first->dist2(*right.second)/4.0);
}
EffectivePartonPtr ep1 = EffectiveParton::create(*p1, range1);
EffectivePartonPtr ep2 = EffectiveParton::create(*p2, range2);
EffectivePartonPtr ep1sec, ep2sec;
if ( p1sec ) ep1sec = EffectiveParton::create(*p1sec, range1);
if ( p2sec ) ep2sec = EffectiveParton::create(*p2sec, range2);
TransverseMomentum rec1 = (ints0.first ? recs.first.first:recs.first.second);
TransverseMomentum rec2 = (ints0.second ? recs.second.first:recs.second.second);
Energy pt1 = (ep1->pT() + rec1).pt();
Energy minus1 = sqr(pt1)/ep1->plus();
Energy pt2 = (ep2->pT() + rec2).pt();
Energy minus2 = sqr(pt2)/ep2->plus();
//sum up total supplied and needed LC momentum from each side
Energy leftPlus = ep1->plus() + (p1sec ? ep1sec->plus():ZERO);
Energy leftMinus = minus1;
if ( p1sec ) {
TransverseMomentum rec1sec = (ints0.first ? recs.first.second:recs.first.first);
Energy pt1sec = (ep1sec->pT() + rec1sec).pt();
Energy minus1sec = sqr(pt1sec)/ep1sec->plus();
leftMinus += minus1sec;
}
Energy rightPlus = ep2->plus() + (p2sec ? ep2sec->plus():ZERO);
Energy rightMinus = minus2 + (p2sec ? ep2sec->minus():ZERO);
if ( p2sec ) {
TransverseMomentum rec2sec = (ints0.second ? recs.second.second:recs.second.first);
Energy pt2sec = (ep2sec->pT() + rec2sec).pt();
Energy minus2sec = sqr(pt2sec)/ep2sec->plus();
rightMinus += minus2sec;
}
if ( theIntOrdering == 2 ) {
Energy maxRec = max(max(recs.first.first.pt() ,recs.first.second.pt()),
max(recs.second.first.pt() ,recs.second.second.pt()));
if ( leftPlus*rightPlus < 16.0*sqr(maxRec) ) return true;
else return false;
}
//check enough energy to set all on shell
if ( leftPlus*rightPlus < 16.0*leftMinus*rightMinus ) {
return true;
}
//take LC momentum transfers in account
Energy plus1 = ep1->plus()*(1.0 - rightMinus/leftPlus);
minus1 /= 1.0 - rightMinus/leftPlus;
Energy plus2 = ep2->plus()*(1.0 - leftMinus/rightPlus);
minus2 /= 1.0 - leftMinus/rightPlus;
//check ordering of the key partons (secondaries can be unordered if they want)
double PSInf = Current<DipoleEventHandler>()->emitter().PSInflation();
if ( theIntOrdering == 0 ) {
//just check plus and minus ordering after recoils
if ( plus1*PSInf < minus2 ) return true;
if ( plus2*PSInf < minus1 ) return true;
}
else if ( theIntOrdering == 1 ) {
//check p- ordering from both sides, as if it was evolution.
//that is, as if no future recoils.
double PMOrd = Current<DipoleEventHandler>()->emitter().PMinusOrdering();
TransverseMomentum rec1 = (ints0.first ? recs.first.first:recs.first.second);
TransverseMomentum rec2 = (ints0.second ? recs.second.first:recs.second.second);
if ( sqr(max(rec1.pt(), rec2.pt())*PSInf) < minus1*minus2*PMOrd )
return true;
}
//check that the partons stay on their side, to avoid doublecounting
double yInt = 0;
if ( p1->dipoles().first ) yInt = p1->dipoles().first->dipoleState().ymax();
else if ( p1->dipoles().second ) yInt = p1->dipoles().second->dipoleState().ymax();
double y1 = 0.5*log(minus1/plus1);
if ( y1 > yInt ) return true;
double y2 = 0.5*log(plus2/minus2);
if ( y2 < yInt ) return true;
//should we check secondaries as well here?
//if no veto triggered, it should not be vetoed
return false;
}
else {
cerr << "only interaction 0 is supported in kinematics veto atm, sorry" << endl;
}
return false;
}
bool DipoleXSec::kinematicsVeto(const Dipole & dleft,
const Dipole & dright,
const ImpactParameters & b,
const pair<bool,bool> & ints0) const {
pair<tPartonPtr, tPartonPtr> left = dleft.partons();
pair<tPartonPtr, tPartonPtr> right = dright.partons();
pair<pair<bool, bool>, pair<bool, bool> > ints = doesInt(left, right, b);
InteractionRecoil recs = recoil(left, right, b, ints, ints0);
if ( theInteraction == 0 ) {
//first set up effective partons with range etc
tPartonPtr p1 = (ints0.first ? left.first:left.second);
tPartonPtr p2 = (ints0.second ? right.first:right.second);
//there MAY be secondary partons in the interaction, decided by ints.
tPartonPtr p1sec, p2sec;
if ( ints.first.first && ints.first.second )
p1sec = (ints0.first ? left.second:left.first);
if ( ints.second.first && ints.second.second )
p2sec = (ints0.second ? right.second:right.first);
//only distance between key partons will affect range (reasonable?)
InvEnergy range1 = sqrt(min(left.first->dist2(*left.second)/4.0, b.dist2(*p1, *p2)));
InvEnergy range2 = sqrt(min(right.first->dist2(*right.second)/4.0, b.dist2(*p1, *p2)));
if ( Current<DipoleEventHandler>()->emitter().rangeMode() == 1 ) {
range1 = sqrt(left.first->dist2(*left.second)/4.0);
range2 = sqrt(right.first->dist2(*right.second)/4.0);
}
EffectivePartonPtr ep1 = dleft.getEff(p1, range1);
EffectivePartonPtr ep2 = dright.getEff(p2, range2);
EffectivePartonPtr ep1sec, ep2sec;
if ( p1sec ) ep1sec = dleft.getEff(p1sec, range1);
if ( p2sec ) ep2sec = dright.getEff(p2sec, range2);
TransverseMomentum rec1 = (ints0.first ? recs.first.first:recs.first.second);
TransverseMomentum rec2 = (ints0.second ? recs.second.first:recs.second.second);
Energy pt1 = (ep1->pT() + rec1).pt();
Energy minus1 = sqr(pt1)/ep1->plus();
Energy pt2 = (ep2->pT() + rec2).pt();
Energy minus2 = sqr(pt2)/ep2->plus();
//sum up total supplied and needed LC momentum from each side
Energy leftPlus = ep1->plus() + (p1sec ? ep1sec->plus():ZERO);
Energy leftMinus = minus1;
if ( p1sec ) {
TransverseMomentum rec1sec = (ints0.first ? recs.first.second:recs.first.first);
Energy pt1sec = (ep1sec->pT() + rec1sec).pt();
Energy minus1sec = sqr(pt1sec)/ep1sec->plus();
leftMinus += minus1sec;
}
Energy rightPlus = ep2->plus() + (p2sec ? ep2sec->plus():ZERO);
Energy rightMinus = minus2 + (p2sec ? ep2sec->minus():ZERO);
if ( p2sec ) {
TransverseMomentum rec2sec = (ints0.second ? recs.second.second:recs.second.first);
Energy pt2sec = (ep2sec->pT() + rec2sec).pt();
Energy minus2sec = sqr(pt2sec)/ep2sec->plus();
rightMinus += minus2sec;
}
if ( theIntOrdering == 2 ) {
Energy maxRec = max(max(recs.first.first.pt() ,recs.first.second.pt()),
max(recs.second.first.pt() ,recs.second.second.pt()));
if ( leftPlus*rightPlus < 16.0*sqr(maxRec) ) return true;
else return false;
}
//check enough energy to set all on shell
if ( leftPlus*rightPlus < 16.0*leftMinus*rightMinus ) {
return true;
}
//take LC momentum transfers in account
Energy plus1 = ep1->plus()*(1.0 - rightMinus/leftPlus);
minus1 /= 1.0 - rightMinus/leftPlus;
Energy plus2 = ep2->plus()*(1.0 - leftMinus/rightPlus);
minus2 /= 1.0 - leftMinus/rightPlus;
//check ordering of the key partons (secondaries can be unordered if they want)
double PSInf = Current<DipoleEventHandler>()->emitter().PSInflation();
if ( theIntOrdering == 0 ) {
//just check plus and minus ordering after recoils
if ( plus1*PSInf < minus2 ) return true;
if ( plus2*PSInf < minus1 ) return true;
}
else if ( theIntOrdering == 1 ) {
//check p- ordering from both sides, as if it was evolution.
//that is, as if no future recoils.
double PMOrd = Current<DipoleEventHandler>()->emitter().PMinusOrdering();
TransverseMomentum rec1 = (ints0.first ? recs.first.first:recs.first.second);
TransverseMomentum rec2 = (ints0.second ? recs.second.first:recs.second.second);
if ( sqr(max(rec1.pt(), rec2.pt())*PSInf) < minus1*minus2*PMOrd )
return true;
}
//check that the partons stay on their side, to avoid doublecounting
double yInt = 0;
if ( p1->dipoles().first ) yInt = p1->dipoles().first->dipoleState().ymax();
else if ( p1->dipoles().second ) yInt = p1->dipoles().second->dipoleState().ymax();
double y1 = 0.5*log(minus1/plus1);
if ( y1 > yInt ) return true;
double y2 = 0.5*log(plus2/minus2);
if ( y2 < yInt ) return true;
//should we check secondaries as well here?
//if no veto triggered, it should not be vetoed
return false;
}
else {
cerr << "only interaction 0 is supported in kinematics veto atm, sorry" << endl;
}
return false;
}
double DipoleXSec::
sumf(const DipoleState & sl, const DipoleState & sr,
const ImpactParameters & b) const {
Nfij = 0;
NBVeto = 0;
NScalVeto = 0;
scalVeto = 0.0;
bVeto = 0.0;
vector<tDipolePtr> dl;
sl.extract(back_inserter(dl));
vector<tDipolePtr> dr;
sr.extract(back_inserter(dr));
double sum = 0.0;
for ( int i = 0, N = dl.size(); i < N; ++i )
for ( int j = 0, M = dr.size(); j < M; ++j )
sum += fij(*dl[i], *dr[j], b);
return sum;
}
DipoleXSec::FList
DipoleXSec::flist(const DipoleState & sl, const DipoleState & sr,
const ImpactParameters & b) const {
FList ret;
vector<tDipolePtr> dl;
sl.extract(back_inserter(dl));
vector<tDipolePtr> dr;
sr.extract(back_inserter(dr));
//dont save the lowest fij. Otherwise the FList for LHC PbPb will take too much memory.
double cutoff = min(0.00000001, 1.0/double(dl.size()*dr.size()));
if ( dl.size()*dr.size() < 1000000 ) cutoff = 0.0000000001;
int total = 0;
int skipped = 0;
for ( int i = 0, N = dl.size(); i < N; ++i ) {
for ( int j = 0, M = dr.size(); j < M; ++j ) {
double f = fij(dl[i]->partons(), dr[j]->partons(), b, false)*2.0;
//extra 2 added from the non-diffractive interaction probability.
total++;
if ( f > cutoff &&
!kinematicsVeto(dl[i]->partons(), dr[j]->partons(), b) )
ret.insert(make_pair(make_pair(f, unitarize(f)), make_pair(dl[i], dr[j])));
else skipped++;
}
}
return ret;
}
DipoleXSec::FList
DipoleXSec::effectiveFlist(const DipoleState & sl, const DipoleState & sr,
const ImpactParameters & b) const {
FList ret;
vector<tDipolePtr> dl;
sl.extract(back_inserter(dl));
vector<tDipolePtr> dr;
sr.extract(back_inserter(dr));
set< pair<pair<tPartonPtr, tPartonPtr>, pair<tPartonPtr, tPartonPtr> > >
backChecks;
double cutoff = min(0.00000001, 1.0/double(dl.size()*dr.size()));
if ( dl.size()*dr.size() < 1000000 ) cutoff = 0.0000000001;
for ( int i = 0, N = dl.size(); i < N; ++i ) {
for ( int j = 0, M = dr.size(); j < M; ++j ) {
double f = fij(dl[i]->partons(), dr[j]->partons(), b)*2.0;
//extra 2 added from the non-diffractive interaction probability.
//if vetoed, go check the previous dipoles until non-zero fij is found
tPartonPtr p11 = dl[i]->partons().first;
tPartonPtr p12 = dl[i]->partons().second;
tPartonPtr p21 = dr[j]->partons().first;
tPartonPtr p22 = dr[j]->partons().second;
while ( f == 0.0 ) {
//replace the most forward parton on each side by its parent.
bool changed = false;
if ( p11->y() > p12->y() && p11->y() > p21->y() && p11->y() > p22->y() &&
p11->parents().first ) {
p11 = p11->parents().first;
changed = true;
}
else if ( p12->y() > p21->y() && p12->y() > p22->y() && p12->parents().second ) {
p12 = p12->parents().second;
changed = true;
}
else if ( p21->y() > p22->y() && p21->parents().first ) {
p21 = p21->parents().first;
changed = true;
}
else if ( p22->parents().second ) {
p22 = p22->parents().second;
changed = true;
}
//if no replacements found, return 0
if ( !changed ) break;
//if the 4 new partons are not already checked from another fij,
//then calculate and return the new fij
pair<tPartonPtr, tPartonPtr> lp = make_pair(p11, p12);
pair<tPartonPtr, tPartonPtr> rp = make_pair(p21, p22);
if ( backChecks.find(make_pair(lp, rp)) == backChecks.end() ) {
f = fij(lp, rp, b)*2.0;
backChecks.insert(make_pair(lp, rp));
}
else {
break;
}
}
//if f is large enough to bother, save it in the flist
if ( f > cutoff )
ret.insert(make_pair(make_pair(f, unitarize(f)), make_pair(dl[i], dr[j])));
}
}
return ret;
}
DipoleXSec::InteractionRecoil
DipoleXSec::recoil(const pair<tPartonPtr, tPartonPtr> left,
const pair<tPartonPtr, tPartonPtr> right,
const ImpactParameters & b,
pair<pair<bool, bool>, pair<bool, bool> > doesInt) const {
return recoil(left, right, b, doesInt, int0Partons(left.first, left.second,
right.first, right.second, b));
}
DipoleXSec::InteractionRecoil
DipoleXSec::recoil(const pair<tPartonPtr, tPartonPtr> left,
const pair<tPartonPtr, tPartonPtr> right,
const ImpactParameters & b,
pair<pair<bool, bool>, pair<bool, bool> > doesInt,
pair<bool, bool> ints) const {
tPartonPtr p1 = left.first;
tPartonPtr p2 = left.second;
tPartonPtr p3 = right.first;
tPartonPtr p4 = right.second;
double pTScale = Current<DipoleEventHandler>()->emitter().pTScale();
if ( theInteraction == 2 ) { //swing recoil, only new dips
TransverseMomentum rec14 = -pTScale*b.difference(p1->position(), p4->position())/
( b.dist2(*p1,*p4) );
TransverseMomentum rec23 = -pTScale*b.difference(p2->position(), p3->position())/
( b.dist2(*p2,*p3) );
return make_pair(make_pair(rec14, rec23),
make_pair(-rec23, -rec14));
}
//4 parton-parton recoils (full diagonals)
if ( theInteraction == 1 ) {
TransverseMomentum rec13 = -pTScale*b.difference(p1->position(), p3->position())/
(b.dist2(*p1,*p3) );
TransverseMomentum rec14 = -pTScale*b.difference(p1->position(), p4->position())/
(b.dist2(*p1,*p4) );
TransverseMomentum rec23 = -pTScale*b.difference(p2->position(), p3->position())/
(b.dist2(*p2,*p3) );
TransverseMomentum rec24 = -pTScale*b.difference(p2->position(), p4->position())/
(b.dist2(*p2,*p4) );
return make_pair(make_pair(rec14 + rec13, rec23 + rec24),
make_pair(b.invRotatePT(-rec23 - rec13),
b.invRotatePT(-rec14 - rec24)));
}
//2 parton-parton recoils (no diagonals)
if ( theInteraction == 3 ) {
TransverseMomentum rec13 = -pTScale*b.difference(p1->position(), p3->position())/
(b.dist2(*p1,*p3) );
TransverseMomentum rec14 = -pTScale*b.difference(p1->position(), p4->position())/
(b.dist2(*p1,*p4) );
TransverseMomentum rec23 = -pTScale*b.difference(p2->position(), p3->position())/
(b.dist2(*p2,*p3) );
TransverseMomentum rec24 = -pTScale*b.difference(p2->position(), p4->position())/
(b.dist2(*p2,*p4) );
if ( doesInt.first.first && doesInt.first.second &&
doesInt.second.first && doesInt.second.second )
return make_pair(make_pair(rec14, rec23),
make_pair(b.invRotatePT(-rec23), b.invRotatePT(-rec14)));
else {
TransverseMomentum rec11 = TransverseMomentum();
if ( doesInt.first.first && doesInt.second.first ) rec11 += rec13;
if ( doesInt.first.first && doesInt.second.second ) rec11 += rec14;
TransverseMomentum rec12 = TransverseMomentum();
if ( doesInt.first.second && doesInt.second.first ) rec12 += rec23;
if ( doesInt.first.second && doesInt.second.second ) rec12 += rec24;
TransverseMomentum rec21 = TransverseMomentum();
if ( doesInt.second.first && doesInt.first.first ) rec21 -= rec13;
if ( doesInt.second.first && doesInt.first.second ) rec21 -= rec23;
TransverseMomentum rec22 = TransverseMomentum();
if ( doesInt.second.second && doesInt.first.first ) rec22 -= rec14;
if ( doesInt.second.second && doesInt.first.second ) rec22 -= rec24;
return make_pair(make_pair(rec11, rec12),
make_pair(b.invRotatePT(rec21), b.invRotatePT(rec22)));
}
}
if ( theInteraction == 0 ) { //dip-dip recoil
TransverseMomentum rec13 = -pTScale*b.difference(p1->position(), p3->position())/
(b.dist2(*p1,*p3) );
TransverseMomentum rec14 = -pTScale*b.difference(p1->position(), p4->position())/
(b.dist2(*p1,*p4) );
TransverseMomentum rec23 = -pTScale*b.difference(p2->position(), p3->position())/
(b.dist2(*p2,*p3) );
TransverseMomentum rec24 = -pTScale*b.difference(p2->position(), p4->position())/
(b.dist2(*p2,*p4) );
if ( p1->oY() + p3->oY() > p2->oY() + p4->oY() ) rec24 = TransverseMomentum();
else rec13 = TransverseMomentum();
TransverseMomentum rec11 = TransverseMomentum();
if ( doesInt.first.first && doesInt.second.first ) rec11 += rec13;
if ( doesInt.first.first && doesInt.second.second ) rec11 += rec14;
TransverseMomentum rec12 = TransverseMomentum();
if ( doesInt.first.second && doesInt.second.first ) rec12 += rec23;
if ( doesInt.first.second && doesInt.second.second ) rec12 += rec24;
TransverseMomentum rec21 = TransverseMomentum();
if ( doesInt.second.first && doesInt.first.first ) rec21 -= rec13;
if ( doesInt.second.first && doesInt.first.second ) rec21 -= rec23;
TransverseMomentum rec22 = TransverseMomentum();
if ( doesInt.second.second && doesInt.first.first ) rec22 -= rec14;
if ( doesInt.second.second && doesInt.first.second ) rec22 -= rec24;
return make_pair(make_pair(rec11, rec12),
make_pair(b.invRotatePT(rec21), b.invRotatePT(rec22)));
}
return make_pair(make_pair(TransverseMomentum(), TransverseMomentum()),
make_pair(TransverseMomentum(), TransverseMomentum()));
}
DipoleXSec::RealInteraction
DipoleXSec::initialiseInteraction(const pair<DipolePtr, DipolePtr> inter,
RealPartonStatePtr lrs, RealPartonStatePtr rrs,
pair<pair<bool, bool>, pair<bool, bool> > doesInt,
const ImpactParameters & b) const {
RealInteraction ret;
ret.lrs = lrs;
ret.rrs = rrs;
ret.d1 = inter.first;
ret.d2 = inter.second;
if ( doesInt.first.first ) ret.p11 = lrs->getReal(ret.d1->partons().first);
else ret.p11 = RealPartonPtr();
if ( doesInt.first.second ) ret.p12 = lrs->getReal(ret.d1->partons().second);
else ret.p12 = RealPartonPtr();
if ( doesInt.second.first ) ret.p21 = rrs->getReal(inter.second->partons().first);
else ret.p21 = RealPartonPtr();
if ( doesInt.second.second ) ret.p22 = rrs->getReal(inter.second->partons().second);
else ret.p22 = RealPartonPtr();
if ( ret.p11 && ret.p11->fluct != -1 && ret.p12 && ret.p12->fluct == ret.p11->fluct )
lrs->splitFluct(ret.p11, ret.p12);
if ( ret.p21 && ret.p21->fluct != -1 && ret.p22 && ret.p22->fluct == ret.p21->fluct )
rrs->splitFluct(ret.p21, ret.p22);
ret.range11 = sqrt(min(min(inter.first->partons().first->dist2
(*inter.second->partons().first),
inter.first->partons().first->dist2
(*inter.second->partons().second)),
inter.first->partons().first->dist2
(*inter.first->partons().second)/4.0));
ret.range12 = sqrt(min(min(inter.first->partons().second->dist2
(*inter.second->partons().first),
inter.first->partons().second->dist2
(*inter.second->partons().second)),
inter.first->partons().second->dist2
(*inter.first->partons().first)/4.0));
ret.range21 = sqrt(min(min(inter.second->partons().first->dist2
(*inter.first->partons().first),
inter.second->partons().first->dist2
(*inter.first->partons().second)),
inter.second->partons().first->dist2
(*inter.second->partons().second)/4.0));
ret.range22 = sqrt(min(min(inter.second->partons().second->dist2
(*inter.first->partons().first),
inter.second->partons().second->dist2
(*inter.first->partons().second)),
inter.second->partons().second->dist2
(*inter.second->partons().first)/4.0));
if ( theInteraction == 3 ) {
ret.range11 = sqrt(min(inter.first->partons().first->dist2
(*inter.second->partons().second),
inter.first->partons().first->dist2
(*inter.first->partons().second)/4.0));
ret.range12 = sqrt(min(inter.first->partons().second->dist2
(*inter.second->partons().first),
inter.first->partons().second->dist2
(*inter.first->partons().first)/4.0));
ret.range21 = sqrt(min(inter.second->partons().first->dist2
(*inter.first->partons().second),
inter.second->partons().first->dist2
(*inter.second->partons().second)/4.0));
ret.range22 = sqrt(min(inter.second->partons().second->dist2
(*inter.first->partons().first),
inter.second->partons().second->dist2
(*inter.second->partons().first)/4.0));
}
if ( theInteraction == 0 ) {
pair<bool, bool> ints;
ints = int0Partons(ret.d1->partons().first, ret.d1->partons().second,
inter.second->partons().first, inter.second->partons().second, b);
InvEnergy2 range2;
if ( ints.first && ints.second ) range2 = b.dist2(*ret.p11->theParton,*ret.p21->theParton);
if ( !ints.first && ints.second ) range2 = b.dist2(*ret.p12->theParton,*ret.p21->theParton);
if ( ints.first && !ints.second ) range2 = b.dist2(*ret.p11->theParton,*ret.p22->theParton);
if ( !ints.first && !ints.second ) range2 = b.dist2(*ret.p12->theParton,*ret.p22->theParton);
InvEnergy range = sqrt(range2);
ret.range11 = min(range, ret.d1->size()/2.0);
ret.range12 = min(range, ret.d1->size()/2.0);
ret.range21 = min(range, ret.d2->size()/2.0);
ret.range22 = min(range, ret.d2->size()/2.0);
if ( Current<DipoleEventHandler>()->emitter().rangeMode() == 1 ) {
ret.range11 = ret.d1->size()/2.0;
ret.range12 = ret.d1->size()/2.0;
ret.range21 = ret.d2->size()/2.0;
ret.range22 = ret.d2->size()/2.0;
}
}
InvEnergy2 rr11 = (ret.p11 && ret.p21) ? ret.p11->theParton->dist2(*ret.p21->theParton):ZERO;
InvEnergy2 rr12 = (ret.p11 && ret.p22) ? ret.p11->theParton->dist2(*ret.p22->theParton):ZERO;
InvEnergy2 rr21 = (ret.p12 && ret.p21) ? ret.p12->theParton->dist2(*ret.p21->theParton):ZERO;
InvEnergy2 rr22 = (ret.p12 && ret.p22) ? ret.p12->theParton->dist2(*ret.p22->theParton):ZERO;
InvEnergy2 rm11 = (ret.p11 && ret.p11->mothers.first ?
ret.p11->theParton->dist2(*ret.p11->mothers.first->theParton):ZERO);
InvEnergy2 rm12 = (ret.p12 && ret.p12->mothers.first ?
ret.p12->theParton->dist2(*ret.p12->mothers.first->theParton):ZERO);
InvEnergy2 rm21 = (ret.p21 && ret.p21->mothers.first ?
ret.p21->theParton->dist2(*ret.p21->mothers.first->theParton):ZERO);
InvEnergy2 rm22 = (ret.p22 && ret.p22->mothers.first ?
ret.p22->theParton->dist2(*ret.p22->mothers.first->theParton):ZERO);
ret.max11 = rr11 < rm11 && rr11 < rm21;
ret.max12 = rr12 < rm11 && rr12 < rm22;
ret.max21 = rr21 < rm12 && rr21 < rm21;
ret.max22 = rr22 < rm12 && rr22 < rm22;
Energy2 den = ((ret.p11 ? 1./rr11:ZERO) + (ret.p12 ? 1./rr12:ZERO)
+ (ret.p21 ? 1./rr21:ZERO) + (ret.p22 ? 1./rr22:ZERO));
ret.P11 = ret.p11 ? (1./rr11)/den:ZERO;
ret.P12 = ret.p12 ? (1./rr12)/den:ZERO;
ret.P21 = ret.p21 ? (1./rr21)/den:ZERO;
ret.P22 = ret.p22 ? (1./rr22)/den:ZERO;
//look only at the new dipole pairs, the cross pairs get zero weight.
if ( theInteraction == 3 ) {
den = (1./rr12 + 1./rr21);
ret.P12 = (1./rr12)/den;
ret.P21 = (1./rr21)/den;
ret.P11 = 0.0;
ret.P22 = 0.0;
}
//set only the selected pair to weight 1, the others to 0.
if ( theInteraction == 0 ) {
pair<bool, bool> ints;
ints = int0Partons(inter.first->partons().first, inter.first->partons().second,
inter.second->partons().first, inter.second->partons().second, b);
ret.P11 = 0.0;
ret.P22 = 0.0;
ret.P21 = 0.0;
ret.P12 = 0.0;
if ( ints.first && ints.second ) ret.P11 = 1.0;
if ( ints.first && !ints.second ) ret.P12 = 1.0;
if ( !ints.first && ints.second ) ret.P21 = 1.0;
if ( !ints.first && !ints.second ) ret.P22 = 1.0;
}
return ret;
}
pair<pair<bool, bool>, pair<bool, bool> >
DipoleXSec::doesInt(const pair<tPartonPtr, tPartonPtr> left,
const pair<tPartonPtr, tPartonPtr> right,
const ImpactParameters & b) const {
//decide which of the 4 partons will end up on shell
return make_pair(make_pair(true, true), make_pair(true, true));
if ( Current<DipoleEventHandler>()->eventFiller().singleMother() ) {
//when single mother not all are chosen
pair<pair<bool, bool>, pair<bool, bool> > ret =
make_pair(make_pair(false, false), make_pair(false, false));
if ( theInteraction == 0 ) {
//if interaction 0, then always keep the same partons used in fij
pair<bool, bool> ints;
ints = int0Partons(left.first, left.second, right.first, right.second, b);
if ( ints.first ) ret.first.first = true;
else ret.first.second = true;
if ( ints.second ) ret.second.first =true;
else ret.second.second = true;
}
else {
//select which two partons the gluons are exchanged between,
//weighted by 1/distance^2
InvEnergy2 r11 = b.dist2(*left.first, *right.first);
InvEnergy2 r12 = b.dist2(*left.first, *right.second);
InvEnergy2 r21 = b.dist2(*left.second, *right.first);
InvEnergy2 r22 = b.dist2(*left.second, *right.second);
Selector<int, double> sel;
sel.insert(1./r11/(1./r11 + 1./r12 + 1./r21 + 1./r22), 1);
sel.insert(1./r12/(1./r11 + 1./r12 + 1./r21 + 1./r22), 2);
sel.insert(1./r21/(1./r11 + 1./r12 + 1./r21 + 1./r22), 3);
sel.insert(1./r22/(1./r11 + 1./r12 + 1./r21 + 1./r22), 4);
double dummy = (r11 + r22 + r12 + r21)*sqr(GeV);
double pseudoRnd = 10000.0*dummy - int(10000.0*dummy);
switch ( sel[pseudoRnd] ) {
case 1:
ret.first.first = true;
ret.second.first = true;
break;
case 2:
ret.first.first = true;
ret.second.second = true;
break;
case 3:
ret.first.second = true;
ret.second.first = true;
break;
case 4:
ret.first.second = true;
ret.second.second = true;
break;
}
}
//check for swinged emission, in which case both partons are real
if ( !(left.first->parents().second == left.second ||
left.second->parents().first == left.first) ) {
ret.first.first = true;
ret.first.second = true;
}
if ( !(right.first->parents().second == right.second ||
right.second->parents().first == right.first) ) {
ret.second.first = true;
ret.second.second = true;
}
return ret;
}
//if not single mother, all partons are on shell
return make_pair(make_pair(true, true), make_pair(true, true));
}
pair<bool, bool> DipoleXSec::int0Partons(tcPartonPtr p11, tcPartonPtr p12,
tcPartonPtr p21, tcPartonPtr p22,
const ImpactParameters & b) const {
//chose partons (pseudo-)randomly
InvEnergy2 rr11 = b.dist2(*p11, *p21);
InvEnergy2 rr22 = b.dist2(*p12, *p22);
double dummy = (rr11 + rr22)*GeV2;
while ( dummy > 100 ) dummy /= 10;
bool firstDipole = (1000000.0*dummy - long(1000000.0*dummy) > 0.5 );
bool secondDipole = (10000000.0*dummy - long(10000000.0*dummy) > 0.5 );
return make_pair(firstDipole, secondDipole);
}
void DipoleXSec::updateMomenta(RealInteraction * i) const {
if ( i->p11 ) {
pair<Energy, Energy> pm11 = i->p11->effectivePlusMinus(i->range11, true);
i->effectivePlus11 = pm11.first;
i->effectiveMinus11 = pm11.second;
}
if ( i->p12 ) {
pair<Energy, Energy> pm12 = i->p12->effectivePlusMinus(i->range12, false);
i->effectivePlus12 = pm12.first;
i->effectiveMinus12 = pm12.second;
}
if ( i->p21 ) {
pair<Energy, Energy> pm21 = i->p21->effectivePlusMinus(i->range21, true);
i->effectivePlus21 = pm21.first;
i->effectiveMinus21 = pm21.second;
}
if ( i->p22 ) {
pair<Energy, Energy> pm22 = i->p22->effectivePlusMinus(i->range22, false);
i->effectivePlus22 = pm22.first;
i->effectiveMinus22 = pm22.second;
}
}
void DipoleXSec::doTransverseRecoils(RealInteraction i, InteractionRecoil recs) const {
if ( Current<DipoleEventHandler>()->eventFiller().mode() != 1 ) {
i.lrs->totalRecoil += recs.first.first + recs.first.second;
i.rrs->totalRecoil += recs.second.first + recs.second.second;
if ( i.p11 ) i.p11->intRecoil += recs.first.first;
if ( i.p12 ) i.p12->intRecoil += recs.first.second;
if ( i.p21 ) i.p21->intRecoil += recs.second.first;
if ( i.p22 ) i.p22->intRecoil += recs.second.second;
}
if ( i.p11 ) {
if ( i.p22 ) i.p22->doEffectiveRecoil(i.p11, i.range11, true, ZERO, -recs.first.first);
else i.p21->doEffectiveRecoil(i.p11, i.range11, true, ZERO, -recs.first.first);
}
if ( i.p12 ) {
if ( i.p22 ) i.p22->doEffectiveRecoil(i.p12, i.range12, false, ZERO, -recs.first.second);
else i.p21->doEffectiveRecoil(i.p12, i.range12, false, ZERO, -recs.first.second);
}
if ( i.p21 ) {
if ( i.p12 ) i.p12->doEffectiveRecoil(i.p21, i.range21, true, ZERO, -recs.second.first);
else i.p11->doEffectiveRecoil(i.p21, i.range21, true, ZERO, -recs.second.first);
}
if ( i.p22 ) {
if ( i.p11 ) i.p11->doEffectiveRecoil(i.p22, i.range22, false, ZERO, -recs.second.second);
else i.p12->doEffectiveRecoil(i.p22, i.range22, false, ZERO, -recs.second.second);
}
}
pair<double, double> DipoleXSec::findBoosts(RealInteraction i) const {
Energy neededMinus = ZERO;
if ( checkOffShell ) neededMinus += i.lrs->neededValenceMinus();
if ( i.p11 ) neededMinus += i.p11->effectiveGiveMinus(i.range11, true);
if ( i.p12 ) neededMinus += i.p12->effectiveGiveMinus(i.range12, false);
Energy neededPlus = ZERO;
if ( checkOffShell ) neededPlus += i.rrs->neededValenceMinus();
if ( i.p21 ) neededPlus += i.p21->effectiveGiveMinus(i.range21, true);
if ( i.p22 ) neededPlus += i.p22->effectiveGiveMinus(i.range22, false);
Energy intPlus1 = ZERO;
if ( i.p11 ) intPlus1 += i.effectivePlus11;
if ( i.p12 ) intPlus1 += i.effectivePlus12;
Energy intPlus2 = ZERO;
if ( i.p21 ) intPlus2 += i.p21->inRangeMinus(i.range21, true);
if ( i.p22 ) intPlus2 += i.p22->inRangeMinus(i.range22, false);
Energy intMinus1 = ZERO;
if ( i.p11 ) intMinus1 += i.p11->inRangeMinus(i.range11, true);
if ( i.p12 ) intMinus1 += i.p12->inRangeMinus(i.range12, false);
Energy intMinus2 = ZERO;
if ( i.p21 ) intMinus2 += i.effectivePlus21;
if ( i.p22 ) intMinus2 += i.effectivePlus22;
Energy evoPlus2 = neededPlus - intPlus2;
Energy evoMinus1 = neededMinus - intMinus1;
pair<double, double> boosts = findBoosts(intPlus1, intPlus2, intMinus1, intMinus2, evoPlus2, evoMinus1);
if ( boosts.first == 0.0 || isnan(boosts.first) || isnan(boosts.second) ) {
return make_pair(0.0,0.0);
}
if ( boosts.second < 0.0 || boosts.first < 0.0 ) {
//can be over 1.0 if the valenceminus is more than needed
return make_pair(0.0,0.0);;
}
return boosts;
}
void DipoleXSec::doBoosts(RealInteraction i, pair<double, double> boosts) const {
doBoost(i.p11, i.range11, i.p12, i.range12, boosts.first);
doBoost(i.p21, i.range21, i.p22, i.range22, boosts.second);
}
void DipoleXSec::reduceRecoil(RealInteraction RI, InteractionRecoil recs) const {
//check if the interacting partons have passed each other
while ( max((RI.p11 ? RI.p11->y:RI.p12->y), (RI.p12 ? RI.p12->y:RI.p11->y)) >
-max((RI.p21 ? RI.p21->y:RI.p22->y), (RI.p22 ? RI.p22->y:RI.p21->y)) ) {
//and if the recoil is larger than 1 GeV
if ( max(max(recs.first.first.pt(), recs.first.second.pt()),
max(recs.second.first.pt(), recs.second.second.pt())) < 1*GeV ) {
break;
}
//then undo the recoil and redo 90% of it.
recs = make_pair(make_pair(-recs.first.first, -recs.first.second),
make_pair(-recs.second.first, -recs.second.second));
doTransverseRecoils(RI, recs);
recs = make_pair(make_pair(-recs.first.first*0.9, -recs.first.second*0.9),
make_pair(-recs.second.first*0.9, -recs.second.second*0.9));
doTransverseRecoils(RI, recs);
}
}
bool DipoleXSec::doInteraction(InteractionRecoil recs, const FList::const_iterator inter,
RealPartonStatePtr lrs, RealPartonStatePtr rrs,
pair<pair<bool, bool>, pair<bool, bool> > doesInt,
const ImpactParameters & b) const {
static DebugItem checkkinematics("DIPSY::CheckKinematics", 6);
if ( checkkinematics && lrs->checkForNegatives() )
Throw<InteractionKinematicException>()
<< "negatives found at start of interaction!" << Exception::warning;
if ( checkkinematics && rrs->checkForNegatives() )
Throw<InteractionKinematicException>()
<< "negatives found at start of interaction!" << Exception::warning;
RealInteraction RI = initialiseInteraction(inter->second, lrs, rrs, doesInt, b);
doTransverseRecoils(RI, recs);
if ( checkkinematics && lrs->checkForNegatives() )
Throw<InteractionKinematicException>()
<< "negatives found after transverse recoil in interaction!" << Exception::warning;
if ( checkkinematics && rrs->checkForNegatives() )
Throw<InteractionKinematicException>()
<< "negatives found after transverse recoil in interaction!" << Exception::warning;
if ( theRecoilReduction ) {
reduceRecoil(RI, recs);
}
if ( checkkinematics && lrs->checkForNegatives() )
Throw<InteractionKinematicException>()
<< "negatives found after recoil reduction in interaction!" << Exception::warning;
if ( checkkinematics && rrs->checkForNegatives() )
Throw<InteractionKinematicException>()
<< "negatives found after recoil reduction in interaction!" << Exception::warning;
updateMomenta(& RI);
if ( checkkinematics && lrs->checkForNegatives() )
Throw<InteractionKinematicException>()
<< "negatives found after update in interaction!" << Exception::warning;
if ( checkkinematics && rrs->checkForNegatives() )
Throw<InteractionKinematicException>()
<< "negatives found after update in interaction!" << Exception::warning;
pair<double, double> boosts = findBoosts(RI);
if ( boosts.first == 0.0 ) {
return false;
}
doBoosts(RI, boosts);
if ( checkkinematics && lrs->checkForNegatives() )
Throw<InteractionKinematicException>()
<< "negatives found after boost in interaction!" << Exception::warning;
if ( checkkinematics && rrs->checkForNegatives() )
Throw<InteractionKinematicException>()
<< "negatives found after boost in interaction!" << Exception::warning;
if ( ordered(RI, recs, b) ) {
setOnShell(RI);
if ( checkkinematics && lrs->checkForNegatives() )
Throw<InteractionKinematicException>()
<< "negatives found at end of interaction!" << Exception::warning;
if ( checkkinematics && rrs->checkForNegatives() )
Throw<InteractionKinematicException>()
<< "negatives found at end of interaction!" << Exception::warning;
return true;
}
return false;
}
bool DipoleXSec::checkInteractions(DipolePairVector & ints, RealPartonStatePtr lrs,
RealPartonStatePtr rrs, const ImpactParameters & b) const {
bool ok = true;
list<pair<RealInteraction, pair<double, double> > > boostList;
for ( int i = 0; i < int(ints.size()); i++ ) {
RealInteraction RI = initialiseInteraction(ints[i]->second, lrs, rrs,
make_pair(make_pair(true, true),make_pair(true, true)), b);
InteractionRecoil recs = recoil(ints[i]->second.first->partons(),
ints[i]->second.second->partons(), b,
make_pair(make_pair(true, true), make_pair(true, true)));
doTransverseRecoils(RI, recs);
updateMomenta(& RI);
pair<double, double> boosts = findBoosts(RI);
if ( boosts.first == 0.0 ) {
undoPTRecoils(RI);
ok = false;
break;
}
doBoosts(RI, boosts);
boostList.push_back(make_pair(RI, boosts));
if ( !ordered(RI, recs, b) ) {
ok = false;
break;
}
}
for ( list<pair<RealInteraction, pair<double, double> > >::iterator it = boostList.begin();
it != boostList.end(); it++ ) {
pair<double, double> inverse = make_pair(1.0/it->second.first, 1.0/it->second.second);
doBoosts(it->first, inverse);
undoPTRecoils(it->first);
}
return ok;
}
void DipoleXSec::undoPTRecoils(RealInteraction RI) const {
RI.p11->undoInteractionRecoils();
RI.p12->undoInteractionRecoils();
RI.p21->undoInteractionRecoils();
RI.p22->undoInteractionRecoils();
}
bool DipoleXSec::performInteractions(DipolePairVector & ints, RealPartonStatePtr lrs,
RealPartonStatePtr rrs, const ImpactParameters & b) const {
return true;
}
bool DipoleXSec::ordered(RealInteraction i, InteractionRecoil recs,
const ImpactParameters & b) const {
//this options means only momentum conservation, and that is already checked by
//finding a boost. no extra ordering wanted.
if ( theIntOrdering == 2 ) {
return true;
}
double PSInf = Current<DipoleEventHandler>()->emitter().PSInflation();
bool ordered = true;
bool both = Current<DipoleEventHandler>()->emitter().bothOrderedFS();
//if not a local pt max, check p+- ordering
if ( theIntOrdering == 0 ) {
if ( theInteraction == 0 ) {
//check ordering only for the key partons
pair<bool, bool> ints0 = int0Partons(i.d1->partons().first, i.d1->partons().second,
i.d2->partons().first, i.d2->partons().second, b);
Energy effMinus1 = (ints0.first ? i.effectiveMinus11:i.effectiveMinus12);
Energy effMinus2 = (ints0.second ? i.effectiveMinus21:i.effectiveMinus22);
Energy effPlus1 = (ints0.first ? i.effectivePlus11:i.effectivePlus12);
Energy effPlus2 = (ints0.second ? i.effectivePlus21:i.effectivePlus22);
if ( effPlus1*PSInf < effMinus2 ) ordered = false;
if ( effPlus2*PSInf < effMinus1 ) ordered = false;
}
else {
if ( !i.max11 && i.p11 && i.p21 ) {
if ( i.effectivePlus11*PSInf < i.effectiveMinus21*(both ? 1.0:i.P11) ) ordered = false;
if ( (both ? 1.0:i.P11)*i.effectiveMinus11/PSInf > i.effectivePlus21 ) ordered = false;
}
if ( !i.max12 && i.p11 && i.p22 ) {
if ( i.effectivePlus11*PSInf < i.effectiveMinus22*(both ? 1.0:i.P12) ) ordered = false;
if ( (both ? 1.0:i.P12)*i.effectiveMinus11/PSInf > i.effectivePlus22 ) ordered = false;
}
if ( !i.max21 && i.p12 && i.p21 ) {
if ( i.effectivePlus12*PSInf < i.effectiveMinus21*(both ? 1.0:i.P21) ) ordered = false;
if ( (both ? 1.0:i.P21)*i.effectiveMinus12/PSInf > i.effectivePlus21 ) ordered = false;
}
if ( !i.max22 && i.p12 && i.p22 ) {
if ( i.effectivePlus12*PSInf < i.effectiveMinus22*(both ? 1.0:i.P22) ) ordered = false;
if ( (both ? 1.0:i.P22)*i.effectiveMinus12/PSInf > i.effectivePlus22 ) ordered = false;
}
}
}
if ( theIntOrdering == 1 && theInteraction == 0 ) {
double PMOrd = Current<DipoleEventHandler>()->emitter().PMinusOrdering();
//check ordering only for the key partons
pair<bool, bool> ints0 = int0Partons(i.d1->partons().first, i.d1->partons().second,
i.d2->partons().first, i.d2->partons().second, b);
Energy effMinus1 = (ints0.first ? i.effectiveMinus11:i.effectiveMinus12);
Energy effMinus2 = (ints0.second ? i.effectiveMinus21:i.effectiveMinus22);
Energy rec1 = (ints0.first ? recs.first.first.pt():recs.first.second.pt());
Energy rec2 = (ints0.second ? recs.second.first.pt():recs.second.second.pt());
if ( sqr(max(rec1, rec2)*PSInf) < effMinus1*effMinus2*PMOrd ) ordered = false;
}
if ( (i.p11 && i.p11->searchNegative(i.range11, true)) ||
(i.p12 && i.p12->searchNegative(i.range12, false)) ||
(i.p21 && i.p21->searchNegative(i.range21, true)) ||
(i.p22 && i.p22->searchNegative(i.range22, false)) )
ordered = false;
return ordered;
}
void DipoleXSec::setOnShell(RealInteraction i) const {
if ( i.p11 ) i.p11->effectiveGiveMinus(i.range11, true);
if ( i.p12 ) i.p12->effectiveGiveMinus(i.range12, false);
if ( i.p21 ) i.p21->effectiveGiveMinus(i.range21, true);
if ( i.p22 ) i.p22->effectiveGiveMinus(i.range22, false);
}
bool DipoleXSec::checkOrderedInteraction(tRealPartonPtr p11, tRealPartonPtr p12,
tRealPartonPtr p21, tRealPartonPtr p22) const {
InvEnergy range11 = sqrt(min(min(p11->theParton->dist2(*p21->theParton),
p11->theParton->dist2(*p22->theParton)),
p11->theParton->dist2(*p12->theParton)/4.0));
InvEnergy range12 = sqrt(min(min(p12->theParton->dist2(*p21->theParton),
p12->theParton->dist2(*p22->theParton)),
p12->theParton->dist2(*p11->theParton)/4.0));
InvEnergy range21 = sqrt(min(min(p21->theParton->dist2(*p11->theParton),
p21->theParton->dist2(*p12->theParton)),
p21->theParton->dist2(*p22->theParton)/4.0));
InvEnergy range22 = sqrt(min(min(p22->theParton->dist2(*p11->theParton),
p22->theParton->dist2(*p12->theParton)),
p22->theParton->dist2(*p21->theParton)/4.0));
pair<Energy, Energy> pm11 = p11->effectivePlusMinus(range11, true);
pair<Energy, Energy> pm12 = p12->effectivePlusMinus(range12, false);
pair<Energy, Energy> pm21 = p21->effectivePlusMinus(range21, true);
pair<Energy, Energy> pm22 = p22->effectivePlusMinus(range22, false);
InvEnergy2 rr11 = p11->theParton->dist2(*p21->theParton);
InvEnergy2 rr12 = p11->theParton->dist2(*p22->theParton);
InvEnergy2 rr21 = p12->theParton->dist2(*p21->theParton);
InvEnergy2 rr22 = p12->theParton->dist2(*p22->theParton);
bool max11 = p11->mothers.first && rr11 < p11->theParton->dist2(*p11->mothers.first->theParton) &&
p21->mothers.first && rr11 < p21->theParton->dist2(*p21->mothers.first->theParton);
bool max12 = p11->mothers.first && rr12 < p11->theParton->dist2(*p11->mothers.first->theParton) &&
p22->mothers.first && rr12 < p22->theParton->dist2(*p22->mothers.first->theParton);
bool max21 = p12->mothers.first && rr21 < p21->theParton->dist2(*p21->mothers.first->theParton) &&
p21->mothers.first && rr21 < p21->theParton->dist2(*p21->mothers.first->theParton);
bool max22 = p12->mothers.first && rr22 < p12->theParton->dist2(*p12->mothers.first->theParton) &&
p22->mothers.first && rr22 < p22->theParton->dist2(*p22->mothers.first->theParton);
Energy2 den = (1./rr11 + 1./rr12 + 1./rr21 + 1./rr22);
double P11 = (1./rr11)/den;
double P12 = (1./rr12)/den;
double P21 = (1./rr21)/den;
double P22 = (1./rr22)/den;
double PSInf = Current<DipoleEventHandler>()->emitter().PSInflation();
bool ordered = true;
//if p11-p22 is not a local pt max, check p+- ordering
if ( !max11 ) {
if ( pm11.first*PSInf/P11 < pm21.second ) ordered = false;
if ( P11*pm11.second/PSInf > pm21.first ) ordered = false;
}
if ( !max12 ) {
if ( pm11.first*PSInf/P12 < pm22.second ) ordered = false;
if ( P12*pm11.second/PSInf > pm22.first ) ordered = false;
}
if ( !max21 ) {
if ( pm12.first*PSInf/P21 < pm21.second ) ordered = false;
if ( P21*pm12.second/PSInf > pm21.first ) ordered = false;
}
if ( !max22 ) {
if ( pm12.first*PSInf/P22 < pm22.second ) ordered = false;
if ( P22*pm12.second/PSInf > pm22.first ) ordered = false;
}
return ordered;
}
bool DipoleXSec::reconnect(tDipolePtr d1, tDipolePtr d2) const {
if ( d1->children().second && !d1->children().first ) {
return reconnect(d1->children().second, d2);
}
if ( d2->children().second && !d2->children().first ) {
return reconnect(d1, d2->children().second);
}
if ( !d1->children().first && !d2->children().first ) { //none has rescattered
d1->swingDipole(d2);
Current<DipoleEventHandler>()->swinger().recombine(*d1);
d1->children().first->interact(*d2->children().first);
d2->children().first->interact(*d1->children().first);
return true;
}
tPartonPtr p11 = d1->partons().first;
tPartonPtr p12 = d1->partons().second;
tPartonPtr p21 = d2->partons().first;
tPartonPtr p22 = d2->partons().second;
tDipolePtr d11 = p11->dipoles().second;
tDipolePtr d12 = p12->dipoles().first;
tDipolePtr d21 = p21->dipoles().second;
tDipolePtr d22 = p22->dipoles().first;
tDipolePtr swing1;
tDipolePtr swing2;
if ( d11 == d12 ) d1 = d11; //dipole has swinged back
if ( d21 == d22 ) d2 = d21;
if ( !d1->children().first && !d2->children().first ) { //both are original dipole
swing1 = d1;
swing2 = d2;
}
else if ( d1->children().first && !d2->children().first ) { //one dip d1 is rescattering
tDipolePtr temp = d1;
d1 = d2;
d2 = temp;
p11 = d1->partons().first;
p12 = d1->partons().second;
p21 = d2->partons().first;
p22 = d2->partons().second;
d11 = p11->dipoles().second;
d12 = p12->dipoles().first;
d21 = p21->dipoles().second;
d22 = p22->dipoles().first;
}
if ( !d1->children().first && d2->children().first ) { //one dip d2 is rescattering
if ( p11 != d21->partons().second && p12 != d22->partons().first ) {
//no connections, swing with one of the two randomly
swing1 = d1;
if ( UseRandom::rnd() > 0.5 ) swing2 = d21;
else swing2 = d22;
}
else if ( p11 == d21->partons().second && p12 != d22->partons().first ) {
//share one swinged dip, swing with the other
swing1 = d1;
swing2 = d22;
}
else if ( p11 != d21->partons().second && p12 == d22->partons().first ) {
//share other swinged dip, swing with the first
swing1 = d1;
swing2 = d21;
}
else if ( p11 == d21->partons().second && p12 == d22->partons().first ) {
//share both swinged dip, swing back to original
swing1 = d21;
swing2 = d22;
}
}
else if ( d1->children().first && d2->children().first ) { //both dips are rescattering
bool found = false;
int i = 0;
while ( !found && i < 1000 ) {
if ( UseRandom::rnd() > 0.5 ) swing1 = d11;
else swing1 = d12;
if ( UseRandom::rnd() > 0.5 ) swing2 = d21;
else swing2 = d22;
if ( swing1 != swing2 && swing1->partons().first != swing2->partons().second &&
swing2->partons().first != swing1->partons().second )
found = true;
}
}
if ( !swing1 || !swing2 ) {
d1->dipoleState().diagnosis(true);
return false;
}
swing1->swingDipole(swing2);
Current<DipoleEventHandler>()->swinger().recombine(*swing1);
swing1->children().first->interact(*swing2->children().first);
swing2->children().first->interact(*swing1->children().first);
return true;
}
vector<pair<DipolePtr, DipolePtr> >
DipoleXSec::getColourExchanges(tRealPartonStatePtr lrs, tRealPartonStatePtr rrs) const {
vector<pair<DipolePtr, DipolePtr> > ret;
while ( ret.empty() ) {
list<tDipolePtr>::iterator rightDip = rrs->interactions.begin();
for ( list<tDipolePtr>::iterator leftDip = lrs->interactions.begin();
leftDip != lrs->interactions.end(); leftDip++, rightDip++ ) {
if ( unitarize(fij((*leftDip)->partons(), (*rightDip)->partons(),
ImpactParameters(), false))*0.99
< UseRandom::rnd() || true )
ret.push_back(make_pair(*leftDip, *rightDip));
}
}
return ret;
}
pair< double, double> DipoleXSec::findBoosts(Energy intPlus1, Energy intPlus2,
Energy intMinus1, Energy intMinus2,
Energy evoPlus2, Energy evoMinus1) const {
Energy2 A = (intPlus1 - evoPlus2)*intMinus2;
Energy2 B = intPlus1*(evoMinus1 + intMinus1 - intMinus2) -
evoPlus2*(evoMinus1 - intMinus2) - intPlus2*intMinus2;
Energy2 C = -intPlus2*(evoMinus1 - intMinus2);
if ( sqr(B/(2*A)) - C/A < 0.0 ) return make_pair(0.0, 0.0);
double y = -B/(2*A) + sqrt(sqr(B/(2*A)) - C/A); //is the + sqrt() always the right solution?
double x = 1.0 - intPlus2/(y*intPlus1) - evoPlus2/intPlus1;
return make_pair(x, y);
}
void DipoleXSec::doBoost(tRealPartonPtr p1, InvEnergy range1,
tRealPartonPtr p2, InvEnergy range2, double x) const {
//we here have to use the plusweighted recoil to fit the x, y above.
//Other weights get a lot more complicated equations for the boosts.
if ( p1 ) {
pair<Energy, Energy> pm1 = p1->effectivePlusMinus(range1, true);
p1->doPlusWeightedRecoil(p1, range1, true, (1.0 - x)*pm1.first, TransverseMomentum());
}
if ( p2 ) {
pair<Energy, Energy> pm2 = p2->effectivePlusMinus(range2, false);
p2->doPlusWeightedRecoil(p2, range2, false, (1.0 - x)*pm2.first, TransverseMomentum());
}
}
double DipoleXSec::unitarize(double f) const {
return Math::exp1m(-f);
}
void DipoleXSec::persistentOutput(PersistentOStream & os) const {
os << ounit(theRMax, InvGeV) << theInteraction << theIntOrdering
<< theRecoilReduction << checkOffShell;
}
void DipoleXSec::persistentInput(PersistentIStream & is, int) {
is >> iunit(theRMax, InvGeV) >> theInteraction >> theIntOrdering
>> theRecoilReduction >> checkOffShell;
}
// Static variable needed for the type description system in ThePEG.
#include "ThePEG/Utilities/DescribeClass.h"
DescribeClass<DipoleXSec,HandlerBase>
- describeDIPSYDipoleXSec("DIPSY::DipoleXSec", "libDIPSY.so");
+ describeDIPSYDipoleXSec("DIPSY::DipoleXSec", "libAriadne5.so libDIPSY.so");
void DipoleXSec::Init() {
static ClassDocumentation<DipoleXSec> documentation
("There is no documentation for the DipoleXSec class");
static Parameter<DipoleXSec,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.",
&DipoleXSec::theRMax, InvGeV, 0.0*InvGeV, 0.0*InvGeV, 0*InvGeV,
true, false, Interface::lowerlim);
static Parameter<DipoleXSec, int> interfaceInteraction
("Interaction",
"Which interaction to be used. Determines f_{ij} and recoils. "
"0 is the sinus interaction with 4 identical recoils"
"1 is the sinus interaction with recoils between all 4 parton pairs"
"2 is the swing interaction"
"3 is the sinus interaction with recoils between the 2 parton pairs"
" that get the new dipoles",
&DipoleXSec::theInteraction, 1, 1, 0, 0,
true, false, Interface::lowerlim);
static Switch<DipoleXSec,int> interfaceIntOrdering
("IntOrdering",
"How the real state is found from the virtual cascade. Speed versus consistency.",
&DipoleXSec::theIntOrdering, 0, true, false);
static SwitchOption interfaceIntOrderingDefault
(interfaceIntOrdering,
"Default",
"plus and minus reuired to be ordered after all recoils.",
0);
static SwitchOption interfaceIntOrderingAsEvo
(interfaceIntOrdering,
"AsEvo",
"Try to emulate the ordering in the evolution by requesting ordering"
" on the colliding particle if it would've been part of the cascade."
" That is, ignore recoils from the colliding cascade.",
1);
static SwitchOption interfaceIntOrderingVeryOpen
(interfaceIntOrdering,
"VeryOpen",
"Only checks that there is enough energy to put the interaction recoil on shell."
" Does not care about ordering, or setting evolution pt on shell. Same as Emils code.",
2);
static Switch<DipoleXSec,int> interfaceRecoilReduction
("RecoilReduction",
"What to do with large recoils",
&DipoleXSec::theRecoilReduction, 0, true, false);
static SwitchOption interfaceRecoilReductionOff
(interfaceRecoilReduction,
"Off",
"Do nothing special.",
0);
static SwitchOption interfaceRecoilReductionRapidityOrdered
(interfaceRecoilReduction,
"RapidityOrdered",
"Reduce the recoil until all interacting partons are rapidity ordered with each other.",
1);
static Switch<DipoleXSec,bool> interfaceCheckOffShell
("CheckOffShell",
"Make sure there is energy available to put incoming particles on-shell. Only necessary for virtual photons.",
&DipoleXSec::checkOffShell, true, true, false);
static SwitchOption interfaceCheckOffShellYes
(interfaceCheckOffShell,
"Yes",
"Do the check",
true);
static SwitchOption interfaceCheckOffShellNo
(interfaceCheckOffShell,
"No",
"No check is made.",
false);
}
diff --git a/DIPSY/EffectiveParton.cc b/DIPSY/EffectiveParton.cc
--- a/DIPSY/EffectiveParton.cc
+++ b/DIPSY/EffectiveParton.cc
@@ -1,467 +1,467 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the EffectiveParton class.
//
#include "EffectiveParton.h"
#include "Dipole.h"
#include "DipoleState.h"
#include "DipoleEventHandler.h"
#include "ThePEG/Utilities/Current.h"
#include "ThePEG/Utilities/Throw.h"
#include "ThePEG/Utilities/MaxCmp.h"
#include "ThePEG/Utilities/UnitIO.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace DIPSY;
EffectiveParton::EffectiveParton() {}
template <typename T>
bool sortof(const T & t1, const T & t2) {
return sqr(t1 - t2 ) <= 1.0e-16*sqr(t1 + t2);
}
template <typename T>
bool sortof(const pair<T,T> & t1, const pair<T,T> & t2) {
return sortof(t1.first, t2.first) && sortof(t1.second, t2.second);
}
template <typename T>
bool sortof(const Transverse<T> & t1, const Transverse<T> & t2) {
return sortof(t1.first, t2.first) && sortof(t1.second, t2.second);
}
EffectiveParton::EffectiveParton(Parton & p): Parton(p) {}
void EffectiveParton::uncache() {
plus(cache[currange].plus);
pT(cache[currange].pT);
y(cache[currange].y);
minus(cache[currange].minus);
dipoles(cache[currange].dipair);
}
void EffectiveParton::recache() {
for ( int ir = 0, Nr = cache.size(); ir < Nr; ++ir ) {
cache[ir].plus = ZERO;
cache[ir].pT = TransverseMomentum();
for ( int i = 0, N = cache[ir].partons.size(); i < N; ++i ) {
cache[ir].plus += cache[ir].partons[i]->plus();
cache[ir].pT += cache[ir].partons[i]->pT();
}
cache[ir].y = log(cache[ir].pT.pt()/cache[ir].plus);
cache[ir].minus = cache[ir].pT.pt()*exp(cache[ir].y);
}
uncache();
}
/*
void EffectiveParton::checkCache() const {
if ( cache.empty() ) return;
if ( internalPartons().empty() ) return;
if ( !sortof(plus(), cache[currange].plus) )
breakThePEG();
if ( !sortof(pT(), cache[currange].pT) )
breakThePEG();
if (internalPartons().size() != cache[currange].partons.size() )
breakThePEG();
set<tPartonPtr> ps = internalPartons();
for ( int i = 0, N = cache[currange].partons.size(); i < N; ++i )
if ( !ps.erase(cache[currange].partons[i]) ) breakThePEG();
if (theInternalDipoles.size() != cache[currange].dipoles.size() )
breakThePEG();
else
for ( int i = 0, N = cache[currange].dipoles.size(); i < N; ++i )
if ( cache[currange].dipoles[i] != theInternalDipoles[i] )
breakThePEG();
if ( dipoles().first != cache[currange].dipair.first ||
dipoles().second != cache[currange].dipair.second )
breakThePEG();
}
*/
EffectivePartonPtr EffectiveParton::create(Parton & p, InvEnergy range) {
EffectivePartonPtr effp = new_ptr(EffectiveParton(p));
effp->theOriginalParton = & p;
if ( Current<DipoleEventHandler>()->effectivePartonMode() >= 2 )
effp->setupCache(range);
else
effp->setRange(range);
while ( effp->pT().pt() <= 10.0*Constants::epsilon*p.pT().pt() ) {
MaxCmp<InvEnergy2> maxdist;
// If pt is zero, shrink the range below the parton which is furthest away.
for ( set<tPartonPtr>::const_iterator it = effp->internalPartons().begin();
it != effp->internalPartons().end(); ++it )
maxdist(effp->dist2(**it));
effp->setRange((1.0 - 10.0*Constants::epsilon)*sqrt(maxdist.value()));
}
effp->y(log(effp->pT().pt()/effp->plus()));
effp->minus(effp->pT().pt2()/effp->plus());
return effp;
}
EffectiveParton::~EffectiveParton() {}
-Ariadne::ClonePtr EffectiveParton::clone() const {
+Ariadne5::ClonePtr EffectiveParton::clone() const {
return new_ptr(*this);
}
void EffectiveParton::rebind(const TranslationMap & trans) {
theOriginalParton = trans.translate(theOriginalParton);
vector<tDipolePtr> idips;
idips.swap(theInternalDipoles);
trans.translate(inserter(theInternalDipoles), idips.begin(), idips.end());
set<tPartonPtr> ipars;
ipars.swap(theInternalPartons);
trans.translate(inserter(theInternalPartons), ipars.begin(), ipars.end());
for ( int ir = 0, Nr = cache.size(); ir < Nr; ++ir ) {
vector<tPartonPtr> pv;
pv.swap(cache[ir].partons);
trans.translate(inserter(cache[ir].partons), pv.begin(), pv.end());
vector<tDipolePtr> dv;
dv.swap(cache[ir].dipoles);
trans.translate(inserter(cache[ir].dipoles), dv.begin(), dv.end());
cache[ir].dipair.first = trans.translate(cache[ir].dipair.first);
cache[ir].dipair.second = trans.translate(cache[ir].dipair.second);
}
}
void EffectiveParton::printData() {
const set<tPartonPtr> & partons = internalPartons();
Energy sum = 0.0*GeV;
for ( set<tPartonPtr>::const_iterator it = partons.begin();
it != partons.end(); it++ ) {
tPartonPtr p = *it;
sum += p->plus();
}
if ( abs(sum/plus() - 1.0) > 0.000001 || true ) {
for ( set<tPartonPtr>::iterator it = partons.begin(); it != partons.end(); it++ ) {
tPartonPtr p = *it;
}
}
}
void EffectiveParton::setRange( InvEnergy range ) {
if ( cache.size() ) {
currange = 1;
while ( currange < int(cache.size()) &&
sqr(range) >= cache[currange].range ) ++currange;
--currange;
uncache();
return;
}
theInternalDipoles.clear();
theInternalPartons.clear();
dipoles( theOriginalParton->dipoles() );
addPartons(range);
if ( cache.size() ) uncache();
}
void EffectiveParton::setupCache(InvEnergy maxrange) {
if ( maxrange > Current<DipoleEventHandler>()->coherenceRange() )
maxrange = Current<DipoleEventHandler>()->coherenceRange();
InvEnergy2 cut = sqr(maxrange);
cache.clear();
cache.resize(1);
cache.back().range = ZERO;
cache.back().plus = theOriginalParton->plus();
cache.back().pT = theOriginalParton->pT();
cache.back().partons.push_back(theOriginalParton);
cache.back().dipair = dipoles();
pair<InvEnergy2,InvEnergy2> ranges(cut*2.0, cut*2.0);
pair<tDipolePtr, tDipolePtr> dips = dipoles();
if ( dips.first && dips.first->partons().first != theOriginalParton )
ranges.first = dips.first->partons().first->dist2(*this);
if ( dips.second && dips.second->partons().second != theOriginalParton )
ranges.second = dips.second->partons().second->dist2(*this);
while ( min(ranges.first, ranges.second) <= cut ) {
tPartonPtr mergeparton;
tDipolePtr mergedipole;
InvEnergy2 range = ZERO;
if ( ranges.first < ranges.second ) {
mergeparton = dips.first->partons().first;
range = ranges.first;
mergedipole = dips.first;
dips.first = dips.first->neighbors().first;
if ( dips.first && dips.first->partons().first != theOriginalParton )
ranges.first = dips.first->partons().first->dist2(*this);
} else {
mergeparton = dips.second->partons().second;
range = ranges.second;
mergedipole = dips.second;
dips.second = dips.second->neighbors().second;
if ( dips.second && dips.second->partons().second != theOriginalParton )
ranges.second = dips.second->partons().second->dist2(*this);
}
if ( range > cache.back().range ) {
cache.resize(cache.size() + 1, cache.back());
cache.back().range = range;
}
cache.back().partons.push_back(mergeparton);
cache.back().dipoles.push_back(mergedipole);
cache.back().dipair = dips;
}
currange = cache.size() - 1;
recache();
}
void EffectiveParton::addPartons( InvEnergy range ) {
if ( range > Current<DipoleEventHandler>()->coherenceRange() )
range = Current<DipoleEventHandler>()->coherenceRange();
if ( Current<DipoleEventHandler>()->effectivePartonMode() == 1 )
return addRelatives(range, theOriginalParton);
PartonPtr mergeParton;
if ( dipoles().first &&
dipoles().first->partons().first->dist2( *this ) <= sqr(range) &&
dipoles().first->partons().first != theOriginalParton ) {
mergeParton = dipoles().first->partons().first;
theInternalDipoles.push_back( dipoles().first );
dipoles( make_pair(dipoles().first->neighbors().first, dipoles().second));
addPartons( range );
}
else if ( dipoles().second &&
dipoles().second->partons().second->dist2( *this ) <= sqr(range) &&
dipoles().second->partons().second != theOriginalParton ) {
mergeParton = dipoles().second->partons().second;
theInternalDipoles.push_back( dipoles().second );
dipoles( make_pair(dipoles().first, dipoles().second->neighbors().second));
addPartons( range );
}
if ( mergeParton ) merge(mergeParton);
else {
plus(ZERO);
pT(TransverseMomentum());
merge(theOriginalParton);
}
}
void EffectiveParton::addRelatives( InvEnergy range, tPartonPtr p ) {
if ( !p ) return;
//if already added, dont do anything
if ( theInternalPartons.find(p) != theInternalPartons.end() ) return;
//we may only have one valence in an effective parton
//if not in range, dont do anything
if ( p->dist2(*this) > sqr(range) ) return;
//otherwise add the new parton
merge(p);
//and recur to parents and children in range
addRelatives(range, p->parents().first);
addRelatives(range, p->parents().second);
if ( p->children().empty() ) return;
const set<tPartonPtr> & kids = p->children();
for ( set<tPartonPtr>::const_iterator it = kids.begin();
it != kids.end(); it++) {
addRelatives(range, *it);
}
}
void EffectiveParton::merge(tPartonPtr p) {
// if ( theInternalPartons.find(p) != theInternalPartons.end() ) return;
if ( theInternalPartons.empty() ) {
plus(ZERO);
pT(TransverseMomentum());
}
if ( theInternalPartons.insert(p).second ) {
plus( plus() + p->plus() );
pT( pT() + p->pT() );
}
}
bool EffectiveParton::changed() {
if ( cache.size() ) {
for ( int i = 0, N = cache[currange].dipoles.size(); i < N; ++i )
if ( cache[currange].dipoles[i]->children().first ||
cache[currange].dipoles[i]->children().second )
return true;
} else {
for (int i = 0; i < int(theInternalDipoles.size()); i++ ) {
if ( theInternalDipoles[i]->children().first ||
theInternalDipoles[i]->children().second ) {
return true;
}
}
}
if ( (dipoles().first && dipoles().first->children().first) ||
(dipoles().first && dipoles().first->children().second) ||
(dipoles().second && dipoles().second->children().first) ||
(dipoles().second && dipoles().second->children().second) ) {
return true;
}
TransverseMomentum sum = TransverseMomentum();
if ( cache.size() ) {
for ( int i = 0, N = cache[currange].partons.size(); i < N; ++i )
sum += cache[currange].partons[i]->pT();
} else {
const set<tPartonPtr> & partons = internalPartons();
for ( set<tPartonPtr>::const_iterator it = partons.begin();
it != partons.end(); it++ ) {
tPartonPtr p = *it;
sum += p->pT();
}
}
if ( (sum - pT()).pt() > 0.000000001*GeV ) return true;
return false;
}
bool EffectiveParton::
recoilsOverYMax(TransverseMomentum recoilPT,
Energy recoilPlus, double yMax) const {
if ( cache.size() ) {
for ( int i = 0, N = cache[currange].partons.size(); i < N; ++i ) {
tPartonPtr p = cache[currange].partons[i];
if ( p != theOriginalParton &&
log(p->pT().pt()/(p->plus() - recoilPlus*p->plus()/plus())) > yMax )
return true;
}
} else {
const set<tPartonPtr> & partons = internalPartons();
for ( set<tPartonPtr>::const_iterator it = partons.begin();
it != partons.end(); it++ ) {
tPartonPtr p = *it;
if ( p != theOriginalParton &&
log( p->pT().pt()/(p->plus() - recoilPlus*p->plus()/plus()) ) > yMax )
return true;
}
}
if ( log( (theOriginalParton->pT() - recoilPT).pt()/
(theOriginalParton->plus()*(1.0 - recoilPlus/plus())) ) > yMax )
return true;
return false;
}
void EffectiveParton::recoil( TransverseMomentum recoilPT, Energy recoilPlus ) {
int opteffw = Current<DipoleEventHandler>()->eventFiller().effectiveWeights();
if ( cache.size() ) {
for ( int i = 0, N = cache[currange].partons.size(); i < N; ++i ) {
tPartonPtr p = cache[currange].partons[i];
if ( opteffw == 0 )
p->pT( p->pT() - recoilPT*p->plus()/plus() );
else if ( opteffw == 1 )
p->pT( p->pT() - recoilPT/double(N) );
else if ( opteffw == 2 ) {
if ( p == theOriginalParton ) p->pT( p->pT() - recoilPT );
}
p->plus( p->plus() - recoilPlus*p->plus()/plus() );
p->y( log(p->pT().pt()/p->plus()) );
p->minus( p->pT().pt()*exp(p->y()) );
}
recache();
} else {
const set<tPartonPtr> & partons = internalPartons();
for ( set<tPartonPtr>::const_iterator it = partons.begin();
it != partons.end(); it++ ) {
tPartonPtr p = *it;
if ( opteffw == 0 )
p->pT( p->pT() - recoilPT*p->plus()/plus() );
else if ( opteffw == 1 )
p->pT( p->pT() - recoilPT/double(partons.size()) );
else if ( opteffw == 2 ) {
if ( p == theOriginalParton ) p->pT( p->pT() - recoilPT );
}
p->plus( p->plus() - recoilPlus*p->plus()/plus() );
p->y( log(p->pT().pt()/p->plus()) );
p->minus( p->pT().pt()*exp(p->y()) );
}
pT( pT() - recoilPT );
plus( plus() - recoilPlus );
y( log(pT().pt()/plus()) );
minus( pT().pt()*exp(y()) );
}
}
void EffectiveParton::newRecoil( Energy recoilPlus ) {
//first update pT of the original parton (the only pt that changes, since
// its the only dipole that changes.)
theOriginalParton->updateMomentum();
//then recoil plus, and update y and minus correspondingly
if ( cache.size() ) {
for ( int i = 0, N = cache[currange].partons.size(); i < N; ++i ) {
tPartonPtr p = cache[currange].partons[i];
p->plus( p->plus() - recoilPlus*p->plus()/plus() );
p->y( log(p->pT().pt()/p->plus()) );
if ( p->y() > 0.0 )
p->minus( p->pT().pt()*exp(p->y()) );
}
} else {
const set<tPartonPtr> & partons = internalPartons();
for ( set<tPartonPtr>::const_iterator it = partons.begin();
it != partons.end(); it++ ) {
tPartonPtr p = *it;
p->plus( p->plus() - recoilPlus*p->plus()/plus() );
p->y( log(p->pT().pt()/p->plus()) );
if ( p->y() > 0.0 )
p->minus( p->pT().pt()*exp(p->y()) );
}
}
//update total momentum
plus( plus() - recoilPlus );
updateMomentum();
}
bool EffectiveParton::checkSums() const {
TransverseMomentum sumPT = TransverseMomentum();
Energy sumPlus = ZERO;
if ( cache.size() ) {
for ( int i = 0, N = cache[currange].partons.size(); i < N; ++i ) {
sumPT += cache[currange].partons[i]->pT();
sumPlus += cache[currange].partons[i]->plus();
}
} else {
const set<tPartonPtr> & partons = internalPartons();
for ( set<tPartonPtr>::const_iterator it = partons.begin();
it != partons.end(); it ++ ) {
sumPT += (*it)->pT();
sumPlus += (*it)->plus();
}
}
if ( (sumPT - pT()).pt() > 0.00000001*GeV ) {
dipoles().first->dipoleState().diagnosis(true);
return false;
}
if ( abs(sumPlus - plus()) > 0.00000001*GeV ) {
return false;
}
return true;
}
void EffectiveParton::persistentOutput(PersistentOStream & os) const {
os << theOriginalParton << theInternalDipoles << theInternalPartons;
os << cache.size();
for ( int ir = 0, Nr = cache.size(); ir < Nr; ++ ir )
os << ounit(cache[ir].range, sqr(InvGeV)) << ounit(cache[ir].pT, GeV)
<< ounit(cache[ir].plus, GeV) << ounit(cache[ir].minus, GeV)
<< cache[ir].partons << cache[ir].y << cache[ir].dipoles
<< cache[ir].dipair;
}
void EffectiveParton::persistentInput(PersistentIStream & is, int) {
is >> theOriginalParton >> theInternalDipoles >> theInternalPartons;
long Nr = 0;
is >> Nr;
cache.resize(Nr);
for ( int ir = 0; ir < Nr; ++ ir )
is >> iunit(cache[ir].range, sqr(InvGeV)) >> iunit(cache[ir].pT, GeV)
>> iunit(cache[ir].plus, GeV) >> iunit(cache[ir].minus, GeV)
>> cache[ir].partons >> cache[ir].y >> cache[ir].dipoles
>> cache[ir].dipair;
}
// Static variable needed for the type description system in ThePEG.
#include "ThePEG/Utilities/DescribeClass.h"
DescribeClass<EffectiveParton,DIPSY::Parton>
- describeDIPSYEffectiveParton("DIPSY::EffectiveParton", "libDIPSY.so");
+ describeDIPSYEffectiveParton("DIPSY::EffectiveParton", "libAriadne5.so libDIPSY.so");
void EffectiveParton::Init() {}
diff --git a/DIPSY/EffectiveParton.h b/DIPSY/EffectiveParton.h
--- a/DIPSY/EffectiveParton.h
+++ b/DIPSY/EffectiveParton.h
@@ -1,288 +1,288 @@
// -*- C++ -*-
#ifndef DIPSY_EffectiveParton_H
#define DIPSY_EffectiveParton_H
//
// This is the declaration of the EffectiveParton class.
//
#include "Ariadne/DIPSY/Parton.h"
#include "Ariadne/DIPSY/EffectiveParton.fh"
namespace DIPSY {
using namespace ThePEG;
/**
* An effective parton is a colour chain of partons that are close
* enough to each other so that the neighbouring dipole can't really
* resolve them.
*/
class EffectiveParton: public Parton {
public:
/**
* Caching info for Partons.
*/
struct RangeInfo {
/**
* The range at which the number of partons included changes.
*/
InvEnergy2 range;
/**
* The effective transverse momentum at this range;
*/
TransverseMomentum pT;
/**
* The effective positive light-cone momentum at this range.
*/
Energy plus;
/**
* The effective negative light-cone momentum at this range.
*/
Energy minus;
/**
* The effective rapidity for this range.
*/
double y;
/**
* Included partons.
*/
vector<tPartonPtr> partons;
/**
* Included dipoles.
*/
vector<tDipolePtr> dipoles;
/**
* The external connecting dipoles.
*/
pair<tDipolePtr,tDipolePtr> dipair;
};
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
EffectiveParton();
/**
* Constructs an effective parton for \a p.
*/
EffectiveParton(Parton & p);
/**
* Static creation method that also performs
* initialization. Constructs an effective parton around p,
* including other partons within range.
*/
static EffectivePartonPtr create(Parton & p, InvEnergy range);
/**
* The destructor.
*/
virtual ~EffectiveParton();
//@}
protected:
/**
* Setup the and access cache of range information.
*/
void setupCache(InvEnergy maxrange);
void uncache();
void recache();
/** @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 Ariadne::ClonePtr clone() const;
+ 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:
/**
* Returns the internal dipoles in the nonresolved chain.
*/
inline const vector<tDipolePtr> & internalDipoles() {
return cache.empty()? theInternalDipoles: cache[currange].dipoles;
}
/**
* Returns the internal dipoles in the nonresolved chain.
*/
inline tPartonPtr originalParton() {
return theOriginalParton;
}
/**
* recalculates the partons and dipoles within the range, and updates
* theInternalDipoles and momenta accordingly.
*/
void printData();
/**
* recalculates the partons and dipoles within the range, and updates
* theInternalDipoles and momenta accordingly.
*/
void setRange( InvEnergy range );
/**
* returns true if any of the internal dipoles, or their neighbours,
* has emitted.
*/
bool changed();
/**
* Finds and returns the partons belonging to the internal dipoles.
*/
const set<tPartonPtr> & internalPartons() const {
return theInternalPartons;
};
/**
* Finds and returns the partons belonging to the internal dipoles.
*/
const vector<tPartonPtr> & cachedPartons() const {
return cache.back().partons;
};
/**
* Check if a recoil of pT and plus will push any of the internal partons above
* rapidity ymax.
*/
bool recoilsOverYMax(TransverseMomentum pT, Energy plus, double ymax) const;
/**
* recoils the effective parton from providing an emission with
* pT transverse momentum, and plus p+. Goes with the pT definition
* where every recoil in every emission is remembered.
*/
void recoil( TransverseMomentum pT, Energy plus );
/**
* recoils the effective parton from providing an emission with
* plus p+. pT is decided from each partons two dipole neighbours.
* Goes with the pT determined only from the two current
* colour neighbours, without history dependence.
*/
void newRecoil( Energy plus );
protected:
/**
* recursively add partons within range.
*/
void addPartons( InvEnergy range );
/**
* recursively add partons within range. USes the "Relatives" mode of adding partons.
*/
void addRelatives( InvEnergy range, tPartonPtr p );
/**
* Adds p to the internal partons, and updates the momentum of the effective parton.
*/
void merge(tPartonPtr p);
/**
* checks that the sum ofh the partons momenta is the momenta of the effective parton.
*/
bool checkSums() const;
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/**
* Exception class used when effective parton gets (almost) zero pt)
*/
struct EffectivePartonPTException: public Exception {};
private:
/**
* The original parton.
*/
PartonPtr theOriginalParton;
/**
* The internal dipoles in the nonresolved chain.
*/
vector<tDipolePtr> theInternalDipoles;
/**
* The internal partons in the nonresolved effective parton.
*/
set<tPartonPtr> theInternalPartons;
/**
* Cache informations about different ranges.
*/
vector<RangeInfo> cache;
/**
* The current range
*/
int currange;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
EffectiveParton & operator=(const EffectiveParton &);
};
}
#endif /* DIPSY_EffectiveParton_H */
diff --git a/DIPSY/Emitter.cc b/DIPSY/Emitter.cc
--- a/DIPSY/Emitter.cc
+++ b/DIPSY/Emitter.cc
@@ -1,581 +1,581 @@
// -*- 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 "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 <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);
//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) cout<<endl << "XT keep prob is " << correctDist/overestimate
<<endl << "r12 = " << R12*GeV << ", Rr13 = " << R13*GeV << ", r23 = " << R23*GeV << endl<< endl;
//generate a random number and check if veto or not.
if(correctDist/overestimate>UseRandom::rnd())
return false;
else
return true;
}
/*
* 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
}
/*
* 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;
}
}
/*
* 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);
}
/*
* 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 {
//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;
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)) )
cout << "emission below r-cutoff passed vetos!!!!!!!!!!!!!!!!!!!1!!!" << endl
<< "r12 = " << r12*GeV << ", r13 = " << r13*GeV << ", r23 = " << r23*GeV << endl
<< "v1/pt = " << min(v1.pt(), v2.pt())/pt.pt() << endl;
// 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;
}
}
/*
* 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.
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::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);
}
#ifndef THEPEG_NEW_CLASS_DESCRIPTION
ClassDescription<Emitter> Emitter::initEmitter;
// Definition of the static class description member.
#else
// Static variable needed for the type description system in ThePEG.
#include "ThePEG/Utilities/DescribeClass.h"
DescribeClass<Emitter,HandlerBase>
-describeDIPSYEmitter("DIPSY::Emitter", "libDIPSY.so");
+describeDIPSYEmitter("DIPSY::Emitter", "libAriadne5.so libDIPSY.so");
#endif
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);
}
diff --git a/DIPSY/Emitter.h b/DIPSY/Emitter.h
--- a/DIPSY/Emitter.h
+++ b/DIPSY/Emitter.h
@@ -1,325 +1,325 @@
// -*- C++ -*-
#ifndef DIPSY_Emitter_H
#define DIPSY_Emitter_H
//
// This is the declaration of the Emitter class.
//
#define THEPEG_NEW_CLASS_DESCRIPTION
#include "ThePEG/Handlers/HandlerBase.h"
#include "Emitter.fh"
#include "Dipole.fh"
#include "Parton.h"
namespace DIPSY {
using namespace ThePEG;
/**
* The Emitter class is responsible for generating and performing
* emissions from dipoles. This base class does the standard thing. Any
* non-standard thing must be implemented in a sub-class overriding
* the generate() and/or emit() functions.
*
* @see \ref EmitterInterfaces "The interfaces"
* defined for Emitter.
*/
class Emitter: public HandlerBase {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
inline Emitter();
/**
* The destructor.
*/
virtual ~Emitter();
//@}
public:
/** @name Virtual functions which may be overridden by sub-classes. */
//@{
/**
* Return the running coupling for the given size (scale). /CF
*/
double alphaS(InvEnergy r) const;
/**
* if pT is 1/r or 2/r.
*/
inline double pTScale() const;
/**
* Alpha bar = alphas*Nc/pi /CF
*/
inline double alphaBar(InvEnergy r) const;
/**
* Sets the shape of the overestimate in the genreation.
* The cross section does not (should not) depend on rScale. /CF
*/
inline void rScale(InvEnergy rScale);
/**
* Get bothordered.
*/
inline bool bothOrderedEvo() const {
return theBothOrderedEvo;
};
inline bool bothOrderedInt() const {
return theBothOrderedInt;
};
inline bool bothOrderedFS() const {
return theBothOrderedFS;
};
/**
* Set PSInfaltion
*/
inline void PSInflation(double PSInflation);
/**
* Get PSInfaltion
*/
inline double PSInflation() const;
/**
* Set PSInfaltion
*/
inline void PMinusOrdering(double PMinusOrdering);
/**
* Get PSInfaltion
*/
inline double PMinusOrdering() const;
/**
* get the rangeMode
**/
inline int rangeMode() const {
return theRangeMode;
}
/**
* get the minusOrderingMode
**/
inline int minusOrderingMode() const {
return theMinusOrderingMode;
}
/**
* The confinement scale.
*/
InvEnergy rMax() const;
/**
* Generate a possible emission or a swing from a given dipole in the
* given rapidity interval [\a miny,\a maxy].
*/
virtual void generate(Dipole & dipole, double miny, double maxy) const;
/**
* Perform the emission previously generated for the given \a
* dipole. If no emission has been generated a runtime_error is
* thrown.
*/
virtual void emit(Dipole & dipole) const;
//@}
protected:
/**
* Internal function.
*/
virtual bool OEVeto(DipolePtr dip, double y0, Parton::Point p) const;
/**
* Internal function.
*/
virtual bool YVeto(double y, DipolePtr dip, double Coe, double rateOE) const;
/**
* Internal function.
*/
virtual double generateY(DipolePtr dip, double ymin, double ymax) const;
/**
* Internal function.
*/
virtual Parton::Point generateXT(DipolePtr dip, double y0) const;
public:
/**
* Debugging and testing
*/
mutable bool testingPS;
mutable double fixY;
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected: //@{
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
inline virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
inline virtual IBPtr fullclone() const;
//@}
// If needed, insert declarations of virtual function defined in the
// InterfacedBase class here (using ThePEG-interfaced-decl in Emacs).
protected:
/**
* How much P+- ordering should be required. 1 is nomral ordering
* high values are no ordering, low number are strong ordering.
*/
double thePSInflation;
/**
* Controls the strength of the p- ordering in the evolution.
*/
double thePMinusOrdering;
/**
* if pt is 1/r or 2/r.
*/
double thePTScale;
/**
* the scale in the distribution of transverse r. /CF
*/
InvEnergy theRScale;
/**
* The confinement scale.
*/
InvEnergy theRMax;
/**
* If the plus/minus ordering should be full strenght
* for both parents in teh cascade, interaction and final state.
*/
bool theBothOrderedEvo;
bool theBothOrderedInt;
bool theBothOrderedFS;
/**
* How the range is determined.
**/
int theRangeMode;
/**
* How the minus ordering is made in the cascade.
**/
int theMinusOrderingMode;
/**
* If test-modification to evolution should be on. /CF
*/
bool thestMode;
private:
#ifndef THEPEG_NEW_CLASS_DESCRIPTION
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<Emitter> initEmitter;
#endif
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
Emitter & operator=(const Emitter &);
};
}
#ifndef THEPEG_NEW_CLASS_DESCRIPTION
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of Emitter. */
template <>
struct BaseClassTrait<DIPSY::Emitter,1> {
/** Typedef of the first base class of Emitter. */
typedef HandlerBase NthBase;
};
/** This template specialization informs ThePEG about the name of
* the Emitter class and the shared object where it is defined. */
template <>
struct ClassTraits<DIPSY::Emitter>
: public ClassTraitsBase<DIPSY::Emitter> {
/** Return a platform-independent class name */
static string className() { return "DIPSY::Emitter"; }
/**
* The name of a file containing the dynamic library where the class
* Emitter is implemented. It may also include several, space-separated,
* libraries if the class Emitter depends on other classes (base classes
* excepted). In this case the listed libraries will be dynamically
* linked in the order they are specified.
*/
- static string library() { return "libDIPSY.so"; }
+ static string library() { return "libAriadne5.so libDIPSY.so"; }
};
/** @endcond */
}
#endif
#include "Emitter.icc"
#endif /* DIPSY_Emitter_H */
diff --git a/DIPSY/EventFiller.cc b/DIPSY/EventFiller.cc
--- a/DIPSY/EventFiller.cc
+++ b/DIPSY/EventFiller.cc
@@ -1,1032 +1,1032 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the EventFiller class.
//
#include "DipoleEventHandler.h"
#include "EventFiller.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Repository/CurrentGenerator.h"
#include "ThePEG/Utilities/Current.h"
#include "ThePEG/Utilities/Throw.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Repository/CurrentGenerator.h"
#include "ThePEG/EventRecord/Step.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/EventRecord/SubProcess.h"
#include "RealPartonState.h"
#include "ParticleInfo.h"
#include "ThePEG/Utilities/Debug.h"
#include "ThePEG/Utilities/DebugItem.h"
#include "ThePEG/Utilities/UtilityBase.h"
#include "ThePEG/Utilities/SimplePhaseSpace.h"
#include "ThePEG/Handlers/LuminosityFunction.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "../Cascade/EmitterBase.h"
#include <iostream>
#include <fstream>
using namespace DIPSY;
EventFiller::EventFiller()
: currentWeight(0.0), theRecoilScheme(0), theSingleMother(0),
theDGLAPinPT(0), theEffectiveWeights(0), theFSSwingTime(0.0),
theFSSwingTimeStep(0.1),
theValenceChargeNormalisation(0), thePTCut(ZERO), theSoftRemove(1) {}
EventFiller::~EventFiller() {}
IBPtr EventFiller::clone() const {
return new_ptr(*this);
}
IBPtr EventFiller::fullclone() const {
return new_ptr(*this);
}
double EventFiller::fill(Step & step, DipoleEventHandler & eh, tPPair inc,
DipoleState & dl, DipoleState & dr,
const ImpactParameters & b) const {
// Get a list of possible dipole-dipole interactions
FList fl = eh.xSecFn().flist(dl, dr, b);
//Sum over the (ununitarised) interaction probabilities 2*f_{ij}.
//Note that the factor 2 is included in flist(), to give the correct
//ND interaction probability.
double sum = 0.0;
for ( FList::iterator it = fl.begin(); it != fl.end(); ++it )
sum += it->first.first;
//Just check that they are not all 0.
if ( sum == 0.0 ) {
return 0.0;
}
//Non-diffractive interaction probability is 1 - exp(-Sum(2*f_{ij}))
double weight = eh.xSecFn().unitarize(sum);
//Combine the weights from all the sources.
currentWeight =
weight*sqr(hbarc)*dr.weight()*dl.weight()*b.weight()/eh.maxXSec();
// Select the interactions which should be performed.
pair<RealPartonStatePtr, RealPartonStatePtr> realStates =
selectInteractions(fl, b, eh.xSecFn());
//If no interactions found, discard event.
if ( realStates.first->interactions.empty() ) {
return 0.0;
}
//Counts the number of participants in a HI event.
//TODO: interface, or trigger on AA.
countParticipants(dl, dr, b.bVec().pt());
//Figure out which partons to keep, and which to remove.
//Also sort out colour flow, momenta etc.
vector<String> strings = extractStrings(dl, dr, realStates, b);
DipoleState & finalState = dl;
//Discard event if no final state partons were found.
if ( strings.empty() || ! fillStep(step, inc, strings) ) {
weight = 0.0;
currentWeight = 0.0;
return weight;
}
// The last thing we do is to fix up valens configurations.
finalState.fixValence(step);
return weight;
}
void EventFiller::countParticipants(const DipoleState & dl,
const DipoleState & dr, const InvEnergy b) const {
//The initial dipoles. Note that these will in general have emitted
//something, and thus no longer be active. They may have been
//reconnected by a new dipole in the absorption process though.
vector<DipolePtr> valenceDip = dl.initialDipoles();
valenceDip.insert(valenceDip.end(),
dr.initialDipoles().begin(), dr.initialDipoles().end());
//count the nonparticipating nucleons
int untouchedNucleons = 0;
for ( int i = 0; i < int(valenceDip.size()); i++ ) {
//First find the three valence partons in the nucleon that
//the dipole belongs to.
//Two are connected to the dipole, easy.
tPartonPtr p1 = valenceDip[i]->partons().first;
tPartonPtr p2 = valenceDip[i]->partons().second;
//The three dipoles in valenceDip are always after each other,
//so the third parton can be found in the dipole before or
//after (or both).
tPartonPtr p3;
if ( i != int(valenceDip.size())-1 &&
valenceDip[i+1]->partons().first == p2 )
p3 = valenceDip[i+1]->partons().second;
else if ( i != int(valenceDip.size())-1 &&
valenceDip[i+1]->partons().second == p1 )
p3 = valenceDip[i+1]->partons().first;
else if ( i != 0 && valenceDip[i-1]->partons().first == p2 )
p3 = valenceDip[i-1]->partons().second;
else if ( i != 0 && valenceDip[i-1]->partons().second == p1 )
p3 = valenceDip[i-1]->partons().first;
//If none of the valence partons have interacted
//ie (have children that interacted), the nucleon is considered
//to not have interacted. Note that with swings, a single interaction
//can make several nucleons participating.
if ( !(p1->interacted()) &&
!(p2->interacted()) &&
!( p3 && p3->interacted() ) ) {
valenceDip[i]->participating(false);
untouchedNucleons++;
}
else
valenceDip[i]->participating(true);
}
//We will triple count, as we loop through all 3 dipoles in
//each nucleon. Divide by 3 to make up for this.
untouchedNucleons /= 3;
}
/*
* This is the probability that a parton is interacting, given that
* the state interacts, but the partons is not selected as primary.
*
* Prob of p interacting: p
* Prob of p interacting, given that the state interacts: x = p/totalP
* Prob of p being selected as primary, given state interacts: y = p/sumP
* Prob of p being selected as non-primary, given state
* interacts: z
* x = y + z ==> z = p/totalP - p/sumP
* Prob of p not being primary, given state interacts: A = (sumP-p)/sumP
* And now what we are looking for:
* Prob of p being selected as non-primary, given state interacts
* and not selected as primary: B
* z = A*B ==> B = z/A = p(1/totalP - 1/sumP)/((sumP-p)/sumP) =
* = p(sumP/totalP - 1)/(sumP-p)
*/
double correctedProb(double totalP, double sumP, double p) {
return p*(sumP/totalP - 1.0)/(sumP - p);
}
pair<RealPartonStatePtr, RealPartonStatePtr>
EventFiller::selectInteractions(const FList & fl, const ImpactParameters & b,
const DipoleXSec & xSec) const {
DipolePairVector interactions;
double sumfij = 0.0; //the sum of the individual nonuntarised int probs
double sumUP = 0.0; //The sum of the individual unitarised int probs
//Set up a selector, and a map sorted on pt of the interaction.
Selector<FList::const_iterator, double> sel;
DipolePairMap ordered;
//Loop through all possible interactions and fill
//@sel and @ordered.
for ( FList::const_iterator it = fl.begin(); it != fl.end(); ++it ) {
//If no interaction probability, don't bother.
if ( it->first.second == 0.0 ) continue;
//insert into the selector.
sel.insert(it->first.second, it);
sumfij += it->first.first;
sumUP += it->first.second;
//Calculate interaction recoils by calling the DipoleXSec object.
DipoleXSec::InteractionRecoil rec =
xSec.recoil(it->second.first->partons(), it->second.second->partons(), b);
//Insert in @ordered, sorting on max pt recoil.
double pt = max(max(rec.first.first.pt(), rec.first.second.pt()),
max(rec.second.first.pt(), rec.second.second.pt()))/GeV;
ordered.insert(make_pair(pt, it));
}
//interaction probability (for at least one interaction)
//of the two states.
double totalP = Current<DipoleEventHandler>()->xSecFn().unitarize(sumfij);
//create the real states.
RealPartonStatePtr rrs = new_ptr(RealPartonState());
RealPartonStatePtr lrs = new_ptr(RealPartonState());
//Add the valence partons (as they are always real) and save.
lrs->addValence(fl.begin()->second.first->dipoleState());
rrs->addValence(fl.begin()->second.second->dipoleState());
lrs->saveState();
rrs->saveState();
DipolePairMap potential;
DipolePairMap failedPrims;
bool found = false;
int counter = 0;
while ( !found ) {
potential.clear();
//select a first interaction (since there has to be at least one).
FList::const_iterator prim = sel[UseRandom::rnd()];
//Go through the other interactions and check if they are also
//interacting. A modified probability is used, to make up for the
//bias introduced in selecting a primary interaction.
for ( FList::const_iterator it = fl.begin(); it != fl.end(); ++it )
if ( it == prim || correctedProb(totalP,sumUP,it->first.second)
> UseRandom::rnd() ) {
DipoleXSec::InteractionRecoil rec =
xSec.recoil(it->second.first->partons(), it->second.second->partons(), b);
double pt = max(max(rec.first.first.pt(), rec.first.second.pt()),
max(rec.second.first.pt(), rec.second.second.pt()))/GeV;
//If the interaction passed the amplitude test, add it to the list
//of potential interations.
potential.insert(make_pair(pt, it));
}
//Keep track on how many times we have tried to find a consistent
//set of interactions. Give up after 10 tries.
counter++;
if ( counter > 10 ) {
overTenEvents += currentWeight;
return make_pair(lrs, rrs);
}
//test all potetential interactions in order, skipping already failed dips.
//failed first interactions inserted in failedprims,
//and from sel and ordered if first in ordered.
int i = 0;
for ( DipolePairMap::iterator it = potential.begin(); it != potential.end(); ++it ) {
i++;
//Check first interaction, and already failed as first.
//Then autofail without checking again.
if ( failedPrims.find(it->first) != failedPrims.end() && !found ) {
continue;
}
//Try to add the interaction.
if (addInteraction(it->second, lrs, rrs, interactions, b, xSec)) {
found = true;
}
else {
//remember if it was first interaction and failed, to not
//try it again later.
if ( !found ) {
failedPrims.insert(*it);
if ( it == ordered.begin() ) {
ordered.erase(it);
sel.erase(it->second);
}
}
}
}
//if sel (or ordered) empty, give up event. no int can be first.
if ( sel.empty() ) return make_pair(lrs, rrs);
}
//Make sure that the real state partons are on-shell.
//May not actually be needed, not sure... TODO: check!
for( DipolePairVector::iterator it = interactions.begin();
it != interactions.end(); it++ ) {
lrs->setOnShell((*it)->second.first);
rrs->setOnShell((*it)->second.second);
}
for ( RealParton::RealPartonSet::iterator it = lrs->valence.begin();
it != lrs->valence.end(); it++ )
(*it)->setOnShell();
for ( RealParton::RealPartonSet::iterator it = rrs->valence.begin();
it != rrs->valence.end(); it++ )
(*it)->setOnShell();
//return the real states.
return make_pair(lrs, rrs);
}
bool EventFiller::
addInteraction(FList::const_iterator inter, RealPartonStatePtr lrs,
RealPartonStatePtr rrs, DipolePairVector & inters,
const ImpactParameters & b, const DipoleXSec & xSec) const {
rescatter += currentWeight;
//With some settings, only some of the partons actually interact.
//Check which here. Other tunes will just return 4x true.
pair<pair<bool, bool>, pair<bool, bool> > doesInt =
xSec.doesInt(inter->second.first->partons(),
inter->second.second->partons(), b);
//Calculate the recoils from the interaction.
DipoleXSec::InteractionRecoil recs =
xSec.recoil(inter->second.first->partons(),
inter->second.second->partons(), b, doesInt);
//Add the interacting partons and their parents to the real state
//and go through the evolution checking for ordering, local pt-max, etc.
if ( !lrs->fullControlEvolution
(inter->second.first, inter->second.second,
doesInt.first.first, doesInt.first.second,
recs.first.first.pt(), recs.first.second.pt()) ) {
return false;
}
//Add the interaction to the other state, and check that as well.
if ( !rrs->fullControlEvolution
(inter->second.second, inter->second.first,
doesInt.second.first, doesInt.second.second,
recs.second.first.pt(), recs.second.second.pt()) ) {
//If this second evolution failed, remove the interaction from
//the first
//state by reverting it to the previously saved state.
lrs->revertToPrevious(inter->second.first);
return false;
}
//If both evolutions could accomodate the interacting partons,
//add the interaction recoil as well,
//and check that things still are ok.
inters.push_back(inter);
if ( !controlRecoils(inters, lrs, rrs, b, xSec, doesInt) ) {
//If failed, remove the interaction from the evolutions.
lrs->revertToPrevious(inter->second.first);
rrs->revertToPrevious(inter->second.second);
inters.pop_back();
return false;
}
//If the interactions was ok, mark the dipoles as interacting
//and save the real states.
inter->second.first->interact(*inter->second.second);
inter->second.second->interact(*inter->second.first);
lrs->saveState();
rrs->saveState();
return true;
}
vector<EventFiller::String>
EventFiller::extractStrings(DipoleState & dl, DipoleState & dr,
pair<RealPartonStatePtr, RealPartonStatePtr> realStates,
const ImpactParameters & b ) const {
//Just rename a bit for convenience.
DipoleStatePtr rightState = &dr;
DipoleStatePtr leftState = &dl;
RealPartonStatePtr lrs = realStates.first;
RealPartonStatePtr rrs = realStates.second;
//grow back the partons marked as virtuals.
//This will be the ones without interacting children, but not the
//ones removed during ordering/pt-max-fixing.
removeVirtuals(leftState);
removeVirtuals(rightState);
//The unordered and not-ok pt-max were removed by pairing them
//up with other partons that should stay. Now merge all the momentum
//into a single parton, and flag the others as virtual.
lrs->mergeVirtuals();
rrs->mergeVirtuals();
//Save to update the parton information from the realPartons.
lrs->saveState();
rrs->saveState();
//A high-pt parton (so very localised in x_T) can not recoil all
//of a low-pt (so smeared out in x_T) parent, but will rather shoot
//out a recoiling part of the parent. Fix this by replacing recoiled
//low-pt parents by a remnant, and a recoiler.
lrs->addRecoilers();
rrs->addRecoilers();
//Save states to update partons.
lrs->saveState();
rrs->saveState();
//balance p+/p- by moving the entire state. Was first done in the
//interaction (where the interacting partons had to provide the
//energy), but the modifications here changes kinematics so that
//some more balancing may be needed. Should very rarely be
//large changes.
fixBoost(lrs, rrs);
//Translate the right state to it's right place in x_T,
//and mirror it in rapidity so that it actually comes from the
//other side. Finally merge the two cascades into one state.
rightState->translate(b);
rightState->mirror(0.0);
DipoleStatePtr finalState = leftState->merge(rightState);
vector<pair<DipolePtr, DipolePtr> > swinging =
Current<DipoleEventHandler>()->xSecFn().getColourExchanges(lrs, rrs);
//swing the interacting dipoles.
for ( int i = 0; i < int(swinging.size()); i++ ) {
Current<DipoleEventHandler>()->
xSecFn().reconnect(swinging[i].first, swinging[i].second);
}
//now remove the partons that were made virtual by mergeVirtuals.
//This is so that it should be easier to reconnect the colour
//through the interacting dipoles with the state from the other side.
removeVirtuals(finalState);
//do final state swings, aka pythias colour reconnection.
double yrange = FSSwingTime();
double ystep = FSSwingTimeStep();
for ( double y = 0.0; y < yrange; y += ystep ) {
finalState->swingFS(y, y + ystep);
}
// finalState->lambdaMeasure(0.36*GeV2, histDipLength2, histDipMass2);
//compensate for the 6 valence charges in the proton
finalState->normaliseValenceCharge(theValenceChargeNormalisation);
//make sure the non-particpating nucleons (if AA) have the
//original colour flow.
finalState->restoreNonparticipants();
//try to find and fix any problems or inconsistencies that may have
//popped up. Error messages are sent if anything is found.
dodgeErrors(finalState);
//If you want to save the initial state event to file (mainly AA).
//TODO: interface!
//TODO: stop event after this.
//finalState->saveGluonsToFile(currentWeight);
//If you want to make a fancy movie in mathematica of your event. :)
// finalState->printForMovie(0, 1000);
//Sort the remaining partons in strings.
vector<String> ret = finalState->strings();
return ret;
}
bool EventFiller::fillStep (Step & step, tPPair incoming,
const vector<String> & strings) const {
Direction<0> dir(true);
vector< vector<PPtr> > particles(strings.size());
SubProPtr sub = new_ptr(SubProcess(incoming));
for ( int is = 0, NS = strings.size(); is < NS; ++is ) {
int N = strings[is].size();
vector<bool> removed(N, false);
if ( theSoftRemove && pT2Cut() > ZERO && N > 2 ) {
bool changed = true;
while ( changed ) {
changed = false;
for ( int i = 0; i < N; ++i ) {
if ( removed[i] ) continue;
if ( strings[is][i]->valence() && theSoftRemove == 2 ) continue;
if ( strings[is][i]->flavour() != ParticleID::g ) continue;
int i1 = (N + i - 1)%N;
while ( removed[i1] ) i1 = (N + i1 - 1)%N;
int i3 = (i + 1)%N;
while ( removed[i3] ) i3 = (i3 + 1)%N;
if ( i1 == i3 ) continue;
if ( invPT2(strings[is], i1, i, i3) < pT2Cut() ) {
if ( removeGluon(strings[is], i1, i, i3) ) {
removed[i] = changed = true;
} else {
return false;
}
}
}
}
}
particles[is].resize(N);
for ( int i = 0; i < N; ++i ) {
if ( removed[i] ) continue;
particles[is][i] = strings[is][i]->produceParticle();
int ip = i - 1;
while ( ip >= 0 && removed[ip] ) --ip;
if ( ip >= 0 )
particles[is][i]->colourConnect(particles[is][ip]);
if ( i == N - 1 && strings[is][i]->flavour() == ParticleID::g ) {
int i0 = 0;
while ( i0 < i && removed[i0] ) ++i0;
particles[is][i0]->colourConnect(particles[is][i]);
}
sub->addOutgoing(particles[is][i]);
}
if ( strings[is][0]->flavour() == ParticleID::g ) {
int i0 = 0;
int in = N - 1;
while ( i0 < in && removed[i0] ) ++i0;
while ( in > i0 && removed[in] ) --in;
particles[is][i0]->colourConnect(particles[is][in]);
}
}
step.addSubProcess(sub);
return true;
}
void EventFiller::fixBoost(RealPartonStatePtr lrs, RealPartonStatePtr rrs) const {
//access the CoM energy, through a kindof roundabout path...
//TODO: must be a better way! Current?
PartonPtr dummy = lrs->partons.begin()->first;
Energy sqrtS = ((dummy->dipoles().first) ? dummy->dipoles().first:dummy->dipoles().second)->dipoleState().handler().lumiFn().maximumCMEnergy();
//sum left and right p+ and p-.
Energy leftPlus = ZERO;
Energy leftMinus = ZERO;
Energy rightPlus = ZERO;
Energy rightMinus = ZERO;
//loop and sum over the to-keep partons.
for ( map<tPartonPtr,RealPartonPtr>::const_iterator
it =lrs->partons.begin();
it != lrs->partons.end(); it++ ) {
if ( it->second->keep == RealParton::NO ) continue;
leftPlus += it->second->plus;
leftMinus += it->second->minus;
}
for ( map<tPartonPtr,RealPartonPtr>::const_iterator
it = rrs->partons.begin();
it != rrs->partons.end(); it++ ) {
if ( it->second->keep == RealParton::NO ) continue;
rightPlus += it->second->minus;
rightMinus += it->second->plus;
}
//Solve the 2:nd degree equation for how much energy has to be
//transfered to set both states on shell.
double A = (- rightPlus*rightMinus - sqr(sqrtS) + leftPlus*leftMinus)/(2.0*rightMinus*sqrtS);
double B = rightPlus/rightMinus;
double y1 = -1.0;
double x1 = -1.0;
if ( sqr(A) - B > 0.0 ) {
//the factor to change right p- with.
y1 = - A + sqrt(sqr(A) - B);
// double y2 = - A - sqrt(sqr(A) - B);
//The factor to change left p+ with.
x1 = (y1*sqrtS - rightPlus)/(y1*leftPlus);
// double x2 = (y2*sqrtS - rightPlus)/(y2*leftPlus);
}
//error handling
if ( x1 < 0 || y1 < 0 ) {
Throw<SpaceLikeGluons>()
<< "EventFiller::fixBoost gave negative or nan solution to boost equation, "
<< "will not balance momentum.\n"
<< "This is probably caused by a rouge gluon being far too virtual.\n"
<< Exception::warning;
return;
}
//loop again, scaling the p+ and p- according to the solution above.
for ( map<tPartonPtr,RealPartonPtr>::const_iterator it = lrs->partons.begin();
it != lrs->partons.end(); it++) {
if ( it->second->keep == RealParton::NO ) continue;
it->second->plus *= x1;
it->second->minus /= x1;
}
for ( map<tPartonPtr,RealPartonPtr>::const_iterator it = rrs->partons.begin();
it != rrs->partons.end(); it++) {
if ( it->second->keep == RealParton::NO ) continue;
it->second->minus /= y1;
it->second->plus *= y1;
}
//Save state to transfer the changes to the partons.
lrs->saveState();
rrs->saveState();
}
// void EventFiller::fixValence(Step & step, DipoleState & dl, DipoleState & dr) const {
// list<PartonPtr> alll = dl.getPartons();
// set<tcPartonPtr> vall;
// for ( list<PartonPtr>::iterator pit = alll.begin(); pit != alll.end(); ++pit )
// if ( (**pit).valence() ) vall.insert(*pit);
// list<PartonPtr> allr = dr.getPartons();
// set<tcPartonPtr> valr;
// for ( list<PartonPtr>::iterator pit = allr.begin(); pit != allr.end(); ++pit )
// if ( (**pit).valence() ) valr.insert(*pit);
// vector<PPtr> lval;
// vector<PPtr> rval;
// for ( ParticleSet::iterator pit = step.particles().begin();
// pit != step.particles().end(); ++pit ) {
// tcPartonPtr p = ParticleInfo::getParton(**pit);
// if ( !p ) continue;
// if ( member(vall, p) ) lval.push_back(*pit);
// else if ( member(valr, p) ) rval.push_back(*pit);
// }
// if ( UseRandom::rndbool() ) {
// dl.fixValence(step, lval);
// dr.fixValence(step, rval);
// } else {
// dr.fixValence(step, rval);
// dl.fixValence(step, lval);
// }
// }
void EventFiller::dodgeErrors(DipoleStatePtr finalState) const {
list<PartonPtr> partons = finalState->getPartons();
for ( list<PartonPtr>::iterator it = partons.begin(); it != partons.end(); it++ ) {
PartonPtr p = *it;
//check for empty pointers
if ( !p ) {
Throw<SpaceLikeGluons>()
<< "dodgeError found empty pointer from getPartons()! :o" << Exception::warning;
continue;
}
//check for colour flow to itself
//check for 0 monetum
if ( p->pT().pt() == ZERO ) {
Throw<SpaceLikeGluons>()
<< "dodgeError found 0 pt gluon." << Exception::warning;
p->pT(TransverseMomentum(UseRandom::rnd()*GeV,UseRandom::rnd()*GeV));
}
if ( p->plus() == ZERO || p->minus() == ZERO ) {
Throw<SpaceLikeGluons>()
<< "dodgeError found 0 lightcone momentum." << Exception::warning;
p->minus(UseRandom::rnd()*GeV);
p->plus(UseRandom::rnd()*GeV);
}
//check for nan momentum
if ( isnan(p->pT().pt()/GeV) ) {
Throw<SpaceLikeGluons>()
<< "dodgeError found NAN pt gluon, fix pt." << Exception::warning;
p->pT(TransverseMomentum(UseRandom::rnd()*GeV,UseRandom::rnd()*GeV));
}
if ( isnan(p->plus()/GeV) || isnan(p->minus()/GeV) ) {
Throw<SpaceLikeGluons>()
<< "dodgeError found NAN lightcone momentum, fix plus, minus." << Exception::warning;
p->minus(UseRandom::rnd()*GeV);
p->plus(UseRandom::rnd()*GeV);
}
//check for negative momentum
if ( p->pT().pt() < ZERO ) {
Throw<SpaceLikeGluons>()
<< "dodgeError found negative pt gluon.... >_>, fix pt." << Exception::warning;
p->pT(TransverseMomentum(UseRandom::rnd()*GeV,UseRandom::rnd()*GeV));
}
if ( p->plus() < ZERO || p->minus() < ZERO ) {
Throw<SpaceLikeGluons>()
<< "dodgeError found negative lightcone momentum, fix plus,minus." << Exception::warning;
p->minus(UseRandom::rnd()*GeV);
p->plus(UseRandom::rnd()*GeV);
//check for off-shell momentum
if ( sqr(p->plus()*p->minus() - p->pT().pt2() - sqr(p->mass())) > sqr(sqr(0.01*GeV)) ) {
Throw<SpaceLikeGluons>()
<< "dodgeError found off-shell parton, fix pt." << Exception::warning;
if ( p->plus()*p->minus() < sqr(p->mass()) ) {
Throw<SpaceLikeGluons>()
<< "dodgeError found insufficient energy for mass, fix plus,minus." << Exception::warning;
double ratio = 2.0*sqr(p->mass())/(p->plus()*p->minus()); //give a bit extra for pt
p->plus(p->plus()*sqrt(ratio));
p->minus(p->minus()*sqrt(ratio));
}
double mod = sqrt(p->plus()*p->minus() - sqr(p->mass()))/p->pT().pt();
p->pT(p->pT()*mod);
}
}
}
}
bool EventFiller::
controlRecoils(DipolePairVector & sel,
RealPartonStatePtr lrs, RealPartonStatePtr rrs,
const ImpactParameters & b, const DipoleXSec & xSec,
pair<pair<bool, bool>, pair<bool, bool> > doesInt) const {
//Keep track on which partons are interacting.
list<pair<bool, bool> >::const_iterator
leftDoesInt = lrs->doesInts.begin();
list<pair<bool, bool> >::const_iterator
rightDoesInt = rrs->doesInts.begin();
//Loop through the interaction, and
for ( DipolePairVector::const_iterator inter = sel.begin();
inter != sel.end(); inter++ ) {
//Which partons are interacting in this dip-dip interaction
pair<pair<bool, bool>, pair<bool, bool> >
trueDoesInt = make_pair(*leftDoesInt, *rightDoesInt);
//calculate recoils
DipoleXSec::InteractionRecoil recoil =
xSec.recoil((*inter)->second.first->partons(),
(*inter)->second.second->partons(), b, trueDoesInt);
//call the DipoleXSec object to check kinematics and vetos
//for the interaction. If things don't work, undo the changes.
if ( !xSec.doInteraction(recoil, *inter, lrs, rrs, trueDoesInt, b) ) {
//revert the total recoil between the states.
lrs->totalRecoil -= recoil.first.first + recoil.first.second;
rrs->totalRecoil -= recoil.second.first + recoil.second.second;
}
}
return true;
}
void EventFiller::removeVirtuals(DipoleStatePtr state) const {
list<PartonPtr> vP = state->getPartons();
//loop through the partons, and remove the off shell ones.
//this only does colour flow. RealPartonState does the kinematics
//in mergeVirtuals.
for ( list<PartonPtr>::iterator it = vP.begin(); it != vP.end(); it++) {
tPartonPtr p = *it;
//only handle off-shell parton.
if ( !(p->onShell()) ) {
//if there are only 2 or fewer on-shell partons in the colour chain,
//it has to be swinged at some point, and better early than late,
//as last-second forced swings can lead to silly colour connections.
if ( p->nOnShellInChain() < 2 ) {
//tell the absorber to find a swing anywhere in the colour chain
if ( p->dipoles().first ) absorber()->swingLoop(p->dipoles().first, *state);
else absorber()->swingLoop(p->dipoles().second, *state);
}
//once off-shell loops are handled, absorb the parton.
absorber()->removeParton(p);
}
}
}
// If needed, insert default implementations of virtual function defined
// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs).
void EventFiller::doinit() throw(InitException) {
HandlerBase::doinit();
}
void EventFiller::dofinish() {}
void EventFiller::doinitrun() {
HandlerBase::doinitrun();
}
double EventFiller::pTScale(DipoleState & state) const {
return state.handler().emitter().pTScale();
}
Energy2 EventFiller::invPT2(const String & str, int i1, int i2, int i3) {
LorentzMomentum p1 = str[i1]->momentum();
LorentzMomentum p2 = str[i2]->momentum();
LorentzMomentum p3 = str[i3]->momentum();
Energy2 s = (p1 + p2 + p3).m2();
if ( s < sqr(str[i1]->mass() + str[i3]->mass() ) )
Throw<SpaceLikeGluons>()
<< "DIPSY produced space-like gluons. Three neighboring ones had "
<< "negative mass squared. This cannot be fixed at the moment. "
<< "Event discarded." << Exception::eventerror;
Energy2 s12 = (p1 + p2).m2();
Energy2 s23 = (p2 + p3).m2();
if ( s12 < ZERO || s23 < ZERO ) return -1.0*GeV2;
return s12*s23/s;
}
bool EventFiller::removeGluon(const String & str, int i1, int i2, int i3) {
LorentzMomentum p1 = str[i1]->momentum();
LorentzMomentum p2 = str[i2]->momentum();
LorentzMomentum p3 = str[i3]->momentum();
LorentzMomentum ptest = p1 + p2;
if ( ptest.m2() < Constants::epsilon*1000.0*sqr(ptest.e()) ) {
str[i1]->plus(ptest.plus());
str[i1]->pT(TransverseMomentum(ptest.x(), ptest.y()));
return true;
}
ptest = p3 + p2;
if ( ptest.m2() < Constants::epsilon*1000.0*sqr(ptest.e()) ) {
str[i3]->plus(ptest.plus());
str[i3]->pT(TransverseMomentum(ptest.x(), ptest.y()));
return true;
}
Energy2 S = (p1 + p2 + p3).m2();
if ( S <= ZERO ) return false;
LorentzRotation R = Utilities::boostToCM(makeTriplet(&p1, &p2, &p3));
double Psi = Constants::pi - p3.theta();
double beta = 0.0;
Energy W = sqrt(S);
double x1 = 2.0*p1.e()/W;
double x3 = 2.0*p3.e()/W;
bool g1 = str[i1]->flavour() == ParticleID::g;
bool g3 = str[i3]->flavour() == ParticleID::g;
if ( ( g1 && g3 ) || (!g1 && !g3 ) )
beta = Psi*sqr(x3)/(sqr(x1) + sqr(x3)); // minimize pt
else if ( g1 )
beta = Psi;
R.rotateY(-beta);
R.invert();
Lorentz5Momentum p1n(p1.m());
Lorentz5Momentum p3n(p3.m());
try {
SimplePhaseSpace::CMS(p1n, p3n, S, 1.0, 0.0);
} catch ( ImpossibleKinematics ) {
return false;
}
p1n.transform(R);
p3n.transform(R);
str[i1]->plus(p1n.plus());
str[i1]->pT(TransverseMomentum(p1n.x(), p1n.y()));
str[i3]->plus(p3n.plus());
str[i3]->pT(TransverseMomentum(p3n.x(), p3n.y()));
return true;
}
void EventFiller::persistentOutput(PersistentOStream & os) const {
os << theAbsorber << theRecoilScheme << theMode << theSingleMother
<< theDGLAPinPT << theEffectiveWeights << theFSSwingTime
<< theFSSwingTimeStep << theValenceChargeNormalisation
<< ounit(thePTCut, GeV) << theSoftRemove;
}
void EventFiller::persistentInput(PersistentIStream & is, int) {
is >> theAbsorber >> theRecoilScheme >> theMode >> theSingleMother
>> theDGLAPinPT >> theEffectiveWeights >> theFSSwingTime
>> theFSSwingTimeStep >> theValenceChargeNormalisation
>> iunit(thePTCut, GeV) >> theSoftRemove;
}
DescribeClass<EventFiller,HandlerBase>
-describeDIPSYEventFiller("DIPSY::EventFiller", "libDIPSY.so");
+describeDIPSYEventFiller("DIPSY::EventFiller", "libAriadne5.so libDIPSY.so");
void EventFiller::Init() {
static ClassDocumentation<EventFiller> documentation
("The EventFiller class is able to produce an initial ThePEG::Step "
"from two colliding DipoleStates.");
static Reference<EventFiller,DipoleAbsorber> interfaceDipoleAbsorber
("DipoleAbsorber",
"The object used to absorb non-interacting dipoles.",
&EventFiller::theAbsorber, true, false, true, true, false);
static Switch<EventFiller,int> interfaceMode
("Mode",
"How the real state is found from the virtual cascade. Speed versus consistency.",
&EventFiller::theMode, 0, true, false);
static SwitchOption interfaceModeMode
(interfaceMode,
"Consistent",
"The fully consistent version. Not currently reccomended.",
0);
static SwitchOption interfaceModeFast
(interfaceMode,
"Fast",
"Checking only the new real partons introduced by each new interaction, rather than rechecking them all. Good for heavy ions. Not currently reccomended.",
1);
static SwitchOption interfaceModeSingle
(interfaceMode,
"SingleSweep",
"Checking all partons, but sweeping just once in each direction, making it a lot faster. Good for heavy ions. May give an occasional unordered chain, but hopefully not too often. The recommended option.",
2);
static SwitchOption interfaceModeNonRecursive
(interfaceMode,
"NonRecursive",
"Does all evo no matter what. Then removes biggest problem, and does it all over again. Never turns partons back on once switched off.",
3);
static Switch<EventFiller,int> interfaceEffectiveWeights
("EffectiveWeights",
"How the p+ and pT recoils are distributed among the single partons in an effective parton.",
&EventFiller::theEffectiveWeights, 0, true, false);
static SwitchOption interfaceEffectiveWeightsPlusWeighted
(interfaceEffectiveWeights,
"PlusWeighted",
"Weight pt and plus according to p+ of the individual partons.",
0);
static SwitchOption interfaceEffectiveWeightsPlusEvenWeighted
(interfaceEffectiveWeights,
"PlusEvenWeighted",
"The plus is distibuted according to the plus of the partons, but the pt is shared evenly among the partons.",
1);
static SwitchOption interfaceEffectiveWeightsPlusSingleWeighted
(interfaceEffectiveWeights,
"PlusSingleWeighted",
"The plus is distibuted according to the plus of the partons, but the pt is taken only by the colour connected parton",
2);
static Switch<EventFiller,int> interfaceRecoilScheme
("RecoilScheme",
"How to give tread the positive light-cone momentum of a recoiling parton.",
&EventFiller::theRecoilScheme, 0, true, false);
static SwitchOption interfaceRecoilSchemePreservePlus
(interfaceRecoilScheme,
"PreservePlus",
"blaha",
0);
static SwitchOption interfaceRecoilSchemeFixedY
(interfaceRecoilScheme,
"FixedY",
"blahaaa",
1);
static SwitchOption interfaceRecoilSchemeFrameFan
(interfaceRecoilScheme,
"FrameFan",
"dssklajhls",
2);
static Parameter<EventFiller,int> interfaceSingleMother
("SingleMother",
"If an emission is regarded to come from a single parton rather than both "
" partons in the emitting dipole.",
&EventFiller::theSingleMother, 1, 1, 0, 0,
true, false, Interface::lowerlim);
static Parameter<EventFiller,int> interfaceDGLAPinPT
("DGLAPinPT",
"If the DGLAP supression should be made in terms of pt rather than r. "
" partons in the emitting dipole.",
&EventFiller::theDGLAPinPT, 1, 1, 0, 0,
true, false, Interface::lowerlim);
static Parameter<EventFiller,double> interfaceFSSwingTimeStep
("FSSwingTimeStep",
"How long time steps is are to be used for FS colour reconnections.",
&EventFiller::theFSSwingTimeStep, 0.1, 0.0, 0,
true, false, Interface::lowerlim);
static Parameter<EventFiller,double> interfaceFSSwingTime
("FSSwingTime",
"How long time is allowed for FS colour reconnections. 0 turns it off.",
&EventFiller::theFSSwingTime, 0.0, 0.0, 0,
true, false, Interface::lowerlim);
static Switch<EventFiller,int> interfaceValenceChargeNormalisation
("ValenceChargeNormalisation",
"How to treat the (too large) colour charge of the valence partons.",
&EventFiller::theValenceChargeNormalisation, 0, true, false);
static SwitchOption interfaceValenceChargeNormalisationNone
(interfaceValenceChargeNormalisation,
"None",
"Dont do anything.",
0);
static SwitchOption interfaceValenceChargeNormalisationSwing
(interfaceValenceChargeNormalisation,
"Swing",
"Swing some of the dipoles going to the valence partons",
1);
static Parameter<EventFiller,Energy> interfacePTCut
("PTCut",
"The minimum invariant transverse momentum allowed for a gluon. "
"Gluons below the cut will be removed from the final state. "
"If zero, no gluons will be removed.",
&EventFiller::thePTCut, GeV, 0.0*GeV, 0.0*GeV, 0*GeV,
true, false, Interface::lowerlim);
static Switch<EventFiller,int> interfaceSoftRemove
("SoftRemove",
"Determines if gluons with invariant transverse momentum below "
"<interface>PTCut</interface> should be reabsorbed.",
&EventFiller::theSoftRemove, 1, true, false);
static SwitchOption interfaceSoftRemoveOff
(interfaceSoftRemove,
"Off",
"No gluons are absorbed",
0);
static SwitchOption interfaceSoftRemoveAll
(interfaceSoftRemove,
"All",
"All soft gluons below the cut are absorbed.",
1);
static SwitchOption interfaceSoftRemoveNoValence
(interfaceSoftRemove,
"NoValence",
"All except valence gluons are absorbed if below the cut.",
2);
}
diff --git a/DIPSY/FSDipoleOrdering.cc b/DIPSY/FSDipoleOrdering.cc
--- a/DIPSY/FSDipoleOrdering.cc
+++ b/DIPSY/FSDipoleOrdering.cc
@@ -1,140 +1,140 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the FSDipoleOrdering class.
//
#include "FSDipoleOrdering.h"
#include "Ariadne/DipoleCascade/Parton.h"
#include "Ariadne/DipoleCascade/DipoleState.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace DIPSY;
FSDipoleOrdering::FSDipoleOrdering()
: isGenerous(0), useOnlyOriginal(false) {}
FSDipoleOrdering::~FSDipoleOrdering() {}
bool FSDipoleOrdering::
-finalVeto(tcEmiPtr dipole, Ariadne::tcDipoleStatePtr state, tcParPtr parton,
+finalVeto(tcEmiPtr dipole, Ariadne5::tcDipoleStatePtr state, tcParPtr parton,
Energy2 pt2, const EmissionType & type) const {
pair<tcParPtr,tcParPtr> parents = parton->parents();
bool o1 = parents.first->orig();
bool o3 = parents.second->orig();
while ( !parents.first->orig() )
parents.first = parents.first->parents().first;
while ( !parents.second->orig() )
parents.second = parents.second->parents().second;
LorentzMomentum p1 = parents.first->orig()->momentum();
LorentzMomentum p2 = parton->momentum();
LorentzMomentum p3 = parents.second->orig()->momentum();
if ( useOnlyOriginal ) {
if ( !o1 && !o3 ) return false;
if ( o1 && ( p2.perp2() > p1.perp2() ||
p2.plus() > p1.plus() ||
p2.minus() > p1.minus() ) ) return true;
if ( o3 && ( p2.perp2() > p3.perp2() ||
p2.plus() > p3.plus() ||
p2.minus() > p3.minus() ) ) return true;
if ( o1 || o3 ) return false;
}
Energy2 pt2cut = min(p1.perp2(), p3.perp2());
if ( isGenerous > 0 ) pt2cut = sqrt(p1.perp2()*p3.perp2());
if ( isGenerous < 0 ) pt2cut = ZERO;
if ( p2.perp2() < pt2cut ) return false;
if ( p2.plus() < p1.plus() && p2.minus() < p1.minus() ) return false;
if ( p2.plus() < p3.plus() && p2.minus() < p3.minus() ) return false;
return true;
}
IBPtr FSDipoleOrdering::clone() const {
return new_ptr(*this);
}
IBPtr FSDipoleOrdering::fullclone() const {
return new_ptr(*this);
}
// If needed, insert default implementations of virtual function defined
// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs).
void FSDipoleOrdering::persistentOutput(PersistentOStream & os) const {
os << isGenerous << useOnlyOriginal;
}
void FSDipoleOrdering::persistentInput(PersistentIStream & is, int) {
is >> isGenerous >> useOnlyOriginal;
}
// Static variable needed for the type description system in ThePEG.
#include "ThePEG/Utilities/DescribeClass.h"
DescribeClass<FSDipoleOrdering,Ariadne::ReweightBase>
describeDIPSYFSDipoleOrdering("DIPSY::FSDipoleOrdering",
"FSDipoleOrdering.so");
void FSDipoleOrdering::Init() {
static ClassDocumentation<FSDipoleOrdering> documentation
("There is no documentation for the FSDipoleOrdering class");
static Switch<FSDipoleOrdering,int> interfaceGenerous
("Generous",
"Determines whether the phase space constraints for new emissions is "
"relaxed from the minimum of the transverse momenta of the emittors to "
"the geometric mean. Alternatively the phase space can be more "
"constrained giving pure light-cone momentum ordering.",
&FSDipoleOrdering::isGenerous, 0, true, false);
static SwitchOption interfaceGenerousNormal
(interfaceGenerous,
"Normal",
"The transverse momentum of a gluon is restricted to be less than any "
"of its mothers, if outside their light-cone triangle.",
0);
static SwitchOption interfaceGenerousGenerous
(interfaceGenerous,
"Generous",
"The transverse momentum of a gluon is restricted to be less than the "
"geometrical mean of that of its original parents, if outside their "
"light-cone triangle.",
1);
static SwitchOption interfaceGenerousRestrictive
(interfaceGenerous,
"Restrictive",
"No gluons are allowed outside the light-cone triangle of the "
"original parents.",
-1);
static Switch<FSDipoleOrdering,bool> interfaceOnlyOriginal
("OnlyOriginal",
"Determines whether all emissions are restricted by the kinematics of "
"the original partons, or only those where original partons are involved",
&FSDipoleOrdering::useOnlyOriginal, false, true, false);
static SwitchOption interfaceOnlyOriginalAllEmissions
(interfaceOnlyOriginal,
"AllEmissions",
"All emissions are restricted by the kinematics of the original partons.",
false);
static SwitchOption interfaceOnlyOriginalOnlyOriginalEmissions
(interfaceOnlyOriginal,
"OnlyOriginalEmissions",
"Emissions are restricted by the kinematics of the original partons only "
"if original partons are involved in the emission.",
true);
}
diff --git a/DIPSY/ImpactParameterGenerator.cc b/DIPSY/ImpactParameterGenerator.cc
--- a/DIPSY/ImpactParameterGenerator.cc
+++ b/DIPSY/ImpactParameterGenerator.cc
@@ -1,181 +1,181 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the ImpactParameterGenerator class.
//
#include "ImpactParameterGenerator.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Repository/UseRandom.h"
#include "DipoleEventHandler.h" //needed for the selector, where does it point? :o
#include "ThePEG/Utilities/Debug.h"
#ifdef ThePEG_TEMPLATES_IN_CC_FILE
// #include "ImpactParameterGenerator.tcc"
#endif
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace DIPSY;
ImpactParameterGenerator::ImpactParameterGenerator()
: theWidth(5.0*InvGeV) {}
ImpactParameterGenerator::
ImpactParameterGenerator(const ImpactParameterGenerator & x)
: HandlerBase(x), theWidth(x.theWidth) {}
IBPtr ImpactParameterGenerator::clone() const {
return new_ptr(*this);
}
IBPtr ImpactParameterGenerator::fullclone() const {
return new_ptr(*this);
}
ImpactParameterGenerator::~ImpactParameterGenerator() {}
ImpactParameters ImpactParameterGenerator::generate(double seed) const {
// InvEnergy b = sqrt(-2.0*log(rnd()))*width();
// double phi = 2.0*Constants::pi*rnd();
// InvEnergy2 w = 2.0*Constants::pi*sqr(width())*exp(sqr(b/width())/2.0);
// return ImpactParameters(ImpactParameters::Point(b*cos(phi), b*sin(phi)),
// 2.0*Constants::pi*rnd(), w);
InvEnergy b = -log(seed)*width();
double phi = 2.0*Constants::pi*rnd();
InvEnergy2 w = 2.0*Constants::pi*width()*b*exp(b/width());
return ImpactParameters(Point(b*cos(phi), b*sin(phi)),
2.0*Constants::pi*rnd(), w);
}
ImpactParameters ImpactParameterGenerator::
generateDynamic(vector<pair<Point, InvEnergy> > points1,
vector<pair<Point, InvEnergy> > points2) const {
//set up the selector with the product of the widths as weight
vector<double> widths;
Selector<pair<int, int>, InvEnergy2> sel;
for ( int m = 0; m < int(points1.size()); m++ ) {
for ( int n = 0; n < int(points2.size()); n++ ) {
sel.insert(points1[m].second*points2[n].second, make_pair(m, n) );
}
}
pair<int, int> ij = sel[UseRandom::rnd()];
Point p1 = points1[ij.first].first;
Point p2 = points2[ij.second].first;
//set width the geometric mean, let the width set the scale, using the general
//scale 3/Gev, which is roufly the size of the proton, and the confimenet range
InvEnergy dynWidth = width()/(3.0/GeV)*sqrt(points1[ij.first].second*points2[ij.second].second);
// cout << "picked point (" << p1.x()*GeV << ", " << p1.y()*GeV << "), with n,m "
// << ij.first << ", " << ij.second << endl;
// cout << "widths are " << points1[ij.first].second*GeV << " and "
// << points2[ij.second].second*GeV << ", mean " << dynWidth*GeV
// << ", fij weight: " << sqr(dynWidth)*GeV2 << endl;
//first generate the rotation of the second state.
double theta = 2.0*Constants::pi*rnd();
ImpactParameters ip = ImpactParameters(Point(), theta, 1./GeV2);
p2 = ip.rotate(p2);
//generate the distance between the selected points
//overestimate b*exp(-b/w) with 2/w*exp(-b/(2w)-1)
InvEnergy b;
do b = -2.0*dynWidth*log(UseRandom::rnd());
while ( b/(2.0*dynWidth)*exp(1-b/(2.0*dynWidth)) < UseRandom::rnd() );
//generate direction between states
double phi = 2.0*Constants::pi*rnd();
// cout << "picked a p-p distance " << b*GeV << endl;
//find the required translation for the centers of each state.
Point bVec = Point(b*cos(phi), b*sin(phi)) + p1 - p2;
//find what the probability density in d2b is for that translation,
//summed over all pairs of particles.
Energy2 f = ZERO;
double sumWeights = 0.0;
for ( int m = 0; m < int(points1.size()); m++ ) {
for ( int n = 0; n < int(points2.size()); n++ ) {
Point bmn = bVec - points1[m].first + ip.rotate(points2[n].first);
//find the width for this pair
InvEnergy thisWidth = sqrt(points1[m].second*points2[n].second);
//add the prob density of the dist from this pair, with the extra weight
f += exp(-bmn.pt()/thisWidth)/(2.0*Constants::pi)*GeV2;
//keep track of the extra weights of the prob dens
sumWeights += sqr(thisWidth)*GeV2;
// if ( exp(-bmn.pt()/thisWidth)/(2.0*Constants::pi*sqr(thisWidth))/GeV2 > 0.1 )
// cout << "m,n: " << m << ", " << n << ", fnm(b): " << exp(-bmn.pt()/thisWidth)/(2.0*Constants::pi) << endl;
}
}
//normalise by dividing by the sum off all the weights for the individual p-p prob dists
// cout << "sum of all weights: " << sumWeights << endl;
f /= sumWeights;
// cout << "total prob dens " << f/GeV2 << endl;
//weight is 1/f(bVec)
InvEnergy2 w = 1.0/f;
// cout << "weight " << w*GeV2 << endl;
// cout << points1.size() << ", " << points2.size() << ", dynwidth: "
// << GeV*width()*sqrt(1+points1.size()*points2.size())/40.0
// << ", bprime: " << b*GeV << ", 100xf: " << 100.0*f/GeV2 << endl;
if (Debug::level > 5 )
cout << "setting up intercept at (" << p1.x()*GeV << ", " << p1.y()*GeV << ")" << endl;
if (Debug::level > 5 )
cout << "other particle should be at (" << (p1+bVec).x()*GeV << ", "
<< (p1+bVec).y()*GeV << ")" << endl;
// return ImpactParameters(Point(ZERO, 3.0/GeV), theta, 100./GeV2); //for fix b runs
return ImpactParameters(bVec, theta, w);
}
void ImpactParameterGenerator::persistentOutput(PersistentOStream & os) const {
os << ounit(theWidth, InvGeV);
}
void ImpactParameterGenerator::persistentInput(PersistentIStream & is, int) {
is >> iunit(theWidth, InvGeV);
}
// Static variable needed for the type description system in ThePEG.
#include "ThePEG/Utilities/DescribeClass.h"
DescribeClass<ImpactParameterGenerator,HandlerBase>
describeDIPSYImpactParameterGenerator("DIPSY::ImpactParameterGenerator",
- "libDIPSY.so");
+ "libAriadne5.so libDIPSY.so");
void ImpactParameterGenerator::Init() {
static ClassDocumentation<ImpactParameterGenerator> documentation
("The objective of the ImpactParameterGenerator class is to generate "
"ImpactParameters objects to be used when two "
"<code>DipoleState</code>s have been generated w.r.t. origo in the "
"transverse to displace and rotate one of them before "
"collision. This base class will generate impact parameters "
"according to a Gaussian distribution, and the weigth in the "
"produced ImpactParameters objects is set accordingly. Sub-classes "
"may override the generate() function to use any distribution as "
"long as the weight is set accordingly.");
static Parameter<ImpactParameterGenerator,InvEnergy> interfaceWidth
("Width",
"The width of the generated distribution.",
&ImpactParameterGenerator::theWidth, InvGeV, 10.0*InvGeV, 0.0*InvGeV,
0*InvGeV, true, false, Interface::lowerlim);
}
diff --git a/DIPSY/Makefile.am b/DIPSY/Makefile.am
--- a/DIPSY/Makefile.am
+++ b/DIPSY/Makefile.am
@@ -1,146 +1,147 @@
AUTOMAKE_OPTIONS = -Wno-portability
mySOURCES = DipoleEventHandler.cc WaveFunction.cc SimpleProton.cc \
VirtualPhoton.cc DipoleState.cc Dipole.cc Parton.cc DipoleXSec.cc \
ImpactParameterGenerator.cc WFInfo.cc PhotonWFInfo.cc \
VectorMesonBase.cc PhotonDipoleState.cc SimpleProtonState.cc \
Emitter.cc Swinger.cc DipoleAnalysisHandler.cc \
TotalXSecAnalysis.cc EventFiller.cc DipoleAbsorber.cc \
SmallDipoleAbsorber.cc EffectiveParton.cc RealParton.cc \
RealPartonState.cc DiffractiveEventFiller.cc ParticleInfo.cc \
NucleusData.cc
DOCFILES = DipoleEventHandler.h WaveFunction.h SimpleProton.h VirtualPhoton.h \
DipoleState.h Dipole.h Parton.h DipoleXSec.h ImpactParameters.h \
ImpactParameterGenerator.h WFInfo.h PhotonWFInfo.h VectorMesonBase.h \
PhotonDipoleState.h SimpleProtonState.h Emitter.h Swinger.h \
DipoleAnalysisHandler.h TotalXSecAnalysis.h EventFiller.h \
DipoleAbsorber.h SmallDipoleAbsorber.h EffectiveParton.h \
RealParton.h RealPartonState.h DiffractiveEventFiller.h ParticleInfo.h \
NucleusData.h
INCLUDEFILES = $(DOCFILES) DipoleEventHandler.fh \
WaveFunction.icc WaveFunction.fh \
VirtualPhoton.icc DipoleState.fh DipoleState.icc Dipole.fh \
Dipole.icc Parton.fh Parton.icc DipoleXSec.fh DipoleXSec.icc \
ImpactParameters.icc ImpactParameterGenerator.fh WFInfo.fh \
PhotonWFInfo.icc VectorMesonBase.icc PhotonDipoleState.icc \
SimpleProtonState.icc Emitter.fh Emitter.icc Swinger.fh \
Swinger.icc DipoleAnalysisHandler.fh EventFiller.fh \
DipoleAbsorber.fh EffectiveParton.fh \
RealParton.fh RealPartonState.fh CPUTimer.h
pkglib_LTLIBRARIES = libDIPSY.la OldStyleEmitter.la PT1DEmitter.la \
ElasticXSecAnalysis.la LargePTDipoleAbsorber.la \
- SimpleNucleus.la RecoilSwinger.la FSDipoleOrdering.la \
+ SimpleNucleus.la RecoilSwinger.la \
FSDipole5Ordering.la FSAnalysis.la GapAnalysis.la HIAnalysis.la \
FixedImpactGenerator.la NoFluctXSecAnalysis.la GlauberAnalysis.la \
AnalysisProgress.la SemiInclusiveXSecAnalysis.la \
GaussianImpactGenerator.la
INPUTFILES = TestXSecs.in RivetAnalyses.in DIPSYRemove.in DIPSYDefaults.in CurrentTune.in Tune27.in
CLEANFILES = done-all-links
dist_pkgdata_DATA = $(INPUTFILES)
+rpodir = $(pkglibdir)
+nodist_rpo_DATA = DIPSYDefaults.rpo
# Version info should be updated if any interface or persistent I/O
# function is changed
libDIPSY_la_LDFLAGS = -module -version-info 1:0:0
+# libDIPSY_la_LIBADD = ../Config/libAriadne5Config.la
libDIPSY_la_SOURCES = $(mySOURCES) $(INCLUDEFILES)
OldStyleEmitter_la_LDFLAGS = -module -version-info 1:0:0
OldStyleEmitter_la_SOURCES = OldStyleEmitter.cc OldStyleEmitter.h
-FSDipoleOrdering_la_LDFLAGS = -module -version-info 1:0:0
-FSDipoleOrdering_la_SOURCES = FSDipoleOrdering.cc FSDipoleOrdering.h
-
FSDipole5Ordering_la_LDFLAGS = -module -version-info 1:0:0
FSDipole5Ordering_la_SOURCES = FSDipole5Ordering.cc FSDipole5Ordering.h
FSAnalysis_la_LDFLAGS = -module -version-info 1:0:0
FSAnalysis_la_SOURCES = FSAnalysis.cc FSAnalysis.h
GapAnalysis_la_LDFLAGS = -module -version-info 1:0:0
GapAnalysis_la_SOURCES = GapAnalysis.cc GapAnalysis.h
HIAnalysis_la_LDFLAGS = -module -version-info 1:0:0
HIAnalysis_la_SOURCES = HIAnalysis.cc HIAnalysis.h
PT1DEmitter_la_LDFLAGS = -module -version-info 1:0:0
PT1DEmitter_la_SOURCES = PT1DEmitter.cc PT1DEmitter.h
ElasticXSecAnalysis_la_LDFLAGS = -module -version-info 1:0:0
ElasticXSecAnalysis_la_SOURCES = ElasticXSecAnalysis.cc ElasticXSecAnalysis.h
NoFluctXSecAnalysis_la_LDFLAGS = -module -version-info 1:0:0
NoFluctXSecAnalysis_la_SOURCES = NoFluctXSecAnalysis.cc NoFluctXSecAnalysis.h
SemiInclusiveXSecAnalysis_la_LDFLAGS = -module -version-info 1:0:0
SemiInclusiveXSecAnalysis_la_SOURCES = SemiInclusiveXSecAnalysis.cc SemiInclusiveXSecAnalysis.h
GlauberAnalysis_la_LDFLAGS = -module -version-info 1:0:0
GlauberAnalysis_la_SOURCES = GlauberAnalysis.cc GlauberAnalysis.h
AnalysisProgress_la_LDFLAGS = -module -version-info 1:0:0
AnalysisProgress_la_SOURCES = AnalysisProgress.cc AnalysisProgress.h
LargePTDipoleAbsorber_la_LDFLAGS = -module -version-info 1:0:0
LargePTDipoleAbsorber_la_SOURCES = LargePTDipoleAbsorber.cc LargePTDipoleAbsorber.h
SimpleNucleus_la_LDFLAGS = -module -version-info 1:0:0
SimpleNucleus_la_SOURCES = SimpleNucleus.cc SimpleNucleus.h \
SimpleNucleusState.cc SimpleNucleusState.h
RecoilSwinger_la_LDFLAGS = -module -version-info 1:0:0
RecoilSwinger_la_SOURCES = RecoilSwinger.cc RecoilSwinger.h
FixedImpactGenerator_la_LDFLAGS = -module -version-info 1:0:0
FixedImpactGenerator_la_SOURCES = FixedImpactGenerator.cc FixedImpactGenerator.h
GaussianImpactGenerator_la_LDFLAGS = -module -version-info 1:0:0
GaussianImpactGenerator_la_SOURCES = GaussianImpactGenerator.cc GaussianImpactGenerator.h
EXTRACLASSES = OldStyleEmitter.la PT1DEmitter.la ElasticXSecAnalysis.la \
LargePTDipoleAbsorber.la RecoilSwinger.la SimpleNucleus.la \
- FSDipoleOrdering.la FSAnalysis.la GapAnalysis.la HIAnalysis.la \
+ FSAnalysis.la GapAnalysis.la HIAnalysis.la \
FixedImpactGenerator.la FSDipole5Ordering.la
done-all-links:
@EMPTY@ifdef SHOWCOMMAND
for file in $(INPUTFILES); do \
if test ! -f $$file; then $(LN_S) $(srcdir)/$$file $$file; fi; done
echo "stamp" > done-all-links
@EMPTY@else
@echo "sym-linking input files files..."
@for file in $(INPUTFILES); do \
if test ! -f $$file; then $(LN_S) $(srcdir)/$$file $$file; fi; done
@echo "stamp" > done-all-links
@EMPTY@endif
-DIPSYDefaults.rpo: done-all-links DIPSYDefaults.in libDIPSY.la $(EXTRACLASSES) $(THEPEGLIB)/ThePEGDefaults.rpo
+DIPSYDefaults.rpo: done-all-links DIPSYDefaults.in libDIPSY.la $(EXTRACLASSES) $(THEPEGLIB)/ThePEGDefaults.rpo ../lib/Ariadne5Defaults.rpo
$(SETUPTHEPEG) -L../lib -L$(THEPEGLIB) -L ../../TheP8I/lib -L .libs -L ../src/.libs --exitonerror --init -r ../lib/Ariadne5Defaults.rpo -o DIPSYDefaults.rpo DIPSYDefaults.in
+ cd ../lib; $(LN_S) -f ../DIPSY/DIPSYDefaults.rpo .
Test5%.run: Test5%.in DIPSYDefaults.rpo CurrentTune.in RivetAnalyses.in
$(SETUPTHEPEG) --exitonerror -L .libs -L ../../Pythia7/src/.libs -r DIPSYDefaults.rpo $<
%.run: %.in DIPSYDefaults.rpo CurrentTune.in RivetAnalyses.in
$(SETUPTHEPEG) -L../lib --exitonerror -L .libs -r DIPSYDefaults.rpo $<
%.out: %.run
time $(RUNTHEPEG) --tics -d 0 $<
valgrind:
valgrind --leak-check=full --num-callers=25 --track-fds=yes --freelist-vol=100000000 --leak-resolution=med --trace-children=yes $(top_builddir)/../ThePEG/src/setupThePEG -L ../../ThePEG/lib -L../../Pythia7/lib --exitonerror -L../../TheP8I/lib -L .libs -L ../lib -r ../lib/Ariadne5Defaults.rpo TestFull.in &> /tmp/valgrind.out
valgrind --leak-check=full --num-callers=25 --track-fds=yes --freelist-vol=100000000 --leak-resolution=med --trace-children=yes $(top_builddir)/../ThePEG/src/runThePEG -N 10 TestFull.run >> /tmp/valgrind.out 2>&1
install-data-local:
LD_LIBRARY_PATH=$(DESTDIR)$(pkglibdir):$$LD_LIBRARY_PATH $(DESTDIR)$(bindir)/setupThePEG --exitonerror --init -i $(DESTDIR)$(pkgdatadir) -r $(DESTDIR)$(pkglibdir)/ThePEGDefaults.rpo -o $(DESTDIR)$(pkglibdir)/ThePEGDefaults.rpo $(srcdir)/DIPSYDefaults.in
unregister-from-repo:
LD_LIBRARY_PATH=$(DESTDIR)$(pkglibdir):$$LD_LIBRARY_PATH $(DESTDIR)$(bindir)/setupThePEG --exitonerror --init -r $(DESTDIR)$(pkglibdir)/ThePEGDefaults.rpo -o $(DESTDIR)$(pkglibdir)/ThePEGDefaults.rpo $(srcdir)/DIPSYRemove.in
include $(top_srcdir)/Config/Makefile.aminclude
diff --git a/DIPSY/NewSwinger.cc b/DIPSY/NewSwinger.cc
--- a/DIPSY/NewSwinger.cc
+++ b/DIPSY/NewSwinger.cc
@@ -1,425 +1,425 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the Swinger class.
//
#include "Swinger.h"
#include "Dipole.h"
#include "DipoleState.h"
#include "DipoleEventHandler.h"
#include "ThePEG/Utilities/Current.h"
#include "ThePEG/Utilities/Throw.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Interface/Parameter.h"
#include "CPUTimer.h"
#ifdef ThePEG_TEMPLATES_IN_CC_FILE
// #include "Swinger.tcc"
#endif
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace DIPSY;
Swinger::~Swinger() {}
void Swinger::testGenerate(set<DipolePtr> & dips,double miny, double maxy) {
cout << "Testing Swinger....." << endl;
set<DipolePtr>::iterator it;
DipoleState testState = DipoleState();
for(it = dips.begin();it!=dips.end();it++) {
testState.addDipole(*(*it));
(*it)->dipoleState(& testState);
}
testState.sortDipoles();
thestMode = true;
ofstream youtput("SwingerTest.dat");
int ysteps = 100;
double ystepsize = 0.1;
vector<int> ybin(ysteps,0);
double y;
it=dips.begin();
for(int i=0;i<1000000;i++) {
(*it)->generatedY(maxy);
generate(*(*it),miny, maxy,true);
if((*it)->swingDipole()) {
y = (*it)->generatedY();
if(y-miny<ysteps*ystepsize)
ybin[int((y-miny)/ystepsize)]++;
}
(*it)->reset();
}
for(int i=0;i<ysteps;i++) {
youtput << (i+0.5)*ystepsize << '\t' << ybin[i] << endl;
}
youtput.close();
thestMode = false;
cout << "Done testing Swinger."
<< endl;
}
bool Swinger::forceGenerate(Dipole & dipole, double ymax) const {
const vector<tDipolePtr> & candidates =
dipole.dipoleState().swingCandidates(dipole.colour());
for (vector<tDipolePtr>::size_type i = 0; i < candidates.size(); i++ ) {
if ( candidates[i] == & dipole ) continue;
if ( candidates[i]->neighbors().first == & dipole ||
candidates[i]->neighbors().second == & dipole ) continue;
InvEnergy2 a = dipole.partons().first->dist2(*dipole.partons().second);
InvEnergy2 b = candidates[i]->partons().first->dist2(*(candidates[i]->partons().second));
InvEnergy2 c = dipole.partons().second->dist2(*candidates[i]->partons().first);
InvEnergy2 d = dipole.partons().first->dist2(*candidates[i]->partons().second);
a = sqr(Current<DipoleEventHandler>()->rMax())*
sqr(exp(sqrt(a)/Current<DipoleEventHandler>()->rMax()) - 1.0);
b = sqr(Current<DipoleEventHandler>()->rMax())*
sqr(exp(sqrt(b)/Current<DipoleEventHandler>()->rMax()) - 1.0);
c = sqr(Current<DipoleEventHandler>()->rMax())*
sqr(exp(sqrt(c)/Current<DipoleEventHandler>()->rMax()) - 1.0);
d = sqr(Current<DipoleEventHandler>()->rMax())*
sqr(exp(sqrt(d)/Current<DipoleEventHandler>()->rMax()) - 1.0);
double yi = -log( UseRandom::rnd() )*c*d/(a*b);
if ( yi < dipole.generatedY() || !(dipole.swingDipole()) ) {
if( yi < ymax || ymax == 0.0 ) { //Don't do ridiculously improbable swings.
dipole.swingDipole(candidates[i]);
dipole.generatedY(yi);
}
}
}
if( (dipole.swingDipole()) ) return true;
else return false;
}
void Swinger::generateFS(Dipole & dipole, double miny, double maxy) const {
//old implementation
bool force = !dipole.hasGen();
const vector<tDipolePtr> & candidates =
dipole.dipoleState().swingCandidates(dipole.colour());
vector<tDipolePtr>::size_type i = 0;
while ( i < candidates.size() && candidates[i++] != & dipole );
if ( i == candidates.size() && candidates[i - 1] != & dipole )
Throw<SwingConsistencyException>()
<< "FSswinger not found among candidates" << Exception::abortnow;
for (; i < candidates.size(); ++i ) {
if(candidates[i]->children().first)
cout << "OH NOES, parents among the swing candidates!!!! O_o" << endl;
if ( dipole.neighbors().first == candidates[i] ||
dipole.neighbors().second == candidates[i] )
continue;
if ( !force && candidates[i]->hasGen() ) continue;
// Generate a y
double R = -log( UseRandom::rnd() );
double amp = swingAmpFS(dipole.partons(),
candidates[i]->partons(), miny/GeV2);
// double amp = swingAmpFS(dipole, *candidates[i], miny/GeV2);
double yi = Constants::MaxRapidity;
if ( miny*amp + R < Constants::MaxRapidity*amp ) yi = miny + R/amp;
if ( yi < dipole.generatedY() || !dipole.hasGen() ) {
dipole.swingDipole(candidates[i]);
dipole.generatedY(yi);
dipole.recoilSwing(false);
}
}
}
InvEnergy2 Swinger::
swingDistanceFS(const Parton & p1, const Parton & p2, InvEnergy2 time) const {
// static CPUClock cpuclock("DIPSY::Swinger::swingDinstanceFS");
// CPUTimer timer(cpuclock);
static DebugItem notime("DIPSY::NoSwingTime", 60);
if ( notime ) time = ZERO;
Energy2 E2 = p1.plus()*p2.minus() + p1.minus()*p2.plus();
Parton::Point x1 = p1.position() - p2.position() + time*p1.pT();
Parton::Point x2 = p1.position() - p2.position() - time*p2.pT();
InvEnergy2 xxScalar = x1.x()*x2.x() + x1.y()*x2.y();
Energy2 ppScalar = p1.pT().x()*p2.pT().x() + p1.pT().y()*p2.pT().y();
InvEnergy2 a = sqr(time)*E2 + xxScalar - sqr(time)*ppScalar;
if ( a <= ZERO ) return ZERO;
double asa = Current<DipoleEventHandler>()->alphaS(sqrt(a));
InvEnergy rmax = Current<DipoleEventHandler>()->rMax();
return sqr(rmax)/asa*sqr(exp(sqrt(a)/rmax) - 1.0);
}
double Swinger::
swingAmpFS(InvEnergy2 a, InvEnergy2 b, InvEnergy2 c, InvEnergy2 d) const {
static double eps = 0.0000000000001;
if ( a <= ZERO || b <= ZERO || c <= ZERO || d <= ZERO ) return eps;
if ( sqrt(a*b) < sqrt(c)*sqrt(d)*sqrt(theLambda*eps) ) return eps;
return a*b/(c*d)*theLambda;
}
double Swinger::swingAmpFS(const pair<tPartonPtr, tPartonPtr> firstDip,
const pair<tPartonPtr, tPartonPtr> secondDip,
InvEnergy2 time) const {
//parton start in their original transverse position and z = 0, then move at
//lightspeed in a direction determined by the momentum.
static double eps = 0.0000000000001;
tPartonPtr p11 = firstDip.first;
tPartonPtr p12 = firstDip.second;
tPartonPtr p21 = secondDip.first;
tPartonPtr p22 = secondDip.second;
//these squared distances a,b,c,d between partons goes as (x1+t*pt1) - (x2+t*pt2) for small t,
//and as invariant mass times t for large t
Energy2 E2 = p11->plus()*p12->minus() + p11->minus()*p12->plus();
Parton::Point x1 = p11->position() - p12->position() + time*p11->pT();
Parton::Point x2 = p11->position() - p12->position() - time*p12->pT();
InvEnergy2 xxScalar = x1.x()*x2.x() + x1.y()*x2.y();
Energy2 ppScalar = p11->pT().x()*p12->pT().x() + p11->pT().y()*p12->pT().y();
InvEnergy2 a = sqr(time)*E2 + xxScalar - sqr(time)*ppScalar;
E2 = p21->plus()*p22->minus() + p21->minus()*p22->plus();
x1 = p21->position() - p22->position() + time*p21->pT();
x2 = p21->position() - p22->position() - time*p22->pT();
xxScalar = x1.x()*x2.x() + x1.y()*x2.y();
ppScalar = p21->pT().x()*p22->pT().x() + p21->pT().y()*p22->pT().y();
InvEnergy2 b = sqr(time)*E2 + xxScalar - sqr(time)*ppScalar;
E2 = p21->plus()*p12->minus() + p21->minus()*p12->plus();
x1 = p21->position() - p12->position() + time*p21->pT();
x2 = p21->position() - p12->position() - time*p12->pT();
xxScalar = x1.x()*x2.x() + x1.y()*x2.y();
ppScalar = p21->pT().x()*p12->pT().x() + p21->pT().y()*p12->pT().y();
InvEnergy2 c = sqr(time)*E2 + xxScalar - sqr(time)*ppScalar;
E2 = p11->plus()*p22->minus() + p11->minus()*p22->plus();
x1 = p11->position() - p22->position() + time*p11->pT();
x2 = p11->position() - p22->position() - time*p22->pT();
xxScalar = x1.x()*x2.x() + x1.y()*x2.y();
ppScalar = p11->pT().x()*p22->pT().x() + p11->pT().y()*p22->pT().y();
InvEnergy2 d = sqr(time)*E2 + xxScalar - sqr(time)*ppScalar;
if ( a <= ZERO || b <= ZERO || c <= ZERO || d <= ZERO ) return eps;
//normal confinement correction
InvEnergy rmax = Current<DipoleEventHandler>()->rMax();
double asa = Current<DipoleEventHandler>()->alphaS(sqrt(a));
double asb = Current<DipoleEventHandler>()->alphaS(sqrt(b));
double asc = Current<DipoleEventHandler>()->alphaS(sqrt(c));
double asd = Current<DipoleEventHandler>()->alphaS(sqrt(d));
a = sqr(rmax)/asa*sqr(exp(sqrt(a)/rmax) - 1.0);
b = sqr(rmax)/asb*sqr(exp(sqrt(b)/rmax) - 1.0);
c = sqr(rmax)/asc*sqr(exp(sqrt(c)/rmax) - 1.0);
d = sqr(rmax)/asd*sqr(exp(sqrt(d)/rmax) - 1.0);
//normal amplitude
if ( sqrt(a*b) < sqrt(c)*sqrt(d)*sqrt(theLambda*eps) ) return eps;
return a*b/(c*d)*theLambda;
}
void Swinger::generate(Dipole & dipole, double miny, double maxy, bool force) const {
//old implementation
double yi = max(max(dipole.partons().first->y(),
dipole.partons().second->y()), miny);
if ( dipole.partons().second == dipole.partons().first )
Throw<ColourIndexException>()
<< "Found inconsistent colour indices in DIPSY. Event discarded."
<< Exception::eventerror;
if( dipole.children().first)
Throw<SwingConsistencyException>()
<< "OH NOES, parents among the swing candidates!!!! O_o"
<< Exception::abortnow;
const vector<tDipolePtr> & candidates =
dipole.dipoleState().swingCandidates(dipole.colour());
vector<tDipolePtr>::size_type i = 0;
while ( i < candidates.size() && candidates[i++] != &dipole );
for (; i < candidates.size(); ++i ) {
if ( !force && candidates[i]->hasGen() ) continue;
double yn = yi - log(UseRandom::rnd())/swingAmp(dipole, *candidates[i]);
if ( yn < dipole.generatedY() ) {
dipole.swingDipole(candidates[i]);
dipole.generatedY(yn);
dipole.recoilSwing(false);
}
}
}
double Swinger::swingAmp(const Dipole & firstDip,
const Dipole & secondDip) const {
InvEnergy rmax = Current<DipoleEventHandler>()->rMax();
InvEnergy2 a = firstDip.swingCache;
if ( a < ZERO ) {
a = firstDip.partons().first->dist2(*firstDip.partons().second);
a = sqr(rmax)/(Current<DipoleEventHandler>()->alphaS(sqrt(a)))*
sqr(exp(sqrt(a)/rmax) - 1.0);
firstDip.swingCache = a;
}
InvEnergy2 b = secondDip.swingCache;
if ( b < ZERO ) {
b = secondDip.partons().first->dist2(*(secondDip.partons().second));
b = sqr(rmax)/(Current<DipoleEventHandler>()->alphaS(sqrt(b)))*
sqr(exp(sqrt(b)/rmax) - 1.0);
secondDip.swingCache = b;
}
InvEnergy2 c = firstDip.partons().second->dist2(*secondDip.partons().first);
c = sqr(rmax)/(Current<DipoleEventHandler>()->alphaS(sqrt(c)))*
sqr(exp(sqrt(c)/rmax) - 1.0);
InvEnergy2 d = firstDip.partons().first->dist2(*secondDip.partons().second);
d = sqr(rmax)/(Current<DipoleEventHandler>()->alphaS(sqrt(d)))*
sqr(exp(sqrt(d)/rmax) - 1.0);
return a*b/(c*d)*theLambda;
}
double Swinger::swingAmp(const pair<tPartonPtr, tPartonPtr> firstDip,
const pair<tPartonPtr, tPartonPtr> secondDip) const {
InvEnergy rmax = Current<DipoleEventHandler>()->rMax();
InvEnergy2 a = firstDip.first->dist2(*firstDip.second);
InvEnergy2 b = secondDip.first->dist2(*(secondDip.second));
InvEnergy2 c = firstDip.second->dist2(*secondDip.first);
InvEnergy2 d = firstDip.first->dist2(*secondDip.second);
a = sqr(rmax)/
(Current<DipoleEventHandler>()->alphaS(sqrt(a)))*
sqr(exp(sqrt(a)/rmax) - 1.0);
b = sqr(rmax)/
(Current<DipoleEventHandler>()->alphaS(sqrt(b)))*
sqr(exp(sqrt(b)/rmax) - 1.0);
c = sqr(rmax)/
(Current<DipoleEventHandler>()->alphaS(sqrt(c)))*
sqr(exp(sqrt(c)/rmax) - 1.0);
d = sqr(rmax)/
(Current<DipoleEventHandler>()->alphaS(sqrt(d)))*
sqr(exp(sqrt(d)/rmax) - 1.0);
return a*b/(c*d)*theLambda;
}
bool Swinger::checkMaxY(DipolePtr d1, DipolePtr d2, double maxy) const {
tPartonPtr p1 = d1->partons().first;
tPartonPtr p2 = d1->partons().second;
tPartonPtr p3 = d2->partons().first;
tPartonPtr p4 = d2->partons().second;
TransverseMomentum rec12 = (p1->position() - p2->position())/
(p1->position() - p2->position()).pt2();
TransverseMomentum rec34 = (p3->position() - p4->position())/
(p3->position() - p4->position()).pt2();
TransverseMomentum rec14 = (p1->position() - p4->position())/
(p1->position() - p4->position()).pt2();
TransverseMomentum rec32 = (p3->position() - p2->position())/
(p3->position() - p2->position()).pt2();
if ( log( (p1->pT() - rec12 + rec14).pt()/p1->plus()) > maxy )
return false;
if ( log( (p2->pT() + rec12 - rec32).pt()/p2->plus()) > maxy )
return false;
if ( log( (p3->pT() - rec34 + rec32).pt()/p3->plus()) > maxy )
return false;
if ( log( (p4->pT() + rec34 - rec14).pt()/p4->plus()) > maxy )
return false;
return true;
}
void Swinger::recombineFS(Dipole & d1) const {
Dipole & d2 = *d1.swingDipole();
pair<tPartonPtr, tPartonPtr> d1p = d1.partons();
pair<tPartonPtr, tPartonPtr> d2p = d2.partons();
pair<tDipolePtr, tDipolePtr> d1n = d1.neighbors();
pair<tDipolePtr, tDipolePtr> d2n = d2.neighbors();
d1.partons(make_pair(d1p.first, d2p.second));
d1.neighbors(make_pair(d1n.first, d2n.second));
if ( d1n.first ) d1n.first->secondNeighbor(&d1);
if ( d2n.second ) d2n.second->firstNeighbor(&d1);
d2.partons(make_pair(d2p.first, d1p.second));
d2.neighbors(make_pair(d2n.first, d1n.second));
if ( d2n.first ) d2n.first->secondNeighbor(&d2);
if ( d1n.second ) d1n.second->firstNeighbor(&d2);
d1.partons().first->dipoles(make_pair(d1.neighbors().first, &d1));
d1.partons().second->dipoles(make_pair(&d1, d1.neighbors().second));
d2.partons().first->dipoles(make_pair(d2.neighbors().first, &d2));
d2.partons().second->dipoles(make_pair(&d2, d2.neighbors().second));
d1.reset();
d2.reset();
d1.touch();
d2.touch();
}
void Swinger::recombine(Dipole & d1) const {
DipoleState & state = d1.dipoleState();
Dipole & d2 = *d1.swingDipole();
if(d2.children().second) {
Throw<SwingConsistencyException>()
<< "swinging with someone thats emitted already (second child). "
<< "(partons at " << d1.partons().first->y() << ", "
<< d1.partons().second->y() << "; " << d2.partons().first->y()
<< ", " << d2.partons().second->y() << ")" << Exception::eventerror;
state.diagnosis(true);
}
else if(d2.children().first) {
Throw<SwingConsistencyException>()
<< "swinging with someone thats emitted already (first child). "
<< "(partons at " << d1.partons().first->y() << ", "
<< d1.partons().second->y() << "; " << d2.partons().first->y()
<< ", " << d2.partons().second->y() << ")" << Exception::eventerror;
state.diagnosis(true);
}
DipolePtr d11 = d1.children().first = state.createDipole();
DipolePtr d22 = d2.children().first = state.createDipole();
d11->partons(make_pair(d1.partons().first, d2.partons().second));
d11->neighbors(make_pair(d1.neighbors().first, d2.neighbors().second));
if ( d1.neighbors().first ) d1.neighbors().first->secondNeighbor(d11);
if ( d2.neighbors().second ) d2.neighbors().second->firstNeighbor(d11);
d22->partons(make_pair(d2.partons().first, d1.partons().second));
d22->neighbors(make_pair(d2.neighbors().first, d1.neighbors().second));
if ( d2.neighbors().first ) d2.neighbors().first->secondNeighbor(d22);
if ( d1.neighbors().second ) d1.neighbors().second->firstNeighbor(d22);
d11->colour(d1.colour());
d22->colour(d2.colour());
d11->partons().first->dipoles(make_pair(d11->neighbors().first,d11));
d11->partons().second->dipoles(make_pair(d11,d11->neighbors().second));
d22->partons().first->dipoles(make_pair(d22->neighbors().first,d22));
d22->partons().second->dipoles(make_pair(d22,d22->neighbors().second));
if (d1.DGLAPsafe() || d2.DGLAPsafe() ) {
d11->DGLAPsafe(true);
d22->DGLAPsafe(true);
}
if ( d1.interacted() ) d11->interact(*d1.interacted());
if ( d2.interacted() ) d22->interact(*d2.interacted());
d1.reset();
d2.reset(); //are these really needed?
}
void Swinger::persistentOutput(PersistentOStream & os) const {
os << ounit(theLambda, 1.0);
}
void Swinger::persistentInput(PersistentIStream & is, int) {
is >> iunit(theLambda, 1.0);
}
// Static variable needed for the type description system in ThePEG.
#include "ThePEG/Utilities/DescribeClass.h"
DescribeClass<Swinger,HandlerBase>
- describeDIPSYSwinger("DIPSY::Swinger", "libDIPSY.so");
+ describeDIPSYSwinger("DIPSY::Swinger", "libAriadne5.so libDIPSY.so");
void Swinger::Init() {
static ClassDocumentation<Swinger> documentation
("There is no documentation for the Swinger class");
static Parameter<Swinger,double> interfaceLambda
("Lambda",
"The frequency of the swings.",
&Swinger::theLambda, 1.0, 1.0, 0.0, 0.0,
true, false, Interface::lowerlim);
}
diff --git a/DIPSY/NucleusData.cc b/DIPSY/NucleusData.cc
--- a/DIPSY/NucleusData.cc
+++ b/DIPSY/NucleusData.cc
@@ -1,102 +1,102 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the NucleusData class.
//
#include "NucleusData.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace DIPSY;
NucleusData::NucleusData() : theA(2), theZ(1) {}
NucleusData::~NucleusData() {}
NucleusData::NucleusData(long newId, string newPDGName)
: ParticleData(newId, newPDGName), theA(2), theZ(1) {}
PDPtr NucleusData::
Create(long newId, string newPDGName) {
return new_ptr(NucleusData(newId, newPDGName));
}
PDPair NucleusData::
Create(long newId, string newPDGName, string newAntiPDGName) {
PDPair pap;
pap.first = new_ptr(NucleusData(newId, newPDGName));
pap.second = new_ptr(NucleusData(-newId, newAntiPDGName));
antiSetup(pap);
return pap;
}
void NucleusData::readSetup(istream & is) {
ParticleData::readSetup(is);
is >> theA >> theZ;
}
PDPtr NucleusData::pdclone() const {
return new_ptr(*this);
}
IBPtr NucleusData::clone() const {
return new_ptr(*this);
}
IBPtr NucleusData::fullclone() const {
return new_ptr(*this);
}
// If needed, insert default implementations of virtual function defined
// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs).
void NucleusData::persistentOutput(PersistentOStream & os) const {
os << theA << theZ;
}
void NucleusData::persistentInput(PersistentIStream & is, int) {
is >> theA >> theZ;
}
// *** Attention *** The following static variable is needed for the type
// description system in ThePEG. Please check that the template arguments
// are correct (the class and its base class), and that the constructor
// arguments are correct (the class name and the name of the dynamically
// loadable library where the class implementation can be found).
DescribeClass<NucleusData,ThePEG::ParticleData>
- describeDIPSYNucleusData("DIPSY::NucleusData", "libDIPSY.so");
+ describeDIPSYNucleusData("DIPSY::NucleusData", "libAriadne5.so libDIPSY.so");
void NucleusData::Init() {
static ClassDocumentation<NucleusData> documentation
("There is no documentation for the NucleusData class");
static Parameter<NucleusData,unsigned int> interfaceA
("A",
"The atomic number for this nucleus.",
&NucleusData::theA, 2, 2, 0,
true, false, Interface::lowerlim);
static Parameter<NucleusData,int> interfaceZ
("Z",
"The number of protons in this nucleus.",
&NucleusData::theZ, 1, 0, 0,
true, false, Interface::nolimits);
}
diff --git a/DIPSY/PPTune/PPTune.inc b/DIPSY/PPTune/PPTune.inc
--- a/DIPSY/PPTune/PPTune.inc
+++ b/DIPSY/PPTune/PPTune.inc
@@ -1,83 +1,143 @@
cd /DIPSY
## First we setup some previously tuned tuned parameters
#read CurrentTune.in
read ../Tune31.in
## Now we set up an event generator.
cp EventHandler PPEventHandler
set stdProton:R0 0.0
set stdAntiProton:R0 0.0
+set Proton:R0 0.0
+set AntiProton:R0 0.0
set PPEventHandler:WFL stdProton
set PPEventHandler:WFR stdProton
set PPEventHandler:ConsistencyLevel 0
set PPEventHandler:XSecFn:CheckOffShell false
set PPEventHandler:CascadeHandler NULL
set PPEventHandler:HadronizationHandler NULL
set PPEventHandler:DecayHandler NULL
create ThePEG::FixedCMSLuminosity PPLumi
set PPEventHandler:LuminosityFunction PPLumi
cp Generator PPGenerator
erase PPGenerator:AnalysisHandlers[0]
set PPGenerator:HistogramFactory NULL
set PPGenerator:EventHandler PPEventHandler
set PPGenerator:NumberOfEvents 0
set PPGenerator:EventHandler:EventFiller:PTCut 0.6
set PPEventHandler:BGen:Width 5
set PPEventHandler:EffectivePartonMode Colours
## These are the analysess we will run
## Some semi-inclusive cross section for DIPSY which need at least
## four combinations of left- and right-moving cascades.
erase PPEventHandler:AnalysisHandlers[0]
erase PPEventHandler:AnalysisHandlers[0]
create DIPSY::SemiInclusiveXSecAnalysis SemiIncl SemiInclusiveXSecAnalysis.so
insert PPEventHandler:AnalysisHandlers[0] SemiIncl
set PPEventHandler:PreSampleL 2
set PPEventHandler:PreSampleR 2
## This is just to keep track of the progress of a run
create DIPSY::AnalysisProgress AnaLog AnalysisProgress.so
set AnaLog:Interval 600
insert PPEventHandler:AnalysisHandlers[0] AnaLog
## The sample rates need to be adjusted so that we get a reasonable
## statistics in a reasonable time. It is typically efficient to
## sample a number of impact parameter values for each pair of DIPSY
## cascades.
set PPEventHandler:PreSampleB 10
## But we need a good sample of cascades
set PPEventHandler:PreSamples 1000
## We need the same set of parameters for all different energies, so
## we use a separate random generator.
cp /Defaults/Random RandomArg
set PPGenerator:SeparateRandom RandomArg
## These are the parameters we want to tune
do PPGenerator:AddRndInterface /DIPSY/PPEventHandler:RMax 100 2.0 4.0 2.9 0.3
do PPGenerator:AddRndInterface /DIPSY/PPEventHandler:LambdaQCD 1 0.10 0.3 0.22 0.04
do PPGenerator:AddRndInterface /DIPSY/PPEventHandler:BaryonSize 1 2.0 4.0 2.9 0.3
do PPGenerator:AddRndInterface /DIPSY/PPEventHandler:Emitter:PMinusOrdering 1 0.5 2.0 1.0 0.2
do PPGenerator:AddRndInterface /DIPSY/PPEventHandler:Emitter:PSInflation 1 0.5 2.0 1.0 0.2
## Now we want to run for all energies and two values for YFrametest
-SAVERUN PP02XSEC PPGenerator
+SAVERUN PP01XSEC PPGenerator
## Set the pp energy and interaction frame we want to run with
do PPGenerator:RemoveInterface /DIPSY/PPEventHandler:BaryonSize
set /DIPSY/PPEventHandler:BaryonSize 0.0
do PPGenerator:AddRndInterface /DIPSY/PPEventHandler:Emitter:PSInflation 1 0.5 2.0 1.0 0.2
SAVERUN PP02XSEC PPGenerator
do PPGenerator:RemoveInterface /DIPSY/PPEventHandler:Emitter:PSInflation
do PPGenerator:AddRndInterface /DIPSY/PPEventHandler:Swinger:Lambda 1 0.5 4.0 1.0 0.5
-SAVERUN PP03XSEC PPGenerator
+SAVERUN PP05XSEC PPGenerator
do PPGenerator:RemoveInterface /DIPSY/PPEventHandler:Swinger:Lambda
-do PPGenerator:AddRndInterface /DIPSY/PPEventHandler:Swinger:Lambda 1 0.0 6.0
+do PPGenerator:AddRndInterface /DIPSY/PPEventHandler:Swinger:Lambda 2 0.0 6.0
-SAVERUN PP04XSEC PPGenerator
+SAVERUN PP06XSEC PPGenerator
+
+do PPGenerator:RemoveInterface /DIPSY/PPEventHandler:Swinger:Lambda
+set PPEventHandler:Swinger:Lambda 5.0
+do PPGenerator:RemoveInterface /DIPSY/PPEventHandler:RMax
+do PPGenerator:AddRndInterface /DIPSY/PPEventHandler:RMax 100 1.0 5.0 2.9 0.6
+SAVERUN PP07XSEC PPGenerator
+do PPGenerator:AddRndInterface /DIPSY/PPEventHandler:BaryonSize 1 2.0 4.0 2.9 0.5
+SAVERUN PP08XSEC PPGenerator
+set PPEventHandler:Swinger:Lambda 2.0
+SAVERUN PP09XSEC PPGenerator
+
+do PPGenerator:RemoveInterface /DIPSY/PPEventHandler:Swinger:Lambda
+do PPGenerator:RemoveInterface /DIPSY/PPEventHandler:Emitter:PMinusOrdering
+do PPGenerator:RemoveInterface /DIPSY/PPEventHandler:RMax
+do PPGenerator:RemoveInterface /DIPSY/PPEventHandler:LambdaQCD
+do PPGenerator:RemoveInterface /DIPSY/PPEventHandler:BaryonSize
+set PPEventHandler:RMax 2.95
+set PPEventHandler:Swinger:Lambda 1.3
+set PPEventHandler:Emitter:PMinusOrdering 0.52
+set PPEventHandler:LambdaQCD 0.20
+SAVERUN PP05XSECt PPGenerator
+
+set PPEventHandler:RMax 3.0
+set PPEventHandler:Swinger:Lambda 2.0
+set PPEventHandler:Emitter:PMinusOrdering 0.48
+set PPEventHandler:LambdaQCD 0.20
+SAVERUN PP03XSECt PPGenerator
+
+set Frag8:StringZ_aLund 0.42
+set Frag8:StringZ_bLund 0.40
+set Frag8:StringPT_sigma 0.32
+set Frag8:StringFlav_probQQtoQ 0.084
+set Frag8:StringFlav_probStoUD 0.22
+
+set PPGenerator:EventHandler:YFrametest 0.5
+set PPGenerator:EventHandler:DecayHandler /Defaults/Handlers/StandardDecayHandler
+set PPGenerator:EventHandler:HadronizationHandler Frag8
+set PPGenerator:EventHandler:CascadeHandler AriadneCascade
+set PPGenerator:EventHandler:PreSamples 0
+set PPGenerator:NumberOfEvents 1000
+create ThePEG::ProgressLog Logger ProgressLog.so
+set Logger:Interval 600
+insert PPGenerator:AnalysisHandlers[0] Logger
+create ThePEG::RivetAnalysis RivetLHC RivetAnalysis.so
+insert RivetLHC:Analyses[0] ATLAS_2010_S8918562
+insert PPGenerator:AnalysisHandlers[0] RivetLHC
+
+saverun PP01Full70 PPGenerator
+set PPEventHandler:WFL:RemnantDecayer /Defaults/Partons/BaryonRemnantDecayer
+set PPEventHandler:EventFiller:SoftRemove NoValence
+saverun PP03Full70 PPGenerator
+
+set PPEventHandler:WFL Proton
+set PPEventHandler:WFR Proton
+set PPEventHandler:EventFiller:SoftRemove NoValence
+# set PPEventHandler:EventFiller:ValenceChargeNormalisation None
+saverun PP02Full70 PPGenerator
+
diff --git a/DIPSY/PPTune/mkprof.pl b/DIPSY/PPTune/mkprof.pl
--- a/DIPSY/PPTune/mkprof.pl
+++ b/DIPSY/PPTune/mkprof.pl
@@ -1,90 +1,95 @@
#! /usr/bin/perl -w
use strict;
use Getopt::Std;
my %opts;
getopts('trw:c:',\%opts);
my $weights = "";
$weights = $opts{'w'} if defined($opts{'w'});
my $combinations = "30:100";
$combinations = $opts{'c'} if defined($opts{'c'});
die "No filetag specified" if !@ARGV;
my $tag = $ARGV[0];
my $profdir = "$tag.prof";
mkdir $profdir;
mkdir "$profdir/mc";
my @files = glob("$tag*.log");
foreach my $file ( @files ) {
system("./seminc.pl $file");
my $YF = 0;
if ( $file =~ /Y(\d)\.log/ ) {
$YF = $1;
print "shifted frame ($YF) in $file\n";
}
open(LOGFILE, "<$file");
while ( <LOGFILE> ) {
if ( /^>> (\w+) sub-run number (\d+)/ ) {
my $dir = "$profdir/mc/$tag-$2";
+ my $runno = $2;
+ my $runname = $1;
+ if ( $runname =~ /^(.*)#/ ) {
+ $runname = $1;
+ }
mkdir $dir;
- my $yodafile = "$1:$2.yoda";
+ my $yodafile = "$runname:$runno.yoda";
my $copy = "cp $yodafile $dir/$yodafile";
if ( $YF ) {
system("sed -e 's/\-x0/-x8/' $yodafile > $dir/$yodafile");
} else {
system("cp $yodafile $dir/$yodafile");
}
if ( defined($opts{'r'}) ) {
system("rm $yodafile");
}
my $params = "$dir/used_params";
$params = "$dir/new_params" if -e $params;
while ( <LOGFILE> ) {
if ( /^\s+set\s+(\S+)\s+(\S+)/ ) {
system("echo $1 $2 >> $params");
} else {
last;
}
}
if ( -e "$dir/new_params" ) {
if ( system("diff -q $dir/new_params $dir/used_params") ) {
die "Warning: inconsistent parameters in $dir/used_params";
}
system("rm $dir/new_params");
}
}
}
}
foreach my $dir ( glob("$profdir/mc/$tag-*") ) {
system("cd $dir; cat *.yoda > out.yoda; yoda2aida out.yoda out.aida");
}
system ("cd $profdir; ln -s ../refs ref");
if ( $weights ) {
die "Cannot find weights file $weights"
if system("cp $weights $profdir/weights");
}
elsif ( -e "$tag.weights" ) {
system("cp $tag.weights $profdir/weights");
}
else {
system("cd $profdir; prof-lsobs --mcdir mc --weight=1.0 > weights");
}
system("cd $profdir; prof-runcombs --mcdir mc -c $combinations -o runcombs.dat; prof-interpolate --datadir . --weights weights --runs runcombs.dat");
if ( defined($opts{'t'}) ) {
system("cd $profdir; prof-tune --datadir . --weights weights --runs runcombs.dat");
}
diff --git a/DIPSY/PPTune/seminc.pl b/DIPSY/PPTune/seminc.pl
--- a/DIPSY/PPTune/seminc.pl
+++ b/DIPSY/PPTune/seminc.pl
@@ -1,116 +1,119 @@
#!/usr/bin/perl -w
use strict;
sub inputerror($);
sub writefile($$$$$);
my @energy;
my @frame;
my @xsec;
my @xsecerr;
my @elxsec;
my @elxsecerr;
-my $i;
+my $i = 0;
my $runname = "";
my $E = 0;
my $hist = "d00";
my $x = 0;
my $dx = 0;
while ( <> ) {
if ( />> (\S+) sub-run number\s+(\d+)/ ) {
$i = $2;
$runname = $1;
+ if ( $runname =~ /^(.*)#/ ) {
+ $runname = $1;
+ }
}
elsif ( /Starting DIPSY run at CoM energy (\d+) GeV/ ) {
$E = $1;
if ( $E == 7000 ) {
$hist = "d01";
}
elsif ( $E == 1800 ) {
$hist = "d02";
}
elsif ( $E == 540 ) {
$hist = "d03";
}
elsif ( $E == 140 ) {
$hist = "d04";
}
else {
$hist = "";
}
}
elsif ( /SemiIncl: Total:\s*(\S+)/ ) {
if ( $hist && $hist ne "d03" ) {
($x, $dx) = inputerror($1);
writefile("$runname:$i.yoda", "$hist-x01-y01", $E, $x, $dx);
}
}
elsif ( /SemiIncl: Elastic:\s*(\S+)/ ) {
if ( $hist && $hist ne "d04" ) {
($x, $dx) = inputerror($1);
writefile("$runname:$i.yoda", "$hist-x01-y02", $E, $x, $dx);
}
}
}
sub inputerror($) {
if ( $_[0] =~ /([-+]?\d+\.?(\d*))\((\d+)\)([eE][+-]?\d+)/ ) {
return ( "$1$4", $3*"1$4"*10**(-length($2)) );
}
return (0, 0);
}
sub writefile($$$$$) {
my $file = $_[0];
my $tag = $_[1];
my $E = $_[2];
my $x = $_[3];
my $dx = $_[4];
my $old = 0;
if ( -e $file ) {
system("mv $file $file~" );
$old = 1;
}
open NFL, ">$file";
if ( $old ) {
open OFL, "<$file~";
my $keep = 1;
while ( <OFL> ) {
if ( $keep ) {
if ( /# BEGIN YODA_SCATTER2D \/TOTALXSEC\/$tag/ ) {
$keep = 0;
} else {
print NFL;
}
} else {
if ( /# END YODA_SCATTER2D/ ) {
$keep = 1;
<OFL>;
}
}
}
} else {
open NFL, ">$file";
}
print NFL "# BEGIN YODA_SCATTER2D /TOTALXSEC/$tag\n";
print NFL "Path=/TOTALXSEC/$tag\n";
print NFL "Type=Scatter2D\n";
print NFL "# xval xerr- xerr+ yval yerr- yerr+\n";
printf NFL "%e %e %e %e %e %e\n",
$E, 5.0, 5.0, $x/1000000.0, $dx/1000000.0, $dx/1000000.0;
print NFL "# END YODA_SCATTER2D\n\n";
close NFL;
if ( $old ) {
close OFL;
system("rm $file~" );
}
}
diff --git a/DIPSY/Parton.cc b/DIPSY/Parton.cc
--- a/DIPSY/Parton.cc
+++ b/DIPSY/Parton.cc
@@ -1,250 +1,250 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the Parton class.
//
#include "Parton.h"
#include "DipoleState.h"
#include "DipoleEventHandler.h"
#include "Dipole.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/Repository/CurrentGenerator.h"
#include "ThePEG/Utilities/Debug.h"
#include "ThePEG/Utilities/Throw.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Utilities/DescribeClass.h"
using namespace DIPSY;
Parton::~Parton() {}
-Ariadne::ClonePtr Parton::clone() const {
+Ariadne5::ClonePtr Parton::clone() const {
return new_ptr(*this);
}
void Parton::rebind(const TranslationMap & trans) {
theParents.first = trans.translate(theParents.first);
theParents.second = trans.translate(theParents.second);
theDipoles.first = trans.translate(theDipoles.first);
theDipoles.second = trans.translate(theDipoles.second);
set<tPartonPtr> kids;
kids.swap(theChildren);
trans.translate(inserter(theChildren), kids.begin(), kids.end());
}
void Parton::interact() {
if ( interacted() ) return;
hasInteracted = true;
if ( parents().first ) parents().first->interact();
if ( parents().second ) parents().second->interact();
}
bool Parton::inInteractingLoop() const {
//search in one direction
DipolePtr d = dipoles().first;
while ( d && d != dipoles().second && !(d->interacted()) ) {
if ( d->neighbors().first )
d = d->neighbors().first;
else
break;
}
if ( !d ) { //if stopped at a quark, look also in other direction
d = dipoles().second;
while ( d && d != dipoles().second && !(d->interacted()) ) {
if ( d->neighbors().first )
d = d->neighbors().first;
else
break;
}
}
if ( d && d->interacted() )
return true;
else
return false;
}
int Parton::nOnShellInChain() const {
int ret = 0;
DipolePtr d = dipoles().first;
if ( onShell() ) ret++;
while ( d && d != dipoles().second ) {
if ( d->partons().first->onShell() ) ret++;
d = d->neighbors().first;
}
if ( !d ) {
d = dipoles().second;
while ( d ) {
if ( d->partons().second->valence() ) ret++;
d = d->neighbors().second;
}
}
return ret;
}
DipoleState& Parton::dipoleState() const {
if ( dipoles().first ) return dipoles().first->dipoleState();
else return dipoles().second->dipoleState();
}
bool Parton::valenceParton() const {
DipoleState & state = dipoleState();
for ( int i = 0, N = state.initialDipoles().size(); i < N; i++ ) {
if ( state.initialDipoles()[i]->partons().first == this ||
state.initialDipoles()[i]->partons().second == this )
return true;
}
return false;
}
bool Parton::inValenceChain() const {
//search in one direction
DipolePtr d = dipoles().first;
if ( valence() ) {
if ( !d )
cout << "found valence quark" << endl;
return true;
}
while ( d && d != dipoles().second ) {
if ( d->partons().first->valence() ) {
return true;
}
d = d->neighbors().first;
}
if ( !d ) { //if stopped at a quark, look also in other direction
cout << "found non-valence quark at x =" << position().x()*GeV
<< ", y = " << position().y()*GeV << endl;
DipoleState & state = dipoleState();
for ( int i = 0, N = state.initialDipoles().size(); i < N; i++ ) {
cout << "valence partons at x = "
<< state.initialDipoles()[i]->partons().first->position().x()*GeV
<< ", y = " << state.initialDipoles()[i]->partons().first->position().y()*GeV << endl;
cout << "valence partons at x = "
<< state.initialDipoles()[i]->partons().second->position().x()*GeV
<< ", y = "
<< state.initialDipoles()[i]->partons().second->position().y()*GeV << endl;
}
d = dipoles().second;
while ( d && d != dipoles().second ) {
if ( d->partons().second->valence() ) {
return true;
}
d = d->neighbors().second;
}
}
return false;
}
bool Parton::swingedEmission() const {
if ( !parents().first || !parents().second ) return false;
else if ( parents().first->parents().second == parents().second ) return false;
else if ( parents().second->parents().first == parents().first ) return false;
if ( Debug::level > 5 ) cout << "parton at " << oY() << " is a swinged emission" << endl;
return true;
}
bool Parton::absorbed() const {
return dipoles().first->children().first || dipoles().first->children().second ||
dipoles().second->children().first || dipoles().second->children().second;
}
double Parton::pTScale() const {
return dipoleState().handler().emitter().pTScale();
}
void Parton::updateMomentum() {
if ( dipoles().first && dipoles().second ) {
tPartonPtr p1 = dipoles().first->partons().first;
tPartonPtr p2 = dipoles().second->partons().second;
pT( pTScale()*((position() - p1->position())/(position() - p1->position()).pt2() +
(position() - p2->position())/(position() - p2->position()).pt2()) );
}
else if ( dipoles().first ) {
tPartonPtr p1 = dipoles().first->partons().first;
pT( pTScale()*(position() - p1->position())/(position() - p1->position()).pt2());
}
else if ( dipoles().second ) {
tPartonPtr p2 = dipoles().second->partons().second;
pT( pTScale()*(position() - p2->position())/(position() - p2->position()).pt2() );
}
else
cout << "Parton without any dipoles?? :o" << endl;
if ( isRightMoving ) {
y( log(pT().pt()/plus()) );
minus( pT().pt()*exp(y()) );
}
else {
y( log(minus()/pT().pt()) );
plus( pT().pt()*exp(-y()) );
}
}
TransverseMomentum Parton::recoil(tPartonPtr p) const {
return pTScale()*(position() - p->position())/dist2(*p);
}
Energy Parton::mass() const {
if ( theMass < ZERO )
theMass = CurrentGenerator::current().getParticleData(flavour())->mass();
return theMass;
}
PPtr Parton::produceParticle() const {
return dipoleState().getParticle(this);
}
void Parton::coutData() {
cout << "data for Parton " << this << endl;
cout << "thePosition1: " << thePosition.first*GeV
<< ", thePosition2: " << thePosition.second*GeV
<< ", thePlus: " << thePlus/GeV
<< ", theOriginalY: " << theOriginalY
<< ", thePT: " << thePT.pt()/GeV
<< ", theValencePT: " << theValencePT.pt()/GeV
<< ", theValencePlus: " << theValencePlus/GeV
<< ", theMinus: " << theMinus/GeV
<< ", theY: " << theY
<< ", isRightMoving: " << isRightMoving
<< ", theFlavour: " << theFlavour
<< ", theParents1: " << theParents.first
<< ", theParents2: " << theParents.second
<< ", theChildren: ";
for( set<tPartonPtr>::iterator it = theChildren.begin();
it != theChildren.end();it++)
cout << *it << ", ";
cout << "theDipoles1: " << theDipoles.first
<< ", theDipoles2: " << theDipoles.second
<< ", hasInteracted: " << hasInteracted
<< ", isOrdered: " << isOrdered
<< ", isOnShell: " << isOnShell
<< ", isValence: " << isValence
<< ", theNumber: " << theNumber
<< ", theMass: " << theMass/GeV << endl;
}
void Parton::persistentOutput(PersistentOStream & os) const {
os << ounit(thePosition, InvGeV) << ounit(thePlus, GeV) << theOriginalY
<< ounit(thePT, GeV) << ounit(theValencePT, GeV)
<< ounit(theValencePlus, GeV) << ounit(theMinus, GeV) << theY
<< isRightMoving << theFlavour << theParents << theDipoles
<< hasInteracted << isOrdered << isOnShell << isValence
<< ounit(theMass, GeV);
}
void Parton::persistentInput(PersistentIStream & is, int) {
is >> iunit(thePosition, InvGeV) >> iunit(thePlus, GeV) >> theOriginalY
>> iunit(thePT, GeV) >> iunit(theValencePT, GeV)
>> iunit(theValencePlus, GeV) >> iunit(theMinus, GeV) >> theY
>> isRightMoving >> theFlavour >> theParents >> theDipoles
>> hasInteracted >> isOrdered >> isOnShell >> isValence
>> iunit(theMass, GeV);
}
-DescribeClass<Parton,Ariadne::CloneBase>
-describeDIPSYParton("DIPSY::Parton", "libDIPSY.so");
+DescribeClass<Parton,Ariadne5::CloneBase>
+describeDIPSYParton("DIPSY::Parton", "libAriadne5.so libDIPSY.so");
// Definition of the static class description member.
void Parton::Init() {}
diff --git a/DIPSY/Parton.h b/DIPSY/Parton.h
--- a/DIPSY/Parton.h
+++ b/DIPSY/Parton.h
@@ -1,539 +1,539 @@
// -*- C++ -*-
#ifndef DIPSY_Parton_H
#define DIPSY_Parton_H
//
// This is the declaration of the Parton class.
//
#include "ThePEG/Config/ThePEG.h"
#include "ThePEG/Vectors/Transverse.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "Ariadne/Config/CloneBase.h"
#include "Parton.fh"
#include "Dipole.fh"
namespace DIPSY {
using namespace ThePEG;
/**
* Here is the documentation of the Parton class.
*/
-class Parton: public Ariadne::CloneBase {
+class Parton: public Ariadne5::CloneBase {
public:
friend class RealParton;
/**
* Typedef for position in transverse coordinate space.
*/
typedef Transverse<InvEnergy> Point;
/**
* A pair of partons.
*/
typedef pair<tPartonPtr,tPartonPtr> tPartonPair;
/**
* A pair of dipoles.
*/
typedef pair<tDipolePtr,tDipolePtr> tDipolePair;
/**
* The Dipole is a friend.
*/
friend class Dipole;
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
inline Parton();
/**
* The copy constructor.
*/
inline Parton(const Parton &);
/**
* The destructor.
*/
virtual ~Parton();
//@}
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 Ariadne::ClonePtr clone() const;
+ 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 Parton &) const;
/**
* Produce a ThePEG::Particle corresponding to this parton.
*/
PPtr produceParticle() const;
/**
* The mass of this parton.
*/
Energy mass() const;
/**
* The final-state momentum of this particle.
*/
LorentzMomentum momentum() const {
return lightCone(plus(), (pT().pt2() + sqr(mass()))/plus(), pT());
}
/** @name Simple access functions. */
//@{
/**
* Get the position in impact parameter space.
*/
inline const Point & position() const;
/**
* Get the positive light-cone momentum.
*/
inline Energy plus() const;
/**
* Get the transverse momentum.
*/
inline TransverseMomentum pT() const;
/**
* Get the transverse valence momentum. 0 if not a valence parton.
*/
inline TransverseMomentum valencePT() const;
/**
* Get the valence energy. 0 if not a valence parton.
*/
inline Energy valencePlus() const;
/**
* Get the accumulated negative light-cone momentum deficit.
*/
inline Energy minus() const;
/**
* Get the rapidity.
*/
inline double y() const;
/**
* Get the flavour of this parton.
*/
inline long flavour() const;
/**
* Get the parent partons.
*/
inline tPartonPair parents() const;
/**
* Get the children partons.
*/
inline const set<tPartonPtr> & children() const {
return theChildren;
};
/**
* Remove a child
**/
inline void removeChild(PartonPtr child) {
theChildren.erase(child);
};
/**
* Remove all children
**/
inline void removeAllChildren() {
theChildren.clear();
};
/**
* Get the connecting dipoles.
*/
inline tDipolePair dipoles() const;
/**
* Indicate if this parton has interacted.
*/
inline bool interacted() const;
/**
* Indicate if this parton is ordered.
*/
inline bool ordered() const;
/**
* Set if this parton is ordered.
*/
inline void ordered(bool);
/**
* Return if this parton is on shell.
*/
inline bool onShell() const;
/**
* Set if this parton is on shell.
*/
inline void onShell(bool);
/**
* Return if this parton is a valence parton.
*/
inline bool valence() const;
/**
* Returns true if the parton is absorbed.
*/
bool absorbed() const;
/**
* Set if this parton is a valence parton.
*/
inline void valence(bool);
/**
* Set the position in impact parameter space.
*/
inline void position(const Point &);
/**
* Set the positive light-cone momentum.
*/
inline void plus(Energy);
/**
* Set the transverse momentum.
*/
inline void pT(TransverseMomentum);
/**
* Set the transverse valence momentum, and set isValence to true.
*/
inline void valencePT(TransverseMomentum);
/**
* Set the valence energy.
*/
inline void valencePlus(Energy);
/**
* Set the accumulated negative light-cone momentum deficit.
*/
inline void minus(Energy);
/**
* Set the rapidity.
*/
inline void y(double);
/**
* Set the flavour of this parton.
*/
inline void flavour(long);
/**
* Set the parent partons.
*/
inline void parents(tPartonPair);
/**
* Set the connecting dipoles.
*/
inline void dipoles(tDipolePair);
/**
* Get the original emission rapidity.
*/
inline const double oY() const;
/**
* Set the original emission rapidity.
*/
inline void oY(double);
/**
* Indicate that this parton has interacted.
*/
void interact();
/**
* Returns true if the parton comes from a rightmoving state.
*/
inline bool rightMoving() const;
/**
* Set the direction of the original state.
*/
inline void rightMoving(bool);
/**
* Get and set the number of the parton.
*/
inline int number() {
return theNumber;
}
inline void number(int N) {
theNumber = N;
}
/**
* Checks if the parton is colour connected (in many steps if
* needed) to an interacting dipole.
*/
bool inInteractingLoop() const;
/**
* counts the number of on shell partons in this partons colour chain.
*/
int nOnShellInChain() const;
/**
* Checks if the parton is part of on of its states original dipoles.
*/
bool valenceParton() const;
/**
* Checks if the parton is in a colour chain containing a valenceparton.
*/
bool inValenceChain() const;
/**
* Returns true if the dipole the parton was emitted from is the result of a swing.
**/
bool swingedEmission() const;
/**
* Updates pT according to the colour neighbours, and changes y and
* plus/minus for right/left moving. minus/plus unchanged.
*/
void updateMomentum();
/**
* Updates y and p- from plus and pT.
*/
inline void updateYMinus() {
theY = log(thePT.pt()/thePlus);
theMinus = thePT.pt()*exp(theY);
}
/**
* Prints all the member variables to cout.
*/
void coutData();
/**
* Returns the recoil this parton would get from the argument parton.
*/
TransverseMomentum recoil(tPartonPtr) const;
//@}
public:
/**
* debugging
*/
mutable TransverseMomentum m1pT, m2pT;
mutable Energy m1plus, m2plus;
mutable InvEnergy minr1, minr2, maxr1, maxr2;
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 position in impact parameter space.
*/
Point thePosition;
/**
* The positive light-cone momentum.
*/
Energy thePlus;
/**
* The enumeration of this emission.
*/
double theOriginalY;
/**
* The transverse momentum.
*/
TransverseMomentum thePT;
/**
* The transverse momentum and energy a valenceparton got at creation.
*/
TransverseMomentum theValencePT;
Energy theValencePlus;
/**
* The accumulated negative light-cone momentum deficit.
*/
Energy theMinus;
/**
* The rapidity.
*/
double theY;
/**
* The original direction of the particle.
*/
bool isRightMoving;
/**
* The flavour of this parton.
*/
long theFlavour;
/**
* The parent partons.
*/
tPartonPair theParents;
/**
* The children
**/
set<tPartonPtr> theChildren;
/**
* The connecting dipoles.
*/
tDipolePair theDipoles;
/**
* Indicate if this parton has interacted.
*/
bool hasInteracted;
/**
* Indicate if this parton is ordered with respect to its colour neighbours.
*/
bool isOrdered;
/**
* 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;
/**
* Indicate if this parton is a valence parton.
*/
bool isValence;
/**
* A number that identifies the parton in a dipole state.
*/
int theNumber;
/**
* The mass of this parton.
*/
mutable Energy theMass;
protected:
/**
* Exception class for bad kinematics.
*/
struct PartonKinematicsException: public Exception {};
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
Parton & operator=(const Parton &);
};
}
template <typename T, typename Alloc>
std::vector<T,Alloc> &
expandToFit(std::vector<T,Alloc> & v,
typename std::vector<T,Alloc>::size_type indx) {
if ( indx >= v.size() ) v.resize(indx + 1);
return v;
}
template <typename T, typename Alloc>
T & forceAt(std::vector<T,Alloc> & v,
typename std::vector<T,Alloc>::size_type indx) {
return expandToFit(v, indx)[indx];
}
#include "Parton.icc"
#endif /* DIPSY_Parton_H */
diff --git a/DIPSY/PhotonDipoleState.cc b/DIPSY/PhotonDipoleState.cc
--- a/DIPSY/PhotonDipoleState.cc
+++ b/DIPSY/PhotonDipoleState.cc
@@ -1,84 +1,84 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the PhotonDipoleState class.
//
#include "PhotonDipoleState.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Utilities/Current.h"
#include "DipoleEventHandler.h"
#ifdef ThePEG_TEMPLATES_IN_CC_FILE
// #include "PhotonDipoleState.tcc"
#endif
using namespace DIPSY;
PhotonDipoleState::
PhotonDipoleState(const DipoleEventHandler & eh, Energy plus, Energy minus,
Ptr<PhotonWFInfo>::pointer wfi, double wgt)
: DipoleState(eh, wfi) {
PPtr inc = wfi->wf().particle()->produceParticle(lightCone(plus, minus));
inc->getInfo().push_back(wfi);
vector<PartonPtr> & partons = theIncoming[inc];
thePlus = plus;
theMinus = minus;
weight(wgt);
PartonPtr q = new_ptr(Parton());
partons.push_back(q);
PartonPtr qb = new_ptr(Parton());
partons.push_back(qb);
DipolePtr d = createDipole();
d->partons(make_pair(q, qb));
q->dipoles(make_pair(DipolePtr(), d));
qb->dipoles(make_pair(d, DipolePtr()));
generateColourIndex(d);
double phi = UseRandom::rnd()*2.0*Constants::pi;
Parton::Point point(wfi->r()*cos(phi)/2.0, wfi->r()*sin(phi)/2.0);
q->position(point);
qb->position(-point);
TransverseMomentum pt = q->recoil(qb);
q->pT(pt);
q->plus(wfi->z()*plus);
q->updateYMinus();
q->oY(q->y());
q->flavour(wfi->flav());
qb->pT(-pt);
qb->plus((1.0 - wfi->z())*plus);
qb->updateYMinus();
qb->oY(qb->y());
qb->flavour(-wfi->flav());
q->valencePT(q->pT());
qb->valencePT(qb->pT());
q->valencePlus(q->plus());
qb->valencePlus(qb->plus());
theInitialDipoles.push_back(d);
//trying to conserve 4-momentum
theMinusDeficit = - minus + q->minus() + qb->minus();
// cout << "new state with plus, minus: " << plus/GeV << ", " << minus/GeV << endl;
// cout << "minusDeficit: " << theMinusDeficit/GeV << endl;
}
PhotonDipoleState::~PhotonDipoleState() {}
// Static variable needed for the type description system in ThePEG.
#include "ThePEG/Utilities/DescribeClass.h"
DescribeNoPIOClass<PhotonDipoleState,DIPSY::DipoleState>
- describeDIPSYPhotonDipoleState("DIPSY::PhotonDipoleState", "libDIPSY.so");
+ describeDIPSYPhotonDipoleState("DIPSY::PhotonDipoleState", "libAriadne5.so libDIPSY.so");
void PhotonDipoleState::Init() {}
diff --git a/DIPSY/PhotonWFInfo.cc b/DIPSY/PhotonWFInfo.cc
--- a/DIPSY/PhotonWFInfo.cc
+++ b/DIPSY/PhotonWFInfo.cc
@@ -1,35 +1,35 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the PhotonWFInfo class.
//
#include "PhotonWFInfo.h"
#ifdef ThePEG_TEMPLATES_IN_CC_FILE
// #include "PhotonWFInfo.tcc"
#endif
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace DIPSY;
PhotonWFInfo::~PhotonWFInfo() {}
void PhotonWFInfo::persistentOutput(PersistentOStream & os) const {
os << theZ << thePol << theH << theHbar << theFlav;
}
void PhotonWFInfo::persistentInput(PersistentIStream & is, int) {
is >> theZ >> thePol >> theH >> theHbar >> theFlav;
}
// Static variable needed for the type description system in ThePEG.
#include "ThePEG/Utilities/DescribeClass.h"
DescribeClass<PhotonWFInfo,DIPSY::WFInfo>
- describeDIPSYPhotonWFInfo("DIPSY::PhotonWFInfo", "libDIPSY.so");
+ describeDIPSYPhotonWFInfo("DIPSY::PhotonWFInfo", "libAriadne5.so libDIPSY.so");
void PhotonWFInfo::Init() {}
diff --git a/DIPSY/SimpleProton.cc b/DIPSY/SimpleProton.cc
--- a/DIPSY/SimpleProton.cc
+++ b/DIPSY/SimpleProton.cc
@@ -1,318 +1,321 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the SimpleProton class.
//
#include "SimpleProton.h"
#include "SimpleProtonState.h"
#include "DipoleEventHandler.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/PDT/ParticleData.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/Utilities/Throw.h"
#include "ThePEG/Utilities/UtilityBase.h"
#include "ThePEG/Utilities/SimplePhaseSpace.h"
#include "ThePEG/Utilities/MaxCmp.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/PDT/StandardMatchers.h"
#include "ThePEG/Utilities/Current.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "gsl/gsl_sf_erf.h"
using namespace DIPSY;
SimpleProton::SimpleProton()
: theR(0.0*InvGeV), theR0(0.0*InvGeV), theRapidityWidth(0.0), theAngleWidth(0.0),
theConnected(0), theCollapseTolerance(0.1*GeV) {}
SimpleProton::~SimpleProton() {}
IBPtr SimpleProton::clone() const {
return new_ptr(*this);
}
IBPtr SimpleProton::fullclone() const {
return new_ptr(*this);
}
InvEnergy SimpleProton::R() const {
return theR > ZERO? theR: Current<DipoleEventHandler>()->rMax();
}
InvEnergy SimpleProton::r0() const {
return theR0 > ZERO? theR0: Current<DipoleEventHandler>()->baryonSize();
}
void SimpleProton::initialize(const DipoleEventHandler & eh) {
tcPDPtr gluon = generator()->getParticleData(ParticleID::g);
if ( remdec && !remdec->canHandle(particle(), gluon ) )
Throw<InitException>()
<< "The given remnant decayer could not handle the particle "
<< "in this wave function.";
}
Energy2 SimpleProton::m2() const {
return sqr(particle()->mass());
}
DipoleStatePtr SimpleProton::
generate(const DipoleEventHandler & eh, Energy plus) {
InvEnergy r = rndShiftGauss();
Energy minus = m2()/plus;
return new_ptr(SimpleProtonState(eh, plus, minus, theAngleWidth, theRapidityWidth,
connectOption(), new_ptr(WFInfo(this, r)), 1.0));
}
InvEnergy SimpleProton::rndShiftGauss() const {
InvEnergy2 s1 = R()*r0()*sqrt(Constants::pi);
InvEnergy2 s2 = sqr(R());
InvEnergy2 s3 = s1*gsl_sf_erf(r0()/R());
do {
InvEnergy2 rsum = UseRandom::rnd()*(s1 + s2 + s3);
if ( s1 > rsum )
return R()*UseRandom::rndGauss() + r0();
else if ( s1 + s2 > rsum )
return R()*sqrt(-log(UseRandom::rnd())) + r0();
InvEnergy r = r0() - R()*UseRandom::rndGauss();
if ( r > 0.0*InvGeV && r/r0() > UseRandom::rnd() ) return r;
} while ( true );
return 0.0*InvGeV;
}
void SimpleProton::setParticle(PDPtr p) {
if ( !BaryonMatcher::Check(abs(p->id())) )
throw InterfaceException()
<< "Cannot set " << p->name()
<< " as particle for a proton wave function. "
<< "Only baryons are allowed." << Exception::warning;
WaveFunction::setParticle(p);
}
void SimpleProton::fixValence(Step & step, tPPtr particle, const vector<PPtr> & val) const {
if ( connectOption() != 0 || !remdec ) return;
// If the hadron is not colour connected to the rest of the state,
// then try to collapse it into the original hadron.
if ( collapseToProton(step, particle, val) ) return;
// Otherwise first find the gluon to split into a q and qq pair and split it.
splitValence(step, particle, val);
}
bool SimpleProton::collapseToProton(Step & step, tPPtr p, const vector<PPtr> & val) const {
if ( val.size() != 3 ) return false;
if ( val[0]->colourLine() == val[1]->antiColourLine() ) {
if ( val[1]->colourLine() != val[2]->antiColourLine() ) return false;
if ( val[2]->colourLine() != val[0]->antiColourLine() ) return false;
} else {
if ( val[0]->colourLine() != val[2]->antiColourLine() ) return false;
if ( val[2]->colourLine() != val[1]->antiColourLine() ) return false;
if ( val[1]->colourLine() != val[0]->antiColourLine() ) return false;
}
// Get an instance of the hadron and check that its mass is not too different.
Lorentz5Momentum pv = Utilities::sumMomentum(val);
if ( abs(pv.mass() - p->mass()) > collapseTolerance() ) return false;
// get the total momentum of the collision and determine how to
// boost it to put the hadron on-shell.
Lorentz5Momentum ptot = step.collision()->incoming().first->momentum() +
step.collision()->incoming().second->momentum();
Lorentz5Momentum pr = ptot - pv; // This is the recoil system to be used for momentum shuffling
LorentzRotation Rshift;
try {
p->setMomentum(DipoleState::changeMass(pv, p->mass(), pr, &Rshift));
} catch ( ImpossibleKinematics e ) {
return false;
}
p->setVertex((val[0]->vertex() + val[1]->vertex() + val[2]->vertex())/3.0);
step.addDecayProduct(val.begin(), val.end(), p);
step.collision()->incoming().first->transform(Rshift);
step.collision()->incoming().second->transform(Rshift);
return true;
}
bool SimpleProton::splitValence(Step & step, tPPtr p, const vector<PPtr> & val) const {
// First get the total momentum of the collision.
LorentzMomentum ptot = step.collision()->incoming().first->momentum() +
step.collision()->incoming().second->momentum();
// Now we choose the valence gluon with the smallest transverse
// momentum. Primarily we only consider those valence gluons which
// can be split into massive quarks and di-quarks, if this is not
// possible also others are considered with quark masses put to zero
// and hoping for the best.
MinCmp<Energy2,tPPtr> sel, primsel;
- for ( int i = 0, N = val.size(); i < N; ++i )
+ LorentzPoint vnew;
+ for ( int i = 0, N = val.size(); i < N; ++i ) {
+ vnew += val[i]->vertex()/double(N);
if ( val[i]->id() == ParticleID::g ) {
sel(val[i]->momentum().perp2(), val[i]);
if ( ptot.m() - (ptot - val[i]->momentum()).m() > 2.0*p->mass() )
primsel(val[i]->momentum().perp2(), val[i]);
}
+ }
tPVector valence(1, sel.index());
if ( valence.empty() ) return false;
if ( primsel.index() ) valence[0] = primsel.index();
tPPtr coln = valence[0]->colourNeighbour(val.begin(), val.end());
tColinePtr coll = valence[0]->colourLine();
tColinePtr acol = valence[0]->antiColourLine();
if ( coln && (valence[0]->momentum() + coln->momentum()).m() < p->mass() ) {
valence.push_back(coln);
acol = coln->antiColourLine();
}
coln = valence[0]->antiColourNeighbour(val.begin(), val.end());
if ( coln && (valence[0]->momentum() + coln->momentum()).m() < p->mass() ) {
valence.push_back(coln);
coll = coln->colourLine();
}
if ( valence.size() == 3 && ( valence[1] == valence[2] || coll == acol ) ) {
valence = tPVector(1, valence[0]);
coll = valence[0]->colourLine();
acol = valence[0]->antiColourLine();
}
// Now find the momentum of the recoil system used to put the remnants on-shell.
Lorentz5Momentum pv = Utilities::sumMomentum(valence);
LorentzMomentum pr = ptot - pv;
Energy maxmass = sqrt(sqr(ptot.m() - pr.mt()) - pr.perp2());
const SimpleBaryonRemnantDecayer::BaryonContent & bi = remdec->getBaryonInfo(p->dataPtr());
while ( true ) {
// Select remnant flavours
pair<int,int> r = bi.flavsel.select(UseRandom::current());
PPtr qv = getParticleData(r.first*bi.sign)->produceParticle();
PPtr dqv = getParticleData(r.second*bi.sign)->produceParticle();
// Generate transverse momenum and energy splitting.
TransverseMomentum ptv = remdec->pTGenerator()->generate();
Energy2 mt02 = qv->momentum().mass2() + ptv.pt2();
Energy2 mt12 = dqv->momentum().mass2() + ptv.pt2();
// If still too large recoil mass we put quark masses to zero and hope for the best.
if ( maxmass < 2.0*p->mass() ) mt02 = mt12 = ptv.pt2();
double z = remdec->zGenerator().generate(dqv->dataPtr(), qv->dataPtr(), mt12);
Energy mv = sqrt(mt02/(1.0 - z) + mt12/z);
// Make shure the mass is small enough to be kinamatically allowd.
if ( mv >= maxmass ) continue;
// Calculate the momenta of the remnants and how much the rest
// frame of the collision has moved due to momentum reshuffling.
LorentzMomentum pqv = lightCone((1.0 - z)*mv, mt02/((1.0 - z)*mv), ptv);
LorentzMomentum pdqv = lightCone(z*mv, mt12/(z*mv), -ptv);
LorentzRotation Rshift;
LorentzRotation Rr = Utilities::transformFromCMS(DipoleState::changeMass(pv, mv, pr, &Rshift));
qv->setMomentum(Rr*pqv);
if ( qv->hasColour() ) coll->addColoured(qv);
else acol->addAntiColoured(qv);
dqv->setMomentum(Rr*pdqv);
if ( dqv->hasColour() ) coll->addColoured(dqv);
else acol->addAntiColoured(dqv);
- qv->setVertex((val[0]->vertex() + val[1]->vertex() + val[2]->vertex())/3.0);
- dqv->setVertex(qv->vertex());
+ qv->setVertex(vnew);
+ dqv->setVertex(vnew);
step.addDecayProduct(valence.begin(), valence.end(), qv);
step.addDecayProduct(valence.begin(), valence.end(), dqv);
step.collision()->incoming().first->transform(Rshift);
step.collision()->incoming().second->transform(Rshift);
return true;
}
return false;
}
void SimpleProton::persistentOutput(PersistentOStream & os) const {
os << ounit(theR, InvGeV) << ounit(theR0, InvGeV)
<< ounit(theRapidityWidth, 1.0) << ounit(theAngleWidth, 1.0) << theConnected
<< ounit(theCollapseTolerance, GeV) << remdec;
}
void SimpleProton::persistentInput(PersistentIStream & is, int) {
is >> iunit(theR, InvGeV) >> iunit(theR0, InvGeV)
>> iunit(theRapidityWidth, 1.0) >> iunit(theAngleWidth, 1.0) >> theConnected
>> iunit(theCollapseTolerance, GeV) >> remdec;
}
// Static variable needed for the type description system in ThePEG.
#include "ThePEG/Utilities/DescribeClass.h"
DescribeClass<SimpleProton,DIPSY::WaveFunction>
- describeDIPSYSimpleProton("DIPSY::SimpleProton", "libDIPSY.so");
+ describeDIPSYSimpleProton("DIPSY::SimpleProton", "libAriadne5.so libDIPSY.so");
void SimpleProton::Init() {
static ClassDocumentation<SimpleProton> documentation
("The SimpleProton class represents the unevolved proton wave function "
"described in terms of an equilatteral triangle of dipoles with a size "
"distributed as a Gaussian.");
static Parameter<SimpleProton,InvEnergy> interfaceR
("R",
"The width of the Gaussian distribution in units of inverse GeV. If zero, "
"the value of <interface>DipoleEventHandler::RMax</interface> of the "
"controlling event handler will be used.",
&SimpleProton::theR, InvGeV, 0.0*InvGeV, 0.0*InvGeV, 0.0*InvGeV,
true, false, Interface::lowerlim);
static Parameter<SimpleProton,InvEnergy> interfaceR0
("R0",
"The shift in the average of the Gaussian distribution in units of "
"inverse GeV. If zero, <interface>DipoleEventHandler::BaryonSize</interface> "
"is used instead.",
&SimpleProton::theR0, InvGeV, 0.0*InvGeV, 0.0*InvGeV, 0.0*InvGeV,
true, false, Interface::lowerlim);
static Parameter<SimpleProton, double> interfaceRapidityWidth
("RapidityWidth",
"The width of the gaussian smearing in rapidity of the individual partons "
"in the starting triangle.",
&SimpleProton::theRapidityWidth, 1.0, 0.2, 0.0, 0.0,
true, false, Interface::lowerlim);
static Parameter<SimpleProton, double> interfaceAngleWidth
("AngleWidth",
"The width in radians of the gaussian smearing of the shape of the triangle. ",
&SimpleProton::theAngleWidth, 1.0, 0.2, 0.0, 0.0,
true, false, Interface::lowerlim);
static Switch<SimpleProton,int> interfaceConnected
("Connected",
"If the three dipoles are connected or not.",
&SimpleProton::theConnected, 0, true, false);
static SwitchOption interfaceConnectedConnected
(interfaceConnected,
"Connected",
"Three gluons.",
0);
static SwitchOption interfaceDisconnected
(interfaceConnected,
"Disconnected",
"6 quarks, pairwise on top of each other.",
1);
static Parameter<SimpleProton,Energy> interfaceCollapseTolerance
("CollapseTolerance",
"The maximum mass difference between the valence system and the "
"hadron allowed for collapsing into the original hadron after "
"the evolution.",
&SimpleProton::theCollapseTolerance, GeV, 0.1*GeV, 0.0*GeV, 0*GeV,
true, false, Interface::lowerlim);
static Reference<SimpleProton,SimpleBaryonRemnantDecayer> interfaceRemnantDecayer
("RemnantDecayer",
"A RemnantDecayer object which is able to produce remnants for the particle ",
&SimpleProton::remdec, false, false, true, true, true);
}
diff --git a/DIPSY/SimpleProtonState.cc b/DIPSY/SimpleProtonState.cc
--- a/DIPSY/SimpleProtonState.cc
+++ b/DIPSY/SimpleProtonState.cc
@@ -1,204 +1,204 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the SimpleProtonState class.
//
#include "SimpleProtonState.h"
#include "ThePEG/Repository/UseRandom.h"
#include "SimpleProton.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/EventRecord/Particle.h"
#ifdef ThePEG_TEMPLATES_IN_CC_FILE
// #include "SimpleProtonState.tcc"
#endif
using namespace DIPSY;
SimpleProtonState::
SimpleProtonState(const DipoleEventHandler & eh, Energy plus, Energy minus,
double angleWidth, double rapWidth, int connected, WFInfoPtr wfi, double weight)
: DipoleState(eh, wfi) {
PPtr inc = wfi->wf().particle()->produceParticle(lightCone(plus, minus));
inc->getInfo().push_back(wfi);
vector<PartonPtr> & partons = theIncoming[inc];
thePlus = plus;
theMinus = minus;
PartonPtr q1 = new_ptr(Parton());
partons.push_back(q1);
PartonPtr q2 = new_ptr(Parton());
partons.push_back(q2);
PartonPtr q3 = new_ptr(Parton());
partons.push_back(q3);
DipolePtr d1 = createDipole();
DipolePtr d2 = createDipole();
DipolePtr d3 = createDipole();
d1->partons(make_pair(q1, q2));
d2->partons(make_pair(q2, q3));
d3->partons(make_pair(q3, q1));
d1->neighbors(make_pair(d3, d2));
d2->neighbors(make_pair(d1, d3));
d3->neighbors(make_pair(d2, d1));
generateColourIndex(d1);
generateColourIndex(d2);
generateColourIndex(d3);
double phi1 = UseRandom::rnd()*2.0*Constants::pi/3.0;
double phi2 = phi1 + 2.0*Constants::pi/3.0 + UseRandom::rndGauss(angleWidth,0.0);
// double phi3 = phi2 + 2.0*Constants::pi/3.0 + UseRandom::rndGauss(angleWidth,0.0);
InvEnergy r = wfi->r()/sqrt(3.0);
// gets p+ and y right. pT and p- adapts.
//generate distribution in rapidity
double R1(0.0),R2(0.0),R3(0.0);
while (R1 > 1.0 || R1 == 0.0)
R1 = exp(UseRandom::rndGauss(rapWidth,0.0))/3.0;
while (R2 > (1.0 - R1) || R2 == 0.0)
R2 = (1.0 - R1)*exp(UseRandom::rndGauss(rapWidth,0.0))/2.0;
R3 = 1.0 - R1 - R2;
q1->plus(plus*R1);
q2->plus(plus*R2);
q3->plus(plus*R3);
q1->position(Parton::Point(r*cos(phi1), r*sin(phi1)));
q2->position(Parton::Point(r*cos(phi2), r*sin(phi2)));
// q3->position(Parton::Point(r*cos(phi3), r*sin(phi3)));
q3->position(-q1->position() - q2->position());
q1->dipoles(make_pair(d3, d1));
q2->dipoles(make_pair(d1, d2));
q3->dipoles(make_pair(d2, d3));
q1->pT(q1->recoil(q2) + q1->recoil(q3));
q2->pT(q2->recoil(q1) + q2->recoil(q3));
q3->pT(q3->recoil(q1) + q3->recoil(q2));
double reScale = sqrt(minus/(sqr(q1->pT().pt())/q1->plus() +
sqr(q2->pT().pt())/q2->plus() + sqr(q3->pT().pt())/q3->plus()));
q1->pT(q1->pT()*reScale);
q2->pT(q2->pT()*reScale);
q3->pT(q3->pT()*reScale);
q1->y(log(q1->pT().pt()/q1->plus()));
q2->y(log(q2->pT().pt()/q2->plus()));
q3->y(log(q3->pT().pt()/q3->plus()));
q1->oY(q1->y());
q2->oY(q2->y());
q3->oY(q3->y());
q1->minus( q1->pT().pt()*exp( q1->y() ) );
q2->minus( q2->pT().pt()*exp( q2->y() ) );
q3->minus( q3->pT().pt()*exp( q3->y() ) );
q1->valence(true);
q2->valence(true);
q3->valence(true);
q1->valencePT(q1->pT());
q2->valencePT(q2->pT());
q3->valencePT(q3->pT());
q1->valencePlus(q1->plus());
q2->valencePlus(q2->plus());
q3->valencePlus(q3->plus());
theInitialDipoles.push_back(d1);
theInitialDipoles.push_back(d2);
theInitialDipoles.push_back(d3);
if ( connected == 1 ) {//disconnected
PartonPtr qbar1 = new_ptr(Parton());
partons.push_back(qbar1);
PartonPtr qbar2 = new_ptr(Parton());
partons.push_back(qbar2);
PartonPtr qbar3 = new_ptr(Parton());
partons.push_back(qbar3);
d1->partons(make_pair(q1, qbar2));
d2->partons(make_pair(q2, qbar3));
d3->partons(make_pair(q3, qbar1));
d1->neighbors(make_pair(tDipolePtr(), tDipolePtr()));
d2->neighbors(make_pair(tDipolePtr(), tDipolePtr()));
d3->neighbors(make_pair(tDipolePtr(), tDipolePtr()));
q1->plus(q1->plus()/2.0);
q2->plus(q2->plus()/2.0);
q3->plus(q3->plus()/2.0);
qbar1->plus(q1->plus());
qbar2->plus(q2->plus());
qbar3->plus(q3->plus());
Parton::Point pos1 = Parton::Point(q1->position().x() + UseRandom::rndGauss(0.0,0.0)/GeV,
q1->position().y() + UseRandom::rndGauss(0.0,0.0)/GeV);
Parton::Point pos2 = Parton::Point(q2->position().x() + UseRandom::rndGauss(0.0,0.0)/GeV,
q2->position().y() + UseRandom::rndGauss(0.0,0.0)/GeV);
Parton::Point pos3 = Parton::Point(q3->position().x() + UseRandom::rndGauss(0.0,0.0)/GeV,
q3->position().y() + UseRandom::rndGauss(0.0,0.0)/GeV);
qbar1->position(pos1);
qbar2->position(pos2);
qbar3->position(pos3);
qbar1->dipoles(make_pair(d3, tDipolePtr()));
qbar2->dipoles(make_pair(d1, tDipolePtr()));
qbar3->dipoles(make_pair(d2, tDipolePtr()));
q1->dipoles(make_pair(tDipolePtr(), d1));
q2->dipoles(make_pair(tDipolePtr(), d2));
q3->dipoles(make_pair(tDipolePtr(), d3));
q1->pT(q1->pT()/2.0);
q2->pT(q2->pT()/2.0);
q3->pT(q3->pT()/2.0);
qbar1->pT(q1->pT()/2.0);
qbar2->pT(q2->pT()/2.0);
qbar3->pT(q3->pT()/2.0);
q1->updateYMinus();
q2->updateYMinus();
q3->updateYMinus();
qbar1->updateYMinus();
qbar2->updateYMinus();
qbar3->updateYMinus();
qbar1->oY(qbar1->y());
qbar2->oY(qbar2->y());
qbar3->oY(qbar3->y());
qbar1->valence(true);
qbar2->valence(true);
qbar3->valence(true);
q1->valencePT(q1->pT());
q2->valencePT(q2->pT());
q3->valencePT(q3->pT());
qbar1->valencePT(qbar1->pT());
qbar2->valencePT(qbar2->pT());
qbar3->valencePT(qbar3->pT());
q1->valencePlus(q1->plus());
q2->valencePlus(q2->plus());
q3->valencePlus(q3->plus());
qbar1->valencePlus(qbar1->plus());
qbar2->valencePlus(qbar2->plus());
qbar3->valencePlus(qbar3->plus());
qbar1->flavour(ParticleID::dbar);
q1->flavour(ParticleID::d);
qbar2->flavour(ParticleID::ubar);
q2->flavour(ParticleID::u);
qbar3->flavour(ParticleID::ubar);
q3->flavour(ParticleID::u);
if ( wfi->wf().particle() ) {
if ( wfi->wf().particle()->id() == ParticleID::pplus )
q1->flavour(ParticleID::u);
if ( wfi->wf().particle()->id() == ParticleID::pbarminus )
qbar1->flavour(ParticleID::ubar);
}
}
}
SimpleProtonState::~SimpleProtonState() {}
// Static variable needed for the type description system in ThePEG.
#include "ThePEG/Utilities/DescribeClass.h"
DescribeNoPIOClass<SimpleProtonState,DIPSY::DipoleState>
- describeDIPSYSimpleProtonState("DIPSY::SimpleProtonState", "libDIPSY.so");
+ describeDIPSYSimpleProtonState("DIPSY::SimpleProtonState", "libAriadne5.so libDIPSY.so");
void SimpleProtonState::Init() {}
diff --git a/DIPSY/SmallDipoleAbsorber.cc b/DIPSY/SmallDipoleAbsorber.cc
--- a/DIPSY/SmallDipoleAbsorber.cc
+++ b/DIPSY/SmallDipoleAbsorber.cc
@@ -1,777 +1,777 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the SmallDipoleAbsorber class.
//
#include "SmallDipoleAbsorber.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Utilities/Current.h"
#include "DipoleEventHandler.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace DIPSY;
SmallDipoleAbsorber::SmallDipoleAbsorber() {}
SmallDipoleAbsorber::~SmallDipoleAbsorber() {}
IBPtr SmallDipoleAbsorber::clone() const {
return new_ptr(*this);
}
IBPtr SmallDipoleAbsorber::fullclone() const {
return new_ptr(*this);
}
void printInfo( DipolePtr d ) {
cout << "dipole " << d << " has size " << d->size()*GeV <<
". Has neighbours " << d->neighbors().first << " (" << d->neighbors().first->DGLAPsafe()
<< "), " << d->neighbors().second <<" ("<< d->neighbors().second->DGLAPsafe() <<
"). Has children " << d->children().first << ", " << d->children().second <<
". Is DGLAPsafe: " << d->DGLAPsafe() << endl;
}
void SmallDipoleAbsorber::
absorbParton(tPartonPtr p, DipoleState & state ) const {
DipolePtr d1 = p->dipoles().first;
DipolePtr d2 = p->dipoles().second;
if ( !d1 ) {
if ( !(d2->neighbors().second) )
cout << "absorbing qqbar pair!!!!!!!!!!!!!!!!!! :o (bad!)" << endl;
PartonPtr g = d2->partons().second;
d2->neighbors().second->firstNeighbor(d1);
g->dipoles(make_pair(d1, d2->neighbors().second));
d2->children().second = d2->neighbors().second;
g->plus(g->plus() + p->plus());
g->updateMomentum();
g->flavour(p->flavour());
if ( p->valence() ) {
g->valencePT(p->valencePT());
p->parents(make_pair(g,g));
}
state.save();
return;
}
if ( !d2 ) {
if ( !(d1->neighbors().first) )
cout << "absorbing qqbar pair!!!!!!!!!!!!!!!!!! :o (bad!)" << endl;
PartonPtr g = d1->partons().first;
d1->neighbors().first->secondNeighbor(d2);
g->dipoles(make_pair(d1->neighbors().first, d2));
d1->children().second = d1->neighbors().first;
g->plus(g->plus() + p->plus());
g->updateMomentum();
g->flavour(p->flavour());
if ( p->valence() ) {
g->valencePT(p->valencePT());
p->parents(make_pair(g,g));
}
state.save();
return;
}
PartonPtr p1 = d1->partons().first;
PartonPtr p2 = d2->partons().second;
if ( p1 == p2 ) {
state.sortDipoles();
if( !(state.forceSwing(p, 5.0, 0.0)) ) {
cout << "couldnt find swing" << endl;
return; //TODO: move to this class. think through.
}
d1 = p->dipoles().first;
d2 = p->dipoles().second;
p1 = d1->partons().first;
p2 = d2->partons().second;
}
//always save interacting dip, and otherwise the bigger DGLAP safe dip.
if ( ( (d1->DGLAPsafe() && ( !(d2->DGLAPsafe()) || d1->size() >= d2->size()) ) ||
( !(d2->DGLAPsafe()) && d1->size() >= d2->size()) ||
( d1->interacted() )) && !(d2->interacted()) ) {
d2->children().second = d1;
p2->dipoles(make_pair(d1,p2->dipoles().second));
d1->partons(make_pair(p1,p2));
d1->secondNeighbor(d2->neighbors().second);
if ( d1->neighbors().second ) d1->neighbors().second->firstNeighbor(d1);
}
else {
d1->children().second = d2;
p1->dipoles(make_pair(p1->dipoles().first, d2));
d2->partons(make_pair(p1,p2));
d2->firstNeighbor(d1->neighbors().first);
if ( d2->neighbors().first ) d2->neighbors().first->secondNeighbor(d2);
}
//Conserve pT and p+ based on dipole sizes. y and p- adapt.
Parton::Point r1 = p->position() - p1->position();
Parton::Point r2 = p->position() - p2->position();
double P1 = sqr(r2.pt())/( sqr(r1.pt()) + sqr(r2.pt()) );
//dont give p+ to a parton ahead in rapidity if possible.
if ( p1->y() < p->y() && p->y() < p2->y() ) {
P1 = 1.0;
}
else if ( p2->y() < p->y() && p->y() < p1->y() ) {
P1 = 0.0;
}
else if ( p->y() < p2->y() && p->y() < p1->y() && p1->y() > p2->y() ) {
P1 = 0.0;
}
else if ( p->y() < p2->y() && p->y() < p1->y() && p2->y() > p1->y() ) {
P1 = 1.0;
}
//with valence-status comes always also the p+ though. or?? >_>
if ( p->valence() ) {
if ( r1.pt() < r2.pt() || p2->valence() ) {
p1->valencePT(p->valencePT());
p->parents(make_pair(p1,p1));
P1 = 1.0;
}
else {
p2->valencePT(p->valencePT());
p->parents(make_pair(p2,p2));
P1 = 0.0;
}
}
double P2 = 1.0 - P1;
p1->plus( p1->plus() + P1*p->plus() );
p2->plus( p2->plus() + P2*p->plus() );
p1->updateMomentum();
p2->updateMomentum();
if ( d1->size()/(d1->size()+d2->size()) < UseRandom::rnd() )
d1->colour(d2->colour());
state.save();
}
void SmallDipoleAbsorber::setDGLAPsafe ( tDipolePtr dip ) const {
dip->DGLAPsafe( true );
InvEnergy firstLength = dip->size();
InvEnergy secondLength = dip->size();
if ( dip->interacted() ) {
firstLength = dip->interactionLengths().first;
secondLength = dip->interactionLengths().second;
}
if ( dip->neighbors().first && !(dip->neighbors().first->interacted()) &&
dip->neighbors().first->size() > firstLength )
setDGLAPsafe( dip->neighbors().first );
if ( dip->neighbors().second && !(dip->neighbors().second->interacted()) &&
dip->neighbors().second->size() > secondLength )
setDGLAPsafe( dip->neighbors().second );
}
template < typename Sort >
void SmallDipoleAbsorber::setOrdered ( tPartonPtr p, Sort sorted ) const {
p->ordered( true );
if ( p->dipoles().first && sorted( p, p->dipoles().first->partons().first ) )
setOrdered( p->dipoles().first->partons().first, sorted );
if ( p->dipoles().second && sorted(p, p->dipoles().second->partons().second) )
setOrdered( p->dipoles().second->partons().second, sorted );
}
void SmallDipoleAbsorber::DGLAPabsorb(tPartonPtr p, DipoleState & state ) const {
DipolePtr shortDip, longDip, shortNeighbor;
PartonPtr shortP, secondShortP;
InvEnergy firstLength = p->dipoles().first->size();
InvEnergy secondLength = p->dipoles().second->size();
if ( p->dipoles().first->interacted() )
firstLength = p->dipoles().first->interactionLengths().second;
if ( p->dipoles().second->interacted() )
secondLength = p->dipoles().second->interactionLengths().first;
if (firstLength > secondLength ) {
shortDip = p->dipoles().second;
longDip = p->dipoles().first;
shortP = shortDip->partons().second;
shortNeighbor = shortDip->neighbors().second;
secondShortP = shortNeighbor->partons().second;
}
else {
shortDip = p->dipoles().first;
longDip = p->dipoles().second;
shortP = shortDip->partons().first;
shortNeighbor = shortDip->neighbors().first;
secondShortP = shortNeighbor->partons().first;
}
if ( p->valence() && shortP->valence() ) {
setDGLAPsafe(shortDip);
return;
}
if ( shortNeighbor->interacted() ) {
if ( longDip->interacted() ) {
//move the larger of the interacting dips
if ( shortDip->neighbors().first->interactionLengths().second >
shortDip->neighbors().second->interactionLengths().first )
absorbParton( shortDip->partons().first, state );
else
absorbParton( shortDip->partons().second, state );
}
else
absorbParton(p, state);
return; //dont recur
}
if ( shortNeighbor->DGLAPsafe() ) {
if ( longDip->size() > shortNeighbor->size() )
absorbParton( p, state );
else
absorbParton( shortP, state );
return; //dont recur
}
absorbParton(shortP, state);
if ( p->dist2(*secondShortP) < p->dist2(*shortP) ) {
DGLAPabsorb(p, state);
}
}
bool rapSort(PartonPtr part1,PartonPtr part2) {
return (part1->y() >= part2->y());
}
bool minusSort(PartonPtr p1, PartonPtr p2) {
return ( p1->minus() >= p2->minus() );
}
bool plusSort(PartonPtr p1, PartonPtr p2) {
return ( p1->plus() <= p2->plus() );
}
bool SmallDipoleAbsorber::swing( tDipolePtr d1, tDipolePtr d2 ) const {
if ( DipoleAbsorber::swing(d1, d2) ) return true;
DipoleState & state = d1->dipoleState();
state.sortDipoles();
if( !(state.forceSwing(d1->partons().second, 5.0, 0.0)) ) return false;
return DipoleAbsorber::swing(d1->partons().first->dipoles().second,
d2->partons().second->dipoles().first);
}
// void SmallDipoleAbsorber::isolateNonParticipating( DipoleState & state ) const {
// for( int i = 0; i < int(state.initialDipoles().size()); i++ ) {
// DipolePtr d = state.initialDipoles()[i];
// if ( !(d->participating()) ) {
// if ( d->partons().first->dipoles().second != d->partons().second->dipoles().first )
// swing( d->partons().first->dipoles().second, d->partons().second->dipoles().first );
// d->partons().first->dipoles().second->participating( false );
// }
// }
// }
void SmallDipoleAbsorber::hiddenRecoil(DipoleState & state) const {
cout << "entering hiddenrecoil--------------------" << endl;
state.diagnosis(true);
list<PartonPtr> partons = state.getPartons();
list<PartonPtr> toBeAbsorbed;
cout << partons.size() << " number o partons." << endl;
//reset momenta
for ( list<PartonPtr>::iterator it = partons.begin();
it != partons.end(); it++ )
(*it)->pT(0.0*(*it)->pT());
for ( list<PartonPtr>::iterator it = partons.begin();
it != partons.end(); it++ ) {
tPartonPtr p = *it;
if ( p->valence() ) {
p->pT(p->pT() + p->valencePT());
if ( p->pT().pt() == ZERO )
cout << "zero momentum valence parton in hiddenrecoil" << endl;
if ( p->rightMoving() ) {
p->y( log(p->pT().pt()/p->plus()) );
p->minus( p->pT().pt()*exp(p->y()) );
}
else {
p->y( log(p->minus()/p->pT().pt()) );
p->plus( p->pT().pt()*exp(-p->y()) );
}
cout << "added valence momentum" << endl;
state.diagnosis(true);
continue;
}
tPartonPtr p1 = p;
tPartonPtr p2 = p;
//find first real ancestor on each side, and recoil with them
do { p1 = p1->parents().first; } while (p1->absorbed());
do { p2 = p2->parents().second; } while (p2->absorbed());
recoil( p, p1, state.ymax() );
recoil( p, p2, state.ymax() );
cout << "did normal recoil" << endl;
state.diagnosis(true);
if ( p->y() > state.ymax() && !(p->dipoles().first->interacted() &&
p->dipoles().second->interacted()) )
toBeAbsorbed.push_back(p);
}
//if any partons needed to be absorbed, absorb them and restart.
if ( toBeAbsorbed.size() != 0 ) {
bool absorbed = false;
for ( list<PartonPtr>::iterator it = toBeAbsorbed.begin();
it != toBeAbsorbed.end(); it++ ) {
cout << "absorbing parton" << endl;
state.diagnosis(true);
absorbParton(*it, state);
if ( (*it)->dipoles().first->children().second ||
(*it)->dipoles().second->children().second )
absorbed = true;
}
if ( absorbed ) {
cout << "recur" << endl;
hiddenRecoil(state);
}
}
}
void SmallDipoleAbsorber::
recoil(tPartonPtr p1, tPartonPtr p2, double ymax) const {
Parton::Point r = p1->position() - p2->position();
TransverseMomentum recoil = p1->pTScale()*r/sqr(r.pt());
p1->pT( p1->pT() + recoil );
p2->pT( p2->pT() - recoil );
if ( p1->rightMoving() ) {
p1->y( log(p1->pT().pt()/p1->plus()) );
p1->minus( p1->pT().pt()*exp(p1->y()) );
}
else {
p1->y( log(p1->minus()/p1->pT().pt()) );
p1->plus( p1->pT().pt()*exp(-p1->y()) );
}
if ( p2->rightMoving() ) {
p2->y( log(p2->pT().pt()/p2->plus()) );
p2->minus( p2->pT().pt()*exp(p2->y()) );
}
else {
p2->y( log(p2->minus()/p2->pT().pt()) );
p2->plus( p2->pT().pt()*exp(-p2->y()) );
}
//check if one of the partons is between two interacting dipoles,
//and got pushed over ymax. Should happen very rarely.
if ( ( p1->y() > ymax
&& (p1->dipoles().first->interacted() && p1->dipoles().second->interacted()) )
||
( p2->y() > ymax
&& (p2->dipoles().first->interacted() && p2->dipoles().second->interacted()) ) )
cout << "parton got pushed over ymax!!" << endl;
}
template <typename Sort>
void SmallDipoleAbsorber::absorbNonOrderedPartons( DipoleState & state, Sort ordered ) const {
list < PartonPtr > partons = state.getPartons();
list < PartonPtr > marked;
while ( true ) {
for ( list<PartonPtr>::iterator p = partons.begin();
p != partons.end(); p++ ) {
(*p)->ordered(false);
}
//mark the ones in a sorted chain from an interacting parton
for ( list<PartonPtr>::iterator p = partons.begin();
p != partons.end(); p++ ) {
if ( (**p).ordered() ) continue;
if ( ((*p)->dipoles().first && (*p)->dipoles().first->interacted()) ||
((*p)->dipoles().second && (*p)->dipoles().second->interacted()) ) {
setOrdered( (*p), ordered );
}
}
//manually set the marked partons safe.
for ( list<PartonPtr>::const_iterator p = marked.begin(); p != marked.end(); p++ ) {
setOrdered( *p, ordered );
}
//find the highest non-ordered parton absP with an ordered neighbour
PartonPtr absP;
for ( list<PartonPtr>::iterator p = partons.begin();
p != partons.end(); p++ ) {
if ( !((*p)->ordered()) &&
( ((*p)->dipoles().first &&
(*p)->dipoles().first->partons().first->ordered()) ||
((*p)->dipoles().second &&
(*p)->dipoles().second->partons().second->ordered()) ) )
if ( !absP || ordered( *p, absP) ) absP = *p;
}
//check that the unordered partons isnt a valence parton.
if ( absP && absP->valence() ) {
bool firstCanBeAbsorbed = false;
bool secondCanBeAbsorbed = false;
if ( absP->dipoles().first ) {
PartonPtr p1 = absP->dipoles().first->partons().first;
if ( !(p1->valence()) &&
!( (p1->dipoles().first && p1->dipoles().first->interacted()) ||
(p1->dipoles().second && p1->dipoles().second->interacted()) ) &&
p1->ordered() )
firstCanBeAbsorbed = true;
}
if ( absP->dipoles().second ) {
PartonPtr p2 = absP->dipoles().second->partons().second;
if ( !(p2->valence()) &&
!( (p2->dipoles().first && p2->dipoles().first->interacted()) ||
(p2->dipoles().second && p2->dipoles().second->interacted()) ) &&
p2->ordered() )
secondCanBeAbsorbed = true;
}
if ( firstCanBeAbsorbed && !secondCanBeAbsorbed ) {
absP = absP->dipoles().first->partons().first;
}
else if ( !firstCanBeAbsorbed && secondCanBeAbsorbed ) {
absP = absP->dipoles().second->partons().second;
}
else if ( firstCanBeAbsorbed && secondCanBeAbsorbed ) {
if ( ordered ( absP->dipoles().first->partons().first,
absP->dipoles().second->partons().second ) )
absP = absP->dipoles().first->partons().first;
else
absP = absP->dipoles().second->partons().second;
}
else if ( !firstCanBeAbsorbed && !secondCanBeAbsorbed ) {
marked.push_back(absP);
continue;
}
}
if ( absP ) {
absorbParton( absP, state);
partons.remove(absP);
} else { //if there is none, look for unordered loops
PartonPtr highestP;
for ( list<PartonPtr>::iterator p = partons.begin();
p != partons.end(); p++ ) {
if ( !((*p)->ordered()) )
if ( !highestP || ordered((*p), highestP) )
highestP = *p;
}
if ( highestP ) { //mark the highest parton in the loop as safe
marked.push_back(highestP);
}
else {//no unordered partons, we are done
break;
}
}
}
}
bool SmallDipoleAbsorber::checkDGLAPsafe ( InvEnergy r1, InvEnergy r2 ) const {
return sqr(r1)/Current<DipoleEventHandler>()->alphaS(r1) >
(sqr(r2)/Current<DipoleEventHandler>()->alphaS(r2))*UseRandom::rnd();
}
void SmallDipoleAbsorber::absorbSmallDipoles( DipoleState & state ) const {
set<DipolePtr> marked; //the manually marked safe dipoles.
//start by adding the interacting dipoles as safe.
list< DipolePtr > dipoles = state.getDipoles();
InvEnergy minScale = 0.0/GeV;
for ( list<DipolePtr>::const_iterator it = dipoles.begin();
it != dipoles.end(); it++ ) { DipolePtr dip = *it;
if ( dip->interacted() ) {
InvEnergy thisScale =
min( sqrt(dip->partons().first->dist2(*(dip->interacted()->partons().second))),
sqrt(dip->partons().second->dist2(*(dip->interacted()->partons().first))));
if ( minScale == 0.0/GeV || thisScale < minScale )
minScale = thisScale;
marked.insert(dip);
}
}
//find all loops, and decide if they should be absorbed or not.
// first mark all partons as nonordered, so it can be used for safe loops.
list<PartonPtr> partons = state.getPartons();
for ( list<PartonPtr>::const_iterator p = partons.begin(); p != partons.end(); p++ ) {
(*p)->ordered(false);
}
set< list<PartonPtr> > loops = state.loops();
for ( set< list<PartonPtr> >::iterator it = loops.begin();
it != loops.end(); it++ ) { list<PartonPtr> loop = *it;
bool keep = false;
DipolePtr maxDip;
for( list<PartonPtr>::const_iterator jt = loop.begin();
jt != loop.end(); jt++ ) { PartonPtr p = *jt;
if ( !(p->dipoles().first) ) continue;
if ( p->dipoles().first->interacted() ) keep = true;
if ( p->ordered() ) keep = true;
if ( !maxDip || p->dipoles().first->size() > maxDip->size() )
maxDip = p->dipoles().first;
}
if ( !keep && checkDGLAPsafe( maxDip->size(), minScale ) ) {
keep = true;
maxDip->partons().first->ordered(true);
}
if ( !keep ) { //otherwise absorb loop, update and restart loop iteration
absorbLoop( (*(loop.begin()))->dipoles().first, state );
loops = state.loops();
it = loops.begin();
}
}
//now mark the largest dips in non-interacting loop
for ( set< list<PartonPtr> >::iterator it = loops.begin();
it != loops.end(); it++ ) { list<PartonPtr> loop = *it;
bool interacting = false;
DipolePtr maxDip;
for( list<PartonPtr>::const_iterator jt = loop.begin();
jt != loop.end(); jt++ ) { PartonPtr p = *jt;
if ( !(p->dipoles().first) ) continue;
if ( !maxDip || p->dipoles().first->size() > maxDip->size() )
maxDip = p->dipoles().first;
if ( p->dipoles().first->interacted() )
interacting = true;
}
if ( !interacting )
marked.insert(maxDip);
}
//now look through all non-safe dipoles, and mark them as safe, or absorb them.
while( true ) {
//first update the lists and safe flags
for( list<DipolePtr>::iterator it = dipoles.begin();
it != dipoles.end(); it++ ) { DipolePtr dip = *it;
if ( dip->children().first || dip->children().second ) {
it = dipoles.erase(it);
it--;
continue;
}
else if ( dip->partons().first->valence() && dip->partons().second->valence() ) {
marked.insert(dip);
}
dip->DGLAPsafe(false);
}
for( set<DipolePtr>::iterator it = marked.begin();
it != marked.end(); it++ ) { DipolePtr dip = *it;
setDGLAPsafe(dip);
}
//then find a safe - nonsafe neighbouring pair.
DipolePtr safeDip;
DipolePtr nonSafeDip;
bool found = false;
InvEnergy smallest = 0.0/GeV;
for( list<DipolePtr>::iterator it = dipoles.begin();
it != dipoles.end(); it++ ) { DipolePtr dip = *it;
if ( !(dip->DGLAPsafe()) ) {
if ( dip->neighbors().first->DGLAPsafe() &&
(!found || dip->size() < smallest) ) {
nonSafeDip = dip;
safeDip = dip->neighbors().first;
found = true;
smallest = dip->size();
}
if ( dip->neighbors().second->DGLAPsafe() &&
(!found || dip->size() < smallest ||
(dip == nonSafeDip &&
dip->neighbors().second->size() < safeDip->size()) ) ) {
nonSafeDip = dip;
safeDip = dip->neighbors().second;
found = true;
smallest = dip->size();
}
}
}
//if a pair is found, decide if the nonsafe one should be absorbed or marked
if ( found ) {
InvEnergy safeScale = safeDip->size();
if ( safeDip->interacted() ) { //use the interacted dipsize for interacting dips
if ( nonSafeDip == safeDip->neighbors().first )
safeScale = safeDip->interactionLengths().first;
else
safeScale = safeDip->interactionLengths().second;
}
if ( checkDGLAPsafe( nonSafeDip->size(), safeScale ) ) {
marked.insert(nonSafeDip);
}
else {
if ( safeDip == nonSafeDip->neighbors().first )
DGLAPabsorb(safeDip->partons().second, state);
else if ( safeDip == nonSafeDip->neighbors().second )
DGLAPabsorb(safeDip->partons().first, state);
else cout << "safedip and nonsafe dip not neighbors! :(" << endl;
}
}
//if no nonsafe dips left, we're done.
else
break;
}
}
void SmallDipoleAbsorber::reabsorb( DipoleState & state) const {
realValence( state );
state.save();
absorbVirtualPartons( state );
// isolateNonParticipating( state );
absorbSmallDipoles( state );
absorbNonOrderedPartons( state, minusSort );
absorbNonOrderedPartons( state, plusSort );
hiddenRecoil( state );
}
void SmallDipoleAbsorber::realValence( DipoleState & state ) const {
vector<DipolePtr> dips = state.initialDipoles();
for ( int i = 0; i < int(dips.size());i++) {
dips[i]->partons().first->interact();
dips[i]->partons().second->interact();
}
}
DipolePtr SmallDipoleAbsorber::largestNonsafeDipole(list<DipolePtr> dipoles,
DipoleState & state ) const {
DipolePtr largestDip;
InvEnergy DGLAPScale = 0.0/GeV;
InvEnergy size = 0.0/GeV;
//find largest dipole that is not safe, and the smallest safe dipole.
// ***************** ATTENTION PHYSICS HERE!! WHAT SCALE TO PICK!?!?! ***********
for ( list<DipolePtr>::const_iterator dPtr = dipoles.begin();
dPtr != dipoles.end(); dPtr++ ) {
if ( !((*dPtr)->children().first || (*dPtr)->children().second )) {
if ( (*dPtr)->DGLAPsafe() ) {
if (DGLAPScale == 0.0/GeV || (*dPtr)->size() < DGLAPScale )
DGLAPScale = (*dPtr)->size();
}
else if( (*dPtr)->size() > size ) {
largestDip = *dPtr;
size = (*dPtr)->size();
}
}
}
//compare them, and mark as safe or absorb the entire loop.
//do not automatically save valence chains, as this creates many high pT events
if ( largestDip ) {
if ( (sqr(largestDip->size())/Current<DipoleEventHandler>()->alphaS(largestDip->size())) >
(sqr(DGLAPScale)/Current<DipoleEventHandler>()->alphaS(DGLAPScale))*
UseRandom::rnd() ) {
return largestDip;
}
else {
absorbLoop( largestDip, state );
return largestNonsafeDipole(dipoles, state);
}
}
else {
return largestDip;
}
}
void SmallDipoleAbsorber::absorbLoop( DipolePtr d, DipoleState & state ) const {
//make a list of the partons and dipoles in the loop.
list<PartonPtr> partons;
list<DipolePtr> dipoles;
tPartonPtr p = d->partons().second;
partons.push_back(p);
dipoles.push_back(d);
bool forward = true;
while ( p != d->partons().first && (forward || p->dipoles().first) ) {
if ( !(p->dipoles().second) ) {
cout << "found a quark in SmallDipoleAbsorber::absorbLoop!!!!!!!" << endl;
state.diagnosis(true);
p = d->partons().first;
partons.push_back(p);
forward = false;
continue;
}
if ( forward ) {
p = p->dipoles().second->partons().second;
dipoles.push_back(p->dipoles().first);
}
else {
p = p->dipoles().first->partons().first;
dipoles.push_back(p->dipoles().second);
}
partons.push_back(p);
}
//find and perform a probable swing. Don't bother with colours...
list<DipolePtr> otherDips = d->dipoleState().getDipoles();
for ( list<DipolePtr>::iterator i = dipoles.begin(); i != dipoles.end(); i++ ) {
for ( list<DipolePtr>::iterator j = otherDips.begin(); j != otherDips.end(); j++ ) {
if ( *i == *j )
j = otherDips.erase(j)--;
}
}
if ( dipoles.size() == 0 )
cout << "wtf, no dipoles in loop!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1" << endl;
if ( otherDips.size() == 0 ) {
cout << "wtf, no other dipoles in loop!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1" << endl;
state.diagnosis(true);
}
DipolePtr d1, d2;
double maxy = 0.0;
for ( list<DipolePtr>::iterator i = dipoles.begin(); i != dipoles.end(); i++ ) {
for ( list<DipolePtr>::iterator j = otherDips.begin(); j != otherDips.end(); j++ ) {
double R = log( UseRandom::rnd() );
InvEnergy2 a = (*i)->partons().first->dist2(*(*i)->partons().second);
InvEnergy2 b = (*j)->partons().first->dist2(*(*j)->partons().second);
InvEnergy2 c = (*i)->partons().second->dist2(*(*j)->partons().first);
InvEnergy2 d = (*i)->partons().first->dist2(*(*j)->partons().second);
a = sqr(Current<DipoleEventHandler>()->rMax())/
(Current<DipoleEventHandler>()->alphaS(sqrt(a)))*
sqr(exp(sqrt(a)/Current<DipoleEventHandler>()->rMax()) - 1.0);
b = sqr(Current<DipoleEventHandler>()->rMax())/
(Current<DipoleEventHandler>()->alphaS(sqrt(b)))*
sqr(exp(sqrt(b)/Current<DipoleEventHandler>()->rMax()) - 1.0);
c = sqr(Current<DipoleEventHandler>()->rMax())/
(Current<DipoleEventHandler>()->alphaS(sqrt(c)))*
sqr(exp(sqrt(c)/Current<DipoleEventHandler>()->rMax()) - 1.0);
d = sqr(Current<DipoleEventHandler>()->rMax())/
(Current<DipoleEventHandler>()->alphaS(sqrt(d)))*
sqr(exp(sqrt(d)/Current<DipoleEventHandler>()->rMax()) - 1.0);
double A = c*d/(a*b);
double y = R*A;
if ( y < maxy || maxy == 0.0 ) {
maxy = y;
d1 = *i;
d2 = *j;
}
}
}
swing(d1, d2);
//then sort the partons in rapidity, and absorb them.
//leave all valence partons, or if none, the lowest rapidity parton.
partons.sort(rapSort);
bool valence;
for ( list<PartonPtr>::const_iterator it = partons.begin() ;
(!valence && it != partons.end()--) || (valence && it == partons.end()); it++ ) {
if ( (*it)->valence() )
valence = true;
else
absorbParton((*it), state);
}
}
// If needed, insert default implementations of virtual function defined
// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs).
void SmallDipoleAbsorber::persistentOutput(PersistentOStream & os) const {
// *** ATTENTION *** os << ; // Add all member variable which should be written persistently here.
}
void SmallDipoleAbsorber::persistentInput(PersistentIStream & is, int) {
// *** ATTENTION *** is >> ; // Add all member variable which should be read persistently here.
}
// Static variable needed for the type description system in ThePEG.
#include "ThePEG/Utilities/DescribeClass.h"
DescribeClass<SmallDipoleAbsorber,DIPSY::DipoleAbsorber>
- describeDIPSYSmallDipoleAbsorber("DIPSY::SmallDipoleAbsorber", "libDIPSY.so");
+ describeDIPSYSmallDipoleAbsorber("DIPSY::SmallDipoleAbsorber", "libAriadne5.so libDIPSY.so");
void SmallDipoleAbsorber::Init() {
static ClassDocumentation<SmallDipoleAbsorber> documentation
("The SmallDipoleAbsorber class implements a model describing how "
"non-interacted dipoles will be reabsorbed. The model is based on "
"the removal of small dipoles.");
}
diff --git a/DIPSY/Swinger.cc b/DIPSY/Swinger.cc
--- a/DIPSY/Swinger.cc
+++ b/DIPSY/Swinger.cc
@@ -1,424 +1,424 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the Swinger class.
//
#include "Swinger.h"
#include "Dipole.h"
#include "DipoleState.h"
#include "DipoleEventHandler.h"
#include "ThePEG/Utilities/Current.h"
#include "ThePEG/Utilities/Throw.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Interface/Parameter.h"
#include "CPUTimer.h"
#ifdef ThePEG_TEMPLATES_IN_CC_FILE
// #include "Swinger.tcc"
#endif
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace DIPSY;
Swinger::~Swinger() {}
void Swinger::testGenerate(set<DipolePtr> & dips,double miny, double maxy) {
cout << "Testing Swinger....." << endl;
set<DipolePtr>::iterator it;
DipoleState testState = DipoleState();
for(it = dips.begin();it!=dips.end();it++) {
testState.addDipole(*(*it));
(*it)->dipoleState(& testState);
}
testState.sortDipoles();
thestMode = true;
ofstream youtput("SwingerTest.dat");
int ysteps = 100;
double ystepsize = 0.1;
vector<int> ybin(ysteps,0);
double y;
it=dips.begin();
for(int i=0;i<1000000;i++) {
(*it)->generatedY(maxy);
generate(*(*it),miny, maxy,true);
if((*it)->swingDipole()) {
y = (*it)->generatedY();
if(y-miny<ysteps*ystepsize)
ybin[int((y-miny)/ystepsize)]++;
}
(*it)->reset();
}
for(int i=0;i<ysteps;i++) {
youtput << (i+0.5)*ystepsize << '\t' << ybin[i] << endl;
}
youtput.close();
thestMode = false;
cout << "Done testing Swinger."
<< endl;
}
bool Swinger::forceGenerate(Dipole & dipole, double ymax) const {
const vector<tDipolePtr> & candidates =
dipole.dipoleState().swingCandidates(dipole.colour());
for (vector<tDipolePtr>::size_type i = 0; i < candidates.size(); i++ ) {
if ( candidates[i] == & dipole ) continue;
if ( candidates[i]->neighbors().first == & dipole ||
candidates[i]->neighbors().second == & dipole ) continue;
InvEnergy2 a = dipole.partons().first->dist2(*dipole.partons().second);
InvEnergy2 b = candidates[i]->partons().first->dist2(*(candidates[i]->partons().second));
InvEnergy2 c = dipole.partons().second->dist2(*candidates[i]->partons().first);
InvEnergy2 d = dipole.partons().first->dist2(*candidates[i]->partons().second);
a = sqr(Current<DipoleEventHandler>()->rMax())*
sqr(exp(sqrt(a)/Current<DipoleEventHandler>()->rMax()) - 1.0);
b = sqr(Current<DipoleEventHandler>()->rMax())*
sqr(exp(sqrt(b)/Current<DipoleEventHandler>()->rMax()) - 1.0);
c = sqr(Current<DipoleEventHandler>()->rMax())*
sqr(exp(sqrt(c)/Current<DipoleEventHandler>()->rMax()) - 1.0);
d = sqr(Current<DipoleEventHandler>()->rMax())*
sqr(exp(sqrt(d)/Current<DipoleEventHandler>()->rMax()) - 1.0);
double yi = -log( UseRandom::rnd() )*c*d/(a*b);
if ( yi < dipole.generatedY() || !(dipole.swingDipole()) ) {
if( yi < ymax || ymax == 0.0 ) { //Don't do ridiculously improbable swings.
dipole.swingDipole(candidates[i]);
dipole.generatedY(yi);
}
}
}
if( (dipole.swingDipole()) ) return true;
else return false;
}
void Swinger::generateFS(Dipole & dipole, double miny, double maxy) const {
//old implementation
bool force = !dipole.hasGen();
const vector<tDipolePtr> & candidates =
dipole.dipoleState().swingCandidates(dipole.colour());
vector<tDipolePtr>::size_type i = 0;
while ( i < candidates.size() && candidates[i++] != & dipole );
if ( i == candidates.size() && candidates[i - 1] != & dipole )
Throw<SwingConsistencyException>()
<< "FSswinger not found among candidates" << Exception::abortnow;
for (; i < candidates.size(); ++i ) {
if(candidates[i]->children().first)
cout << "OH NOES, parents among the swing candidates!!!! O_o" << endl;
if ( dipole.neighbors().first == candidates[i] ||
dipole.neighbors().second == candidates[i] )
continue;
if ( !force && candidates[i]->hasGen() ) continue;
// Generate a y
double R = -log( UseRandom::rnd() );
double amp = swingAmpFS(dipole.partons(),
candidates[i]->partons(), miny/GeV2);
// double amp = swingAmpFS(dipole, *candidates[i], miny/GeV2);
double yi = Constants::MaxRapidity;
if ( miny*amp + R < Constants::MaxRapidity*amp ) yi = miny + R/amp;
if ( yi < dipole.generatedY() || !dipole.hasGen() ) {
dipole.swingDipole(candidates[i]);
dipole.generatedY(yi);
dipole.recoilSwing(false);
}
}
}
InvEnergy2 Swinger::
swingDistanceFS(const Parton & p1, const Parton & p2, InvEnergy2 time) const {
// static CPUClock cpuclock("DIPSY::Swinger::swingDinstanceFS");
// CPUTimer timer(cpuclock);
static DebugItem notime("DIPSY::NoSwingTime", 60);
if ( notime ) time = ZERO;
Energy2 E2 = p1.plus()*p2.minus() + p1.minus()*p2.plus();
Parton::Point x1 = p1.position() - p2.position() + time*p1.pT();
Parton::Point x2 = p1.position() - p2.position() - time*p2.pT();
InvEnergy2 xxScalar = x1.x()*x2.x() + x1.y()*x2.y();
Energy2 ppScalar = p1.pT().x()*p2.pT().x() + p1.pT().y()*p2.pT().y();
InvEnergy2 a = sqr(time)*E2 + xxScalar - sqr(time)*ppScalar;
if ( a <= ZERO ) return ZERO;
double asa = Current<DipoleEventHandler>()->alphaS(sqrt(a));
InvEnergy rmax = Current<DipoleEventHandler>()->rMax();
return sqr(rmax)/asa*sqr(exp(sqrt(a)/rmax) - 1.0);
}
double Swinger::
swingAmpFS(InvEnergy2 a, InvEnergy2 b, InvEnergy2 c, InvEnergy2 d) const {
static double eps = 0.0000000000001;
if ( a <= ZERO || b <= ZERO || c <= ZERO || d <= ZERO ) return eps;
if ( sqrt(a*b) < sqrt(c)*sqrt(d)*sqrt(theLambda*eps) ) return eps;
return a*b/(c*d)*theLambda;
}
double Swinger::swingAmpFS(const pair<tPartonPtr, tPartonPtr> firstDip,
const pair<tPartonPtr, tPartonPtr> secondDip,
InvEnergy2 time) const {
//parton start in their original transverse position and z = 0, then move at
//lightspeed in a direction determined by the momentum.
static double eps = 0.0000000000001;
tPartonPtr p11 = firstDip.first;
tPartonPtr p12 = firstDip.second;
tPartonPtr p21 = secondDip.first;
tPartonPtr p22 = secondDip.second;
//these squared distances a,b,c,d between partons goes as (x1+t*pt1) - (x2+t*pt2) for small t,
//and as invariant mass times t for large t
Energy2 E2 = p11->plus()*p12->minus() + p11->minus()*p12->plus();
Parton::Point x1 = p11->position() - p12->position() + time*p11->pT();
Parton::Point x2 = p11->position() - p12->position() - time*p12->pT();
InvEnergy2 xxScalar = x1.x()*x2.x() + x1.y()*x2.y();
Energy2 ppScalar = p11->pT().x()*p12->pT().x() + p11->pT().y()*p12->pT().y();
InvEnergy2 a = sqr(time)*E2 + xxScalar - sqr(time)*ppScalar;
E2 = p21->plus()*p22->minus() + p21->minus()*p22->plus();
x1 = p21->position() - p22->position() + time*p21->pT();
x2 = p21->position() - p22->position() - time*p22->pT();
xxScalar = x1.x()*x2.x() + x1.y()*x2.y();
ppScalar = p21->pT().x()*p22->pT().x() + p21->pT().y()*p22->pT().y();
InvEnergy2 b = sqr(time)*E2 + xxScalar - sqr(time)*ppScalar;
E2 = p21->plus()*p12->minus() + p21->minus()*p12->plus();
x1 = p21->position() - p12->position() + time*p21->pT();
x2 = p21->position() - p12->position() - time*p12->pT();
xxScalar = x1.x()*x2.x() + x1.y()*x2.y();
ppScalar = p21->pT().x()*p12->pT().x() + p21->pT().y()*p12->pT().y();
InvEnergy2 c = sqr(time)*E2 + xxScalar - sqr(time)*ppScalar;
E2 = p11->plus()*p22->minus() + p11->minus()*p22->plus();
x1 = p11->position() - p22->position() + time*p11->pT();
x2 = p11->position() - p22->position() - time*p22->pT();
xxScalar = x1.x()*x2.x() + x1.y()*x2.y();
ppScalar = p11->pT().x()*p22->pT().x() + p11->pT().y()*p22->pT().y();
InvEnergy2 d = sqr(time)*E2 + xxScalar - sqr(time)*ppScalar;
if ( a <= ZERO || b <= ZERO || c <= ZERO || d <= ZERO ) return eps;
//normal confinement correction
InvEnergy rmax = Current<DipoleEventHandler>()->rMax();
double asa = Current<DipoleEventHandler>()->alphaS(sqrt(a));
double asb = Current<DipoleEventHandler>()->alphaS(sqrt(b));
double asc = Current<DipoleEventHandler>()->alphaS(sqrt(c));
double asd = Current<DipoleEventHandler>()->alphaS(sqrt(d));
a = sqr(rmax)/asa*sqr(exp(sqrt(a)/rmax) - 1.0);
b = sqr(rmax)/asb*sqr(exp(sqrt(b)/rmax) - 1.0);
c = sqr(rmax)/asc*sqr(exp(sqrt(c)/rmax) - 1.0);
d = sqr(rmax)/asd*sqr(exp(sqrt(d)/rmax) - 1.0);
//normal amplitude
if ( sqrt(a*b) < sqrt(c)*sqrt(d)*sqrt(theLambda*eps) ) return eps;
return a*b/(c*d)*theLambda;
}
void Swinger::generate(Dipole & dipole, double miny, double maxy, bool force) const {
double yi = max(max(dipole.partons().first->y(),
dipole.partons().second->y()), miny);
if ( dipole.partons().second == dipole.partons().first )
Throw<ColourIndexException>()
<< "Found inconsistent colour indices in DIPSY. Event discarded."
<< Exception::eventerror;
if( dipole.children().first)
Throw<SwingConsistencyException>()
<< "OH NOES, parents among the swing candidates!!!! O_o"
<< Exception::abortnow;
const vector<tDipolePtr> & candidates =
dipole.dipoleState().swingCandidates(dipole.colour(), !force);
vector<tDipolePtr>::const_iterator it = candidates.begin();
if ( force ) while ( it != candidates.end() && *it++ != &dipole );
for (; it != candidates.end(); ++it ) {
if ( !force && (**it).hasGen() ) continue;
double yn = yi - log(UseRandom::rnd())/swingAmp(dipole, **it);
if ( yn < dipole.generatedY() ) {
dipole.swingDipole(*it);
dipole.generatedY(yn);
dipole.recoilSwing(false);
}
}
}
double Swinger::swingAmp(const Dipole & firstDip,
const Dipole & secondDip) const {
InvEnergy rmax = Current<DipoleEventHandler>()->rMax();
InvEnergy2 a = firstDip.swingCache;
if ( a < ZERO ) {
a = firstDip.partons().first->dist2(*firstDip.partons().second);
a = sqr(rmax)/(Current<DipoleEventHandler>()->alphaS(sqrt(a)))*
sqr(exp(sqrt(a)/rmax) - 1.0);
firstDip.swingCache = a;
}
InvEnergy2 b = secondDip.swingCache;
if ( b < ZERO ) {
b = secondDip.partons().first->dist2(*(secondDip.partons().second));
b = sqr(rmax)/(Current<DipoleEventHandler>()->alphaS(sqrt(b)))*
sqr(exp(sqrt(b)/rmax) - 1.0);
secondDip.swingCache = b;
}
InvEnergy2 c = firstDip.partons().second->dist2(*secondDip.partons().first);
c = sqr(rmax)/(Current<DipoleEventHandler>()->alphaS(sqrt(c)))*
sqr(exp(sqrt(c)/rmax) - 1.0);
InvEnergy2 d = firstDip.partons().first->dist2(*secondDip.partons().second);
d = sqr(rmax)/(Current<DipoleEventHandler>()->alphaS(sqrt(d)))*
sqr(exp(sqrt(d)/rmax) - 1.0);
return a*b/(c*d)*theLambda;
}
double Swinger::swingAmp(const pair<tPartonPtr, tPartonPtr> firstDip,
const pair<tPartonPtr, tPartonPtr> secondDip) const {
InvEnergy rmax = Current<DipoleEventHandler>()->rMax();
InvEnergy2 a = firstDip.first->dist2(*firstDip.second);
InvEnergy2 b = secondDip.first->dist2(*(secondDip.second));
InvEnergy2 c = firstDip.second->dist2(*secondDip.first);
InvEnergy2 d = firstDip.first->dist2(*secondDip.second);
a = sqr(rmax)/
(Current<DipoleEventHandler>()->alphaS(sqrt(a)))*
sqr(exp(sqrt(a)/rmax) - 1.0);
b = sqr(rmax)/
(Current<DipoleEventHandler>()->alphaS(sqrt(b)))*
sqr(exp(sqrt(b)/rmax) - 1.0);
c = sqr(rmax)/
(Current<DipoleEventHandler>()->alphaS(sqrt(c)))*
sqr(exp(sqrt(c)/rmax) - 1.0);
d = sqr(rmax)/
(Current<DipoleEventHandler>()->alphaS(sqrt(d)))*
sqr(exp(sqrt(d)/rmax) - 1.0);
return a*b/(c*d)*theLambda;
}
bool Swinger::checkMaxY(DipolePtr d1, DipolePtr d2, double maxy) const {
tPartonPtr p1 = d1->partons().first;
tPartonPtr p2 = d1->partons().second;
tPartonPtr p3 = d2->partons().first;
tPartonPtr p4 = d2->partons().second;
TransverseMomentum rec12 = (p1->position() - p2->position())/
(p1->position() - p2->position()).pt2();
TransverseMomentum rec34 = (p3->position() - p4->position())/
(p3->position() - p4->position()).pt2();
TransverseMomentum rec14 = (p1->position() - p4->position())/
(p1->position() - p4->position()).pt2();
TransverseMomentum rec32 = (p3->position() - p2->position())/
(p3->position() - p2->position()).pt2();
if ( log( (p1->pT() - rec12 + rec14).pt()/p1->plus()) > maxy )
return false;
if ( log( (p2->pT() + rec12 - rec32).pt()/p2->plus()) > maxy )
return false;
if ( log( (p3->pT() - rec34 + rec32).pt()/p3->plus()) > maxy )
return false;
if ( log( (p4->pT() + rec34 - rec14).pt()/p4->plus()) > maxy )
return false;
return true;
}
void Swinger::recombineFS(Dipole & d1) const {
Dipole & d2 = *d1.swingDipole();
pair<tPartonPtr, tPartonPtr> d1p = d1.partons();
pair<tPartonPtr, tPartonPtr> d2p = d2.partons();
pair<tDipolePtr, tDipolePtr> d1n = d1.neighbors();
pair<tDipolePtr, tDipolePtr> d2n = d2.neighbors();
d1.partons(make_pair(d1p.first, d2p.second));
d1.neighbors(make_pair(d1n.first, d2n.second));
if ( d1n.first ) d1n.first->secondNeighbor(&d1);
if ( d2n.second ) d2n.second->firstNeighbor(&d1);
d2.partons(make_pair(d2p.first, d1p.second));
d2.neighbors(make_pair(d2n.first, d1n.second));
if ( d2n.first ) d2n.first->secondNeighbor(&d2);
if ( d1n.second ) d1n.second->firstNeighbor(&d2);
d1.partons().first->dipoles(make_pair(d1.neighbors().first, &d1));
d1.partons().second->dipoles(make_pair(&d1, d1.neighbors().second));
d2.partons().first->dipoles(make_pair(d2.neighbors().first, &d2));
d2.partons().second->dipoles(make_pair(&d2, d2.neighbors().second));
d1.reset();
d2.reset();
d1.touch();
d2.touch();
}
void Swinger::recombine(Dipole & d1) const {
DipoleState & state = d1.dipoleState();
Dipole & d2 = *d1.swingDipole();
if(d2.children().second) {
Throw<SwingConsistencyException>()
<< "swinging with someone thats emitted already (second child). "
<< "(partons at " << d1.partons().first->y() << ", "
<< d1.partons().second->y() << "; " << d2.partons().first->y()
<< ", " << d2.partons().second->y() << ")" << Exception::eventerror;
state.diagnosis(true);
}
else if(d2.children().first) {
Throw<SwingConsistencyException>()
<< "swinging with someone thats emitted already (first child). "
<< "(partons at " << d1.partons().first->y() << ", "
<< d1.partons().second->y() << "; " << d2.partons().first->y()
<< ", " << d2.partons().second->y() << ")" << Exception::eventerror;
state.diagnosis(true);
}
DipolePtr d11 = d1.children().first = state.createDipole();
DipolePtr d22 = d2.children().first = state.createDipole();
d11->partons(make_pair(d1.partons().first, d2.partons().second));
d11->neighbors(make_pair(d1.neighbors().first, d2.neighbors().second));
if ( d1.neighbors().first ) d1.neighbors().first->secondNeighbor(d11);
if ( d2.neighbors().second ) d2.neighbors().second->firstNeighbor(d11);
d22->partons(make_pair(d2.partons().first, d1.partons().second));
d22->neighbors(make_pair(d2.neighbors().first, d1.neighbors().second));
if ( d2.neighbors().first ) d2.neighbors().first->secondNeighbor(d22);
if ( d1.neighbors().second ) d1.neighbors().second->firstNeighbor(d22);
d11->colour(d1.colour());
d22->colour(d2.colour());
d11->partons().first->dipoles(make_pair(d11->neighbors().first,d11));
d11->partons().second->dipoles(make_pair(d11,d11->neighbors().second));
d22->partons().first->dipoles(make_pair(d22->neighbors().first,d22));
d22->partons().second->dipoles(make_pair(d22,d22->neighbors().second));
if (d1.DGLAPsafe() || d2.DGLAPsafe() ) {
d11->DGLAPsafe(true);
d22->DGLAPsafe(true);
}
if ( d1.interacted() ) d11->interact(*d1.interacted());
if ( d2.interacted() ) d22->interact(*d2.interacted());
d1.reset();
d2.reset(); //are these really needed?
}
void Swinger::persistentOutput(PersistentOStream & os) const {
os << ounit(theLambda, 1.0);
}
void Swinger::persistentInput(PersistentIStream & is, int) {
is >> iunit(theLambda, 1.0);
}
// Static variable needed for the type description system in ThePEG.
#include "ThePEG/Utilities/DescribeClass.h"
DescribeClass<Swinger,HandlerBase>
- describeDIPSYSwinger("DIPSY::Swinger", "libDIPSY.so");
+ describeDIPSYSwinger("DIPSY::Swinger", "libAriadne5.so libDIPSY.so");
void Swinger::Init() {
static ClassDocumentation<Swinger> documentation
("There is no documentation for the Swinger class");
static Parameter<Swinger,double> interfaceLambda
("Lambda",
"The frequency of the swings.",
&Swinger::theLambda, 1.0, 1.0, 0.0, 0.0,
true, false, Interface::lowerlim);
}
diff --git a/DIPSY/TotalXSecAnalysis.cc b/DIPSY/TotalXSecAnalysis.cc
--- a/DIPSY/TotalXSecAnalysis.cc
+++ b/DIPSY/TotalXSecAnalysis.cc
@@ -1,76 +1,76 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the TotalXSecAnalysis class.
//
#include "TotalXSecAnalysis.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "DipoleXSec.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace DIPSY;
TotalXSecAnalysis::TotalXSecAnalysis(): sum(0.0*picobarn), sum2(0.0*sqr(picobarn)) {}
TotalXSecAnalysis::~TotalXSecAnalysis() {}
void TotalXSecAnalysis::initialize() {
sum = 0.0*picobarn;
sum2 = sqr(sum);
}
void TotalXSecAnalysis::
analyze(const DipoleState & dl, const DipoleState & dr,
const ImpactParameters & b, const DipoleXSec & xsec,
double fsum, CrossSection weight) {
sum += 2.0*xsec.unitarize(fsum)*weight;
sum2 += sqr(2.0*xsec.unitarize(fsum)*weight);
}
void TotalXSecAnalysis::finalize(long neve) {
if ( neve <= 0 ) return;
sum /= neve;
sum2 /= neve;
CrossSection err = sqrt((sum2 - sqr(sum))/neve);
generator()->log().setf(ios::left, ios::adjustfield);
generator()->log() << setw(50) << name() + ": Total cross section: "
<< ouniterr(sum, err, nanobarn) << " nb." << endl;
}
IBPtr TotalXSecAnalysis::clone() const {
return new_ptr(*this);
}
IBPtr TotalXSecAnalysis::fullclone() const {
return new_ptr(*this);
}
void TotalXSecAnalysis::persistentOutput(PersistentOStream & os) const {
os << ounit(sum, picobarn) << ounit(sum2, sqr(picobarn));
}
void TotalXSecAnalysis::persistentInput(PersistentIStream & is, int) {
is >> iunit(sum, picobarn) >> iunit(sum2, sqr(picobarn));
}
// Static variable needed for the type description system in ThePEG.
#include "ThePEG/Utilities/DescribeClass.h"
DescribeClass<TotalXSecAnalysis,DIPSY::DipoleAnalysisHandler>
- describeDIPSYTotalXSecAnalysis("DIPSY::TotalXSecAnalysis", "libDIPSY.so");
+ describeDIPSYTotalXSecAnalysis("DIPSY::TotalXSecAnalysis", "libAriadne5.so libDIPSY.so");
void TotalXSecAnalysis::Init() {
static ClassDocumentation<TotalXSecAnalysis> documentation
("TotalXSecAnalysis class calculates the total cross section in the "
"presampling phase of the DipoleEventHandler.");
}
diff --git a/DIPSY/Tune31.in b/DIPSY/Tune31.in
--- a/DIPSY/Tune31.in
+++ b/DIPSY/Tune31.in
@@ -1,94 +1,109 @@
pushd /DIPSY
set stdProton:R 0.1
set stdProton:R0 2.9
set stdProton:RapidityWidth 0.1
set stdProton:AngleWidth 0.1
set stdProton:Connected Connected
+set Proton:R 0.1
+set Proton:R0 2.9
+set Proton:RapidityWidth 0.1
+set Proton:AngleWidth 0.1
+set Proton:Connected Connected
#set stdProton:Connected Disconnected
set stdAntiProton:R 0.1
set stdAntiProton:R0 2.9
set stdAntiProton:RapidityWidth 0.1
set stdAntiProton:AngleWidth 0.1
set stdAntiProton:Connected Connected
+set AntiProton:R 0.1
+set AntiProton:R0 2.9
+set AntiProton:RapidityWidth 0.1
+set AntiProton:AngleWidth 0.1
+set AntiProton:Connected Connected
#set stdAntiProton:Connected Disconnected
+set Neutron:R 0.1
+set Neutron:R0 2.9
+set Neutron:RapidityWidth 0.1
+set Neutron:AngleWidth 0.1
+set Neutron:Connected Connected
set stdEmitter:RScale 1.0
set stdEmitter:PTScale 1.0
set stdEmitter:PSInflation 1.0
set stdEmitter:PMinusOrdering 0.8
set stdEmitter:BothOrderedEvo True
set stdEmitter:BothOrderedInt True
set stdEmitter:BothOrderedFS True
set stdEmitter:RangeMode Min
#set stdEmitter:RangeMode Mother
#set stdEmitter:MinusOrderingMode EffectiveParton
set stdEmitter:MinusOrderingMode EffectivePT
# set stdFiller:RecoilScheme FrameFan
set stdFiller:RecoilScheme PreservePlus
# set stdFiller:DipoleAbsorber largePTAbsorber
# set stdFiller:Mode Consistent
set stdFiller:Mode SingleSweep
# set stdFiller:Mode NonRecursive
# set stdFiller:Mode Fast
set stdFiller:EffectiveWeights PlusWeighted
#set stdFiller:EffectiveWeights PlusEvenWeighted
#set stdFiller:EffectiveWeights PlusSingleWeighted
set stdFiller:SingleMother 0
set stdFiller:FSSwingTime 0.0
#set stdFiller:ValenceChargeNormalisation None
set stdFiller:ValenceChargeNormalisation Swing
set stdXSec:Interaction 0
#set stdXSec:IntOrdering Default
#set stdXSec:IntOrdering AsEvo
set stdXSec:IntOrdering VeryOpen
#set stdXSec:RecoilReduction Off
set stdXSec:RecoilReduction RapidityOrdered
mset . DIPSY::DipoleEventHandler LambdaQCD 0.23
mset . DIPSY::DipoleEventHandler RMax 2.9
mset . DIPSY::DipoleEventHandler CoherenceRange 2.9
mset . DIPSY::DipoleEventHandler NF 3
mset . DIPSY::DipoleEventHandler YFrametest 0.5
mset . DIPSY::DipoleEventHandler NColours 9
mset . DIPSY::DipoleEventHandler ShowHistory 0
#mset . DIPSY::DipoleEventHandler EffectivePartonMode Colours
mset . DIPSY::DipoleEventHandler EffectivePartonMode Relatives
set Frag8:StringZ_aLund 0.23
set Frag8:StringZ_bLund 0.34
set Frag8:StringPT_sigma 0.405
set FSOrdering:Generous -1
#set FSOrdering:Generous Restrictive
#set FSOrdering:OnlyOriginal false
#read ../../TheP8I/src/OverlapStringFragmenter.in
#mset . DIPSY::DipoleEventHandler HadronizationHandler /TheP8I/Handlers/StringFrag/Overlap6StringFragmenter
#mset . DIPSY::DipoleEventHandler HadronizationHandler /TheP8I/Handlers/StringFrag/Overlap2StringFragmenter
#mset . DIPSY::DipoleEventHandler HadronizationHandler /TheP8I/Handlers/StringFrag/Overlap1StringFragmenter
#set Frag8:StringPT_sigma 0.5
#set Frag8:StringZ_aLund 0.21
#set Frag8:StringZ_bLund 0.352
#set Frag8:StringPT_sigma 0.453
mset . DIPSY::DipoleEventHandler DecayHandler:MaxLifeTime 10
set virtualPhoton:QuarkMasses[1] 0.06
set virtualPhoton:QuarkMasses[2] 0.06
set virtualPhoton:QuarkMasses[3] 0.06
set virtualPhoton:QuarkMasses[4] 1.4
set virtualPhoton:ShrinkR 4.3
set virtualPhoton:VMDLightA 9
set virtualPhoton:VMDLightR 3
set virtualPhoton:VMDLightW 0.2
set virtualPhoton:VMDCharmA 9
set virtualPhoton:VMDCharmR 3
set virtualPhoton:VMDCharmW 0.2
#set virtualPhoton:ShrinkR 0.0
#set virtualPhoton:VMDLightA 0.0
popd
diff --git a/DIPSY/VectorMesonBase.cc b/DIPSY/VectorMesonBase.cc
--- a/DIPSY/VectorMesonBase.cc
+++ b/DIPSY/VectorMesonBase.cc
@@ -1,73 +1,73 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the VectorMesonBase class.
//
#include "VectorMesonBase.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/ParVector.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/PDT/ParticleData.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace DIPSY;
VectorMesonBase::~VectorMesonBase() {}
Energy2 VectorMesonBase::psi2(InvEnergy r, double z) {
Energy2 sum = 0.0*GeV2;
for ( int f = 1; f <= abs(maxFlav()); ++f )
sum += sqr(psi(0, 1, 1, f, r, z)) + sqr(psi(1, 1, -1, f, r, z)) +
sqr(psi(1, -1, 1, f, r, z)) + sqr(psi(1, 1, 1, f, r, z));
return sum;
}
void VectorMesonBase::doinit() throw(InitException) {
WaveFunction::doinit();
for ( int f = 1; f <= abs(maxFlav()); ++f )
if ( qmass[f] < 0.0*GeV ) qmass[f] = generator()->getParticleData(f)->mass();
}
void VectorMesonBase::persistentOutput(PersistentOStream & os) const {
os << theMaxFlav << ounit(qmass, GeV);
}
void VectorMesonBase::persistentInput(PersistentIStream & is, int) {
is >> theMaxFlav >> iunit(qmass, GeV);
}
// Static variable needed for the type description system in ThePEG.
#include "ThePEG/Utilities/DescribeClass.h"
DescribeAbstractClass<VectorMesonBase,DIPSY::WaveFunction>
- describeDIPSYVectorMesonBase("DIPSY::VectorMesonBase", "libDIPSY.so");
+ describeDIPSYVectorMesonBase("DIPSY::VectorMesonBase", "libAriadne5.so libDIPSY.so");
void VectorMesonBase::Init() {
static ClassDocumentation<VectorMesonBase> documentation
("The VectorMesonBase class inherits from WaveFunction and is the "
"base class of all vector meson wave functions. It includes abstract "
"functions for different polarization and helicity components.");
static Parameter<VectorMesonBase,int> interfaceMaxFlav
("MaxFlav",
"The maxumim number of flavours considered. If negative only the "
"corresponding flavour will be considered.",
&VectorMesonBase::theMaxFlav, 4, -6, 6,
true, false, Interface::limited);
static ParVector<VectorMesonBase,Energy> interfaceQuarkMasses
("QuarkMasses",
"The quark masses to be used (zero'th component is always ignored). "
"If negative, the value in the default corresponding ParticleData "
"object is used instead.",
&VectorMesonBase::qmass, GeV, 7, -1.0*GeV, 0*GeV, 0*GeV,
true, false, Interface::nolimits);
}
diff --git a/DIPSY/VirtualPhoton.cc b/DIPSY/VirtualPhoton.cc
--- a/DIPSY/VirtualPhoton.cc
+++ b/DIPSY/VirtualPhoton.cc
@@ -1,404 +1,404 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the VirtualPhoton class.
//
#include "VirtualPhoton.h"
#include "PhotonWFInfo.h"
#include "ThePEG/Interface/Switch.h"
#include "PhotonDipoleState.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/StandardModel/StandardModelBase.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Utilities/Selector.h"
#include "ThePEG/Utilities/Throw.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "gsl/gsl_sf_bessel.h"
using namespace DIPSY;
VirtualPhoton::~VirtualPhoton() {}
void VirtualPhoton::initialize(const DipoleEventHandler &) {
cout << "preparing virtual photon generation for " << this << endl;
//find the normalisation and maximum value of r^3*2*pi*(sum_i Psi_i^2(r,z))
//this is the distribution that will be used to generate dipoles, and it is
//only the wavefunction, times an extra r^2 for interaction probability
//and converging integral
rMax = 10.0/GeV;
r2Psi2Int = ZERO;
r2Psi2Max = ZERO;
int samples = 10000;
InvEnergy sum = ZERO;
for ( int i = 0; i < samples; i++ ) {
double z = UseRandom::rnd();
InvEnergy r = UseRandom::rnd()*rMax;
InvEnergy value = sqr(r)*sumPsi2(r, z);
if ( value > r2Psi2Max ) r2Psi2Max = value;
sum += value;
}
r2Psi2Int = sum*rMax/double(samples);
cout << "photon generation ready. Max value: " << r2Psi2Max*GeV << "GeV-1, integral: "
<< r2Psi2Int*GeV2 << "GeV-2" << endl;
}
Energy2 VirtualPhoton::m2() const {
return -Q2();
}
DipoleStatePtr VirtualPhoton::
generate2(const DipoleEventHandler & eh, Energy plus) {
//first generate an r and z with (normalised) distribution P_0(r) = r^2 P_true(r)
InvEnergy r;
double z;
while (true) {
r = UseRandom::rnd()*rMax;
z = UseRandom::rnd();
if ( sqr(r)*sumPsi2(r, z) > UseRandom::rnd()*r2Psi2Max ) break;
}
//set weight to account for normalisation of P_0(r), and to make up
//for the extra r^2 to get to P_true(r)
double weight = r2Psi2Int/sqr(r);
//pick flavour according to the square of the wavefunction for this r and z
Selector<int,Energy2> selFlav;
for ( int f = 1; f < maxFlav(); ++f ) {
Energy2 prob = ZERO;
if ( polarisation() == 0 || polarisation() == 2 )
prob += sqr(psi(0, 1, 1, f, r, z))*2.0;
if ( polarisation() == 0 || polarisation() == 1 ) {
prob += sqr(psi(1, 1, -1, f, r, z));
prob += sqr(psi(1, -1, 1, f, r, z));
prob += sqr(psi(1, 1, 1, f, r, z));
}
selFlav.insert((f%2? 1.0: 4.0)*prob, f);
}
int f = selFlav[UseRandom::rnd()];
// Now pick helicity, with the weights of the squared wavefunction
//for this r, z and f.
Energy2 PLhh = sqr(psi(0, 1, 1, f, r, z))*2.0;
Energy2 PTpm = sqr(psi(1, 1, -1, f, r, z));
Energy2 PTmp = sqr(psi(1, -1, 1, f, r, z));
Energy2 PThh = sqr(psi(1, 1, 1, f, r, z));
if ( polarisation() == 1 )
PLhh = ZERO;
if ( polarisation() == 2 ) {
PTpm = ZERO;
PTmp = ZERO;
PThh = ZERO;
}
Energy2 sum = PLhh + PTpm + PTmp + PThh;
Energy2 rsum = sum*UseRandom::rnd();
Ptr<PhotonWFInfo>::pointer wfi;
if ( PLhh > rsum ) {
if ( UseRandom::rndbool() )
wfi = new_ptr(PhotonWFInfo(this, r, z, 0, 1, 1, f));
else
wfi = new_ptr(PhotonWFInfo(this, r, z, 0, -1, -1, f));
}
else if ( PLhh + PThh > rsum ) {
if ( UseRandom::rndbool() )
wfi = new_ptr(PhotonWFInfo(this, r, z, 1, 1, 1, f));
else
wfi = new_ptr(PhotonWFInfo(this, r, z, -1, -1, -1, f));
}
else if ( PLhh + PThh + PTpm > rsum ) {
if ( UseRandom::rndbool() )
wfi = new_ptr(PhotonWFInfo(this, r, z, 1, 1, -1, f));
else
wfi = new_ptr(PhotonWFInfo(this, r, z, -1, 1, -1, f));
}
else {
if ( UseRandom::rndbool() )
wfi = new_ptr(PhotonWFInfo(this, r, z, 1, -1, 1, f));
else
wfi = new_ptr(PhotonWFInfo(this, r, z, -1, -1, 1, f));
}
return new_ptr(PhotonDipoleState(eh, plus, -Q2()/plus, wfi, weight));
}
DipoleStatePtr VirtualPhoton::
generate(const DipoleEventHandler & eh, Energy plus) {
// z is always chosen uniformly
double z = UseRandom::rnd();
// flavour is chosen with (normalized) integrated probability
// proportional to ef^2 exp(-2*epsf*r)
Selector<int,InvEnergy> sel;
Energy eps = sqrt(z*(1.0 - z)*Q2() + sqr(qmass[abs(maxFlav())]));
sel.insert((abs(maxFlav())%2? 1.0: 4.0)/(18.0*eps), abs(maxFlav()));
for ( int f = 1; f < maxFlav(); ++f ) {
Energy eps = sqrt(z*(1.0 - z)*Q2() + sqr(qmass[f]));
sel.insert((f%2? 1.0: 4.0)/(18.0*eps), f);
}
int f = sel[UseRandom::rnd()];
// r is chosen according to (normalized) probability exp(-2*epsf*r).
eps = sqrt(z*(1.0 - z)*Q2() + sqr(qmass[f]));
InvEnergy r =-log(UseRandom::rnd())/(2.0*eps);
// Przf is the probability with which we have chosen r, z and f
Energy Przf = (f%2? 1.0: 4.0)*exp(-2.0*r*eps)/(9.0*sel.sum());
// Now find the squared wavefunction (differential in r) for the
// different helicities and choose one.
Energy PLhh = r*sqr(psi(0, 1, 1, f, r, z))*4.0*Constants::pi;
Energy PTpm = r*sqr(psi(1, 1, -1, f, r, z))*2.0*Constants::pi;
Energy PTmp = r*sqr(psi(1, -1, 1, f, r, z))*2.0*Constants::pi;
Energy PThh = r*sqr(psi(1, 1, 1, f, r, z))*2.0*Constants::pi;
if ( polarisation() == 1 )
PLhh = ZERO;
if ( polarisation() == 2 ) {
PTpm = ZERO;
PTmp = ZERO;
PThh = ZERO;
}
Energy sum = PLhh + PTpm + PTmp + PThh;
Energy rsum = sum*UseRandom::rnd();
Ptr<PhotonWFInfo>::pointer wfi;
double weight = sum/Przf;
if ( PLhh > rsum ) {
if ( UseRandom::rndbool() )
wfi = new_ptr(PhotonWFInfo(this, r, z, 0, 1, 1, f));
else
wfi = new_ptr(PhotonWFInfo(this, r, z, 0, -1, -1, f));
}
else if ( PLhh + PThh > rsum ) {
if ( UseRandom::rndbool() )
wfi = new_ptr(PhotonWFInfo(this, r, z, 1, 1, 1, f));
else
wfi = new_ptr(PhotonWFInfo(this, r, z, -1, -1, -1, f));
}
else if ( PLhh + PThh + PTpm > rsum ) {
if ( UseRandom::rndbool() )
wfi = new_ptr(PhotonWFInfo(this, r, z, 1, 1, -1, f));
else
wfi = new_ptr(PhotonWFInfo(this, r, z, -1, 1, -1, f));
}
else {
if ( UseRandom::rndbool() )
wfi = new_ptr(PhotonWFInfo(this, r, z, 1, -1, 1, f));
else
wfi = new_ptr(PhotonWFInfo(this, r, z, -1, -1, 1, f));
}
// cout << setprecision(7);
// if ( r == ZERO ) cout << "r is identically zero" << endl;
// cout << "generated photon with r = " << r*GeV << ", z = " << z
// << ", weight = " << weight << endl;
return new_ptr(PhotonDipoleState(eh, plus, -Q2()/plus, wfi, weight));
}
Energy VirtualPhoton::
pertPsi(int pol, int h, int hbar, int flav, InvEnergy r, double z) {
double ef = flav%2? -1.0/3.0: 2.0/3.0;
Energy eps = sqrt(z*(1.0 - z)*Q2() + sqr(qmass[flav]));
double epsr = eps*r;
if ( epsr > 100.0 ) return ZERO;
if ( epsr == 0.0 ) return ZERO;
if ( pol == 0 ) {
if ( h != hbar ) return 0.0*GeV;
return sqrt(SM().alphaEM()*SM().Nc()*Q2())*z*(1.0 - z)*ef*
gsl_sf_bessel_K0(epsr)/Constants::pi;
} else {
if ( h == pol && hbar == -pol )
return sqrt(SM().alphaEM()*SM().Nc()/2.0)*ef*z*eps*
gsl_sf_bessel_K1(epsr)/Constants::pi;
else if ( h == -pol && hbar == pol )
return sqrt(SM().alphaEM()*SM().Nc()/2.0)*ef*(1.0 - z)*eps*
gsl_sf_bessel_K1(epsr)/Constants::pi;
else if ( h == pol && hbar == pol )
return sqrt(SM().alphaEM()*SM().Nc()/2.0)*ef*qmass[flav]*
gsl_sf_bessel_K0(epsr)/Constants::pi;
else
return 0.0*GeV;
}
}
// int status = gsl_sf_bessel_K1_e(epsr,&result);
// if (status) {
// //handle error.
// }
// result.val;
// typedef struct
// {
// double val;
// double err;
// } gsl_sf_result;
Energy VirtualPhoton::
psi(int pol, int h, int hbar, int flav, InvEnergy r, double z) {
// Start out with the perturbative wavefunciton for the unconfined r.
InvEnergy rPert = r;
double jacobian = 1.0;
//taking confinement into account, what perturbative (nonconfined)
//r_pert is the final confined r_conf associated with?
if ( shrinkR() != ZERO ) rPert = shrinkR()*sqrt(-Math::exp1m(sqr(r/shrinkR())));
//events are generated in dr_conf, but the wavefuntion create them
//with dr_pert, so we need an extra dr_pert/dr_conf to account for how
//the dip sizes gets clumped up around confinement scale.
if ( shrinkR() != ZERO )
jacobian = r/shrinkR()*exp(sqr(r/shrinkR()))/sqrt(expm1(sqr(r/shrinkR())));
Energy ret = pertPsi(pol, h, hbar, flav, rPert, z);
//vector meson resonance enhances the wavefunction if the final confined r
//is about the size of a vector emson.
ret *= sqrt(VMDCorr(r, flav)*jacobian);
return ret;
}
Energy VirtualPhoton::
sumPsi2(InvEnergy r, double z) {
//sum all wavefunctions contribution to this r and z
Energy ret = ZERO;
//sum over flavours
for ( int f = 1; f < maxFlav(); ++f ) {
//sum over helicities
if ( polarisation() == 0 || polarisation() == 2 )
ret += r*sqr(psi(0, 1, 1, f, r, z))*4.0*Constants::pi;
if ( polarisation() == 0 || polarisation() == 1 ) {
ret += r*sqr(psi(1, 1, -1, f, r, z))*2.0*Constants::pi;
ret += r*sqr(psi(1, -1, 1, f, r, z))*2.0*Constants::pi;
ret += r*sqr(psi(1, 1, 1, f, r, z))*2.0*Constants::pi;
}
}
return ret;
}
double VirtualPhoton::VMDCorr(InvEnergy r, int flav) {
if ( VMDLightA() == 0.0 ) return 1.0;
if ( flav == 1 || flav == 2 || flav == 3 )
return (1.0 + VMDLightA()*exp(-sqr((r-VMDLightR())/VMDLightW())))/
(1.0 + VMDLightA()*exp(-sqr(VMDLightR()/VMDLightW())));
else if ( flav == 4 )
return (1.0 + VMDCharmA()*exp(-sqr((r-VMDCharmR())/VMDCharmW())))/
(1.0 + VMDCharmA()*exp(-sqr(VMDCharmR()/VMDCharmW())));
cerr << "vector meson dominance parameters only added for up, down, strange and charm. Heavier quarks get the charm parameters. flavour is " << flav << endl;
return (1.0 + VMDCharmA()*exp(-sqr((r-VMDCharmR())/VMDCharmW())))/
(1.0 + VMDCharmA()*exp(-sqr(VMDCharmR()/VMDCharmW())));
}
void VirtualPhoton::setParticle(PDPtr p) {
if ( p->id() != ParticleID::gamma )
throw InterfaceException()
<< "Cannot set " << p->name()
<< " as particle for a VirtualPhoton wave function. "
<< "Only Photons are allowed." << Exception::warning;
WaveFunction::setParticle(p);
}
void VirtualPhoton::persistentOutput(PersistentOStream & os) const {
os << ounit(theQ2, GeV2) << ounit(theShrinkR, InvGeV) << thePolarisation << theVMDLightA
<< ounit(theVMDLightR, InvGeV) << ounit(theVMDLightW, InvGeV) << theVMDCharmA
<< ounit(theVMDCharmR, InvGeV) << ounit(theVMDCharmW, InvGeV) << ounit(rMax, InvGeV)
<< ounit(r2Psi2Int, sqr(InvGeV)) << ounit(r2Psi2Max, InvGeV);
}
void VirtualPhoton::persistentInput(PersistentIStream & is, int) {
is >> iunit(theQ2, GeV2) >> iunit(theShrinkR, InvGeV) >> thePolarisation >> theVMDLightA
>> iunit(theVMDLightR, InvGeV) >> iunit(theVMDLightW, InvGeV) >> theVMDCharmA
>> iunit(theVMDCharmR, InvGeV) >> iunit(theVMDCharmW, InvGeV) >> iunit(rMax, InvGeV)
>> iunit(r2Psi2Int, sqr(InvGeV)) >> iunit(r2Psi2Max, InvGeV);
}
// Static variable needed for the type description system in ThePEG.
#include "ThePEG/Utilities/DescribeClass.h"
DescribeClass<VirtualPhoton,DIPSY::VectorMesonBase>
- describeDIPSYVirtualPhoton("DIPSY::VirtualPhoton", "libDIPSY.so");
+ describeDIPSYVirtualPhoton("DIPSY::VirtualPhoton", "libAriadne5.so libDIPSY.so");
void VirtualPhoton::Init() {
static ClassDocumentation<VirtualPhoton> documentation
("The VirtualPhoton class represents the perturbative quark--anti-quark "
"dipole wave function of a virtual photon with a given virtuality.");
static Parameter<VirtualPhoton,Energy2> interfaceQ2
("Q2",
"The virtuality of the photon in units of GeV\\f$^2\\f$.",
&VirtualPhoton::theQ2, GeV2, 0.0*GeV2, 0.0*GeV2, 0*GeV2,
true, false, Interface::lowerlim);
static Parameter<VirtualPhoton, InvEnergy> interfaceShrinkR
("ShrinkR",
"Sets the confinement scale of the photon wavefunction. Due to different"
"parametrisations, this paramter should be about 1.5 times rmax in DipoleEventHandler.",
&VirtualPhoton::theShrinkR, InvGeV, 0.0*InvGeV, 0.0*InvGeV, 0.0*InvGeV,
true, false, Interface::lowerlim);
static Parameter<VirtualPhoton, double> interfaceVMDLightA
("VMDLightA",
"Sets the amplitude of the vector meson resonence boost for the wavefunction.",
&VirtualPhoton::theVMDLightA, 0.0, 0.0, 0.0, 0.0,
true, false, Interface::lowerlim);
static Parameter<VirtualPhoton, InvEnergy> interfaceVMDLightR
("VMDLightR",
"Sets the typical size of the vector meson resonence in wavefunction.",
&VirtualPhoton::theVMDLightR, InvGeV, 0.0*InvGeV, 0.0*InvGeV, 0.0*InvGeV,
true, false, Interface::lowerlim);
static Parameter<VirtualPhoton, InvEnergy> interfaceVMDLightW
("VMDLightW",
"Sets the width of the vector meson resonence in wavefunction.",
&VirtualPhoton::theVMDLightW, InvGeV, 0.0*InvGeV, 0.0*InvGeV, 0.0*InvGeV,
true, false, Interface::lowerlim);
static Parameter<VirtualPhoton, double> interfaceVMDCharmA
("VMDCharmA",
"Sets the amplitude of the vector meson resonence boost for the wavefunction.",
&VirtualPhoton::theVMDCharmA, 0.0, 0.0, 0.0, 0.0,
true, false, Interface::lowerlim);
static Parameter<VirtualPhoton, InvEnergy> interfaceVMDCharmR
("VMDCharmR",
"Sets the typical size of the vector meson resonence in wavefunction.",
&VirtualPhoton::theVMDCharmR, InvGeV, 0.0*InvGeV, 0.0*InvGeV, 0.0*InvGeV,
true, false, Interface::lowerlim);
static Parameter<VirtualPhoton, InvEnergy> interfaceVMDCharmW
("VMDCharmW",
"Sets the width of the vector meson resonence in wavefunction.",
&VirtualPhoton::theVMDCharmW, InvGeV, 0.0*InvGeV, 0.0*InvGeV, 0.0*InvGeV,
true, false, Interface::lowerlim);
static Switch<VirtualPhoton,int> interfacePolarisation
("Polarisation",
"What helicity of the photon to run.",
&VirtualPhoton::thePolarisation, 0, true, false);
static SwitchOption interfaceHelicityBoth
(interfacePolarisation,
"Both",
"Use both T and L helicities, effectiviely giving F_2.",
0);
static SwitchOption interfaceHelicityTransverse
(interfacePolarisation,
"Transverse",
"Use only transverse helicity photons.",
1);
static SwitchOption interfaceHelicityLongitudinal
(interfacePolarisation,
"Longitudinal",
"Use only longitudinal polarisation, giving F_L",
2);
}
diff --git a/DIPSY/WFInfo.cc b/DIPSY/WFInfo.cc
--- a/DIPSY/WFInfo.cc
+++ b/DIPSY/WFInfo.cc
@@ -1,40 +1,40 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the WFInfo class.
//
#include "WFInfo.h"
#include "WaveFunction.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace DIPSY;
WFInfo::~WFInfo() {}
tcWFInfoPtr WFInfo::getWFInfo(const Particle & particle) {
for ( int i = 0, N = particle.getInfo().size(); i < N; ++i )
if ( const WFInfo * win =
dynamic_cast<const WFInfo *>(particle.getInfo()[i].operator->()) )
return win;
return tcWFInfoPtr();
}
void WFInfo::persistentOutput(PersistentOStream & os) const {
os << theWF << ounit(theR, InvGeV);
}
void WFInfo::persistentInput(PersistentIStream & is, int) {
is >> theWF >> iunit(theR, InvGeV);
}
// Static variable needed for the type description system in ThePEG.
#include "ThePEG/Utilities/DescribeClass.h"
DescribeClass<WFInfo,ThePEG::EventInfoBase>
- describeDIPSYWFInfo("DIPSY::WFInfo", "libDIPSY.so");
+ describeDIPSYWFInfo("DIPSY::WFInfo", "libAriadne5.so libDIPSY.so");
void WFInfo::Init() {}
diff --git a/DIPSY/WaveFunction.cc b/DIPSY/WaveFunction.cc
--- a/DIPSY/WaveFunction.cc
+++ b/DIPSY/WaveFunction.cc
@@ -1,58 +1,58 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the WaveFunction class.
//
#include "WaveFunction.h"
#include "DipoleEventHandler.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace DIPSY;
WaveFunction::~WaveFunction() {}
void WaveFunction::fixValence(Step &, tPPtr, const vector<PPtr> &) const {}
void WaveFunction::initialize(const DipoleEventHandler & eh) {
theEventHandler = &eh;
}
void WaveFunction::persistentOutput(PersistentOStream & os) const {
os << theEventHandler << theParticle;
}
void WaveFunction::persistentInput(PersistentIStream & is, int) {
is >> theEventHandler >> theParticle;
}
void WaveFunction::setParticle(PDPtr p) {
theParticle = p;
}
// Static variable needed for the type description system in ThePEG.
#include "ThePEG/Utilities/DescribeClass.h"
DescribeAbstractClass<WaveFunction,HandlerBase>
- describeDIPSYWaveFunction("DIPSY::WaveFunction", "libDIPSY.so");
+ describeDIPSYWaveFunction("DIPSY::WaveFunction", "libAriadne5.so libDIPSY.so");
void WaveFunction::Init() {
static ClassDocumentation<WaveFunction> documentation
("WaveFunction is the base class for wavefunction objects capable of "
"generating initial DipoleState objects.");
static Reference<WaveFunction,ParticleData> interfaceParticle
("Particle",
"The corresponding particle.",
&WaveFunction::theParticle, true, false, true, false, false,
&WaveFunction::setParticle,
(Ptr<ParticleData>::pointer(WaveFunction::*)()const)(0),
(bool(WaveFunction::*)(Ptr<ParticleData>::const_pointer)const)(0));
}
diff --git a/Makefile.am b/Makefile.am
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,5 +1,5 @@
-SUBDIRS = include Config DipoleCascade Cascade lib src DIPSY
+SUBDIRS = include Config Cascade lib src DIPSY
EXTRA_DIST = GUIDELINES
ACLOCAL_AMFLAGS = -I m4
diff --git a/lib/Makefile.am b/lib/Makefile.am
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -1,21 +1,21 @@
-LINKDIRS = DipoleCascade Cascade
+LINKDIRS = Cascade
all-local: done-all-links
done-all-links: ../DipoleCascade/Makefile ../Cascade/Makefile
@EMPTY@ifdef SHOWCOMMAND
for dir in $(LINKDIRS); do \
for sofile in ../$$dir/.libs/*.so* ../$$dir/.libs/*.la; \
do if test -f $$sofile; then $(LN_S) -f $$sofile .; fi; done; done
echo "stamp" > done-all-links
@EMPTY@else
@echo "Sym-linking all shared libraries ..."
@for dir in $(LINKDIRS); do \
for sofile in ../$$dir/.libs/*.so* ../$$dir/.libs/*.la; \
do if test -f $$sofile; then $(LN_S) -f $$sofile .; fi; done; done
@echo "stamp" > done-all-links
@EMPTY@endif
clean-local:
rm -f *.so* *.la *.rpo done-all-links
diff --git a/src/FTuneLEP.in b/src/FTuneLEP.in
--- a/src/FTuneLEP.in
+++ b/src/FTuneLEP.in
@@ -1,86 +1,87 @@
mkdir /Ariadne5/MultiLEP
cd /Ariadne5/MultiLEP
create ThePEG::MultiEventGenerator MultiLEPGenerator MultiEventGenerator.so
set MultiLEPGenerator:EventHandler /Ariadne5/Generators/LEP/LEPGenerator:EventHandler
set MultiLEPGenerator:RandomNumberGenerator /Ariadne5/Generators/LEP/LEPGenerator:RandomNumberGenerator
set MultiLEPGenerator:StandardModelParameters /Ariadne5/Generators/LEP/LEPGenerator:StandardModelParameters
set MultiLEPGenerator:Strategy /Ariadne5/StdStrategy
set MultiLEPGenerator:NumberOfEvents 100000
set MultiLEPGenerator:DebugLevel 0
set MultiLEPGenerator:PrintEvent 0
create ThePEG::RivetAnalysis RivetLEP RivetAnalysis.so
insert RivetLEP:Analyses[0] PDG_HADRON_MULTIPLICITIES_RATIOS
insert RivetLEP:Analyses[0] DELPHI_1996_S3430090
insert RivetLEP:Analyses[0] DELPHI_2002_069_CONF_603
insert RivetLEP:Analyses[0] DELPHI_2000_S4328825
insert RivetLEP:Analyses[0] OPAL_1998_S3780481
insert MultiLEPGenerator:AnalysisHandlers[0] RivetLEP
do MultiLEPGenerator:AddRndInterface /Ariadne5/Defaults/Frag8:StringZ_aLund 200 0.05 2.0 0.3 0.2
do MultiLEPGenerator:AddRndInterface /Ariadne5/Defaults/Frag8:StringZ_bLund 1 0.21 2.0 0.80 0.4
do MultiLEPGenerator:AddRndInterface /Ariadne5/Defaults/Frag8:StringPT_sigma 1 0.05 1.0 0.3 0.2
do MultiLEPGenerator:AddRndInterface /Ariadne5/Defaults/Frag8:StringFlav_probQQtoQ 1 0.0 1.0 0.09 0.05
do MultiLEPGenerator:AddRndInterface /Ariadne5/Defaults/Frag8:StringFlav_probStoUD 1 0.0 1.0 0.19 0.10
set /Ariadne5/Cascade/BasicConsistency:CheckGluonPT Off
erase /Ariadne5/Cascade/Models/FSGluon:Reweighters[0]
cp /Ariadne5/Cascade/AriadneCascade AriadneSwingCascade
set AriadneSwingCascade:PurgeStrategy BeforeAndAfter
set AriadneSwingCascade:PurgeFactor 1.0
create Ariadne5::DipoleSwinger Swinger
do Swinger:SetRmax -2.7
set Swinger:SizeOpt 1
set Swinger:Lambda 1
set Swinger:Linear Logarithmic
set Swinger:RhoCut -1.0
insert AriadneSwingCascade:Emitters[0] Swinger
cp /Ariadne5/Generators/LEP/LEPHandler SwingHandler
set SwingHandler:CascadeHandler AriadneSwingCascade
create ThePEG::ProgressLog Logger ProgressLog.so
set Logger:Interval 600
insert MultiLEPGenerator:AnalysisHandlers[0] Logger
cp MultiLEPGenerator MultiLEPGeneratorSw
set MultiLEPGeneratorSw:EventHandler SwingHandler
saverun FTuneLEP01 MultiLEPGenerator
set MultiLEPGeneratorSw:NumberOfEvents 10000
saverun FTuneSwLEP02 MultiLEPGeneratorSw
set MultiLEPGeneratorSw:NumberOfEvents 100000
saverun FTuneSwLEP03 MultiLEPGeneratorSw
do MultiLEPGenerator:RemoveInterface /Ariadne5/Defaults/Frag8:StringZ_aLund
do MultiLEPGenerator:RemoveInterface /Ariadne5/Defaults/Frag8:StringZ_bLund
do MultiLEPGenerator:RemoveInterface /Ariadne5/Defaults/Frag8:StringPT_sigma
do MultiLEPGenerator:RemoveInterface /Ariadne5/Defaults/Frag8:StringFlav_probQQtoQ
do MultiLEPGenerator:RemoveInterface /Ariadne5/Defaults/Frag8:StringFlav_probStoUD
set MultiLEPGenerator:NumberOfEvents 10000000
set /Ariadne5/Defaults/Frag8:StringZ_aLund 0.30
set /Ariadne5/Defaults/Frag8:StringZ_bLund 0.36
set /Ariadne5/Defaults/Frag8:StringPT_sigma 0.33
set /Ariadne5/Defaults/Frag8:StringFlav_probQQtoQ 0.082
set /Ariadne5/Defaults/Frag8:StringFlav_probStoUD 0.22
saverun FTuneLEP01t MultiLEPGenerator
do MultiLEPGeneratorSw:RemoveInterface /Ariadne5/Defaults/Frag8:StringZ_aLund
do MultiLEPGeneratorSw:RemoveInterface /Ariadne5/Defaults/Frag8:StringZ_bLund
do MultiLEPGeneratorSw:RemoveInterface /Ariadne5/Defaults/Frag8:StringPT_sigma
do MultiLEPGeneratorSw:RemoveInterface /Ariadne5/Defaults/Frag8:StringFlav_probQQtoQ
do MultiLEPGeneratorSw:RemoveInterface /Ariadne5/Defaults/Frag8:StringFlav_probStoUD
set MultiLEPGeneratorSw:NumberOfEvents 10000000
set /Ariadne5/Defaults/Frag8:StringZ_aLund 0.42
set /Ariadne5/Defaults/Frag8:StringZ_bLund 0.40
set /Ariadne5/Defaults/Frag8:StringPT_sigma 0.32
set /Ariadne5/Defaults/Frag8:StringFlav_probQQtoQ 0.084
set /Ariadne5/Defaults/Frag8:StringFlav_probStoUD 0.22
saverun FTuneSwLEP01t MultiLEPGeneratorSw
saverun FTuneSwLEP02t MultiLEPGeneratorSw
saverun FTuneSwLEP02t73 MultiLEPGeneratorSw
+saverun FTuneSwLEP03t MultiLEPGeneratorSw
diff --git a/src/Makefile.am b/src/Makefile.am
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,103 +1,76 @@
AUTOMAKE_OPTIONS = -Wno-portability
-dist_pkgdata_DATA = TestAriadne.in TestAriadneDY.in TestAriadneDIS.in \
- AriadneDefaults.in AriadneRemove.in Ariadne5Defaults.in \
- Ariadne5Remove.in TestAriadne5.in TestAriadne5DIS.in \
- TestAriadne5Z0.in
+dist_pkgdata_DATA = Ariadne5Defaults.in Ariadne5Remove.in TestAriadne5.in \
+ TestAriadne5DIS.in TestAriadne5Z0.in
rpodir = $(pkglibdir)
-nodist_rpo_DATA = AriadneDefaults.rpo Ariadne5Defaults.rpo
+nodist_rpo_DATA = Ariadne5Defaults.rpo
-CLEANFILES = TestAriadne.log TestAriadne.out TestAriadne.run TestAriadne.tex \
- TestAriadneDY.log TestAriadneDY.out TestAriadneDY.run \
- TestAriadneDY.tex TestAriadneDY.aida TestAriadneDY.dat \
- TestAriadneDIS.log TestAriadneDIS.out TestAriadneDIS.run \
- TestAriadneDIS.tex TestAriadneDIS.aida TestAriadneDIS.dat \
- AriadneDefaults.rpo Ariadne5Defaults.rpo done-all-links \
- .runThePEG.timer.TestAriadne.run testariadnedy.rz \
- TestAriadneDY.hzlog testariadnedis.rz TestAriadneDIS.hzlog \
+CLEANFILES = Ariadne5Defaults.rpo done-all-links \
TestAriadne5.log TestAriadne5.out TestAriadne5.run TestAriadne5.tex \
TestAriadne5Z0.log TestAriadne5Z0.out TestAriadne5Z0.run \
TestAriadne5Z0.tex TestAriadne5DIS.log TestAriadne5DIS.out \
TestAriadne5DIS.run TestAriadne5DIS.tex
-INPUTFILES = AriadneDefaults.in AriadneRemove.in Ariadne5Defaults.in \
- Ariadne5Remove.in TestAriadne.in TestAriadne5.in \
+INPUTFILES = Ariadne5Defaults.in Ariadne5Remove.in TestAriadne5.in \
TestAriadne5Z0.in TestAriadne5DIS.in
pkglib_LTLIBRARIES = MEqq2gZ2ll.la DYAnalysis.la DISAnalysis.la ETFlow.la
# Version info should be updated if any interface or persistent I/O
# function is changed
MEqq2gZ2ll_la_LDFLAGS = -module -version-info 1:0:0
MEqq2gZ2ll_la_SOURCES = MEqq2gZ2ll.cc MEqq2gZ2ll.h MEqq2gZ2ll.icc
# Version info should be updated if any interface or persistent I/O
# function is changed
DYAnalysis_la_LDFLAGS = -module -version-info 1:0:0
DYAnalysis_la_SOURCES = DYAnalysis.cc DYAnalysis.h DYAnalysis.icc
DISAnalysis_la_LDFLAGS = -module -version-info 1:0:0
DISAnalysis_la_SOURCES = DISAnalysis.cc DISAnalysis.h DISAnalysis.icc
ETFlow_la_LDFLAGS = -module -version-info 1:0:0
ETFlow_la_SOURCES = ETFlow.cc ETFlow.h
done-all-links:
@EMPTY@ifdef SHOWCOMMAND
for file in $(INPUTFILES); do \
if test ! -f $$file; then $(LN_S) $(srcdir)/$$file $$file; fi; done
echo "stamp" > done-all-links
@EMPTY@else
@echo "sym-linking input files files..."
@for file in $(INPUTFILES); do \
if test ! -f $$file; then $(LN_S) $(srcdir)/$$file $$file; fi; done
@echo "stamp" > done-all-links
@EMPTY@endif
-AriadneDefaults.rpo: done-all-links AriadneDefaults.in ../lib/libArCascade.so $(THEPEGLIB)/ThePEGDefaults.rpo $(PYTHIA7LIBPATH)/Pythia7Defaults.rpo
- $(SETUPTHEPEG) --exitonerror --init -L../lib -L$(PYTHIA7LIBPATH) -L$(THEPEGLIB) -r $(PYTHIA7LIBPATH)/Pythia7Defaults.rpo -o AriadneDefaults.rpo AriadneDefaults.in
- cd ../lib; $(LN_S) -f ../src/AriadneDefaults.rpo .
-
Ariadne5Defaults.rpo: done-all-links Ariadne5Defaults.in ../lib/libAriadne5.so $(THEPEGLIB)/ThePEGDefaults.rpo $(THEP8ILIBPATH)/TheP8IDefaults.rpo MEqq2gZ2ll.la
$(SETUPTHEPEG) --exitonerror --init -L../lib -L$(THEP8ILIBPATH) -L$(THEPEGLIB) -L.libs -r $(THEP8ILIBPATH)/TheP8IDefaults.rpo -o Ariadne5Defaults.rpo Ariadne5Defaults.in
cd ../lib; $(LN_S) -f ../src/Ariadne5Defaults.rpo .
check-local:
$(SETUPTHEPEG) --exitonerror -r ../lib/Ariadne5Defaults.rpo TestAriadne5.in
time $(RUNTHEPEG) -d 0 TestAriadne5.run
$(SETUPTHEPEG) --exitonerror -r ../lib/Ariadne5Defaults.rpo TestAriadne5DIS.in
time $(RUNTHEPEG) -d 0 TestAriadne5DIS.run
$(SETUPTHEPEG) --exitonerror -r ../lib/Ariadne5Defaults.rpo TestAriadne5Z0.in
time $(RUNTHEPEG) -d 0 TestAriadne5Z0.run
-TestAriadne.run: done-all-links TestAriadne.in AriadneDefaults.rpo
- $(SETUPTHEPEG) --exitonerror -L../../TheP8I/lib -r ../lib/AriadneDefaults.rpo TestAriadne.in
-
-TestAriadne.out: TestAriadne.run
- time $(RUNTHEPEG) -d 0 TestAriadne.run
-
-TestAriadneDY.run: done-all-links TestAriadneDY.in AriadneDefaults.rpo MEqq2gZ2ll.la
- $(SETUPTHEPEG) --exitonerror -L../../TheP8I/lib -L .libs -L ../../test/HZTOOL/.libs -r ../lib/AriadneDefaults.rpo TestAriadneDY.in
-
-TestAriadneDY.out: TestAriadneDY.run
- time $(RUNTHEPEG) -d 0 TestAriadneDY.run
-
%.run: %.in done-all-links Ariadne5Defaults.rpo
$(SETUPTHEPEG) --exitonerror -r ../lib/Ariadne5Defaults.rpo $<
%.out: %.run
time $(RUNTHEPEG) $<
install-data-local:
- LD_LIBRARY_PATH=$(DESTDIR)$(pkglibdir):$$LD_LIBRARY_PATH $(DESTDIR)$(bindir)/setupThePEG --exitonerror --init -r $(DESTDIR)$(pkglibdir)/ThePEGDefaults.rpo -o $(DESTDIR)$(pkglibdir)/ThePEGDefaults.rpo $(srcdir)/AriadneDefaults.in
LD_LIBRARY_PATH=$(DESTDIR)$(pkglibdir):$$LD_LIBRARY_PATH $(DESTDIR)$(bindir)/setupThePEG --exitonerror --init -r $(DESTDIR)$(pkglibdir)/ThePEGDefaults.rpo -o $(DESTDIR)$(pkglibdir)/ThePEGDefaults.rpo $(srcdir)/Ariadne5Defaults.in
installcheck-local:
$(mkdir_p) _test
cd _test; $(DESTDIR)$(bindir)/setupThePEG $(DESTDIR)$(pkgdatadir)/TestAriadne5.in; $(DESTDIR)$(bindir)/runThePEG TestAriadne5.run; $(DESTDIR)$(bindir)/setupThePEG $(DESTDIR)$(pkgdatadir)/TestAriadne5DIS.in; $(DESTDIR)$(bindir)/runThePEG TestAriadne5DIS.run; $(DESTDIR)$(bindir)/setupThePEG $(DESTDIR)$(pkgdatadir)/TestAriadne5Z0.in; $(DESTDIR)$(bindir)/runThePEG TestAriadne5Z0.run
rm -rf _test
save:
mkdir -p save
cp *.rpo *.out *.log *.tex .*.timer.* save

File Metadata

Mime Type
text/x-diff
Expires
Sat, May 3, 6:57 AM (18 h, 49 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4983208
Default Alt Text
(594 KB)

Event Timeline