Page MenuHomeHEPForge

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/Cascade/AriadneHandler.cc b/Cascade/AriadneHandler.cc
--- a/Cascade/AriadneHandler.cc
+++ b/Cascade/AriadneHandler.cc
@@ -1,697 +1,728 @@
// -*- 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) {}
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);
Current<AriadneHandler> current(this);
DipoleStatePtr state;
tSubProPtr sub;
tPVector final;
Energy rhomax = ZERO;
- Energy rhomin = pTCut();
+ // 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();
while ( ( rhomax = state->select(rhomin, rhomax) ) > rhomin &&
( maxEmissions() == 0 || emnbr < maxEmissions() ) ) {
SaveDipoleState backup(state);
if ( state->perform() ) {
perf = true;
emnbr++;
+ if ( tupleswing ) {
+ static ofstream swingtuple;
+ static bool isopen = false;
+ static long lastevent = 0;
+ 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(state->selected()->rho/GeV);
+ pair<double,int> lam = state->lambdaMeasure(sqr(pTCut()));
+ swingtuple << lrho << '\t' << lam.first/lam.second << '\t' << lam.first << '\t'
+ << state->selected()->geno << '\t' << state->selected()->emno;
+ if ( DipoleSwing * em = dynamic_cast<DipoleSwing*>((Emission*)(state->selected())) ) {
+ swingtuple << "s\t" << state->index(em->dipoles.first) << '\t'
+ << state->index(em->dipoles.second);
+ }
+ else if ( dynamic_cast<FSGluonEmission*>((Emission*)(state->selected())) )
+ swingtuple << "g\t" << state->index(state->selected()->dipole);
+ else if ( dynamic_cast<FSQQEmission*>((Emission*)(state->selected())) )
+ swingtuple << "q\t" << 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());
+ 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();
}
} 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 ( 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 "
<< "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;
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;
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);
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/ColourIndex.h b/Cascade/ColourIndex.h
--- a/Cascade/ColourIndex.h
+++ b/Cascade/ColourIndex.h
@@ -1,127 +1,147 @@
// -*- C++ -*-
#ifndef Ariadne5_ColourIndex_H
#define Ariadne5_ColourIndex_H
+
+#include "Ariadne/Config/Ariadne5.h"
+
//
// This is the declaration of the ColourIndex class.
//
namespace Ariadne5 {
/**
* The olourIndex class keeps track of the colour structure in a
* DipoleState such that when colour reconnections are included only
* those reconnections which are allowed can be performed.
*/
class ColourIndex {
public:
/**
* The default constructor.
*/
ColourIndex(unsigned isys = 0): index(0), systemIndex(isys) {}
public:
/**
* Check for equality.
*/
bool operator==(const ColourIndex & c) const {
return index == c.index && systemIndex == c.systemIndex;
}
/**
* Check for inequality.
*/
bool operator!=(const ColourIndex & c) const {
return index != c.index || systemIndex != c.systemIndex;
}
/**
* Check for ordering.
*/
bool operator<(const ColourIndex & c) const {
return index < c.index || ( index == c.index && systemIndex < c.systemIndex );
}
/**
* Return the system index.
*/
unsigned system() const {
return systemIndex;
}
/**
* Set the system index.
*/
void system(unsigned i) {
systemIndex = i;
}
/**
* Randomize this index making sure it is not the same as any of the
* indices given as argument.
*/
void generate(const ColourIndex & c1 = ColourIndex(),
const ColourIndex & c2 = ColourIndex(),
const ColourIndex & c3 = ColourIndex());
/**
* Generate a new index making sure it is not the same as this index
* or any of the indices given as argument.
*/
ColourIndex generateNew(const ColourIndex & c1 = ColourIndex(),
const ColourIndex & c2 = ColourIndex()) const {
ColourIndex ret(system());
ret.generate(*this, c1, c2);
return ret;
}
/**
* Print function for PersistentOStrema.
*/
template <typename OS>
void print(OS & os) const {
os << index << systemIndex;
}
/**
* Read function for PersistentIStrema.
*/
template <typename IS>
void read(IS & is) {
is >> index >> systemIndex;
}
private:
/**
* The actual colour index.
*/
unsigned index;
/**
* An additional index to keep different systems separate.
*/
unsigned systemIndex;
};
}
-template <typename OS>
-OS & operator<<(OS & os, const Ariadne5::ColourIndex & c) {
+// template <typename OS>
+// OS & operator<<(OS & os, const Ariadne5::ColourIndex & c) {
+// c.print(os);
+// return os;
+// }
+
+// template <typename IS>
+// IS & operator>>(IS & is, Ariadne5::ColourIndex & c) {
+// c.read(is);
+// return is;
+// }
+
+inline std::ostream & operator<<(std::ostream & os, const Ariadne5::ColourIndex & c) {
+ c.print(os);
+ return os;
+}
+
+inline ThePEG::PersistentOStream & operator<<(ThePEG::PersistentOStream & os,
+ const Ariadne5::ColourIndex & c) {
c.print(os);
return os;
}
template <typename IS>
IS & operator>>(IS & is, Ariadne5::ColourIndex & c) {
c.read(is);
return is;
}
#endif /* Ariadne5_ColourIndex_H */
diff --git a/Cascade/DipoleState.cc b/Cascade/DipoleState.cc
--- a/Cascade/DipoleState.cc
+++ b/Cascade/DipoleState.cc
@@ -1,680 +1,682 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the DipoleState class.
//
#include "DipoleState.h"
#include "Resonance.h"
#include "ResonanceParton.h"
#include "RemnantParton.h"
#include "AriadneHandler.h"
#include "EMDipole.h"
#include "QCDDipole.h"
#include "StateDipole.h"
#include "Junction.h"
#include "PartonTraits.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/EventRecord/SubProcess.h"
#include "ThePEG/EventRecord/Step.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/PDF/PartonExtractor.h"
#include "ThePEG/PDF/PartonBinInstance.h"
#include "ThePEG/Config/algorithm.h"
#include "ThePEG/Utilities/UtilityBase.h"
#include "ThePEG/Utilities/MaxCmp.h"
#include "ThePEG/Utilities/Throw.h"
#include "ThePEG/Utilities/UtilityBase.h"
#include "ThePEG/Utilities/DebugItem.h"
#include "ThePEG/Utilities/StringUtils.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace Ariadne5;
DipoleState::DipoleState(tPPair inc): theIncoming(inc), theNe(0) {
dipindx(tcDBPtr());
parindx(tcParPtr());
}
DipoleState::~DipoleState() {}
ClonePtr DipoleState::clone() const {
return new_ptr(*this);
}
void DipoleState::setup(SubProcess & sub) {
set<tPPtr> left(sub.outgoing().begin(), sub.outgoing().end());
// First check if this is a DIS-like event.
pair<tRemParPtr,tRemParPtr> leptons = handler()->findDISLeptons(sub, *this);
pair<tRemParPtr,tRemParPtr> quarks =
handler()->findDISQuarks(leptons, sub, *this);
if ( quarks.first ) {
quarks.first->setupHard(1);
leptons.first->setupHard(1);
theRemnants.first.push_back(quarks.first);
theRemnants.first.push_back(leptons.first);
addHadronicFS(quarks.first);
addHardFS(leptons.first);
left.erase(quarks.first->orig());
left.erase(leptons.first->orig());
}
if ( quarks.second ) {
quarks.second->setupHard(-1);
leptons.second->setupHard(-1);
theRemnants.second.push_back(quarks.second);
theRemnants.second.push_back(leptons.second);
addHadronicFS(quarks.second);
addHardFS(leptons.second);
left.erase(quarks.second->orig());
left.erase(leptons.second->orig());
}
// Now setup the rest of the remnants.
tPBIPtr pb = handler()->lastXComb().partonBinInstance(sub.incoming().first);
while ( pb && pb->incoming() ) {
tRemParPtr rem = create<RemnantParton>();
rem->setup(*pb, 1);
addFS(rem);
theRemnants.first.push_back(rem);
pb = pb->incoming();
}
pb = handler()->lastXComb().partonBinInstance(sub.incoming().second);
while ( pb && pb->incoming() ) {
tRemParPtr rem = create<RemnantParton>();
rem->setup(*pb, -1);
addFS(rem);
theRemnants.second.push_back(rem);
pb = pb->incoming();
}
// After that we should identify all resonances.
tPVector resv = handler()->resonances(sub);
theResonances.resize(resv.size());
for ( int i = 0, N = resv.size(); i < N; ++i ) {
tResPtr res = create<Resonance>();
res->orig(resv[i]);
res->decaySystem(i + 1);
theResonances[i] = res;
}
for ( int i = 0, N = resv.size(); i < N; ++i ) {
tResPtr res = theResonances[i];
if ( resv[i]->parents().size() == 1 ) {
tPVector::iterator pit = find(resv, resv[i]->parents()[0]);
if ( pit != resv.end() )
res->parentResonance(theResonances[pit - resv.begin()]);
}
// Children in the final state should be of type ResonanceParton.
for ( int ic = 0, Nc = resv[i]->children().size(); ic < Nc; ++ic ) {
set<tPPtr>::iterator pit = find(left, resv[i]->children()[ic]);
if ( pit != left.end() ) {
tResParPtr rp = create<ResonanceParton>();
rp->orig(*pit);
rp->setResonance(res);
addHadronicFS(rp);
left.erase(pit);
}
}
}
// What is left is just ordinary partons.
setup(left);
// Save a pointer to the SubProcess
subprocess = &sub;
}
void DipoleState::setup(const set<tPPtr> & out) {
subprocess = tSubProPtr();
// Here we only have ordinary partons, life is simple.
for ( set<tPPtr>::iterator pit = out.begin(); pit != out.end(); ++pit ) {
tParPtr p = create<Parton>();
p->orig(*pit);
addHadronicFS(p);
}
// Now identify all QCD dipoles.
vector<tQCDPtr> dips = handler()->findQCDDipoles(*this);
active.insert(dips.begin(), dips.end());
// And the EM dipoles.
vector<tEMDipPtr> emdips = handler()->findEMDipoles(*this);
active.insert(emdips.begin(), emdips.end());
// Finally we add a StateDipole to be used by global models.
active.insert(create<StateDipole>());
sumTotalMomentum();
}
Energy DipoleState::select(Energy rhomin, Energy rhomax) {
theSelected = EmPtr();
// Energy rho = ZERO;
MaxCmp<Energy> rhosel;
for ( set<tDBPtr>::iterator it = active.begin(); it != active.end(); ++it ) {
pair<set<EmissionGenerator>::iterator, bool> ins =
generators.insert(EmissionGenerator(*it));
const EmissionGenerator & gen = *ins.first;
if ( ins.second ) gen.init();
else gen.reinit();
if ( rhosel(gen.generate(rhomin, rhomax)) && gen.emission ) {
if ( !gen.emission->geno ) gen.emission->geno = theNe + 1;
theSelected = gen.emission;
rhomin = gen.rho();
}
}
for ( BaseSet::iterator it = objects.begin(); it != objects.end(); ++it)
(**it).untouch();
if ( selected() ) emissions.push_back(selected());
untouch();
return rhosel;
}
bool DipoleState::perform() {
static DebugItem printsteps("Ariadne5::PrintSteps", 6);
touch();
if ( !selected() ) return false;
if ( printsteps )
cerr << "Ariadne5::PrintStep: Performing emission " << theNe + 1
<< " of type " << typeid(*selected()).name() << endl;
// Save four momentum before the emission.
LorentzMomentum ptot = totalMomentum();
if ( !selected()->perform() ) {
selected()->dipole->touch();
if ( printsteps )
cerr << "Ariadne5::PrintStep: Emission of type "
<< typeid(*selected()).name() << " failed" << endl;
return false;
}
// Inform other partons that an emission was performed.
for ( set<tParPtr>::const_iterator it = finalState().begin();
it != finalState().end(); ++it )
(**it).notify(*selected());
++theNe;
selected()->emno = theNe;
// Check conservation of four momentum.
Energy2 s = ptot.m2();
ptot -= sumTotalMomentum();
if( (ptot.vect().mag2() + sqr(ptot.e()) )/s > 1.0e-16)
throw MomentumException()
<< "Ariadne5::DipoleState::perform: Emission of type "
<< StringUtils::typeName(typeid(*selected()))
<< " did not conserve four momentum." << Exception::eventerror;
// Do additional consistency checks.
return selected()->failsafe ||
Current<AriadneHandler>()->checkState(*this, selected());
}
void DipoleState::fill(Step & step) const {
set<tParPtr> done;
// Determine the scale to be assigned to the produced particles.
Energy2 scale = sqr(handler()->pTCut());
if ( selected() ) scale = max(scale, sqr(selected()->rho));
// First create all the ThePEG::Particles
for ( set<tParPtr>::const_iterator it = finalState().begin();
it != finalState().end(); ++it )
if ( (**it).produceParticle() && (**it).particle() )
(**it).particle()->scale(scale);
// Then it's time to fix all colour lines.
vector<ColinePtr> colines;
for ( set<tDBPtr>::const_iterator it = active.begin();
it != active.end(); ++it )
if ( ColinePtr cl = (**it).colourLine() ) colines.push_back(cl);
// Now collect all relevant particles (ie. ell except soft
// remnants), andfind all original final state partons have actually
// radiated.
set<tPPtr> radiated;
vector<PPtr> final;
for ( set<tParPtr>::const_iterator it = hardFS().begin();
it != hardFS().end(); ++it ) {
if ( !(**it).orig() ) (**it).getOriginalParents(inserter(radiated));
if ( tPPtr p = (**it).particle() ) final.push_back(p);
}
// Now we can fix all mother-daughter relationships and add new
// particles to the step.
for ( set<tParPtr>::const_iterator it = hardFS().begin();
it != hardFS().end(); ++it )
if ( (**it).orig() && !member(radiated, (**it).orig()) )
step.setCopy((**it).orig(), (**it).particle());
else {
vector<tPPtr> parents;
(**it).getOriginalParents(inserter(parents));
step.addDecayProduct(parents.begin(), parents.end(),
(**it).particle(), false);
}
// Now add all intermediate resonances them to the step and fix up
// the parenthood.
for ( int i = 0, N = resonances().size(); i < N; ++i ) {
final.push_back(resonances()[i]->produceParticle());
step.setCopy(resonances()[i]->orig(), resonances()[i]->particle());
if ( tColinePtr cl = resonances()[i]->orig()->colourLine() )
cl->addColoured(resonances()[i]->particle());
if ( tColinePtr cl = resonances()[i]->orig()->antiColourLine() )
cl->addAntiColoured(resonances()[i]->particle());
}
for ( int i = 0, N = resonances().size(); i < N; ++i ) {
tPPtr orig = resonances()[i]->orig();
for ( int ic = 0, Nc = orig->children().size(); ic < Nc; ++ic ) {
tPPtr child = orig->children()[ic];
if ( child->next() )
step.addDecayProduct(orig->final(), child->final());
else if ( child->children().size() )
step.addDecayProduct(orig->final(), child->children().begin(),
child->children().end(), false);
}
}
if ( !subprocess ) return;
// Now start with the innermost soft remnants and go outwards and
// reextract the incoming particles.
// First skip all hard remnants.
vector<tRemParPtr>::const_iterator rit1 = remnants().first.begin();
while ( rit1 != remnants().first.end() && (**rit1).hard() ) ++rit1;
vector<tRemParPtr>::const_iterator rit2 = remnants().second.begin();
while ( rit2 != remnants().second.end() && (**rit2).hard() ) ++rit2;
PartonExtractor & pex = *(handler()->lastExtractor());
while ( rit1 != remnants().first.end() || rit2 != remnants().second.end() ) {
// If there are no soft remnants on one side oldinc=newinc is
// taken to be the colliding particle and nothing will happen on
// that side.
PPair oldinc = subprocess->incoming();
PPair newinc = subprocess->incoming();
if ( rit1 != remnants().first.end() ) {
oldinc.first = (**rit1).originalExtracted();
newinc.first = (**rit1).extracted();
}
if ( rit2 != remnants().second.end() ) {
oldinc.second = (**rit2).originalExtracted();
newinc.second = (**rit2).extracted();
}
Lorentz5Momentum p1 = newinc.first->momentum();
Lorentz5Momentum p2 = newinc.second->momentum();
// Re-extract the remnants and calculate the boost needed to put
// them on-shell.
PBIPair newbins = pex.newRemnants(oldinc, newinc, &step);
LorentzRotation tot =
pex.boostRemnants(newbins, p1, p2,
newbins.first && newbins.first->incoming(),
newbins.second && newbins.second->incoming());
// Perform the boost also for the final state.
Utilities::transform(final.begin(), final.end(), tot);
// Add the new remnants to the final state.
if ( rit1 != remnants().first.end() ) {
newinc.first->addChild(oldinc.first);
step.addIntermediate(newinc.first);
final.insert(final.end(), newbins.first->remnants().begin(),
newbins.first->remnants().end());
++rit1;
}
if ( rit2 != remnants().second.end() ) {
newinc.second->addChild(oldinc.second);
step.addIntermediate(newinc.second);
final.insert(final.end(), newbins.second->remnants().begin(),
newbins.second->remnants().end());
++rit2;
}
}
}
const Lorentz5Momentum & DipoleState::sumTotalMomentum() {
theTotalMomentum = Utilities::sumMomentum(finalState());
theHardMomentum = Utilities::sumMomentum(hardFS());
theHadronicMomentum = Utilities::sumMomentum(hadronicFS());
theTotalMomentum.rescaleMass();
theHardMomentum.rescaleMass();
theHadronicMomentum.rescaleMass();
return theTotalMomentum;
}
-double DipoleState::lambdaMeasure(Energy2 scale) const {
- double lam = 0.0;
+pair<double,int> DipoleState::lambdaMeasure(Energy2 scale) const {
+ pair<double,int> lam (0.0, 0);
for ( set<tDBPtr>::const_iterator it = activeDipoles().begin();
it != activeDipoles().end(); ++it )
if ( tQCDPtr d = dynamic_ptr_cast<tQCDPtr>(*it) ) {
- lam += log(d->sdip()/scale);
+ Energy2 m2 = d->sdip();
+ if ( m2 > scale ) lam.first += log(m2/scale);
+ ++lam.second;
}
return lam;
}
tParPtr DipoleState::create(tcPDPtr pd, tcParPtr parent, bool hfs) {
tParPtr p = create<Parton>();
p->data(pd);
if ( parent ) p->origSystem(parent->system());
if ( hfs ) addHadronicFS(p);
return p;
}
void DipoleState::forgetParton(tParPtr p) {
theHadronicFinalState.erase(p);
theHardFinalState.erase(p);
theFinalState.erase(p);
objects.erase(p);
}
void DipoleState::forgetDipole(tDBPtr d) {
active.erase(d);
objects.erase(d);
}
DipoleStatePtr DipoleState::fullclone() const {
TranslationMap trans;
DipoleStatePtr copy = preclone(trans);
copy->postclone(trans);
return copy;
}
DipoleStatePtr DipoleState::preclone(TranslationMap & trans) const {
CloneSet tocopy(objects.begin(), objects.end());
tocopy.insert(tcDipoleStatePtr(this));
CloneSet tocheck = tocopy;
while ( ! tocheck.empty() ) {
CloneSet additional;
for ( CloneSet::const_iterator it = tocheck.begin();
it != tocheck.end(); ++it )
if ( *it ) (**it).fillReferences(additional);
tocheck.clear();
for ( CloneSet::const_iterator it = additional.begin();
it != additional.end(); ++it )
if ( tocopy.insert(*it).second )
tocheck.insert(*it);
}
tocopy.erase(cDipoleStatePtr(this));
DipoleStatePtr copy = dynamic_ptr_cast<DipoleStatePtr>(clone());
trans[tcDipoleStatePtr(this)] = copy;
for ( CloneSet::const_iterator it = tocopy.begin();
it != tocopy.end(); ++it ) if ( *it ) trans[*it] = (**it).clone();
return copy;
}
void DipoleState::postclone(const TranslationMap & trans) const {
for ( TranslationMap::const_iterator it = trans.map().begin();
it != trans.map().end(); ++it ) it->second->rebind(trans);
}
void DipoleState::fillReferences(CloneSet & cs) const {
CascadeBase::fillReferences(cs);
cs.insert(theSelected);
for ( set<EmissionGenerator>::iterator it = generators.begin();
it != generators.end(); ++it )
if ( it->emission ) cs.insert(it->emission);
}
void DipoleState::rebind(const TranslationMap & trans) {
BaseSet old;
old.swap(objects);
objects.clear();
trans.translate(inserter(objects), old.begin(), old.end());
set<tParPtr> oldfs;
oldfs.swap(theFinalState);
theFinalState.clear();
trans.translate(inserter(theFinalState), oldfs.begin(), oldfs.end());
oldfs.swap(theHardFinalState);
theHardFinalState.clear();
trans.translate(inserter(theHardFinalState), oldfs.begin(), oldfs.end());
oldfs.swap(theHadronicFinalState);
theHadronicFinalState.clear();
trans.translate(inserter(theHadronicFinalState), oldfs.begin(), oldfs.end());
vector<tRemParPtr> orem;
orem.swap(theRemnants.first);
theRemnants.first.clear();
trans.translate(inserter(theRemnants.first), orem.begin(), orem.end());
orem.swap(theRemnants.second);
theRemnants.second.clear();
trans.translate(inserter(theRemnants.second), orem.begin(), orem.end());
vector<tResPtr> ores;
ores.swap(theResonances);
theResonances.clear();
trans.translate(inserter(theResonances), ores.begin(), ores.end());
set<tDBPtr> odip;
odip.swap(active);
active.clear();
trans.translate(inserter(active), odip.begin(), odip.end());
theSelected = trans.translate(theSelected);
set<EmissionGenerator> gold;
gold.swap(generators);
for ( set<EmissionGenerator>::iterator it = gold.begin();
it != gold.end(); ++ it ) {
EmissionGenerator gen(trans.translate(it->dipole));
gen.emission = trans.translate(it->emission);
generators.insert(gen);
}
dipindx.clear();
parindx.clear();
}
void DipoleState::persistentOutput(PersistentOStream & os) const {
os << subprocess << theIncoming << objects << theFinalState << theRemnants
<< theResonances
<< active << ounit(theTotalMomentum, GeV) << ounit(theHardMomentum, GeV)
<< ounit(theHadronicMomentum, GeV) << generators.size()
<< theNe << theSelected;
for ( set<EmissionGenerator>::const_iterator it = generators.begin();
it != generators.end(); ++it ) os << *it;
}
void DipoleState::persistentInput(PersistentIStream & is, int) {
int gsize;
is >> subprocess >> theIncoming >> objects >> theFinalState >> theRemnants
>> theResonances
>> active >> iunit(theTotalMomentum, GeV) >> iunit(theHardMomentum, GeV)
>> iunit(theHadronicMomentum, GeV) >> gsize >>
theNe >> theSelected;
generators.clear();
EmissionGenerator eg;
while ( gsize-- ) {
is >> eg;
generators.insert(eg);
}
}
void DipoleState::touchHadronicState() {
for ( int i = 0, N = theRemnants.first.size(); i < N; ++i )
if ( hadronicFS().find(theRemnants.first[i]) == hadronicFS().end() )
theRemnants.first[i]->touch();
for ( int i = 0, N = theRemnants.second.size(); i < N; ++i )
if ( hadronicFS().find(theRemnants.second[i]) == hadronicFS().end() )
theRemnants.second[i]->touch();
}
void DipoleState::untouchHadronicState() {
for ( int i = 0, N = theRemnants.first.size(); i < N; ++i )
if ( hadronicFS().find(theRemnants.first[i]) == hadronicFS().end() )
theRemnants.first[i]->untouch();
for ( int i = 0, N = theRemnants.second.size(); i < N; ++i )
if ( hadronicFS().find(theRemnants.second[i]) == hadronicFS().end() )
theRemnants.second[i]->untouch();
}
void DipoleState::transformHadronicState(const LorentzRotation & R) {
UtilityBase::transform(theHadronicFinalState, R);
touchHadronicState();
}
// The following static variable is needed for the type description
// system in ThePEG.
DescribeClass<DipoleState,CascadeBase>
describeAriadne5DipoleState("Ariadne5::DipoleState", "libAriadne5.so");
void DipoleState::Init() {}
pair<tQCDPtr,tQCDPtr> DipoleState::StringEnds(tQCDPtr d) {
pair<tQCDPtr,tQCDPtr> ret = make_pair(d, d);
while ( tQCDPtr dn = ret.second->next() ) {
if ( dn == d ) return ret;
ret.second = dn;
}
while ( tQCDPtr dp = ret.first->prev() ) {
if ( dp == d ) return ret;
ret.first = dp;
}
return ret;
}
void DipoleState::debugme() const {
CascadeBase::debugme();
cerr << "DipoleState:" << endl;
LorentzMomentum sum;
set<tParPtr> allpartons = finalState();
set<tDBPtr> dipoles = activeDipoles();
cerr << "> active dipoles:" << endl;
while ( !dipoles.empty() ) {
if ( tQCDPtr d = dynamic_ptr_cast<tQCDPtr>(*dipoles.begin()) ) {
dipoles.erase(d);
pair<tQCDPtr,tQCDPtr> range = StringEnds(d);
tParPtr p1 = range.first->iPart();
tParPtr p2 = range.second->oPart();
if ( p1 == p2 )
cerr << " string loop:" << endl;
else
cerr << " string: " << index(p1)
<< " ... " << index(p2) << endl;
while ( range.first ) {
range.first->iPart()->debug();
cerr << endl;
sum += range.first->iPart()->momentum();
allpartons.erase(range.first->iPart());
range.first->debug();
cerr << endl;
dipoles.erase(range.first);
if ( range.first == range.second )
range.first = tQCDPtr();
else
range.first = range.first->next();
}
if ( p1 != p2 ) {
p2->debug();
cerr << endl;
sum += p2->momentum();
allpartons.erase(p2);
}
} else {
cerr << " other dipole:" << endl;
(**dipoles.begin()).debug();
cerr << endl;
dipoles.erase(dipoles.begin());
}
}
cerr << "> rest of final state:" << endl;
while ( !allpartons.empty() ) {
(**allpartons.begin()).debug();
cerr << endl;
sum += (**allpartons.begin()).momentum();
allpartons.erase(allpartons.begin());
}
cerr << "> sum of momenta:" << setprecision(3)
<< setw(9) << ( abs(sum.x()) > MeV? sum.x(): 0.0*GeV )/GeV
<< setw(9) << ( abs(sum.y()) > MeV? sum.y(): 0.0*GeV )/GeV
<< setw(9) << ( abs(sum.z()) > MeV? sum.z(): 0.0*GeV )/GeV
<< setw(9) << sum.e()/GeV
<< setw(9) << sum.m()/GeV << endl;
if ( selected() ) {
cerr << "> selected emission:" << endl;
selected()->debug();
cerr << "selected dipole: " << index(selected()->cdipole);
cerr << endl;
}
}
void DipoleState::debugEmissions() const {
for ( unsigned i = 0; i < emissions.size(); ++i )
if ( emissions[i] ) emissions[i]->debug();
}
bool DipoleState::checkIntegrity() {
for ( set<tDBPtr>::iterator it = active.begin();
it != active.end(); ++it ) {
if( ! (*it)->checkIntegrity() ) {
return false;
}
}
return true;
}
int DipoleState::index(tcCascadeBasePtr o) const {
dipindx(tcDBPtr());
parindx(tcParPtr());
if ( dynamic_ptr_cast<tcDBPtr>(o) )
return dipindx(dynamic_ptr_cast<tcDBPtr>(o));
if ( dynamic_ptr_cast<tcParPtr>(o) )
return parindx(dynamic_ptr_cast<tcParPtr>(o));
return 0;
}
SaveDipoleState::SaveDipoleState(tDipoleStatePtr state, bool force)
: forced(force) {
if ( force ||
!( state->selected()->failsafe || state->selected()->reversible ) )
backup = state->preclone(trans);
else
backup = state;
}
tDipoleStatePtr SaveDipoleState::revert() {
static DebugItem printsteps("Ariadne5::PrintSteps", 6);
if ( printsteps )
cerr << "Ariadne5::PrintStep: Reverting emission " << backup->theNe + 1
<< " of type " << typeid(*(backup->selected())).name() << endl;
if ( forced ||
!( backup->selected()->failsafe || backup->selected()->reversible ) )
backup->postclone(trans);
else if ( backup->selected()->failsafe )
Throw<Exception>()
<< "The emitter model " << backup->selected()->model->fullName()
<< " has reported that an emission is failsafe, but the emission "
<< "failed anyway. Please contact the author to have this error "
<< "corrected." << Exception::runerror;
else if ( backup->selected()->reversible ) {
// Save four momentum before reverting.
LorentzMomentum ptot = backup->totalMomentum();
backup->selected()->revert();
Energy2 s = ptot.m2();
ptot -= backup->sumTotalMomentum();
if( (ptot.vect().mag2() + sqr(ptot.e()) )/s > 1.0e-16)
throw DipoleState::MomentumException()
<< "Ariadne5::DipoleState::perform: "
<< "Emission did not conserve four momentum."
<< Exception::eventerror;
}
backup->untouch();
return backup;
}
diff --git a/Cascade/DipoleState.h b/Cascade/DipoleState.h
--- a/Cascade/DipoleState.h
+++ b/Cascade/DipoleState.h
@@ -1,585 +1,585 @@
// -*- C++ -*-
#ifndef Ariadne5_DipoleState_H
#define Ariadne5_DipoleState_H
//
// This is the declaration of the DipoleState class.
//
#include "Ariadne/Cascade/CascadeBase.h"
#include "DipoleState.fh"
#include "DipoleBase.h"
#include "Parton.h"
#include "EmissionGenerator.h"
#include "Emission.h"
#include "RemnantParton.h"
#include "Resonance.fh"
#include "ThePEG/Utilities/ObjectIndexer.h"
namespace Ariadne5 {
using namespace ThePEG;
/**
* The DipoleState class describes a complete state of partons and
* dipoles in a Ariadne cascade at a given stage of the process.
*/
class DipoleState: public CascadeBase {
public:
/**
* A vector of CascadeBase pointers.
*/
typedef set<CascadeBasePtr> BaseSet;
/**
* A set of dipole pointers.
*/
typedef list<tDBPtr> DipoleSet;
/**
* The SaveDipoleState helper class is a friend.
*/
friend class SaveDipoleState;
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor. Optional argument is the incoming
* particles to the collision.
*/
DipoleState(tPPair inc = tPPair());
/**
* The destructor.
*/
virtual ~DipoleState();
//@}
public:
/**
* Setup this DipoleState from a SubProcess.
*/
void setup(SubProcess &);
/**
* Setup this DipoleState from a simple set of final-state particles
*/
void setup(const set<tPPtr> &);
/**
* Select a dipole. Go through the list of active DipoleBase objects
* and tell them to calculate the scale of the next emission and
* select the Emitter with largest transverse momentum. Subsequent
* calls to selected() will return the selected dipole.
*
* @param rhomin the minimum allowed evolution scale.
*
* @param pt2max the maximum allowed evolution scale.
*
* @return the generated evolution scale. If less that rhomin, no
* emission was generated and subsequent calls to selected() will
* return null.
*/
Energy select(Energy rhomin, Energy rhomax);
/**
* Perform an emission.
*
* @return false if no emission was possible.
*/
bool perform();
/**
* After the cascade is done, fill the produced partons in the
* supplied Step.
*/
void fill(Step &) const;
/** @name Simple access functions. */
//@{
/**
* The next Emission
*/
inline tEmPtr selected() const {
return theSelected;
}
/**
* Set the next Emission.
*/
inline void selected(const tEmPtr & x) {
theSelected = x;
}
/**
* The number of emissions made from this state so far.
*/
inline int nEmissions() const {
return theNe;
}
/**
* Return the colliding particles if present.
*/
tPPair incoming() const {
return theIncoming;
}
/**
* Return the final-state partons. This includes all final-state
* particles, also remnants.
*/
const set<tParPtr> & finalState() const {
return theFinalState;
}
/**
* Add a parton to the final state.
*/
void addFS(tParPtr p) {
theFinalState.insert(p);
}
/**
* Add a parton to the hard final state.
*/
void addHardFS(tParPtr p) {
theHardFinalState.insert(p);
addFS(p);
}
/**
* Add a parton to the hadronic final state.
*/
void addHadronicFS(tParPtr p) {
theHadronicFinalState.insert(p);
addHardFS(p);
}
/**
* Remove the given parton from the final state and forget it ever
* existed.
*/
void forgetParton(tParPtr p);
/**
* Remove the given dipole from the active dipoles and forget it ever
* existed.
*/
void forgetDipole(tDBPtr d);
/**
* Return the partons in the hard final state. Returns finalState()
* excluding all soft remnants.
*/
const set<tParPtr> & hardFS() const {
return theHardFinalState;
}
/**
* Return the partons in the hadronic final state excluding all soft
* and non-coloured remnants.
*/
const set<tParPtr> & hadronicFS() const {
return theHadronicFinalState;
}
/**
* Return the remnants. Are a subset of theFinalState
*/
const pair< vector<tRemParPtr>, vector<tRemParPtr> > & remnants() const {
return theRemnants;
}
/**
* Return the set of active dipoles.
*/
const set<tDBPtr> & activeDipoles() const {
return active;
}
/**
* Return massive resonances.
*/
const vector<tResPtr> & resonances() const {
return theResonances;
}
//@}
public:
/** @name Functions relating to the book-keeping of included objects. */
//@{
/**
* Create a new object to be included in this DipoleState.
*/
template <typename Class>
inline typename Ptr<Class>::pointer create() {
typedef typename Ptr<Class>::pointer PTR;
PTR obj = ptr_new<PTR>();
objects.insert(objects.end(), obj);
obj->state(this);
if ( tDBPtr d = dynamic_ptr_cast<tDBPtr>(obj) ) {
active.insert(d);
dipindx(d);
}
if ( tParPtr p = dynamic_ptr_cast<tParPtr>(obj) ) parindx(p);
return obj;
}
/**
* Create a Parton of the given type \a pd. Optionally inherit the
* system properties of the \a parent parton and insert in the
* hadronic final state if \a hfs is true.
*/
tParPtr create(tcPDPtr pd, tcParPtr parent = tcParPtr(), bool hfs = true);
/**
* Remove a Parton from the final state. (The parton will still
* exist in the DipoleState).
*/
void remove(tParPtr p) {
theFinalState.erase(p);
theHardFinalState.erase(p);
theHadronicFinalState.erase(p);
}
/**
* Clone this DipoleState. Also cloning all included objects and fixing up
* their inter-dependence.
*/
DipoleStatePtr fullclone() const;
/**
* Clone this DipoleState. Also clone all included objects but do
* not fix up their inter-dependence, ie. the cloned objects in the
* new DipoleState may still point to objects in the this. Before
* the new DipoleState can be used, its postclone() function must
* be called with the \a trans object as argument. The \a trans
* object will contain the translation map between the objects in
* the old and new DipoleState.
*/
DipoleStatePtr preclone(TranslationMap & trans) const;
/**
* Fix up the inter-dependence among the included objects in this
* DipoleState which was produced by the preclone() function. The
* same \a trans object which was used in the preclone() call must
* be given here as argument.
*/
void postclone(const TranslationMap & trans) const;
//@}
public:
/**
* Calculate the total momentum of the dipole state.
*/
const Lorentz5Momentum & sumTotalMomentum();
/**
* Return the total momentum of the dipole state. This is
* recalculated after each emission.
*/
const Lorentz5Momentum & totalMomentum() const {
return theTotalMomentum;
}
/**
* Calculate the total momentum of the hardFinalState().
*/
const Lorentz5Momentum & sumHardMomentum();
/**
* Return the total momentum of the hardFS(). This is
* recalculated after each emission.
*/
const Lorentz5Momentum & hardMomentum() const {
return theHardMomentum;
}
/**
* Return the total momentum of the hadronicFS(). This is
* recalculated after each emission.
*/
const Lorentz5Momentum & hadronicMomentum() const {
return theHadronicMomentum;
}
/**
* Return the total sting length in terms of the lambda measure
* using the given scale.
*/
- double lambdaMeasure(Energy2 scale = 1.0*GeV2) const;
+ pair<double,int> lambdaMeasure(Energy2 scale = 1.0*GeV2) const;
/**
* Transform the hadronicFS().
*/
void transformHadronicState(const LorentzRotation & R);
/**
* Touch all remnants to indicate that the hadronicFS() has changed
* collectively.
*/
void touchHadronicState();
/**
* Untouch all remnants to indicate that the hadronicFS() has
* reverted collectively.
*/
void untouchHadronicState();
/**
* Print out debugging information on std::cerr.
*/
virtual void debugme() const;
/**
* Print out more debugging information on std::cerr.
*/
void debugEmissions() const;
/**
* Check integrity of all dipoles. Return false if error is
* found.
*/
bool checkIntegrity();
/**
* Create and return an index for the given object. Only used in for
* debugging.
*/
int index(tcCascadeBasePtr o) const;
protected:
/**
* Trace a dipole to find (a piece of) string.
*/
static pair<tQCDPtr,tQCDPtr> StringEnds(tQCDPtr);
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;
/**
* 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 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 SubProcess from which this state was created (may be null).
*/
tSubProPtr subprocess;
/**
* The colliding particles in the SubProcess or 0 if none was
* present.
*/
tPPair theIncoming;
/**
* The set of all diferent objects belonging to this state.
*/
BaseSet objects;
/**
* The final state partons.
*/
set<tParPtr> theFinalState;
/**
* The hard final state partons, excluding all soft remnants.
*/
set<tParPtr> theHardFinalState;
/**
* The hadronic final state, excluding all soft and non-coloured
* remnants.
*/
set<tParPtr> theHadronicFinalState;
/**
* The remnants. Are a subset of theFinalState
*/
pair< vector<tRemParPtr>, vector<tRemParPtr> > theRemnants;
/**
* The massive resonances.
*/
vector<tResPtr> theResonances;
/**
* The total momentum of this state.
*/
Lorentz5Momentum theTotalMomentum;
/**
* The total momentum of the hardFS().
*/
Lorentz5Momentum theHardMomentum;
/**
* The total momentum of the hadronicFS().
*/
Lorentz5Momentum theHadronicMomentum;
/**
* The active Dipoles.
*/
set<tDBPtr> active;
/**
* The set of EmissionGenerators corresponding to the dipoles
* included in this state.
*/
set<EmissionGenerator> generators;
/**
* The number of emissions made in this state.
*/
int theNe;
/**
* The Emitter selected to perform the next emission.
*/
EmPtr theSelected;
/**
* The list of emissions treated in this DipoleState.
*/
vector<EmPtr> emissions;
/**
* Keep track of indices for debugging purposes.
*/
mutable ObjectIndexer<int,const DipoleBase> dipindx;
/**
* Keep track of indices for debugging purposes.
*/
mutable ObjectIndexer<int,const Parton> parindx;
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
DipoleState & operator=(const DipoleState &);
public:
/** @cond EXCEPTIONCLASSES */
/** Exception class used by DipoleState if four momentum is
* not conserved.
*/
class MomentumException: public Exception {};
/** Exception class used by DipoleState if the SubProcess was
* querried when none was available.
*/
class SubProcessException: public Exception {};
/** @endcond */
};
/**
* Helper class to be able to revert changes made to a DipoleState.
*/
class SaveDipoleState {
public:
/**
* The constructor taking a pointer to the \a state to be saved. If
* necessary (or if \a force is true) the state will be cloned.
*/
SaveDipoleState(tDipoleStatePtr state, bool force = false);
/**
* Return the translation map relating the objects in the original
* state with the ones in the backup state.
*/
const DipoleState::TranslationMap & translationMap() const {
return trans;
}
/**
* Return a copy of the original state.
*/
tDipoleStatePtr revert();
private:
/**
* The backup state.
*/
DipoleStatePtr backup;
/**
* The translation map relating the objects in the original state
* with the ones in the backup state.
*/
DipoleState::TranslationMap trans;
/**
* Flag to indicate that precloning was forced.
*/
bool forced;
};
}
#endif /* Ariadne5_DipoleState_H */
diff --git a/Cascade/EmissionGenerator.cc b/Cascade/EmissionGenerator.cc
--- a/Cascade/EmissionGenerator.cc
+++ b/Cascade/EmissionGenerator.cc
@@ -1,73 +1,76 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the EmissionGenerator class.
//
#include "EmissionGenerator.h"
#include "AriadneHandler.h"
#include "EmitterBase.h"
#include "ThePEG/Utilities/Current.h"
+#include "ThePEG/Utilities/MaxCmp.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace Ariadne5;
bool EmissionGenerator::init() const {
emitters.clear();
emission = EmPtr();
exhausted = false;
const vector<EmitterPtr> & potential = Current<AriadneHandler>()->emitters();
for ( int i = potential.size() - 1; i >= 0; --i ) {
bool ok = true;
if ( !potential[i]->canHandle(*dipole) ) continue;
list<tEmitterPtr>::iterator it = emitters.begin();
while ( it != emitters.end() ) {
if ( (**it).overrides(*potential[i], *dipole) ) {
ok = false;
break;
}
if ( potential[i]->overrides(**it, *dipole) )
it = emitters.erase(it);
else
++it;
}
if ( ok ) emitters.push_back(potential[i]);
}
return !emitters.empty();
}
bool EmissionGenerator::reinit() const {
if ( dipole->touched() ) return init();
for ( list<tEmitterPtr>::iterator it = emitters.begin();
it != emitters.end(); ++it )
if ( (**it).touched(*dipole) ) return init();
return false;
}
Energy EmissionGenerator::generate(Energy rhomin, Energy rhomax) const {
if ( emission || exhausted ) return rho();
- rhomin = max(rhomin, dipole->rhoCut());
+ // rhomin = max(rhomin, dipole->rhoCut());
+ MinCmp<Energy> mincut;
for ( list<tEmitterPtr>::iterator it = emitters.begin();
it != emitters.end(); ++it ) {
- EmPtr em = (**it).generate(*dipole, rhomin, rhomax);
- if ( em ) {
+ Energy rhocut = (**it).rhoCut();
+ mincut(rhocut);
+ EmPtr em = (**it).generate(*dipole, max(rhomin, rhocut), rhomax);
+ if ( em && em->rho > max(rhomin, rhocut) ) {
emission = em;
rhomin = em->rho;
em->dipole = dipole;
}
}
- if ( !emission && rhomin <= dipole->rhoCut() )
- exhausted = true;
+ if ( !emission && rhomin <= mincut.value() ) exhausted = true;
return rho();
}
void EmissionGenerator::persistentOutput(PersistentOStream & os) const {
os << dipole << emitters << emission << exhausted;
}
void EmissionGenerator::persistentInput(PersistentIStream & is) {
is >> dipole >> emitters >> emission >> exhausted;
}
diff --git a/Cascade/EmitterBase.cc b/Cascade/EmitterBase.cc
--- a/Cascade/EmitterBase.cc
+++ b/Cascade/EmitterBase.cc
@@ -1,359 +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 '"
<< 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");
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.",
&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/EmitterBase.h b/Cascade/EmitterBase.h
--- a/Cascade/EmitterBase.h
+++ b/Cascade/EmitterBase.h
@@ -1,320 +1,327 @@
// -*- C++ -*-
#ifndef Ariadne5_EmitterBase_H
#define Ariadne5_EmitterBase_H
//
// This is the declaration of the EmitterBase class.
//
#include "ThePEG/Handlers/HandlerBase.h"
#include "DipoleBase.h"
#include "QCDDipole.fh"
#include "ReweightBase.h"
#include "EmitterBase.fh"
#include "Emission.fh"
#include "ThePEG/Utilities/Triplet.h"
#include "ThePEG/Utilities/Current.h"
#include "AriadneHandler.h"
namespace Ariadne5 {
using namespace ThePEG;
/**
* 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.
*
* @see \ref EmitterBaseInterfaces "The interfaces"
* defined for EmitterBase.
*/
class EmitterBase: public HandlerBase {
public:
/** Convenient typedef. */
typedef Triplet<Lorentz5Momentum,Lorentz5Momentum,Lorentz5Momentum> Trip;
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
EmitterBase(bool reco = false): canReconstruct(reco), willReconstruct(reco) {}
/**
* The destructor.
*/
virtual ~EmitterBase() {}
//@}
public:
/** @name Virtual functions to be overridden by sub-classes. */
//@{
/**
* Return true if and only if this emitter can handle the given \a
* dipole.
*/
virtual bool canHandle(const DipoleBase & dipole) const = 0;
/**
* If the given \a emitter overlaps with this model for the given \a
* dipole, return true if this object should take precedence. Must
* only be called for a \a dipole for which canHandle() is true.
*/
virtual bool overrides(const EmitterBase & emitter,
DipoleBase & dipole) const = 0;
/**
* Check if objects related to the given \a dipole have been touched
* in a way such that emissions must be regenerated.
*/
virtual bool touched(const DipoleBase & dipole) const;
/**
* Generate the a phase space point for an emission corresponding to
* this model. Must only be called for a \a dipole for which
* canHandle() is true.
*/
virtual EmPtr generate(const DipoleBase & dipole,
Energy rhomin, Energy rhomax) const = 0;
/**
* Perform the \a emission previously generated.
* @return true if the emission was successful
*/
virtual bool perform(const Emission & emission) const = 0;
/**
* Reverse a previously performed emission. Sub-classes which has
* signalled that they can revert an emission but fails to do so,
* must throw a Exception::runerror.
*/
virtual void revert(const Emission & emission) const;
/**
* Return true if this emitter should be used to reconstruct
* emissions in the CKKW-L algorithm.
*/
bool reconstructor() const {
return willReconstruct;
}
/**
* Return a list of inverse emissions which this model could have
* performed to arrive at the given \a state.
*/
virtual vector<EmPtr> inverseEmissions(const DipoleState & state) const;
/**
* Check if an inverse \a emission suggested by the given \a emitter
* should rather be handled by this model.
*/
virtual bool overrideInverse(const Emission & emission) const;
/**
* Perform the inverse \a emission, previously reported by
* inverseEmissions().
* @return false of the reconstruction failed.
*/
virtual bool performInverse(const Emission &, DipoleState &) const;
+ /**
+ * Possibility to override the general non-perturbative cutoff for
+ * this process. The default is AriadneHandler::pTCut() which is
+ * typically used for QCD radiation.
+ */
+ virtual Energy rhoCut() const;
+
//@}
/** @name These functions are related to external reweighting of
* emissions and should normally not be overridden. */
//@{
/**
* Return the product of preweights from all reweighters registered
* for this model.
*/
virtual double preweight(const Emission & emission) const;
/**
* Return the product of reweights from all reweighters registered
* for this emission model.
*/
virtual double reweight(const Emission & emission) const;
/**
* Return true if any of the reweighters registered for this
* emission model says so.
*/
virtual bool finalVeto(const Emission & emission) const;
/**
* Return true if any of the reweighters registered for this
* emission model may veto in finalVeto().
*/
virtual bool hasFinalVeto() const;
//@}
/**
* Access the AriadneHandler object currently in use.
*/
static AriadneHandler & handler() {
return Current<AriadneHandler>::current();
}
/**
* Generate an squared invariant transverse momentum. The
* distribution used is \f$C\alpha_S\frac{dp_\perp^2}{p_\perp^2}\f$
* multiplied with the corresponding Sudakov formfactor. The maximum
* \f$p_\perp^2\f$ is \a pt2max and \a C is the constant. If we are
* using a running \f$\alpha_S\f$ runrdnsud() will be called
* automatically.
*/
static Energy2 rndsud(double C, Energy2 pt2max, Energy2 pt2min);
/**
* Generate an squared invariant transverse momentum. The
* distribution used is \f$C\alpha_S\frac{dp_\perp^2}{p_\perp^2}\f$
* multiplied with the corresponding Sudakov formfactor. The maximum
* \f$p_\perp^2\f$ is \a pt2max and \a C is the constant. This
* function takes care of the running of \f$\alpha_S\f$ or whatever.
*/
static Energy2 runrndsud(double C, Energy2 pt2max, Energy2 pt2min);
/**
* Check consistency of generated phase-space point for standard
* dipole variables.
*/
static bool check(double x1, double x3, double y1, double y2, double y3);
/**
* Return the invariant transverse momentum of parton \a p2
* w.r.t. partons \a p1 and \a p3.
*/
static Energy2 invPT2(tcParPtr p1, tcParPtr p2, tcParPtr p3);
/**
* Return the invariant rapidity of parton \a p2 w.r.t. partons \a
* p1 and \a p3.
*/
static double invY(tcParPtr p1, tcParPtr p2, tcParPtr p3);
/**
* Return the momenta of three particles with masses \a m1, \a m2
* and \a m3 respectively and where the first particle takes an
* energy fraction \a x1 and the third an energy fraction \a x3
* (x1+x2+x3=2). If \a nr1 is true the first particle will b along
* the positive z-axis. Conversely if \a nr3 is true the third
* particle will always be along the negative z-axis. If \a nr1 and
* \a nr3 is true, the summed squared transverse energy of the
* first and third momenta will be minimized, and if niether \a nr1
* or \a nr3 is true, \a nr1 (\a nr3) will be set to true with
* probability \f$x_{1(3)}^2/(x_1^2+x_3^2)\f$. If \a userho is true,
* the recoils will be determined by the momentum fractions rather
* than the energy fractions.
*/
static Trip getMomenta(Energy2 s, double x1, double x3,
Energy m1, Energy m2, Energy m3,
bool nr1, bool nr3, bool userho = false);
/**
* Same as
* getMomenta(Energy2,double,double,Energy,Energy,Energy,bool,bool,bool),
* but also rotate an angle phi around z-axis
*/
static Trip getMomenta(Energy2 s, double x1, double x3,
Energy m1, Energy m2, Energy m3,
bool nr1, bool nr3, double phi, bool userho = false);
/**
* Calls
* getMomenta(Energy2,double,double,Energy,Energy,Energy,bool,bool,bool)
* But also rotates the resulting momenta an angle \a phi around the
* z-axis and transforms them from the rest frame of \a p1 and \a
* p3). \a s must be the squared invariant mass of \a p1 and \a p3.
*/
static Trip 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 = false);
protected:
/**
* Exception class used if weights larger that one is encountered.
*/
struct WeightException: 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);
//@}
public:
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
// If needed, insert declarations of virtual function defined in the
// InterfacedBase class here (using ThePEG-interfaced-decl in Emacs).
private:
/**
* A list of reweighting objects which may be applied to
* emissions generated by this emission model.
*/
vector<DipoleRWPtr> theReweighters;
/**
* If true, this emitter can be used to perform inverse emissions in
* the CKKW-L algorithm.
*/
bool canReconstruct;
/**
* If true, this emitter will be used to perform inverse emissions in
* the CKKW-L algorithm.
*/
bool willReconstruct;
private:
/**
* Utility function for the interface.
*/
void setReconstruct(bool t);
/**
* Utility function for the interface.
*/
bool defReconstruct() const;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
EmitterBase & operator=(const EmitterBase &);
};
}
#endif /* Ariadne5_EmitterBase_H */
diff --git a/Cascade/Models/DipoleSwing.cc b/Cascade/Models/DipoleSwing.cc
--- a/Cascade/Models/DipoleSwing.cc
+++ b/Cascade/Models/DipoleSwing.cc
@@ -1,67 +1,68 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the FSGluonEmission class.
//
#include "DipoleSwing.h"
#include "Ariadne/Cascade/DipoleState.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace Ariadne5;
DipoleSwing::~DipoleSwing() {}
ClonePtr DipoleSwing::clone() const {
return new_ptr(*this);
}
ClonePtr DipoleSwing::fullclone() const {
return new_ptr(*this);
}
-void DipoleSwing::setup(QCDDipole & d1, QCDDipole & d2) {
+void DipoleSwing::setup(QCDDipole & d1, QCDDipole & d2, Time dt) {
dipoles = make_pair(&d1, &d2);
radiators.clear();
radiators.push_back(colourParent = d1.iPart());
radiators.push_back(antiColourParent = d1.oPart());
radiators.push_back(d2.iPart());
radiators.push_back(d2.oPart());
// partons = radiators;
// swap(partons[1], partons[3]);
geno = d1.state()->nEmissions() + 1;
index = d1.colourIndex();
+ rho = hbarc/dt;
}
void DipoleSwing::persistentOutput(PersistentOStream & os) const {
os << dipoles;
}
void DipoleSwing::persistentInput(PersistentIStream & is, int) {
is >> dipoles;
}
DescribeClass<DipoleSwing,Emission>
describeAriadne5DipoleSwing("Ariadne5::DipoleSwing", "libAriadne5.so");
void DipoleSwing::Init() {}
void DipoleSwing::debugme() const {
Emission::debugme();
cerr << "Swinging dipoles (colour index " << index << "):" << endl
<< cdipole->state()->index(dipoles.first)
<< " (partons " << cdipole->state()->index(dipoles.first->iPart())
<< " and " << cdipole->state()->index(dipoles.first->oPart())
<< " colour index " << dipoles.first->colourIndex() << ")" << endl
<< cdipole->state()->index(dipoles.second)
<< " (partons " << cdipole->state()->index(dipoles.second->iPart())
<< " and " << cdipole->state()->index(dipoles.second->oPart())
<< " colour index " << dipoles.second->colourIndex() << ")" << endl;
}
diff --git a/Cascade/Models/DipoleSwing.h b/Cascade/Models/DipoleSwing.h
--- a/Cascade/Models/DipoleSwing.h
+++ b/Cascade/Models/DipoleSwing.h
@@ -1,124 +1,124 @@
// -*- C++ -*-
#ifndef ARIADNE5_DipoleSwing_H
#define ARIADNE5_DipoleSwing_H
//
// This is the declaration of the DipoleSwing class.
//
#include "Ariadne/Cascade/Emission.h"
#include "Ariadne/Cascade/StateDipole.h"
#include "Ariadne/Cascade/QCDDipole.h"
#include "Ariadne/Cascade/DipoleState.h"
namespace Ariadne5 {
using namespace ThePEG;
/**
* The DipoleSwing class contains all information about a generated
* Swing.
*/
class DipoleSwing: public Emission {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The only relevant constructor.
*/
DipoleSwing(const EmitterBase & inmodel, const DipoleBase & indipole,
- QCDDipole & d1, QCDDipole & d2)
+ QCDDipole & d1, QCDDipole & d2, Time dt)
: Emission(inmodel, indipole) {
- setup(d1, d2);
+ setup(d1, d2, dt);
}
/**
* The deault constructor should not normally be used.
*/
DipoleSwing() {}
/**
* The destructor.
*/
virtual ~DipoleSwing();
//@}
public:
- void setup(QCDDipole & d1, QCDDipole & d2);
+ void setup(QCDDipole & d1, QCDDipole & d2, Time dt);
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
virtual ClonePtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
virtual ClonePtr fullclone() const;
//@}
public:
/**
* The the pair of dipoles that should swing.
*/
pair<tQCDPtr,tQCDPtr> dipoles;
/**
* The colour index of the dipoles that should swing.
*/
ColourIndex index;
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.
*/
DipoleSwing & operator=(const DipoleSwing &);
};
}
#endif /* ARIADNE_DipoleSwing_H */
diff --git a/Cascade/Models/DipoleSwinger.cc b/Cascade/Models/DipoleSwinger.cc
--- a/Cascade/Models/DipoleSwinger.cc
+++ b/Cascade/Models/DipoleSwinger.cc
@@ -1,347 +1,429 @@
// -*- 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/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) {}
+DipoleSwinger::DipoleSwinger(): lambda(1.0), Rmax(3.5*InvGeV*hbarc), linear(false), sizeOpt(0), theRhoCut(-1.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 )
- cerr << rat(dt1 + (i + 0.5)*(dt2 - dt1)/double(N))/rmax << endl;
+ 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;
+ }
}
-DipoleSwinger::TauRatio::TauRatio(const QCDDipole & d1, const QCDDipole & d2, Length Rmaxin)
- : d1tau2(d1.iPart(), d1.oPart()), d2tau2(d2.iPart(), d2.oPart()),
- r1tau2(d1.iPart(), d2.oPart()), r2tau2(d2.iPart(), d1.oPart()), Rmax(Rmaxin){}
+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), d2tau2(d2.iPart(), d2.oPart(), optin),
+ r1tau2(d1.iPart(), d2.oPart(), optin), r2tau2(d2.iPart(), d1.oPart(), optin),
+ 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 )
+ 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 sqr((exp(sqrt(d1tau2(dt))/Rmax) - 1.0)*(exp(sqrt(d2tau2(dt))/Rmax) - 1.0)/
- ((exp(sqrt(r1tau2(dt))/Rmax) - 1.0)*(exp(sqrt(r2tau2(dt))/Rmax) - 1.0)));
+ 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;
}
+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);
+ if ( swinglast && rhomax > 1.0*GeV ) return EmPtr();
+
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);
Time dtmax = hbarc/rhomin;
Time dtmin = hbarc/rhomax;
+ Time dtmaxcut = hbarc/rhoCut();
Time t0 = hbarc/Current<AriadneHandler>()->pTCut();
bool redoFull = dipole.state() != lastState;
lastState = dipole.state();
if ( redoFull ) cache.clear();
if ( redoFull || dipole.touched() ) lastSelected = DipSwPtr();
if ( lastSelected && ( lastSelected->dipoles.first->touched() ||
lastSelected->dipoles.second->touched() ) )
lastSelected = DipSwPtr();
if ( logme && redoFull )
generator()->log() << "DipoleSwinger: Starting new event." << endl;
if ( logme ) generator()->log()
<< "DipoleSwinger: Starting new swing search." << endl;
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 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() ||
+ if ( !sel || ( sel->dipoles.second->touched() ||
sel->dipoles.second->iPart()->touched() ||
- sel->dipoles.second->oPart()->touched() ) ) {
+ sel->dipoles.second->oPart()->touched() ||
+ sel->dipoles.second->colourIndex() != d1.colourIndex() ) ) {
redo = true;
sel = cit.first->second = DipSwPtr();
}
const vector<tQCDPtr> * secondp = &active;
int i2 = i1 + 1;
if ( !redo ) {
- if ( ti1 < 0 ) continue;
+ 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 ) {
QCDDipole & d2 = *second[i2];
if ( d1.iPart() == d2.oPart() || d2.iPart() == d1.oPart() ) {
cerr << "Bullocks! Try to swing a gluon into colour singlet!" << endl;
}
- TauRatio tauRatio(d1, d2, Rmax);
+ 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 = hbarc/sel->rho;
+ if ( sel ) dtcut = min(dtcut, hbarc/sel->rho);
do {
+ double logR = log(UseRandom::rnd());
if ( linear )
- dt += log(UseRandom::rnd())*Cinv*t0;
- else
- dt *= pow(UseRandom::rnd(), Cinv);
+ 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 overestimat swing probability: "
+ cerr << "Ooops failed to overestimate swing probability: "
<< tauRatio(dt)/ratmax << endl;
}
} while ( dt < dtcut && tauRatio(dt) < UseRandom::rnd()*ratmax );
- if ( dt < dtcut ) {
- if ( sel ) sel->setup(d1, d2);
- else sel = new_ptr(DipoleSwing(*this, dipole, d1, d2));
- sel->rho = hbarc/dt;
- }
+
+ if ( !sel ) sel = new_ptr(DipoleSwing(*this, dipole, d1, d2, dt));
+ else if ( dt < dtcut ) sel->setup(d1, d2, dt);
+
}
- cit.first->second = sel;
-
- if ( sel && ( !lastSelected || sel->rho > lastSelected->rho ) ) lastSelected = sel;
+ select(cit.first->second = sel);
+
}
}
+ if ( lastSelected->rho < rhomin ) lastSelected = DipSwPtr();
return lastSelected;
}
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);
+ 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 ( 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)
+ os << lambda << ounit(Rmax, femtometer) << oenum(linear) << sizeOpt << ounit(theRhoCut, GeV)
<< cache << lastState << lastSelected;
}
void DipoleSwinger::persistentInput(PersistentIStream & is, int) {
- is >> lambda >> iunit(Rmax, femtometer) >> ienum(linear)
+ is >> lambda >> iunit(Rmax, femtometer) >> ienum(linear) >> sizeOpt >> iunit(theRhoCut, GeV)
>> cache >> lastState >> lastSelected;
}
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*femtometer,
- true, false, Interface::lowerlim);
+ &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);
+
}
diff --git a/Cascade/Models/DipoleSwinger.h b/Cascade/Models/DipoleSwinger.h
--- a/Cascade/Models/DipoleSwinger.h
+++ b/Cascade/Models/DipoleSwinger.h
@@ -1,331 +1,406 @@
// -*- C++ -*-
#ifndef ARIADNE5_DipoleSwinger_H
#define ARIADNE5_DipoleSwinger_H
//
// This is the declaration of the DipoleSwinger class.
//
#include "Ariadne/Cascade/EmitterBase.h"
#include "DipoleSwing.h"
#include "Ariadne/Cascade/QCDDipole.h"
namespace Ariadne5 {
using namespace ThePEG;
/**
* The DipoleSwinger class implements the final-state swing method for
* colour reconections.
*
* @see \ref DipoleSwingerInterfaces "The interfaces"
* defined for DipoleSwinger.
*/
class DipoleSwinger: public EmitterBase {
public:
/**
* Convenient typedef.
*/
ThePEG_DECLARE_POINTERS(Ariadne5::DipoleSwing,DipSwPtr);
/**
* Another convenient typedef.
*/
typedef map<tcQCDPtr,DipSwPtr> CacheMap;
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
DipoleSwinger();
/**
* The destructor.
*/
virtual ~DipoleSwinger();
//@}
/** @name Virtual functions to be overridden by sub-classes. */
//@{
/**
* Return true if and only if this model can handle the given
* Emitter.
*/
virtual bool canHandle(const DipoleBase &) const;
/**
* If the given EmissionModel overlaps with this model for the given
* Emitter, return true if this model should take precedence. Must
* only be called for Emitters for which canHandle() is true.
*/
virtual bool overrides(const EmitterBase &, DipoleBase &) const;
/**
* Check if objects related to the given \a dipole have been touched
* in a way such that emissions must be regenerated.
*/
virtual bool touched(const DipoleBase & dipole) const;
/**
* Generate the a phase space point for an emission corresponding to
* this model. Must only be called for Emitters for which
* canHandle() is true.
*/
virtual EmPtr generate(const DipoleBase &, Energy rhomin, Energy rhomax) const;
/**
* Perform an emission previously generated for this Emitter. Must
* only be called for Emitters for which canHandle() is true.
* @return true if the emission was successful
*/
virtual bool perform(const Emission &) const;
/**
* Reverse a previously performed emission. Sub-classes which has
* signalled that they can revert an emission but fails to do so,
* must throw a Exception::runerror.
*/
virtual void revert(const Emission & emission) const;
+
+ /**
+ * Possibility to override the general non-perturbative cutoff for
+ * this process. The default is AriadneHandler::pTCut() which is
+ * typically used for QCD radiation.
+ */
+ virtual Energy rhoCut() const;
+
//@}
/**
* Swing the given dipoles.
*/
static void swing(tQCDPtr d1, tQCDPtr d2);
public:
/**
+ * Select the given Swing if it has the largerst scale.
+ */
+ void select(DipSwPtr sel) const {
+ if ( sel && ( !lastSelected || sel->rho > lastSelected->rho ) ) lastSelected = sel;
+ }
+
+
+ /**
* Internal helper class to keep track of distnaces between partons.
*/
struct DeltaTau2 {
/**
* Constructor taked two partons and calculates the variables
* needed to get the distance as a function of time.
*/
- DeltaTau2(tcParPtr p1, tcParPtr p2) {
+ DeltaTau2(tcParPtr p1, tcParPtr p2, int optin): sizeOpt(optin) {
LorentzDistance dx = p1->vertex() - p2->vertex();
dx2 = dx.m2();
LorentzVector<double> dp =
p1->momentum()/p1->momentum().e() - p2->momentum()/p2->momentum().e();
dp2 = dp.m2();
dpdotdx = dp*dx;
+ if ( sizeOpt == 1 ) dp2 = (p1->momentum() + p2->momentum()).m2()/GeV2;
+ pp1 = p1;
+ pp2 = p2;
}
/**
* Return distance between partons after a given time \a dt.
*/
Area dTau2(Time dt) const {
- return - dx2 - dt*2.0*dpdotdx - sqr(dt)*dp2;
+ if ( sizeOpt <= 0 )
+ return - dx2 - dt*2.0*dpdotdx - sqr(dt)*dp2;
+ else
+ return sqr(dt)*dp2;
+ }
+
+ /**
+ * Return the impact-parameter distance between partons after a
+ * given time \a dt.
+ */
+ Length db() const {
+ return sqrt(-dx2);
}
/**
* Function version of dTau2
*/
Area operator()(Time dt) const {
return dTau2(dt);
}
/**
* If the distance between the partons may become zero in the
* given time interval, return the corresponding times. If there
* are no zeros, time=0 will be returned.
*/
pair<Length,Length> zeros(Time dt1, Time dt2) const {
pair<Length,Length> ret;
Area squarg = sqr(dpdotdx) - dx2*dp2;
if ( squarg < ZERO ) return ret;
Time t0 = - (dpdotdx + sqrt(squarg))/dp2;
if ( dt1 <= t0 && t0 <= dt2 ) ret.first = t0;
t0 = - (dpdotdx - sqrt(squarg))/dp2;
if ( dt1 <= t0 && t0 <= dt2 ) ret.second = t0;
return ret;
}
/**
* Return the minimum and maximum in the given interval.
*/
pair<Area,Area> minmax(Time dt1, Time dt2) const {
pair<Area,Area> ret(dTau2(dt1),dTau2(dt2));
if ( ret.first > ret.second ) swap(ret.first, ret.second);
Time dtext = -dpdotdx/dp2;
if ( dtext >= dt2 || dt1 >= dtext ) return ret;
Area dtau2ext = dTau2(dtext);
if ( dtau2ext > ret.second ) ret.second = dtau2ext;
if ( dtau2ext < ret.first ) ret.first = dtau2ext;
return ret;
}
/**
* Return the extreme point if in the given interval.
*/
Time extreme(Time dt1, Time dt2) const {
return min(max(dt1, -dpdotdx/dp2), dt2);
}
/**
* The initial distance between the partons.
*/
Area dx2;
/**
* The distance between the momentum vectors, scaled by their energies.
*/
double dp2;
/**
+ * Different options for calculating the dipole size.
+ */
+ int sizeOpt;
+
+ /**
* The scalar product between the difference between momentum
* vectors (scaled with their energies) and the difference between
* the initial positions.
*/
Length dpdotdx;
+ /* **** ATTENTION *** Only for debugging */
+ InvEnergy2 chris(Time dt) const {
+ InvEnergy2 time = sqr(dt/hbarc);
+ Energy2 E2 = pp1->momentum().plus()*pp2->momentum().minus() +
+ pp1->momentum().minus()*pp2->momentum().plus();
+ InvEnergy x1x = pp1->vertex().x()/hbarc - pp2->vertex().x()/hbarc + time*pp1->momentum().x();
+ InvEnergy x1y = pp1->vertex().y()/hbarc - pp2->vertex().y()/hbarc + time*pp1->momentum().y();
+ InvEnergy x2x = pp1->vertex().x()/hbarc - pp2->vertex().x()/hbarc - time*pp2->momentum().x();
+ InvEnergy x2y = pp1->vertex().y()/hbarc - pp2->vertex().y()/hbarc - time*pp2->momentum().y();
+ InvEnergy2 xxScalar = x1x*x2x + x1y*x2y;
+ Energy2 ppScalar = pp1->momentum().x()*pp2->momentum().x() +
+ pp1->momentum().y()*pp2->momentum().y();
+ return sqr(time)*E2 + xxScalar - sqr(time)*ppScalar;
+ }
+
+ tcParPtr pp1, pp2;
+
};
/**
* Internal helper class to keep track of ratio of distances between
* original and reconected dipoles.
*/
struct TauRatio {
/**
* The constructor takes the original dipole pair as argument.
*/
- TauRatio(const QCDDipole & d1, const QCDDipole & d2, Length Rmaxin);
+ TauRatio(const QCDDipole & d1, const QCDDipole & d2, Length Rmaxin, int optin);
/**
* Return the swing ratio at the given time.
*/
double rat(Time dt) const;
/**
* Return the swing ratio at the given time.
*/
double operator()(Time dt) const {
return rat(dt);
}
/**
* Estimate a maximum value of the swing ratio.
*/
double maximum(Time dt1, Time dt2) const;
void plot(Time dt1, Time dt2, int N = 20) const;
/**
* The objects for calculating distances between the original and
* reconnected dipoles.
*/
DeltaTau2 d1tau2, d2tau2, r1tau2, r2tau2;
/**
* Hadronic size to regularize large dipoles.
*/
Length Rmax;
+ /**
+ * Different options for calculating the dipole size.
+ */
+ int sizeOpt;
+
+ /* **** ATTENTION *** Only for debugging */
+ void debug() const;
+ double chris(Time dt) const {
+ return d1tau2.chris(dt)*d2tau2.chris(dt)/(r1tau2.chris(dt)*r2tau2.chris(dt));
+ }
+ double srat;
+ Energy2 s12, s34, s14, s32;
+
};
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
virtual IBPtr fullclone() const;
//@}
// If needed, insert declarations of virtual function defined in the
// InterfacedBase class here (using ThePEG-interfaced-decl in Emacs).
protected:
/**
* The parameter giving the rate of swinging
*/
double lambda;
/**
* The confinement scale used to prevent swinging to too large dipoles.
*/
Length Rmax;
/**
* Should we use linear or logarithmic evolution in time?
*/
bool linear;
/**
+ * Different options for calculating the dipole size.
+ */
+ int sizeOpt;
+
+ /**
+ * Cutoff in evolution the variable, if different from the standard QCD cutoff.
+ */
+ Energy theRhoCut;
+
+ /**
* Previously calculated cached swings.
*/
mutable CacheMap cache;
/**
* A pointer to the DipoleState last treated.
*/
mutable tDipoleStatePtr lastState;
/**
* A pointer to the last selected generated swing.
*/
mutable DipSwPtr lastSelected;
private:
/**
* Helper function used by the interface.
*/
string setRmax(string);
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
DipoleSwinger & operator=(const DipoleSwinger &);
};
}
#endif /* ARIADNE5_DipoleSwinger_H */
diff --git a/Cascade/QCDDipole.cc b/Cascade/QCDDipole.cc
--- a/Cascade/QCDDipole.cc
+++ b/Cascade/QCDDipole.cc
@@ -1,131 +1,131 @@
// -*- 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());
}
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", "libArriadne5.so");
+describeAriadne5QCDDipole("Ariadne::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(this) << " "
+ << setw(3) << state()->index(iPart()) << " "
<< setw(3) << state()->index(oPart())
<< setw(10) << setprecision(3)
<< (touched()? " *": " ")
<< "[" << colourIndex() << "]";
}
bool QCDDipole::checkIntegrity() {
return DipoleBase::checkIntegrity() &&
iPart() && (!next() || next()->prev() == this) &&
oPart() && (!prev() || prev()->next() == this);
}
diff --git a/Cascade/StateDipole.cc b/Cascade/StateDipole.cc
--- a/Cascade/StateDipole.cc
+++ b/Cascade/StateDipole.cc
@@ -1,35 +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() {}
+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");
void StateDipole::Init() {}
diff --git a/DIPSY/DipoleState.cc b/DIPSY/DipoleState.cc
--- a/DIPSY/DipoleState.cc
+++ b/DIPSY/DipoleState.cc
@@ -1,1262 +1,1304 @@
// -*- 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 "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), theWFInfo(x.theWFInfo),
theWeight(x.theWeight), doTakeHistory(x.doTakeHistory), theYmax(x.theYmax),
theCollidingEnergy(x.theCollidingEnergy), theHistory(x.theHistory),
allDipoles(x.allDipoles) {
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;
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());
}
return copy;
}
void DipoleState::sortDipolesFS() {
theSwingCandidates.clear();
theSwingCandidates.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 > scale ) 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);
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 theSwingCandidates[d.colour()].push_back(& d);
}
void DipoleState::sortDipoles() {
theSwingCandidates.clear();
theSwingCandidates.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
theSwingCandidates[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) {
do {
d->colour(UseRandom::irnd(handler().nColours()));
} 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);
//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();
for ( int c=0;c < Current<DipoleEventHandler>()->nColours();c++ ) {
d1->colour(c);
d1->forceGenerateRec(ymax2);
}
d1->colour(trueColour);
foundFirstDipole = d1->swingDipole();
trueColour = d2->colour();
for ( int c=0;c < Current<DipoleEventHandler>()->nColours();c++ ) {
d2->colour(c);
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());
allDipoles.insert(otherState->allDipoles.begin(),otherState->allDipoles.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;
}
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()));
}
}
}
}
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
//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::persistentOutput(PersistentOStream & os) const {
os << ounit(thePlus, GeV) << ounit(theMinus, GeV)
<< ounit(theMinusDeficit, GeV) << theHandler << theInitialDipoles
<< theSwingCandidates << theWFInfo << theWeight << doTakeHistory
<< theYmax << ounit(theCollidingEnergy, GeV) << allDipoles;
}
void DipoleState::persistentInput(PersistentIStream & is, int) {
is >> iunit(thePlus, GeV)>> iunit(theMinus, GeV)
>> iunit(theMinusDeficit, GeV) >> theHandler >> theInitialDipoles
>> theSwingCandidates >> theWFInfo >> theWeight >> doTakeHistory
>> theYmax >> iunit(theCollidingEnergy, GeV) >> allDipoles;
}
// Static variable needed for the type description system in ThePEG.
#include "ThePEG/Utilities/DescribeClass.h"
DescribeClass<DipoleState,PersistentBase>
describeDIPSYDipoleState("DIPSY::DipoleState", "libDIPSY.so");
void DipoleState::Init() {}
diff --git a/DIPSY/DipoleState.h b/DIPSY/DipoleState.h
--- a/DIPSY/DipoleState.h
+++ b/DIPSY/DipoleState.h
@@ -1,511 +1,527 @@
// -*- C++ -*-
#ifndef DIPSY_DipoleState_H
#define DIPSY_DipoleState_H
//
// This is the declaration of the DipoleState class.
//
#include "ThePEG/Config/ThePEG.h"
#include "DipoleState.fh"
#include "Dipole.h"
#include "DipoleEventHandler.fh"
#include "WFInfo.h"
#include "DipoleXSec.h"
+#include "ThePEG/Analysis/FactoryBase.h"
+
+#ifndef LWH_AIAnalysisFactory_H
+#ifndef LWH
+#define LWH ThePEGLWH
+#endif
+#include "ThePEG/Analysis/LWH/AnalysisFactory.h"
+#endif
+
namespace DIPSY {
using namespace ThePEG;
/**
* Here is the documentation of the DipoleState class.
*/
class DipoleState: public PersistentBase {
public:
/**
* Copy FList typedef from DipoleXSec.
*/
typedef DipoleXSec::FList FList;
/**
* A String is simply a vector of colour-connected partons.
*/
typedef vector<PartonPtr> String;
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The standard constructor taking the controlling
* DipoleEventHandler as argument.
*/
inline DipoleState(const DipoleEventHandler &, WFInfoPtr wf = WFInfoPtr());
/**
* The default constructor.
*/
inline DipoleState();
/**
* The copy constructor.
*/
DipoleState(const DipoleState &);
/**
* The destructor.
*/
virtual ~DipoleState();
//@}
public:
/**
* Runs through a final state evolution checking for swings only.
*/
void swingFS(double ymin, double ymax);
/**
* Does some colour recconection for the valence partons to account for
* original 3 colour colour structure of a proton.
*/
void normaliseValenceCharge(int mode);
/**
* Makes sure the non-participating nucleons of an AA collision have the
* colour flow of the original triangles.
*/
void restoreNonparticipants();
/**
* counts and returns the number of spectating nucleons.
*/
int numberOfSpectators() const;
/**
* Makes sure the the two partons are conected by a dipole with p1 as first parton.
* returns false if it fails, and they are left not connected.
*/
bool restoreDipole(PartonPtr p1, PartonPtr p2);
/**
* Evolve this state from the given minimum to the given maximum
* rapidity, assuming there will be p- coming from the other state.
*/
void evolve(double ymin, double ymax);
/**
* Makes the state merge with another colliding state.
*/
DipoleStatePtr collide(DipoleStatePtr otherState,
const vector<FList::const_iterator> & sel,
const ImpactParameters & b);
/**
* Makes the state merge with another colliding state.
*/
DipoleStatePtr merge(DipoleStatePtr otherState);
/**
* mirrors the state in rapidity around y0.
*/
void mirror(double y0);
/**
* moves all partons and their pT according to the imparctparameter b.
*/
void translate(const ImpactParameters & b );
/**
* returns the positions of all partons in the state,
* together with the size of the largest neighbouring dipole.
*/
vector<pair<Parton::Point, InvEnergy> > points();
/**
* Checks through all partons and reabsorbs the ones which are
* considered enough gain in some kind of virtuality.
*/
void absorbSmallDipoles();
/**
* Removes all the parents of the dipoles, and sets the currently
* active dipoles as the initial ones.
**/
void makeOriginal();
/**
* returns teh average distance in rapidity of the interacting dipoles.
*/
double avYInInt() const;
/**
* Controls and couts various info about the state. Returns false
* if something is too wrong.
*/
bool diagnosis(bool print) const;
/**
* Prints the state to file.
*/
void saveGluonsToFile(double weight) const;
/**
* Returns the partons sorted in Strings.
*/
vector<DipoleState::String> strings();
/**
* Returns the active partons.
*/
list<PartonPtr> getPartons() const;
/**
* Returns the active dipoles.
*/
list<DipolePtr> getDipoles() const;
/**
* Returns all dipoles.
*/
set<DipolePtr> getAllDipoles() const {
return allDipoles;
}
/**
* Makes the state reabsorb a parton.
*/
void reabsorb(PartonPtr p);
/**
* Makes the state reabsorb a parton, and continues to absorb as
* long as the dipoles gets smaller along the colour chain.
*/
void recursiveReabsorb(PartonPtr p);
/**
* Forces one of the dipoles connected to the parton
* to immediately swing. But not with higher rapdity
* step than /a ymax1 of same colour, or /a ymax2 of
* another colour if same colour cant be found.
* /a ymax = 0 mean no limit.
*/
bool forceSwing(PartonPtr d, double ymax1, double ymax2);
/**
* Shuffles p+ and p- between the left and right part of the state
* so that the particles are really on shell. Assumes m=0 atm.
*/
void balanceMomenta();
/**
* Get the weight associated with the generation of this dipole state.
*/
inline double weight() const;
/**
* Set the weight associated with the generation of this dipole state.
*/
inline void weight(double);
/**
* Get the p+ that the original particle brought.
*/
inline Energy plus() const {
return thePlus;
}
/**
* Set the p+ that the original particle brought.
*/
inline void plus(Energy E) {
thePlus = E;
}
/**
* Get the p- that the original particle brought.
*/
inline Energy minus() const {
return theMinus;
}
/**
* Set the p- that the original particle brought.
*/
inline void minus(Energy E) {
theMinus = E;
}
/**
* Get the p- that the original particle was missing.
*/
inline Energy minusDeficit() const {
return theMinusDeficit;
}
/**
* Set if the state should save its history or not.
*/
inline void takeHistory(bool);
/**
* saves the current state into the states history, but only if
* doTakeHistory is true.
*/
inline void save();
/**
* The list of initial dipoles.
*/
inline const vector<DipolePtr> & initialDipoles() const;
/**
* Adds a dipole to the initial Dipoles.
* Mainly for testing purposes.
*/
inline void addDipole(Dipole & dip);
/**
* Get additional info about the wavefunction used to create this state.
*/
inline WFInfoPtr WFInfo() const;
/**
* Get additional info about the wavefunction used to create this state.
*/
inline const WaveFunction & wf() const;
/**
* Set additional info about the wavefunction used to create this state.
*/
inline void WFInfo(WFInfoPtr);
/**
* The controlling DipoleEventHandler.
*/
inline const DipoleEventHandler & handler() const;
/**
* Set the controlling DipoleEventHandler.
* added by CF to access from emitter.
*/
inline void handler(tcDipoleEventHandlerPtr);
/**
* Create a Dipole belonging to this state.
*/
inline tDipolePtr createDipole();
/**
* Generate a consistent colour index for the given Dipole.
*/
void generateColourIndex(tDipolePtr);
/**
* Returns all active dipoles of a certain colour.
*/
inline const vector<tDipolePtr> & swingCandidates(int) const;
/**
* adds the dipole, and all its children, to theSwingCandidates list.
* includes interacting dipoles.
*/
void sortDipoleFS(Dipole &);
/**
* Sort in colour all the dipoles originating from initialDipoles.
* includes interacting dipoles.
*/
void sortDipolesFS();
/**
* Sort in colour all the dipoles originating from initialDipoles.
* includes interacting dipoles.
*/
void sortFSDipoles();
/**
+ * Return the total lambda measure for all final state dipoles.
+ */
+ pair<double,int> lambdaMeasure(Energy2 scale = 1.0*GeV2,
+ FactoryBase::tH1DPtr histlength = 0,
+ FactoryBase::tH1DPtr histmass = 0) const;
+
+ /**
* adds the dipole, and all its children, to theSwingCandidates list.
*/
void sortDipole(Dipole &);
/**
* Sort in colour all the dipoles originating from initialDipoles.
*/
void sortDipoles();
/**
* Returns a list of all the active nonvalence partons that has not interacted.
*/
const list<PartonPtr> virtualPartons() const;
/**
* Calculates and returns the set of the loops in the state.
*/
const set< list<PartonPtr> > loops() const;
/**
* Returns the highest rapidity in any parton in the state.
*/
const double highestY() const;
/**
* Returns the highest rapidity in any parton in the state.
*/
const double lowestY() const;
/**
* Returns the rapidity the state has been evolved to.
*/
const double ymax() const;
/**
* Gets the energy the colliding state will supply.
*/
const Energy collidingEnergy() const;
/**
* Sets the energy the colliding state will supply.
*/
void collidingEnergy(Energy);
/**
* 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>
inline void extract(OutputIterator it) 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();
public:
/**
* Clone this state and all the dipoles and partons in it.
*/
DipoleStatePtr clone();
protected:
/**
* The p+ and p- that the original particle had.
*/
Energy thePlus;
Energy theMinus;
/**
* Keeps track of extra missing p- that is not reflected in the
* valence partons.
*/
Energy theMinusDeficit;
/**
* The controlling DipoleEventHandler.
*/
tcDipoleEventHandlerPtr theHandler;
/**
* The list of initial dipoles.
*/
vector<DipolePtr> theInitialDipoles;
/**
* The active dipoles sorted by colour. /CF
*/
vector< vector<tDipolePtr> > theSwingCandidates;
/**
* Additional info about the wavefunction used to create this state.
*/
WFInfoPtr theWFInfo;
/**
* The weight associated with the generation of this dipole state.
*/
double theWeight;
/**
* If the history should be saved and displayed or not.
*/
bool doTakeHistory;
/**
* The rapidity the state has been evolved to.
*/
double theYmax;
/**
* How much energy the meeting particle have.
*/
Energy theCollidingEnergy;
/**
* The history of this state.
*/
vector<DipoleStatePtr> theHistory;
/**
* The set of all dipoles belonging to this state.
*/
set<DipolePtr> allDipoles;
protected:
/**
* Exception class for badly connected dipoles.
*/
struct DipoleConnectionException: public Exception {};
/**
* Exception class for bad kinematics.
*/
struct DipoleKinematicsException: public Exception {};
/**
* Exception class for bad DGLAP checks.
*/
struct DipoleDGLAPSafeException: public Exception {};
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
DipoleState & operator=(const DipoleState &);
};
}
#include "DipoleState.icc"
#endif /* DIPSY_DipoleState_H */
diff --git a/DIPSY/FSAnalysis.cc b/DIPSY/FSAnalysis.cc
--- a/DIPSY/FSAnalysis.cc
+++ b/DIPSY/FSAnalysis.cc
@@ -1,2555 +1,2555 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the FSAnalysis class.
//
#include "FSAnalysis.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "DipoleEventHandler.h"
#include "EventFiller.h"
#include "DiffractiveEventFiller.h"
#include "ThePEG/Utilities/Current.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#ifndef LWH_AIAnalysisFactory_H
#ifndef LWH
#define LWH ThePEGLWH
#endif
#include "ThePEG/Analysis/LWH/AnalysisFactory.h"
#endif
using namespace DIPSY;
FSAnalysis::FSAnalysis() {}
FSAnalysis::~FSAnalysis() {}
pair<double, double> FSAnalysis::findCoG(vector < vector<double> > gluons) {
if ( gluons.empty() ) return make_pair(0.0, 0.0);
pair<double, double> sum = make_pair(0.0, 0.0);
for ( int i = 0; i < int(gluons.size()); i++) {
sum.first += gluons[i][1];
sum.second += gluons[i][2];
}
sum.first /= double(gluons.size());
sum.second /= double(gluons.size());
return sum;
}
double FSAnalysis::eccentricity(int n, vector < vector<double> > gluons, pair<double, double> CoG) {
return eccentricity(n, gluons, CoG, true, false);
}
double FSAnalysis::eccentricityN(int n, vector < vector<double> > gluons, pair<double, double> CoG) {
return eccentricity(n, gluons, CoG, false, false);
}
double FSAnalysis::eccentricityW(int n, vector < vector<double> > gluons, pair<double, double> CoG) {
return eccentricity(n, gluons, CoG, true, true);
}
double FSAnalysis::eccentricity(int n, vector < vector<double> > gluons, pair<double, double> CoG, bool always2, bool weighted) {
if ( n < 1 ) return 0.0;
if ( int(gluons.size()) < 2 ) return 0.0;
double avRnCos = 0.0; // <r^n cos(n phi)>
double avRnSin = 0.0; // <r^n sin(n phi)>
double avRn = 0.0; // <r^n>
int power = always2 ? 2:n;
if ( n == 1 ) power = 3;
for ( int i = 0; i < int(gluons.size()); i++) {
pair<double, double> p = make_pair(gluons[i][1] - CoG.first, gluons[i][2] - CoG.second);
double r = sqrt(sqr(p.first) + sqr(p.second));
double rn = 1.0;
for ( int j = 0; j < power; j++ ) rn *= r;
if ( weighted ) rn *= max(1.0,log(sqrt(sqr(gluons[i][3]) + sqr(gluons[i][4])))+1.0);
double phi = atan2(p.second, p.first);
avRnCos += rn*cos(n*phi);
avRnSin += rn*sin(n*phi);
avRn += rn;
}
avRnCos /= double(gluons.size());
avRnSin /= double(gluons.size());
avRn /= double(gluons.size());
return sqrt(sqr(avRnCos) + sqr(avRnSin))/avRn;
}
double FSAnalysis::participantAngle(int n, vector < vector<double> > gluons, pair<double, double> CoG) {
return participantAngle(n, gluons, CoG, true, false);
}
double FSAnalysis::participantAngleN(int n, vector < vector<double> > gluons, pair<double, double> CoG) {
return participantAngle(n, gluons, CoG, false, false);
}
double FSAnalysis::participantAngleW(int n, vector < vector<double> > gluons, pair<double, double> CoG) {
return participantAngle(n, gluons, CoG, true, true);
}
double FSAnalysis::participantAngle(int n, vector < vector<double> > gluons, pair<double, double> CoG, bool always2, bool weighted) {
if ( n < 1 ) return 0.0;
if ( int(gluons.size()) < 2 ) return 0.0;
double avRnCos = 0.0; // <r^n cos(n phi)>
double avRnSin = 0.0; // <r^n sin(n phi)>
int power = always2 ? 2:n;
if ( n == 1 ) power = 3;
for ( int i = 0; i < int(gluons.size()); i++) {
pair<double, double> p = make_pair(gluons[i][1] - CoG.first, gluons[i][2] - CoG.second);
double r = sqrt(sqr(p.first) + sqr(p.second));
double rn = 1.0;
for ( int j = 0; j < power; j++ ) rn *= r;
if ( weighted ) rn *= max(1.0,log(sqrt(sqr(gluons[i][3]) + sqr(gluons[i][4])))+1.0);
double phi = atan2(p.second, p.first);
avRnCos += rn*cos(n*phi);
avRnSin += rn*sin(n*phi);
}
avRnCos /= double(gluons.size());
avRnSin /= double(gluons.size());
return atan2(avRnSin, avRnCos)/double(n);
}
vector<double> FSAnalysis::getValues(char line[256]) {
vector<double> ret;
for( int i = 0; line[i] != '\0'; i++) {
char value[256] = "";
bool found = false;
for(int j = 0; line[i]!=' '; i++, j++) {
found = true;
value[j] = line[i];
}
if ( found ) {
ret.push_back(atof(value));
}
}
return ret;
}
pair<double, double> FSAnalysis::getB(char line[256]) {
pair<double, double> ret;
int words = 0;
for( int i = 0; line[i] != '\0'; i++) {
char value[256] = "";
bool found = false;
for(int j = 0; line[i]!=' '; i++, j++) {
found = true;
value[j] = line[i];
}
if ( found ) {
words++;
if ( words == 2 ) ret.first = atof(value);
if ( words == 3 ) ret.second = atof(value);
if ( words > 2 ) return ret;
}
}
return ret;
}
double FSAnalysis::getWeight(char line[256]) {
double ret = 0.0;
int words = 0;
for( int i = 0; line[i] != '\0'; i++) {
char value[256] = "";
bool found = false;
for(int j = 0; line[i]!=' '; i++, j++) {
found = true;
value[j] = line[i];
}
if ( found ) {
words++;
if ( words == 2 ) ret = atof(value);
if ( words > 1 ) return ret;
}
}
return ret;
}
int FSAnalysis::getNSpectators(char line[256]) {
double ret = 0;
int words = 0;
for( int i = 0; line[i] != '\0'; i++) {
char value[256] = "";
bool found = false;
for(int j = 0; line[i]!=' '; i++, j++) {
found = true;
value[j] = line[i];
}
if ( found ) {
words++;
if ( words == 5 ) ret = atoi(value);
if ( words > 4 ) return ret;
}
}
return ret;
}
vector < vector<double> > FSAnalysis::extractEvent(string filename) {
vector < vector<double> > ret;
ifstream infile(filename.c_str());
if ( !infile ) {
cout << "file " << filename << " didnt exist!! :o" << endl;
getchar();
return ret;
}
char line[256] = "";
for ( int i = 0; i < 11; i++ ) infile.getline(line,256);
while( infile.good() ) {
infile.getline(line,256);
if ( infile.gcount() < 5 ) continue;
vector<double> values = getValues(line);
ret.push_back(values);
}
infile.close();
return ret;
}
pair<double, double> FSAnalysis::extractB(string filename) {
pair<double, double> ret;
ifstream infile(filename.c_str());
if ( !infile ) {
cout << "file " << filename << " didnt exist!! :o" << endl;
getchar();
return ret;
}
char line[256] = "";
for ( int i = 0; i < 5; i++ ) infile.getline(line,256);
if( infile.good() ) {
infile.getline(line,256);
if ( infile.gcount() < 5 ) return ret;
ret = getB(line);
}
infile.close();
return ret;
}
double FSAnalysis::extractWeight(string filename) {
double ret = 0.0;
ifstream infile(filename.c_str());
if ( !infile ) {
cout << "file " << filename << " didnt exist!! :o" << endl;
getchar();
return ret;
}
char line[256] = "";
for ( int i = 0; i < 3; i++ ) infile.getline(line,256);
if( infile.good() ) {
infile.getline(line,256);
if ( infile.gcount() < 5 ) return ret;
ret = getWeight(line);
}
infile.close();
return ret;
}
int FSAnalysis::extractNSpectators(string filename) {
int ret = 0;
ifstream infile(filename.c_str());
if ( !infile ) {
cout << "file " << filename << " didnt exist!! :o" << endl;
getchar();
return ret;
}
char line[256] = "";
for ( int i = 0; i < 7; i++ ) infile.getline(line,256);
if( infile.good() ) {
infile.getline(line,256);
if ( infile.gcount() < 5 ) return ret;
ret = getNSpectators(line);
}
infile.close();
return ret;
}
void FSAnalysis::changeWeight(string filename, double factor) {
// double ret = 0.0;
// fstream infile(filename.c_str());
// cout << "changeing weight in file " << filename << endl;
// if ( !infile ) {
// cout << "file " << filename << " didnt exist!! :o" << endl;
// getchar();
// return;
// }
// char line[256] = "";
// for ( int i = 0; i < 3; i++ ) infile.getline(line,256);
// if( infile.good() ) {
// infile.getline(line,256);
// if ( infile.gcount() < 5 ) return;
// ret = getWeight(line);
// cout << "found weight " << ret;
// infile << "this is inserted text" << endl;
// infile.write("this is inserted text with put", 20);
// infile.flush();
// }
// infile.close();
// getchar();
// return;
}
void FSAnalysis::eccentricities(tEventPtr event) {
//extract the information from file
ostringstream filename;
//this determined which directories are analysed.
//for example "./LHCPbPb/LHCPbPbB" can be used to
//run the same analysis on LHC lead-lead
string name = generator()->filename();
filename << "/scratch/parton/christof/DIPSY/events/" << name << "B";
int Bbin = int ((event->number()-1)/1000);
int eventNumber = ((event->number()-1) % 1000) + 1;
filename << Bbin << Bbin+1 << "/event" << eventNumber << ".dat";
if ( int(event->number()/100) == double(event->number())/100.0 )
cout << "Analysing event " << filename.str() << endl;
vector < vector<double> > gluons = extractEvent(filename.str());
pair<double, double> Bvec = extractB(filename.str());
double B = sqrt(sqr(Bvec.first) + sqr(Bvec.second));
double W = extractWeight(filename.str());
int nSpectators = extractNSpectators(filename.str());
int nGlue = gluons.size();
//find the gluons in rapidity [-1,1]
vector<vector<double> > centralGluons;
int centralNGlue = 0;
double centralWeightedNGlue = 0.0;
for ( int i = 0; i < nGlue; i++ ) {
if ( abs(gluons[i][5]) < 1.0 ) {
centralNGlue++;
double pt2 = sqr(gluons[i][3]) + sqr(gluons[i][4]);
centralWeightedNGlue += log(max(1.0, pt2));
centralGluons.push_back(gluons[i]);
}
}
//find all gluons that do not have the valence pt only.
vector<vector<double> > touched;
for ( int i = 0; i < nGlue; i++ ) {
double pt2 = sqr(gluons[i][3]) + sqr(gluons[i][4]);
if ( pt2 > sqr(0.315) ||
pt2 < sqr(0.3) ) {
touched.push_back(gluons[i]);
}
}
//find the gluons in [-3,-1]
vector < vector<double> > participantsm3tom1;
for ( int i = 0; i < nGlue; i++ ) {
if ( abs(gluons[i][5] + 2.0) < 1.0 ) {
participantsm3tom1.push_back(gluons[i]);
}
}
//find the gluons in [1,3]
vector < vector<double> > participantsp1top3;
for ( int i = 0; i < nGlue; i++ ) {
if ( abs(gluons[i][5] - 2.0) < 1.0 ) {
participantsp1top3.push_back(gluons[i]);
}
}
histNGlue->fill(B, centralNGlue*W);
histNGlueSqr->fill(B, sqr(centralNGlue)*W);
histNGlueWeights->fill(B, W);
histNGlueSpect->fill(nSpectators, centralNGlue*W);
histNGlueSpectSqr->fill(nSpectators, sqr(centralNGlue)*W);
histNGlueSpectWeights->fill(nSpectators, W);
histNSpectator->fill(B, nSpectators*W);
histNSpectatorSqr->fill(B, sqr(nSpectators)*W);
histNSpectatorWeights->fill(B, W);
centralGlueMult += nGlue*W;
//analysis with usual central participants
pair<double, double> CoG = findCoG(centralGluons);
double Psi = atan2(Bvec.second, Bvec.first);
totalWeight += W;
if ( B < 3 ) centralWeight += W;
if ( B > 5 && B < 9 ) midWeight += W;
double e1N = eccentricityN(1, centralGluons, CoG);
double e1W = eccentricityW(1, centralGluons, CoG);
double e1 = eccentricity(1, centralGluons, CoG);
histe1->fill(nSpectators, e1*W);
histe1Weights->fill(nSpectators, W);
histe1N->fill(nSpectators, e1N*W);
histe1NWeights->fill(nSpectators, W);
histe1W->fill(nSpectators, e1W*W);
histe1WWeights->fill(nSpectators, W);
double phi1N = participantAngleN(1, centralGluons, CoG);
double phi1W = participantAngleW(1, centralGluons, CoG);
double phi1 = participantAngle(1, centralGluons, CoG);
double phiPsi1N = M_PI/2.0 - abs(fmod(M_PI - abs(M_PI - abs(phi1N - Psi)),M_PI/1.0)-M_PI/2.0);
double phiPsi1W = M_PI/2.0 - abs(fmod(M_PI - abs(M_PI - abs(phi1W - Psi)),M_PI/1.0)-M_PI/2.0);
double phiPsi1 = M_PI/2.0 - abs(fmod(M_PI - abs(M_PI - abs(phi1 - Psi)),M_PI/1.0)-M_PI/2.0);
if ( nSpectators < 294 ) {
histphi1->fill(phiPsi1, W);
if ( nSpectators < 44 ) histphi1central->fill(phiPsi1, W);
if ( nSpectators > 143 ) histphi1mid->fill(phiPsi1, W);
histphi1N->fill(phiPsi1N, W);
histphi1W->fill(phiPsi1W, W);
}
double e2N = eccentricityN(2, centralGluons, CoG);
double e2W = eccentricityW(2, centralGluons, CoG);
double e2 = eccentricity(2, centralGluons, CoG);
histe2->fill(nSpectators, e2*W);
histe2Weights->fill(nSpectators, W);
histe2N->fill(nSpectators, e2N*W);
histe2NWeights->fill(nSpectators, W);
histe2W->fill(nSpectators, e2W*W);
histe2WWeights->fill(nSpectators, W);
double phi2N = participantAngleN(2, centralGluons, CoG);
double phi2W = participantAngleW(2, centralGluons, CoG);
double phi2 = participantAngle(2, centralGluons, CoG);
double phiPsi2N = M_PI/2.0 - abs(fmod(M_PI - abs(M_PI - abs(phi2N - Psi)),M_PI/1.0)-M_PI/2.0);
double phiPsi2W = M_PI/2.0 - abs(fmod(M_PI - abs(M_PI - abs(phi2W - Psi)),M_PI/1.0)-M_PI/2.0);
double phiPsi2 = M_PI/2.0 - abs(fmod(M_PI - abs(M_PI - abs(phi2 - Psi)),M_PI/1.0)-M_PI/2.0);
if ( nSpectators < 294 ) {
histphi2->fill(phiPsi2, W);
if ( nSpectators < 44 ) histphi2central->fill(phiPsi2, W);
if ( nSpectators > 143 ) histphi2mid->fill(phiPsi2, W);
histphi2N->fill(phiPsi2N, W);
histphi2W->fill(phiPsi2W, W);
}
double e3N = eccentricityN(3, centralGluons, CoG);
double e3W = eccentricityW(3, centralGluons, CoG);
double e3 = eccentricity(3, centralGluons, CoG);
histe3->fill(nSpectators, e3*W);
histe3Weights->fill(nSpectators, W);
histe3N->fill(nSpectators, e3N*W);
histe3NWeights->fill(nSpectators, W);
histe3W->fill(nSpectators, e3W*W);
histe3WWeights->fill(nSpectators, W);
double phi3N = participantAngleN(3, centralGluons, CoG);
double phi3W = participantAngleW(3, centralGluons, CoG);
double phi3 = participantAngle(3, centralGluons, CoG);
double phiPsi3N = M_PI/3.0 - abs(fmod(M_PI - abs(M_PI - abs(phi3N - Psi)),M_PI/1.5)-M_PI/3.0);
double phiPsi3W = M_PI/3.0 - abs(fmod(M_PI - abs(M_PI - abs(phi3W - Psi)),M_PI/1.5)-M_PI/3.0);
double phiPsi3 = M_PI/3.0 - abs(fmod(M_PI - abs(M_PI - abs(phi3 - Psi)),M_PI/1.5)-M_PI/3.0);
if ( nSpectators < 294 ) {
histphi3->fill(phiPsi3, W);
if ( nSpectators < 44 ) histphi3central->fill(phiPsi3, W);
if ( nSpectators > 143 ) histphi3mid->fill(phiPsi3, W);
histphi3N->fill(phiPsi3N, W);
histphi3W->fill(phiPsi3W, W);
}
double e4N = eccentricityN(4, centralGluons, CoG);
double e4W = eccentricityW(4, centralGluons, CoG);
double e4 = eccentricity(4, centralGluons, CoG);
histe4->fill(nSpectators, e4*W);
histe4Weights->fill(nSpectators, W);
histe4N->fill(nSpectators, e4N*W);
histe4NWeights->fill(nSpectators, W);
histe4W->fill(nSpectators, e4W*W);
histe4WWeights->fill(nSpectators, W);
double phi4N = participantAngleN(4, centralGluons, CoG);
double phi4W = participantAngleW(4, centralGluons, CoG);
double phi4 = participantAngle(4, centralGluons, CoG);
double phiPsi4N = M_PI/4.0 - abs(fmod(M_PI - abs(M_PI - abs(phi4N - Psi)),M_PI/2.)-M_PI/4.0);
double phiPsi4W = M_PI/4.0 - abs(fmod(M_PI - abs(M_PI - abs(phi4W - Psi)),M_PI/2.)-M_PI/4.0);
double phiPsi4 = M_PI/4.0 - abs(fmod(M_PI - abs(M_PI - abs(phi4 - Psi)),M_PI/2.)-M_PI/4.0);
if ( nSpectators < 294 ) {
histphi4->fill(phiPsi4, W);
if ( nSpectators < 44 ) histphi4central->fill(phiPsi4, W);
if ( nSpectators > 143 ) histphi4mid->fill(phiPsi4, W);
histphi4N->fill(phiPsi4N, W);
histphi4W->fill(phiPsi4W, W);
}
double e5N = eccentricityN(5, centralGluons, CoG);
double e5W = eccentricityW(5, centralGluons, CoG);
double e5 = eccentricity(5, centralGluons, CoG);
histe5->fill(nSpectators, e5*W);
histe5Weights->fill(nSpectators, W);
histe5N->fill(nSpectators, e5N*W);
histe5NWeights->fill(nSpectators, W);
histe5W->fill(nSpectators, e5W*W);
histe5WWeights->fill(nSpectators, W);
double phi5N = participantAngleN(5, centralGluons, CoG);
double phi5W = participantAngleW(5, centralGluons, CoG);
double phi5 = participantAngle(5, centralGluons, CoG);
double phiPsi5N = M_PI/5.0 - abs(fmod(M_PI - abs(M_PI - abs(phi5N - Psi)),M_PI/2.5)-M_PI/5.0);
double phiPsi5W = M_PI/5.0 - abs(fmod(M_PI - abs(M_PI - abs(phi5W - Psi)),M_PI/2.5)-M_PI/5.0);
double phiPsi5 = M_PI/5.0 - abs(fmod(M_PI - abs(M_PI - abs(phi5 - Psi)),M_PI/2.5)-M_PI/5.0);
if ( nSpectators < 294 ) {
histphi5->fill(phiPsi5, W);
if ( nSpectators < 44 ) histphi5central->fill(phiPsi5, W);
if ( nSpectators > 143 ) histphi5mid->fill(phiPsi5, W);
histphi5N->fill(phiPsi5N, W);
histphi5W->fill(phiPsi5W, W);
}
if ( centralGluons.size() > 2 ) {
Area area = averageOverlapArea(centralGluons);
histArea->fill(nSpectators, area/sqr(femtometer)*W);
histAreaWeights->fill(nSpectators, W);
}
histe1Sqrd->fill(nSpectators, sqr(e1)*W);
histe1SqrdWeights->fill(nSpectators, W);
histe2Sqrd->fill(nSpectators, sqr(e2)*W);
histe2SqrdWeights->fill(nSpectators, W);
histe3Sqrd->fill(nSpectators, sqr(e3)*W);
histe3SqrdWeights->fill(nSpectators, W);
histe4Sqrd->fill(nSpectators, sqr(e4)*W);
histe4SqrdWeights->fill(nSpectators, W);
histe5Sqrd->fill(nSpectators, sqr(e5)*W);
histe5SqrdWeights->fill(nSpectators, W);
histe1Quad->fill(nSpectators, sqr(sqr(e1))*W);
histe1QuadWeights->fill(nSpectators, W);
histe2Quad->fill(nSpectators, sqr(sqr(e2))*W);
histe2QuadWeights->fill(nSpectators, W);
histe3Quad->fill(nSpectators, sqr(sqr(e3))*W);
histe3QuadWeights->fill(nSpectators, W);
histe4Quad->fill(nSpectators, sqr(sqr(e4))*W);
histe4QuadWeights->fill(nSpectators, W);
histe5Quad->fill(nSpectators, sqr(sqr(e5))*W);
histe5QuadWeights->fill(nSpectators, W);
//all touched partons, used for the non-evo case
pair<double, double> CoGTouched = findCoG(touched);
double e2Touched = eccentricity(2, touched, CoGTouched);
histe2Touched->fill(nSpectators, e2Touched*W);
histe2TouchedWeights->fill(nSpectators, W);
double e3Touched = eccentricity(3, touched, CoGTouched);
histe3Touched->fill(nSpectators, e3Touched*W);
histe3TouchedWeights->fill(nSpectators, W);
double e4Touched = eccentricity(4, touched, CoGTouched);
histe4Touched->fill(nSpectators, e4Touched*W);
histe4TouchedWeights->fill(nSpectators, W);
double e5Touched = eccentricity(5, touched, CoGTouched);
histe5Touched->fill(nSpectators, e5Touched*W);
histe5TouchedWeights->fill(nSpectators, W);
//all (-3,-1) partons
pair<double, double> CoGm3tom1 = findCoG(participantsm3tom1);
double e1m3tom1 = eccentricity(1, participantsm3tom1, CoGm3tom1);
histe1m3tom1->fill(nSpectators, e1m3tom1*W);
histe1m3tom1Weights->fill(nSpectators, W);
double e2m3tom1 = eccentricity(2, participantsm3tom1, CoGm3tom1);
histe2m3tom1->fill(nSpectators, e2m3tom1*W);
histe2m3tom1Weights->fill(nSpectators, W);
double e3m3tom1 = eccentricity(3, participantsm3tom1, CoGm3tom1);
histe3m3tom1->fill(nSpectators, e3m3tom1*W);
histe3m3tom1Weights->fill(nSpectators, W);
double e4m3tom1 = eccentricity(4, participantsm3tom1, CoGm3tom1);
histe4m3tom1->fill(nSpectators, e4m3tom1*W);
histe4m3tom1Weights->fill(nSpectators, W);
double e5m3tom1 = eccentricity(5, participantsm3tom1, CoGm3tom1);
histe5m3tom1->fill(nSpectators, e5m3tom1*W);
histe5m3tom1Weights->fill(nSpectators, W);
//all (1,3) partons
pair<double, double> CoGp1top3 = findCoG(participantsp1top3);
double e1p1top3 = eccentricity(1, participantsp1top3, CoGp1top3);
histe1p1top3->fill(nSpectators, e1p1top3*W);
histe1p1top3Weights->fill(nSpectators, W);
double e2p1top3 = eccentricity(2, participantsp1top3, CoGp1top3);
histe2p1top3->fill(nSpectators, e2p1top3*W);
histe2p1top3Weights->fill(nSpectators, W);
double e3p1top3 = eccentricity(3, participantsp1top3, CoGp1top3);
histe3p1top3->fill(nSpectators, e3p1top3*W);
histe3p1top3Weights->fill(nSpectators, W);
double e4p1top3 = eccentricity(4, participantsp1top3, CoGp1top3);
histe4p1top3->fill(nSpectators, e4p1top3*W);
histe4p1top3Weights->fill(nSpectators, W);
double e5p1top3 = eccentricity(5, participantsp1top3, CoGp1top3);
histe5p1top3->fill(nSpectators, e5p1top3*W);
histe5p1top3Weights->fill(nSpectators, W);
//CoG distance
double CoGdist = sqrt(sqr(CoGm3tom1.first - CoGp1top3.first) +
sqr(CoGm3tom1.second - CoGp1top3.second));
histCoGdistance->fill(CoGdist, W);
//correaltions
if ( nSpectators < 294 ) {
over100Weight += W;
histeCorr1->fill(e1m3tom1, e1p1top3, W);
histeCorr2->fill(e2m3tom1, e2p1top3, W);
histeCorr3->fill(e3m3tom1, e3p1top3, W);
histeCorr4->fill(e4m3tom1, e4p1top3, W);
histeCorr5->fill(e5m3tom1, e5p1top3, W);
}
if ( nSpectators < 294 ) {
epFepB1 += e1m3tom1*e1p1top3*W;
epF1 += e1p1top3*W;
epB1 += e1m3tom1*W;
epSqrdF1 += sqr(e1p1top3)*W;
epSqrdB1 += sqr(e1m3tom1)*W;
epFepB2 += e2m3tom1*e2p1top3*W;
epF2 += e2p1top3*W;
epB2 += e2m3tom1*W;
epSqrdF2 += sqr(e2p1top3)*W;
epSqrdB2 += sqr(e2m3tom1)*W;
if ( nSpectators < 44 ) {
over350Weight += W;
epFepB2central += e2m3tom1*e2p1top3*W;
epF2central += e2p1top3*W;
epB2central += e2m3tom1*W;
epSqrdF2central += sqr(e2p1top3)*W;
epSqrdB2central += sqr(e2m3tom1)*W;
}
if ( nSpectators > 143 ) {
over100under250Weight += W;
epFepB2mid += e2m3tom1*e2p1top3*W;
epF2mid += e2p1top3*W;
epB2mid += e2m3tom1*W;
epSqrdF2mid += sqr(e2p1top3)*W;
epSqrdB2mid += sqr(e2m3tom1)*W;
}
epFepB3 += e3m3tom1*e3p1top3*W;
epF3 += e3p1top3*W;
epB3 += e3m3tom1*W;
epSqrdF3 += sqr(e3p1top3)*W;
epSqrdB3 += sqr(e3m3tom1)*W;
epFepB4 += e4m3tom1*e4p1top3*W;
epF4 += e4p1top3*W;
epB4 += e4m3tom1*W;
epSqrdF4 += sqr(e4p1top3)*W;
epSqrdB4 += sqr(e4m3tom1)*W;
}
histe1e1p1top3->fill(nSpectators, e1m3tom1*e1p1top3*W);
histe1e1p1top3Weights->fill(nSpectators, W);
histe2e2p1top3->fill(nSpectators, e2m3tom1*e2p1top3*W);
histe2e2p1top3Weights->fill(nSpectators, W);
histe3e3p1top3->fill(nSpectators, e3m3tom1*e3p1top3*W);
histe3e3p1top3Weights->fill(nSpectators, W);
histe4e4p1top3->fill(nSpectators, e4m3tom1*e4p1top3*W);
histe4e4p1top3Weights->fill(nSpectators, W);
histe5e5p1top3->fill(nSpectators, e5m3tom1*e5p1top3*W);
histe5e5p1top3Weights->fill(nSpectators, W);
if ( nSpectators < 294 ) {
double phi1m = participantAngle(1, participantsm3tom1, CoGm3tom1);
double phi1p = participantAngle(1, participantsp1top3, CoGp1top3);
double phiDiff1 = M_PI/1.0 - abs(fmod(abs(phi1m - phi1p), 2.0*M_PI/1.0) - M_PI/1.0);
histphiCorr1->fill(phiDiff1, W);
double phi2m = participantAngle(2, participantsm3tom1, CoGm3tom1);
double phi2p = participantAngle(2, participantsp1top3, CoGp1top3);
double phiDiff2 = M_PI/2.0 - abs(fmod(abs(phi2m - phi2p), 2.0*M_PI/2.0) - M_PI/2.0);
histphiCorr2->fill(phiDiff2, W);
if ( nSpectators < 44 ) histphiCorr2central->fill(phiDiff2, W);
if ( nSpectators > 143 ) histphiCorr2mid->fill(phiDiff2, W);
double phi3m = participantAngle(3, participantsm3tom1, CoGm3tom1);
double phi3p = participantAngle(3, participantsp1top3, CoGp1top3);
double phiDiff3 = M_PI/3.0 - abs(fmod(abs(phi3m - phi3p), 2.0*M_PI/3.0) - M_PI/3.0);
histphiCorr3->fill(phiDiff3, W);
double phi4m = participantAngle(4, participantsm3tom1, CoGm3tom1);
double phi4p = participantAngle(4, participantsp1top3, CoGp1top3);
double phiDiff4 = M_PI/4.0 - abs(fmod(abs(phi4m - phi4p), 2.0*M_PI/4.0) - M_PI/4.0);
histphiCorr4->fill(phiDiff4, W);
double phi5m = participantAngle(5, participantsm3tom1, CoGm3tom1);
double phi5p = participantAngle(5, participantsp1top3, CoGp1top3);
double phiDiff5 = M_PI/5.0 - abs(fmod(abs(phi5m - phi5p), 2.0*M_PI/5.0) - M_PI/5.0);
histphiCorr5->fill(phiDiff5, W);
}
//dN/dy in centrality classes
for ( int i = 0; i < nGlue; i++ ) {
histdNdnSpectdeta->fill(nSpectators, gluons[i][5], W);
if (nSpectators < 100) histdNdeta0to100spect->fill(gluons[i][5], W);
else if (nSpectators < 200) histdNdeta100to200spect->fill(gluons[i][5], W);
else if (nSpectators < 300) histdNdeta200to300spect->fill(gluons[i][5], W);
else if (nSpectators < 400) histdNdeta300to400spect->fill(gluons[i][5], W);
}
if (nSpectators < 100) spect0to100Weight += W;
else if (nSpectators < 200) spect100to200Weight += W;
else if (nSpectators < 300) spect200to300Weight += W;
else if (nSpectators < 400) spect300to400Weight += W;
//flux tube analysis
//sort the particles in [-3,-2] and [2,3] in bins of r (using CoGTouched).
vector< vector < vector<double> > > participantsFluxMinus, participantsFluxPlus;
for ( int i = 0; i < 15; i++) {
vector < vector<double> > dummy1, dummy2;
participantsFluxMinus.push_back(dummy1);
participantsFluxPlus.push_back(dummy2);
}
for ( int i = 0; i < int(gluons.size()); i++ ) {
if ( abs(gluons[i][5] + 2.5) < 0.5 ) {
double r = sqrt(sqr(gluons[i][1] - CoGTouched.first) +
sqr(gluons[i][2] - CoGTouched.second));
if ( r < 15 )
participantsFluxMinus[int(r)].push_back(gluons[i]);
}
else if ( abs(gluons[i][5] - 2.5) < 0.5 ) {
double r = sqrt(sqr(gluons[i][1] - CoGTouched.first) +
sqr(gluons[i][2] - CoGTouched.second));
if ( r < 15 )
participantsFluxPlus[int(r)].push_back(gluons[i]);
}
}
for ( int i = 0; i < 15; i++ ) {
for ( int j = 0; j < int(participantsFluxMinus[i].size()); j++ ) {
double phi1 = atan2(participantsFluxMinus[i][j][3] - CoGTouched.second,
participantsFluxMinus[i][j][2] - CoGTouched.first);
for ( int k = 0; k < int(participantsFluxPlus[i].size()); k++ ) {
double phi2 = atan2(participantsFluxPlus[i][k][3] - CoGTouched.second,
participantsFluxPlus[i][k][2] - CoGTouched.first);
double diff = min(abs(phi1 - phi2), 2*M_PI - abs(phi1 - phi2));
histFluxTube->fill(double(i)+0.5, diff, W);
}
}
for ( double j = M_PI/100.0; j < 2.0*M_PI; j += 2.0*M_PI/100.0 ) {
histFluxTubeWeights->fill(double(i)+0.5, j, W*2.0*M_PI/100.0);
}
}
}
double FSAnalysis::reactionPlaneEccentricity(const vector<cPPtr> partons) {
const int n = partons.size();
assert(n > 0);
double xsum = 0.0;
double ysum = 0.0;
double x2sum = 0.0;
double y2sum = 0.0;
for (vector<cPPtr>::const_iterator it = partons.begin(); it !=
partons.end(); ++ it) {
cPPtr p = *it;
const double x = p->vertex().x()/femtometer;
const double y = p->vertex().y()/femtometer;
xsum += x;
ysum += y;
x2sum += sqr(x);
y2sum += sqr(y);
}
const double xave = xsum / (double)n;
const double yave = ysum / (double)n;
const double x2ave = x2sum / (double)n;
const double y2ave = y2sum / (double)n;
const double xx = x2ave - sqr(xave);
const double yy = y2ave - sqr(yave);
return (yy - xx) / (yy + xx);
}
/**
* The definition of the participant eccentricity parameter.
* PLB641 (2006) 260, Eq. 2.
*/
double FSAnalysis::participantEccentricity(const vector<cPPtr> partons) {
const int n = partons.size();
assert(n > 0);
double xsum = 0.0;
double ysum = 0.0;
double x2sum = 0.0;
double y2sum = 0.0;
double xysum = 0.0;
for (vector<cPPtr>::const_iterator it = partons.begin(); it !=
partons.end(); ++ it) {
cPPtr p = *it;
const double x = p->vertex().x()/femtometer;
const double y = p->vertex().y()/femtometer;
xsum += x;
ysum += y;
x2sum += sqr(x);
y2sum += sqr(y);
xysum += x * y;
}
const double xave = xsum / (double)n;
const double yave = ysum / (double)n;
const double x2ave = x2sum / (double)n;
const double y2ave = y2sum / (double)n;
const double xyave = xysum / (double)n;
const double xx = x2ave - sqr(xave);
const double yy = y2ave - sqr(yave);
const double xy = xyave - xave * yave;
return sqrt(sqr(yy - xx) + 4 * sqr(xy)) / (yy + xx);
}
/**
* The definition of the average overlap area.
* PRC81, 024901 (2010), Eq. 11.
*/
Area FSAnalysis::averageOverlapArea(const vector<cPPtr> partons) {
const int n = partons.size();
assert(n > 0);
double xsum = 0.0;
double ysum = 0.0;
double x2sum = 0.0;
double y2sum = 0.0;
double xysum = 0.0;
for (vector<cPPtr>::const_iterator it = partons.begin(); it !=
partons.end(); ++ it) {
cPPtr p = *it;
const double x = p->vertex().x()/femtometer;
const double y = p->vertex().y()/femtometer;
xsum += x;
ysum += y;
x2sum += sqr(x);
y2sum += sqr(y);
xysum += x * y;
}
const double xave = xsum / (double)n;
const double yave = ysum / (double)n;
const double x2ave = x2sum / (double)n;
const double y2ave = y2sum / (double)n;
const double xyave = xysum / (double)n;
const double xx = x2ave - sqr(xave);
const double yy = y2ave - sqr(yave);
const double xy = xyave - xave * yave;
if ( xx * yy - sqr(xy) < 0.0 ) return ZERO;
return 4*M_PI * sqrt(xx * yy - sqr(xy))*sqr(femtometer);
}
Area FSAnalysis::averageOverlapArea(vector < vector<double> > gluons) {
const int n = gluons.size();
assert(n > 0);
double xsum = 0.0;
double ysum = 0.0;
double x2sum = 0.0;
double y2sum = 0.0;
double xysum = 0.0;
for (int i = 0; i < n; i++) {
const double x = gluons[i][1];
const double y = gluons[i][2];
xsum += x;
ysum += y;
x2sum += sqr(x);
y2sum += sqr(y);
xysum += x * y;
}
const double xave = xsum / (double)n;
const double yave = ysum / (double)n;
const double x2ave = x2sum / (double)n;
const double y2ave = y2sum / (double)n;
const double xyave = xysum / (double)n;
const double xx = x2ave - sqr(xave);
const double yy = y2ave - sqr(yave);
const double xy = xyave - xave * yave;
if ( xx * yy - sqr(xy) < 0.0 ) return ZERO;
return 4*M_PI * sqrt(xx * yy - sqr(xy))*sqr(femtometer);
}
void FSAnalysis::v2GluonAnalyze(tEventPtr event) {
SubProPtr sub = event->primarySubProcess();
double W = event->weight();
tPVector particles = event->getFinalState();
vector<cPPtr> centrals;
int multF = 0;
for ( int i = 0; i < int(particles.size()); i++ ) {
if ( particles[i]->data().charge() != ZERO && abs(particles[i]->eta()) < 0.9 ) {
multF++;
centrals.push_back(particles[i]);
}
}
double pairs = 0.0;
double cos2 = 0.0;
for ( int i = 0; i < int(centrals.size()); i++ ) {
for ( int j = 0; j < int(centrals.size()); j++ ) {
if ( i == j ) continue;
pairs++;
cos2 += cos(2.0*(centrals[i]->momentum().phi() - centrals[j]->momentum().phi()));
}
}
if ( pairs > 0.0 ) {
cos2 /= pairs;
v2final->fill(multF, cos2*W);
v2finalWeights->fill(multF, W);
dNchFinal->fill(multF, W);
}
int pairsgap = 0;
double eliptic12 = 0.0;
for ( int i = 0; i < int(particles.size()); i++ ) {
if ( particles[i]->data().charge() != ZERO
&& particles[i]->eta() < -0.5 && particles[i]->eta() > -2.0 ) {
for ( int j = 0; j < i; j++ ) {
if ( particles[j]->data().charge() != ZERO
&& particles[j]->eta() > 0.5 && particles[j]->eta() < 2.0 ) {
pairsgap++;
Energy pix = particles[i]->momentum().x();
Energy piy = particles[i]->momentum().y();
Energy pjx = particles[j]->momentum().x();
Energy pjy = particles[j]->momentum().y();
Energy pti = sqrt(sqr(pix) + sqr(piy));
Energy ptj = sqrt(sqr(pjx) + sqr(pjy));
eliptic12 += 1.0-2.0*sqr((pix*pjy - pjx*piy)/(pti*ptj));
}
}
}
}
if ( pairsgap > 0 ) {
eliptic12 /= double(pairsgap);
v2gap->fill(multF, event->weight()*eliptic12);
}
//find gluons in [-5,5]. Should cut away the spectators.
vector<cPPtr> participants;
int multG = 0.0;
for ( int i = 0; i < int(sub->outgoing().size()); i++ ) {
if ( abs(sub->outgoing()[i]->eta()) < 5.0 ) {
multG++;
participants.push_back(sub->outgoing()[i]);
}
}
nParticipants->fill(multG, W);
averageNParticipants += multG*event->weight();
if ( multG > 2 ) {
//calculate the eccentricity and area of the participants
double RPE = reactionPlaneEccentricity(participants);
double PE = participantEccentricity(participants);
Area AOA = averageOverlapArea(participants);
RPEcc->fill(RPE, W);
PartEcc->fill(PE, W);
OverlapArea->fill(AOA/sqr(femtometer), W);
EccArea->fill(AOA/sqr(femtometer), PE*W);
AreaPart->fill(multG, AOA/sqr(femtometer)*W);
PE2->fill(multG,sqr(PE)*W);
PE4->fill(multG,sqr(sqr(PE))*W);
//calculate the square of eq 5 in the v2 paper event by event
double averageMultG = 7.6;
double averagedN = 1.5*6.2;
double dN = multG*averagedN/averageMultG;
double dNch = dN/1.5;
double eq5Sqr = sqr(PE*0.2/(1.0 + (5.8/sqr(femtometer))*AOA/dN));
v2flow->fill(dNch, eq5Sqr*W);
dNchFlow->fill(dNch, W);
density->fill(dNch, dN/(AOA/sqr(femtometer))*W);
if ( dNch > 10. && dN/1.5 < 20. ) density1020->fill(dN/(AOA/sqr(femtometer)), W);
if ( dNch > 40. && dN/1.5 < 60. ) density4060->fill(dN/(AOA/sqr(femtometer)), W);
if ( dNch > 60. ) density60plus->fill(dN/(AOA/sqr(femtometer)), W);
//and the same for v_2(4)^4
double flowquad = sqr(sqr(PE*0.2/(1.0 + (5.8/sqr(femtometer))*AOA/dN)));
v4flow->fill(dNch, flowquad*W);
if ( dN/AOA > 5.8/sqr(femtometer) ) {
v2mix->fill(dNch*1.8, eq5Sqr*W);
dNchMix->fill(dNch*1.8, W);
denseRatio->fill(dNch*1.8, W);
}
else {
v2mix->fill(multF, cos2*W);
dNchMix->fill(multF, W);
}
denseRatioWeights->fill(dNch*1.8, W);
}
else {
v2mix->fill(multF, cos2*W);
dNchMix->fill(multF, W);
}
tPVector chargedMid;
for ( int i = 0; i < int(particles.size()); i++ )
if ( particles[i]->data().charge() != ZERO && abs(particles[i]->eta()) < 0.9 )
chargedMid.push_back(particles[i]);
double quad = 0.0;
int quads = 0;
for ( int i = 0; i < int(chargedMid.size()); i++ ) {
for ( int j = 0; j < int(chargedMid.size()); j++ ) {
if ( j == i ) continue;
for ( int k = 0; k < int(chargedMid.size()); k++ ) {
if ( k == i || k == j ) continue;
for ( int l = 0; l < int(chargedMid.size()); l++ ) {
if ( l == i || l == j || l == k ) continue;
quads++;
quad += cos(2.0*(chargedMid[i]->momentum().phi() + chargedMid[j]->momentum().phi() -
chargedMid[k]->momentum().phi() - chargedMid[l]->momentum().phi()));
}
}
}
}
quad /= double(quads);
if ( quads > 0 ) {
v2quad->fill(multF, event->weight()*quad);
v2quadWeights->fill(multF, event->weight());
}
}
void FSAnalysis::analyze(tEventPtr event, long ieve, int loop, int state) {
AnalysisHandler::analyze(event, ieve, loop, state);
// exportToSPheRIO(event);
// getchar();
PPair incoming = event->incoming();
// totalWeight += event->weight();
weights->fill(log(event->weight()), 1.0);
// First go through the gluons coming directly from DIPSY
SubProPtr sub = event->primarySubProcess();
int nglue = 0;
Energy maxPT = ZERO;
Energy sumPT = ZERO;
for ( int i = 0, N = sub->outgoing().size(); i < N; ++i ) {
PPtr p = sub->outgoing()[i];
if ( p->id() == ParticleID::g ) ++nglue;
Energy pt = sqrt(sqr(p->momentum().x()) + sqr(p->momentum().y()));
DIPSYPT->fill(p->rapidity(), pt/GeV*event->weight());
if ( pt > maxPT ) maxPT = pt;
if ( abs(p->eta()) < 1.0 ) sumPT += pt;
}
DIPSYSumPT->fill(sumPT/GeV, event->weight());
ngbefore->fill(nglue, event->weight());
maxPTBefore->fill(maxPT/GeV, event->weight());
int nGlueDIPSY = nglue;
// Now find the last step before string fragmentation
int colstep = 0;
for ( int is = 0, Ns = event->primaryCollision()->steps().size(); is < Ns; ++is ) {
StepPtr step = event->primaryCollision()->steps()[is];
for ( ParticleSet::iterator it = step->particles().begin();
it != step->particles().end(); ++it ) {
PPtr p = *it;
if ( p->hasColour() ) colstep = is;
}
}
// Go through the gluons after the final state shower, before hadronisation.
StepPtr step = event->primaryCollision()->steps()[colstep];
nglue = 0;
for ( ParticleSet::iterator it = step->particles().begin();
it != step->particles().end(); ++it ) {
PPtr p = *it;
Energy pt = sqrt(sqr(p->momentum().x()) + sqr(p->momentum().y()));
if ( p->id() == ParticleID::g ) ++nglue;
secondLastPT->fill(p->rapidity(), pt/GeV*event->weight());
if ( p->id() == ParticleID::g ) {
etaDiffAriadne += event->weight()*abs(step->colourNeighbour(p)->eta() - p->eta());
NGlueAriadne += event->weight();
}
}
ngafter->fill(nglue, event->weight());
//now look at final state
bool isINEL = false;
int Ncharge = 0;
int nGamma = 0;
tPVector particles = event->getFinalState();
Energy sumET = ZERO;
for ( int i = 0; i < int(particles.size()); i++ ) {
PPtr p = particles[i];
Energy pt = sqrt(sqr(p->momentum().x()) + sqr(p->momentum().y()));
Energy Et = sqrt(sqr(p->momentum().x()) + sqr(p->momentum().y()) +sqr(p->mass()));
finalPT->fill(p->rapidity(), pt/GeV*event->weight());
finalPTeta->fill(p->eta(), pt/GeV*event->weight());
finalETeta->fill(p->eta(), Et/GeV*event->weight());
if ( p->data().charge() != ZERO ) {
chargedPT->fill(p->rapidity(), pt/GeV*event->weight());
finalChargedPTeta->fill(p->eta(), pt/GeV*event->weight());
finalNcheta->fill(p->eta(), event->weight());
chargedN->fill(p->rapidity(), event->weight());
if ( abs(particles[i]->eta()) < 1 ) {
sumET += Et;
isINEL = true;
chargedNALICE->fill(p->eta(), event->weight());
Ncharge++;
}
if ( abs(particles[i]->eta()) < 1.0 )
EtDensPHENIX += event->weight()*Et;
if ( p->eta() > 2.0 ) nGamma++;
}
}
//for the SD analysis. first find largest rapidity gap
double gapY = 0.0;
double maxGap = 0.0;
PSet ordered;
for ( int i = 0; i < int(particles.size()); i++ )
ordered.insert(particles[i]);
for ( PSet::iterator it = ordered.begin(); it != ordered.end(); it++ ) {
if ( it == ordered.begin() ) continue;
PPtr p = *it;
it--;
PPtr prev = *it;
it++;
double eta1 = p->eta();
if ( abs(p->eta()) > 1000.0 ) {
if ( p->momentum().z() > ZERO ) eta1 = 10.0;
else eta1 = -10.0;
}
double eta2 = prev->eta();
if ( abs(prev->eta()) > 1000.0 ) {
if ( prev->momentum().z() > ZERO ) eta2 = 10.0;
else eta2 = -10.0;
}
if ( eta1 - eta2 > maxGap ) {
gapY = (eta1 + eta2)/2.0;
maxGap = eta1 - eta2;
}
}
//UA4 trigger: one charged particle in 2.5 - 5.6 eta.
bool AU4SD = false;
for ( int i = 0; i < int(particles.size()); i++ ) {
PPtr p = particles[i];
if ( p->data().charge() != ZERO && p->eta() > 2.5 && p->eta() < 5.6 )
AU4SD = true;
}
if ( AU4SD ) {
AU4SDweights->fill(log(event->weight()), 1.0);
PSet X;
for ( PSet::iterator it = ordered.begin(); it != ordered.end(); it++ ) {
PPtr p = *it;
double eta = p->eta();
if ( abs(p->eta()) > 1000.0 ) {
if ( p->momentum().z() > ZERO ) eta = 10.0;
else eta = -10.0;
}
// cout << ", " << eta;
if ( eta > gapY ) X.insert(p);
}
// cout << endl;
int NchDiff = 0;
Lorentz5Momentum diffMom;
for ( PSet::iterator it = X.begin(); it != X.end(); it++ ) {
PPtr p = *it;
diffMom += p->momentum();
if ( p->data().charge() != ZERO ) NchDiff++;
}
diffMom.rescaleMass();
// cout << "weight is " << event->weight()
// << ", M_X is " << diffMom.mass()/GeV << ", <n> is " << NchDiff << endl;
// cout << "-----------------------------------------------------" << endl;
double MX = diffMom.mass()/GeV;
for ( PSet::iterator it = X.begin(); it != X.end(); it++ ) {
PPtr p = *it;
if ( p->eta() != ZERO && p->data().charge() != ZERO ) {
if ( MX < 50 ) UA4dndetaMX20->fill(p->eta(), event->weight());
else if ( MX < 70 ) UA4dndetaMX60->fill(p->eta(), event->weight());
else if ( MX < 90 ) UA4dndetaMX80->fill(p->eta(), event->weight());
else if ( MX < 110 ) UA4dndetaMX100->fill(p->eta(), event->weight());
else if ( MX < 120 ) UA4dndetaMX115->fill(p->eta(), event->weight());
else if ( MX < 160 ) UA4dndetaMX140->fill(p->eta(), event->weight());
}
}
if ( MX < 50 ) {
for ( double eta = -10+0.5*0.1; eta < 10; eta += 0.1 ) {
UA4dndetaMX20Weights->fill(eta, event->weight()*0.1);
}
} else if ( MX < 70 ) {
for ( double eta = -10+0.5*0.1; eta < 10; eta += 0.1 ) {
UA4dndetaMX60Weights->fill(eta, event->weight()*0.1);
}
} else if ( MX < 90 ) {
for ( double eta = -10+0.5*0.1; eta < 10; eta += 0.1 ) {
UA4dndetaMX80Weights->fill(eta, event->weight()*0.1);
}
} else if ( MX < 110 ) {
for ( double eta = -10+0.5*0.1; eta < 10; eta += 0.1 ) {
UA4dndetaMX100Weights->fill(eta, event->weight()*0.1);
}
} else if ( MX < 120 ) {
for ( double eta = -10+0.5*0.1; eta < 10; eta += 0.1 ) {
UA4dndetaMX115Weights->fill(eta, event->weight()*0.1);
}
} else if ( MX < 160 ) {
for ( double eta = -10+0.5*0.1; eta < 10; eta += 0.1 ) {
UA4dndetaMX140Weights->fill(eta, event->weight()*0.1);
}
}
double lnMX2 = -1000.0;
if ( MX > 0.001 ) lnMX2 = 2.0*log(MX);
SDavN->fill(lnMX2, NchDiff*event->weight());
SDavNWeights->fill(lnMX2, event->weight());
SDavN2->fill(lnMX2, sqr(NchDiff)*event->weight());
SDavN2Weights->fill(lnMX2, event->weight());
}
if ( maxGap > 3 ) { //require rapidity gap of 3 units to do SD analysis
//DipoleEventHandlerPtr eh = Current<DipoleEventHandler>().ptr();
//EventFiller & def = eh->eventFiller();
//cout << "ncascades: " << eh->eventFiller().nSubcascades() << endl;
PSet X;
for ( PSet::iterator it = ordered.begin(); it != ordered.end(); it++ ) {
PPtr p = *it;
double eta = p->eta();
if ( abs(p->eta()) > 1000.0 ) {
if ( p->momentum().z() > ZERO ) eta = 10.0;
else eta = -10.0;
}
// cout << ", " << eta;
if ( eta > gapY ) X.insert(p);
}
// cout << endl;
int NchDiff = 0;
Lorentz5Momentum diffMom;
for ( PSet::iterator it = X.begin(); it != X.end(); it++ ) {
PPtr p = *it;
diffMom += p->momentum();
if ( p->data().charge() != ZERO ) NchDiff++;
}
diffMom.rescaleMass();
// cout << "weight is " << event->weight()
// << ", M_X is " << diffMom.mass()/GeV << ", <n> is " << NchDiff << endl;
double MX = diffMom.mass()/GeV;
// if ( MX > 120 ) getchar();
double lnMX2 = -1000.0;
if ( MX > 0.001 )
lnMX2 = 2.0*log(MX);
lnMX2dist->fill(lnMX2, event->weight());
lnMX2distFrac->fill(lnMX2, event->weight());
if ( nGlueDIPSY == 0 ) lnMX2dist0->fill(lnMX2, event->weight());
if ( nGlueDIPSY == 1 ) lnMX2dist1->fill(lnMX2, event->weight());
if ( nGlueDIPSY > 1 ) lnMX2dist2->fill(lnMX2, event->weight());
for ( double y = -1.0+0.5*0.1; y < 19; y += 0.1 ) {
lnMX2distWeights->fill(y, event->weight());
lnMX2dist0Weights->fill(y, event->weight());
lnMX2dist1Weights->fill(y, event->weight());
lnMX2dist2Weights->fill(y, event->weight());
}
// cout << "gap: " << gapY-maxGap/2.0 << " to " << gapY+maxGap/2.0 << ", MX: " << MX
// << ", ln(MX^2): " << lnMX2 << ", N: " << NchDiff << endl;
//the rapidity of the X system
MXmaxY->fill(gapY + maxGap/2.0, event->weight()*MX);
MXmaxYWeights->fill(gapY + maxGap/2.0, event->weight());
MX2maxY->fill(gapY + maxGap/2.0, event->weight()*sqr(MX));
MX2maxYWeights->fill(gapY + maxGap/2.0, event->weight());
double CMS = 0.0;
if ( MX > 0.001 )
CMS = 0.5*log(diffMom.plus()/diffMom.minus());
double x = sqrt(diffMom.plus()/diffMom.minus());
SDweights->fill(log(event->weight()), 1.0);
// cout << "CMS y: " << CMS << endl;
for ( PSet::iterator it = X.begin(); it != X.end(); it++ ) {
PPtr p = *it;
SDNchdeta->fill(p->eta(), event->weight());
double y = 0.5*log(p->momentum().plus()/p->momentum().minus()) - CMS;
//boost to rest system of X
Energy plusBoost = p->momentum().plus()/x;
Energy minusBoost = p->momentum().minus()*x;
Energy eBoost = (plusBoost + minusBoost)/2.0;
Energy pzBoost = (plusBoost - minusBoost)/2.0;
Energy pT = sqrt(sqr(p->momentum().x()) + sqr(p->momentum().y()));
double etaStar = -log(tan(atan2(pT,pzBoost)/2.0));
// cout << "this particle, rel. y: " << y << ", rel. eta: " << etaStar << endl;
// cout << "pT: " << pT/GeV << ", pzBoost: " << pzBoost/GeV
// << ", mass: " << p->mass()/GeV << endl;
//dndy
if ( MX > 3.0 && MX < 8.0 && p->data().charge() != ZERO )
SDNchdyMX38->fill(y, event->weight());
if ( MX > 8.0 && MX < 15.0 && p->data().charge() != ZERO )
SDNchdyMX815->fill(y, event->weight());
if ( MX > 15.0 && MX < 30.0 && p->data().charge() != ZERO )
SDNchdyMX1530->fill(y, event->weight());
//dE/deta
if ( MX > 3.0 && MX < 8.0 )
SDdedetaMX38->fill(etaStar, eBoost/GeV*event->weight());
if ( MX > 8.0 && MX < 18.0 )
SDdedetaMX818->fill(etaStar, eBoost/GeV*event->weight());
if ( MX > 18.0 && MX < 30.0 )
SDdedetaMX1830->fill(etaStar, eBoost/GeV*event->weight());
}
if ( MX > 3.0 && MX < 8.0 ) {
for ( double y = -10+0.5*0.1; y < 10; y += 0.1 ) {
SDNchdyMX38Weights->fill(y, event->weight());
}
for ( double eta = -10+0.5*0.1; eta < 10; eta += 0.1 ) {
SDdedetaMX38Weights->fill(eta, event->weight());
}
}
if ( MX > 8.0 && MX < 15.0 ) {
for ( double y = -10+0.5*0.1; y < 10; y += 0.1 ) {
SDNchdyMX815Weights->fill(y, event->weight());
}
}
if ( MX > 8.0 && MX < 18.0 ) {
for ( double eta = -10+0.5*0.1; eta < 10; eta += 0.1 ) {
SDdedetaMX818Weights->fill(eta, event->weight());
}
}
if ( MX > 15.0 && MX < 30.0 ) {
for ( double y = -10+0.5*0.1; y < 10; y += 0.1 ) {
SDNchdyMX1530Weights->fill(y, event->weight());
}
}
if ( MX > 18.0 && MX < 30.0 ) {
for ( double eta = -10+0.5*0.1; eta < 10; eta += 0.1 ) {
SDdedetaMX1830Weights->fill(eta, event->weight());
}
}
// SDavN->fill(lnMX2, NchDiff*event->weight());
// SDavNWeights->fill(lnMX2, event->weight());
// SDavN2->fill(lnMX2, sqr(NchDiff)*event->weight());
// SDavN2Weights->fill(lnMX2, event->weight());
}
finalSumET->fill(sumET/GeV, event->weight());
if ( isINEL ) {
INEL += event->weight();
chargeMultALICE->fill(Ncharge, event->weight());
}
//track the 2D energy density in a central rapidity slice
sub = event->primarySubProcess();
for ( int i = 0, N = sub->outgoing().size(); i < N; ++i ) {
PPtr p = sub->outgoing()[i];
if ( p->rapidity() < -1.0 || p->rapidity() > 1.0 ) continue;
Energy E = sqrt(sqr(p->momentum().x()) + sqr(p->momentum().y()) + sqr(p->momentum().z()) +sqr(p->mass()));
double x1 = p->vertex().x()/femtometer;
double x2 = p->vertex().y()/femtometer;
test2D->fill(x1, x2, E/GeV*event->weight());
test2DWeights->fill(x1, x2, event->weight());
}
- v2GluonAnalyze(event);
+ // v2GluonAnalyze(event);
// eccentricities(event);
// saveGluonsToFile(event);
}
void FSAnalysis::saveGluonsToFile(tEventPtr event) {
string filename = generator()->filename();
//set up outfile
ostringstream os;
os << "events/" << filename << "/event" << event->number() << ".dat";
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 impact parameter.
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;
outfile << "impact_parameter(fm):" << " " << bx << " " << by << endl;
SubProPtr sub = event->primarySubProcess();
outfile << "number_of_particles:" << " " <<sub->outgoing().size() << endl << endl;
outfile << "number of spectating nucleons: " << numberOfSpectators(event) << 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, N = sub->outgoing().size(); i < N; ++i ) {
PPtr p = sub->outgoing()[i];
outfile << p->number() << " "
<< p->vertex().x()/femtometer << " "
<< p->vertex().y()/femtometer << " "
<< p->momentum().x()/GeV << " "
<< p->momentum().y()/GeV << " "
<< p->eta() << " ";
if ( event->primaryCollision()->steps()[0]->colourNeighbour(p) )
outfile << event->primaryCollision()->steps()[0]->colourNeighbour(p)->number() << " ";
else outfile << -1 << " ";
if ( event->primaryCollision()->steps()[0]->antiColourNeighbour(p) )
outfile << event->primaryCollision()->steps()[0]->antiColourNeighbour(p)->number() << " ";
else outfile << -1 << " ";
outfile << endl;
}
outfile.close();
cout << "printed gluons to file " << "events/" << filename << "/event" << event->number()
<< ".dat" << endl;
}
void FSAnalysis::exportToSPheRIO(tEventPtr event) {
string filename = generator()->filename();
//set up outfile
ostringstream os;
os << "SPheRIO/" << filename << "/event" << event->number() << ".dat";
ofstream outfile (os.str().c_str());
PPair incoming = event->incoming();
//Energy
outfile << (incoming.first->momentum().t() + incoming.first->momentum().t())/GeV << endl;
//nuclei info CALL WF SOMEHOW!! FIX!!
int targetN = 79;
int targetA = 197;
int projectileN = 79;
int projectileA = 197;
outfile << targetN << " " << targetA << endl;
outfile << projectileN << " " << projectileA << endl;
//print impact parameter.
LorentzPoint p1 = incoming.first->vertex();
LorentzPoint p2 = incoming.second->vertex();
double bx = (p1-p2).x()/femtometer;
double by = (p1-p2).y()/femtometer;
outfile << bx << " " << by << endl;
//set up output matrix
int xBins = 25;
double xMin = -10.0;
double xMax = 10.0;
double xBinSize = (xMax-xMin)/double(xBins);
int yBins = 25;
double yMin = -10.0;
double yMax = 10.0;
double yBinSize = (yMax-yMin)/double(yBins);
int zBins = 25;
double zMin = -10.0;
double zMax = 10.0;
double zBinSize = (zMax-zMin)/double(zBins);
vector<double> bin(23, 0.0);
vector<vector<double> > xline(xBins, bin);
vector<vector<vector<double> > > xyPlane(yBins, xline);
vector<vector<vector<vector<double> > > > theMatrix(zBins, xyPlane);
//the transverse length the particles are streamed
Length freeStream = 1.0*femtometer;
//fill the matrix
tPVector particles = event->getFinalState();
for ( int i = 0; i < int(particles.size()); i++ ) {
PPtr p = particles[i];
Lorentz5Momentum q = p->momentum();
//free stream
Length deltaX = freeStream*p->momentum().x()/
sqrt(sqr(p->momentum().x())+sqr(p->momentum().y()));
Length deltaY = freeStream*p->momentum().y()/
sqrt(sqr(p->momentum().x())+sqr(p->momentum().y()));
double x = (p->vertex().x()+deltaX)/femtometer;
double y = (p->vertex().y()+deltaY)/femtometer;
double z = p->eta();
int xBin = int((x-xMin)/xBinSize);
if ( xBin < 0 || xBin > xBins-1 ) continue;
int yBin = int((y-yMin)/yBinSize);
if ( yBin < 0 || yBin > yBins-1 ) continue;
int zBin = int((z-zMin)/zBinSize);
if ( zBin < 0 || zBin > zBins-1 ) continue;
//T00, T01, ..., T33
theMatrix[xBin][yBin][zBin][3] += q.t()/GeV; //T00
theMatrix[xBin][yBin][zBin][4] += q.x()/GeV;
theMatrix[xBin][yBin][zBin][5] += q.y()/GeV;
theMatrix[xBin][yBin][zBin][6] += q.z()/GeV;
theMatrix[xBin][yBin][zBin][7] += q.x()/GeV; //T10
theMatrix[xBin][yBin][zBin][8] += q.x()*q.x()/q.t()/GeV;
theMatrix[xBin][yBin][zBin][9] += q.x()*q.y()/q.t()/GeV;
theMatrix[xBin][yBin][zBin][10] += q.x()*q.z()/q.t()/GeV;
theMatrix[xBin][yBin][zBin][11] += q.y()/GeV; //T20
theMatrix[xBin][yBin][zBin][12] += q.y()*q.x()/q.t()/GeV;
theMatrix[xBin][yBin][zBin][13] += q.y()*q.y()/q.t()/GeV;
theMatrix[xBin][yBin][zBin][14] += q.y()*q.z()/q.t()/GeV;
theMatrix[xBin][yBin][zBin][15] += q.z()/GeV; //T30
theMatrix[xBin][yBin][zBin][16] += q.z()*q.x()/q.t()/GeV;
theMatrix[xBin][yBin][zBin][17] += q.z()*q.y()/q.t()/GeV;
theMatrix[xBin][yBin][zBin][18] += q.z()*q.z()/q.t()/GeV;
//energy density
theMatrix[xBin][yBin][zBin][19] += q.t()/(xBinSize*yBinSize*zBinSize)/GeV;
}
outfile << "1 1 1" << endl;
outfile << xBins << " " << yBins << " " << zBins << endl;
outfile << xMin << " " << xMax << " "
<< yMin << " " << yMax << " "
<< zMin << " " << zMax << " " << endl;
outfile << endl;
for ( int i = 0; i < int(xBins); i++ ) {
for ( int j = 0; j < int(yBins); j++ ) {
for ( int k = 0; k < int(zBins); k++ ) {
theMatrix[i][j][k][0] = xMin + xBinSize*(double(i)+0.5);
theMatrix[i][j][k][1] = yMin + yBinSize*(double(j)+0.5);
theMatrix[i][j][k][2] = zMin + zBinSize*(double(k)+0.5);
if ( theMatrix[i][j][k][3] != 0.0 ) {
double E = theMatrix[i][j][k][3];
double px = theMatrix[i][j][k][4];
double py = theMatrix[i][j][k][5];
double pz = theMatrix[i][j][k][6];
theMatrix[i][j][k][20] = px/E;
theMatrix[i][j][k][21] = py/E;
theMatrix[i][j][k][22] = pz/E;
}
for (int l = 0; l < int(theMatrix[i][j][k].size()); l++) {
outfile << theMatrix[i][j][k][l] << " ";
}
outfile << endl;
}
}
}
outfile.close();
cout << "printed gluons to file " << "events/" << filename << "/event"
<< event->number() << ".dat" << endl;
}
int FSAnalysis::numberOfSpectators(tEventPtr event) {
SubProPtr sub = event->primarySubProcess();
vector<cPPtr> unTouched;
for ( int i = 0; i < int(sub->outgoing().size()); i++ ) {
if ( sub->outgoing()[i]->momentum().perp() < 0.47*GeV &&
sub->outgoing()[i]->momentum().perp() > 0.46*GeV ) {
unTouched.push_back(sub->outgoing()[i]);
}
}
int nSpectators = 0;
for ( int i = 0, N = unTouched.size(); i < N; ++i ) {
//check if third colour neigbour is itself, then spectator.
cPPtr p = unTouched[i];
cPPtr p1 = event->primaryCollision()->steps()[0]->colourNeighbour(p);
cPPtr p2 = event->primaryCollision()->steps()[0]->colourNeighbour(p1);
cPPtr p3 = event->primaryCollision()->steps()[0]->colourNeighbour(p2);
if ( p3 == p ) nSpectators++;
}
return nSpectators/3;
}
LorentzRotation FSAnalysis::transform(tEventPtr event) const {
return LorentzRotation();
// Return the Rotation to the frame in which you want to perform the analysis.
}
void FSAnalysis::analyze(const tPVector & particles) {
AnalysisHandler::analyze(particles);
// Calls analyze() for each particle.
}
void FSAnalysis::analyze(tPPtr) {}
IBPtr FSAnalysis::clone() const {
return new_ptr(*this);
}
IBPtr FSAnalysis::fullclone() const {
return new_ptr(*this);
}
void FSAnalysis::doinitrun() {
AnalysisHandler::doinitrun();
histogramFactory().initrun();
histogramFactory().registerClient(this);
epsRP = histogramFactory().createHistogram1D
("epsRP",200,-0.0,1.0);
epsPart = histogramFactory().createHistogram1D
("epsPart",200,-0.0,1.0);
epsPartOver20 = histogramFactory().createHistogram1D
("epsPartOver20",200,-0.0,1.0);
epsPartOver40 = histogramFactory().createHistogram1D
("epsPartOver40",200,-0.0,1.0);
mult12 = histogramFactory().createHistogram1D
("mult12",200,-0.5,199.5);
weights = histogramFactory().createHistogram1D
("weights",200,-30.0,5.0);
SDweights = histogramFactory().createHistogram1D
("SDweights",200,-20.0,20.0);
AU4SDweights = histogramFactory().createHistogram1D
("AU4SDweights",200,-20.0,20.0);
SDavN = histogramFactory().createHistogram1D
("SDavN",30, 0.0, 10.0);
SDavNWeights = histogramFactory().createHistogram1D
("SDavNWeights",30, 0.0, 10.0);
SDavN2 = histogramFactory().createHistogram1D
("SDavN2",30, 0.0, 10.0);
SDavN2Weights = histogramFactory().createHistogram1D
("SDavN2Weights",30, 0.0, 10.0);
ngbefore = histogramFactory().createHistogram1D
("ngbefore",100,-0.5,99.5);
ngafter = histogramFactory().createHistogram1D
("ngafter",100,-0.5,99.5);
DIPSYPT = histogramFactory().createHistogram1D
("DIPSYPT",200,-10.0,10.0);
finalPT = histogramFactory().createHistogram1D
("finalPT",200,-10.0,10.0);
finalPTeta = histogramFactory().createHistogram1D
("finalPTeta",200,-10.0,10.0);
finalChargedPTeta = histogramFactory().createHistogram1D
("finalChargedPTeta",200,-10.0,10.0);
finalETeta = histogramFactory().createHistogram1D
("finalETeta",200,-10.0,10.0);
finalNcheta = histogramFactory().createHistogram1D
("finalNcheta",200,-10.0,10.0);
lnMX2dist = histogramFactory().createHistogram1D
("lnMX2dist",200,-1.0,19.0);
lnMX2distFrac = histogramFactory().createHistogram1D
("lnMX2distFrac",200,-1.0,19.0);
lnMX2distWeights = histogramFactory().createHistogram1D
("lnMX2distWeights",200,-1.0,19.0);
lnMX2dist0 = histogramFactory().createHistogram1D
("lnMX2dist0",200,-1.0,19.0);
lnMX2dist0Weights = histogramFactory().createHistogram1D
("lnMX2dist0Weights",200,-1.0,19.0);
lnMX2dist1 = histogramFactory().createHistogram1D
("lnMX2dist1",200,-1.0,19.0);
lnMX2dist1Weights = histogramFactory().createHistogram1D
("lnMX2dist1Weights",200,-1.0,19.0);
lnMX2dist2 = histogramFactory().createHistogram1D
("lnMX2dist2",200,-1.0,19.0);
lnMX2dist2Weights = histogramFactory().createHistogram1D
("lnMX2dist2Weights",200,-1.0,19.0);
SDNchdeta = histogramFactory().createHistogram1D
("SDNchdeta",200,-10.0,10.0);
MXmaxY = histogramFactory().createHistogram1D
("MXmaxY",200,-10.0,10.0);
MXmaxYWeights = histogramFactory().createHistogram1D
("MXmaxYWeights",200,-10.0,10.0);
MX2maxY = histogramFactory().createHistogram1D
("MX2maxY",200,-10.0,10.0);
MX2maxYWeights = histogramFactory().createHistogram1D
("MX2maxYWeights",200,-10.0,10.0);
//UA4
UA4dndetaMX20 = histogramFactory().createHistogram1D
("UA4dndetaMX20",200,-10.0,10.0);
UA4dndetaMX20Weights = histogramFactory().createHistogram1D
("UA4dndetaMX20Weights",200,-10.0,10.0);
UA4dndetaMX60 = histogramFactory().createHistogram1D
("UA4dndetaMX60",200,-10.0,10.0);
UA4dndetaMX60Weights = histogramFactory().createHistogram1D
("UA4dndetaMX60Weights",200,-10.0,10.0);
UA4dndetaMX80 = histogramFactory().createHistogram1D
("UA4dndetaMX80",200,-10.0,10.0);
UA4dndetaMX80Weights = histogramFactory().createHistogram1D
("UA4dndetaMX80Weights",200,-10.0,10.0);
UA4dndetaMX100 = histogramFactory().createHistogram1D
("UA4dndetaMX100",200,-10.0,10.0);
UA4dndetaMX100Weights = histogramFactory().createHistogram1D
("UA4dndetaMX100Weights",200,-10.0,10.0);
UA4dndetaMX115 = histogramFactory().createHistogram1D
("UA4dndetaMX115",200,-10.0,10.0);
UA4dndetaMX115Weights = histogramFactory().createHistogram1D
("UA4dndetaMX115Weights",200,-10.0,10.0);
UA4dndetaMX140 = histogramFactory().createHistogram1D
("UA4dndetaMX140",200,-10.0,10.0);
UA4dndetaMX140Weights = histogramFactory().createHistogram1D
("UA4dndetaMX140Weights",200,-10.0,10.0);
SDNchdyMX38 = histogramFactory().createHistogram1D
("SDNchdyMX38",200,-10.0,10.0);
SDNchdyMX815 = histogramFactory().createHistogram1D
("SDNchdyMX815",200,-10.0,10.0);
SDNchdyMX1530 = histogramFactory().createHistogram1D
("SDNchdyMX1530",200,-10.0,10.0);
SDNchdyMX38Weights = histogramFactory().createHistogram1D
("SDNchdyMX38Weights",200,-10.0,10.0);
SDNchdyMX815Weights = histogramFactory().createHistogram1D
("SDNchdyMX815Weights",200,-10.0,10.0);
SDNchdyMX1530Weights = histogramFactory().createHistogram1D
("SDNchdyMX1530Weights",200,-10.0,10.0);
SDdedetaMX38 = histogramFactory().createHistogram1D
("SDdedetaMX38",200,-10.0,10.0);
SDdedetaMX818 = histogramFactory().createHistogram1D
("SDdedetaMX818",200,-10.0,10.0);
SDdedetaMX1830 = histogramFactory().createHistogram1D
("SDdedetaMX1830",200,-10.0,10.0);
SDdedetaMX38Weights = histogramFactory().createHistogram1D
("SDdedetaMX38Weights",200,-10.0,10.0);
SDdedetaMX818Weights = histogramFactory().createHistogram1D
("SDdedetaMX818Weights",200,-10.0,10.0);
SDdedetaMX1830Weights = histogramFactory().createHistogram1D
("SDdedetaMX1830Weights",200,-10.0,10.0);
secondLastPT = histogramFactory().createHistogram1D
("secondLastPT",200,-10.0,10.0);
etaDiffAriadne = 0.0;
NGlueAriadne = 0.0;
chargedPT = histogramFactory().createHistogram1D
("chargedPT",200,-10.0,10.0);
chargedN = histogramFactory().createHistogram1D
("chargedN",200,-10.0,10.0);
chargedNALICE = histogramFactory().createHistogram1D
("chargedNALICE",10,-1.0,1.0);
INEL = 0.0;
EtDensPHENIX = ZERO;
totalWeight = 0.0;
centralWeight = 0.0;
midWeight = 0.0;
over100Weight = 0.0;
over100under250Weight = 0.0;
over350Weight = 0.0;
chargeMultALICE = histogramFactory().createHistogram1D
("chargeMultALICE",101,-0.5,100.5);
maxPTBefore = histogramFactory().createHistogram1D
("maxPTBefore",200,0.0,100.0);
DIPSYSumPT = histogramFactory().createHistogram1D
("DIPSYSumPT",200,0.0,100.0);
finalSumET = histogramFactory().createHistogram1D
("finalSumET",200,0.0,100.0);
//v2
nParticipants = histogramFactory().createHistogram1D
("nParticipants",200,-1.0,199.5);
RPEcc = histogramFactory().createHistogram1D
("RPEcc",200,-1.0,1.0);
PartEcc = histogramFactory().createHistogram1D
("PartEcc",200,-1.0,1.0);
OverlapArea = histogramFactory().createHistogram1D
("OverlapArea",200,0.0,10.0);
EccArea = histogramFactory().createHistogram1D
("EccArea",200,0.0,10.0);
AreaPart = histogramFactory().createHistogram1D
("AreaPart",200,-1.0,199.5);
PE2 = histogramFactory().createHistogram1D
("PE2",200,-1.0,199.5);
PE4 = histogramFactory().createHistogram1D
("PE4",200,-1.0,199.5);
v2flow = histogramFactory().createHistogram1D
("v2flow",200, -1.0, 199.5);
v4flow = histogramFactory().createHistogram1D
("v4flow",200, -1.0, 199.5);
dNchFlow = histogramFactory().createHistogram1D
("dNchFlow",200, -1.0, 199.5);
v2mix = histogramFactory().createHistogram1D
("v2mix",200, -1.0, 199.5);
dNchMix = histogramFactory().createHistogram1D
("dNchMix",200, -1.0, 199.5);
v2final = histogramFactory().createHistogram1D
("v2final",200, -1.0, 199.5);
v2finalWeights = histogramFactory().createHistogram1D
("v2finalWeights",200, -1.0, 199.5);
dNchFinal = histogramFactory().createHistogram1D
("dNchFinal",200, -1.0, 199.5);
denseRatio = histogramFactory().createHistogram1D
("denseRatio",200, -1.0, 199.5);
denseRatioWeights = histogramFactory().createHistogram1D
("denseRatioWeights",200, -1.0, 199.5);
density = histogramFactory().createHistogram1D
("density",200, -1.0, 199.5);
density1020 = histogramFactory().createHistogram1D
("density1020",200, -1.0, 199.5);
density4060 = histogramFactory().createHistogram1D
("density4060",200, -1.0, 199.5);
density60plus = histogramFactory().createHistogram1D
("density60plus",200, -1.0, 199.5);
v2quad = histogramFactory().createHistogram1D
("v2quad",200, -1.0, 199.5);
v2quadWeights = histogramFactory().createHistogram1D
("v2quadWeights",200, -1.0, 199.5);
v2gap = histogramFactory().createHistogram1D
("v2gap",200, -1.0, 199.5);
test2D = histogramFactory().createHistogram2D
("test2D",150, -10.0, 20.0, 100, -10.0, 10.0);
test2DWeights = histogramFactory().createHistogram2D
("test2DWeights",150, -20.0, 10.0, 100, -10.0, 10.0);
averageNParticipants = 0.0;
//end v2
//eccentricities
centralGlueMult = 0.0;
histNGlue = histogramFactory().createHistogram1D
("nGlue",100, 0.0, 20.0);
histNGlueSqr = histogramFactory().createHistogram1D
("nGlueSqr",100, 0.0, 20.0);
histNGlueWeights = histogramFactory().createHistogram1D
("nGlueWeights",100, 0.0, 20.0);
histNGlueSpect = histogramFactory().createHistogram1D
("nGlueSpect",100, 0.0, 500.0);
histNGlueSpectSqr = histogramFactory().createHistogram1D
("nGlueSpectSqr",100, 0.0, 500.0);
histNGlueSpectWeights = histogramFactory().createHistogram1D
("nGlueSpectWeights",100, 0.0, 500.0);
histNSpectator = histogramFactory().createHistogram1D
("nSpectator",100, 0.0, 20.0);
histNSpectatorSqr = histogramFactory().createHistogram1D
("nSpectatorSqr",100, 0.0, 20.0);
histNSpectatorWeights = histogramFactory().createHistogram1D
("nSpectatorWeights",100, 0.0, 20.0);
histArea = histogramFactory().createHistogram1D
("area",200, 0.0, 600.0);
histAreaWeights = histogramFactory().createHistogram1D
("areaWeights",200, 0.0, 600.0);
//eps1
histe1 = histogramFactory().createHistogram1D
("e1",200, 0.0, 600.0);
histe1Weights = histogramFactory().createHistogram1D
("e1Weights",200, 0.0, 600.0);
histe1N = histogramFactory().createHistogram1D
("e1N",200, 0.0, 600.0);
histe1NWeights = histogramFactory().createHistogram1D
("e1NWeights",200, 0.0, 600.0);
histe1W = histogramFactory().createHistogram1D
("e1W",200, 0.0, 600.0);
histe1WWeights = histogramFactory().createHistogram1D
("e1WWeights",200, 0.0, 600.0);
histphi1 = histogramFactory().createHistogram1D
("phi1",200, 0.0, M_PI);
histphi1central = histogramFactory().createHistogram1D
("phi1central",200, 0.0, M_PI);
histphi1mid = histogramFactory().createHistogram1D
("phi1mid",200, 0.0, M_PI);
histphi1N = histogramFactory().createHistogram1D
("phi1N",200, 0.0, M_PI);
histphi1W = histogramFactory().createHistogram1D
("phi1W",200, 0.0, M_PI);
//eps2
histe2 = histogramFactory().createHistogram1D
("e2",200, 0.0, 600.0);
histe2Weights = histogramFactory().createHistogram1D
("e2Weights",200, 0.0, 600.0);
histe2N = histogramFactory().createHistogram1D
("e2N",200, 0.0, 600.0);
histe2NWeights = histogramFactory().createHistogram1D
("e2NWeights",200, 0.0, 600.0);
histe2W = histogramFactory().createHistogram1D
("e2W",200, 0.0, 600.0);
histe2WWeights = histogramFactory().createHistogram1D
("e2WWeights",200, 0.0, 600.0);
histphi2 = histogramFactory().createHistogram1D
("phi2",200, 0.0, M_PI);
histphi2central = histogramFactory().createHistogram1D
("phi2central",200, 0.0, M_PI);
histphi2mid = histogramFactory().createHistogram1D
("phi2mid",200, 0.0, M_PI);
histphi2N = histogramFactory().createHistogram1D
("phi2N",200, 0.0, M_PI);
histphi2W = histogramFactory().createHistogram1D
("phi2W",200, 0.0, M_PI);
//eps3
histe3 = histogramFactory().createHistogram1D
("e3",200, 0.0, 600.0);
histe3Weights = histogramFactory().createHistogram1D
("e3Weights",200, 0.0, 600.0);
histe3N = histogramFactory().createHistogram1D
("e3N",200, 0.0, 600.0);
histe3NWeights = histogramFactory().createHistogram1D
("e3NWeights",200, 0.0, 600.0);
histe3W = histogramFactory().createHistogram1D
("e3W",200, 0.0, 600.0);
histe3WWeights = histogramFactory().createHistogram1D
("e3WWeights",200, 0.0, 600.0);
histphi3 = histogramFactory().createHistogram1D
("phi3",200, 0.0, M_PI);
histphi3central = histogramFactory().createHistogram1D
("phi3central",200, 0.0, M_PI);
histphi3mid = histogramFactory().createHistogram1D
("phi3mid",200, 0.0, M_PI);
histphi3N = histogramFactory().createHistogram1D
("phi3N",200, 0.0, M_PI);
histphi3W = histogramFactory().createHistogram1D
("phi3W",200, 0.0, M_PI);
//eps4
histe4 = histogramFactory().createHistogram1D
("e4",200, 0.0, 600.0);
histe4Weights = histogramFactory().createHistogram1D
("e4Weights",200, 0.0, 600.0);
histe4N = histogramFactory().createHistogram1D
("e4N",200, 0.0, 600.0);
histe4NWeights = histogramFactory().createHistogram1D
("e4NWeights",200, 0.0, 600.0);
histe4W = histogramFactory().createHistogram1D
("e4W",200, 0.0, 600.0);
histe4WWeights = histogramFactory().createHistogram1D
("e4WWeights",200, 0.0, 600.0);
histphi4 = histogramFactory().createHistogram1D
("phi4",200, 0.0, M_PI);
histphi4central = histogramFactory().createHistogram1D
("phi4central",200, 0.0, M_PI);
histphi4mid = histogramFactory().createHistogram1D
("phi4mid",200, 0.0, M_PI);
histphi4N = histogramFactory().createHistogram1D
("phi4N",200, 0.0, M_PI);
histphi4W = histogramFactory().createHistogram1D
("phi4W",200, 0.0, M_PI);
//eps5
histe5 = histogramFactory().createHistogram1D
("e5",200, 0.0, 600.0);
histe5Weights = histogramFactory().createHistogram1D
("e5Weights",200, 0.0, 600.0);
histe5N = histogramFactory().createHistogram1D
("e5N",200, 0.0, 600.0);
histe5NWeights = histogramFactory().createHistogram1D
("e5NWeights",200, 0.0, 600.0);
histe5W = histogramFactory().createHistogram1D
("e5W",200, 0.0, 600.0);
histe5WWeights = histogramFactory().createHistogram1D
("e5WWeights",200, 0.0, 600.0);
histphi5 = histogramFactory().createHistogram1D
("phi5",200, 0.0, M_PI);
histphi5central = histogramFactory().createHistogram1D
("phi5central",200, 0.0, M_PI);
histphi5mid = histogramFactory().createHistogram1D
("phi5mid",200, 0.0, M_PI);
histphi5N = histogramFactory().createHistogram1D
("phi5N",200, 0.0, M_PI);
histphi5W = histogramFactory().createHistogram1D
("phi5W",200, 0.0, M_PI);
//eps^2
histe1Sqrd = histogramFactory().createHistogram1D
("e1Sqrd",200, 0.0, 600.0);
histe1SqrdWeights = histogramFactory().createHistogram1D
("e1SqrdWeights",200, 0.0, 600.0);
histe2Sqrd = histogramFactory().createHistogram1D
("e2Sqrd",200, 0.0, 600.0);
histe2SqrdWeights = histogramFactory().createHistogram1D
("e2SqrdWeights",200, 0.0, 600.0);
histe3Sqrd = histogramFactory().createHistogram1D
("e3Sqrd",200, 0.0, 600.0);
histe3SqrdWeights = histogramFactory().createHistogram1D
("e3SqrdWeights",200, 0.0, 600.0);
histe4Sqrd = histogramFactory().createHistogram1D
("e4Sqrd",200, 0.0, 600.0);
histe4SqrdWeights = histogramFactory().createHistogram1D
("e4SqrdWeights",200, 0.0, 600.0);
histe5Sqrd = histogramFactory().createHistogram1D
("e5Sqrd",200, 0.0, 600.0);
histe5SqrdWeights = histogramFactory().createHistogram1D
("e5SqrdWeights",200, 0.0, 600.0);
//eps^4
histe1Quad = histogramFactory().createHistogram1D
("e1Quad",200, 0.0, 600.0);
histe1QuadWeights = histogramFactory().createHistogram1D
("e1QuadWeights",200, 0.0, 600.0);
histe2Quad = histogramFactory().createHistogram1D
("e2Quad",200, 0.0, 600.0);
histe2QuadWeights = histogramFactory().createHistogram1D
("e2QuadWeights",200, 0.0, 600.0);
histe3Quad = histogramFactory().createHistogram1D
("e3Quad",200, 0.0, 600.0);
histe3QuadWeights = histogramFactory().createHistogram1D
("e3QuadWeights",200, 0.0, 600.0);
histe4Quad = histogramFactory().createHistogram1D
("e4Quad",200, 0.0, 600.0);
histe4QuadWeights = histogramFactory().createHistogram1D
("e4QuadWeights",200, 0.0, 600.0);
histe5Quad = histogramFactory().createHistogram1D
("e5Quad",200, 0.0, 600.0);
histe5QuadWeights = histogramFactory().createHistogram1D
("e5QuadWeights",200, 0.0, 600.0);
//for touched analysis
//eps2
histe2Touched = histogramFactory().createHistogram1D
("e2Touched",200, 0.0, 600.0);
histe2TouchedWeights = histogramFactory().createHistogram1D
("e2TouchedWeights",200, 0.0, 600.0);
//eps3
histe3Touched = histogramFactory().createHistogram1D
("e3Touched",200, 0.0, 600.0);
histe3TouchedWeights = histogramFactory().createHistogram1D
("e3TouchedWeights",200, 0.0, 600.0);
//eps4
histe4Touched = histogramFactory().createHistogram1D
("e4Touched",200, 0.0, 600.0);
histe4TouchedWeights = histogramFactory().createHistogram1D
("e4TouchedWeights",200, 0.0, 600.0);
//eps5
histe5Touched = histogramFactory().createHistogram1D
("e5Touched",200, 0.0, 600.0);
histe5TouchedWeights = histogramFactory().createHistogram1D
("e5TouchedWeights",200, 0.0, 600.0);
//for (-3,-1) analysis
//eps1
histe1m3tom1 = histogramFactory().createHistogram1D
("e1m3tom1",200, 0.0, 600.0);
histe1m3tom1Weights = histogramFactory().createHistogram1D
("e1m3tom1Weights",200, 0.0, 600.0);
//eps2
histe2m3tom1 = histogramFactory().createHistogram1D
("e2m3tom1",200, 0.0, 600.0);
histe2m3tom1Weights = histogramFactory().createHistogram1D
("e2m3tom1Weights",200, 0.0, 600.0);
//eps3
histe3m3tom1 = histogramFactory().createHistogram1D
("e3m3tom1",200, 0.0, 600.0);
histe3m3tom1Weights = histogramFactory().createHistogram1D
("e3m3tom1Weights",200, 0.0, 600.0);
//eps4
histe4m3tom1 = histogramFactory().createHistogram1D
("e4m3tom1",200, 0.0, 600.0);
histe4m3tom1Weights = histogramFactory().createHistogram1D
("e4m3tom1Weights",200, 0.0, 600.0);
//eps5
histe5m3tom1 = histogramFactory().createHistogram1D
("e5m3tom1",200, 0.0, 600.0);
histe5m3tom1Weights = histogramFactory().createHistogram1D
("e5m3tom1Weights",200, 0.0, 600.0);
//for (1,3) analysis
//eps1
histe1p1top3 = histogramFactory().createHistogram1D
("e1p1top3",200, 0.0, 600.0);
histe1p1top3Weights = histogramFactory().createHistogram1D
("e1p1top3Weights",200, 0.0, 600.0);
//eps2
histe2p1top3 = histogramFactory().createHistogram1D
("e2p1top3",200, 0.0, 600.0);
histe2p1top3Weights = histogramFactory().createHistogram1D
("e2p1top3Weights",200, 0.0, 600.0);
//eps3
histe3p1top3 = histogramFactory().createHistogram1D
("e3p1top3",200, 0.0, 600.0);
histe3p1top3Weights = histogramFactory().createHistogram1D
("e3p1top3Weights",200, 0.0, 600.0);
//eps4
histe4p1top3 = histogramFactory().createHistogram1D
("e4p1top3",200, 0.0, 600.0);
histe4p1top3Weights = histogramFactory().createHistogram1D
("e4p1top3Weights",200, 0.0, 600.0);
//eps5
histe5p1top3 = histogramFactory().createHistogram1D
("e5p1top3",200, 0.0, 600.0);
histe5p1top3Weights = histogramFactory().createHistogram1D
("e5p1top3Weights",200, 0.0, 600.0);
//CoG distance
histCoGdistance = histogramFactory().createHistogram1D
("CoGdistance",200, 0.0, 20.0);
//correlations
histeCorr1 = histogramFactory().createHistogram2D
("eCorr1",50, 0.0, 1.0, 50, 0.0, 1.0);
histeCorr2 = histogramFactory().createHistogram2D
("eCorr2",50, 0.0, 1.0, 50, 0.0, 1.0);
histeCorr3 = histogramFactory().createHistogram2D
("eCorr3",50, 0.0, 1.0, 50, 0.0, 1.0);
histeCorr4 = histogramFactory().createHistogram2D
("eCorr4",50, 0.0, 1.0, 50, 0.0, 1.0);
histeCorr5 = histogramFactory().createHistogram2D
("eCorr5",50, 0.0, 1.0, 50, 0.0, 1.0);
histphiCorr1 = histogramFactory().createHistogram1D
("phiCorr1",200, 0.0, M_PI);
histphiCorr2 = histogramFactory().createHistogram1D
("phiCorr2",200, 0.0, M_PI);
histphiCorr2mid = histogramFactory().createHistogram1D
("phiCorr2mid",200, 0.0, M_PI);
histphiCorr2central = histogramFactory().createHistogram1D
("phiCorr2central",200, 0.0, M_PI);
histphiCorr3 = histogramFactory().createHistogram1D
("phiCorr3",200, 0.0, M_PI);
histphiCorr4 = histogramFactory().createHistogram1D
("phiCorr4",200, 0.0, M_PI);
histphiCorr5 = histogramFactory().createHistogram1D
("phiCorr5",200, 0.0, M_PI);
//<eps(1,3)*eps(-3,-1)>
epFepB1 = epF1 = epB1 = epSqrdF1 = epSqrdB1 = 0.0;
epFepB2 = epF2 = epB2 = epSqrdF2 = epSqrdB2 = 0.0;
epFepB2mid = epF2mid= epB2mid = epSqrdF2mid = epSqrdB2mid = 0.0;
epFepB2central = epF2central= epB2central = epSqrdF2central = epSqrdB2central = 0.0;
epFepB3 = epF3 = epB3 = epSqrdF3 = epSqrdB3 = 0.0;
epFepB4 = epF4 = epB4 = epSqrdF4 = epSqrdB4 = 0.0;
histe1e1p1top3 = histogramFactory().createHistogram1D
("e1e1p1top3",200, 0.0, 600.0);
histe1e1p1top3Weights = histogramFactory().createHistogram1D
("e1e1p1top3Weights",200, 0.0, 600.0);
histe2e2p1top3 = histogramFactory().createHistogram1D
("e2e2p1top3",200, 0.0, 600.0);
histe2e2p1top3Weights = histogramFactory().createHistogram1D
("e2e2p1top3Weights",200, 0.0, 600.0);
histe3e3p1top3 = histogramFactory().createHistogram1D
("e3e3p1top3",200, 0.0, 600.0);
histe3e3p1top3Weights = histogramFactory().createHistogram1D
("e3e3p1top3Weights",200, 0.0, 600.0);
histe4e4p1top3 = histogramFactory().createHistogram1D
("e4e4p1top3",200, 0.0, 600.0);
histe4e4p1top3Weights = histogramFactory().createHistogram1D
("e4e4p1top3Weights",200, 0.0, 600.0);
histe5e5p1top3 = histogramFactory().createHistogram1D
("e5e5p1top3",200, 0.0, 600.0);
histe5e5p1top3Weights = histogramFactory().createHistogram1D
("e5e5p1top3Weights",200, 0.0, 600.0);
//dN/deta
histdNdnSpectdeta = histogramFactory().createHistogram2D
("dNdnSpectdeta",25, 0.0, 500.0, 100, -10.0, 10.0);
histdNdeta0to100spect = histogramFactory().createHistogram1D
("dNdeta0to100spect",200, -10, 10);
histdNdeta100to200spect = histogramFactory().createHistogram1D
("dNdeta100to200spect",200, -10, 10);
histdNdeta200to300spect = histogramFactory().createHistogram1D
("dNdeta200to300spect",200, -10, 10);
histdNdeta300to400spect = histogramFactory().createHistogram1D
("dNdeta300to400spect",200, -10, 10);
spect0to100Weight = 0.0;
spect100to200Weight = 0.0;
spect200to300Weight = 0.0;
spect300to400Weight = 0.0;
//flux tubes
histFluxTube = histogramFactory().createHistogram2D
("fluxTube",15, 0, 15.0, 100, 0.0, 2.0*M_PI);
histFluxTubeWeights = histogramFactory().createHistogram2D
("fluxTubeWeights",15, 0, 15.0, 100, 0.0, 2.0*M_PI);
}
void FSAnalysis::dofinish() {
AnalysisHandler::dofinish();
double sumw = weights->sumBinHeights();
double SDsumw = SDweights->sumBinHeights();
double AU4SDsumw = AU4SDweights->sumBinHeights();
double xsecw = generator()->integratedXSec()/millibarn;
double totalWeightScale = 0.0;
double over100WeightScale = 0.0;
double over100under250WeightScale = 0.0;
double over350WeightScale = 0.0;
double spect0to100WeightScale = 0.0;
double spect100to200WeightScale = 0.0;
double spect200to300WeightScale = 0.0;
double spect300to400WeightScale = 0.0;
if ( totalWeight != 0.0 ) totalWeightScale = 1.0/totalWeight;
if ( over100Weight != 0.0 ) over100WeightScale = 1.0/over100Weight;
if ( over100under250Weight != 0.0 ) over100under250WeightScale = 1.0/over100under250Weight;
if ( over350Weight != 0.0 ) over350WeightScale = 1.0/over350Weight;
if ( spect0to100Weight != 0.0 ) spect0to100WeightScale = 1.0/spect0to100Weight;
if ( spect100to200Weight != 0.0 ) spect100to200WeightScale = 1.0/spect100to200Weight;
if ( spect200to300Weight != 0.0 ) spect200to300WeightScale = 1.0/spect200to300Weight;
if ( spect300to400Weight != 0.0 ) spect300to400WeightScale = 1.0/spect300to400Weight;
generator()->log()
<< setprecision(10)
<< "integrated xsec in microbarn: " << 1000.0*xsecw << endl;
if ( xsecw <= 0.0 || sumw <= 0.0 ) return;
normalize(ngbefore);
normalize(ngafter);
if ( sumw > 0.0 ) weights->scale(1.0/sumw);
if ( SDsumw > 0.0 ) SDweights->scale(1.0/SDsumw);
if ( AU4SDsumw > 0.0 ) AU4SDweights->scale(1.0/SDsumw);
normalize(epsRP, millibarn);
normalize(epsPart, millibarn);
normalize(epsPartOver20, millibarn);
normalize(epsPartOver40, millibarn);
normalize(mult12, millibarn);
normalize(DIPSYPT, millibarn);
DIPSYPT->scale( 1.0/generator()->integratedXSec()*(millibarn) );
normalize(finalPT, millibarn);
finalPT->scale( 1.0/generator()->integratedXSec()*(millibarn) );
normalize(finalPTeta, millibarn);
finalPTeta->scale( 1.0/generator()->integratedXSec()*(millibarn) );
normalize(finalChargedPTeta, millibarn);
finalChargedPTeta->scale( 1.0/generator()->integratedXSec()*(millibarn) );
normalize(finalETeta, millibarn);
finalETeta->scale( 1.0/generator()->integratedXSec()*(millibarn) );
normalize(finalNcheta, millibarn);
finalNcheta->scale( 1.0/generator()->integratedXSec()*(millibarn) );
generator()->histogramFactory()->normalizeToXSecFraction(lnMX2distFrac);
generator()->histogramFactory()->histogramFactory().
divide("/lnMX2distNorm", *lnMX2dist, *lnMX2distWeights);
generator()->histogramFactory()->histogramFactory().
divide("/lnMX2dist0Norm", *lnMX2dist0, *lnMX2dist0Weights);
generator()->histogramFactory()->histogramFactory().
divide("/lnMX2dist1Norm", *lnMX2dist1, *lnMX2dist1Weights);
generator()->histogramFactory()->histogramFactory().
divide("/lnMX2dist2Norm", *lnMX2dist2, *lnMX2dist2Weights);
normalize(SDNchdeta, millibarn);
generator()->histogramFactory()->histogramFactory().
divide("/MXmaxYNorm", *MXmaxY, *MXmaxYWeights);
generator()->histogramFactory()->histogramFactory().
divide("/MX2maxYNorm", *MX2maxY, *MX2maxYWeights);
SDNchdeta->scale( 1.0/generator()->integratedXSec()*(millibarn) );
generator()->histogramFactory()->histogramFactory().
divide("/UA4dndetaMX20Norm", *UA4dndetaMX20, *UA4dndetaMX20Weights);
generator()->histogramFactory()->histogramFactory().
divide("/UA4dndetaMX60Norm", *UA4dndetaMX60, *UA4dndetaMX60Weights);
generator()->histogramFactory()->histogramFactory().
divide("/UA4dndetaMX80Norm", *UA4dndetaMX80, *UA4dndetaMX80Weights);
generator()->histogramFactory()->histogramFactory().
divide("/UA4dndetaMX100Norm", *UA4dndetaMX100, *UA4dndetaMX100Weights);
generator()->histogramFactory()->histogramFactory().
divide("/UA4dndetaMX115Norm", *UA4dndetaMX115, *UA4dndetaMX115Weights);
generator()->histogramFactory()->histogramFactory().
divide("/UA4dndetaMX140Norm", *UA4dndetaMX140, *UA4dndetaMX140Weights);
generator()->histogramFactory()->histogramFactory().
divide("/SDNchdyMX38Norm", *SDNchdyMX38, *SDNchdyMX38Weights);
generator()->histogramFactory()->histogramFactory().
divide("/SDNchdyMX815Norm", *SDNchdyMX815, *SDNchdyMX815Weights);
generator()->histogramFactory()->histogramFactory().
divide("/SDNchdyMX1530Norm", *SDNchdyMX1530, *SDNchdyMX1530Weights);
generator()->histogramFactory()->histogramFactory().
divide("/SDdedetaMX38Norm", *SDdedetaMX38, *SDdedetaMX38Weights);
generator()->histogramFactory()->histogramFactory().
divide("/SDdedetaMX818Norm", *SDdedetaMX818, *SDdedetaMX818Weights);
generator()->histogramFactory()->histogramFactory().
divide("/SDdedetaMX1830Norm", *SDdedetaMX1830, *SDdedetaMX1830Weights);
normalize(secondLastPT, millibarn);
secondLastPT->scale( 1.0/generator()->integratedXSec()*(millibarn) );
generator()->log()
<< "average eta distance from FSR gluon to colour neighbour: "
<< etaDiffAriadne/NGlueAriadne << endl;
normalize(chargedPT, millibarn);
chargedPT->scale( 1.0/generator()->integratedXSec()*(millibarn) );
normalize(chargedN, millibarn);
chargedN->scale( 1.0/generator()->integratedXSec()*(millibarn) );
chargedNALICE->scale(5.0/INEL);
chargeMultALICE->scale(1.0/INEL);
EtDensPHENIX *= totalWeightScale;
generator()->log() << "average et density is " << EtDensPHENIX/GeV << endl;
normalize(maxPTBefore, millibarn);
normalize(DIPSYSumPT, millibarn);
DIPSYSumPT->scale( 1.0/generator()->integratedXSec()*(millibarn) );
normalize(finalSumET, millibarn);
finalSumET->scale( 1.0/generator()->integratedXSec()*(millibarn) );
//v2
generator()->histogramFactory()->histogramFactory().
divide("/AreaPartNorm", *AreaPart, *nParticipants);
tH1DPtr PE2Norm = generator()->histogramFactory()->histogramFactory().
divide("/PE2Norm", *PE2, *nParticipants);
tH1DPtr PE4Norm = generator()->histogramFactory()->histogramFactory().
divide("/PE4Norm", *PE4, *nParticipants);
tH1DPtr PE22 = generator()->histogramFactory()->histogramFactory().
multiply("/PE22", *PE2Norm, *PE2Norm);
tH1DPtr PE22d = generator()->histogramFactory()->histogramFactory().
add("/PE22d", *PE22, *PE22);
generator()->histogramFactory()->histogramFactory().
subtract("/eps4", *PE4Norm, *PE22d);
generator()->histogramFactory()->histogramFactory().
divide("/EccAreaNorm", *EccArea, *OverlapArea);
normalize(RPEcc, millibarn);
normalize(PartEcc, millibarn);
normalize(OverlapArea, millibarn);
tH1DPtr v22 = generator()->histogramFactory()->histogramFactory().
divide("/v22Flow", *v2flow, *dNchFlow);
generator()->histogramFactory()->histogramFactory().
divide("/v22Mix", *v2mix, *dNchMix);
generator()->histogramFactory()->histogramFactory().
divide("/v2finalNorm", *v2final, *v2finalWeights);
tH1DPtr v4flowNorm = generator()->histogramFactory()->histogramFactory().
divide("/v42Flow", *v4flow, *dNchFlow);
tH1DPtr v24 = generator()->histogramFactory()->histogramFactory().
multiply("/v24", *v22, *v22);
tH1DPtr temp = generator()->histogramFactory()->histogramFactory().
subtract("/temp", *v4flowNorm, *v24);
generator()->histogramFactory()->histogramFactory().
subtract("/v4", *temp, *v24);
generator()->histogramFactory()->histogramFactory().
divide("/v2quadNorm", *v2quad, *v2quadWeights);
generator()->histogramFactory()->histogramFactory().
divide("/v2gapMean", *v2gap, *dNchFinal);
generator()->histogramFactory()->histogramFactory().
divide("/denseRatioNorm", *denseRatio, *denseRatioWeights);
generator()->histogramFactory()->histogramFactory().
divide("/densityNorm", *density, *dNchFlow);
//SD
generator()->histogramFactory()->histogramFactory().
divide("/SDavNNorm", *SDavN, *SDavNWeights);
generator()->histogramFactory()->histogramFactory().
divide("/SDavN2Norm", *SDavN2, *SDavN2Weights);
normalize(dNchFlow, millibarn);
normalize(dNchMix, millibarn);
normalize(dNchFinal, millibarn);
normalize(nParticipants, millibarn);
normalize(density1020, millibarn);
normalize(density4060, millibarn);
normalize(density60plus, millibarn);
test2D->scale( totalWeightScale );
generator()->log()
<< "average number of participants: "
<< averageNParticipants*totalWeightScale << endl
<< "average number of gluons in rapidity [-1,1]: "
<< centralGlueMult*totalWeightScale << endl;
generator()->log()
<< "/totalWeight "
<< totalWeight << endl;
//end v2
//eccentricities
generator()->histogramFactory()->histogramFactory().
divide("/nGlueNorm", *histNGlue, *histNGlueWeights);
generator()->histogramFactory()->histogramFactory().
divide("/nGlueSqrNorm", *histNGlueSqr, *histNGlueWeights);
generator()->histogramFactory()->histogramFactory().
divide("/nGlueSpectNorm", *histNGlueSpect, *histNGlueSpectWeights);
generator()->histogramFactory()->histogramFactory().
divide("/nGlueSpectSqrNorm", *histNGlueSpectSqr, *histNGlueSpectWeights);
generator()->histogramFactory()->histogramFactory().
divide("/nSpectatorNorm", *histNSpectator, *histNSpectatorWeights);
generator()->histogramFactory()->histogramFactory().
divide("/nSpectatorSqrNorm", *histNSpectatorSqr, *histNSpectatorWeights);
generator()->histogramFactory()->histogramFactory().
divide("/areaNorm", *histArea, *histAreaWeights);
//eps1
generator()->histogramFactory()->histogramFactory().
divide("/e1Norm", *histe1, *histe1Weights);
generator()->histogramFactory()->histogramFactory().
divide("/e1NNorm", *histe1N, *histe1NWeights);
generator()->histogramFactory()->histogramFactory().
divide("/e1WNorm", *histe1W, *histe1WWeights);
histphi1->scale( over100WeightScale );
histphi1central->scale( over350WeightScale );
histphi1mid->scale( over100under250WeightScale );
histphi1W->scale( over100WeightScale );
histphi1N->scale( over100WeightScale );
//eps2
generator()->histogramFactory()->histogramFactory().
divide("/e2Norm", *histe2, *histe2Weights);
generator()->histogramFactory()->histogramFactory().
divide("/e2NNorm", *histe2N, *histe2NWeights);
generator()->histogramFactory()->histogramFactory().
divide("/e2WNorm", *histe2W, *histe2WWeights);
histphi2->scale( over100WeightScale );
histphi2central->scale( over350WeightScale );
histphi2mid->scale( over100under250WeightScale );
histphi2W->scale( over100WeightScale );
histphi2N->scale( over100WeightScale );
//eps3
generator()->histogramFactory()->histogramFactory().
divide("/e3Norm", *histe3, *histe3Weights);
generator()->histogramFactory()->histogramFactory().
divide("/e3NNorm", *histe3N, *histe3NWeights);
generator()->histogramFactory()->histogramFactory().
divide("/e3WNorm", *histe3W, *histe3WWeights);
histphi3->scale( over100WeightScale );
histphi3central->scale( over350WeightScale );
histphi3mid->scale( over100under250WeightScale );
histphi3W->scale( over100WeightScale );
histphi3N->scale( over100WeightScale );
//eps4
generator()->histogramFactory()->histogramFactory().
divide("/e4Norm", *histe4, *histe4Weights);
generator()->histogramFactory()->histogramFactory().
divide("/e4NNorm", *histe4N, *histe4NWeights);
generator()->histogramFactory()->histogramFactory().
divide("/e4WNorm", *histe4W, *histe4WWeights);
histphi4->scale( over100WeightScale );
histphi4central->scale( over350WeightScale );
histphi4mid->scale( over100under250WeightScale );
histphi4W->scale( over100WeightScale );
histphi4N->scale( over100WeightScale );
//eps5
generator()->histogramFactory()->histogramFactory().
divide("/e5Norm", *histe5, *histe5Weights);
generator()->histogramFactory()->histogramFactory().
divide("/e5NNorm", *histe5N, *histe5NWeights);
generator()->histogramFactory()->histogramFactory().
divide("/e5WNorm", *histe5W, *histe5WWeights);
histphi5->scale( over100WeightScale );
histphi5central->scale( over350WeightScale );
histphi5mid->scale( over100under250WeightScale );
histphi5W->scale( over100WeightScale );
histphi5N->scale( over100WeightScale );
//eps^2
generator()->histogramFactory()->histogramFactory().
divide("/e1SqrdNorm", *histe1Sqrd, *histe1SqrdWeights);
generator()->histogramFactory()->histogramFactory().
divide("/e2SqrdNorm", *histe2Sqrd, *histe2SqrdWeights);
generator()->histogramFactory()->histogramFactory().
divide("/e3SqrdNorm", *histe3Sqrd, *histe3SqrdWeights);
generator()->histogramFactory()->histogramFactory().
divide("/e4SqrdNorm", *histe4Sqrd, *histe4SqrdWeights);
generator()->histogramFactory()->histogramFactory().
divide("/e5SqrdNorm", *histe5Sqrd, *histe5SqrdWeights);
//eps^4
generator()->histogramFactory()->histogramFactory().
divide("/e1QuadNorm", *histe1Quad, *histe1QuadWeights);
generator()->histogramFactory()->histogramFactory().
divide("/e2QuadNorm", *histe2Quad, *histe2QuadWeights);
generator()->histogramFactory()->histogramFactory().
divide("/e3QuadNorm", *histe3Quad, *histe3QuadWeights);
generator()->histogramFactory()->histogramFactory().
divide("/e4QuadNorm", *histe4Quad, *histe4QuadWeights);
generator()->histogramFactory()->histogramFactory().
divide("/e5QuadNorm", *histe5Quad, *histe5QuadWeights);
//eps for touched
generator()->histogramFactory()->histogramFactory().
divide("/e2TouchedNorm", *histe2Touched, *histe2TouchedWeights);
generator()->histogramFactory()->histogramFactory().
divide("/e3TouchedNorm", *histe3Touched, *histe3TouchedWeights);
generator()->histogramFactory()->histogramFactory().
divide("/e4TouchedNorm", *histe4Touched, *histe4TouchedWeights);
generator()->histogramFactory()->histogramFactory().
divide("/e5TouchedNorm", *histe5Touched, *histe5TouchedWeights);
//eps in (-3,-1)
generator()->histogramFactory()->histogramFactory().
divide("/e1m3tom1Norm", *histe1m3tom1, *histe1m3tom1Weights);
generator()->histogramFactory()->histogramFactory().
divide("/e2m3tom1Norm", *histe2m3tom1, *histe2m3tom1Weights);
generator()->histogramFactory()->histogramFactory().
divide("/e3m3tom1Norm", *histe3m3tom1, *histe3m3tom1Weights);
generator()->histogramFactory()->histogramFactory().
divide("/e4m3tom1Norm", *histe4m3tom1, *histe4m3tom1Weights);
generator()->histogramFactory()->histogramFactory().
divide("/e5m3tom1Norm", *histe5m3tom1, *histe5m3tom1Weights);
//eps in (1,3)
generator()->histogramFactory()->histogramFactory().
divide("/e1p1top3Norm", *histe1p1top3, *histe1p1top3Weights);
generator()->histogramFactory()->histogramFactory().
divide("/e2p1top3Norm", *histe2p1top3, *histe2p1top3Weights);
generator()->histogramFactory()->histogramFactory().
divide("/e3p1top3Norm", *histe3p1top3, *histe3p1top3Weights);
generator()->histogramFactory()->histogramFactory().
divide("/e4p1top3Norm", *histe4p1top3, *histe4p1top3Weights);
generator()->histogramFactory()->histogramFactory().
divide("/e5p1top3Norm", *histe5p1top3, *histe5p1top3Weights);
//CoG distance
histCoGdistance->scale( totalWeightScale );
//correlations
histeCorr1->scale( over100WeightScale );
histeCorr2->scale( over100WeightScale );
histeCorr3->scale( over100WeightScale );
histeCorr4->scale( over100WeightScale );
histeCorr5->scale( over100WeightScale );
histphiCorr1->scale( over100WeightScale );
histphiCorr2->scale( over100WeightScale );
histphiCorr2mid->scale( over100under250WeightScale );
histphiCorr2central->scale( over350WeightScale );
histphiCorr3->scale( over100WeightScale );
histphiCorr4->scale( over100WeightScale );
histphiCorr5->scale( over100WeightScale );
//<eps(1,3)*eps(-3,-1)>
epFepB1 *= over100WeightScale;
epF1 *= over100WeightScale;
epB1 *= over100WeightScale;
epSqrdF1 *= over100WeightScale;
epSqrdB1 *= over100WeightScale;
epFepB2 *= over100WeightScale;
epF2 *= over100WeightScale;
epB2 *= over100WeightScale;
epSqrdF2 *= over100WeightScale;
epSqrdB2 *= over100WeightScale;
epFepB2mid *= over100under250WeightScale;
epF2mid *= over100under250WeightScale;
epB2mid *= over100under250WeightScale;
epSqrdF2mid *= over100under250WeightScale;
epSqrdB2mid *= over100under250WeightScale;
epFepB2central *= over350WeightScale;
epF2central *= over350WeightScale;
epB2central *= over350WeightScale;
epSqrdF2central *= over350WeightScale;
epSqrdB2central *= over350WeightScale;
epFepB3 *= over100WeightScale;
epF3 *= over100WeightScale;
epB3 *= over100WeightScale;
epSqrdF3 *= over100WeightScale;
epSqrdB3 *= over100WeightScale;
epFepB4 *= over100WeightScale;
epF4 *= over100WeightScale;
epB4 *= over100WeightScale;
epSqrdF4 *= over100WeightScale;
epSqrdB4 *= over100WeightScale;
if ( over100WeightScale != 0.0 ) {
rho1 = (epFepB1-epF1*epB1)/(sqrt(epSqrdF1 - sqr(epF1))*sqrt(epSqrdB1 - sqr(epB1)));
rho2 = (epFepB2-epF2*epB2)/(sqrt(epSqrdF2 - sqr(epF2))*sqrt(epSqrdB2 - sqr(epB2)));
rho2mid = (epFepB2mid-epF2mid*epB2mid)/
(sqrt(epSqrdF2mid - sqr(epF2mid))*sqrt(epSqrdB2mid - sqr(epB2mid)));
rho2central = (epFepB2central-epF2central*epB2central)/
(sqrt(epSqrdF2central - sqr(epF2central))*sqrt(epSqrdB2central - sqr(epB2central)));
rho3 = (epFepB3-epF3*epB3)/(sqrt(epSqrdF3 - sqr(epF3))*sqrt(epSqrdB3 - sqr(epB3)));
rho4 = (epFepB4-epF4*epB4)/(sqrt(epSqrdF4 - sqr(epF4))*sqrt(epSqrdB4 - sqr(epB4)));
// cout << "rho1 = " << rho1 << endl;
// cout << "rho2 = " << rho2 << endl;
// cout << "rho2mid = " << rho2mid << endl;
// cout << "rho2central = " << rho2central << endl;
// cout << "rho3 = " << rho3 << endl;
// cout << "rho4 = " << rho4 << endl;
}
generator()->histogramFactory()->histogramFactory().
divide("/e1e1p1top3Norm", *histe1e1p1top3, *histe1e1p1top3Weights);
generator()->histogramFactory()->histogramFactory().
divide("/e2e2p1top3Norm", *histe2e2p1top3, *histe2e2p1top3Weights);
generator()->histogramFactory()->histogramFactory().
divide("/e3e3p1top3Norm", *histe3e3p1top3, *histe3e3p1top3Weights);
generator()->histogramFactory()->histogramFactory().
divide("/e4e4p1top3Norm", *histe4e4p1top3, *histe4e4p1top3Weights);
generator()->histogramFactory()->histogramFactory().
divide("/e5e5p1top3Norm", *histe5e5p1top3, *histe5e5p1top3Weights);
//dN/deta/dnSpect
histdNdnSpectdeta->scale( totalWeightScale );
histdNdeta0to100spect->scale( spect0to100WeightScale );
histdNdeta100to200spect->scale( spect100to200WeightScale );
histdNdeta200to300spect->scale( spect200to300WeightScale );
histdNdeta300to400spect->scale( spect300to400WeightScale );
//flux tube analysis
generator()->histogramFactory()->histogramFactory().
divide("/fluxTubeNorm", *histFluxTube, *histFluxTubeWeights);
}
void FSAnalysis::persistentOutput(PersistentOStream & os) const {
// *** ATTENTION *** os << ; // Add all member variable which should be written persistently here.
}
void FSAnalysis::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<FSAnalysis,AnalysisHandler>
describeDIPSYFSAnalysis("DIPSY::FSAnalysis", "FSAnalysis.so");
void FSAnalysis::Init() {
static ClassDocumentation<FSAnalysis> documentation
("There is no documentation for the FSAnalysis class");
}
diff --git a/DIPSY/FSDipole5Ordering.cc b/DIPSY/FSDipole5Ordering.cc
--- a/DIPSY/FSDipole5Ordering.cc
+++ b/DIPSY/FSDipole5Ordering.cc
@@ -1,157 +1,203 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the FSDipole5Ordering class.
//
#include "FSDipole5Ordering.h"
+#include "Ariadne/Cascade/AriadneHandler.h"
#include "Ariadne/Cascade/Parton.h"
#include "Ariadne/Cascade/DipoleState.h"
#include "ThePEG/Utilities/DescribeClass.h"
+#include "ThePEG/Utilities/UtilityBase.h"
+#include "ThePEG/Utilities/Current.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace DIPSY;
FSDipole5Ordering::FSDipole5Ordering()
: ReweightBase(true), isGenerous(0), useOnlyOriginal(false), f(1.0),
- ptmin(ZERO) {}
+ ptmin(ZERO), hardSuppression(0), fudge(1.0) {}
FSDipole5Ordering::~FSDipole5Ordering() {}
bool FSDipole5Ordering::
finalVeto(const Emission & emission) const {
if ( emission.rho < ptmin || emission.partons.empty() ) return false;
+
+ pair<tcParPtr,tcParPtr> parents =
+ make_pair(emission.colourParent, emission.antiColourParent);
+
+ if ( hardSuppression ) {
+ LorentzRotation Rcm = Utilities::getBoostToCM(emission.pold);
+ double alpha = ( hardSuppression == 1? Current<AriadneHandler>()->hardAlpha():
+ Current<AriadneHandler>()->softAlpha());
+ double beta = Current<AriadneHandler>()->beta();
+ Energy W = (emission.pold.first + emission.pold.second).m();
+ double frac =
+ (fudge*emission.rho*(Rcm*(parents.first->vertex() - parents.second->vertex())).perp())/hbarc;
+ double fmax = pow(1.0 - (Rcm*parents.first->momentum()).plus()/W, -1.0/alpha);
+ if ( frac > fmax && pow(fmax/frac, beta) < UseRandom::rnd() ) return true;
+ fmax = pow(1.0 - (Rcm*parents.first->momentum()).minus()/W, -1.0/alpha);
+ if ( frac > fmax && pow(fmax/frac, beta) < UseRandom::rnd() ) return true;
+ }
+
+ bool o1 = parents.first->orig();
+ bool o3 = parents.second->orig();
+ while ( !parents.first->orig() )
+ parents.first = parents.first->emission()->colourParent;
+ while ( !parents.second->orig() )
+ parents.second = parents.second->emission()->antiColourParent;
+ LorentzMomentum p1 = parents.first->orig()->momentum();
+ LorentzMomentum p3 = parents.second->orig()->momentum();
+
for ( int i = 0, N = emission.partons.size(); i < N; ++i ) {
tcParPtr parton = emission.partons[i];
- pair<tcParPtr,tcParPtr> parents =
- make_pair(emission.colourParent, emission.antiColourParent);
- bool o1 = parents.first->orig();
- bool o3 = parents.second->orig();
- while ( !parents.first->orig() )
- parents.first = parents.first->emission()->colourParent;
- while ( !parents.second->orig() )
- parents.second = parents.second->emission()->antiColourParent;
- 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() > f*p1.perp2() ||
p2.plus() > f*p1.plus() ||
p2.minus() > f*p1.minus() ) ) return true;
if ( o3 && ( p2.perp2() > f*p3.perp2() ||
p2.plus() > f*p3.plus() ||
p2.minus() > f*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() < f*pt2cut ) return false;
if ( p2.plus() < f*p1.plus() && p2.minus() < f*p1.minus() ) return false;
if ( p2.plus() < f*p3.plus() && p2.minus() < f*p3.minus() ) return false;
}
return true;
}
IBPtr FSDipole5Ordering::clone() const {
return new_ptr(*this);
}
IBPtr FSDipole5Ordering::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 FSDipole5Ordering::persistentOutput(PersistentOStream & os) const {
- os << isGenerous << useOnlyOriginal << f << ounit(ptmin, GeV);
+ os << isGenerous << useOnlyOriginal << f << ounit(ptmin, GeV) << hardSuppression << fudge;
}
void FSDipole5Ordering::persistentInput(PersistentIStream & is, int) {
- is >> isGenerous >> useOnlyOriginal >> f >> iunit(ptmin, GeV);
+ is >> isGenerous >> useOnlyOriginal >> f >> iunit(ptmin, GeV) >> hardSuppression >> fudge;
}
DescribeClass<FSDipole5Ordering,Ariadne5::ReweightBase>
describeDIPSYFSDipole5Ordering("DIPSY::FSDipole5Ordering",
"FSDipole5Ordering.so");
void FSDipole5Ordering::Init() {
static ClassDocumentation<FSDipole5Ordering> documentation
("There is no documentation for the FSDipole5Ordering class");
static Switch<FSDipole5Ordering,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.",
&FSDipole5Ordering::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<FSDipole5Ordering,bool> interfaceOnlyOriginal
("OnlyOriginal",
"Determines whether all emissions are restricted by the kinematics of "
"the original partons, or only those where original partons are involved",
&FSDipole5Ordering::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);
static Parameter<FSDipole5Ordering,double> interfaceFudge
("Fudge",
"Fudge parameter to allow less strict ordering if larger than unity.",
&FSDipole5Ordering::f, 1.0, 0.0, 2.0,
true, false, Interface::limited);
static Parameter<FSDipole5Ordering,Energy> interfacePTMin
("PTMin",
"Limit on invariant transverse momentum. Any emission below this is "
"not checked.",
&FSDipole5Ordering::ptmin, GeV, 0.0*GeV, 0.0*GeV, 0*GeV,
true, false, Interface::lowerlim);
+ static Switch<FSDipole5Ordering,int> interfaceHardSuppression
+ ("HardSuppression",
+ "Options for suppression of hard emissions due to the distance between the partons in the radiating dipole.",
+ &FSDipole5Ordering::hardSuppression, 0, true, false);
+ static SwitchOption interfaceHardSuppressionOff
+ (interfaceHardSuppression,
+ "Off",
+ "No suppression.",
+ 0);
+ static SwitchOption interfaceHardSuppressionSuppression
+ (interfaceHardSuppression,
+ "HardParameters",
+ "Suppression using the parameters for hard remnants in the soft radiation model.",
+ 1);
+ static SwitchOption interfaceHardSuppressionSoftParameters
+ (interfaceHardSuppression,
+ "SoftParameters",
+ "Suppression using the parameters for soft remnants in the soft radiation model.",
+ 2);
+
+ static Parameter<FSDipole5Ordering,double> interfaceHardFudge
+ ("HardFudge",
+ "Fudge factor multiplying transverse momentum of an emission when calculating hard suppression.",
+ &FSDipole5Ordering::fudge, 1.0, 0.0, 0,
+ true, false, Interface::lowerlim);
+
}
diff --git a/DIPSY/FSDipole5Ordering.h b/DIPSY/FSDipole5Ordering.h
--- a/DIPSY/FSDipole5Ordering.h
+++ b/DIPSY/FSDipole5Ordering.h
@@ -1,131 +1,143 @@
// -*- C++ -*-
#ifndef DIPSY_FSDipole5Ordering_H
#define DIPSY_FSDipole5Ordering_H
//
// This is the declaration of the FSDipole5Ordering class.
//
#include "Ariadne/Cascade/ReweightBase.h"
namespace DIPSY {
using namespace Ariadne5;
/**
* Here is the documentation of the FSDipole5Ordering class.
*
* @see \ref FSDipole5OrderingInterfaces "The interfaces"
* defined for FSDipole5Ordering.
*/
class FSDipole5Ordering: public Ariadne5::ReweightBase {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
FSDipole5Ordering();
/**
* The destructor.
*/
virtual ~FSDipole5Ordering();
//@}
public:
/**
* 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;
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
virtual IBPtr fullclone() const;
//@}
// If needed, insert declarations of virtual function defined in the
// InterfacedBase class here (using ThePEG-interfaced-decl in Emacs).
private:
/**
* If positive, the phase space restriction on final-state emissions
* is somewhat relaxed. If negative the phase space is strict and
* only given by light-cone momentum non-ordering.
*/
int isGenerous;
/**
* Veto only emissions from original partons.
*/
bool useOnlyOriginal;
/**
* Fudge factor for +/- ordering. Values above one increases the
* phase space.
*/
double f;
/**
* Limit on invariant transverse momentum. Any emission below this
* is not checked.
*/
Energy ptmin;
+ /**
+ * Option for suppression of hard radiation if partons in the dipole
+ * are far separated.
+ */
+ int hardSuppression;
+
+ /**
+ * Fudge factor to scale the fraction of light-cone momentum
+ * available for radiation.
+ */
+ double fudge;
+
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
FSDipole5Ordering & operator=(const FSDipole5Ordering &);
};
}
#endif /* DIPSY_FSDipoleOrdering_H */
diff --git a/DIPSY/LHCPbPb.in b/DIPSY/LHCPbPb.in
--- a/DIPSY/LHCPbPb.in
+++ b/DIPSY/LHCPbPb.in
@@ -1,48 +1,79 @@
cd /DIPSY
+read Tune30.in
+set stdEmitter:MinusOrderingMode EffectiveParton
+set stdEmitter:PMinusOrdering 1.5
+set stdProton:R0 2.7
+set stdAntiProton:R0 2.7
+mset . DIPSY::DipoleEventHandler LambdaQCD 0.22
+
set /Defaults/Particles/u:NominalMass 0.33
set /Defaults/Particles/d:NominalMass 0.33
set /Defaults/Particles/s:NominalMass 0.5
set /Defaults/Particles/c:NominalMass 1.5
set /Defaults/Particles/b:NominalMass 4.8
-read CurrentTune.in
-
read RivetAnalyses.in
create DIPSY::HIAnalysis HIAna HIAnalysis.so
create ThePEG::ProgressLog Logger ProgressLog.so
set Logger:Interval 600
-set LHCPbPbGenerator:NumberOfEvents 2
+set LHCPbPbGenerator:NumberOfEvents 25
set LHCPbPbEventHandler:PreSamples 0
set LHCPbPbEventHandler:ConsistencyLevel 0
set LHCPbPbEventHandler:DecayHandler:MaxLifeTime 10
set LHCPbPbEventHandler:BGen:Width 20
set LHCPbPbEventHandler:XSecFn:CheckOffShell false
insert LHCPbPbGenerator:AnalysisHandlers[0] Logger
insert LHCPbPbGenerator:AnalysisHandlers[0] HIAna
set LHCGenerator:EventHandler:EventFiller:PTCut 0.6
# This is the plain run
saverun LHCPbPb0 LHCPbPbGenerator
create DIPSY::FixedImpactGenerator FixedB FixedImpactGenerator.so
set FixedB:MaxB = 0.0
set FixedB:MinB = 0.0
+set LHCPbPbGenerator:EventHandler:BGen FixedB
cp stdFiller SwingFiller
+set SwingFiller:FSSwingTime 1.0
+set SwingFiller:FSSwingTimeStep 0.1
+set LHCPbPbGenerator:EventHandler:EventFiller SwingFiller
+saverun LHCPbPbCC LHCPbPbGenerator
+
+set FixedB:MaxB 3.3
+saverun LHCPbPbC LHCPbPbGenerator
+set SwingFiller:FSSwingTime 0.0
+saverun LHCPbPbC0 LHCPbPbGenerator
+
+create Ariadne5::DipoleSwinger Swinger
+insert RHICGenerator:EventHandler:CascadeHandler:Emitters[0] Swinger
+set Swinger:SizeOpt 1
+do Swinger:SetRmax -2.7
+set Swinger:Lambda 5
+saverun LHCPbPbCNs5r LHCPbPbGenerator
+set FSOrdering:HardSuppression SoftParameters
+saverun LHCPbPbCNs5rH LHCPbPbGenerator
+do Swinger:SetRmax 2.7
+saverun LHCPbPbCNs5RH LHCPbPbGenerator
+set FSOrdering:HardSuppression Off
+saverun LHCPbPbCNs5R LHCPbPbGenerator
+do Swinger:SetRmax 6.1
+saverun LHCPbPbCNs5Rr LHCPbPbGenerator
+erase RHICGenerator:EventHandler:CascadeHandler:Emitters[0]
+
+set FixedB:MinB = 0.0
set SwingFiller:FSSwingTime 8
set SwingFiller:FSSwingTimeStep 0.4
cp stdEmitter UnorderedEmitter
set UnorderedEmitter:BothOrderedEvo False
set UnorderedEmitter:BothOrderedInt False
set UnorderedEmitter:BothOrderedFS False
-set LHCPbPbGenerator:EventHandler:BGen FixedB
set LHCPbPbGenerator:EventHandler:Emitter UnorderedEmitter
-set LHCPbPbGenerator:EventHandler:EventFiller SwingFiller
# This is the b=0 unordered emissions with final-state swing
saverun LHCPbPbA LHCPbPbGenerator
diff --git a/DIPSY/RHICAuAu.in b/DIPSY/RHICAuAu.in
--- a/DIPSY/RHICAuAu.in
+++ b/DIPSY/RHICAuAu.in
@@ -1,140 +1,214 @@
cd /DIPSY
read Tune30.in
set stdEmitter:MinusOrderingMode EffectiveParton
set stdEmitter:PMinusOrdering 1.5
set stdProton:R0 2.7
set stdAntiProton:R0 2.7
mset . DIPSY::DipoleEventHandler LambdaQCD 0.22
set /Defaults/Particles/u:NominalMass 0.33
set /Defaults/Particles/d:NominalMass 0.33
set /Defaults/Particles/s:NominalMass 0.5
set /Defaults/Particles/c:NominalMass 1.5
set /Defaults/Particles/b:NominalMass 4.8
erase RHICGenerator:AnalysisHandlers[0]
library HIAnalysis.so
create DIPSY::HIAnalysis HIAna
create ThePEG::ProgressLog Logger ProgressLog.so
set Logger:Interval 600
set RHICGenerator:NumberOfEvents 100
set RHICEventHandler:PreSamples 0
set RHICEventHandler:ConsistencyLevel 0
set RHICEventHandler:DecayHandler:MaxLifeTime 10
set RHICEventHandler:BGen:Width 25
set RHICEventHandler:XSecFn:CheckOffShell false
insert RHICGenerator:AnalysisHandlers[0] Logger
insert RHICGenerator:AnalysisHandlers[0] HIAna
set RHICEventHandler:LuminosityFunction:Energy 39400
set RHICGenerator:EventHandler:EventFiller:PTCut 0.6
set RHICEventHandler:EventFiller:FSSwingTime 1.0
set RHICEventHandler:EventFiller:FSSwingTimeStep 0.1
saverun RHICAuAu RHICGenerator
set RHICEventHandler:EventFiller:FSSwingTime 0.0
saverun RHICAuAu0 RHICGenerator
set RHICEventHandler:EventFiller:FSSwingTime 1.0
create DIPSY::FixedImpactGenerator FixedB FixedImpactGenerator.so
set RHICEventHandler:BGen FixedB
+set FixedB:MaxB 0.0
+set FixedB:MinB 0.0
+saverun RHICAuAuCC RHICGenerator
set FixedB:MaxB 3.2
-set FixedB:MinB 0.0
saverun RHICAuAuC RHICGenerator
+set RHICEventHandler:EventFiller:FSSwingTime 10.0
+saverun RHICAuAuC10 RHICGenerator
set RHICEventHandler:EventFiller:FSSwingTime 0.0
saverun RHICAuAuC0 RHICGenerator
set stdSwinger:Lambda 2.0
saverun RHICAuAuC02 RHICGenerator
set stdSwinger:Lambda 5.0
saverun RHICAuAuC05 RHICGenerator
set stdSwinger:Lambda 20.0
saverun RHICAuAuC020 RHICGenerator
set stdSwinger:Lambda 100.0
saverun RHICAuAuC0100 RHICGenerator
set stdSwinger:Lambda 1.0
# New Final state swing
# With maximum energy scale
create Ariadne5::DipoleSwinger Swinger
set Swinger:Rmax 0.0
insert RHICGenerator:EventHandler:CascadeHandler:Emitters[0] Swinger
saverun RHICAuAuCNM1 RHICGenerator
+set Swinger:Lambda 0.01
+saverun RHICAuAuCNM001 RHICGenerator
set Swinger:Lambda 2
saverun RHICAuAuCNM2 RHICGenerator
set Swinger:Lambda 10
saverun RHICAuAuCNM10 RHICGenerator
set Swinger:Lambda 50
saverun RHICAuAuCNM50 RHICGenerator
set Swinger:Lambda 100
saverun RHICAuAuCNM100 RHICGenerator
set Swinger:Lambda 1
-set Swinger:Rmax 2.7
+do Swinger:SetRmax 2.7
saverun RHICAuAuCNM1R RHICGenerator
set Swinger:Lambda 10
saverun RHICAuAuCNM10R RHICGenerator
set Swinger:Lambda 1
+set Swinger:RhoCut 0.3
+saverun RHICAuAuCNM1R3 RHICGenerator
+set Swinger:SizeOpt -1
+set Swinger:RhoCut 0.1
+saverun RHICAuAuCNM1R1 RHICGenerator
+set Swinger:Lambda 10
+saverun RHICAuAuCNM10R1 RHICGenerator
+set Swinger:Lambda 1
+set Swinger:RhoCut -1.0
+set Swinger:SizeOpt 0
set Swinger:Rmax 0.0
set Swinger:Linear Linear
saverun RHICAuAuCNM1L RHICGenerator
set Swinger:Lambda 10
saverun RHICAuAuCNM10L RHICGenerator
set Swinger:Lambda 1
set Swinger:Linear Logarithmic
+set Swinger:SizeOpt 1
+set Swinger:Lambda 1
+saverun RHICAuAuCNMS1 RHICGenerator
+do Swinger:SetRmax 2.7
+saverun RHICAuAuCNMS1R RHICGenerator
+set Swinger:RhoCut 0.1
+saverun RHICAuAuCNMS1R1 RHICGenerator
+set Swinger:RhoCut -1.0
+set Swinger:Lambda 2
+saverun RHICAuAuCNMS2R RHICGenerator
+set Swinger:Lambda 20
+saverun RHICAuAuCNMS20R RHICGenerator
+set Swinger:Lambda 200
+saverun RHICAuAuCNMS200R RHICGenerator
+set Swinger:Lambda 1
+set Swinger:Rmax 0.0
+set Swinger:SizeOpt 0
+
+
# With maximum pt scale
create Ariadne5::MaxPTScale MaxPTScale MaxPTScale.so
set MaxPTScale:Strategy ActualPT
set RHICGenerator:EventHandler:CascadeHandler:ScaleSetter MaxPTScale
saverun RHICAuAuCN1 RHICGenerator
set Swinger:Lambda 2
saverun RHICAuAuCN2 RHICGenerator
set Swinger:Lambda 0.1
saverun RHICAuAuCN01 RHICGenerator
set Swinger:Lambda 5
saverun RHICAuAuCN5 RHICGenerator
set Swinger:Lambda 10
saverun RHICAuAuCN10 RHICGenerator
set Swinger:Lambda 20
saverun RHICAuAuCN20 RHICGenerator
set Swinger:Lambda 50
saverun RHICAuAuCN50 RHICGenerator
set Swinger:Lambda 100
saverun RHICAuAuCN100 RHICGenerator
set Swinger:Lambda 200
saverun RHICAuAuCN200 RHICGenerator
set Swinger:Rmax 2.7
set Swinger:Lambda 1
saverun RHICAuAuCN1R RHICGenerator
+
+set Swinger:SizeOpt 1
+do Swinger:SetRmax 2.7
+saverun RHICAuAuCNs1R RHICGenerator
+do Swinger:SetRmax -2.7
+saverun RHICAuAuCNs1r RHICGenerator
+set Swinger:Lambda 2
+saverun RHICAuAuCNs2r RHICGenerator
+set Swinger:Lambda 5
+saverun RHICAuAuCNs5r RHICGenerator
+set FSOrdering:HardSuppression SoftParameters
+saverun RHICAuAuCNs5rH RHICGenerator
+set FSOrdering:HardFudge 0.5
+saverun RHICAuAuCNs5rh RHICGenerator
+set FSOrdering:HardFudge 0.05
+saverun RHICAuAuCNs5rh0 RHICGenerator
+set FSOrdering:HardFudge 1.0
+set FSOrdering:HardSuppression Off
+set Swinger:Lambda 10
+saverun RHICAuAuCNs10r RHICGenerator
+set Swinger:Lambda 1
+set Swinger:Linear Linear
+saverun RHICAuAuCNs1rL RHICGenerator
+set Swinger:Linear Logarithmic
+set Swinger:Rmax 0.0
+set Swinger:SizeOpt 0
+
set Swinger:Lambda 10
saverun RHICAuAuCN10R RHICGenerator
set Swinger:Lambda 20
saverun RHICAuAuCN20R RHICGenerator
set Swinger:Linear Linear
set Swinger:Lambda 1
saverun RHICAuAuCN1L RHICGenerator
set Swinger:Lambda 10
saverun RHICAuAuCN10L RHICGenerator
set Swinger:Lambda 100
saverun RHICAuAuCN100L RHICGenerator
set Swinger:Linear Logarithmic
set Swinger:Rmax 0.0
set Swinger:Lambda 1
# With scalar sum pt scale
set MaxPTScale:Strategy ScalarSum
saverun RHICAuAuCNS1 RHICGenerator
+set Swinger:SizeOpt 1
+do Swinger:SetRmax 2.7
+saverun RHICAuAuCNSs1R RHICGenerator
+do Swinger:SetRmax 6.1
+saverun RHICAuAuCNSs1Rr RHICGenerator
+do Swinger:SetRmax -2.7
+saverun RHICAuAuCNSs1r RHICGenerator
+set Swinger:Lambda 5
+saverun RHICAuAuCNSs5r RHICGenerator
+set Swinger:Lambda 1
+set Swinger:Rmax 0.0
+set Swinger:SizeOpt 0
set Swinger:Lambda 2
saverun RHICAuAuCNS2 RHICGenerator
set Swinger:Lambda 10
saverun RHICAuAuCNS10 RHICGenerator
set Swinger:Rmax 2.7
set Swinger:Linear Linear
saverun RHICAuAuCNS10L RHICGenerator
set Swinger:Lambda 100
saverun RHICAuAuCNS100L RHICGenerator
diff --git a/DIPSY/Swinger.cc b/DIPSY/Swinger.cc
--- a/DIPSY/Swinger.cc
+++ b/DIPSY/Swinger.cc
@@ -1,425 +1,426 @@
// -*- 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
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(candidates[i]->children().first) cout << "OH NOES, parents among the swing candidates!!!! O_o" << endl;
if ( !force && candidates[i]->hasGen() ) continue;
if ( dipole.partons().second == dipole.partons().first ||
candidates[i]->partons().second == candidates[i]->partons().first )
Throw<ColourIndexException>()
<< "Found inconsistent colour indices in DIPSY. Event discarded."
<< Exception::eventerror;
// Generate a y
double R = -log( UseRandom::rnd() );
// double yi = max(max(dipole.partons().first->y(),
// dipole.partons().second->y()), miny)
// + R/swingAmp(dipole.partons(), candidates[i]->partons());
double yi = max(max(dipole.partons().first->y(),
dipole.partons().second->y()), miny)
+ R/swingAmp(dipole, *candidates[i]);
if ( yi < dipole.generatedY() ) {
dipole.swingDipole(candidates[i]);
dipole.generatedY(yi);
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");
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/Test5ppFS.in b/DIPSY/Test5ppFS.in
--- a/DIPSY/Test5ppFS.in
+++ b/DIPSY/Test5ppFS.in
@@ -1,271 +1,276 @@
cd /DIPSY
# read Tune30.in
# set stdEmitter:MinusOrderingMode EffectiveParton
# set stdEmitter:PMinusOrdering 1.5
# set stdProton:R0 2.7
# set stdAntiProton:R0 2.7
# mset . DIPSY::DipoleEventHandler LambdaQCD 0.22
set /Defaults/Particles/u:NominalMass 0.33
set /Defaults/Particles/d:NominalMass 0.33
set /Defaults/Particles/s:NominalMass 0.5
set /Defaults/Particles/c:NominalMass 1.5
set /Defaults/Particles/b:NominalMass 4.8
read CurrentTune.in
read RivetAnalyses.in
create ThePEG::ProgressLog Logger ProgressLog.so
set Logger:Interval 600
set LHCGenerator:NumberOfEvents 10000
set LHCEventHandler:PreSamples 0
set LHCEventHandler:ConsistencyLevel Never
set LHCEventHandler:DecayHandler:MaxLifeTime 10
insert LHCGenerator:AnalysisHandlers[0] Logger
set LHCGenerator:MaxErrors 10000
set TevatronGenerator:NumberOfEvents 1000000
set TevatronEventHandler:PreSamples 0
set TevatronEventHandler:DecayHandler:MaxLifeTime 10
insert TevatronGenerator:AnalysisHandlers[0] Logger
set TevatronGenerator:MaxErrors 10000
set LHCGenerator:EventHandler:EventFiller:PTCut 0.6
set LHCLumi:Energy 70.0
#saverun RHIC LHCGenerator
#saverun RHICCuAu LHCGenerator
#saverun LHCPbPb LHCGenerator
set LHCGenerator:RandomNumberGenerator:Seed 1
set LHCLumi:Energy 7000.0
saverun Test5ppFS70debug LHCGenerator
#create ThePEG::RivetAnalysis RivetCMS
#insert RivetCMS:Paths[0] .
#insert RivetCMS:Analyses[0] CMS_2012_PAS_FWD_11_003
#insert RivetCMS:Analyses[0] CMS_FWD_11_003_PRIVATE
#insert LHCGenerator:AnalysisHandlers[0] RivetCMS
set LHCGenerator:NumberOfEvents 1000000
saverun Test5ppFS70CMS LHCGenerator
set LHCLumi:Energy 2760.0
saverun Test5ppFS27CMS LHCGenerator
set LHCLumi:Energy 900.0
saverun Test5ppFS09CMS LHCGenerator
set LHCLumi:Energy 7000.0
set LHCGenerator:EventHandler:YFrametest 0.3
saverun Test5ppFS70CMS03 LHCGenerator
set LHCLumi:Energy 2760.0
saverun Test5ppFS27CMS03 LHCGenerator
set LHCLumi:Energy 900.0
saverun Test5ppFS09CMS03 LHCGenerator
set LHCLumi:Energy 7000.0
set LHCGenerator:EventHandler:YFrametest 0.5
set LHCGenerator:EventHandler:YFrametest 0.7
saverun Test5ppFS70CMS07 LHCGenerator
set LHCLumi:Energy 2760.0
saverun Test5ppFS27CMS07 LHCGenerator
set LHCLumi:Energy 900.0
saverun Test5ppFS09CMS07 LHCGenerator
set LHCLumi:Energy 7000.0
set LHCGenerator:EventHandler:YFrametest 0.5
set LHCGenerator:NumberOfEvents 10000
# saverun LHCpp30d LHCGenerator
set LHCGenerator:EventHandler:YFrametest 0.3
saverun LHCpp30cFrame03 LHCGenerator
set LHCGenerator:EventHandler:YFrametest 0.5
set LHCGenerator:RandomNumberGenerator:Seed 1
set LHCGenerator:NumberOfEvents 0
set LHCEventHandler:PreSamples 4000000
set LHCLumi:Energy 100.0
saverun pp100Inc LHCGenerator
set LHCLumi:Energy 200.0
#saverun pp200Inc LHCGenerator
set LHCLumi:Energy 400.0
#saverun pp400Inc LHCGenerator
set LHCLumi:Energy 900.0
#saverun pp900Inc LHCGenerator
set LHCLumi:Energy 1800.0
#saverun pp1800Inc LHCGenerator
set LHCLumi:Energy 2360.0
#saverun pp2360Inc LHCGenerator
set LHCLumi:Energy 7000.0
saverun pp7000Inc4MSeed1 LHCGenerator
set LHCLumi:Energy 14000.0
#saverun pp14000Inc LHCGenerator
create DIPSY::FixedImpactGenerator FixedB FixedImpactGenerator.so
set FixedB:MaxB 1.28
set FixedB:MinB 1.28
set FixedB:BAngle 0
set LHCEventHandler:BGen FixedB
set LHCLumi:Energy 200.0
#saverun ppW200B128temp LHCGenerator
set LHCLumi:Energy 7000.0
set LHCEventHandler:BGen stdBGenerator
#saverun Test5ppFS23 LHCGenerator
set LHCLumi:Energy 900.0
#insert LHCGenerator:AnalysisHandlers[0] RivetLHC
set LHCLumi:Energy 900.0
#saverun Test5ppFS09 LHCGenerator
set LHCGenerator:EventHandler:EventFiller:PTCut 0.6
#saverun Test5ppFS09cut LHCGenerator
set /DIPSY/FSOrdering:OnlyOriginal OnlyOriginalEmissions
#saverun Test5ppFS09orig LHCGenerator
#set /DIPSY/stdXSec:Smoothing 0.1
#saverun Test5ppFS09smooth LHCGenerator
#set /DIPSY/stdXSec:Smoothing 0.0
set /DIPSY/FSOrdering:Fudge 1.2
#saverun Test5ppFS09fudge LHCGenerator
set /DIPSY/FSOrdering:Fudge 1.0
set /DIPSY/FSOrdering:PTMin 2.0
set LHCGenerator:EventHandler:EventFiller:PTCut 2.0
#saverun Test5ppFS09ptlim LHCGenerator
set LHCGenerator:EventHandler:EventFiller:PTCut 0.6
set /DIPSY/FSOrdering:PTMin 0.0
set /DIPSY/FSOrdering:Fudge 1.0
set /DIPSY/FSOrdering:OnlyOriginal AllEmissions
set LHCLumi:Energy 7000.0
#set LHCGenerator:RandomNumberGenerator:Seed 0
#saverun LHCpp0 LHCGenerator
#...
#set LHCGenerator:RandomNumberGenerator:Seed 20
#saverun LHCpp20 LHCGenerator
#set LHCGenerator:RandomNumberGenerator:Seed 21
#saverun LHCpp21 LHCGenerator
#set LHCGenerator:RandomNumberGenerator:Seed 22
#saverun LHCpp22 LHCGenerator
#set LHCGenerator:RandomNumberGenerator:Seed 23
#saverun LHCpp23 LHCGenerator
#set LHCGenerator:RandomNumberGenerator:Seed 24
#saverun LHCpp24 LHCGenerator
#set LHCGenerator:RandomNumberGenerator:Seed 25
#saverun LHCpp25 LHCGenerator
#set LHCGenerator:RandomNumberGenerator:Seed 26
#saverun LHCpp26 LHCGenerator
#set LHCGenerator:RandomNumberGenerator:Seed 27
#saverun LHCpp27 LHCGenerator
#set LHCGenerator:RandomNumberGenerator:Seed 28
#saverun LHCpp28 LHCGenerator
#set LHCGenerator:RandomNumberGenerator:Seed 29
#saverun LHCpp29 LHCGenerator
#set LHCGenerator:RandomNumberGenerator:Seed 30
#saverun LHCpp30 LHCGenerator
#set LHCGenerator:RandomNumberGenerator:Seed 31
#saverun LHCpp31 LHCGenerator
#set LHCGenerator:RandomNumberGenerator:Seed 32
#saverun LHCpp32 LHCGenerator
#set LHCGenerator:RandomNumberGenerator:Seed 33
#saverun LHCpp33 LHCGenerator
#set LHCGenerator:RandomNumberGenerator:Seed 34
#saverun LHCpp34 LHCGenerator
#set LHCGenerator:RandomNumberGenerator:Seed 35
#saverun LHCpp35 LHCGenerator
#set LHCGenerator:RandomNumberGenerator:Seed 36
#saverun LHCpp36 LHCGenerator
#set LHCGenerator:RandomNumberGenerator:Seed 37
#saverun LHCpp37 LHCGenerator
#set LHCGenerator:RandomNumberGenerator:Seed 38
#saverun LHCpp38 LHCGenerator
#set LHCGenerator:RandomNumberGenerator:Seed 39
#saverun LHCpp39 LHCGenerator
set LHCGenerator:EventHandler:YFrametest 0.3
set LHCLumi:Energy 900.0
#saverun Test5ppFS09frame03 LHCGenerator
set LHCLumi:Energy 7000.0
set LHCGenerator:NumberOfEvents 200000
#saverun Test5ppFS70frame03 LHCGenerator
set LHCGenerator:EventHandler:YFrametest 0.5
set TevatronLumi:Energy 1800.0
insert TevatronGenerator:AnalysisHandlers[0] RivetCDF
#saverun Test5ppFS18 TevatronGenerator
set TevatronGenerator:EventHandler:YFrametest 0.3
#saverun Test5ppFS18frame03 TevatronGenerator
set TevatronGenerator:EventHandler:YFrametest 0.5
cp LHCGenerator LHCcentral
create DIPSY::FixedImpactGenerator FixedB FixedImpactGenerator.so
set FixedB:MaxB = 0.0
set FixedB:MinB = 0.0
set LHCcentral:EventHandler:BGen FixedB
erase LHCcentral:AnalysisHandlers[0]
#erase LHCcentral:AnalysisHandlers[0]
erase LHCcentral:AnalysisHandlers[0]
insert LHCcentral:AnalysisHandlers[0] Logger
create DIPSY::HIAnalysis HIAna HIAnalysis.so
insert LHCcentral:AnalysisHandlers[0] HIAna
cp LHCcentral LHCppC
do LHCcentral:AddInterface /DIPSY/stdFiller:FSSwingTime 0, 0.5, 1.0, 1.5, 2.0
do LHCcentral:AddInterface /DIPSY/stdFiller:FSSwingTimeStep 0.05, 0.1
set LHCcentral:NumberOfEvents 1000
#saverun LHCppc LHCcentral
do LHCppC:AddInterface /DIPSY/stdFiller:FSSwingTime 0, 0.25, 0.5, 0.75, 1.0
do LHCppC:AddInterface /DIPSY/stdFiller:FSSwingTimeStep 0.05, 0.1, 0.2
set LHCppC:NumberOfEvents 1000
#saverun LHCppC LHCppC
cp LHCGenerator LHCridge0
set LHCridge0:NumberOfEvents 4000000
cp FixedB SmallB
set SmallB:MinB 0.0
set SmallB:MaxB 0.1
set LHCridge0:EventHandler:BGen SmallB
#erase LHCridge0:AnalysisHandlers[0]
erase LHCridge0:AnalysisHandlers[0]
erase LHCridge0:AnalysisHandlers[0]
insert LHCridge0:AnalysisHandlers[0] Logger
create ThePEG::CMSlrnsac CMSlrnsac CMSlrnsac.so
insert LHCridge0:AnalysisHandlers[0] CMSlrnsac
#saverun LHCridge0 LHCridge0
set SmallB:MaxB 0.2
#saverun LHCridge1 LHCridge0
set SmallB:MaxB 0.3
#saverun LHCridge2 LHCridge0
set stdEmitter:BothOrderedEvo False
set stdEmitter:BothOrderedInt False
set stdEmitter:BothOrderedFS False
set stdFiller:FSSwingTime 0.6
set stdFiller:FSSwingTimeStep 0.2
#saverun LHCridge3 LHCridge0
set SmallB:MaxB 0.2
#saverun LHCridge4 LHCridge0
set SmallB:MaxB 0.3
set SmallB:MinB 0.2
saverun LHCridge5 LHCridge0
set SmallB:MaxB 0.2
set SmallB:MinB 0.1
saverun LHCridge6 LHCridge0
set LHCcentral:EventHandler:BGen stdBGenerator
#saverun Test5ppFS70swing LHCGenerator
set LHCLumi:Energy 900.0
#saverun Test5ppFS09swing LHCGenerator
set LHCLumi:Energy 7000.0
set stdEmitter:BothOrderedEvo True
set stdEmitter:BothOrderedInt True
set stdEmitter:BothOrderedFS True
#saverun Test5ppFS70sw2 LHCGenerator
set LHCLumi:Energy 900.0
#saverun Test5ppFS09sw2 LHCGenerator
set LHCLumi:Energy 7000.0
set stdFiller:FSSwingTime 0.0
set stdFiller:FSSwingTimeStep 0.1
+create Ariadne5::DipoleSwinger Swinger
+set Swinger:Rmax 0.0
+insert LHCGenerator:EventHandler:CascadeHandler:Emitters[0] Swinger
+set LHCEventHandler:PreSamples 0
+saverun Test5ppFS70sw23 LHCGenerator

File Metadata

Mime Type
text/x-diff
Expires
Tue, Nov 19, 7:25 PM (1 d, 11 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3805817
Default Alt Text
(332 KB)

Event Timeline