Page MenuHomeHEPForge

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/Cascade/ColourIndex.h b/Cascade/ColourIndex.h
--- a/Cascade/ColourIndex.h
+++ b/Cascade/ColourIndex.h
@@ -1,152 +1,153 @@
// -*- 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), parity(false) {}
+ ColourIndex(unsigned isys = 0, unsigned indx = 0)
+ : index(indx), systemIndex(isys), parity(false) {}
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 PersistentOStream.
*/
template <typename OS>
void print(OS & os) const {
os << index << systemIndex << parity;
}
/**
* Read function for PersistentIStream.
*/
template <typename IS>
void read(IS & is) {
is >> index >> systemIndex >> parity;
}
private:
/**
* The actual colour index.
*/
unsigned index;
/**
* An additional index to keep different systems separate.
*/
unsigned systemIndex;
/**
* A parity for allowing junction swings.
*/
bool parity;
};
}
// 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/QCDDipole.h b/Cascade/QCDDipole.h
--- a/Cascade/QCDDipole.h
+++ b/Cascade/QCDDipole.h
@@ -1,279 +1,282 @@
// -*- C++ -*-
#ifndef Ariadne5_QCDDipole_H
#define Ariadne5_QCDDipole_H
//
// This is the declaration of the QCDDipole class.
//
#include "DipoleBase.h"
#include "QCDDipole.fh"
#include "Parton.fh"
#include "DipoleState.fh"
#include "ColourIndex.h"
namespace Ariadne5 {
using namespace ThePEG;
/**
+ * *** TODO WARNING! *** The following is wrong! the incoming parton iPart() carries
+ * colour and the outgoing (oPart()) carries anti-colour.
+ *
* The QCDDipole class represents QCD dipoles between
* <code>Parton</code>s. The QCDDipole also defines the colour flow
* from the incoming to the outgoing Parton, where the incoming Parton
* carries anti-colour and the outgoing Parton carries colour.
*
* NOTE! The dipole rest frame is defined such that the
* anti-colour-carrying parton is along the positive z-axis.
*/
class QCDDipole: public DipoleBase {
public:
/**
* The QCDDipoleState is a friend.
*/
friend class DipoleState;
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
QCDDipole();
/**
* The destructor.
*/
inline virtual ~QCDDipole() {};
//@}
public:
/**
* Get (or create and return) the colour line corresponding
* corresponding to this dipole, if present. Is only meaningful if
* Parton::produceParticle() has been called for the connected
* partons. The colour line should be properly connected to the
* produced particle.
*/
virtual ColinePtr colourLine() const;
/** @name Simple access functions. */
//@{
/**
* The anti-colour-carrying parton in this dipole.
*/
inline tParPtr iPart() const {
return theIPart;
}
/**
* The previous dipole in the string. Returns the dipole whose
* oPart() is this iPart() if any.
*/
tQCDPtr prev() const {
return thePrev;
}
/**
* Set the previous dipole in the string.
*/
void prev(tQCDPtr d) {
thePrev = d;
}
/**
* The colour-carrying parton in this dipole.
*/
inline tParPtr oPart() const {
return theOPart;
}
/**
* The next dipole in the string. Returns the dipole whose
* iPart() is this oPart() if any.
*/
tQCDPtr next() const {
return theNext;
}
/**
* Set the next dipole in the string.
*/
void next(tQCDPtr d) {
theNext = d;
}
/**
* Return all partons in this string (or string piece if it is in a junction).
*/
vector<tParPtr> string() const;
/**
* The colour index of this dipole.
*/
inline const ColourIndex & colourIndex() const {
return theColourIndex;
}
/**
* Set the anti-colour-carrying parton in this dipole.
*/
inline void iPart(tParPtr x) {
theIPart = x;
}
/**
* Set the colour-carrying parton in this dipole.
*/
inline void oPart(tParPtr x) {
theOPart = x;
}
/**
* Set the colour index of this dipole.
*/
inline void colourIndex(const ColourIndex & x) {
theColourIndex = x;
}
/**
* Generte a colour index of this dipole.
*/
void generateColourIndex();
/**
* Return the squared invariant mass of this dipole.
*/
Energy2 sdip() const;
// *** ATTENTION *** Do we need this?
/**
* The particle type if this dipole comes directly from a decay of a
* resonance. If not, null is returned.
*/
inline tcPDPtr resonance() const {
return theResonance;
}
/**
* The particle type if this dipole comes directly from a decay of a
* resonance.
*/
inline void resonance(tcPDPtr x) {
theResonance = x;
}
//@}
protected:
/** @name Functions relating to the DipoleState to which this belongs. */
//@{
/**
* 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 anti-colour-carrying parton in this dipole.
*/
tParPtr theIPart;
/**
* The colour-carrying parton in this dipole.
*/
tParPtr theOPart;
/**
* The next dipole in the string.
*/
tQCDPtr theNext;
/**
* The previous dipole in the string.
*/
tQCDPtr thePrev;
/**
* The colour index of this dipole. 0 means no index has been assigned.
*/
ColourIndex theColourIndex;
/**
* The particle type if this dipole comes directly from a decay of a
* resonance.
*/
tcPDPtr theResonance;
public:
/**
* Print out debugging information on std::cerr.
*/
virtual void debugme() const;
/**
* Check integrity of the emitter. Return false if error is found.
*/
virtual bool checkIntegrity();
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
QCDDipole & operator=(const QCDDipole &);
};
}
#endif /* Ariadne5_QCDDipole_H */
diff --git a/Cascade/QCDDipoleFinder.cc b/Cascade/QCDDipoleFinder.cc
--- a/Cascade/QCDDipoleFinder.cc
+++ b/Cascade/QCDDipoleFinder.cc
@@ -1,159 +1,168 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the QCDDipoleFinder class.
//
#include "QCDDipoleFinder.h"
#include "QCDDipole.h"
#include "ResonanceParton.h"
#include "Junction.h"
#include "Resonance.h"
#include "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/Utilities/Throw.h"
+#include "Ariadne/Config/ColourInfo.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace Ariadne5;
QCDDipoleFinder::QCDDipoleFinder() {}
QCDDipoleFinder::~QCDDipoleFinder() {}
IBPtr QCDDipoleFinder::clone() const {
return new_ptr(*this);
}
IBPtr QCDDipoleFinder::fullclone() const {
return new_ptr(*this);
}
vector<tQCDPtr> QCDDipoleFinder::findDipoles(DipoleState & state) const {
typedef multimap<tColinePtr,tParPtr>::iterator MapIt;
vector<tQCDPtr> ret;
multimap<tColinePtr,tParPtr> icol;
multimap<tColinePtr,tParPtr> ocol;
multimap<tColinePtr,tParPtr> iorphans;
for ( set<tParPtr>::const_iterator it = state.finalState().begin();
it != state.finalState().end(); ++it ) {
tColinePtr ic = (**it).origICol();
tColinePtr oc = (**it).origOCol();
if ( oc ) {
ocol.insert(make_pair(oc, *it));
tColinePair jsource = oc->sourceNeighbours();
if ( jsource.first && jsource.second ) {
tJunctionPtr j = state.create<Junction>();
icol.insert(make_pair(oc, j));
icol.insert(make_pair(jsource.first, j));
icol.insert(make_pair(jsource.second, j));
}
}
if ( ic ) {icol.insert(make_pair(ic, *it));
tColinePair jsink = ic->sinkNeighbours();
if ( jsink.first && jsink.second ) {
tJunctionPtr j = state.create<Junction>();
ocol.insert(make_pair(ic, j));
ocol.insert(make_pair(jsink.first, j));
ocol.insert(make_pair(jsink.second, j));
}
}
}
while ( icol.size() ) {
MapIt it1 = icol.begin();
MapIt it2 = ocol.find(it1->first);
if ( it2 != ocol.end() ) {
ret.push_back(createDipole(it1->second, it2->second, state));
ocol.erase(it2);
} else {
Throw<QCDFinderException>()
<< "The QCDDipoleFinder '" << name()
<< "' was not able to construct dipoles for all colour lines "
<< "in the final state. This is a serious problem. "
<< "Please contact the author." << Exception::runerror;
}
icol.erase(it1);
}
if ( ocol.size() )
Throw<QCDFinderException>()
<< "The QCDDipoleFinder '" << name()
<< "' was not able to construct dipoles for all colour lines "
<< "in the final state. This is a serious problem. "
<< "Please contact the author." << Exception::runerror;
// Now we need to connect the dipoles with eachother.
for ( int i = 0, N = ret.size(); i < N; ++i )
if ( ret[i]->oPart()->isG() ) {
for ( int j = 0; j < N; ++j )
if ( ret[i]->oPart() == ret[j]->iPart() ) {
ret[i]->next(ret[j]);
ret[j]->prev(ret[i]);
break;
}
if ( !ret[i]->next() )
Throw<QCDFinderException>()
<< "The QCDDipoleFinder '" << name()
<< "' was not able to construct dipoles for all colour lines "
<< "in the final state. This is a serious problem. "
<< "Please contact the author." << Exception::runerror;
}
- // Finally we need to generate colour indices.
- for ( int i = 0, N = ret.size(); i < N; ++i )
- ret[i]->generateColourIndex();
+ // Finally we need to generate colour indices unless it has been set from the outside.
+ for ( int i = 0, N = ret.size(); i < N; ++i ) {
+ tcPPtr ip = ret[i]->iPart()->orig();
+ tcPPtr op = ret[i]->oPart()->orig();
+ unsigned coli = ip? ColourInfo::colIndex(*ip): 0;
+ unsigned acoi = op? ColourInfo::acoIndex(*op): 0;
+ if ( acoi && acoi == coli )
+ ret[i]->colourIndex(ColourIndex(ret[i]->colourIndex().system(), acoi));
+ else
+ ret[i]->generateColourIndex();
+ }
return ret;
}
tQCDPtr QCDDipoleFinder::
createDipole(tParPtr pi, tParPtr po, DipoleState & state) const {
tQCDPtr dip = state.create<QCDDipole>();
dip->oPart(pi);
dip->iPart(po);
// If either parton is a junction, we cannot connect dipoles in the
// normal way. Instead we setup the junction.
if ( tJunctionPtr j = dynamic_ptr_cast<tJunctionPtr>(pi) )
j->replace(tQCDPtr(), dip);
if ( tJunctionPtr j = dynamic_ptr_cast<tJunctionPtr>(po) )
j->replace(tQCDPtr(), dip);
// If both partons come from a resonance we must put them in another
// colour system.
tResParPtr rpi = dynamic_ptr_cast<tResParPtr>(pi);
tResParPtr rpo = dynamic_ptr_cast<tResParPtr>(po);
if ( rpi && rpo )
dip->colourIndex(ColourIndex(min(rpi->resonance()->decaySystem(),
rpo->resonance()->decaySystem())));
return dip;
}
// If needed, insert default implementations of virtual function defined
// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs).
void QCDDipoleFinder::persistentOutput(PersistentOStream & os) const {}
void QCDDipoleFinder::persistentInput(PersistentIStream & is, int) {}
// The following static variable is needed for the type description
// system in ThePEG.
DescribeClass<QCDDipoleFinder,HandlerBase>
describeAriadne5QCDDipoleFinder("Ariadne5::QCDDipoleFinder",
"libAriadne5.so");
void QCDDipoleFinder::Init() {
static ClassDocumentation<QCDDipoleFinder> documentation
("The QCDDipoleFinder class and its sub-classes are responsible for "
"identifying and introducing of QCD dipoles in the setup phase of a "
"given DipoleState.");
}
diff --git a/Config/ColourInfo.cc b/Config/ColourInfo.cc
new file mode 100644
--- /dev/null
+++ b/Config/ColourInfo.cc
@@ -0,0 +1,61 @@
+// -*- C++ -*-
+//
+// This is the implementation of the non-inlined, non-templated member
+// functions of the ColourInfo class.
+//
+
+#include "ColourInfo.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;
+
+ColourInfo::~ColourInfo() {}
+
+int ColourInfo::colIndex(const Particle & p) {
+ for ( int i = 0, N = p.getInfo().size(); i < N; ++i )
+ if ( const ColourInfo * cin =
+ dynamic_cast<const ColourInfo *>(p.getInfo()[i].operator->()) )
+ return cin->indices().first;
+ return 0;
+}
+
+int ColourInfo::acoIndex(const Particle & p) {
+ for ( int i = 0, N = p.getInfo().size(); i < N; ++i )
+ if ( const ColourInfo * cin =
+ dynamic_cast<const ColourInfo *>(p.getInfo()[i].operator->()) )
+ return cin->indices().second;
+ return 0;
+}
+
+void ColourInfo::persistentOutput(PersistentOStream & os) const {
+ os << theIndices;
+}
+
+void ColourInfo::persistentInput(PersistentIStream & is, int) {
+ is >> theIndices;
+}
+
+
+// *** Attention *** The following static variable is needed for the type
+// description system in ThePEG. Please check that the template arguments
+// are correct (the class and its base class), and that the constructor
+// arguments are correct (the class name and the name of the dynamically
+// loadable library where the class implementation can be found).
+DescribeClass<ColourInfo,ThePEG::EventInfoBase>
+ describeAriadne5ColourInfo("Ariadne5::ColourInfo", "libAriadne5.so");
+
+void ColourInfo::Init() {
+
+ static ClassDocumentation<ColourInfo> documentation
+ ("There is no documentation for the ColourInfo class");
+
+}
+
diff --git a/Config/ColourInfo.h b/Config/ColourInfo.h
new file mode 100644
--- /dev/null
+++ b/Config/ColourInfo.h
@@ -0,0 +1,103 @@
+// -*- C++ -*-
+#ifndef Ariadne5_ColourInfo_H
+#define Ariadne5_ColourInfo_H
+//
+// This is the declaration of the ColourInfo class which is used to
+// convey colour indices of connecting dipoles for coloured particles.
+//
+
+#include "ThePEG/EventRecord/EventInfoBase.h"
+#include "ThePEG/EventRecord/Particle.h"
+
+namespace Ariadne5 {
+
+using namespace ThePEG;
+
+/**
+ * Here is the documentation of the ColourInfo class.
+ */
+class ColourInfo: public ThePEG::EventInfoBase {
+
+public:
+
+ /** @name Standard constructors and destructors. */
+ //@{
+ /**
+ * The default constructor, optionally taking indices on the colour
+ * and anticolour side as arguments.
+ */
+ ColourInfo(unsigned colindx = 0, unsigned acoindx = 0): theIndices(colindx, acoindx) {}
+
+ /**
+ * The destructor.
+ */
+ virtual ~ColourInfo();
+ //@}
+
+public:
+
+ /**
+ * Return the colour indices of connecting dipoles on the colour and
+ * anti-colour side.
+ */
+ pair<unsigned,unsigned> indices() const {
+ return theIndices;
+ }
+
+ /**
+ * Return the colour index of a dipole connecting the given
+ * particle's colour. If no ColourInfo is present or no index
+ * is defined, return -1.
+ */
+ static int colIndex(const Particle & p);
+
+ /**
+ * Return the colour index of a dipole connecting the given
+ * particle's anti colour. If no ColourInfo is present or no index
+ * is defined, return -1.
+ */
+ static int acoIndex(const Particle & p);
+
+ /** @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 colour indices of connecting dipoles on the colour and
+ * anti-colour side.
+ */
+ pair<unsigned,unsigned> theIndices;
+
+ /**
+ * The assignment operator is private and must never be called.
+ * In fact, it should not even be implemented.
+ */
+ ColourInfo & operator=(const ColourInfo &);
+
+};
+
+}
+
+#endif /* Ariadne5_ColourInfo_H */
diff --git a/Config/Makefile.am b/Config/Makefile.am
--- a/Config/Makefile.am
+++ b/Config/Makefile.am
@@ -1,13 +1,13 @@
-mySOURCES = CloneBase.cc Settings.cc
+mySOURCES = CloneBase.cc Settings.cc ColourInfo.cc
-DOCFILES = Ariadne5.h CloneBase.h UnitFO.h Settings.h
+DOCFILES = Ariadne5.h CloneBase.h UnitFO.h Settings.h ColourInfo.h
INCLUDEFILES = $(DOCFILES) config.h CloneBase.fh CloneBase.icc
EXTRA_DIST = $(INCLUDEFILES)
noinst_LTLIBRARIES = libAriadne5Config.la
libAriadne5Config_la_SOURCES = $(mySOURCES) $(INCLUDEFILES)
include $(top_srcdir)/Config/Makefile.aminclude
diff --git a/DIPSY/DipoleAbsorber.cc b/DIPSY/DipoleAbsorber.cc
--- a/DIPSY/DipoleAbsorber.cc
+++ b/DIPSY/DipoleAbsorber.cc
@@ -1,209 +1,209 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the DipoleAbsorber class.
//
#include "DipoleAbsorber.h"
#include "Ariadne/DIPSY/DipoleState.h"
#include "Ariadne/DIPSY/Parton.h"
#include "Ariadne/DIPSY/Dipole.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Utilities/Throw.h"
#include "ThePEG/Utilities/Current.h"
#include "DipoleEventHandler.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace DIPSY;
DipoleAbsorber::DipoleAbsorber() {}
DipoleAbsorber::~DipoleAbsorber() {}
bool rapSorty(tcPartonPtr part1, tcPartonPtr part2) {
return (part1->y() >= part2->y());
}
void DipoleAbsorber::removeParton(tPartonPtr p) const {
DipolePtr d1 = p->dipoles().first;
DipolePtr d2 = p->dipoles().second;
//if a quark (ie only one colour line out), then just remove
//the parton and the connected dipole.
if ( !d1 ) {
PartonPtr g = d2->partons().second;
if ( !g->dipoles().first ) return;
d2->neighbors().second->firstNeighbor(d1);
g->dipoles(make_pair(d1, d2->neighbors().second));
d2->children().second = d2->neighbors().second;
g->flavour(p->flavour());
return;
}
if ( !d2 ) {
PartonPtr g = d1->partons().first;
if ( !g->dipoles().second ) return;
d1->neighbors().first->secondNeighbor(d2);
g->dipoles(make_pair(d1->neighbors().first, d2));
d1->children().second = d1->neighbors().first;
g->flavour(p->flavour());
return;
}
PartonPtr p1 = d1->partons().first;
PartonPtr p2 = d2->partons().second;
if ( p1->dipoles().second->partons().second == p2 ) return;
d2->children().second = d1;
p2->dipoles(make_pair(d1,p2->dipoles().second));
d1->partons(make_pair(p1,p2));
d1->secondNeighbor(d2->neighbors().second);
if ( d1->neighbors().second ) d1->neighbors().second->firstNeighbor(d1);
if ( d1->size()/(d1->size()+d2->size()) < UseRandom::rnd() )
d1->colour(d2->colour());
}
void DipoleAbsorber::absorbVirtualPartons( DipoleState & state ) const {
list<PartonPtr> virtualPartons = state.virtualPartons();
virtualPartons.sort(rapSorty);
while ( !(virtualPartons.empty()) ) {
virtualPartons.sort(rapSorty);
absorbParton( virtualPartons.front(), state );
virtualPartons.pop_front();
}
}
bool DipoleAbsorber::swing( DipolePtr d1, DipolePtr d2 ) const {
if ( d1->neighbors().second == d2 ) return false;
if ( d2->neighbors().second == d1 ) return false;
if (d1 == d2) Throw<Exception>()
<< "lol, swinging with itself?? >_>" << Exception::abortnow;
if (d2->children().second || d2->children().first)
Throw<Exception>()
<< "swinging with someone thats emitted already" << Exception::abortnow;
PartonPtr p11 = d1->partons().first;
PartonPtr p12 = d1->partons().second;
PartonPtr p21 = d2->partons().first;
PartonPtr p22 = d2->partons().second;
d1->partons(make_pair(p11, p22));
d1->neighbors(make_pair(p11->dipoles().first, p22->dipoles().second));
if ( d1->neighbors().second ) d1->neighbors().second->firstNeighbor(d1);
d2->partons(make_pair(p21, p12));
d2->neighbors(make_pair(p21->dipoles().first, p12->dipoles().second));
if ( d2->neighbors().second ) d2->neighbors().second->firstNeighbor(d2);
p12->dipoles(make_pair(d2, p12->dipoles().second));
p22->dipoles(make_pair(d1, p22->dipoles().second));
return true;
}
void DipoleAbsorber::isolateNonParticipating( DipoleState & state ) const {
for( int i = 0; i < int(state.initialDipoles().size()); i++ ) {
DipolePtr d = state.initialDipoles()[i];
if ( !(d->participating()) ) {
if ( d->partons().first->dipoles().second != d->partons().second->dipoles().first )
swing( d->partons().first->dipoles().second, d->partons().second->dipoles().first );
d->partons().first->dipoles().second->participating( false );
}
}
}
void DipoleAbsorber::swingLoop( DipolePtr d, DipoleState & state ) const {
//make a list of the partons and dipoles in the loop.
list<PartonPtr> partons;
list<DipolePtr> dipoles;
PartonPtr p = d->partons().second;
partons.push_back(p);
dipoles.push_back(d);
bool forward = true;
while ( p != d->partons().first && (forward || p->dipoles().first) ) {
if ( !(p->dipoles().second) ) {
// cout << "found a quark in SmallDipoleAbsorber::absorbLoop!!!!!!!" << endl;
// state.diagnosis(true);
p = d->partons().first;
partons.push_back(p);
forward = false;
continue;
}
if ( forward ) {
p = p->dipoles().second->partons().second;
dipoles.push_back(p->dipoles().first);
}
else {
p = p->dipoles().first->partons().first;
dipoles.push_back(p->dipoles().second);
}
partons.push_back(p);
}
//find and perform a probable swing. Don't bother with colours...
list<DipolePtr> otherDips = d->dipoleState().getDipoles();
for ( list<DipolePtr>::iterator i = dipoles.begin(); i != dipoles.end(); i++ ) {
for ( list<DipolePtr>::iterator j = otherDips.begin(); j != otherDips.end(); j++ ) {
if ( *i == *j )
j = otherDips.erase(j)--;
}
}
DipolePtr d1, d2;
double maxy = 0.0;
for ( list<DipolePtr>::iterator i = dipoles.begin(); i != dipoles.end(); i++ ) {
for ( list<DipolePtr>::iterator j = otherDips.begin(); j != otherDips.end(); j++ ) {
double R = log( UseRandom::rnd() );
InvEnergy2 a = (*i)->partons().first->dist2(*(*i)->partons().second);
InvEnergy2 b = (*j)->partons().first->dist2(*(*j)->partons().second);
InvEnergy2 c = (*i)->partons().second->dist2(*(*j)->partons().first);
InvEnergy2 d = (*i)->partons().first->dist2(*(*j)->partons().second);
a = sqr(Current<DipoleEventHandler>()->rMax())/
- (Current<DipoleEventHandler>()->alphaS(sqrt(a)))*
+ (Current<DipoleEventHandler>()->alphaSr(sqrt(a)))*
sqr(exp(sqrt(a)/Current<DipoleEventHandler>()->rMax()) - 1.0);
b = sqr(Current<DipoleEventHandler>()->rMax())/
- (Current<DipoleEventHandler>()->alphaS(sqrt(b)))*
+ (Current<DipoleEventHandler>()->alphaSr(sqrt(b)))*
sqr(exp(sqrt(b)/Current<DipoleEventHandler>()->rMax()) - 1.0);
c = sqr(Current<DipoleEventHandler>()->rMax())/
- (Current<DipoleEventHandler>()->alphaS(sqrt(c)))*
+ (Current<DipoleEventHandler>()->alphaSr(sqrt(c)))*
sqr(exp(sqrt(c)/Current<DipoleEventHandler>()->rMax()) - 1.0);
d = sqr(Current<DipoleEventHandler>()->rMax())/
- (Current<DipoleEventHandler>()->alphaS(sqrt(d)))*
+ (Current<DipoleEventHandler>()->alphaSr(sqrt(d)))*
sqr(exp(sqrt(d)/Current<DipoleEventHandler>()->rMax()) - 1.0);
double A = c*d/(a*b);
double y = R*A;
if ( y < maxy || maxy == 0.0 ) {
maxy = y;
d1 = *i;
d2 = *j;
}
}
}
swing(d1, d2);
}
// If needed, insert default implementations of virtual function defined
// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs).
// Static variable needed for the type description system in ThePEG.
#include "ThePEG/Utilities/DescribeClass.h"
DescribeAbstractNoPIOClass<DipoleAbsorber,HandlerBase>
describeDIPSYDipoleAbsorber("DIPSY::DipoleAbsorber", "libAriadne5.so libDIPSY.so");
void DipoleAbsorber::Init() {
static ClassDocumentation<DipoleAbsorber> documentation
("DipoleAbsorber is a base class to be used for models describing how "
"non-interacted dipoles will be reabsorbed.");
}
diff --git a/DIPSY/DipoleEventHandler.cc b/DIPSY/DipoleEventHandler.cc
--- a/DIPSY/DipoleEventHandler.cc
+++ b/DIPSY/DipoleEventHandler.cc
@@ -1,888 +1,898 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the DipoleEventHandler class.
//
#include "DipoleEventHandler.h"
#include "SimpleProtonState.h"
#include "PhotonDipoleState.h"
#include "Parton.h"
#include "OldStyleEmitter.h"
#include "ThePEG/Interface/Switch.h"
#include "PT1DEmitter.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Repository/CurrentGenerator.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Handlers/LuminosityFunction.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/RefVector.h"
#include "ThePEG/Config/algorithm.h"
#include "gsl/gsl_sf_bessel.h"
#include "ThePEG/Utilities/Current.h"
#include "ThePEG/Cuts/Cuts.h"
#include "ThePEG/PDF/PartonExtractor.h"
#include "ThePEG/Utilities/Debug.h"
#include "ThePEG/Utilities/DebugItem.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "CPUTimer.h"
#include <iostream>
#include <fstream>
using namespace DIPSY;
DipoleEventHandler::DipoleEventHandler()
- : EventHandler(false), theNColours(9), theRMax(3.5*InvGeV), thePTScale(2.0),
- theBaryonSize(0.0*InvGeV),
+ : EventHandler(false), theNColours(9), theRMax(3.5*InvGeV), theM0(0.6*GeV),
+ thePTScale(2.0), theBaryonSize(0.0*InvGeV),
theCoherenceRange(0.5*InvGeV), theEffectivePartonMode(0), theCollisionType(0),
doShowHistory(false), theLambdaQCD(0.22*GeV), theNF(0),
theFixedAlphaS(0.0), theExternalAlphaS(ASPtr()),
theWFR(WaveFunctionPtr()), theWFL(WaveFunctionPtr()),
theBGen(ImpactParameterGeneratorPtr()), theYFrame(0.5), theFudgeME(0), theFudgeFactorME(1.0),
thePreSamples(1000), thePreSampleL(1), thePreSampleR(1), thePreSampleB(1),
theXSecFn(DipoleXSecPtr()), theEmitter(EmitterPtr()),
theSwinger(SwingerPtr()) {}
DipoleEventHandler::~DipoleEventHandler() {}
IBPtr DipoleEventHandler::clone() const {
return new_ptr(*this);
}
IBPtr DipoleEventHandler::fullclone() const {
return new_ptr(*this);
}
double DipoleEventHandler::elapsed() {
static long last = 0;
long el = clock() - last;
last += el;
return double(el)*0.000001;
}
void DipoleEventHandler::presample() {
//redirect diffractive runs, as the cross section calculation
//then requires more than a single loop over collisions.
if ( collisionType() == 1 ) return diffractivePresample();
//Set up before the loop
Current<DipoleEventHandler> current(this);
for_each(analyses, mem_fun(&DipoleAnalysisHandler::initialize));
CrossSection xmax = 0.0*picobarn;
CrossSection xnmax = 0.0*picobarn;
elapsed();
generator()->log()
<< endl << "Starting DIPSY run at CoM energy "
<< lumiFn().maximumCMEnergy()/GeV << " GeV" << endl;
//Loop over collisions
for ( int i = 0, N = preSamples(); i < N; ++i ) {
//Setup before collision. Energy, jacobian, luminosity.
Energy W = lumiFn().maximumCMEnergy();
double jac = 1.0;
pair<double,double> ll(1.0, 1.0);
if ( int ndim = lumiFn().nDim(make_pair(WFL().particle(), WFR().particle())) ) {
vector<double> r = UseRandom::rndvec(ndim);
ll = lumiFn().generateLL(&(r[0]), jac);
W *= exp(-0.5*(ll.first + ll.second));
}
//Find the p+ (or p-) of each state.
Energy2 a = WFL().m2() - WFR().m2() + sqr(W);
Energy PL = (a + sqrt(sqr(a) - WFL().m2()*sqr(W)))*0.5/W;
a = WFR().m2() - WFL().m2() + sqr(W);
Energy PR = (a + sqrt(sqr(a) - WFR().m2()*sqr(W)))*0.5/W;
//Create the dipole states and impact parameters.
vector<DipoleStatePtr> vl(preSampleL());
vector<DipoleStatePtr> vr(preSampleR());
vector<ImpactParameters> vb(preSampleB());
vector< vector< vector<double> > >
probs(preSampleL(),
vector< vector<double> >(preSampleR(), vector<double>(preSampleB(), 0.0)));
// Setup a number of left- and right-moving states
double highYL = 0.0;
for ( int il = 0; il < preSampleL(); ++il ) {
DipoleStatePtr dl = WFL().generate(*this, PL);
vl[il] = dl;
dl->collidingEnergy(PR);
highYL += dl->highestY();
}
double highYR = 0.0;
for ( int ir = 0; ir < preSampleR(); ++ir ) {
DipoleStatePtr dr = WFR().generate(*this, PR);
vr[ir] = dr;
dr->collidingEnergy(PL);
highYR += dr->highestY();
}
// Evolve the states
double y0 = interactionFrame(highYL/double(preSampleL()), -highYR/double(preSampleR()));
for ( int il = 0; il < preSampleL(); ++il ) {
vl[il]->evolve(vl[il]->lowestY(), y0);
vl[il]->unifyColourSystems();
}
for ( int ir = 0; ir < preSampleR(); ++ir ) {
vr[ir]->evolve(vr[ir]->lowestY(), -y0);
vr[ir]->unifyColourSystems();
}
for ( int ib = 0; ib < preSampleB(); ++ib ) {
ImpactParameters b = bGen().generate();
vb[ib] = b;
}
for ( int il = 0; il < preSampleL(); ++il )
for ( int ir = 0; ir < preSampleR(); ++ir )
for ( int ib = 0; ib < preSampleB(); ++ib ) {
DipoleStatePtr dl =vl[il];
DipoleStatePtr dr =vr[ir];
ImpactParameters b = vb[ib];
double prob = 0;
//Calculate interaction probability, and apply all the weights
if ( eventFiller().mode() == 4 || effectivePartonMode() < 0 )
prob = xSecFn().sumf(b, *dr, *dl);
else
prob = xSecFn().sumf(*dr, *dl, b);
probs[il][ir][ib] = prob;
CrossSection weight = sqr(hbarc)*dr->weight()*dl->weight()*b.weight()*jac;
//This is the contribution to the non-diffractive
//cross section 1 - exp(-2(amp)^2)
CrossSection x = weight*xSecFn().unitarize(2.0*prob);
if ( x > xmax ) {
xnmax = xmax;
xmax = x;
} else
xnmax = max(x, xnmax);
//Call the analysis (which calculates cross sections)
for ( int i = 0, N = analyses.size(); i < N; ++i )
analyses[i]->analyze(*dr, *dl, b, xSecFn(), prob, weight);
}
// Call the analysis (which calculates cross sections) for all
// systems and impact parameters.
for ( int i = 0, N = analyses.size(); i < N; ++i )
analyses[i]->analyze(vr, vl, vb, xSecFn(), probs, jac);
}
//Write output (also from the called analyses) to log file.
if ( preSamples() > 0 ) {
generator()->log()
<< "Presampled " << preSamples() << " collisions ("
<< elapsed()/max(preSamples(),0) << " seconds per collisions)" << endl
<< "Maximum cross section: "
<< ouniterr(xmax, xmax-xnmax, nanobarn) << " nb." <<endl;
for_each(analyses,
bind2nd(mem_fun(&DipoleAnalysisHandler::finalize),
preSamples()*preSampleL()*preSampleR()*preSampleB()));
generator()->log() << endl;
}
stats = XSecStat(xmax > 0.0*nanobarn? xmax: 1.0*millibarn);
}
void DipoleEventHandler::diffractivePresample() {
//Setup before
Current<DipoleEventHandler> current(this);
for_each(analyses, mem_fun(&DipoleAnalysisHandler::initialize));
CrossSection xmax = 0.0*picobarn;
CrossSection xnmax = 0.0*picobarn;
elapsed();
generator()->log()
<< endl << "Starting Diffractive DIPSY run at CoM energy "
<< lumiFn().maximumCMEnergy()/GeV << " GeV" << endl;
Energy W = lumiFn().maximumCMEnergy();
double jac = 1.0;
pair<double,double> ll(1.0, 1.0);
//Create the starting states from their wavefunction.
if ( int ndim = lumiFn().nDim(make_pair(WFL().particle(), WFR().particle())) ) {
vector<double> r = UseRandom::rndvec(ndim);
ll = lumiFn().generateLL(&(r[0]), jac);
W *= exp(-0.5*(ll.first + ll.second));
}
//Calculate the energy of each incoming state in this frame.
Energy2 a = WFL().m2() - WFR().m2() + sqr(W);
Energy PL = (a + sqrt(sqr(a) - WFL().m2()*sqr(W)))*0.5/W;
a = WFR().m2() - WFL().m2() + sqr(W);
Energy PR = (a + sqrt(sqr(a) - WFR().m2()*sqr(W)))*0.5/W;
//Set up rapidity intervals to evolve over.
double y0 = interactionFrame(-log(PL/sqrt(abs(WFL().m2()))), log(PR/sqrt(abs(WFR().m2()))));
//Pre-generate the virtual cascade, ie the ones from the
//elastic side (right side by default).
vector<DipoleStatePtr> virtualCascades;
for ( int i = 0, N = preSamples(); i < N; i ++ ) {
DipoleStatePtr virt = WFR().generate(*this, PR);
virt->collidingEnergy(PL);
virt->evolve(virt->lowestY(), -y0);
virtualCascades.push_back(virt);
}
CrossSection sigmaSD = ZERO;
QTY<4,0,0>::Type sigmaSD2 = ZERO;
//Now run main loop over the real (excited in final state) cascades.
for ( int i = 0, N = preSamples(); i < N; ++i ) {
DipoleStatePtr dl = WFL().generate(*this, PL);
dl->collidingEnergy(PR);
dl->evolve(dl->lowestY(), y0);
ImpactParameters b = bGen().generate();
double sum = 0.0;
double sumWeights = 0.0;
//Loop over the pregenerated virtual elastic
for ( int j = 0; j < N; j ++ ) {
double amp = xSecFn().unitarize(xSecFn().sumf(*virtualCascades[j], *dl, b));
sum += amp*virtualCascades[j]->weight();
sumWeights += virtualCascades[j]->weight();
}
double average = sum/sumWeights;
//Take statistics on inclusive single diffractive cross section.
CrossSection weight = sqr(hbarc)*dl->weight()*b.weight()*jac;
CrossSection x = weight*average;
sigmaSD += weight*sqr(average);
sigmaSD2 += sqr(weight*sqr(average));
if ( x > xmax ) {
xnmax = xmax;
xmax = x;
} else
xnmax = max(x, xnmax);
//Pass on to analysers.
for ( int j = 0, M = analyses.size(); j < M; ++j )
analyses[j]->analyze(*WFR().generate(*this, PR), *dl, b, xSecFn(), average, weight);
}
//Output results to log file.
if ( preSamples() > 0 ) {
sigmaSD /= preSamples();
sigmaSD2 /= preSamples();
//Estimate error from the fluctuations.
CrossSection err = sqrt((sigmaSD2 - sqr(sigmaSD))/preSamples());
generator()->log()
<< "Presampled " << preSamples() << " real cascades, collided with "
<< preSamples() << " virtual cascades ("
<< elapsed()/max(preSamples(),0) << " seconds per real cascade)" << endl
<< "Maximum cross section: "
<< ouniterr(xmax, xmax-xnmax, nanobarn) << " nb." <<endl
<< "Integrated single diffractive cross section up to y = " << y0
<< " is " << ouniterr(sigmaSD, err, nanobarn) << " nb." <<endl;
for_each(analyses,
bind2nd(mem_fun(&DipoleAnalysisHandler::finalize), preSamples()));
generator()->log() << endl;
}
stats = XSecStat(xmax > 0.0*nanobarn? xmax: 1.0*millibarn);
}
void DipoleEventHandler::initialize() {
Current<DipoleEventHandler> current(this);
theWFL->initialize(*this);
theWFR->initialize(*this);
}
EventPtr DipoleEventHandler::generateEvent() {
//Redirect diffractive events.
if ( collisionType() == 1 ) return generateDiffractiveEvent();
while ( true ) {
Current<DipoleEventHandler> current(this);
//Set up energy, jacobians and wavefunctions.
Energy W = lumiFn().maximumCMEnergy();
double jac = 1.0;
pair<double,double> ll(1.0, 1.0);
if ( int ndim = lumiFn().nDim(make_pair(WFL().particle(), WFR().particle())) ) {
vector<double> r = UseRandom::rndvec(ndim);
ll = lumiFn().generateLL(&(r[0]), jac);
}
//Find lightcone momenta.
Energy2 a = WFL().m2() - WFR().m2() + sqr(W);
Energy PL = (a + sqrt(sqr(a) - 4.0*WFL().m2()*sqr(W)))*0.5/W;
a = WFR().m2() - WFL().m2() + sqr(W);
Energy PR = (a + sqrt(sqr(a) - 4.0*WFR().m2()*sqr(W)))*0.5/W;
PPair inc(WFL().particle()->produceParticle(lightCone(PL, WFL().m2()/PL)),
WFR().particle()->produceParticle(lightCone(WFR().m2()/PR, PR)));
LorentzRotation cmboost =
lumiFn().getBoost()*LorentzRotation(0.0, 0.0, tanh(0.5*(ll.second - ll.first)));
inc.first->transform(cmboost);
inc.second->transform(cmboost);
//Create dipole states.
DipoleStatePtr dr = WFR().generate(*this, PR);
DipoleStatePtr dl = WFL().generate(*this, PL);
//in some settings, the states need to know about the
//energy of the other state.
dr->collidingEnergy(PL);
dl->collidingEnergy(PR);
double y0 = interactionFrame(dl->highestY(), -dr->highestY());
dr->evolve(dr->lowestY(), -y0);
dr->unifyColourSystems();
dl->evolve(dl->lowestY(), y0);
dl->unifyColourSystems();
// This generates the impact parameter depending on the position
//of the partons. Intention was to generate high-pt events more
//often by selecting a b such that two partons would end up
//very close to each other more often. Should work in theory, but
//didn't make as big difference as hoped, maybe due to too many
//of the high pTs coming from the cascade.
// vector<pair<Parton::Point, InvEnergy> > points1 = dl->points();
// vector<pair<Parton::Point, InvEnergy> > points2 = dr->points();
// ImpactParameters b = bGen().generateDynamic(points1, points2);
//Standard impact parameter generation.
ImpactParameters b = bGen().generate();
inc.first->setVertex
(LorentzPoint(hbarc*b.bVec().x()/2, hbarc*b.bVec().y()/2, ZERO, ZERO));
inc.second->setVertex
(LorentzPoint(-hbarc*b.bVec().x()/2, -hbarc*b.bVec().y()/2, ZERO, ZERO));
currentEvent(new_ptr(Event(inc, this, generator()->runName(),
generator()->currentEventNumber(), 1.0)));
currentCollision(new_ptr(Collision(inc, currentEvent(), this)));
if ( currentEvent() ) currentEvent()->addCollision(currentCollision());
currentStep(new_ptr(Step(currentCollision())));
currentCollision()->addStep(currentStep());
double genweight = sqr(hbarc)*dr->weight()*dl->weight()*b.weight()*jac/
stats.maxXSec();
//Pass to filler. This is where the final state is decided.
double prob = eventFiller().fill(*currentStep(), *this, inc, *dl, *dr, b);
double weight = prob*genweight;
stats.select(weight);
currentEvent()->weight(weight);
if ( weight <= 0.0 ) continue;
stats.accept();
try {
initGroups();
continueCollision();
return currentEvent();
}
catch (Veto) {
stats.reject(weight);
}
catch (Stop) {
break;
}
catch (Exception &) {
stats.reject(weight);
throw;
}
}
return currentEvent();
}
EventPtr DipoleEventHandler::generateDiffractiveEvent() {
//Very similar to generateEvent.
while ( true ) {
//Same setup as in the non-diffractive case.
Current<DipoleEventHandler> current(this);
Energy W = lumiFn().maximumCMEnergy();
double jac = 1.0;
pair<double,double> ll(1.0, 1.0);
if ( int ndim = lumiFn().nDim(make_pair(WFL().particle(), WFR().particle())) ) {
vector<double> r = UseRandom::rndvec(ndim);
ll = lumiFn().generateLL(&(r[0]), jac);
}
Energy2 a = WFL().m2() - WFR().m2() + sqr(W);
Energy PL = (a + sqrt(sqr(a) - 4.0*WFL().m2()*sqr(W)))*0.5/W;
a = WFR().m2() - WFL().m2() + sqr(W);
Energy PR = (a + sqrt(sqr(a) - 4.0*WFR().m2()*sqr(W)))*0.5/W;
PPair inc(WFL().particle()->produceParticle(lightCone(PL, WFL().m2()/PL)),
WFR().particle()->produceParticle(lightCone(WFL().m2()/PR, PR)));
LorentzRotation cmboost =
lumiFn().getBoost()*LorentzRotation(0.0, 0.0, tanh(0.5*(ll.second - ll.first)));
inc.first->transform(cmboost);
inc.second->transform(cmboost);
//create real excited valence. Evolution is done in diffFill.
DipoleStatePtr dr = WFL().generate(*this, PL);
//create elastic
DipoleStatePtr de = WFR().generate(*this, PR);
ImpactParameters b = bGen().generate();
inc.first->setVertex
(LorentzPoint(hbarc*b.bVec().x()/2, hbarc*b.bVec().y()/2, ZERO, ZERO));
inc.second->setVertex
(LorentzPoint(-hbarc*b.bVec().x()/2, -hbarc*b.bVec().y()/2, ZERO, ZERO));
currentEvent(new_ptr(Event(inc, this, generator()->runName(),
generator()->currentEventNumber(), 1.0)));
currentCollision(new_ptr(Collision(inc, currentEvent(), this)));
if ( currentEvent() ) currentEvent()->addCollision(currentCollision());
currentStep(new_ptr(Step(currentCollision())));
currentCollision()->addStep(currentStep());
double genweight = sqr(hbarc)*dr->weight()*de->weight()*b.weight()*jac/
stats.maxXSec();
//Call filler, which will be redirected to diffractive version.
double prob = eventFiller().fill(*currentStep(), *this, inc, *dr, *de, b);
double weight = prob*genweight;
if ( weight <= 0.0 ) continue;
if ( isnan(weight) ) {
continue;
}
stats.select(weight);
currentEvent()->weight(weight);
stats.accept();
try {
initGroups();
continueCollision();
return currentEvent();
}
catch (Veto) {
stats.reject(weight);
}
catch (Stop) {
break;
}
catch (Exception &) {
stats.reject(weight);
throw;
}
}
return currentEvent();
}
CrossSection DipoleEventHandler::integratedXSec() const {
return stats.xSec();
}
CrossSection DipoleEventHandler::integratedXSecErr() const {
return stats.xSecErr();
}
CrossSection DipoleEventHandler::maxXSec() const {
return stats.maxXSec();
}
CrossSection DipoleEventHandler::histogramScale() const {
return stats.xSec()/stats.sumWeights();
}
void DipoleEventHandler::statistics(ostream & os) const {
string line = "======================================="
"=======================================\n";
if ( stats.accepted() <= 0 ) {
os << line << "No events generated by event handler '" << name() << "'."
<< endl;
return;
}
os << line << "Statistics for event handler \'" << name() << "\':\n"
<< " "
<< "generated number of Cross-section\n"
<< " "
<< " events attempts (nb)\n";
os << line << "Total:" << setw(42) << stats.accepted() << setw(13)
<< stats.attempts() << setw(17)
<< ouniterr(stats.xSec(), stats.xSecErr(), nanobarn)
<< endl << line;
}
void DipoleEventHandler::doinit() throw(InitException) {
Current<DipoleEventHandler> current(this);
EventHandler::doinit();
}
void DipoleEventHandler::dofinish() {
generator()->log() << endl << "Ending DIPSY run at CoM energy "
<< lumiFn().maximumCMEnergy()/GeV << " GeV" << endl;
theEventFiller->finish();
EventHandler::dofinish();
CPUClock::dump(generator()->log());
}
void DipoleEventHandler::doinitrun() {
Current<DipoleEventHandler> current(this);
EventHandler::doinitrun();
theNErr = 0;
for_each(analyses, mem_fun(&DipoleAnalysisHandler::initrun));
if ( theSwinger ) theSwinger->initrun();
theEmitter->initrun();
theBGen->initrun();
theXSecFn->initrun();
theEventFiller->initrun();
theWFL->initrun();
theWFR->initrun();
if ( externalAlphaS() ) externalAlphaS()->initrun();
presample();
// Fix up a dummy XComb object
Energy emax = lumiFn().maximumCMEnergy();
cuts()->initialize(sqr(emax), 0.0);
cPDPair incoming = make_pair(WFL().particle(), WFR().particle());
PartonPairVec bins = partonExtractor()->getPartons(emax, incoming, *cuts());
theLastXComb = new_ptr(XComb(emax, incoming, this, partonExtractor(),
tCascHdlPtr(), bins[0], cuts()));
theLastXComb->lastSHat(sqr(emax));
theLastXComb->lastY(0.0);
theLastXComb->lastP1P2(make_pair(0.0, 0.0));
theLastXComb->lastL1L2(make_pair(0.0, 0.0));
theLastXComb->lastX1X2(make_pair(1.0, 1.0));
theLastXComb->lastScale(sqr(emax));
theLastXComb->lastAlphaS(1.0);
theLastXComb->lastAlphaEM(1.0/137.0);
partonExtractor()->select(theLastXComb);
}
void DipoleEventHandler::rebind(const TranslationMap & trans) throw(RebindException) {
// dummy = trans.translate(dummy);
EventHandler::rebind(trans);
}
IVector DipoleEventHandler::getReferences() {
IVector ret = EventHandler::getReferences();
// ret.push_back(dummy);
return ret;
}
-double DipoleEventHandler::alphaS(InvEnergy r) const {
+double DipoleEventHandler::alphaS(Energy mu) const {
double alps = 0.0;
+ mu = max(mu, m0());
if ( fixedAlphaS() > 0.0 )
alps = fixedAlphaS();
- else if ( LambdaQCD() > 0.0*GeV && LambdaQCD() < pTScale()/rMax() )
- alps = 6.0*Constants::pi/((33.0 - 2.0*nF())*
- log(pTScale()/(min(r,rMax())*LambdaQCD())));
+ else if ( LambdaQCD() > 0.0*GeV && LambdaQCD() < m0() )
+ alps = 6.0*Constants::pi/((33.0 - 2.0*nF())*log(mu/LambdaQCD()));
else if ( externalAlphaS() )
- alps = externalAlphaS()->value(sqr(pTScale()/min(r,rMax())), SM());
+ alps = externalAlphaS()->value(sqr(mu), SM());
else
- alps = SM().alphaS(sqr(pTScale()/min(r,rMax())));
+ alps = SM().alphaS(sqr(mu));
if ( fixedAlphaS() < 0.0 ) {
alps = min(alps, -fixedAlphaS());
if ( alps < 0.0 ) alps = -fixedAlphaS();
}
return alps;
}
double DipoleEventHandler::interactionFrame(double ymin, double ymax) const {
double yframe = yFrame();
if ( yFrame() < -1.0 && yFrame() >= -1.5 ) {
double dum = -(yFrame() + 1.0);
yframe = UseRandom::rnd(dum, 1.0 - dum);
}
double y0 = ymin + yframe*(ymax - ymin);
if ( y0 > ymax ) y0 = max(ymin, ymax + (1.0 - yframe));
else if ( y0 < ymin ) y0 = min(ymax, ymin + yframe);
return y0;
}
void DipoleEventHandler::persistentOutput(PersistentOStream & os) const {
- os << theNColours << ounit(theRMax, InvGeV) << thePTScale
+ os << theNColours << ounit(theRMax, InvGeV) << ounit(theM0, GeV) << thePTScale
<< ounit(theBaryonSize, InvGeV)
<< ounit(theCoherenceRange, InvGeV)
<< theEffectivePartonMode << theCollisionType << doShowHistory
<< ounit(theLambdaQCD, GeV) << theNF << theFixedAlphaS << theExternalAlphaS
<< theWFR << theWFL << theBGen << theYFrame << theFudgeME << theFudgeFactorME << thePreSamples << thePreSampleL
<< thePreSampleR << thePreSampleB << theXSecFn << theEmitter << theSwinger
<< theEventFiller << analyses << stats;
}
void DipoleEventHandler::persistentInput(PersistentIStream & is, int) {
- is >> theNColours >> iunit(theRMax, InvGeV) >> thePTScale
+ is >> theNColours >> iunit(theRMax, InvGeV) >> iunit(theM0, GeV) >> thePTScale
>> iunit(theBaryonSize, InvGeV)
>> iunit(theCoherenceRange, InvGeV)
>> theEffectivePartonMode >> theCollisionType >> doShowHistory
>> iunit(theLambdaQCD, GeV) >> theNF >> theFixedAlphaS >> theExternalAlphaS
>> theWFR >> theWFL >> theBGen >> theYFrame >> theFudgeME >> theFudgeFactorME >> thePreSamples >> thePreSampleL
>> thePreSampleR >> thePreSampleB >> theXSecFn >> theEmitter >> theSwinger
>> theEventFiller >> analyses >> stats;
}
// Static variable needed for the type description system in ThePEG.
#include "ThePEG/Utilities/DescribeClass.h"
DescribeClass<DipoleEventHandler,EventHandler>
describeDIPSYDipoleEventHandler("DIPSY::DipoleEventHandler",
"libAriadne5.so libDIPSY.so");
void DipoleEventHandler::Init() {
static ClassDocumentation<DipoleEventHandler> documentation
("The DipoleEventHandler is a special EventHandler capable of generating "
"minimum-bias events using the Lund version of the Mueller dipole model.");
static Parameter<DipoleEventHandler,int> interfaceNColours
("NColours",
"The number of different colour indices in the swing mechanism. Should be "
"\\f$N_c^2\\f$ but can be varied to investigate swing effects.",
&DipoleEventHandler::theNColours, 9, 3, 0,
true, false, Interface::lowerlim);
static Parameter<DipoleEventHandler,InvEnergy> interfaceRMax
("RMax",
- "The general hadronic size in units of inverse GeV.",
+ "The general hadronic size in units of inverse GeV. This parameter is overridden "
+ "if <interface>M0</interface> is larger than zero, in which case "
+ "<interface>PTScale</interface>/<interface>M0</interface> is used instead.",
&DipoleEventHandler::theRMax, InvGeV, 3.5*InvGeV, 0.0*InvGeV, 0*InvGeV,
true, false, Interface::lowerlim);
+ static Parameter<DipoleEventHandler,Energy> interfaceM0
+ ("M0",
+ "The non-perturbative scale in GeV. If set to zero or less, "
+ "<interface>PTScale</interface>/<interface>RMax</interface> will be used instead.",
+ &DipoleEventHandler::theM0, GeV, 0.0*GeV, 0.0*GeV, 0.0*GeV,
+ true, false, Interface::lowerlim);
+
+
static Parameter<DipoleEventHandler,double> interfacePTScale
("PTScale",
"The scale used to relate impactparameter distances and transverse "
"momenta. If negative, it is instead taken from the assigned "
"<interface>Emitter::PTScale</interface>.",
&DipoleEventHandler::thePTScale, 2.0, 0, 0,
true, false, Interface::nolimits);
static Parameter<DipoleEventHandler,InvEnergy> interfaceCoherenceRange
("CoherenceRange",
"The maximum range at which partons are allowed to emit coherently."
"This is also used as maximum range in the DGLAP suppression",
&DipoleEventHandler::theCoherenceRange, InvGeV, 0.5*InvGeV, 0.0*InvGeV, 0*InvGeV,
true, false, Interface::lowerlim);
static Switch<DipoleEventHandler,int> interfaceEffectivePartonMode
("EffectivePartonMode",
"How the partons are grouped inteo effective partons.",
&DipoleEventHandler::theEffectivePartonMode, 0, true, false);
static SwitchOption interfaceEffectivePartonModeColours
(interfaceEffectivePartonMode,
"Colours",
"Groups with colour neighbours. Makes more sence since the "
"colour flow determines how the emissions are made, but the "
"swing makes this mode not always group up recoiling partons, "
"which can mess up availible phase space and ordering. "
"This is default.",
0);
static SwitchOption interfaceEffectivePartonModeFastColours
(interfaceEffectivePartonMode,
"FastColours",
"Groups with colour neighbours as for the \"Colour\" option, "
"but speed up the generation by caching different ranges for "
"the same parton.",
2);
static SwitchOption interfaceEffectivePartonModeFastColours2
(interfaceEffectivePartonMode,
"FastColours2",
"Groups with colour neighbours as for the \"FastColour\" option, "
"but speed up the generation by caching different ranges for "
"the same parton.",
3);
static SwitchOption interfaceEffectivePartonModeRelatives
(interfaceEffectivePartonMode,
"Relatives",
"Groups with parents and childs. Always pairs up with the "
"recoiling pt, and should get the phase space and ordering "
"correct, but makes the emissions depend on the history"
", not only current state.",
1);
static SwitchOption interfaceEffectivePartonModeShadows
(interfaceEffectivePartonMode,
"Shadows",
"Don't use Effective partons, use shadow partons instead.",
-1);
static SwitchOption interfaceEffectivePartonModeNewShadows
(interfaceEffectivePartonMode,
"NewShadows",
"Don't use Effective partons, use shadow partons instead.",
-2);
static Switch<DipoleEventHandler,int> interfaceCollisionType
("CollisionType",
"What type of collison.",
&DipoleEventHandler::theCollisionType, 0, true, false);
static SwitchOption interfaceCollisionTypeNonDiffractive
(interfaceCollisionType,
"NonDiffractive",
"Should be self explanatory. :P",
0);
static SwitchOption interfaceTypeSingleDiffractive
(interfaceCollisionType,
"SingleDiffractive",
"Should be self explanatory. :P",
1);
static Parameter<DipoleEventHandler,bool> interfaceShowHistory
("ShowHistory",
"If the history of every event should be studied manually."
"Note that only final state events get studied, not the presamples.",
&DipoleEventHandler::doShowHistory, false, false, false,
true, false, Interface::lowerlim);
static Parameter<DipoleEventHandler,Energy> interfaceLambdaQCD
("LambdaQCD",
"The value of \\f$\\Lambda_{QCD}\\f$ to be used in the running coupling. "
"If zero, the <interface>AlphaS</interface> object will be used for the "
"coupling instead.",
&DipoleEventHandler::theLambdaQCD, GeV, 0.22*GeV, 0.0*GeV, 0*GeV,
true, false, Interface::lowerlim);
static Parameter<DipoleEventHandler,double> interfaceFixedAlphaS
("FixedAlphaS",
"The value of the constant coupling. If zero, a running coupling is "
"assumed.",
&DipoleEventHandler::theFixedAlphaS, 0.0, 0.0, 0,
true, false, Interface::nolimits);
static Reference<DipoleEventHandler,AlphaSBase> interfaceExternalAlphaS
("ExternalAlphaS",
"An external \\f$\\alpha_S\\f$ object to be used if "
"<interface>LambdaQCD</interface> is zero. If null the object "
"specified in the overall StandardModel object will be used insted.",
&DipoleEventHandler::theExternalAlphaS, true, false, true, true, false);
static Parameter<DipoleEventHandler,int> interfaceNF
("NF",
"The number of flavours to be used in the running coupling. Not active "
"if an external running coupling (<interface>ExternalAlphaS</interface> "
"is used.",
&DipoleEventHandler::theNF, 3, 1, 0,
true, false, Interface::lowerlim);
static Reference<DipoleEventHandler,WaveFunction> interfaceWFR
("WFR",
"The wave function of the incoming particle along the positive z-axis.",
&DipoleEventHandler::theWFR, true, false, true, false, false);
static Reference<DipoleEventHandler,WaveFunction> interfaceWFL
("WFL",
"The wave function of the incoming particle along the negative z-axis.",
&DipoleEventHandler::theWFL, true, false, true, false, false);
static Parameter<DipoleEventHandler,double> interfaceYFrame
("YFrametest",
"Indicate in which frame the dipole systems should collide. A value of "
"0.5 means that both systems will be evolved an equal rapidity distance. "
"0.0 (1.0) means that the right(left)-moving system will not be evolved "
"at all while the left(right)-moving system will be evolved as much as "
"possible. A value larger than 1.0 (less than 0.0) means the right-(left-)moving "
"system will be evolved a fixed rapidity interval YFrametest - 1 (-YFrametest)",
&DipoleEventHandler::theYFrame, 0.5, 0.0, 1.0,
true, false, Interface::nolimits);
static Switch<DipoleEventHandler,int> interfaceFudgeME
("FudgeME",
"Indicate whether a fudge factor should be included to tame the high-pt tail "
"according to an approximate matrix element correction.",
&DipoleEventHandler::theFudgeME, 0, true, false);
static SwitchOption interfaceFudgeMEFudge
(interfaceFudgeME,
"Fudge",
"Include fudge factor",
1);
static SwitchOption interfaceFudgeMEFudgeC
(interfaceFudgeME,
"Fudge",
"Include fudge factor and make cross section dependent on the colour "
"indices of the colliding dipoles",
2);
static SwitchOption interfaceFudgeMENoFudge
(interfaceFudgeME,
"NoFudge",
"Do not include fudge factor",
0);
static Parameter<DipoleEventHandler,double> interfaceFudgeFactorME
("FudgeFactorME",
"Extra factor to be applied for high-pt scattering in interactions.",
&DipoleEventHandler::theFudgeFactorME, 1.0, 0.0, 0,
true, false, Interface::lowerlim);
static Parameter<DipoleEventHandler,int> interfacePreSamples
("PreSamples",
"The number of collisions to analyze in the presampling.",
&DipoleEventHandler::thePreSamples, 1000, 0, 0,
true, false, Interface::lowerlim);
static Parameter<DipoleEventHandler,int> interfacePreSampleL
("PreSampleL",
"The number of left-moving systems to generate for each presample.",
&DipoleEventHandler::thePreSampleL, 1, 1, 0,
true, false, Interface::lowerlim);
static Parameter<DipoleEventHandler,int> interfacePreSampleR
("PreSampleR",
"The number of right-moving systems to generate for each presample.",
&DipoleEventHandler::thePreSampleR, 1, 1, 0,
true, false, Interface::lowerlim);
static Parameter<DipoleEventHandler,int> interfacePreSampleB
("PreSampleB",
"The number ofimpact parameters to generate for each presample.",
&DipoleEventHandler::thePreSampleB, 1, 1, 0,
true, false, Interface::lowerlim);
static Reference<DipoleEventHandler,DipoleXSec> interfaceXSecFn
("XSecFn",
"The object responsible for calculating the cross section for two "
"colliding dipole systems.",
&DipoleEventHandler::theXSecFn, true, false, true, false, false);
static Reference<DipoleEventHandler,ImpactParameterGenerator> interfaceBGen
("BGen",
"The object responsible for generating the impact parameters.",
&DipoleEventHandler::theBGen, true, false, true, false, false);
static Reference<DipoleEventHandler,Emitter> interfaceEmitter
("Emitter",
"The object responsible for generating and performing dipole emissions "
"of gluons.",
&DipoleEventHandler::theEmitter, true, false, true, false, false);
static Reference<DipoleEventHandler,Swinger> interfaceSwinger
("Swinger",
"The object responsible for generating and performing dipole swings.",
&DipoleEventHandler::theSwinger, true, false, true, true, false);
static Reference<DipoleEventHandler,EventFiller> interfaceEventFiller
("EventFiller",
"The object responsible for filling an event with final state gluons.",
&DipoleEventHandler::theEventFiller, true, false, true, false, false);
static RefVector<DipoleEventHandler,DipoleAnalysisHandler>
interfaceAnalysisHandlers
("AnalysisHandlers",
"A list of analysis to be performed in the presample phase.",
&DipoleEventHandler::analyses, -1, true, false, true, false, false);
static Parameter<DipoleEventHandler,InvEnergy> interfaceBaryonSize
("BaryonSize",
"The typical size of a baryon to be used by wave functions not "
"defining their own. If zero, <interface>RMax</interface> will "
"be used instead.",
&DipoleEventHandler::theBaryonSize, InvGeV, 0.0*InvGeV, 0.0*InvGeV, 0*InvGeV,
true, false, Interface::lowerlim);
}
diff --git a/DIPSY/DipoleEventHandler.h b/DIPSY/DipoleEventHandler.h
--- a/DIPSY/DipoleEventHandler.h
+++ b/DIPSY/DipoleEventHandler.h
@@ -1,632 +1,660 @@
// -*- C++ -*-
#ifndef DIPSY_DipoleEventHandler_H
#define DIPSY_DipoleEventHandler_H
//
// This is the declaration of the DipoleEventHandler class.
//
#include "ThePEG/Handlers/EventHandler.h"
#include "DipoleEventHandler.fh"
#include "WaveFunction.h"
#include "DipoleXSec.h"
#include "Emitter.h"
#include "Swinger.h"
#include "EventFiller.h"
// #include "DiffractiveEventFiller.h"
#include "ImpactParameterGenerator.h"
#include "DipoleAnalysisHandler.h"
#include "ThePEG/StandardModel/AlphaSBase.h"
#include "ThePEG/StandardModel/StandardModelBase.h"
#include "ThePEG/Utilities/XSecStat.h"
namespace DIPSY {
using namespace ThePEG;
/**
* Here is the documentation of the DipoleEventHandler class.
*
* @see \ref DipoleEventHandlerInterfaces "The interfaces"
* defined for DipoleEventHandler.
*/
class DipoleEventHandler: public EventHandler {
public:
/** Declare a pointer to an AlphaSBase object. */
typedef Ptr<AlphaSBase>::pointer ASPtr;
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
DipoleEventHandler();
/**
* The destructor.
*/
virtual ~DipoleEventHandler();
//@}
public:
/**
* Initialize this event handler and all related objects needed to
* generate events.
*/
virtual void initialize();
/**
* Pre-sample the cross section before generating events.
* This does inclusive cross section for non-diffractive collisions.
* Diffractive inclusive cross sections are redirected.
*/
void presample();
/**
* Pre-sample the single diffractive cross section before
* generating events. This requires a different method, as it
* needs a double loop over events.
*/
void diffractivePresample();
/**
* Generate an event.
*/
virtual EventPtr generateEvent();
/**
* Generate a diffractive event.
*/
virtual EventPtr generateDiffractiveEvent();
/**
* Write out statistics.
*/
virtual void statistics(ostream &) const;
/**
* The total integrated cross section of the processes generated in
* this run.
* @return 0 if no integrated cross section could be estimated.
*/
virtual CrossSection integratedXSec() const;
/**
* The error total integrated cross section of the processes
* generated in this run.
* @return 0 if no integrated cross section could be estimated.
*/
virtual CrossSection integratedXSecErr() const;
/**
* The overestimated cross section ised in the generation.
*/
CrossSection maxXSec() const;
/**
* Histogram scale. A histogram bin which has been filled with the
* weights associated with the Event objects should be scaled by
* this factor to give the correct cross section.
*/
virtual CrossSection histogramScale() const;
/**
- * Return the running coupling for the given size (scale).
+ * Return the running coupling for the given scale.
*/
- double alphaS(InvEnergy r) const;
+ double alphaS(Energy mu) const;
+
+ /**
+ * Return the running coupling for the given size.
+ */
+ inline double alphaSr(InvEnergy r) const {
+ return alphaS(pTScale()/r);
+ }
/** @name Simple access functions. */
//@{
/**
* The number of different colour indices.
*/
inline int nColours() const {
return theNColours;
}
/**
* The general hadronic size.
*/
inline InvEnergy rMax() const {
- return theRMax;
+ return theM0 <= ZERO? theRMax: pTScale()/theM0;
+ }
+
+ /**
+ * The non-perturbative scale.
+ */
+ inline Energy m0() const {
+ return theM0 > ZERO? theM0: pTScale()/theRMax;
}
/**
* Get the typical size of a baryon to be used by wave functions not
* defining their own.
*/
inline InvEnergy baryonSize() const {
return theBaryonSize > ZERO? theBaryonSize: rMax();
}
/**
* The maximum range at which coherent emissions are allowed.
*/
inline InvEnergy coherenceRange() const {
return theCoherenceRange;
}
/**
* Return the effective parton mode.
*/
inline int effectivePartonMode() const {
return theEffectivePartonMode;
}
/**
* Return the collision type.
*/
inline int collisionType() const {
return theCollisionType;
}
/**
* The value of \f$\Lambda_{QCD}\f$ to be used in the running coupling.
*/
inline Energy LambdaQCD() const {
return theLambdaQCD;
}
/**
* The number of flavours to be used in the running coupling.
*/
inline int nF() const {
return theNF;
}
/**
* The value of the constant coupling. If zero, a running coupling is assumed.
*/
inline double fixedAlphaS() const {
return theFixedAlphaS;
}
/**
* An external \f$\alpha_S\f$ object to be used if LambdaQCD() is zero.
*/
inline ASPtr externalAlphaS() const {
return theExternalAlphaS;
}
/**
* Alpha bar = alphas*Nc/pi
*/
- inline double alphaBar(InvEnergy r) const {
- return alphaS(r)*3.0/M_PI;
+ inline double alphaBarr(InvEnergy r) const {
+ return alphaSr(r)*3.0/M_PI;
+ }
+
+ /**
+ * Alpha bar = alphas*Nc/pi
+ */
+ inline double alphaBar(Energy mu) const {
+ return alphaS(mu)*3.0/M_PI;
}
/**
* Get the wave function of the incoming particle along the positive z-axis.
*/
inline WaveFunction & WFR() const {
return *theWFR;
}
/**
* Get the wave function of the incoming particle along the negative z-axis.
*/
inline WaveFunction & WFL() const {
return *theWFL;
}
/**
* Get the object responsible for generating the impact parameters.
*/
inline const ImpactParameterGenerator & bGen() const {
return *theBGen;
}
/**
* Indicate whether a fudge factor should be included to tame the
* high-pt tail according to an approximate matrix element
* correction.
*/
inline int fudgeME() const {
return theFudgeME;
}
/**
* Indicate whether an additional fudge factor should be included to tame the
* high-pt tail in the interactions.
*/
inline double fudgeFactorME() const {
return theFudgeFactorME;
}
/**
* Indicate in which frame the dipole systems should collide.
*/
inline double yFrame() const {
return theYFrame;
}
/**
* Return the rapidity to use for the interaction frame.
*/
double interactionFrame(double ymin, double ymax) const;
/**
* Get the number of collisions to analyze in the presampling.
*/
inline int preSamples() const {
return thePreSamples;
}
/**
* The number of left-moving systems to generate for each presample.
*/
inline int preSampleL() const {
return thePreSampleL;
}
/**
* The number of right-moving systems to generate for each presample.
*/
inline int preSampleR() const {
return thePreSampleR;
}
/**
* The number of impact parameters to generate for each presample.
*/
inline int preSampleB() const {
return thePreSampleB;
}
/**
* Get the object responsible for calculating the cross section for
* two colliding dipole systems.
*/
inline const DipoleXSec & xSecFn() const {
return *theXSecFn;
}
/**
* Get the object responsible for generating and performing dipole
* emissions of gluons.
*/
inline const Emitter & emitter() const {
return *theEmitter;
}
/**
* Get the scale used to convert between impact parameters and
* transverse momenta.
*/
double pTScale() const {
return thePTScale > 0? thePTScale: emitter().pTScale();
}
/**
* Set the object responsible for generating and performing dipole
* emissions of gluons.
* Added by CF to access from emitter.
*/
inline void emitter(EmitterPtr em) {
theEmitter = em;
}
/**
* Set the object responsible for generating and performing dipole
* swings.
* Added by CF to access from emitter.
*/
inline void swinger(SwingerPtr sw) {
theSwinger = sw;
}
/**
* Get the object responsible for generating and performing dipole swings.
*/
inline const Swinger & swinger() const {
return *theSwinger;
}
/**
* Get the object responsible for generating and performing dipole swings.
*/
inline tSwingerPtr swingPtr() const {
return theSwinger;
}
/**
* Get the object responsible for filling an event with final state gluons.
*/
inline const EventFiller & eventFiller() const {
return *theEventFiller;
}
// /**
// * Get the object responsible for filling an event with final state gluons.
// */
// inline const DiffractiveEventFiller & diffractiveEventFiller() const {
// return *theDiffractiveEventFiller;
// };
/**
* adds an error to the counter
**/
inline void err() const {
theNErr++;
};
/**
* returns teh number of errors so far.
**/
inline const long nErr() const {
return theNErr;
};
//@}
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:
/**
* The number of different colour indices.
*/
int theNColours;
/**
* The general hadronic size.
*/
InvEnergy theRMax;
/**
+ * The Non-perturbative scale correponding to a small gluon mass. If
+ * zero or less it is instead given by thePTScale/theRMax.
+ */
+ Energy theM0;
+
+
+ /**
* The scale used to relate impactparameter distances and transverse
* momenta.
*/
double thePTScale;
/**
* The typical size of a baryon to be used by wave functions not
- * defining their own. If zero, theRMax will be used instead.
+ * defining their own. If zero, theRMax or theM0 will be used instead.
*/
InvEnergy theBaryonSize;
/**
* The maximum range at which partons can emit coherently as effective partons.
*/
InvEnergy theCoherenceRange;
/**
* The way the partons are grouped into effective partons.
*/
int theEffectivePartonMode;
/**
* The type of collison. 0: non diffractive, 1: single diffractive
*/
int theCollisionType;
/**
* if the history of every event should be studied manually.
*/
bool doShowHistory;
/**
* The value of \f$\Lambda_{QCD}\f$ to be used in the running coupling.
*/
Energy theLambdaQCD;
/**
* The number of flavours to be used in the running coupling.
*/
int theNF;
/**
* The value of the constant coupling. If zero, a running coupling is assumed.
*/
double theFixedAlphaS;
/**
* An external \f$\alpha_S\f$ object to be used if LambdaQCD() is zero.
*/
ASPtr theExternalAlphaS;
/**
* The wave function of the incoming particle along the positive z-axis.
*/
WaveFunctionPtr theWFR;
/**
* The wave function of the incoming particle along the negative z-axis.
*/
WaveFunctionPtr theWFL;
/**
* The object responsible for generating the impact parameters.
*/
ImpactParameterGeneratorPtr theBGen;
/**
* Indicate in which frame the dipole systems should collide.
*/
double theYFrame;
/**
* Indicate whether a fudge factor should be included to tame the
* high-pt tail according to an approximate matrix element correction,
* and, if so, should the dipole colours be taken into account.
*/
int theFudgeME;
/**
* Indicate whether an extra fudge factor should be included to tame
* the high-pt tail in the interactions according to an approximate
* matrix element correction.
*/
double theFudgeFactorME;
/**
* The number of collisions to analyze in the presampling.
*/
int thePreSamples;
/**
* The number of left-moving systems generated for each presample.
*/
int thePreSampleL;
/**
* The number of right-moving systems generated for each presample.
*/
int thePreSampleR;
/**
* The number of impact parameters generated for each presample.
*/
int thePreSampleB;
/**
* The object responsible for calculating the cross section for two
* colliding dipole systems.
*/
DipoleXSecPtr theXSecFn;
/**
* The object responsible for generating and performing dipole
* emissions of gluons.
*/
EmitterPtr theEmitter;
/**
* The object responsible for generating and performing dipole swings.
*/
SwingerPtr theSwinger;
/**
* The object responsible for filling an event with final state gluons.
*/
EventFillerPtr theEventFiller;
// /**
// * The object responsible for filling an event with diffractive final state gluons.
// */
// DiffractiveEventFillerPtr theDiffractiveEventFiller;
/**
* A list of analysis objects to be applied in the presample phase.
*/
vector<DipoleAnalysisHandlerPtr> analyses;
/**
* Collect statistics.
*/
XSecStat stats;
/**
* The number of error messages.
**/
mutable long theNErr;
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit() throw(InitException);
/**
* Initialize this object. Called in the run phase just before
* a run begins.
*/
virtual void doinitrun();
/**
* Finalize this object. Called in the run phase just after a
* run has ended. Used eg. to write out statistics.
*/
virtual void dofinish();
/**
* Rebind pointer to other Interfaced objects. Called in the setup phase
* after all objects used in an EventGenerator has been cloned so that
* the pointers will refer to the cloned objects afterwards.
* @param trans a TranslationMap relating the original objects to
* their respective clones.
* @throws RebindException if no cloned object was found for a given
* pointer.
*/
virtual void rebind(const TranslationMap & trans) throw(RebindException);
/**
* Return a vector of all pointers to Interfaced objects used in this
* object.
* @return a vector of pointers.
*/
virtual IVector getReferences();
//@}
public:
/** Return the elapsed number of seconds since lat call. */
static double elapsed();
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
DipoleEventHandler & operator=(const DipoleEventHandler &);
};
}
#endif /* DIPSY_DipoleEventHandler_H */
diff --git a/DIPSY/DipoleXSec.cc b/DIPSY/DipoleXSec.cc
--- a/DIPSY/DipoleXSec.cc
+++ b/DIPSY/DipoleXSec.cc
@@ -1,2196 +1,2196 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the DipoleXSec class.
//
#include "DipoleXSec.h"
#include "Dipole.h"
#include "DipoleState.h"
#include "Parton.h"
#include "DipoleEventHandler.h"
#include "RealParton.h"
#include "RealPartonState.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Utilities/Current.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Repository/CurrentGenerator.h"
#include "ThePEG/Utilities/Debug.h"
#include "ThePEG/Utilities/DebugItem.h"
#include "ThePEG/Utilities/Throw.h"
#ifdef ThePEG_TEMPLATES_IN_CC_FILE
// #include "DipoleXSec.tcc"
#endif
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "gsl/gsl_sf_bessel.h"
using namespace ThePEG;
using namespace DIPSY;
DipoleXSec::~DipoleXSec() {}
DipoleInteraction::DipoleInteraction(Dipole & dlin, Dipole & drin,
const ImpactParameters & bin, int ordering)
: dips(&dlin, &drin), dnext(dlin.neighbors().first, drin.neighbors().first),
dprev(dlin.neighbors().second, drin.neighbors().second),
b(&bin), sints(tSPartonPtr(), tSPartonPtr()),
f2(0.0), uf2(0.0), norec(false), kt(ZERO), prob(0.0), id(0),
status(UNKNOWN), intOrdering(ordering) {
static DebugItem attraction("DIPSY::Attraction", 9);
// If different colours interaction is either between c-c or
// cbar-cbar. If the same colour we only haver c-cbar.
ints = make_pair(dlin.partons().first, drin.partons().first);
spec = make_pair(dlin.partons().second, drin.partons().second);
if ( dlin.colour() == drin.colour() ) {
// if ( UseRandom::rnd() > 0.5 )
if ( UseRandom::rndbool() )
swap(ints.second, spec.second);
else
swap(ints.first, spec.first);
}
if ( Current<DipoleEventHandler>()->eventFiller().compat ) {
// *** TODO *** debugging to be removed!
InvEnergy2 rr11 = bin.dist2(*dlin.partons().first, *drin.partons().first);
InvEnergy2 rr22 = bin.dist2(*dlin.partons().second, *drin.partons().second);
double dummy = (rr11 + rr22)*GeV2;
while ( dummy > 100 ) dummy /= 10;
if ( 1000000.0*dummy - long(1000000.0*dummy) > 0.5 ) {
swap(ints.first, spec.first);
swap(ints.second, spec.second);
}
} else {
// if ( UseRandom::rnd() < 0.5 ) {
if ( UseRandom::rndbool() ) {
swap(ints.first, spec.first);
swap(ints.second, spec.second);
}
}
Parton::Point r =
bin.difference(ints.first->position(), ints.second->position());
d2 = min(min(r.pt2(), dlin.size2()), drin.size2());
// kt = 1.0/sqrt(d2);
rec = -Current<DipoleEventHandler>()->xSecFn().pTScale()*r/r.pt2();
if ( attraction && dlin.colour() == drin.colour() ) rec = -rec;
kt = rec.pt();
if ( ints.first->shadow() ) {
sints = make_pair(ints.first->shadow()->resolveInteraction(d2, spec.first),
ints.second->shadow()->resolveInteraction(d2, spec.second));
}
}
void DipoleInteraction::prepare() const {
sints = make_pair(ints.first->shadow()->resolveInteraction(d2, spec.first),
ints.second->shadow()->resolveInteraction(d2, spec.second));
sints.first->insertInteraction(id);
sints.second->insertInteraction(id);
}
void DipoleInteraction::debug() const {
sints.first->memememe = sints.second->memememe = true;
ints.first->shadow()->memememe = ints.second->shadow()->memememe = true;
TransverseMomentum rrec;
if ( !norec ) rrec = rec;
cerr << setw(15) << rrec.x()/GeV << setw(15) << rrec.y()/GeV << endl;
dips.first->dipoleState().debugShadowTree();
rrec = b->invRotatePT(-rrec);
cerr << setw(15) << rrec.x()/GeV << setw(15) << rrec.y()/GeV << endl;
dips.second->dipoleState().debugShadowTree();
sints.first->memememe = sints.second->memememe = false;
ints.first->shadow()->memememe = ints.second->shadow()->memememe = false;
list<PartonPtr> plist = dips.first->dipoleState().getPartons();
LorentzMomentum sum;
for ( list<PartonPtr>::iterator it = plist.begin(); it != plist.end(); ++it )
if ( (**it).onShell() ) sum += (**it).momentum();
cerr << "left: "
<< setw(15) << sum.x()/GeV << setw(15) << sum.y()/GeV
<< setw(15) << sum.z()/GeV << setw(15) << sum.t()/GeV << endl;
plist = dips.second->dipoleState().getPartons();
sum = LorentzMomentum();
for ( list<PartonPtr>::iterator it = plist.begin(); it != plist.end(); ++it )
if ( (**it).onShell() ) sum += (**it).momentum();
TransverseMomentum sumt = b->rotatePT(TransverseMomentum(sum.x(), sum.y()));
cerr << "right: "
<< setw(15) << sumt.x()/GeV << setw(15) << sumt.y()/GeV
<< setw(15) << sum.z()/GeV << setw(15) << sum.t()/GeV << endl;
}
void DipoleInteraction::fail(int i ) const {
int off = i < 0? 4: 0;
if ( i > 0 ) status = ORDERING;
else {
if ( ints.first == dips.first->partons().first &&
ints.second == dips.second->partons().first )
i = 10;
else if ( ints.first == dips.first->partons().first )
i = 11;
else if ( ints.second == dips.second->partons().first )
i = 12;
else
i = 13;
}
i += off;
++ofail[i];
if ( uf2 > 0.2 ) ++o1fail[i];
}
// *** TODO *** Remove status, it is only for debugging.
DipoleInteraction::Status DipoleInteraction::check(int mode) const {
static DebugItem breakme("DIPSY::Stop", 6);
static DebugItem no2ndrec("DIPSY::No2ndRec", 6);
if ( mode >= 0 && breakme ) breakThePEG();
status = UNKNOWN;
sints = make_pair(ints.first->shadow()->resolveInteraction(d2, spec.first),
ints.second->shadow()->resolveInteraction(d2, spec.second));
if ( id > 1 && ( !sints.first->checkInteractionRoot(id) ||
!sints.second->checkInteractionRoot(id) ) )
return status = PROPFAIL;
ShadowParton::Propagator ppl =
sints.first->propagator(d2, spec.first, mode);
ShadowParton::Propagator ppr =
sints.second->propagator(d2, spec.second, mode);
fail(-1);
if ( ppl.fail || ppr.fail ) return status = PROPFAIL;
LorentzMomentum pl = ppl.p;
LorentzMomentum pr = ppr.p;
if ( mode >= 0 ) {
TransverseMomentum ptr0(pr.x(), pr.y());
checkShadowMomentum(pl + lightCone(pr.minus(), pr.plus(),
b->rotatePT(ptr0)));
}
TransverseMomentum rrec;
if ( !norec ) rrec = rec;
TransverseMomentum ptl =
TransverseMomentum(pl.x(), pl.y()) + rrec;
Energy2 mtl2 = ptl.pt2() + sqr(sints.first->mass());
TransverseMomentum ptr =
TransverseMomentum(pr.x(), pr.y()) + b->invRotatePT(-rrec);
Energy2 mtr2 = ptr.pt2() + sqr(sints.second->mass());
Energy PP = pl.plus() + pr.minus();
Energy PM = pl.minus() + pr.plus();
if ( PP <= ZERO || PM <= ZERO ) return status = PROPFAIL;
if ( PP*PM + mtl2 - mtr2 < ZERO || PP*PM + mtr2 - mtl2 < ZERO ) {
if ( id <= 1 || !no2ndrec ) return status = KINEFAIL;
ptl = TransverseMomentum(pl.x(), pl.y());
mtl2 = ptl.pt2() + sqr(sints.first->mass());
ptr = TransverseMomentum(pr.x(), pr.y());
mtr2 = ptr.pt2() + sqr(sints.second->mass());
if ( PP*PM + mtl2 - mtr2 < ZERO || PP*PM + mtr2 - mtl2 < ZERO )
return status = KINEFAIL;
}
Energy2 sqrl = (sqr(PP*PM + mtl2 - mtr2) - 4.0*mtl2*PM*PP)/sqr(PM);
Energy2 sqrr = (sqr(PP*PM + mtr2 - mtl2) - 4.0*mtr2*PM*PP)/sqr(PP);
if ( sqrl < ZERO || sqrr < ZERO ) {
if ( id <= 1 || !no2ndrec ) return status = KINEFAIL;
ptl = TransverseMomentum(pl.x(), pl.y());
mtl2 = ptl.pt2() + sqr(sints.first->mass());
ptr = TransverseMomentum(pr.x(), pr.y());
mtr2 = ptr.pt2() + sqr(sints.second->mass());
return status = KINEFAIL;
if ( sqrl < ZERO || sqrr < ZERO ) return status = KINEFAIL;
}
sints.first->pTplus(ptl, 0.5*(PP + mtl2/PM - mtr2/PM + sqrt(sqrl)));
sints.second->pTplus(ptr, 0.5*(PM + mtr2/PP - mtl2/PP + sqrt(sqrr)));
if ( intOrdering <= 2 ) {
if ( PP > min(ppl.colpos, ppl.acopos) ||
PM > min(ppr.colpos, ppr.acopos) ) return status = ORDERING;
} else if ( intOrdering >= 4 ) {
if ( orderfail(ppl, ppr) ) return status = ORDERING;
}
if ( mode < 0 && intOrdering == 5 ) {
kt = max(ppl.maxkt, ppr.maxkt);
kt = max(kt, (ppl.p - sints.first->momentum()).perp());
}
if ( !id ) return status = ACCEPTED;
sints.first->setOnShell(mode);
sints.second->setOnShell(mode);
if ( mode >= 0 ) {
sints.first->interacting(id);
sints.first->acceptInteraction(id);
sints.second->interacting(id);
sints.second->acceptInteraction(id);
}
if ( mode > 0 ) {
sints.first->original()->interact(true);
sints.second->original()->interact(true);
// *** TODO *** tobe removed- only for debugging
- InvEnergy2 res = d2*Current<DipoleEventHandler>()->alphaS(sqrt(d2));
+ InvEnergy2 res = d2*Current<DipoleEventHandler>()->alphaSr(sqrt(d2));
if ( max(ptl.pt(), ptr.pt()) > 10.0*GeV && res > ZERO ) breakThePEG();
}
if ( mode >= 0 ) checkShadowMomentum();
return status = ACCEPTED;
}
void DipoleInteraction::checkShadowMomentum(const LorentzMomentum & pin) const {
static DebugItem checkkinematics("DIPSY::CheckKinematics", 6);
if ( !checkkinematics ) return;
Sum20Momentum sum20;
dips.first->dipoleState().checkShadowMomentum(sum20);
dips.second->dipoleState().checkShadowMomentum(sum20, b);
sum20 -= pin;
if ( !sum20 ) {
Throw<InteractionKinematicException>()
<< "Shadow trees had inconsistent momentum" << Exception::warning;
debug();
}
}
bool DipoleInteraction::orderfail(const ShadowParton::Propagator & ppl,
const ShadowParton::Propagator & ppr) const {
pair<bool,bool> parcol(ints.first == dips.first->partons().first,
ints.second == dips.second->partons().first);
Energy2 ptl = ppl.p.perp2();
Energy2 ptr = ppr.p.perp2();
Energy2 ptm = (ppl.p - sints.first->momentum()).perp2();
Energy2 ptlm = max(ptl, ptm);
Energy2 ptrm = max(ptr, ptm);
fail(0);
if ( parcol.first && disorder(cending(ppl.acoptp, ptl, ptm),
ppl.acopos, ppl.aconeg, sints.first) )
// If left is coloured it should be ordered wrt. previous emissions
// on the anti-colour line.
fail(1);
if ( !parcol.first && disorder(cending(ppl.colptp, ptl, ptm),
ppl.colpos, ppl.colneg, sints.first) )
// And vice vers.
fail(2);
if ( parcol.second && disorder(cending(ppr.acoptp, ptr, ptm),
ppr.acopos, ppr.aconeg, sints.second) )
// If right is coloured it should be ordered wrt. previous emissions
// on the anti-colour line.
fail(3);
if ( !parcol.second && disorder(cending(ppr.colptp, ptr, ptm),
ppr.colpos, ppr.colneg, sints.second) )
// And vice vers.
fail(4);
if ( parcol.first != parcol.second && disorder(cending(ptl, ptm, ptr)) )
// If colour--anto-colour combinations,left and right should be
// ordered wrt. eachother
fail(5);
if ( parcol.first && parcol.second ) {
// If both partons are coloured they should be ordered wrt. the
// others incoming emissions on the colour line.
if ( disorder(cending(ppl.colptp, ptlm, ppr.colptp),
sints.first, ppr.colneg, ppr.colpos) )
fail(6);
if ( disorder(cending(ppr.colptp, ptrm, ppl.colptp),
sints.second, ppl.colneg, ppl.colpos) )
fail(7);
}
if ( !parcol.first && !parcol.second ) {
// ... and vice versa for anti.colour - anti-colour
if ( disorder(cending(ppl.acoptp, ptlm, ppr.acoptp),
sints.first, ppr.aconeg, ppr.acopos) )
fail(8);
if ( disorder(cending(ppr.acoptp, ptrm, ppl.acoptp),
sints.second, ppl.aconeg, ppl.acopos) )
fail(9);
}
return ( status == ORDERING );
}
void DipoleInteraction::reject() const {
ints.first->shadow()->rejectInteraction(id);
ints.second->shadow()->rejectInteraction(id);
}
void DipoleInteraction::accept() const {
sints = make_pair(ints.first->shadow()->resolveInteraction(d2, spec.first),
ints.second->shadow()->resolveInteraction(d2, spec.second));
}
InvEnergy DipoleXSec::rMax() const {
return theRMax > 0.0*InvGeV? theRMax:
( theRMax == ZERO? Current<DipoleEventHandler>()->rMax():
Current<DipoleEventHandler>()->emitter().rMax());
}
double DipoleXSec::pTScale() const {
return thePTScale > 0.0? thePTScale:
Current<DipoleEventHandler>()->emitter().pTScale();
}
double DipoleXSec::fSinFn(const Parton::Point & rho1, const Parton::Point & rho2,
const TransverseMomentum & pt) const {
if ( sinFunction == 1 ) {
double r1 = rho1.pt2()*pt.pt2();
double r2 = rho2.pt2()*pt.pt2();
return r1*r2/(4.0*(r1 + 1.0)*(r2 + 1.0));
}
double s1 = pt.x()*rho1.x() + pt.y()*rho1.y();
double s2 = pt.x()*rho2.x() + pt.y()*rho2.y();
if ( sinFunction == 2 ) return sqr(sin(s1)*sin(s2))/sqr(pTScale());
return sqr(sin(s1)*sin(s2));
}
double DipoleXSec::
fij(const pair<tPartonPtr, tPartonPtr> left,
const pair<tPartonPtr, tPartonPtr> right,
const ImpactParameters & b, bool veto) const {
Nfij++;
tcPartonPtr p11 = left.first;
tcPartonPtr p12 = left.second;
tcPartonPtr p21 = right.first;
tcPartonPtr p22 = right.second;
//TODO: keep only interaction 0, as that is the only one supported anyway
if ( theInteraction == 0 || theInteraction == 1 || theInteraction == 3 || theInteraction == 4 ) {
InvEnergy2 rr11 = b.dist2(*p11, *p21);
InvEnergy2 rr21 = b.dist2(*p12, *p21);
InvEnergy2 rr12 = b.dist2(*p11, *p22);
InvEnergy2 rr22 = b.dist2(*p12, *p22);
if ( veto && kinematicsVeto(left, right, b) ) {
return 0.0;
}
TransverseMomentum pt;
InvEnergy rscale = sqrt(min(min(min(rr12, rr21),min(rr11, rr22)),
min(p11->dist2(*p12), p21->dist2(*p22))));
double fudgeME= 1.0;
if ( theInteraction == 0 ) {
pair<bool, bool> ints;
ints = int0Partons(p11, p12, p21, p22, b);
Parton::Point r1 = b.difference((ints.first ? p11->position():p12->position()),
(ints.second ? p21->position():p22->position()));
if ( r1.pt2() < min(p11->dist2(*p12), p21->dist2(*p22)) &&
Current<DipoleEventHandler>()->fudgeME() ) {
double deltay = ( ints.first? p11->y(): p12->y() ) +
( ints.second? p21->y(): p22->y() );
fudgeME = 1.0 - 1.0/(1.0 + cosh(deltay));
fudgeME *= Current<DipoleEventHandler>()->fudgeFactorME();
}
pt = pTScale()*r1/r1.pt2();
rscale = sqrt(min(min(r1.pt2(),p11->dist2(*p12)), p21->dist2(*p22)));
}
if ( theInteraction == 1 ) { //4 parton distance
Parton::Point r1 = b.difference(p11->position(), p21->position());
Parton::Point r2 = b.difference(p11->position(), p22->position());
Parton::Point r3 = b.difference(p12->position(), p21->position());
Parton::Point r4 = b.difference(p12->position(), p22->position());
pt = pTScale()*(r1/sqr(r1.pt()) + r2/sqr(r2.pt()) +
r3/sqr(r3.pt()) + r4/sqr(r4.pt()))*0.35;
}
if ( theInteraction == 3 ) { //2 parton distance
Parton::Point r1 = b.difference(p11->position(), p22->position());
Parton::Point r2 = b.difference(p12->position(), p21->position());
pt = pTScale()*(r1/sqr(r1.pt()) + r2/sqr(r2.pt()))*0.6;
}
Parton::Point rho1 = (p12->position() - p11->position())/2.0;
Parton::Point rho2 = b.rotate(p22->position() - p21->position())/2.0;
- return 8.0*fudgeME*sqr(Current<DipoleEventHandler>()->alphaS(rscale))*
+ return 8.0*fudgeME*sqr(Current<DipoleEventHandler>()->alphaSr(rscale))*
fSinFn(rho1, rho2, pt)*
sqr(sqr(pt.pt()))/sqr(sqr(pt.pt()) + sqr(pTScale()/rMax()));
}
return 0.0;
}
double DipoleXSec::
fij(const Dipole & dleft, const Dipole & dright,
const ImpactParameters & b, bool veto) const {
pair<tPartonPtr, tPartonPtr> left = dleft.partons();
pair<tPartonPtr, tPartonPtr> right = dright.partons();
pair<bool, bool> ints;
Nfij++;
double fudgeME = 1.0;
tcPartonPtr p11 = left.first;
tcPartonPtr p12 = left.second;
tcPartonPtr p21 = right.first;
tcPartonPtr p22 = right.second;
ints = int0Partons(p11, p12, p21, p22, b);
//TODO: keep only interaction 0, as that is the only one supported anyway
if ( theInteraction == 0 || theInteraction == 1 || theInteraction == 3 || theInteraction == 4 ) {
InvEnergy2 rr11 = b.dist2(*p11, *p21);
InvEnergy2 rr21 = b.dist2(*p12, *p21);
InvEnergy2 rr12 = b.dist2(*p11, *p22);
InvEnergy2 rr22 = b.dist2(*p12, *p22);
if ( veto && kinematicsVeto(dleft, dright, b, ints) ) {
return 0.0;
}
TransverseMomentum pt;
InvEnergy rscale = sqrt(min(min(min(rr12, rr21),min(rr11, rr22)),
min(p11->dist2(*p12), p21->dist2(*p22))));
if ( theInteraction == 0 ) {
Parton::Point r1 = b.difference((ints.first ? p11->position():p12->position()),
(ints.second ? p21->position():p22->position()));
if ( r1.pt2() < min(p11->dist2(*p12), p21->dist2(*p22)) &&
Current<DipoleEventHandler>()->fudgeME() ) {
double deltay = ( ints.first? p11->y(): p12->y() ) +
( ints.second? p21->y(): p22->y() );
fudgeME = 1.0 - 1.0/(1.0 + cosh(deltay));
}
if ( Current<DipoleEventHandler>()->fudgeME() > 1 ) {
if ( dleft.colour() == dright.colour() ) fudgeME *= 9.0/2.0;
else fudgeME *= 9.0/16.0;
}
pt = pTScale()*r1/sqr(r1.pt());
rscale = sqrt(min(min(sqr(r1.pt()),p11->dist2(*p12)), p21->dist2(*p22)));
}
if ( theInteraction == 1 ) { //4 parton distance
Parton::Point r1 = b.difference(p11->position(), p21->position());
Parton::Point r2 = b.difference(p11->position(), p22->position());
Parton::Point r3 = b.difference(p12->position(), p21->position());
Parton::Point r4 = b.difference(p12->position(), p22->position());
pt = pTScale()*(r1/sqr(r1.pt()) + r2/sqr(r2.pt()) +
r3/sqr(r3.pt()) + r4/sqr(r4.pt()))*0.35;
}
if ( theInteraction == 3 ) { //2 parton distance
Parton::Point r1 = b.difference(p11->position(), p22->position());
Parton::Point r2 = b.difference(p12->position(), p21->position());
pt = pTScale()*(r1/sqr(r1.pt()) + r2/sqr(r2.pt()))*0.6;
}
Parton::Point rho1 = (p12->position() - p11->position())/2.0;
Parton::Point rho2 = b.rotate(p22->position() - p21->position())/2.0;
- return 8.0*fudgeME*sqr(Current<DipoleEventHandler>()->alphaS(rscale))*
+ return 8.0*fudgeME*sqr(Current<DipoleEventHandler>()->alphaSr(rscale))*
fSinFn(rho1, rho2, pt)*
sqr(sqr(pt.pt()))/sqr(sqr(pt.pt()) + sqr(pTScale()/rMax()));
}
return 0.0;
}
DipoleInteraction DipoleXSec::
fij(const ImpactParameters & b, Dipole & dleft, Dipole & dright,
bool veto) const {
DipoleInteraction di(dleft, dright, b, theIntOrdering);
Nfij++;
double fudgeME = 1.0;
if ( veto && kinematicsVeto(di) ) return di;
Energy m0 = pTScale()/rMax();
Parton::Point r1 = b.difference(di.ints.first->position(), di.ints.second->position());
if ( r1.pt2() < min(dleft.size2(), dright.size2()) &&
Current<DipoleEventHandler>()->fudgeME() ) {
double deltay = di.ints.first->y() + di.ints.second->y();
fudgeME = 1.0 - 1.0/(1.0 + cosh(deltay));
fudgeME *= Current<DipoleEventHandler>()->fudgeFactorME();
}
if ( Current<DipoleEventHandler>()->fudgeME() > 1 ) {
if ( dleft.colour() == dright.colour() ) fudgeME *= 9.0/2.0;
else fudgeME *= 9.0/16.0;
}
Parton::Point rho1 = di.dips.first->vSize()/2.0;
Parton::Point rho2 = b.rotate(di.dips.second->vSize())/2.0;
- di.f2 = 16.0*fudgeME*sqr(Current<DipoleEventHandler>()->alphaS(sqrt(di.d2)))*
+ di.f2 = 16.0*fudgeME*sqr(Current<DipoleEventHandler>()->alphaSr(sqrt(di.d2)))*
fSinFn(rho1, rho2, di.rec)*sqr(di.rec.pt2())/sqr(di.rec.pt2() + sqr(m0));
if ( ktpow > 0.0 ) {
Energy kt = di.rec.pt();
if ( kt > kt0 )
// di.rec *= (kt0 + (kt - kt0)*pow(sqr(kt0)/(sqr(kt0)+sqr(kt)), ktpow))/kt;
di.rec *= kt0/kt;
}
di.prob = di.uf2 = unitarize(di.f2);
return di;
}
bool DipoleXSec::kinematicsVeto(const pair<tPartonPtr, tPartonPtr> left,
const pair<tPartonPtr, tPartonPtr> right,
const ImpactParameters & b) const {
pair<pair<bool, bool>, pair<bool, bool> > ints = doesInt(left, right, b);
if ( Current<DipoleEventHandler>()->eventFiller().compat ) {
pair<bool,bool> int0 =
int0Partons(left.first, left.second, right.first, right.second, b);
ints = make_pair(make_pair(int0.first, !int0.first),
make_pair(int0.second, !int0.second));
}
InteractionRecoil recs = recoil(left, right, b, ints);
if ( theInteraction == 0 ) {
//the key partons for f_ij
pair<bool, bool> ints0 = int0Partons(left.first, left.second, right.first, right.second, b);
//first set up effective partons with range etc
tPartonPtr p1 = (ints0.first ? left.first:left.second);
tPartonPtr p2 = (ints0.second ? right.first:right.second);
//there MAY be secondary partons in the interaction, decided by ints.
tPartonPtr p1sec, p2sec;
if ( ints.first.first && ints.first.second )
p1sec = (ints0.first ? left.second:left.first);
if ( ints.second.first && ints.second.second )
p2sec = (ints0.second ? right.second:right.first);
//only distance between key partons will affect range (reasonable?)
InvEnergy range1 = sqrt(min(left.first->dist2(*left.second)/4.0, b.dist2(*p1, *p2)));
InvEnergy range2 = sqrt(min(right.first->dist2(*right.second)/4.0, b.dist2(*p1, *p2)));
if ( Current<DipoleEventHandler>()->emitter().rangeMode() == 1 ) {
range1 = sqrt(left.first->dist2(*left.second)/4.0);
range2 = sqrt(right.first->dist2(*right.second)/4.0);
}
EffectivePartonPtr ep1 = EffectiveParton::create(*p1, range1);
EffectivePartonPtr ep2 = EffectiveParton::create(*p2, range2);
EffectivePartonPtr ep1sec, ep2sec;
if ( p1sec ) ep1sec = EffectiveParton::create(*p1sec, range1);
if ( p2sec ) ep2sec = EffectiveParton::create(*p2sec, range2);
TransverseMomentum rec1 = (ints0.first ? recs.first.first:recs.first.second);
TransverseMomentum rec2 = (ints0.second ? recs.second.first:recs.second.second);
Energy pt1 = (ep1->pT() + rec1).pt();
Energy minus1 = sqr(pt1)/ep1->plus();
Energy pt2 = (ep2->pT() + rec2).pt();
Energy minus2 = sqr(pt2)/ep2->plus();
//sum up total supplied and needed LC momentum from each side
Energy leftPlus = ep1->plus() + (p1sec ? ep1sec->plus():ZERO);
Energy leftMinus = minus1;
if ( p1sec ) {
TransverseMomentum rec1sec = (ints0.first ? recs.first.second:recs.first.first);
Energy pt1sec = (ep1sec->pT() + rec1sec).pt();
Energy minus1sec = sqr(pt1sec)/ep1sec->plus();
leftMinus += minus1sec;
}
Energy rightPlus = ep2->plus() + (p2sec ? ep2sec->plus():ZERO);
Energy rightMinus = minus2 + (p2sec ? ep2sec->minus():ZERO);
if ( p2sec ) {
TransverseMomentum rec2sec = (ints0.second ? recs.second.second:recs.second.first);
Energy pt2sec = (ep2sec->pT() + rec2sec).pt();
Energy minus2sec = sqr(pt2sec)/ep2sec->plus();
rightMinus += minus2sec;
}
if ( theIntOrdering == 2 ) {
Energy maxRec = max(max(recs.first.first.pt() ,recs.first.second.pt()),
max(recs.second.first.pt() ,recs.second.second.pt()));
if ( leftPlus*rightPlus < 16.0*sqr(maxRec) ) return true;
else return false;
}
//check enough energy to set all on shell
if ( leftPlus*rightPlus < 16.0*leftMinus*rightMinus ) {
return true;
}
//take LC momentum transfers in account
Energy plus1 = ep1->plus()*(1.0 - rightMinus/leftPlus);
minus1 /= 1.0 - rightMinus/leftPlus;
Energy plus2 = ep2->plus()*(1.0 - leftMinus/rightPlus);
minus2 /= 1.0 - leftMinus/rightPlus;
//check ordering of the key partons (secondaries can be unordered if they want)
double PSInf = Current<DipoleEventHandler>()->emitter().PSInflation();
if ( theIntOrdering == 0 ) {
//just check plus and minus ordering after recoils
if ( plus1*PSInf < minus2 ) return true;
if ( plus2*PSInf < minus1 ) return true;
}
else if ( theIntOrdering == 1 ) {
//check p- ordering from both sides, as if it was evolution.
//that is, as if no future recoils.
double PMOrd = Current<DipoleEventHandler>()->emitter().PMinusOrdering();
TransverseMomentum rec1 = (ints0.first ? recs.first.first:recs.first.second);
TransverseMomentum rec2 = (ints0.second ? recs.second.first:recs.second.second);
if ( sqr(max(rec1.pt(), rec2.pt())*PSInf) < minus1*minus2*PMOrd )
return true;
}
//check that the partons stay on their side, to avoid doublecounting
double yInt = 0;
if ( p1->dipoles().first ) yInt = p1->dipoles().first->dipoleState().ymax();
else if ( p1->dipoles().second ) yInt = p1->dipoles().second->dipoleState().ymax();
double y1 = 0.5*log(minus1/plus1);
if ( y1 > yInt ) return true;
double y2 = 0.5*log(plus2/minus2);
if ( y2 < yInt ) return true;
//should we check secondaries as well here?
//if no veto triggered, it should not be vetoed
return false;
}
else {
cerr << "only interaction 0 is supported in kinematics veto atm, sorry" << endl;
}
return false;
}
bool DipoleXSec::kinematicsVeto(const Dipole & dleft,
const Dipole & dright,
const ImpactParameters & b,
const pair<bool,bool> & ints0) const {
pair<tPartonPtr, tPartonPtr> left = dleft.partons();
pair<tPartonPtr, tPartonPtr> right = dright.partons();
pair<pair<bool, bool>, pair<bool, bool> > ints = doesInt(left, right, b);
if ( Current<DipoleEventHandler>()->eventFiller().compat ) {
ints = make_pair(make_pair(ints0.first, !ints0.first),
make_pair(ints0.second, !ints0.second));
}
InteractionRecoil recs = recoil(left, right, b, ints, ints0);
if ( theInteraction == 0 ) {
//first set up effective partons with range etc
tPartonPtr p1 = (ints0.first ? left.first:left.second);
tPartonPtr p2 = (ints0.second ? right.first:right.second);
//there MAY be secondary partons in the interaction, decided by ints.
tPartonPtr p1sec, p2sec;
if ( ints.first.first && ints.first.second )
p1sec = (ints0.first ? left.second:left.first);
if ( ints.second.first && ints.second.second )
p2sec = (ints0.second ? right.second:right.first);
//only distance between key partons will affect range (reasonable?)
InvEnergy range1 = sqrt(min(left.first->dist2(*left.second)/4.0, b.dist2(*p1, *p2)));
InvEnergy range2 = sqrt(min(right.first->dist2(*right.second)/4.0, b.dist2(*p1, *p2)));
if ( Current<DipoleEventHandler>()->emitter().rangeMode() == 1 ) {
range1 = sqrt(left.first->dist2(*left.second)/4.0);
range2 = sqrt(right.first->dist2(*right.second)/4.0);
}
EffectivePartonPtr ep1 = dleft.getEff(p1, range1);
EffectivePartonPtr ep2 = dright.getEff(p2, range2);
EffectivePartonPtr ep1sec, ep2sec;
if ( p1sec ) ep1sec = dleft.getEff(p1sec, range1);
if ( p2sec ) ep2sec = dright.getEff(p2sec, range2);
TransverseMomentum rec1 = (ints0.first ? recs.first.first:recs.first.second);
TransverseMomentum rec2 = (ints0.second ? recs.second.first:recs.second.second);
Energy pt1 = (ep1->pT() + rec1).pt();
Energy minus1 = sqr(pt1)/ep1->plus();
Energy pt2 = (ep2->pT() + rec2).pt();
Energy minus2 = sqr(pt2)/ep2->plus();
//sum up total supplied and needed LC momentum from each side
Energy leftPlus = ep1->plus() + (p1sec ? ep1sec->plus():ZERO);
Energy leftMinus = minus1;
if ( p1sec ) {
TransverseMomentum rec1sec = (ints0.first ? recs.first.second:recs.first.first);
Energy pt1sec = (ep1sec->pT() + rec1sec).pt();
Energy minus1sec = sqr(pt1sec)/ep1sec->plus();
leftMinus += minus1sec;
}
Energy rightPlus = ep2->plus() + (p2sec ? ep2sec->plus():ZERO);
Energy rightMinus = minus2 + (p2sec ? ep2sec->minus():ZERO);
if ( p2sec ) {
TransverseMomentum rec2sec = (ints0.second ? recs.second.second:recs.second.first);
Energy pt2sec = (ep2sec->pT() + rec2sec).pt();
Energy minus2sec = sqr(pt2sec)/ep2sec->plus();
rightMinus += minus2sec;
}
if ( theIntOrdering == 2 ) {
Energy maxRec = max(max(recs.first.first.pt() ,recs.first.second.pt()),
max(recs.second.first.pt() ,recs.second.second.pt()));
if ( leftPlus*rightPlus < 16.0*sqr(maxRec) ) return true;
else return false;
}
//check enough energy to set all on shell
if ( leftPlus*rightPlus < 16.0*leftMinus*rightMinus ) {
return true;
}
//take LC momentum transfers in account
Energy plus1 = ep1->plus()*(1.0 - rightMinus/leftPlus);
minus1 /= 1.0 - rightMinus/leftPlus;
Energy plus2 = ep2->plus()*(1.0 - leftMinus/rightPlus);
minus2 /= 1.0 - leftMinus/rightPlus;
//check ordering of the key partons (secondaries can be unordered if they want)
double PSInf = Current<DipoleEventHandler>()->emitter().PSInflation();
if ( theIntOrdering == 0 ) {
//just check plus and minus ordering after recoils
if ( plus1*PSInf < minus2 ) return true;
if ( plus2*PSInf < minus1 ) return true;
}
else if ( theIntOrdering == 1 ) {
//check p- ordering from both sides, as if it was evolution.
//that is, as if no future recoils.
double PMOrd = Current<DipoleEventHandler>()->emitter().PMinusOrdering();
TransverseMomentum rec1 = (ints0.first ? recs.first.first:recs.first.second);
TransverseMomentum rec2 = (ints0.second ? recs.second.first:recs.second.second);
if ( sqr(max(rec1.pt(), rec2.pt())*PSInf) < minus1*minus2*PMOrd )
return true;
}
//check that the partons stay on their side, to avoid doublecounting
double yInt = 0;
if ( p1->dipoles().first ) yInt = p1->dipoles().first->dipoleState().ymax();
else if ( p1->dipoles().second ) yInt = p1->dipoles().second->dipoleState().ymax();
double y1 = 0.5*log(minus1/plus1);
if ( y1 > yInt ) return true;
double y2 = 0.5*log(plus2/minus2);
if ( y2 < yInt ) return true;
//should we check secondaries as well here?
//if no veto triggered, it should not be vetoed
return false;
}
else {
cerr << "only interaction 0 is supported in kinematics veto atm, sorry" << endl;
}
return false;
}
bool DipoleXSec::kinematicsVeto(const DipoleInteraction & di) const {
if ( di.sints.first ) return di.check(-1); // Hey! We're using shadows!
ImpactParameters b = *di.b;
const Dipole & dleft = *di.dips.first;
const Dipole & dright = *di.dips.second;
//first set up effective partons with range etc
tcPartonPtr p1 = di.ints.first;
tcPartonPtr p2 = di.ints.second;
//only distance between key partons will affect range (reasonable?)
InvEnergy range1 = sqrt(min(dleft.size2()/4.0, b.dist2(*p1, *p2)));
InvEnergy range2 = sqrt(min(dright.size2()/4.0, b.dist2(*p1, *p2)));
EffectivePartonPtr ep1 = dleft.getEff(p1, range1);
EffectivePartonPtr ep2 = dright.getEff(p2, range2);
TransverseMomentum rec1 = di.rec;
TransverseMomentum rec2 = di.b->invRotatePT(-di.rec);
Energy pt1 = (ep1->pT() + rec1).pt();
Energy minus1 = sqr(pt1)/ep1->plus();
Energy pt2 = (ep2->pT() + rec2).pt();
Energy minus2 = sqr(pt2)/ep2->plus();
//sum up total supplied and needed LC momentum from each side
Energy leftPlus = ep1->plus();
Energy leftMinus = minus1;
Energy rightPlus = ep2->plus();
Energy rightMinus = minus2;
if ( theIntOrdering == 2 ) {
if ( leftPlus*rightPlus < 16.0*rec1.pt2() ) return true;
else return false;
}
//check enough energy to set all on shell
if ( leftPlus*rightPlus < 16.0*leftMinus*rightMinus ) {
return true;
}
//take LC momentum transfers in account
Energy plus1 = ep1->plus()*(1.0 - rightMinus/leftPlus);
minus1 /= 1.0 - rightMinus/leftPlus;
Energy plus2 = ep2->plus()*(1.0 - leftMinus/rightPlus);
minus2 /= 1.0 - leftMinus/rightPlus;
//check ordering of the key partons (secondaries can be unordered if they want)
double PSInf = Current<DipoleEventHandler>()->emitter().PSInflation();
if ( theIntOrdering == 0 ) {
//just check plus and minus ordering after recoils
if ( plus1*PSInf < minus2 ) return true;
if ( plus2*PSInf < minus1 ) return true;
}
//check that the partons stay on their side, to avoid doublecounting
double yInt = 0;
if ( p1->dipoles().first ) yInt = p1->dipoles().first->dipoleState().ymax();
else if ( p1->dipoles().second ) yInt = p1->dipoles().second->dipoleState().ymax();
double y1 = 0.5*log(minus1/plus1);
if ( y1 > yInt ) return true;
double y2 = 0.5*log(plus2/minus2);
if ( y2 < yInt ) return true;
//should we check secondaries as well here?
//if no veto triggered, it should not be vetoed
return false;
return false;
}
double DipoleXSec::
sumf(const DipoleState & sl, const DipoleState & sr,
const ImpactParameters & b) const {
Nfij = 0;
NBVeto = 0;
NScalVeto = 0;
scalVeto = 0.0;
bVeto = 0.0;
vector<tDipolePtr> dl;
sl.extract(back_inserter(dl));
vector<tDipolePtr> dr;
sr.extract(back_inserter(dr));
double sum = 0.0;
for ( int i = 0, N = dl.size(); i < N; ++i )
for ( int j = 0, M = dr.size(); j < M; ++j )
sum += fij(*dl[i], *dr[j], b);
return sum;
}
double DipoleXSec::
sumf(const ImpactParameters & b, const DipoleState & sl, const DipoleState & sr) const {
Nfij = 0;
NBVeto = 0;
NScalVeto = 0;
scalVeto = 0.0;
bVeto = 0.0;
vector<tDipolePtr> dl;
sl.extract(back_inserter(dl));
vector<tDipolePtr> dr;
sr.extract(back_inserter(dr));
double sum = 0.0;
for ( int i = 0, N = dl.size(); i < N; ++i )
for ( int j = 0, M = dr.size(); j < M; ++j ) {
if ( (M*i + j)%8 == 0 ) UseRandom::rnd();
DipoleInteraction di = fij(b, *dl[i], *dr[j], false);
if ( !di.check(-1) )
sum += di.f2/2.0; /*** TODO: this is because we need proper f here. FIX CONFUSION */
}
return sum;
}
DipoleXSec::FList
DipoleXSec::flist(const DipoleState & sl, const DipoleState & sr,
const ImpactParameters & b) const {
FList ret;
vector<tDipolePtr> dl;
sl.extract(back_inserter(dl));
vector<tDipolePtr> dr;
sr.extract(back_inserter(dr));
//dont save the lowest fij. Otherwise the FList for LHC PbPb will take too much memory.
double cutoff = min(0.00000001, 1.0/double(dl.size()*dr.size()));
if ( dl.size()*dr.size() < 1000000 ) cutoff = 0.0000000001;
int total = 0;
int skipped = 0;
for ( int i = 0, N = dl.size(); i < N; ++i ) {
for ( int j = 0, M = dr.size(); j < M; ++j ) {
double f = fij(*dl[i], *dr[j], b, false)*2.0;
//extra 2 added from the non-diffractive interaction probability.
total++;
if ( f > cutoff &&
!kinematicsVeto(dl[i]->partons(), dr[j]->partons(), b) )
ret.insert(make_pair(make_pair(f, unitarize(f)), make_pair(dl[i], dr[j])));
else skipped++;
}
}
return ret;
}
DipoleInteraction::List
DipoleXSec::flist(const ImpactParameters & b,
const DipoleState & sl, const DipoleState & sr) const {
nIAccepted = 0;
nIBelowCut = 0;
nIPropFail = 0;
nIKineFail = 0;
nIOrdering = 0;
DipoleInteraction::List ret;
vector<tDipolePtr> dl;
sl.extract(back_inserter(dl));
vector<tDipolePtr> dr;
sr.extract(back_inserter(dr));
//dont save the lowest fij. Otherwise the FList for LHC PbPb will take too much memory.
double cutoff = min(0.00000001, 1.0/double(dl.size()*dr.size()));
if ( dl.size()*dr.size() < 1000000 ) cutoff = 0.0000000001;
int total = 0;
int skipped = 0;
for ( int i = 0, N = dl.size(); i < N; ++i ) {
for ( int j = 0, M = dr.size(); j < M; ++j ) {
if ( (M*i + j)%8 == 0 ) UseRandom::rnd();
/*** TODO: WHY IS VETO FALSE - because we don't want to check
kinematics if below cut ***/
DipoleInteraction di = fij(b, *dl[i], *dr[j], false);
total++;
if ( di.f2 > cutoff && !kinematicsVeto(di) ) {
ret.insert(di);
++nIAccepted;
} else {
skipped++;
ret.insert(di);
if ( di.f2 <= cutoff ) ++nIBelowCut;
else switch ( di.status ) {
case DipoleInteraction::PROPFAIL:
++nIPropFail;
break;
case DipoleInteraction::KINEFAIL:
++nIKineFail;
break;
case DipoleInteraction::ORDERING:
++nIOrdering;
break;
case DipoleInteraction::UNKNOWN:
case DipoleInteraction::ACCEPTED:
break;
}
}
}
}
return ret;
}
DipoleXSec::InteractionRecoil
DipoleXSec::recoil(const DipoleInteraction & di) const {
InteractionRecoil ret;
if ( di.norec ) return ret;
if ( di.ints.first == di.dips.first->partons().first )
ret.first.first = di.rec;
else
ret.first.second = di.rec;
if ( di.ints.second == di.dips.second->partons().first )
ret.second.first = di.b->invRotatePT(-di.rec);
else
ret.second.second = di.b->invRotatePT(-di.rec);
return ret;
}
DipoleXSec::InteractionRecoil
DipoleXSec::recoil(const pair<tPartonPtr, tPartonPtr> left,
const pair<tPartonPtr, tPartonPtr> right,
const ImpactParameters & b,
pair<pair<bool, bool>, pair<bool, bool> > doesInt) const {
return recoil(left, right, b, doesInt, int0Partons(left.first, left.second,
right.first, right.second, b));
}
DipoleXSec::InteractionRecoil
DipoleXSec::recoil(const pair<tPartonPtr, tPartonPtr> left,
const pair<tPartonPtr, tPartonPtr> right,
const ImpactParameters & b,
pair<pair<bool, bool>, pair<bool, bool> > doesInt,
pair<bool, bool> ints) const {
tPartonPtr p1 = left.first;
tPartonPtr p2 = left.second;
tPartonPtr p3 = right.first;
tPartonPtr p4 = right.second;
if ( theInteraction == 2 ) { //swing recoil, only new dips
TransverseMomentum rec14 =
-pTScale()*b.difference(p1->position(), p4->position())/
( b.dist2(*p1,*p4) );
TransverseMomentum rec23 =
-pTScale()*b.difference(p2->position(), p3->position())/
( b.dist2(*p2,*p3) );
return make_pair(make_pair(rec14, rec23),
make_pair(-rec23, -rec14));
}
//4 parton-parton recoils (full diagonals)
if ( theInteraction == 1 ) {
TransverseMomentum rec13 = -pTScale()*
b.difference(p1->position(), p3->position())/b.dist2(*p1, *p3);
TransverseMomentum rec14 = -pTScale()*
b.difference(p1->position(), p4->position())/b.dist2(*p1, *p4);
TransverseMomentum rec23 = -pTScale()*
b.difference(p2->position(), p3->position())/b.dist2(*p2, *p3);
TransverseMomentum rec24 = -pTScale()*
b.difference(p2->position(), p4->position())/b.dist2(*p2, *p4);
return make_pair(make_pair(rec14 + rec13, rec23 + rec24),
make_pair(b.invRotatePT(-rec23 - rec13),
b.invRotatePT(-rec14 - rec24)));
}
//2 parton-parton recoils (no diagonals)
if ( theInteraction == 3 ) {
TransverseMomentum rec13 = -pTScale()*
b.difference(p1->position(), p3->position())/b.dist2(*p1, *p3);
TransverseMomentum rec14 = -pTScale()*
b.difference(p1->position(), p4->position())/b.dist2(*p1, *p4);
TransverseMomentum rec23 = -pTScale()*
b.difference(p2->position(), p3->position())/b.dist2(*p2, *p3);
TransverseMomentum rec24 = -pTScale()*
b.difference(p2->position(), p4->position())/b.dist2(*p2, *p4);
if ( doesInt.first.first && doesInt.first.second &&
doesInt.second.first && doesInt.second.second )
return make_pair(make_pair(rec14, rec23),
make_pair(b.invRotatePT(-rec23), b.invRotatePT(-rec14)));
else {
TransverseMomentum rec11 = TransverseMomentum();
if ( doesInt.first.first && doesInt.second.first ) rec11 += rec13;
if ( doesInt.first.first && doesInt.second.second ) rec11 += rec14;
TransverseMomentum rec12 = TransverseMomentum();
if ( doesInt.first.second && doesInt.second.first ) rec12 += rec23;
if ( doesInt.first.second && doesInt.second.second ) rec12 += rec24;
TransverseMomentum rec21 = TransverseMomentum();
if ( doesInt.second.first && doesInt.first.first ) rec21 -= rec13;
if ( doesInt.second.first && doesInt.first.second ) rec21 -= rec23;
TransverseMomentum rec22 = TransverseMomentum();
if ( doesInt.second.second && doesInt.first.first ) rec22 -= rec14;
if ( doesInt.second.second && doesInt.first.second ) rec22 -= rec24;
return make_pair(make_pair(rec11, rec12),
make_pair(b.invRotatePT(rec21), b.invRotatePT(rec22)));
}
}
if ( theInteraction == 0 ) { //dip-dip recoil
TransverseMomentum rec13 = -pTScale()*
b.difference(p1->position(), p3->position())/b.dist2(*p1, *p3);
TransverseMomentum rec14 = -pTScale()*
b.difference(p1->position(), p4->position())/b.dist2(*p1, *p4);
TransverseMomentum rec23 = -pTScale()*
b.difference(p2->position(), p3->position())/b.dist2(*p2, *p3);
TransverseMomentum rec24 = -pTScale()*
b.difference(p2->position(), p4->position())/
(b.dist2(*p2,*p4) );
/*** TODO: WHAT IS THIS? ***/
if ( !Current<DipoleEventHandler>()->eventFiller().compat ) {
if ( p1->oY() + p3->oY() > p2->oY() + p4->oY() ) rec24 = TransverseMomentum();
else rec13 = TransverseMomentum();
}
// if ( p1->flavour() == ParticleID::g ) {
// rec13 /= 2.0;
// rec14 /= 2.0;
// }
// if ( p2->flavour() == ParticleID::g ) {
// rec23 /= 2.0;
// rec24 /= 2.0;
// }
// if ( p3->flavour() == ParticleID::g ) {
// rec13 /= 2.0;
// rec23 /= 2.0;
// }
// if ( p4->flavour() == ParticleID::g ) {
// rec14 /= 2.0;
// rec24 /= 2.0;
// }
TransverseMomentum rec11 = TransverseMomentum();
if ( doesInt.first.first && doesInt.second.first ) rec11 += rec13;
if ( doesInt.first.first && doesInt.second.second ) rec11 += rec14;
TransverseMomentum rec12 = TransverseMomentum();
if ( doesInt.first.second && doesInt.second.first ) rec12 += rec23;
if ( doesInt.first.second && doesInt.second.second ) rec12 += rec24;
TransverseMomentum rec21 = TransverseMomentum();
if ( doesInt.second.first && doesInt.first.first ) rec21 -= rec13;
if ( doesInt.second.first && doesInt.first.second ) rec21 -= rec23;
TransverseMomentum rec22 = TransverseMomentum();
if ( doesInt.second.second && doesInt.first.first ) rec22 -= rec14;
if ( doesInt.second.second && doesInt.first.second ) rec22 -= rec24;
return make_pair(make_pair(rec11, rec12),
make_pair(b.invRotatePT(rec21), b.invRotatePT(rec22)));
}
return make_pair(make_pair(TransverseMomentum(), TransverseMomentum()),
make_pair(TransverseMomentum(), TransverseMomentum()));
}
DipoleXSec::RealInteraction
DipoleXSec::initialiseInteraction(const pair<DipolePtr, DipolePtr> inter,
RealPartonStatePtr lrs, RealPartonStatePtr rrs,
pair<pair<bool, bool>, pair<bool, bool> > doesInt,
const ImpactParameters & b) const {
RealInteraction ret;
ret.lrs = lrs;
ret.rrs = rrs;
ret.d1 = inter.first;
ret.d2 = inter.second;
if ( doesInt.first.first ) ret.p11 = lrs->getReal(ret.d1->partons().first);
else ret.p11 = RealPartonPtr();
if ( doesInt.first.second ) ret.p12 = lrs->getReal(ret.d1->partons().second);
else ret.p12 = RealPartonPtr();
if ( doesInt.second.first ) ret.p21 = rrs->getReal(inter.second->partons().first);
else ret.p21 = RealPartonPtr();
if ( doesInt.second.second ) ret.p22 = rrs->getReal(inter.second->partons().second);
else ret.p22 = RealPartonPtr();
if ( ret.p11 && ret.p11->fluct != -1 && ret.p12 && ret.p12->fluct == ret.p11->fluct )
lrs->splitFluct(ret.p11, ret.p12);
if ( ret.p21 && ret.p21->fluct != -1 && ret.p22 && ret.p22->fluct == ret.p21->fluct )
rrs->splitFluct(ret.p21, ret.p22);
ret.range11 = sqrt(min(min(inter.first->partons().first->dist2
(*inter.second->partons().first),
inter.first->partons().first->dist2
(*inter.second->partons().second)),
inter.first->partons().first->dist2
(*inter.first->partons().second)/4.0));
ret.range12 = sqrt(min(min(inter.first->partons().second->dist2
(*inter.second->partons().first),
inter.first->partons().second->dist2
(*inter.second->partons().second)),
inter.first->partons().second->dist2
(*inter.first->partons().first)/4.0));
ret.range21 = sqrt(min(min(inter.second->partons().first->dist2
(*inter.first->partons().first),
inter.second->partons().first->dist2
(*inter.first->partons().second)),
inter.second->partons().first->dist2
(*inter.second->partons().second)/4.0));
ret.range22 = sqrt(min(min(inter.second->partons().second->dist2
(*inter.first->partons().first),
inter.second->partons().second->dist2
(*inter.first->partons().second)),
inter.second->partons().second->dist2
(*inter.second->partons().first)/4.0));
if ( theInteraction == 3 ) {
ret.range11 = sqrt(min(inter.first->partons().first->dist2
(*inter.second->partons().second),
inter.first->partons().first->dist2
(*inter.first->partons().second)/4.0));
ret.range12 = sqrt(min(inter.first->partons().second->dist2
(*inter.second->partons().first),
inter.first->partons().second->dist2
(*inter.first->partons().first)/4.0));
ret.range21 = sqrt(min(inter.second->partons().first->dist2
(*inter.first->partons().second),
inter.second->partons().first->dist2
(*inter.second->partons().second)/4.0));
ret.range22 = sqrt(min(inter.second->partons().second->dist2
(*inter.first->partons().first),
inter.second->partons().second->dist2
(*inter.second->partons().first)/4.0));
}
if ( theInteraction == 0 ) {
pair<bool, bool> ints;
ints = int0Partons(ret.d1->partons().first, ret.d1->partons().second,
inter.second->partons().first, inter.second->partons().second, b);
InvEnergy2 range2;
if ( ints.first && ints.second ) range2 = b.dist2(*ret.p11->theParton,*ret.p21->theParton);
if ( !ints.first && ints.second ) range2 = b.dist2(*ret.p12->theParton,*ret.p21->theParton);
if ( ints.first && !ints.second ) range2 = b.dist2(*ret.p11->theParton,*ret.p22->theParton);
if ( !ints.first && !ints.second ) range2 = b.dist2(*ret.p12->theParton,*ret.p22->theParton);
InvEnergy range = sqrt(range2);
ret.range11 = min(range, ret.d1->size()/2.0);
ret.range12 = min(range, ret.d1->size()/2.0);
ret.range21 = min(range, ret.d2->size()/2.0);
ret.range22 = min(range, ret.d2->size()/2.0);
if ( Current<DipoleEventHandler>()->emitter().rangeMode() == 1 ) {
ret.range11 = ret.d1->size()/2.0;
ret.range12 = ret.d1->size()/2.0;
ret.range21 = ret.d2->size()/2.0;
ret.range22 = ret.d2->size()/2.0;
}
}
InvEnergy2 rr11 = (ret.p11 && ret.p21) ? ret.p11->theParton->dist2(*ret.p21->theParton):ZERO;
InvEnergy2 rr12 = (ret.p11 && ret.p22) ? ret.p11->theParton->dist2(*ret.p22->theParton):ZERO;
InvEnergy2 rr21 = (ret.p12 && ret.p21) ? ret.p12->theParton->dist2(*ret.p21->theParton):ZERO;
InvEnergy2 rr22 = (ret.p12 && ret.p22) ? ret.p12->theParton->dist2(*ret.p22->theParton):ZERO;
InvEnergy2 rm11 = (ret.p11 && ret.p11->mothers.first ?
ret.p11->theParton->dist2(*ret.p11->mothers.first->theParton):ZERO);
InvEnergy2 rm12 = (ret.p12 && ret.p12->mothers.first ?
ret.p12->theParton->dist2(*ret.p12->mothers.first->theParton):ZERO);
InvEnergy2 rm21 = (ret.p21 && ret.p21->mothers.first ?
ret.p21->theParton->dist2(*ret.p21->mothers.first->theParton):ZERO);
InvEnergy2 rm22 = (ret.p22 && ret.p22->mothers.first ?
ret.p22->theParton->dist2(*ret.p22->mothers.first->theParton):ZERO);
ret.max11 = rr11 < rm11 && rr11 < rm21;
ret.max12 = rr12 < rm11 && rr12 < rm22;
ret.max21 = rr21 < rm12 && rr21 < rm21;
ret.max22 = rr22 < rm12 && rr22 < rm22;
Energy2 den = ((ret.p11 ? 1./rr11:ZERO) + (ret.p12 ? 1./rr12:ZERO)
+ (ret.p21 ? 1./rr21:ZERO) + (ret.p22 ? 1./rr22:ZERO));
ret.P11 = ret.p11 ? (1./rr11)/den:ZERO;
ret.P12 = ret.p12 ? (1./rr12)/den:ZERO;
ret.P21 = ret.p21 ? (1./rr21)/den:ZERO;
ret.P22 = ret.p22 ? (1./rr22)/den:ZERO;
//look only at the new dipole pairs, the cross pairs get zero weight.
if ( theInteraction == 3 ) {
den = (1./rr12 + 1./rr21);
ret.P12 = (1./rr12)/den;
ret.P21 = (1./rr21)/den;
ret.P11 = 0.0;
ret.P22 = 0.0;
}
//set only the selected pair to weight 1, the others to 0.
if ( theInteraction == 0 ) {
pair<bool, bool> ints;
ints = int0Partons(inter.first->partons().first, inter.first->partons().second,
inter.second->partons().first, inter.second->partons().second, b);
ret.P11 = 0.0;
ret.P22 = 0.0;
ret.P21 = 0.0;
ret.P12 = 0.0;
if ( ints.first && ints.second ) ret.P11 = 1.0;
if ( ints.first && !ints.second ) ret.P12 = 1.0;
if ( !ints.first && ints.second ) ret.P21 = 1.0;
if ( !ints.first && !ints.second ) ret.P22 = 1.0;
}
return ret;
}
DipoleXSec::RealInteraction
DipoleXSec::initialiseInteraction(const DipoleInteraction & di,
RealPartonStatePtr lrs, RealPartonStatePtr rrs) const {
RealInteraction ret;
const ImpactParameters & b = *di.b;
ret.lrs = lrs;
ret.rrs = rrs;
ret.d1 = di.dips.first;
ret.d2 = di.dips.second;
if ( ret.d1->partons().first == di.ints.first ) ret.p11 = lrs->getReal(di.ints.first);
if ( ret.d1->partons().second == di.ints.first ) ret.p12 = lrs->getReal(di.ints.first);
if ( ret.d2->partons().first == di.ints.second ) ret.p21 = rrs->getReal(di.ints.second);
if ( ret.d2->partons().second == di.ints.second ) ret.p22 = rrs->getReal(di.ints.second);
if ( ret.p11 && ret.p11->fluct != -1 && ret.p12 && ret.p12->fluct == ret.p11->fluct )
lrs->splitFluct(ret.p11, ret.p12);
if ( ret.p21 && ret.p21->fluct != -1 && ret.p22 && ret.p22->fluct == ret.p21->fluct )
rrs->splitFluct(ret.p21, ret.p22);
ret.range11 = sqrt(min(min(ret.d1->partons().first->dist2
(*ret.d2->partons().first),
ret.d1->partons().first->dist2
(*ret.d2->partons().second)),
ret.d1->partons().first->dist2
(*ret.d1->partons().second)/4.0));
ret.range12 = sqrt(min(min(ret.d1->partons().second->dist2
(*ret.d2->partons().first),
ret.d1->partons().second->dist2
(*ret.d2->partons().second)),
ret.d1->partons().second->dist2
(*ret.d1->partons().first)/4.0));
ret.range21 = sqrt(min(min(ret.d2->partons().first->dist2
(*ret.d1->partons().first),
ret.d2->partons().first->dist2
(*ret.d1->partons().second)),
ret.d2->partons().first->dist2
(*ret.d2->partons().second)/4.0));
ret.range22 = sqrt(min(min(ret.d2->partons().second->dist2
(*ret.d1->partons().first),
ret.d2->partons().second->dist2
(*ret.d1->partons().second)),
ret.d2->partons().second->dist2
(*ret.d2->partons().first)/4.0));
pair<bool, bool> ints(ret.d1->partons().first == di.ints.first,
ret.d2->partons().first == di.ints.second);
InvEnergy2 range2 = b.dist2(*di.ints.first, *di.ints.second);
InvEnergy range = sqrt(range2);
ret.range11 = min(range, ret.d1->size()/2.0);
ret.range12 = min(range, ret.d1->size()/2.0);
ret.range21 = min(range, ret.d2->size()/2.0);
ret.range22 = min(range, ret.d2->size()/2.0);
if ( Current<DipoleEventHandler>()->emitter().rangeMode() == 1 ) {
ret.range11 = ret.d1->size()/2.0;
ret.range12 = ret.d1->size()/2.0;
ret.range21 = ret.d2->size()/2.0;
ret.range22 = ret.d2->size()/2.0;
}
InvEnergy2 rr11 = (ret.p11 && ret.p21) ? ret.p11->theParton->dist2(*ret.p21->theParton):ZERO;
InvEnergy2 rr12 = (ret.p11 && ret.p22) ? ret.p11->theParton->dist2(*ret.p22->theParton):ZERO;
InvEnergy2 rr21 = (ret.p12 && ret.p21) ? ret.p12->theParton->dist2(*ret.p21->theParton):ZERO;
InvEnergy2 rr22 = (ret.p12 && ret.p22) ? ret.p12->theParton->dist2(*ret.p22->theParton):ZERO;
InvEnergy2 rm11 = (ret.p11 && ret.p11->mothers.first ?
ret.p11->theParton->dist2(*ret.p11->mothers.first->theParton):ZERO);
InvEnergy2 rm12 = (ret.p12 && ret.p12->mothers.first ?
ret.p12->theParton->dist2(*ret.p12->mothers.first->theParton):ZERO);
InvEnergy2 rm21 = (ret.p21 && ret.p21->mothers.first ?
ret.p21->theParton->dist2(*ret.p21->mothers.first->theParton):ZERO);
InvEnergy2 rm22 = (ret.p22 && ret.p22->mothers.first ?
ret.p22->theParton->dist2(*ret.p22->mothers.first->theParton):ZERO);
ret.max11 = rr11 < rm11 && rr11 < rm21;
ret.max12 = rr12 < rm11 && rr12 < rm22;
ret.max21 = rr21 < rm12 && rr21 < rm21;
ret.max22 = rr22 < rm12 && rr22 < rm22;
Energy2 den = ((ret.p11 ? 1./rr11:ZERO) + (ret.p12 ? 1./rr12:ZERO)
+ (ret.p21 ? 1./rr21:ZERO) + (ret.p22 ? 1./rr22:ZERO));
ret.P11 = ret.p11 ? (1./rr11)/den:ZERO;
ret.P12 = ret.p12 ? (1./rr12)/den:ZERO;
ret.P21 = ret.p21 ? (1./rr21)/den:ZERO;
ret.P22 = ret.p22 ? (1./rr22)/den:ZERO;
//look only at the new dipole pairs, the cross pairs get zero weight.
if ( theInteraction == 3 ) {
den = (1./rr12 + 1./rr21);
ret.P12 = (1./rr12)/den;
ret.P21 = (1./rr21)/den;
ret.P11 = 0.0;
ret.P22 = 0.0;
}
//set only the selected pair to weight 1, the others to 0.
ret.P11 = 0.0;
ret.P22 = 0.0;
ret.P21 = 0.0;
ret.P12 = 0.0;
if ( ints.first && ints.second ) ret.P11 = 1.0;
if ( ints.first && !ints.second ) ret.P12 = 1.0;
if ( !ints.first && ints.second ) ret.P21 = 1.0;
if ( !ints.first && !ints.second ) ret.P22 = 1.0;
return ret;
}
pair<pair<bool, bool>, pair<bool, bool> >
DipoleXSec::doesInt(const pair<tPartonPtr, tPartonPtr> left,
const pair<tPartonPtr, tPartonPtr> right,
const ImpactParameters & b) const {
//decide which of the 4 partons will end up on shell
// if ( Current<DipoleEventHandler>()->eventFiller().compat ) {
// pair<bool,bool> int0 =
// int0Partons(left.first, left.second, right.first, right.second, b);
// return make_pair(make_pair(int0.first, !int0.first),
// make_pair(int0.second, !int0.second));
// } else {
return make_pair(make_pair(true, true), make_pair(true, true));
// }
if ( Current<DipoleEventHandler>()->eventFiller().singleMother() ) {
//when single mother not all are chosen
pair<pair<bool, bool>, pair<bool, bool> > ret =
make_pair(make_pair(false, false), make_pair(false, false));
if ( theInteraction == 0 ) {
//if interaction 0, then always keep the same partons used in fij
pair<bool, bool> ints;
ints = int0Partons(left.first, left.second, right.first, right.second, b);
if ( ints.first ) ret.first.first = true;
else ret.first.second = true;
if ( ints.second ) ret.second.first =true;
else ret.second.second = true;
}
else {
//select which two partons the gluons are exchanged between,
//weighted by 1/distance^2
InvEnergy2 r11 = b.dist2(*left.first, *right.first);
InvEnergy2 r12 = b.dist2(*left.first, *right.second);
InvEnergy2 r21 = b.dist2(*left.second, *right.first);
InvEnergy2 r22 = b.dist2(*left.second, *right.second);
Selector<int, double> sel;
sel.insert(1./r11/(1./r11 + 1./r12 + 1./r21 + 1./r22), 1);
sel.insert(1./r12/(1./r11 + 1./r12 + 1./r21 + 1./r22), 2);
sel.insert(1./r21/(1./r11 + 1./r12 + 1./r21 + 1./r22), 3);
sel.insert(1./r22/(1./r11 + 1./r12 + 1./r21 + 1./r22), 4);
double dummy = (r11 + r22 + r12 + r21)*sqr(GeV);
double pseudoRnd = 10000.0*dummy - int(10000.0*dummy);
switch ( sel[pseudoRnd] ) {
case 1:
ret.first.first = true;
ret.second.first = true;
break;
case 2:
ret.first.first = true;
ret.second.second = true;
break;
case 3:
ret.first.second = true;
ret.second.first = true;
break;
case 4:
ret.first.second = true;
ret.second.second = true;
break;
}
}
//check for swinged emission, in which case both partons are real
if ( !(left.first->parents().second == left.second ||
left.second->parents().first == left.first) ) {
ret.first.first = true;
ret.first.second = true;
}
if ( !(right.first->parents().second == right.second ||
right.second->parents().first == right.first) ) {
ret.second.first = true;
ret.second.second = true;
}
return ret;
}
//if not single mother, all partons are on shell
return make_pair(make_pair(true, true), make_pair(true, true));
}
pair<bool, bool> DipoleXSec::int0Partons(tcPartonPtr p11, tcPartonPtr p12,
tcPartonPtr p21, tcPartonPtr p22,
const ImpactParameters & b) const {
//chose partons (pseudo-)randomly
InvEnergy2 rr11 = b.dist2(*p11, *p21);
InvEnergy2 rr22 = b.dist2(*p12, *p22);
double dummy = (rr11 + rr22)*GeV2;
while ( dummy > 100 ) dummy /= 10;
if ( Current<DipoleEventHandler>()->fudgeME() > 1 ) {
pair<bool, bool> ret = make_pair(true, true);
if ( p11->dipoles().second->colour() == p21->dipoles().second->colour() )
ret.second = false;
if ( 1000000.0*dummy - long(1000000.0*dummy) > 0.5 ) {
ret.first = !ret.first;
ret.second = !ret.second;
}
return ret;
}
bool firstDipole = ( 1000000.0*dummy - long(1000000.0*dummy) > 0.5 );
bool secondDipole = ( 10000000.0*dummy - long(10000000.0*dummy) > 0.5 );
return make_pair(firstDipole, secondDipole);
}
void DipoleXSec::updateMomenta(RealInteraction * i) const {
if ( i->p11 ) {
pair<Energy, Energy> pm11 = i->p11->effectivePlusMinus(i->range11, true);
i->effectivePlus11 = pm11.first;
i->effectiveMinus11 = pm11.second;
}
if ( i->p12 ) {
pair<Energy, Energy> pm12 = i->p12->effectivePlusMinus(i->range12, false);
i->effectivePlus12 = pm12.first;
i->effectiveMinus12 = pm12.second;
}
if ( i->p21 ) {
pair<Energy, Energy> pm21 = i->p21->effectivePlusMinus(i->range21, true);
i->effectivePlus21 = pm21.first;
i->effectiveMinus21 = pm21.second;
}
if ( i->p22 ) {
pair<Energy, Energy> pm22 = i->p22->effectivePlusMinus(i->range22, false);
i->effectivePlus22 = pm22.first;
i->effectiveMinus22 = pm22.second;
}
}
void DipoleXSec::doTransverseRecoils(RealInteraction i, InteractionRecoil recs) const {
if ( Current<DipoleEventHandler>()->eventFiller().mode() != 1 ) {
i.lrs->totalRecoil += recs.first.first + recs.first.second;
i.rrs->totalRecoil += recs.second.first + recs.second.second;
if ( i.p11 ) i.p11->intRecoil += recs.first.first;
if ( i.p12 ) i.p12->intRecoil += recs.first.second;
if ( i.p21 ) i.p21->intRecoil += recs.second.first;
if ( i.p22 ) i.p22->intRecoil += recs.second.second;
}
if ( i.p11 ) {
if ( i.p22 ) i.p22->doEffectiveRecoil(i.p11, i.range11, true, ZERO, -recs.first.first);
else i.p21->doEffectiveRecoil(i.p11, i.range11, true, ZERO, -recs.first.first);
}
if ( i.p12 ) {
if ( i.p22 ) i.p22->doEffectiveRecoil(i.p12, i.range12, false, ZERO, -recs.first.second);
else i.p21->doEffectiveRecoil(i.p12, i.range12, false, ZERO, -recs.first.second);
}
if ( i.p21 ) {
if ( i.p12 ) i.p12->doEffectiveRecoil(i.p21, i.range21, true, ZERO, -recs.second.first);
else i.p11->doEffectiveRecoil(i.p21, i.range21, true, ZERO, -recs.second.first);
}
if ( i.p22 ) {
if ( i.p11 ) i.p11->doEffectiveRecoil(i.p22, i.range22, false, ZERO, -recs.second.second);
else i.p12->doEffectiveRecoil(i.p22, i.range22, false, ZERO, -recs.second.second);
}
}
pair<double, double> DipoleXSec::findBoosts(RealInteraction i) const {
Energy neededMinus = ZERO;
if ( checkOffShell ) neededMinus += i.lrs->neededValenceMinus();
if ( i.p11 ) neededMinus += i.p11->effectiveGiveMinus(i.range11, true);
if ( i.p12 ) neededMinus += i.p12->effectiveGiveMinus(i.range12, false);
Energy neededPlus = ZERO;
if ( checkOffShell ) neededPlus += i.rrs->neededValenceMinus();
if ( i.p21 ) neededPlus += i.p21->effectiveGiveMinus(i.range21, true);
if ( i.p22 ) neededPlus += i.p22->effectiveGiveMinus(i.range22, false);
Energy intPlus1 = ZERO;
if ( i.p11 ) intPlus1 += i.effectivePlus11;
if ( i.p12 ) intPlus1 += i.effectivePlus12;
Energy intPlus2 = ZERO;
if ( i.p21 ) intPlus2 += i.p21->inRangeMinus(i.range21, true);
if ( i.p22 ) intPlus2 += i.p22->inRangeMinus(i.range22, false);
Energy intMinus1 = ZERO;
if ( i.p11 ) intMinus1 += i.p11->inRangeMinus(i.range11, true);
if ( i.p12 ) intMinus1 += i.p12->inRangeMinus(i.range12, false);
Energy intMinus2 = ZERO;
if ( i.p21 ) intMinus2 += i.effectivePlus21;
if ( i.p22 ) intMinus2 += i.effectivePlus22;
Energy evoPlus2 = neededPlus - intPlus2;
Energy evoMinus1 = neededMinus - intMinus1;
pair<double, double> boosts = findBoosts(intPlus1, intPlus2, intMinus1, intMinus2, evoPlus2, evoMinus1);
if ( boosts.first == 0.0 || isnan(boosts.first) || isnan(boosts.second) ) {
return make_pair(0.0,0.0);
}
if ( boosts.second < 0.0 || boosts.first < 0.0 ) {
//can be over 1.0 if the valenceminus is more than needed
return make_pair(0.0,0.0);;
}
return boosts;
}
void DipoleXSec::doBoosts(RealInteraction i, pair<double, double> boosts) const {
doBoost(i.p11, i.range11, i.p12, i.range12, boosts.first);
doBoost(i.p21, i.range21, i.p22, i.range22, boosts.second);
}
void DipoleXSec::reduceRecoil(RealInteraction RI, InteractionRecoil recs) const {
//check if the interacting partons have passed each other
while ( max((RI.p11 ? RI.p11->y:RI.p12->y), (RI.p12 ? RI.p12->y:RI.p11->y)) >
-max((RI.p21 ? RI.p21->y:RI.p22->y), (RI.p22 ? RI.p22->y:RI.p21->y)) ) {
//and if the recoil is larger than 1 GeV
if ( max(max(recs.first.first.pt(), recs.first.second.pt()),
max(recs.second.first.pt(), recs.second.second.pt())) < 1*GeV ) {
break;
}
//then undo the recoil and redo 90% of it.
recs = make_pair(make_pair(-recs.first.first, -recs.first.second),
make_pair(-recs.second.first, -recs.second.second));
doTransverseRecoils(RI, recs);
recs = make_pair(make_pair(-recs.first.first*0.9, -recs.first.second*0.9),
make_pair(-recs.second.first*0.9, -recs.second.second*0.9));
doTransverseRecoils(RI, recs);
}
}
bool DipoleXSec::doInteraction(InteractionRecoil recs, const FList::const_iterator inter,
RealPartonStatePtr lrs, RealPartonStatePtr rrs,
pair<pair<bool, bool>, pair<bool, bool> > doesInt,
const ImpactParameters & b) const {
static DebugItem checkkinematics("DIPSY::CheckKinematics", 6);
if ( checkkinematics && lrs->checkForNegatives() )
Throw<InteractionKinematicException>()
<< "negatives found at start of interaction!" << Exception::warning;
if ( checkkinematics && rrs->checkForNegatives() )
Throw<InteractionKinematicException>()
<< "negatives found at start of interaction!" << Exception::warning;
RealInteraction RI = initialiseInteraction(inter->second, lrs, rrs, doesInt, b);
doTransverseRecoils(RI, recs);
if ( checkkinematics && lrs->checkForNegatives() )
Throw<InteractionKinematicException>()
<< "negatives found after transverse recoil in interaction!" << Exception::warning;
if ( checkkinematics && rrs->checkForNegatives() )
Throw<InteractionKinematicException>()
<< "negatives found after transverse recoil in interaction!" << Exception::warning;
if ( theRecoilReduction ) {
reduceRecoil(RI, recs);
}
if ( checkkinematics && lrs->checkForNegatives() )
Throw<InteractionKinematicException>()
<< "negatives found after recoil reduction in interaction!" << Exception::warning;
if ( checkkinematics && rrs->checkForNegatives() )
Throw<InteractionKinematicException>()
<< "negatives found after recoil reduction in interaction!" << Exception::warning;
updateMomenta(& RI);
if ( checkkinematics && lrs->checkForNegatives() )
Throw<InteractionKinematicException>()
<< "negatives found after update in interaction!" << Exception::warning;
if ( checkkinematics && rrs->checkForNegatives() )
Throw<InteractionKinematicException>()
<< "negatives found after update in interaction!" << Exception::warning;
pair<double, double> boosts = findBoosts(RI);
if ( boosts.first == 0.0 ) {
return false;
}
doBoosts(RI, boosts);
if ( checkkinematics && lrs->checkForNegatives() )
Throw<InteractionKinematicException>()
<< "negatives found after boost in interaction!" << Exception::warning;
if ( checkkinematics && rrs->checkForNegatives() )
Throw<InteractionKinematicException>()
<< "negatives found after boost in interaction!" << Exception::warning;
if ( ordered(RI, recs, b) ) {
setOnShell(RI);
if ( checkkinematics && lrs->checkForNegatives() )
Throw<InteractionKinematicException>()
<< "negatives found at end of interaction!" << Exception::warning;
if ( checkkinematics && rrs->checkForNegatives() )
Throw<InteractionKinematicException>()
<< "negatives found at end of interaction!" << Exception::warning;
return true;
}
return false;
}
bool DipoleXSec::doInteraction(InteractionRecoil recs,
const DipoleInteraction::List::const_iterator inter,
RealPartonStatePtr lrs, RealPartonStatePtr rrs,
pair<pair<bool, bool>, pair<bool, bool> > doesInt) const {
const ImpactParameters & b = *(inter->b);
static DebugItem checkkinematics("DIPSY::CheckKinematics", 6);
if ( checkkinematics && lrs->checkForNegatives() )
Throw<InteractionKinematicException>()
<< "negatives found at start of interaction!" << Exception::warning;
if ( checkkinematics && rrs->checkForNegatives() )
Throw<InteractionKinematicException>()
<< "negatives found at start of interaction!" << Exception::warning;
RealInteraction RI = initialiseInteraction(*inter, lrs, rrs);
doTransverseRecoils(RI, recs);
if ( checkkinematics && lrs->checkForNegatives() )
Throw<InteractionKinematicException>()
<< "negatives found after transverse recoil in interaction!" << Exception::warning;
if ( checkkinematics && rrs->checkForNegatives() )
Throw<InteractionKinematicException>()
<< "negatives found after transverse recoil in interaction!" << Exception::warning;
if ( theRecoilReduction ) {
reduceRecoil(RI, recs);
}
if ( checkkinematics && lrs->checkForNegatives() )
Throw<InteractionKinematicException>()
<< "negatives found after recoil reduction in interaction!" << Exception::warning;
if ( checkkinematics && rrs->checkForNegatives() )
Throw<InteractionKinematicException>()
<< "negatives found after recoil reduction in interaction!" << Exception::warning;
updateMomenta(& RI);
if ( checkkinematics && lrs->checkForNegatives() )
Throw<InteractionKinematicException>()
<< "negatives found after update in interaction!" << Exception::warning;
if ( checkkinematics && rrs->checkForNegatives() )
Throw<InteractionKinematicException>()
<< "negatives found after update in interaction!" << Exception::warning;
pair<double, double> boosts = findBoosts(RI);
if ( boosts.first == 0.0 ) {
return false;
}
doBoosts(RI, boosts);
if ( checkkinematics && lrs->checkForNegatives() )
Throw<InteractionKinematicException>()
<< "negatives found after boost in interaction!" << Exception::warning;
if ( checkkinematics && rrs->checkForNegatives() )
Throw<InteractionKinematicException>()
<< "negatives found after boost in interaction!" << Exception::warning;
if ( ordered(RI, recs, b) ) {
setOnShell(RI);
if ( checkkinematics && lrs->checkForNegatives() )
Throw<InteractionKinematicException>()
<< "negatives found at end of interaction!" << Exception::warning;
if ( checkkinematics && rrs->checkForNegatives() )
Throw<InteractionKinematicException>()
<< "negatives found at end of interaction!" << Exception::warning;
return true;
}
return false;
}
bool DipoleXSec::ordered(RealInteraction i, InteractionRecoil recs,
const ImpactParameters & b) const {
//this options means only momentum conservation, and that is already checked by
//finding a boost. no extra ordering wanted.
if ( theIntOrdering == 2 ) {
return true;
}
double PSInf = Current<DipoleEventHandler>()->emitter().PSInflation();
bool ordered = true;
bool both = Current<DipoleEventHandler>()->emitter().bothOrderedFS();
//if not a local pt max, check p+- ordering
if ( theIntOrdering == 0 ) {
if ( theInteraction == 0 ) {
//check ordering only for the key partons
pair<bool, bool> ints0 = int0Partons(i.d1->partons().first, i.d1->partons().second,
i.d2->partons().first, i.d2->partons().second, b);
Energy effMinus1 = (ints0.first ? i.effectiveMinus11:i.effectiveMinus12);
Energy effMinus2 = (ints0.second ? i.effectiveMinus21:i.effectiveMinus22);
Energy effPlus1 = (ints0.first ? i.effectivePlus11:i.effectivePlus12);
Energy effPlus2 = (ints0.second ? i.effectivePlus21:i.effectivePlus22);
if ( effPlus1*PSInf < effMinus2 ) ordered = false;
if ( effPlus2*PSInf < effMinus1 ) ordered = false;
}
else {
if ( !i.max11 && i.p11 && i.p21 ) {
if ( i.effectivePlus11*PSInf < i.effectiveMinus21*(both ? 1.0:i.P11) ) ordered = false;
if ( (both ? 1.0:i.P11)*i.effectiveMinus11/PSInf > i.effectivePlus21 ) ordered = false;
}
if ( !i.max12 && i.p11 && i.p22 ) {
if ( i.effectivePlus11*PSInf < i.effectiveMinus22*(both ? 1.0:i.P12) ) ordered = false;
if ( (both ? 1.0:i.P12)*i.effectiveMinus11/PSInf > i.effectivePlus22 ) ordered = false;
}
if ( !i.max21 && i.p12 && i.p21 ) {
if ( i.effectivePlus12*PSInf < i.effectiveMinus21*(both ? 1.0:i.P21) ) ordered = false;
if ( (both ? 1.0:i.P21)*i.effectiveMinus12/PSInf > i.effectivePlus21 ) ordered = false;
}
if ( !i.max22 && i.p12 && i.p22 ) {
if ( i.effectivePlus12*PSInf < i.effectiveMinus22*(both ? 1.0:i.P22) ) ordered = false;
if ( (both ? 1.0:i.P22)*i.effectiveMinus12/PSInf > i.effectivePlus22 ) ordered = false;
}
}
}
if ( theIntOrdering == 1 && theInteraction == 0 ) {
double PMOrd = Current<DipoleEventHandler>()->emitter().PMinusOrdering();
//check ordering only for the key partons
pair<bool, bool> ints0 = int0Partons(i.d1->partons().first, i.d1->partons().second,
i.d2->partons().first, i.d2->partons().second, b);
Energy effMinus1 = (ints0.first ? i.effectiveMinus11:i.effectiveMinus12);
Energy effMinus2 = (ints0.second ? i.effectiveMinus21:i.effectiveMinus22);
Energy rec1 = (ints0.first ? recs.first.first.pt():recs.first.second.pt());
Energy rec2 = (ints0.second ? recs.second.first.pt():recs.second.second.pt());
if ( sqr(max(rec1, rec2)*PSInf) < effMinus1*effMinus2*PMOrd ) ordered = false;
}
if ( (i.p11 && i.p11->searchNegative(i.range11, true)) ||
(i.p12 && i.p12->searchNegative(i.range12, false)) ||
(i.p21 && i.p21->searchNegative(i.range21, true)) ||
(i.p22 && i.p22->searchNegative(i.range22, false)) )
ordered = false;
return ordered;
}
void DipoleXSec::setOnShell(RealInteraction i) const {
if ( i.p11 ) i.p11->effectiveGiveMinus(i.range11, true);
if ( i.p12 ) i.p12->effectiveGiveMinus(i.range12, false);
if ( i.p21 ) i.p21->effectiveGiveMinus(i.range21, true);
if ( i.p22 ) i.p22->effectiveGiveMinus(i.range22, false);
}
bool DipoleXSec::reconnect(tDipolePtr d1, tDipolePtr d2) const {
if ( d1->children().second && !d1->children().first ) {
return reconnect(d1->children().second, d2);
}
if ( d2->children().second && !d2->children().first ) {
return reconnect(d1, d2->children().second);
}
if ( !d1->children().first && !d2->children().first ) { //none has rescattered
d1->swingDipole(d2);
Current<DipoleEventHandler>()->swinger().recombine(*d1);
interact(*d1->children().first, *d2->children().first);
// d1->children().first->interact(*d2->children().first);
// d2->children().first->interact(*d1->children().first);
return true;
}
tPartonPtr p11 = d1->partons().first;
tPartonPtr p12 = d1->partons().second;
tPartonPtr p21 = d2->partons().first;
tPartonPtr p22 = d2->partons().second;
tDipolePtr d11 = p11->dipoles().second;
tDipolePtr d12 = p12->dipoles().first;
tDipolePtr d21 = p21->dipoles().second;
tDipolePtr d22 = p22->dipoles().first;
tDipolePtr swing1;
tDipolePtr swing2;
if ( d11 == d12 ) d1 = d11; //dipole has swinged back
if ( d21 == d22 ) d2 = d21;
if ( !d1->children().first && !d2->children().first ) { //both are original dipole
swing1 = d1;
swing2 = d2;
}
else if ( d1->children().first && !d2->children().first ) { //one dip d1 is rescattering
tDipolePtr temp = d1;
d1 = d2;
d2 = temp;
p11 = d1->partons().first;
p12 = d1->partons().second;
p21 = d2->partons().first;
p22 = d2->partons().second;
d11 = p11->dipoles().second;
d12 = p12->dipoles().first;
d21 = p21->dipoles().second;
d22 = p22->dipoles().first;
}
if ( !d1->children().first && d2->children().first ) { //one dip d2 is rescattering
if ( p11 != d21->partons().second && p12 != d22->partons().first ) {
//no connections, swing with one of the two randomly
swing1 = d1;
if ( UseRandom::rnd() > 0.5 ) swing2 = d21;
else swing2 = d22;
}
else if ( p11 == d21->partons().second && p12 != d22->partons().first ) {
//share one swinged dip, swing with the other
swing1 = d1;
swing2 = d22;
}
else if ( p11 != d21->partons().second && p12 == d22->partons().first ) {
//share other swinged dip, swing with the first
swing1 = d1;
swing2 = d21;
}
else if ( p11 == d21->partons().second && p12 == d22->partons().first ) {
//share both swinged dip, swing back to original
swing1 = d21;
swing2 = d22;
}
}
else if ( d1->children().first && d2->children().first ) { //both dips are rescattering
bool found = false;
int i = 0;
while ( !found && i < 1000 ) {
if ( UseRandom::rnd() > 0.5 ) swing1 = d11;
else swing1 = d12;
if ( UseRandom::rnd() > 0.5 ) swing2 = d21;
else swing2 = d22;
if ( swing1 != swing2 && swing1->partons().first != swing2->partons().second &&
swing2->partons().first != swing1->partons().second )
found = true;
}
}
if ( !swing1 || !swing2 ) {
d1->dipoleState().diagnosis(true);
return false;
}
swing1->swingDipole(swing2);
Current<DipoleEventHandler>()->swinger().recombine(*swing1);
interact(*swing1->children().first, *swing2->children().first);
// swing1->children().first->interact(*swing2->children().first);
// swing2->children().first->interact(*swing1->children().first);
return true;
}
void DipoleXSec::interact(Dipole & d1, Dipole & d2) const {
d1.interact(d2, partonicInteraction());
d2.interact(d1, partonicInteraction());
}
vector<pair<DipolePtr, DipolePtr> >
DipoleXSec::getColourExchanges(tRealPartonStatePtr lrs, tRealPartonStatePtr rrs) const {
vector<pair<DipolePtr, DipolePtr> > ret;
while ( ret.empty() ) {
list<tDipolePtr>::iterator rightDip = rrs->interactions.begin();
for ( list<tDipolePtr>::iterator leftDip = lrs->interactions.begin();
leftDip != lrs->interactions.end(); leftDip++, rightDip++ ) {
if ( unitarize(fij((*leftDip)->partons(), (*rightDip)->partons(),
ImpactParameters(), false))*0.99
< UseRandom::rnd() || true )
ret.push_back(make_pair(*leftDip, *rightDip));
}
}
return ret;
}
pair< double, double> DipoleXSec::findBoosts(Energy intPlus1, Energy intPlus2,
Energy intMinus1, Energy intMinus2,
Energy evoPlus2, Energy evoMinus1) const {
Energy2 A = (intPlus1 - evoPlus2)*intMinus2;
Energy2 B = intPlus1*(evoMinus1 + intMinus1 - intMinus2) -
evoPlus2*(evoMinus1 - intMinus2) - intPlus2*intMinus2;
Energy2 C = -intPlus2*(evoMinus1 - intMinus2);
if ( sqr(B/(2*A)) - C/A < 0.0 ) return make_pair(0.0, 0.0);
double y = -B/(2*A) + sqrt(sqr(B/(2*A)) - C/A); //is the + sqrt() always the right solution?
double x = 1.0 - intPlus2/(y*intPlus1) - evoPlus2/intPlus1;
return make_pair(x, y);
}
void DipoleXSec::doBoost(tRealPartonPtr p1, InvEnergy range1,
tRealPartonPtr p2, InvEnergy range2, double x) const {
//we here have to use the plusweighted recoil to fit the x, y above.
//Other weights get a lot more complicated equations for the boosts.
if ( p1 ) {
pair<Energy, Energy> pm1 = p1->effectivePlusMinus(range1, true);
p1->doPlusWeightedRecoil(p1, range1, true, (1.0 - x)*pm1.first, TransverseMomentum());
}
if ( p2 ) {
pair<Energy, Energy> pm2 = p2->effectivePlusMinus(range2, false);
p2->doPlusWeightedRecoil(p2, range2, false, (1.0 - x)*pm2.first, TransverseMomentum());
}
}
double DipoleXSec::unitarize(double f) const {
return Math::exp1m(-f);
}
void DipoleXSec::persistentOutput(PersistentOStream & os) const {
os << ounit(theRMax, InvGeV) << theInteraction << sinFunction
<< usePartonicInteraction << theIntOrdering << theRecoilReduction
<< thePTScale << ounit(kt0, GeV) << ktpow << checkOffShell;
}
void DipoleXSec::persistentInput(PersistentIStream & is, int) {
is >> iunit(theRMax, InvGeV) >> theInteraction >> sinFunction
>> usePartonicInteraction >> theIntOrdering >> theRecoilReduction
>> thePTScale >> iunit(kt0, GeV) >> ktpow >> checkOffShell;
}
// Static variable needed for the type description system in ThePEG.
#include "ThePEG/Utilities/DescribeClass.h"
DescribeClass<DipoleXSec,HandlerBase>
describeDIPSYDipoleXSec("DIPSY::DipoleXSec", "libAriadne5.so libDIPSY.so");
void DipoleXSec::Init() {
static ClassDocumentation<DipoleXSec> documentation
("There is no documentation for the DipoleXSec class");
static Parameter<DipoleXSec,InvEnergy> interfaceRMax
("RMax",
"The confinement scale (in iverse GeV). If set to zero, "
"the value of <interface>DipoleEventHandler::RMax</interface> of the "
"controlling event handler will be used. If less than zero the value "
"of <interface>Emitter::RMax</interface> of the "
"controlling event handler will be used.",
&DipoleXSec::theRMax, InvGeV, -1.0*InvGeV, -1.0*InvGeV, 0.0*InvGeV,
true, false, Interface::lowerlim);
static Parameter<DipoleXSec,double> interfacePTScale
("PTScale",
"The scale relating distances and transverse momenta. If set to zero, "
"the value of the <interface>Emitter::PTScale</interface> of the "
"controlling event handler will be used.",
&DipoleXSec::thePTScale, 0.0, 0.0, 0,
true, false, Interface::lowerlim);
static Parameter<DipoleXSec, int> interfaceInteraction
("Interaction",
"Which interaction to be used. Determines f_{ij} and recoils. "
"0 is the sinus interaction with 4 identical recoils"
"1 is the sinus interaction with recoils between all 4 parton pairs"
"2 is the swing interaction"
"3 is the sinus interaction with recoils between the 2 parton pairs"
" that get the new dipoles",
&DipoleXSec::theInteraction, 1, 1, 0, 0,
true, false, Interface::lowerlim);
static Switch<DipoleXSec,int> interfaceSinFunction
("SinFunction",
"Determine what approximation to the sine functions in the interaction strength "
"to use.",
&DipoleXSec::sinFunction, 0, true, false);
static SwitchOption interfaceSinFunctionExact
(interfaceSinFunction,
"Exact",
"The actual function.",
0);
static SwitchOption interfaceSinFunctionAverage
(interfaceSinFunction,
"Average",
"Average over angle of dipole and of the resulting bessel fuction.",
1);
static SwitchOption interfaceSinFunctionScaled
(interfaceSinFunction,
"Scaled",
"The actual function, correctly scaled with "
"<interface>Emitter::PTScale</interface>.",
2);
static Switch<DipoleXSec,int> interfaceIntOrdering
("IntOrdering",
"How the real state is found from the virtual cascade. "
"Speed versus consistency.",
&DipoleXSec::theIntOrdering, 0, true, false);
static SwitchOption interfaceIntOrderingDefault
(interfaceIntOrdering,
"Default",
"plus and minus reuired to be ordered after all recoils.",
0);
static SwitchOption interfaceIntOrderingAsEvo
(interfaceIntOrdering,
"AsEvo",
"Try to emulate the ordering in the evolution by requesting ordering"
" on the colliding particle if it would've been part of the cascade."
" That is, ignore recoils from the colliding cascade.",
1);
static SwitchOption interfaceIntOrderingVeryOpen
(interfaceIntOrdering,
"VeryOpen",
"Only checks that there is enough energy to put the interaction recoil "
"on shell. Does not care about ordering, or setting evolution pt on "
"shell. Same as Emils code.",
2);
static SwitchOption interfaceIntOrderingShadowOpen
(interfaceIntOrdering,
"ShadowOpen",
"Only checks that there is enough energy to put the interaction recoil "
"on shell.",
3);
static SwitchOption interfaceIntOrderingShadowColour
(interfaceIntOrdering,
"ShadowColour",
"Check that all partons on the same colour line are ordered.",
4);
static SwitchOption interfaceIntOrderingShadowColourMax
(interfaceIntOrdering,
"ShadowColourMax",
"Check that all partons on the same colour line are ordered. Also let "
"maximum transverse momenum of the propagator chain determine the order "
"of interactions.",
5);
static Switch<DipoleXSec,int> interfaceRecoilReduction
("RecoilReduction",
"What to do with large recoils",
&DipoleXSec::theRecoilReduction, 0, true, false);
static SwitchOption interfaceRecoilReductionOff
(interfaceRecoilReduction,
"Off",
"Do nothing special.",
0);
static SwitchOption interfaceRecoilReductionRapidityOrdered
(interfaceRecoilReduction,
"RapidityOrdered",
"Reduce the recoil until all interacting partons are rapidity ordered with each other.",
1);
static Switch<DipoleXSec,bool> interfaceCheckOffShell
("CheckOffShell",
"Make sure there is energy available to put incoming particles on-shell. Only necessary for virtual photons.",
&DipoleXSec::checkOffShell, true, true, false);
static SwitchOption interfaceCheckOffShellYes
(interfaceCheckOffShell,
"Yes",
"Do the check",
true);
static SwitchOption interfaceCheckOffShellNo
(interfaceCheckOffShell,
"No",
"No check is made.",
false);
static Switch<DipoleXSec,bool> interfacePartonicInteraction
("PartonicInteraction",
"Flag determining if only one parton in each dipole is considered interacting or both.",
&DipoleXSec::usePartonicInteraction, false, true, false);
static SwitchOption interfacePartonicInteractionDipole
(interfacePartonicInteraction,
"Dipole",
"The both partons in a dipole interact.",
false);
static SwitchOption interfacePartonicInteractionParton
(interfacePartonicInteraction,
"Parton",
"Only one parton in a dipole interacts.",
true);
static Parameter<DipoleXSec,Energy> interfaceKT0
("KT0",
"Artificially suppress transverse momenta in the interaction by a "
"factor <interface>KT0</interface>/(<interface>KT0</interface> + kt)"
"^<interface>KTPow</interface>.",
&DipoleXSec::kt0, GeV, 5.0*GeV, 0.0*GeV, 0*GeV,
true, false, Interface::lowerlim);
static Parameter<DipoleXSec,double> interfaceKTPow
("KTPow",
"Artificially suppress transverse momenta in the interaction by a "
"factor <interface>KT0</interface>/(<interface>KT0</interface> + kt)"
"^<interface>KTPow</interface>.",
&DipoleXSec::ktpow, 0.0, 0.0, 0,
true, false, Interface::lowerlim);
}
vector<int> DipoleInteraction::ofail(18, 0);
vector<int> DipoleInteraction::o1fail(18, 0);
diff --git a/DIPSY/Emitter.cc b/DIPSY/Emitter.cc
--- a/DIPSY/Emitter.cc
+++ b/DIPSY/Emitter.cc
@@ -1,1201 +1,1429 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the Emitter class.
//
//Commented
#include "Emitter.h"
#include "Parton.h"
#include "ShadowParton.h"
#include "Dipole.h"
#include "DipoleState.h"
#include "EffectiveParton.h"
#include "ThePEG/Utilities/Current.h"
#include "DipoleEventHandler.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Utilities/Throw.h"
#include "ThePEG/Utilities/DebugItem.h"
#include <iostream>
#ifdef ThePEG_TEMPLATES_IN_CC_FILE
// #include "Emitter.tcc"
#endif
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "gsl/gsl_sf_bessel.h"
using namespace DIPSY;
Emitter::~Emitter() {}
InvEnergy2 Emitter::size2(const Dipole & d) const {
return size2(d.size2());
}
InvEnergy Emitter::size(const Dipole & d) const {
return size(d.size());
}
/*
* Just a shortcut to access the input parameter from the Current handler.
*/
InvEnergy Emitter::rMax() const {
return theRMax > 0.0*InvGeV? theRMax: Current<DipoleEventHandler>()->rMax();
}
/*
* Shortcut to access running alpha from the Current handler.
*/
-double Emitter::alphaS(InvEnergy r) const {
- return Current<DipoleEventHandler>()->alphaS(r);
+double Emitter::alphaSr(InvEnergy r) const {
+ return Current<DipoleEventHandler>()->alphaSr(r);
+}
+
+/*
+ * Shortcut to access running alpha from the Current handler.
+ */
+double Emitter::alphaS(Energy mu) const {
+ return Current<DipoleEventHandler>()->alphaS(mu);
}
/*
* The veto check for the overestimates done previously.
* This calculates the overestimated emission probability, and checks the
* actual probability it should have been in this point, and then returns
* true or false randomly depending on the ratio.
* Note that this is not the final distribution, as there are still more
* vetos done later.
*/
bool Emitter::OEVeto(DipolePtr dip, double y0, Parton::Point p) const {
//set up dipole sizes.
InvEnergy R13 = (dip->effectivePartons().first->position() - p).pt();
InvEnergy R23 = (dip->effectivePartons().second->position() - p).pt();
InvEnergy R12 = dip->size();
//Too large dipoles messes up the bessel functions, and will not make it
//through the p- veto anyways, so can be vetoed already now, to avoid
//errors from the bessel function.
if(R13*GeV > 100.0) return true;
if(R23*GeV > 100.0) return true;
if(R12*GeV > 100.0) return false;
//some more set up.
double bess13 = gsl_sf_bessel_K1(R13/rMax());
double bess23 = gsl_sf_bessel_K1(R23/rMax());
//this is the correct probability distribution used in the paper.
- Energy2 correctDist = alphaBar(min(min(R13,R23),R12))/(M_PI*2.0*sqr(rMax()))*
+ Energy2 correctDist = alphaBarr(min(min(R13,R23),R12))/(M_PI*2.0*sqr(rMax()))*
(sqr(bess13) + sqr(bess23) - (sqr(R13) + sqr(R23) - sqr(R12))/
(R13*R23)*bess13*bess23);
// If we create dipoles which are larger than the original, the
// original partons will be distributed as dpt2/pt4. Here we may
// include an extra fudge factor to emulate a matrix element
// correction.
if ( R13 > R12 && R23 > R12 && Current<DipoleEventHandler>()->fudgeME() )
correctDist *= 1.0 - 1.0/(1.0 + cosh(dip->partons().first->y() -
dip->partons().second->y()));
//Now calculate the overestimated distribution in the same way as it is done in gerateY() and generateXT().
- double Coe = alphaBar(R12/2.0)/M_PI*
+ double Coe = alphaBarr(R12/2.0)/M_PI*
sqr(gsl_sf_bessel_K1(R12/(2.0*rMax())))*
sqr(R12/(2.0*rMax()))*
(R12/(2.0*theRScale)+2.0);
if(R12>2.0*rMax()) //double check that this is ok!!!!
Coe *= sqrt(R12/(2.0*rMax()))*
exp(R12/(rMax())-2.0);
//this is the overestime
Energy2 overestimate = Coe*(1.0/(sqr(R13)*(R13/theRScale+2.0)) +
1.0/(sqr(R23)*(R23/theRScale+2.0)));
//if the overestimate is ok, this should never happen.
if( correctDist/overestimate > 1.0 )
Throw<EmitterException>()
<< "In DIPSY::Emitter " << name() << ": XT keep prob is " << correctDist/overestimate
<< " (r12 = " << R12*GeV << ", Rr13 = " << R13*GeV << ", r23 = " << R23*GeV << ")"
<< Exception::warning;
//generate a random number and check if veto or not.
if(correctDist/overestimate>UseRandom::rnd())
return false;
else
return true;
}
/*
* The veto check for the overestimates done previously using shadows.
* This calculates the overestimated emission probability, and checks the
* actual probability it should have been in this point, and then returns
* true or false randomly depending on the ratio.
* Note that this is not the final distribution, as there are still more
* vetos done later.
*/
bool Emitter::OEVeto(DipolePtr dip, tSPartonPtr sp1, tSPartonPtr sp2,
double y0, Parton::Point p) const {
//set up dipole sizes.
InvEnergy R13 = (dip->partons().first->position() - p).pt();
InvEnergy R23 = (dip->partons().second->position() - p).pt();
InvEnergy R12 = dip->size();
//Too large dipoles messes up the bessel functions, and will not make it
//through the p- veto anyways, so can be vetoed already now, to avoid
//errors from the bessel function.
if ( R13*GeV > 100.0 || R23*GeV > 100.0 ) return true;
if ( R12*GeV > 100.0 ) return false;
//some more set up.
double bess13 = gsl_sf_bessel_K1(R13/rMax());
double bess23 = gsl_sf_bessel_K1(R23/rMax());
//this is the correct probability distribution used in the paper.
- Energy2 correctDist = alphaBar(min(min(R13,R23),R12))/(M_PI*2.0*sqr(rMax()))*
+ Energy2 correctDist = alphaBarr(min(min(R13,R23),R12))/(M_PI*2.0*sqr(rMax()))*
(sqr(bess13) + sqr(bess23) - (sqr(R13) + sqr(R23) - sqr(R12))/
(R13*R23)*bess13*bess23);
// If we create dipoles which are larger than the original, the
// original partons will be distributed as dpt2/pt4. Here we may
// include an extra fudge factor to emulate a matrix element
// correction.
if ( R13 > R12 && R23 > R12 && Current<DipoleEventHandler>()->fudgeME() )
correctDist *= 1.0 - 1.0/(1.0 + cosh(dip->partons().first->y() -
dip->partons().second->y()));
//Now calculate the overestimated distribution in the same way as it is done in gerateY() and generateXT().
- double Coe = alphaBar(R12/2.0)/M_PI*
+ double Coe = alphaBarr(R12/2.0)/M_PI*
sqr(gsl_sf_bessel_K1(R12/(2.0*rMax())))*
sqr(R12/(2.0*rMax()))*
(R12/(2.0*theRScale)+2.0);
if(R12>2.0*rMax()) //double check that this is ok!!!!
Coe *= sqrt(R12/(2.0*rMax()))*
exp(R12/(rMax())-2.0);
//this is the overestime
Energy2 overestimate = Coe*(1.0/(sqr(R13)*(R13/theRScale+2.0)) +
1.0/(sqr(R23)*(R23/theRScale+2.0)));
//if the overestimate is ok, this should never happen.
//TODO: write a proper error message.
if ( correctDist/overestimate > 1.0 )
Throw<EmitterException>()
<< "In DIPSY::Emitter " << name() << ": XT keep prob is " << correctDist/overestimate
<< " (r12 = " << R12*GeV << ", Rr13 = " << R13*GeV << ", r23 = " << R23*GeV << ")"
<< Exception::warning;
//generate a random number and check if veto or not.
return !UseRandom::rndbool(correctDist/overestimate);
}
InvEnergy Emitter::rCut(DipolePtr dip, double y) const {
tEffectivePartonPtr p1 = dip->effectivePartons().first;
tEffectivePartonPtr p2 = dip->effectivePartons().second;
return 0.99*0.5*
min(pTScale()/(p1->plus()*exp(y) + p1->pT().pt()/2.0),
min(pTScale()/(p2->plus()*exp(y) + p2->pT().pt()/2.0),
dip->size()/4.0))/thePlusInflation;
// *** TODO *** interface before/after recoil.
// InvEnergy cutoff = 0.99*
// min(2.0/3.0*pTScale()*exp(-y)/p1->plus(),
// min(2.0/3.0*pTScale()*exp(-y)/p2->plus(),
// dip->size()/4.0)); //if ordered BEFORE recoil
}
/*
* This corrects the overestimated emission probability in Y used in
* generateY(). The correct emission rate is calculated for the
* rapidity in question and compared to the overestimate rate used in
* generateY(). Note that this is not the final correct
* y-distribution, as there are still several vetos to be checked, it
* is just a step closer to the correct distribution.
*/
bool Emitter::YVeto(double y,DipolePtr dip, double Coe, double rateOE) const {
//calculate the correct rate at the rapidity y in question and
//compare with the calculated overestimated rate according the what
//is used in generateY().
return !UseRandom::rndbool(2.0*M_PI*Coe*log(1.0 + 2.0*theRScale/rCut(dip, y))/
rateOE);
}
InvEnergy Emitter::rCut(DipolePtr dip, tSPartonPtr sp1,
tSPartonPtr sp2, double y) const {
if ( theMinusOrderingMode < 5 )
return 0.99*0.5*
min(pTScale()/(sp1->plus0()*exp(y) + sp1->pT0().pt()/2.0),
min(pTScale()/(sp2->plus0()*exp(y) + sp2->pT0().pt()/2.0),
dip->size()/4.0))/thePlusInflation;
else
return 0.99*0.5*
min(pTScale()/(sp1->plus()*exp(y)),
min(pTScale()/(sp2->plus()*exp(y)),
dip->size()/4.0))/thePlusInflation;
}
/*
* This corrects the overestimated emission probability in Y used in generateY().
* The correct emission rate is calculated for the rapidity in question and
* compared to the overestimate rate used in generateY().
* Note that this is not the final correct y-distribution, as there are still several
* vetos to be checked, it is just a step closer to the correct distribution.
*/
bool Emitter::YVeto(double y, DipolePtr dip, tSPartonPtr sp1, tSPartonPtr sp2,
double Coe, double rateOE) const {
//calculate the correct rate at the rapidity y in question and
//compare with the calculated overestimated rate according the what
//is used in generateY().
return !UseRandom::rndbool(2.0*M_PI*Coe*log(1.0 + 2.0*theRScale/
rCut(dip, sp1, sp2, y))/
rateOE);
}
/*
* Generates a rapidity for the next emission.
* The distribution f(y) in this member is using is an overestimate, and will be
* vetoed down to correct distribution in the checks of the x_T distribution.
*
* Already the overestimate f(y) is too messy to generate directly though,
* so it has to be done through a further overestimate g(y) > f(y) which is
* then vetoed (only depending on y) down to f(y) with YVeto().
* Look at the writeup for more details on f() and g().
*/
double Emitter::
generateY(DipolePtr dip, double ymin, double ymax) const {
//set up shorter names.
tEffectivePartonPtr p1 = dip->effectivePartons().first;
tEffectivePartonPtr p2 = dip->effectivePartons().second;
InvEnergy r = dip->size();
//To large dipoles will mess up the bessel function, so just shut them
// off by emitting after the maximum y.
if ( r*GeV > 100.0 ) return ymax + 1.0;
//Calculate the overestimated coefficient. See writeup for details.
- double Coe = alphaBar(r/2.0)/M_PI*
+ double Coe = alphaBarr(r/2.0)/M_PI*
sqr(gsl_sf_bessel_K1(r/(2.0*rMax())))*
sqr(r/(2.0*rMax()))*
(r/(2.0*theRScale)+2.0);
//For assymptotically large dipoles, the overestimated emission rate grows
//faster than Coe, so add an extra factor for large dipoles.
//this will have to be removed in the veto.
if(r>2.0*rMax()) //double check that this is ok!!!
Coe *= sqrt(r/(2.0*rMax()))*
exp(r/(rMax())-2.0);
//calculate the overestimated rate of emission (per unit rapidity).
double rateOE = 2.0*M_PI*Coe*log(1.0 + 2.0*theRScale/rCut(dip, ymin));
//generate the rapidity. (see writeup for details.)
double y = ymin + log(1.0-log(UseRandom::rnd())/rateOE);
//veto to get to correct distribution, recur if vetoed.
if(YVeto(y,dip,Coe,rateOE*exp(y-ymin)) && y < ymax)
return generateY(dip, y, ymax);
else{
return y;
}
}
/*
* Generates a rapidity for the next emission using shadows.
* The distribution f(y) in this member is using is an overestimate, and will be
* vetoed down to correct distribution in the checks of the x_T distribution.
*
* Already the overestimate f(y) is too messy to generate directly though,
* so it has to be done through a further overestimate g(y) > f(y) which is
* then vetoed (only depending on y) down to f(y) with YVeto().
* Look at the writeup for more details on f() and g().
*/
double Emitter::generateY(DipolePtr dip, tSPartonPtr sp1, tSPartonPtr sp2,
double ymin, double ymax) const {
//set up shorter names.
InvEnergy r = dip->size();
//To large dipoles will mess up the bessel function, so just shut them
// off by emitting after the maximum y.
if ( r*GeV > 100.0 ) return ymax + 1.0;
//Calculate the overestimated coefficient. See writeup for details.
- double Coe = alphaBar(r/2.0)/M_PI*
+ double Coe = alphaBarr(r/2.0)/M_PI*
sqr(gsl_sf_bessel_K1(r/(2.0*rMax())))*
sqr(r/(2.0*rMax()))*
(r/(2.0*theRScale)+2.0);
//For assymptotically large dipoles, the overestimated emission rate grows
//faster than Coe, so add an extra factor for large dipoles.
//this will have to be removed in the veto.
if(r>2.0*rMax()) //double check that this is ok!!!
Coe *= sqrt(r/(2.0*rMax()))*
exp(r/(rMax())-2.0);
//calculate the overestimated rate of emission (per unit rapidity).
double rateOE = 2.0*M_PI*Coe*log(1.0 + 2.0*theRScale/
rCut(dip, sp1, sp2, ymin));
//generate the rapidity. (see writeup for details.)
double y = ymin + log(1.0-log(UseRandom::rnd())/rateOE);
//veto to get to correct distribution, recur if vetoed.
if( YVeto(y, dip, sp1, sp2, Coe, rateOE*exp(y-ymin)) && y < ymax )
return generateY(dip, sp1, sp2, y, ymax);
return y;
}
/*
* Generate the transverse position. First generate the distance r
* larger than the cutoff used in generateY(), then decide around which
* parton, and then the angle. Distributions found in writeup.
*/
Parton::Point Emitter::generateXT(DipolePtr dip, double y0) const {
//set up
tEffectivePartonPtr p1 = dip->effectivePartons().first;
tEffectivePartonPtr p2 = dip->effectivePartons().second;
//The normalisation. See writeup for details.
double C2 = 2.0/log(1.0+2.0*theRScale/rCut(dip, y0)); //normalises g(z)
//Generate the distance.
InvEnergy r = 2.0*theRScale/(exp(2.0*UseRandom::rnd()/C2)-1.0);
//tested to give correct distribution C2/(r^3/theRScale+2r^2)
//generate the angle.
double phi = 2.0*M_PI*UseRandom::rnd();
//decide which parton, and create the Point to be returned.
if(UseRandom::rnd()>0.5)
return Parton::Point(p1->position().first + cos(phi)*r,
p1->position().second + sin(phi)*r);
else
return Parton::Point(p2->position().first + cos(phi)*r,
p2->position().second + sin(phi)*r);
}
/*
* Generate the transverse position. First generate the distance r
* larger than the cutoff used in generateY(), then decide around which
* parton, and then the angle. Distributions found in writeup.
*/
Parton::Point
Emitter::generateXT(DipolePtr dip, tSPartonPtr sp1, tSPartonPtr sp2, double y0) const {
//The normalisation. See writeup for details.
double C2 = 2.0/log(1.0 + 2.0*theRScale/rCut(dip, sp1, sp2, y0));
//normalises g(z)
//Generate the distance.
InvEnergy r = 2.0*theRScale/(exp(2.0*UseRandom::rnd()/C2)-1.0);
//tested to give correct distribution C2/(r^3/theRScale+2r^2)
// InvEnergy RM2 = rMax()*sqrt(2.0);
// double C = sqr(RM2/rCut(dip, sp1, sp2, y0)) + 1.0; // exponential of normalization
// InvEnergy rnew =
// RM2/sqrt(pow(C + 1.0, UseRandom::rnd()) - 1.0);
// // Gives the distribution 1/(r+r^3/2R^2) which is everywhere larger
// // than r(K1(r/R)^2.
//generate the angle.
double phi = 2.0*M_PI*UseRandom::rnd();
//decide which parton, and create the Point to be returned.
tPartonPtr pp =
UseRandom::rndbool()? dip->partons().first: dip->partons().second;
return Point(pp->position().first + cos(phi)*r,
pp->position().second + sin(phi)*r);
}
/*
* the main function to be called from outside. Other functions are mainly to help
* this one. To get the emission right, several layers of overestimates and vetoes
* are used.
*/
void Emitter::generate(Dipole & dip, double ymin, double ymax) const {
if ( dip.partons().first->shadow() ) {
if ( theMinusOrderingMode == 6 )
generateWithShadowsAgain(dip, ymin, ymax);
+ else if ( theMinusOrderingMode == 7 )
+ generateWithShadowsYetAgain(dip, ymin, ymax);
else
generateWithShadows(dip, ymin, ymax);
return;
}
//Lowest allowed emission rapidity. Not before any of the partons
//in the dipole, and not before the supplied ymin.
double y0 = max(ymin,max(dip.partons().first->y(),dip.partons().second->y()));
//define the resolved effective partons, as function of the dipole size.
//Later, when the transverse position is decided, this will have to
//be recalculated with the actual resolution ranges.
//This is an overestimate, as later lowering the range can only
//decrease the allowed phase space through less p+, and increased p_T.
dip.effectivePartons(EffectiveParton::create(*(dip.partons().first),
size(dip)),
EffectiveParton::create(*(dip.partons().second),
size(dip)));
//Some renaming to save space later.
tEffectivePartonPtr p1 = dip.effectivePartons().first;
tEffectivePartonPtr p2 = dip.effectivePartons().second;
//We will go through the while loop until something passes all the vetoes
//or pass the maximum allowed rapidity ymax. However, put a limit
//on the number of trials not to get stuck. So define the count to keep
//track. Possibly a for loop would be more appropriate at this point...
while ( true ) {
//reset the range to the overestimate, as we do not know
//what x_T will eb chosen this trial.
p1->setRange(size(dip));
p2->setRange(size(dip));
//generate a rapidity, according to an overestimate.
y0 = generateY(& dip, y0, ymax);
//if the generated rapidity is above the limit, return an empty pointer
if ( y0 > ymax ) {
dip.generatedGluon(new_ptr(Parton()));
dip.generatedY(y0);
break;
}
//generate a transverse position, using an overestimated
//phase space.
Parton::Point p = generateXT(& dip, y0);
//Bring down the overestimate in the distribution
//to get the right amplitude. After this, only phase space limitations
//left.
if(OEVeto(& dip,y0,p)) {
continue;
}
//Set up notation.
InvEnergy r13 = (p1->position() - p).pt();
InvEnergy r23 = (p2->position() - p).pt();
InvEnergy r12 = dip.size();
//this is to what extent the first parent emitted, and to what extent the
//second one. Here, it is some kind of superposition where they are emitting
//together, so both parents recoil a bit, etc.
double P1 = sqr(r23)/(sqr(r23) + sqr(r13));
double P2 = sqr(r13)/(sqr(r13) + sqr(r23));
//check how much is actually resolved, small emissions resolve more
if ( Current<DipoleEventHandler>()->emitter().rangeMode() != 1 ) {
if ( r13 < size(r12) )
p1->setRange( r13 );
if ( r23 < size(r12) )
p2->setRange( r23 );
}
//The transverse momentum of the new parton from the parents.
TransverseMomentum v1 = pTScale()*(p - p1->position())/sqr(r13);
TransverseMomentum v2 = pTScale()*(p - p2->position())/sqr(r23);
//calculate the 4-momentum of the emitted gluon.
TransverseMomentum pt = v1 + v2;
Energy pplus = pt.pt()*exp(-y0);
Energy pminus = pt.pt2()/pplus;
//check that there's enough p+
if ( p1->plus() - P1*pplus <= 0.0*GeV ){
continue;
}
if ( p2->plus() - P2*pplus <= 0.0*GeV ){
continue;
}
//calculate the new 4-momenta of the recoiled parents.
TransverseMomentum pt1 = p1->pT() - v1;
TransverseMomentum pt2 = p2->pT() - v2;
Energy plus1 = p1->plus() - P1*pplus;
Energy plus2 = p2->plus() - P2*pplus;
double y1 = log(pt1.pt()/plus1);
double y2 = log(pt2.pt()/plus2);
Energy minus1 = pt1.pt2()/plus1;
Energy minus2 = pt2.pt2()/plus2;
//this option use the p- ordering of the non-effective parton,
//so p- should be calculated from the non-effective parton.
if ( theMinusOrderingMode == 1 ) {
minus1 = pt1.pt()*exp(dip.partons().first->y());
minus2 = pt2.pt()*exp(dip.partons().second->y());
}
//in the first option, p- is required to be fully ordered with both parents.
//in the second option, the parton has to be ordered mainly to the parton that
//emitted it most, so it is allowed to be unordered by a factor P1 and P2.
//PSInflation is a plain factor that the emission is allowed to be unordered by.
if ( bothOrderedEvo() ) {
if ( pminus*thePSInflation < max(minus1, minus2)*thePMinusOrdering ) continue;
}
else {
if ( pminus*thePSInflation < max(P1*minus1, P2*minus2)*thePMinusOrdering ) continue;
}
//check rapidity ordered with the two recoiled parents.
if ( y1 > y0 ) {
continue;
}
if ( y2 > y0 ) {
continue;
}
//check that none of the internal partons recoiled over ymax.
if ( p1->recoilsOverYMax( v1, P1*pplus, ymax ) ) {
continue;
}
if ( p2->recoilsOverYMax( v2, P2*pplus, ymax ) ) {
continue;
}
//This is a self-consistency check.
//If things are donw correctly, then emissions at the limit of the
//cutoff in x_T used in generateXT() and generateY() should all be vetoed.
//if emissions at the limit go through, it means that we are missing part of
//the phase space just within the cutoff, which is bad.
//
//to check this, the cutoff is decreased by a factor 0.99 in generateY() etc above,
//to create the occasional emission in a region that should always be vetoed if the
//overestimates are fair. This is a check at the end so that none of these emission
//between 1 and 0.99 of the cutoff went through.
//TODO: match this with cutoff above
//TODO: proper error message.
if ( min(r13, r23) < min(2.0/3.0*pTScale()/(p1->plus()*exp(y0)),
min(2.0/3.0*pTScale()/(p2->plus()*exp(y0)),
dip.size()/4.0)) )
Throw<EmitterException>()
<< "In DIPSY::Emitter " << name() << ": Emission below r-cutoff passed vetos!"
<< " (r12 = " << ounit(r12, InvGeV) << ", r13 = " << ounit(r13, InvGeV)
<< ", r23 = " << ounit(r23, InvGeV)
<< "v1/pt = " << double(min(v1.pt(), v2.pt())/pt.pt()) << ")"
<< Exception::warning;
// passed. Set up a new parton for the dipole with the information of the emission.
PartonPtr gluon = new_ptr(Parton());
gluon->position(p);
dip.generatedGluon(gluon);
dip.generatedY(y0);
//leave the while loop.
break;
}
}
/*
* the main function to be called from outside when using
* shadows. Other functions are mainly to help this one. To get the
* emission right, several layers of overestimates and vetoes are used.
*/
void Emitter::generateWithShadows(Dipole & dip, double ymin, double ymax) const {
static DebugItem trace("DIPSY::Trace", 9);
static DebugItem attraction("DIPSY::Attraction", 9);
static DebugItem hardsup("DIPSY::HardSup", 9);
if ( trace ) cerr << "Gen " << dip.tag() << endl;
// Handy pointers to the partons.
tPartonPtr p1 = dip.partons().first;
tPartonPtr p2 = dip.partons().second;
//First check how far down the history we must consider previous shadows.
tSPartonPtr sp1 =
dip.partons().first->shadow()->resolve(size2(dip), dip.partons().second);
tSPartonPtr sp2 =
dip.partons().second->shadow()->resolve(size2(dip), dip.partons().first);
//Lowest allowed emission rapidity. Not before any of the partons
//in the dipole, and not before the supplied ymin.
double y0 = max(ymin, max(sp1->y0(), sp2->y0()));
ShadowParton::Propagator pp1 = sp1->propagator(size2(dip), p2, -1);
ShadowParton::Propagator pp2 = sp2->propagator(size2(dip), p1, -1);
p1->plus(max(pp1.colpos, pp1.acopos));
p2->plus(max(pp2.colpos, pp2.acopos));
//We will go through the while loop until something passes all the vetoes
//or pass the maximum allowed rapidity ymax. However, put a limit
//on the number of trials not to get stuck. So define the count to keep
//track. Possibly a for loop would be more appropriate at this point...
while ( true ) {
//generate a rapidity, according to an overestimate.
y0 = generateY(&dip, sp1, sp2, y0, ymax);
if ( isnan(y0) ) {
Throw<EmitterException>()
<< "Emitter: \"" << name()
<< "\" caught in infinite loop. Dipole skipped."
<< Exception::warning;
dip.generatedGluon(new_ptr(Parton()));
dip.generatedY(ymax + 1.0);
return;
}
//if the generated rapidity is above the limit, return an empty pointer
if ( y0 > ymax ) {
dip.generatedGluon(new_ptr(Parton()));
dip.generatedY(y0);
return;
}
//generate a transverse position, using an overestimated
//phase space.
Parton::Point p = generateXT(&dip, sp1, sp2, y0);
//Bring down the overestimate in the distribution
//to get the right amplitude. After this, only phase space limitations
//left.
if ( OEVeto(&dip, sp1, sp2, y0, p) ) {
continue;
}
//Set up notation.
InvEnergy2 r13 = (p1->position() - p).pt2();
InvEnergy2 r23 = (p2->position() - p).pt2();
InvEnergy2 r12 = dip.size2();
// We need to already here decide which parton is emitting.
bool firstsplit = UseRandom::rndbool(r23/(r23 + r13));
tPartonPtr pe = firstsplit? p1: p2;
tPartonPtr pr = firstsplit? p2: p1;
tSPartonPtr spe = firstsplit? sp1: sp2;
InvEnergy2 re3 = firstsplit? r13: r23;
// The emitting parton may be further resolved by the emission.
tSPartonPtr spre = re3 < size2(r12)? pe->shadow()->resolve(re3, pr): spe;
//The transverse momentum of the new parton from the emitter.
TransverseMomentum pt = pTScale()*(p - pe->position())/re3;
if ( hardsup && pt.pt() > 5.0*GeV && !UseRandom::rndbool(5.0*GeV/pt.pt()))
continue;
if ( attraction ) pt = -pt;
Energy pplus = pt.pt()*exp(-y0);
Energy pminus = pt.pt2()/pplus;
// //check that there's enough p+
// if ( pplus >= spre->plus0() ) continue;
// //calculate the new 4-momenta of the recoiled parents.
// TransverseMomentum pte = spre->pT() - pt;
// Energy pluse = spre->plus0() - pplus;
// double ye = log(pte.pt()/pluse);
// Energy minuse = pte.pt2()/pluse;
// if ( theMinusOrderingMode >= 2 ) {
// ShadowParton::Propagator prop =
// spre->propagator(min(re3, r12/4.0), pr, -1);
// if ( prop.fail ) continue;
// pluse = prop.p.plus() - pplus;
// if ( pluse <= ZERO ) continue;
// pte = TransverseMomentum(prop.p) - pt;
// ye = log(pte.pt()/pluse);
// if ( theMinusOrderingMode == 4 ) {
// minuse = ZERO;
// }
// else if ( theMinusOrderingMode >= 3 ) {
// minuse = pte.pt2()/pluse;
// if ( firstsplit ) {
// if ( pplus > prop.colpos || pminus < prop.colneg ) continue;
// } else {
// if ( pplus > prop.acopos || pminus < prop.aconeg ) continue;
// }
// }
// // *** TODO *** fix masses!
// }
// else if ( theMinusOrderingMode == 1 ) {
// minuse = pte.pt()*exp(pe->y());
// }
// // Ensure approximate minus ordering.
// if ( pminus*thePSInflation < minuse*thePMinusOrdering ) continue;
// //check rapidity ordered with the two recoiled parents.
// if ( ye > y0 ) continue;
if ( theMinusOrderingMode >= 2 ) {
ShadowParton::Propagator prop =
spre->propagator(min(re3, size2(r12)), pr, -1);
if ( prop.fail ) continue;
Energy pluse = prop.p.plus() - pplus;
if ( pluse <= ZERO ) continue;
TransverseMomentum pte = TransverseMomentum(prop.p) - pt;
double ye = log(pte.pt()/pluse);
if ( ye >= y0 ) continue;
if ( theMinusOrderingMode == 3 ) {
if ( firstsplit ) {
if ( pplus > prop.colpos || pminus < prop.colneg ) continue;
} else {
if ( pplus > prop.acopos || pminus < prop.aconeg ) continue;
}
Energy minuse = pte.pt2()/pluse;
if ( pminus*thePSInflation < minuse*thePMinusOrdering ) continue;
} else if ( theMinusOrderingMode == 2 ) {
Energy minuse = pte.pt2()/pluse;
if ( pminus*thePSInflation < minuse*thePMinusOrdering ) continue;
} else if ( theMinusOrderingMode >= 4 ) {
Energy minuse = pt.pt2()/pluse;
if ( firstsplit ) {
if ( pplus > prop.colpos && pluse > prop.acopos ) continue;
if ( pminus < prop.colneg && minuse < prop.aconeg ) continue;
} else {
if ( pplus > prop.acopos && pluse > prop.colpos ) continue;
if ( pminus < prop.aconeg && minuse < prop.colneg ) continue;
}
}
} else {
//check that there's enough p+
if ( pplus >= spre->plus0() ) continue;
//calculate the new 4-momenta of the recoiled parents.
TransverseMomentum pte = spre->pT() - pt;
Energy pluse = spre->plus0() - pplus;
double ye = log(pte.pt()/pluse);
if ( ye > y0 ) continue;
Energy minuse = pte.pt2()/pluse;
if ( pminus*thePSInflation < minuse*thePMinusOrdering ) continue;
}
// passed. Set up a new parton for the dipole with the information of the emission.
PartonPtr gluon = new_ptr(Parton());
gluon->position(p);
gluon->mainParent(pe);
dip.generatedGluon(gluon);
dip.generatedY(y0);
// And we're done!
return;
}
}
/*
-* the main function to be called from outside when using
-* shadows. Other functions are mainly to help this one. To get the
-* emission right, several layers of overestimates and vetoes are used.
-*/
+ * the main function to be called from outside when using
+ * shadows. Other functions are mainly to help this one. To get the
+ * emission right, several layers of overestimates and vetoes are used.
+ */
void Emitter::generateWithShadowsAgain(Dipole & dip, double ymin, double ymax) const {
static DebugItem trace("DIPSY::Trace", 9);
if ( trace ) cerr << "Gen " << dip.tag() << endl;
// Handy pointers to the partons.
tPartonPtr p1 = dip.partons().first;
tPartonPtr p2 = dip.partons().second;
//First check how far down the history we must consider previous shadows.
tSPartonPtr sp10 =
p1->shadow()->resolve(dip.size2(), dip.partons().second);
tSPartonPtr sp20 =
p2->shadow()->resolve(dip.size2(), dip.partons().first);
//Lowest allowed emission rapidity. Not before any of the partons
//in the dipole, and not before the supplied ymin.
double y0 = max(ymin, max(sp10->y0(), sp20->y0()));
// Also find the largest plus of previously emitted gluons.
ShadowParton::Propagator pp1 = sp10->propagator(dip.size2(), p2, -1);
ShadowParton::Propagator pp2 = sp20->propagator(dip.size2(), p1, -1);
Energy plus0 = max(max(pp1.colpos, pp1.acopos),
max(pp2.colpos, pp2.acopos));
// The maxumum alphabar
- double alb0 = alphaBar(dip.size());
+ double alb0 = alphaBarr(dip.size());
+
+ // The overall over estimated normalization.
+ double C = splitF? 2.25: 2.0;
// This gives the maxumum allowed kt^2 for the highest allowed y
Energy2 QM2 = sqr(exp(ymax)*plus0);
// The confinement scale
Energy2 m02 = sqr(pTScale()/rMax());
// The overestimated kt-integral at maximum rapidity.
- double intYM = 2.0*alb0*log(QM2/m02 + 1.0);
+ double intYM = C*alb0*log(QM2/m02 + 1.0);
// Place a dummy gluon as emitted;
dip.generatedGluon(new_ptr(Parton()));
//We will go through the while loop until something passes all the vetoes
//or pass the maximum allowed rapidity ymax.
while ( true ) {
// This gives the maxumum allowed kt^2 for the lowest allowed y
Energy2 QL2 = sqr(exp(y0)*plus0);
// The overestimated kt-integral at maximum rapidity.
- double intYL = 2.0*alb0*log(QL2/m02 + 1.0);
+ double intYL = C*alb0*log(QL2/m02 + 1.0);
// We assume that the kt-integral increases approximately with y
// according to intY = B+A(y-ymin), with
double B = intYL;
double A = (intYM - intYL)/(ymax - y0);
// Since the second derivative wrt y of the actual integral is
// always positive this linear interpolation is always an
// overestimate. So we can generate a new y according to it
double y = y0 + (sqrt(sqr(B)-2.0*A*log(UseRandom::rnd())) - B)/A;
dip.generatedY(y);
if ( isnan(y) || y < y0 ) {
Throw<EmitterException>()
<< "Emitter: \"" << name()
<< "\" caught in infinite loop. Dipole skipped."
<< Exception::warning;
dip.generatedY(ymax + 1.0);
return;
}
// If the generated rapidity is above the limit, return an empty pointer
if ( y > ymax ) return;
Energy2 Q2 = sqr(exp(y)*plus0);
- double intY = 2.0*alb0*log(Q2/m02 + 1.0);
+ double intY = C*alb0*log(Q2/m02 + 1.0);
double rat = intY/(A*(y - y0) + B);
+
y0 = y;
if ( rat > 1.0000000000001 )
Throw<EmitterException>() << Exception::abortnow;
if ( !UseRandom::rndbool(rat) ) continue;
// Now we have a rapidity, let's generate transverse momenta.
Energy2 pt2 = m02*pow(Q2/m02 + 1.0, UseRandom::rnd()) - m02;
Energy pt = sqrt(pt2);
double phi = UseRandom::rnd(2.0*M_PI);
TransverseMomentum kT(pt*sin(phi), pt*cos(phi));
// Then we choose which parton to radiate from and consstruct the
// position and distances for the new gluon.
bool firstsplit = UseRandom::rndbool();
tPartonPtr pe = firstsplit? p1: p2;
tPartonPtr pr = firstsplit? p2: p1;
Parton::Point p = pe->position() + pTScale()*kT/pt2;
InvEnergy2 d2eg = (pe->position() - p).pt2();
InvEnergy2 d2rg = (pr->position() - p).pt2();
InvEnergy2 d2er = dip.size2();
InvEnergy2 scale = min(d2eg, d2er);
// Throw according to overestimate
- rat = alphaBar(sqrt(scale))*d2er/(alb0*2.0*(d2eg + d2rg));
+ rat = alphaBarr(sqrt(scale))*d2er/(alb0*2.0*(d2eg + d2rg));
if ( !UseRandom::rndbool(rat) ) continue;
// Now get resolve the shadow parton actually doing the emission
// and calculate the kinematics.
tSPartonPtr spe = pe->shadow()->resolve(scale, pr);
Energy pplus = pt*exp(-y);
Energy pminus = pt2/pplus;
ShadowParton::Propagator prop = spe->propagator(scale, pr, -1);
if ( prop.fail ) continue;
Energy pluse = prop.p.plus() - pplus;
if ( pluse <= ZERO ) continue;
+
+ // Optionally correct for full splitting function.
+ if ( splitF ) {
+ double z = pplus/prop.p.plus();
+ if ( z > 0.5 ) continue;
+ double rat = sqr(1.0 - z*(1.0 - z))/(1.125*(1.0 - z));
+ if ( !UseRandom::rndbool(rat) ) continue;
+ if ( splitF > 1 &&
+ sqrt(m02/(m02 + pt2)) < UseRandom::rnd() ) continue;
+ }
+
TransverseMomentum pte = TransverseMomentum(prop.p) - kT;
double ye = log(pte.pt()/pluse);
if ( ye >= y ) continue;
Energy minuse = pt2/pluse;
if ( firstsplit ) {
if ( pplus > prop.colpos && pluse > prop.acopos ) continue;
if ( pminus < prop.colneg && minuse < prop.aconeg ) continue;
} else {
if ( pplus > prop.acopos && pluse > prop.colpos ) continue;
if ( pminus < prop.aconeg && minuse < prop.colneg ) continue;
}
// All kinematical constraints passed. Set up a new parton for the
// dipole with the information of the emission.
PartonPtr gluon = new_ptr(Parton());
gluon->position(p);
gluon->mainParent(pe);
gluon->plus(pplus);
gluon->pT(kT);
gluon->y(y);
dip.generatedGluon(gluon);
dip.generatedY(y);
// And we're done!
return;
}
}
+
+/*
+ * the main function to be called from outside when using
+ * shadows. Other functions are mainly to help this one. To get the
+ * emission right, several layers of overestimates and vetoes are used.
+ */
+void Emitter::generateWithShadowsYetAgain(Dipole & dip, double ymin, double ymax) const {
+
+ static DebugItem trace("DIPSY::Trace", 9);
+
+ if ( trace ) cerr << "Gen " << dip.tag() << endl;
+
+ // Handy pointers to the partons.
+ tPartonPtr p1 = dip.partons().first;
+ tPartonPtr p2 = dip.partons().second;
+
+ // First check how far down the history we must consider previous shadows.
+ tSPartonPtr sp10 =
+ p1->shadow()->resolve(dip.size2(), dip.partons().second);
+ tSPartonPtr sp20 =
+ p2->shadow()->resolve(dip.size2(), dip.partons().first);
+
+ // Also get the corresponding propagators
+ ShadowParton::Propagator pp1 = sp10->propagator(dip.size2(), p2, -1);
+ ShadowParton::Propagator pp2 = sp20->propagator(dip.size2(), p1, -1);
+
+ //Lowest allowed emission rapidity. Not before any of the partons
+ //in the dipole, and not before the supplied ymin.
+ double y0 = max(ymin, max(sp10->y0(), sp20->y0()));
+
+ // The generation of pt is limited by qplus/pplus = z < 0.5, and
+ // since qplus = qt*exp(-y) we get a limit qt < maxplus*exp(y) where
+ Energy maxplus = max(pp1.p.plus(), pp2.p.plus())/2.0;
+
+ // The maxumum alphabar
+ double alb0 = alphaBarr(dip.size());
+
+ // The overall over estimated normalization.
+ double C = splitF? 2.25: 2.0;
+
+ // This gives the maxumum allowed kt^2 for the highest allowed y
+ Energy2 QM2 = sqr(exp(ymax)*maxplus);
+
+ // The confinement scale
+ Energy2 m02 = sqr(pTScale()/rMax());
+
+ // The overestimated kt-integral at maximum rapidity.
+ double intYM = C*alb0*log(QM2/m02 + 1.0);
+
+ // Place a dummy gluon as emitted;
+ PartonPtr gluon = new_ptr(Parton());
+ dip.generatedGluon(gluon);
+ dip.generatedY(ymax + 1.0);
+
+
+ //We will go through the while loop until something passes all the vetoes
+ //or pass the maximum allowed rapidity ymax.
+ while ( true ) {
+
+ // This gives the maxumum allowed kt^2 for the lowest allowed y
+ Energy2 QL2 = sqr(exp(y0)*maxplus);
+
+ // The overestimated kt-integral at maximum rapidity.
+ double intYL = C*alb0*log(QL2/m02 + 1.0);
+
+ // We assume that the kt-integral increases approximately with y
+ // according to intY = B+A(y-ymin), with
+ double B = intYL;
+ double A = (intYM - intYL)/(ymax - y0);
+
+ // Since the second derivative wrt y of the actual integral is
+ // always positive this linear interpolation is always an
+ // overestimate. So we can generate a new y according to it
+ double y = y0 + (sqrt(sqr(B)-2.0*A*log(UseRandom::rnd())) - B)/A;
+
+
+ dip.generatedY(y);
+
+ if ( isnan(y) || y < y0 ) {
+ Throw<EmitterException>()
+ << "Emitter: \"" << name() << "\" caught in infinite loop. Dipole skipped."
+ << Exception::warning;
+ return;
+ }
+
+ // If the generated rapidity is above the limit, return an empty pointer
+ if ( y > ymax ) return;
+
+ Energy2 Q2 = sqr(exp(y)*maxplus);
+ double intY = C*alb0*log(Q2/m02 + 1.0);
+ double rat = intY/(A*(y - y0) + B);
+
+ y0 = y;
+ if ( rat > 1.0000000000001 )
+ Throw<EmitterException>() << Exception::abortnow;
+ if ( !UseRandom::rndbool(rat) ) continue;
+
+ // Now we have a rapidity, let's generate transverse momenta.
+ Energy2 pt2 = m02*pow(Q2/m02 + 1.0, UseRandom::rnd()) - m02;
+ Energy pt = sqrt(pt2);
+ double phi = UseRandom::rnd(2.0*M_PI);
+ TransverseMomentum pT(pt*sin(phi), pt*cos(phi));
+
+ // Then we choose which parton to radiate from and construct the
+ // position and distances for the new gluon.
+ bool firstsplit = UseRandom::rndbool();
+ tPartonPtr pe = firstsplit? p1: p2;
+ tPartonPtr pr = firstsplit? p2: p1;
+ Parton::Point p = pe->position() + pTScale()*pT/pt2;
+
+ InvEnergy2 d2eg = (pe->position() - p).pt2();
+ InvEnergy2 d2rg = (pr->position() - p).pt2();
+ InvEnergy2 d2er = dip.size2();
+ InvEnergy2 scale = min(d2eg, d2er);
+
+ // Throw according to overestimate
+ rat = alphaBarr(sqrt(scale))*d2er/(alb0*2.0*(d2eg + d2rg));
+ if ( !UseRandom::rndbool(rat) ) continue;
+
+ // Now get resolve the shadow parton actually doing the emission
+ // and calculate the kinematics.
+ tSPartonPtr spe = pe->shadow()->resolve(scale, pr);
+ Energy pplus = pt*exp(-y);
+ ShadowParton::Propagator prop = spe->propagator(scale, pr, -1);
+ if ( prop.fail ) continue;
+ double z = pplus/prop.p.plus();
+ if ( z > 0.5 ) continue;
+
+ // Optionally correct for full splitting function.
+ if ( splitF && !UseRandom::rndbool(sqr(1.0 - z*(1.0 - z))/(1.125*(1.0 - z))) ) continue;
+ if ( splitF > 1 &&
+ sqrt(m02/(m02 + pt2/sqr(splitF))) < UseRandom::rnd() ) continue;
+ if ( splitF < 0 &&
+ sqrt(sqrt(m02/(m02 + pt2/sqr(splitF)))) < UseRandom::rnd() ) continue;
+
+
+ // *** TODO *** we may want to check here if the emission is at all
+ // possible in the sense that either the emitter or the emitted
+ // can be put on shell with light-cone ordering. But lets keep all
+ // possible emissions for now so that we won't lose anything
+ // (eg. what if both enter in separate interactions?).
+
+ gluon->position(p);
+ gluon->mainParent(pe);
+ gluon->plus(pplus);
+ gluon->pT(pT);
+ gluon->y(y);
+ dip.generatedY(y);
+
+ // And we're done!
+ return;
+ }
+}
+
/*
* Maked the dipole actually emit the dipole prepared in generate(), setting up
* parents, children, changing 4-momenta etc.
*/
void Emitter::emit(Dipole & d) const {
//some notation.
if ( d.partons().first->shadow() ) {
emitWithShadows(d);
return;
}
PartonPtr p = d.generatedGluon();
InvEnergy r13 = (d.partons().first->position() - p->position()).pt();
InvEnergy r23 = (d.partons().second->position() - p->position()).pt();
//The recoils.
//TODO: use recoil().
TransverseMomentum v1 = pTScale()*(p->position() - d.partons().first->position())/sqr(r13);
TransverseMomentum v2 = pTScale()*(p->position() - d.partons().second->position())/sqr(r23);
//the ratio each parent emitted the gluon with.
double P1 = sqr(r23)/(sqr(r13) + sqr(r23));
double P2 = 1.0 - P1;
//set 4-momenta for emission.
p->pT(v1 + v2);
p->y(d.generatedY());
p->plus(p->pT().pt()*exp(-d.generatedY()));
p->minus(p->pT().pt()*exp(d.generatedY()));
p->oY(p->y());
//change the dipole structure, generate new colour etc.
d.splitDipole(P2);
//perform the recoil on the effective partons.
//the resolution ranges should be set since the generation of the emission.
d.effectivePartons().first->recoil( v1, P1*p->plus() );
d.effectivePartons().second->recoil( v2, P2*p->plus() );
}
void Emitter::emitWithShadows(Dipole & d) const {
static DebugItem trace("DIPSY::Trace", 9);
static DebugItem attraction("DIPSY::Attraction", 9);
if ( trace ) cerr << "Emit " << d.tag();
//some notation.
PartonPtr p = d.generatedGluon();
// Decide which parton is the emitter.
bool em1 = ( p->mainParent() == d.partons().first );
tPartonPtr emitter = em1? d.partons().first: d.partons().second;
tPartonPtr recoiler = em1? d.partons().second: d.partons().first;
InvEnergy2 res = emitter->dist2(*p);
InvEnergy2 scale =
- min(res, theMinusOrderingMode == 6? d.size2(): size2(d));
+ min(res, theMinusOrderingMode >= 6? d.size2(): size2(d));
tSPartonPtr sem = emitter->shadow()->resolve(scale, recoiler);
TransverseMomentum rec =
pTScale()*(p->position() - emitter->position())/res;
if ( attraction ) rec = -rec;
//change the dipole structure, generate new colour etc.
d.splitDipole(em1? 0.0: 1.0);
//set 4-momenta for emission.
p->pT(rec);
p->y(d.generatedY());
p->plus(p->pT().pt()*exp(-d.generatedY()));
p->minus(p->pT().pt()*exp(d.generatedY()));
p->oY(p->y());
if ( theMinusOrderingMode >= 2 ) {
ShadowParton::Propagator prop = sem->propagator(scale, recoiler, -1);
emitter->pT(TransverseMomentum(prop.p) - rec);
emitter->plus(prop.p.plus() - p->plus());
emitter->y(log(emitter->mt()/emitter->plus()));
emitter->minus(emitter->mt2()/emitter->plus());
} else {
emitter->pT(sem->pT() - rec);
emitter->plus(sem->plus() - p->plus());
emitter->y(log(emitter->pT().pt()/emitter->plus()));
emitter->minus(emitter->mt2()/emitter->plus());
}
emitter->shadow()->setupEmission(*emitter, *p, *recoiler);
if ( trace ) cerr << " -> " << d.children().first->tag()
<< " + " << d.children().second->tag() << endl;
}
void Emitter::persistentOutput(PersistentOStream & os) const {
os << ounit(thePSInflation, 1.0)
<< ounit(thePMinusOrdering, 1.0)
<< ounit(theRScale, InvGeV)
<< ounit(theRMax, InvGeV)
<< ounit(thePTScale, 1.0)
<< ounit(theBothOrderedEvo, true)
<< ounit(theBothOrderedInt, true)
<< ounit(theBothOrderedFS, true)
<< ounit(theRangeMode, 1)
- << ounit(theMinusOrderingMode, 1) << thePlusInflation << sizeFactor;
+ << ounit(theMinusOrderingMode, 1) << splitF << thePlusInflation << sizeFactor;
}
void Emitter::persistentInput(PersistentIStream & is, int) {
is >> iunit(thePSInflation, 1.0)
>> iunit(thePMinusOrdering, 1.0)
>> iunit(theRScale, InvGeV)
>> iunit(theRMax, InvGeV)
>> iunit(thePTScale, 1.0)
>> iunit(theBothOrderedEvo, true)
>> iunit(theBothOrderedInt, true)
>> iunit(theBothOrderedFS, true)
>> iunit(theRangeMode, 1)
- >> iunit(theMinusOrderingMode, 1) >> thePlusInflation >> sizeFactor;
+ >> iunit(theMinusOrderingMode, 1) >> splitF >> thePlusInflation >> sizeFactor;
}
// Static variable needed for the type description system in ThePEG.
#include "ThePEG/Utilities/DescribeClass.h"
DescribeClass<Emitter,HandlerBase>
describeDIPSYEmitter("DIPSY::Emitter", "libAriadne5.so libDIPSY.so");
void Emitter::Init() {
static ClassDocumentation<Emitter> documentation
("The Emitter class is responsible for generating and performing "
"emissions from dipoles. This base class does the default emission "
"strategy.");
static Parameter<Emitter,InvEnergy> interfaceRScale
("RScale",
"Constant used in overestimate of emission probability.",
&Emitter::theRScale, InvGeV, 1.0*InvGeV, 0.0*InvGeV, 0.0*InvGeV,
true, false, Interface::lowerlim);
static Parameter<Emitter,double> interfacePlusInflation
("PlusInflation",
"How much p+ ordering should be enforced in the generation. 1 is normal "
"ordering, high numbers are no ordering(energy must still be conserved "
"though), low number demands stronger ordering",
&Emitter::thePlusInflation, 1.0, 1.0, 0.0, 0.0,
true, false, Interface::lowerlim);
static Parameter<Emitter,double> interfaceSizeFactor
("SizeFactor",
"The factor dividing the emitting dipole size when determining the resolution of previous emissions or EffectiveParton range.",
&Emitter::sizeFactor, 2.0, 0.0, 0,
true, false, Interface::lowerlim);
static Parameter<Emitter,double> interfacePSInflation
("PSInflation",
"How much p+- ordering should be enforced. 1 is normal ordering, high numbers "
"are no ordering(energy must still be conserved though), "
"low number demands stronger ordering",
&Emitter::thePSInflation, 1.0, 1.0, 0.0, 0.0,
true, false, Interface::lowerlim);
static Parameter<Emitter,double> interfacePMinusOrdering
("PMinusOrdering",
"An extra factor strengthening the p- ordering on top of the PSInflation."
"A large value will suppress large dipoles more.",
&Emitter::thePMinusOrdering, 1.0, 1.0, 0.0, 0.0,
true, false, Interface::lowerlim);
static Parameter<Emitter,double> interfacePTScale
("PTScale",
"If pT is 1/r or 2/r.",
&Emitter::thePTScale, 1.0, 1.0, 0.0, 0.0,
true, false, Interface::lowerlim);
static Parameter<Emitter,InvEnergy> interfaceRMax
("RMax",
"The confinement scale (in iverse GeV). If set to zero, "
"the value of <interface>DipoleEventHandler::RMax</interface> of the "
"controlling event handler will be used.",
&Emitter::theRMax, InvGeV, 0.0*InvGeV, 0.0*InvGeV, 0*InvGeV,
true, false, Interface::lowerlim);
static Switch<Emitter,bool> interfaceBothOrderedEvo
("BothOrderedEvo",
"If an emission should be fully ordered with both its parents."
"otherwise it will be weighted according to how close they are.",
&Emitter::theBothOrderedEvo, false, true, false);
static SwitchOption interfaceBothOrderedEvoTrue
(interfaceBothOrderedEvo,"True","both parents fully ordered.",true);
static SwitchOption interfaceBothOrderedEvoFalse
(interfaceBothOrderedEvo,"False","weighted by distance.",false);
static Switch<Emitter,bool> interfaceBothOrderedInt
("BothOrderedInt",
"If an emission should be fully ordered with both its parents."
"otherwise it will be weighted according to how close they are.",
&Emitter::theBothOrderedInt, false, true, false);
static SwitchOption interfaceBothOrderedIntTrue
(interfaceBothOrderedInt,"True","both parents fully ordered.",true);
static SwitchOption interfaceBothOrderedIntFalse
(interfaceBothOrderedInt,"False","weighted by distance.",false);
static Switch<Emitter,bool> interfaceBothOrderedFS
("BothOrderedFS",
"If an emission should be fully ordered with both its parents."
"otherwise it will be weighted according to how close they are.",
&Emitter::theBothOrderedFS, false, true, false);
static SwitchOption interfaceBothOrderedFSTrue
(interfaceBothOrderedFS,"True","both parents fully ordered.",true);
static SwitchOption interfaceBothOrderedFSFalse
(interfaceBothOrderedFS,"False","weighted by distance.",false);
static Switch<Emitter,int> interfaceRangeMode
("RangeMode",
"How the range of coherenent emissions is determined.",
&Emitter::theRangeMode, 0, true, false);
static SwitchOption interfaceRangeModeMin
(interfaceRangeMode,
"Min",
"minimum of half mother dipole and distance to emission. Default.",
0);
static SwitchOption interfaceRangeModeMax
(interfaceRangeMode,
"Mother",
"Half distance of mother dipole, no matter how close the emission is.",
1);
static Switch<Emitter,int> interfaceMinusOrderingMode
("MinusOrderingMode",
"Sets how the ordering in p- is done in the virtual cascade, in relation to effective partons mainly.",
&Emitter::theMinusOrderingMode, 0, true, false);
static SwitchOption interfaceMinusOrderingModeEffectiveParton
(interfaceMinusOrderingMode,
"EffectiveParton",
"Uses the momentum of the effective parton to order, both plus and pt.",
0);
static SwitchOption interfaceMinusOrderingModeEffectivePT
(interfaceMinusOrderingMode,
"EffectivePT",
"Uses the pt of the effective parton, but the rapidity of the single emitting parton.",
1);
static SwitchOption interfaceMinusOrderingModeTrueShadow
(interfaceMinusOrderingMode,
"TrueShadow",
"Use the full shadow mechanism for resolved emissions to get the "
"incoming propagator.",
2);
static SwitchOption interfaceMinusOrderingModeOrderedShadow
(interfaceMinusOrderingMode,
"OrderedShadow",
"Use the full shadow mechanism for resolved emissions to get the "
"incoming propagator and checking ordering with previous emissions.",
3);
static SwitchOption interfaceMinusOrderingModeUnorderedShadow
(interfaceMinusOrderingMode,
"UnorderedShadow",
"In shadow mechanism, do not order in emissions - this is anyway done "
"later on in the construction of propagators.",
4);
static SwitchOption interfaceMinusOrderingModeCutShadow
(interfaceMinusOrderingMode,
"CutShadow",
"In shadow mechanism, do not order in emissions - this is anyway done "
"later on in the construction of propagators. But allow it to influence "
"the cutoff in dipole sizes.",
5);
static SwitchOption interfaceMinusOrderingModePtGen
(interfaceMinusOrderingMode,
"PtGen",
"As cut shadow but completely new generation in transverse momentum.",
6);
+ static SwitchOption interfaceMinusOrderingModePtGenZ
+ (interfaceMinusOrderingMode,
+ "PtGenZ",
+ "As cut shadow but completely new generation in transverse momentum using "
+ "only z < 0.5 to limit transverse momenum.",
+ 7);
+
+
+ static Switch<Emitter,int> interfaceSplittingFunction
+ ("SplittingFunction",
+ "Determines which splitting function to use.",
+ &Emitter::splitF, 0, true, false);
+ static SwitchOption interfaceSplittingFunctionSmallX
+ (interfaceSplittingFunction,
+ "SmallX",
+ "Only use the leading small-x pole 1/z.",
+ 0);
+ static SwitchOption interfaceSplittingFunctionFullAP
+ (interfaceSplittingFunction,
+ "FullAP",
+ "Use the full Altarelli-Parisi splitting function.",
+ 1);
+
+ static SwitchOption interfaceSplittingFunctionFullAPkTsup
+ (interfaceSplittingFunction,
+ "FullAPkTsup",
+ "Use the full Altarelli-Parisi splitting function and an "
+ "additionan suppression of large kt",
+ 2);
+
+ static SwitchOption interfaceSplittingFunctionFullAPkTsup3
+ (interfaceSplittingFunction,
+ "FullAPkTsup3",
+ "Use the full Altarelli-Parisi splitting function and an "
+ "additionan suppression of large kt",
+ 3);
+
+ static SwitchOption interfaceSplittingFunctionFullAPkTsup4
+ (interfaceSplittingFunction,
+ "FullAPkTsup4",
+ "Use the full Altarelli-Parisi splitting function and an "
+ "additionan suppression of large kt",
+ 4);
+ static SwitchOption interfaceSplittingFunctionFullAPkTsupm4
+ (interfaceSplittingFunction,
+ "FullAPkTsupm4",
+ "Use the full Altarelli-Parisi splitting function and an "
+ "additionan suppression of large kt",
+ -4);
+
}
diff --git a/DIPSY/Emitter.h b/DIPSY/Emitter.h
--- a/DIPSY/Emitter.h
+++ b/DIPSY/Emitter.h
@@ -1,424 +1,442 @@
// -*- C++ -*-
#ifndef DIPSY_Emitter_H
#define DIPSY_Emitter_H
//
// This is the declaration of the Emitter class.
//
#define THEPEG_NEW_CLASS_DESCRIPTION
#include "ThePEG/Handlers/HandlerBase.h"
#include "Emitter.fh"
#include "Dipole.fh"
#include "Parton.h"
namespace DIPSY {
using namespace ThePEG;
/**
* The Emitter class is responsible for generating and performing
* emissions from dipoles. This base class does the standard thing. Any
* non-standard thing must be implemented in a sub-class overriding
* the generate() and/or emit() functions.
*
* @see \ref EmitterInterfaces "The interfaces"
* defined for Emitter.
*/
class Emitter: public HandlerBase {
public:
/** Convenietn typedef. */
typedef Parton::Point Point;
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
inline Emitter()
: testingPS(false), fixY(0.0), thePSInflation(1.0), thePMinusOrdering(1.0),
thePTScale(1.0), theRScale(1.0*InvGeV), theRMax(0.0*InvGeV),
theBothOrderedEvo(true), theBothOrderedInt(true), theBothOrderedFS(true),
- theRangeMode(0),theMinusOrderingMode(0), thestMode(false),
+ theRangeMode(0),theMinusOrderingMode(0), splitF(0), thestMode(false),
thePlusInflation(1.0), sizeFactor(2.0) {}
/**
* The destructor.
*/
virtual ~Emitter();
//@}
public:
/** @name Virtual functions which may be overridden by sub-classes. */
//@{
/**
* Return the running coupling for the given size (scale). /CF
*/
- double alphaS(InvEnergy r) const;
+ double alphaSr(InvEnergy r) const;
+
+ /**
+ * Return the running coupling for the given size (scale). /CF
+ */
+ double alphaS(Energy mu) const;
/**
* if pT is 1/r or 2/r.
*/
inline double pTScale() const {
return thePTScale;
}
/**
* Alpha bar = alphas*Nc/pi /CF
*/
- inline double alphaBar(InvEnergy r) const {
- return alphaS(r)*3.0/M_PI;
+ inline double alphaBar(Energy mu) const {
+ return alphaS(mu)*3.0/M_PI;
+ }
+
+ /**
+ * Alpha bar = alphas*Nc/pi /CF
+ */
+ inline double alphaBarr(InvEnergy r) const {
+ return alphaSr(r)*3.0/M_PI;
}
/**
* Sets the shape of the overestimate in the genreation.
* The cross section does not (should not) depend on rScale. /CF
*/
inline void rScale(InvEnergy rScale) {
theRScale = rScale;
}
/**
* Get bothordered.
*/
inline bool bothOrderedEvo() const {
return theBothOrderedEvo;
};
inline bool bothOrderedInt() const {
return theBothOrderedInt;
};
inline bool bothOrderedFS() const {
return theBothOrderedFS;
};
/**
* Set PSInfaltion
*/
inline void PSInflation(double PSInflation) {
thePSInflation = PSInflation;
}
/**
* Get PSInfaltion
*/
inline double PSInflation() const {
return thePSInflation;
}
/**
* Set PMinusOrdering
*/
inline void PMinusOrdering(double x) {
thePMinusOrdering = x;
}
/**
* Get PMinusOrdering
*/
inline double PMinusOrdering() const {
return thePMinusOrdering;
}
/**
* get the rangeMode
**/
inline int rangeMode() const {
return theRangeMode;
}
/**
* get the minusOrderingMode
**/
inline int minusOrderingMode() const {
return theMinusOrderingMode;
}
/**
* The confinement scale.
*/
InvEnergy rMax() const;
/**
* The resolution size of an emitting dipole or its EffectiveParton
* range.
*/
InvEnergy2 size2(InvEnergy2 r2) const {
return r2/sqr(sizeFactor);
}
InvEnergy size(InvEnergy r) const {
return r/sizeFactor;
}
InvEnergy2 size2(const Dipole & d) const;
InvEnergy size(const Dipole & d) const;
/**
* Generate a possible emission or a swing from a given dipole in the
* given rapidity interval [\a miny,\a maxy].
*/
virtual void generate(Dipole & dipole, double miny, double maxy) const;
/**
* Generate a possible emission or a swing from a given dipole using
* shadows in the given rapidity interval [\a miny,\a maxy].
*/
virtual void generateWithShadows(Dipole & dipole, double miny, double maxy) const;
virtual void generateWithShadowsAgain(Dipole & dipole, double miny, double maxy) const;
+ virtual void generateWithShadowsYetAgain(Dipole & dipole, double miny, double maxy) const;
/**
* Perform the emission previously generated for the given \a
* dipole. If no emission has been generated a runtime_error is
* thrown.
*/
virtual void emit(Dipole & dipole) const;
/**
* Perform the emission previously generated for the given \a
* dipole using shadows. If no emission has been generated a runtime_error is
* thrown.
*/
virtual void emitWithShadows(Dipole & dipole) const;
//@}
protected:
/**
* Internal function.
*/
virtual InvEnergy rCut(DipolePtr dip, double y) const;
/**
* Internal function.
*/
virtual bool OEVeto(DipolePtr dip, double y0, Point p) const;
/**
* Internal function.
*/
virtual InvEnergy rCut(DipolePtr dip, tSPartonPtr sp1,
tSPartonPtr sp2, double y) const;
/**
* Internal function.
*/
virtual bool OEVeto(DipolePtr dip, tSPartonPtr sp1,
tSPartonPtr sp2, double y0, Point p) const;
/**
* Internal function.
*/
virtual bool YVeto(double y, DipolePtr dip, double Coe, double rateOE) const;
/**
* Internal function.
*/
virtual bool YVeto(double y, DipolePtr dip, tSPartonPtr sp1, tSPartonPtr sp2,
double Coe, double rateOE) const;
/**
* Internal function.
*/
virtual double generateY(DipolePtr dip, double ymin, double ymax) const;
/**
* Internal function.
*/
virtual double generateY(DipolePtr dip, tSPartonPtr sp1, tSPartonPtr sp2,
double ymin, double ymax) const;
/**
* Internal function.
*/
virtual Point generateXT(DipolePtr dip, double y0) const;
/**
* Internal function.
*/
virtual Point generateXT(DipolePtr dip, tSPartonPtr sp1, tSPartonPtr sp2, double y0) const;
public:
/**
* Debugging and testing
*/
mutable bool testingPS;
mutable double fixY;
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected: //@{
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
inline virtual IBPtr clone() const {
return new_ptr(*this);
}
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
inline virtual IBPtr fullclone() const {
return new_ptr(*this);
}
//@}
// If needed, insert declarations of virtual function defined in the
// InterfacedBase class here (using ThePEG-interfaced-decl in Emacs).
protected:
/**
* How much P+- ordering should be required. 1 is nomral ordering
* high values are no ordering, low number are strong ordering.
*/
double thePSInflation;
/**
* Controls the strength of the p- ordering in the evolution.
*/
double thePMinusOrdering;
/**
* if pt is 1/r or 2/r.
*/
double thePTScale;
/**
* the scale in the distribution of transverse r. /CF
*/
InvEnergy theRScale;
/**
* The confinement scale.
*/
InvEnergy theRMax;
/**
* If the plus/minus ordering should be full strenght
* for both parents in teh cascade, interaction and final state.
*/
bool theBothOrderedEvo;
bool theBothOrderedInt;
bool theBothOrderedFS;
/**
* How the range is determined.
**/
int theRangeMode;
/**
* How the minus ordering is made in the cascade.
**/
int theMinusOrderingMode;
/**
+ * Determines which splitting function to use.
+ */
+ int splitF;
+
+ /**
* If test-modification to evolution should be on. /CF
*/
bool thestMode;
/**
* Allow extra room for plus momenta in generation.
*/
double thePlusInflation;
/**
* The factor dividing the emitting dipole size when determining the
* resolution of previous emissions or EffectiveParton range.
*/
double sizeFactor;
public:
/**
* Exception class.
*/
struct EmitterException: public Exception {};
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
Emitter & operator=(const Emitter &);
};
}
#ifndef THEPEG_NEW_CLASS_DESCRIPTION
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of Emitter. */
template <>
struct BaseClassTrait<DIPSY::Emitter,1> {
/** Typedef of the first base class of Emitter. */
typedef HandlerBase NthBase;
};
/** This template specialization informs ThePEG about the name of
* the Emitter class and the shared object where it is defined. */
template <>
struct ClassTraits<DIPSY::Emitter>
: public ClassTraitsBase<DIPSY::Emitter> {
/** Return a platform-independent class name */
static string className() { return "DIPSY::Emitter"; }
/**
* The name of a file containing the dynamic library where the class
* Emitter is implemented. It may also include several, space-separated,
* libraries if the class Emitter depends on other classes (base classes
* excepted). In this case the listed libraries will be dynamically
* linked in the order they are specified.
*/
static string library() { return "libAriadne5.so libDIPSY.so"; }
};
/** @endcond */
}
#endif
#endif /* DIPSY_Emitter_H */
diff --git a/DIPSY/GlauberAnalysis.cc b/DIPSY/GlauberAnalysis.cc
--- a/DIPSY/GlauberAnalysis.cc
+++ b/DIPSY/GlauberAnalysis.cc
@@ -1,674 +1,775 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the GlauberAnalysis class.
//
#include "GlauberAnalysis.h"
#include "DipoleXSec.h"
#include "DipoleState.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Parameter.h"
#include "Bin.h"
#include "gsl/gsl_sf_bessel.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace DIPSY;
template <typename T>
valarray<T> sqr(valarray<T> v) { return v*v; }
valarray<double> vsqr(const valarray<double> & v) { return v*v; }
GlauberAnalysis::GlauberAnalysis()
- : nnSigTot(50.0*millibarn), nnSigEl(9.2*millibarn), nnSigInND(35.9*millibarn), Nt(1000), tMax(10.0*GeV2) {}
+ : nnSigTot(50.0*millibarn), nnSigEl(9.2*millibarn), nnSigInND(35.9*millibarn)
+ , nnSigSD(2.9*millibarn), Nt(1000), tMax(10.0*GeV2) {}
GlauberAnalysis::~GlauberAnalysis() {}
void GlauberAnalysis::initialize() {
generator()->histogramFactory()->initrun();
generator()->histogramFactory()->registerClient(this);
ntot = 0;
sigtot = signd = sigel = sigdt = sigdr = sigdl = sigdd = sigql = sigqr
= valarray<double>(ZERO, nstr);
sigtot2 = signd2 = sigel2 = sigdt2 = sigdr2 = sigdl2 = sigdd2 = sigql2 = sigqr2
= valarray<double>(ZERO, nstr);
- hists = vector<FactoryBase::tH1DPtr>(5*nstr);
+ hists = vector<FactoryBase::tH1DPtr>(8*nstr);
sumlr = sumnd = sum2lr = sumlr2 = suml2r = sumr2l =
Bin< valarray<double> >(valarray<double>(0.0, nstr));
bookHistos();
+ grey2R.sigTot = nnSigTot;
+ grey2R.sigEl = nnSigEl;
+ grey2R.sigD = nnSigTot - nnSigEl - nnSigInND;
+ grey2R.sigSD = nnSigSD;
+ grey2R.init();
+ GlauberBase::fit(grey2R);
+ stub(" grey2R Fitted sigTot:") << grey2R.stot() << " (" << nnSigTot/millibarn << ") mb" << endl;
+ stub(" grey2R Fitted sigEl:") << grey2R.sel() << " (" << nnSigEl/millibarn << ") mb" << endl;
+ stub(" grey2R Fitted sigD:") << grey2R.sD() << " (" << grey2R.sigD/millibarn << ") mb" << endl;
+ stub(" grey2R Fitted sigSD:") << grey2R.sSD() << " (" << nnSigSD/millibarn << ") mb" << endl;
+ stub(" grey2R Fitted c:") << grey2R.c << endl;
+ stub(" grey2R Fitted alpha:") << grey2R.alpha << endl;
+ stub(" grey2R Fitted R:") << grey2R.R*sqrt(millibarn)/femtometer << " fm" << endl;
+ stub(" grey2R Fitted r:") << grey2R.r*sqrt(millibarn)/femtometer << " fm" << endl;
}
void GlauberAnalysis::
setupProb(int Nr, const DipoleState & dr,
int Nl, const DipoleState & dl) const {
double ar = sqrt(2.0*nnSigEl/nnSigTot);
if ( probl.find(&dl) == probl.end() )
for ( int il = 0; il < Nl; ++il )
probl[&dl].push_back(UseRandom::rndbool(ar));
if ( probr.find(&dr) == probr.end() )
for ( int ir = 0; ir < Nr; ++ir )
probr[&dr].push_back(UseRandom::rndbool(ar));
}
valarray<double>
GlauberAnalysis::getT(const DipoleState & dr, const DipoleState & dl,
const ImpactParameters & b, const DipoleXSec & xsec,
double fsum) const {
- valarray<double> T(0.0, nstr);
+ valarray<double> T(0.0, 3*nstr);
T[0] = xsec.unitarize(fsum);
+ T[10] = 1.0;
int Ndl = dl.initialDipoles().size();
if ( Ndl%3 && Ndl != 1 ) return T;
int Ndr = dr.initialDipoles().size();
if ( Ndr%3 && Ndr != 1 ) return T;
int Nl = dl.initialDipoles().size()/3;
if ( Ndl == 1 ) Nl = 1;
int Nr = dr.initialDipoles().size()/3;
if ( Ndr == 1 ) Nr = 1;
setupProb(Nr, dr, Nl, dl);
double alpha = 2.0*(1.0 - nnSigInND/nnSigTot);
int nalpha = 0;
bool strikprob = UseRandom::rndbool(2.0*nnSigEl/nnSigTot);
-
+
+ vector< vector<bool> > lpart(Nl, vector<bool>(nstr, false));
+ vector< vector<bool> > rpart(Nr, vector<bool>(nstr, false));
for ( int il = 0; il < Nl; ++il ) {
Parton::Point pl =
(dl.initialDipoles()[0]->partons().first->position() +
dl.initialDipoles()[0]->partons().second->position())/2.0;
if ( Ndl > 1 )
pl = (dl.initialDipoles()[il*3]->partons().first->position() +
dl.initialDipoles()[il*3 + 1]->partons().first->position() +
dl.initialDipoles()[il*3 + 2]->partons().first->position())/3.0;
+ tPartonPtr ppl = dl.initialDipoles()[il*3]->partons().first;
for ( int ir = 0; ir < Nr; ++ir ) {
Parton::Point pr =
(dr.initialDipoles()[0]->partons().first->position() +
dr.initialDipoles()[0]->partons().second->position())/2.0;
if ( Ndr > 1 )
pr = (dr.initialDipoles()[ir*3]->partons().first->position() +
dr.initialDipoles()[ir*3 + 1]->partons().first->position() +
dr.initialDipoles()[ir*3 + 2]->partons().first->position())/3.0;
-
+ tPartonPtr ppr = dr.initialDipoles()[ir*3]->partons().first;
+
Length r = b.difference(pl, pr).pt()*hbarc;
// Black disc
Length R = sqrt(nnSigTot/(2.0*Constants::pi));
- if ( r <= R ) T[1] = 1.0;
+ if ( r <= R ) {
+ T[1] = 1.0;
+ lpart[il][1] = rpart[ir][1] = true;
+ }
// Gray disc
R = nnSigTot/sqrt(4.0*Constants::pi*nnSigEl);
double a = 2.0*nnSigEl/nnSigTot;
- if ( r <= R && UseRandom::rndbool(a) ) T[2] = 1.0;
+ if ( r <= R && UseRandom::rndbool(a) ) {
+ T[2] = 1.0;
+ lpart[il][2] = rpart[ir][2] = true;
+ }
// Gray3 disc
R = nnSigTot/sqrt(4.0*Constants::pi*nnSigEl);
a = nnSigEl/(nnSigTot - nnSigInND);
- if ( r <= R && UseRandom::rndbool(a) ) ++nalpha;
+ if ( r <= R && UseRandom::rndbool(a) ) {
+ ++nalpha;
+ if ( UseRandom::rndbool(alpha*(2.0 - alpha)) )
+ lpart[il][3] = rpart[ir][3] = true;
+ }
// Gussian
R = nnSigTot/sqrt(8.0*Constants::pi*nnSigEl);
a = 4.0*nnSigEl/nnSigTot;
- if ( UseRandom::rndbool(a*exp(-sqr(r/R))) ) T[4] = 1.0;
+ if ( UseRandom::rndbool(a*exp(-sqr(r/R))) ) {
+ T[4] = 1.0;
+ lpart[il][4] = rpart[ir][4] = true;
+ }
// Old black Disk
R = sqrt((nnSigTot - nnSigEl)/Constants::pi);
- if ( r <= R ) T[5] = 1.0;
+ if ( r <= R ) {
+ T[5] = 1.0;
+ lpart[il][5] = rpart[ir][5] = true;
+ }
// Old gray disk
R = sqrt(nnSigTot/Constants::pi);
a = (nnSigTot - nnSigEl)/nnSigTot;
- if ( r <= R && UseRandom::rndbool(a) ) T[6] = 1.0;
+ if ( r <= R && UseRandom::rndbool(a) ) {
+ T[6] = 1.0;
+ lpart[il][6] = rpart[ir][6] = true;
+ }
// ND black Disk
R = sqrt(nnSigInND/Constants::pi);
- if ( r <= R ) T[7] = 1.0;
+ if ( r <= R ) {
+ T[7] = 1.0;
+ lpart[il][7] = rpart[ir][7] = true;
+ }
// Gray disc 2
R = nnSigTot/sqrt(4.0*Constants::pi*nnSigEl);
- if ( r <= R && probr[&dr][ir] && probl[&dl][il] ) T[8] = 1.0;
+ if ( r <= R && probr[&dr][ir] && probl[&dl][il] ) {
+ T[8] = 1.0;
+ lpart[il][8] = rpart[ir][8] = true;
+ }
// Gray disc strikman
R = nnSigTot/sqrt(4.0*Constants::pi*nnSigEl);
- if ( r <= R && strikprob ) T[9] = 1.0;
+ if ( r <= R && strikprob ) {
+ T[9] = 1.0;
+ lpart[il][9] = rpart[ir][9] = true;
+ }
+
+ // Gray disk with two radii
+ double TT = grey2R.T(ppr, ppl, r);
+ T[10] *= 1.0 - TT;
+ if ( UseRandom::rndbool(TT*(2.0 - TT)) )
+ lpart[il][10] = rpart[ir][10] = true;
+
}
}
T[3] = 1.0 - pow(1.0 - alpha, nalpha);
+ T[10] = 1.0 - T[10];
+
+ for ( int istr = 1; istr < nstr; ++istr ) {
+ for ( int il = 0; il < Nl; ++il )
+ if ( lpart[il][istr] ) T[nstr + istr] += 1.0;
+ for ( int ir = 0; ir < Nr; ++ir )
+ if ( rpart[ir][istr] ) T[2*nstr + istr] += 1.0;
+ }
return T;
}
void GlauberAnalysis::
analyze(const vector<DipoleStatePtr> & vr, const vector<DipoleStatePtr> & vl,
const vector<ImpactParameters> & vb, const DipoleXSec & xsec,
const Vec3D & probs, double jac) {
if ( a2 ) {
analyze2(vr, vl, vb, xsec, probs, jac);
return;
}
int Nr = vr.size();
int Nl = vl.size();
int Nb = vb.size();
if ( Nr*Nl*vb.size() == 0 ) return;
+ grey2R.clearStates();
vector < vector< vector < valarray<double> > > >
UTB(Nb, vector< vector < valarray<double> > >
(Nl, vector < valarray<double> >
- (Nr)));
+ (Nr, valarray<double>(nstr))));
for ( int ib = 0; ib < Nb; ++ib ) {
CrossSection bweight = sqr(hbarc)*vb[ib].weight()*jac;
double bw = bweight/nanobarn;
double bw2 = sqr(bw);
valarray<double> sumLR(0.0, nstr); // T averaged over L and R
int nLR = 0;
valarray<double> sum2LR(0.0, nstr); // T^2 average over L and R
int n2LR = 0;
valarray<double> sumLR2(0.0, nstr); // (T averaged over L and R )^2
int nLR2 = 0;
valarray<double> sumL2R(0.0, nstr); // (T averaged over L)^2 averaged over R
int nL2R = 0;
valarray<double> sumR2L(0.0, nstr); // (T averaged over R)^2 averaged over L
int nR2L = 0;
vector< vector < valarray<double> > >
UT(Nl, vector < valarray<double> >(Nr));
probl.clear();
probr.clear();
for ( int ir1 = 0; ir1 < Nr; ++ir1 )
for ( int il1 = 0; il1 < Nl; ++il1 )
- UTB[ib][il1][ir1] = UT[il1][ir1] =
- getT(*vl[il1], *vr[ir1], vb[ib], xsec, probs[il1][ir1][ib]);
+ for ( int il1 = 0; il1 < Nl; ++il1 ) {
+ valarray<double> ret = getT(*vl[il1], *vr[ir1], vb[ib], xsec, probs[il1][ir1][ib]);
+ for ( int istr = 0; istr < nstr; ++istr )
+ UTB[ib][il1][ir1][istr] = UT[il1][ir1][istr] = ret[istr];
+ }
for ( int ir1 = 0; ir1 < Nr; ++ir1 ) for ( int il1 = 0; il1 < Nl; ++il1 ) {
valarray<double> UT1 = UT[il1][ir1];
double w1 = vr[ir1]->weight()*vl[il1]->weight();
sumLR += UT1*w1;
++nLR;
sum2LR += sqr(UT1)*w1;
++n2LR;
for ( int ir2 = 0; ir2 < Nr; ++ir2 ) for ( int il2 = 0; il2 < Nl; ++il2 ) {
valarray<double> UT2 = UT[il2][ir2];
double w2 = vr[ir2]->weight()*vl[il2]->weight();
// valarray<double> UT12 = UT1*w1*UT2*w2;
valarray<double> UT12 = UT1*UT2;
if ( il1 != il2 && ir1 != ir2 ){
sumLR2 += UT12*w1*w2;
++nLR2;
}
if ( il1 != il2 && ir1 == ir2 ) {
sumL2R += UT12*w1*w2;
++nL2R;
}
if ( il1 == il2 && ir1 != ir2 ) {
sumR2L += UT12*w1*w2;
++nR2L;
}
}
}
sumLR /=double(nLR);
sum2LR /=double(n2LR);
sumL2R /=double(nL2R);
sumR2L /=double(nR2L);
sumLR2 /=double(nLR2);
sigtot += 2.0*sumLR*bw;
sigtot2 += 4.0*sqr(sumLR)*bw2;
signd += (2.0*sumLR - sum2LR)*bw;
signd2 += (2.0*sumLR - sum2LR)*(2.0*sumLR - sum2LR)*bw2;
sigel += sumLR2*bw;
sigel2 += sumLR2*sumLR2*bw2;
sigdl += (sumL2R - sumLR2)*bw;
sigdl2 += (sumL2R - sumLR2)*(sumL2R - sumLR2)*bw2;
sigql += sumL2R*bw;
sigql2 += sumL2R*sumL2R*bw2;
sigdr += (sumR2L - sumLR2)*bw;
sigdr2 += (sumR2L - sumLR2)*(sumR2L - sumLR2)*bw2;
sigqr += sumR2L*bw;
sigqr2 += sumR2L*sumR2L*bw2;
sigdd += (sum2LR - sumR2L - sumL2R + sumLR2)*bw;
sigdd2 += (sum2LR - sumR2L - sumL2R + sumLR2)*(sum2LR - sumR2L - sumL2R + sumLR2)*bw2;
sigdt += (sum2LR - sumLR2)*bw;
sigdt2 += (sum2LR - sumLR2)*(sum2LR - sumLR2)*bw2;
InvEnergy b = vb[ib].bVec().pt();
for ( int it = 0; it < Nt; ++it ) {
Energy q = sqrt((double(it) + 0.5)*tMax/double(Nt));
double J0 = gsl_sf_bessel_J0(b*q);
for ( int i = 0; i < nstr; ++i ) {
hists[i]->fill(sqr(q)/GeV2, J0*sumLR[i]*bw);
// hists[i + nstr]->fill(sqr(q)/GeV2, J0*sumLR[i]*bw);
// hists[i + 2*nstr]->fill(sqr(q)/GeV2, 2.0*Constants::pi*J0*sumLR[i]*bw);
hists[i + 3*nstr]->fill(sqr(q)/GeV2, J0*sqrt(sumL2R[i])*bw);
hists[i + 4*nstr]->fill(sqr(q)/GeV2, J0*sqrt(sumR2L[i])*bw);
}
}
++ntot;
}
double xBLR = double((Nb-1)*Nl*(Nl-1)*Nr*(Nr-1))/8.0;
vector< vector<double> > J0(Nb, vector<double>(Nt));
vector< vector< vector<double> > >
J02(Nb, vector< vector<double> >(Nb, vector<double>(Nt)));
for ( int it = 0; it < Nt; ++it ) {
Energy q = sqrt((double(it) + 0.5)*tMax/double(Nt));
for ( int ib1 = 0; ib1 < Nb; ++ib1 ) {
J0[ib1][it] = gsl_sf_bessel_J0(vb[ib1].bVec().pt()*q);
for ( int ib2 = ib1 + 1; ib2 < Nb; ++ib2 )
J02[ib1][ib2][it] =
gsl_sf_bessel_J0((vb[ib1].bVec() - vb[ib2].bVec()).pt()*q);
}
}
vector<double> bw(Nb);
for ( int ib1 = 0; ib1 < Nb; ++ib1 )
bw[ib1] = sqr(hbarc)*vb[ib1].weight()*jac/nanobarn;
for ( int ib1 = 0; ib1 < Nb; ++ib1 )
for ( int ir1 = 0; ir1 < Nr; ++ir1 )
for ( int il1 = 0; il1 < Nl; ++il1 ) {
valarray<double> UT1 = UTB[ib1][il1][ir1];
double w1 = vr[ir1]->weight()*vl[il1]->weight();
for ( int ib2 = ib1; ib2 < Nb; ++ib2 )
for ( int ir2 = ir1; ir2 < Nr; ++ir2 )
for ( int il2= il1; il2 < Nl; ++il2 ) {
valarray<double> UT2 = UTB[ib2][il2][ir2];
double w2 = vr[ir2]->weight()*vl[il2]->weight();
if ( ib1 != ib2 && il1 != il2 && ir1 != ir2 ) {
for ( int it = 0; it < Nt; ++it ) {
double q2 = (double(it) + 0.5)*tMax/double(Nt)/GeV2;
for ( int i = 0; i < nstr; ++i ) {
hists[i + nstr]->fill(q2,
J0[ib1][it]*UT1[i]*w1*bw[ib1]*
J0[ib2][it]*UT2[i]*w2*bw[ib2]/xBLR);
hists[i + 2*nstr]->fill(q2,
J02[ib1][ib2][it]*
UT1[i]*w1*bw[ib1]*
UT2[i]*w2*bw[ib2]/xBLR);
}
}
}
}
}
}
void GlauberAnalysis::
analyze2(const vector<DipoleStatePtr> & vr, const vector<DipoleStatePtr> & vl,
const vector<ImpactParameters> & vb, const DipoleXSec & xsec,
const Vec3D & probs, double jac) {
int Nr = vr.size();
int Nl = vl.size();
int Nb = vb.size();
if ( Nr*Nl*Nb == 0 ) return;
+ grey2R.clearStates();
vector < vector< vector < valarray<double> > > >
UTB(Nb, vector< vector < valarray<double> > >
(Nl, vector < valarray<double> >
- (Nr)));
+ (Nr, valarray<double>(nstr))));
for ( int ib1 = 0; ib1 < Nb; ++ib1 ) {
probl.clear();
probr.clear();
for ( int ir1 = 0; ir1 < Nr; ++ir1 )
- for ( int il1 = 0; il1 < Nl; ++il1 )
- UTB[ib1][il1][ir1] =
- getT(*vl[il1], *vr[ir1], vb[ib1], xsec, probs[il1][ir1][ib1]);
+ for ( int il1 = 0; il1 < Nl; ++il1 ) {
+ valarray<double> ret = getT(*vl[il1], *vr[ir1], vb[ib1], xsec, probs[il1][ir1][ib1]);
+ for ( int istr = 0; istr < nstr; ++istr ) {
+ UTB[ib1][il1][ir1][istr] = ret[istr];
+ double weight =
+ sqr(hbarc)*vb[ib1].weight()*vr[ir1]->weight()*vl[il1]->weight()
+ *(jac/nanobarn)/double(Nb*Nl*Nr);
+ hists[5*nstr + istr]->fill(ret[nstr + istr], weight);
+ hists[6*nstr + istr]->fill(ret[2*nstr + istr], weight);
+ hists[7*nstr + istr]->fill((ret[nstr + istr] + ret[2*nstr + istr])/2.0, weight);
+ }
+ }
}
vector< vector<double> > J0(Nb, vector<double>(Nt));
vector< vector< vector<double> > >
J02(Nb, vector< vector<double> >(Nb, vector<double>(Nt)));
for ( int it = 0; it < Nt; ++it ) {
Energy q = sqrt((double(it) + 0.5)*tMax/double(Nt));
for ( int ib1 = 0; ib1 < Nb; ++ib1 ) {
J0[ib1][it] = gsl_sf_bessel_J0(vb[ib1].bVec().pt()*q);
for ( int ib2 = ib1 + 1; ib2 < Nb; ++ib2 )
J02[ib1][ib2][it] =
gsl_sf_bessel_J0((vb[ib1].bVec() - vb[ib2].bVec()).pt()*q);
}
}
vector<double> bw(Nb);
for ( int ib1 = 0; ib1 < Nb; ++ib1 )
bw[ib1] = sqr(hbarc)*vb[ib1].weight()*jac/nanobarn;
for ( int ib1 = 0; ib1 < Nb; ++ib1 )
for ( int ir1 = 0; ir1 < Nr; ++ir1 )
for ( int il1 = 0; il1 < Nl; ++il1 ) {
valarray<double> UT1 = UTB[ib1][il1][ir1];
double w1 = vr[ir1]->weight()*vl[il1]->weight();
sumlr += 2.0*UT1*w1*bw[ib1];
sumnd += (2.0*UT1 - vsqr(UT1))*w1*bw[ib1];
sum2lr += vsqr(UT1)*w1*bw[ib1];
for ( int it = 0; it < Nt; ++it )
tel0[it] += J0[ib1][it]*UT1*w1*bw[ib1];
for ( int ib2 = ib1; ib2 < Nb; ++ib2 )
for ( int ir2 = ir1; ir2 < Nr; ++ir2 )
for ( int il2 = il1; il2 < Nl; ++il2 ) {
valarray<double> UT2 = UTB[ib2][il2][ir2];
double w2 = vr[ir2]->weight()*vl[il2]->weight();
valarray<double> UT12 = UT1*UT2;
if ( ib1 == ib2 && il1 != il2 && ir1 != ir2 )
sumlr2 += UT12*w1*w2*bw[ib1];
if ( ib1 == ib2 && il1 != il2 && ir1 == ir2 )
suml2r += UT12*w1*w2*bw[ib1];
if ( ib1 == ib2 && il1 == il2 && ir1 != ir2 )
sumr2l += UT12*w1*w2*bw[ib1];
if ( ib1 != ib2 && il1 != il2 && ir1 != ir2 )
for ( int it = 0; it < Nt; ++it )
tel[it] += J02[ib1][ib2][it]*UT12*w1*w2*bw[ib1]*bw[ib2];
if ( ib1 != ib2 && il1 != il2 && ir1 == ir2 )
for ( int it = 0; it < Nt; ++it )
telql[it] += J02[ib1][ib2][it]*UT12*w1*w2*bw[ib1]*bw[ib2];
if ( ib1 != ib2 && il1 == il2 && ir1 != ir2 )
for ( int it = 0; it < Nt; ++it )
telqr[it] += J02[ib1][ib2][it]*UT12*w1*w2*bw[ib1]*bw[ib2];
}
}
}
string GlauberAnalysis::getStrat(int i) const {
string strat = "DIPSY";
if ( i == 1 ) strat = "black disc";
if ( i == 2 ) strat = "grey disc";
if ( i == 3 ) strat = "grey3 disc";
if ( i == 4 ) strat = "Gaussian";
if ( i == 5 ) strat = "old black disc";
if ( i == 6 ) strat = "old grey disc";
if ( i == 7 ) strat = "blakc disc ND";
if ( i == 8 ) strat = "grey2 disc";
if ( i == 9 ) strat = "grey strick";
+ if ( i == 10 ) strat = "grey2R";
return strat;
}
void GlauberAnalysis::bookHistos() {
generator()->histogramFactory()->mkdirs("/Glauber");
generator()->histogramFactory()->mkdirs("/tmp");
for ( int i = 0; i < nstr; ++i ) {
+ string I(1, '0' + i);
if ( a2 ) {
tel = tel0 = telql= telqr = vector< Bin< valarray<double> > >
(Nt, Bin< valarray<double> >(valarray<double>(0.0, nstr)));
+ hists[5*nstr + i] = generator()->histogramFactory()->createHistogram1D
+ ("/tmp/dSigmadNl-" + I, Nt, -0.5, 199.5);
+ hists[6*nstr + i] = generator()->histogramFactory()->createHistogram1D
+ ("/tmp/dSigmadNr-" + I, Nt, -0.5, 199.5);
+ hists[7*nstr + i] = generator()->histogramFactory()->createHistogram1D
+ ("/tmp/dSigmadNlr-" + I, Nt, -0.5, 199.5);
} else {
- string I(1, '0' + i);
hists[i] = generator()->histogramFactory()->createHistogram1D
("/tmp/dSigmadt-a-" + I, Nt, 0.0, tMax/GeV2);
hists[nstr + i] = generator()->histogramFactory()->createHistogram1D
("/Glauber/dSigmadt-b-" + I, Nt, 0.0, tMax/GeV2);
hists[2*nstr + i] = generator()->histogramFactory()->createHistogram1D
("/Glauber/dSigmadt-c-" + I, Nt, 0.0, tMax/GeV2);
hists[3*nstr + i] = generator()->histogramFactory()->createHistogram1D
("/tmp/dSigmadt-ql-" + I, Nt, 0.0, tMax/GeV2);
hists[4*nstr + i] = generator()->histogramFactory()->createHistogram1D
("/tmp/dSigmadt-qr-" + I, Nt, 0.0, tMax/GeV2);
}
}
}
void GlauberAnalysis::print(valarray<double> sig, valarray<double> sig2,
int ntot, string xstype) const {
for ( int i = 0; i < nstr; ++i ) {
string strat = getStrat(i);
sig[i] /= double(ntot);
sig2[i] /= double(ntot);
double err = sqrt((sig2[i] - sqr(sig[i]))/double(ntot));
stub(": " + xstype + ": (" + strat + "):")
<< ouniterr(sig[i], err, 1.0) << " nb." << endl;
}
}
void GlauberAnalysis::print(valarray<double> sig, valarray<double> err,
string xstype) const {
for ( int i = 0; i < nstr; ++i ) {
string strat = getStrat(i);
stub(": " + xstype + ": (" + strat + "):")
<< ouniterr(sig[i], err[i], 1.0) << " nb." << endl;
}
}
void GlauberAnalysis::print(const Bin< valarray<double> > & sig,
string xstype) const {
for ( int i = 0; i < nstr; ++i ) {
string strat = getStrat(i);
stub(": " + xstype + ": (" + strat + "):")
<< ouniterr(sig.average()[i], sig.err()[i], 1.0) << " nb." << endl;
}
}
void GlauberAnalysis::finalize(long neve) {
if ( neve <= 0 ) return;
if ( a2 ) {
finalize2(neve);
return;
}
stub(": Total: (pp):")
<< ouniterr(double(nnSigTot/nanobarn), 10000.0, 1.0)
<< " nb." << endl;
print(sigtot, sigtot2, ntot, "Total");
stub(": Inelastic(ND): (pp):")
<< ouniterr(double(nnSigInND/nanobarn), 10000.0, 1.0)
<< " nb." << endl;
print(signd, signd2, ntot, "Inelastic(ND)");
stub(": Inelastic(tot): (pp):")
<< ouniterr(double((nnSigTot - nnSigEl)/nanobarn), 10000.0, 1.0)
<< " nb." << endl;
print(sigtot - sigel, sigtot2 - sigel2, ntot, "Inelastic(tot)");
stub(": Elastic: (pp):")
<< ouniterr(double(nnSigEl/nanobarn), 10000.0, 1.0) << " nb." << endl;
print(sigel, sigel2, ntot, "Elastic");
stub(": Diff. total: (pp):")
<< ouniterr(double((nnSigTot - nnSigEl - nnSigInND)/nanobarn), 10000.0, 1.0)
<< " nb." << endl;
print(sigdt, sigdt2, ntot, "Diff. total");
+ stub(": Diff. sing. exc. L+R: (pp):")
+ << ouniterr(double(nnSigSD/nanobarn), 10000.0, 1.0)
+ << " nb." << endl;
print(sigdr, sigdr2, ntot, "Diff. exc. (R)");
print(sigdl, sigdl2, ntot, "Diff. exc. (L)");
print(sigqr, sigqr2, ntot, "Quasi El. (R)");
print(sigql, sigql2, ntot, "Quasi El. (L)");
print(sigdd, sigdd2, ntot, "Double diff. exc.");
for (int i = 0; i < nstr; ++i ) {
string I(1, '0' + i);
FactoryBase::tH1DPtr tmp =
generator()->histogramFactory()->histogramFactory().multiply
("/Glauber/dSigmadt-a-" + I, *hists[i], *hists[i]);
tmp->setTitle("dSigma/dt a (" + getStrat(i) + ")");
tmp->scale(nanobarn*GeV2/(sqr(hbarc)*double(ntot*ntot)*4.0*Constants::pi));
generator()->histogramFactory()->histogramFactory().destroy(hists[i]);
stub(": Elastic cross check a: (" + getStrat(i) + ")")
<< tmp->sumAllBinHeights()*(tMax/GeV2)/double(Nt) << endl;
tmp = hists[i + nstr];
tmp->setTitle("dSigma/dt b (" + getStrat(i) + ")");
tmp->scale(nanobarn*GeV2/(sqr(hbarc)*double(ntot)*4.0*Constants::pi));
stub(": Elastic cross check b: (" + getStrat(i) + ")")
<< tmp->sumAllBinHeights()*(tMax/GeV2)/double(Nt) << endl;
tmp = hists[i + 2*nstr];
tmp->setTitle("dSigma/dt c (" + getStrat(i) + ")");
tmp->scale(nanobarn*GeV2/(sqr(hbarc)*double(ntot)*4.0*Constants::pi));
stub(": Elastic cross check c: (" + getStrat(i) + ")")
<< tmp->sumAllBinHeights()*(tMax/GeV2)/double(Nt) << endl;
tmp = generator()->histogramFactory()->histogramFactory().multiply
("/Glauber/dSigmadt-ql-" + I, *hists[3*nstr + i], *hists[3*nstr+ i]);
tmp->setTitle("dSigma/dt ql (" + getStrat(i) + ")");
tmp->scale(nanobarn*GeV2/(sqr(hbarc)*double(ntot*ntot)*2.0*Constants::pi));
generator()->histogramFactory()->histogramFactory().destroy(hists[3*nstr + i]);
tmp = generator()->histogramFactory()->histogramFactory().multiply
("/Glauber/dSigmadt-qr-" + I, *hists[4*nstr + i], *hists[4*nstr+ i]);
tmp->setTitle("dSigma/dt qr (" + getStrat(i) + ")");
tmp->scale(nanobarn*GeV2/(sqr(hbarc)*double(ntot*ntot)*2.0*Constants::pi));
generator()->histogramFactory()->histogramFactory().destroy(hists[4*nstr + i]);
}
}
void GlauberAnalysis::finalize2(long neve) {
if ( neve <= 0 ) return;
stub(": Total: (pp) [New procedure]:")
<< ouniterr(double(nnSigTot/nanobarn), 10000.0, 1.0)
<< " nb." << endl;
print(sumlr, "Total");
stub(": Inelastic(ND): (pp):")
<< ouniterr(double(nnSigInND/nanobarn), 10000.0, 1.0)
<< " nb." << endl;
print(sumnd, "Inelastic(ND)");
stub(": Inelastic(tot): (pp):")
<< ouniterr(double((nnSigTot - nnSigEl)/nanobarn), 10000.0, 1.0)
<< " nb." << endl;
print(sumlr - sumlr2, "Inelastic(tot)");
stub(": Elastic: (pp):")
<< ouniterr(double(nnSigEl/nanobarn), 10000.0, 1.0) << " nb." << endl;
print(sumlr2, "Elastic");
stub(": Diff. total: (pp):")
<< ouniterr(double((nnSigTot - nnSigEl - nnSigInND)/nanobarn), 10000.0, 1.0)
<< " nb." << endl;
print(sum2lr - sumlr2, "Diff. total");
+ stub(": Diff. sing. exc. L+R: (pp):")
+ << ouniterr(double(nnSigSD/nanobarn), 10000.0, 1.0)
+ << " nb." << endl;
print(sumr2l - sumlr2, "Diff. exc. (R)");
print(suml2r - sumlr2, "Diff. exc. (L)");
print(sumr2l, "Quasi El. (R)");
print(suml2r, "Quasi El. (L)");
print(sum2lr - sumr2l - suml2r + sumlr2, "Double diff. exc.");
ofstream os((generator()->path() + "/" + generator()->runName() +
"-tdep.dat").c_str());
double tfac = nanobarn*GeV2/(sqr(hbarc)*4.0*Constants::pi);
for (int i = 0; i < nstr; ++i ) {
- string I(1, '0' + i);
+ string I(1, i < 10? '0' + i: 'a' + i);
os << "# tdep" << I << endl;
for ( int it = 0; it < Nt; ++it )
os << (double(it) + 0.5)*(tMax/GeV2)/double(Nt) << '\t'
<< tel[it].average()[i]*tfac << '\t' << tel[it].err()[i]*tfac << endl;
os << endl;
os << "# t0dep" << I << endl;
for ( int it = 0; it < Nt; ++it ) {
Bin< valarray<double> > b = tel0[it].sqr();
os << (double(it) + 0.5)*(tMax/GeV2)/double(Nt) << '\t'
<< b.average()[i]*tfac << '\t' << b.err()[i]*tfac << endl;
}
os << endl;
os << "# tdepr" << I << endl;
for ( int it = 0; it < Nt; ++it )
os << (double(it) + 0.5)*(tMax/GeV2)/double(Nt) << '\t'
<< telqr[it].average()[i]*tfac << '\t' << telqr[it].err()[i]*tfac << endl;
os << endl;
os << "# tdepl" << I << endl;
for ( int it = 0; it < Nt; ++it )
os << (double(it) + 0.5)*(tMax/GeV2)/double(Nt) << '\t'
<< telql[it].average()[i]*tfac << '\t' << telql[it].err()[i]*tfac << endl;
os << endl;
+
+ hists[5*nstr + i]->scale(1.0/neve);
+ hists[6*nstr + i]->scale(1.0/neve);
+ hists[7*nstr + i]->scale(1.0/neve);
}
}
IBPtr GlauberAnalysis::clone() const {
return new_ptr(*this);
}
IBPtr GlauberAnalysis::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 GlauberAnalysis::persistentOutput(PersistentOStream & os) const {
const CrossSection nb = nanobarn;
os << ounit(nnSigTot, nb) << ounit(nnSigEl, nb) << ounit(nnSigInND, nb)
- << ntot << sigtot << signd << sigel
+ << ounit(nnSigSD, nb) << ntot << sigtot << signd << sigel
<< sigdt << sigdl << sigdr << sigdd << sigql << sigqr
<< sigtot2 << signd2 << sigel2
<< sigdt2 << sigdl2 << sigdr2 << sigdd2 << sigql2 << sigqr2
<< Nt << ounit(tMax,GeV2);
}
void GlauberAnalysis::persistentInput(PersistentIStream & is, int) {
const CrossSection nb = nanobarn;
is >> iunit(nnSigTot, nb) >> iunit(nnSigEl, nb) >> iunit(nnSigInND, nb)
- >> ntot >> sigtot >> signd >> sigel
+ >> iunit(nnSigSD, nb) >> ntot >> sigtot >> signd >> sigel
>> sigdt >> sigdl >> sigdr >> sigdd >> sigql >> sigqr
>> sigtot2 >> signd2 >> sigel2
>> sigdt2 >> sigdl2 >> sigdr2 >> sigdd2 >> sigql2 >> sigqr2
>> Nt >> iunit(tMax, GeV2);
hists.resize(5*nstr);
// bookHistos();
}
// Static variable needed for the type description system in ThePEG.
#include "ThePEG/Utilities/DescribeClass.h"
DescribeClass<GlauberAnalysis,DIPSY::DipoleAnalysisHandler>
describeDIPSYGlauberAnalysis("DIPSY::GlauberAnalysis",
"GlauberAnalysis.so");
void GlauberAnalysis::Init() {
static ClassDocumentation<GlauberAnalysis> documentation
("There is no documentation for the GlauberAnalysis class");
static Parameter<GlauberAnalysis,CrossSection> interfaceTotalnnXSec
("TotalnnXSec",
"The assumed total nucleon-nucleon cross section assumed in the calculation (in mb).",
&GlauberAnalysis::nnSigTot, millibarn, 96.0*millibarn, 0.0*millibarn, 0*millibarn,
true, false, Interface::lowerlim);
static Parameter<GlauberAnalysis,CrossSection> interfaceElasticnnXSec
("ElasticnnXSec",
"The assumed elastic nucleon-nucleon cross section assumed in the calculation (in mb).",
&GlauberAnalysis::nnSigEl, millibarn, 24.0*millibarn, 0.0*millibarn, 0*millibarn,
true, false, Interface::lowerlim);
static Parameter<GlauberAnalysis,CrossSection> interfaceElasticnnXSecInND
("InElasticnnXSec",
"The assumed inelastic, non-diffractive nucleon-nucleon cross section "
"assumed in the calculation (in mb).",
&GlauberAnalysis::nnSigInND, millibarn, 30.0*millibarn, 0.0*millibarn, 0*millibarn,
true, false, Interface::lowerlim);
+ static Parameter<GlauberAnalysis,CrossSection> interfaceElasticnnXSecSD
+ ("SDnnXSec",
+ "The assumed single-diffractive nucleon-nucleon cross section "
+ "assumed in the calculation (in mb).",
+ &GlauberAnalysis::nnSigSD, millibarn, 30.0*millibarn, 0.0*millibarn, 0*millibarn,
+ true, false, Interface::lowerlim);
+
static Parameter<GlauberAnalysis,int> interfaceNt
("Nt",
"Number of bins in t-plots.",
&GlauberAnalysis::Nt, 1000, 0, 0,
true, false, Interface::lowerlim);
static Parameter<GlauberAnalysis,Energy2> interfacetMax
("tMax",
"Maximum t-value in t-plot.",
&GlauberAnalysis::tMax, GeV2, 10.0*GeV2, 0.0*GeV2, 0*GeV2,
true, false, Interface::lowerlim);
}
diff --git a/DIPSY/GlauberAnalysis.h b/DIPSY/GlauberAnalysis.h
--- a/DIPSY/GlauberAnalysis.h
+++ b/DIPSY/GlauberAnalysis.h
@@ -1,234 +1,242 @@
// -*- C++ -*-
#ifndef DIPSY_GlauberAnalysis_H
#define DIPSY_GlauberAnalysis_H
//
// This is the declaration of the GlauberAnalysis class.
//
#include "DipoleAnalysisHandler.h"
#include "ThePEG/Analysis/FactoryBase.h"
#include "ThePEG/Analysis/LWH/AnalysisFactory.h"
#include <valarray>
#include "Bin.h"
+#include "GlauberModels.h"
namespace DIPSY {
using namespace ThePEG;
using std::valarray;
/**
* Here is the documentation of the GlauberAnalysis class.
*
* @see \ref GlauberAnalysisInterfaces "The interfaces"
* defined for GlauberAnalysis.
*/
class GlauberAnalysis: public DIPSY::DipoleAnalysisHandler {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
GlauberAnalysis();
/**
* The destructor.
*/
virtual ~GlauberAnalysis();
//@}
public:
/** @name Standard virtual functions inherited from the classes. */
//@{
/**
* Initialize the analysis object.
*/
virtual void initialize();
/**
* Analyze a given set of collision given a set of left- and
* right-moving dipole states in \a vl and \a vr, an a set of
* ImpactParameters object in \a vb, and a cross section object, \a
* xsec. Also a jacobian, \a jac, is supplied in case of varying
* total energy.
*/
virtual void analyze(const vector<DipoleStatePtr> & vr, const vector<DipoleStatePtr> & vl,
const vector<ImpactParameters> & vb, const DipoleXSec & xsec,
const Vec3D & probs, double jac);
virtual void analyze2(const vector<DipoleStatePtr> & vr, const vector<DipoleStatePtr> & vl,
const vector<ImpactParameters> & vb, const DipoleXSec & xsec,
const Vec3D & probs, double jac);
/**
* Finalize the analysis, (compute statistics etc.). \a neve is the
* number of times analyze() has been called since last
* initialize().
*/
virtual void finalize(long neve);
virtual void finalize2(long neve);
//@}
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;
//@}
private:
/**
* Convenient typedef.
*/
typedef QTY<4,0,0>::Type CrossSection2;
/**
* The assumed total nucleon - nucleon cross section
*/
CrossSection nnSigTot;
/**
* The assumed elastic nucleon - nucleon cross section
*/
CrossSection nnSigEl;
/**
* The assumed inelastic, non-diffracitve nucleon - nucleon cross section
*/
CrossSection nnSigInND;
/**
+ * The assumed single diffractive nucleon - nucleon cross section.
+ */
+ CrossSection nnSigSD;
+
+ /**
* Number of strategies.
*/
- static const int nstr = 10;
+ static const int nstr = 11;
/**
* The sums.
*/
valarray<double> sigtot, signd, sigel,
sigdt, sigdr, sigdl, sigdd, sigql, sigqr;
Bin< valarray<double> > sumlr, sumnd, sum2lr, sumlr2, suml2r, sumr2l;
/**
* The sum of squares.
*/
valarray<double> sigtot2, signd2, sigel2,
sigdt2, sigdr2, sigdl2, sigdd2, sigql2, sigqr2;
/**
* The number of b-values.
*/
long ntot;
/**
* The number of t-bins for the elastic cross section
*/
int Nt;
/**
* The maximum t-value for the elastic cross section.
*/
Energy2 tMax;
/**
* The t-values, first and second strategy
*/
vector<FactoryBase::tH1DPtr> hists;
vector< Bin< valarray<double> > > tel, tel0, telql, telqr;
/**
* The grey2 probabilities for the nucleons,
*/
mutable map<const DipoleState *, vector<bool> > probl, probr;
/**
* Calulate all transition probabilities
*/
valarray<double> getT(const DipoleState & dr, const DipoleState & dl,
const ImpactParameters & b, const DipoleXSec & xsec,
double fsum) const;
/**
* Setup probabilities for grey2 nucleons.
*/
void setupProb(int Nr, const DipoleState & dr,
int Nl, const DipoleState & dl) const;
/**
* helper function for printing
*/
void print(valarray<double> sig, valarray<double> sig2,
int ntot, string xstype) const;
void print(valarray<double> sig, valarray<double> sig2,
string xstype) const;
void print(const Bin< valarray<double> > & sig, string xstype) const;
/**
* helper function for histogram booking;
*/
void bookHistos();
/**
* helper function for printing
*/
string getStrat(int i) const;
static const bool a2 = 1;
+ Glauber2R grey2R;
+
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
GlauberAnalysis & operator=(const GlauberAnalysis &);
};
}
#endif /* DIPSY_GlauberAnalysis_H */
diff --git a/DIPSY/LHCpPb.in b/DIPSY/LHCpPb.in
--- a/DIPSY/LHCpPb.in
+++ b/DIPSY/LHCpPb.in
@@ -1,260 +1,260 @@
cd /DIPSY
#To get output to a file, uncomment
#finalState->saveGluonsToFile(currentWeight)
#in EventFiller.cc. The events are saved to files
#~/DIPSYevents/filename/eventN.dat
#Where the directory ~/DIPSYevents/filename must exist before the run.
#Otherwise the directory can be set in DipoleState::saveGluonsToFile
#Filename is the name of the runfile, so LHCpPb or LHCpPbB01 in
#this case.
#Probably want to switch off FSR and hadronisation as well, as
#the event is saved before that.
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 Tune31.in
read RivetAnalyses.in
create ThePEG::ProgressLog Logger ProgressLog.so
set Logger:Interval 600
set LHCpPbEventHandler:PreSamples 0
set LHCpPbEventHandler:ConsistencyLevel 0
set LHCpPbEventHandler:DecayHandler:MaxLifeTime 10
set LHCpPbEventHandler:XSecFn:CheckOffShell false
insert LHCpPbGenerator:AnalysisHandlers[0] Logger
#insert LHCpPbGenerator:AnalysisHandlers[0] HIAna
set LHCpPbGenerator:EventHandler:EventFiller:PTCut 0.6
create ThePEG::LuminosityFunction LHCpPbLabLumi
set LHCpPbEventHandler:LuminosityFunction LHCpPbLabLumi
set LHCpPbLabLumi:BeamEMaxA 2500
set LHCpPbLabLumi:BeamEMaxB 520000
set LHCpPbEventHandler:YFrametest 0.9
set LHCpPbEventHandler:BGen:Width 40
set LHCpPbEventHandler:PreSamples 1000
set LHCpPbEventHandler:PreSampleL 10
set LHCpPbEventHandler:PreSampleR 1
set LHCpPbEventHandler:PreSampleB 1
create DIPSY::SemiInclusiveXSecAnalysis SemiIncl SemiInclusiveXSecAnalysis.so
insert LHCpPbEventHandler:AnalysisHandlers[0] SemiIncl
create DIPSY::NoFluctXSecAnalysis NoFluct NoFluctXSecAnalysis.so
insert LHCpPbEventHandler:AnalysisHandlers[0] NoFluct
create DIPSY::GlauberAnalysis Glauber GlauberAnalysis.so
insert LHCpPbEventHandler:AnalysisHandlers[0] Glauber
create DIPSY::AnalysisProgress AnaLog AnalysisProgress.so
set AnaLog:Interval 600
insert LHCpPbEventHandler:AnalysisHandlers[0] AnaLog
set LHCpPbGenerator:NumberOfEvents 2
set LHCpPbEventHandler:PreSamples 10
saverun LHCpPbTestQ LHCpPbGenerator
set Lead:InterNucleonSwing Off
saverun LHCpPbTestQI LHCpPbGenerator
set Lead:InterNucleonSwing On
set LHCpPbEventHandler:PreSamples 1000
saverun LHCpPbTest0 LHCpPbGenerator
set LHCpPbEventHandler:BGen:Width 30
saverun LHCpPbTest1 LHCpPbGenerator
set LHCpPbEventHandler:PreSampleB 4
saverun LHCpPbTest2 LHCpPbGenerator
set LHCpPbEventHandler:BGen:Width 50
saverun LHCpPbTest3 LHCpPbGenerator
# Interlude with pp to get the total xsec
set LHCpPbLabLumi:BeamEMaxB 2500
set LHCpPbEventHandler:WFR stdProton
set LHCpPbEventHandler:BGen:Width 10
set LHCpPbEventHandler:YFrametest 0.5
set LHCpPbEventHandler:PreSamples 10000
set LHCpPbEventHandler:PreSampleL 1
set LHCpPbEventHandler:PreSampleB 1
saverun LHCpPbTest0pp LHCpPbGenerator
set Glauber:TotalnnXSec 89.9
set Glauber:ElasticnnXSec 22.1
set Glauber:InElasticnnXSec 58.1
saverun LHCpPbTest1pp LHCpPbGenerator
set LHCpPbEventHandler:BGen:Width 5
saverun LHCpPbTest2pp LHCpPbGenerator
set LHCpPbEventHandler:PreSampleB 16
set LHCpPbEventHandler:PreSampleL 1
set LHCpPbEventHandler:PreSampleR 1
saverun LHCpPbTest21pp LHCpPbGenerator
set LHCpPbEventHandler:PreSampleB 8
set LHCpPbEventHandler:PreSampleL 2
set LHCpPbEventHandler:PreSampleR 1
saverun LHCpPbTest22pp LHCpPbGenerator
set LHCpPbEventHandler:PreSampleB 4
set LHCpPbEventHandler:PreSampleL 2
set LHCpPbEventHandler:PreSampleR 2
saverun LHCpPbTest23pp LHCpPbGenerator
set LHCpPbEventHandler:PreSampleB 2
set LHCpPbEventHandler:PreSampleL 2
set LHCpPbEventHandler:PreSampleR 4
saverun LHCpPbTest24pp LHCpPbGenerator
set LHCpPbEventHandler:PreSampleB 1
set LHCpPbEventHandler:PreSampleL 4
set LHCpPbEventHandler:PreSampleR 4
saverun LHCpPbTest25pp LHCpPbGenerator
set LHCpPbEventHandler:PreSampleL 1
set LHCpPbEventHandler:PreSampleR 1
set LHCpPbEventHandler:PreSampleB 1
set LHCpPbEventHandler:BGen:Width 2
saverun LHCpPbTest3pp LHCpPbGenerator
set LHCpPbEventHandler:PreSamples 1000000
set LHCpPbEventHandler:BGen:Width 5
saverun LHCpPbTest4pp LHCpPbGenerator
set LHCpPbEventHandler:PreSampleB 10
saverun LHCpPbTest7pp LHCpPbGenerator
# Check lower energies
set LHCpPbLabLumi:BeamEMaxA 100
set LHCpPbLabLumi:BeamEMaxB 100
set LHCpPbEventHandler:PreSampleB 10
set Glauber:TotalnnXSec 50.04
set Glauber:ElasticnnXSec 9.197
set Glauber:InElasticnnXSec 35.98
saverun LHCpPbTest40pp LHCpPbGenerator
set Glauber:TotalnnXSec 49.92
set Glauber:ElasticnnXSec 9.176
set Glauber:InElasticnnXSec 35.89
saverun LHCpPbTest41pp LHCpPbGenerator
set Glauber:TotalnnXSec 89.9
set Glauber:ElasticnnXSec 22.1
set Glauber:InElasticnnXSec 58.1
set LHCpPbEventHandler:PreSampleB 1
set LHCpPbLabLumi:BeamEMaxA 2500
set LHCpPbLabLumi:BeamEMaxB 2500
set LHCpPbEventHandler:PreSamples 10000
set LHCpPbEventHandler:PreSampleL 10
saverun LHCpPbTest5pp LHCpPbGenerator
set LHCpPbEventHandler:PreSamples 100000
saverun LHCpPbTest50pp LHCpPbGenerator
set LHCpPbEventHandler:PreSamples 20000
set LHCpPbEventHandler:PreSampleL 5
saverun LHCpPbTest6pp LHCpPbGenerator
set LHCpPbEventHandler:PreSamples 200000
saverun LHCpPbTest60pp LHCpPbGenerator
set LHCpPbEventHandler:PreSampleL 1
set LHCpPbEventHandler:YFrametest 0.9
set LHCpPbEventHandler:PreSamples 10000
saverun LHCpPbTest4pp9 LHCpPbGenerator
set LHCpPbEventHandler:YFrametest 0.5
set LHCpPbLabLumi:BeamEMaxB 40000
set LHCpPbEventHandler:WFR Oxygen
set LHCpPbEventHandler:BGen:Width 20
set LHCpPbEventHandler:PreSamples 10
set LHCpPbEventHandler:PreSampleB 10
set LHCpPbEventHandler:PreSampleL 2
saverun LHCpPbTest0O LHCpPbGenerator
set LHCpPbEventHandler:PreSampleB 1
set LHCpPbEventHandler:PreSamples 10000
saverun LHCpPbTest1O LHCpPbGenerator
set LHCpPbEventHandler:PreSamples 100000
saverun LHCpPbTest2O LHCpPbGenerator
set LHCpPbLabLumi:BeamEMaxB 157500
set LHCpPbEventHandler:WFR Copper
set LHCpPbEventHandler:BGen:Width 20
set LHCpPbEventHandler:PreSamples 4
saverun LHCpPbTest0Cu LHCpPbGenerator
set LHCpPbEventHandler:PreSamples 1000
saverun LHCpPbTest1Cu LHCpPbGenerator
set LHCpPbEventHandler:PreSamples 4000
saverun LHCpPbTest2Cu LHCpPbGenerator
set LHCpPbEventHandler:PreSamples 1000
set LHCpPbEventHandler:PreSampleB 4
saverun LHCpPbTest3Cu LHCpPbGenerator
set LHCpPbEventHandler:PreSampleB 40
saverun LHCpPbTest4Cu LHCpPbGenerator
set Copper:InterNucleonSwing Off
saverun LHCpPbTest5Cu LHCpPbGenerator
set Copper:InterNucleonSwing On
set LHCpPbLabLumi:BeamEMaxB 520000
set LHCpPbEventHandler:WFR Lead
set LHCpPbEventHandler:YFrametest 0.9
set LHCpPbEventHandler:PreSampleL 10
set LHCpPbEventHandler:PreSampleB 4
set Glauber:TotalnnXSec 50.04
set Glauber:ElasticnnXSec 9.197
set Glauber:InElasticnnXSec 35.98
set LHCpPbLabLumi:BeamEMaxA 100
set LHCpPbLabLumi:BeamEMaxB 20800
set LHCpPbEventHandler:PreSamples 10000
set LHCpPbEventHandler:BGen:Width 40
set LHCpPbEventHandler:PreSampleB 1
saverun RHICpPbTest0 LHCpPbGenerator
set LHCpPbEventHandler:BGen:Width 20
set LHCpPbEventHandler:PreSampleB 40
set LHCpPbEventHandler:PreSampleL 1
set LHCpPbEventHandler:PreSamples 10000
set LHCpPbEventHandler:YFrametest 0.5
saverun LHCpPbTest40Pb LHCpPbGenerator
set Lead:InterNucleonSwing Off
saverun LHCpPbTest50Pb LHCpPbGenerator
set Lead:InterNucleonSwing On
set Glauber:TotalnnXSec 49.92
set Glauber:ElasticnnXSec 9.176
set Glauber:InElasticnnXSec 35.89
set LHCpPbEventHandler:PreSamples 1000
saverun LHCpPbTest41Pb LHCpPbGenerator
set LHCpPbEventHandler:PreSamples 10000
set Lead:InterNucleonSwing Off
saverun LHCpPbTest51Pb LHCpPbGenerator
set Lead:InterNucleonSwing On
#Not sure what CoM energy they will run at. 4TeV is about same
#nucleon-nucleon as PbPb.
set LHCpPbLumi:Energy 400.0
#Run with fix impact parameter, like in AA.
#This generates events in a ring. The weight
#(with interaction probability of 1) will automatically
#be set to 1, 3, 5, 7 in the B-ranges 0-1, 1-2, 2-3, etc, so
#nothing should have to be micromanaged with the weights,
#as long as the events are run in the below B rings.
#With equal amount of events in all rings (out to where int prob
#is very low), one can then find expectation values by average over
#all events, with the provided weights.
create DIPSY::FixedImpactGenerator FixedB FixedImpactGenerator.so
set LHCpPbGenerator:EventHandler:BGen FixedB
#AA has 1000 events per ring.
#pPb will run much faster, but maybe not take that much less memory.
#See how much time/space you got.
set LHCpPbGenerator:NumberOfEvents 1000
-set FixedB:MinB = 0.0
-set FixedB:MaxB = 1.0
+set FixedB:MinB 0.0
+set FixedB:MaxB 1.0
saverun LHCpPbB01 LHCpPbGenerator
-set FixedB:MinB = 1.0
-set FixedB:MaxB = 2.0
+set FixedB:MinB 1.0
+set FixedB:MaxB 2.0
saverun LHCpPbB12 LHCpPbGenerator
-set FixedB:MinB = 2.0
-set FixedB:MaxB = 3.0
+set FixedB:MinB 2.0
+set FixedB:MaxB 3.0
saverun LHCpPbB23 LHCpPbGenerator
#etc.
#I ran Au-Au up to B=15, and PbPb to 19.
#So up to 15 should be enough here.
#See where the weight start dropping of too much.
diff --git a/DIPSY/Makefile.am b/DIPSY/Makefile.am
--- a/DIPSY/Makefile.am
+++ b/DIPSY/Makefile.am
@@ -1,151 +1,151 @@
AUTOMAKE_OPTIONS = -Wno-portability
mySOURCES = DipoleEventHandler.cc WaveFunction.cc SimpleProton.cc \
VirtualPhoton.cc DipoleState.cc Dipole.cc Parton.cc DipoleXSec.cc \
ImpactParameterGenerator.cc WFInfo.cc PhotonWFInfo.cc \
VectorMesonBase.cc PhotonDipoleState.cc SimpleProtonState.cc \
Emitter.cc Swinger.cc DipoleAnalysisHandler.cc \
TotalXSecAnalysis.cc EventFiller.cc DipoleAbsorber.cc \
SmallDipoleAbsorber.cc EffectiveParton.cc RealParton.cc \
RealPartonState.cc DiffractiveEventFiller.cc ParticleInfo.cc \
NucleusData.cc ShadowParton.cc
DOCFILES = DipoleEventHandler.h WaveFunction.h SimpleProton.h VirtualPhoton.h \
DipoleState.h Dipole.h Parton.h DipoleXSec.h ImpactParameters.h \
ImpactParameterGenerator.h WFInfo.h PhotonWFInfo.h VectorMesonBase.h \
PhotonDipoleState.h SimpleProtonState.h Emitter.h Swinger.h \
DipoleAnalysisHandler.h TotalXSecAnalysis.h EventFiller.h \
DipoleAbsorber.h SmallDipoleAbsorber.h EffectiveParton.h \
RealParton.h RealPartonState.h DiffractiveEventFiller.h ParticleInfo.h \
NucleusData.h ShadowParton.h
INCLUDEFILES = $(DOCFILES) DipoleEventHandler.fh WaveFunction.fh \
DipoleState.fh Dipole.fh Parton.fh DipoleXSec.fh \
ImpactParameterGenerator.fh WFInfo.fh \
Emitter.fh Swinger.fh DipoleAnalysisHandler.fh EventFiller.fh \
DipoleAbsorber.fh EffectiveParton.fh \
RealParton.fh RealPartonState.fh CPUTimer.h ShadowParton.fh
pkglib_LTLIBRARIES = libDIPSY.la OldStyleEmitter.la PT1DEmitter.la \
ElasticXSecAnalysis.la LargePTDipoleAbsorber.la \
SimpleNucleus.la RecoilSwinger.la \
FSDipole5Ordering.la FSAnalysis.la GapAnalysis.la \
HIAnalysis.la FixedImpactGenerator.la \
NoFluctXSecAnalysis.la GlauberAnalysis.la \
AnalysisProgress.la SemiInclusiveXSecAnalysis.la \
GaussianImpactGenerator.la PTAnalysis.la \
DipoleDensityAnalysis.la
INPUTFILES = TestXSecs.in RivetAnalyses.in DIPSYRemove.in DIPSYDefaults.in CurrentTune.in Tune27.in
CLEANFILES = done-all-links
dist_pkgdata_DATA = $(INPUTFILES)
rpodir = $(pkglibdir)
nodist_rpo_DATA = DIPSYDefaults.rpo
# Version info should be updated if any interface or persistent I/O
# function is changed
libDIPSY_la_LDFLAGS = -module -version-info 1:0:0
# libDIPSY_la_LIBADD = ../Config/libAriadne5Config.la
libDIPSY_la_SOURCES = $(mySOURCES) $(INCLUDEFILES)
OldStyleEmitter_la_LDFLAGS = -module -version-info 1:0:0
OldStyleEmitter_la_SOURCES = OldStyleEmitter.cc OldStyleEmitter.h
FSDipole5Ordering_la_LDFLAGS = -module -version-info 1:0:0
FSDipole5Ordering_la_SOURCES = FSDipole5Ordering.cc FSDipole5Ordering.h
FSAnalysis_la_LDFLAGS = -module -version-info 1:0:0
FSAnalysis_la_SOURCES = FSAnalysis.cc FSAnalysis.h
PTAnalysis_la_LDFLAGS = -module -version-info 1:0:0
PTAnalysis_la_SOURCES = PTAnalysis.cc PTAnalysis.h
GapAnalysis_la_LDFLAGS = -module -version-info 1:0:0
GapAnalysis_la_SOURCES = GapAnalysis.cc GapAnalysis.h
HIAnalysis_la_LDFLAGS = -module -version-info 1:0:0
HIAnalysis_la_SOURCES = HIAnalysis.cc HIAnalysis.h
PT1DEmitter_la_LDFLAGS = -module -version-info 1:0:0
PT1DEmitter_la_SOURCES = PT1DEmitter.cc PT1DEmitter.h
ElasticXSecAnalysis_la_LDFLAGS = -module -version-info 1:0:0
ElasticXSecAnalysis_la_SOURCES = ElasticXSecAnalysis.cc ElasticXSecAnalysis.h
DipoleDensityAnalysis_la_LDFLAGS = -module -version-info 1:0:0
DipoleDensityAnalysis_la_SOURCES = DipoleDensityAnalysis.cc DipoleDensityAnalysis.h
NoFluctXSecAnalysis_la_LDFLAGS = -module -version-info 1:0:0
NoFluctXSecAnalysis_la_SOURCES = NoFluctXSecAnalysis.cc NoFluctXSecAnalysis.h
SemiInclusiveXSecAnalysis_la_LDFLAGS = -module -version-info 1:0:0
SemiInclusiveXSecAnalysis_la_SOURCES = SemiInclusiveXSecAnalysis.cc SemiInclusiveXSecAnalysis.h
GlauberAnalysis_la_LDFLAGS = -module -version-info 1:0:0
-GlauberAnalysis_la_SOURCES = GlauberAnalysis.cc GlauberAnalysis.h
+GlauberAnalysis_la_SOURCES = GlauberAnalysis.cc GlauberAnalysis.h GlauberModels.h
AnalysisProgress_la_LDFLAGS = -module -version-info 1:0:0
AnalysisProgress_la_SOURCES = AnalysisProgress.cc AnalysisProgress.h
LargePTDipoleAbsorber_la_LDFLAGS = -module -version-info 1:0:0
LargePTDipoleAbsorber_la_SOURCES = LargePTDipoleAbsorber.cc LargePTDipoleAbsorber.h
SimpleNucleus_la_LDFLAGS = -module -version-info 1:0:0
SimpleNucleus_la_SOURCES = SimpleNucleus.cc SimpleNucleus.h \
SimpleNucleusState.cc SimpleNucleusState.h
RecoilSwinger_la_LDFLAGS = -module -version-info 1:0:0
RecoilSwinger_la_SOURCES = RecoilSwinger.cc RecoilSwinger.h
FixedImpactGenerator_la_LDFLAGS = -module -version-info 1:0:0
FixedImpactGenerator_la_SOURCES = FixedImpactGenerator.cc FixedImpactGenerator.h
GaussianImpactGenerator_la_LDFLAGS = -module -version-info 1:0:0
GaussianImpactGenerator_la_SOURCES = GaussianImpactGenerator.cc GaussianImpactGenerator.h
EXTRACLASSES = OldStyleEmitter.la PT1DEmitter.la ElasticXSecAnalysis.la \
LargePTDipoleAbsorber.la RecoilSwinger.la SimpleNucleus.la \
FSAnalysis.la GapAnalysis.la HIAnalysis.la \
FixedImpactGenerator.la FSDipole5Ordering.la
done-all-links:
@EMPTY@ifdef SHOWCOMMAND
for file in $(INPUTFILES); do \
if test ! -f $$file; then $(LN_S) $(srcdir)/$$file $$file; fi; done
echo "stamp" > done-all-links
@EMPTY@else
@echo "sym-linking input files files..."
@for file in $(INPUTFILES); do \
if test ! -f $$file; then $(LN_S) $(srcdir)/$$file $$file; fi; done
@echo "stamp" > done-all-links
@EMPTY@endif
DIPSYDefaults.rpo: done-all-links DIPSYDefaults.in libDIPSY.la $(EXTRACLASSES) $(THEPEGLIB)/ThePEGDefaults.rpo ../lib/Ariadne5Defaults.rpo
$(SETUPTHEPEG) -L../lib -L$(THEPEGLIB) -L ../../TheP8I/lib -L .libs -L ../src/.libs --exitonerror --init -r ../lib/Ariadne5Defaults.rpo -o DIPSYDefaults.rpo DIPSYDefaults.in
cd ../lib; $(LN_S) -f ../DIPSY/DIPSYDefaults.rpo .
Test5%.run: Test5%.in DIPSYDefaults.rpo CurrentTune.in RivetAnalyses.in
$(SETUPTHEPEG) --exitonerror -L .libs -L ../../Pythia7/src/.libs -r DIPSYDefaults.rpo $<
%.run: %.in DIPSYDefaults.rpo CurrentTune.in RivetAnalyses.in
$(SETUPTHEPEG) -L../lib --exitonerror -L .libs -r DIPSYDefaults.rpo $<
%.out: %.run
time $(RUNTHEPEG) --tics -d 0 $<
valgrind:
valgrind --leak-check=full --num-callers=25 --track-fds=yes --freelist-vol=100000000 --leak-resolution=med --trace-children=yes $(top_builddir)/../ThePEG/src/setupThePEG -L ../../ThePEG/lib -L../../Pythia7/lib --exitonerror -L../../TheP8I/lib -L .libs -L ../lib -r ../lib/Ariadne5Defaults.rpo TestFull.in &> /tmp/valgrind.out
valgrind --leak-check=full --num-callers=25 --track-fds=yes --freelist-vol=100000000 --leak-resolution=med --trace-children=yes $(top_builddir)/../ThePEG/src/runThePEG -N 10 TestFull.run >> /tmp/valgrind.out 2>&1
install-data-local:
LD_LIBRARY_PATH=$(DESTDIR)$(pkglibdir):$$LD_LIBRARY_PATH $(DESTDIR)$(bindir)/setupThePEG --exitonerror --init -i $(DESTDIR)$(pkgdatadir) -r $(DESTDIR)$(pkglibdir)/ThePEGDefaults.rpo -o $(DESTDIR)$(pkglibdir)/ThePEGDefaults.rpo $(srcdir)/DIPSYDefaults.in
unregister-from-repo:
LD_LIBRARY_PATH=$(DESTDIR)$(pkglibdir):$$LD_LIBRARY_PATH $(DESTDIR)$(bindir)/setupThePEG --exitonerror --init -r $(DESTDIR)$(pkglibdir)/ThePEGDefaults.rpo -o $(DESTDIR)$(pkglibdir)/ThePEGDefaults.rpo $(srcdir)/DIPSYRemove.in
include $(top_srcdir)/Config/Makefile.aminclude
diff --git a/DIPSY/NewSwinger.cc b/DIPSY/NewSwinger.cc
--- a/DIPSY/NewSwinger.cc
+++ b/DIPSY/NewSwinger.cc
@@ -1,427 +1,427 @@
// -*- 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));
+ double asa = Current<DipoleEventHandler>()->alphaSr(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));
+ double asa = Current<DipoleEventHandler>()->alphaSr(sqrt(a));
+ double asb = Current<DipoleEventHandler>()->alphaSr(sqrt(b));
+ double asc = Current<DipoleEventHandler>()->alphaSr(sqrt(c));
+ double asd = Current<DipoleEventHandler>()->alphaSr(sqrt(d));
a = sqr(rmax)/asa*sqr(exp(sqrt(a)/rmax) - 1.0);
b = sqr(rmax)/asb*sqr(exp(sqrt(b)/rmax) - 1.0);
c = sqr(rmax)/asc*sqr(exp(sqrt(c)/rmax) - 1.0);
d = sqr(rmax)/asd*sqr(exp(sqrt(d)/rmax) - 1.0);
//normal amplitude
if ( sqrt(a*b) < sqrt(c)*sqrt(d)*sqrt(theLambda*eps) ) return eps;
return a*b/(c*d)*theLambda;
}
void Swinger::generate(Dipole & dipole, double miny, double maxy, bool force) const {
//old implementation
double yi = max(max(dipole.partons().first->y(),
dipole.partons().second->y()), miny);
if ( dipole.partons().second == dipole.partons().first )
Throw<ColourIndexException>()
<< "Found inconsistent colour indices in DIPSY. Event discarded."
<< Exception::eventerror;
if( dipole.children().first)
Throw<SwingConsistencyException>()
<< "OH NOES, parents among the swing candidates!!!! O_o"
<< Exception::abortnow;
const vector<tDipolePtr> & candidates =
dipole.dipoleState().swingCandidates(dipole.colour());
vector<tDipolePtr>::size_type i = 0;
while ( i < candidates.size() && candidates[i++] != &dipole );
for (; i < candidates.size(); ++i ) {
if ( !force && candidates[i]->hasGen() ) continue;
double yn = yi - log(UseRandom::rnd())/swingAmp(dipole, *candidates[i]);
if ( yn < dipole.generatedY() ) {
dipole.swingDipole(candidates[i]);
dipole.generatedY(yn);
dipole.recoilSwing(false);
}
}
}
double Swinger::swingAmp(const Dipole & firstDip,
const Dipole & secondDip) const {
InvEnergy rmax = Current<DipoleEventHandler>()->rMax();
InvEnergy2 a = firstDip.swingCache;
if ( a < ZERO ) {
a = firstDip.partons().first->dist2(*firstDip.partons().second);
- a = sqr(rmax)/(Current<DipoleEventHandler>()->alphaS(sqrt(a)))*
+ a = sqr(rmax)/(Current<DipoleEventHandler>()->alphaSr(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)))*
+ b = sqr(rmax)/(Current<DipoleEventHandler>()->alphaSr(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)))*
+ c = sqr(rmax)/(Current<DipoleEventHandler>()->alphaSr(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)))*
+ d = sqr(rmax)/(Current<DipoleEventHandler>()->alphaSr(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)))*
+ (Current<DipoleEventHandler>()->alphaSr(sqrt(a)))*
sqr(exp(sqrt(a)/rmax) - 1.0);
b = sqr(rmax)/
- (Current<DipoleEventHandler>()->alphaS(sqrt(b)))*
+ (Current<DipoleEventHandler>()->alphaSr(sqrt(b)))*
sqr(exp(sqrt(b)/rmax) - 1.0);
c = sqr(rmax)/
- (Current<DipoleEventHandler>()->alphaS(sqrt(c)))*
+ (Current<DipoleEventHandler>()->alphaSr(sqrt(c)))*
sqr(exp(sqrt(c)/rmax) - 1.0);
d = sqr(rmax)/
- (Current<DipoleEventHandler>()->alphaS(sqrt(d)))*
+ (Current<DipoleEventHandler>()->alphaSr(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->interacted(d1.interacted());
if ( d2.interacted() ) d22->interacted(d2.interacted());
// 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", "libAriadne5.so libDIPSY.so");
void Swinger::Init() {
static ClassDocumentation<Swinger> documentation
("There is no documentation for the Swinger class");
static Parameter<Swinger,double> interfaceLambda
("Lambda",
"The frequency of the swings.",
&Swinger::theLambda, 1.0, 1.0, 0.0, 0.0,
true, false, Interface::lowerlim);
}
diff --git a/DIPSY/OldStyleEmitter.cc b/DIPSY/OldStyleEmitter.cc
--- a/DIPSY/OldStyleEmitter.cc
+++ b/DIPSY/OldStyleEmitter.cc
@@ -1,200 +1,200 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the OldStyleEmitter class.
//
#include "OldStyleEmitter.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "Parton.h"
#include "Dipole.h"
#include "DipoleState.h"
#include "ThePEG/Utilities/Current.h"
#include "DipoleEventHandler.h"
#include "ThePEG/Repository/UseRandom.h"
#include "gsl/gsl_sf_bessel.h"
#include <limits>
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace DIPSY;
OldStyleEmitter::OldStyleEmitter() {}
OldStyleEmitter::~OldStyleEmitter() {}
IBPtr OldStyleEmitter::clone() const {
return new_ptr(*this);
}
IBPtr OldStyleEmitter::fullclone() const {
return new_ptr(*this);
}
// Old y generator
double OldStyleEmitter::oldGenerateY(Dipole dip,double ymin) const {
double yshift=log(2000.0);
Energy ppsum = (dip.partons().first->plus() + dip.partons().second->plus())*exp(-yshift);
return -yshift- log(sqrt(1.0 + sqr(ppsum/(4.0*GeV)))) +
sqrt(sqr(log(sqrt(1.0 + sqr(ppsum/(4.0*GeV)))) + ymin+yshift)
- - log(UseRandom::rnd())/(4.0*alphaBar(Current<DipoleEventHandler>()->rMax())));
+ - log(UseRandom::rnd())/(4.0*alphaBarr(Current<DipoleEventHandler>()->rMax())));
}
//Old xy generator
pair<double,double> OldStyleEmitter::oldGenerateXY(Dipole dip, double y0) const {
double ppsum = dip.partons().first->plus()/GeV + dip.partons().second->plus()/GeV;
double rho = 2.0*exp(-y0)/ppsum ;
pair<double,double> ret;
double R1 = UseRandom::rnd();
double R2 = UseRandom::rnd();
double ir2 = pow(1.0 + 1.0/(4.0*sqr(rho)),R2) - 1.0;
double r = 0.0;
if ( ir2 < std::numeric_limits<double>::epsilon() ) r = rho/sqrt(R2);
else r = 0.5*sqrt(1.0/ir2);
double x = r*cos(2.0*M_PI*R1);
double y = r*sin(2.0*M_PI*R1);
ret.first = x;
if ( UseRandom::rnd() > 0.5 ) ret.first = 1.0 - x;
ret.second = y;
return ret;
}
void OldStyleEmitter::generate(Dipole & dip, double ymin, double ymax) const {
int vetoCounter = 0;
double y0 = 0.0*log(2000) + max(ymin,max(dip.partons().first->y(),dip.partons().second->y()));
// Generate the r,y and pp values for a possible emission.
while ( true ) {
vetoCounter++;
//first generate a starting y
// cout << "calling generate Y with y0 = " << y0 << endl;
y0 = oldGenerateY(dip,y0);
if(thestMode) y0 = 1.0;
if ( y0 > ymax ) {
dip.generatedGluon(new_ptr(Parton()));
dip.generatedY(y0);
break;
}
//OLD GENERATION! SHOULD BE REMOVED EVENTUALLY, BUT KEPT AS BACKUP....
//generate a xy FIX THIS; WRONG GENERATION!
pair<double,double> xy = oldGenerateXY(dip,y0);
Energy ppsum = dip.partons().first->plus() + dip.partons().second->plus();
double pbar = ppsum/4.0/GeV;
double yshift=log(2000.0);
y0 += yshift;
pbar *= exp(-yshift);
double gfratio = ((log(1.0 + sqr(pbar*exp(y0))))/(log(1.0 + sqr(pbar)) + 2.0*y0))*
(sqr(xy.first) + sqr(xy.second) + 0.25)*(sqr(1.0 - xy.first) + sqr(xy.second) + 0.25)/
((sqr(1.0 - xy.first) + sqr(xy.second))*(sqr(1.0 - xy.first) + sqr(xy.second) + 0.25) +
(sqr(xy.first) + sqr(xy.second))*(sqr(xy.first) + sqr(xy.second) + 0.25));
pbar *= exp(yshift);
y0 += -yshift;
if ( gfratio < UseRandom::rnd() )
continue;
PartonPtr q1 = dip.partons().first;
PartonPtr q2 = dip.partons().second;
double rx = xy.first*(q2->position().first*GeV - q1->position().first*GeV) -
xy.second*(q2->position().second*GeV - q1->position().second*GeV) + q1->position().first*GeV;
double ry = xy.first*(q2->position().second*GeV - q1->position().second*GeV) +
xy.second*(q2->position().first*GeV - q1->position().first*GeV) + q1->position().second*GeV;
double rij = dip.size()*GeV;
double rin = rij*sqrt(sqr(xy.first) + sqr(xy.second));
double rjn = rij*sqrt(sqr(1.0 - xy.first) + sqr(xy.second));
double rmax=Current<DipoleEventHandler>()->rMax()*GeV;
if(rin+rjn>rij+100) continue;
if ( sqr(rin*rjn/(rij))*sqr(1.0/rmax)*(sqr(gsl_sf_bessel_K1(rin/rmax)) +
sqr(gsl_sf_bessel_K1(rjn/rmax)) - (sqr(rin) + sqr(rjn) - sqr(rij))/(rin*rjn)* gsl_sf_bessel_K1(rin/rmax)*gsl_sf_bessel_K1(rjn/rmax)) < UseRandom::rnd() )
continue;
- if ( alphaBar(min(min(rin,rjn),rij)/GeV) < UseRandom::rnd()*alphaBar(rmax/GeV) )
+ if ( alphaBarr(min(min(rin,rjn),rij)/GeV) < UseRandom::rnd()*alphaBarr(rmax/GeV) )
continue;
double pt = 2.0/min(rin,rjn);
double pplus = pt*exp(-y0);
double pminus = pt*exp(y0);
if ( q1->plus()/GeV - (rjn/(rjn + rin))*pplus <= 0.0 )
continue;
if ( q2->plus()/GeV - (rin/(rin + rjn))*pplus <= 0.0 )
continue;
if ( pminus < (2.0/rij)*exp(max(q1->y(),q2->y())) ) //probably wrong, left to reproduce results
continue;
double pt1 = max(q1->pT().pt()/GeV, 2.0/rin);
double pt2 = max(q2->pT().pt()/GeV, 2.0/rjn);
if ( log(pt1/(q1->plus()/GeV - (rjn/(rin + rjn))*pplus)) > y0 )
continue;
if ( log(pt2/(q2->plus()/GeV - (rin/(rin + rjn))*pplus)) > y0 )
continue;
PartonPtr gluon = new_ptr(Parton());
gluon->position(Parton::Point(rx/GeV,ry/GeV));
dip.generatedGluon(gluon);
dip.generatedY(y0);
break;
}
}
void OldStyleEmitter::emit(Dipole & d) const {
TransverseMomentum e1 = TransverseMomentum(1.0*GeV,0.0*GeV);
double rin = sqrt(d.generatedGluon()->dist2(*d.partons().first))*GeV;
double rjn = sqrt(d.generatedGluon()->dist2(*d.partons().second))*GeV;
double P1 = rjn/(rin+rjn);
double P2 = 1.0-P1;
d.generatedGluon()->pT(e1*2.0/min(rin,rjn));
d.generatedGluon()->y(d.generatedY());
d.generatedGluon()->plus(d.generatedGluon()->pT().pt()*exp(-d.generatedY()));
d.generatedGluon()->minus(d.generatedGluon()->pT().pt()*exp(d.generatedY()));
d.generatedGluon()->oY(d.generatedGluon()->y());
d.partons().first->plus(d.partons().first->plus() - P1*d.generatedGluon()->plus());
d.partons().first->pT(e1*max(d.partons().first->pT().pt()/GeV, 2.0/rin));
d.partons().first->y(log(d.partons().first->pT().pt()/d.partons().first->plus()));
d.partons().first->minus(d.partons().first->pT().pt()*exp(d.partons().first->y()));
d.partons().second->plus(d.partons().second->plus() - P2*d.generatedGluon()->plus());
d.partons().second->pT(e1*max(d.partons().second->pT().pt()/GeV, 2.0/rjn));
d.partons().second->y(log(d.partons().second->pT().pt()/d.partons().second->plus()));
d.partons().second->minus(d.partons().second->pT().pt()*exp(d.partons().second->y()));
d.splitDipole(P2);
}
void OldStyleEmitter::persistentOutput(PersistentOStream & os) const {
// *** ATTENTION *** os << ; // Add all member variable which should be written persistently here.
}
void OldStyleEmitter::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<OldStyleEmitter,DIPSY::Emitter>
describeDIPSYOldStyleEmitter("DIPSY::OldStyleEmitter", "OldStyleEmitter.so");
void OldStyleEmitter::Init() {
static ClassDocumentation<OldStyleEmitter> documentation
("There is no documentation for the OldStyleEmitter class");
}
diff --git a/DIPSY/PAXSec.in b/DIPSY/PAXSec.in
--- a/DIPSY/PAXSec.in
+++ b/DIPSY/PAXSec.in
@@ -1,701 +1,718 @@
cd /DIPSY
## First we setup some tuned parameters
#read CurrentTune.in
read Tune31.in
## Now we set up an event generator. We start with running pp rahter than pA.
cp EventHandler PAEventHandler
set PAEventHandler:WFL stdProton
set PAEventHandler:WFR stdProton
set PAEventHandler:ConsistencyLevel 0
set PAEventHandler:XSecFn:CheckOffShell false
set PAEventHandler:CascadeHandler NULL
set PAEventHandler:HadronizationHandler NULL
set PAEventHandler:DecayHandler NULL
create ThePEG::LuminosityFunction PALumi
set PAEventHandler:LuminosityFunction PALumi
cp Generator PAGenerator
set PAGenerator:EventHandler PAEventHandler
set PAGenerator:NumberOfEvents 0
set PAGenerator:EventHandler:EventFiller:PTCut 0.6
set PAGenerator:Path PAXSec
erase PAGenerator:AnalysisHandlers[0]
set PAEventHandler:BGen:Width 10
set PAEventHandler:EffectivePartonMode Colours
## These are the analysess we will run
## First the Glauber analyses
erase PAEventHandler:AnalysisHandlers[0]
create DIPSY::GlauberAnalysis Glauber GlauberAnalysis.so
set Glauber:tMax 4
set Glauber:Nt 200
insert PAEventHandler:AnalysisHandlers[0] Glauber
## Some semi-inclusive cross section for DIPSY which need at least
## four combinations of left- and right-moving cascades.
create DIPSY::SemiInclusiveXSecAnalysis SemiIncl SemiInclusiveXSecAnalysis.so
insert PAEventHandler:AnalysisHandlers[0] SemiIncl
set PAEventHandler:PreSampleL 2
set PAEventHandler:PreSampleR 2
## This is just to keep track of the progress of a run
create DIPSY::AnalysisProgress AnaLog AnalysisProgress.so
set AnaLog:Interval 600
insert PAEventHandler:AnalysisHandlers[0] AnaLog
## Set the interaction frame
set PAEventHandler:YFrametest 0.5
# set PAEventHandler:YFrametest 0.9
## The sample rates need to be adjusted so that we get a reasonable
## statistics in a reasonable time. It is typically efficient to
## sample a number of impact parameter values for each pair of DIPSY
## cascades.
set PAEventHandler:PreSampleB 10
## But we need a good sample of cascades
set PAEventHandler:PreSamples 100000
## Set the pp energy we want to run with
set PALumi:BeamEMaxA 100
set PALumi:BeamEMaxB 100
## We run pp to get the nucleon--nucleon cross sections
saverun PA01pp0 PAGenerator
set PAEventHandler:BGen:Width 5
saverun PA01pp0t PAGenerator
set PAEventHandler:BGen:Width 10
saverun PA01pp0o PAGenerator
saverun PA01pp0c PAGenerator
# set PAEventHandler:EffectivePartonMode Relatives
set PALumi:BeamEMaxA 5000
set PALumi:BeamEMaxB 5000
saverun PA50pp1 PAGenerator
set PALumi:BeamEMaxA 200
set PALumi:BeamEMaxB 200
saverun PA02pp0 PAGenerator
set PALumi:BeamEMaxA 273
set PALumi:BeamEMaxB 273
saverun PAU2pp0 PAGenerator
set PAEventHandler:BGen:Width 1
saverun PAU2pp01 PAGenerator
set PAEventHandler:BGen:Width 10
# playground ...
set PAEventHandler:PreSampleB 4
set PAEventHandler:PreSamples 10000
saverun PAU2pp1 PAGenerator
saverun PAU2pp12 PAGenerator
set PAEventHandler:BGen:Width 4
saverun PAU2pp4 PAGenerator
set PAEventHandler:BGen:Width 10
set stdProton:R0 2.8
set PAEventHandler:RMax 3.1
set PAEventHandler:CoherenceRange 3.0
set stdEmitter:PMinusOrdering 1.0
saverun PAU2pp2 PAGenerator
set stdProton:R 0.001
set PAEventHandler:PreSamples 1000000
saverun PAU2pp3 PAGenerator
set stdProton:R 0.5
saverun PAU2pp5 PAGenerator
set stdProton:R 0.1
set stdEmitter:PMinusOrdering 0.8
set PAEventHandler:CoherenceRange 2.9
set PAEventHandler:RMax 2.9
set PAEventHandler:PreSampleB 10
set PAEventHandler:PreSamples 100000
# ... end
set stdProton:R0 2.9
set PALumi:BeamEMaxA 315
set PALumi:BeamEMaxB 315
saverun PAU3pp0 PAGenerator
set PALumi:BeamEMaxA 500
set PALumi:BeamEMaxB 500
saverun PA05pp0 PAGenerator
set PALumi:BeamEMaxA 900
set PALumi:BeamEMaxB 900
saverun PA09pp0 PAGenerator
set PALumi:BeamEMaxA 1000
set PALumi:BeamEMaxB 1000
saverun PA10pp0 PAGenerator
set PALumi:BeamEMaxA 2500
set PALumi:BeamEMaxB 2500
saverun PA25pp0 PAGenerator
set PALumi:BeamEMaxA 3500
set PALumi:BeamEMaxB 3500
saverun PA35pp0 PAGenerator
set PALumi:BeamEMaxA 5000
set PALumi:BeamEMaxB 5000
saverun PA50pp0 PAGenerator
set PAEventHandler:PreSampleB 1
set PAEventHandler:PreSamples 10000
create ThePEG::LWHFactory HFac LWHFactory.so
set HFac:StoreType flat
set HFac:Suffix dat
set PAGenerator:HistogramFactory HFac
create DIPSY::DipoleDensityAnalysis Density DipoleDensityAnalysis.so
insert PAEventHandler:AnalysisHandlers[0] Density
saverun Density70 PAGenerator
set PAEventHandler:Swinger NULL
saverun Density70ns PAGenerator
set PAEventHandler:Swinger stdSwinger
set PALumi:BeamEMaxA 1750
set PALumi:BeamEMaxB 1750
saverun Density35 PAGenerator
set PALumi:BeamEMaxA 875
set PALumi:BeamEMaxB 875
saverun Density18 PAGenerator
erase PAEventHandler:AnalysisHandlers[0]
set PAEventHandler:PreSampleB 10
set PAEventHandler:PreSamples 100000
set PALumi:BeamEMaxA 3500
set PALumi:BeamEMaxB 3500
## Now we take these cross sections and feed them into the Glauber analysis
## My numbers for 100 GeV (in millibarns)
set Glauber:TotalnnXSec 49.71
set Glauber:ElasticnnXSec 9.10
set Glauber:InElasticnnXSec 35.80
set PALumi:BeamEMaxA 100
set PALumi:BeamEMaxB 100
## Run again to make sure that the cross sections are reproduced, at least by "grey3 disc"
saverun PA01pp1 PAGenerator
set PAEventHandler:PreSamples 1000000
saverun PA01pp2 PAGenerator
saverun PA01pp3 PAGenerator
## Interlude for gamma-p Q^2 = 5 GeV^2
set virtualPhoton:Q2 5.0
set PAEventHandler:WFL virtualPhoton
set PAEventHandler:PreSamples 100000
saverun PA01gp1 PAGenerator
set ElXSec:NBins 200
set ElXSec:DeltaB 0.25
set ElXSec:NqBins 400
set ElXSec:Deltaq 0.02
set PAEventHandler:PreSamples 10000
saverun PA01gp2 PAGenerator
set Glauber:TotalnnXSec 0.0268
set Glauber:ElasticnnXSec 0.00000531
set Glauber:InElasticnnXSec 0.0227
set PAEventHandler:PreSamples 1000000
set virtualPhoton:Q2 45.0
saverun PA01gp3 PAGenerator
set virtualPhoton:Q2 15.0
saverun PA01gp4 PAGenerator
set virtualPhoton:Q2 3.5
saverun PA01gp5 PAGenerator
set virtualPhoton:Q2 90.0
saverun PA01gp6 PAGenerator
set PALumi:BeamEMaxA 50
set PALumi:BeamEMaxB 50
set virtualPhoton:Q2 45.0
saverun PA01gp7 PAGenerator
set PALumi:BeamEMaxA 100
set PALumi:BeamEMaxB 100
set PAEventHandler:WFL stdProton
## My numbers for 200 GeV
set Glauber:TotalnnXSec 58.52
set Glauber:ElasticnnXSec 11.64
set Glauber:InElasticnnXSec 41.05
+set Glauber:SDnnXSec 3.75
set PALumi:BeamEMaxA 200
set PALumi:BeamEMaxB 200
set PAEventHandler:PreSamples 100000
saverun PA02pp1 PAGenerator
+saverun PA02pp4 PAGenerator
set PAEventHandler:PreSamples 1000000
saverun PA02pp2 PAGenerator
saverun PA02pp3 PAGenerator
## My numbers for 500 GeV
set Glauber:TotalnnXSec 70.53
set Glauber:ElasticnnXSec 15.36
set Glauber:InElasticnnXSec 47.88
set PALumi:BeamEMaxA 500
set PALumi:BeamEMaxB 500
set PAEventHandler:PreSamples 100000
saverun PA05pp1 PAGenerator
set PAEventHandler:PreSamples 1000000
saverun PA05pp2 PAGenerator
saverun PA05pp3 PAGenerator
## My numbers for 1000 GeV
set Glauber:TotalnnXSec 79.63
set Glauber:ElasticnnXSec 18.35
set Glauber:InElasticnnXSec 52.85
set PALumi:BeamEMaxA 1000
set PALumi:BeamEMaxB 1000
set PAEventHandler:PreSamples 100000
saverun PA10pp1 PAGenerator
set PAEventHandler:PreSamples 1000000
saverun PA10pp2 PAGenerator
saverun PA10pp3 PAGenerator
## My numbers for 2500 GeV
set Glauber:TotalnnXSec 91.43
set Glauber:ElasticnnXSec 22.35
set Glauber:InElasticnnXSec 59.12
+set Glauber:SDnnXSec 7.13
set PALumi:BeamEMaxA 2500
set PALumi:BeamEMaxB 2500
set PAEventHandler:PreSamples 100000
saverun PA25pp1 PAGenerator
saverun PA25pp2 PAGenerator
+saverun PA25pp5 PAGenerator
set PAEventHandler:PreSamples 1000000
saverun PA25pp3 PAGenerator
+saverun PA25pp4 PAGenerator
set Glauber:TotalnnXSec 95.86
set Glauber:ElasticnnXSec 23.88
set Glauber:InElasticnnXSec 61.41
set PALumi:BeamEMaxA 3500
set PALumi:BeamEMaxB 3500
set PAEventHandler:PreSamples 100000
saverun PA35pp1 PAGenerator
saverun PA35pp2 PAGenerator
set PALumi:BeamEMaxA 5000
set PALumi:BeamEMaxB 5000
set PAEventHandler:PreSamples 100000
saverun PA50pp2 PAGenerator
## Finally it's time to run with a heavy ion.
create DIPSY::GaussianImpactGenerator BGauss GaussianImpactGenerator.so
set PAEventHandler:BGen BGauss
set BGauss:Width 15
set PAEventHandler:WFR Oxygen
set PALumi:BeamEMaxA 100
set PALumi:BeamEMaxB 1600
set Glauber:TotalnnXSec 49.71
set Glauber:ElasticnnXSec 9.10
set Glauber:InElasticnnXSec 35.80
set Copper:InterNucleonSwing On
set PAEventHandler:PreSampleB 40
set PAEventHandler:PreSampleL 20
set PAEventHandler:PreSamples 1000
saverun PA01pO1 PAGenerator
set Copper:InterNucleonSwing Off
saverun PA01pO2 PAGenerator
set Oxygen:Rn 0
saverun PA01pO2a PAGenerator
set Oxygen:Rn -1.3
saverun PA01pO2b PAGenerator
set Oxygen:Rn 1.3
saverun PA01pO2c PAGenerator
set Oxygen:w 0.051
saverun PA01pO2d PAGenerator
set Oxygen:Rn 0
saverun PA01pO2e PAGenerator
set PAEventHandler:WFR Copper
# set PAEventHandler:WFR Lead
set PALumi:BeamEMaxA 100
set PALumi:BeamEMaxB 6300
set Glauber:TotalnnXSec 49.71
set Glauber:ElasticnnXSec 9.10
set Glauber:InElasticnnXSec 35.80
set Copper:InterNucleonSwing On
set PAEventHandler:PreSampleB 40
set PAEventHandler:PreSampleL 20
set PAEventHandler:PreSamples 1000
saverun PA01pCu1 PAGenerator
set Copper:InterNucleonSwing Off
saverun PA01pCu2 PAGenerator
set PALumi:BeamEMaxA 200
set PALumi:BeamEMaxB 12600
set Glauber:TotalnnXSec 58.52
set Glauber:ElasticnnXSec 11.64
set Glauber:InElasticnnXSec 41.05
set Copper:InterNucleonSwing On
set PAEventHandler:PreSampleB 40
set PAEventHandler:PreSampleL 20
set PAEventHandler:PreSamples 1000
saverun PA02pCu1 PAGenerator
set Copper:InterNucleonSwing Off
saverun PA02pCu2 PAGenerator
set PALumi:BeamEMaxA 500
set PALumi:BeamEMaxB 31500
set Glauber:TotalnnXSec 70.53
set Glauber:ElasticnnXSec 15.36
set Glauber:InElasticnnXSec 47.88
set Copper:InterNucleonSwing On
set PAEventHandler:PreSampleB 40
set PAEventHandler:PreSampleL 20
set PAEventHandler:PreSamples 1000
saverun PA05pCu1 PAGenerator
set Copper:InterNucleonSwing Off
saverun PA05pCu2 PAGenerator
set Copper:InterNucleonSwing On
do Copper:SetNucleus Cu GLISSANDO
set Copper:Recenter true
saverun PA05pCu3 PAGenerator
set Copper:InterNucleonSwing Off
saverun PA05pCu5 PAGenerator
set Copper:InterNucleonSwing On
set Copper:Recenter false
saverun PA05pCu4 PAGenerator
do Copper:SetNucleus Cu
set PALumi:BeamEMaxA 1000
set PALumi:BeamEMaxB 63000
set Glauber:TotalnnXSec 79.63
set Glauber:ElasticnnXSec 18.35
set Glauber:InElasticnnXSec 52.85
set Copper:InterNucleonSwing On
set PAEventHandler:PreSampleB 40
set PAEventHandler:PreSampleL 20
set PAEventHandler:PreSamples 500
saverun PA10pCu1 PAGenerator
set Copper:InterNucleonSwing Off
saverun PA10pCu2 PAGenerator
saverun PA10pCu3 PAGenerator
set PALumi:BeamEMaxA 2500
set PALumi:BeamEMaxB 157500
set Glauber:TotalnnXSec 91.43
set Glauber:ElasticnnXSec 22.35
set Glauber:InElasticnnXSec 59.12
+set Glauber:SDnnXSec 7.13
set Copper:InterNucleonSwing On
set PAEventHandler:PreSampleB 40
set PAEventHandler:PreSampleL 20
set PAEventHandler:PreSamples 500
saverun PA25pCu1 PAGenerator
set Copper:InterNucleonSwing Off
saverun PA25pCu2 PAGenerator
# Let's do lead as well
set PAEventHandler:WFR Lead
# Just testing Glauber first
set Lead:Rn -0.9
set Lead:R 6.407
set Lead:a 0.459
set PALumi:BeamEMaxA 10
set PALumi:BeamEMaxB 2080
set PAEventHandler:PreSampleB 40
set PAEventHandler:PreSampleL 20
set PAEventHandler:PreSamples 500
set Glauber:TotalnnXSec 49.71
set Glauber:ElasticnnXSec 9.10
set Glauber:InElasticnnXSec 35.80
saverun PA01pPbG PAGenerator
set Glauber:TotalnnXSec 58.52
set Glauber:ElasticnnXSec 11.64
set Glauber:InElasticnnXSec 41.05
saverun PA02pPbG PAGenerator
set Glauber:TotalnnXSec 70.53
set Glauber:ElasticnnXSec 15.36
set Glauber:InElasticnnXSec 47.88
saverun PA05pPbG PAGenerator
set Glauber:TotalnnXSec 79.63
set Glauber:ElasticnnXSec 18.35
set Glauber:InElasticnnXSec 52.85
saverun PA10pPbG PAGenerator
set Glauber:TotalnnXSec 91.43
set Glauber:ElasticnnXSec 22.35
set Glauber:InElasticnnXSec 59.12
+set Glauber:SDnnXSec 7.13
set PAEventHandler:WFR stdProton
set PAEventHandler:PreSamples 5000
saverun PA10ppG PAGenerator
set PAEventHandler:PreSamples 500
set PAEventHandler:WFR Lead
saverun PA25pPbG PAGenerator
set Glauber:TotalnnXSec 95.6
set Glauber:ElasticnnXSec 23.82
set Glauber:InElasticnnXSec 61.22
saverun PA35pPbG PAGenerator
set Glauber:TotalnnXSec 95.86
set Glauber:ElasticnnXSec 23.88
set Glauber:InElasticnnXSec 61.41
saverun PA35pPbG2 PAGenerator
set Glauber:TotalnnXSec 95.79
set Glauber:ElasticnnXSec 23.86
set Glauber:InElasticnnXSec 61.36
saverun PA35pPbG3 PAGenerator
set Glauber:TotalnnXSec 99.8
set Glauber:ElasticnnXSec 25.1
set Glauber:InElasticnnXSec 63.4
saverun PA50pPbG PAGenerator
set PAEventHandler:PreSampleB 1
set PAEventHandler:PreSampleL 1
set PAEventHandler:PreSamples 20000
set Lead:R 6.407
set Lead:a 0.459
set Lead:Rn -0.9
set Lead:w 0
set Lead:NTry 0
saverun PA35pPb9GL0 PAGenerator
set Lead:NTry 1
saverun PA35pPb9GL1 PAGenerator
set Lead:NTry 100
saverun PA35pPb9GL100 PAGenerator
set Lead:R 6.491
set Lead:a 0.54
set Lead:Rn 0.0
set Lead:w 0
set Lead:NTry 0
saverun PA35pPb0GL0 PAGenerator
set Lead:NTry 1
saverun PA35pPb0GL1 PAGenerator
set Lead:NTry 100
saverun PA35pPb0GL100 PAGenerator
set Lead:R 6.531
set Lead:a 0.46
set Lead:Rn 0.0
set Lead:w 0
set Lead:NTry 0
saverun PA35pPb1GL0 PAGenerator
set Lead:NTry 1
saverun PA35pPb1GL1 PAGenerator
set Lead:NTry 100
saverun PA35pPb1GL100 PAGenerator
set PAEventHandler:PreSampleB 40
set PAEventHandler:PreSampleL 20
set PAEventHandler:PreSamples 500
do Lead:SetNucleus Pb
set Lead:Rn 1.3
# Now include also DIPSY
set PALumi:BeamEMaxA 100
set PALumi:BeamEMaxB 20800
set Glauber:TotalnnXSec 49.71
set Glauber:ElasticnnXSec 9.10
set Glauber:InElasticnnXSec 35.80
set Lead:InterNucleonSwing On
set PAEventHandler:PreSampleB 40
set PAEventHandler:PreSampleL 20
set PAEventHandler:PreSamples 500
saverun PA01pPb1 PAGenerator
saverun PA01pPb1o PAGenerator
set Lead:Rn -1.3
saverun PA01pPb1c PAGenerator
set Lead:Rn 1.3
saverun PA01pPb1C PAGenerator
set Lead:Rn 0.0
saverun PA01pPb1h PAGenerator
set Lead:Rn -0.9
set Lead:R 6.407
set Lead:a 0.459
saverun PA01pPb1g PAGenerator
set PAEventHandler:PreSamples 50
saverun PA01pPb1g2 PAGenerator
set PAEventHandler:PreSamples 500
do Lead:SetNucleus Pb
set Lead:Rn 1.3
set Lead:InterNucleonSwing Off
saverun PA01pPb2 PAGenerator
set PALumi:BeamEMaxA 200
set PALumi:BeamEMaxB 41600
set Glauber:TotalnnXSec 58.52
set Glauber:ElasticnnXSec 11.64
set Glauber:InElasticnnXSec 41.05
set Lead:InterNucleonSwing On
set PAEventHandler:PreSampleB 40
set PAEventHandler:PreSampleL 20
set PAEventHandler:PreSamples 250
saverun PA02pPb1 PAGenerator
set Lead:InterNucleonSwing Off
saverun PA02pPb2 PAGenerator
set Lead:InterNucleonSwing On
set Lead:Rn -0.9
set Lead:R 6.407
set Lead:a 0.459
saverun PA02pPb3 PAGenerator
set Lead:InterNucleonSwing Off
saverun PA02pPb4 PAGenerator
set Lead:InterNucleonSwing On
do Lead:SetNucleus Pb
set Lead:Rn 1.3
set PALumi:BeamEMaxA 500
set PALumi:BeamEMaxB 10400
set Glauber:TotalnnXSec 70.53
set Glauber:ElasticnnXSec 15.36
set Glauber:InElasticnnXSec 47.88
set Lead:InterNucleonSwing On
set PAEventHandler:PreSampleB 40
set PAEventHandler:PreSampleL 20
set PAEventHandler:PreSamples 250
saverun PA05pPb1 PAGenerator
set Lead:InterNucleonSwing Off
saverun PA05pPb2 PAGenerator
do Lead:SetNucleus Pb GLISSANDO
set Lead:Recenter true
saverun PA05pPb3 PAGenerator
set Lead:Recenter false
saverun PA05pPb4 PAGenerator
do Lead:SetNucleus Pb
set PALumi:BeamEMaxA 1000
set PALumi:BeamEMaxB 208000
set Glauber:TotalnnXSec 79.63
set Glauber:ElasticnnXSec 18.35
set Glauber:InElasticnnXSec 52.85
set Lead:InterNucleonSwing On
set PAEventHandler:PreSampleB 40
set PAEventHandler:PreSampleL 20
set PAEventHandler:PreSamples 250
saverun PA10pPb1 PAGenerator
set Lead:InterNucleonSwing Off
saverun PA10pPb2 PAGenerator
set PALumi:BeamEMaxA 2500
set PALumi:BeamEMaxB 416000
set Glauber:TotalnnXSec 91.43
set Glauber:ElasticnnXSec 22.35
set Glauber:InElasticnnXSec 59.12
+set Glauber:SDnnXSec 7.13
set Lead:InterNucleonSwing On
set PAEventHandler:PreSampleB 40
set PAEventHandler:PreSampleL 20
set PAEventHandler:PreSamples 100
saverun PA25pPb1 PAGenerator
set Lead:InterNucleonSwing Off
saverun PA25pPb2 PAGenerator
set Lead:InterNucleonSwing On
set Lead:Rn -0.9
set Lead:R 6.407
set Lead:a 0.459
saverun PA25pPb3 PAGenerator
set Lead:InterNucleonSwing Off
saverun PA25pPb4 PAGenerator
set Lead:InterNucleonSwing On
do Lead:SetNucleus Pb GLISSANDO
saverun PA25pPb5 PAGenerator
set Lead:Recenter true
saverun PA25pPb7 PAGenerator
set Lead:Recenter false
set Lead:InterNucleonSwing Off
saverun PA25pPb6 PAGenerator
set Lead:Recenter true
saverun PA25pPb8 PAGenerator
set Lead:Recenter false
set PALumi:BeamEMaxA 10
set PALumi:BeamEMaxB 2080
set PAEventHandler:PreSamples 5000
saverun PA25pPbGG PAGenerator
set Lead:Recenter true
saverun PA25pPbGR PAGenerator
+saverun PA25pPbGR2 PAGenerator
+set PAEventHandler:PreSamples 500
+saverun PA25pPbGR3 PAGenerator
+set Glauber:TotalnnXSec 89.6
+set Glauber:ElasticnnXSec 22.35
+set Glauber:InElasticnnXSec 59.12
+set Glauber:SDnnXSec 7.13
+set PAEventHandler:PreSamples 5000
+
set Lead:Recenter false
set PAEventHandler:PreSamples 100
set Lead:InterNucleonSwing On
do Lead:SetNucleus Pb
set Lead:Rn 1.3
set PALumi:BeamEMaxA 3500
set PALumi:BeamEMaxB 728000
set Glauber:TotalnnXSec 95.79
set Glauber:ElasticnnXSec 23.86
set Glauber:InElasticnnXSec 61.36
set Lead:InterNucleonSwing On
set PAEventHandler:PreSampleB 40
set PAEventHandler:PreSampleL 20
set PAEventHandler:PreSamples 100
saverun PA35pPb1 PAGenerator
set Lead:InterNucleonSwing Off
saverun PA35pPb2 PAGenerator
set Lead:InterNucleonSwing On
set Lead:Rn -0.9
set Lead:R 6.407
set Lead:a 0.459
saverun PA35pPb3 PAGenerator
set Lead:InterNucleonSwing Off
saverun PA35pPb4 PAGenerator
set Lead:InterNucleonSwing On
do Lead:SetNucleus Pb
set Lead:Rn 1.3
set PALumi:BeamEMaxA 5000
set PALumi:BeamEMaxB 832000
set Glauber:TotalnnXSec 99.54
set Glauber:ElasticnnXSec 25.12
set Glauber:InElasticnnXSec 63.2
set Lead:InterNucleonSwing On
set PAEventHandler:PreSampleB 20
set PAEventHandler:PreSampleL 10
set PAEventHandler:PreSamples 100
saverun PA50pPb1 PAGenerator
set Lead:InterNucleonSwing Off
saverun PA50pPb2 PAGenerator
set Lead:InterNucleonSwing On
set Lead:Rn -0.9
set Lead:R 6.407
set Lead:a 0.459
saverun PA50pPb3 PAGenerator
set Lead:InterNucleonSwing Off
saverun PA50pPb4 PAGenerator
set Lead:InterNucleonSwing On
do Lead:SetNucleus Pb GLISSANDO
saverun PA50pPb5 PAGenerator
set Lead:Recenter true
saverun PA50pPb7 PAGenerator
set Lead:Recenter false
set Lead:InterNucleonSwing Off
saverun PA50pPb6 PAGenerator
set Lead:Recenter true
saverun PA50pPb8 PAGenerator
set Lead:Recenter false
set PALumi:BeamEMaxA 10
set PALumi:BeamEMaxB 2080
set PAEventHandler:PreSamples 5000
saverun PA50pPbGG PAGenerator
set Lead:Recenter true
saverun PA50pPbGR PAGenerator
set Lead:Recenter false
# set PALumi:BeamEMaxB 12600
# set PALumi:BeamEMaxB 31500
# set PALumi:BeamEMaxB 63000
# set PALumi:BeamEMaxB 157500
## We may need to adjust the sampling. Especially since the nucleus
## cascade is time consuming, it may be worth running several protons
## per nucleus.
# set PAEventHandler:PreSampleB 10
set PAEventHandler:PreSampleL 10
set PAEventHandler:PreSamples 2000
## Let's go
# saverun PA01pCu2 PAGenerator
## And let's run one more time with the swing between nucleons turned
## off
set Copper:InterNucleonSwing Off
# saverun PA01pCu3 PAGenerator
set PAEventHandler:BGen:Width 10
# saverun PA01pCu4 PAGenerator
set PAEventHandler:BGen:Width 15
# saverun PA01pCu5 PAGenerator
set PAEventHandler:PreSamples 200
create DIPSY::GaussianImpactGenerator BGauss GaussianImpactGenerator.so
# saverun PA01pCu6 PAGenerator
set BGauss:Width 21
set PAEventHandler:BGen BGauss
# saverun PA01pCu7 PAGenerator
set BGauss:Width 15
set Copper:InterNucleonSwing On
set PAEventHandler:PreSamples 1000
# saverun PA01pCu80 PAGenerator
set PAEventHandler:PreSampleL 20
set PAEventHandler:PreSamples 500
# saverun PA01pCu81 PAGenerator
set PAEventHandler:PreSampleR 4
set PAEventHandler:PreSamples 250
# saverun PA01pCu82 PAGenerator
diff --git a/DIPSY/PPTune/Makefile b/DIPSY/PPTune/Makefile
--- a/DIPSY/PPTune/Makefile
+++ b/DIPSY/PPTune/Makefile
@@ -1,4 +1,7 @@
+PPTune.inc:
+ @echo "Cannot make PPTune.inc"
+
%: PPTune.inc
./expand.pl -p $@ PPTune.inc > PPTune.in
../../../ThePEG/src/setupThePEG -L ../../../ThePEG/lib -L../../../Pythia7/lib -L../../../TheP8I/lib -L../../lib --exitonerror -L ../.libs -r ../DIPSYDefaults.rpo PPTune.in
diff --git a/DIPSY/PPTune/PPTune.inc b/DIPSY/PPTune/PPTune.inc
--- a/DIPSY/PPTune/PPTune.inc
+++ b/DIPSY/PPTune/PPTune.inc
@@ -1,611 +1,776 @@
# -*- eval: (ThePEG-repository-mode) -*-
# HOW TO TUNE
#
# We need to generate a number of yoda files for different energies
# different observables and different parameter settings. This can be
# done in an semi-automated way.
#
# For the total and elastic cross sections we do not need to generate
# final states and these runs can in principle be done once and for
# all. In fact running PP16XSECYM??.run (generated in the SAVERUNYM
# just after the line "# 16 inclusive observables" below) will produce
# all necessary data.
#
# This input file is (to make a gross understatement) a terrible
# mess. It needs to beprocessed by the script ./expand.pl before going
# to setupThePEG and it will produce an awfull amount of .run
# files. However doing eg.
# > make blaha
# in this directory yo will only produce the .run files matching "blaha".
#
# For the final state you have to run the files generated after the
# line "# 16 final state observables" below. You will have one run per
# energy in PP16XSECYM@??.run (where @ is some arbitrary letter used
# to differentiate between settings). The 7TeV will take quite a while
# so it is best to divide it up in smaller runs. Using the scripts
# "sub" and "runtag" in ~leif/bin you can start the programs as
# follows:
#
# > sub runtag ./runThePEG, PP16XSECYM@02, PP16XSECYM@09,
# PP16XSECYM@71_61-80, PP16XSECYM@71_41-60,
# PP16XSECYM@71_21-40, PP16XSECYM@71_1-20
# PP16XSECYM@71_81-100
#
# After these runs are done you can start the actual tuning with
# professor. First you need to copy the relevant files from the
# inclusive runs to match the names of the final states runs as
# follows:
# > cp PP16XSECYM01.log PP16XSECYM@01.log
# > cp PP16XSECYM05.log PP16XSECYM@05.log
# > cp PP16XSECYM18.log PP16XSECYM@18.log
# > cp PP16XSECYM70.log PP16XSECYM@70.log
# then run the mkprof.pl script as follows to get a "global" tune
#
# > ./mkprof.pl -t -w PPTuneFS00.weights -o PP16XSECYM@00.prof PP16XSECYM@
# preferably redirecting both stdout and stderr to some file (there
# will be a lot of output). Similarly
# > ./mkprof.pl -t -w PPTuneFS70.weights -o PP16XSECYM@70.prof PP16XSECYM@
# will give the tune restricting the final state data to 7TeV, and
# changing all "70" to "09" or "02" will give 900 GeV or 200 GeV to
# look at the result check the file
# PP16XSECYM@00.prof/tunes/results.pkl or use the following script
# > ./profsum.pl PP16XSECYM@00.prof/tunes/results.pkl
# To get just a summary.
#
# After the line "# 16 pipeing the tunes" below you can then pipe the
# different tunes, just set the parameters according to the fit, do
# > make PPT16XSECYM@
# and run eg.
# > sub runtag ./runThePEG, PPT16XSECYM@02, PPT16XSECYM@09, PPT16XSECYM@71,
# PPT16XSECYM@0202, PPT16XSECYM@0909, PPT16XSECYM@7170
#
#
#
#
cd /DIPSY
## First we setup some previously tuned tuned parameters
#read CurrentTune.in
read ../Tune31.in
## Now we set up an event generator.
cp EventHandler PPEventHandler
set stdProton:R0 0.0
set stdAntiProton:R0 0.0
set Proton:R0 0.0
set AntiProton:R0 0.0
set PPEventHandler:WFL stdProton
set PPEventHandler:WFR stdProton
set PPEventHandler:ConsistencyLevel 1
set PPEventHandler:XSecFn:CheckOffShell false
set PPEventHandler:CascadeHandler AriadneCascade
set PPEventHandler:HadronizationHandler Frag8
set PPEventHandler:DecayHandler /Defaults/Handlers/StandardDecayHandler
create ThePEG::FixedCMSLuminosity PPLumi
set PPEventHandler:LuminosityFunction PPLumi
cp Generator PPGenerator
erase PPGenerator:AnalysisHandlers[0]
set PPGenerator:HistogramFactory NULL
set PPGenerator:EventHandler PPEventHandler
set PPEventHandler:BGen:Width 5
set PPEventHandler:WFL Proton
set PPEventHandler:WFR Proton
set PPEventHandler:EventFiller:SoftRemove NoValence
set PPEventHandler:FudgeME 1
set PPEventHandler:EventFiller:PTCut 1.0
set FSOrdering:PTMin 1.0
set PPEventHandler:Emitter:PSInflation 1.0
set PPEventHandler:Swinger:Lambda 1.0
set PPEventHandler:EffectivePartonMode Colours
set PPEventHandler:CoherenceRange 2.5
## These are the analysess we will run
## Some semi-inclusive cross section for DIPSY which need at least
## four combinations of left- and right-moving cascades.
erase PPEventHandler:AnalysisHandlers[0]
erase PPEventHandler:AnalysisHandlers[0]
create DIPSY::SemiInclusiveXSecAnalysis SemiIncl SemiInclusiveXSecAnalysis.so
insert PPEventHandler:AnalysisHandlers[0] SemiIncl
set PPEventHandler:PreSampleL 2
set PPEventHandler:PreSampleR 2
## This is just to keep track of the progress of a run
create DIPSY::AnalysisProgress AnaLog AnalysisProgress.so
set AnaLog:Interval 600
insert PPEventHandler:AnalysisHandlers[0] AnaLog
## The sample rates need to be adjusted so that we get a reasonable
## statistics in a reasonable time. It is typically efficient to
## sample a number of impact parameter values for each pair of DIPSY
## cascades.
set PPEventHandler:PreSampleB 1
## We need the same set of parameters for all different energies, so
## we use a separate random generator.
cp /Defaults/Random RandomArg
set PPGenerator:SeparateRandom RandomArg
## These are the parameters we want to tune
## Now we want to run for all energies and two values for YFrametest
set Frag8:Collapser /Ariadne5/Defaults/Collapser
# This is the fragmentation parameters tuned without rope and with swing at LEP
# ../../src/FTuneSwLEP01.prin
set Frag8:FragmentationScheme none
set Frag8:StringZ_aLund 0.42
set Frag8:StringZ_bLund 0.40
set Frag8:StringPT_sigma 0.32
set Frag8:StringFlav_probQQtoQ 0.084
set Frag8:StringFlav_probStoUD 0.22
# This is the fragmentation parameters tuned without rope and swing at LEP
# ../../src/FTuneLEP01.prin
cp Frag8 Frag8Sw0
set Frag8Sw0:StringZ_aLund 0.30
set Frag8Sw0:StringZ_bLund 0.36
set Frag8Sw0:StringPT_sigma 0.32
set Frag8Sw0:StringFlav_probQQtoQ 0.082
set Frag8Sw0:StringFlav_probStoUD 0.22
# TEST fragmentation parameters tuned at LEP without rope and swing with MaxRho = 1
# ../../src/FTuneswLEP03.prin
cp Frag8 Frag8Sw2
set Frag8Sw2:StringZ_aLund 0.45
set Frag8Sw2:StringZ_bLund 0.42
set Frag8Sw2:StringPT_sigma 0.32
set Frag8Sw2:StringFlav_probQQtoQ 0.085
set Frag8Sw2:StringFlav_probStoUD 0.22
# This is the fragmentation parameters tuned to rope and default swing at LEP
# ../../src/FTuneSwLEP07.prin
cp Frag8 Frag8Rope
set Frag8Rope:FragmentationScheme dipole
set Frag8Rope:StringR0 1.0
set Frag8Rope:Stringm0 0.2
set Frag8Rope:Average false
set Frag8Rope:ThrowAway true
set Frag8Rope:BaryonSuppression 0.25
set Frag8Rope:StringZ_aLund 0.41
set Frag8Rope:StringZ_bLund 0.37
set Frag8Rope:StringPT_sigma 0.31
set Frag8Rope:StringFlav_probQQtoQ 0.073
set Frag8Rope:StringFlav_probStoUD 0.21
cp AriadneCascade AriadneNoSwing
erase AriadneNoSwing:Emitters[0]
set PPGenerator:EventHandler:PreSamples 0
set PPGenerator:EventHandler:YFrametest 0.5
set /DIPSY/PPEventHandler:BaryonSize 0.0
set FSSwinger:SetRmax -2.7
set FSSwinger:MaxRho -2.0
create ThePEG::ProgressLog Logger ProgressLog.so
set Logger:Interval 600
create ThePEG::RivetAnalysis RivetTune RivetAnalysis.so
insert RivetTune:Paths[0] .
insert RivetTune:Analyses[0] ATLAS_2010_S8918562
insert RivetTune:Analyses[0] STAR_2008_S7869363
insert RivetTune:Analyses[0] CMS_2011_S8978280
insert RivetTune:Analyses[0] PYTHIA_TUNING
insert PPGenerator:AnalysisHandlers[0] Logger
insert PPGenerator:AnalysisHandlers[0] RivetTune
set PPGenerator:EventHandler:LuminosityFunction:Energy 7000
set PPGenerator:DumpPeriod 0
cp PPGenerator PPTestTune
set PPGenerator:NumberOfEvents 10000
set PPTestTune:NumberOfEvents 100000
create ThePEG::LWHFactory LWHFactory LWHFactory.so
set LWHFactory:Suffix dat
set LWHFactory:StoreType flat
set PPTestTune:HistogramFactory LWHFactory
create DIPSY::PTAnalysis PTAnalysis PTAnalysis.so
insert PPTestTune:AnalysisHandlers[0] PTAnalysis
do PPGenerator:AddRndInterface /DIPSY/PPEventHandler:RMax 100 1.0 5.0 2.9 0.6
do PPGenerator:AddRndInterface /DIPSY/PPEventHandler:LambdaQCD 1 0.10 0.3 0.22 0.04
do PPGenerator:AddRndInterface /DIPSY/PPEventHandler:Emitter:PTScale 1 0.5 2.5 1.4 0.5
do PPGenerator:AddRndInterface /DIPSY/PPEventHandler:Emitter:PMinusOrdering 1 0.5 2.0 1.0 0.2
cp PPGenerator PPXSecGenerator
erase PPXSecGenerator:AnalysisHandlers[0]
erase PPXSecGenerator:AnalysisHandlers[0]
create ThePEG::Settings OnlyXSec
do OnlyXSec:set PPXSecGenerator:EventHandler:PreSamples 1000
insert PPXSecGenerator:DefaultObjects[0] OnlyXSec
set PPXSecGenerator:NumberOfEvents 0
cp OnlyXSec AddXSec
insert PPTestTune:DefaultObjects[0] AddXSec
create ThePEG::Settings Default
cp Default NoSwing
cp Default DefRope
do Default:set PPEventHandler:HadronizationHandler Frag8
do Default:set PPEventHandler:CascadeHandler AriadneCascade
do NoSwing:set PPEventHandler:HadronizationHandler Frag8Sw0
do NoSwing:set PPEventHandler:CascadeHandler AriadneNoSwing
do DefRope:set PPEventHandler:HadronizationHandler Frag8Rope
do DefRope:set PPEventHandler:CascadeHandler AriadneCascade
insert PPGenerator:DefaultObjects[0] Default
insert PPXSecGenerator:DefaultObjects[0] Default
insert PPTestTune:DefaultObjects[0] Default
cp Default NewSing
do NewSing:set PPEventHandler:EventFiller:Mode NewSingle
do NewSing:set PPTestTune:EventHandler:EventFiller:OnlyOnce true
do NewSing:set PPEventHandler:FudgeME 2
do NewSing:set PPEventHandler:XSecFn:SinFunction Average
cp Default NewSinF
do NewSinF:set PPEventHandler:XSecFn:SinFunction Average
cp Default NewSinS
do NewSinS:set PPEventHandler:XSecFn:SinFunction Scaled
cp Default EffPRel
do EffPRel:set PPEventHandler:EffectivePartonMode Relatives
cp Default DefaY7F
do DefaY7F:set PPGenerator:EventHandler:YFrametest 0.7
cp DefaY7F Def01Y7
do Def01Y7:set PPEventHandler:Swinger:Lambda 0.1
cp Default DefEven
do DefEven:set PPEventHandler:EventFiller:EffectiveWeights PlusEvenWeighted
cp Default DefSwL4
do DefSwL4:set PPEventHandler:Swinger:Lambda 4.0
cp Default DefSw01
do DefSw01:set PPEventHandler:Swinger:Lambda 0.1
cp Default DefFSGO
do DefFSGO:set FSOrdering:Generous Generous
do DefFSGO:set FSOrdering:OnlyOriginal OnlyOriginalEmissions
cp DefFSGO DefFSG2
do DefFSG2:set FSOrdering:Fudge 1.6
cp Default Shadows
do Shadows:set PPEventHandler:EffectivePartonMode Shadows
cp Default DefSing
do DefSing:set PPEventHandler:FudgeME 2
do DefSing:set PPTestTune:EventHandler:EventFiller:OnlyOnce true
do DefSing:set PPTestTune:EventHandler:EventFiller:SingleMother 1
cp DefSing DefComp
do DefComp:set PPTestTune:EventHandler:EventFiller:CompatMode 1
cp Default Shadow8
do Shadow8:set PPEventHandler:EffectivePartonMode Shadows
do Shadow8:set PPEventHandler:FudgeME 2
do Shadow8:set PPTestTune:EventHandler:EventFiller:OnlyOnce true
do Shadow8:set PPTestTune:EventHandler:EventFiller:SingleMother 1
do Shadow8:set stdEmitter:MinusOrderingMode OrderedShadow
do Shadow8:set stdXSec:IntOrdering ShadowOpen
cp Default Shadow9
do Shadow9:set PPEventHandler:EffectivePartonMode Shadows
do Shadow9:set PPEventHandler:FudgeME 2
do Shadow9:set PPTestTune:EventHandler:EventFiller:OnlyOnce true
do Shadow9:set PPTestTune:EventHandler:EventFiller:SingleMother 1
do Shadow9:set stdEmitter:MinusOrderingMode OrderedShadow
do Shadow9:set stdXSec:IntOrdering ShadowColour
cp Default ShadowA
do ShadowA:set PPEventHandler:EffectivePartonMode Shadows
do ShadowA:set PPEventHandler:FudgeME 2
do ShadowA:set PPTestTune:EventHandler:EventFiller:OnlyOnce true
do ShadowA:set PPTestTune:EventHandler:EventFiller:SingleMother 1
do ShadowA:set stdEmitter:MinusOrderingMode UnrderedShadow
do ShadowA:set stdXSec:IntOrdering ShadowColour
# cp ShadowA ShadowB the former is with new setEmissionMomentum (-DDIPSY::PlusEvo)
# cp ShadowA ShadowC the former with small bugfix?
cp Default ShadowD
do ShadowD:set PPEventHandler:EffectivePartonMode Shadows
do ShadowD:set PPEventHandler:FudgeME 2
do ShadowD:set PPTestTune:EventHandler:EventFiller:OnlyOnce false
do ShadowD:set PPTestTune:EventHandler:EventFiller:SingleMother 1
do ShadowD:set stdEmitter:MinusOrderingMode CutShadow
do ShadowD:set stdXSec:IntOrdering ShadowColourMax
cp Default ShadowE
do ShadowE:set PPEventHandler:EffectivePartonMode Shadows
do ShadowE:set PPEventHandler:FudgeME 2
do ShadowE:set PPTestTune:EventHandler:EventFiller:OnlyOnce false
do ShadowE:set PPTestTune:EventHandler:EventFiller:SingleMother 1
do ShadowE:set stdEmitter:MinusOrderingMode CutShadow
do ShadowE:set stdXSec:IntOrdering ShadowColourMax
do ShadowE:set stdXSec:RMax -1.0
cp Default ShadowF
do ShadowF:set PPEventHandler:EffectivePartonMode Shadows
do ShadowF:set PPEventHandler:FudgeME 2
do ShadowF:set PPTestTune:EventHandler:EventFiller:OnlyOnce false
do ShadowF:set PPTestTune:EventHandler:EventFiller:SingleMother 1
do ShadowF:set stdEmitter:MinusOrderingMode CutShadow
do ShadowF:set stdXSec:IntOrdering ShadowColourMax
do ShadowF:set stdXSec:SinFunction Scaled
do ShadowF:set stdXSec:RMax -1.0
cp Default ShadowG
do ShadowG:set PPEventHandler:EffectivePartonMode Shadows
do ShadowG:set PPEventHandler:FudgeME 2
do ShadowG:set PPTestTune:EventHandler:EventFiller:OnlyOnce false
do ShadowG:set PPTestTune:EventHandler:EventFiller:SingleMother 1
do ShadowG:set stdEmitter:MinusOrderingMode CutShadow
do ShadowG:set stdXSec:IntOrdering ShadowColourMax
do ShadowG:set stdXSec:PTScale 1.0
do ShadowG:set stdXSec:RMax -1.0
cp Default ShadowH
do ShadowH:set PPEventHandler:EffectivePartonMode Shadows
do ShadowH:set PPEventHandler:FudgeME 2
do ShadowH:set PPTestTune:EventHandler:EventFiller:OnlyOnce false
do ShadowH:set PPTestTune:EventHandler:EventFiller:SingleMother 1
do ShadowH:set stdEmitter:MinusOrderingMode CutShadow
do ShadowH:set stdXSec:IntOrdering ShadowColourMax
cp Default ShadowI
do ShadowI:set PPEventHandler:EffectivePartonMode Shadows
do ShadowI:set PPEventHandler:FudgeME 2
# do ShadowI:set PPTestTune:EventHandler:EventFiller:OnlyOnce false
do ShadowI:set PPTestTune:EventHandler:EventFiller:SingleMother 1
do ShadowI:set PPTestTune:EventHandler:PTScale -1
do ShadowI:set PPTestTune:EventHandler:FixedAlphaS -0.5
do ShadowI:set stdEmitter:MinusOrderingMode PtGen
do ShadowI:set stdXSec:IntOrdering ShadowColourMax
+cp Default ShadowJ
+do ShadowJ:set PPEventHandler:EffectivePartonMode Shadows
+do ShadowJ:set PPEventHandler:FudgeME 2
+do ShadowJ:set PPTestTune:EventHandler:EventFiller:SingleMother 1
+do ShadowJ:set PPTestTune:EventHandler:PTScale -1
+do ShadowJ:set PPTestTune:EventHandler:FixedAlphaS -0.5
+do ShadowJ:set stdEmitter:MinusOrderingMode PtGen
+do ShadowJ:set stdXSec:IntOrdering ShadowColourMax
+do ShadowJ:set stdXSec:SinFunction Scaled
+cp Default ShadowK
+do ShadowK:set PPEventHandler:EffectivePartonMode Shadows
+do ShadowK:set PPEventHandler:FudgeME 2
+do ShadowK:set PPTestTune:EventHandler:EventFiller:SingleMother 1
+do ShadowK:set PPTestTune:EventHandler:PTScale -1
+do ShadowK:set PPTestTune:EventHandler:FixedAlphaS -0.5
+do ShadowK:set stdEmitter:MinusOrderingMode CutShadow
+do ShadowK:set stdXSec:IntOrdering ShadowColourMax
+do ShadowK:set stdXSec:SinFunction Scaled
+
+cp Default ShadowL
+do ShadowL:set PPEventHandler:EffectivePartonMode Shadows
+do ShadowL:set PPEventHandler:FudgeME 2
+do ShadowL:set PPTestTune:EventHandler:EventFiller:SingleMother 1
+do ShadowL:set PPTestTune:EventHandler:PTScale -1
+do ShadowL:set PPTestTune:EventHandler:FixedAlphaS -0.5
+do ShadowL:set stdEmitter:MinusOrderingMode PtGen
+do ShadowL:set stdXSec:IntOrdering ShadowColourMax
+do ShadowL:set stdXSec:SinFunction Scaled
+do ShadowL:set stdEmitter:SplittingFunction FullAP
+
+cp Default ShadowM
+do ShadowM:set PPEventHandler:EffectivePartonMode Shadows
+do ShadowM:set PPEventHandler:FudgeME 2
+do ShadowM:set PPTestTune:EventHandler:EventFiller:SingleMother 1
+do ShadowM:set PPTestTune:EventHandler:PTScale -1
+do ShadowM:set PPTestTune:EventHandler:FixedAlphaS -0.5
+do ShadowM:set stdEmitter:MinusOrderingMode PtGen
+do ShadowM:set stdXSec:IntOrdering ShadowColourMax
+do ShadowM:set stdXSec:SinFunction Scaled
+do ShadowM:set stdEmitter:SplittingFunction FullAP
+do ShadowM:set PPTestTune:EventHandler:EventFiller:OnlyOnce true
+
+cp Default ShadowN
+do ShadowN:set PPEventHandler:EffectivePartonMode Shadows
+do ShadowN:set PPEventHandler:FudgeME 2
+do ShadowN:set PPTestTune:EventHandler:EventFiller:SingleMother 1
+do ShadowN:set PPTestTune:EventHandler:PTScale -1
+do ShadowN:set PPTestTune:EventHandler:FixedAlphaS -0.5
+do ShadowN:set stdEmitter:MinusOrderingMode PtGen
+do ShadowN:set stdXSec:IntOrdering ShadowColourMax
+do ShadowN:set stdXSec:SinFunction Scaled
+do ShadowN:set stdEmitter:SplittingFunction FullAP
+do ShadowN:set PPTestTune:EventHandler:EventFiller:OnlyOnce true
+
+cp Default ShadowO
+do ShadowO:set PPEventHandler:EffectivePartonMode Shadows
+do ShadowO:set PPEventHandler:FudgeME 2
+do ShadowO:set PPTestTune:EventHandler:EventFiller:SingleMother 1
+do ShadowO:set PPTestTune:EventHandler:PTScale -1
+do ShadowO:set PPTestTune:EventHandler:FixedAlphaS -0.5
+do ShadowO:set stdEmitter:MinusOrderingMode PtGen
+do ShadowO:set stdXSec:IntOrdering ShadowColourMax
+do ShadowO:set stdEmitter:SplittingFunction FullAP
+do ShadowO:set PPTestTune:EventHandler:EventFiller:OnlyOnce true
+
+cp Default ShadowP
+do ShadowP:set PPEventHandler:EffectivePartonMode Shadows
+do ShadowP:set PPEventHandler:FudgeME 2
+do ShadowP:set PPTestTune:EventHandler:EventFiller:SingleMother 1
+do ShadowP:set PPTestTune:EventHandler:PTScale -1
+do ShadowP:set PPTestTune:EventHandler:FixedAlphaS -0.5
+do ShadowP:set stdEmitter:MinusOrderingMode PtGen
+do ShadowP:set stdXSec:IntOrdering ShadowColourMax
+do ShadowP:set stdEmitter:SplittingFunction FullAP
+do ShadowP:set PPTestTune:EventHandler:EventFiller:OnlyOnce false
+
+cp Default ShadowQ
+do ShadowQ:set PPEventHandler:EffectivePartonMode Shadows
+do ShadowQ:set PPEventHandler:FudgeME 2
+do ShadowQ:set PPTestTune:EventHandler:EventFiller:SingleMother 1
+do ShadowQ:set PPTestTune:EventHandler:PTScale -1
+do ShadowQ:set PPTestTune:EventHandler:FixedAlphaS -0.5
+do ShadowQ:set stdEmitter:MinusOrderingMode PtGenZ
+do ShadowQ:set stdXSec:IntOrdering ShadowColourMax
+do ShadowQ:set stdEmitter:SplittingFunction FullAP
+do ShadowQ:set PPTestTune:EventHandler:EventFiller:OnlyOnce false
+
+cp Default ShadowR
+do ShadowR:set PPEventHandler:EffectivePartonMode Shadows
+do ShadowR:set PPEventHandler:FudgeME 2
+do ShadowR:set PPTestTune:EventHandler:EventFiller:SingleMother 1
+do ShadowR:set PPTestTune:EventHandler:PTScale -1
+do ShadowR:set PPTestTune:EventHandler:FixedAlphaS -1.0
+do ShadowR:set stdEmitter:MinusOrderingMode PtGenZ
+do ShadowR:set stdXSec:IntOrdering ShadowColourMax
+do ShadowR:set stdEmitter:SplittingFunction FullAP
+do ShadowR:set PPTestTune:EventHandler:EventFiller:OnlyOnce false
cp Default Defaupt
do Defaupt:set PPTestTune:EventHandler:EventFiller:PTCut 2.0
do Defaupt:set FSOrdering:PTMin 2.0
# Run for tuning
SAVERUNFSXD Default PPGenerator Default PPXSecGenerator
SAVERUNFSXD DefRope PPGenerator Default PPXSecGenerator
SAVERUNFSXD NoSwing PPGenerator Default PPXSecGenerator
SAVERUNFSXD NewSinF PPGenerator NewSinF PPXSecGenerator
SAVERUNFSXD NewSinS PPGenerator NewSinS PPXSecGenerator
SAVERUNFSXD NewSing PPGenerator NewSing PPXSecGenerator
SAVERUNFSXD EffPRel PPGenerator EffPRel PPXSecGenerator
SAVERUNFSXD DefaY7F PPGenerator DefaY7F PPXSecGenerator
SAVERUNFSXD Def01Y7 PPGenerator Def01Y7 PPXSecGenerator
SAVERUNFSXD DefEven PPGenerator DefEven PPXSecGenerator
SAVERUNFSXD DefSwL4 PPGenerator DefSwL4 PPXSecGenerator
SAVERUNFSXD DefSw01 PPGenerator DefSw01 PPXSecGenerator
SAVERUNFSXD DefFSGO PPGenerator Default PPXSecGenerator
SAVERUNFSXD DefFSG2 PPGenerator Default PPXSecGenerator
SAVERUNFSXD Shadows PPGenerator Shadows PPXSecGenerator
SAVERUNFSXD DefSing PPGenerator DefSing PPXSecGenerator
SAVERUNFSXD DefComp PPGenerator DefComp PPXSecGenerator
SAVERUNFSXD Shadow8 PPGenerator Shadow8 PPXSecGenerator
SAVERUNFSXD Shadow9 PPGenerator Shadow9 PPXSecGenerator
SAVERUNFSXD ShadowA PPGenerator ShadowA PPXSecGenerator
SAVERUNFSXD ShadowD PPGenerator ShadowD PPXSecGenerator
SAVERUNFSXD Defaupt PPGenerator Defaupt PPXSecGenerator
do PPGenerator:RemoveInterface /DIPSY/PPEventHandler:Emitter:PMinusOrdering
do PPGenerator:AddRndInterface /DIPSY/PPEventHandler:Emitter:RMax 1 1.0 5.0 2.9 0.6
do PPXSecGenerator:RemoveInterface /DIPSY/PPEventHandler:Emitter:PMinusOrdering
do PPXSecGenerator:AddRndInterface /DIPSY/PPEventHandler:Emitter:RMax 1 1.0 5.0 2.9 0.6
SAVERUNFSXD ShadowE PPGenerator ShadowE PPXSecGenerator
SAVERUNFSXD ShadowF PPGenerator ShadowF PPXSecGenerator
SAVERUNFSXD ShadowG PPGenerator ShadowG PPXSecGenerator
do PPGenerator:RemoveInterface /DIPSY/PPEventHandler:Emitter:RMax
do PPGenerator:AddRndInterface /DIPSY/PPEventHandler:BaryonSize 1 1.0 5.0 2.9 0.6
do PPXSecGenerator:RemoveInterface /DIPSY/PPEventHandler:Emitter:RMax
do PPXSecGenerator:AddRndInterface /DIPSY/PPEventHandler:BaryonSize 1 1.0 5.0 2.9 0.6
SAVERUNFSXD ShadowH PPGenerator ShadowH PPXSecGenerator
SAVERUNFSXD ShadowI PPGenerator ShadowI PPXSecGenerator
+do PPGenerator:AddRndInterface /DIPSY/PPEventHandler:Emitter:PTScale 1 1.5 2.5 1.0 0.5
+do PPXSecGenerator:AddRndInterface /DIPSY/PPEventHandler:Emitter:PTScale 1 1.5 2.5 1.0 0.5
+SAVERUNFSXD ShadowJ PPGenerator ShadowJ PPXSecGenerator
+SAVERUNFSXD ShadowK PPGenerator ShadowK PPXSecGenerator
+SAVERUNFSXD ShadowL PPGenerator ShadowL PPXSecGenerator
+SAVERUNFSXD ShadowM PPGenerator ShadowM PPXSecGenerator
+
+do PPGenerator:AddRndInterface /DIPSY/PPEventHandler:Emitter:PTScale 1 0.5 2.5 1.5 0.5
+do PPXSecGenerator:AddRndInterface /DIPSY/PPEventHandler:Emitter:PTScale 1 0.5 2.5 1.5 0.5
+do PPGenerator:RemoveInterface /DIPSY/PPEventHandler:RMax
+do PPGenerator:AddRndInterface /DIPSY/PPEventHandler:M0 100 0.5 2.0 0.8 0.6
+do PPXSecGenerator:RemoveInterface /DIPSY/PPEventHandler:RMax
+do PPXSecGenerator:AddRndInterface /DIPSY/PPEventHandler:M0 100 0.5 2.0 0.8 0.6
+SAVERUNFSXD ShadowN PPGenerator ShadowN PPXSecGenerator
+SAVERUNFSXD ShadowO PPGenerator ShadowO PPXSecGenerator
+SAVERUNFSXD ShadowP PPGenerator ShadowP PPXSecGenerator
+SAVERUNFSXD ShadowQ PPGenerator ShadowQ PPXSecGenerator
+SAVERUNFSXD ShadowR PPGenerator ShadowR PPXSecGenerator
+
+
# testing the tunes
SAVERUNTUNED Default PPTestTune
SAVERUNTUNED DefRope PPTestTune
SAVERUNTUNED NewSinF PPTestTune
SAVERUNTUNED NewSinS PPTestTune
SAVERUNTUNED NoSwing PPTestTune
SAVERUNTUNED NewSing PPTestTune
SAVERUNTUNED EffPRel PPTestTune
SAVERUNTUNED DefaY7F PPTestTune
SAVERUNTUNED Def01Y7 PPTestTune
SAVERUNTUNED DefEven PPTestTune
SAVERUNTUNED DefSwL4 PPTestTune
SAVERUNTUNED DefSw01 PPTestTune
SAVERUNTUNED DefFSGO PPTestTune
SAVERUNTUNED DefFSG2 PPTestTune
SAVERUNTUNED Shadows PPTestTune
SAVERUNTUNED DefSing PPTestTune
SAVERUNTUNED DefComp PPTestTune
SAVERUNTUNED Shadow8 PPTestTune
SAVERUNTUNED Shadow9 PPTestTune
SAVERUNTUNED ShadowA PPTestTune
SAVERUNTUNED ShadowD PPTestTune
SAVERUNTUNED ShadowE PPTestTune
SAVERUNTUNED ShadowF PPTestTune
SAVERUNTUNED ShadowG PPTestTune
SAVERUNTUNED ShadowH PPTestTune
SAVERUNTUNED ShadowI PPTestTune
+SAVERUNTUNED ShadowJ PPTestTune
+SAVERUNTUNED ShadowK PPTestTune
+SAVERUNTUNED ShadowL PPTestTune
+SAVERUNTUNED ShadowM PPTestTune
+SAVERUNTUNED ShadowN PPTestTune
+SAVERUNTUNED ShadowO PPTestTune
+SAVERUNTUNED ShadowP PPTestTune
+SAVERUNTUNED ShadowQ PPTestTune
+SAVERUNTUNED ShadowR PPTestTune
SAVERUNTUNED Defaupt PPTestTune
##### playground #####
erase PPTestTune:DefaultObjects[0]
set PPTestTune:DefaultObjects[0] Default
set PPEventHandler:LambdaQCD 0.22
set PPEventHandler:RMax 3.0
set stdEmitter:PMinusOrdering 1.0
set stdEmitter:PTScale 1.0
set PPGenerator:EventHandler:PreSamples 0
# set PPGenerator:EventHandler:PreSamples 0
set PPGenerator:EventHandler:EventFiller:DebugHist 1
set PPTestTune:NumberOfEvents 10000
saverun compare PPTestTune
set stdEmitter:PTScale 2
saverun compar6 PPTestTune
set stdEmitter:PTScale 1
set stdEmitter:PMinusOrdering 2.0
saverun compar5 PPTestTune
set stdEmitter:PMinusOrdering 1.0
set PPEventHandler:FudgeME 2
set PPTestTune:EventHandler:EventFiller:OnlyOnce true
set PPTestTune:EventHandler:EventFiller:SingleMother 1
saverun compar2 PPTestTune
set PPTestTune:EventHandler:EventFiller:CompatMode 1
saverun compar3 PPTestTune
set PPTestTune:EventHandler:EventFiller:CompatMode 0
set PPTestTune:EventHandler:EffectivePartonMode Relatives
saverun compar4 PPTestTune
set PPTestTune:EventHandler:EventFiller:OnlyOnce false
set PPEventHandler:FudgeME 1
set PPTestTune:EventHandler:EventFiller:SingleMother 0
set PPTestTune:EventHandler:EventFiller:CompatMode 0
set PPTestTune:EventHandler:EffectivePartonMode Shadows
saverun shadows PPTestTune
set PPEventHandler:FudgeME 2
set PPTestTune:EventHandler:EventFiller:OnlyOnce true
set PPTestTune:EventHandler:EventFiller:SingleMother 1
saverun shadow2 PPTestTune
saverun shadow3 PPTestTune
set stdEmitter:MinusOrderingMode EffectiveParton
saverun shadow4 PPTestTune
set stdEmitter:MinusOrderingMode TrueShadow
saverun shadow6 PPTestTune
set stdEmitter:MinusOrderingMode OrderedShadow
saverun shadow7 PPTestTune
set stdXSec:IntOrdering ShadowOpen
saverun shadow8 PPTestTune
set stdXSec:IntOrdering ShadowColour
set PPTestTune:NumberOfEvents 10000
saverun shadow9 PPTestTune
set PPTestTune:EventHandler:EventFiller:PTCut 2.0
set FSOrdering:PTMin 2.0
saverun shadow11 PPTestTune
set PPTestTune:EventHandler:EventFiller:PTCut 4.0
set FSOrdering:PTMin 4.0
saverun shadow12 PPTestTune
set PPTestTune:EventHandler:EventFiller:PTCut 1.0
set FSOrdering:PTMin 1.0
set stdEmitter:MinusOrderingMode UnorderedShadow
saverun shadow14 PPTestTune
set stdXSec:IntOrdering ShadowColourMax
saverun shadow15 PPTestTune
saverun shadow16 PPTestTune
saverun shadow17 PPTestTune
set stdEmitter:PlusInflation 2.0
saverun shadow18 PPTestTune
set stdEmitter:PlusInflation 1.0
set stdEmitter:MinusOrderingMode CutShadow
# erase PPTestTune:AnalysisHandlers[0]
# erase PPTestTune:AnalysisHandlers[0]
# erase PPTestTune:AnalysisHandlers[0]
# set PPTestTune:EventHandler:CascadeHandler NULL
# set PPTestTune:EventHandler:HadronizationHandler NULL
# set PPTestTune:EventHandler:DecayHandler NULL
# erase PPTestTune:DefaultObjects[0]
saverun shadow21 PPTestTune
set PPTestTune:EventHandler:EventFiller:OnlyOnce false
saverun shadow23 PPTestTune
set stdEmitter:SizeFactor 1.0
saverun shadow30 PPTestTune
set stdEmitter:SizeFactor 2.0
# set stdEmitter:MinusOrderingMode PtGen
# saverun shadow32 PPTestTune
set stdEmitter:MinusOrderingMode CutShadow
set stdXSec:KTPow 2.0
set stdXSec:KT0 1.0
saverun shadow29 PPTestTune
set stdEmitter:SizeFactor 1.0
saverun shadow31 PPTestTune
set stdEmitter:SizeFactor 2.0
set stdXSec:KTPow 0.0
set stdEmitter:PMinusOrdering 2.0
saverun shadow25 PPTestTune
set stdEmitter:PMinusOrdering 1.0
set stdEmitter:PTScale 2.0
saverun shadow26 PPTestTune
set stdXSec:PTScale 1
saverun shadow28 PPTestTune
set stdXSec:PTScale 0
set stdXSec:SinFunction Scaled
saverun shadow27 PPTestTune
set stdEmitter:PTScale 1.0
set stdXSec:SinFunction Exact
set PPTestTune:EventHandler:EventFiller:OnlyOnce true
set PPTestTune:EventHandler:EffectivePartonMode NewShadows
saverun shadow22 PPTestTune
set PPTestTune:EventHandler:EventFiller:OnlyOnce false
saverun shadow24 PPTestTune
set PPTestTune:EventHandler:EventFiller:OnlyOnce true
set PPTestTune:EventHandler:EffectivePartonMode Shadows
saverun shadow23 PPTestTune
set stdEmitter:PTScale 2
saverun shadow33 PPTestTune
set PPTestTune:EventHandler:PTScale -1
+set PPTestTune:NumberOfEvents 10000
saverun shadow34 PPTestTune
set stdEmitter:MinusOrderingMode PtGen
saverun shadow35 PPTestTune
+set stdEmitter:SplittingFunction FullAP
+saverun shadow36 PPTestTune
+set stdEmitter:MinusOrderingMode PtGenZ
+saverun shadow37 PPTestTune
+set PPTestTune:EventHandler:EventFiller:OnlyOnce false
+set PPTestTune:EventHandler:FixedAlphaS -0.5
+set PPTestTune:EventHandler:PTScale -1
+saverun shadow40 PPTestTune
+saverun shadow41 PPTestTune
+saverun shadow42 PPTestTune
+set stdEmitter:SplittingFunction FullAPkTsup
+saverun shadow43 PPTestTune
+set stdEmitter:SplittingFunction FullAPkTsup3
+saverun shadow44 PPTestTune
+set stdEmitter:SplittingFunction FullAPkTsup4
+saverun shadow45 PPTestTune
+set stdEmitter:SplittingFunction FullAPkTsup4
+saverun shadow45 PPTestTune
+set stdEmitter:SplittingFunction FullAPkTsupm4
+saverun shadow48 PPTestTune
+set stdEmitter:SplittingFunction FullAP
+set stdEmitter:PTScale 1
+saverun shadow46 PPTestTune
+set stdEmitter:PTScale 0.5
+saverun shadow47 PPTestTune
+set stdEmitter:PTScale 1
+set stdEmitter:RMax 0.1
+saverun shadow49 PPTestTune
+set stdEmitter:RMax 0
+
+
+set stdXSec:SinFunction Scaled
+saverun shadow38 PPTestTune
+set stdXSec:SinFunction Exact
+set PPTestTune:EventHandler:EventFiller:OnlyOnce false
+saverun shadow39 PPTestTune
+set PPTestTune:EventHandler:EventFiller:OnlyOnce true
+set stdEmitter:SplittingFunction SmallX
set stdEmitter:MinusOrderingMode CutShadow
set PPTestTune:EventHandler:PTScale 2
set stdEmitter:PTScale 1
set stdXSec:IntOrdering ShadowColour
set stdEmitter:MinusOrderingMode OrderedShadow
set PPTestTune:NumberOfEvents 2
set PPGenerator:EventHandler:PreSamples 10000
saverun shadow10 PPTestTune
set stdEmitter:MinusOrderingMode UnorderedShadow
saverun shadow13 PPTestTune
set stdXSec:IntOrdering ShadowColourMax
saverun shadow19 PPTestTune
set stdEmitter:PlusInflation 10.0
saverun shadow20 PPTestTune
set stdEmitter:PlusInflation 1.0
set stdEmitter:MinusOrderingMode OrderedShadow
set PPGenerator:EventHandler:PreSamples 0
set PPTestTune:NumberOfEvents 10000
set stdXSec:IntOrdering VeryOpen
set stdEmitter:MinusOrderingMode EffectivePT
saverun shadow5 PPTestTune
set PPEventHandler:FudgeME 1
set PPTestTune:EventHandler:EventFiller:OnlyOnce false
set PPTestTune:EventHandler:EventFiller:SingleMother 0
set PPTestTune:EventHandler:EffectivePartonMode Colours
set PPTestTune:EventHandler:EventFiller:Mode NewSingle
saverun compsng PPTestTune
set PPEventHandler:FudgeME 2
set PPTestTune:EventHandler:EventFiller:OnlyOnce true
set PPTestTune:EventHandler:EventFiller:SingleMother 1
saverun compsn2 PPTestTune
set PPTestTune:EventHandler:EventFiller:CompatMode 1
saverun compsn3 PPTestTune
set PPEventHandler:FudgeME 1
set PPTestTune:EventHandler:EventFiller:OnlyOnce false
set PPTestTune:EventHandler:EventFiller:SingleMother 0
set PPTestTune:EventHandler:EventFiller:CompatMode 0
diff --git a/DIPSY/PPTune/PPTuneFS00.weights b/DIPSY/PPTune/PPTuneFS00.weights
--- a/DIPSY/PPTune/PPTuneFS00.weights
+++ b/DIPSY/PPTune/PPTuneFS00.weights
@@ -1,51 +1,51 @@
# /ATLAS_2010_S8918562/d01-x01-y01 1.0
# /ATLAS_2010_S8918562/d03-x01-y01 1.0
# /ATLAS_2010_S8918562/d04-x01-y01 2.0
# /ATLAS_2010_S8918562/d05-x01-y01 2.0
/ATLAS_2010_S8918562/d06-x01-y01 12.0
/ATLAS_2010_S8918562/d07-x01-y01 12.0
# /ATLAS_2010_S8918562/d08-x01-y01 1.0
# /ATLAS_2010_S8918562/d10-x01-y01 1.0
# /ATLAS_2010_S8918562/d11-x01-y01 2.0
# /ATLAS_2010_S8918562/d12-x01-y01 2.0
/ATLAS_2010_S8918562/d13-x01-y01 12.0
/ATLAS_2010_S8918562/d14-x01-y01 12.0
-/ATLAS_2010_S8918562/d15-x01-y01:5.5:200.0 2.0
-/ATLAS_2010_S8918562/d17-x01-y01:5.5:200.0 2.0
-/ATLAS_2010_S8918562/d18-x01-y01:5.5:200.0 2.0
-/ATLAS_2010_S8918562/d19-x01-y01:5.5:200.0 2.0
-/ATLAS_2010_S8918562/d20-x01-y01 6.0
-/ATLAS_2010_S8918562/d21-x01-y01 6.0
+# /ATLAS_2010_S8918562/d15-x01-y01:5.5:200.0 2.0
+# /ATLAS_2010_S8918562/d17-x01-y01:5.5:200.0 2.0
+# /ATLAS_2010_S8918562/d18-x01-y01:5.5:200.0 2.0
+# /ATLAS_2010_S8918562/d19-x01-y01:5.5:200.0 2.0
+/ATLAS_2010_S8918562/d20-x01-y01 10.0
+/ATLAS_2010_S8918562/d21-x01-y01 10.0
/ATLAS_2010_S8918562/d22-x01-y01:5.5:200.0 1.0
/ATLAS_2010_S8918562/d23-x01-y01:5.5:200.0 1.0
/ATLAS_2010_S8918562/d24-x01-y01:5.5:200.0 2.0
/ATLAS_2010_S8918562/d25-x01-y01:5.5:200.0 2.0
/ATLAS_2010_S8918562/d26-x01-y01 2.0
/ATLAS_2010_S8918562/d27-x01-y01 2.0
-# /ATLAS_2010_S8918562/d28-x01-y01 1.0
-# /ATLAS_2010_S8918562/d29-x01-y01 1.0
+/ATLAS_2010_S8918562/d28-x01-y01 2.0
+/ATLAS_2010_S8918562/d29-x01-y01 2.0
/ATLAS_2010_S8918562/d30-x01-y01 2.0
/ATLAS_2010_S8918562/d31-x01-y01 2.0
-# /ATLAS_2010_S8918562/d32-x01-y01 1.0
-# /ATLAS_2010_S8918562/d33-x01-y01 1.0
-# /ATLAS_2010_S8918562/d34-x01-y01 1.0
-# /ATLAS_2010_S8918562/d35-x01-y01 1.0
-# /ATLAS_2010_S8918562/d36-x01-y01 1.0
-# /ATLAS_2010_S8918562/d37-x01-y01 1.0
-# /ATLAS_2010_S8918562/d38-x01-y01 1.0
-# /ATLAS_2010_S8918562/d39-x01-y01 1.0
+/ATLAS_2010_S8918562/d32-x01-y01 1.0
+/ATLAS_2010_S8918562/d33-x01-y01 1.0
+/ATLAS_2010_S8918562/d34-x01-y01 1.0
+/ATLAS_2010_S8918562/d35-x01-y01 1.0
+/ATLAS_2010_S8918562/d36-x01-y01 1.0
+/ATLAS_2010_S8918562/d37-x01-y01 1.0
+/ATLAS_2010_S8918562/d38-x01-y01 1.0
+/ATLAS_2010_S8918562/d39-x01-y01 1.0
/TOTALXSEC/d01-x01-y01 100.0
/TOTALXSEC/d01-x01-y02 100.0
# /TOTALXSEC/d01-x81-y01 20.0
# /TOTALXSEC/d01-x81-y02 20.0
/TOTALXSEC/d02-x01-y01 100.0
/TOTALXSEC/d02-x01-y02 100.0
# /TOTALXSEC/d02-x81-y01 20.0
# /TOTALXSEC/d02-x81-y02 20.0
/TOTALXSEC/d03-x01-y02 100.0
# /TOTALXSEC/d03-x81-y02 20.0
/TOTALXSEC/d04-x01-y01 100.0
# /TOTALXSEC/d04-x81-y01 20.0
/STAR_2008_S7869363/d01-x01-y01:5.5:200.0 1.0
# /STAR_2008_S7869363/d02-x01-y01 0.1
# /STAR_2008_S7869363/d02-x01-y02 0.1
diff --git a/DIPSY/PPTune/PPTuneFS09.weights b/DIPSY/PPTune/PPTuneFS09.weights
--- a/DIPSY/PPTune/PPTuneFS09.weights
+++ b/DIPSY/PPTune/PPTuneFS09.weights
@@ -1,48 +1,48 @@
# /ATLAS_2010_S8918562/d01-x01-y01 1.0
# /ATLAS_2010_S8918562/d03-x01-y01 1.0
#/ATLAS_2010_S8918562/d04-x01-y01 4.0
# /ATLAS_2010_S8918562/d05-x01-y01 2.0
/ATLAS_2010_S8918562/d06-x01-y01 24.0
# /ATLAS_2010_S8918562/d07-x01-y01 6.0
# /ATLAS_2010_S8918562/d08-x01-y01 1.0
# /ATLAS_2010_S8918562/d10-x01-y01 1.0
#/ATLAS_2010_S8918562/d11-x01-y01 4.0
# /ATLAS_2010_S8918562/d12-x01-y01 2.0
/ATLAS_2010_S8918562/d13-x01-y01 24.0
# /ATLAS_2010_S8918562/d14-x01-y01 6.0
-/ATLAS_2010_S8918562/d15-x01-y01:5.5:200.0 4.0
+# /ATLAS_2010_S8918562/d15-x01-y01:5.5:200.0 4.0
# /ATLAS_2010_S8918562/d17-x01-y01 1.0
-/ATLAS_2010_S8918562/d18-x01-y01:5.5:200.0 4.0
+# /ATLAS_2010_S8918562/d18-x01-y01:5.5:200.0 4.0
# /ATLAS_2010_S8918562/d19-x01-y01 2.0
-/ATLAS_2010_S8918562/d20-x01-y01 12.0
+/ATLAS_2010_S8918562/d20-x01-y01 20.0
# /ATLAS_2010_S8918562/d21-x01-y01 6.0
/ATLAS_2010_S8918562/d22-x01-y01:5.5:200.0 2.0
# /ATLAS_2010_S8918562/d23-x01-y01 1.0
/ATLAS_2010_S8918562/d24-x01-y01:5.5:200.0 4.0
# /ATLAS_2010_S8918562/d25-x01-y01 2.0
/ATLAS_2010_S8918562/d26-x01-y01 4.0
# /ATLAS_2010_S8918562/d27-x01-y01 2.0
-# /ATLAS_2010_S8918562/d28-x01-y01 1.0
+/ATLAS_2010_S8918562/d28-x01-y01 4.0
# /ATLAS_2010_S8918562/d29-x01-y01 1.0
/ATLAS_2010_S8918562/d30-x01-y01 4.0
# /ATLAS_2010_S8918562/d31-x01-y01 2.0
-# /ATLAS_2010_S8918562/d32-x01-y01 1.0
+/ATLAS_2010_S8918562/d32-x01-y01 2.0
# /ATLAS_2010_S8918562/d33-x01-y01 1.0
-# /ATLAS_2010_S8918562/d34-x01-y01 1.0
+/ATLAS_2010_S8918562/d34-x01-y01 2.0
# /ATLAS_2010_S8918562/d35-x01-y01 1.0
-# /ATLAS_2010_S8918562/d36-x01-y01 1.0
+/ATLAS_2010_S8918562/d36-x01-y01 2.0
# /ATLAS_2010_S8918562/d37-x01-y01 1.0
-# /ATLAS_2010_S8918562/d38-x01-y01 1.0
+/ATLAS_2010_S8918562/d38-x01-y01 2.0
# /ATLAS_2010_S8918562/d39-x01-y01 1.0
/TOTALXSEC/d01-x01-y01 100.0
/TOTALXSEC/d01-x01-y02 100.0
# /TOTALXSEC/d01-x81-y01 20.0
# /TOTALXSEC/d01-x81-y02 20.0
/TOTALXSEC/d02-x01-y01 100.0
/TOTALXSEC/d02-x01-y02 100.0
# /TOTALXSEC/d02-x81-y01 20.0
# /TOTALXSEC/d02-x81-y02 20.0
/TOTALXSEC/d03-x01-y02 100.0
# /TOTALXSEC/d03-x81-y02 20.0
/TOTALXSEC/d04-x01-y01 100.0
# /TOTALXSEC/d04-x81-y01 20.0
diff --git a/DIPSY/PPTune/PPTuneFS28.weights b/DIPSY/PPTune/PPTuneFS28.weights
--- a/DIPSY/PPTune/PPTuneFS28.weights
+++ b/DIPSY/PPTune/PPTuneFS28.weights
@@ -1,57 +1,62 @@
# /ATLAS_2010_S8918562/d01-x01-y01 1.0
# /ATLAS_2010_S8918562/d03-x01-y01 1.0
# /ATLAS_2010_S8918562/d04-x01-y01 4.0
# /PYTHIA_TUNING/d04-x01-y01 0.5
# /ATLAS_2010_S8918562/d05-x01-y01 2.0
-#/ATLAS_2010_S8918562/d06-x01-y01 12.0
+# /ATLAS_2010_S8918562/d06-x01-y01 12.0
/PYTHIA_TUNING/d06-x01-y01 8.0
# /ATLAS_2010_S8918562/d07-x01-y01 6.0
# /ATLAS_2010_S8918562/d08-x01-y01 1.0
# /ATLAS_2010_S8918562/d10-x01-y01 1.0
#/ATLAS_2010_S8918562/d11-x01-y01 4.0
# /PYTHIA_TUNING/d11-x01-y01 0.5
# /ATLAS_2010_S8918562/d12-x01-y01 2.0
#/ATLAS_2010_S8918562/d13-x01-y01 12.0
/PYTHIA_TUNING/d13-x01-y01 8.0
# /ATLAS_2010_S8918562/d14-x01-y01 6.0
# /ATLAS_2010_S8918562/d15-x01-y01 1.0
# /ATLAS_2010_S8918562/d17-x01-y01 1.0
# /ATLAS_2010_S8918562/d18-x01-y01 4.0
-/PYTHIA_TUNING/d18-x01-y01:5.5:200.0 2.0
+# /PYTHIA_TUNING/d18-x01-y01:5.5:200.0 2.0
# /ATLAS_2010_S8918562/d19-x01-y01 2.0
# /ATLAS_2010_S8918562/d20-x01-y01 12.0
-/PYTHIA_TUNING/d20-x01-y01:5.5:200.0 8.0
+/PYTHIA_TUNING/d20-x01-y01:5.5:200.0 10.0
# /ATLAS_2010_S8918562/d21-x01-y01 6.0
-# /ATLAS_2010_S8918562/d22-x01-y01 1.0
+/ATLAS_2010_S8918562/d22-x01-y01 4.0
# /ATLAS_2010_S8918562/d23-x01-y01 1.0
# /ATLAS_2010_S8918562/d24-x01-y01 4.0
-/PYTHIA_TUNING/d24-x01-y01:5.5:200.0 2.0
+/PYTHIA_TUNING/d24-x01-y01:5.5:200.0 4.0
# /ATLAS_2010_S8918562/d25-x01-y01 2.0
#/ATLAS_2010_S8918562/d26-x01-y01 4.0
-/PYTHIA_TUNING/d26-x01-y01 2.0
+/PYTHIA_TUNING/d26-x01-y01 4.0
# /ATLAS_2010_S8918562/d27-x01-y01 2.0
# /ATLAS_2010_S8918562/d28-x01-y01 1.0
+/PYTHIA_TUNING/d30-x01-y01 2.0
# /ATLAS_2010_S8918562/d29-x01-y01 1.0
# /ATLAS_2010_S8918562/d30-x01-y01 4.0
/PYTHIA_TUNING/d30-x01-y01 2.0
# /ATLAS_2010_S8918562/d31-x01-y01 2.0
# /ATLAS_2010_S8918562/d32-x01-y01 1.0
+/PYTHIA_TUNING/d32-x01-y01 2.0
# /ATLAS_2010_S8918562/d33-x01-y01 1.0
# /ATLAS_2010_S8918562/d34-x01-y01 1.0
+/PYTHIA_TUNING/d34-x01-y01 2.0
# /ATLAS_2010_S8918562/d35-x01-y01 1.0
# /ATLAS_2010_S8918562/d36-x01-y01 1.0
+/PYTHIA_TUNING/d36-x01-y01 2.0
# /ATLAS_2010_S8918562/d37-x01-y01 1.0
# /ATLAS_2010_S8918562/d38-x01-y01 1.0
+/PYTHIA_TUNING/d38-x01-y01 2.0
# /ATLAS_2010_S8918562/d39-x01-y01 1.0
/TOTALXSEC/d01-x01-y01 100.0
/TOTALXSEC/d01-x01-y02 100.0
# /TOTALXSEC/d01-x81-y01 20.0
# /TOTALXSEC/d01-x81-y02 20.0
/TOTALXSEC/d02-x01-y01 100.0
/TOTALXSEC/d02-x01-y02 100.0
# /TOTALXSEC/d02-x81-y01 20.0
# /TOTALXSEC/d02-x81-y02 20.0
/TOTALXSEC/d03-x01-y02 100.0
# /TOTALXSEC/d03-x81-y02 20.0
/TOTALXSEC/d04-x01-y01 100.0
# /TOTALXSEC/d04-x81-y01 20.0
diff --git a/DIPSY/PPTune/PPTuneFS70.weights b/DIPSY/PPTune/PPTuneFS70.weights
--- a/DIPSY/PPTune/PPTuneFS70.weights
+++ b/DIPSY/PPTune/PPTuneFS70.weights
@@ -1,48 +1,48 @@
# /ATLAS_2010_S8918562/d01-x01-y01 1.0
# /ATLAS_2010_S8918562/d03-x01-y01 1.0
# /ATLAS_2010_S8918562/d04-x01-y01 2.0
# /ATLAS_2010_S8918562/d05-x01-y01 4.0
# /ATLAS_2010_S8918562/d06-x01-y01 6.0
/ATLAS_2010_S8918562/d07-x01-y01 24.0
# /ATLAS_2010_S8918562/d08-x01-y01 1.0
# /ATLAS_2010_S8918562/d10-x01-y01 1.0
# /ATLAS_2010_S8918562/d11-x01-y01 2.0
# /ATLAS_2010_S8918562/d12-x01-y01 4.0
# /ATLAS_2010_S8918562/d13-x01-y01 6.0
/ATLAS_2010_S8918562/d14-x01-y01 24.0
# /ATLAS_2010_S8918562/d15-x01-y01 1.0
-/ATLAS_2010_S8918562/d17-x01-y01:5.5:200.0 4.0
+#/ATLAS_2010_S8918562/d17-x01-y01:5.5:200.0 4.0
# /ATLAS_2010_S8918562/d18-x01-y01 2.0
-/ATLAS_2010_S8918562/d19-x01-y01:5.5:200.0 4.0
+# /ATLAS_2010_S8918562/d19-x01-y01:5.5:200.0 4.0
# /ATLAS_2010_S8918562/d20-x01-y01 6.0
-/ATLAS_2010_S8918562/d21-x01-y01 12.0
+/ATLAS_2010_S8918562/d21-x01-y01 20.0
# /ATLAS_2010_S8918562/d22-x01-y01 1.0
/ATLAS_2010_S8918562/d23-x01-y01:5.5:200.0 2.0
# /ATLAS_2010_S8918562/d24-x01-y01 2.0
/ATLAS_2010_S8918562/d25-x01-y01:5.5:200.0 4.0
# /ATLAS_2010_S8918562/d26-x01-y01 2.0
/ATLAS_2010_S8918562/d27-x01-y01 4.0
# /ATLAS_2010_S8918562/d28-x01-y01 1.0
-# /ATLAS_2010_S8918562/d29-x01-y01 1.0
+/ATLAS_2010_S8918562/d29-x01-y01 4.0
# /ATLAS_2010_S8918562/d30-x01-y01 2.0
/ATLAS_2010_S8918562/d31-x01-y01 4.0
# /ATLAS_2010_S8918562/d32-x01-y01 1.0
-# /ATLAS_2010_S8918562/d33-x01-y01 1.0
+/ATLAS_2010_S8918562/d33-x01-y01 2.0
# /ATLAS_2010_S8918562/d34-x01-y01 1.0
-# /ATLAS_2010_S8918562/d35-x01-y01 1.0
+/ATLAS_2010_S8918562/d35-x01-y01 2.0
# /ATLAS_2010_S8918562/d36-x01-y01 1.0
-# /ATLAS_2010_S8918562/d37-x01-y01 1.0
+/ATLAS_2010_S8918562/d37-x01-y01 2.0
# /ATLAS_2010_S8918562/d38-x01-y01 1.0
-# /ATLAS_2010_S8918562/d39-x01-y01 1.0
+/ATLAS_2010_S8918562/d39-x01-y01 2.0
/TOTALXSEC/d01-x01-y01 100.0
/TOTALXSEC/d01-x01-y02 100.0
# /TOTALXSEC/d01-x81-y01 20.0
# /TOTALXSEC/d01-x81-y02 20.0
/TOTALXSEC/d02-x01-y01 100.0
/TOTALXSEC/d02-x01-y02 100.0
# /TOTALXSEC/d02-x81-y01 20.0
# /TOTALXSEC/d02-x81-y02 20.0
/TOTALXSEC/d03-x01-y02 100.0
# /TOTALXSEC/d03-x81-y02 20.0
/TOTALXSEC/d04-x01-y01 100.0
# /TOTALXSEC/d04-x81-y01 20.0
diff --git a/DIPSY/PPTune/profsum.pl b/DIPSY/PPTune/profsum.pl
--- a/DIPSY/PPTune/profsum.pl
+++ b/DIPSY/PPTune/profsum.pl
@@ -1,50 +1,95 @@
#!/usr/bin/perl -w
use strict;
while ( @ARGV ) {
print "** $ARGV[0] **\n";
open(PIPE, "prof-showminresults $ARGV[0]|")
or die "prof-showminresults failed";
my $file;
if ( $ARGV[0] =~ /(\w+).prof\// ) {
$file = "$1.prin";
open(FILE, ">>$file") or die "Could not open $file!";
print FILE "# Tuning from $ARGV[0]\n"
}
my $sum = 0.0;
my $sum2 = 0.0;
my $nrun = 0;
my $finish = 0;
+ my %params;
+ my @psum;
+ my @psum2;
+ my @pname;
+ my $nparams = 0;
+ my @xy;
while ( <PIPE> ) {
if ( /Goodness of fit\/Ndf:\s+(\S+)/ ) {
$sum += $1;
$sum2 += $1*$1;
++$nrun;
}
+ elsif ( /^Param/ ) {
+ my @val;
+ my $ip = 0;
+ while ( <PIPE> ) {
+ if ( /(\S+)\s+(\S+)/ ) {
+ if ( !exists($params{$1}) ) {
+ $params{$1} = $nparams++;
+ push @psum, 0.0;
+ push @psum2, 0.0;
+# push @xy, 0.0;
+ push @pname, $1;
+ for ( my $i = 0; $i< $ip; ++$i ) {
+ $xy[$ip][$i] = 0.0;
+ }
+ }
+ $val[$ip] = $2;
+ $psum[$params{$1}] += $2;
+ $psum2[$params{$1}] += $2*$2;
+ for ( my $i = 0; $i< $ip; ++$i ) {
+ $xy[$ip][$i] += $val[$ip]*$val[$i];
+ }
+ ++$ip;
+ } else {
+ last;
+ }
+ }
+ }
elsif ( /Summary of \d+ minimization results:/ ) {
$finish = 1;
}
elsif ( $finish && /\S+/ ) {
print;
my ( $par, $val ) = split;
print FILE "set $par $val\n" if $file;
}
}
if ( $nrun > 0 ) {
$sum /= $nrun;
$sum2 /= $nrun;
- print "Chi2/Ndf: ", $sum, " (", sqrt($sum2 - $sum*$sum), ")\n";
+ print "Chi2/Ndf: ", $sum, " (", sqrt($sum2 - $sum*$sum), ")\n\n";
+ for ( my $ip = 0; $ip < $nparams; ++$ip ) {
+ $psum[$ip] /= $nrun;
+ $psum2[$ip] = sqrt($psum2[$ip]/$nrun - $psum[$ip]*$psum[$ip]);
+ printf("%-30s %8.3f %8.3f ", $pname[$ip], $psum[$ip], $psum2[$ip]);
+ for ( my $i = 0; $i< $ip; ++$i ) {
+ my $v = $xy[$ip][$i];
+ $v = ($v/$nrun - $psum[$ip]*$psum[$i])/
+ ($psum2[$ip]*$psum2[$i]);
+ printf(" %8.3f", $v);
+ }
+ print "\n";
+ }
}
print "-- $ARGV[0] --\n\n";
shift @ARGV;
}
diff --git a/DIPSY/ParticleInfo.cc b/DIPSY/ParticleInfo.cc
--- a/DIPSY/ParticleInfo.cc
+++ b/DIPSY/ParticleInfo.cc
@@ -1,56 +1,59 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the ParticleInfo class.
//
#include "ParticleInfo.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 "Dipole.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace DIPSY;
-ParticleInfo::ParticleInfo(tcPartonPtr p): theParton(p) {}
+ParticleInfo::ParticleInfo(tcPartonPtr p)
+ : ColourInfo(p->dipoles().second? p->dipoles().second->colour() + 1: 0,
+ p->dipoles().first? p->dipoles().first->colour() + 1: 0), theParton(p) {}
ParticleInfo::~ParticleInfo() {}
tcPartonPtr ParticleInfo::getParton(const Particle & particle) {
for ( int i = 0, N = particle.getInfo().size(); i < N; ++i )
if ( const ParticleInfo * pin =
dynamic_cast<const ParticleInfo *>(particle.getInfo()[i].operator->()) )
return pin->parton();
return tcPartonPtr();
}
void ParticleInfo::persistentOutput(PersistentOStream & os) const {
os << theParton;
}
void ParticleInfo::persistentInput(PersistentIStream & is, int) {
is >> theParton;
}
// *** Attention *** The following static variable is needed for the type
// description system in ThePEG. Please check that the template arguments
// are correct (the class and its base class), and that the constructor
// arguments are correct (the class name and the name of the dynamically
// loadable library where the class implementation can be found).
-DescribeClass<ParticleInfo,ThePEG::EventInfoBase>
+DescribeClass<ParticleInfo,Ariadne5::ColourInfo>
describeDIPSYParticleInfo("DIPSY::ParticleInfo", "ParticleInfo.so");
void ParticleInfo::Init() {
static ClassDocumentation<ParticleInfo> documentation
("There is no documentation for the ParticleInfo class");
}
diff --git a/DIPSY/ParticleInfo.h b/DIPSY/ParticleInfo.h
--- a/DIPSY/ParticleInfo.h
+++ b/DIPSY/ParticleInfo.h
@@ -1,95 +1,94 @@
// -*- C++ -*-
#ifndef DIPSY_ParticleInfo_H
#define DIPSY_ParticleInfo_H
//
// This is the declaration of the ParticleInfo class.
//
-#include "ThePEG/EventRecord/EventInfoBase.h"
-#include "ThePEG/EventRecord/Particle.h"
+#include "Ariadne/Config/ColourInfo.h"
#include "Parton.h"
namespace DIPSY {
using namespace ThePEG;
/**
* Here is the documentation of the ParticleInfo class.
*/
-class ParticleInfo: public ThePEG::EventInfoBase {
+class ParticleInfo: public Ariadne5::ColourInfo {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
ParticleInfo(tcPartonPtr p = tcPartonPtr());
/**
* The destructor.
*/
virtual ~ParticleInfo();
//@}
public:
/**
* Return the parton from which the particle was created.
*/
tcPartonPtr parton() const {
return theParton;
}
/**
* Return the parton from which the given particle was created.
*/
static tcPartonPtr getParton(const Particle & particle);
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 DIPSY::Parton from which the particle was created.
*/
cPartonPtr theParton;
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
ParticleInfo & operator=(const ParticleInfo &);
};
}
#endif /* DIPSY_ParticleInfo_H */
diff --git a/DIPSY/RealParton.cc b/DIPSY/RealParton.cc
--- a/DIPSY/RealParton.cc
+++ b/DIPSY/RealParton.cc
@@ -1,1712 +1,1712 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the RealParton class.
//
#include "Dipole.h"
#include "RealParton.h"
#include "RealPartonState.h"
#include "DipoleEventHandler.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Utilities/Current.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Utilities/Debug.h"
#include "ThePEG/Utilities/DebugItem.h"
#include "ThePEG/Utilities/Throw.h"
#include <iostream>
using namespace DIPSY;
RealParton::RealParton(tPartonPtr p):
keep(NO), cKeep(NO), interacting(DipolePtr()), cInteracting(DipolePtr()), firstInt(false),
secondInt(false), cFirstInt(false), cSecondInt(false), theParton(p),
interactionRecoil(make_pair(TransverseMomentum(), ZERO)), fluct(-1), cFluct(-1), cValence(false),
givenMinus(ZERO), DGLAPchecked(false), intRecoil(TransverseMomentum()), cIntRecoil(TransverseMomentum()) {}
RealParton::~RealParton() {}
void RealParton::setFirstOMother(tRealPartonPtr rp) {
if (!(oMothers.first) ) {
oMothers.first = rp;
if ( rp )
rp->oChildren.second.insert(this);
}
}
void RealParton::setSecondOMother(tRealPartonPtr rp) {
if (!(oMothers.second) ) {
oMothers.second = rp;
if ( rp )
rp->oChildren.first.insert(this);
}
}
void RealParton::setOMother(tRealPartonPtr rp) {
if (!oMother ) {
oMother = rp;
if ( rp && theParton->parents().first == rp->theParton ) {
oMothers.first = rp;
oMothers.second = rp->oMothers.second;
rp->oChildren.second.insert(this);
}
else {
oMothers.second = rp;
oMothers.first = rp->oMothers.first;
rp->oChildren.first.insert(this);
}
}
}
void RealParton::addInteraction(tDipolePtr intDip) {
interactions.insert(intDip);
plus1veto = 0;
plus2veto = 0;
minus1veto = 0;
minus2veto = 0;
unDGLAP = 0;
if ( oMothers.first ) oMothers.first->addInteraction(intDip);
if ( oMothers.second ) oMothers.second->addInteraction(intDip);
if ( oMother ) oMother->addInteraction(intDip);
}
void RealParton::eraseMothers() {
tPartonPtr p = theParton;
if ( mothers.second ) {
mothers.second->eraseFirstChild(this);
}
if ( mothers.first ) {
mothers.first->eraseSecondChild(this);
}
if ( mother ) {
mother->eraseFirstChild(this);
mother->eraseSecondChild(this);
}
y = theParton->oY();
}
void RealParton::eraseChildren() {
for ( RealPartonSet::const_iterator it = children.first.begin();
it != children.first.end(); it++ )
eraseFirstChild(*it);
for ( RealPartonSet::const_iterator it = children.second.begin();
it != children.second.end(); it++ )
eraseSecondChild(*it);
}
RealPartonPtr RealParton::firstColourNeighbor() {
//if children on the other side, they will have the colour flow
if ( !children.first.empty() )
return *(--children.first.end());
//if only one mother, that will have the color flow
else if ( nMothers == 1 && mother )
return mother;
else
return mothers.first;
//this will not find valence neighbors. but maybe that's ok?
}
RealPartonPtr RealParton::secondColourNeighbor() {
if ( !children.second.empty() )
return *(--children.second.end());
else if ( nMothers == 1 && mother )
return mother;
else
return mothers.second;
//this will not find valence dipoles as effective partons. but maybe that's good?
}
RealParton::RealPartonSet RealParton::effectiveParton(InvEnergy range, bool firstSide) {
RealPartonSet ret;
ret.insert(this);
if ( range > Current<DipoleEventHandler>()->coherenceRange() )
range = Current<DipoleEventHandler>()->coherenceRange();
// if ( range == ZERO ) return ret;
if ( firstSide ) {
RealPartonPtr last = secondColourNeighbor();
for ( RealPartonPtr rp = firstColourNeighbor();
rp && rp->theParton->dist2(*theParton) < sqr(0.99*range);
rp = rp->firstColourNeighbor() ) {
if ( rp != this && ret.find(rp) != ret.end() ) {
break;
}
ret.insert(rp);
}
}
else {
RealPartonPtr last = firstColourNeighbor();
for ( RealPartonPtr rp = secondColourNeighbor();
rp && rp->theParton->dist2(*theParton) < sqr(0.99*range);
rp = rp->secondColourNeighbor() ) {
if ( rp != this && ret.find(rp) != ret.end() ) {
break;
}
ret.insert(rp);
}
}
//check for split virtuals
for ( RealPartonSet::iterator it = ret.begin(); it != ret.end(); it++) {
if ( (*it)->fluct != -1 )
ret.insert(realState->flucts[(*it)->fluct].begin(), realState->flucts[(*it)->fluct].end());
}
return ret;
}
void RealParton::doRecoil( RealPartonPtr p, Energy recPlus, TransverseMomentum recPT ) {
DipoleStatePtr state;
//first catch some cases that no recoiler wants.
if ( !theParton->valence() && (!mothers.first || !mothers.second) &&
!Current<DipoleEventHandler>()->eventFiller().singleMother() )
return;
if ( !theParton->valence() && mothers.first == mothers.second &&
!Current<DipoleEventHandler>()->eventFiller().singleMother() ) return;
if ( theParton->dipoles().first ) state = & theParton->dipoles().first->dipoleState();
else state = & theParton->dipoles().second->dipoleState();
//do the recoil
p->future.insert(this);
switch (state->handler().eventFiller().recoilScheme()) {
case 0:
doXmasRecoil(p, recPlus, recPT);
break;
case 1:
doRainfallRecoil(p, recPlus, recPT);
break;
case 2:
sunshineRecoil(p, recPlus, recPT);
break;
default:
doXmasRecoil(p, recPlus, recPT);
}
}
void RealParton::doXmasRecoil( RealPartonPtr p, Energy recPlus, TransverseMomentum recPT ) {
p->pT -= recPT;
p->plus -= recPlus;
// if ( Debug::level > 5 )
// cout << " do recoil of " << recPlus/GeV << ", (" << -recPT.x()/GeV << ", "
// << -recPT.y()/GeV << ") at "
// << p->oY() << ", (" << p->theParton->position().x()*GeV << ", "
// << p->theParton->position().y()*GeV << ")\n";
if ( p->realState != realState ) {
p->interactionRecoil.first -= recPT;
p->interactionRecoil.second -= recPlus;
recoils.push_back(make_pair(p, make_pair(recPT, recPlus)));
}
else
recoils.push_back(make_pair(p, make_pair(recPT, recPlus)));
p->updateYMinus();
// if ( Debug::level > 5 )
// cout << oY() << " is recoiling to " << p->oY() << " with (" << (recPT).x()/GeV << ", "
// << (recPT).y()/GeV << ")" << endl;
}
void RealParton::doRainfallRecoil( RealPartonPtr p, Energy recPlus, TransverseMomentum recPT ) {
cout << "Rainfall recoil scheme not implemented yet, using Xmas instead." << endl;
doRecoil(p, recPlus, recPT);
}
void RealParton::sunshineRecoil(RealPartonPtr p, Energy recPlus, TransverseMomentum recPT) {
cerr << "note, sunshine recoil not consistent with fast realMode atm" << endl;
//valencepartons cant borrow extra p+, so do xmas recoil
if ( p->theParton->valence() ) {
doXmasRecoil(p, recPlus, recPT);
return;
}
//find CoM energy.
DipoleStatePtr state;
if ( theParton->dipoles().first ) state = & theParton->dipoles().first->dipoleState();
else state = & theParton->dipoles().second->dipoleState();
Energy CoM = (state->plus() + state->collidingEnergy())/2.0;
//calculate the right angle (plus^a/minus^b=const) to update y and p- in.
if ( p->minus < ZERO || p->plus < ZERO ) {
cerr << "negative minus or plus!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << endl;
cerr << oY() << " is giving recoil to " << p->oY() << " with plus,minus "
<< p->plus/GeV << ", " << p->minus/GeV << endl;
realState->diagnosis(true);
}
double a = log(p->minus/CoM)/log(p->plus/CoM);
double C = pow(CoM/GeV,a - 1.0);
p->pT -= recPT;
recoils.push_back(make_pair(p, make_pair(recPT, ZERO)));
//calculate new plus for mother
Energy newPlus = pow(C*sqr(p->pT.pt()/GeV),1.0/(1.0 + a))*GeV;
Energy extraPlus = newPlus - p->plus;
//check that grandmothers have enough p+, otherwise leave it as xmas recoil
double P1 = p->mothers.first->plus/(p->mothers.first->plus + p->mothers.second->plus);
double P2 = 1.0 - P1;
if ( p->mothers.first->plus < P1*extraPlus || p->mothers.second->plus < P2*extraPlus ) {
p->plus -= recPlus;
recoils.push_back(make_pair(p, make_pair(TransverseMomentum(), recPlus)));
p->updateYMinus();
return;
}
//set the new plus and store the recoils
p->plus = newPlus - recPlus;
recoils.push_back(make_pair(p, make_pair(TransverseMomentum(), -extraPlus + recPlus)));
p->updateYMinus();
p->mothers.first->plus -= P1*extraPlus;
recoils.push_back(make_pair(p->mothers.first, make_pair(TransverseMomentum(), P1*extraPlus)));
p->mothers.first->updateYMinus();
p->mothers.second->plus -= P2*extraPlus;
recoils.push_back(make_pair(p->mothers.second, make_pair(TransverseMomentum(), P2*extraPlus)));
p->mothers.second->updateYMinus();
// realState->plotState(true);
}
void RealParton::doEffectiveRecoil( RealPartonPtr p, InvEnergy range, bool firstSide,
Energy recPlus, TransverseMomentum recPT ) {
RealPartonSet partons = p->effectiveParton(range, firstSide);
//find the ratio each individual parton should take of the recoil.
list<double> ratios = effectiveWeights(partons);
//do the recoils.
list<double>::iterator ratio = ratios.begin();
for ( RealPartonSet::iterator it = partons.begin();
it != partons.end(); it++, ratio++ ) {
if ( Current<DipoleEventHandler>()->eventFiller().effectiveWeights() == 0 ) {
if ( *ratio != 0.0 )
doRecoil(*it, recPlus*(*ratio), recPT*(*ratio));
}
else if ( Current<DipoleEventHandler>()->eventFiller().effectiveWeights() == 1 ) {
if ( *ratio != 0.0 )
doRecoil(*it, recPlus*(*ratio), recPT/double(partons.size()));
}
else if ( Current<DipoleEventHandler>()->eventFiller().effectiveWeights() == 2 ) {
if ( *ratio != 0.0 )
doRecoil(*it, recPlus*(*ratio), ((p == *it) ? recPT:TransverseMomentum()));
}
else cerr << "no effective weights specified in RealParton" << endl;
}
}
void RealParton::doPlusWeightedRecoil( RealPartonPtr p, InvEnergy range, bool firstSide,
Energy recPlus, TransverseMomentum recPT ) {
RealPartonSet partons = p->effectiveParton(range, firstSide);
Energy totalPlus = ZERO;
//find the total plus in the effective parton to be recoiled.
for ( RealPartonSet::const_iterator it = partons.begin(); it != partons.end(); it++ )
totalPlus += (*it)->plus;
//find the ratio each individual parton should take of the recoil.
list<double> ratios;
for ( RealPartonSet::const_iterator it = partons.begin(); it != partons.end(); it++ )
ratios.push_back((*it)->plus/totalPlus);
//do the recoils, using Xmas recoil scheme.
list<double>::iterator ratio = ratios.begin();
for ( RealPartonSet::iterator it = partons.begin(); it != partons.end(); it++, ratio++ ) {
Energy diff = -(*it)->minus;
doXmasRecoil(*it, recPlus*(*ratio), recPT*(*ratio));
diff += (*it)->minus;
}
}
void RealParton::undoRecoils() {
if ( Debug::level > 5 ) cout << "undoing " << recoils.size() << " recoils." << endl;
for ( list< Recoil >::iterator it = recoils.begin(); it != recoils.end(); it++ ) {
if ( it->first->realState != realState ) {
continue;
}
//save interaction recoils in case this parton is swithced on again.
it->first->pT += it->second.first;
it->first->plus += it->second.second;
it->first->updateYMinus();
it->first->future.erase(this);
if ( it->first->fluct != -1 ) {
if ( it->first->fluct >= int(realState->flucts.size()) || it->first->fluct < -1 ) {
cerr << "fluctuation index out of bounds at " << oY() << "!" << endl;
if ( Debug::level > 5 ) realState->plotState(true);
}
// if ( it->first->fluct < -1 ) realState->diagnosis(true);
realState->makeCollinear(realState->flucts[it->first->fluct]);
}
}
recoils.clear();
}
void RealParton::undoInteractionRecoils() {
if ( Debug::level > 5 ) cout << "undointrecs called at " << oY() << endl;
for ( list< Recoil >::iterator it = recoils.begin(); it != recoils.end(); it++ ) {
if ( it->first->realState == realState ) continue;
if ( Debug::level > 5 ) cout << "removing interaction recoil (" << it->second.first.x()/GeV
<< ", " << it->second.first.y()/GeV << ") at " << it->first->oY() << endl;
it->first->pT += it->second.first;
it->first->plus += it->second.second;
it->first->updateYMinus();
it->first->future.erase(this);
recoils.erase(it);
it--;
}
}
// void RealParton::checkInteractionRecoils() {
// if ( keep == NO || savedInteractionRecoils.empty() ) return;
// // This parton has been switchen off and then on again and should
// // therefore reobtain its interaction recoils.
// for ( list< Recoil >::iterator it = savedInteractionRecoils.begin();
// it != savedInteractionRecoils.end(); it++ ) {
// pT += it->second.first;
// plus += it->second.second;
// updateYMinus();
// recoils.insert(*it);
// }
// savedInteractionRecoils.clear();
// }
bool RealParton::setNO() {
if ( theParton->valence() ) moveValenceStatus();
future.clear();
eraseMothers();
undoRecoils();
eraseExchanges();
keep = NO;
return false;
}
bool RealParton::setYES() {
if ( movedValence && !theParton->valence() ) reclaimValenceStatus();
if ( nMothers == 1 ) setMother();
else setMothers();
keep = YES;
return doRecoil();
}
bool RealParton::quickSetYES() {
if ( movedValence && !theParton->valence() ) reclaimValenceStatus();
setMothers();
keep = YES;
return quickDoRecoil();
}
void RealParton::reclaimValenceStatus() {
if ( theParton->valence() ) return;
if ( !movedValence )
cerr << "RealParton::reclaimValenceStatus called without movedValence" << endl;
movedValence->theParton->valence(false);
realState->valence.erase(movedValence);
movedValence->movedValence = tRealPartonPtr();
movedValence = tRealPartonPtr();
theParton->valence(true);
realState->valence.insert(this);
}
void RealParton::eraseExchanges() {
if ( exchanges.empty() )
return;
for ( set<pair<pair<tRealPartonPtr, tRealPartonPtr>,
pair<tRealPartonPtr, tRealPartonPtr> > >::iterator it = exchanges.begin();
it != exchanges.end(); it++ ) {
RealPartonPtr rp11 = it->first.first;
RealPartonPtr rp12 = it->first.second;
RealPartonPtr rp21 = it->second.first;
RealPartonPtr rp22 = it->second.second;
DipoleXSec::InteractionRecoil rec = Current<DipoleEventHandler>()->xSecFn().
recoil(make_pair(rp11->theParton, rp12->theParton),
make_pair(rp21->theParton, rp22->theParton), ImpactParameters());
rp11->pT -= rec.first.first;
rp12->pT -= rec.first.second;
rp21->pT -= rec.second.first;
rp22->pT -= rec.second.second;
rp11->updateYMinus();
rp12->updateYMinus();
rp21->updateYMinus();
rp22->updateYMinus();
}
exchanges.clear();
}
pair<Energy, Energy> RealParton::effectivePlusMinus(InvEnergy range, bool firstSide) {
RealPartonSet ep = effectiveParton(range, firstSide);
Energy ePlus = ZERO;
TransverseMomentum ePT = TransverseMomentum();
for ( RealPartonSet::iterator it = ep.begin();
it != ep.end(); it++ ) {
ePlus += (*it)->plus;
ePT += (*it)->pT;
}
Energy eMinus = sqr(ePT.pt())/ePlus;
return make_pair(ePlus, eMinus);
}
Energy RealParton::inRangeMinus(InvEnergy range, bool firstSide) {
RealPartonSet ep = effectiveParton(range, firstSide);
Energy eMinus = ZERO;
for ( RealPartonSet::iterator it = ep.begin(); it != ep.end(); it++ ) {
eMinus += (*it)->minus;
}
return eMinus;
}
bool RealParton::searchNegative(InvEnergy range, bool firstSide) {
RealPartonSet ep = effectiveParton(range, firstSide);
for ( RealPartonSet::iterator it = ep.begin(); it != ep.end(); it++ ) {
if ( (*it)->plus < ZERO || (*it)->minus < ZERO ) return true;
}
return false;
}
TransverseMomentum RealParton::opT() {
TransverseMomentum ret = theParton->valencePT();
if ( mothers.first ) ret += theParton->recoil(mothers.first->theParton);
if ( mothers.second ) ret += theParton->recoil(mothers.second->theParton);
if ( nMothers == 1 && mother )
ret = theParton->valencePT() + theParton->recoil(mother->theParton);
if ( ret.pt() == ZERO ) ret = theParton->pT();
return ret;
}
bool RealParton::isOrdered() {
if ( nMothers == 1 ) return isSingleOrdered();
double PSInf = Current<DipoleEventHandler>()->emitter().PSInflation();
double PMOrd = Current<DipoleEventHandler>()->emitter().PMinusOrdering();
if ( theParton->valence() ) {
return true;
}
double P1 = theParton->dist2(*mothers.second->theParton)/
(theParton->dist2(*mothers.first->theParton)+theParton->dist2(*mothers.second->theParton));
double P2 = 1 - P1;
if ( y < max(mothers.first->y, mothers.second->y) ) return false;
else if ( mothers.first->plus < ZERO || mothers.second->plus < ZERO ) return false;
// else return true;
if ( fluct == -1 || fluct != mothers.first->fluct ) {
InvEnergy range1 = sqrt(min(theParton->dist2(*mothers.first->theParton),
mothers.second->theParton->dist2(*mothers.first->theParton)/4.0));
if ( Current<DipoleEventHandler>()->emitter().rangeMode() == 1 )
range1 = sqrt(mothers.second->theParton->dist2(*mothers.first->theParton)/4.0);
pair<Energy, Energy> pm1 = mothers.first->effectivePlusMinus(range1, true);
if ( Current<DipoleEventHandler>()->emitter().minusOrderingMode() == 1 ) {
pm1.second = sqrt(pm1.second*mothers.first->minus);
}
if ( Current<DipoleEventHandler>()->emitter().bothOrderedFS() ) {
P1 = 1.0; //leaves the ordering unweighted
P2 = 1.0;
}
if ( true ) { //Current<DipoleEventHandler>()->emitter().recoilerVeto() ) {
TransverseMomentum opT1 = mothers.first->opT();
if ( (pT - opT1).pt() > 2.0*opT1.pt() ) {
P1 *= pT.pt()/(opT1.pt());
}
}
if ( P1*plus/PSInf > pm1.first ) {
if ( Debug::level > 5 ) cout << oY() << " is plus unordered to " << mothers.first->oY() << endl;
plus1veto++;
return false;}
if ( minus*PSInf/P1 < pm1.second*PMOrd ) {
if ( Debug::level > 5 ) cout << oY() << " is minus unordered to " << mothers.first->oY() << endl;
minus1veto++;
return false;}
}
if ( fluct == -1 || fluct != mothers.second->fluct ) {
InvEnergy range2 = sqrt(min(theParton->dist2(*mothers.second->theParton),
mothers.second->theParton->dist2(*mothers.first->theParton)/4.0));
if ( Current<DipoleEventHandler>()->emitter().rangeMode() == 1 )
range2 = sqrt(mothers.second->theParton->dist2(*mothers.first->theParton)/4.0);
pair<Energy, Energy> pm2 = mothers.second->effectivePlusMinus(range2, false);
if ( Current<DipoleEventHandler>()->emitter().minusOrderingMode() == 1 ) {
pm2.second = sqrt(pm2.second*mothers.second->minus);
}
if ( true ) { //Current<DipoleEventHandler>()->emitter().recoilerVeto() ) {
TransverseMomentum opT2 = mothers.second->opT();
if ( pT.pt() > 2.0*opT2.pt() ) {
P2 *= pT.pt()/(opT2.pt());
}
}
if ( P2*plus/PSInf > pm2.first ) {
if ( Debug::level > 5 ) cout << oY() << " is plus unordered to " << mothers.second->oY() << endl;
plus2veto++;
return false;}
if ( minus*PSInf/P2 < pm2.second*PMOrd ) {
if ( Debug::level > 5 ) cout << oY() << " is minus unordered to " << mothers.second->oY() << endl;
minus2veto++;
return false;}
}
//check that the recoil didnt push any parton into negative p+
for ( list< pair<tRealPartonPtr, pair<TransverseMomentum, Energy> > >::iterator it =
recoils.begin(); it != recoils.end(); it++ ) {
if ( it->first->plus < ZERO ) return false;
}
return true;
}
bool RealParton::isFirstOrdered() {
double PMOrd = Current<DipoleEventHandler>()->emitter().PMinusOrdering();
double PSInf = Current<DipoleEventHandler>()->emitter().PSInflation();
if ( realState->monitored && realState->interactions.size() > 1) realState->plotState(false);
if ( theParton->valence() ) {
return true;
}
double P1 = theParton->dist2(*mothers.second->theParton)/
(theParton->dist2(*mothers.first->theParton)+theParton->dist2(*mothers.second->theParton));
InvEnergy range1 = sqrt(min(theParton->dist2(*mothers.first->theParton),
mothers.second->theParton->dist2(*mothers.first->theParton)/4.0));
pair<Energy, Energy> pm1 = mothers.first->effectivePlusMinus(range1, true);
if ( Current<DipoleEventHandler>()->emitter().bothOrderedFS() ) {
P1 = 1.0; //leaves the ordering unweighted
}
if ( P1*plus/PSInf > pm1.first ) return false;
if ( minus*PSInf/P1 < pm1.second*PMOrd ) return false;
//check that the recoil didnt push any parton into negative p+
for ( list< pair<tRealPartonPtr, pair<TransverseMomentum, Energy> > >::iterator it =
recoils.begin(); it != recoils.end(); it++ ) {
if ( it->first->plus < ZERO ) return false;
}
return true;
}
bool RealParton::isSecondOrdered() {
double PMOrd = Current<DipoleEventHandler>()->emitter().PMinusOrdering();
double PSInf = Current<DipoleEventHandler>()->emitter().PSInflation();
if ( realState->monitored && realState->interactions.size() > 1) realState->plotState(false);
if ( theParton->valence() ) {
return true;
}
double P1 = theParton->dist2(*mothers.second->theParton)/
(theParton->dist2(*mothers.first->theParton)+theParton->dist2(*mothers.second->theParton));
double P2 = 1 - P1;
if ( Current<DipoleEventHandler>()->emitter().bothOrderedFS() )
P2 = 1.0;
InvEnergy range2 = sqrt(min(theParton->dist2(*mothers.second->theParton),
mothers.second->theParton->dist2(*mothers.first->theParton)/4.0));
pair<Energy, Energy> pm2 = mothers.second->effectivePlusMinus(range2, false);
if ( P2*plus/PSInf > pm2.first ) return false;
if ( minus*PSInf/P2 < pm2.second*PMOrd ) return false;
//check that the recoil didnt push any parton into negative p+
for ( list< pair<tRealPartonPtr, pair<TransverseMomentum, Energy> > >::iterator it =
recoils.begin(); it != recoils.end(); it++ ) {
if ( it->first->plus < ZERO ) return false;
}
return true;
}
bool RealParton::isSingleOrdered() {
if ( fluct != -1 && fluct == mother->fluct ) return true;
double PMOrd = Current<DipoleEventHandler>()->emitter().PMinusOrdering();
double PSInf = Current<DipoleEventHandler>()->emitter().PSInflation();
if ( theParton->valence() ) return true;
InvEnergy range = sqrt(theParton->dist2(*mother->theParton));
pair<Energy, Energy> pm = mother->effectivePlusMinus(range, true);
if ( y < mother->y ) return false;
else if ( mother->plus < ZERO ) return false;
else return true;
if ( Current<DipoleEventHandler>()->emitter().minusOrderingMode() == 1 ) {
pm.second = sqrt(pm.second*mother->minus);
}
if ( plus/PSInf > pm.first ) {
if ( Debug::level > 5 ) cout << oY() << " is plus unordered to " << mother->oY() << endl;
plus1veto++;
return false;
}
if ( minus*PSInf < pm.second*PMOrd ) {
if ( Debug::level > 5 ) cout << oY() << " is minus unordered to " << mother->oY() << endl;
minus1veto++;
return false;
}
//check that the recoil didnt push any parton into negative p+
for ( list< pair<tRealPartonPtr, pair<TransverseMomentum, Energy> > >::iterator it =
recoils.begin(); it != recoils.end(); it++ )
if ( it->first->plus < ZERO ) return false;
return true;
}
bool RealParton::hasEnergy() {
for ( list< pair<tRealPartonPtr, pair<TransverseMomentum, Energy> > >::iterator it =
recoils.begin(); it != recoils.end(); it++ )
if ( it->first->plus < ZERO ) {
return false;
}
return true;
}
Energy RealParton::problemScale() {
return max(max(orderedScale(),DGLAPScale()),motherScale());
}
Energy RealParton::orderedScale() {
return emissionScale;
}
Energy RealParton::DGLAPScale() {
if ( DGLAPSafe() ) return ZERO;
if ( children.first.empty() ) return 1.0/sqrt(theParton->dist2(*mothers.first->theParton));
if ( children.second.empty() ) return 1.0/sqrt(theParton->dist2(*mothers.second->theParton));
cerr << "non DGLAP safe with children on both sides in DGLAPScale!!!!!" << endl;
return ZERO;
}
Energy RealParton::motherScale() {
Energy ret = ZERO;
if ( !theParton->valence() ) {
Energy firstOMother = 1.0/sqrt(theParton->dist2(*oMothers.first->theParton));
Energy secondOMother = 1.0/sqrt(theParton->dist2(*oMothers.second->theParton));
if ( !mothers.first )
ret = max(ret, firstOMother);
if ( !mothers.second )
ret = max(ret, secondOMother);
if ( mothers.first && mothers.first == mothers.second )
ret = max(ret, 1.0/sqrt(theParton->dist2(*mothers.first->theParton)));
if ( !interacting && children.first.empty() && children.second.empty() )
ret = max(ret, pT.pt()); //since this is a virtual fluct, the pT of the parton sets the scale
}
return ret;
}
RealPartonPtr RealParton::findCause() {
Energy oScale = orderedScale();
Energy DScale = DGLAPScale();
Energy mScale = motherScale();
RealPartonPtr cause;
if ( oScale > max(DScale, mScale) ) {
// cout << " unordered" << endl;
cause = orderedCause();
}
else if ( DScale > mScale ) {
// cout << " dglap is the cause" << endl;
cause = DGLAPCause();
}
else if ( mScale > ZERO ) {
// cout << " bad mother structure" << endl;
cause = motherCause();
}
else cerr << "findCause() called without any errors... >_>" << endl;
if ( !cause ) {
cerr << "all error scales ZERO for primary cause" << endl;
realState->plotState(true);
return cause;
}
// cout << " cause at " << cause->oY() << ", ("
// << cause->theParton->position().x()*GeV << ", "
// << cause->theParton->position().y()*GeV << ")" << endl;
//now try to handle if an interacting parton is the cause.
while ( cause->interacting ) {
// cout << " interacting cause, move" << endl;
if ( cause->theParton->valence() ) { //trying to remove interacting valence --> screwed
if ( !interacting ) return this;
// cout << "interacting valence parton is the cause, screwed." << endl;
if ( oScale > max(DScale, mScale) )
cout << " failed evo due to unordered\n";
else if ( DScale > mScale )
cout << " failed evo due to DGLAP\n";
else
cout << " failed evo due to mother structure\n";
realState->plotState(true);
return RealPartonPtr();
}
if ( !cause->mothers.first && !cause->mothers.second ) {
// cout << "want to remove interacting nonvalence wihtout mothers at " << cause->oY() << endl;
// realState->plotState(true);
return RealPartonPtr();
}
if ( !cause->mothers.first ) cause = cause->mothers.second; //take only existing mother
else if ( !cause->mothers.second ) cause = cause->mothers.first;
else if ( cause->mothers.first->interacting && !cause->mothers.second->interacting )
cause = cause->mothers.second; //otherwise take non-interacting mother
else if ( !cause->mothers.first->interacting && cause->mothers.second->interacting )
cause = cause->mothers.first;
else if ( cause->theParton->dist2(*cause->mothers.first->theParton) <
cause->theParton->dist2(*cause->mothers.second->theParton) )
cause = cause->mothers.first; //otherwise take closest mother
else
cause = cause->mothers.second;
}
// cout << " final cause at " << cause->oY() << ", ("
// << cause->theParton->position().x()*GeV << ", "
// << cause->theParton->position().y()*GeV << ")" << endl;
if ( cause && realState->toCheck.find(cause) == realState->toCheck.end() )
cout << "cause is outside toCheck!!" << endl;
return cause;
}
void RealParton::checkEmissionProblem() {
double PSInf = Current<DipoleEventHandler>()->emitter().PSInflation();
emissionScale = ZERO;
emissionCause = RealPartonPtr();
if ( theParton->valence() || !mothers.first || !mothers.second ) { //what to do if 1 mother?
return;
}
double P1 = theParton->dist2(*mothers.second->theParton)/
(theParton->dist2(*mothers.first->theParton)+theParton->dist2(*mothers.second->theParton));
double P2 = 1 - P1;
InvEnergy range1 = sqrt(min(theParton->dist2(*mothers.first->theParton),
mothers.second->theParton->dist2(*mothers.first->theParton)/4.0));
pair<Energy, Energy> pm1 = mothers.first->effectivePlusMinus(range1, true);
InvEnergy range2 = sqrt(min(theParton->dist2(*mothers.second->theParton),
mothers.second->theParton->dist2(*mothers.first->theParton)/4.0));
pair<Energy, Energy> pm2 = mothers.second->effectivePlusMinus(range2, false);
if ( P1*plus/PSInf > pm1.first && pT.pt() > emissionScale ) {
emissionScale = pT.pt();
emissionCause = this;
}
if ( minus*PSInf/P1 < pm1.second && mothers.first->pT.pt() > emissionScale ) {
emissionScale = mothers.first->pT.pt();
emissionCause = mothers.first;
}
if ( P2*plus/PSInf > pm2.first && pT.pt() > emissionScale ) {
emissionScale = pT.pt();
emissionCause = this;
}
if ( minus*PSInf/P2 < pm2.second && mothers.second->pT.pt() > emissionScale ) {
emissionScale = mothers.second->pT.pt();
emissionCause = mothers.second;
}
if ( !hasEnergy() ) {
emissionScale = pT.pt();
emissionCause = this;
}
}
RealPartonPtr RealParton::orderedCause() {
return emissionCause;
}
RealPartonPtr RealParton::DGLAPCause() {
if ( DGLAPSafe() ) cerr << "asked for DGLAPCause from dglap safe parton." << endl;
return this;
// if ( children.first.empty() ) return mothers.first;
// if ( children.second.empty() ) return mothers.second;
cerr << "non DGLAP safe with children on both sides in DGLAPScale!!!!!" << endl;
return RealPartonPtr();
}
RealPartonPtr RealParton::motherCause() {
return this;
}
RealPartonPtr RealParton::findSuspect() {
if ( theParton->valence() ) {
cout << "valence, couldnt find suspect." << endl;
return RealPartonPtr();
}
if ( !mothers.first || !mothers.second ) {
cout << " no mother at " << oY() << endl;
realState->plotState(true);
}
if ( mothers.first && !mothers.second ) return mothers.first;
if ( !mothers.first && mothers.second ) return mothers.second;
if ( !mothers.first && !mothers.second ) return RealPartonPtr();
double PSInf = Current<DipoleEventHandler>()->emitter().PSInflation();
double P1 = theParton->dist2(*mothers.second->theParton)/
(theParton->dist2(*mothers.first->theParton)+theParton->dist2(*mothers.second->theParton));
double P2 = 1 - P1;
InvEnergy range1 = sqrt(min(theParton->dist2(*mothers.first->theParton),
mothers.second->theParton->dist2(*mothers.first->theParton)/4.0));
pair<Energy, Energy> pm1 = mothers.first->effectivePlusMinus(range1, true);
InvEnergy range2 = sqrt(min(theParton->dist2(*mothers.second->theParton),
mothers.second->theParton->dist2(*mothers.first->theParton)/4.0));
pair<Energy, Energy> pm2 = mothers.second->effectivePlusMinus(range2, false);
bool firstSuspect = false;
bool secondSuspect = false;
if ( P1*plus/PSInf > pm1.first || minus*PSInf/P1 < pm1.second ) firstSuspect = true;
if ( P2*plus/PSInf > pm2.first || minus*PSInf/P2 < pm2.second ) secondSuspect = true;
cout << "first, second suspect: " << firstSuspect << ", " << secondSuspect << endl;
if ( firstSuspect && !secondSuspect ) return mothers.first;
else if ( !firstSuspect && secondSuspect ) return mothers.second;
else if ( mothers.first->oY() > mothers.second->oY() ) return mothers.first;
else return mothers.second;
//switch of the youngest of the mothers when in doubt.
}
void RealParton::setValenceMomentum() {
if ( !theParton->valence() ) return;
pT = theParton->valencePT();
plus = theParton->valencePlus();
y = log(pT.pt()/plus);
minus = pT.pt()*exp(y);
// cout << " set valencemomentum (" << pT.x()/GeV << ", " << pT.y()/GeV << ") at "
// << oY() << ", (" << theParton->position().x()*GeV << ", "
// << theParton->position().y()*GeV << ")\n";
}
bool RealParton::doRecoil() {
if ( theParton->valence() ) {
setValenceMomentum();
return true;
}
recoils.clear();
if ( nMothers == 1 )
return doSingleRecoil();
tRealPartonPtr m1 = mothers.first;
tRealPartonPtr m2 = mothers.second;
bool ok = true;
if ( !m1 && !m2 ) return false;
tPartonPtr p = theParton;
pT = TransverseMomentum(ZERO, ZERO);
y = p->oY();
if ( m1 && !m2 ) {
tPartonPtr p1 = m1->theParton;
pT += p->recoil(p1);
plus = pT.pt()*exp(-p->oY());
minus = pT.pt()*exp(p->oY());
// cout << " emit1 with pt (" << pT.x()/GeV << ", " << pT.y()/GeV << ") at "
// << oY() << ", (" << theParton->position().x()*GeV << ", "
// << theParton->position().y()*GeV << ")\n";
ok = false;
InvEnergy range1 = sqrt(p->dist2(*p1));
doEffectiveRecoil(m1, range1, true, plus, p->recoil(p1));
}
else if ( !m1 && m2 ) {
tPartonPtr p2 = m2->theParton;
ok = false;
pT += p->recoil(p2);
plus = pT.pt()*exp(-p->oY());
minus = pT.pt()*exp(p->oY());
// cout << " emit2 with pt (" << pT.x()/GeV << ", " << pT.y()/GeV << ") at "
// << oY() << ", (" << theParton->position().x()*GeV << ", "
// << theParton->position().y()*GeV << ")\n";
InvEnergy range2 = sqrt(p->dist2(*p2));
doEffectiveRecoil(m2, range2, false, plus, p->recoil(p2));
}
else {
tPartonPtr p1 = m1->theParton;
tPartonPtr p2 = m2->theParton;
pT += p->recoil(p1) + p->recoil(p2);
plus = pT.pt()*exp(-p->oY());
minus = pT.pt()*exp(p->oY());
// cout << " emit3 with pt (" << pT.x()/GeV << ", " << pT.y()/GeV << ") at "
// << oY() << ", (" << theParton->position().x()*GeV << ", "
// << theParton->position().y()*GeV << ")\n";
//potentially put this one back eventually
// doSwingRecoil();
// checkPS();
double P1 = p->dist2(*m2->theParton)/
(p->dist2(*m1->theParton) + p->dist2(*m2->theParton));
double P2 = 1.0 - P1;
InvEnergy range1 = sqrt(min(p->dist2(*p1), p2->dist2(*p1)/4.0));
if ( Current<DipoleEventHandler>()->emitter().rangeMode() == 1 )
range1 = sqrt(p2->dist2(*p1)/4.0);
doEffectiveRecoil(m1, range1, true, plus*P1, p->recoil(p1));
InvEnergy range2 = sqrt(min(p->dist2(*p2), p1->dist2(*p2)/4.0));
if ( Current<DipoleEventHandler>()->emitter().rangeMode() == 1 )
range2 = sqrt(p1->dist2(*p2)/4.0);
doEffectiveRecoil(m2, range2, false, plus*P2, p->recoil(p2));
ok = isOrdered(); //check ordering recoil
}
return ok;
}
bool RealParton::doSingleRecoil() {
tPartonPtr p = theParton;
y = p->oY();
pT = p->recoil(mother->theParton);
plus = pT.pt()*exp(-p->oY());
minus = pT.pt()*exp(p->oY());
InvEnergy range = sqrt(p->dist2(*mother->theParton));
doEffectiveRecoil(mother, range, true, plus, p->recoil(mother->theParton));
return isSingleOrdered();
}
bool RealParton::quickDoRecoil() {
if ( theParton->valence() ) {
setValenceMomentum();
return true;
}
recoils.clear();
tRealPartonPtr m1 = mothers.first;
tRealPartonPtr m2 = mothers.second;
bool ok = true;
if ( !m1 && !m2 ) return false;
tPartonPtr p = theParton;
pT = TransverseMomentum(ZERO, ZERO);
y = p->oY();
if ( m1 && !m2 ) { //can I let these through really? will rest of evo be ok?
tPartonPtr p1 = m1->theParton;
pT += p->recoil(p1);
// cout << " pt at creation1 (" << pT.x()/GeV << ", " << pT.y()/GeV << ") at "
// << oY() << ", (" << theParton->position().x()*GeV << ", "
// << theParton->position().y()*GeV << ")\n";
plus = pT.pt()*exp(-p->oY());
minus = pT.pt()*exp(p->oY());
InvEnergy range1 = sqrt(p->dist2(*p1));
doEffectiveRecoil(m1, range1, true, plus, p->recoil(p1));
}
else if ( !m1 && m2 ) {
tPartonPtr p2 = m2->theParton;
pT += p->recoil(p2);
// cout << " pt at creation2 (" << pT.x()/GeV << ", " << pT.y()/GeV << ") at "
// << oY() << ", (" << theParton->position().x()*GeV << ", "
// << theParton->position().y()*GeV << ")\n";
plus = pT.pt()*exp(-p->oY());
minus = pT.pt()*exp(p->oY());
InvEnergy range2 = sqrt(p->dist2(*p2));
doEffectiveRecoil(m2, range2, false, plus, p->recoil(p2));
}
else {
tPartonPtr p1 = m1->theParton;
tPartonPtr p2 = m2->theParton;
pT += p->recoil(p1) + p->recoil(p2);
// cout << " pt at creation3 (" << pT.x()/GeV << ", " << pT.y()/GeV << ") at "
// << oY() << ", (" << theParton->position().x()*GeV << ", "
// << theParton->position().y()*GeV << ")\n";
plus = pT.pt()*exp(-p->oY());
minus = pT.pt()*exp(p->oY());
//potentially put this one back eventually
// doSwingRecoil();
// checkPS();
double P1 = p->dist2(*m2->theParton)/
(p->dist2(*m1->theParton) + p->dist2(*m2->theParton));
double P2 = 1.0 - P1;
InvEnergy range1 = sqrt(min(p->dist2(*p1), p2->dist2(*p1)/4.0));
doEffectiveRecoil(m1, range1, true, plus*P1, p->recoil(p1));
InvEnergy range2 = sqrt(min(p->dist2(*p2), p1->dist2(*p2)/4.0));
doEffectiveRecoil(m2, range2, false, plus*P2, p->recoil(p2));
ok = hasEnergy(); //check ordering recoil
}
return ok;
}
void RealParton::checkPS() const {
cout << "checking PS" << endl;
if ( mothers.first == mothers.second ) {
cout << "same mothers" << endl;
return;
}
DipolePtr dip = new_ptr(Dipole());
PartonPtr parton1 = new_ptr(Parton());
PartonPtr parton2 = new_ptr(Parton());
parton1->position(mothers.first->theParton->position());
parton1->y(mothers.first->y);
parton1->pT(mothers.first->pT);
parton1->plus(mothers.first->plus);
parton1->minus(mothers.first->minus);
parton2->position(mothers.second->theParton->position());
parton2->y(mothers.second->y);
parton2->pT(mothers.second->pT);
parton2->plus(mothers.second->plus);
parton2->minus(mothers.second->minus);
dip->partons(make_pair(parton1, parton2));
DipoleStatePtr teststate = new_ptr(DipoleState());
teststate->handler(&Current<DipoleEventHandler>::current());
dip->dipoleState(teststate);
teststate->collidingEnergy(2000.0*GeV);
Current<DipoleEventHandler>()->emitter().testingPS = true;
// double inflation = Current<DipoleEventHandler>()->emitter().PSInflation();
// Current<DipoleEventHandler>()->emitter().PSInflation = 1.0; REMOVED DUE TO INTERFACED
Current<DipoleEventHandler>()->emitter().fixY = oY();
InvEnergy minr1 = ZERO, minr2 = ZERO, maxr1 = ZERO, maxr2 = ZERO;
maxr2 = ZERO;
for ( int i = 0; i < 10000; i++ ) {
Current<DipoleEventHandler>()->emitter().generate(*dip, oY() - 1.0, oY() + 1.0);
if ( dip->generatedGluon() ) {
InvEnergy r1 = (dip->generatedGluon()->position() - dip->partons().first->position()).pt();
InvEnergy r2 = (dip->generatedGluon()->position() - dip->partons().second->position()).pt();
if ( maxr2 == ZERO || r1 < minr1 )
minr1 = r1;
if ( maxr2 == ZERO || r2 < minr2 )
minr2 = r2;
if ( maxr2 == ZERO || r1 > maxr1 )
maxr1 = r1;
if ( maxr2 == ZERO || r2 > maxr2 )
maxr2 = r2;
}
}
cout << "done testing!" << endl;
Current<DipoleEventHandler>()->emitter().testingPS = false;
// Current<DipoleEventHandler>()->emitter().PSInflation = inflation; REMOVED DUE TO INTERFACED
cout << "at oY = " << oY() << ", r1 = "
<< (theParton->position() - mothers.first->theParton->position()).pt()*GeV << ", r2 = "
<< (theParton->position() - mothers.second->theParton->position()).pt()*GeV << endl;
cout << "orig emission: m1pT.pt() = " << theParton->m1pT.pt()/GeV
<< ", m1plus = " << theParton->m1plus/GeV
<< ", m2pT.pt() = " << theParton->m2pT.pt()/GeV
<< ", m2plus = " << theParton->m2plus/GeV << endl;
cout << "orig emission: minr1 = " << theParton->minr1*GeV << ", minr2 = " << theParton->minr2*GeV
<< ", maxr1 = " << theParton->maxr1*GeV << ", maxr2 = " << theParton->maxr2*GeV << endl;
cout << "real emission: m1pT.pt() = " << mothers.first->pT.pt()/GeV
<< ", m1plus = " << mothers.first->plus/GeV
<< ", m2pT.pt() = " << mothers.second->pT.pt()/GeV
<< ", m2plus = " << mothers.second->plus/GeV << endl
<< "real emission: minr1 = " << minr1*GeV << ", minr2 = " << minr2*GeV
<< ", maxr1 = " << maxr1*GeV << ", maxr2 = " << maxr2*GeV << endl << endl;
cout << "ratios: min1: " << minr1/theParton->minr1
<< ", min2: " << minr2/theParton->minr2
<< ", max1: " << theParton->maxr1/maxr1
<< ", max2: " << theParton->maxr2/maxr2 << endl;
}
bool RealParton::doSwingRecoil() {
if ( !mothers.first || !mothers.second )
cerr << "doswingrecoil in realparton called without mother" << endl;
RealPartonPtr m1 = mothers.first;
RealPartonPtr m2 = mothers.second;
RealPartonPtr gm12 = mothers.first->mothers.second;
RealPartonPtr gm21 = mothers.second->mothers.first;
//normal non-swing parent structure.
if ( !gm12 || !gm21 || gm12 == m2 || gm21 == m1 || m1 == m2 )
return false;
//standard swing structure
if ( gm12 != gm21 ) {
//maybe do recoil m1,gm12 vs gm21,m2
// if ( 9.0*Current<DipoleEventHandler>()->xSecFn().
// fij(make_pair(m1->theParton, gm12->theParton),
// make_pair(gm21->theParton, m2->theParton), ImpactParameters())/
// Current<DipoleEventHandler>()->swinger().
// swingAmp(make_pair(m1->theParton, gm12->theParton),
// make_pair(gm21->theParton, m2->theParton) ) > UseRandom::rnd() ) {
// Current<DipoleEventHandler>()->xSecFn().
// recoil(make_pair(m1->theParton, gm12->theParton),
// make_pair(gm21->theParton, m2->theParton), ImpactParameters());
// cout << "did extra recoil in realparton!!" << endl;
// return true;
// }
if ( 1.0/3.0 > UseRandom::rnd() ) {
// if ( realState->monitored )
// cout << "doing swing recoil!" << endl;
// realState->diagnosis(true);
DipoleXSec::InteractionRecoil rec = Current<DipoleEventHandler>()->xSecFn().
recoil(make_pair(m1->theParton, gm12->theParton),
make_pair(gm21->theParton, m2->theParton), ImpactParameters());
m1->pT += rec.first.first;
gm12->pT += rec.first.second;
gm21->pT += rec.second.first;
m2->pT += rec.second.second;
m1->updateYMinus();
m2->updateYMinus();
gm12->updateYMinus();
gm21->updateYMinus();
exchanges.insert(make_pair(make_pair(m1, gm12), make_pair(gm21, m2)));
// cout << "done swing recoil!" << endl;
// realState->diagnosis(true);
// cout << "did extra recoil in realparton!!" << endl;
return true;
}
else {
// cout << "tested and failed recoilswing in realparton" << endl;
return false;
}
}
//M-emission, must have been 2 swings, but do only last
else {
// cout << "M-emission in realparton, cant find the recoil. :(" << endl;
return false;
}
return false;
}
void RealParton::updateYMinus() {
if ( plus <= ZERO || pT.pt2() <= ZERO ) {
y = 0.0;
}
else {
y = log(pT.pt()/plus);
minus = pT.pt2()/plus;
}
}
void RealParton::eraseFirstChild(tRealPartonPtr rp) {
children.first.erase(rp);
}
void RealParton::eraseSecondChild(tRealPartonPtr rp) {
children.second.erase(rp);
}
bool RealParton::singleDGLAPSafe(InvEnergy scale) {
cout << "entering singledglap" << endl;
if ( secondInt || firstInt )
return checkDGLAPSafe(mother, RealPartonPtr(), scale);
if ( children.first.empty() ) return true;
else return checkDGLAPSafe(mother, *(--children.first.end()), scale);
}
bool RealParton::DGLAPSafe(InvEnergy scale) {
if ( nMothers == 1 )
return singleDGLAPSafe(scale);
bool DGLAPSuppresion = true; //should probably be interfaced. switches dglap suppression off.
if ( !DGLAPSuppresion ) return true;
//check for the right structure: no childs or int on one side
//and a child or an int (or both) on the other. pass on if right structure.
if ( children.first.empty() && !firstInt ) {
if ( secondInt )
return checkDGLAPSafe(mothers.first, RealPartonPtr(), scale);
else if ( !children.second.empty() )
return checkDGLAPSafe(mothers.first, *(--children.second.end()), scale);
else return true;
}
if ( children.second.empty() && !secondInt ) {
if ( firstInt )
return checkDGLAPSafe(mothers.second, RealPartonPtr(), scale);
else if ( !children.first.empty() )
return checkDGLAPSafe(mothers.second, *(--children.first.end()), scale);
else return true;
}
return true;
}
bool RealParton::checkDGLAPSafe(tRealPartonPtr mother, tRealPartonPtr child, InvEnergy scale) {
if ( !mother ) return true;
//if the small dipole is interacting, the dipole is always safe.
if ( interacting && interacting == mother->interacting ) return true; //not perfect solution
//the size of the small (backwards) dipole
InvEnergy r1 = sqrt(mother->theParton->dist2(*theParton));
//take the large (forward) size from the interaction, or otherwise last child.
InvEnergy r2;
if ( !child ) r2 = intDist;
else r2 = sqrt(child->theParton->dist2(*theParton));
//set the forward scale to what is supplied, if something is supplied.
//this is if there are several steps down in pt after each other. compare to bottom.
if ( scale != ZERO ) r2 = scale;
// *** ATTENTION *** this is to avoid divide by zero in alphaS.
if ( r2 == ZERO ) return true;
//never suppress above coherence range
if ( r2 > Current<DipoleEventHandler>()->coherenceRange() )
r2 = Current<DipoleEventHandler>()->coherenceRange();
// Calculate fudge factor to emulate ME-corrections
double fudgeME = Current<DipoleEventHandler>()->fudgeME()?
1.0 - 1.0/(1.0 + cosh(theParton->y() - mother->theParton->y())): 1.0;
//check if the parton has been checked with this mother before.
//if so, reuse the randomised resolution scale r1^2*alphas(r1)*R
map<tRealPartonPtr, InvEnergy2>::iterator it = resolutionScales.lower_bound(mother);
if ( (*it).first == mother )
- return (*it).second > sqr(r2)*Current<DipoleEventHandler>()->alphaS(r2);
+ return (*it).second > sqr(r2)*Current<DipoleEventHandler>()->alphaSr(r2);
//otherwise generate a new resolution scale r1^2*alphas(r1)*R
resolutionScales.insert(pair<tRealPartonPtr, InvEnergy2>
- (mother, fudgeME*(sqr(r1)*Current<DipoleEventHandler>()->alphaS(r1))
+ (mother, fudgeME*(sqr(r1)*Current<DipoleEventHandler>()->alphaSr(r1))
/(UseRandom::rnd())));
if ( Debug::level > 5 ) {
cout << "mother scale: " << r1*GeV << ", child scale: " << r2*GeV;
- if ( resolutionScales[mother] > (sqr(r2)*Current<DipoleEventHandler>()->alphaS(r2)) )
+ if ( resolutionScales[mother] > (sqr(r2)*Current<DipoleEventHandler>()->alphaSr(r2)) )
cout << " safe!" << endl;
else cout << " NOT safe!!" << endl;
}
//return safe if the forwards dipole is small enough to see the backward dipole.
- return resolutionScales[mother] > (sqr(r2)*Current<DipoleEventHandler>()->alphaS(r2));
+ return resolutionScales[mother] > (sqr(r2)*Current<DipoleEventHandler>()->alphaSr(r2));
}
tRealPartonPtr RealParton::youngestFirstChild(tRealPartonPtr rp, bool checkMother) {
if ( oChildren.first.size() > 0 ) {
RealPartonSet::iterator it = oChildren.first.lower_bound(rp);
if ( it != oChildren.first.begin() ) {
if ( (*(--it))->keep == YES ) return *it;
else {
tRealPartonPtr cand = (*it)->youngestFirstChild(rp, false);
if ( cand ) return cand;
}
}
}
if ( !checkMother ) return RealPartonPtr();
if ( !(oMothers.first) ) {
if ( movedValence && movedValence->oY() < rp->oY() ) {
// cout << "returning " << movedValence->oY() << ", ("
// << movedValence->theParton->position().x()*GeV << ", "
// << movedValence->theParton->position().y()*GeV << ") as first mother to "
// << rp->oY() << ", (" << rp->theParton->position().x()*GeV << ", "
// << rp->theParton->position().y()*GeV << ")\n";
return movedValence;
}
return RealPartonPtr();
}
if ( oMothers.first->keep == YES ) return oMothers.first;
else return oMothers.first->youngestFirstChild(rp, true);
}
tRealPartonPtr RealParton::youngestSecondChild(tRealPartonPtr rp, bool checkMother) {
if ( oChildren.second.size() > 0 ) {
RealParton::RealPartonSet::iterator it = oChildren.second.lower_bound(rp);
if ( it != oChildren.second.begin() ) {
if ( (*(--it))->keep == YES ) return *it;
else {
tRealPartonPtr cand = (*it)->youngestSecondChild(rp, false);
if ( cand ) return cand;
}
}
}
if ( !checkMother ) return RealPartonPtr();
if ( !(oMothers.second) ) {
if ( movedValence && movedValence->oY() < rp->oY() ) {
// cout << "returning " << movedValence->oY() << ", ("
// << movedValence->theParton->position().x()*GeV << ", "
// << movedValence->theParton->position().y()*GeV << ") as first mother to "
// << rp->oY() << ", (" << rp->theParton->position().x()*GeV << ", "
// << rp->theParton->position().y()*GeV << ")\n";
return movedValence;
}
return RealPartonPtr();
}
if ( oMothers.second->keep == YES ) return oMothers.second;
else return oMothers.second->youngestSecondChild(rp, true);
}
void RealParton::setMothers() {
if ( nMothers == 1 ) {
setMother();
return;
}
tRealPartonPtr first;
tRealPartonPtr second;
if ( theParton->valence() ) {
mothers = pair<tRealPartonPtr, tRealPartonPtr>(first, second);
return;
}
if ( oMothers.first->keep == YES ) first = oMothers.first;
else first = oMothers.first->youngestFirstChild(this, true);
if ( oMothers.second->keep == YES ) second = oMothers.second;
else second = oMothers.second->youngestSecondChild(this, true);
mothers = pair<tRealPartonPtr, tRealPartonPtr>(first, second);
if ( first ) first->children.second.insert(this);
if ( second ) second->children.first.insert(this);
}
void RealParton::setMother() {
if ( theParton->valence() ) {
mother = RealPartonPtr();
return;
}
if ( !oMother ) cerr << "non-valence parton without mother at y0 = " << oY() << "! :o" << endl;
if ( oMother->keep == YES ) {
mother = oMother;
if ( oMothers.first ) mother->children.second.insert(this);
else if ( oMothers.second ) mother->children.first.insert(this);
}
else {
if ( oMothers.first ) {
mother = oMother->youngestFirstChild(this, true);
mother->children.second.insert(this);
}
else if ( oMothers.second ) {
mother = oMother->youngestSecondChild(this, true);
mother->children.first.insert(this);
}
else
cerr << "single mother, but neither first or second side!! :(" << endl;
}
}
void RealParton::setOnShell() {
if ( keep == NO ) return;
theParton->onShell(true);
if ( mothers.first ) mothers.first->setOnShell();
if ( mothers.second ) mothers.second->setOnShell();
if ( mother ) mother->setOnShell();
}
bool RealParton::moveValenceStatus() {
if ( !theParton->valence() )
cerr << "realparton::moveValenceStatus called for non valence parton." << endl;
if ( !movedValence ) return moveValenceStatus(oldestHeir(this));
else return moveValenceStatus(movedValence->oldestHeir(this));
}
tRealPartonPtr RealParton::oldestHeir(tRealPartonPtr rp) {
tRealPartonPtr ret = tRealPartonPtr();
for ( RealPartonSet::iterator it = oChildren.first.begin();
it != oChildren.first.end(); it++ ) {
tRealPartonPtr cand;
if ( (*it)->interactions.empty() ) continue;
if ( (*it)->theParton->oY() <= rp->theParton->oY() || (*it)->theParton->valence() )
cand = (*it)->oldestHeir(rp);
else
cand = *it;
if ( cand && (!ret || cand->theParton->oY() < ret->theParton->oY()) )
ret = cand;
}
for ( RealPartonSet::iterator it = oChildren.second.begin();
it != oChildren.second.end(); it++ ) {
tRealPartonPtr cand;
if ( (*it)->interactions.empty() ) continue;
if ( (*it)->theParton->oY() <= rp->theParton->oY() || (*it)->theParton->valence() )
cand = (*it)->oldestHeir(rp);
else
cand = *it;
if ( cand && (!ret || cand->theParton->oY() < ret->theParton->oY()) )
ret = cand;
}
if ( ret && realState->toCheck.find(ret) == realState->toCheck.end() ) {
// cout << "found oldest heir not in toCheck, search more..." << endl;
ret = oldestHeir(ret);
}
return ret;
}
RealParton::RealPartonSet RealParton::ancestors() {
RealPartonSet ret;
ret.insert(this);
if ( oMothers.first ) {
RealPartonSet m1 = oMothers.first->ancestors();
ret.insert(m1.begin(), m1.end());
}
if ( oMothers.second ) {
RealPartonSet m2 = oMothers.second->ancestors();
ret.insert(m2.begin(), m2.end());
}
if ( oMother ) {
RealPartonSet m = oMother->ancestors();
ret.insert(m.begin(), m.end());
}
return ret;
}
bool RealParton::moveValenceStatus(RealPartonPtr rp) {
if ( !rp ) return false;
if ( realState->toCheck.find(rp) == realState->toCheck.end() ) return false;
if ( rp->theParton->valence() )
cerr << "RealParton::moveValenceStatus moving valence to a valence" << endl;
rp->theParton->valencePT(theParton->valencePT());
rp->theParton->valencePlus(theParton->valencePlus());
rp->theParton->valence(true);
realState->valence.insert(rp);
theParton->valence(false);
realState->valence.erase(this);
if ( movedValence ) {
rp->movedValence = movedValence;
movedValence->movedValence = rp;
movedValence = RealPartonPtr();
}
else {
rp->movedValence = this;
movedValence = rp;
}
// cout << "moved valence status from " << oY() << ", (" << theParton->position().x()*GeV << ","
// << theParton->position().y()*GeV << ") to " << rp->oY() << ", ("
// << rp->theParton->position().x()*GeV << "," << rp->theParton->position().y()*GeV << ")\n";
return true;
}
Energy RealParton::effectiveCheckMinus(InvEnergy range, bool firstSide, RealPartonSet checked) {
RealPartonSet ep = effectiveParton(range, firstSide);
Energy ret = ZERO;
for ( RealPartonSet::iterator it = ep.begin();
it != ep.end(); it++ ) {
ret += (*it)->checkMinus(checked);
}
return ret;
}
Energy RealParton::checkMinus(RealPartonSet checked) {
if ( checked.find(this) != checked.end() )
return ZERO;
checked.insert(this);
if ( keep == NO ) {
cout << "NO parton " << oY() << " encountered in RealParton::checkminus()" << endl;
realState->plotState(true);
return ZERO;
}
Energy ret = minus - givenMinus;
if ( theParton->valence() ) {
Energy valenceMinus = sqr(theParton->valencePT().pt())/theParton->valencePlus();
ret = (minus - valenceMinus) - givenMinus;
return ret;
}
return ret + mothers.first->giveMinus() + mothers.second->giveMinus();
}
Energy RealParton::effectiveGiveMinus(InvEnergy range, bool firstSide) {
RealPartonSet ep = effectiveParton(range, firstSide);
Energy ret = ZERO;
for ( RealPartonSet::iterator it = ep.begin();
it != ep.end(); it++ ) {
ret += (*it)->giveMinus();
}
return ret;
}
Energy RealParton::giveMinus() {
Energy ret = ZERO;
if ( theParton->valence() ) {
Energy newminus = minus -
sqr(theParton->theValencePT.pt())/theParton->theValencePlus;
ret = newminus - givenMinus;
givenMinus = newminus;
return ret;
}
if ( keep == YES ) {
ret = minus - givenMinus;
givenMinus = minus;
}
if ( oMothers.first ) ret += oMothers.first->giveMinus();
if ( oMothers.second ) ret += oMothers.second->giveMinus();
if ( oMother ) ret += oMother->giveMinus();
return ret;
// if ( keep == NO ) {
// cout << "NO parton " << oY() << " encountered in RealParton::giveminus()" << endl;
// realState->diagnosis(true);
// return ZERO;
// }
// Energy ret = minus - givenMinus;
// if ( theParton->valence() ) {
// Energy valenceMinus = sqr(theParton->valencePT().pt())/theParton->valencePlus();
// ret = (minus - valenceMinus) - givenMinus;
// givenMinus = (minus - valenceMinus);
// return ret;
// }
// givenMinus = minus;
// if ( nMothers == 2 ) {
// if ( mothers.first ) ret += mothers.first->giveMinus();
// if ( mothers.second ) ret += mothers.second->giveMinus();
// }
// if ( nMothers == 1 )
// if ( mother ) ret += mother->giveMinus();
// return ret;
}
void RealParton::emitRecoiler(TransverseMomentum rec, double plusRatio) {
//create gluons
DipolePtr dip;
PartonPtr p = theParton;
bool firstSide = false;
if ( p->dipoles().first && p->dipoles().second ) {
if ( p->dipoles().first->partons().first->y() > p->dipoles().second->partons().second->y() )
firstSide = true;
else firstSide = false;
}
else if ( p->dipoles().first ) firstSide = true;
else firstSide = false;
if ( firstSide ) dip = p->dipoles().first;
else dip = p->dipoles().second;
PartonPtr recoiler = new_ptr(Parton());
recoiler->onShell(true);
dip->generatedGluon(recoiler);
//fix colour flow for dipole state (let it be connected to the original one)
dip->splitDipole(0.5); //use better approximation for colour choice?
//initialise real recoiler
RealPartonPtr realRecoiler = realState->getReal(recoiler);
realRecoiler->nMothers = 1;
realRecoiler->setOMother(this);
realRecoiler->mother = this;
realRecoiler->keep = RealParton::YES;
//set momentum of recoiler
realRecoiler->pT = rec;
pT -= rec;
//otherwise use ymax to limit how far the recoiler can go in rapidity
realRecoiler->plus = plusRatio*plus;
plus *= 1.0 - plusRatio;
realRecoiler->updateYMinus();
updateYMinus();
recoiler->oY(realRecoiler->y);
while ( realRecoiler->minus > dip->dipoleState().collidingEnergy()/10.0 ) {
plus -= realRecoiler->plus;
realRecoiler->plus += realRecoiler->plus;
realRecoiler->updateYMinus();
updateYMinus();
recoiler->oY(realRecoiler->y);
}
if ( Debug::level > 5 )
cout << "recoiler takes plus ratio " << plusRatio << endl;
//set position of recoiler
recoiler->position(p->position() + p->pTScale()*rec/sqr(rec.pt()));
//set mother structure
for ( RealPartonSet::iterator it = children.first.begin();
it != children.first.end(); it++ ) {
RealPartonPtr child = *it;
realRecoiler->children.first.insert(child);
if ( child->nMothers == 1 ) child->mother = realRecoiler;
if ( child->nMothers == 2 ) child->mothers.second = realRecoiler;
}
children.first.clear();
if ( firstSide ) children.first.insert(realRecoiler);
for ( RealPartonSet::iterator it = children.second.begin();
it != children.second.end(); it++ ) {
RealPartonPtr child = *it;
realRecoiler->children.second.insert(child);
if ( child->nMothers == 1 ) child->mother = realRecoiler;
if ( child->nMothers == 2 ) child->mothers.first = realRecoiler;
}
children.second.clear();
if ( !firstSide ) children.second.insert(realRecoiler);
//fix interacting tags
if ( firstInt ) {
realRecoiler->interacting = interacting;
interacting = DipolePtr();
firstInt = false;
realRecoiler->firstInt = true;
realRecoiler->intDist = intDist;
}
if ( secondInt ) {
realRecoiler->interacting = interacting;
interacting = DipolePtr();
secondInt = false;
realRecoiler->secondInt = true;
realRecoiler->intDist = intDist;
}
saveState();
realRecoiler->saveState();
if ( Debug::level > 5 ) cout << "added recoiler at " << realRecoiler->oY() << endl;
}
list<double> RealParton::effectiveWeights(const RealPartonSet & partons) {
Energy totalPlus = ZERO;
Energy totalMinus = ZERO;
double maxy = (*partons.begin())->oY();
//find the total plus in the effective parton to be recoiled.
for ( RealPartonSet::const_iterator it = partons.begin();
it != partons.end(); it++ ) {
totalPlus += (*it)->plus;
totalMinus += (*it)->minus;
if ( (*it)->oY() > maxy )
maxy = (*it)->oY();
}
list<double> ret;
for ( RealPartonSet::const_iterator it = partons.begin();
it != partons.end(); it++ ) {
// ret.push_back( ((*it)->oY()==maxy) ? 1.0:0.0 );
ret.push_back((*it)->plus/totalPlus);
// ret.push_back((*it)->minus/totalMinus);
// ret.push_back(1.0/double(partons.size()));
}
return ret;
}
void RealParton::saveState() {
theParton->plus(plus);
theParton->minus(minus);
theParton->pT(pT);
theParton->y(y);
cMothers = mothers;
cChildren = children;
cKeep = keep;
cInteracting = interacting;
// if ( Debug::level > 5 && interacting ) cout << "saving " << oY() << " as interacting" << endl;
cFirstInt = firstInt;
cSecondInt = secondInt;
cIntRecoil = intRecoil;
cInteractionRecoil.first = interactionRecoil.first;
cInteractionRecoil.second = interactionRecoil.second;
cGivenMinus = givenMinus;
cValence = theParton->valence();
cValencePlus = theParton->valencePlus();
cValencePT = theParton->valencePT();
cMovedValence = movedValence;
cIntDist = intDist;
cExchanges = exchanges;
cFluct = fluct;
cInteractions.clear();
cInteractions.insert(interactions.begin(), interactions.end());
}
void RealParton::revert(tDipolePtr intDip) {
plus1veto = 0;
plus2veto = 0;
minus1veto = 0;
minus2veto = 0;
unDGLAP = 0;
plus = theParton->plus();
minus = theParton->minus();
pT = theParton->pT();
y = theParton->y();
mothers = cMothers;
children = cChildren;
keep = cKeep;
// if ( Debug::level > 5 && interacting && !cInteracting ) cout << "reverting " << oY()
// << " to non-interacting" << endl;
interacting = cInteracting;
firstInt = cFirstInt;
secondInt = cSecondInt;
intRecoil = cIntRecoil;
interactionRecoil.first = cInteractionRecoil.first;
interactionRecoil.second = cInteractionRecoil.second;
givenMinus = cGivenMinus;
if ( cValence && !theParton->valence() )
realState->valence.insert(this);
if ( !cValence && theParton->valence() )
realState->valence.erase(this);
theParton->valence(cValence);
if ( cValence ) {
theParton->valencePT(cValencePT);
theParton->valencePlus(cValencePlus);
}
movedValence = cMovedValence;
interactions.clear();
interactions.insert(cInteractions.begin(), cInteractions.end());
intDist = cIntDist;
exchanges = cExchanges;
fluct = cFluct;
}
bool RealParton::checkMomentum() const {
if ( keep == NO ) return true; //NO partons are not expected to be anything.
bool ok = true;
TransverseMomentum expPT = theParton->valencePT() + intRecoil;
if ( !theParton->valence() ) {
if ( mothers.first )
expPT += theParton->recoil(mothers.first->theParton);
if ( mothers.second )
expPT += theParton->recoil(mothers.second->theParton);
}
for ( RealPartonSet::const_iterator it = children.first.begin();
it != children.first.end(); it++ ) {
if ( !(*it)->theParton->valence() )
expPT += theParton->recoil((*it)->theParton);
}
for ( RealPartonSet::const_iterator it = children.second.begin();
it != children.second.end(); it++ ) {
if ( !(*it)->theParton->valence() )
expPT += theParton->recoil((*it)->theParton);
}
if ( (expPT - pT).pt() > 0.000000001*GeV ) {
cout << "* has unexpected pT = (" << pT.x()/GeV << ", "
<< pT.y()/GeV << ") at oY = " << theParton->oY() << endl
<< "* expected was pT = (" << expPT.x()/GeV << ", " << expPT.y()/GeV << ")" << endl;
ok = false;
}
if ( abs(pT.pt()*exp(y) - minus) > 0.000000001*GeV ||
abs(pT.pt()*exp(-y) - plus) > 0.000000001*GeV ) {
cout << "* not on shell, pT = " << pT.pt()/GeV << ", y = " << y << endl
<< "* expected plus = " << pT.pt()*exp(-y)/GeV
<< ", expected minus = " << pT.pt()*exp(y)/GeV << endl
<< "* plus = " << plus/GeV << ", minus = " << minus/GeV << endl;
ok = false;
}
return ok;
}
diff --git a/DIPSY/RealPartonState.cc b/DIPSY/RealPartonState.cc
--- a/DIPSY/RealPartonState.cc
+++ b/DIPSY/RealPartonState.cc
@@ -1,2442 +1,2442 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the RealPartonState class.
//
#include "RealPartonState.h"
#include "RealParton.h"
#include "Dipole.h"
#include "DipoleState.h"
#include "DipoleEventHandler.h"
#include "ThePEG/Utilities/Current.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Utilities/Debug.h"
#include "ThePEG/Utilities/DebugItem.h"
#include "ThePEG/Utilities/Throw.h"
#include "ThePEG/Repository/CurrentGenerator.h"
#include <iostream>
using namespace DIPSY;
RealPartonState::RealPartonState(): consistent(true), calls(0) {}
RealPartonState::~RealPartonState() {}
void RealPartonState::newInteraction(tDipolePtr intDip, tDipolePtr otherIntDip,
bool firstInt, bool secondInt,
Energy rec1, Energy rec2) {
//The ancestors of the interacting partons, ie the partons that have
//been involved in making the interacting dipole.
RealPartonSet ancestors;
//diagnostics
if ( Debug::level > 5 )
cout << "adding interaction " << intDip << " to " << this << endl;
//clear the partons to be checked in this interaction.
//Only partons involved in this interaction are checked,
//ther others are assumed to still be ok since last check.
toCheck.clear();
//Add interacting dipoles and which partons are interacting.
interactions.push_back(intDip);
doesInts.push_back(make_pair(firstInt, secondInt));
//Set up the real partons.
//Some settings only add one of partons in the interacting dipole,
//hence all the "if (firstInt )" etc.
//Note that addParton recursively calls the parents as well,
//so all new realparton instances needed are created.
RealPartonPtr rp1, rp2;
if ( firstInt ) {
if ( Debug::level > 5 ) cout << "calling first addparton for interacting parton " << intDip->partons().first->oY() << endl;
addParton(intDip->partons().first);
rp1 = getReal(intDip->partons().first);
}
if ( secondInt ) {
if ( Debug::level > 5 ) cout << "calling second addparton for interacting parton " << intDip->partons().second->oY() << endl;
addParton(intDip->partons().second);
rp2 = getReal(intDip->partons().second);
}
//Find the interaction distance of the interacting partons.
//This is needed when checking pT-ordering (or almost equivalently dipole-
//size ordering) later, and the last-before-interaction dipole needs
//to be checked. The picture here is to compare along the colour chains
//AFTER the interacting dipole has swinged, which is a more frame-
//independent approach, as otherwise we would have to compare the
//last-before-interacting dipole with a dipole that is not present in
//the final state.
//Also, since the interacting dipole has (roughly) the weight of a
//dipole that has emitted, it would mess up the weights if it entered
//the pT-max reweighting scheme.
if ( rp1 ) {
if ( !rp1->interacting ) {
if ( rec1 == ZERO ) rec1 = rec2;
if ( rec1 == ZERO ) cerr << "zero recoil in realpartonstate::newinteraction" << endl;
rp1->intDist = rp1->theParton->pTScale()/rec1;
}
else {
if ( rec1 == ZERO ) rec1 = rec2;
if ( rec1 == ZERO ) cerr << "zero recoil in realpartonstate::newinteraction" << endl;
rp1->intDist = min(rp1->intDist, rp1->theParton->pTScale()/rec1);
}
//book keeping.
rp1->interacting = intDip;
rp1->secondInt = true;
RealPartonSet a1 = rp1->ancestors();
ancestors.insert(a1.begin(), a1.end());
}
if ( rp2 ) {
if ( !rp2->interacting ) {
if ( rec2 == ZERO ) rec2 = rec1;
if ( rec2 == ZERO ) cerr << "zero recoil in realpartonstate::newinteraction" << endl;
rp2->intDist = rp2->theParton->pTScale()/rec2;
}
else {
if ( rec2 == ZERO ) rec2 = rec1;
if ( rec2 == ZERO ) cerr << "zero recoil in realpartonstate::newinteraction" << endl;
rp2->intDist = min(rp2->intDist, rp2->theParton->pTScale()/rec2);
}
//book keeping for future referens
rp2->interacting = intDip;
rp2->firstInt = true;
RealPartonSet a2 = rp2->ancestors();
ancestors.insert(a2.begin(), a2.end());
}
//and make all the ancestors remember that they contributed.
for ( RealPartonSet::iterator it = ancestors.begin(); it != ancestors.end(); it++ ) {
(*it)->interactions.insert(intDip);
}
}
void RealPartonState::
newInteraction(tDipolePtr intDip, tDipolePtr otherIntDip,
tPartonPtr parton, const TransverseMomentum & recoil) {
//The ancestors of the interacting partons, ie the partons that have
//been involved in making the interacting dipole.
RealPartonSet ancestors;
bool firstInt = ( parton == intDip->partons().first );
bool secondInt = ( parton == intDip->partons().second );
//diagnostics
if ( Debug::level > 5 )
cout << "adding interaction " << intDip << " to " << this << endl;
//clear the partons to be checked in this interaction.
//Only partons involved in this interaction are checked,
//ther others are assumed to still be ok since last check.
toCheck.clear();
//Add interacting dipoles and which partons are interacting.
interactions.push_back(intDip);
doesInts.push_back(make_pair(firstInt, secondInt));
//Set up the real partons.
//Some settings only add one of partons in the interacting dipole,
//hence all the "if (firstInt )" etc.
//Note that addParton recursively calls the parents as well,
//so all new realparton instances needed are created.
RealPartonPtr rp1, rp2;
if ( firstInt ) {
if ( Debug::level > 5 ) cout << "calling first addparton for interacting parton " << intDip->partons().first->oY() << endl;
addParton(intDip->partons().first);
rp1 = getReal(intDip->partons().first);
}
if ( secondInt ) {
if ( Debug::level > 5 ) cout << "calling second addparton for interacting parton " << intDip->partons().second->oY() << endl;
addParton(intDip->partons().second);
rp2 = getReal(intDip->partons().second);
}
//Find the interaction distance of the interacting partons.
//This is needed when checking pT-ordering (or almost equivalently dipole-
//size ordering) later, and the last-before-interaction dipole needs
//to be checked. The picture here is to compare along the colour chains
//AFTER the interacting dipole has swinged, which is a more frame-
//independent approach, as otherwise we would have to compare the
//last-before-interacting dipole with a dipole that is not present in
//the final state.
//Also, since the interacting dipole has (roughly) the weight of a
//dipole that has emitted, it would mess up the weights if it entered
//the pT-max reweighting scheme.
if ( rp1 ) {
if ( !rp1->interacting ) {
rp1->intDist = rp1->theParton->pTScale()/recoil.pt();
} else {
rp1->intDist = min(rp1->intDist, rp1->theParton->pTScale()/recoil.pt());
}
//book keeping.
rp1->interacting = intDip;
rp1->secondInt = true;
RealPartonSet a1 = rp1->ancestors();
ancestors.insert(a1.begin(), a1.end());
}
if ( rp2 ) {
if ( !rp2->interacting ) {
rp2->intDist = rp2->theParton->pTScale()/recoil.pt();
} else {
rp2->intDist = min(rp2->intDist, rp2->theParton->pTScale()/recoil.pt());
}
//book keeping for future referens
rp2->interacting = intDip;
rp2->firstInt = true;
RealPartonSet a2 = rp2->ancestors();
ancestors.insert(a2.begin(), a2.end());
}
//and make all the ancestors remember that they contributed.
for ( RealPartonSet::iterator it = ancestors.begin(); it != ancestors.end(); it++ ) {
(*it)->interactions.insert(intDip);
}
}
tRealPartonPtr RealPartonState::getReal(tPartonPtr p) {
//If the parton already exists in the real state, just retur
//the real parton.
map<tPartonPtr,RealPartonPtr>::iterator it = partons.lower_bound(p);
if ( it->first == p ) return it->second;
//Otherwise create a new realparton for the parton.
RealPartonPtr rp = new_ptr(RealParton(p));
rp->realState = this;
//fluct -1 means that they are not a fluctuation,
//ie they are not (yet) set up to be merged with an other partons.
rp->fluct = -1;
rp->cFluct = -1;
//insert in the right place in the ordered map of parton -> realparton.
if ( it != partons.begin() ) partons.insert(--it, make_pair(p, rp));
else partons.insert(make_pair(p, rp));
return rp;
}
tRealPartonPtr RealPartonState::addParton(tPartonPtr p) {
if ( !p ) return RealPartonPtr();
if ( partons.lower_bound(p)->first == p ) return getReal(p);
RealPartonPtr rp = getReal(p);
rp->nMothers = 2;
if ( !(p->valence()) && rp->interactions.size() == 0 ) {
if ( Current<DipoleEventHandler>()->eventFiller().singleMother() &&
!p->swingedEmission() ) {
rp->nMothers = 1;
double P1 = p->dist2(*p->parents().second)/
(p->dist2(*p->parents().second) + p->dist2(*p->parents().first));
if ( P1 > UseRandom::rnd() ) {//pick feynman diagram
rp->setOMother(addParton(p->parents().first));
}
else
rp->setOMother(addParton(p->parents().second));
}
else {
rp->setFirstOMother(addParton(p->parents().first));
rp->setSecondOMother(addParton(p->parents().second));
}
}
if ( p->valence() && rp->interactions.size() == 0 ) {
valence.insert(rp);
rp->setYES();
}
else toCheck.insert(rp);
return rp;
}
void RealPartonState::addValence(DipoleState & state) {
if ( Debug::level > 5 ) cout << "entering addvalence" << endl;
plus = state.plus();
minus = state.minus();
if ( Debug::level > 5 ) cout << " total plus and minus set to " << plus/GeV << ", " << minus/GeV << endl;
monitored = false;
totalRecoil = TransverseMomentum(ZERO, ZERO);
if ( Debug::level > 5 ) cout << " total recoil set to 0" << endl;
vector<DipolePtr> valenceDip = state.initialDipoles();
for ( int i = 0; i < int(valenceDip.size()); i++) {
tRealPartonPtr p1 = addParton(valenceDip[i]->partons().first);
tRealPartonPtr p2 = addParton(valenceDip[i]->partons().second);
p1->cValence = true;
p1->cValencePlus = p1->theParton->valencePlus();
p1->cValencePT = p1->theParton->valencePT();
p2->cValence = true;
p2->cValencePlus = p2->theParton->valencePlus();
p2->cValencePT = p2->theParton->valencePT();
oValence.insert(p1);
oValence.insert(p2);
}
}
void RealPartonState::merge(RealPartonPtr rp1, RealPartonPtr rp2) {
if ( Debug::level > 5 )
cout << "merging partons at y = " << rp1->oY() << ", " << rp2->oY() << " or ("
<< rp1->theParton->position().x()*GeV << ", " << rp1->theParton->position().y()*GeV << "), ("
<< rp2->theParton->position().x()*GeV << ", " << rp2->theParton->position().y()*GeV << ")\n";
if ( rp1->fluct != -1 && rp2->fluct != -1 ) {
//merge flucts if different (can they already be in same?)
if ( rp1->fluct != rp2->fluct ) {
flucts[rp1->fluct].insert(flucts[rp2->fluct].begin(), flucts[rp2->fluct].end());
int old = rp2->fluct;
for ( RealPartonSet::iterator it = flucts[old].begin(); it != flucts[old].end(); it++ )
(*it)->fluct = rp1->fluct;
flucts[old].clear();
}
}
else if ( rp1->fluct != -1 ) {
rp2->fluct = rp1->fluct;
flucts[rp1->fluct].insert(rp2);
}
else if ( rp2->fluct != -1 ) {
rp1->fluct = rp2->fluct;
flucts[rp2->fluct].insert(rp1);
}
else {
flucts.push_back(RealPartonSet());
int i = flucts.size() - 1;
flucts[i].insert(rp1);
flucts[i].insert(rp2);
rp1->fluct = i;
rp2->fluct = i;
}
// redistributePlus(flucts[rp1->fluct]);
//dela upp p+ och pT jamnt mellan de virtuella
makeCollinear(flucts[rp1->fluct]);
if ( Debug::level > 5 ) cout << " done merging" << endl;
}
void RealPartonState::makeCollinear(const RealPartonSet & rps) {
if ( rps.empty() ) return;
Energy avPlus = ZERO;
TransverseMomentum avPT = TransverseMomentum();
for ( RealPartonSet::const_iterator it = rps.begin(); it != rps.end(); it++ ) {
avPlus += (*it)->plus;
avPT += (*it)->pT;
}
avPlus /= rps.size();
avPT /= rps.size();
for ( RealPartonSet::const_iterator it = rps.begin();
it != rps.end(); it++ ) {
(*it)->plus = avPlus;
(*it)->pT = avPT;
(*it)->updateYMinus();
}
}
void RealPartonState::redistributePlus(const RealPartonSet & rps) {
if ( rps.empty() ) return;
Energy totalPlus = ZERO;
double totalWeight = ZERO;
for ( RealPartonSet::const_iterator it = rps.begin();
it != rps.end(); it++ ) {
totalWeight += exp(-(*it)->oY());
totalPlus += (*it)->plus;
}
for ( RealPartonSet::const_iterator it = rps.begin();
it != rps.end(); it++ ) {
(*it)->plus = totalPlus*exp(-(*it)->oY())/totalWeight;
(*it)->updateYMinus();
// cout << " redistributed plus at " << (*it)->oY() << " to " << (*it)->plus/GeV
// << ", relative y is " << -log(exp(-(*it)->oY())/totalWeight) << endl;
}
}
void RealPartonState::splitFluct(RealPartonPtr rp1, RealPartonPtr rp2) {
// cout << "entered splitFluct with rps " << rp1->oY() << ", " << rp2->oY() << "!\n";
// diagnosis(true);
if ( rp1->fluct == -1 || rp2->fluct == -1 ) {
// cout << "asked to split a fluct where the partons werent in a fluct" << endl;
return;
}
else if ( rp1->fluct != rp2->fluct ) {
// cout << "asked to split a fluct that is already split" << endl;
return;
}
int i = rp1->fluct;
//create two new flucts with rp1 and rp2
flucts.push_back(RealPartonSet());
int i1 = flucts.size() - 1;
flucts[i1].insert(rp1);
flucts.push_back(RealPartonSet());
int i2 = flucts.size() - 1;
flucts[i2].insert(rp2);
// cout << " created new flucts " << i1 << " and " << i2 << ", old was " << i << endl;
//move all other partons to the fluct belonging to the closest parton.
for ( RealPartonSet::iterator it = flucts[i].begin(); it != flucts[i].end(); it++) {
if ((*it)->theParton->dist2(*rp1->theParton) < (*it)->theParton->dist2(*rp2->theParton) ) {
// cout << " move " << (*it)->oY() << " to " << i1 << endl;
(*it)->fluct = i1;
flucts[i1].insert(*it);
}
else {
// cout << " move " << (*it)->oY() << " to " << i2 << endl;
(*it)->fluct = i2;
flucts[i2].insert(*it);
}
}
// cout << " empty old fluct" << endl;
flucts[i].clear();
//find highest oY parton.
RealPartonPtr firstRP = (rp1->oY() < rp2->oY() ) ? rp1:rp2;
RealPartonPtr secondRP = (rp1->oY() < rp2->oY() ) ? rp2:rp1;
//let the higher oY recoil to the lower if they are connected. pT only, no plus transfer.
if ( secondRP->mothers.first == firstRP ) {
// cout << firstRP->oY() << " is first mother of " << secondRP << endl;
secondRP->pT += secondRP->theParton->recoil(firstRP->theParton);
secondRP->updateYMinus();
InvEnergy range = sqrt(min(secondRP->theParton->dist2(*firstRP->theParton),
firstRP->theParton->dist2(*secondRP->mothers.second->theParton)/4.0));
secondRP->doEffectiveRecoil(firstRP, range, true, ZERO,
secondRP->theParton->recoil(firstRP->theParton));
}
else if ( secondRP->mothers.second == firstRP ) {
secondRP->pT += secondRP->theParton->recoil(firstRP->theParton);
secondRP->updateYMinus();
InvEnergy range = sqrt(min(secondRP->theParton->dist2(*firstRP->theParton),
firstRP->theParton->dist2(*secondRP->mothers.first->theParton)/4.0));
secondRP->doEffectiveRecoil(firstRP, range, false, ZERO,
secondRP->theParton->recoil(firstRP->theParton));
}
makeCollinear(flucts[i1]);
makeCollinear(flucts[i2]);
// diagnosis(true);
//given yminus should be ok I hope?
}
bool RealPartonState::isMotherStepUp(tRealPartonPtr mom, bool firstSide, InvEnergy scale) {
if ( mom->theParton->valence() ) return false;
tRealPartonPtr grandMom = (firstSide ? mom->mothers.first:mom->mothers.second);
if ( mom->nMothers == 1 ) grandMom = mom->mother;
if ( firstSide && (!mom->children.first.empty() || !mom->firstInt) ) return false;
if ( !firstSide && (!mom->children.second.empty() || !mom->secondInt) ) return false;
if ( mom->theParton->dist2(*grandMom->theParton) > sqr(scale) ) return false;
else return true;
}
bool RealPartonState::inFSRRegion(tRealPartonPtr rp) {
//valence are always ok
if ( rp->theParton->valence() ) return false;
//if parton is outside, but not to an interaction
if ( isOutside(rp, true) ) {
RealPartonPtr mom = (rp->nMothers == 1 ? rp->mother:rp->mothers.first);
//merged partons will share the momentum, and thus only have 1/N of the pt.
int nMerged = 1;
if ( rp->fluct != -1 ) nMerged = flucts[rp->fluct].size();
//check ordering with outside partons without effective partons
//dont chek if already merged, and account for that plus and minus is shared
//between merged partons
if ( !(mom->fluct != -1 && mom->fluct == rp->fluct) ) {
if ( Debug::level > 5 ) cout << "checking FSR PS for " << rp->oY() << ", mom: "
<< mom->oY() << endl;
int nMomMerged = 1;
if ( mom->fluct != -1 ) nMomMerged = flucts[mom->fluct].size();
if ( mom->minus*double(nMomMerged) > rp->minus*double(nMerged) ) return true;
}
//dont bother to check child if rp is interacting since
//we dont know where the other parton is yet
if ( !rp->secondInt && !rp->children.second.empty() ) {
RealPartonPtr child = *rp->children.second.rbegin();
if ( !(child->fluct != -1 && child->fluct == rp->fluct) ) {
if ( Debug::level > 5 ) cout << "checking FSR PS for " << rp->oY()
<< ", child: " << child->oY() << endl;
int nChildMerged = 1;
if ( child->fluct != -1 ) nChildMerged = flucts[child->fluct].size();
if ( child->plus*double(nChildMerged) > rp->plus*double(nMerged) ) return true;
}
}
}
//and check for outside on the other side in the same way.
if ( isOutside(rp, false) ) {
RealPartonPtr mom = (rp->nMothers == 1 ? rp->mother:rp->mothers.second);
//merged partons will share the momentum, and thus only have 1/N of the pt.
int nMerged = 1;
if ( rp->fluct != -1 ) nMerged = flucts[rp->fluct].size();
//check ordering with outside partons without effective partons
//dont chek if already merged, and account for that plus and minus is shared
//between merged partons
if ( !(mom->fluct != -1 && mom->fluct == rp->fluct) ) {
if ( Debug::level > 5 ) cout << "checking FSR PS for " << rp->oY() << ", mom: "
<< mom->oY() << endl;
int nMomMerged = 1;
if ( mom->fluct != -1 ) nMomMerged = flucts[mom->fluct].size();
if ( mom->minus*double(nMomMerged) > rp->minus*double(nMerged) ) return true;
}
//dont bother to check child if rp is interacting since
//we dont know where the other parton is yet
if ( !rp->firstInt && !rp->children.first.empty() ) {
RealPartonPtr child = *rp->children.first.rbegin();
if ( !(child->fluct != -1 && child->fluct == rp->fluct) ) {
if ( Debug::level > 5 ) cout << "checking FSR PS for " << rp->oY()
<< ", child: " << child->oY() << endl;
int nChildMerged = 1;
if ( child->fluct != -1 ) nChildMerged = flucts[child->fluct].size();
if ( child->plus*double(nChildMerged) > rp->plus*double(nMerged) ) return true;
}
}
}
return false;
}
void RealPartonState::fixFSRDoubleCounting(tRealPartonPtr rp) {
RealPartonPtr mom;
if ( rp->nMothers == 1 ) mom = rp->mother;
else if ( isOutside(rp, true) ) mom = rp->mothers.first;
else mom = rp->mothers.second;
if ( rp->fluct != -1 && rp->fluct == mom->fluct ) return;
if ( Debug::level > 5 ) cout << rp->oY() << " is FSR Double Counted with respect to "
<< mom->oY() << ". Merge." << endl;
if ( !rp->recoils.empty() ) {
TransverseMomentum pT;
if ( rp->nMothers == 1 ) pT = rp->theParton->recoil(mom->theParton);
else pT = rp->theParton->recoil(rp->mothers.first->theParton) +
rp->theParton->recoil(rp->mothers.second->theParton);
if ( Debug::level > 5 ) cout << "removing pT (" << pT.x()/GeV << ", " << pT.y()/GeV << ")" << endl;
rp->pT -= pT;
rp->plus -= pT.pt()*exp(-rp->oY());
rp->undoRecoils();
if ( rp->plus < ZERO ) fixNegativePlus(rp);
}
merge(rp, mom);
if ( Debug::level > 5 ) cout << "fixed FSR double counting." << endl;
}
Energy RealPartonState::fixNegativePlus(RealPartonPtr rp) {
//if already nonnegative, nothing has to be done.
if ( rp->plus >= ZERO ) return rp->plus;
//valence partons cant be helped, since there are no parents.
if ( rp->theParton->valence() ) {
cerr << "valence parton with negative plus in RealPartonState::fixNegativePlus" << endl;
return rp->plus;
}
if ( rp->nMothers == 1 ) {
InvEnergy range = sqrt(rp->theParton->dist2(*rp->mother->theParton));
Energy totalPlus = rp->mother->effectivePlusMinus(range, true).first + rp->plus;
//check that there is enough plus in parents, otherwise return false.
if ( totalPlus < ZERO ) {
Throw<RealPartonKinematicException>()
<< "not enough plus in single parent to balance negative plus in "
<< "RealPartonState::fixNegativePlus" << Exception::warning;
return rp->plus;
}
//if enough, divide up so that the parton takes 10% of the effective parents plus.
rp->doEffectiveRecoil(rp->mother, range, true,
-rp->plus + totalPlus/10.0, TransverseMomentum());
rp->plus = totalPlus/10.0;
return totalPlus/10.0;
}
else if ( rp->nMothers == 2 ) {
RealPartonPtr mom1 = rp->mothers.first;
RealPartonPtr mom2 = rp->mothers.second;
InvEnergy range1 = sqrt(min(rp->theParton->dist2(*mom1->theParton),
mom2->theParton->dist2(*mom1->theParton)/4.0));
InvEnergy range2 = sqrt(min(rp->theParton->dist2(*mom2->theParton),
mom1->theParton->dist2(*mom2->theParton)/4.0));
Energy plus1 = mom1->effectivePlusMinus(range1, true).first;
Energy plus2 = mom2->effectivePlusMinus(range2, false).first;
Energy parentPlus = plus1 + plus2;
Energy totalPlus = parentPlus + rp->plus;
//check that there is enough plus in parents, otherwise return false.
if ( parentPlus + rp->plus < ZERO ) {
Throw<RealPartonKinematicException>()
<< "not enough plus in parents to balance negative plus in "
<< "RealPartonState::fixNegativePlus" << Exception::warning;
return rp->plus;
}
//if enough, give enough to put plus to 0
rp->doEffectiveRecoil(mom1, range1, true,
-rp->plus*plus1/parentPlus + totalPlus*plus1/parentPlus/10.0,
TransverseMomentum());
rp->doEffectiveRecoil(mom2, range2, false,
-rp->plus*plus2/parentPlus + totalPlus*plus2/parentPlus/10.0,
TransverseMomentum());
rp->plus = totalPlus/10.0;
return totalPlus/10.0;
}
return rp->plus;
}
bool RealPartonState::isOutside(tRealPartonPtr rp, bool firstSide) {
//to be outside, there can be neither kids not an interaction on one side
//the other side has to have either an interaction or a child. also valence dont count.
if ( (firstSide || rp->nMothers == 1) && rp->children.first.empty() && !rp->firstInt &&
( rp->secondInt || !rp->children.second.empty() ) && !rp->theParton->valence() )
return true;
if ( (!firstSide || rp->nMothers == 1) && rp->children.second.empty() && !rp->secondInt &&
( rp->firstInt || !rp->children.first.empty() ) && !rp->theParton->valence() )
return true;
return false;
}
InvEnergy RealPartonState::childScale(tRealPartonPtr rp, bool firstSide) {
InvEnergy ret = ZERO;
if ( !rp->interacting ) { //if no interaction, then take last child
if ( firstSide ? rp->children.second.empty():rp->children.first.empty() ) return ZERO;
RealPartonPtr child = (firstSide ? *rp->children.second.rbegin():
*rp->children.first.rbegin());
if ( Debug::level > 5 ) cout << " child is " << child->oY() << endl;
ret = sqrt(rp->theParton->dist2(*child->theParton));
if ( Debug::level > 5 ) cout << " child dist is " << ret*GeV << endl;
if (rp->fluct != -1 && child->fluct == rp->fluct) {
ret = childScale(child, firstSide);
if ( Debug::level > 5 ) cout << " in same fluct, recur " << endl;
}
else {
InvEnergy childDist = min(child->intDist, Current<DipoleEventHandler>()->coherenceRange());
if ( child->interacting && child->resolutionScales.lower_bound(rp)->first == rp &&
child->resolutionScales[rp] <
- sqr(childDist)*Current<DipoleEventHandler>()->alphaS(childDist) ) {
+ sqr(childDist)*Current<DipoleEventHandler>()->alphaSr(childDist) ) {
ret = child->intDist;
if ( Debug::level > 5 ) cout << " child is merged int, new scale: " << ret*GeV << endl;
}
}
}
else {
ret = rp->intDist;
if ( Debug::level > 5 ) cout << " intdist is " << ret*GeV << endl;
}
return ret;
}
bool RealPartonState::checkFixSingleDGLAP(RealPartonPtr rp, InvEnergy scale) {
if ( rp->DGLAPchecked ) return true;
rp->DGLAPchecked = true;
tRealPartonPtr mom = rp->mother;
if ( Debug::level > 5 ) cout << rp->oY() << " is outside (single). mother: " << mom->oY() << endl;
//if the parton is already tagged to merge with the mother, then dont do anything
if ( rp->fluct != -1 && mom->fluct == rp->fluct ) {
if ( Debug::level > 5 ) cout << " already merged, nm." << endl;
return false;
}
if ( isOutside(rp, true) ) {
//if no scale (distance to mother and child) was supplied, then calculate them
if ( scale == ZERO ) scale = childScale(rp, true);
// *** ATTENTION *** not used: InvEnergy motherScale = sqrt(rp->theParton->dist2(*(mom->theParton)));
//check if mom is a further step up in pt, then check her first, with this scale
if ( isMotherStepUp(mom, true, scale) || isMotherStepUp(mom, false, scale) ) {
//if the higher backwards pt max is safe, then this is also ok.
if ( checkFixDGLAP(mom, scale) ) {
if ( Debug::level > 5 ) cout << mom->oY() << " is safe. then so is " << rp->oY() << endl;
return true;
}
}
//compare to mother and fix if not safe
if ( !rp->DGLAPSafe(scale) ) {
fixDGLAP(rp);
return false;
}
}
if ( isOutside(rp, false) ) {
//if no scale (distance to mother and child) was supplied, then calculate them
if ( scale == ZERO ) scale = childScale(rp, false);
// *** ATTENTION *** not used: InvEnergy motherScale = sqrt(rp->theParton->dist2(*(mom->theParton)));
//check if mom is a further step up in pt, then check her first, with this scale
if ( isMotherStepUp(mom, true, scale) || isMotherStepUp(mom, false, scale) ) {
//if the higher backwards pt max is safe, then this is also ok.
if ( checkFixDGLAP(mom, scale) ) {
if ( Debug::level > 5 ) cout << mom->oY() << " is safe. then so is " << rp->oY() << endl;
return true;
}
}
//compare to mother and fix if not safe
if ( !rp->DGLAPSafe(scale) ) {
fixDGLAP(rp);
return false;
}
}
return true;
}
void RealPartonState::fixSingleDGLAP(RealPartonPtr rp) {
if ( rp->fluct != -1 && rp->fluct == rp->mother->fluct )
return; //already merged with the mother.
else if ( rp->fluct != -1 && rp->recoils.empty() ) {
if ( !rp->interacting )
merge(rp, rp->mother); //no recoils that has to be undone.
return;
}
TransverseMomentum pT = rp->theParton->recoil(rp->mother->theParton);
rp->pT -= pT; //remove rec from itself
Energy originalPlus = (pT).pt()*exp(-rp->oY());
rp->plus -= originalPlus;
rp->undoRecoils();
//now readd some recoil limited by the DGLAP scale.
InvEnergy r = ZERO;
if ( rp->interacting ) r = rp->intDist;
else if ( !rp->children.first.empty() )
r = sqrt((*rp->children.first.rbegin())->theParton->dist2(*rp->theParton));
else if ( !rp->children.second.empty() )
r = sqrt((*rp->children.second.rbegin())->theParton->dist2(*rp->theParton));
else cerr << "fixing single DGLAP, but no children, or interaction scales!" << endl;
//find from the resolutionscale (alpha_s(r)*r^2) what the minimum r couldve been.
//since alpha_s(r) has no analytic inverse, do 3 recursive steps from cohernce range.
if ( r > Current<DipoleEventHandler>()->coherenceRange() )
r = Current<DipoleEventHandler>()->coherenceRange();
InvEnergy resScale = sqrt(rp->resolutionScales[rp->mother]/
- Current<DipoleEventHandler>()->alphaS(r));
+ Current<DipoleEventHandler>()->alphaSr(r));
resScale = sqrt(rp->resolutionScales[rp->mother]/
- Current<DipoleEventHandler>()->alphaS(resScale));
+ Current<DipoleEventHandler>()->alphaSr(resScale));
resScale = sqrt(rp->resolutionScales[rp->mother]/
- Current<DipoleEventHandler>()->alphaS(resScale));
+ Current<DipoleEventHandler>()->alphaSr(resScale));
double penalty = resScale/r;
if ( !rp->interacting || true )
penalty = 0.0;
else if ( Debug::level > 5 ) {
cout << " SINGLE: penalty for " << rp->oY() << " is " << penalty << ", PT1 to " << rp->mother->oY()
<< " goes from " << pT.pt()/GeV << " to "
<< penalty*pT.pt()/GeV << endl;
}
Energy plusRec = (penalty*pT).pt()*exp(-rp->oY());
rp->pT += penalty*pT;
rp->plus += plusRec;
rp->doEffectiveRecoil(rp->mother, sqrt(rp->theParton->dist2(*rp->mother->theParton)),
true, plusRec, penalty*pT);
if ( !rp->interacting || true )
merge(rp, rp->mother);
else if ( rp->plus < ZERO || rp->mother->plus < ZERO ) {
merge(rp, rp->mother);
}
if ( (rp->plus < ZERO || rp->mother->plus < ZERO) )
cerr << "negative p+ after fixsingleDGLAP! :o" << endl;
}
bool RealPartonState::checkFixDGLAP(RealPartonPtr rp, InvEnergy scale) {
if ( rp->DGLAPchecked ) return true;
rp->DGLAPchecked = true;
//DGLAP should be checked only for partons on the "outside" of a chain.
//if it is
if ( isOutside(rp, true) ) { //if kids/interaction on only second side
tRealPartonPtr mom;
if ( rp->nMothers == 1 ) mom = rp->mother;
else mom = rp->mothers.first;
if ( Debug::level > 5 ) cout << rp->oY() << " is outside 1. mother: " << mom->oY() << endl;
//if the parton is already tagged to merge with the mother, then dont do anything
if ( rp->fluct != -1 && mom->fluct == rp->fluct ) {
if ( Debug::level > 5 ) cout << rp->oY() << " already merged, nm." << endl;
return false;
}
//if no scale (distance to mother and child) was supplied, then calculate them
if ( scale == ZERO ) scale = childScale(rp, true);
InvEnergy motherScale = sqrt(rp->theParton->dist2(*(mom->theParton)));
if ( Debug::level > 5 ) cout << rp->oY() << " scale: " << scale*GeV
<< ", motherscale: " << motherScale*GeV << endl;
//if grandmother is a further step up in pt, then go there and check first
//then compare to THIS childs scale, to get full suppression
if ( isMotherStepUp(mom, true, motherScale) || isMotherStepUp(mom, false, motherScale) ) {
if ( Debug::level > 5 ) cout << " mother is step up. recur to " << mom->oY() << endl;
//if the higher backwards pt max is safe, then this is also ok.
if ( checkFixDGLAP(mom, scale) ) {
if ( Debug::level > 5 ) cout << mom->oY() << " is safe. then so is " << rp->oY() << endl;
return true;
}
//if the backwards max is removed, then this is the new max, and should be checked
}
if ( Debug::level > 5 ) cout << " checkDGLAPsafe." << endl;
//check if the recoil should be removed or not
if ( !rp->checkDGLAPSafe(mom, rp, scale) ) {
fixDGLAP(rp);
return false;
}
}
//the same thing, if kids/interaction on only first side
if ( isOutside(rp, false) ) {
tRealPartonPtr mom;
if ( rp->nMothers == 1 ) mom = rp->mother;
else mom = rp->mothers.second;
if ( Debug::level > 5 ) cout << rp->oY() << " is outside 2. mother: " << mom->oY() << endl;
if ( rp->fluct != -1 && mom->fluct == rp->fluct ) {
if ( Debug::level > 5 ) cout << rp->oY() << " already merged, nm." << endl;
return false;
}
if ( scale == ZERO ) scale = childScale(rp, false);
InvEnergy motherScale = sqrt(rp->theParton->dist2(*(mom->theParton)));
if ( Debug::level > 5 ) cout << rp->oY() << " scale: " << scale*GeV
<< ", motherscale: " << motherScale*GeV << endl;
if ( isMotherStepUp(mom, true, motherScale) || isMotherStepUp(mom, false, motherScale) ) {
if ( Debug::level > 5 ) cout << " mother is step up. recur to " << mom->oY() << endl;
if ( checkFixDGLAP(mom, scale) ) {
if ( Debug::level > 5 ) cout << mom->oY() << " is safe. then so is " << rp->oY() << endl;
return true;
}
}
if ( Debug::level > 5 ) cout << " checkDGLAPsafe." << endl;
if ( !rp->checkDGLAPSafe(mom, rp, scale) ) {
fixDGLAP(rp);
return false;
}
}
if ( Debug::level > 5 ) cout << rp->oY() << " is not outside" << endl;
return true;
}
void RealPartonState::fixDGLAP(RealPartonPtr rp) {
if ( Debug::level > 5 && monitored ) cout << rp->oY() << " is unordered. Remove." << endl;
if ( rp->nMothers == 1 ) {
fixSingleDGLAP(rp);
return;
}
RealPartonPtr mother = ((rp->children.first.empty() && !rp->firstInt) ? rp->mothers.first:rp->mothers.second);
if ( rp->fluct != -1 && flucts[rp->fluct].find(mother) != flucts[rp->fluct].end() ) {
return; //already merged with the mother.
}
else if ( rp->fluct != -1 && rp->recoils.empty() ) {
if ( !rp->interacting )
merge(rp, mother); //recoils already undone, dont reundo them.
return;
}
if ( (rp->plus < ZERO || mother->plus < ZERO) && Debug::level > 5 )
cerr << "negative p+ before fixdglap" << endl;
//remove recoil between itself and other mother, but save recs from future emissions.
//recoil with merging mother doesnt matter, since averaged anyways.
RealPartonPtr otherMother = (mother == rp->mothers.first) ?
rp->mothers.second:rp->mothers.first;
TransverseMomentum pT1 = rp->theParton->recoil(mother->theParton);
TransverseMomentum pT2 = rp->theParton->recoil(otherMother->theParton);
rp->pT -= pT1 + pT2; //remove rec from itself
rp->plus -= (pT1 + pT2).pt()*exp(-rp->oY());
rp->undoRecoils();
//now readd some recoil limited by the DGLAP scale.
InvEnergy r2;
if ( rp->interacting ) r2 = rp->intDist;
else {
if ( mother == rp->mothers.first )
r2 = sqrt((*rp->children.second.rbegin())->theParton->dist2(*rp->theParton));
else
r2 = sqrt((*rp->children.first.rbegin())->theParton->dist2(*rp->theParton));
}
if ( r2 > Current<DipoleEventHandler>()->coherenceRange() )
r2 = Current<DipoleEventHandler>()->coherenceRange();
InvEnergy resScale = sqrt(rp->resolutionScales[mother]/
- Current<DipoleEventHandler>()->alphaS(r2));
+ Current<DipoleEventHandler>()->alphaSr(r2));
resScale = sqrt(rp->resolutionScales[mother]/
- Current<DipoleEventHandler>()->alphaS(resScale));
+ Current<DipoleEventHandler>()->alphaSr(resScale));
resScale = sqrt(rp->resolutionScales[mother]/
- Current<DipoleEventHandler>()->alphaS(resScale));
+ Current<DipoleEventHandler>()->alphaSr(resScale));
double penalty = resScale/r2;
if ( !rp->interacting )
penalty = 0.0;
else if ( Debug::level > 5 ) {
cout << " penalty for " << rp->oY() << " is " << penalty << ", PT1 to " << mother->oY()
<< " goes from " << pT1.pt()/GeV << " to "
<< penalty*pT1.pt()/GeV << endl;
}
double P1 = rp->theParton->dist2(*otherMother->theParton)/
(rp->theParton->dist2(*mother->theParton) + rp->theParton->dist2(*otherMother->theParton));
double P2 = 1.0 - P1;
Energy plusRec = (penalty*pT1 + pT2).pt()*exp(-rp->oY());
rp->pT += penalty*pT1 + pT2;
rp->plus += plusRec;
if ( Debug::level > 5 ) {
cout << " readding pT of (" << (penalty*pT1 + pT2).x()/GeV << ", "
<< (penalty*pT1 + pT2).y()/GeV << ")" << endl;
cout << " pT is (" << rp->pT.x()/GeV << ", " << rp->pT.y()/GeV << endl;
cout << "second plus recoil is " << P2*plusRec/GeV << endl;
}
rp->doEffectiveRecoil(mother, sqrt(min(rp->theParton->dist2(*mother->theParton), mother->theParton->dist2(*otherMother->theParton)/4.0)), mother == rp->mothers.first, P1*plusRec, penalty*pT1);
rp->doEffectiveRecoil(otherMother, sqrt(min(rp->theParton->dist2(*otherMother->theParton), mother->theParton->dist2(*otherMother->theParton)/4.0)), otherMother == rp->mothers.first, P2*plusRec, pT2);
if ( rp->plus + mother->plus < ZERO ) { //handle this case. should be kindof rare.
// if ( Debug::level > 5 ) cout << "returned too much plus in fixDGLAP. taking some back again... :/" << endl;
// if ( Debug::level > 5 ) cout << " plus is " << rp->plus/GeV << endl;
rp->doEffectiveRecoil(otherMother, sqrt(min(rp->theParton->dist2(*otherMother->theParton), mother->theParton->dist2(*otherMother->theParton)/4.0)), otherMother == rp->mothers.first, -rp->plus, TransverseMomentum());
rp->plus = ZERO;
}
if ( !rp->interacting || true )
merge(rp, mother);
else if ( rp->plus < ZERO || mother->plus < ZERO ) {
merge(rp, mother);
if ( (rp->plus < ZERO || mother->plus < ZERO) )
Throw<RealPartonKinematicException>()
<< "even after refix negative p+ after fixdglap with interacting!" << Exception::warning;
}
if ( otherMother->plus < ZERO ) {
merge(rp, mother);
merge(rp, otherMother);
}
if ( otherMother->plus < ZERO )
Throw<RealPartonKinematicException>()
<< "other mother in RealPartonState::fixDGLAP() has negative p+!" << Exception::warning;
}
void RealPartonState::fixUnOrdered(RealPartonPtr rp, bool forced) {
if ( !rp ) {
cerr << "fixUnOrdered called without a realparton!" << endl;
}
if ( rp->theParton->valence() ) return;
RealPartonPtr closestMother;
if ( rp->nMothers == 1 ) closestMother = rp->mother;
else
closestMother = ( (rp->theParton->dist2(*rp->mothers.first->theParton)
< rp->theParton->dist2(*rp->mothers.second->theParton))
? rp->mothers.first:rp->mothers.second);
//dont merge interacting unless forced
if ( rp->interacting && !forced && rp->nMothers == 2 ) {
//force the unordered parents to merge
if ( !rp->isFirstOrdered() && !rp->mothers.first->theParton->valence() )
fixUnOrdered(rp->mothers.first, true);
if ( !rp->isSecondOrdered() && !rp->mothers.second->theParton->valence() )
fixUnOrdered(rp->mothers.second, true);
return;
}
else if ( rp->interacting && !forced && rp->nMothers == 1 ) {
if ( !rp->isSingleOrdered() && !rp->mother->theParton->valence() )
fixUnOrdered(rp->mother, true);
return;
}
if ( rp->fluct != -1 && rp->fluct == closestMother->fluct ) {
if ( Debug::level > 5 && closestMother->theParton->valence() )
cout << "WARNING, recuring back to valence in RPS::fixUnOrdered" << endl;
fixUnOrdered(closestMother, forced);
return;
}
//remove recoil between itself and other mother, but save recs from future emissions.
//recoil with merging mother doesnt matter, since averaged anyways.
RealPartonPtr otherMother = (closestMother == rp->mothers.first) ?
rp->mothers.second:rp->mothers.first;
TransverseMomentum pT1 = rp->theParton->recoil(closestMother->theParton);
TransverseMomentum pT2;
if ( rp->nMothers == 1 ) pT2 = TransverseMomentum();
else pT2 = rp->theParton->recoil(otherMother->theParton);
rp->pT -= pT1 + pT2; //remove rec from itself
rp->plus -= (pT1 + pT2).pt()*exp(-rp->oY());
rp->undoRecoils();
merge(rp, closestMother);
}
bool RealPartonState::checkPlusMinus() {
Energy totalPlus = ZERO;
Energy totalMinus = ZERO;
Energy onShellMinus = ZERO;
for ( map<tPartonPtr,RealPartonPtr>::iterator it = partons.begin();
it != partons.end(); it++ ) {
tRealPartonPtr rp = (*it).second;
if ( rp->keep == RealParton::NO ) continue;
totalPlus += rp->plus;
totalMinus += rp->minus;
onShellMinus += rp->givenMinus;
if ( rp->theParton->valence() )
onShellMinus += sqr(rp->theParton->valencePT().pt())/rp->theParton->valencePlus();
}
if ( Debug::level > 5 ) cout << " total plus: " << totalPlus/GeV << endl
<< " total minus: " << totalMinus/GeV << endl
<< "onshell minus: " << onShellMinus/GeV << endl;
return true;
}
bool RealPartonState::checkForNegatives() {
bool ret = false;
for ( map<tPartonPtr,RealPartonPtr>::iterator it = partons.begin();
it != partons.end(); it++ ) {
tRealPartonPtr rp = (*it).second;
if ( rp->keep == RealParton::NO ) continue;
if ( rp->minus < ZERO ) {
// Throw<RealPartonKinematicException>()
// << "negative minus in real parton at oY " << rp->oY() << Exception::warning;
ret = true;
}
if ( rp->plus < ZERO ) {
// Throw<RealPartonKinematicException>()
// << "negative plus in real parton at oY " << rp->oY() << Exception::warning;
ret = true;
}
}
return ret;
}
bool RealPartonState::checkFlucts() {
bool ok = true;
for ( vector< RealPartonSet>::iterator it = flucts.begin(); it != flucts.end(); it++ ) {
RealPartonSet & fluct = *it;
if ( fluct.empty() ) continue;
Energy plus = (*fluct.begin())->plus;
Energy minus = (*fluct.begin())->minus;
Energy ptx = (*fluct.begin())->pT.x();
Energy pty = (*fluct.begin())->pT.y();
double oy = (*fluct.begin())->oY();
for( RealPartonSet::iterator jt = ++fluct.begin(); jt != fluct.end(); jt++) {
RealPartonPtr rp = *jt;
if ( abs((rp->plus - plus)/plus) > 0.01 ) {
ok = false;
if ( Debug::level > 5 )
cout << "real parton at " << rp->oY() << " has plus " << rp->plus/GeV << ", while "
<< oy << " in the same fluct has " << plus/GeV << endl;
}
if ( abs((rp->minus - minus)/minus) > 0.01 ) {
ok = false;
if ( Debug::level > 5 )
cout << "real parton at " << rp->oY() << " has minus " << rp->minus/GeV << ", while "
<< oy << " in the same fluct has " << minus/GeV << endl;
}
if ( abs((rp->pT.x() - ptx)/ptx) > 0.01 ) {
ok = false;
if ( Debug::level > 5 )
cout << "real parton at " << rp->oY() << " has ptx " << rp->pT.x()/GeV << ", while "
<< oy << " in the same fluct has " << ptx/GeV << endl;
}
if ( abs((rp->pT.y() - pty)/pty) > 0.01 ) {
ok = false;
if ( Debug::level > 5 )
cout << "real parton at " << rp->oY() << " has pty " << rp->pT.y()/GeV << ", while "
<< oy << " in the same fluct has " << pty/GeV << endl;
}
}
}
return ok;
}
void RealPartonState::mergeVirtuals() {
if ( !checkFlucts() ) {
Throw<RealPartonKinematicException>()
<< "the fluctuations are not collinear in mergevirtuals!!" << Exception::warning;
}
for ( vector< RealPartonSet>::iterator it = flucts.begin(); it != flucts.end(); it++ ) {
RealPartonSet & fluct = *it;
if ( fluct.empty() ) continue;
RealPartonPtr mother = *fluct.begin();
if ( Debug::level > 5 ) cout << "merging a fluct from " << mother->oY() << " with "
<< fluct.size() << " partons" << endl;
for( RealPartonSet::iterator jt = ++fluct.begin(); jt != fluct.end(); jt++) {
RealPartonPtr rp = *jt;
if ( rp->theParton->valence() ) {
if ( Debug::level > 5 ) cout << " dont merge valence partons!" << endl;
continue;
}
if ( Debug::level > 5 ) cout << " removing " << rp->oY() << endl;
if ( abs(mother->y - rp->y) > 0.00001 ) {
cout << " different y!!!! " << endl;
plotState(true);
}
mother->plus += rp->plus;
mother->pT += rp->pT;
rp->theParton->onShell(false);
rp->keep = RealParton::NO;
for ( RealPartonSet::iterator kt = rp->children.first.begin();
kt != rp->children.first.end(); kt++ ) {
if ( (*kt)->nMothers == 2 ) {
(*kt)->mothers.second = mother;
mother->children.first.insert(*kt);
}
if ( (*kt)->nMothers == 1 ) {
(*kt)->mother = mother;
mother->children.first.insert(*kt);
}
}
for ( RealPartonSet::iterator kt = rp->children.second.begin();
kt != rp->children.second.end(); kt++ ) {
if ( (*kt)->nMothers == 2 ) {
(*kt)->mothers.first = mother;
mother->children.second.insert(*kt);
}
if ( (*kt)->nMothers == 1 ) {
(*kt)->mother = mother;
mother->children.second.insert(*kt);
}
}
if ( !rp->theParton->valence() ) {
if ( rp->nMothers == 2 ) {
rp->mothers.first->children.second.erase(rp);
rp->mothers.second->children.first.erase(rp);
rp->mothers.first = RealPartonPtr();
rp->mothers.second = RealPartonPtr();
}
if ( rp->nMothers == 1 ) {
rp->mother->children.second.erase(rp);
rp->mother->children.first.erase(rp);
rp->mother = RealPartonPtr();
}
}
}
mother->updateYMinus();
// plotState(true);
}
// cout << "done merging\n";
}
void RealPartonState::doEvolution() {
// cout << "entering doEvolution" << endl;
for ( RealPartonSet::iterator it = toCheck.begin(); it != toCheck.end(); it++ ) {
RealPartonPtr rp = *it;
currentY = rp->theParton->oY();
if ( !rp->quickSetYES() ) {
rp->checkEmissionProblem();
break;
}
rp->checkEmissionProblem();
}
}
bool RealPartonState::findConsistentEvolution(RealPartonSet::iterator it) {
if ( it == toCheck.end() ) {
return true;}
partonCalls++;
if ( partonCalls > 1000000 ) {return false;}
tRealPartonPtr rp = *it;
currentY = rp->theParton->oY();
if ( !(rp->setYES()) ) {
unOrdered++;
if ( monitored && interactions.size() > 1 )
cout << "unordered" << endl;
// cout << rp->oY() << " unordered" << endl;
return rp->setNO();
}
if ( !rp->theParton->valence() && (!rp->mothers.first || !rp->mothers.second) ) {
if ( monitored && interactions.size() > 1 )
cout << "non-valence without mothers, NO" << endl;
// cout << rp->oY() << " mother structure error" << endl;
return rp->setNO();
}
if ( rp->mothers.first && rp->mothers.first == rp->mothers.second ) {
if ( monitored && interactions.size() > 1 )
cout << "samme mothers" << endl;
// cout << rp->oY() << " mother structure error" << endl;
return rp->setNO();
}
// cout << rp->oY() << " passed first tests. check." << endl;
bool existHistory = false;
while ( !existHistory ) {
existHistory = findConsistentEvolution(++it);
currentY = rp->theParton->oY();
if ( existHistory && !(rp->DGLAPSafe()) ) {
if ( monitored && interactions.size() > 1 )
cout << "unDGLAP" << endl;
// cout << rp->oY() << ", (" << rp->theParton->position().x()*GeV << ", "
// << rp->theParton->position().y()*GeV << ") is unDGLAP" << endl;
unDGLAP++;
rp->unDGLAP++;
existHistory = false;
}
if ( existHistory && !(rp->interacting) && !(rp->theParton->valence()) && !(rp->hasChild()) )
existHistory = false;
// if ( !existHistory && it != toCheck.end() ) {
// cout << rp->oY() << " found no history at " << (*it)->oY() << ", set future NO" << endl;
// // plotState(true);
// }
if ( !existHistory ) setFutureNO(rp); //behovs denna verkligen??
if ( !existHistory && (it == toCheck.end() || (*it)->interacting) ) return rp->setNO();
if ( !existHistory && (*it)->theParton->valence() ) return rp->setNO();
}
return existHistory;
}
bool RealPartonState::controlEvolution(tDipolePtr intDip, tDipolePtr otherIntDip) {
if ( failedInts.find(intDip) != failedInts.end() ) return false;
//think through how to do this without redoing the evolution!
if ( intDip->interacted() ) {
rescatter = true;
// return false; //removes rescattering
}
else rescatter = false;
unOrdered = 0;
unDGLAP = 0;
partonCalls = 0;
newInteraction(intDip, otherIntDip, true, true);
// checkOnlyNew(intDip);
checkHistory(getReal(intDip->partons().first));
checkHistory(getReal(intDip->partons().second));
checkFuture();
cout << "new evo------------------- " << toCheck.size() << " to check ---------------------" << endl;
cout << "-- interaction partons are " << getReal(intDip->partons().first)->oY() << " and "
<< getReal(intDip->partons().second)->oY() << endl;
// checkInteraction(intDip);
// cout << "starting real evo" << endl;
// diagnosis(true);
if ( (getReal(intDip->partons().first)->interactions.size() > 1 &&
getReal(intDip->partons().first)->keep == RealParton::NO) ||
(getReal(intDip->partons().second)->interactions.size() > 1 &&
getReal(intDip->partons().second)->keep == RealParton::NO) ) {
cout << "interacting valence NO" << endl;
revertToPrevious(intDip);
failedInts.insert(intDip);
return false;
}
if ( !toCheck.empty() && !rescatter ) { //think through rescatter. will intpT still be ok?
for ( RealPartonSet::iterator it = toCheck.begin(); !findConsistentEvolution(it); it++ ) {
if ( (*it)->interacting || (*it)->theParton->valence() ) {
cout << "failed evo, unordered: " << unOrdered << ", unDGLAP: " << unDGLAP << endl;
revertToPrevious(intDip);
failedInts.insert(intDip);
return false;
}
}
}
if ( !toCheck.empty() )
currentY = (**(--toCheck.end())).theParton->oY();
cout << "found evo" << endl;
// for ( RealPartonSet::iterator it = toCheck.begin(); it != toCheck.end(); it++ )
// (*it)->checkInteractionRecoils();
return true;
}
bool RealPartonState::singleControlEvolution(tDipolePtr intDip, tDipolePtr otherIntDip,
bool firstInt, bool secondInt,
Energy rec1, Energy rec2) {
ostream & log = CurrentGenerator::log();
static DebugItem printstepdetails("DIPSY::PrintStepDetails", 6);
static DebugItem checkkinematics("DIPSY::CheckKinematics", 6);
if ( failedInts.find(intDip) != failedInts.end() ) return false;
if ( intDip->interacted() ) {
if ( monitored )
cout << " rescatter, autopass evolution" << endl;
rescatter = true;
}
else rescatter = false;
if ( printstepdetails )
log << "<DIPSY> enter singlecontrolevolution." << endl;
unOrdered = 0;
unDGLAP = 0;
partonCalls = 0;
newInteraction(intDip, otherIntDip, firstInt, secondInt, rec1, rec2);
reset();
checkAllInteracting();
for ( RealPartonSet::iterator it = toCheck.begin(); it != toCheck.end(); it++ )
if ( !(*it)->setYES() ) fixUnOrdered(*it);
if ( printstepdetails ) log << "<DIPSY> done with forward sweep." << endl;
if ( monitored ) plotState(true);
for ( RealPartonSet::reverse_iterator it = toCheck.rbegin(); it != toCheck.rend(); it++ )
checkFixDGLAP(*it);
if ( printstepdetails )
log << "<DIPSY> done with DGLAP corrections." << endl;
if ( monitored ) plotState(true);
for ( RealPartonSet::iterator it = toCheck.begin(); it != toCheck.end(); it++ ) {
if ( inFSRRegion(*it) ) {
if ( printstepdetails )
log << "<DIPSY> FSR conflict found (check) at " << (*it)->oY() << endl;
fixFSRDoubleCounting(*it);
if ( printstepdetails ) log << " fixed, check." << endl;
}
}
if ( printstepdetails ) log << "<DIPSY> done with FSR matching" << endl;
if ( monitored ) plotState(true);
//make sure all fluctuations are collinear. In general not needed.
for ( int i = 0; i < int(flucts.size()); i++ ) {
makeCollinear(flucts[i]);
}
if ( checkkinematics && checkForNegatives() )
Throw<RealPartonKinematicException>()
<< "negatives found at end of cascade evo!" << Exception::warning;
return true;
}
bool RealPartonState::
singleControlEvolution(tDipolePtr intDip, tDipolePtr otherIntDip,
tPartonPtr parton, const TransverseMomentum & recoil) {
ostream & log = CurrentGenerator::log();
static DebugItem printstepdetails("DIPSY::PrintStepDetails", 6);
static DebugItem checkkinematics("DIPSY::CheckKinematics", 6);
if ( failedInts.find(intDip) != failedInts.end() ) return false;
if ( intDip->interacted() ) {
if ( monitored )
cout << " rescatter, autopass evolution" << endl;
rescatter = true;
}
else rescatter = false;
if ( printstepdetails )
log << "<DIPSY> enter singlecontrolevolution." << endl;
unOrdered = 0;
unDGLAP = 0;
partonCalls = 0;
newInteraction(intDip, otherIntDip, parton, recoil);
reset();
checkAllInteracting();
for ( RealPartonSet::iterator it = toCheck.begin(); it != toCheck.end(); it++ )
if ( !(*it)->setYES() ) fixUnOrdered(*it);
if ( printstepdetails ) log << "<DIPSY> done with forward sweep." << endl;
if ( monitored ) plotState(true);
for ( RealPartonSet::reverse_iterator it = toCheck.rbegin(); it != toCheck.rend(); it++ )
checkFixDGLAP(*it);
if ( printstepdetails )
log << "<DIPSY> done with DGLAP corrections." << endl;
if ( monitored ) plotState(true);
for ( RealPartonSet::iterator it = toCheck.begin(); it != toCheck.end(); it++ ) {
if ( inFSRRegion(*it) ) {
if ( printstepdetails )
log << "<DIPSY> FSR conflict found (check) at " << (*it)->oY() << endl;
fixFSRDoubleCounting(*it);
if ( printstepdetails ) log << " fixed, check." << endl;
}
}
if ( printstepdetails ) log << "<DIPSY> done with FSR matching" << endl;
if ( monitored ) plotState(true);
//make sure all fluctuations are collinear. In general not needed.
for ( int i = 0; i < int(flucts.size()); i++ ) {
makeCollinear(flucts[i]);
}
if ( checkkinematics && checkForNegatives() )
Throw<RealPartonKinematicException>()
<< "negatives found at end of cascade evo!" << Exception::warning;
return true;
}
bool RealPartonState::nonRecursiveControlEvolution(tDipolePtr intDip, tDipolePtr otherIntDip) {
if ( failedInts.find(intDip) != failedInts.end() ) return false;
if ( intDip->interacted() ) {
if ( monitored )
cout << " rescatter, autopass evolution" << endl;
rescatter = true;
}
else rescatter = false;
// cout << "entering nonrecursivecontrol\n";
// diagnosis(false);
unOrdered = 0;
unDGLAP = 0;
partonCalls = 0;
newInteraction(intDip, otherIntDip, true, true);
reset();
checkAllInteracting();
// cout << "enter loop to find evo------------------------------------------" << endl;
while ( true ) {
undoEmissions();
doEvolution();
// cout << "did evo" << endl;
RealPartonPtr worstProblem = findWorstProblem();
// if ( worstProblem )
// cout << "worst problem at " << worstProblem->oY() << ", ("
// << worstProblem->theParton->position().x()*GeV << ", "
// << worstProblem->theParton->position().y()*GeV << ")" << endl;
// else {
// cout << "no problem! evo ok for " << this << "" << endl;
// // diagnosis(false);
// }
if ( !worstProblem ) return true;
if ( !fix(worstProblem) ) {
// cout << "failed fixing theproblem, interaction failed" << endl;
revertToPrevious(intDip);
failedInts.insert(intDip);
return false;
}
}
}
bool RealPartonState::fullControlEvolution(tDipolePtr intDip, tDipolePtr otherIntDip,
bool firstInt, bool secondInt,
Energy rec1, Energy rec2) {
if ( intDip->dipoleState().handler().eventFiller().mode() == 1 )
return controlEvolution(intDip, otherIntDip);
if ( intDip->dipoleState().handler().eventFiller().mode() == 2 )
return singleControlEvolution(intDip, otherIntDip, firstInt, secondInt, rec1, rec2);
if ( intDip->dipoleState().handler().eventFiller().mode() == 3 )
return nonRecursiveControlEvolution(intDip, otherIntDip);
if ( failedInts.find(intDip) != failedInts.end() ) return false;
//think through how to do this without redoing the evolution!
if ( intDip->interacted() ) {
if ( monitored )
cout << " rescatter, autopass evolution" << endl;
rescatter = true;
cout << "rescatter!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
// return false; //removes rescattering
}
else rescatter = false;
unOrdered = 0;
unDGLAP = 0;
partonCalls = 0;
newInteraction(intDip, otherIntDip, true, true);
reset();
checkAllInteracting();
cout << "new evo---------------------------------------------------------" << endl;
for ( RealPartonSet::iterator it = toCheck.begin(); !findConsistentEvolution(it); it++ ) {
if ( (*it)->interacting || (*it)->theParton->valence() ) {
// cout << "failed evo, unordered: " << unOrdered << ", unDGLAP: " << unDGLAP << endl;
// for ( RealPartonSet::iterator jt = toCheck.begin(); jt != toCheck.end(); jt++ ) {
// (*jt)->setYES();
// }
// plotState(true);
revertToPrevious(intDip);
failedInts.insert(intDip);
return false;
}
}
cout << " found consistent evolution!" << endl;
// diagnosis(false);
// cout << "checked" << endl;
currentY = (**(--toCheck.end())).theParton->oY();
// cout << " did " << partonCalls << " calls on " << toCheck.size() << " partons.";
return true;
}
void RealPartonState::reset() {
for ( RealPartonSet::iterator it = oValence.begin(); it != oValence.end(); it++ ) {
(*it)->setYES();
}
for ( map<tPartonPtr,RealPartonPtr>::iterator it = partons.begin();
it != partons.end(); it++ ) {
(*it).second->givenMinus = ZERO;
(*it).second->fluct = -1;
(*it).second->DGLAPchecked = false;
if ( (*it).second->keep == RealParton::YES && !(*it).second->theParton->valence() ) {
(*it).second->setNO();
}
(*it).second->intRecoil = TransverseMomentum();
}
// for ( RealPartonSet::iterator it = valence.begin(); it != valence.end(); it++ ) {
// (*it)->setYES();
// }
totalRecoil = TransverseMomentum();
backwardsPartons.clear();
flucts.clear();
suspects.clear();
toCheck.clear();
minusDeficit = (*interactions.begin())->dipoleState().minusDeficit();
}
void RealPartonState::undoEmissions() {
for ( RealPartonSet::reverse_iterator it = toCheck.rbegin();
it != toCheck.rend(); it++ ) {
RealPartonPtr rp = *it;
if ( !rp->theParton->valence() )
rp->setNO();
else {
if ( rp->mothers.first ) rp->mothers.first->children.second.erase(rp);
if ( rp->mothers.second ) rp->mothers.second->children.first.erase(rp);
rp->quickSetYES();
}
}
}
void RealPartonState::checkOnlyNew(tDipolePtr intDip) {
cout << "implement checkonlynew if you really want to use it!!" << endl;
// toCheck.clear();
// //interacting partons cannot be left NO, even if earlier evos did so.
// if ( getReal(intDip->partons().first)->keep == RealParton::NO )
// toCheck.insert(getReal(intDip->partons().first));
// if ( getReal(intDip->partons().second)->keep == RealParton::NO )
// toCheck.insert(getReal(intDip->partons().second));
// for ( map<tPartonPtr,RealPartonPtr>::iterator it = partons.begin();
// it != partons.end(); it++ ) {
// if ( ((*it).second->interactions.size() == 1) &&
// (*it).second->interactions.find(intDip) != (*it).second->interactions.end() ) {
// toCheck.insert(it->second);
// }
// }
// currentY = 0.0;
}
void RealPartonState::checkInteraction(tDipolePtr intDip) {
toCheck.clear();
RealPartonPtr rp1 = getReal(intDip->partons().first);
checkHistory(rp1);
RealPartonPtr rp2 = getReal(intDip->partons().second);
checkHistory(rp2);
}
void RealPartonState::checkHistory(tRealPartonPtr rp) {
toCheck.insert(rp);
if ( rp->oMothers.first )
checkHistory(rp->oMothers.first);
if ( rp->oMothers.second )
checkHistory(rp->oMothers.second);
}
void RealPartonState::checkFuture() {
RealPartonSet future;
for ( RealPartonSet::iterator it = toCheck.begin(); it != toCheck.end(); it++ ) {
RealPartonPtr rp = *it;
if ( !rp->future.empty() )
future.insert(rp->future.begin(), rp->future.end());
}
if ( !future.empty() )
toCheck.insert(future.begin(), future.end());
}
void RealPartonState::checkAllInteracting() { //goes through all partons.
for ( map<tPartonPtr,RealPartonPtr>::iterator it = partons.begin();
it != partons.end(); it++ ) {
if ( !((*it).second->interactions.empty()) ) {
toCheck.insert(it->second);
}
if ( it->first->valence() ) it->second->setValenceMomentum();
}
currentY = 0.0;
}
void RealPartonState::setFutureNO(tRealPartonPtr rp) { //remade to go from high y to low/
for ( RealPartonSet::reverse_iterator it = toCheck.rbegin(); *it != rp; it++) {
if ( (*it)->keep == RealParton::YES && !(*it)->theParton->valence() )
(*it)->setNO();
}
}
void RealPartonState::setNO(const RealPartonSet & rps) {
for ( RealPartonSet::const_reverse_iterator it = rps.rbegin();
it != rps.rend(); it++)
if ( (*it)->keep == RealParton::YES &&
!(*it)->theParton->valence() ) (*it)->setNO();
}
RealPartonPtr RealPartonState::findWorstProblem() {
// cout << "entering worst problem" << endl;
Energy largestScale = ZERO;
RealPartonPtr ret;
for ( RealPartonSet::iterator it = toCheck.begin(); it != toCheck.end(); it++) {
if ( (*it)->keep == RealParton::NO ) break;
Energy scale = (*it)->problemScale();
// cout << "got scale " << scale/GeV << " at " << (*it)->oY() << ", ("
// << (*it)->theParton->position().x()*GeV << ", "
// << (*it)->theParton->position().y()*GeV << ")" << endl;
if ( scale > largestScale ) {
largestScale = scale;
ret = *it;
}
}
return ret;
}
bool RealPartonState::fix(RealPartonPtr problem) {
// cout << "entered fix" << endl;
RealPartonPtr cause = problem->findCause();
if ( !cause ) return false;
cause->setNO();
toCheck.erase(cause);
return true;
}
void RealPartonState::saveState() {
if ( Debug::level > 5 ) cout << "entering RPS::saveState" << endl;
for ( map<tPartonPtr, RealPartonPtr>::iterator it = partons.begin();
it != partons.end(); it++) {
(*it).second->saveState();
}
for ( RealPartonSet::iterator it = valence.begin(); //can be removed?
it != valence.end(); it++) {
(*it)->saveState();
}
failedInts.clear(); //when interaction found, the fails may now be ok.
if ( Debug::level > 5 ) cout << " failedInts cleared" << endl;
cTotalRecoil = totalRecoil;
cFlucts = flucts;
}
void RealPartonState::revertToPrevious(DipolePtr intDip) {
if ( Debug::level > 5 ) cout << "revert to previous called with intdip " << intDip << endl;
// if ( rescatter ) {
// //if rescattering, some extra care has to be taken in
// //removing the interaction tags from the partons,
// //so dont remove any tags the normal way, and call removeLastRescatter instead.
// removeLastRescatter(intDip);
// intDip = DipolePtr();
// }
for ( map<tPartonPtr,RealPartonPtr>::iterator it = partons.begin();
it != partons.end(); it++) {
it->second->revert(intDip);
}
interactions.pop_back();
doesInts.pop_back();
totalRecoil = cTotalRecoil;
flucts = cFlucts;
}
void RealPartonState::removeLastRescatter(tDipolePtr intDip) {
if ( Debug::level > 5 ) cout << "entering removeLastRescatter for intdip " << intDip << endl;
//first check which of the two partons has been interacting in previous interactions
bool firstOldInt = false;
bool secondOldInt = false;
//loop over all but the last interaction, to not include this last rescattering
if ( Debug::level > 5 ) cout << " number of interactions total: " << interactions.size() << endl;
list<pair<bool, bool> > ::iterator jt = doesInts.begin();
for ( list<tDipolePtr>::iterator it = interactions.begin(); it != --interactions.end();
it++, jt++ ) {
if ( Debug::level > 5 ) cout << " old int " << *it << endl;
if ( *it == intDip ) {
if ( Debug::level > 5 ) cout << " found old rescattering" << endl;
if ( jt->first ) firstOldInt = true;
if ( jt->second ) secondOldInt = true;
}
}
//if one of the partons was not tagged before, but got tagged by this last rescatter,
//then those new tags should be removed, otherwise nothing has to be done.
tRealPartonPtr oldInt;
if ( firstOldInt == false && doesInts.rbegin()->first ) {
if ( Debug::level > 5 ) cout << " reverting tags" << endl;
//the tags should be only from the second parton, so remove first, and readd second
//only removing ancestors of first does not work, since they may share ancestors
removeInt(getReal(intDip->partons().first), intDip);
addInt(getReal(intDip->partons().second), intDip);
}
else if ( secondOldInt == false && doesInts.rbegin()->second ) {
if ( Debug::level > 5 ) cout << " reverting tags" << endl;
removeInt(getReal(intDip->partons().second), intDip);
addInt(getReal(intDip->partons().first), intDip);
}
if ( Debug::level > 5 ) cout << "done in removeLastRescatter" << endl;
}
void RealPartonState::removeInt(tRealPartonPtr rp, DipolePtr intDip) {
rp->interactions.erase(intDip);
if ( rp->oMothers.first ) removeInt(rp->oMothers.first, intDip);
if ( rp->oMothers.second ) removeInt(rp->oMothers.second, intDip);
if ( rp->oMother ) removeInt(rp->oMother, intDip);
}
void RealPartonState::addInt(tRealPartonPtr rp, DipolePtr intDip) {
rp->interactions.insert(intDip);
if ( rp->oMothers.first ) addInt(rp->oMothers.first, intDip);
if ( rp->oMothers.second ) addInt(rp->oMothers.second, intDip);
if ( rp->oMother ) addInt(rp->oMother, intDip);
}
Energy RealPartonState::neededValenceMinus() {
if ( interactions.empty() ) cerr << "neededvalenceminus called for a state "
" without interaction!" << endl;
Energy ret = minusDeficit;
minusDeficit = ZERO;
for ( RealPartonSet::iterator it = valence.begin();
it != valence.end(); it++ ) {
ret += (**it).giveMinus();
}
return ret;
}
void RealPartonState::setOnShell(tDipolePtr intDip) {
getReal(intDip->partons().first)->setOnShell();
getReal(intDip->partons().second)->setOnShell();
}
void RealPartonState::removeBackwards() {
for ( RealPartonSet::const_iterator it = backwardsPartons.begin();
it != backwardsPartons.end(); it++ ) {
}
}
Energy RealPartonState::totalMinus() {
Energy ret = ZERO;
for ( map<tPartonPtr,RealPartonPtr>::const_iterator it = partons.begin();
it != partons.end(); it++) {
tRealPartonPtr rp = (*it).second;
if ( rp->keep == RealParton::YES ) {
ret += rp->minus;
}
}
return ret;
}
Energy RealPartonState::totalPlus() {
Energy ret = ZERO;
for ( map<tPartonPtr,RealPartonPtr>::const_iterator it = partons.begin();
it != partons.end(); it++) {
tRealPartonPtr rp = (*it).second;
if ( rp->keep == RealParton::YES ) {
ret += rp->plus;
}
}
return ret;
}
void RealPartonState::addRecoilers() {
if ( Debug::level > 5 ) {
cout << "before recoilers" << endl;
// plotState(true);
}
//loop over all active partons
for ( map<tPartonPtr,RealPartonPtr>::const_iterator it = partons.begin();
it != partons.end(); it++) {
if ( (*it).second->keep == RealParton::NO ) continue;
//hit holes in the parton from the recoils
addRecoiler2((*it).second);
}
if ( Debug::level > 5 ) {
cout << "with recoilers" << endl;
// plotState(true);
}
}
void RealPartonState::addRecoiler2(RealPartonPtr rp) {
TransverseMomentum opt = rp->theParton->valencePT();
if ( rp->mothers.first ) opt += rp->theParton->recoil(rp->mothers.first->theParton);
if ( rp->mothers.second ) opt += rp->theParton->recoil(rp->mothers.second->theParton);
if ( rp->nMothers == 1 && rp->mother ) opt = rp->theParton->valencePT() +
rp->theParton->recoil(rp->mother->theParton);
if ( opt.pt() == ZERO ) opt = rp->theParton->pT();
TransverseMomentum rec = rp->pT - opt;
if ( rec.pt() > 2.0*opt.pt() ) {
double plusRatio = opt.pt()/rec.pt();
rp->emitRecoiler(rec, plusRatio);
if ( Debug::level > 5 ) {
cout << "added recoiler for " << rp->oY() << endl;
// plotState(true);
}
}
}
void RealPartonState::addRecoiler(RealPartonPtr rp) {
PartonPtr p = rp->theParton;
//loop over all children.
//if any first children, create extra gluon in both real and dipole state
if ( !rp->children.first.empty() || rp->firstInt ) {
if ( Debug::level > 5 ) {
cout << "try to create first recoiler to " << rp->oY() << endl;
}
//set up
DipolePtr dip;
if ( p->dipoles().first ) dip = p->dipoles().first;
else {
Throw<RealPartonKinematicException>()
<< "Quark wants to create Recoiler on the wrong side!" << Exception::warning;
return;
}
TransverseMomentum pt = TransverseMomentum();
double ymax = rp->oY();
//move pt from rp to the new recoiler
if ( !rp->children.first.empty() ) {
for ( RealPartonSet::iterator it = rp->children.first.begin();
it != rp->children.first.end(); it++ ) {
RealPartonPtr child = *it;
//loop through "recoils" and move all pt recoils to the recoiler
for ( list< RealParton::Recoil >::iterator jt = child->recoils.begin();
jt != child->recoils.end(); jt++ ) {
cout << child->oY() << " has a recoil of " << jt->second.first.pt()/GeV
<< " to " << jt->first->oY() << endl;
if ( jt->first != rp ) continue;
if ( ymax < (*it)->y ) ymax = (*it)->y;
pt -= jt->second.first;
if ( Debug::level > 5 )
cout << child->oY() << " gives a pt kick of " << jt->second.first.pt()/GeV
<< " to " << rp->oY() << endl;
if ( Debug::level > 5 )
cout << child->oY() << " recoilers pt is now " << pt.pt()/GeV << endl;
}
// if ( child->nMothers == 1 ) child->mother = realRecoiler;
// if (child->nMothers == 2 ) child->mothers.second = realRecoiler;
}
}
if ( rp->firstInt ) {
vector<RealPartonPtr> ints;
//do the same, but use intDist to set the recoil
for ( list< RealParton::Recoil >::iterator it = rp->recoils.begin();
it != rp->recoils.end(); it++ ) {
if ( it->first->realState != this ) {
ints.push_back(it->first);
}
for (int i = 0; i < int(ints.size()); i++ ) {
//loop through "recoils" and move all pt recoils to the recoiler
for ( list< RealParton::Recoil >::iterator jt = ints[i]->recoils.begin();
jt != ints[i]->recoils.end(); jt++ ) {
cout << -ints[i]->oY() << " has an int recoil of " << jt->second.first.pt()/GeV
<< " to " << jt->first->oY() << endl;
if ( jt->first != rp ) continue;
if ( ymax < -ints[i]->y ) ymax = -ints[i]->y;
pt -= jt->second.first;
if ( Debug::level > 5 )
cout << ints[i]->oY() << " from other state gives a pt kick of " << jt->second.first.pt()/GeV
<< " to " << rp->oY() << endl;
if ( Debug::level > 5 )
cout << ints[i]->oY() << " recoilers pt is now " << pt.pt()/GeV << endl;
}
}
}
//maybe take direction from current pt?
//can "recoils" be used? does it store int recoils?
}
//if the hole is smaller than the mother, kick out a recoiler
if ( pt.pt() > (rp->pT - pt).pt() ) {
//create gluons
PartonPtr recoiler = new_ptr(Parton());
recoiler->onShell(true);
dip->generatedGluon(recoiler);
//fix colour flow for dipole state (let it be connected to the original one)
dip->splitDipole(0.5); //use better approximation for colour choice?
//initialise real recoiler
RealPartonPtr realRecoiler = getReal(recoiler);
realRecoiler->nMothers = 1;
realRecoiler->setOMother(rp);
realRecoiler->mother = rp;
realRecoiler->keep = RealParton::YES;
//set momentum of recoiler
realRecoiler->pT = pt;
rp->pT -= pt;
//otherwise use ymax to limit how far the recoiler can go in rapidity
double plusRatio = rp->pT.pt()/(realRecoiler->pT.pt() + rp->pT.pt());
realRecoiler->plus = plusRatio*rp->plus;
rp->plus = (1.0 - plusRatio)*rp->plus;
realRecoiler->updateYMinus();
rp->updateYMinus();
recoiler->oY(realRecoiler->y);
rp->saveState();
realRecoiler->saveState();
if ( Debug::level > 5 )
cout << "recoiler takes plus ratio " << plusRatio << endl;
//set position of recoiler
recoiler->position(p->position() + p->pTScale()*pt/sqr(pt.pt()));
//set mother structure
if ( !rp->firstInt ) {
RealPartonPtr lastChild = *rp->children.first.rbegin();
if ( lastChild->nMothers == 1 ) lastChild->mother = realRecoiler;
if ( lastChild->nMothers == 2 ) lastChild->mothers.second = realRecoiler;
realRecoiler->children.first.insert(lastChild);
}
else {
realRecoiler->interacting = rp->interacting;
realRecoiler->intDist = rp->intDist;
realRecoiler->firstInt = true;
}
if ( Debug::level > 5 ) {
cout << "recoiler places at transverse distance " << p->pTScale()*rp->pT.pt()/sqr(rp->pT.pt())*GeV << endl;
cout << "recoiler got pt " << realRecoiler->pT.pt()/GeV << endl;
cout << "done with first recoiler of " << rp->oY() << endl;
// dip->dipoleState().plotState(false);
// plotState(true);
}
}
else {
if ( Debug::level > 5 ) {
cout << "not enough pt, dont do recoiler" << endl;
cout << "recoiler pt was " << pt.pt()/GeV << ", canceled parent pt "
<< (rp->pT - pt).pt()/GeV << endl;
// plotState(true);
}
}
}
//same for other side
//if any first children, create extra gluon in both real and dipole state
if ( !rp->children.second.empty() || rp->secondInt ) {
if ( Debug::level > 5 ) {
cout << "try to create second recoiler to " << rp->oY() << endl;
}
//set up
DipolePtr dip;
if ( p->dipoles().second ) dip = p->dipoles().second;
else {
Throw<RealPartonKinematicException>()
<< "Quark wants to create Recoiler on the wrong side!" << Exception::warning;
return;
}
TransverseMomentum pt = TransverseMomentum();
double ymax = rp->oY();
//move pt from rp to the new recoiler
if ( !rp->children.second.empty() ) {
for ( RealPartonSet::iterator it = rp->children.second.begin();
it != rp->children.second.end(); it++ ) {
RealPartonPtr child = *it;
if ( rp->children.first.find(child) != rp->children.first.end() ) {
cout << "found second child at " << child->oY()
<< " that is also first. skip!" << endl;
plotState(true);
continue;
}
//loop through "recoils" and move all pt recoils to the recoiler
for ( list< RealParton::Recoil >::iterator jt = child->recoils.begin();
jt != child->recoils.end(); jt++ ) {
cout << child->oY() << " has a recoil of " << jt->second.first.pt()/GeV
<< " to " << jt->first->oY() << endl;
if ( jt->first != rp ) continue;
if ( ymax < (*it)->y ) ymax = (*it)->y;
pt -= jt->second.first;
if ( Debug::level > 5 )
cout << child->oY() << "gives a pt kick of " << jt->second.first.pt()/GeV
<< " to " << rp->oY() << endl;
if ( Debug::level > 5 )
cout << child->oY() << "recoilers pt is now " << pt.pt()/GeV << endl;
}
// if ( child->nMothers == 1 ) child->mother = realRecoiler;
// if (child->nMothers == 2 ) child->mothers.second = realRecoiler;
}
}
if ( rp->secondInt ) {
//do the same, but use intDist to set the recoil
//maybe take direction from current pt?
//can "recoils" be used? does it store int recoils?
}
//if the hole is smaller than the mother, kick out a recoiler
if ( pt.pt() > (rp->pT - pt).pt() ) {
//create gluons
PartonPtr recoiler = new_ptr(Parton());
recoiler->onShell(true);
dip->generatedGluon(recoiler);
//fix colour flow for dipole state (let it be connected to the original one)
dip->splitDipole(0.5); //use better approximation for colour choice?
//initialise real recoiler
RealPartonPtr realRecoiler = getReal(recoiler);
realRecoiler->nMothers = 1;
realRecoiler->setOMother(rp);
realRecoiler->mother = rp;
realRecoiler->keep = RealParton::YES;
//set momentum of recoiler
realRecoiler->pT = pt;
rp->pT -= pt;
//otherwise use ymax to limit how far the recoiler can go in rapidity
double plusRatio = rp->pT.pt()/(realRecoiler->pT.pt() + rp->pT.pt());
realRecoiler->plus = plusRatio*rp->plus;
rp->plus = (1.0 - plusRatio)*rp->plus;
realRecoiler->updateYMinus();
rp->updateYMinus();
recoiler->oY(realRecoiler->y);
rp->saveState();
realRecoiler->saveState();
if ( Debug::level > 5 )
cout << "recoiler takes plus ratio " << plusRatio << endl;
//set position of recoiler
recoiler->position(p->position() + p->pTScale()*pt/sqr(pt.pt()));
//set mother structure
if ( !rp->secondInt ) {
RealPartonPtr lastChild = *rp->children.second.rbegin();
if ( lastChild->nMothers == 1 ) lastChild->mother = realRecoiler;
if ( lastChild->nMothers == 2 ) lastChild->mothers.first = realRecoiler;
realRecoiler->children.second.insert(lastChild);
}
else {
realRecoiler->interacting = rp->interacting;
realRecoiler->intDist = rp->intDist;
realRecoiler->secondInt = true;
}
if ( Debug::level > 5 ) {
cout << "recoiler places at transverse distance " << p->pTScale()*rp->pT.pt()/sqr(rp->pT.pt())*GeV << endl;
cout << "recoiler got pt " << realRecoiler->pT.pt()/GeV << endl;
cout << "done with first recoiler of " << rp->oY() << endl;
// dip->dipoleState().plotState(false);
// plotState(true);
}
}
else {
if ( Debug::level > 5 ) {
cout << "not enough pt, dont do recoiler" << endl;
cout << "recoiler pt was " << pt.pt()/GeV << ", canceled parent pt "
<< (rp->pT - pt).pt()/GeV << endl;
// plotState(true);
}
}
}
cout << "done with " << rp->oY() << endl;
plotState(true);
}
void RealPartonState::plotState(bool pause) const {
cout << "print state to realState.dat" << endl;
ofstream file ("realState.dat");
plotStateToFile(file, false);
file.close();
if ( pause && Debug::level > 5 ) {
cout << "press any key to continue..." << endl;
getchar();
}
}
void RealPartonState::plotBothStates(RealPartonStatePtr rrs, bool pause) const {
cout << "print state to realState.dat" << endl;
ofstream file ("realState.dat");
plotStateToFile(file, false);
rrs->plotStateToFile(file, true);
file.close();
if ( pause && Debug::level > 5 ) {
cout << "press any key to continue..." << endl;
getchar();
}
}
void RealPartonState::plotStateToFile(ostream & file, bool m) const {
double ptmax = -100;
double ptmin = 100000;
double ymax = 0.0;
PartonPtr p = partons.begin()->second->theParton;
if ( p->dipoles().first ) ymax = p->dipoles().first->dipoleState().ymax();
if ( p->dipoles().second ) ymax = p->dipoles().second->dipoleState().ymax();
for ( map<tPartonPtr,RealPartonPtr>::const_iterator it = partons.begin();
it != partons.end(); it++) {
RealPartonPtr rp = it->second;
if ( rp->pT.pt()/GeV > ptmax ) ptmax = rp->pT.pt()/GeV;
if ( rp->pT.pt()/GeV < ptmin ) ptmin = rp->pT.pt()/GeV;
bool val = rp->theParton->valence();
TransverseMomentum opt = rp->theParton->valencePT();
if ( rp->mothers.first ) opt += rp->theParton->recoil(rp->mothers.first->theParton);
if ( rp->mothers.second ) opt += rp->theParton->recoil(rp->mothers.second->theParton);
if ( rp->nMothers == 1 && rp->mother ) opt = rp->theParton->valencePT() +
rp->theParton->recoil(rp->mother->theParton);
if ( opt.pt() == ZERO ) opt = rp->theParton->pT();
//the main real partons
file << ((!m) ? rp->theParton->oY():-rp->theParton->oY()) << '\t'
<< rp->theParton->position().y()*GeV << '\t'
<< rp->keep << '\t'
<< ((!m) ? rp->y:-rp->y) << '\t'
<< val << '\t'
<< opt.pt()/GeV << '\t'
<< bool(toCheck.find(rp) != toCheck.end()) << '\t'
<< rp->theParton->position().x()*GeV << endl << endl;
//info on the consistent state, N/A if state never saved.
if ( interactions.size() > 1 || cTotalRecoil == totalRecoil ) {
file << ((!m) ? rp->theParton->oY():-rp->theParton->oY()) << '\t'
<< opt.pt()/GeV << '\t'
<< 3 << '\t' << endl;
file << ((!m) ? rp->theParton->y():abs(rp->theParton->y())) << '\t'
<< rp->theParton->pT().pt()/GeV << '\t'
<< 4 << '\t' << endl << endl;
}
//the interacting marks
if ( rp->interacting )
file << ((!m) ? rp->theParton->oY():-rp->theParton->oY()) << '\t'
<< rp->theParton->position().y()*GeV << '\t'
<< 2 << '\t'
<< ((!m) ? rp->y:-rp->y) << '\t'
<< val << '\t'
<< opt.pt()/GeV << '\t'
<< rp->theParton->position().x()*GeV << endl
<< ymax << '\t'
<< rp->theParton->position().y()*GeV << '\t'
<< 2 << '\t'
<< ((!m) ? rp->y:-rp->y) << '\t'
<< val << '\t'
<< rp->theParton->pTScale()/rp->intDist/GeV << '\t'
<< rp->theParton->position().x()*GeV << endl << endl;
//line to current state
file << ((!m) ? rp->theParton->oY():-rp->theParton->oY()) << '\t'
<< rp->theParton->position().y()*GeV << '\t'
<< rp->keep << '\t'
<< 7 << '\t'
<< opt.pt()/GeV << endl
<< ((!m) ? rp->y:-rp->y) << '\t'
<< rp->theParton->position().y()*GeV << '\t'
<< rp->keep << '\t'
<< 8 << '\t'
<< rp->pT.pt()/GeV << endl << endl;
//the pT
file << ((!m) ? rp->theParton->oY():-rp->theParton->oY()) << '\t'
<< rp->theParton->position().y()*GeV << '\t'
<< ((rp->keep == RealParton::YES) ? 9:10) << '\t'
<< rp->theParton->position().x()*GeV << '\t'
<< 0.0 << '\t'
<< 0.0 << endl
<< ((!m) ? rp->theParton->oY():-rp->theParton->oY()) << '\t'
<< rp->theParton->position().y()*GeV << '\t'
<< ((rp->keep == RealParton::YES) ? 9:10) << '\t'
<< rp->theParton->position().x()*GeV << '\t'
<< rp->pT.x()/GeV << '\t'
<< rp->pT.y()/GeV << endl << endl;
vector<RealPartonPtr> mots;
mots.push_back(rp->oMothers.first);
mots.push_back(rp->oMothers.second);
mots.push_back(rp->mothers.first);
mots.push_back(rp->mothers.second);
mots.push_back(rp->oMother);
mots.push_back(rp->mother);
//lines to mothers and original mothers
for ( int i = 0; i < int(mots.size()); i++) {
RealPartonPtr rp2 = rp;
if ( mots[i] ) rp2 = mots[i];
TransverseMomentum opt2 = rp2->theParton->valencePT();
if ( rp2->mothers.first ) opt2 += rp2->theParton->recoil(rp2->mothers.first->theParton);
if ( rp2->mothers.second ) opt2 += rp2->theParton->recoil(rp2->mothers.second->theParton);
if ( rp2->nMothers == 1 && rp2->mother ) opt2 = rp2->theParton->valencePT() +
rp2->theParton->recoil(rp2->mother->theParton);
if ( opt2.pt() == ZERO ) opt2 = rp2->theParton->pT();
file << ((!m) ? rp->theParton->oY():-rp->theParton->oY()) << '\t'
<< rp->theParton->position().y()*GeV << '\t'
<< rp->keep << '\t'
<< i+3 + 100 << '\t'
<< opt.pt()/GeV << '\t'
<< rp->theParton->position().x()*GeV << '\t'
<< rp->nMothers + 10 << endl
<< ((!m) ? rp2->theParton->oY():-rp2->theParton->oY()) << '\t'
<< rp2->theParton->position().y()*GeV << '\t'
<< rp2->keep << '\t'
<< i+3 + 100 << '\t'
<< opt2.pt()/GeV << '\t'
<< rp2->theParton->position().x()*GeV << '\t'
<< rp->nMothers + 10 << endl;
}
}
file << ymax << '\t' << ptmax << '\t' << 10 << '\t' << 10 << endl
<< ymax << '\t' << ptmin << '\t' << 10 << '\t' << 10 << endl;
file << ((!m) ? currentY:-currentY) << '\t' << ptmax << '\t' << 10 << '\t' << 9 << endl
<< ((!m) ? currentY:-currentY) << '\t' << ptmin << '\t' << 10 << '\t' << 9 << endl;
}
pair<int, int> RealPartonState::countYESNO() const {
int yes = 0;
int no = 0;
for ( map<tPartonPtr,RealPartonPtr>::const_iterator it = partons.begin();
it != partons.end(); it++) {
if ( (*it).second->keep == RealParton::YES ) yes++;
else no++;
}
return make_pair(yes, no);
}
double RealPartonState::avYInEvo() const {
double number = 0.0;
double length = 0.0;
for ( map<tPartonPtr,RealPartonPtr>::const_iterator it = partons.begin();
it != partons.end(); it++) {
RealPartonPtr rp = (*it).second;
if ( rp->keep == RealParton::YES && !(rp->theParton->valence()) ) {
number++;
if ( rp->nMothers == 2 )
length += (abs(rp->y - rp->mothers.first->y) + abs(rp->y - rp->mothers.second->y))/2.0;
if ( rp->nMothers == 1 )
length += abs(rp->y - rp->mother->y);
}
}
if (number == 0.0 ) return 0.0;
return length/number;
}
bool RealPartonState::diagnosis(bool pause) const {
calls++;
bool ok = true;
// cout << "diagnosis call number " << calls << " for " << this << endl;
TransverseMomentum pT = TransverseMomentum();
Energy dplus = ZERO;
Energy dminus = ZERO;
TransverseMomentum cpT = TransverseMomentum();
Energy cplus = ZERO;
Energy cminus = ZERO;
Energy gminus = ZERO;
int yes = 0;
int consInt = 0;
int vals = 0;
int mothers = 0;
int kids = 0;
int exchanges = 0;
int interactingPartons = 0;
TransverseMomentum valPT = TransverseMomentum();
TransverseMomentum intPT = TransverseMomentum();
Energy valPlus = ZERO;
Energy valMinus = ZERO;
for ( map<tPartonPtr,RealPartonPtr>::const_iterator it = partons.begin();
it != partons.end(); it++) {
tRealPartonPtr rp = (*it).second;
if ( !rp->exchanges.empty() )
exchanges += rp->exchanges.size();
if ( rp->cInteracting ) consInt++;
if ( rp->theParton->valence() ) {
vals++;
valPT += rp->theParton->valencePT();
valPlus += rp->theParton->valencePlus();
if ( rp->movedValence )
valMinus += rp->theParton->valencePlus()*exp(2.0*rp->movedValence->oY());
else
valMinus += rp->theParton->valencePlus()*exp(2.0*rp->oY());
if ( rp->keep == RealParton::NO ) {
pT += rp->theParton->valencePT();
dplus += rp->theParton->valencePlus();
dminus += sqr(rp->theParton->valencePT().pt())/rp->theParton->valencePlus();
cout << "* valence parton that is NO!!" << endl;
ok = false;
}
}
if ( rp->keep == RealParton::YES ) {
yes++;
pT += rp->pT;
dplus += rp->plus;
dminus += rp->minus;
gminus += rp->givenMinus;
if ( rp->mothers.first ) mothers++;
if ( rp->mothers.second ) mothers++;
if ( rp->mother ) mothers++;
kids += rp->children.first.size();
kids += rp->children.second.size();
if ( rp->interacting ) interactingPartons++;
}
if ( rp->cKeep == RealParton::YES ) {
cpT += rp->theParton->pT();
cplus += rp->theParton->plus();
cminus += rp->theParton->minus();
}
if ( rp->interacting ) {
intPT += rp->intRecoil;
}
// if ( rp->interacting && toCheck.find(rp) == toCheck.end() ) {
// cout << "interacting parton at " << rp->theParton->oY() << " is not in tocheck" << endl;
// ok = false;
// }
}
for ( map<tPartonPtr,RealPartonPtr>::const_iterator it = partons.begin();
it != partons.end(); it++) {
tRealPartonPtr rp = (*it).second;
if ( rp->keep != RealParton::NO && rp->keep != RealParton::YES )
Throw<RealPartonKinematicException>()
<< "Real parton at oY " << rp->oY() << " is neither YES nor NO..." << Exception::warning;
if ( rp->keep == RealParton::YES ) {
// if ( !rp->checkMomentum() && !(rp->interacting && totalRecoil.pt() != ZERO )
// && rp->theParton->oY() <= currentY )
// ok = false;
if ( rp->plus < ZERO ) {
Throw<RealPartonKinematicException>()
<< "negative plus in real parton diagnosis at oY " << rp->oY() << Exception::warning;
ok = false;
}
if ( rp->minus < ZERO ) {
Throw<RealPartonKinematicException>()
<< "negative minus in real parton diagnosis at oY " << rp->oY() << Exception::warning;
ok = false;
}
for ( RealPartonSet::const_iterator it = rp->children.first.begin();
it != rp->children.first.end(); it++ ) {
if ( (*it)->mothers.second != rp && (*it)->mother != rp ) {
cout << "\n* parton at " << (*it)->theParton->oY() << " doesnt have " << rp->theParton->oY()
<< " as second mother! child-mother broken!" << endl;
ok = false;
}
if ( (*it)->keep == RealParton::NO ) {
cout << "\n* parton at " << rp->theParton->oY() << "has a NO-child at "
<< (*it)->theParton->oY() << endl;
ok = false;
}
}
for ( RealPartonSet::const_iterator it = rp->children.second.begin();
it != rp->children.second.end(); it++ ) {
if ( (*it)->mothers.first != rp && (*it)->mother != rp ) {
cout << "\n* parton at " << (*it)->theParton->oY() << " doesnt have " << rp->theParton->oY()
<< " as first mother! child-mother broken!" << endl;
ok = false;
}
if ( (*it)->keep == RealParton::NO ) {
cout << "\n* parton at " << rp->theParton->oY() << "has a NO-child at "
<< (*it)->theParton->oY() << endl;
ok = false;
}
}
if ( rp->mothers.first && (rp->mothers.first->children.second.find(rp)
== rp->mothers.first->children.second.end()) ) {
cout << "\n* first mother of " << rp->oY() << " doesnt have this as second child!" << endl;
ok = false;
}
if ( rp->mothers.second && (rp->mothers.second->children.first.find(rp)
== rp->mothers.second->children.first.end()) ) {
cout << "\n* second mother of " << rp->oY() << " doesnt have this as first child!" << endl;
ok = false;
}
if ( rp->mother &&
(rp->mother->children.first.find(rp) == rp->mother->children.first.end()) &&
(rp->mother->children.second.find(rp) == rp->mother->children.second.end()) ) {
cout << "\n* single mother of " << rp->oY()
<< " doesnt have this as first or second child!" << endl;
ok = false;
}
if ( !rp->interacting && !rp->theParton->valence() &&
rp->children.first.empty() && rp->children.second.empty() ) {
cout << "\n* " << rp->oY() << " has no kids, and isnt interacting! where to get p-??\n";
ok = false;
}
}
}
if ( (intPT - totalRecoil).pt() > 0.000000001*GeV ) {
cout << "* sum of intPT != totalRecoil" << endl;
ok = false;
}
if ( (pT - totalRecoil).pt() > 0.000000001*GeV ) {
cout << "* total pT != totalRecoil" << endl;
ok = false;
}
// if ( valence.size() != 3 ) {
// cout << "* size of valence is not 3" << endl;
// ok = false;
// }
if ( valPT.pt() > 0.000000001*GeV ) {
cout << "* valencePT does dot add up to zero!" << endl;
ok = false;
}
if ( vals != int(valence.size()) ) {
cout << "* there are " << vals << " valence partons, but size of valence is "
<< valence.size() << endl;
ok = false;
}
if ( kids != mothers ) {
cout << "* not same number of kids as mothers!" << endl;
ok = false;
}
if ( abs(valPlus - dplus) > 0.00000001*GeV && totalRecoil.pt() == ZERO ) {
cout << "* initial state plus not conserved" << endl;
ok = false;
}
if ( dplus == ZERO ) {
cout << "* no plus!" << endl;
ok = false;
}
if ( isnan(dplus/GeV) || isnan(dminus/GeV) ) {
cout << "* plus or minus is nan!!" << endl;
ok = false;
}
if ( !ok && Debug::level > 5 ) {
cout << "*\n* REAL STATE NOT OK!!!\n*\n";
}
if ((!ok || pause) && Debug::level > 5 ) {
cout << setprecision(10);
cout << "********* Diagnosis for " << this << " ******* call nr " << calls << " ********" << endl;
cout << "* number of partons: " << partons.size() << endl;
cout << "* size of valence: " << valence.size() << endl;
cout << "* number of valence part: " << vals << endl;
cout << "* number of toCheck: " << toCheck.size() << endl;
cout << "* number of interacting: " << interacting.size() << endl;
cout << "* number of int rps: " << interactingPartons << endl;
cout << "* number of cInteracting: " << consInt << endl;
cout << "* number of interactions: " << interactions.size() << endl;
cout << "* number gluon exchanges: " << exchanges << endl;
cout << "* consistent: " << consistent << endl;
cout << "* total no of kids = " << kids << endl;
cout << "* total no mothers = " << mothers << endl;
cout << "* number of YES or INT: " << yes << endl
<< "* " << endl;
cout << "* total transverse = (" << pT.x()/GeV << ", " << pT.y()/GeV << ")" << endl;
cout << "* total recoil = (" << totalRecoil.x()/GeV << ", "
<< totalRecoil.y()/GeV << ")" << endl;
cout << "* sum of int recoil = (" << intPT.x()/GeV << ", "
<< intPT.y()/GeV << ")" << endl;
cout << "* original plus = " << plus/GeV << endl;
cout << "* total plus = " << dplus/GeV << endl;
cout << "* 1800 - total plus + " << 1800.0 - dplus/GeV << endl;
cout << "* original minus = " << minus/GeV << endl;
cout << "* total minus = " << dminus/GeV << endl;
cout << "* given +val minus = " << (gminus + valMinus)/GeV << endl;
cout << "* valence minus = " << valMinus/GeV << endl;
cout << "* total ctransverse = (" << cpT.x()/GeV << ", " << cpT.y()/GeV << ")" << endl;
cout << "* total cplus = " << cplus/GeV << endl;
cout << "* total cminus = " << cminus/GeV << endl;
cout << "* total valencePT = (" << valPT.x()/GeV << ", " << valPT.y()/GeV << ")" << endl;
cout << "* total valencePlus = " << valPlus/GeV << endl;
cout << "* number of flucts = " << flucts.size() << endl;
for ( map<tPartonPtr,RealPartonPtr>::const_iterator it = partons.begin();
it != partons.end(); it++) {
tRealPartonPtr rp = (*it).second;
if ( rp->fluct != -1 ) {
cout << "* " << rp->oY() << " belongs to fluct no " << rp->fluct << endl;
}
// cout << "* rp at " << rp->theParton->oY() << " has vetoed p+1: " << rp->plus1veto
// << ", p+2: " << rp->plus2veto << ", p-1: " << rp->minus1veto << ", p-2: " << rp->minus2veto
// << ", DGLAP: " << rp->unDGLAP << endl;
// if ( rp->theParton->valence() )
// cout << "* valencepT: (" << rp->theParton->valencePT().x()/GeV << ", "
// << rp->theParton->valencePT().y()/GeV
// << "), valenceplus: " << rp->theParton->valencePlus()/GeV << endl;
}
cout << "*********************************************************" << endl;
plotState(pause || !ok);
}
if ( Debug::level > 5 ) cout << "real state tested. ok: " << ok << endl;
return ok;
}
diff --git a/DIPSY/RecoilSwinger.cc b/DIPSY/RecoilSwinger.cc
--- a/DIPSY/RecoilSwinger.cc
+++ b/DIPSY/RecoilSwinger.cc
@@ -1,169 +1,169 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the RecoilSwinger class.
//
#include "RecoilSwinger.h"
#include "Dipole.h"
#include "DipoleState.h"
#include "DipoleEventHandler.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Utilities/Current.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace DIPSY;
RecoilSwinger::RecoilSwinger() {}
RecoilSwinger::~RecoilSwinger() {}
IBPtr RecoilSwinger::clone() const {
return new_ptr(*this);
}
IBPtr RecoilSwinger::fullclone() const {
return new_ptr(*this);
}
void RecoilSwinger::
generate(Dipole & dipole, double miny, double maxy, bool force) const {
Swinger::generate(dipole, miny, maxy, force);
// generateExchange(dipole, miny, maxy, force);
}
void RecoilSwinger::recombine(Dipole & dip) const {
DipolePtr d1 = & dip;
DipolePtr d2 = d1->swingDipole();
// if ( !kinematicsVeto(d1->partons(), d2->partons()) &&
// exchangeAmp(d1->partons(), d2->partons())/
// swingAmp(d1->partons(), d2->partons()) > UseRandom::rnd() ) {
// cout << "recombining. swingamp: " << swingAmp(d1->partons(), d2->partons())
// << ", exchangeamp: " << exchangeAmp(d1->partons(), d2->partons()) << endl;
// exchange(*d1);
// }
if ( 1.0/3.0 > UseRandom::rnd() ) {
exchange(*d1);
}
else
Swinger::recombine(*d1);
}
void RecoilSwinger::exchange(Dipole & d1) const {
// cout << "doing gluon exchange!!" << endl;
// d1.dipoleState().diagnosis(true);
Dipole & d2 = *d1.swingDipole();
DipoleXSec::InteractionRecoil recoil =
Current<DipoleEventHandler>()->xSecFn().recoil(d1.partons(), d2.partons(), ImpactParameters());
d1.partons().first->pT() += recoil.first.first;
d1.partons().second->pT() += recoil.first.second;
d2.partons().first->pT() += recoil.second.first;
d2.partons().second->pT() += recoil.second.second;
d1.partons().first->updateYMinus();
d1.partons().second->updateYMinus();
d2.partons().first->updateYMinus();
d2.partons().second->updateYMinus();
Swinger::recombine(d1);
// cout << "done gluon exchange for a pt of " << (recoil.first.first.pt() + recoil.first.second.pt() + recoil.second.first.pt() + recoil.second.second.pt())/GeV << endl;
// d1.dipoleState().diagnosis(true);
}
double RecoilSwinger::
exchangeAmp(const pair<tPartonPtr, tPartonPtr> first,
const pair<tPartonPtr, tPartonPtr> second) const {
return Current<DipoleEventHandler>()->xSecFn().fij(first, second, ImpactParameters())*9.0;
}
bool RecoilSwinger::
kinematicsVeto(const pair<tPartonPtr, tPartonPtr> first,
const pair<tPartonPtr, tPartonPtr> second) const {
return false; //the veto is included in fij
// return Current<DipoleEventHandler>()->xSecFn().kinematicsVeto(d1, d2, ImpactParameters());
}
void RecoilSwinger::
generateExchange(Dipole & dipole, double miny, double maxy, bool force) const {
cout << "generating exchange for dip at "
<< max(max(dipole.partons().first->y(), dipole.partons().second->y()), miny) << endl;
const list<DipolePtr> & candidates = dipole.dipoleState().getDipoles();
list<DipolePtr>::const_iterator it = candidates.begin();
while( it != candidates.end() && *(it++) != & dipole );
for (; it != candidates.end(); it++ ) {
if ( !force && (*it)->hasGen() ) continue;
if ( dipole.partons().second == (*it)->partons().first ||
(*it)->partons().second == dipole.partons().first )
continue;
InvEnergy2 a = dipole.partons().first->dist2(*dipole.partons().second);
InvEnergy2 b = (*it)->partons().first->dist2(*((*it)->partons().second));
InvEnergy2 c = dipole.partons().second->dist2(*(*it)->partons().first);
InvEnergy2 d = dipole.partons().first->dist2(*(*it)->partons().second);
//calculate recoils and kinematics
if ( false ) //veto from kinematics
continue;
a = sqr(Current<DipoleEventHandler>()->rMax())/
- (Current<DipoleEventHandler>()->alphaS(sqrt(a)))*
+ (Current<DipoleEventHandler>()->alphaSr(sqrt(a)))*
sqr(exp(sqrt(a)/Current<DipoleEventHandler>()->rMax()) - 1.0);
b = sqr(Current<DipoleEventHandler>()->rMax())/
- (Current<DipoleEventHandler>()->alphaS(sqrt(b)))*
+ (Current<DipoleEventHandler>()->alphaSr(sqrt(b)))*
sqr(exp(sqrt(b)/Current<DipoleEventHandler>()->rMax()) - 1.0);
c = sqr(Current<DipoleEventHandler>()->rMax())/
- (Current<DipoleEventHandler>()->alphaS(sqrt(c)))*
+ (Current<DipoleEventHandler>()->alphaSr(sqrt(c)))*
sqr(exp(sqrt(c)/Current<DipoleEventHandler>()->rMax()) - 1.0);
d = sqr(Current<DipoleEventHandler>()->rMax())/
- (Current<DipoleEventHandler>()->alphaS(sqrt(d)))*
+ (Current<DipoleEventHandler>()->alphaSr(sqrt(d)))*
sqr(exp(sqrt(d)/Current<DipoleEventHandler>()->rMax()) - 1.0);
InvEnergy scale = sqrt(min(min(a, b),min(c, d)));
double A = c*d/(a*b);
double y = max(max(dipole.partons().first->y(), dipole.partons().second->y()), miny)
- - A*log(UseRandom::rnd())/sqr(Current<DipoleEventHandler>()->alphaS(scale));
+ - A*log(UseRandom::rnd())/sqr(Current<DipoleEventHandler>()->alphaSr(scale));
//decide at what rate this happens!!! alpha_S should be there...
cout << "generated exchange: " << y << ", yGen " << dipole.generatedY() << endl;
if ( y < dipole.generatedY() ) {
cout << "generated exchange for y = " << y << endl;
dipole.swingDipole(*it);
dipole.generatedY(y);
dipole.recoilSwing(true);
}
}
}
// If needed, insert default implementations of virtual function defined
// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs).
void RecoilSwinger::persistentOutput(PersistentOStream & os) const {
// *** ATTENTION *** os << ; // Add all member variable which should be written persistently here.
}
void RecoilSwinger::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<RecoilSwinger,DIPSY::Swinger>
describeDIPSYRecoilSwinger("DIPSY::RecoilSwinger", "RecoilSwinger.so");
void RecoilSwinger::Init() {
static ClassDocumentation<RecoilSwinger> documentation
("There is no documentation for the RecoilSwinger class");
}
diff --git a/DIPSY/ShadowParton.cc b/DIPSY/ShadowParton.cc
--- a/DIPSY/ShadowParton.cc
+++ b/DIPSY/ShadowParton.cc
@@ -1,575 +1,575 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the ShadowParton class.
//
#include "ShadowParton.h"
#include "Parton.h"
#include "DipoleState.h"
#include "DipoleEventHandler.h"
#include "Dipole.h"
#include "ImpactParameters.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/Repository/CurrentGenerator.h"
#include "ThePEG/Utilities/Debug.h"
#include "ThePEG/Utilities/Throw.h"
#include "ThePEG/Utilities/EnumIO.h"
#include "ThePEG/Utilities/Current.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Utilities/DebugItem.h"
using namespace DIPSY;
ShadowParton::ShadowParton(Parton & p)
: theOriginal(&p), thePlus(p.plus()),
thePT(p.pT()), thePT0(p.pT()), theMass(p.mass()), theMinus(p.minus()),
theY(p.y()), theY0(p.y()), theFlavour(p.flavour()),
theEmissionFactor(ZERO), theRes(ZERO), isLocked(false),
hasInteracted(false), isOnShell(false),
isValence(p.valence()), hasColourSibling(false), memememe(false) {}
ShadowParton::~ShadowParton() {}
void ShadowParton::setupParton() {
if ( tSPartonPtr sp = original()->shadow() ) {
sp->theNext = this;
thePrevious = sp;
}
original()->shadow(this);
}
SPartonPtr ShadowParton::createValence(Parton & p) {
SPartonPtr sp = new_ptr(ShadowParton(p));
sp->setupParton();
sp->isValence = true;
return sp;
}
void ShadowParton::setupEmission(Parton & emitter,
Parton & produced, Parton & recoiler) {
SPartonPtr se = new_ptr(ShadowParton(emitter));
se->setupParton();
SPartonPtr sp = new_ptr(ShadowParton(produced));
sp->setupParton();
se->theSibling = sp;
se->hasColourSibling =
( emitter.dipoles().first &&
emitter.dipoles().first == produced.dipoles().second );
sp->theParent = this;
sp->theSibling = se;
sp->hasColourSibling = !se->hasColourSibling;
theChild = sp;
InvEnergy2 d2 = se->dist2(*sp);
- se->theRes = sp->theRes = alphaS(d2)*d2;
+ se->theRes = sp->theRes = alphaSr(d2)*d2;
se->theEmissionFactor = sp->theEmissionFactor = se->res()/UseRandom::rnd();
// se->theRes = sp->theRes = d2;
// se->theEmissionFactor = sp->theEmissionFactor = alphaS(d2)*d2/UseRandom::rnd();
}
void ShadowParton::lock() {
if ( mother() ) mother()->lock();
isLocked = true;
}
void ShadowParton::unlock() {
if ( mother() && locked() ) mother()->unlock();
isLocked = false;
}
tSPartonPtr ShadowParton::last() {
if ( next() ) return next();
return this;
}
tSPartonPtr ShadowParton::initial() {
if ( previous() ) return previous();
return this;
}
tSPartonPtr ShadowParton::valenceMother() {
if ( mother() ) return mother()->valenceMother();
return this;
}
tcSPartonPtr ShadowParton::last() const {
if ( next() ) return next();
return this;
}
-double ShadowParton::alphaS(InvEnergy2 r2) {
- return Current<DipoleEventHandler>()->alphaS(sqrt(r2));
+double ShadowParton::alphaSr(InvEnergy2 r2) {
+ return Current<DipoleEventHandler>()->alphaSr(sqrt(r2));
}
// tcSPartonPtr ShadowParton::resolve(InvEnergy2 r2, tPartonPtr stopp) const {
// if ( resolved(r2, stopp) || !mother() ) return this;
// return mother()->resolve(r2, stopp);
// }
tSPartonPtr ShadowParton::resolve(InvEnergy2 r2) {
if ( resolved(r2) || !mother() ) return this;
return mother()->resolve(r2);
}
tSPartonPtr ShadowParton::resolveInteraction(InvEnergy2 r2) {
if ( resolved(r2)
|| !mother()
|| forceEmission()
|| onShell()
|| ( sibling() && sibling()->interacted() ) ) return this;
return mother()->resolveInteraction(r2);
}
void ShadowParton::pTplus(const TransverseMomentum & qt, Energy qp) {
pT(qt);
plus(qp);
minus(mt2()/plus());
y(log(mt()/plus()));
}
void ShadowParton::setOnShell(int mode) {
if ( mode < 0 ) return;
onShell(true);
if ( mode <= 0 ) return;
original()->plus(plus());
original()->pT(pT());
original()->minus(original()->mt2()/plus());
original()->y(log(original()->mt()/original()->plus()));
original()->onShell(true);
}
void ShadowParton::unsetOnShell() {
if ( onShell() ) {
original()->onShell(false);
onShell(false);
}
}
void ShadowParton::interact() {
if ( interacted() ) return;
hasInteracted = true;
if ( mother() ) mother()->interact();
}
void ShadowParton::resetInteracted() {
if ( !mother() ) {
pT(pT0());
y(y0());
plus(mt()*exp(-y()));
minus(mt()*exp(y()));
}
hasInteracted = false;
theInteractions.clear();
onShell(false);
if ( next() ) next()->resetInteracted();
if ( child() ) child()->resetInteracted();
}
void ShadowParton::reset() {
if ( !mother() ) {
pT(pT0());
y(y0());
plus(mt()*exp(-y()));
minus(mt()*exp(y()));
}
onShell(false);
theInteractions.clear();
hasInteracted = false;
theInteractionRoots.clear();
if ( next() ) next()->reset();
if ( child() ) child()->reset();
}
void ShadowParton::insertInteraction(int i) {
// If this parton has been set on-shell by a previous interaction we
// do not have to look further. Similarly if the sibling has
// interacted.
if ( onShell()
|| ( sibling() && sibling()->interacted() )
|| !mother() ) {
interactionRoot(i);
}
// Otherwise we try with the mother instead.
else mother()->insertInteraction(i);
}
bool ShadowParton::checkInteractionRoot(int i) const {
if ( onShell() ) return true;
if ( mother() ) {
if ( hasInteractionRoot(i) ) return false;
else return mother()->checkInteractionRoot(i);
} else
return hasInteractionRoot(i);
}
void ShadowParton::rejectInteraction(int i) {
if ( hasInteractionRoot(i) ) theInteractionRoots.erase(i);
else mother()->rejectInteraction(i);
}
void ShadowParton::acceptInteraction(int i) {
hasInteracted = true;
if ( !hasInteractionRoot(i) ) mother()->acceptInteraction(i);
}
void ShadowParton::makeIncoming() {
if ( interacted() && onShell() ) onShell(false);
else if ( mother() ) mother()->makeIncoming();
}
bool ShadowParton::setEmissionMomenta(const LorentzMomentum & p,
bool forced) {
static DebugItem plusevo("DIPSY::PlusEvo", 6);
// if ( plusevo )
return setEmissionMomentaPlus(p, forced);
// *** TODO *** Think this through! If the emission unresolved but
// anyway should be done because a valence need to be put on shell,
// or a subsequent emission needs it, the generated pt is ignored
// and the emitted parton and the continuing propagator will share
// the incoming pt, while the generated rapidity of the emission
// remains untouched.
// *** TODO *** Think about the mass of the propagator.
TransverseMomentum qT = parent()? pT0(): sibling()->pT0();
if ( forced ) qT = TransverseMomentum(-p.x()/2.0, -p.y()/2.0);
if ( parent() ) {
// If this parton was emitted, pretend it was actually he emitter
// and continues as a propagator. It will retain its original
// rapidity, but will get the transverse momentum of the incoming
// propagator.
pT(TransverseMomentum(p.x(), p.y()) + qT);
y(y0());
plus(mt()*exp(-y()));
// The sibling will get minus the original transverse momentum and
// what ever is left of the positive light-cone momenta. (return
// false if not enough to put on shell).
sibling()->pT(-qT);
sibling()->plus(p.plus() - plus());
if ( sibling()->plus() <= ZERO ) return false;
sibling()->minus(sibling()->mt2()/sibling()->plus());
sibling()->y(log(sibling()->mt()/sibling()->plus()));
// The propagators negative light-cone momentum is trivial,
// minus(p.minus() - sibling()->minus());
} else {
// If this parton was assumed emitter in the evolution, life is simpler.
sibling()->pT(-qT);
sibling()->y(sibling()->y0());
sibling()->plus(sibling()->mt()*exp(-sibling()->y()));
sibling()->minus(sibling()->mt2()/sibling()->plus());
pT(TransverseMomentum(p.x(), p.y()) + qT);
plus(p.plus() - sibling()->plus());
if ( plus() <= ZERO ) return false;
// minus(mt2()/plus());
y(log(mt()/plus()));
}
minus(p.minus() - sibling()->minus());
return true;
}
bool ShadowParton::setEmissionMomentaPlus(const LorentzMomentum & p, bool forced) {
static DebugItem noforce("DIPSY::NeverForceKT", 6);
static DebugItem forcektz("DIPSY::ForceKTZ", 6);
// *** TODO *** Think this through! What is actually generated in
// the momentum space sense is lightcone fraction and transverese
// momentum. So the emission will always succeed.
TransverseMomentum qT = parent()? -pT0(): sibling()->pT0();
double z = plus0()/(plus0() + sibling()->plus0());
if ( noforce ) forced = false;
double ffac = 0.5;
if ( forcektz) ffac = 1.0 - z;
if ( forced ) qT = ffac*TransverseMomentum(p.x(), p.y());
sibling()->plus((1.0 - z)*p.plus());
if ( sibling()->plus() <= ZERO ) return false;
sibling()->pT(qT);
sibling()->minus(sibling()->mt2()/sibling()->plus());
sibling()->y(log(sibling()->mt()/sibling()->plus()));
plus(z*p.plus());
if ( plus() <= ZERO ) return false;
pT(TransverseMomentum(p.x(), p.y()) - qT);
y(log(mt()/plus()));
minus(p.minus() - sibling()->minus());
return true;
}
bool ShadowParton::orderfail(const Propagator & prop) const {
Energy pos = colourSibling()? prop.acopos: prop.colpos;
Energy neg = colourSibling()? prop.aconeg: prop.colneg;
Energy2 ptp = colourSibling()? prop.acoptp: prop.colptp;
Energy2 ptnow = prop.p.perp2();
Energy2 ptnxt = (prop.p - sibling()->momentum()).perp2();
if ( ptnow >= max(ptp, ptnxt) || ptnow <= min(ptp, ptnxt) )
return false;
return sibling()->plus() > pos || sibling()->minus() < neg;
}
ShadowParton::Propagator ShadowParton::
propagator(InvEnergy2 r2, int mode) {
static DebugItem unorderlock("DIPSY::UnorderLock", 6);
Propagator prop;
// If we reach a parton that has been set on shell, we will simply
// return its momentum and set it off-shell.
if ( onShell() ) {
if ( mode >= 0 ) unsetOnShell();
return momentum();
}
// If this was a valence, ask the DipoleState about its momentum.
if ( !mother() ) return dipoleState().incomingMomentum(this, mode);
// Now, if this emission was not resolved then simply return the
// propagator of the mother. However, if the emission is needed for
// subsequent interactions or if the emitted parton was a valence,
// we need to force it. with a special procedure.
bool forced = forceEmission();
bool unresolved = !resolved(r2);
// First we check if a resolved emission is possible.
if ( !unresolved ) {
// Get the propagator of the mother with the new resolution
// scale. But don't put anything on-shell yet in case the emission
// is rejected later.
prop = mother()->propagator(res(), -1);
// First check that it was at all kinematically possible perform
// the emission.
if ( !prop.fail && setEmissionMomenta(prop.p, false) ) {
// OK. That seemed to work, but we must also check the ordering.
// Now depending on the colour line of the emitted parton, it
// must be ordered in light-cone momenta with previous partons
// on the same side. If that is not the case, the emissionis
// marked unresolved.
if ( !( unorderlock && sibling() && sibling()->locked() ) )
unresolved = orderfail(prop);
} else {
// Since the emission could not be performed, we flag it
// unresolved.
unresolved = true;
}
}
// If the emission was really resolved, we get the incoming
// propagator again, but this time put stuff on-shell. Then we
// return the outgoing propagator, after setting the ordering for
// the subsequent emissions, and we're done.
if ( !unresolved ) {
if ( mode >= 0 ) prop = mother()->propagator(res(), mode);
sibling()->setOnShell(mode);
return setup(prop);
}
// OK, so it was unresolved. Get the incoming propagator with the
// previous resolution scale. If it was not forced, then let it go.
prop = mother()->propagator(r2, mode);
if ( !forced ) return prop;
// However, if we have to force it we need to check that it really works.
if ( !setEmissionMomenta(prop.p, true) ) {
// If it doesn't work, just give up the whole thing and fail the
// whole propagator chain.
prop.fail = true;
return prop;
}
// If it does work we set things on-shell, return the propagator and
// we're done.
sibling()->setOnShell(mode);
prop.p -= sibling()->momentum();
prop.setmaxkt();
return prop;
}
ShadowParton::Propagator ShadowParton::setup(Propagator & prop) const {
if ( colourSibling() ) {
prop.acopos = sibling()->plus();
prop.aconeg = sibling()->minus();
prop.acoptp = prop.p.perp2();
} else {
prop.colpos = sibling()->plus();
prop.colneg = sibling()->minus();
prop.colptp = prop.p.perp2();
}
prop.p -= sibling()->momentum();
prop.setmaxkt();
return prop;
}
tSPartonPtr ShadowParton::findFirstOnShell() {
if ( original()->onShell() ) return this;
if ( !next() ) return tSPartonPtr();
if ( next()->colourSibling() ) {
tSPartonPtr ch = child()->findFirstOnShell();
if ( ch ) return ch;
}
return next()->findFirstOnShell();
}
tSPartonPtr ShadowParton::findSecondOnShell() {
if ( original()->onShell() ) return this;
if ( !next() ) return tSPartonPtr();
if ( !next()->colourSibling() ) {
tSPartonPtr ch = child()->findSecondOnShell();
if ( ch ) return ch;
}
return next()->findSecondOnShell();
}
Ariadne5::ClonePtr ShadowParton::clone() const {
return new_ptr(*this);
}
void ShadowParton::mirror(double yf) {
y(2.0*yf - y());
swap(thePlus, theMinus);
if ( next() ) next()->mirror(yf);
if ( child() ) child()->mirror(yf);
}
void ShadowParton::translate(const ImpactParameters & b) {
thePT = b.rotatePT(thePT);
if ( next() ) next()->translate(b);
if ( child() ) child()->translate(b);
}
void ShadowParton::rebind(const TranslationMap & trans) {
thePrevious = trans.translate(thePrevious);
theParent = trans.translate(theParent);
theSibling = trans.translate(theSibling);
theNext = trans.translate(theNext);
theChild = trans.translate(theChild);
}
DipoleState& ShadowParton::dipoleState() const {
return original()->dipoleState();
}
double ShadowParton::pTScale() const {
return Current<DipoleEventHandler>()->emitter().pTScale();
}
Energy ShadowParton::mass() const {
if ( theMass < ZERO )
theMass = CurrentGenerator::current().getParticleData(flavour())->mass();
return theMass;
}
void ShadowParton::debugme() {
// cout << "data for ShadowParton " << this << endl;
// cout << "thePosition1: " << thePosition.first*GeV
// << ", thePosition2: " << thePosition.second*GeV
// << ", thePlus: " << thePlus/GeV
// << ", thePT: " << thePT.pt()/GeV
// << ", theMinus: " << theMinus/GeV
// << ", theY: " << theY
// << ", theFlavour: " << theFlavour
// << ", hasInteracted: " << hasInteracted
// << ", isOnShell: " << isOnShell
// << ", isValence: " << isValence
// << ", theMass: " << theMass/GeV << endl;
memememe = true;
valenceMother()->debugTree("");
memememe = false;
}
void ShadowParton::checkMomentum(Sum20Momentum & sum20,
const ImpactParameters * b) const {
if ( onShell() ) {
if ( b ) sum20 -= lightCone(minus(), plus(), b->rotatePT(pT()));
else sum20 -= momentum();
}
if ( next() ) next()->checkMomentum(sum20, b);
if ( child() ) child()->checkMomentum(sum20, b);
}
void ShadowParton::debugTree(string indent) {
cerr << indent << (memememe? "==": "--")
<< (valence()? "v": "-") << (locked()? "%": "-");
if ( interactionRoot() ) {
set<int>::iterator i = theInteractionRoots.begin();
cerr << "{" << *i;
while ( ++i != theInteractionRoots.end() )
cerr << "," << *i;
cerr << "}";
}
cerr << (interacted()? "+": "-");
if ( interacting() ) {
set<int>::iterator i = theInteractions.begin();
cerr << "[" << *i;
while ( ++i != theInteractions.end() )
cerr << "," << *i;
cerr << "]";
}
cerr << (onShell()? "*": "-") << (memememe? "=>": "->");
if ( onShell() )
cerr << "[" << pT().x()/GeV << ", "
<< pT().y()/GeV << ", "
<< plus()/GeV << "]";
else if ( interacted() )
cerr << "(" << pT().x()/GeV << ", "
<< pT().y()/GeV << ", "
<< plus()/GeV << ")";
cerr << endl;
if ( indent.size() > 1 && indent[indent.size() - 1] == '\\' )
indent[indent.size() - 1] = ' ';
if ( next() && child() ) {
if ( child()->interacted() ) next()->debugTree(indent + " +");
else next()->debugTree(indent + " |");
}
if ( next() && !child() ) next()->debugTree(indent + " ");
if ( child() ) child()->debugTree(indent + " \\");
}
/*
----->
|---->
| |---->
| \---->
| |---->
| \---->
\---->
*/
void ShadowParton::persistentOutput(PersistentOStream & os) const {
os << theOriginal << ounit(thePlus, GeV)
<< ounit(thePT, GeV) << ounit(thePT0, GeV) << ounit(theMass, GeV)
<< ounit(theMinus, GeV) << theY << theY0 << theFlavour
<< thePrevious << theParent << theSibling
<< theNext << theChild
<< ounit(theEmissionFactor, 1.0/GeV2) << ounit(theRes, 1.0/GeV2)
<< hasInteracted << isOnShell << isValence << hasColourSibling;
}
void ShadowParton::persistentInput(PersistentIStream & is, int) {
is >> theOriginal >> iunit(thePlus, GeV)
>> iunit(thePT, GeV) >> iunit(thePT0, GeV) >> iunit(theMass, GeV)
>> iunit(theMinus, GeV) >> theY >> theY0 >> theFlavour
>> thePrevious >> theParent >> theSibling
>> theNext >> theChild
>> iunit(theEmissionFactor, 1.0/GeV2) >> iunit(theRes, 1.0/GeV2)
>> hasInteracted >> isOnShell >> isValence >> hasColourSibling;
}
DescribeClass<ShadowParton,Ariadne5::CloneBase>
describeDIPSYShadowParton("DIPSY::ShadowParton", "libAriadne5.so libDIPSY.so");
// Definition of the static class description member.
void ShadowParton::Init() {}
diff --git a/DIPSY/ShadowParton.h b/DIPSY/ShadowParton.h
--- a/DIPSY/ShadowParton.h
+++ b/DIPSY/ShadowParton.h
@@ -1,1016 +1,1016 @@
// -*- C++ -*-
#ifndef DIPSY_ShadowParton_H
#define DIPSY_ShadowParton_H
//
// This is the declaration of the ShadowParton class.
//
#include "ThePEG/Config/ThePEG.h"
#include "ThePEG/Vectors/Transverse.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/Repository/UseRandom.h"
#include "Ariadne/Config/CloneBase.h"
#include "ShadowParton.fh"
#include "Parton.h"
#include "Dipole.fh"
#include "DipoleXSec.fh"
#include "Sum20Momentum.h"
namespace DIPSY {
using namespace ThePEG;
class ImpactParameters;
/**
* Here is the documentation of the ShadowParton class.
*/
class ShadowParton: public Ariadne5::CloneBase {
public:
/**
* Typedef for position in transverse coordinate space.
*/
typedef Transverse<InvEnergy> Point;
/**
* A pair of partons.
*/
typedef pair<tSPartonPtr,tSPartonPtr> tSPartonPair;
/**
* Helper class for traversing along a propagator to an interaction
*/
struct Propagator {
/**
* Constructor.
*/
Propagator(): colpos(Constants::MaxEnergy), colneg(ZERO), colptp(ZERO),
acopos(Constants::MaxEnergy), aconeg(ZERO), acoptp(ZERO),
maxkt(ZERO), fail(false) {}
/**
* Copy constructor.
*/
Propagator(const Propagator & k)
: p(k.p), colpos(k.colpos), colneg(k.colneg), colptp(k.colptp),
acopos(k.acopos), aconeg(k.aconeg), acoptp(k.acoptp),
maxkt(k.maxkt), fail(k.fail) {}
/**
* Construct from momentum.
p */
Propagator(const LorentzMomentum & mom)
: p(mom), colpos(Constants::MaxEnergy), colneg(ZERO), colptp(ZERO),
acopos(Constants::MaxEnergy), aconeg(ZERO), acoptp(ZERO),
maxkt(ZERO), fail(false) {}
/**
* The Momentum of the propagator.
*/
LorentzMomentum p;
/**
* The positive light-cone momentum of the previous emission on
* the colour line.
*/
Energy colpos;
/**
* The negative light-cone momentum of the previous emission on
* the colour line.
*/
Energy colneg;
/**
* The pt of the propagator before the previous emission on the
* colour line (ie. previous emission with an inti-colour sibling).
*/
Energy2 colptp;
/**
* The positive light-cone momentum of the previous emission on
* the anti-colour line (ie. previous emission with a colour sibling).
*/
Energy acopos;
/**
* Thenegative light-cone momentum of the previous emission on the
* anti-colour line.
*/
Energy aconeg;
/**
* The pt of the propagator before the previous emission on the
* anti-colour line.
*/
Energy2 acoptp;
/**
* The maximum transverse momentum of the chain of propagators
* leading up to (and including) this.
*/
Energy maxkt;
/**
* Indicate that the propagator has failed.
*/
bool fail;
/**
* Update the maximumtransverse momentum.
*/
void setmaxkt() {
if ( p.perp() > maxkt ) maxkt = p.perp();
}
};
/**
* Helper class to temporarily protect a propagator.
*/
struct Lock {
/**
* The only constructor. Locking the propagator to a given parton.
*/
Lock(tPartonPtr p): sp(p->shadow()) {
sp->lock();
}
/**
* The destructor, unlocking the propagator.
*/
~Lock() {
sp->unlock();
}
/**
* The parton to which the propagator should be locked.
*/
tSPartonPtr sp;
};
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
inline ShadowParton()
: thePlus(ZERO), theMass(-1*GeV), theMinus(0*GeV),
theY(0), theY0(0), theFlavour(ParticleID::g),
theEmissionFactor(ZERO), theRes(ZERO), isLocked(false),
hasInteracted(false), isOnShell(false), isValence(false),
hasColourSibling(false), memememe(false) {}
/**
* Construct from ordinary parton.
*/
ShadowParton(Parton & p);
/**
* The destructor.
*/
virtual ~ShadowParton();
/**
* Create a valence shadow parton from a given ordinary parton.
*/
static SPartonPtr createValence(Parton & p);
/**
* Easy access to alphaS.
*/
- static double alphaS(InvEnergy2 r2);
+ static double alphaSr(InvEnergy2 r2);
/**
* Setup shadow partons in an emission.
*/
void setupEmission(Parton & emitter, Parton & produced, Parton & recoiler);
/**
* Setup pointers to and from neighboring partons.
*/
void setupParton();
//@}
protected:
/** @name The virtual functions to be overridden in sub-classes. */
//@{
/**
* Return a simple clone of this object. Should be implemented as
* <code>return new_ptr(*this);</code> by a derived class.
*/
virtual Ariadne5::ClonePtr clone() const;
/**
* Rebind pointers to other CloneBase objects. Called after a number
* of interconnected CloneBase objects have been cloned, so that
* the cloned objects will refer to the cloned copies afterwards.
*
* @param trans a TranslationMap relating the original objects to
* their respective clones.
*/
virtual void rebind(const TranslationMap & trans);
//@}
public:
/**
* Return the DipoleState to which this parton belongs. If it was
* originally belonged to one state which was subsequently merged
* into another, the parton will belong to the latter state.
*/
DipoleState & dipoleState() const;
/**
* finds the pTscale through the dipolestates emitter.
*/
double pTScale() const;
/**
* Calculate the squared transverse distance to the given parton.
*/
inline InvEnergy2 dist2(const ShadowParton & p) const {
return (position() - p.position()).pt2();
}
/**
* Calculate the transverse distance to the given parton.
*/
inline InvEnergy dist(const ShadowParton & p) const {
return sqrt(dist2(p));
}
/**
* Produce a ThePEG::Particle corresponding to this parton.
*/
PPtr produceParticle() const;
/**
* The mass of this parton.
*/
Energy mass() const;
/**
* The transverse momentum squared of this parton.
*/
Energy2 pt2() const {
return pT().pt2();
}
/**
* The transverse mass squared of this parton.
*/
Energy2 mt2() const {
return pt2() + sqr(mass());
}
/**
* The transverse mass of this parton in the emission.
*/
Energy2 mt02() const {
return pT0().pt2() + sqr(mass());
}
/**
* The transverse mass of this parton in the emission.
*/
Energy mt0() const {
return sqrt(mt02());
}
/**
* The transverse momentum of this parton.
*/
Energy pt() const {
return sqrt(pt2());
}
/**
* The transverse momentum of this parton.
*/
Energy mt() const {
return sqrt(mt2());
}
/**
* The final-state momentum of this particle.
*/
LorentzMomentum momentum() const {
return lightCone(plus(), mt2()/plus(), pT());
}
/** @name Simple access functions. */
//@{
/**
* Get the position in impact parameter space.
*/
inline const Point & position() const {
return original()->position();
}
/**
* Get the positive light-cone momentum.
*/
inline Energy plus() const {
return thePlus;
}
/**
* Get the original positive light-cone momentum.
*/
inline Energy plus0() const {
return mt0()*exp(-y0());
}
/**
* Get the transverse momentum.
*/
inline TransverseMomentum pT() const {
return thePT;
}
/**
* Get the transverse momentum.
*/
inline TransverseMomentum pT0() const {
return thePT0;
}
/**
* Get the accumulated negative light-cone momentum deficit.
*/
inline Energy minus() const {
return theMinus;
}
/**
* Get the rapidity.
*/
inline double y() const {
return theY;
}
/**
* Get the rapidity generated in the emission.
*/
inline double y0() const {
return theY0;
}
/**
* Get the flavour of this parton.
*/
inline long flavour() const {
return theFlavour;
}
/**
* Get the original DIPSY parton.
*/
tPartonPtr original() const {
return theOriginal;
}
/**
* Get the previous instance of this parton befor it was emitted or
* swinged.
*/
inline tSPartonPtr previous() const {
return thePrevious;
}
/**
* Get the parent parton if this was emitted.
*/
inline tSPartonPtr parent() const {
return theParent;
}
/**
* Get the sibling of this parton if any.
*/
inline tSPartonPtr sibling() const {
return theSibling;
}
/**
* Get the next version of this parton if emitted or swinged.
*/
inline tSPartonPtr next() const {
return theNext;
}
/**
* Get the first version of this parton if emitted or swinged.
*/
tSPartonPtr initial();
/**
* Get the first (grand)mother of this parton.
*/
tSPartonPtr valenceMother();
/**
* Get the last version of this parton if emitted or swinged.
*/
tSPartonPtr last();
/**
* Get the last version of this parton if emitted or swinged.
*/
tcSPartonPtr last() const;
/**
* Get the parton this has emitted if any.
*/
inline tSPartonPtr child() const {
return theChild;
}
/**
* Get the mother parton, either previous() or parent().
*/
inline tSPartonPtr mother() const {
return parent()? parent(): previous();
}
/**
* Indicate that the corresponding emission is on a protected
* propagator. Any other propagator must assume that this emission
* must be resolved.
*/
inline bool locked() const {
return isLocked;
}
/**
* Indicate that the propagator leading up to this parton is protected.
*/
void lock();
/**
* Indicate that the propagator leading up to thi parton is no
* longer protected.
*/
void unlock();
/**
* Indicate if this parton has interacted.
*/
inline bool interacted() const {
return hasInteracted;
}
/**
* Return true if the sibling is on the colour side of this parton.
*/
inline bool colourSibling() const {
return hasColourSibling;
}
/**
* Return if this shadow was the root of an interacting propagator.
*/
inline bool interactionRoot() const {
return theInteractionRoots.size() > 0;
}
/**
* Return if this shadow was the root of an interacting propagator.
*/
inline bool hasInteractionRoot(int i) const {
return theInteractionRoots.find(i) != theInteractionRoots.end();
}
/**
* Return if this shadow was directly involved in the interaction.
*/
inline int interacting() const {
return theInteractions.size() > 0;
}
/**
* Return if this parton is on shell.
*/
inline bool onShell() const {
return isOnShell;
}
/**
* Set if this parton is on shell.
*/
inline void onShell(bool b) {
isOnShell = b;
}
/**
* Indicate that this parton is the root of an interaction.
*/
inline void interactionRoot(int i) {
theInteractionRoots.insert(i);
}
/**
* Set if this shadow is directly involved in an interaction.
*/
inline void interacting(int i) {
theInteractions.insert(i);
}
/**
* Return if this parton is a valence parton.
*/
inline bool valence() const {
return isValence;
}
/**
* Set if this parton is a valence parton.
*/
inline void valence(bool b) {
isValence = b;
}
/**
* Set the positive light-cone momentum.
*/
inline void plus(Energy x) {
thePlus = x;
}
/**
* Set the transverse momentum.
*/
inline void pT(const TransverseMomentum & x) {
thePT = x;
}
/**
* Set the momentum using transverse momentum and positive
* light-cone momentum. Set also other components assuming real.
*/
void pTplus(const TransverseMomentum & qt, Energy qp);
/**
* Reset the momentum to its original value in the evolution.
*/
void resetMomentum0() {
pTplus(pT0(), mt0()/exp(y0()));
}
/**
* Set the transverse momentum.
*/
inline void pT0(const TransverseMomentum & x) {
thePT0 = x;
}
/**
* Set the accumulated negative light-cone momentum deficit.
*/
inline void minus(Energy x) {
theMinus = x;
}
/**
* Set the rapidity.
*/
inline void y(double x) {
theY = x;
}
/**
* Set the rapidity.
*/
inline void y0(double x) {
theY0 = x;
}
/**
* Set the flavour of this parton.
*/
inline void flavour(long x) {
theFlavour = (x == 0? ParticleID::g: x);
}
/**
* Set the parent parton.
*/
inline void parent(tSPartonPtr p) {
theParent = p;
}
/**
* Indicate that this parton has interacted and mark all parent and
* original partons if needed.
*/
void interact();
/**
* The emission factor for this parton if emitted or emitter.
*/
InvEnergy2 emissionFactor() const {
return theEmissionFactor;
}
/**
* The resolusion scale factor for this parton if emitted or emitter.
*/
InvEnergy2 res() const {
return theRes;
}
/**
* Return true if this parton and its sibling are resolved.
*/
bool resolved(InvEnergy2 r2) const {
return ( ( sibling() && ( sibling()->locked()
|| emissionFactor() > r2 ) ) );
// return ( ( sibling() && ( sibling()->locked()
// || emissionFactor() > r2*alphaS(r2) ) ) );
}
/**
* Return true if the sibling must be put on-shell even if it was not
* resolved, because it will partake in a subsequent interaction or is
* a valence.
*/
bool forceEmission() const {
return sibling() && ( sibling()->valence()
|| sibling()->interactionRoot() );
}
/**
* Go back in the history of this shadow parton and find the
* original parton which would be resolved at a given size or would
* be the interaction root. Always resolve emissions involving \a
* stopp.
*/
tSPartonPtr resolveInteraction(InvEnergy2 d2, tPartonPtr stopp) {
Lock safeguard(stopp);
- return resolveInteraction(alphaS(d2)*d2);
+ return resolveInteraction(alphaSr(d2)*d2);
// return resolveInteraction(d2);
}
/**
* Go back in the history of this shadow parton and find the
* original parton which would be resolved at a given size scale or
* would be the interaction root.
*/
tSPartonPtr resolveInteraction(InvEnergy2 r2);
/**
* Go back in the history of this shadow parton and find the
* original parton which would be resolved at a given size. Always
* resolve emissions involving \a stopp.
*/
tSPartonPtr resolve(InvEnergy2 d2, tPartonPtr stopp) {
Lock safeguard(stopp);
- return resolve(d2*alphaS(d2));
+ return resolve(d2*alphaSr(d2));
// return resolve(d2);
}
/**
* Go back in the history of this shadow parton and find the
* original parton which would be resolved at a given size. Always
* resolve emissions involving \a stopp. (const version).
*/
// tcSPartonPtr resolve(InvEnergy2 r2, tPartonPtr stopp) const;
/**
* Go back in the history and flag all partons which are resoved by
* the given size to be set on-shell. Always
* resolve emissions involving \a stopp.
*/
// void flagOnShell(InvEnergy2 r2, tPartonPtr stopp);
/**
* If this parton is not on shell, find an emitted parton
* with the same colour lines (modulo swing) that is.
*/
tSPartonPtr findFirstOnShell();
/**
* If this parton is not on shell, find an emitted parton
* with the same colour lines (modulo swing) that is.
*/
tSPartonPtr findSecondOnShell();
/**
* Flag on-shell if \a mode >= 0 and copy to original parton if \a
* mode > 0.
*/
void setOnShell(int mode);
/**
* If prevoíously set on-shell, clear the flag.
*/
void unsetOnShell();
/**
* Go forward in the evolution and reset all interaction flags.
*/
void reset();
/**
* Go forward in the evolution and reset all interacted flags.
*/
void resetInteracted();
/**
* Set the momenta in an emission, assuming the incoming momentum \a p.
*/
bool setEmissionMomenta(const LorentzMomentum & p, bool valencefix);
bool setEmissionMomentaPlus(const LorentzMomentum & p, bool valencefix);
protected:
/**
* Go back in the history of this shadow parton and find the
* original parton which would be resolved at a given size scale.
*/
tSPartonPtr resolve(InvEnergy2 r2);
public:
/**
* Go back in the history and find the momentum of this incoming
* parton. Always resolve emissions involving \a stopp. If \a mode
* >= 0 flag partons which would be put on shell. if \a mode > 0
* also propagate the momentum to the original() parton.
*/
Propagator propagator(InvEnergy2 d2, tPartonPtr stopp, int mode) {
Lock safeguard(stopp);
- return propagator(d2*alphaS(d2), mode);
+ return propagator(d2*alphaSr(d2), mode);
// return propagator(d2, mode);
}
Propagator propagator(InvEnergy2 r2, int mode);
Propagator setMomentum(const Propagator & prop) {
plus(prop.p.plus());
pT(TransverseMomentum(prop.p.x(), prop.p.y()));
return prop;
}
void checkMomentum(Sum20Momentum & sum20,
const ImpactParameters * b = 0) const;
/**
* Check if the propagator leading to this interaction is still
* viable. Ie. Either that it is the primary interaction, or that a
* previous interaction still has put an appropriate parton
* on-shell.
* *** TODO *** fix a better solution to this problem
*/
bool checkInteractionRoot(int i) const;
/**
* Indicate that this parton should be tested for an
* interaction. Insert the corresponding interaction object at the
* correct place in the chain. The primary interaction is always at
* one of the incoming shadows. Secondary interactions are inserted
* at a parton which has been or should be made real by a previous
* emission. If this parton already had an interaction, simply leave
* it as it is.
*/
void insertInteraction(int i);
/**
* Indicate that a previously tested interaction is accepted. This
* is done by marking all propagators interacted() in the chain down
* to the one where the interaction was found.
*/
void acceptInteraction(int i);
/**
* Make this and all its anceseters incoming.
*/
void makeIncoming();
/**
* Indicate that the interaction that has been tested was rejected
* by simply removing the interaction root inserted by
* insertInteraction().
*/
void rejectInteraction(int i);
/**
* Change direction before producing collision.
*/
void mirror(double yframe);
/**
* Translate according to the impagt parameter.
*/
void translate(const ImpactParameters & b);
/**
* Check if the generated emission fails the ordering requirement.
*/
bool orderfail(const Propagator & prop) const;
/**
* Setup the continuing propagater with the generated emission.
*/
Propagator setup(Propagator & prop) const;
/**
* Prints all the member variables to cerr.
*/
void debugme();
/**
* Debug the structure of the shadow tree.
*/
void debugTree(string indent);
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
private:
/**
* The original DIPSY parton
*/
tPartonPtr theOriginal;
/**
* The positive light-cone momentum.
*/
Energy thePlus;
/**
* The transverse momentum.
*/
TransverseMomentum thePT;
/**
* The transverse momentum generated in the emission.
*/
TransverseMomentum thePT0;
/**
* The mass of this parton.
*/
mutable Energy theMass;
/**
* The accumulated negative light-cone momentum deficit.
*/
Energy theMinus;
/**
* The rapidity.
*/
double theY;
/**
* The rapidity generated in the emission.
*/
double theY0;
/**
* The flavour of this parton.
*/
long theFlavour;
/**
* The state of this parton, if any, before the swing or the emission of this
* parton's sibling. Is aways null if theParent exists.
*/
tSPartonPtr thePrevious;
/**
* The parent parton if this has emitted or swinged. Is aways null if
* thePrevious exists.
*/
tSPartonPtr theParent;
/**
* The sibling of this parton if any.
*/
tSPartonPtr theSibling;
/**
* The state of this parton after the emission of the child. Is null
* if this parton has not emitted.
*/
SPartonPtr theNext;
/**
* The child this parton has emitted, if any.
*/
SPartonPtr theChild;
/**
* The emission factor for this parton if emitted or emitter.
*/
InvEnergy2 theEmissionFactor;
/**
* The resolution factor for this parton if emitted or emitter.
*/
InvEnergy2 theRes;
/**
* Indicate that the corresponding emission is on a protected
* propagator. Any other propagator must assume that this emission
* must be resolved.
*/
bool isLocked;
/**
* Indicate if this parton has interacted.
*/
bool hasInteracted;
/**
* Indicate if this parton is on shell, that is if it has
* been supplied with the neccesary p+ or p- for left or rightmoving
* particles respectively.
*/
bool isOnShell;
/**
* This is root of an interaction chain.
*/
set<int> theInteractionRoots;
/**
* The interactions this was directly involved with.
*/
set<int> theInteractions;
/**
* Indicate if this parton is a valence parton.
*/
bool isValence;
/**
* Indicate if this partons sibling is on the colour side (true) or
* the anti-colour side (false).
*/
bool hasColourSibling;
protected:
/**
* Exception class for bad kinematics.
*/
struct ShadowPartonKinematicsException: public Exception {};
public:
bool memememe;
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
ShadowParton & operator=(const ShadowParton &);
};
}
#endif /* DIPSY_ShadowParton_H */
diff --git a/DIPSY/SimpleProton.cc b/DIPSY/SimpleProton.cc
--- a/DIPSY/SimpleProton.cc
+++ b/DIPSY/SimpleProton.cc
@@ -1,327 +1,345 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the SimpleProton class.
//
#include "SimpleProton.h"
#include "SimpleProtonState.h"
#include "DipoleEventHandler.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/PDT/ParticleData.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/Utilities/Throw.h"
#include "ThePEG/Utilities/UtilityBase.h"
#include "ThePEG/Utilities/SimplePhaseSpace.h"
#include "ThePEG/Utilities/MaxCmp.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/PDT/StandardMatchers.h"
#include "ThePEG/Utilities/Current.h"
+#include "Ariadne/Config/ColourInfo.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "gsl/gsl_sf_erf.h"
using namespace DIPSY;
SimpleProton::SimpleProton()
: theR(0.0*InvGeV), theR0(0.0*InvGeV), theRapidityWidth(0.0), theAngleWidth(0.0),
theConnected(0), theCollapseTolerance(0.1*GeV) {}
SimpleProton::~SimpleProton() {}
IBPtr SimpleProton::clone() const {
return new_ptr(*this);
}
IBPtr SimpleProton::fullclone() const {
return new_ptr(*this);
}
InvEnergy SimpleProton::R() const {
return theR > ZERO? theR: Current<DipoleEventHandler>()->rMax();
}
InvEnergy SimpleProton::r0() const {
return theR0 > ZERO? theR0: Current<DipoleEventHandler>()->baryonSize();
}
void SimpleProton::initialize(const DipoleEventHandler & eh) {
tcPDPtr gluon = generator()->getParticleData(ParticleID::g);
if ( remdec && !remdec->canHandle(particle(), gluon ) )
Throw<InitException>()
<< "The given remnant decayer could not handle the particle "
<< "in this wave function.";
}
Energy2 SimpleProton::m2() const {
return sqr(particle()->mass());
}
DipoleStatePtr SimpleProton::
generate(const DipoleEventHandler & eh, Energy plus) {
InvEnergy r = rndShiftGauss();
Energy minus = m2()/plus;
return new_ptr(SimpleProtonState(eh, plus, minus, theAngleWidth, theRapidityWidth,
connectOption(), new_ptr(WFInfo(this, r)), 1.0));
}
InvEnergy SimpleProton::rndShiftGauss() const {
InvEnergy2 s1 = R()*r0()*sqrt(Constants::pi);
InvEnergy2 s2 = sqr(R());
InvEnergy2 s3 = s1*gsl_sf_erf(r0()/R());
do {
InvEnergy2 rsum = UseRandom::rnd()*(s1 + s2 + s3);
if ( s1 > rsum )
return R()*UseRandom::rndGauss() + r0();
else if ( s1 + s2 > rsum )
return R()*sqrt(-log(UseRandom::rnd())) + r0();
InvEnergy r = r0() - R()*UseRandom::rndGauss();
if ( r > 0.0*InvGeV && r/r0() > UseRandom::rnd() ) return r;
} while ( true );
return 0.0*InvGeV;
}
void SimpleProton::setParticle(PDPtr p) {
if ( !BaryonMatcher::Check(abs(p->id())) )
throw InterfaceException()
<< "Cannot set " << p->name()
<< " as particle for a proton wave function. "
<< "Only baryons are allowed." << Exception::warning;
WaveFunction::setParticle(p);
}
void SimpleProton::fixValence(Step & step, tPPtr particle, const vector<PPtr> & val) const {
if ( connectOption() != 0 || !remdec ) return;
// If the hadron is not colour connected to the rest of the state,
// then try to collapse it into the original hadron.
if ( collapseToProton(step, particle, val) ) return;
// Otherwise first find the gluon to split into a q and qq pair and split it.
splitValence(step, particle, val);
}
bool SimpleProton::collapseToProton(Step & step, tPPtr p, const vector<PPtr> & val) const {
if ( val.size() != 3 ) return false;
if ( val[0]->colourLine() == val[1]->antiColourLine() ) {
if ( val[1]->colourLine() != val[2]->antiColourLine() ) return false;
if ( val[2]->colourLine() != val[0]->antiColourLine() ) return false;
} else {
if ( val[0]->colourLine() != val[2]->antiColourLine() ) return false;
if ( val[2]->colourLine() != val[1]->antiColourLine() ) return false;
if ( val[1]->colourLine() != val[0]->antiColourLine() ) return false;
}
// Get an instance of the hadron and check that its mass is not too different.
Lorentz5Momentum pv = Utilities::sumMomentum(val);
if ( abs(pv.mass() - p->mass()) > collapseTolerance() ) return false;
// get the total momentum of the collision and determine how to
// boost it to put the hadron on-shell.
Lorentz5Momentum ptot = step.collision()->incoming().first->momentum() +
step.collision()->incoming().second->momentum();
Lorentz5Momentum pr = ptot - pv; // This is the recoil system to be used for momentum shuffling
LorentzRotation Rshift;
try {
p->setMomentum(DipoleState::changeMass(pv, p->mass(), pr, &Rshift));
} catch ( ImpossibleKinematics e ) {
return false;
}
p->setVertex((val[0]->vertex() + val[1]->vertex() + val[2]->vertex())/3.0);
step.addDecayProduct(val.begin(), val.end(), p);
step.collision()->incoming().first->transform(Rshift);
step.collision()->incoming().second->transform(Rshift);
return true;
}
bool SimpleProton::splitValence(Step & step, tPPtr p, const vector<PPtr> & val) const {
// First get the total momentum of the collision.
LorentzMomentum ptot = step.collision()->incoming().first->momentum() +
step.collision()->incoming().second->momentum();
// Now we choose the valence gluon with the smallest transverse
// momentum. Primarily we only consider those valence gluons which
// can be split into massive quarks and di-quarks, if this is not
// possible also others are considered with quark masses put to zero
// and hoping for the best.
MinCmp<Energy2,tPPtr> sel, primsel;
LorentzPoint vnew;
for ( int i = 0, N = val.size(); i < N; ++i ) {
vnew += val[i]->vertex()/double(N);
if ( val[i]->id() == ParticleID::g ) {
sel(val[i]->momentum().perp2(), val[i]);
if ( ptot.m() - (ptot - val[i]->momentum()).m() > 2.0*p->mass() )
primsel(val[i]->momentum().perp2(), val[i]);
}
}
tPVector valence(1, sel.index());
if ( valence.empty() ) return false;
if ( primsel.index() ) valence[0] = primsel.index();
+ int colindx = Ariadne5::ColourInfo::colIndex(*valence[0]);
+ int acoindx = Ariadne5::ColourInfo::acoIndex(*valence[0]);
+
tPPtr coln = valence[0]->colourNeighbour(val.begin(), val.end());
tColinePtr coll = valence[0]->colourLine();
tColinePtr acol = valence[0]->antiColourLine();
if ( coln && (valence[0]->momentum() + coln->momentum()).m() < p->mass() ) {
valence.push_back(coln);
acol = coln->antiColourLine();
+ acoindx = Ariadne5::ColourInfo::acoIndex(*coln);
}
coln = valence[0]->antiColourNeighbour(val.begin(), val.end());
if ( coln && (valence[0]->momentum() + coln->momentum()).m() < p->mass() ) {
valence.push_back(coln);
coll = coln->colourLine();
+ colindx = Ariadne5::ColourInfo::colIndex(*coln);
}
if ( valence.size() == 3 && ( valence[1] == valence[2] || coll == acol ) ) {
valence = tPVector(1, valence[0]);
coll = valence[0]->colourLine();
acol = valence[0]->antiColourLine();
+ colindx = Ariadne5::ColourInfo::colIndex(*valence[0]);
+ acoindx = Ariadne5::ColourInfo::acoIndex(*valence[0]);
}
// Now find the momentum of the recoil system used to put the remnants on-shell.
Lorentz5Momentum pv = Utilities::sumMomentum(valence);
LorentzMomentum pr = ptot - pv;
Energy maxmass = sqrt(sqr(ptot.m() - pr.mt()) - pr.perp2());
const SimpleBaryonRemnantDecayer::BaryonContent & bi = remdec->getBaryonInfo(p->dataPtr());
while ( true ) {
// Select remnant flavours
pair<int,int> r = bi.flavsel.select(UseRandom::current());
PPtr qv = getParticleData(r.first*bi.sign)->produceParticle();
PPtr dqv = getParticleData(r.second*bi.sign)->produceParticle();
// Generate transverse momenum and energy splitting.
TransverseMomentum ptv = remdec->pTGenerator()->generate();
Energy2 mt02 = qv->momentum().mass2() + ptv.pt2();
Energy2 mt12 = dqv->momentum().mass2() + ptv.pt2();
// If still too large recoil mass we put quark masses to zero and hope for the best.
if ( maxmass < 2.0*p->mass() ) mt02 = mt12 = ptv.pt2();
double z = remdec->zGenerator().generate(dqv->dataPtr(), qv->dataPtr(), mt12);
Energy mv = sqrt(mt02/(1.0 - z) + mt12/z);
// Make sure the mass is small enough to be kinamatically allowd.
if ( mv >= maxmass ) continue;
// Calculate the momenta of the remnants and how much the rest
// frame of the collision has moved due to momentum reshuffling.
LorentzMomentum pqv = lightCone((1.0 - z)*mv, mt02/((1.0 - z)*mv), ptv);
LorentzMomentum pdqv = lightCone(z*mv, mt12/(z*mv), -ptv);
LorentzRotation Rshift;
Lorentz5Momentum pvnew = DipoleState::changeMass(pv, mv, pr, &Rshift);
// LorentzRotation Rr = Utilities::transformFromCMS(pvnew);
LorentzRotation Rr(pvnew.x()/pvnew.e(), pvnew.y()/pvnew.e(),
pvnew.z()/pvnew.e(), pvnew.e()/mv);
qv->setMomentum(Rr*pqv);
- if ( qv->hasColour() ) coll->addColoured(qv);
- else acol->addAntiColoured(qv);
+ if ( qv->hasColour() ) {
+ coll->addColoured(qv);
+ qv->getInfo().push_back(new_ptr(Ariadne5::ColourInfo(colindx, 0)));
+ } else {
+ acol->addAntiColoured(qv);
+ qv->getInfo().push_back(new_ptr(Ariadne5::ColourInfo(0, acoindx)));
+ }
dqv->setMomentum(Rr*pdqv);
- if ( dqv->hasColour() ) coll->addColoured(dqv);
- else acol->addAntiColoured(dqv);
+ if ( dqv->hasColour() ) {
+ coll->addColoured(dqv);
+ dqv->getInfo().push_back(new_ptr(Ariadne5::ColourInfo(colindx, 0)));
+ } else {
+ acol->addAntiColoured(dqv);
+ dqv->getInfo().push_back(new_ptr(Ariadne5::ColourInfo(0, acoindx)));
+ }
// Lorentz5Momentum pvcheck = qv->momentum() + dqv->momentum();
qv->setVertex(vnew);
dqv->setVertex(vnew);
step.addDecayProduct(valence.begin(), valence.end(), qv);
step.addDecayProduct(valence.begin(), valence.end(), dqv);
step.collision()->incoming().first->transform(Rshift);
step.collision()->incoming().second->transform(Rshift);
DipoleState dummy;
dummy.checkFSMomentum(step);
return true;
}
return false;
}
void SimpleProton::persistentOutput(PersistentOStream & os) const {
os << ounit(theR, InvGeV) << ounit(theR0, InvGeV)
<< ounit(theRapidityWidth, 1.0) << ounit(theAngleWidth, 1.0) << theConnected
<< ounit(theCollapseTolerance, GeV) << remdec;
}
void SimpleProton::persistentInput(PersistentIStream & is, int) {
is >> iunit(theR, InvGeV) >> iunit(theR0, InvGeV)
>> iunit(theRapidityWidth, 1.0) >> iunit(theAngleWidth, 1.0) >> theConnected
>> iunit(theCollapseTolerance, GeV) >> remdec;
}
// Static variable needed for the type description system in ThePEG.
#include "ThePEG/Utilities/DescribeClass.h"
DescribeClass<SimpleProton,DIPSY::WaveFunction>
describeDIPSYSimpleProton("DIPSY::SimpleProton", "libAriadne5.so libDIPSY.so");
void SimpleProton::Init() {
static ClassDocumentation<SimpleProton> documentation
("The SimpleProton class represents the unevolved proton wave function "
"described in terms of an equilatteral triangle of dipoles with a size "
"distributed as a Gaussian.");
static Parameter<SimpleProton,InvEnergy> interfaceR
("R",
"The width of the Gaussian distribution in units of inverse GeV. If zero, "
"the value of <interface>DipoleEventHandler::RMax</interface> of the "
"controlling event handler will be used.",
&SimpleProton::theR, InvGeV, 0.0*InvGeV, 0.0*InvGeV, 0.0*InvGeV,
true, false, Interface::lowerlim);
static Parameter<SimpleProton,InvEnergy> interfaceR0
("R0",
"The shift in the average of the Gaussian distribution in units of "
"inverse GeV. If zero, <interface>DipoleEventHandler::BaryonSize</interface> "
"is used instead.",
&SimpleProton::theR0, InvGeV, 0.0*InvGeV, 0.0*InvGeV, 0.0*InvGeV,
true, false, Interface::lowerlim);
static Parameter<SimpleProton, double> interfaceRapidityWidth
("RapidityWidth",
"The width of the gaussian smearing in rapidity of the individual partons "
"in the starting triangle.",
&SimpleProton::theRapidityWidth, 1.0, 0.2, 0.0, 0.0,
true, false, Interface::lowerlim);
static Parameter<SimpleProton, double> interfaceAngleWidth
("AngleWidth",
"The width in radians of the gaussian smearing of the shape of the triangle. ",
&SimpleProton::theAngleWidth, 1.0, 0.2, 0.0, 0.0,
true, false, Interface::lowerlim);
static Switch<SimpleProton,int> interfaceConnected
("Connected",
"If the three dipoles are connected or not.",
&SimpleProton::theConnected, 0, true, false);
static SwitchOption interfaceConnectedConnected
(interfaceConnected,
"Connected",
"Three gluons.",
0);
static SwitchOption interfaceDisconnected
(interfaceConnected,
"Disconnected",
"6 quarks, pairwise on top of each other.",
1);
static Parameter<SimpleProton,Energy> interfaceCollapseTolerance
("CollapseTolerance",
"The maximum mass difference between the valence system and the "
"hadron allowed for collapsing into the original hadron after "
"the evolution.",
&SimpleProton::theCollapseTolerance, GeV, 0.1*GeV, 0.0*GeV, 0*GeV,
true, false, Interface::lowerlim);
static Reference<SimpleProton,SimpleBaryonRemnantDecayer> interfaceRemnantDecayer
("RemnantDecayer",
"A RemnantDecayer object which is able to produce remnants for the particle ",
&SimpleProton::remdec, false, false, true, true, true);
}
diff --git a/DIPSY/SmallDipoleAbsorber.cc b/DIPSY/SmallDipoleAbsorber.cc
--- a/DIPSY/SmallDipoleAbsorber.cc
+++ b/DIPSY/SmallDipoleAbsorber.cc
@@ -1,777 +1,777 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the SmallDipoleAbsorber class.
//
#include "SmallDipoleAbsorber.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Utilities/Current.h"
#include "DipoleEventHandler.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace DIPSY;
SmallDipoleAbsorber::SmallDipoleAbsorber() {}
SmallDipoleAbsorber::~SmallDipoleAbsorber() {}
IBPtr SmallDipoleAbsorber::clone() const {
return new_ptr(*this);
}
IBPtr SmallDipoleAbsorber::fullclone() const {
return new_ptr(*this);
}
void printInfo( DipolePtr d ) {
cout << "dipole " << d << " has size " << d->size()*GeV <<
". Has neighbours " << d->neighbors().first << " (" << d->neighbors().first->DGLAPsafe()
<< "), " << d->neighbors().second <<" ("<< d->neighbors().second->DGLAPsafe() <<
"). Has children " << d->children().first << ", " << d->children().second <<
". Is DGLAPsafe: " << d->DGLAPsafe() << endl;
}
void SmallDipoleAbsorber::
absorbParton(tPartonPtr p, DipoleState & state ) const {
DipolePtr d1 = p->dipoles().first;
DipolePtr d2 = p->dipoles().second;
if ( !d1 ) {
if ( !(d2->neighbors().second) )
cout << "absorbing qqbar pair!!!!!!!!!!!!!!!!!! :o (bad!)" << endl;
PartonPtr g = d2->partons().second;
d2->neighbors().second->firstNeighbor(d1);
g->dipoles(make_pair(d1, d2->neighbors().second));
d2->children().second = d2->neighbors().second;
g->plus(g->plus() + p->plus());
g->updateMomentum();
g->flavour(p->flavour());
if ( p->valence() ) {
g->valencePT(p->valencePT());
p->parents(make_pair(g,g));
}
state.save();
return;
}
if ( !d2 ) {
if ( !(d1->neighbors().first) )
cout << "absorbing qqbar pair!!!!!!!!!!!!!!!!!! :o (bad!)" << endl;
PartonPtr g = d1->partons().first;
d1->neighbors().first->secondNeighbor(d2);
g->dipoles(make_pair(d1->neighbors().first, d2));
d1->children().second = d1->neighbors().first;
g->plus(g->plus() + p->plus());
g->updateMomentum();
g->flavour(p->flavour());
if ( p->valence() ) {
g->valencePT(p->valencePT());
p->parents(make_pair(g,g));
}
state.save();
return;
}
PartonPtr p1 = d1->partons().first;
PartonPtr p2 = d2->partons().second;
if ( p1 == p2 ) {
state.sortDipoles();
if( !(state.forceSwing(p, 5.0, 0.0)) ) {
cout << "couldnt find swing" << endl;
return; //TODO: move to this class. think through.
}
d1 = p->dipoles().first;
d2 = p->dipoles().second;
p1 = d1->partons().first;
p2 = d2->partons().second;
}
//always save interacting dip, and otherwise the bigger DGLAP safe dip.
if ( ( (d1->DGLAPsafe() && ( !(d2->DGLAPsafe()) || d1->size() >= d2->size()) ) ||
( !(d2->DGLAPsafe()) && d1->size() >= d2->size()) ||
( d1->interacted() )) && !(d2->interacted()) ) {
d2->children().second = d1;
p2->dipoles(make_pair(d1,p2->dipoles().second));
d1->partons(make_pair(p1,p2));
d1->secondNeighbor(d2->neighbors().second);
if ( d1->neighbors().second ) d1->neighbors().second->firstNeighbor(d1);
}
else {
d1->children().second = d2;
p1->dipoles(make_pair(p1->dipoles().first, d2));
d2->partons(make_pair(p1,p2));
d2->firstNeighbor(d1->neighbors().first);
if ( d2->neighbors().first ) d2->neighbors().first->secondNeighbor(d2);
}
//Conserve pT and p+ based on dipole sizes. y and p- adapt.
Parton::Point r1 = p->position() - p1->position();
Parton::Point r2 = p->position() - p2->position();
double P1 = sqr(r2.pt())/( sqr(r1.pt()) + sqr(r2.pt()) );
//dont give p+ to a parton ahead in rapidity if possible.
if ( p1->y() < p->y() && p->y() < p2->y() ) {
P1 = 1.0;
}
else if ( p2->y() < p->y() && p->y() < p1->y() ) {
P1 = 0.0;
}
else if ( p->y() < p2->y() && p->y() < p1->y() && p1->y() > p2->y() ) {
P1 = 0.0;
}
else if ( p->y() < p2->y() && p->y() < p1->y() && p2->y() > p1->y() ) {
P1 = 1.0;
}
//with valence-status comes always also the p+ though. or?? >_>
if ( p->valence() ) {
if ( r1.pt() < r2.pt() || p2->valence() ) {
p1->valencePT(p->valencePT());
p->parents(make_pair(p1,p1));
P1 = 1.0;
}
else {
p2->valencePT(p->valencePT());
p->parents(make_pair(p2,p2));
P1 = 0.0;
}
}
double P2 = 1.0 - P1;
p1->plus( p1->plus() + P1*p->plus() );
p2->plus( p2->plus() + P2*p->plus() );
p1->updateMomentum();
p2->updateMomentum();
if ( d1->size()/(d1->size()+d2->size()) < UseRandom::rnd() )
d1->colour(d2->colour());
state.save();
}
void SmallDipoleAbsorber::setDGLAPsafe ( tDipolePtr dip ) const {
dip->DGLAPsafe( true );
InvEnergy firstLength = dip->size();
InvEnergy secondLength = dip->size();
if ( dip->interacted() ) {
firstLength = dip->interactionLengths().first;
secondLength = dip->interactionLengths().second;
}
if ( dip->neighbors().first && !(dip->neighbors().first->interacted()) &&
dip->neighbors().first->size() > firstLength )
setDGLAPsafe( dip->neighbors().first );
if ( dip->neighbors().second && !(dip->neighbors().second->interacted()) &&
dip->neighbors().second->size() > secondLength )
setDGLAPsafe( dip->neighbors().second );
}
template < typename Sort >
void SmallDipoleAbsorber::setOrdered ( tPartonPtr p, Sort sorted ) const {
p->ordered( true );
if ( p->dipoles().first && sorted( p, p->dipoles().first->partons().first ) )
setOrdered( p->dipoles().first->partons().first, sorted );
if ( p->dipoles().second && sorted(p, p->dipoles().second->partons().second) )
setOrdered( p->dipoles().second->partons().second, sorted );
}
void SmallDipoleAbsorber::DGLAPabsorb(tPartonPtr p, DipoleState & state ) const {
DipolePtr shortDip, longDip, shortNeighbor;
PartonPtr shortP, secondShortP;
InvEnergy firstLength = p->dipoles().first->size();
InvEnergy secondLength = p->dipoles().second->size();
if ( p->dipoles().first->interacted() )
firstLength = p->dipoles().first->interactionLengths().second;
if ( p->dipoles().second->interacted() )
secondLength = p->dipoles().second->interactionLengths().first;
if (firstLength > secondLength ) {
shortDip = p->dipoles().second;
longDip = p->dipoles().first;
shortP = shortDip->partons().second;
shortNeighbor = shortDip->neighbors().second;
secondShortP = shortNeighbor->partons().second;
}
else {
shortDip = p->dipoles().first;
longDip = p->dipoles().second;
shortP = shortDip->partons().first;
shortNeighbor = shortDip->neighbors().first;
secondShortP = shortNeighbor->partons().first;
}
if ( p->valence() && shortP->valence() ) {
setDGLAPsafe(shortDip);
return;
}
if ( shortNeighbor->interacted() ) {
if ( longDip->interacted() ) {
//move the larger of the interacting dips
if ( shortDip->neighbors().first->interactionLengths().second >
shortDip->neighbors().second->interactionLengths().first )
absorbParton( shortDip->partons().first, state );
else
absorbParton( shortDip->partons().second, state );
}
else
absorbParton(p, state);
return; //dont recur
}
if ( shortNeighbor->DGLAPsafe() ) {
if ( longDip->size() > shortNeighbor->size() )
absorbParton( p, state );
else
absorbParton( shortP, state );
return; //dont recur
}
absorbParton(shortP, state);
if ( p->dist2(*secondShortP) < p->dist2(*shortP) ) {
DGLAPabsorb(p, state);
}
}
bool rapSort(PartonPtr part1,PartonPtr part2) {
return (part1->y() >= part2->y());
}
bool minusSort(PartonPtr p1, PartonPtr p2) {
return ( p1->minus() >= p2->minus() );
}
bool plusSort(PartonPtr p1, PartonPtr p2) {
return ( p1->plus() <= p2->plus() );
}
bool SmallDipoleAbsorber::swing( tDipolePtr d1, tDipolePtr d2 ) const {
if ( DipoleAbsorber::swing(d1, d2) ) return true;
DipoleState & state = d1->dipoleState();
state.sortDipoles();
if( !(state.forceSwing(d1->partons().second, 5.0, 0.0)) ) return false;
return DipoleAbsorber::swing(d1->partons().first->dipoles().second,
d2->partons().second->dipoles().first);
}
// void SmallDipoleAbsorber::isolateNonParticipating( DipoleState & state ) const {
// for( int i = 0; i < int(state.initialDipoles().size()); i++ ) {
// DipolePtr d = state.initialDipoles()[i];
// if ( !(d->participating()) ) {
// if ( d->partons().first->dipoles().second != d->partons().second->dipoles().first )
// swing( d->partons().first->dipoles().second, d->partons().second->dipoles().first );
// d->partons().first->dipoles().second->participating( false );
// }
// }
// }
void SmallDipoleAbsorber::hiddenRecoil(DipoleState & state) const {
cout << "entering hiddenrecoil--------------------" << endl;
state.diagnosis(true);
list<PartonPtr> partons = state.getPartons();
list<PartonPtr> toBeAbsorbed;
cout << partons.size() << " number o partons." << endl;
//reset momenta
for ( list<PartonPtr>::iterator it = partons.begin();
it != partons.end(); it++ )
(*it)->pT(0.0*(*it)->pT());
for ( list<PartonPtr>::iterator it = partons.begin();
it != partons.end(); it++ ) {
tPartonPtr p = *it;
if ( p->valence() ) {
p->pT(p->pT() + p->valencePT());
if ( p->pT().pt() == ZERO )
cout << "zero momentum valence parton in hiddenrecoil" << endl;
if ( p->rightMoving() ) {
p->y( log(p->pT().pt()/p->plus()) );
p->minus( p->pT().pt()*exp(p->y()) );
}
else {
p->y( log(p->minus()/p->pT().pt()) );
p->plus( p->pT().pt()*exp(-p->y()) );
}
cout << "added valence momentum" << endl;
state.diagnosis(true);
continue;
}
tPartonPtr p1 = p;
tPartonPtr p2 = p;
//find first real ancestor on each side, and recoil with them
do { p1 = p1->parents().first; } while (p1->absorbed());
do { p2 = p2->parents().second; } while (p2->absorbed());
recoil( p, p1, state.ymax() );
recoil( p, p2, state.ymax() );
cout << "did normal recoil" << endl;
state.diagnosis(true);
if ( p->y() > state.ymax() && !(p->dipoles().first->interacted() &&
p->dipoles().second->interacted()) )
toBeAbsorbed.push_back(p);
}
//if any partons needed to be absorbed, absorb them and restart.
if ( toBeAbsorbed.size() != 0 ) {
bool absorbed = false;
for ( list<PartonPtr>::iterator it = toBeAbsorbed.begin();
it != toBeAbsorbed.end(); it++ ) {
cout << "absorbing parton" << endl;
state.diagnosis(true);
absorbParton(*it, state);
if ( (*it)->dipoles().first->children().second ||
(*it)->dipoles().second->children().second )
absorbed = true;
}
if ( absorbed ) {
cout << "recur" << endl;
hiddenRecoil(state);
}
}
}
void SmallDipoleAbsorber::
recoil(tPartonPtr p1, tPartonPtr p2, double ymax) const {
Parton::Point r = p1->position() - p2->position();
TransverseMomentum recoil = p1->pTScale()*r/sqr(r.pt());
p1->pT( p1->pT() + recoil );
p2->pT( p2->pT() - recoil );
if ( p1->rightMoving() ) {
p1->y( log(p1->pT().pt()/p1->plus()) );
p1->minus( p1->pT().pt()*exp(p1->y()) );
}
else {
p1->y( log(p1->minus()/p1->pT().pt()) );
p1->plus( p1->pT().pt()*exp(-p1->y()) );
}
if ( p2->rightMoving() ) {
p2->y( log(p2->pT().pt()/p2->plus()) );
p2->minus( p2->pT().pt()*exp(p2->y()) );
}
else {
p2->y( log(p2->minus()/p2->pT().pt()) );
p2->plus( p2->pT().pt()*exp(-p2->y()) );
}
//check if one of the partons is between two interacting dipoles,
//and got pushed over ymax. Should happen very rarely.
if ( ( p1->y() > ymax
&& (p1->dipoles().first->interacted() && p1->dipoles().second->interacted()) )
||
( p2->y() > ymax
&& (p2->dipoles().first->interacted() && p2->dipoles().second->interacted()) ) )
cout << "parton got pushed over ymax!!" << endl;
}
template <typename Sort>
void SmallDipoleAbsorber::absorbNonOrderedPartons( DipoleState & state, Sort ordered ) const {
list < PartonPtr > partons = state.getPartons();
list < PartonPtr > marked;
while ( true ) {
for ( list<PartonPtr>::iterator p = partons.begin();
p != partons.end(); p++ ) {
(*p)->ordered(false);
}
//mark the ones in a sorted chain from an interacting parton
for ( list<PartonPtr>::iterator p = partons.begin();
p != partons.end(); p++ ) {
if ( (**p).ordered() ) continue;
if ( ((*p)->dipoles().first && (*p)->dipoles().first->interacted()) ||
((*p)->dipoles().second && (*p)->dipoles().second->interacted()) ) {
setOrdered( (*p), ordered );
}
}
//manually set the marked partons safe.
for ( list<PartonPtr>::const_iterator p = marked.begin(); p != marked.end(); p++ ) {
setOrdered( *p, ordered );
}
//find the highest non-ordered parton absP with an ordered neighbour
PartonPtr absP;
for ( list<PartonPtr>::iterator p = partons.begin();
p != partons.end(); p++ ) {
if ( !((*p)->ordered()) &&
( ((*p)->dipoles().first &&
(*p)->dipoles().first->partons().first->ordered()) ||
((*p)->dipoles().second &&
(*p)->dipoles().second->partons().second->ordered()) ) )
if ( !absP || ordered( *p, absP) ) absP = *p;
}
//check that the unordered partons isnt a valence parton.
if ( absP && absP->valence() ) {
bool firstCanBeAbsorbed = false;
bool secondCanBeAbsorbed = false;
if ( absP->dipoles().first ) {
PartonPtr p1 = absP->dipoles().first->partons().first;
if ( !(p1->valence()) &&
!( (p1->dipoles().first && p1->dipoles().first->interacted()) ||
(p1->dipoles().second && p1->dipoles().second->interacted()) ) &&
p1->ordered() )
firstCanBeAbsorbed = true;
}
if ( absP->dipoles().second ) {
PartonPtr p2 = absP->dipoles().second->partons().second;
if ( !(p2->valence()) &&
!( (p2->dipoles().first && p2->dipoles().first->interacted()) ||
(p2->dipoles().second && p2->dipoles().second->interacted()) ) &&
p2->ordered() )
secondCanBeAbsorbed = true;
}
if ( firstCanBeAbsorbed && !secondCanBeAbsorbed ) {
absP = absP->dipoles().first->partons().first;
}
else if ( !firstCanBeAbsorbed && secondCanBeAbsorbed ) {
absP = absP->dipoles().second->partons().second;
}
else if ( firstCanBeAbsorbed && secondCanBeAbsorbed ) {
if ( ordered ( absP->dipoles().first->partons().first,
absP->dipoles().second->partons().second ) )
absP = absP->dipoles().first->partons().first;
else
absP = absP->dipoles().second->partons().second;
}
else if ( !firstCanBeAbsorbed && !secondCanBeAbsorbed ) {
marked.push_back(absP);
continue;
}
}
if ( absP ) {
absorbParton( absP, state);
partons.remove(absP);
} else { //if there is none, look for unordered loops
PartonPtr highestP;
for ( list<PartonPtr>::iterator p = partons.begin();
p != partons.end(); p++ ) {
if ( !((*p)->ordered()) )
if ( !highestP || ordered((*p), highestP) )
highestP = *p;
}
if ( highestP ) { //mark the highest parton in the loop as safe
marked.push_back(highestP);
}
else {//no unordered partons, we are done
break;
}
}
}
}
bool SmallDipoleAbsorber::checkDGLAPsafe ( InvEnergy r1, InvEnergy r2 ) const {
- return sqr(r1)/Current<DipoleEventHandler>()->alphaS(r1) >
- (sqr(r2)/Current<DipoleEventHandler>()->alphaS(r2))*UseRandom::rnd();
+ return sqr(r1)/Current<DipoleEventHandler>()->alphaSr(r1) >
+ (sqr(r2)/Current<DipoleEventHandler>()->alphaSr(r2))*UseRandom::rnd();
}
void SmallDipoleAbsorber::absorbSmallDipoles( DipoleState & state ) const {
set<DipolePtr> marked; //the manually marked safe dipoles.
//start by adding the interacting dipoles as safe.
list< DipolePtr > dipoles = state.getDipoles();
InvEnergy minScale = 0.0/GeV;
for ( list<DipolePtr>::const_iterator it = dipoles.begin();
it != dipoles.end(); it++ ) { DipolePtr dip = *it;
if ( dip->interacted() ) {
InvEnergy thisScale =
min( sqrt(dip->partons().first->dist2(*(dip->interacted()->partons().second))),
sqrt(dip->partons().second->dist2(*(dip->interacted()->partons().first))));
if ( minScale == 0.0/GeV || thisScale < minScale )
minScale = thisScale;
marked.insert(dip);
}
}
//find all loops, and decide if they should be absorbed or not.
// first mark all partons as nonordered, so it can be used for safe loops.
list<PartonPtr> partons = state.getPartons();
for ( list<PartonPtr>::const_iterator p = partons.begin(); p != partons.end(); p++ ) {
(*p)->ordered(false);
}
set< list<PartonPtr> > loops = state.loops();
for ( set< list<PartonPtr> >::iterator it = loops.begin();
it != loops.end(); it++ ) { list<PartonPtr> loop = *it;
bool keep = false;
DipolePtr maxDip;
for( list<PartonPtr>::const_iterator jt = loop.begin();
jt != loop.end(); jt++ ) { PartonPtr p = *jt;
if ( !(p->dipoles().first) ) continue;
if ( p->dipoles().first->interacted() ) keep = true;
if ( p->ordered() ) keep = true;
if ( !maxDip || p->dipoles().first->size() > maxDip->size() )
maxDip = p->dipoles().first;
}
if ( !keep && checkDGLAPsafe( maxDip->size(), minScale ) ) {
keep = true;
maxDip->partons().first->ordered(true);
}
if ( !keep ) { //otherwise absorb loop, update and restart loop iteration
absorbLoop( (*(loop.begin()))->dipoles().first, state );
loops = state.loops();
it = loops.begin();
}
}
//now mark the largest dips in non-interacting loop
for ( set< list<PartonPtr> >::iterator it = loops.begin();
it != loops.end(); it++ ) { list<PartonPtr> loop = *it;
bool interacting = false;
DipolePtr maxDip;
for( list<PartonPtr>::const_iterator jt = loop.begin();
jt != loop.end(); jt++ ) { PartonPtr p = *jt;
if ( !(p->dipoles().first) ) continue;
if ( !maxDip || p->dipoles().first->size() > maxDip->size() )
maxDip = p->dipoles().first;
if ( p->dipoles().first->interacted() )
interacting = true;
}
if ( !interacting )
marked.insert(maxDip);
}
//now look through all non-safe dipoles, and mark them as safe, or absorb them.
while( true ) {
//first update the lists and safe flags
for( list<DipolePtr>::iterator it = dipoles.begin();
it != dipoles.end(); it++ ) { DipolePtr dip = *it;
if ( dip->children().first || dip->children().second ) {
it = dipoles.erase(it);
it--;
continue;
}
else if ( dip->partons().first->valence() && dip->partons().second->valence() ) {
marked.insert(dip);
}
dip->DGLAPsafe(false);
}
for( set<DipolePtr>::iterator it = marked.begin();
it != marked.end(); it++ ) { DipolePtr dip = *it;
setDGLAPsafe(dip);
}
//then find a safe - nonsafe neighbouring pair.
DipolePtr safeDip;
DipolePtr nonSafeDip;
bool found = false;
InvEnergy smallest = 0.0/GeV;
for( list<DipolePtr>::iterator it = dipoles.begin();
it != dipoles.end(); it++ ) { DipolePtr dip = *it;
if ( !(dip->DGLAPsafe()) ) {
if ( dip->neighbors().first->DGLAPsafe() &&
(!found || dip->size() < smallest) ) {
nonSafeDip = dip;
safeDip = dip->neighbors().first;
found = true;
smallest = dip->size();
}
if ( dip->neighbors().second->DGLAPsafe() &&
(!found || dip->size() < smallest ||
(dip == nonSafeDip &&
dip->neighbors().second->size() < safeDip->size()) ) ) {
nonSafeDip = dip;
safeDip = dip->neighbors().second;
found = true;
smallest = dip->size();
}
}
}
//if a pair is found, decide if the nonsafe one should be absorbed or marked
if ( found ) {
InvEnergy safeScale = safeDip->size();
if ( safeDip->interacted() ) { //use the interacted dipsize for interacting dips
if ( nonSafeDip == safeDip->neighbors().first )
safeScale = safeDip->interactionLengths().first;
else
safeScale = safeDip->interactionLengths().second;
}
if ( checkDGLAPsafe( nonSafeDip->size(), safeScale ) ) {
marked.insert(nonSafeDip);
}
else {
if ( safeDip == nonSafeDip->neighbors().first )
DGLAPabsorb(safeDip->partons().second, state);
else if ( safeDip == nonSafeDip->neighbors().second )
DGLAPabsorb(safeDip->partons().first, state);
else cout << "safedip and nonsafe dip not neighbors! :(" << endl;
}
}
//if no nonsafe dips left, we're done.
else
break;
}
}
void SmallDipoleAbsorber::reabsorb( DipoleState & state) const {
realValence( state );
state.save();
absorbVirtualPartons( state );
// isolateNonParticipating( state );
absorbSmallDipoles( state );
absorbNonOrderedPartons( state, minusSort );
absorbNonOrderedPartons( state, plusSort );
hiddenRecoil( state );
}
void SmallDipoleAbsorber::realValence( DipoleState & state ) const {
vector<DipolePtr> dips = state.initialDipoles();
for ( int i = 0; i < int(dips.size());i++) {
dips[i]->partons().first->interact();
dips[i]->partons().second->interact();
}
}
DipolePtr SmallDipoleAbsorber::largestNonsafeDipole(list<DipolePtr> dipoles,
DipoleState & state ) const {
DipolePtr largestDip;
InvEnergy DGLAPScale = 0.0/GeV;
InvEnergy size = 0.0/GeV;
//find largest dipole that is not safe, and the smallest safe dipole.
// ***************** ATTENTION PHYSICS HERE!! WHAT SCALE TO PICK!?!?! ***********
for ( list<DipolePtr>::const_iterator dPtr = dipoles.begin();
dPtr != dipoles.end(); dPtr++ ) {
if ( !((*dPtr)->children().first || (*dPtr)->children().second )) {
if ( (*dPtr)->DGLAPsafe() ) {
if (DGLAPScale == 0.0/GeV || (*dPtr)->size() < DGLAPScale )
DGLAPScale = (*dPtr)->size();
}
else if( (*dPtr)->size() > size ) {
largestDip = *dPtr;
size = (*dPtr)->size();
}
}
}
//compare them, and mark as safe or absorb the entire loop.
//do not automatically save valence chains, as this creates many high pT events
if ( largestDip ) {
- if ( (sqr(largestDip->size())/Current<DipoleEventHandler>()->alphaS(largestDip->size())) >
- (sqr(DGLAPScale)/Current<DipoleEventHandler>()->alphaS(DGLAPScale))*
+ if ( (sqr(largestDip->size())/Current<DipoleEventHandler>()->alphaSr(largestDip->size())) >
+ (sqr(DGLAPScale)/Current<DipoleEventHandler>()->alphaSr(DGLAPScale))*
UseRandom::rnd() ) {
return largestDip;
}
else {
absorbLoop( largestDip, state );
return largestNonsafeDipole(dipoles, state);
}
}
else {
return largestDip;
}
}
void SmallDipoleAbsorber::absorbLoop( DipolePtr d, DipoleState & state ) const {
//make a list of the partons and dipoles in the loop.
list<PartonPtr> partons;
list<DipolePtr> dipoles;
tPartonPtr p = d->partons().second;
partons.push_back(p);
dipoles.push_back(d);
bool forward = true;
while ( p != d->partons().first && (forward || p->dipoles().first) ) {
if ( !(p->dipoles().second) ) {
cout << "found a quark in SmallDipoleAbsorber::absorbLoop!!!!!!!" << endl;
state.diagnosis(true);
p = d->partons().first;
partons.push_back(p);
forward = false;
continue;
}
if ( forward ) {
p = p->dipoles().second->partons().second;
dipoles.push_back(p->dipoles().first);
}
else {
p = p->dipoles().first->partons().first;
dipoles.push_back(p->dipoles().second);
}
partons.push_back(p);
}
//find and perform a probable swing. Don't bother with colours...
list<DipolePtr> otherDips = d->dipoleState().getDipoles();
for ( list<DipolePtr>::iterator i = dipoles.begin(); i != dipoles.end(); i++ ) {
for ( list<DipolePtr>::iterator j = otherDips.begin(); j != otherDips.end(); j++ ) {
if ( *i == *j )
j = otherDips.erase(j)--;
}
}
if ( dipoles.size() == 0 )
cout << "wtf, no dipoles in loop!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1" << endl;
if ( otherDips.size() == 0 ) {
cout << "wtf, no other dipoles in loop!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1" << endl;
state.diagnosis(true);
}
DipolePtr d1, d2;
double maxy = 0.0;
for ( list<DipolePtr>::iterator i = dipoles.begin(); i != dipoles.end(); i++ ) {
for ( list<DipolePtr>::iterator j = otherDips.begin(); j != otherDips.end(); j++ ) {
double R = log( UseRandom::rnd() );
InvEnergy2 a = (*i)->partons().first->dist2(*(*i)->partons().second);
InvEnergy2 b = (*j)->partons().first->dist2(*(*j)->partons().second);
InvEnergy2 c = (*i)->partons().second->dist2(*(*j)->partons().first);
InvEnergy2 d = (*i)->partons().first->dist2(*(*j)->partons().second);
a = sqr(Current<DipoleEventHandler>()->rMax())/
- (Current<DipoleEventHandler>()->alphaS(sqrt(a)))*
+ (Current<DipoleEventHandler>()->alphaSr(sqrt(a)))*
sqr(exp(sqrt(a)/Current<DipoleEventHandler>()->rMax()) - 1.0);
b = sqr(Current<DipoleEventHandler>()->rMax())/
- (Current<DipoleEventHandler>()->alphaS(sqrt(b)))*
+ (Current<DipoleEventHandler>()->alphaSr(sqrt(b)))*
sqr(exp(sqrt(b)/Current<DipoleEventHandler>()->rMax()) - 1.0);
c = sqr(Current<DipoleEventHandler>()->rMax())/
- (Current<DipoleEventHandler>()->alphaS(sqrt(c)))*
+ (Current<DipoleEventHandler>()->alphaSr(sqrt(c)))*
sqr(exp(sqrt(c)/Current<DipoleEventHandler>()->rMax()) - 1.0);
d = sqr(Current<DipoleEventHandler>()->rMax())/
- (Current<DipoleEventHandler>()->alphaS(sqrt(d)))*
+ (Current<DipoleEventHandler>()->alphaSr(sqrt(d)))*
sqr(exp(sqrt(d)/Current<DipoleEventHandler>()->rMax()) - 1.0);
double A = c*d/(a*b);
double y = R*A;
if ( y < maxy || maxy == 0.0 ) {
maxy = y;
d1 = *i;
d2 = *j;
}
}
}
swing(d1, d2);
//then sort the partons in rapidity, and absorb them.
//leave all valence partons, or if none, the lowest rapidity parton.
partons.sort(rapSort);
bool valence;
for ( list<PartonPtr>::const_iterator it = partons.begin() ;
(!valence && it != partons.end()--) || (valence && it == partons.end()); it++ ) {
if ( (*it)->valence() )
valence = true;
else
absorbParton((*it), state);
}
}
// If needed, insert default implementations of virtual function defined
// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs).
void SmallDipoleAbsorber::persistentOutput(PersistentOStream & os) const {
// *** ATTENTION *** os << ; // Add all member variable which should be written persistently here.
}
void SmallDipoleAbsorber::persistentInput(PersistentIStream & is, int) {
// *** ATTENTION *** is >> ; // Add all member variable which should be read persistently here.
}
// Static variable needed for the type description system in ThePEG.
#include "ThePEG/Utilities/DescribeClass.h"
DescribeClass<SmallDipoleAbsorber,DIPSY::DipoleAbsorber>
describeDIPSYSmallDipoleAbsorber("DIPSY::SmallDipoleAbsorber", "libAriadne5.so libDIPSY.so");
void SmallDipoleAbsorber::Init() {
static ClassDocumentation<SmallDipoleAbsorber> documentation
("The SmallDipoleAbsorber class implements a model describing how "
"non-interacted dipoles will be reabsorbed. The model is based on "
"the removal of small dipoles.");
}
diff --git a/DIPSY/Swinger.cc b/DIPSY/Swinger.cc
--- a/DIPSY/Swinger.cc
+++ b/DIPSY/Swinger.cc
@@ -1,424 +1,424 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the Swinger class.
//
#include "Swinger.h"
#include "Dipole.h"
#include "DipoleState.h"
#include "DipoleEventHandler.h"
#include "ThePEG/Utilities/Current.h"
#include "ThePEG/Utilities/Throw.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Interface/Parameter.h"
#include "CPUTimer.h"
#ifdef ThePEG_TEMPLATES_IN_CC_FILE
// #include "Swinger.tcc"
#endif
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace DIPSY;
Swinger::~Swinger() {}
void Swinger::testGenerate(set<DipolePtr> & dips,double miny, double maxy) {
cout << "Testing Swinger....." << endl;
set<DipolePtr>::iterator it;
DipoleState testState = DipoleState();
for(it = dips.begin();it!=dips.end();it++) {
testState.addDipole(*(*it));
(*it)->dipoleState(& testState);
}
testState.sortDipoles();
thestMode = true;
ofstream youtput("SwingerTest.dat");
int ysteps = 100;
double ystepsize = 0.1;
vector<int> ybin(ysteps,0);
double y;
it=dips.begin();
for(int i=0;i<1000000;i++) {
(*it)->generatedY(maxy);
generate(*(*it),miny, maxy,true);
if((*it)->swingDipole()) {
y = (*it)->generatedY();
if(y-miny<ysteps*ystepsize)
ybin[int((y-miny)/ystepsize)]++;
}
(*it)->reset();
}
for(int i=0;i<ysteps;i++) {
youtput << (i+0.5)*ystepsize << '\t' << ybin[i] << endl;
}
youtput.close();
thestMode = false;
cout << "Done testing Swinger."
<< endl;
}
bool Swinger::forceGenerate(Dipole & dipole, double ymax) const {
const vector<tDipolePtr> & candidates =
dipole.dipoleState().swingCandidates(dipole.colour());
for (vector<tDipolePtr>::size_type i = 0; i < candidates.size(); i++ ) {
if ( candidates[i] == & dipole ) continue;
if ( candidates[i]->neighbors().first == & dipole ||
candidates[i]->neighbors().second == & dipole ) continue;
InvEnergy2 a = dipole.partons().first->dist2(*dipole.partons().second);
InvEnergy2 b = candidates[i]->partons().first->dist2(*(candidates[i]->partons().second));
InvEnergy2 c = dipole.partons().second->dist2(*candidates[i]->partons().first);
InvEnergy2 d = dipole.partons().first->dist2(*candidates[i]->partons().second);
a = sqr(Current<DipoleEventHandler>()->rMax())*
sqr(exp(sqrt(a)/Current<DipoleEventHandler>()->rMax()) - 1.0);
b = sqr(Current<DipoleEventHandler>()->rMax())*
sqr(exp(sqrt(b)/Current<DipoleEventHandler>()->rMax()) - 1.0);
c = sqr(Current<DipoleEventHandler>()->rMax())*
sqr(exp(sqrt(c)/Current<DipoleEventHandler>()->rMax()) - 1.0);
d = sqr(Current<DipoleEventHandler>()->rMax())*
sqr(exp(sqrt(d)/Current<DipoleEventHandler>()->rMax()) - 1.0);
double yi = -log( UseRandom::rnd() )*c*d/(a*b);
if ( yi < dipole.generatedY() || !(dipole.swingDipole()) ) {
if( yi < ymax || ymax == 0.0 ) { //Don't do ridiculously improbable swings.
dipole.swingDipole(candidates[i]);
dipole.generatedY(yi);
}
}
}
if( (dipole.swingDipole()) ) return true;
else return false;
}
void Swinger::generateFS(Dipole & dipole, double miny, double maxy) const {
//old implementation
bool force = !dipole.hasGen();
const vector<tDipolePtr> & candidates =
dipole.dipoleState().swingCandidates(dipole.colour());
vector<tDipolePtr>::size_type i = 0;
while ( i < candidates.size() && candidates[i++] != & dipole );
if ( i == candidates.size() && candidates[i - 1] != & dipole )
Throw<SwingConsistencyException>()
<< "FSswinger not found among candidates" << Exception::abortnow;
for (; i < candidates.size(); ++i ) {
if(candidates[i]->children().first)
cout << "OH NOES, parents among the swing candidates!!!! O_o" << endl;
if ( dipole.neighbors().first == candidates[i] ||
dipole.neighbors().second == candidates[i] )
continue;
if ( !force && candidates[i]->hasGen() ) continue;
// Generate a y
double R = -log( UseRandom::rnd() );
double amp = swingAmpFS(dipole.partons(),
candidates[i]->partons(), miny/GeV2);
// double amp = swingAmpFS(dipole, *candidates[i], miny/GeV2);
double yi = Constants::MaxRapidity;
if ( miny*amp + R < Constants::MaxRapidity*amp ) yi = miny + R/amp;
if ( yi < dipole.generatedY() || !dipole.hasGen() ) {
dipole.swingDipole(candidates[i]);
dipole.generatedY(yi);
dipole.recoilSwing(false);
}
}
}
InvEnergy2 Swinger::
swingDistanceFS(const Parton & p1, const Parton & p2, InvEnergy2 time) const {
// static CPUClock cpuclock("DIPSY::Swinger::swingDinstanceFS");
// CPUTimer timer(cpuclock);
static DebugItem notime("DIPSY::NoSwingTime", 60);
if ( notime ) time = ZERO;
Energy2 E2 = p1.plus()*p2.minus() + p1.minus()*p2.plus();
Parton::Point x1 = p1.position() - p2.position() + time*p1.pT();
Parton::Point x2 = p1.position() - p2.position() - time*p2.pT();
InvEnergy2 xxScalar = x1.x()*x2.x() + x1.y()*x2.y();
Energy2 ppScalar = p1.pT().x()*p2.pT().x() + p1.pT().y()*p2.pT().y();
InvEnergy2 a = sqr(time)*E2 + xxScalar - sqr(time)*ppScalar;
if ( a <= ZERO ) return ZERO;
- double asa = Current<DipoleEventHandler>()->alphaS(sqrt(a));
+ double asa = Current<DipoleEventHandler>()->alphaSr(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));
+ double asa = Current<DipoleEventHandler>()->alphaSr(sqrt(a));
+ double asb = Current<DipoleEventHandler>()->alphaSr(sqrt(b));
+ double asc = Current<DipoleEventHandler>()->alphaSr(sqrt(c));
+ double asd = Current<DipoleEventHandler>()->alphaSr(sqrt(d));
a = sqr(rmax)/asa*sqr(exp(sqrt(a)/rmax) - 1.0);
b = sqr(rmax)/asb*sqr(exp(sqrt(b)/rmax) - 1.0);
c = sqr(rmax)/asc*sqr(exp(sqrt(c)/rmax) - 1.0);
d = sqr(rmax)/asd*sqr(exp(sqrt(d)/rmax) - 1.0);
//normal amplitude
if ( sqrt(a*b) < sqrt(c)*sqrt(d)*sqrt(theLambda*eps) ) return eps;
return a*b/(c*d)*theLambda;
}
void Swinger::generate(Dipole & dipole, double miny, double maxy, bool force) const {
double yi = max(max(dipole.partons().first->y(),
dipole.partons().second->y()), miny);
if ( dipole.partons().second == dipole.partons().first )
Throw<ColourIndexException>()
<< "Found inconsistent colour indices in DIPSY. Event discarded."
<< Exception::eventerror;
if( dipole.children().first)
Throw<SwingConsistencyException>()
<< "OH NOES, parents among the swing candidates!!!! O_o"
<< Exception::abortnow;
const vector<tDipolePtr> & candidates =
dipole.dipoleState().swingCandidates(dipole.colour(), !force);
vector<tDipolePtr>::const_iterator it = candidates.begin();
if ( force ) while ( it != candidates.end() && *it++ != &dipole );
for (; it != candidates.end(); ++it ) {
if ( !force && (**it).hasGen() ) continue;
double yn = yi - log(UseRandom::rnd())/swingAmp(dipole, **it);
if ( yn < dipole.generatedY() ) {
dipole.swingDipole(*it);
dipole.generatedY(yn);
dipole.recoilSwing(false);
}
}
}
double Swinger::swingAmp(const Dipole & firstDip,
const Dipole & secondDip) const {
InvEnergy rmax = Current<DipoleEventHandler>()->rMax();
InvEnergy2 a = firstDip.swingCache;
if ( a < ZERO ) {
a = firstDip.partons().first->dist2(*firstDip.partons().second);
- a = sqr(rmax)/(Current<DipoleEventHandler>()->alphaS(sqrt(a)))*
+ a = sqr(rmax)/(Current<DipoleEventHandler>()->alphaSr(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)))*
+ b = sqr(rmax)/(Current<DipoleEventHandler>()->alphaSr(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)))*
+ c = sqr(rmax)/(Current<DipoleEventHandler>()->alphaSr(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)))*
+ d = sqr(rmax)/(Current<DipoleEventHandler>()->alphaSr(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)))*
+ (Current<DipoleEventHandler>()->alphaSr(sqrt(a)))*
sqr(exp(sqrt(a)/rmax) - 1.0);
b = sqr(rmax)/
- (Current<DipoleEventHandler>()->alphaS(sqrt(b)))*
+ (Current<DipoleEventHandler>()->alphaSr(sqrt(b)))*
sqr(exp(sqrt(b)/rmax) - 1.0);
c = sqr(rmax)/
- (Current<DipoleEventHandler>()->alphaS(sqrt(c)))*
+ (Current<DipoleEventHandler>()->alphaSr(sqrt(c)))*
sqr(exp(sqrt(c)/rmax) - 1.0);
d = sqr(rmax)/
- (Current<DipoleEventHandler>()->alphaS(sqrt(d)))*
+ (Current<DipoleEventHandler>()->alphaSr(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->interacted(d1.interacted());
if ( d2.interacted() ) d22->interacted(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", "libAriadne5.so libDIPSY.so");
void Swinger::Init() {
static ClassDocumentation<Swinger> documentation
("There is no documentation for the Swinger class");
static Parameter<Swinger,double> interfaceLambda
("Lambda",
"The frequency of the swings.",
&Swinger::theLambda, 1.0, 1.0, 0.0, 0.0,
true, false, Interface::lowerlim);
}
diff --git a/include/Makefile.am b/include/Makefile.am
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -1,42 +1,43 @@
BUILT_SOURCES = done-all-links
AUTOMAKE_OPTIONS = -Wno-portability
DIRLINKS = $(top_srcdir)/DipoleCascade $(top_srcdir)/Cascade $(top_srcdir)/DIPSY
CONFIGHEADERS = $(top_srcdir)/Config/Ariadne.h \
$(top_srcdir)/Config/Ariadne5.h \
$(top_srcdir)/Config/CloneBase.fh \
$(top_srcdir)/Config/CloneBase.h \
$(top_srcdir)/Config/CloneBase.icc \
- $(top_srcdir)/Config/UnitFO.h
+ $(top_srcdir)/Config/UnitFO.h \
+ $(top_srcdir)/Config/ColourInfo.h
CLEANFILES = done-all-links
done-all-links: $(CONFIGHEADERS) $(DIRLINKS)
@EMPTY@ifdef SHOWCOMMAND
mkdir -p Ariadne/Config
$(LN_S) -f $(addprefix ../, $(DIRLINKS)) Ariadne
$(LN_S) -f $(addprefix ../../, $(CONFIGHEADERS)) Ariadne/Config
$(LN_S) -f ../../../Config/config.h Ariadne/Config
touch done-all-links
@EMPTY@else
@echo "sym-linking header files..."
@mkdir -p Ariadne/Config
@$(LN_S) -f $(addprefix ../, $(DIRLINKS)) Ariadne
@$(LN_S) -f $(addprefix ../../, $(CONFIGHEADERS)) Ariadne/Config
@$(LN_S) -f ../../../Config/config.h Ariadne/Config
@touch done-all-links
@EMPTY@endif
install-data-local:
find Ariadne -maxdepth 2 -follow \( -name '*.h' -or -name '*.icc' \
-or -name '*.tcc' -or -name '*.fh' -or -name '*.xh' \) \
-exec $(install_sh_DATA) \{\} $(DESTDIR)$(includedir)/\{\} \;
uninstall-local:
rm -rf $(DESTDIR)$(includedir)/Ariadne
if test -x $(DESTDIR)$(bindir)/setupThePEG; then $(DESTDIR)$(bindir)/setupThePEG -init -r $(DESTDIR)$(pkglibdir)/ThePEGDefaults.rpo -o $(DESTDIR)$(pkglibdir)/ThePEGDefaults.rpo $(top_srcdir)/src/AriadneRemove.in; fi
clean-local:
rm -rf Ariadne

File Metadata

Mime Type
text/x-diff
Expires
Tue, Nov 19, 3:50 PM (1 d, 21 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3805033
Default Alt Text
(638 KB)

Event Timeline