Page MenuHomeHEPForge

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/Decay/Baryon/OmegaXiStarPionDecayer.cc b/Decay/Baryon/OmegaXiStarPionDecayer.cc
--- a/Decay/Baryon/OmegaXiStarPionDecayer.cc
+++ b/Decay/Baryon/OmegaXiStarPionDecayer.cc
@@ -1,170 +1,170 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the OmegaXiStarPionDecayer class.
//
#include "OmegaXiStarPionDecayer.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/PDT/DecayMode.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace Herwig;
OmegaXiStarPionDecayer::OmegaXiStarPionDecayer() {
// the ids of the particles
idin_ = 3334;
idout_ = 3324;
// the couplings from the paper
- Acomm_ = 20.91e-8;
- AP_ =- 9.20e-8;
- AS_ =- 6.32e-8;
- BP_ = 230.1e-8;
- BS_ =-100.8e-8;
+ Acomm_ = 20.91e-8;
+ AP_ = -9.20e-8;
+ AS_ = -6.32e-8;
+ BP_ = 230.1e-8;
+ BS_ = -100.8e-8;
// maximum weight for the decay
wgtmax_=0.0032;
// intermediates
generateIntermediates(false);
}
void OmegaXiStarPionDecayer::doinit() {
Baryon1MesonDecayerBase::doinit();
// set up the phase space
tPDVector extpart(3);
DecayPhaseSpaceModePtr mode;
vector<double> wgt(0);
extpart[0]=getParticleData(idin_);
extpart[1]=getParticleData(idout_);
extpart[2]=getParticleData(-211);
mode=new_ptr(DecayPhaseSpaceMode(extpart,this));
addMode(mode,wgtmax_,wgt);
}
void OmegaXiStarPionDecayer::doinitrun() {
Baryon1MesonDecayerBase::doinitrun();
if(initialize()) wgtmax_=mode(0)->maxWeight();
}
int OmegaXiStarPionDecayer::modeNumber(bool & cc,tcPDPtr parent,
const tPDVector & children) const {
int imode(-1);
// must be two outgoing particles
if(children.size()!=2){return imode;}
// ids of the particles
int id0(parent->id());
int id1(children[0]->id());
int id2(children[1]->id());
if(id0==idin_) {
if((id1==idout_&&id2==-211)||
(id2==idout_&&id1==-211)) imode=0;
}
else if(id0==-idin_) {
if((id1==-idout_&&id2==211)||
(id2==-idout_&&id1==211)) imode=0;
}
// charge conjugation
cc=id0<0;
// return the answer
return imode;
}
void OmegaXiStarPionDecayer::persistentOutput(PersistentOStream & os) const {
os << Acomm_ << AP_ << AS_ << BP_ << BS_ << idin_ << idout_ << wgtmax_;
}
void OmegaXiStarPionDecayer::persistentInput(PersistentIStream & is, int) {
is >> Acomm_ >> AP_ >> AS_ >> BP_ >> BS_ >> idin_ >> idout_ >> wgtmax_;
}
ClassDescription<OmegaXiStarPionDecayer>
OmegaXiStarPionDecayer::initOmegaXiStarPionDecayer;
// Definition of the static class description member.
void OmegaXiStarPionDecayer::Init() {
static ClassDocumentation<OmegaXiStarPionDecayer> documentation
("The OmegaXiStarPionDecayer class performs the weak decay"
" of the Omega to Xi*0 and pi-",
"The decay of the $\\Omega^-$ to $\\Xi^{*0}\\pi^-$ was simulated"
" using the model of \\cite{Duplancic:2004dy}.",
"\\bibitem{Duplancic:2004dy}\n"
"G.~Duplancic, H.~Pasagic and J.~Trampetic,\n"
"Phys.\\ Rev.\\ D {\\bf 70} (2004) 077506 [arXiv:hep-ph/0405162].\n"
"%%CITATION = PHRVA,D70,077506;%%\n");
static Parameter<OmegaXiStarPionDecayer,double> interfaceAcomm
("Acomm",
"The Acomm coupling for the decay",
&OmegaXiStarPionDecayer::Acomm_, 20.91e-8, -1.e-5, 1.e-5,
false, false, true);
static Parameter<OmegaXiStarPionDecayer,double> interfaceAP
("AP",
"The A_P coupling for the decay",
&OmegaXiStarPionDecayer::AP_, -9.20e-8, -1.e-5, 1.e-5,
false, false, true);
static Parameter<OmegaXiStarPionDecayer,double> interfaceAS
("AS",
"The A_S coupling for the decay",
&OmegaXiStarPionDecayer::AS_, -6.32e-8, -1.e-5, 1.e-5,
false, false, true);
static Parameter<OmegaXiStarPionDecayer,double> interfaceBP
("BP",
"The B_P coupling for the decay",
&OmegaXiStarPionDecayer::BP_, 230.1e-8, -1.e-5, 1.e-5,
false, false, true);
static Parameter<OmegaXiStarPionDecayer,double> interfaceBS
("BS",
"The B_S coupling for the decay",
&OmegaXiStarPionDecayer::BS_, -100.8e-8, -1.e-5, 1.e-5,
false, false, true);
static Parameter<OmegaXiStarPionDecayer,double> interfaceMaximumWeight
("MaximumWeight",
"The maximum weight for the decay",
&OmegaXiStarPionDecayer::wgtmax_, 0.0032, 0., 100.,
false, false, false);
static Parameter<OmegaXiStarPionDecayer,int> interfaceIncoming
("Incoming",
"The PDF code for the incoming baryon",
&OmegaXiStarPionDecayer::idin_, 3334, 0, 1000000,
false, false, true);
static Parameter<OmegaXiStarPionDecayer,int> interfaceOutgoing
("Outgoing",
"The PDF code for the outgoing baryon",
&OmegaXiStarPionDecayer::idout_, 3324, 0, 1000000,
false, false, true);
}
// couplings for spin-3/2 to spin-3/2 spin-0
void OmegaXiStarPionDecayer::
threeHalfThreeHalfScalarCoupling(int,Energy,Energy,Energy,
Complex&A1,Complex&A2,Complex&B1,Complex&B2) const {
useMe();
A2=0.;
B2=0.;
A1=Acomm_+AP_+AS_;
B1=BP_+BS_;
}
void OmegaXiStarPionDecayer::dataBaseOutput(ofstream & output,bool header) const {
if(header) output << "update decayers set parameters=\"";
Baryon1MesonDecayerBase::dataBaseOutput(output,false);
output << "newdef " << name() << ":Acomm " << Acomm_ << "\n";
output << "newdef " << name() << ":AP " << AP_ << "\n";
output << "newdef " << name() << ":AS " << AS_ << "\n";
output << "newdef " << name() << ":BP " << BP_ << "\n";
output << "newdef " << name() << ":BS " << BS_ << "\n";
output << "newdef " << name() << ":MaximumWeight " << wgtmax_ << "\n";
output << "newdef " << name() << ":Incoming " << idin_ << "\n";
output << "newdef " << name() << ":Outgoing " << idout_ << "\n";
if(header) output << "\n\" where BINARY ThePEGName=\""
<< fullName() << "\";" << endl;
}
diff --git a/Decay/FormFactors/BtoSGammaKagan.h b/Decay/FormFactors/BtoSGammaKagan.h
--- a/Decay/FormFactors/BtoSGammaKagan.h
+++ b/Decay/FormFactors/BtoSGammaKagan.h
@@ -1,572 +1,572 @@
// -*- C++ -*-
//
// BtoSGammaKagan.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_BtoSGammaKagan_H
#define HERWIG_BtoSGammaKagan_H
//
// This is the declaration of the BtoSGammaKagan class.
//
#include "Herwig++/Utilities/Interpolator.h"
#include "BtoSGammaHadronicMass.h"
#include "ThePEG/Config/Complex.h"
#include "ThePEG/Config/Constants.h"
namespace Herwig {
using namespace ThePEG;
using namespace ThePEG::Constants;
/** \ingroup Decay
*
* The BtoSGammaKagan class implements the model of hep-ph/9805303 for the
* hadronic mass spectrum in \f$b\to s \gamma\f$ decays.
*/
class BtoSGammaKagan: public BtoSGammaHadronicMass {
/**
* Class for the integration is a friend to access private members
*/
- friend class KaganIntegrand;
+ friend struct KaganIntegrand;
public:
/**
* The default constructor.
*/
BtoSGammaKagan();
/**
* Returns the hadronic mass.
* @param mb The mass of the decaying B meson
* @param mquark The minimum mass of the hadronic system based on the consistuent quark
* masses.
* @return The hadronic mass
*/
virtual Energy hadronicMass(Energy mb,Energy mquark);
/**
* Output the setup information for the particle database
* @param os The stream to output the information to
* @param header Whether or not to output the information for MySQL
* @param create Whether or not to add a statement creating the object
*/
virtual void dataBaseOutput(ofstream & os,bool header,bool create) const;
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
public:
/**
* Members which return integrands
*/
//@{
/**
* Operator to return the integrand for the \f$s_{22}(y)\f$ function
* or \f$s_{27}(y)\f$ functions of hep-ph/9805303
* depending on the value of _iopt to be integrated
*/
double operator ()(double x) const {
if(_iopt==0) {
double reg(realG(x/_zratio)),img(imagG(x/_zratio));
return 16./27.*(1.-x)*(_zratio*_zratio/x/x*(sqr(reg)+sqr(img))+_zratio/x*reg+0.25);
}
else {
return -8./9.*_zratio*(realG(x/_zratio)+0.5*x/_zratio);
}
}
typedef double ValType;
typedef double ArgType;
/**
* Operator to return the integrand of the smeared function or
* Fermi function depending on the value of _iopt to be integrated
*/
InvEnergy smeared(Energy kp) const {
InvEnergy fermi = exponentialFermiFunction(kp,_fermilambda,_fermia,
_ferminorm,_fermilambda1);
if(_iopt==1) fermi *=KNLO(_MB*_y/(_mb+kp))*_MB/(_mb+kp);
return fermi;
}
//@}
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
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.
*/
virtual IBPtr fullclone() const {return new_ptr(*this);}
//@}
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();
/**
* Initialize this object. Called in the run phase just before
* a run begins.
*/
virtual void doinitrun();
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<BtoSGammaKagan> initBtoSGammaKagan;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
BtoSGammaKagan & operator=(const BtoSGammaKagan &);
private:
/** @name Functions to calculate the mass spectrum */
//@{
/**
* The derivative of the Sudakov form-factor from hep-ph/9805303
* @param y Ratio \f$E_\gamma/E^{\rm max}_\gamma\f$.
* @param alphaS The strong coupling, \f$\alpha_S\f$.
*/
double Delta(double y, double alphaS) const {
if(y>_ycut) return 0.;
double ln(log(1.-y));
return -4./3./pi/(1.-y)*alphaS*(ln+1.75)*exp(-2.*alphaS/3./pi*ln*(ln+3.5));
}
/**
* Kinematic function from semi-leptonic decay for normaalisation
*/
double semiLeptonicf() const {
double z2=sqr(_zratio);
return 1.-8.*_zratio*(1.-z2)-sqr(z2)-12.*z2*log(_zratio);
}
/**
* \f$s_{22}(y)\f$ function from hep-ph/9805303. Due to the integration
* required this function is computed by interpolation.
* @param y Ratio \f$E_\gamma/E^{\rm max}_\gamma\f$.
*/
double s22(double y) const {return (*_s22inter)(y);}
/**
* \f$s_{27}(y)\f$ function from hep-ph/9805303. Due to the integration
* required this function is computed by interpolation.
* @param y Ratio \f$E_\gamma/E^{\rm max}_\gamma\f$.
*/
double s27(double y) const {return (*_s27inter)(y);}
/**
* \f$s_{77}(y)\f$ function from hep-ph/9805303
* @param y Ratio \f$E_\gamma/E^{\rm max}_\gamma\f$.
*/
double s77(double y) const {
if(y>_ycut) y=_ycut;
return 1./3.*(7.+y*(1.-2.*y)-2.*(1.+y)*log(1.-y));
}
/**
* \f$s_{78}(y)\f$ function from hep-ph/9805303
* @param y Ratio \f$E_\gamma/E^{\rm max}_\gamma\f$.
*/
double s78(double y) const {
if(y>_ycut) y=_ycut;
return 8./9.*((1.-y)/y*log(1.-y)+1.+0.25*y*y);
}
/**
* \f$s_{88}(y)\f$ function from hep-ph/9805303
* @param y Ratio \f$E_\gamma/E^{\rm max}_\gamma\f$.
*/
double s88(double y) const {
double ratio(_mb/_ms),y2(sqr(y));
if(y>_ycut) y=_ycut;
return 1./27.*(2.*(2.-2.*y+y2)/y*(log(1.-y)+2.*log(ratio))-2.*y2-y-8.*(1.-y)/y);
}
/**
* The real part of the \f$G(t)\f$ function from hep-ph/9805303
*/
double realG(double t) const {
if(t<4.) {
double at(atan(sqrt(t/(4.-t))));
return -2.*sqr(at);
}
else {
double ln(log(0.5*(sqrt(t)+sqrt(t-4.))));
return 2.*(sqr(ln)-0.25*sqr(pi));
}
}
/**
* The imaginary part of the \f$G(t)\f$ function from hep-ph/9805303
*/
double imagG(double t) const {
if(t<4.) return 0.;
else return -2.*pi*log(0.5*(sqrt(t)+sqrt(t-4.)));
}
/**
* Strong coupling \f$\alpha_S\f$ at the scale \f$Q\f$
* @param Q The scale.
*/
double alphaS(Energy Q) {
double lo(1.-0.5*_beta0*_alphaSZ/pi*log(_mz/Q));
return _alphaSZ/lo*(1.-0.25*_beta1/_beta0*_alphaSZ/pi*log(lo)/lo);
}
/**
* Calculate the wilson coefficients we need
*/
void calculateWilsonCoefficients();
/**
* The \f$K'_{NLO}(1-y)\f$ function at parton level from hep-ph/9805303
*/
double KNLO(double y) const {
return _delta*Delta(y,_alphaSM)
+_alphaSM/pi*(s22(y)*sqr(_c20)+s77(y)*sqr(_c70)
+s88(y)*sqr(_c80)+s78(y)*_c70*_c80
+s27(y)*_c20*(_c70-_c80/3.));
}
//@}
private:
/**
* Initialisation of mass spectrum
*/
bool _initialize;
/**
* Quark masses and related parameters
*/
//@{
/**
* The top quark mass
*/
Energy _mt;
/**
* bottom quark mass
*/
Energy _mb;
/**
* charm quark mass
*/
Energy _mc;
/**
* strange quark mass
*/
Energy _ms;
/**
* Ratio of the strange quark mass to the bottom quark mass
*/
double _msovermb;
/**
* The ratio of the charm to bottom quark masses squared, \f$(m_c/m_b)^2\f$
*/
double _zratio;
//@}
/**
* The hadronic \f$\lambda_2\f$ parameter from hep-ph/9805303.
*/
Energy2 _lambda2;
/**
* Masses of other particles
*/
//@{
/**
* The W mass
*/
Energy _mw;
/**
* the Z mass
*/
Energy _mz;
/**
* Mass of the decaying B meson.
*/
Energy _MB;
//@}
/** @name Wilson coefficients, couplings and \f$\beta\f$-function coefficients*/
//@{
/**
* The leading order \f$c_2\f$ coefficient.
*/
double _c20;
/**
* The leading order \f$c_7\f$ coefficient.
*/
double _c70;
/**
* The leading order \f$c_8\f$ coefficient.
*/
double _c80;
/**
* First \f$\beta\f$-function coefficient
*/
double _beta0;
/**
* Second \f$\beta\f$-function coefficient
*/
double _beta1;
/**
* The electromagentic coupling
*/
double _alpha;
/**
* The strong coupling at the Z mass
*/
double _alphaSZ;
/**
* The renormalisation scale
*/
Energy _mub;
/**
* the strong coupling at the renormalisation scale \f$\mu_b\f$.
*/
double _alphaSM;
/**
* The CKM perfactor for the decay
*/
double _ckm;
/**
* Pre-factor for the correction term involving \f$\Delta(y)\f$.
*/
double _delta;
//@}
/**
* Interpolators for the integrate functions and related parameters
*/
//@{
/**
* Interpolator for the \f$s_{22}\f$ function
*/
Interpolator<double,double>::Ptr _s22inter;
/**
* Interpolator for the \f$s_{27}\f$ function
*/
Interpolator<double,double>::Ptr _s27inter;
/**
* Interpolator for the spectrum
*/
Interpolator<InvEnergy,Energy>::Ptr _pmHinter;
/**
* Values of \f$m_H\f$ for the interpolation of the spectrum
*/
vector<Energy> _mHinter;
/**
* Values of the differential rate for the interpolation of the spectrum
*/
vector<InvEnergy> _spectrum;
/**
* Maximum value of the spectrum for unweighting
*/
InvEnergy _spectmax;
/**
* Maximum number of tries for unweighting
*/
unsigned int _maxtry;
//@}
/**
* Parameters for the Fermi function
*/
//@{
/**
* The \f$\bar{\Lambda}\f$ parameter from hep-ph/9805303.
*/
Energy _fermilambda;
/**
* The power from from hep-ph/9805303.
*/
double _fermia;
/**
* The normalisation from hep-ph/9805303.
*/
InvEnergy _ferminorm;
/**
* \f$\lambda_1\f$ scale related to the kinetic energy of the b quark.
*/
Energy2 _fermilambda1;
//@}
/**
* Techincal parameters for the integration of the spectrum
*/
//@{
/**
* Cut-off parameter to avoid the singularity at y=1
*/
double _ycut;
/**
* Value of the energy fraction for which the integral is being performed
*/
double _y;
/**
* Cut-off on the photon energies
*/
double _deltacut;
/**
* Number of points for the interpolation of the s functions
*/
unsigned int _nsfunct;
/**
* Number of points for the interpolation of the spectrum
*/
unsigned int _nspect;
/**
* The function currently being integrated
*/
unsigned int _iopt;
//@}
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of BtoSGammaKagan. */
template <>
struct BaseClassTrait<Herwig::BtoSGammaKagan,1> {
/** Typedef of the first base class of BtoSGammaKagan. */
typedef Herwig::BtoSGammaHadronicMass NthBase;
};
/** This template specialization informs ThePEG about the name of
* the BtoSGammaKagan class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::BtoSGammaKagan>
: public ClassTraitsBase<Herwig::BtoSGammaKagan> {
/** Return a platform-independent class name */
static string className() { return "Herwig::BtoSGammaKagan"; }
/** Return the name of the shared library be loaded to get
* access to the BtoSGammaKagan class and every other class it uses
* (except the base class). */
static string library() { return "HwFormFactors.so"; }
};
/** @endcond */
}
namespace Herwig {
/**
* A struct for the integrand which can access the dimensional value
* member of the BtoSGammaKagan class
*/
struct KaganIntegrand {
/**
* The constructor
*/
KaganIntegrand(Ptr<BtoSGammaKagan>::pointer in) : _kagan(in) {};
/**
* Get the function value
*/
InvEnergy operator ()(Energy arg) const {return _kagan->smeared(arg);}
/** Return type for GaussianIntegrator */
typedef InvEnergy ValType;
/** Argument type for GaussianIntegrator */
typedef Energy ArgType;
/**
* A pointer to the form factor to supply the integrand.
*/
Ptr<BtoSGammaKagan>::pointer _kagan;
};
}
#endif /* HERWIG_BtoSGammaKagan_H */
diff --git a/Decay/General/FFSDecayer.cc b/Decay/General/FFSDecayer.cc
--- a/Decay/General/FFSDecayer.cc
+++ b/Decay/General/FFSDecayer.cc
@@ -1,166 +1,161 @@
// -*- C++ -*-
//
// FFSDecayer.cc is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the FFSDecayer class.
//
#include "FFSDecayer.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/DecayMode.h"
#include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h"
#include "Herwig++/Utilities/Kinematics.h"
using namespace Herwig;
using namespace ThePEG::Helicity;
-FFSDecayer::FFSDecayer() {
- addToSearchList(0);
- addToSearchList(1);
-}
-
IBPtr FFSDecayer::clone() const {
return new_ptr(*this);
}
IBPtr FFSDecayer::fullclone() const {
return new_ptr(*this);
}
void FFSDecayer::doinit() {
_perturbativeVertex = dynamic_ptr_cast<FFSVertexPtr> (getVertex());
_abstractVertex = dynamic_ptr_cast<AbstractFFSVertexPtr>(getVertex());
GeneralTwoBodyDecayer::doinit();
}
void FFSDecayer::persistentOutput(PersistentOStream & os) const {
os << _perturbativeVertex << _abstractVertex;
}
void FFSDecayer::persistentInput(PersistentIStream & is, int) {
is >> _perturbativeVertex >> _abstractVertex;
}
ClassDescription<FFSDecayer> FFSDecayer::initFFSDecayer;
// Definition of the static class description member.
void FFSDecayer::Init() {
static ClassDocumentation<FFSDecayer> documentation
("The FFSDecayer class implements the decay of a fermion to "
"a fermion and a scalar.");
}
double FFSDecayer::me2(const int , const Particle & inpart,
const ParticleVector & decay,
MEOption meopt) const {
//Need to use different barred or unbarred spinors depending on
//whether particle is cc or not.
int itype[2];
if(inpart.dataPtr()->CC()) itype[0] = inpart.id() > 0 ? 0 : 1;
else itype[0] = 2;
if(decay[0]->dataPtr()->CC()) itype[1] = decay[0]->id() > 0 ? 0 : 1;
else itype[1] = 2;
bool ferm(itype[0] == 0 || itype[1] == 0 || (itype[0] == 2 && itype[1] == 2));
if(meopt==Initialize) {
// spinors and rho
if(ferm) {
SpinorWaveFunction ::calculateWaveFunctions(_wave,_rho,
const_ptr_cast<tPPtr>(&inpart),
incoming);
if(_wave[0].wave().Type() != u_spinortype)
for(unsigned int ix = 0; ix < 2; ++ix) _wave [ix].conjugate();
}
else {
SpinorBarWaveFunction::calculateWaveFunctions(_wavebar,_rho,
const_ptr_cast<tPPtr>(&inpart),
incoming);
if(_wavebar[0].wave().Type() != v_spinortype)
for(unsigned int ix = 0; ix < 2; ++ix) _wavebar[ix].conjugate();
}
ME(DecayMatrixElement(PDT::Spin1Half,PDT::Spin1Half,PDT::Spin0));
}
// setup spin info when needed
if(meopt==Terminate) {
// for the decaying particle
if(ferm) {
SpinorWaveFunction::
constructSpinInfo(_wave,const_ptr_cast<tPPtr>(&inpart),incoming,true);
SpinorBarWaveFunction::constructSpinInfo(_wavebar,decay[0],outgoing,true);
}
else {
SpinorBarWaveFunction::
constructSpinInfo(_wavebar,const_ptr_cast<tPPtr>(&inpart),incoming,true);
SpinorWaveFunction::constructSpinInfo(_wave,decay[0],outgoing,true);
}
ScalarWaveFunction::constructSpinInfo(decay[1],outgoing,true);
}
if(ferm)
SpinorBarWaveFunction::
calculateWaveFunctions(_wavebar,decay[0],outgoing);
else
SpinorWaveFunction::
calculateWaveFunctions(_wave ,decay[0],outgoing);
ScalarWaveFunction scal(decay[1]->momentum(),decay[1]->dataPtr(),outgoing);
Energy2 scale(sqr(inpart.mass()));
for(unsigned int if1 = 0; if1 < 2; ++if1) {
for(unsigned int if2 = 0; if2 < 2; ++if2) {
if(ferm) ME()(if1, if2, 0) =
_abstractVertex->evaluate(scale,_wave[if1],_wavebar[if2],scal);
else ME()(if2, if1, 0) =
_abstractVertex->evaluate(scale,_wave[if1],_wavebar[if2],scal);
}
}
double output = (ME().contract(_rho)).real()/scale*UnitRemoval::E2;
// colour and identical particle factors
output *= colourFactor(inpart.dataPtr(),decay[0]->dataPtr(),
decay[1]->dataPtr());
// return the answer
return output;
}
Energy FFSDecayer::partialWidth(PMPair inpart, PMPair outa,
PMPair outb) const {
if( inpart.second < outa.second + outb.second ) return ZERO;
if(_perturbativeVertex) {
double mu1(0.),mu2(0.);
tcPDPtr in = inpart.first->CC() ? tcPDPtr(inpart.first->CC()) : inpart.first;
if(outa.first->iSpin() == PDT::Spin1Half) {
mu1 = outa.second/inpart.second;
mu2 = outb.second/inpart.second;
_perturbativeVertex->setCoupling(sqr(inpart.second), in, outa.first, outb.first);
}
else {
mu1 = outb.second/inpart.second;
mu2 = outa.second/inpart.second;
_perturbativeVertex->setCoupling(sqr(inpart.second), in, outb.first, outa.first);
}
double c2 = norm(_perturbativeVertex->norm());
Complex cl = _perturbativeVertex->left();
Complex cr = _perturbativeVertex->right();
double me2 = c2*( (norm(cl) + norm(cr))*(1. + sqr(mu1) - sqr(mu2))
+ 2.*mu1*(conj(cl)*cr + conj(cr)*cl).real() );
Energy pcm = Kinematics::pstarTwoBodyDecay(inpart.second, outa.second,
outb.second);
Energy output = me2*pcm/16./Constants::pi;
// colour factor
output *= colourFactor(inpart.first,outa.first,outb.first);
// return the answer
return output;
}
else {
return GeneralTwoBodyDecayer::partialWidth(inpart,outa,outb);
}
}
diff --git a/Decay/General/FFSDecayer.h b/Decay/General/FFSDecayer.h
--- a/Decay/General/FFSDecayer.h
+++ b/Decay/General/FFSDecayer.h
@@ -1,191 +1,191 @@
// -*- C++ -*-
//
// FFSDecayer.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_FFSDecayer_H
#define HERWIG_FFSDecayer_H
//
// This is the declaration of the FFSDecayer class.
//
#include "GeneralTwoBodyDecayer.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Helicity/Vertex/Scalar/FFSVertex.h"
namespace Herwig {
using namespace ThePEG;
using Helicity::FFSVertexPtr;
/** \ingroup Decay
* The FFSDecayer class implements the decay of a fermion
* to a fermion and a vector in a general model. It holds an FFVVertex
* pointer that must be typecast from the VertexBase pointer held in
* GeneralTwoBodyDecayer. It implents the virtual functions me2() and
* partialWidth().
*
* @see GeneralTwoBodyDecayer
*/
class FFSDecayer: public GeneralTwoBodyDecayer {
public:
/**
* The default constructor.
*/
- FFSDecayer();
+ FFSDecayer() {}
/** @name Virtual functions required by the Decayer class. */
//@{
/**
* Return the matrix element squared for a given mode and phase-space channel.
* @param ichan The channel we are calculating the matrix element for.
* @param part The decaying Particle.
* @param decay The particles produced in the decay.
* @param meopt Option for the calculation of the matrix element
* @return The matrix element squared for the phase-space configuration.
*/
virtual double me2(const int ichan, const Particle & part,
const ParticleVector & decay, MEOption meopt) const;
/**
* Function to return partial Width
* @param inpart The decaying particle.
* @param outa One of the decay products.
* @param outb The other decay product.
*/
virtual Energy partialWidth(PMPair inpart, PMPair outa,
PMPair outb) const;
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
virtual IBPtr fullclone() const;
//@}
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving and
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit();
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<FFSDecayer> initFFSDecayer;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
FFSDecayer & operator=(const FFSDecayer &);
private:
/**
* Abstract pointer to AbstractFFSVertex
*/
AbstractFFSVertexPtr _abstractVertex;
/**
* Pointer to the perturbative vertex
*/
FFSVertexPtr _perturbativeVertex;
/**
* Spin density matrix
*/
mutable RhoDMatrix _rho;
/**
* Spinor wavefunctions
*/
mutable vector<SpinorWaveFunction> _wave ;
/**
* Barred spinor wavefunctions
*/
mutable vector<SpinorBarWaveFunction> _wavebar;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of FFSDecayer. */
template <>
struct BaseClassTrait<Herwig::FFSDecayer,1> {
/** Typedef of the first base class of FFSDecayer. */
typedef Herwig::GeneralTwoBodyDecayer NthBase;
};
/** This template specialization informs ThePEG about the name of
* the FFSDecayer class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::FFSDecayer>
: public ClassTraitsBase<Herwig::FFSDecayer> {
/** Return a platform-independent class name */
static string className() { return "Herwig::FFSDecayer"; }
};
/** @endcond */
}
#endif /* HERWIG_FFSDecayer_H */
diff --git a/Decay/General/FFVCurrentDecayer.cc b/Decay/General/FFVCurrentDecayer.cc
--- a/Decay/General/FFVCurrentDecayer.cc
+++ b/Decay/General/FFVCurrentDecayer.cc
@@ -1,200 +1,198 @@
// -*- C++ -*-
//
// FFVCurrentDecayer.cc is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the FFVCurrentDecayer class.
//
#include "FFVCurrentDecayer.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h"
#include "ThePEG/StandardModel/StandardModelBase.h"
using namespace Herwig;
using ThePEG::Helicity::u_spinortype;
using ThePEG::Helicity::v_spinortype;
using ThePEG::Helicity::VectorWaveFunction;
using ThePEG::Helicity::SpinorWaveFunction;
using ThePEG::Helicity::SpinorBarWaveFunction;
using ThePEG::Helicity::Direction;
using ThePEG::Helicity::incoming;
using ThePEG::Helicity::outgoing;
IBPtr FFVCurrentDecayer::clone() const {
return new_ptr(*this);
}
IBPtr FFVCurrentDecayer::fullclone() const {
return new_ptr(*this);
}
void FFVCurrentDecayer::doinit() {
_theFFVPtr = dynamic_ptr_cast<FFVVertexPtr>(getVertex());
GeneralCurrentDecayer::doinit();
}
void FFVCurrentDecayer::rebind(const TranslationMap & trans)
{
_theFFVPtr = trans.translate(_theFFVPtr);
GeneralCurrentDecayer::rebind(trans);
}
IVector FFVCurrentDecayer::getReferences() {
IVector ret = GeneralCurrentDecayer::getReferences();
ret.push_back(_theFFVPtr);
return ret;
}
void FFVCurrentDecayer::persistentOutput(PersistentOStream & os) const {
os << _theFFVPtr;
}
void FFVCurrentDecayer::persistentInput(PersistentIStream & is, int) {
is >> _theFFVPtr;
}
ClassDescription<FFVCurrentDecayer> FFVCurrentDecayer::initFFVCurrentDecayer;
// Definition of the static class description member.
void FFVCurrentDecayer::Init() {
static ClassDocumentation<FFVCurrentDecayer> documentation
("There is no documentation for the FFVCurrentDecayer class");
}
double FFVCurrentDecayer::me2(const int ichan, const Particle & inpart,
const ParticleVector & decay,
MEOption meopt) const {
- // map the mode to those in the current
- int mode(modeMap()[imode()]);
// get the particles for the hadronic curret
Energy q;
ParticleVector hadpart(decay.begin()+1,decay.end());
// fermion types
int itype[2];
if(inpart.dataPtr()->CC()) itype[0] = inpart.id() > 0 ? 0 : 1;
else itype[0] = 2;
if(decay[0]->dataPtr()->CC()) itype[1] = decay[0]->id() > 0 ? 0 : 1;
else itype[1] = 2;
//Need to use different barred or unbarred spinors depending on
//whether particle is cc or not.
bool ferm(itype[0] == 0 || itype[1] == 0 || (itype[0] == 2 && itype[1] == 2));
if(meopt==Initialize) {
// spinors and rho
if(ferm) {
SpinorWaveFunction ::calculateWaveFunctions(_wave,_rho,
const_ptr_cast<tPPtr>(&inpart),
incoming);
if(_wave[0].wave().Type() != u_spinortype)
for(unsigned int ix = 0; ix < 2; ++ix) _wave [ix].conjugate();
}
else {
SpinorBarWaveFunction::calculateWaveFunctions(_wavebar,_rho,
const_ptr_cast<tPPtr>(&inpart),
incoming);
if(_wavebar[0].wave().Type() != v_spinortype)
for(unsigned int ix = 0; ix < 2; ++ix) _wavebar[ix].conjugate();
}
}
// setup spin info when needed
if(meopt==Terminate) {
// for the decaying particle
if(ferm) {
SpinorWaveFunction::
constructSpinInfo(_wave,const_ptr_cast<tPPtr>(&inpart),incoming,true);
SpinorBarWaveFunction::constructSpinInfo(_wavebar,decay[0],outgoing,true);
}
else {
SpinorBarWaveFunction::
constructSpinInfo(_wavebar,const_ptr_cast<tPPtr>(&inpart),incoming,true);
SpinorWaveFunction::constructSpinInfo(_wave,decay[0],outgoing,true);
}
- weakCurrent()->current(mode,ichan,q,hadpart,meopt);
+ weakCurrent()->current(mode(),ichan,q,hadpart,meopt);
return 0.;
}
Energy2 scale(sqr(inpart.mass()));
if(ferm)
SpinorBarWaveFunction::
calculateWaveFunctions(_wavebar,decay[0],outgoing);
else
SpinorWaveFunction::
calculateWaveFunctions(_wave ,decay[0],outgoing);
// calculate the hadron current
vector<LorentzPolarizationVectorE>
- hadron(weakCurrent()->current(mode,ichan,q,hadpart,meopt));
+ hadron(weakCurrent()->current(mode(),ichan,q,hadpart,meopt));
// prefactor
double pre = sqr(pow(inpart.mass()/q,int(hadpart.size()-2)));
// work out the mapping for the hadron vector
vector<unsigned int> constants(decay.size()+1),ihel(decay.size()+1);
vector<PDT::Spin> ispin(decay.size());
int itemp(1);
unsigned int hhel,ix(decay.size());
do {
--ix;
ispin[ix]=decay[ix]->data().iSpin();
itemp*=ispin[ix];
constants[ix]=itemp;
}
while(ix>0);
constants[decay.size()]=1;
constants[0]=constants[1];
// compute the matrix element
DecayMatrixElement newME(PDT::Spin1Half,ispin);
VectorWaveFunction vWave;
tcPDPtr vec= inpart.dataPtr()->iCharge()-decay[0]->dataPtr()->iCharge() > 0
? getParticleData(ParticleID::Wplus) : getParticleData(ParticleID::Wminus);
Lorentz5Momentum vmom=inpart.momentum()-decay[0]->momentum();
vmom.rescaleMass();
for(hhel=0;hhel<hadron.size();++hhel) {
// map the index for the hadrons to a helicity state
for(ix=decay.size();ix>1;--ix) ihel[ix]=(hhel%constants[ix-1])/constants[ix];
vWave=VectorWaveFunction(vmom,vec,hadron[hhel]*UnitRemoval::InvE,outgoing);
for(unsigned int if1 = 0; if1 < 2; ++if1) {
for(unsigned int if2 = 0; if2 < 2; ++if2) {
ihel[0]=if1;
ihel[1]=if2;
if(!ferm) swap(ihel[0],ihel[1]);
newME(ihel) = _theFFVPtr->evaluate(scale,_wave[if1],_wavebar[if2],vWave);
}
}
}
// store the matrix element
ME(newME);
// multiply by the CKM element
int iq,ia;
- weakCurrent()->decayModeInfo(mode,iq,ia);
+ weakCurrent()->decayModeInfo(mode(),iq,ia);
double ckm(1.);
if(iq<=6) {
if(iq%2==0) ckm = SM().CKM(iq/2-1,(abs(ia)-1)/2);
else ckm = SM().CKM(abs(ia)/2-1,(iq-1)/2);
}
pre /= 0.125*sqr(_theFFVPtr->weakCoupling(scale));
double output(0.5*pre*ckm*(ME().contract(_rho)).real()*
sqr(SM().fermiConstant()*UnitRemoval::E2));
return output;
}
Energy FFVCurrentDecayer::partialWidth(tPDPtr inpart, tPDPtr outa,
vector<tPDPtr> currout) {
vector<long> id;
id.push_back(inpart->id());
id.push_back(outa->id());
for(unsigned int ix=0;ix<currout.size();++ix) id.push_back(currout[ix]->id());
bool cc;
int mode=modeNumber(cc,id);
imode(mode);
return initializePhaseSpaceMode(mode,true);
}
diff --git a/Decay/General/FFVDecayer.cc b/Decay/General/FFVDecayer.cc
--- a/Decay/General/FFVDecayer.cc
+++ b/Decay/General/FFVDecayer.cc
@@ -1,178 +1,173 @@
// -*- C++ -*-
//
// FFVDecayer.cc is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the FFVDecayer class.
//
#include "FFVDecayer.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/DecayMode.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h"
#include "Herwig++/Utilities/Kinematics.h"
using namespace Herwig;
using namespace ThePEG::Helicity;
-FFVDecayer::FFVDecayer() {
- addToSearchList(0);
- addToSearchList(1);
-}
-
IBPtr FFVDecayer::clone() const {
return new_ptr(*this);
}
IBPtr FFVDecayer::fullclone() const {
return new_ptr(*this);
}
void FFVDecayer::doinit() {
_perturbativeVertex = dynamic_ptr_cast<FFVVertexPtr> (getVertex());
_abstractVertex = dynamic_ptr_cast<AbstractFFVVertexPtr>(getVertex());
GeneralTwoBodyDecayer::doinit();
}
void FFVDecayer::persistentOutput(PersistentOStream & os) const {
os << _abstractVertex << _perturbativeVertex;
}
void FFVDecayer::persistentInput(PersistentIStream & is, int) {
is >> _abstractVertex >> _perturbativeVertex;
}
double FFVDecayer::me2(const int , const Particle & inpart,
const ParticleVector & decay,
MEOption meopt) const {
// type of process
int itype[2];
if(inpart.dataPtr()->CC()) itype[0] = inpart.id() > 0 ? 0 : 1;
else itype[0] = 2;
if(decay[0]->dataPtr()->CC()) itype[1] = decay[0]->id() > 0 ? 0 : 1;
else itype[1] = 2;
//Need to use different barred or unbarred spinors depending on
//whether particle is cc or not.
bool ferm(itype[0] == 0 || itype[1] == 0 || (itype[0] == 2 && itype[1] == 2));
if(meopt==Initialize) {
// spinors and rho
if(ferm) {
SpinorWaveFunction ::calculateWaveFunctions(_wave,_rho,
const_ptr_cast<tPPtr>(&inpart),
incoming);
if(_wave[0].wave().Type() != u_spinortype)
for(unsigned int ix = 0; ix < 2; ++ix) _wave [ix].conjugate();
}
else {
SpinorBarWaveFunction::calculateWaveFunctions(_wavebar,_rho,
const_ptr_cast<tPPtr>(&inpart),
incoming);
if(_wavebar[0].wave().Type() != v_spinortype)
for(unsigned int ix = 0; ix < 2; ++ix) _wavebar[ix].conjugate();
}
ME(DecayMatrixElement(PDT::Spin1Half,PDT::Spin1Half,PDT::Spin1));
}
// setup spin info when needed
if(meopt==Terminate) {
// for the decaying particle
if(ferm) {
SpinorWaveFunction::
constructSpinInfo(_wave,const_ptr_cast<tPPtr>(&inpart),incoming,true);
SpinorBarWaveFunction::constructSpinInfo(_wavebar,decay[0],outgoing,true);
}
else {
SpinorBarWaveFunction::
constructSpinInfo(_wavebar,const_ptr_cast<tPPtr>(&inpart),incoming,true);
SpinorWaveFunction::constructSpinInfo(_wave,decay[0],outgoing,true);
}
VectorWaveFunction::
constructSpinInfo(_vector,decay[1],outgoing,true,false);
}
Energy2 scale(sqr(inpart.mass()));
if(ferm)
SpinorBarWaveFunction::
calculateWaveFunctions(_wavebar,decay[0],outgoing);
else
SpinorWaveFunction::
calculateWaveFunctions(_wave ,decay[0],outgoing);
bool massless = decay[1]->dataPtr()->mass()==ZERO;
VectorWaveFunction::
calculateWaveFunctions(_vector,decay[1],outgoing,massless);
for(unsigned int if1 = 0; if1 < 2; ++if1) {
for(unsigned int if2 = 0; if2 < 2; ++if2) {
for(unsigned int vhel = 0; vhel < 3; ++vhel) {
if(massless && vhel == 1) ++vhel;
if(ferm)
ME()(if1, if2,vhel) =
_abstractVertex->evaluate(scale,_wave[if1],_wavebar[if2],_vector[vhel]);
else
ME()(if2, if1, vhel) =
_abstractVertex->evaluate(scale,_wave[if1],_wavebar[if2],_vector[vhel]);
}
}
}
double output=(ME().contract(_rho)).real()/scale*UnitRemoval::E2;
// colour and identical particle factors
output *= colourFactor(inpart.dataPtr(),decay[0]->dataPtr(),decay[1]->dataPtr());
// return the answer
return output;
}
Energy FFVDecayer::partialWidth(PMPair inpart, PMPair outa,
PMPair outb) const {
if( inpart.second < outa.second + outb.second ) return ZERO;
if(_perturbativeVertex) {
double mu1(outa.second/inpart.second),mu2(outb.second/inpart.second);
tcPDPtr in = inpart.first->CC() ? tcPDPtr(inpart.first->CC()) : inpart.first;
if( outa.first->iSpin() == PDT::Spin1Half)
_perturbativeVertex->setCoupling(sqr(inpart.second), in,
outa.first, outb.first);
else {
swap(mu1,mu2);
_perturbativeVertex->setCoupling(sqr(inpart.second),in,
outb.first,outa.first);
}
Complex cl(_perturbativeVertex->left()),cr(_perturbativeVertex->right());
double me2(0.);
if( mu2 > 0. ) {
me2 = (norm(cl) + norm(cr))*(1. + sqr(mu1*mu2) + sqr(mu2)
- 2.*sqr(mu1) - 2.*sqr(mu2*mu2)
+ sqr(mu1*mu1))
- 6.*mu1*sqr(mu2)*(conj(cl)*cr + conj(cr)*cl).real();
me2 /= sqr(mu2);
}
else
me2 = 2.*( (norm(cl) + norm(cr))*(sqr(mu1) + 1.)
- 4.*mu1*(conj(cl)*cr + conj(cr)*cl).real() );
Energy pcm = Kinematics::pstarTwoBodyDecay(inpart.second, outa.second,
outb.second);
Energy output = norm(_perturbativeVertex->norm())*me2*pcm/16./Constants::pi;
// colour factor
output *= colourFactor(inpart.first,outa.first,outb.first);
// return the answer
return output;
}
else {
return GeneralTwoBodyDecayer::partialWidth(inpart,outa,outb);
}
}
ClassDescription<FFVDecayer> FFVDecayer::initFFVDecayer;
// Definition of the static class description member.
void FFVDecayer::Init() {
static ClassDocumentation<FFVDecayer> documentation
("There is no documentation for the FFVDecayer class");
}
diff --git a/Decay/General/FFVDecayer.h b/Decay/General/FFVDecayer.h
--- a/Decay/General/FFVDecayer.h
+++ b/Decay/General/FFVDecayer.h
@@ -1,198 +1,198 @@
// -*- C++ -*-
//
// FFVDecayer.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_FFVDecayer_H
#define HERWIG_FFVDecayer_H
//
// This is the declaration of the FFVDecayer class.
//
#include "GeneralTwoBodyDecayer.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Helicity/Vertex/Vector/FFVVertex.h"
namespace Herwig {
using namespace ThePEG;
using Helicity::FFVVertexPtr;
/** \ingroup Decay
* The FFVDecayer class implements the decay of a fermion
* to a fermion and a vector in a general model. It holds an FFVVertex
* pointer that must be typecast from the VertexBase pointer held in
* GeneralTwoBodyDecayer. It implents the virtual functions me2() and
* partialWidth().
*
* @see GeneralTwoBodyDecayer
*/
class FFVDecayer: public GeneralTwoBodyDecayer {
public:
/**
* The default constructor.
*/
- FFVDecayer();
+ FFVDecayer() {}
public:
/** @name Virtual functions required by the Decayer class. */
//@{
/**
* Return the matrix element squared for a given mode and phase-space channel.
* @param ichan The channel we are calculating the matrix element for.
* @param part The decaying Particle.
* @param decay The particles produced in the decay.
* @param meopt Option for the matrix element
* @return The matrix element squared for the phase-space configuration.
*/
virtual double me2(const int ichan, const Particle & part,
const ParticleVector & decay, MEOption meopt) const;
/**
* Function to return partial Width
* @param inpart The decaying particle.
* @param outa One of the decay products.
* @param outb The other decay product.
*/
virtual Energy partialWidth(PMPair inpart, PMPair outa,
PMPair outb) const;
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
virtual IBPtr fullclone() const;
//@}
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();
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<FFVDecayer> initFFVDecayer;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
FFVDecayer & operator=(const FFVDecayer &);
private:
/**
* Abstract pointer to AbstractFFVVertex
*/
AbstractFFVVertexPtr _abstractVertex;
/**
* Pointer to the perturbative vertex
*/
FFVVertexPtr _perturbativeVertex;
/**
* Spin density matrix
*/
mutable RhoDMatrix _rho;
/**
* Spinor wavefunction
*/
mutable vector<SpinorWaveFunction> _wave ;
/**
* Barred spinor wavefunction
*/
mutable vector<SpinorBarWaveFunction> _wavebar;
/**
* Polarization vectors
*/
mutable vector<VectorWaveFunction> _vector;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of FFVDecayer. */
template <>
struct BaseClassTrait<Herwig::FFVDecayer,1> {
/** Typedef of the first base class of FFVDecayer. */
typedef Herwig::GeneralTwoBodyDecayer NthBase;
};
/** This template specialization informs ThePEG about the name of
* the FFVDecayer class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::FFVDecayer>
: public ClassTraitsBase<Herwig::FFVDecayer> {
/** Return a platform-independent class name */
static string className() { return "Herwig::FFVDecayer"; }
};
/** @endcond */
}
#endif /* HERWIG_FFVDecayer_H */
diff --git a/Decay/General/FRSDecayer.cc b/Decay/General/FRSDecayer.cc
--- a/Decay/General/FRSDecayer.cc
+++ b/Decay/General/FRSDecayer.cc
@@ -1,178 +1,174 @@
// -*- C++ -*-
//
// FRSDecayer.cc is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the FRSDecayer class.
//
#include "FRSDecayer.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/DecayMode.h"
#include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h"
#include "Herwig++/Utilities/Kinematics.h"
using namespace Herwig;
using namespace ThePEG::Helicity;
-FRSDecayer::FRSDecayer() {
- addToSearchList(1);
-}
-
IBPtr FRSDecayer::clone() const {
return new_ptr(*this);
}
IBPtr FRSDecayer::fullclone() const {
return new_ptr(*this);
}
void FRSDecayer::doinit() {
perturbativeVertex_ = dynamic_ptr_cast<RFSVertexPtr> (getVertex());
abstractVertex_ = dynamic_ptr_cast<AbstractRFSVertexPtr>(getVertex());
GeneralTwoBodyDecayer::doinit();
}
void FRSDecayer::persistentOutput(PersistentOStream & os) const {
os << perturbativeVertex_ << abstractVertex_;
}
void FRSDecayer::persistentInput(PersistentIStream & is, int) {
is >> perturbativeVertex_ >> abstractVertex_;
}
ClassDescription<FRSDecayer> FRSDecayer::initFRSDecayer;
// Definition of the static class description member.
void FRSDecayer::Init() {
static ClassDocumentation<FRSDecayer> documentation
("The FRSDecayer class implements the decay of a fermion to "
"a spin-3/2 fermion and a scalar.");
}
double FRSDecayer::me2(const int , const Particle & inpart,
const ParticleVector & decay,
MEOption meopt) const {
bool ferm = inpart.id() > 0;
if(meopt==Initialize) {
// spinors and rho
if(ferm) {
SpinorWaveFunction ::calculateWaveFunctions(wave_,rho_,
const_ptr_cast<tPPtr>(&inpart),
incoming);
if(wave_[0].wave().Type() != u_spinortype)
for(unsigned int ix = 0; ix < 2; ++ix) wave_ [ix].conjugate();
}
else {
SpinorBarWaveFunction::calculateWaveFunctions(wavebar_,rho_,
const_ptr_cast<tPPtr>(&inpart),
incoming);
if(wavebar_[0].wave().Type() != v_spinortype)
for(unsigned int ix = 0; ix < 2; ++ix) wavebar_[ix].conjugate();
}
ME(DecayMatrixElement(PDT::Spin1Half,PDT::Spin3Half,PDT::Spin0));
}
// setup spin info when needed
if(meopt==Terminate) {
// for the decaying particle
if(ferm) {
SpinorWaveFunction::
constructSpinInfo(wave_,const_ptr_cast<tPPtr>(&inpart),incoming,true);
RSSpinorBarWaveFunction::constructSpinInfo(RSwavebar_,decay[0],outgoing,true);
}
else {
SpinorBarWaveFunction::
constructSpinInfo(wavebar_,const_ptr_cast<tPPtr>(&inpart),incoming,true);
RSSpinorWaveFunction::constructSpinInfo(RSwave_,decay[0],outgoing,true);
}
ScalarWaveFunction::constructSpinInfo(decay[1],outgoing,true);
}
if(ferm)
RSSpinorBarWaveFunction::
calculateWaveFunctions(RSwavebar_,decay[0],outgoing);
else
RSSpinorWaveFunction::
calculateWaveFunctions(RSwave_ ,decay[0],outgoing);
ScalarWaveFunction scal(decay[1]->momentum(),decay[1]->dataPtr(),outgoing);
Energy2 scale(sqr(inpart.mass()));
for(unsigned int if1 = 0; if1 < 2; ++if1) {
for(unsigned int if2 = 0; if2 < 4; ++if2) {
if(ferm) ME()(if1, if2, 0) =
abstractVertex_->evaluate(scale,wave_[if1],RSwavebar_[if2],scal);
else ME()(if1, if2, 0) =
abstractVertex_->evaluate(scale,RSwave_[if2],wavebar_[if1],scal);
}
}
double output = (ME().contract(rho_)).real()/scale*UnitRemoval::E2;
// colour and identical particle factors
output *= colourFactor(inpart.dataPtr(),decay[0]->dataPtr(),
decay[1]->dataPtr());
// test code
// Energy q = inpart.mass();
// Energy m1 = decay[0]->mass();
// Energy m2 = decay[1]->mass();
// Energy2 q2(q*q),m12(m1*m1),m22(m2*m2);
// Energy2 pcm2(0.25*(q2*(q2-2.*m12-2.*m22)+(m12-m22)*(m12-m22))/q2);
// Energy pcm(sqrt(pcm2));
// Energy Qp(sqrt((q+m1)*(q+m1)-m22)),Qm(sqrt((q-m1)*(q-m1)-m22));
// double r23(sqrt(2./3.));
// // couplings
// Complex left = perturbativeVertex_-> left()*perturbativeVertex_-> norm();
// Complex right = perturbativeVertex_->right()*perturbativeVertex_-> norm();
// complex<InvEnergy> A1 = 0.5*(left+right)*UnitRemoval::InvE;
// complex<InvEnergy> B1 = 0.5*(right-left)*UnitRemoval::InvE;
// complex<Energy> h1(-2.*r23*pcm*q/m1*Qm*B1);
// complex<Energy> h2( 2.*r23*pcm*q/m1*Qp*A1);
// cout << "testing 1/2->3/2 0 "
// << output*scale/GeV2 << " "
// << real(h1*conj(h1)+h2*conj(h2))/4./GeV2 << " "
// << real(h1*conj(h1)+h2*conj(h2))/4./(output*scale) << endl;
// return the answer
return output;
}
Energy FRSDecayer::partialWidth(PMPair inpart, PMPair outa,
PMPair outb) const {
if( inpart.second < outa.second + outb.second ) return ZERO;
if(perturbativeVertex_) {
Energy q = inpart.second;
Energy m1 = outa.second;
Energy m2 = outb.second;
Energy2 q2(q*q),m12(m1*m1),m22(m2*m2);
Energy2 pcm2(0.25*(q2*(q2-2.*m12-2.*m22)+(m12-m22)*(m12-m22))/q2);
Energy pcm(sqrt(pcm2));
Energy Qp(sqrt((q+m1)*(q+m1)-m22)),Qm(sqrt((q-m1)*(q-m1)-m22));
double r23(sqrt(2./3.));
// couplings
tcPDPtr in = inpart.first->CC() ? tcPDPtr(inpart.first->CC()) : inpart.first;
perturbativeVertex_->setCoupling(sqr(inpart.second), outa.first,
in, outb.first);
Complex left = perturbativeVertex_-> left()*perturbativeVertex_-> norm();
Complex right = perturbativeVertex_->right()*perturbativeVertex_-> norm();
complex<InvEnergy> A1 = 0.5*(left+right)*UnitRemoval::InvE;
complex<InvEnergy> B1 = 0.5*(right-left)*UnitRemoval::InvE;
complex<Energy> h1(-2.*r23*pcm*q/m1*Qm*B1);
complex<Energy> h2( 2.*r23*pcm*q/m1*Qp*A1);
double me2 = real(h1*conj(h1)+h2*conj(h2))/4./sqr(inpart.second);
Energy output = me2*pcm/8./Constants::pi;
// colour factor
output *= colourFactor(inpart.first,outa.first,outb.first);
// return the answer
return output;
}
else {
return GeneralTwoBodyDecayer::partialWidth(inpart,outa,outb);
}
}
diff --git a/Decay/General/FRSDecayer.h b/Decay/General/FRSDecayer.h
--- a/Decay/General/FRSDecayer.h
+++ b/Decay/General/FRSDecayer.h
@@ -1,201 +1,201 @@
// -*- C++ -*-
//
// FRSDecayer.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_FRSDecayer_H
#define HERWIG_FRSDecayer_H
//
// This is the declaration of the FRSDecayer class.
//
#include "GeneralTwoBodyDecayer.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Helicity/Vertex/Scalar/RFSVertex.h"
namespace Herwig {
using namespace ThePEG;
using Helicity::RFSVertexPtr;
/** \ingroup Decay
* The FRSDecayer class implements the decay of a fermion
* to a spin-3/2 fermion and a vector in a general model. It holds an RFVVertex
* pointer that must be typecast from the VertexBase pointer held in
* GeneralTwoBodyDecayer. It implents the virtual functions me2() and
* partialWidth().
*
* @see GeneralTwoBodyDecayer
*/
class FRSDecayer: public GeneralTwoBodyDecayer {
public:
/**
* The default constructor.
*/
- FRSDecayer();
+ FRSDecayer() {}
/** @name Virtual functions required by the Decayer class. */
//@{
/**
* Return the matrix element squared for a given mode and phase-space channel.
* @param ichan The channel we are calculating the matrix element for.
* @param part The decaying Particle.
* @param decay The particles produced in the decay.
* @param meopt Option for the calculation of the matrix element
* @return The matrix element squared for the phase-space configuration.
*/
virtual double me2(const int ichan, const Particle & part,
const ParticleVector & decay, MEOption meopt) const;
/**
* Function to return partial Width
* @param inpart The decaying particle.
* @param outa One of the decay products.
* @param outb The other decay product.
*/
virtual Energy partialWidth(PMPair inpart, PMPair outa,
PMPair outb) const;
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
virtual IBPtr fullclone() const;
//@}
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving and
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit();
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<FRSDecayer> initFRSDecayer;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
FRSDecayer & operator=(const FRSDecayer &);
private:
/**
* Abstract pointer to AbstractFRSVertex
*/
AbstractRFSVertexPtr abstractVertex_;
/**
* Pointer to the perturbative vertex
*/
RFSVertexPtr perturbativeVertex_;
/**
* Spin density matrix
*/
mutable RhoDMatrix rho_;
/**
* Spinor wavefunctions
*/
mutable vector<SpinorWaveFunction> wave_ ;
/**
* Barred spinor wavefunctions
*/
mutable vector<SpinorBarWaveFunction> wavebar_;
/**
* RS Spinor wavefunctions
*/
mutable vector<RSSpinorWaveFunction> RSwave_ ;
/**
* Barred RS spinor wavefunctions
*/
mutable vector<RSSpinorBarWaveFunction> RSwavebar_;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of FRSDecayer. */
template <>
struct BaseClassTrait<Herwig::FRSDecayer,1> {
/** Typedef of the first base class of FRSDecayer. */
typedef Herwig::GeneralTwoBodyDecayer NthBase;
};
/** This template specialization informs ThePEG about the name of
* the FRSDecayer class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::FRSDecayer>
: public ClassTraitsBase<Herwig::FRSDecayer> {
/** Return a platform-independent class name */
static string className() { return "Herwig::FRSDecayer"; }
};
/** @endcond */
}
#endif /* HERWIG_FRSDecayer_H */
diff --git a/Decay/General/FRVDecayer.cc b/Decay/General/FRVDecayer.cc
--- a/Decay/General/FRVDecayer.cc
+++ b/Decay/General/FRVDecayer.cc
@@ -1,209 +1,205 @@
// -*- C++ -*-
//
// FRVDecayer.cc is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the FRVDecayer class.
//
#include "FRVDecayer.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/DecayMode.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h"
#include "Herwig++/Utilities/Kinematics.h"
using namespace Herwig;
using namespace ThePEG::Helicity;
-FRVDecayer::FRVDecayer() {
- addToSearchList(1);
-}
-
IBPtr FRVDecayer::clone() const {
return new_ptr(*this);
}
IBPtr FRVDecayer::fullclone() const {
return new_ptr(*this);
}
void FRVDecayer::doinit() {
perturbativeVertex_ = dynamic_ptr_cast<RFVVertexPtr> (getVertex());
abstractVertex_ = dynamic_ptr_cast<AbstractRFVVertexPtr>(getVertex());
GeneralTwoBodyDecayer::doinit();
}
void FRVDecayer::persistentOutput(PersistentOStream & os) const {
os << abstractVertex_ << perturbativeVertex_;
}
void FRVDecayer::persistentInput(PersistentIStream & is, int) {
is >> abstractVertex_ >> perturbativeVertex_;
}
double FRVDecayer::me2(const int , const Particle & inpart,
const ParticleVector & decay,
MEOption meopt) const {
// decaying fermion or antifermion
bool ferm = inpart.id() > 0;
// initialize
if(meopt==Initialize) {
// spinors and rho
if(ferm) {
SpinorWaveFunction ::calculateWaveFunctions(wave_,rho_,
const_ptr_cast<tPPtr>(&inpart),
incoming);
if(wave_[0].wave().Type() != u_spinortype)
for(unsigned int ix = 0; ix < 2; ++ix) wave_ [ix].conjugate();
}
else {
SpinorBarWaveFunction::calculateWaveFunctions(wavebar_,rho_,
const_ptr_cast<tPPtr>(&inpart),
incoming);
if(wavebar_[0].wave().Type() != v_spinortype)
for(unsigned int ix = 0; ix < 2; ++ix) wavebar_[ix].conjugate();
}
ME(DecayMatrixElement(PDT::Spin1Half,PDT::Spin3Half,PDT::Spin1));
}
// setup spin info when needed
if(meopt==Terminate) {
// for the decaying particle
if(ferm) {
SpinorWaveFunction::
constructSpinInfo(wave_,const_ptr_cast<tPPtr>(&inpart),incoming,true);
RSSpinorBarWaveFunction::constructSpinInfo(RSwavebar_,decay[0],outgoing,true);
}
else {
SpinorBarWaveFunction::
constructSpinInfo(wavebar_,const_ptr_cast<tPPtr>(&inpart),incoming,true);
RSSpinorWaveFunction::constructSpinInfo(RSwave_,decay[0],outgoing,true);
}
VectorWaveFunction::
constructSpinInfo(vector_,decay[1],outgoing,true,false);
}
Energy2 scale(sqr(inpart.mass()));
if(ferm)
RSSpinorBarWaveFunction::
calculateWaveFunctions(RSwavebar_,decay[0],outgoing);
else
RSSpinorWaveFunction::
calculateWaveFunctions(RSwave_ ,decay[0],outgoing);
bool massless = decay[1]->dataPtr()->mass()==ZERO;
VectorWaveFunction::
calculateWaveFunctions(vector_,decay[1],outgoing,massless);
// loop over helicities
for(unsigned int if1 = 0; if1 < 2; ++if1) {
for(unsigned int if2 = 0; if2 < 4; ++if2) {
for(unsigned int vhel = 0; vhel < 3; ++vhel) {
if(massless && vhel == 1) ++vhel;
if(ferm)
ME()(if1, if2,vhel) =
abstractVertex_->evaluate(scale,wave_[if1],
RSwavebar_[if2],vector_[vhel]);
else
ME()(if1, if2, vhel) =
abstractVertex_->evaluate(scale,RSwave_[if2],
wavebar_[if1],vector_[vhel]);
}
}
}
double output=(ME().contract(rho_)).real()/scale*UnitRemoval::E2;
// test
// Energy m1(inpart.mass()),m2(decay[0]->mass()),m3(decay[1]->mass());
// Energy2 m12(m1*m1),m22(m2*m2),m32(m3*m3);
// Energy Qp(sqrt(sqr(m1+m2)-sqr(m3))),Qm(sqrt(sqr(m1-m2)-sqr(m3)));
// double r2(sqrt(2.)),r3(sqrt(3.));
// Energy pcm(Kinematics::pstarTwoBodyDecay(m1,m2,m3));
// vector<Complex> left = perturbativeVertex_-> left();
// vector<Complex> right = perturbativeVertex_->right();
// Complex A1 = 0.5*(left [0]+right[0])*perturbativeVertex_-> norm();
// Complex B1 = 0.5*(right[0]- left[0])*perturbativeVertex_-> norm();
// complex<InvEnergy> A2 = 0.5*(left [1]+right[1])*perturbativeVertex_-> norm()*UnitRemoval::InvE;
// complex<InvEnergy> B2 = 0.5*(right[1]- left[1])*perturbativeVertex_-> norm()*UnitRemoval::InvE;
// complex<InvEnergy2> A3 = 0.5*(left [2]+right[2])*perturbativeVertex_-> norm()*UnitRemoval::InvE2;
// complex<InvEnergy2> B3 = 0.5*(right[2]- left[2])*perturbativeVertex_-> norm()*UnitRemoval::InvE2;
// complex<Energy> h1(-2.*Qp*A1),h2(2.*Qm*B1);
// complex<Energy> h3(-2./r3*Qp*(A1-Qm*Qm/m2*A2));
// complex<Energy> h4( 2./r3*Qm*(B1-Qp*Qp/m2*B2));
// complex<Energy> h5(ZERO),h6(ZERO);
// if(decay[1]->mass()>ZERO) {
// h5 = -2.*r2/r3/m2/m3*Qp*(0.5*(m12-m22-m32)*A1+0.5*Qm*Qm*(m1+m2)*A2
// +m12*pcm*pcm*A3);
// h6 = 2.*r2/r3/m2/m3*Qm*(0.5*(m12-m22-m32)*B1-0.5*Qp*Qp*(m1-m2)*B2
// +m12*pcm*pcm*B3);
// }
// cout << "testing 1/2->3/2 1 " << inpart.id() << " "
// << output << " "
// << 0.25*(h1*conj(h1)+h2*conj(h2)+h3*conj(h3)+
// h4*conj(h4)+h5*conj(h5)+h6*conj(h6))/sqr(inpart.mass()) << " "
// << 0.25*(h1*conj(h1)+h2*conj(h2)+h3*conj(h3)+
// h4*conj(h4)+h5*conj(h5)+h6*conj(h6))/sqr(inpart.mass())/output << endl;
// colour and identical particle factors
output *= colourFactor(inpart.dataPtr(),decay[0]->dataPtr(),decay[1]->dataPtr());
// return the answer
return output;
}
Energy FRVDecayer::partialWidth(PMPair inpart, PMPair outa,
PMPair outb) const {
if( inpart.second < outa.second + outb.second ) return ZERO;
if(perturbativeVertex_) {
Energy m1(inpart.second),m2(outa.second),m3(outb.second);
Energy2 m12(m1*m1),m22(m2*m2),m32(m3*m3);
Energy Qp(sqrt(sqr(m1+m2)-sqr(m3))),Qm(sqrt(sqr(m1-m2)-sqr(m3)));
double r2(sqrt(2.)),r3(sqrt(3.));
Energy pcm(Kinematics::pstarTwoBodyDecay(m1,m2,m3));
// couplings
tcPDPtr in = inpart.first->CC() ? tcPDPtr(inpart.first->CC()) : inpart.first;
perturbativeVertex_->setCoupling(sqr(inpart.second), outa.first,
in, outb.first);
vector<Complex> left = perturbativeVertex_-> left();
vector<Complex> right = perturbativeVertex_->right();
Complex A1 = 0.5*(left [0]+right[0])*perturbativeVertex_-> norm();
Complex B1 = 0.5*(right[0]- left[0])*perturbativeVertex_-> norm();
complex<InvEnergy> A2 = 0.5*(left [1]+right[1])*perturbativeVertex_-> norm()*UnitRemoval::InvE;
complex<InvEnergy> B2 = 0.5*(right[1]- left[1])*perturbativeVertex_-> norm()*UnitRemoval::InvE;
complex<InvEnergy2> A3 = 0.5*(left [2]+right[2])*perturbativeVertex_-> norm()*UnitRemoval::InvE2;
complex<InvEnergy2> B3 = 0.5*(right[2]- left[2])*perturbativeVertex_-> norm()*UnitRemoval::InvE2;
complex<Energy> h1(-2.*Qp*A1),h2(2.*Qm*B1);
complex<Energy> h3(-2./r3*Qp*(A1-Qm*Qm/m2*A2));
complex<Energy> h4( 2./r3*Qm*(B1-Qp*Qp/m2*B2));
complex<Energy> h5(ZERO),h6(ZERO);
if(outb.second>ZERO) {
h5 = -2.*r2/r3/m2/m3*Qp*(0.5*(m12-m22-m32)*A1+0.5*Qm*Qm*(m1+m2)*A2
+m12*pcm*pcm*A3);
h6 = 2.*r2/r3/m2/m3*Qm*(0.5*(m12-m22-m32)*B1-0.5*Qp*Qp*(m1-m2)*B2
+m12*pcm*pcm*B3);
}
double me2 = 0.25*real(h1*conj(h1)+h2*conj(h2)+h3*conj(h3)+
h4*conj(h4)+h5*conj(h5)+h6*conj(h6))/sqr(inpart.second);
Energy output = me2*pcm/8./Constants::pi;
// colour factor
output *= colourFactor(inpart.first,outa.first,outb.first);
return output;
}
else {
return GeneralTwoBodyDecayer::partialWidth(inpart,outa,outb);
}
}
ClassDescription<FRVDecayer> FRVDecayer::initFRVDecayer;
// Definition of the static class description member.
void FRVDecayer::Init() {
static ClassDocumentation<FRVDecayer> documentation
("The FRVDecayer class handles the decay of a fermion to "
"a spin-3/2 particle and a vector boson.");
}
diff --git a/Decay/General/FRVDecayer.h b/Decay/General/FRVDecayer.h
--- a/Decay/General/FRVDecayer.h
+++ b/Decay/General/FRVDecayer.h
@@ -1,208 +1,208 @@
// -*- C++ -*-
//
// FRVDecayer.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_FRVDecayer_H
#define HERWIG_FRVDecayer_H
//
// This is the declaration of the FRVDecayer class.
//
#include "GeneralTwoBodyDecayer.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Helicity/Vertex/Vector/RFVVertex.h"
namespace Herwig {
using namespace ThePEG;
using Helicity::RFVVertexPtr;
/** \ingroup Decay
* The FRVDecayer class implements the decay of a fermion
* to a spin-3/2 fermion and a vector in a general model. It holds an RFVVertex
* pointer that must be typecast from the VertexBase pointer held in
* GeneralTwoBodyDecayer. It implents the virtual functions me2() and
* partialWidth().
*
* @see GeneralTwoBodyDecayer
*/
class FRVDecayer: public GeneralTwoBodyDecayer {
public:
/**
* The default constructor.
*/
- FRVDecayer();
+ FRVDecayer() {}
public:
/** @name Virtual functions required by the Decayer class. */
//@{
/**
* Return the matrix element squared for a given mode and phase-space channel.
* @param ichan The channel we are calculating the matrix element for.
* @param part The decaying Particle.
* @param decay The particles produced in the decay.
* @param meopt Option for the matrix element
* @return The matrix element squared for the phase-space configuration.
*/
virtual double me2(const int ichan, const Particle & part,
const ParticleVector & decay, MEOption meopt) const;
/**
* Function to return partial Width
* @param inpart The decaying particle.
* @param outa One of the decay products.
* @param outb The other decay product.
*/
virtual Energy partialWidth(PMPair inpart, PMPair outa,
PMPair outb) const;
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
virtual IBPtr fullclone() const;
//@}
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();
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<FRVDecayer> initFRVDecayer;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
FRVDecayer & operator=(const FRVDecayer &);
private:
/**
* Abstract pointer to AbstractFRVVertex
*/
AbstractRFVVertexPtr abstractVertex_;
/**
* Pointer to the perturbative vertex
*/
RFVVertexPtr perturbativeVertex_;
/**
* Spin density matrix
*/
mutable RhoDMatrix rho_;
/**
* Spinor wavefunction
*/
mutable vector<SpinorWaveFunction> wave_ ;
/**
* Barred spinor wavefunction
*/
mutable vector<SpinorBarWaveFunction> wavebar_;
/**
* RS Spinor wavefunction
*/
mutable vector<RSSpinorWaveFunction> RSwave_ ;
/**
* Barred RS spinor wavefunction
*/
mutable vector<RSSpinorBarWaveFunction> RSwavebar_;
/**
* Polarization vectors
*/
mutable vector<VectorWaveFunction> vector_;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of FRVDecayer. */
template <>
struct BaseClassTrait<Herwig::FRVDecayer,1> {
/** Typedef of the first base class of FRVDecayer. */
typedef Herwig::GeneralTwoBodyDecayer NthBase;
};
/** This template specialization informs ThePEG about the name of
* the FRVDecayer class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::FRVDecayer>
: public ClassTraitsBase<Herwig::FRVDecayer> {
/** Return a platform-independent class name */
static string className() { return "Herwig::FRVDecayer"; }
};
/** @endcond */
}
#endif /* HERWIG_FRVDecayer_H */
diff --git a/Decay/General/FtoFFFDecayer.cc b/Decay/General/FtoFFFDecayer.cc
--- a/Decay/General/FtoFFFDecayer.cc
+++ b/Decay/General/FtoFFFDecayer.cc
@@ -1,303 +1,304 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the FtoFFFDecayer class.
//
#include "FtoFFFDecayer.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "Herwig++/Decay/DecayPhaseSpaceMode.h"
#include "Herwig++/PDT/ThreeBodyAllOnCalculator.h"
#include <numeric>
using namespace Herwig;
IBPtr FtoFFFDecayer::clone() const {
return new_ptr(*this);
}
IBPtr FtoFFFDecayer::fullclone() const {
return new_ptr(*this);
}
void FtoFFFDecayer::persistentOutput(PersistentOStream & os) const {
os << _sca << _vec << _ten;
}
void FtoFFFDecayer::persistentInput(PersistentIStream & is, int) {
is >> _sca >> _vec >> _ten;
}
ClassDescription<FtoFFFDecayer> FtoFFFDecayer::initFtoFFFDecayer;
// Definition of the static class description member.
void FtoFFFDecayer::Init() {
static ClassDocumentation<FtoFFFDecayer> documentation
("The FtoFFFDecayer class implements the general decay of a fermion to "
"three fermions.");
}
void FtoFFFDecayer::doinit() {
GeneralThreeBodyDecayer::doinit();
unsigned int ndiags = getProcessInfo().size();
_sca.resize(ndiags);
_vec.resize(ndiags);
_ten.resize(ndiags);
for(unsigned int ix = 0;ix < ndiags; ++ix) {
TBDiagram current = getProcessInfo()[ix];
tcPDPtr offshell = current.intermediate;
if( offshell->CC() ) offshell = offshell->CC();
if(offshell->iSpin() == PDT::Spin0) {
AbstractFFSVertexPtr vert1 = dynamic_ptr_cast<AbstractFFSVertexPtr>
(current.vertices.first);
AbstractFFSVertexPtr vert2 = dynamic_ptr_cast<AbstractFFSVertexPtr>
(current.vertices.second);
if(!vert1||!vert2) throw Exception()
<< "Invalid vertices for a scalar diagram in FtoFFFDecayer::doinit()"
<< Exception::runerror;
_sca[ix] = make_pair(vert1, vert2);
}
else if(offshell->iSpin() == PDT::Spin1) {
AbstractFFVVertexPtr vert1 = dynamic_ptr_cast<AbstractFFVVertexPtr>
(current.vertices.first);
AbstractFFVVertexPtr vert2 = dynamic_ptr_cast<AbstractFFVVertexPtr>
(current.vertices.second);
if(!vert1||!vert2) throw Exception()
<< "Invalid vertices for a vector diagram in FtoFFFDecayer::doinit()"
<< Exception::runerror;
_vec[ix] = make_pair(vert1, vert2);
}
else if(offshell->iSpin() == PDT::Spin2) {
AbstractFFTVertexPtr vert1 = dynamic_ptr_cast<AbstractFFTVertexPtr>
(current.vertices.first);
AbstractFFTVertexPtr vert2 = dynamic_ptr_cast<AbstractFFTVertexPtr>
(current.vertices.second);
if(!vert1||!vert2) throw Exception()
<< "Invalid vertices for a tensor diagram in FtoFFFDecayer::doinit()"
<< Exception::runerror;
_ten[ix] = make_pair(vert1, vert2);
}
}
}
double FtoFFFDecayer::me2(const int ichan, const Particle & inpart,
const ParticleVector & decay,
MEOption meopt) const {
// particle or CC of particle
bool cc = (*getProcessInfo().begin()).incoming != inpart.id();
// special handling or first/last call
const vector<vector<double> > cfactors(getColourFactors());
const vector<vector<double> > nfactors(getLargeNcColourFactors());
const size_t ncf(numberOfFlows());
Energy2 scale(sqr(inpart.mass()));
if(meopt==Initialize) {
SpinorWaveFunction::
calculateWaveFunctions(_inwave.first,_rho,const_ptr_cast<tPPtr>(&inpart),
Helicity::incoming);
_inwave.second.resize(2);
if(_inwave.first[0].wave().Type() == u_spinortype) {
for(unsigned int ix = 0; ix < 2; ++ix) {
_inwave.second[ix] = _inwave.first[ix].bar();
_inwave.second[ix].conjugate();
}
}
else {
for(unsigned int ix = 0; ix < 2; ++ix) {
_inwave.second[ix] = _inwave.first[ix].bar();
_inwave.first[ix].conjugate();
}
}
}
// setup spin info when needed
if(meopt==Terminate) {
// for the decaying particle
if(inpart.id()<0)
SpinorWaveFunction::constructSpinInfo(_inwave.first,
const_ptr_cast<tPPtr>(&inpart),
Helicity::incoming,true);
else
SpinorBarWaveFunction::constructSpinInfo(_inwave.second,
const_ptr_cast<tPPtr>(&inpart),
Helicity::incoming,true);
// outgoing particles
for(unsigned int ix = 0; ix < 3; ++ix) {
SpinorWaveFunction::
constructSpinInfo(_outwave[ix].first,decay[ix],Helicity::outgoing,true);
}
}
// outgoing particles
for(unsigned int ix = 0; ix < 3; ++ix) {
SpinorWaveFunction::
calculateWaveFunctions(_outwave[ix].first,decay[ix],Helicity::outgoing);
_outwave[ix].second.resize(2);
if(_outwave[ix].first[0].wave().Type() == u_spinortype) {
for(unsigned int iy = 0; iy < 2; ++iy) {
_outwave[ix].second[iy] = _outwave[ix].first[iy].bar();
_outwave[ix].first[iy].conjugate();
}
}
else {
for(unsigned int iy = 0; iy < 2; ++iy) {
_outwave[ix].second[iy] = _outwave[ix].first[iy].bar();
_outwave[ix].second[iy].conjugate();
}
}
}
bool ferm = inpart.id()>0;
vector<Complex> flows(ncf, Complex(0.)),largeflows(ncf, Complex(0.));
static const unsigned int out2[3]={1,0,0},out3[3]={2,2,1};
vector<DecayMatrixElement> mes(ncf,DecayMatrixElement(PDT::Spin1Half,PDT::Spin1Half,
PDT::Spin1Half,PDT::Spin1Half));
vector<DecayMatrixElement> mel(ncf,DecayMatrixElement(PDT::Spin1Half,PDT::Spin1Half,
PDT::Spin1Half,PDT::Spin1Half));
unsigned int ihel[4];
for(ihel[0] = 0; ihel[0] < 2; ++ihel[0]) {
for(ihel[1] = 0; ihel[1] < 2; ++ihel[1]) {
for(ihel[2] = 0; ihel[2] < 2; ++ihel[2]) {
for(ihel[3] = 0; ihel[3] < 2; ++ihel[3]) {
flows = vector<Complex>(ncf, Complex(0.));
largeflows = vector<Complex>(ncf, Complex(0.));
unsigned int idiag=0;
for(vector<TBDiagram>::const_iterator dit=getProcessInfo().begin();
dit!=getProcessInfo().end();++dit) {
if(ichan>=0&&diagramMap()[ichan]!=idiag) {
++idiag;
continue;
}
// the sign from normal ordering
double sign = ferm ? 1. : -1;
// outgoing wavefunction and NO sign
if (dit->channelType==TBDiagram::channel23) sign *= -1.;
else if(dit->channelType==TBDiagram::channel13) sign *= 1.;
else if(dit->channelType==TBDiagram::channel12) sign *= -1.;
else throw Exception()
<< "Unknown diagram type in FtoFFFDecayer::me2()" << Exception::runerror;
// wavefunctions
SpinorWaveFunction w0,w3;
SpinorBarWaveFunction w1,w2;
// incoming wavefunction
if(ferm) {
w0 = _inwave.first [ihel[0]];
w1 = _outwave[dit->channelType].second[ihel[dit->channelType+1]];
}
else {
w0 = _outwave[dit->channelType].first [ihel[dit->channelType+1]];
w1 = _inwave.second[ihel[0]];
}
if(decay[out2[dit->channelType]]->id()<0&&
decay[out3[dit->channelType]]->id()>0) {
w2 = _outwave[out3[dit->channelType]].second[ihel[out3[dit->channelType]+1]];
w3 = _outwave[out2[dit->channelType]].first [ihel[out2[dit->channelType]+1]];
sign *= -1.;
}
else {
w2 = _outwave[out2[dit->channelType]].second[ihel[out2[dit->channelType]+1]];
w3 = _outwave[out3[dit->channelType]].first [ihel[out3[dit->channelType]+1]];
}
tcPDPtr offshell = dit->intermediate;
if(cc&&offshell->CC()) offshell=offshell->CC();
Complex diag(0.);
// intermediate scalar
if (offshell->iSpin() == PDT::Spin0) {
ScalarWaveFunction inters = _sca[idiag].first->
evaluate(scale, widthOption(), offshell, w0, w1);
diag = _sca[idiag].second->evaluate(scale,w3,w2,inters);
}
// intermediate vector
else if(offshell->iSpin() == PDT::Spin1) {
VectorWaveFunction interv = _vec[idiag].first->
evaluate(scale, widthOption(), offshell, w0, w1);
diag = -_vec[idiag].second->evaluate(scale,w3,w2,interv);
}
// intermediate tensor
else if(offshell->iSpin() == PDT::Spin2) {
TensorWaveFunction intert = _ten[idiag].first->
evaluate(scale, widthOption(), offshell, w0, w1);
diag = _ten[idiag].second->evaluate(scale,w3,w2,intert);
}
// unknown
else throw Exception()
<< "Unknown intermediate in FtoFFFDecayer::me2()"
<< Exception::runerror;
// apply NO sign
diag *= sign;
// matrix element for the different colour flows
if(ichan<0) {
for(unsigned iy = 0; iy < dit->colourFlow.size(); ++iy) {
flows[dit->colourFlow[iy].first - 1] +=
dit->colourFlow[iy].second * diag;
}
for(unsigned iy = 0; iy < dit->largeNcColourFlow.size(); ++iy) {
largeflows[dit->largeNcColourFlow[iy].first - 1] +=
dit->largeNcColourFlow[iy].second * diag;
}
}
else {
for(unsigned iy = 0; iy < dit->colourFlow.size(); ++iy) {
if(dit->colourFlow[iy].first - 1!=colourFlow()) continue;
flows[dit->colourFlow[iy].first - 1] +=
dit->colourFlow[iy].second * diag;
}
for(unsigned iy = 0; iy < dit->largeNcColourFlow.size(); ++iy) {
if(dit->colourFlow[iy].first - 1!=colourFlow()) continue;
largeflows[dit->largeNcColourFlow[iy].first - 1] +=
dit->largeNcColourFlow[iy].second * diag;
}
}
++idiag;
}
// now add the flows to the me2 with appropriate colour factors
for(unsigned int ix = 0; ix < ncf; ++ix) {
mes[ix](ihel[0],ihel[1],ihel[2],ihel[3]) = flows[ix];
mel[ix](ihel[0],ihel[1],ihel[2],ihel[3]) = largeflows[ix];
}
}
}
}
}
double me2(0.);
if(ichan<0) {
vector<double> pflows(ncf,0.);
for(unsigned int ix = 0; ix < ncf; ++ix) {
for(unsigned int iy = 0; iy < ncf; ++ iy) {
double con = cfactors[ix][iy]*(mes[ix].contract(mes[iy],_rho)).real();
me2 += con;
if(ix==iy) {
con = nfactors[ix][iy]*(mel[ix].contract(mel[iy],_rho)).real();
pflows[ix] += con;
}
}
}
double ptotal(std::accumulate(pflows.begin(),pflows.end(),0.));
ptotal *=UseRandom::rnd();
for(unsigned int ix=0;ix<pflows.size();++ix) {
if(ptotal<=pflows[ix]) {
colourFlow(ix);
ME(mes[ix]);
break;
}
ptotal-=pflows[ix];
}
}
else {
unsigned int iflow = colourFlow();
me2 = nfactors[iflow][iflow]*(mel[iflow].contract(mel[iflow],_rho)).real();
}
// return the matrix element squared
return me2;
}
WidthCalculatorBasePtr FtoFFFDecayer::
threeBodyMEIntegrator(const DecayMode & ) const {
vector<int> intype;
vector<Energy> inmass,inwidth;
vector<double> inpow,inweights;
constructIntegratorChannels(intype,inmass,inwidth,inpow,inweights);
return new_ptr(ThreeBodyAllOnCalculator<FtoFFFDecayer>
(inweights,intype,inmass,inwidth,inpow,*this,0,
- outgoing()[0]->mass(),outgoing()[1]->mass(),outgoing()[2]->mass()));
+ outgoing()[0]->mass(),outgoing()[1]->mass(),outgoing()[2]->mass(),
+ relativeError()));
}
diff --git a/Decay/General/FtoFVVDecayer.cc b/Decay/General/FtoFVVDecayer.cc
--- a/Decay/General/FtoFVVDecayer.cc
+++ b/Decay/General/FtoFVVDecayer.cc
@@ -1,390 +1,390 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the FtoFVVDecayer class.
//
#include "FtoFVVDecayer.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "Herwig++/Decay/DecayPhaseSpaceMode.h"
#include "Herwig++/PDT/ThreeBodyAllOnCalculator.h"
#include <numeric>
using namespace Herwig;
IBPtr FtoFVVDecayer::clone() const {
return new_ptr(*this);
}
IBPtr FtoFVVDecayer::fullclone() const {
return new_ptr(*this);
}
void FtoFVVDecayer::persistentOutput(PersistentOStream & os) const {
os << _sca << _fer << _vec << _ten;
}
void FtoFVVDecayer::persistentInput(PersistentIStream & is, int) {
is >> _sca >> _fer >> _vec >> _ten;
}
ClassDescription<FtoFVVDecayer> FtoFVVDecayer::initFtoFVVDecayer;
// Definition of the static class description member.
void FtoFVVDecayer::Init() {
static ClassDocumentation<FtoFVVDecayer> documentation
("The FtoFVVDecayer class implements the general decay of a fermion to "
"a fermion and a pair of vectors.");
}
void FtoFVVDecayer::doinit() {
GeneralThreeBodyDecayer::doinit();
unsigned int ndiags = getProcessInfo().size();
_sca.resize(ndiags);
_fer.resize(ndiags);
_vec.resize(ndiags);
_ten.resize(ndiags);
for(unsigned int ix = 0;ix < ndiags; ++ix) {
TBDiagram current = getProcessInfo()[ix];
tcPDPtr offshell = current.intermediate;
if(offshell->iSpin() == PDT::Spin0) {
AbstractFFSVertexPtr vert1 = dynamic_ptr_cast<AbstractFFSVertexPtr>
(current.vertices.first);
AbstractVVSVertexPtr vert2 = dynamic_ptr_cast<AbstractVVSVertexPtr>
(current.vertices.second);
if(!vert1||!vert2) throw Exception()
<< "Invalid vertices for a scalar diagram in FtoFVVDecayer::doinit()"
<< Exception::runerror;
_sca[ix] = make_pair(vert1, vert2);
}
else if(offshell->iSpin() == PDT::Spin1Half) {
AbstractFFVVertexPtr vert1 = dynamic_ptr_cast<AbstractFFVVertexPtr>
(current.vertices.first);
AbstractFFVVertexPtr vert2 = dynamic_ptr_cast<AbstractFFVVertexPtr>
(current.vertices.second);
if(!vert1||!vert2) throw Exception()
<< "Invalid vertices for a scalar diagram in FtoFVVDecayer::doinit()"
<< Exception::runerror;
_fer[ix] = make_pair(vert1, vert2);
}
else if(offshell->iSpin() == PDT::Spin1) {
AbstractFFVVertexPtr vert1 = dynamic_ptr_cast<AbstractFFVVertexPtr>
(current.vertices.first);
AbstractVVVVertexPtr vert2 = dynamic_ptr_cast<AbstractVVVVertexPtr>
(current.vertices.second);
if(!vert1||!vert2) throw Exception()
<< "Invalid vertices for a vector diagram in FtoFVVDecayer::doinit()"
<< Exception::runerror;
_vec[ix] = make_pair(vert1, vert2);
}
else if(offshell->iSpin() == PDT::Spin2) {
AbstractFFTVertexPtr vert1 = dynamic_ptr_cast<AbstractFFTVertexPtr>
(current.vertices.first);
AbstractVVTVertexPtr vert2 = dynamic_ptr_cast<AbstractVVTVertexPtr>
(current.vertices.second);
if(!vert1||!vert2) throw Exception()
<< "Invalid vertices for a tensor diagram in FtoFVVDecayer::doinit()"
<< Exception::runerror;
_ten[ix] = make_pair(vert1, vert2);
}
}
}
double FtoFVVDecayer::me2(const int ichan, const Particle & inpart,
const ParticleVector & decay,
MEOption meopt) const {
// particle or CC of particle
bool cc = (*getProcessInfo().begin()).incoming != inpart.id();
// special handling or first/last call
//Set up wave-functions
bool ferm( inpart.id() > 0 );
if(meopt==Initialize) {
if( ferm ) {
SpinorWaveFunction::
calculateWaveFunctions(_fwave,_rho,const_ptr_cast<tPPtr>(&inpart),
Helicity::incoming);
if( _fwave[0].wave().Type() != u_spinortype )
_fwave[0].conjugate();
if( _fwave[1].wave().Type() != u_spinortype )
_fwave[1].conjugate();
}
else {
SpinorBarWaveFunction::
calculateWaveFunctions(_fbwave, _rho, const_ptr_cast<tPPtr>(&inpart),
Helicity::incoming);
if( _fbwave[0].wave().Type() != v_spinortype )
_fbwave[0].conjugate();
if( _fbwave[1].wave().Type() != v_spinortype )
_fbwave[1].conjugate();
}
}
// setup spin info when needed
if(meopt==Terminate) {
// for the decaying particle
if(ferm)
SpinorWaveFunction::constructSpinInfo(_fwave,
const_ptr_cast<tPPtr>(&inpart),
Helicity::incoming,true);
else
SpinorBarWaveFunction::constructSpinInfo(_fbwave,
const_ptr_cast<tPPtr>(&inpart),
Helicity::incoming,true);
int ivec(-1);
// outgoing particles
for(int ix = 0; ix < 3; ++ix) {
tPPtr p = decay[ix];
if( p->dataPtr()->iSpin() == PDT::Spin1Half ) {
if( ferm ) {
SpinorBarWaveFunction::
constructSpinInfo(_fbwave, p, Helicity::outgoing,true);
}
else {
SpinorWaveFunction::
constructSpinInfo(_fwave , p, Helicity::outgoing,true);
}
}
else if( p->dataPtr()->iSpin() == PDT::Spin1 ) {
if( ivec < 0 ) {
ivec = ix;
VectorWaveFunction::
constructSpinInfo(_vwave.first , p, Helicity::outgoing, true, false);
}
else {
VectorWaveFunction::
constructSpinInfo(_vwave.second, p, Helicity::outgoing, true, false);
}
}
}
return 0.;
}
// outgoing, keep track of fermion and first occurrence of vector positions
int isp(-1), ivec(-1);
// outgoing particles
for(int ix = 0; ix < 3; ++ix) {
tPPtr p = decay[ix];
if( p->dataPtr()->iSpin() == PDT::Spin1Half ) {
isp = ix;
if( ferm ) {
SpinorBarWaveFunction::
calculateWaveFunctions(_fbwave, p, Helicity::outgoing);
if( _fbwave[0].wave().Type() != u_spinortype )
_fbwave[0].conjugate();
if( _fbwave[1].wave().Type() != u_spinortype )
_fbwave[1].conjugate();
}
else {
SpinorWaveFunction::
calculateWaveFunctions(_fwave, p, Helicity::outgoing);
if( _fwave[0].wave().Type() != v_spinortype )
_fwave[0].conjugate();
if( _fwave[1].wave().Type() != v_spinortype )
_fwave[1].conjugate();
}
}
else if( p->dataPtr()->iSpin() == PDT::Spin1 ) {
if( ivec < 0 ) {
ivec = ix;
VectorWaveFunction::
calculateWaveFunctions(_vwave.first , p, Helicity::outgoing, false);
}
else {
VectorWaveFunction::
calculateWaveFunctions(_vwave.second, p, Helicity::outgoing, false);
}
}
}
assert(isp >= 0 && ivec >= 0);
Energy2 scale(sqr(inpart.mass()));
const vector<vector<double> > cfactors(getColourFactors());
const vector<vector<double> > nfactors(getLargeNcColourFactors());
const size_t ncf(numberOfFlows());
vector<Complex> flows(ncf, Complex(0.)), largeflows(ncf, Complex(0.));
vector<DecayMatrixElement>
mes(ncf,DecayMatrixElement(PDT::Spin1Half,
(isp == 0) ? PDT::Spin1Half : PDT::Spin1,
(isp == 1) ? PDT::Spin1Half : PDT::Spin1,
(isp == 2) ? PDT::Spin1Half : PDT::Spin1));
vector<DecayMatrixElement>
mel(ncf,DecayMatrixElement(PDT::Spin1Half,
(isp == 0) ? PDT::Spin1Half : PDT::Spin1,
(isp == 1) ? PDT::Spin1Half : PDT::Spin1,
(isp == 2) ? PDT::Spin1Half : PDT::Spin1));
//Helicity calculation
for( unsigned int if1 = 0; if1 < 2; ++if1 ) {
for( unsigned int if2 = 0; if2 < 2; ++if2 ) {
for( unsigned int iv1 = 0; iv1 < 3; ++iv1 ) {
for( unsigned int iv2 = 0; iv2 < 3; ++iv2 ) {
flows = vector<Complex>(ncf, Complex(0.));
largeflows = vector<Complex>(ncf, Complex(0.));
unsigned int idiag(0);
for(vector<TBDiagram>::const_iterator dit = getProcessInfo().begin();
dit != getProcessInfo().end(); ++dit) {
// If we are selecting a particular channel
if( ichan >= 0 && diagramMap()[ichan] != idiag ) {
++idiag;
continue;
}
tcPDPtr offshell = (*dit).intermediate;
if(cc&&offshell->CC()) offshell=offshell->CC();
Complex diag;
if( offshell->iSpin() == PDT::Spin1Half ) {
// Make sure we connect the correct particles
VectorWaveFunction vw1, vw2;
if( (*dit).channelType == TBDiagram::channel23 ) {
vw1 = _vwave.first[iv1];
vw2 = _vwave.second[iv2];
}
else if( (*dit).channelType == TBDiagram::channel12 ) {
vw1 = _vwave.second[iv2];
vw2 = _vwave.first[iv1];
}
else {
if( ivec < isp ) {
vw1 = _vwave.second[iv2];
vw2 = _vwave.first[iv1];
}
else {
vw1 = _vwave.first[iv1];
vw2 = _vwave.second[iv2];
}
}
if( ferm ) {
SpinorWaveFunction inters =
_fer[idiag].first->evaluate(scale, widthOption(), offshell,
_fwave[if1], vw1);
diag = _fer[idiag].second->evaluate(scale, inters, _fbwave[if2],
vw2);
}
else {
SpinorBarWaveFunction inters =
_fer[idiag].first->evaluate(scale, widthOption(), offshell,
_fbwave[if2], vw1);
diag = _fer[idiag].second->evaluate(scale, _fwave[if1], inters,
vw2);
}
}
else if( offshell->iSpin() == PDT::Spin0 ) {
ScalarWaveFunction inters =
_sca[idiag].first->evaluate(scale, widthOption(), offshell,
_fwave[if1], _fbwave[if2]);
diag = _sca[idiag].second->evaluate(scale, _vwave.first[iv1],
_vwave.second[iv2], inters);
}
else if( offshell->iSpin() == PDT::Spin1 ) {
VectorWaveFunction interv =
_vec[idiag].first->evaluate(scale, widthOption(), offshell,
_fwave[if1], _fbwave[if2]);
diag = _vec[idiag].second->evaluate(scale, _vwave.first[iv1],
_vwave.second[iv2], interv);
}
else if( offshell->iSpin() == PDT::Spin2 ) {
TensorWaveFunction intert =
_ten[idiag].first->evaluate(scale, widthOption(), offshell,
_fwave[if1], _fbwave[if2]);
diag = _ten[idiag].second->evaluate(scale, _vwave.first[iv1],
_vwave.second[iv2], intert);
}
else
throw Exception()
<< "Unknown intermediate in FtoFVVDecayer::me2()"
<< Exception::runerror;
//NO sign
if( !ferm ) diag *= -1;
if(ichan<0) {
for(unsigned iy = 0; iy < dit->colourFlow.size(); ++iy) {
flows[dit->colourFlow[iy].first - 1] +=
dit->colourFlow[iy].second * diag;
}
for(unsigned iy = 0; iy < dit->largeNcColourFlow.size(); ++iy) {
largeflows[dit->largeNcColourFlow[iy].first - 1] +=
dit->largeNcColourFlow[iy].second * diag;
}
}
else {
for(unsigned iy = 0; iy < dit->colourFlow.size(); ++iy) {
if(dit->colourFlow[iy].first - 1!=colourFlow()) continue;
flows[dit->colourFlow[iy].first - 1] +=
dit->colourFlow[iy].second * diag;
}
for(unsigned iy = 0; iy < dit->largeNcColourFlow.size(); ++iy) {
if(dit->colourFlow[iy].first - 1!=colourFlow()) continue;
largeflows[dit->largeNcColourFlow[iy].first - 1] +=
dit->largeNcColourFlow[iy].second * diag;
}
}
++idiag;
}// end diagram loop
// now add the flows to the me2
unsigned int h1(if1), h2(if2);
if( !ferm ) swap(h1,h2);
for(unsigned int ix = 0; ix < ncf; ++ix) {
if(isp == 0) {
mes[ix](h1, h2, iv1, iv2) = flows[ix];
mel[ix](h1, h2, iv1, iv2) = largeflows[ix];
}
else if(isp == 1) {
mes[ix](h1, iv1, h2, iv2) = flows[ix];
mel[ix](h1, iv1, h2, iv2) = largeflows[ix];
}
else if(isp == 2) {
mes[ix](h1, iv1, iv2, h2) = flows[ix];
mel[ix](h1, iv1, h2, iv2) = largeflows[ix];
}
}
}//v2
}//v1
}//f2
}//f1
//Finally, work out me2. This depends on whether we are selecting channels
//or not
double me2(0.);
if(ichan<0) {
vector<double> pflows(ncf,0.);
for(unsigned int ix = 0; ix < ncf; ++ix) {
for(unsigned int iy = 0; iy < ncf; ++ iy) {
double con = cfactors[ix][iy]*(mes[ix].contract(mes[iy],_rho)).real();
me2 += con;
if(ix==iy) {
con = nfactors[ix][iy]*(mel[ix].contract(mel[iy],_rho)).real();
pflows[ix] += con;
}
}
}
double ptotal(std::accumulate(pflows.begin(),pflows.end(),0.));
ptotal *= UseRandom::rnd();
for(unsigned int ix=0;ix<pflows.size();++ix) {
if(ptotal<=pflows[ix]) {
colourFlow(ix);
ME(mes[ix]);
break;
}
ptotal-=pflows[ix];
}
}
else {
unsigned int iflow = colourFlow();
me2 = nfactors[iflow][iflow]*(mel[iflow].contract(mel[iflow],_rho)).real();
}
// return the matrix element squared
return me2;
}
WidthCalculatorBasePtr FtoFVVDecayer::
threeBodyMEIntegrator(const DecayMode & ) const {
vector<int> intype;
vector<Energy> inmass,inwidth;
vector<double> inpow,inweights;
constructIntegratorChannels(intype,inmass,inwidth,inpow,inweights);
return new_ptr(ThreeBodyAllOnCalculator<FtoFVVDecayer>
(inweights,intype,inmass,inwidth,inpow,*this,0,
outgoing()[0]->mass(),outgoing()[1]->mass(),
- outgoing()[2]->mass()));
+ outgoing()[2]->mass(),relativeError()));
}
diff --git a/Decay/General/GeneralCurrentDecayer.cc b/Decay/General/GeneralCurrentDecayer.cc
--- a/Decay/General/GeneralCurrentDecayer.cc
+++ b/Decay/General/GeneralCurrentDecayer.cc
@@ -1,204 +1,160 @@
// -*- C++ -*-
//
// GeneralCurrentDecayer.cc is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the GeneralCurrentDecayer class.
//
#include "GeneralCurrentDecayer.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/ParVector.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace Herwig;
void GeneralCurrentDecayer::persistentOutput(PersistentOStream & os) const {
- os << _theVertex << _inpart << _outpart << _current << ounit(_maxmass,GeV)
- << _modemap << _modestart << _wgtloc
- << _wgtmax << _weights;
+ os << _theVertex << _inpart << _outpart << _currentOut
+ << _current << ounit(_maxmass,GeV)
+ << _mode << _wgtloc << _wgtmax << _weights;
}
void GeneralCurrentDecayer::persistentInput(PersistentIStream & is, int) {
- is >> _theVertex >> _inpart >> _outpart >> _current >> iunit(_maxmass,GeV)
- >> _modemap >> _modestart >> _wgtloc
- >> _wgtmax >> _weights;
+ is >> _theVertex >> _inpart >> _outpart >> _currentOut
+ >> _current >> iunit(_maxmass,GeV)
+ >> _mode >> _wgtloc >> _wgtmax >> _weights;
}
AbstractClassDescription<GeneralCurrentDecayer> GeneralCurrentDecayer::initGeneralCurrentDecayer;
// Definition of the static class description member.
void GeneralCurrentDecayer::Init() {
static ClassDocumentation<GeneralCurrentDecayer> documentation
("The GeneralCurrentDecayer class is designed to be the base class for all "
"decays using the WeakDecayCurrents");
+}
- static Reference<GeneralCurrentDecayer,Helicity::VertexBase> interfaceDecayVertex
- ("DecayVertex",
- "Pointer to decayer vertex",
- &GeneralCurrentDecayer::_theVertex, false, false, true, false);
+void GeneralCurrentDecayer::setDecayInfo(PDPtr in, PDPtr out, const vector<tPDPtr> & outCurrent,
+ VertexBasePtr vertex, WeakDecayCurrentPtr current,
+ Energy maxmass) {
+ _inpart = in;
+ _outpart = out;
+ _currentOut = outCurrent;
+ _theVertex = vertex;
+ _current = current;
+ _maxmass = maxmass;
+}
- static ParVector<GeneralCurrentDecayer,int> interfaceIncomingPart
- ("Incoming",
- "PDG Codes for incoming particles",
- &GeneralCurrentDecayer::_inpart, 0, -1, 0, 0,
- false, false, false);
- static ParVector<GeneralCurrentDecayer,int> interfaceOutgoingPart
- ("Outgoing",
- "PDG Codes for the outgoing particles",
- &GeneralCurrentDecayer::_outpart, 0, -1, 0, 0,
- false, false, false);
-
- static Reference<GeneralCurrentDecayer,WeakDecayCurrent> interfaceCurrent
- ("Current",
- "The weak current for the decay",
- &GeneralCurrentDecayer::_current, false, false, true, false, false);
-
- static Parameter<GeneralCurrentDecayer,Energy> interfaceMaximumMass
- ("MaximumMass",
- "The maximum mass difference for the decay",
- &GeneralCurrentDecayer::_maxmass, GeV, 5.0*GeV, 1.0*GeV, 10.0*GeV,
- false, false, Interface::limited);
-}
int GeneralCurrentDecayer::modeNumber(bool & cc, tcPDPtr parent,
const tPDVector & children) const {
vector<long> id;
id.push_back(parent->id());
for(unsigned int ix=0;ix<children.size();++ix) id.push_back(children[ix]->id());
return modeNumber(cc,id);
}
void GeneralCurrentDecayer::doinitrun() {
_current->initrun();
DecayIntegrator::doinitrun();
}
void GeneralCurrentDecayer::doinit() {
DecayIntegrator::doinit();
// make sure the current got initialised
_current->init();
- _modemap.clear();
- _modestart.clear();
- // extract the possible particles for the modes
- vector<long> particles;
- for(unsigned int ix=0;ix<3;++ix) {
- vector<long> temp = _theVertex->search(ix,ParticleID::Wplus);
- particles.insert(particles.end(),temp.begin(),temp.end());
- }
- _inpart.clear();
- _outpart.clear();
- while(!particles.empty()) {
- vector<tPDPtr> part;
- for(unsigned int ix=0;ix<3;++ix) {
- if(abs(particles.back())!=ParticleID::Wplus)
- part.push_back(getParticleData(particles.back()));
- particles.pop_back();
- }
- if(part[0]->mass()<part[1]->mass()) swap(part[0],part[1]);
- if(part[0]->CC()) part[0]=part[0]->CC();
- if(part[0]->mass()-part[1]->mass()>_maxmass) continue;
- // set up the phase-space channels
- DecayPhaseSpaceModePtr mode;
- DecayPhaseSpaceChannelPtr channel;
- tPDVector extpart,ptemp;
- extpart.push_back(part[0]);
- extpart.push_back(part[1]);
- Energy mdiff(part[0]->mass()-part[1]->mass());
- double maxweight;
- vector<double> channelwgts;
- int iq(0),ia(0);
- unsigned int ix,iy;
- bool done;
- vector<double>::iterator start,end;
- _modestart.push_back(_modemap.size());
- _inpart.push_back(part[0]->id());
- _outpart.push_back(part[1]->id());
- for(ix=0;ix<_current->numberOfModes();++ix) {
- // get the external particles for this mode
- extpart.resize(2);
- ptemp=_current->particles(part[0]->iCharge()-part[1]->iCharge(),ix,iq,ia);
- for(iy=0;iy<ptemp.size();++iy){extpart.push_back(ptemp[iy]);}
- // create the mode
- mode=new_ptr(DecayPhaseSpaceMode(extpart,this));
- // create the first piece of the channel
- channel = new_ptr(DecayPhaseSpaceChannel(mode));
- channel->addIntermediate(extpart[0],0,0.0,-1,1);
- done=_current->createMode(part[0]->iCharge()-part[1]->iCharge(),
- ix,mode,2,1,channel,mdiff);
- if(done) {
- // the maximum weight and the channel weights
- // the maximum
- if(_wgtmax.size()>numberModes()) maxweight=_wgtmax[numberModes()];
- else maxweight=0.;
- // the weights for the channel
- if(_wgtloc.size()>numberModes()&&
- _wgtloc[numberModes()]+mode->numberChannels()<=_weights.size()) {
- start=_weights.begin()+_wgtloc[numberModes()];
- end = start+mode->numberChannels();
- channelwgts=vector<double>(start,end);
+ // set up the phase-space channels
+ DecayPhaseSpaceModePtr mode;
+ DecayPhaseSpaceChannelPtr channel;
+ tPDVector extpart;
+ extpart.push_back(_inpart);
+ extpart.push_back(_outpart);
+ Energy mdiff(_inpart->mass()-_outpart->mass());
+ vector<double> channelwgts;
+ int iq(0),ia(0);
+ bool done;
+ vector<double>::iterator start,end;
+ for(unsigned int ix=0;ix<_current->numberOfModes();++ix) {
+ // get the external particles for this mode
+ extpart.resize(2);
+ tPDVector ptemp=_current->particles(_inpart->iCharge()-_outpart->iCharge(),ix,iq,ia);
+ // check this is the right mode
+ if(ptemp.size()!=_currentOut.size()) continue;
+ vector<bool> matched(ptemp.size(),false);
+ bool match = true;
+ for(unsigned int iy=0;iy<_currentOut.size();++iy) {
+ bool found = false;
+ for(unsigned int iz=0;iz<ptemp.size();++iz) {
+ if(!matched[iz]&&ptemp[iz]==_currentOut[iy]) {
+ found = true;
+ matched[iz] = true;
+ break;
}
- else {
- channelwgts.resize(mode->numberChannels(),1./(mode->numberChannels()));
- }
- _modemap.push_back(ix);
- // special for the two body modes
- if(extpart.size()==3) {
- channelwgts.clear();
- mode=new_ptr(DecayPhaseSpaceMode(extpart,this));
- }
- addMode(mode,maxweight,channelwgts);
+ }
+ if(!found) {
+ match = false;
+ break;
}
}
+ if(!match) continue;
+ for(unsigned int iy=0;iy<ptemp.size();++iy)
+ extpart.push_back(ptemp[iy]);
+ // create the mode
+ mode=new_ptr(DecayPhaseSpaceMode(extpart,this));
+ // create the first piece of the channel
+ channel = new_ptr(DecayPhaseSpaceChannel(mode));
+ channel->addIntermediate(extpart[0],0,0.0,-1,1);
+ done=_current->createMode(_inpart->iCharge()-_outpart->iCharge(),
+ ix,mode,2,1,channel,mdiff);
+ if(done) {
+ // the maximum weight and the channel weights
+ // the weights for the channel
+ if(_weights.empty()) {
+ _weights.resize(mode->numberChannels(),1./(mode->numberChannels()));
+ }
+ _mode = ix;
+ // special for the two body modes
+ if(extpart.size()==3) {
+ _weights.clear();
+ mode=new_ptr(DecayPhaseSpaceMode(extpart,this));
+ }
+ addMode(mode,_wgtmax,_weights);
+ }
+ break;
}
}
int GeneralCurrentDecayer::modeNumber(bool & cc, vector<long> id) const {
// incoming particle
int idtemp[2];
tPDPtr p0=getParticleData(id[0]);
idtemp[0] = p0->CC() ? -id[0] : id[0];
- // loop over possible particles
- for(unsigned int ipart=0;ipart<_inpart.size();++ipart) {
- if(id [0]==_inpart[ipart]) {
- cc=false;
- }
- else if(idtemp[0]==_inpart[ipart]) {
- cc=true;
- }
- else
- continue;
- tPDPtr p1 = getParticleData(_outpart[ipart]);
- if(cc) p1 = p1->CC() ? p1->CC() : p1;
- // if this in the particles
- vector<long>::iterator iloc = std::find(++id.begin(), id.end(), p1->id());
- if(idtemp[0]==id[0]&&iloc==id.end()) {
- iloc = std::find(++id.begin(), id.end(), p1->CC()->id());
- }
- if(iloc==id.end()) continue;
- vector<int> idother;
- for(vector<long>::iterator it=++id.begin();it!=id.end();++it) {
- if(it!=iloc) idother.push_back(*it);
- }
- unsigned int icurr=_current->decayMode(idother);
- int imode,imax;
- if(ipart+1<_modestart.size()) imax=_modestart[ipart+1];
- else imax=_modemap.size();
- for(imode=_modestart[ipart];imode<imax;++imode) {
- if(_modemap[imode]==icurr) break;
- }
- if(imode>=imax) imode=-1;
- if(imode>=0) return imode;
+ if(id [0]==_inpart->id()) cc=false;
+ else if(idtemp[0]==_inpart->id()) cc=true ;
+ else return -1;
+ tPDPtr p1 = _outpart;
+ if(cc&&p1->CC()) p1 = p1->CC();
+ // if this in the particles
+ vector<long>::iterator iloc = std::find(++id.begin(), id.end(), p1->id());
+ if(idtemp[0]==id[0]&&iloc==id.end()) {
+ iloc = std::find(++id.begin(), id.end(), p1->CC()->id());
}
- return -1;
+ if(iloc==id.end()) return -1;
+ vector<int> idother;
+ for(vector<long>::iterator it=++id.begin();it!=id.end();++it) {
+ if(it!=iloc) idother.push_back(*it);
+ }
+ unsigned int icurr=_current->decayMode(idother);
+ if(_mode==icurr) return 0;
+ else return -1;
}
diff --git a/Decay/General/GeneralCurrentDecayer.h b/Decay/General/GeneralCurrentDecayer.h
--- a/Decay/General/GeneralCurrentDecayer.h
+++ b/Decay/General/GeneralCurrentDecayer.h
@@ -1,239 +1,246 @@
// -*- C++ -*-
//
// GeneralCurrentDecayer.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_GeneralCurrentDecayer_H
#define HERWIG_GeneralCurrentDecayer_H
//
// This is the declaration of the GeneralCurrentDecayer class.
//
#include "Herwig++/Decay/DecayIntegrator.h"
#include "Herwig++/Decay/WeakCurrents/WeakDecayCurrent.h"
#include "Herwig++/Decay/DecayPhaseSpaceMode.h"
#include "ThePEG/Helicity/Vertex/VertexBase.h"
#include "GeneralCurrentDecayer.fh"
namespace Herwig {
using namespace ThePEG;
using Helicity::VertexBasePtr;
/**
* Here is the documentation of the GeneralCurrentDecayer class.
*
* @see \ref GeneralCurrentDecayerInterfaces "The interfaces"
* defined for GeneralCurrentDecayer.
*/
class GeneralCurrentDecayer: public DecayIntegrator {
public:
/**
* The default constructor.
*/
GeneralCurrentDecayer() :
- _maxmass(5.*GeV) {}
+ _maxmass(5.*GeV), _wgtmax(0.) {}
/** @name Virtual functions required by the Decayer class. */
//@{
/**
* Which of the possible decays is required
* @param cc Is this mode the charge conjugate
* @param parent The decaying particle
* @param children The decay products
*/
virtual int modeNumber(bool & cc, tcPDPtr parent,const tPDVector & children) const;
/**
* Return the matrix element squared for a given mode and phase-space channel
* @param ichan The channel we are calculating the matrix element for.
* @param part The decaying Particle.
* @param decay The particles produced in the decay.
* @param meopt Option for the calculation of the matrix element
* @return The matrix element squared for the phase-space configuration.
*/
virtual double me2(const int ichan, const Particle & part,
const ParticleVector & decay, MEOption meopt) const = 0;
/**
* Function to return partial Width
* @param inpart Pointer to incoming particle data object
* @param outa Pointer to first outgoing particle data object
* @param currout Pointer to particles in the current
*/
virtual Energy partialWidth(tPDPtr inpart, tPDPtr outa,
vector<tPDPtr> currout) = 0;
//@}
+ /**
+ * set up the decay
+ */
+ void setDecayInfo(PDPtr in, PDPtr out, const vector<tPDPtr> & outCurrent,
+ VertexBasePtr vertex, WeakDecayCurrentPtr current,
+ Energy maxmass);
+
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 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();
/**
* Initialize this object. Called in the run phase just before
* a run begins.
*/
virtual void doinitrun();
//@}
protected:
/**
* The number of the mode
* @param cc Whether of not this is the charge conjugate of the defined mode
* @param id The PDG codes of the particles
*/
int modeNumber(bool & cc, vector<long> id) const;
/**
* Access to the map between the number of the mode and the modes in
* the current
*/
- vector<unsigned int> modeMap() const { return _modemap; }
+ unsigned int mode() const { return _mode; }
/**
* Access to the weak current
*/
WeakDecayCurrentPtr weakCurrent() const { return _current; }
/**
* Get vertex pointer
* @return a pointer to the vertex
*/
VertexBasePtr getVertex() const { return _theVertex; }
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is an abstract class with persistent data.
*/
static AbstractClassDescription<GeneralCurrentDecayer> initGeneralCurrentDecayer;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
GeneralCurrentDecayer & operator=(const GeneralCurrentDecayer &);
private:
/**
* Pointer to vertex set in inheriting class
*/
VertexBasePtr _theVertex;
/**
- * PDG codes for all incoming particles
+ * Incoming particle
**/
- vector<int> _inpart;
+ PDPtr _inpart;
/**
- * PDG codes for the first outgoing particle
+ * First outgoing particle
*/
- vector<int> _outpart;
+ PDPtr _outpart;
+
+ /**
+ * Outgoing particles from the current
+ */
+ vector<tPDPtr> _currentOut;
/**
* Pointer to the current
*/
WeakDecayCurrentPtr _current;
/**
* Maximum mass difference
*/
Energy _maxmass;
/**
* mapping of the modes to the currents
*/
- vector<unsigned int> _modemap;
+ unsigned int _mode;
/**
* location of the weights
*/
- vector<int> _wgtloc;
-
- /**
- * location in the map
- */
- vector<unsigned int> _modestart;
+ int _wgtloc;
/**
* the maximum weight
*/
- vector<double> _wgtmax;
+ double _wgtmax;
/**
* The weights for the different channels
*/
vector<double> _weights;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of GeneralCurrentDecayer. */
template <>
struct BaseClassTrait<Herwig::GeneralCurrentDecayer,1> {
/** Typedef of the first base class of GeneralCurrentDecayer. */
typedef Herwig::DecayIntegrator NthBase;
};
/** This template specialization informs ThePEG about the name of
* the GeneralCurrentDecayer class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::GeneralCurrentDecayer>
: public ClassTraitsBase<Herwig::GeneralCurrentDecayer> {
/** Return a platform-independent class name */
static string className() { return "Herwig::GeneralCurrentDecayer"; }
};
/** @endcond */
}
#endif /* HERWIG_GeneralCurrentDecayer_H */
diff --git a/Decay/General/GeneralThreeBodyDecayer.cc b/Decay/General/GeneralThreeBodyDecayer.cc
--- a/Decay/General/GeneralThreeBodyDecayer.cc
+++ b/Decay/General/GeneralThreeBodyDecayer.cc
@@ -1,608 +1,660 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the GeneralThreeBodyDecayer class.
//
#include "GeneralThreeBodyDecayer.h"
#include "Herwig++/Decay/DecayPhaseSpaceMode.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "Herwig++/PDT/ThreeBodyAllOnCalculator.h"
using namespace Herwig;
/**
* A struct to order the particles in the same way as in the DecayMode's
*/
struct ParticleOrdering {
bool operator()(PDPtr p1, PDPtr p2) {
return abs(p1->id()) > abs(p2->id()) ||
( abs(p1->id()) == abs(p2->id()) && p1->id() > p2->id() ) ||
( p1->id() == p2->id() && p1->fullName() > p2->fullName() );
}
};
/**
* A set of ParticleData objects ordered as for the DecayMode's
*/
typedef multiset<PDPtr,ParticleOrdering> OrderedParticles;
void GeneralThreeBodyDecayer::persistentOutput(PersistentOStream & os) const {
os << _incoming << _outgoing << _diagrams << _diagmap << _colour << _colourLargeNC
- << _nflow << _widthopt << _reftag << _reftagcc;
+ << _nflow << _widthopt << _reftag << _reftagcc << _intOpt << _relerr;
}
void GeneralThreeBodyDecayer::persistentInput(PersistentIStream & is, int) {
is >> _incoming >> _outgoing >> _diagrams >> _diagmap >> _colour >> _colourLargeNC
- >> _nflow >> _widthopt >> _reftag >> _reftagcc;;
+ >> _nflow >> _widthopt >> _reftag >> _reftagcc >> _intOpt >> _relerr;
}
AbstractClassDescription<GeneralThreeBodyDecayer>
GeneralThreeBodyDecayer::initGeneralThreeBodyDecayer;
// Definition of the static class description member.
void GeneralThreeBodyDecayer::Init() {
static ClassDocumentation<GeneralThreeBodyDecayer> documentation
("The GeneralThreeBodyDecayer class is the base class for the implementation of"
" all three body decays based on spin structures in Herwig++.");
static Switch<GeneralThreeBodyDecayer,unsigned int> interfaceWidthOption
("WidthOption",
"Option for the treatment of the widths of the intermediates",
&GeneralThreeBodyDecayer::_widthopt, 1, false, false);
static SwitchOption interfaceWidthOptionFixed
(interfaceWidthOption,
"Fixed",
"Use fixed widths",
1);
static SwitchOption interfaceWidthOptionRunning
(interfaceWidthOption,
"Running",
"Use running widths",
2);
static SwitchOption interfaceWidthOptionZero
(interfaceWidthOption,
"Zero",
"Set the widths to zero",
3);
+ static Switch<GeneralThreeBodyDecayer,unsigned int> interfacePartialWidthIntegration
+ ("PartialWidthIntegration",
+ "Switch to control the partial width integration",
+ &GeneralThreeBodyDecayer::_intOpt, 0, false, false);
+ static SwitchOption interfacePartialWidthIntegrationAllPoles
+ (interfacePartialWidthIntegration,
+ "AllPoles",
+ "Include all potential poles",
+ 0);
+ static SwitchOption interfacePartialWidthIntegrationShallowestPole
+ (interfacePartialWidthIntegration,
+ "ShallowestPole",
+ "Only include the shallowest pole",
+ 1);
+
+ static Parameter<GeneralThreeBodyDecayer,double> interfaceRelativeError
+ ("RelativeError",
+ "The relative error for the GQ integration of the partial width",
+ &GeneralThreeBodyDecayer::_relerr, 1e-2, 1e-10, 1.,
+ false, false, Interface::limited);
+
}
ParticleVector GeneralThreeBodyDecayer::decay(const Particle & parent,
const tPDVector & children) const {
// return empty vector if products heavier than parent
Energy mout(ZERO);
for(tPDVector::const_iterator it=children.begin();
it!=children.end();++it) mout+=(**it).massMin();
if(mout>parent.mass()) return ParticleVector();
// generate the decay
bool cc;
int imode=modeNumber(cc,parent.dataPtr(),children);
// generate the kinematics
ParticleVector decay=generate(generateIntermediates(),cc,imode,parent);
// make the colour connections
colourConnections(parent, decay);
// return the answer
return decay;
}
int GeneralThreeBodyDecayer::
modeNumber(bool & cc, tcPDPtr in, const tPDVector & outin) const {
assert( !_reftag.empty() && !_reftagcc.empty() );
// check number of outgoing particles
if( outin.size() != 3 || abs(in->id()) != _incoming->id() ) return -1;
OrderedParticles testmode(outin.begin(), outin.end());
OrderedParticles::const_iterator dit = testmode.begin();
string testtag(in->name() + "->");
for( unsigned int i = 1; dit != testmode.end(); ++dit, ++i) {
testtag += (**dit).name();
if( i != 3 ) testtag += string(",");
}
if( testtag == _reftag ) {
cc = false;
return 0;
}
else if ( testtag == _reftagcc ) {
cc = true;
return 0;
}
else return -1;
}
void GeneralThreeBodyDecayer::setDecayInfo(PDPtr incoming,
vector<PDPtr> outgoing,
const vector<TBDiagram> & process,
const vector<DVector> & factors,
const vector<DVector> & Ncfactors,
const unsigned int ncf) {
// set the member variables from the info supplied
_incoming = incoming;
_outgoing = outgoing;
_diagrams = process;
_colour = factors;
_colourLargeNC = Ncfactors;
_nflow = ncf;
assert( _outgoing.size() == 3 );
// Construct reference tags for testing in modeNumber function
OrderedParticles refmode(_outgoing.begin(), _outgoing.end());
OrderedParticles::const_iterator dit = refmode.begin();
_reftag = _incoming->name() + "->";
for( unsigned int i = 1; dit != refmode.end(); ++dit, ++i) {
_reftag += (**dit).name();
if( i != 3 ) _reftag += string(",");
}
//CC-mode
refmode.clear();
_reftagcc = _incoming->CC() ? _incoming->CC()->name() :
_incoming->name();
_reftagcc += "->";
for( unsigned int i = 0; i < 3; ++i ) {
if( _outgoing[i]->CC() ) refmode.insert( _outgoing[i]->CC() );
else refmode.insert( _outgoing[i] );
}
dit = refmode.begin();
for( unsigned int i = 1; dit != refmode.end(); ++dit , ++i) {
_reftagcc += (**dit).name();
if( i != 3 ) _reftagcc += string(",");
}
}
void GeneralThreeBodyDecayer::doinit() {
DecayIntegrator::doinit();
// create the phase space integrator
tPDVector extpart(1,_incoming);
extpart.insert(extpart.end(),_outgoing.begin(),_outgoing.end());
// create the integration channels for the decay
DecayPhaseSpaceModePtr mode(new_ptr(DecayPhaseSpaceMode(extpart,this,true)));
DecayPhaseSpaceChannelPtr newchannel;
// create the phase-space channels for the integration
unsigned int nmode(0);
for(unsigned int ix=0;ix<_diagrams.size();++ix) {
if(_diagrams[ix].channelType==TBDiagram::fourPoint||
_diagrams[ix].channelType==TBDiagram::UNDEFINED) continue;
// create the new channel
newchannel=new_ptr(DecayPhaseSpaceChannel(mode));
if(_diagrams[ix].channelType==TBDiagram::channel23) {
newchannel->addIntermediate(extpart[0],0,0.0,-1,1);
newchannel->addIntermediate(_diagrams[ix].intermediate,0,0.0, 2,3);
}
else if(_diagrams[ix].channelType==TBDiagram::channel13) {
newchannel->addIntermediate(extpart[0],0,0.0,-1,2);
newchannel->addIntermediate(_diagrams[ix].intermediate,0,0.0, 1,3);
}
else if(_diagrams[ix].channelType==TBDiagram::channel12) {
newchannel->addIntermediate(extpart[0],0,0.0,-1,3);
newchannel->addIntermediate(_diagrams[ix].intermediate,0,0.0, 1,2);
}
_diagmap.push_back(ix);
mode->addChannel(newchannel);
++nmode;
}
if(nmode==0) {
string mode = extpart[0]->PDGName() + "->";
for(unsigned int ix=1;ix<extpart.size();++ix) mode += extpart[ix]->PDGName() + " ";
throw Exception() << "No decay channels in GeneralThreeBodyDecayer::"
<< "doinit() for " << mode << "\n" << Exception::runerror;
}
// add the mode
vector<double> wgt(nmode,1./double(nmode));
addMode(mode,1.,wgt);
}
double GeneralThreeBodyDecayer::
threeBodyMatrixElement(const int imode, const Energy2 q2,
const Energy2 s3, const Energy2 s2,
const Energy2 s1, const Energy m1,
const Energy m2, const Energy m3) const {
// calculate the momenta of the outgoing particles
Energy m0=sqrt(q2);
// energies
Energy eout[3] = {0.5*(q2+sqr(m1)-s1)/m0,
0.5*(q2+sqr(m2)-s2)/m0,
0.5*(q2+sqr(m3)-s3)/m0};
// magnitudes of the momenta
Energy pout[3] = {sqrt(sqr(eout[0])-sqr(m1)),
sqrt(sqr(eout[1])-sqr(m2)),
sqrt(sqr(eout[2])-sqr(m3))};
double cos2 = 0.5*(sqr(pout[0])+sqr(pout[1])-sqr(pout[2]))/pout[0]/pout[1];
double cos3 = 0.5*(sqr(pout[0])-sqr(pout[1])+sqr(pout[2]))/pout[0]/pout[2];
double sin2 = sqrt(1.-sqr(cos2)), sin3 = sqrt(1.-sqr(cos3));
Lorentz5Momentum out[3]=
{Lorentz5Momentum( ZERO , ZERO , pout[0] , eout[0] , m1),
Lorentz5Momentum( pout[1]*sin2 , ZERO , -pout[1]*cos2 , eout[1] , m2),
Lorentz5Momentum( -pout[2]*sin3 , ZERO , -pout[2]*cos3 , eout[2] , m3)};
// create the incoming
PPtr inpart=mode(imode)->externalParticles(0)->
produceParticle(Lorentz5Momentum(sqrt(q2)));
// and outgoing particles
ParticleVector decay;
for(unsigned int ix=1;ix<4;++ix)
decay.push_back(mode(imode)->externalParticles(ix)->produceParticle(out[ix-1]));
// return the matrix element
return me2(-1,*inpart,decay,Initialize);
}
double GeneralThreeBodyDecayer::brat(const DecayMode &, const Particle & p,
double oldbrat) const {
ParticleVector children = p.children();
if( children.size() != 3 || !p.data().widthGenerator() )
return oldbrat;
// partial width for this mode
Energy scale = p.mass();
Energy pwidth =
partialWidth( make_pair(p.dataPtr(), scale),
make_pair(children[0]->dataPtr(), children[0]->mass()),
make_pair(children[1]->dataPtr(), children[1]->mass()),
make_pair(children[2]->dataPtr(), children[2]->mass()) );
Energy width = p.data().widthGenerator()->width(p.data(), scale);
return pwidth/width;
}
Energy GeneralThreeBodyDecayer::partialWidth(PMPair inpart, PMPair outa,
PMPair outb, PMPair outc) const {
if(inpart.second<outa.second+outb.second+outc.second) return ZERO;
// create the object to calculate the width if it doesn't all ready exist
if(!_widthcalc) {
string tag = _incoming->name() + "->";
tag += _outgoing[0]->name() + "," + _outgoing[1]->name() + ","
+ _outgoing[2]->name() + ";";
DMPtr dm = generator()->findDecayMode(tag);
_widthcalc = threeBodyMEIntegrator(*dm);
}
return _widthcalc->partialWidth(sqr(inpart.second));
}
void GeneralThreeBodyDecayer::
colourConnections(const Particle & parent,
const ParticleVector & out) const {
// first extract the outgoing particles and intermediate
PPtr inter;
ParticleVector outgoing;
if(!generateIntermediates()) {
outgoing=out;
}
else {
// find the diagram
unsigned int idiag = diagramMap()[mode(imode())->selectedChannel()];
PPtr child;
for(unsigned int ix=0;ix<out.size();++ix) {
if(out[ix]->children().empty()) child = out[ix];
else inter = out[ix];
}
outgoing.resize(3);
switch(_diagrams[idiag].channelType) {
case TBDiagram::channel23:
outgoing[0] = child;
outgoing[1] = inter->children()[0];
outgoing[2] = inter->children()[1];
break;
case TBDiagram::channel13:
outgoing[0] = inter->children()[0];
outgoing[1] = child;
outgoing[2] = inter->children()[1];
break;
case TBDiagram::channel12:
outgoing[0] = inter->children()[0];
outgoing[1] = inter->children()[1];
outgoing[2] = child;
break;
default:
throw Exception() << "unknown diagram type in GeneralThreeBodyDecayer::"
<< "colourConnections()" << Exception::runerror;
}
}
// extract colour of the incoming and outgoing particles
PDT::Colour inColour(parent.data().iColour());
vector<PDT::Colour> outColour;
vector<int> singlet,octet,triplet,antitriplet;
for(unsigned int ix=0;ix<outgoing.size();++ix) {
outColour.push_back(outgoing[ix]->data().iColour());
switch(outColour.back()) {
case PDT::Colour0 :
singlet.push_back(ix);
break;
case PDT::Colour3 :
triplet.push_back(ix);
break;
case PDT::Colour3bar:
antitriplet.push_back(ix);
break;
case PDT::Colour8 :
octet.push_back(ix);
break;
default:
throw Exception() << "Unknown colour for particle in GeneralThreeBodyDecayer::"
<< "colourConnections()" << Exception::runerror;
}
}
// colour neutral decaying particle
if ( inColour == PDT::Colour0) {
// options are all neutral or triplet/antitriplet+ neutral
if(singlet.size()==3) return;
else if(singlet.size()==1&&triplet.size()==1&&antitriplet.size()==1) {
outgoing[triplet[0]]->antiColourNeighbour(outgoing[antitriplet[0]]);
// add intermediate if needed
if(inter&&inter->coloured()) {
if(inter->dataPtr()->iColour()==PDT::Colour3)
outgoing[triplet[0]]->colourLine()->addColoured(inter);
else if(inter->dataPtr()->iColour()==PDT::Colour3bar)
outgoing[triplet[0]]->colourLine()->addAntiColoured(inter);
}
}
else if(octet.size()==1&&triplet.size()==1&&antitriplet.size()==1) {
outgoing[ triplet[0]]->antiColourNeighbour(outgoing[octet[0]]);
outgoing[antitriplet[0]]-> colourNeighbour(outgoing[octet[0]]);
if(inter&&inter->coloured()) {
if(inter->dataPtr()->iColour()==PDT::Colour3)
outgoing[antitriplet[0]]->antiColourLine()->addColoured(inter);
else if(inter->dataPtr()->iColour()==PDT::Colour3bar)
outgoing[ triplet[0]]-> colourLine()->addAntiColoured(inter);
else if(inter->dataPtr()->iColour()==PDT::Colour8) {
outgoing[antitriplet[0]]->antiColourLine()->addAntiColoured(inter);
outgoing[ triplet[0]]-> colourLine()->addColoured(inter);
}
}
}
else {
string mode = parent.PDGName() + " -> " + out[0]->PDGName() + " "
+ out[1]->PDGName() + " " + out[2]->PDGName();
throw Exception()
<< "Unknown colour structure in GeneralThreeBodyDecayer::"
<< "colourConnections() for singlet decaying particle "
<< mode << Exception::runerror;
}
}
// colour triplet decaying particle
else if( inColour == PDT::Colour3) {
if(singlet.size()==2&&triplet.size()==1) {
outgoing[triplet[0]]->incomingColour(const_ptr_cast<tPPtr>(&parent));
if(inter&&inter->coloured())
outgoing[triplet[0]]->colourLine()->addColoured(inter);
}
else if(antitriplet.size()==1&&triplet.size()==2) {
if(colourFlow()==0) {
outgoing[triplet[0]]->incomingColour(const_ptr_cast<tPPtr>(&parent));
outgoing[antitriplet[0]]->colourNeighbour(outgoing[triplet[1]]);
if(inter&&inter->coloured()) {
switch (inter->dataPtr()->iColour()) {
case PDT::Colour8:
inter->incomingColour(const_ptr_cast<tPPtr>(&parent));
outgoing[triplet[1]]->colourLine()->addAntiColoured(inter);
break;
default:
string mode = parent.PDGName() + " -> " + out[0]->PDGName() + " "
+ out[1]->PDGName() + " " + out[2]->PDGName();
throw Exception() << "Unknown colour for intermediate in "
<< "GeneralThreeBodyDecayer::"
<< "colourConnections() for "
<< "decaying colour triplet "
<< mode << Exception::runerror;
}
}
}
else {
outgoing[triplet[1]]->incomingColour(const_ptr_cast<tPPtr>(&parent));
outgoing[antitriplet[0]]->colourNeighbour(outgoing[triplet[0]]);
if(inter&&inter->coloured()) {
switch (inter->dataPtr()->iColour()) {
case PDT::Colour8:
inter->incomingColour(const_ptr_cast<tPPtr>(&parent));
outgoing[triplet[0]]->colourLine()->addAntiColoured(inter);
break;
default:
string mode = parent.PDGName() + " -> " + out[0]->PDGName() + " "
+ out[1]->PDGName() + " " + out[2]->PDGName();
throw Exception() << "Unknown colour for intermediate in "
<< "GeneralThreeBodyDecayer::"
<< "colourConnections() for "
<< "decaying colour triplet "
<< mode << Exception::runerror;
}
}
}
}
else if (singlet.size()==1&&triplet.size()==1&&octet.size()==1) {
if(inter) {
if(inter->children()[0]->dataPtr()->iColour()==PDT::Colour8 ||
inter->children()[1]->dataPtr()->iColour()==PDT::Colour8) {
inter->incomingColour(const_ptr_cast<tPPtr>(&parent));
outgoing[octet[0]]->incomingColour(inter);
outgoing[octet[0]]->colourNeighbour(outgoing[triplet[0]]);
}
else {
outgoing[octet[0]]->incomingColour(inter);
outgoing[octet[0]]->colourNeighbour(inter);
outgoing[triplet[0]]->incomingColour(inter);
}
}
else {
outgoing[octet[0]]->incomingColour(const_ptr_cast<tPPtr>(&parent));
outgoing[octet[0]]->colourNeighbour(outgoing[triplet[0]]);
}
}
else {
string mode = parent.PDGName() + " -> " + out[0]->PDGName() + " "
+ out[1]->PDGName() + " " + out[2]->PDGName();
throw Exception()
<< "Unknown colour structure in GeneralThreeBodyDecayer::"
<< "colourConnections() for triplet decaying particle "
<< mode << Exception::runerror;
}
}
else if( inColour == PDT::Colour3bar) {
if(singlet.size()==2&&antitriplet.size()==1) {
outgoing[antitriplet[0]]->incomingAntiColour(const_ptr_cast<tPPtr>(&parent));
}
else if(antitriplet.size()==2&&triplet.size()==1) {
if(colourFlow()==0) {
outgoing[antitriplet[0]]->incomingAntiColour(const_ptr_cast<tPPtr>(&parent));
outgoing[triplet[0]]->antiColourNeighbour(outgoing[antitriplet[1]]);
if(inter&&inter->coloured()) {
switch (inter->dataPtr()->iColour()) {
case PDT::Colour8:
inter->incomingAntiColour(const_ptr_cast<tPPtr>(&parent));
outgoing[antitriplet[1]]->antiColourLine()->addAntiColoured(inter);
break;
default:
string mode = parent.PDGName() + " -> " + out[0]->PDGName() + " "
+ out[1]->PDGName() + " " + out[2]->PDGName();
throw Exception() << "Unknown colour for intermediate in"
<< " GeneralThreeBodyDecayer::"
<< "colourConnections() for "
<< "decaying colour antitriplet "
<< mode << Exception::runerror;
}
}
}
else {
outgoing[antitriplet[1]]->incomingAntiColour(const_ptr_cast<tPPtr>(&parent));
outgoing[triplet[0]]->antiColourNeighbour(outgoing[antitriplet[0]]);
if(inter&&inter->coloured()) {
switch (inter->dataPtr()->iColour()) {
case PDT::Colour8:
inter->incomingAntiColour(const_ptr_cast<tPPtr>(&parent));
outgoing[antitriplet[0]]->antiColourLine()->addAntiColoured(inter);
break;
default:
string mode = parent.PDGName() + " -> " + out[0]->PDGName() + " "
+ out[1]->PDGName() + " " + out[2]->PDGName();
throw Exception() << "Unknown colour for intermediate in "
<< "GeneralThreeBodyDecayer::"
<< "colourConnections() for "
<< "decaying colour antitriplet "
<< mode << Exception::runerror;
}
}
}
}
else if (singlet.size()==1&&antitriplet.size()==1&&octet.size()==1) {
if(inter) {
if(inter->children()[0]->dataPtr()->iColour()==PDT::Colour8 ||
inter->children()[1]->dataPtr()->iColour()==PDT::Colour8) {
inter->incomingColour(const_ptr_cast<tPPtr>(&parent));
outgoing[octet[0]]->incomingAntiColour(inter);
outgoing[octet[0]]->antiColourNeighbour(outgoing[antitriplet[0]]);
}
else {
outgoing[octet[0]]->incomingAntiColour(inter);
outgoing[octet[0]]->antiColourNeighbour(inter);
outgoing[antitriplet[0]]->incomingAntiColour(inter);
}
}
else {
outgoing[octet[0]]->incomingAntiColour(const_ptr_cast<tPPtr>(&parent));
outgoing[octet[0]]->antiColourNeighbour(outgoing[antitriplet[0]]);
}
}
else {
string mode = parent.PDGName() + " -> " + out[0]->PDGName() + " "
+ out[1]->PDGName() + " " + out[2]->PDGName();
throw Exception()
<< "Unknown colour structure in GeneralThreeBodyDecayer::"
<< "colourConnections() for anti-triplet decaying particle"
<< mode << Exception::runerror;
}
}
else if( inColour == PDT::Colour8) {
if(triplet.size()==1&&antitriplet.size()==1&&singlet.size()==1) {
outgoing[ triplet[0]]->incomingColour (const_ptr_cast<tPPtr>(&parent));
outgoing[antitriplet[0]]->incomingAntiColour(const_ptr_cast<tPPtr>(&parent));
if(inter&&inter->coloured()) {
switch (inter->dataPtr()->iColour()) {
case PDT::Colour3:
outgoing[triplet[0]]->colourLine()->addColoured(inter);
break;
case PDT::Colour3bar:
outgoing[antitriplet[0]]->antiColourLine()->addAntiColoured(inter);
break;
default:
string mode = parent.PDGName() + " -> " + out[0]->PDGName() + " "
+ out[1]->PDGName() + " " + out[2]->PDGName();
throw Exception() << "Unknown colour for intermediate"
<< " in GeneralThreeBodyDecayer::"
<< "colourConnections() for "
<< "decaying colour octet "
<< mode << Exception::runerror;
}
}
}
else {
string mode = parent.PDGName() + " -> " + out[0]->PDGName() + " "
+ out[1]->PDGName() + " " + out[2]->PDGName();
throw Exception()
<< "Unknown colour structure in GeneralThreeBodyDecayer::"
<< "colourConnections() for octet decaying particle"
<< mode << Exception::runerror;
}
}
}
void GeneralThreeBodyDecayer::
constructIntegratorChannels(vector<int> & intype, vector<Energy> & inmass,
vector<Energy> & inwidth, vector<double> & inpow,
vector<double> & inweights) const {
Energy min = incoming()->mass();
int nchannel(0);
pair<int,Energy> imin[4]={make_pair(-1,-1.*GeV),make_pair(-1,-1.*GeV),
make_pair(-1,-1.*GeV),make_pair(-1,-1.*GeV)};
+ Energy absmin = -1e20*GeV;
+ int minType = -1;
for(unsigned int iy=0;iy<_diagmap.size();++iy) {
unsigned int ix=_diagmap[iy];
- Energy deltam(min);
if(getProcessInfo()[ix].channelType==TBDiagram::fourPoint) continue;
+ Energy dm1(min-getProcessInfo()[ix].intermediate->mass());
+ Energy dm2(getProcessInfo()[ix].intermediate->mass());
int itype(0);
if (getProcessInfo()[ix].channelType==TBDiagram::channel23) {
- deltam -= outgoing()[0]->mass();
+ dm1 -= outgoing()[0]->mass();
+ dm2 -= outgoing()[1]->mass()+outgoing()[2]->mass();
itype = 3;
}
else if(getProcessInfo()[ix].channelType==TBDiagram::channel13) {
- deltam -= outgoing()[1]->mass();
+ dm1 -= outgoing()[1]->mass();
+ dm2 -= outgoing()[0]->mass()+outgoing()[2]->mass();
itype = 2;
}
else if(getProcessInfo()[ix].channelType==TBDiagram::channel12) {
- deltam -= outgoing()[2]->mass();
+ dm1 -= outgoing()[2]->mass();
+ dm2 -= outgoing()[0]->mass()+outgoing()[1]->mass();
itype = 1;
}
- deltam -= getProcessInfo()[ix].intermediate->mass();
- // if(deltam<ZERO&&getProcessInfo()[ix].intermediate->width()>ZERO) {
- if(deltam<ZERO) {
- if (imin[itype].first < 0 ) imin[itype] = make_pair(ix,deltam);
- else if (imin[itype].second<deltam) imin[itype] = make_pair(ix,deltam);
+ if(dm1<ZERO||dm2<ZERO) {
+ if (imin[itype].first < 0 ||
+ (dm1<ZERO && imin[itype].second < dm1) ) {
+ imin[itype] = make_pair(ix,dm1);
+ if(dm1<ZERO&&absmin<dm1) {
+ absmin = dm1;
+ minType = itype;
+ }
+ }
+ continue;
}
- if(deltam<ZERO) continue;
if(getProcessInfo()[ix].intermediate->id()!=ParticleID::gamma) {
intype.push_back(itype);
inpow.push_back(0.);
inmass.push_back(getProcessInfo()[ix].intermediate->mass());
inwidth.push_back(getProcessInfo()[ix].intermediate->width());
++nchannel;
}
else if(getProcessInfo()[ix].intermediate->id()==ParticleID::gamma) {
intype.push_back(itype);
inpow.push_back(-2.);
inmass.push_back(-1.*GeV);
inwidth.push_back(-1.*GeV);
++nchannel;
}
}
+ // physical poles, use them and return
+ if(nchannel>0) {
+ inweights = vector<double>(nchannel,1./double(nchannel));
+ return;
+ }
+ // use shallowest pole
+ else if(_intOpt==1&&minType>0) {
+ intype.push_back(minType);
+ if(getProcessInfo()[imin[minType].first].intermediate->id()!=ParticleID::gamma) {
+ inpow.push_back(0.);
+ inmass.push_back(getProcessInfo()[imin[minType].first].intermediate->mass());
+ inwidth.push_back(getProcessInfo()[imin[minType].first].intermediate->width());
+ }
+ else {
+ inpow.push_back(-2.);
+ inmass.push_back(-1.*GeV);
+ inwidth.push_back(-1.*GeV);
+ }
+ inweights = vector<double>(1,1.);
+ return;
+ }
for(unsigned int ix=1;ix<4;++ix) {
if(imin[ix].first>=0) {
intype.push_back(ix);
if(getProcessInfo()[imin[ix].first].intermediate->id()!=ParticleID::gamma) {
inpow.push_back(0.);
inmass.push_back(getProcessInfo()[imin[ix].first].intermediate->mass());
inwidth.push_back(getProcessInfo()[imin[ix].first].intermediate->width());
}
else {
inpow.push_back(-2.);
inmass.push_back(-1.*GeV);
inwidth.push_back(-1.*GeV);
}
++nchannel;
}
}
inweights = vector<double>(nchannel,1./double(nchannel));
}
diff --git a/Decay/General/GeneralThreeBodyDecayer.h b/Decay/General/GeneralThreeBodyDecayer.h
--- a/Decay/General/GeneralThreeBodyDecayer.h
+++ b/Decay/General/GeneralThreeBodyDecayer.h
@@ -1,347 +1,363 @@
// -*- C++ -*-
#ifndef HERWIG_GeneralThreeBodyDecayer_H
#define HERWIG_GeneralThreeBodyDecayer_H
//
// This is the declaration of the GeneralThreeBodyDecayer class.
//
#include "Herwig++/Decay/DecayIntegrator.h"
#include "Herwig++/Models/General/TBDiagram.h"
#include "GeneralThreeBodyDecayer.fh"
namespace Herwig {
using namespace ThePEG;
/**
* Here is the documentation of the GeneralThreeBodyDecayer class.
*
* @see \ref GeneralThreeBodyDecayerInterfaces "The interfaces"
* defined for GeneralThreeBodyDecayer.
*/
class GeneralThreeBodyDecayer: public DecayIntegrator {
public:
/** A ParticleData ptr and (possible) mass pair.*/
typedef pair<tcPDPtr, Energy> PMPair;
public:
/**
* The default constructor.
*/
GeneralThreeBodyDecayer() : _nflow(999), _widthopt(1),
- _reftag(), _reftagcc(), _iflow(999)
+ _reftag(), _reftagcc(), _iflow(999),
+ _intOpt(0), _relerr(1e-2)
{}
/** @name Virtual functions required by the Decayer class. */
//@{
/**
* For a given decay mode and a given particle instance, perform the
* decay and return the decay products. As this is the base class this
* is not implemented.
* @return The vector of particles produced in the decay.
*/
virtual ParticleVector decay(const Particle & parent,
const tPDVector & children) const;
/**
* Which of the possible decays is required
* @param cc Is this mode the charge conjugate
* @param parent The decaying particle
* @param children The decay products
*/
virtual int modeNumber(bool & cc, tcPDPtr parent,const tPDVector & children) const;
/**
* Return the matrix element squared for a given mode and phase-space channel
* @param ichan The channel we are calculating the matrix element for.
* @param part The decaying Particle.
* @param decay The particles produced in the decay.
* @param meopt Option for the calculation of the matrix element
* @return The matrix element squared for the phase-space configuration.
*/
virtual double me2(const int ichan, const Particle & part,
const ParticleVector & decay, MEOption meopt) const = 0;
/**
* The matrix element to be integrated for the three-body decays as a function
* of the invariant masses of pairs of the outgoing particles.
* @param imode The mode for which the matrix element is needed.
* @param q2 The scale, \e i.e. the mass squared of the decaying particle.
* @param s3 The invariant mass squared of particles 1 and 2, \f$s_3=m^2_{12}\f$.
* @param s2 The invariant mass squared of particles 1 and 3, \f$s_2=m^2_{13}\f$.
* @param s1 The invariant mass squared of particles 2 and 3, \f$s_1=m^2_{23}\f$.
* @param m1 The mass of the first outgoing particle.
* @param m2 The mass of the second outgoing particle.
* @param m3 The mass of the third outgoing particle.
* @return The matrix element
*/
virtual double threeBodyMatrixElement(const int imode, const Energy2 q2,
const Energy2 s3, const Energy2 s2,
const Energy2 s1, const Energy m1,
const Energy m2, const Energy m3) const;
/**
* Function to return partial Width
* @param inpart The decaying particle.
* @param outa First decay product.
* @param outb Second decay product.
* @param outc Third decay product.
*/
virtual Energy partialWidth(PMPair inpart, PMPair outa,
PMPair outb, PMPair outc) const;
/**
* An overidden member to calculate a branching ratio for a certain
* particle instance.
* @param dm The DecayMode of the particle
* @param p The particle object
* @param oldbrat The branching fraction given in the DecayMode object
*/
virtual double brat(const DecayMode & dm, const Particle & p,
double oldbrat) const;
//@}
/**
* Set the diagrams
*/
void setDecayInfo(PDPtr incoming,vector<PDPtr> outgoing,
const vector<TBDiagram> & process,
const vector<DVector> & factors,
const vector<DVector> & Ncfactors,
const unsigned int ncf);
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 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();
//@}
protected:
/**
* Access the TBDiagrams that store the required information
* to create the diagrams
*/
const vector<TBDiagram> & getProcessInfo() const {
return _diagrams;
}
/**
* Incoming particle
*/
PDPtr incoming() const { return _incoming; }
/**
* Outgoing particles
*/
const vector<PDPtr> & outgoing() const { return _outgoing; }
/**
* Number of colour flows
*/
unsigned int numberOfFlows() const { return _nflow; }
/**
* Return the matrix of colour factors
*/
const vector<DVector> & getColourFactors() const { return _colour; }
/**
* Return the matrix of colour factors
*/
const vector<DVector> & getLargeNcColourFactors() const {
return _colourLargeNC;
}
/**
* Get the mapping between the phase-space channel and the diagram
*/
const vector<unsigned int> & diagramMap() const {
return _diagmap;
}
/**
* Option for the handling of the widths of the intermediate particles
*/
unsigned int widthOption() const { return _widthopt; }
/**
* Set colour connections
* @param parent Parent particle
* @param out Particle vector containing particles to
* connect colour lines
*/
void colourConnections(const Particle & parent,
const ParticleVector & out) const;
/**
* Method to construct the channels for the integrator to give the partial width
* @param intype Types of the channels
* @param inmass Mass for the channels
* @param inwidth Width for the channels
* @param inpow Power for the channels
* @param inweights Weights for the channels
*/
void constructIntegratorChannels(vector<int> & intype, vector<Energy> & inmass,
vector<Energy> & inwidth, vector<double> & inpow,
vector<double> & inweights) const;
/**
* Set the colour flow
* @param flow The value for the colour flow
*/
void colourFlow(unsigned int flow) const { _iflow = flow; }
/**
* Set the colour flow
*/
unsigned int const & colourFlow() const { return _iflow; }
+ /**
+ * Relative error for GQ integration
+ */
+ double relativeError() const {return _relerr;}
+
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is an abstract class with persistent data.
*/
static AbstractClassDescription<GeneralThreeBodyDecayer> initGeneralThreeBodyDecayer;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
GeneralThreeBodyDecayer & operator=(const GeneralThreeBodyDecayer &);
private:
/**
* Store the incoming particle
*/
PDPtr _incoming;
/**
* Outgoing particles
*/
vector<PDPtr> _outgoing;
/**
* Store the diagrams for the decay
*/
vector<TBDiagram> _diagrams;
/**
* Map between the diagrams and the phase-space channels
*/
vector<unsigned int> _diagmap;
/**
* Store colour factors for ME calc.
*/
vector<DVector> _colour;
/**
* Store cololur factors for ME calc at large N_c
*/
vector<DVector> _colourLargeNC;
/**
* The number of colourflows.
*/
unsigned int _nflow;
/**
* Reference to object to calculate the partial width
*/
mutable WidthCalculatorBasePtr _widthcalc;
/**
* Option for the treatment of the widths
*/
unsigned int _widthopt;
/**
* Store a decay tag for this mode that can be tested when
* trying to determine whether it can be generated by
* this Decayer
*/
string _reftag;
/**
* Store a decay tag for the cc-mode that can be tested when
* trying to determine whether it can be generated by
* this Decayer
*/
string _reftagcc;
/**
* The colour flow
*/
mutable unsigned int _iflow;
+
+ /**
+ * Option for the construction of the gaussian integrator
+ */
+ unsigned int _intOpt;
+
+ /**
+ * Relative error for GQ integration of partial width
+ */
+ double _relerr;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of GeneralThreeBodyDecayer. */
template <>
struct BaseClassTrait<Herwig::GeneralThreeBodyDecayer,1> {
/** Typedef of the first base class of GeneralThreeBodyDecayer. */
typedef Herwig::DecayIntegrator NthBase;
};
/** This template specialization informs ThePEG about the name of
* the GeneralThreeBodyDecayer class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::GeneralThreeBodyDecayer>
: public ClassTraitsBase<Herwig::GeneralThreeBodyDecayer> {
/** Return a platform-independent class name */
static string className() { return "Herwig::GeneralThreeBodyDecayer"; }
};
/** @endcond */
}
#endif /* HERWIG_GeneralThreeBodyDecayer_H */
diff --git a/Decay/General/GeneralTwoBodyDecayer.cc b/Decay/General/GeneralTwoBodyDecayer.cc
--- a/Decay/General/GeneralTwoBodyDecayer.cc
+++ b/Decay/General/GeneralTwoBodyDecayer.cc
@@ -1,482 +1,397 @@
// -*- C++ -*-
//
// GeneralTwoBodyDecayer.cc is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the GeneralTwoBodyDecayer class.
//
#include "GeneralTwoBodyDecayer.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/ParVector.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/DecayMode.h"
#include "ThePEG/Utilities/Exception.h"
using namespace Herwig;
ParticleVector GeneralTwoBodyDecayer::decay(const Particle & parent,
const tPDVector & children) const {
// return empty vector if products heavier than parent
Energy mout(ZERO);
for(tPDVector::const_iterator it=children.begin();
it!=children.end();++it) mout+=(**it).massMin();
if(mout>parent.mass()) return ParticleVector();
// generate the decay
bool cc;
int imode=modeNumber(cc,parent.dataPtr(),children);
// generate the kinematics
ParticleVector decay=generate(generateIntermediates(),cc,imode,parent);
// make the colour connections
colourConnections(parent, decay);
// return the answer
return decay;
}
void GeneralTwoBodyDecayer::doinit() {
DecayIntegrator::doinit();
assert( _theVertex );
+ assert( _incoming && _outgoing.size()==2);
_theVertex->init();
- vector<double> wgt;
- set<tPDPtr> parents = _theVertex->incoming();
- for( set<tPDPtr>::const_iterator it = parents.begin();
- it != parents.end(); ++it ) {
- long pid = (*it)->id();
- if( pid < 0 ) continue;
- tcPDPtr inpart = *it;
- Energy m1 = inpart->mass();
- tPDVector decaylist;
- for(unsigned int il = 0; il< _thelist.size(); ++il) {
- tPDVector temp = _theVertex->search(_thelist[il], inpart);
- decaylist.insert(decaylist.end(),temp.begin(),temp.end());
- }
- tPDVector::size_type ndec = decaylist.size();
- for( tPDVector::size_type j = 0; j < ndec; j +=3 ) {
- tPDPtr pa(decaylist[j]), pb(decaylist[j + 1]), pc(decaylist[j + 2]);
- if( pb->id() == pid ) swap(pa, pb);
- if( pc->id() == pid ) swap(pa, pc);
- //allowed on-shell decay?
- if( m1 <= pb->mass() + pc->mass() ) continue;
- //vertices are defined with all particles incoming
- if( pb->CC() ) pb = pb->CC();
- if( pc->CC() ) pc = pc->CC();
- //store ids so that the decayer knows what it is allowed to
- //decay
- _inpart.push_back(pid); _outparta.push_back(pb->id());
- _outpartb.push_back(pc->id());
- //create phase space mode
- tPDVector extpart(3);
- extpart[0] = pa;
- extpart[1] = pb;
- extpart[2] = pc;
- addMode(new_ptr(DecayPhaseSpaceMode(extpart, this)),
- _maxweight[0], wgt);
-
- }
- }
- unsigned int isize(_inpart.size()), oasize(_outparta.size()),
- obsize(_outpartb.size());
- if( isize == 0 || oasize == 0 || obsize == 0 )
- throw InitException()
- << "GeneralTwoBodyDecayer::doinit() - Atleast one of the particle "
- << "vectors has zero size, cannot continue."
- << isize << " " << oasize << " " << obsize
- << Exception::abortnow;
-
- if( isize != oasize || isize != obsize )
- throw InitException()
- << "GeneralTwoBodyDecayer::doinit() - The particle vectors have "
- << "different sizes. " << isize << " " << oasize << " " << obsize
- << Exception::abortnow;
-
+ //create phase space mode
+ tPDVector extpart(3);
+ extpart[0] = _incoming;
+ extpart[1] = _outgoing[0];
+ extpart[2] = _outgoing[1];
+ addMode(new_ptr(DecayPhaseSpaceMode(extpart, this)), _maxweight, vector<double>());
}
int GeneralTwoBodyDecayer::modeNumber(bool & cc, tcPDPtr parent,
const tPDVector & children) const {
long parentID = parent->id();
long id1 = children[0]->id();
long id2 = children[1]->id();
- int imode(-1);
- unsigned ii(0), nipart(_inpart.size());
cc = false;
- do {
- long listpid(_inpart[ii]), listid1(_outparta[ii]),
- listid2(_outpartb[ii]);
- if( parentID == listpid &&
- ((id1 == listid1 && id2 == listid2) ||
- (id1 == listid2 && id2 == listid1)) )
- imode = ii;
- //cc-mode
- else if(parentID == -listpid) {
- cc = true;
- if((id1 == -listid1 && id2 == -listid2) ||
- (id1 == -listid2 && id2 == -listid1) ||
- (id1 == listid1 && id2 == -listid2) ||
- (id1 == -listid1 && id2 == listid2) ||
- (id1 == listid2 && id2 == -listid1) ||
- (id1 == -listid2 && id2 == listid1) )
- imode = ii;
- else ++ii;
- }
- else ++ii;
+ long out1 = _outgoing[0]->id();
+ long out2 = _outgoing[1]->id();
+ if( parentID == _incoming->id() &&
+ ((id1 == out1 && id2 == out2) ||
+ (id1 == out2 && id2 == out1)) ) {
+ return 0;
}
- while( imode < 0 && ii < nipart );
- return imode;
+ else if(_incoming->CC() && parentID == _incoming->CC()->id()) {
+ cc = true;
+ if( _outgoing[0]->CC()) out1 = _outgoing[0]->CC()->id();
+ if( _outgoing[1]->CC()) out2 = _outgoing[1]->CC()->id();
+ if((id1 == out1 && id2 == out2) ||
+ (id1 == out2 && id2 == out1)) return 0;
+ }
+ return -1;
}
void GeneralTwoBodyDecayer::
colourConnections(const Particle & parent,
const ParticleVector & out) const {
PDT::Colour incColour(parent.data().iColour());
PDT::Colour outaColour(out[0]->data().iColour());
PDT::Colour outbColour(out[1]->data().iColour());
//incoming colour singlet
if(incColour == PDT::Colour0) {
// colour triplet-colourantitriplet
if((outaColour == PDT::Colour3 && outbColour == PDT::Colour3bar) ||
(outaColour == PDT::Colour3bar && outbColour == PDT::Colour3)) {
bool ac(out[0]->id() < 0);
out[0]->colourNeighbour(out[1],!ac);
}
//colour octet
else if(outaColour == PDT::Colour8 && outbColour == PDT::Colour8) {
out[0]->colourNeighbour(out[1]);
out[0]->antiColourNeighbour(out[1]);
}
// colour singlets
else if(outaColour == PDT::Colour0 && outbColour == PDT::Colour0) {
}
// unknown
else
throw Exception() << "Unknown outgoing colours for decaying "
<< "colour singlet in "
<< "GeneralTwoBodyDecayer::colourConnections "
<< outaColour << " " << outbColour
<< Exception::runerror;
}
//incoming colour triplet
else if(incColour == PDT::Colour3) {
// colour triplet + singlet
if(outaColour == PDT::Colour3 && outbColour == PDT::Colour0) {
out[0]->incomingColour(const_ptr_cast<tPPtr>(&parent));
}
//opposite order
else if(outaColour == PDT::Colour0 && outbColour == PDT::Colour3) {
out[1]->incomingColour(const_ptr_cast<tPPtr>(&parent));
}
// octet + triplet
else if(outaColour == PDT::Colour8 && outbColour == PDT::Colour3) {
out[0]->incomingColour(const_ptr_cast<tPPtr>(&parent));
out[1]->antiColourNeighbour(out[0]);
}
//opposite order
else if(outaColour == PDT::Colour3 && outbColour == PDT::Colour8) {
out[1]->incomingColour(const_ptr_cast<tPPtr>(&parent));
out[0]->antiColourNeighbour(out[1]);
}
else
throw Exception() << "Unknown outgoing colours for decaying "
<< "colour triplet in "
<< "GeneralTwoBodyDecayer::colourConnections() "
<< outaColour << " " << outbColour
<< Exception::runerror;
}
// incoming colour anti triplet
else if(incColour == PDT::Colour3bar) {
// colour antitriplet +singlet
if(outaColour == PDT::Colour3bar && outbColour == PDT::Colour0) {
out[0]->incomingAntiColour(const_ptr_cast<tPPtr>(&parent));
}
//opposite order
else if(outaColour == PDT::Colour0 && outbColour == PDT::Colour3bar) {
out[1]->incomingAntiColour(const_ptr_cast<tPPtr>(&parent));
}
//octet + antitriplet
else if(outaColour == PDT::Colour3bar && outbColour == PDT::Colour8) {
out[1]->incomingAntiColour(const_ptr_cast<tPPtr>(&parent));
out[0]->colourNeighbour(out[1]);
}
//opposite order
else if(outaColour == PDT::Colour8 && outbColour == PDT::Colour3bar) {
out[0]->incomingAntiColour(const_ptr_cast<tPPtr>(&parent));
out[1]->colourNeighbour(out[0]);
}
else
throw Exception() << "Unknown outgoing colours for decaying "
<< "colour antitriplet "
<< "in GeneralTwoBodyDecayer::colourConnections() "
<< outaColour << " " << outbColour
<< Exception::runerror;
}
//incoming colour octet
else if(incColour == PDT::Colour8) {
// triplet-antitriplet
if(outaColour == PDT::Colour3&&outbColour == PDT::Colour3bar) {
out[0]->incomingColour(const_ptr_cast<tPPtr>(&parent));
out[1]->incomingAntiColour(const_ptr_cast<tPPtr>(&parent));
}
// opposite order
else if(outbColour == PDT::Colour3&&outaColour == PDT::Colour3bar) {
out[0]->incomingAntiColour(const_ptr_cast<tPPtr>(&parent));
out[1]->incomingColour(const_ptr_cast<tPPtr>(&parent));
}
// neutral octet
else if(outaColour == PDT::Colour0&&outbColour == PDT::Colour8) {
out[1]->incomingColour(const_ptr_cast<tPPtr>(&parent));
out[1]->incomingAntiColour(const_ptr_cast<tPPtr>(&parent));
}
else if(outbColour == PDT::Colour0&&outaColour == PDT::Colour8) {
out[0]->incomingColour(const_ptr_cast<tPPtr>(&parent));
out[0]->incomingAntiColour(const_ptr_cast<tPPtr>(&parent));
}
else
throw Exception() << "Unknown outgoing colours for decaying "
<< "colour octet "
<< "in GeneralTwoBodyDecayer::colourConnections() "
<< outaColour << " " << outbColour
<< Exception::runerror;
}
else
throw Exception() << "Unknown incoming colour in "
<< "GeneralTwoBodyDecayer::colourConnections() "
<< incColour
<< Exception::runerror;
}
bool GeneralTwoBodyDecayer::twoBodyMEcode(const DecayMode & dm, int & mecode,
double & coupling) const {
- long parent = dm.parent()->id();
+ assert(dm.parent()->id() == _incoming->id());
ParticleMSet::const_iterator pit = dm.products().begin();
long id1 = (*pit)->id();
++pit;
long id2 = (*pit)->id();
- bool order(false);
- vector<int>::size_type ix(0);
- do {
- if( parent == _inpart[ix] ) {
- long id1t(_outparta[ix]), id2t(_outpartb[ix]);
- if( id1 == id1t && id2 == id2t ) {
- order = true;
- break;
- }
- if( id1 == id2t && id2 == id1t ) {
- order = false;
- break;
- }
- }
- ++ix;
- }
- while( ix < _inpart.size() );
+ long id1t(_outgoing[0]->id()), id2t(_outgoing[1]->id());
mecode = -1;
coupling = 1.;
- return order;
+ if( id1 == id1t && id2 == id2t ) {
+ return true;
+ }
+ else if( id1 == id2t && id2 == id1t ) {
+ return false;
+ }
+ else
+ assert(false);
+ return false;
}
void GeneralTwoBodyDecayer::persistentOutput(PersistentOStream & os) const {
- os << _thelist << _theVertex << _inpart << _outparta << _outpartb
- << _maxweight;
+ os << _theVertex << _incoming << _outgoing << _maxweight;
}
void GeneralTwoBodyDecayer::persistentInput(PersistentIStream & is, int) {
- is >> _thelist >> _theVertex >>_inpart >>_outparta >>_outpartb
- >> _maxweight;
+ is >> _theVertex >> _incoming >> _outgoing >> _maxweight;
}
AbstractClassDescription<GeneralTwoBodyDecayer>
GeneralTwoBodyDecayer::initGeneralTwoBodyDecayer;
// Definition of the static class description member.
void GeneralTwoBodyDecayer::Init() {
static ClassDocumentation<GeneralTwoBodyDecayer> documentation
("This class is designed to be a base class for all 2 body decays"
"in a general model");
-
- static Reference<GeneralTwoBodyDecayer,Helicity::VertexBase> interfaceDecayVertex
- ("DecayVertex",
- "Pointer to decayer vertex",
- &GeneralTwoBodyDecayer::_theVertex, false, false, true, false);
-
- static ParVector<GeneralTwoBodyDecayer,double> interfaceMaxWeight
- ("MaxWeight",
- "Maximum weight for integration",
- &GeneralTwoBodyDecayer::_maxweight, 1.0, -1, 0, 0,
- false, false, false,&GeneralTwoBodyDecayer::setWeight, 0 ,0, 0, 0);
-
- static ParVector<GeneralTwoBodyDecayer,int> interfaceIncomingPart
- ("Incoming",
- "PDG Codes for incoming particles",
- &GeneralTwoBodyDecayer::_inpart, 0, -1, 0, 0,
- false, false, false);
-
- static ParVector<GeneralTwoBodyDecayer,int> interfaceOutgoingPartA
- ("OutgoingA",
- "PDG Codes for first set of outgoing particles",
- &GeneralTwoBodyDecayer::_outparta, 0, -1, 0, 0,
- false, false, false);
-
- static ParVector<GeneralTwoBodyDecayer,int> interfaceOutgoingPartB
- ("OutgoingB",
- "PDG Codes for second set of outgoing particles",
- &GeneralTwoBodyDecayer::_outpartb, 0, -1, 0, 0,
- false, false, false);
}
double GeneralTwoBodyDecayer::brat(const DecayMode &, const Particle & p,
double oldbrat) const {
ParticleVector children = p.children();
if( children.size() != 2 || !p.data().widthGenerator() )
return oldbrat;
// partial width for this mode
Energy scale = p.mass();
Energy pwidth =
partialWidth( make_pair(p.dataPtr(), scale),
make_pair(children[0]->dataPtr(), children[0]->mass()),
make_pair(children[1]->dataPtr(), children[1]->mass()) );
Energy width = p.data().widthGenerator()->width(p.data(), scale);
return pwidth/width;
}
void GeneralTwoBodyDecayer::doinitrun() {
DecayIntegrator::doinitrun();
for(unsigned int ix=0;ix<numberModes();++ix) {
double fact = pow(1.5,int(mode(ix)->externalParticles(0)->iSpin())-1);
mode(ix)->setMaxWeight(fact*mode(ix)->maxWeight());
}
}
double GeneralTwoBodyDecayer::colourFactor(tcPDPtr in, tcPDPtr out1,
tcPDPtr out2) const {
// identical particle symmetry factor
double output = out1->id()==out2->id() ? 0.5 : 1.;
// colour neutral incoming particle
if(in->iColour()==PDT::Colour0) {
// both colour neutral
if(out1->iColour()==PDT::Colour0 && out2->iColour()==PDT::Colour0)
output *= 1.;
// colour triplet/ antitriplet
else if((out1->iColour()==PDT::Colour3 && out2->iColour()==PDT::Colour3bar) ||
(out1->iColour()==PDT::Colour3bar && out2->iColour()==PDT::Colour3 ) ) {
output *= 3.;
}
// colour octet colour octet
else if(out1->iColour()==PDT::Colour8 && out2->iColour()==PDT::Colour8 ) {
output *= 8.;
}
else
throw Exception() << "Unknown colour for the outgoing particles"
<< " for decay colour neutral particle in "
<< "GeneralTwoBodyDecayer::colourFactor() for "
<< in->PDGName() << " -> "
<< out1->PDGName() << " " << out2->PDGName()
<< Exception::runerror;
}
// triplet
else if(in->iColour()==PDT::Colour3) {
// colour triplet + neutral
if((out1->iColour()==PDT::Colour0 && out2->iColour()==PDT::Colour3) ||
(out1->iColour()==PDT::Colour3 && out2->iColour()==PDT::Colour0) ) {
output *= 1.;
}
// colour triplet + octet
else if((out1->iColour()==PDT::Colour8 && out2->iColour()==PDT::Colour3) ||
(out1->iColour()==PDT::Colour3 && out2->iColour()==PDT::Colour8) ) {
output *= 4./3.;
}
else
throw Exception() << "Unknown colour for the outgoing particles"
<< " for decay colour triplet particle in "
<< "GeneralTwoBodyDecayer::colourFactor() for "
<< in->PDGName() << " -> "
<< out1->PDGName() << " " << out2->PDGName()
<< Exception::runerror;
}
// anti triplet
else if(in->iColour()==PDT::Colour3bar) {
// colour anti triplet + neutral
if((out1->iColour()==PDT::Colour0 && out2->iColour()==PDT::Colour3bar ) ||
(out1->iColour()==PDT::Colour3bar && out2->iColour()==PDT::Colour0 ) ) {
output *= 1.;
}
// colour anti triplet + octet
else if((out1->iColour()==PDT::Colour8 && out2->iColour()==PDT::Colour3bar ) ||
(out1->iColour()==PDT::Colour3bar && out2->iColour()==PDT::Colour8 ) ) {
output *= 4./3.;
}
else
throw Exception() << "Unknown colour for the outgoing particles"
<< " for decay colour anti triplet particle in "
<< "GeneralTwoBodyDecayer::colourFactor() for "
<< in->PDGName() << " -> "
<< out1->PDGName() << " " << out2->PDGName()
<< Exception::runerror;
}
else if(in->iColour()==PDT::Colour8) {
// colour octet + neutral
if((out1->iColour()==PDT::Colour0 && out2->iColour()==PDT::Colour8 ) ||
(out1->iColour()==PDT::Colour8 && out2->iColour()==PDT::Colour0 ) ) {
output *= 1.;
}
// colour triplet/antitriplet
else if((out1->iColour()==PDT::Colour3 && out2->iColour()==PDT::Colour3bar) ||
(out1->iColour()==PDT::Colour3bar && out2->iColour()==PDT::Colour3 ) ) {
output *= 0.5;
}
else
throw Exception() << "Unknown colour for the outgoing particles"
<< " for decay colour octet particle in "
<< "GeneralTwoBodyDecayer::colourFactor() for "
<< in->PDGName() << " -> "
<< out1->PDGName() << " " << out2->PDGName()
<< Exception::runerror;
}
else
throw Exception() << "Unknown colour for the decaying particle in "
<< "GeneralTwoBodyDecayer::colourFactor() for "
<< in->PDGName() << " -> "
<< out1->PDGName() << " " << out2->PDGName()
<< Exception::runerror;
return output;
}
Energy GeneralTwoBodyDecayer::partialWidth(PMPair inpart, PMPair outa,
PMPair outb) const {
// select the number of the mode
tPDVector children;
children.push_back(const_ptr_cast<PDPtr>(outa.first));
children.push_back(const_ptr_cast<PDPtr>(outb.first));
bool cc;
int nmode=modeNumber(cc,inpart.first,children);
tcPDPtr newchild[2] = {mode(nmode)->externalParticles(1),
mode(nmode)->externalParticles(2)};
// make the particles
Lorentz5Momentum pparent = Lorentz5Momentum(inpart.second);
PPtr parent = inpart.first->produceParticle(pparent);
Lorentz5Momentum pout[2];
double ctheta,phi;
Kinematics::generateAngles(ctheta,phi);
Kinematics::twoBodyDecay(pparent, outa.second, outb.second,
ctheta, phi,pout[0],pout[1]);
if( ( !cc && outa.first!=newchild[0]) ||
( cc && !(( outa.first->CC() && outa.first->CC() == newchild[0])||
( !outa.first->CC() && outa.first == newchild[0]) )))
swap(pout[0],pout[1]);
ParticleVector decay;
decay.push_back(newchild[0]->produceParticle(pout[0]));
decay.push_back(newchild[1]->produceParticle(pout[1]));
double me = me2(-1,*parent,decay,Initialize);
Energy pcm = Kinematics::pstarTwoBodyDecay(inpart.second,
outa.second, outb.second);
return me/(8.*Constants::pi)*pcm;
}
+
+void GeneralTwoBodyDecayer::setDecayInfo(PDPtr incoming,PDPair outgoing,
+ VertexBasePtr vertex) {
+ _incoming=incoming;
+ _outgoing.clear();
+ _outgoing.push_back(outgoing.first );
+ _outgoing.push_back(outgoing.second);
+ _theVertex = vertex;
+}
diff --git a/Decay/General/GeneralTwoBodyDecayer.h b/Decay/General/GeneralTwoBodyDecayer.h
--- a/Decay/General/GeneralTwoBodyDecayer.h
+++ b/Decay/General/GeneralTwoBodyDecayer.h
@@ -1,274 +1,264 @@
// -*- C++ -*-
//
// GeneralTwoBodyDecayer.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_GeneralTwoBodyDecayer_H
#define HERWIG_GeneralTwoBodyDecayer_H
//
// This is the declaration of the GeneralTwoBodyDecayer class.
//
#include "Herwig++/Decay/DecayIntegrator.h"
#include "Herwig++/Decay/DecayPhaseSpaceMode.h"
#include "ThePEG/Helicity/Vertex/VertexBase.h"
#include "GeneralTwoBodyDecayer.fh"
namespace Herwig {
using namespace ThePEG;
using Helicity::VertexBasePtr;
/** \ingroup Decay
* The GeneralTwoBodyDecayer class is designed to be the base class
* for 2 body decays for some general model. It inherits from
* DecayIntegrator and implements the modeNumber() virtual function
* that is the same for all of the decays. A decayer for
* a specific spin configuration should inherit from this and implement
* the me2() and partialWidth() member functions. The colourConnections()
* member should be called from inside me2() in the inheriting decayer
* to set up the colour lines.
*
* @see \ref GeneralTwoBodyDecayerInterfaces "The interfaces"
* defined for GeneralTwoBodyDecayer.
* @see DecayIntegrator
*/
class GeneralTwoBodyDecayer: public DecayIntegrator {
public:
/** A ParticleData ptr and (possible) mass pair.*/
typedef pair<tcPDPtr, Energy> PMPair;
public:
/**
* The default constructor.
*/
- GeneralTwoBodyDecayer() : _thelist(0,0), _maxweight(1,1.) {}
+ GeneralTwoBodyDecayer() : _maxweight(1.) {}
/** @name Virtual functions required by the Decayer class. */
//@{
/**
* For a given decay mode and a given particle instance, perform the
* decay and return the decay products. As this is the base class this
* is not implemented.
* @return The vector of particles produced in the decay.
*/
virtual ParticleVector decay(const Particle & parent,
const tPDVector & children) const;
/**
* Which of the possible decays is required
* @param cc Is this mode the charge conjugate
* @param parent The decaying particle
* @param children The decay products
*/
virtual int modeNumber(bool & cc, tcPDPtr parent,const tPDVector & children) const;
/**
* Return the matrix element squared for a given mode and phase-space channel
* @param ichan The channel we are calculating the matrix element for.
* @param part The decaying Particle.
* @param decay The particles produced in the decay.
* @param meopt Option for the calculation of the matrix element
* @return The matrix element squared for the phase-space configuration.
*/
virtual double me2(const int ichan, const Particle & part,
const ParticleVector & decay, MEOption meopt) const = 0;
/**
* Function to return partial Width
* @param inpart The decaying particle.
* @param outa One of the decay products.
* @param outb The other decay product.
*/
virtual Energy partialWidth(PMPair inpart, PMPair outa,
PMPair outb) const;
/**
* Specify the \f$1\to2\f$ matrix element to be used in the running width
* calculation.
* @param dm The DecayMode
* @param mecode The code for the matrix element as described
* in the GenericWidthGenerator class.
* @param coupling The coupling for the matrix element.
* @return True if the the order of the particles in the
* decayer is the same as the DecayMode tag.
*/
virtual bool twoBodyMEcode(const DecayMode & dm, int & mecode,
double & coupling) const;
/**
* An overidden member to calculate a branching ratio for a certain
* particle instance.
* @param dm The DecayMode of the particle
* @param p The particle object
* @param oldbrat The branching fraction given in the DecayMode object
*/
virtual double brat(const DecayMode & dm, const Particle & p,
double oldbrat) const;
//@}
+ /**
+ * Set the information on the decay
+ */
+ void setDecayInfo(PDPtr incoming,PDPair outgoing,
+ VertexBasePtr);
+
protected:
/** @name Functions used by inheriting decayers. */
//@{
- /** Set list to search
- * @param ilist
- */
- void addToSearchList(unsigned int ilist) {
- _thelist.push_back(ilist);
- }
/**
* Get vertex pointer
* @return a pointer to the vertex
*/
VertexBasePtr getVertex() const { return _theVertex; }
/**
* Set integration weight
* @param wgt Maximum integration weight
*/
- void setWeight(const vector<double> & wgt) { _maxweight = wgt; }
+ void setWeight(const double & wgt) { _maxweight = wgt; }
/**
* Set colour connections
* @param parent Parent particle
* @param out Particle vector containing particles to
* connect colour lines
*/
void colourConnections(const Particle & parent,
const ParticleVector & out) const;
/**
* Compute the spin and colour factor
*/
double colourFactor(tcPDPtr in, tcPDPtr out1, tcPDPtr out2) const;
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name 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();
/**
* Initialize this object. Called in the run phase just before
* a run begins.
*/
virtual void doinitrun();
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is an abstract class with persistent data.
*/
static AbstractClassDescription<GeneralTwoBodyDecayer> initGeneralTwoBodyDecayer;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
GeneralTwoBodyDecayer & operator=(const GeneralTwoBodyDecayer &);
private:
/**
- * vector of ints as to which list(s) to search
+ * Store the incoming particle
*/
- vector<unsigned int> _thelist;
+ PDPtr _incoming;
+
+ /**
+ * Outgoing particles
+ */
+ vector<PDPtr> _outgoing;
/**
- * Pointer to vertex set in inheriting class
+ * Pointer to vertex
*/
VertexBasePtr _theVertex;
-
- /**
- * PDG codes for all incoming particles
- **/
- vector<int> _inpart;
-
- /**
- * PDG codes for 1st set of outgoing particles
- **/
- vector<int> _outparta;
-
- /**
- * PDG codes for 2nd set of outgoing particles
- **/
- vector<int> _outpartb;
/**
- * Vector of maximum weights for integration
+ * Maximum weight for integration
*/
- vector<double> _maxweight;
+ double _maxweight;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of GeneralTwoBodyDecayer. */
template <>
struct BaseClassTrait<Herwig::GeneralTwoBodyDecayer,1> {
/** Typedef of the first base class of GeneralTwoBodyDecayer. */
typedef Herwig::DecayIntegrator NthBase;
};
/** This template specialization informs ThePEG about the name of
* the GeneralTwoBodyDecayer class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::GeneralTwoBodyDecayer>
: public ClassTraitsBase<Herwig::GeneralTwoBodyDecayer> {
/** Return a platform-independent class name */
static string className() { return "Herwig::GeneralTwoBodyDecayer"; }
};
/** @endcond */
}
#endif /* HERWIG_GeneralTwoBodyDecayer_H */
diff --git a/Decay/General/SFFDecayer.h b/Decay/General/SFFDecayer.h
--- a/Decay/General/SFFDecayer.h
+++ b/Decay/General/SFFDecayer.h
@@ -1,198 +1,198 @@
// -*- C++ -*-
//
// SFFDecayer.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_SFFDecayer_H
#define HERWIG_SFFDecayer_H
//
// This is the declaration of the SFFDecayer class.
//
#include "GeneralTwoBodyDecayer.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Helicity/Vertex/Scalar/FFSVertex.h"
namespace Herwig {
using namespace ThePEG;
using Helicity::FFSVertexPtr;
/** \ingroup Decay
* The SFFDecayer class implements the decay of a scalar to 2
* fermions in a general model. It holds an FFSVertex pointer that
* must be typecast from the VertexBase pointer held in
* GeneralTwoBodyDecayer. It implents the virtual functions me2() and
* partialWidth().
*
* @see GeneralTwoBodyDecayer
*/
class SFFDecayer: public GeneralTwoBodyDecayer {
public:
/**
* The default constructor.
*/
- SFFDecayer() { addToSearchList(2); }
+ SFFDecayer() {}
/** @name Virtual functions required by the Decayer class. */
//@{
/**
* Return the matrix element squared for a given mode and phase-space channel.
* @param ichan The channel we are calculating the matrix element for.
* @param part The decaying Particle.
* @param decay The particles produced in the decay.
* @param meopt Option for the calculation of the matrix element
* @return The matrix element squared for the phase-space configuration.
*/
virtual double me2(const int ichan, const Particle & part,
const ParticleVector & decay, MEOption meopt) const;
/**
* Function to return partial Width
* @param inpart The decaying particle.
* @param outa One of the decay products.
* @param outb The other decay product.
*/
virtual Energy partialWidth(PMPair inpart, PMPair outa,
PMPair outb) const;
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
virtual IBPtr fullclone() const;
//@}
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving and
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit();
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<SFFDecayer> initSFFDecayer;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
SFFDecayer & operator=(const SFFDecayer &);
private:
/**
* Abstract pointer to AbstractFFSVertex
*/
AbstractFFSVertexPtr _abstractVertex;
/**
* Pointer to the perturbative vertex
*/
FFSVertexPtr _perturbativeVertex;
/**
* Spin density matrix
*/
mutable RhoDMatrix _rho;
/**
* Scalar wavefunction
*/
mutable ScalarWaveFunction _swave;
/**
* Spinor wavefunction
*/
mutable vector<SpinorWaveFunction> _wave;
/**
* Barred spinor wavefunction
*/
mutable vector<SpinorBarWaveFunction> _wavebar;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of SFFDecayer. */
template <>
struct BaseClassTrait<Herwig::SFFDecayer,1> {
/** Typedef of the first base class of SFFDecayer. */
typedef Herwig::GeneralTwoBodyDecayer NthBase;
};
/** This template specialization informs ThePEG about the name of
* the SFFDecayer class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::SFFDecayer>
: public ClassTraitsBase<Herwig::SFFDecayer> {
/** Return a platform-independent class name */
static string className() { return "Herwig::SFFDecayer"; }
};
/** @endcond */
}
#endif /* HERWIG_SFFDecayer_H */
diff --git a/Decay/General/SRFDecayer.h b/Decay/General/SRFDecayer.h
--- a/Decay/General/SRFDecayer.h
+++ b/Decay/General/SRFDecayer.h
@@ -1,208 +1,208 @@
// -*- C++ -*-
//
// SRFDecayer.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_SRFDecayer_H
#define HERWIG_SRFDecayer_H
//
// This is the declaration of the SRFDecayer class.
//
#include "GeneralTwoBodyDecayer.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Helicity/Vertex/Scalar/RFSVertex.h"
namespace Herwig {
using namespace ThePEG;
using Helicity::RFSVertexPtr;
/** \ingroup Decay
* The SRFDecayer class implements the decay of a scalar to spin-3/2
* and spin-1/2 fermion in a general model. It holds an RFSVertex pointer that
* must be typecast from the VertexBase pointer held in
* GeneralTwoBodyDecayer. It implents the virtual functions me2() and
* partialWidth().
*
* @see GeneralTwoBodyDecayer
*/
class SRFDecayer: public GeneralTwoBodyDecayer {
public:
/**
* The default constructor.
*/
- SRFDecayer() { addToSearchList(2); }
+ SRFDecayer() {}
/** @name Virtual functions required by the Decayer class. */
//@{
/**
* Return the matrix element squared for a given mode and phase-space channel.
* @param ichan The channel we are calculating the matrix element for.
* @param part The decaying Particle.
* @param decay The particles produced in the decay.
* @param meopt Option for the calculation of the matrix element
* @return The matrix element squared for the phase-space configuration.
*/
virtual double me2(const int ichan, const Particle & part,
const ParticleVector & decay, MEOption meopt) const;
/**
* Function to return partial Width
* @param inpart The decaying particle.
* @param outa One of the decay products.
* @param outb The other decay product.
*/
virtual Energy partialWidth(PMPair inpart, PMPair outa,
PMPair outb) const;
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
virtual IBPtr fullclone() const;
//@}
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving and
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit();
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<SRFDecayer> initSRFDecayer;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
SRFDecayer & operator=(const SRFDecayer &);
private:
/**
* Abstract pointer to AbstractFFSVertex
*/
AbstractRFSVertexPtr abstractVertex_;
/**
* Pointer to the perturbative vertex
*/
RFSVertexPtr perturbativeVertex_;
/**
* Spin density matrix
*/
mutable RhoDMatrix rho_;
/**
* Scalar wavefunction
*/
mutable ScalarWaveFunction swave_;
/**
* Spinor wavefunction
*/
mutable vector<SpinorWaveFunction> wave_;
/**
* Barred spinor wavefunction
*/
mutable vector<SpinorBarWaveFunction> wavebar_;
/**
* RS Spinor wavefunction
*/
mutable vector<RSSpinorWaveFunction> RSwave_;
/**
* Barred RS spinor wavefunction
*/
mutable vector<RSSpinorBarWaveFunction> RSwavebar_;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of SRFDecayer. */
template <>
struct BaseClassTrait<Herwig::SRFDecayer,1> {
/** Typedef of the first base class of SRFDecayer. */
typedef Herwig::GeneralTwoBodyDecayer NthBase;
};
/** This template specialization informs ThePEG about the name of
* the SRFDecayer class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::SRFDecayer>
: public ClassTraitsBase<Herwig::SRFDecayer> {
/** Return a platform-independent class name */
static string className() { return "Herwig::SRFDecayer"; }
};
/** @endcond */
}
#endif /* HERWIG_SRFDecayer_H */
diff --git a/Decay/General/SSSDecayer.cc b/Decay/General/SSSDecayer.cc
--- a/Decay/General/SSSDecayer.cc
+++ b/Decay/General/SSSDecayer.cc
@@ -1,108 +1,102 @@
// -*- C++ -*-
//
// SSSDecayer.cc is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the SSSDecayer class.
//
#include "SSSDecayer.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h"
#include "Herwig++/Utilities/Kinematics.h"
using namespace Herwig;
using namespace ThePEG::Helicity;
-SSSDecayer::SSSDecayer() {
- addToSearchList(0);
- addToSearchList(1);
- addToSearchList(2);
-}
-
IBPtr SSSDecayer::clone() const {
return new_ptr(*this);
}
IBPtr SSSDecayer::fullclone() const {
return new_ptr(*this);
}
void SSSDecayer::doinit() {
_perturbativeVertex = dynamic_ptr_cast<SSSVertexPtr> (getVertex());
_abstractVertex = dynamic_ptr_cast<AbstractSSSVertexPtr>(getVertex());
GeneralTwoBodyDecayer::doinit();
}
void SSSDecayer::persistentOutput(PersistentOStream & os) const {
os << _abstractVertex << _perturbativeVertex;
}
void SSSDecayer::persistentInput(PersistentIStream & is, int) {
is >> _abstractVertex >> _perturbativeVertex;
}
ClassDescription<SSSDecayer> SSSDecayer::initSSSDecayer;
// Definition of the static class description member.
void SSSDecayer::Init() {
static ClassDocumentation<SSSDecayer> documentation
("This class implements the decay of a scalar to 2 scalars.");
}
double SSSDecayer::me2(const int , const Particle & inpart,
const ParticleVector & decay,
MEOption meopt) const {
if(meopt==Initialize) {
ScalarWaveFunction::
calculateWaveFunctions(_rho,const_ptr_cast<tPPtr>(&inpart),incoming);
_swave = ScalarWaveFunction(inpart.momentum(),inpart.dataPtr(),incoming);
ME(DecayMatrixElement(PDT::Spin0,PDT::Spin0,PDT::Spin0));
}
if(meopt==Terminate) {
ScalarWaveFunction::
constructSpinInfo(const_ptr_cast<tPPtr>(&inpart),incoming,true);
for(unsigned int ix=0;ix<2;++ix)
ScalarWaveFunction::
constructSpinInfo(decay[ix],outgoing,true);
}
ScalarWaveFunction s1(decay[0]->momentum(),decay[0]->dataPtr(),outgoing);
ScalarWaveFunction s2(decay[1]->momentum(),decay[1]->dataPtr(),outgoing);
Energy2 scale(sqr(inpart.mass()));
ME()(0,0,0) = _abstractVertex->evaluate(scale,s1,s2,_swave);
double output = (ME().contract(_rho)).real()/scale*UnitRemoval::E2;
// colour and identical particle factors
output *= colourFactor(inpart.dataPtr(),decay[0]->dataPtr(),
decay[1]->dataPtr());
// return the answer
return output;
}
Energy SSSDecayer::partialWidth(PMPair inpart, PMPair outa,
PMPair outb) const {
if( inpart.second < outa.second + outb.second ) return ZERO;
if(_perturbativeVertex) {
Energy2 scale(sqr(inpart.second));
tcPDPtr in = inpart.first->CC() ? tcPDPtr(inpart.first->CC()) : inpart.first;
_perturbativeVertex->setCoupling(scale, in, outa.first, outb.first);
Energy pcm = Kinematics::pstarTwoBodyDecay(inpart.second, outa.second,
outb.second);
double c2 = norm(_perturbativeVertex->norm());
Energy pWidth = c2*pcm/8./Constants::pi/scale*UnitRemoval::E2;
// colour factor
pWidth *= colourFactor(inpart.first,outa.first,outb.first);
return pWidth;
}
else {
return GeneralTwoBodyDecayer::partialWidth(inpart,outa,outb);
}
}
diff --git a/Decay/General/SSSDecayer.h b/Decay/General/SSSDecayer.h
--- a/Decay/General/SSSDecayer.h
+++ b/Decay/General/SSSDecayer.h
@@ -1,186 +1,186 @@
// -*- C++ -*-
//
// SSSDecayer.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_SSSDecayer_H
#define HERWIG_SSSDecayer_H
//
// This is the declaration of the SSSDecayer class.
//
#include "GeneralTwoBodyDecayer.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Helicity/Vertex/Scalar/SSSVertex.h"
namespace Herwig {
using namespace ThePEG;
using Helicity::SSSVertexPtr;
/** \ingroup Decay
* The SSDecayer class implements the decay of a scalar
* to 2 scalars in a general model. It holds a SSSVertex
* pointer that must be typecast from the VertexBase pointer held in
* GeneralTwoBodyDecayer. It implents the virtual functions me2() and
* partialWidth().
*
* @see GeneralTwoBodyDecayer
*/
class SSSDecayer: public GeneralTwoBodyDecayer {
public:
/**
* The default constructor.
*/
- SSSDecayer();
+ SSSDecayer() {}
/** @name Virtual functions required by the Decayer class. */
//@{
/**
* Return the matrix element squared for a given mode and phase-space channel.
* @param ichan The channel we are calculating the matrix element for.
* @param part The decaying Particle.
* @param decay The particles produced in the decay.
* @param meopt Option for the calculation of the matrix element
* @return The matrix element squared for the phase-space configuration.
*/
virtual double me2(const int ichan, const Particle & part,
const ParticleVector & decay, MEOption meopt) const;
/**
* Function to return partial Width
* @param inpart The decaying particle.
* @param outa One of the decay products.
* @param outb The other decay product.
*/
virtual Energy partialWidth(PMPair inpart, PMPair outa,
PMPair outb) const;
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
virtual IBPtr fullclone() const;
//@}
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving and
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit();
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<SSSDecayer> initSSSDecayer;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
SSSDecayer & operator=(const SSSDecayer &);
private:
/**
* Abstract pointer to AbstractSSSVertex
*/
AbstractSSSVertexPtr _abstractVertex;
/**
* Pointer to the perturbative vertex
*/
SSSVertexPtr _perturbativeVertex;
/**
* Spin density matrix
*/
mutable RhoDMatrix _rho;
/**
* Scalar wavefunctions
*/
mutable Helicity::ScalarWaveFunction _swave;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of SSSDecayer. */
template <>
struct BaseClassTrait<Herwig::SSSDecayer,1> {
/** Typedef of the first base class of SSSDecayer. */
typedef Herwig::GeneralTwoBodyDecayer NthBase;
};
/** This template specialization informs ThePEG about the name of
* the SSSDecayer class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::SSSDecayer>
: public ClassTraitsBase<Herwig::SSSDecayer> {
/** Return a platform-independent class name */
static string className() { return "Herwig::SSSDecayer"; }
};
/** @endcond */
}
#endif /* HERWIG_SSSDecayer_H */
diff --git a/Decay/General/SSVDecayer.cc b/Decay/General/SSVDecayer.cc
--- a/Decay/General/SSVDecayer.cc
+++ b/Decay/General/SSVDecayer.cc
@@ -1,138 +1,133 @@
// -*- C++ -*-
//
// SSVDecayer.cc is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the SSVDecayer class.
//
#include "SSVDecayer.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/DecayMode.h"
#include "Herwig++/Utilities/Kinematics.h"
#include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
using namespace Herwig;
using namespace ThePEG::Helicity;
-SSVDecayer::SSVDecayer() {
- addToSearchList(1);
- addToSearchList(2);
-}
-
IBPtr SSVDecayer::clone() const {
return new_ptr(*this);
}
IBPtr SSVDecayer::fullclone() const {
return new_ptr(*this);
}
void SSVDecayer::doinit() {
_perturbativeVertex = dynamic_ptr_cast<VSSVertexPtr> (getVertex());
_abstractVertex = dynamic_ptr_cast<AbstractVSSVertexPtr>(getVertex());
GeneralTwoBodyDecayer::doinit();
}
void SSVDecayer::persistentOutput(PersistentOStream & os) const {
os << _abstractVertex << _perturbativeVertex;
}
void SSVDecayer::persistentInput(PersistentIStream & is, int) {
is >> _abstractVertex >> _perturbativeVertex;
}
ClassDescription<SSVDecayer> SSVDecayer::initSSVDecayer;
// Definition of the static class description member.
void SSVDecayer::Init() {
static ClassDocumentation<SSVDecayer> documentation
("This implements the decay of a scalar to a vector and a scalar");
}
double SSVDecayer::me2(const int , const Particle & inpart,
const ParticleVector & decay,
MEOption meopt) const {
unsigned int isc(0),ivec(1);
if(decay[0]->dataPtr()->iSpin() != PDT::Spin0) swap(isc,ivec);
if(meopt==Initialize) {
ScalarWaveFunction::
calculateWaveFunctions(_rho,const_ptr_cast<tPPtr>(&inpart),incoming);
_swave = ScalarWaveFunction(inpart.momentum(),inpart.dataPtr(),incoming);
if(ivec==1)
ME(DecayMatrixElement(PDT::Spin0,PDT::Spin0,PDT::Spin1));
else
ME(DecayMatrixElement(PDT::Spin0,PDT::Spin1,PDT::Spin0));
}
if(meopt==Terminate) {
ScalarWaveFunction::
constructSpinInfo(const_ptr_cast<tPPtr>(&inpart),incoming,true);
ScalarWaveFunction::
constructSpinInfo(decay[isc],outgoing,true);
VectorWaveFunction::
constructSpinInfo(_vector,decay[ivec],outgoing,true,false);
}
VectorWaveFunction::
calculateWaveFunctions(_vector,decay[ivec],outgoing,false);
ScalarWaveFunction sca(decay[isc]->momentum(),decay[isc]->dataPtr(),outgoing);
Energy2 scale(sqr(inpart.mass()));
//make sure decay matrix element is in the correct order
double output(0.);
if(ivec == 0) {
for(unsigned int ix = 0; ix < 3; ++ix)
ME()(0, ix, 0) = _abstractVertex->evaluate(scale,_vector[ix],sca, _swave);
}
else {
for(unsigned int ix = 0; ix < 3; ++ix)
ME()(0, 0, ix) = _abstractVertex->evaluate(scale,_vector[ix],sca,_swave);
}
output = (ME().contract(_rho)).real()/scale*UnitRemoval::E2;
// colour and identical particle factors
output *= colourFactor(inpart.dataPtr(),decay[0]->dataPtr(),
decay[1]->dataPtr());
// return the answer
return output;
}
Energy SSVDecayer:: partialWidth(PMPair inpart, PMPair outa,
PMPair outb) const {
if( inpart.second < outa.second + outb.second ) return ZERO;
if(_perturbativeVertex) {
double mu1sq(sqr(outa.second/inpart.second)),
mu2sq(sqr(outb.second/inpart.second));
tcPDPtr in = inpart.first->CC() ? tcPDPtr(inpart.first->CC()) : inpart.first;
if(outa.first->iSpin() == PDT::Spin0) {
_perturbativeVertex->setCoupling(sqr(inpart.second), outb.first, outa.first,in);
}
else {
swap(mu1sq,mu2sq);
_perturbativeVertex->setCoupling(sqr(inpart.second), outa.first, outb.first,in);
}
double me2(0.);
if(mu2sq == 0.)
me2 = -2.*mu1sq - 2.;
else
me2 = ( sqr(mu2sq - mu1sq) - 2.*(mu2sq + mu1sq) + 1. )/mu2sq;
Energy pcm = Kinematics::pstarTwoBodyDecay(inpart.second, outa.second,
outb.second);
Energy output = pcm*me2*norm(_perturbativeVertex->norm())/8./Constants::pi;
// colour factor
output *= colourFactor(inpart.first,outa.first,outb.first);
// return the answer
return output;
}
else {
return GeneralTwoBodyDecayer::partialWidth(inpart,outa,outb);
}
}
diff --git a/Decay/General/SSVDecayer.h b/Decay/General/SSVDecayer.h
--- a/Decay/General/SSVDecayer.h
+++ b/Decay/General/SSVDecayer.h
@@ -1,192 +1,192 @@
// -*- C++ -*-
//
// SSVDecayer.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_SSVDecayer_H
#define HERWIG_SSVDecayer_H
//
// This is the declaration of the SSVDecayer class.
//
#include "GeneralTwoBodyDecayer.h"
#include "ThePEG/Helicity/Vertex/Scalar/VSSVertex.h"
#include "ThePEG/Repository/EventGenerator.h"
namespace Herwig {
using namespace ThePEG;
using Helicity::VSSVertexPtr;
/** \ingroup Decay
* The SSVDecayer class implements the decay of a scalar to a vector
* and a scalar in a general model. It holds an VSSVertex pointer
* that must be typecast from the VertexBase pointer held in
* GeneralTwoBodyDecayer. It implents the virtual functions me2() and
* partialWidth().
*
* @see GeneralTwoBodyDecayer
*/
class SSVDecayer: public GeneralTwoBodyDecayer {
public:
/**
* The default constructor.
*/
- SSVDecayer();
+ SSVDecayer() {}
/** @name Virtual functions required by the Decayer class. */
//@{
/**
* Return the matrix element squared for a given mode and phase-space channel
* @param ichan The channel we are calculating the matrix element for.
* @param part The decaying Particle.
* @param decay The particles produced in the decay.
* @param meopt Option for the calculation of the matrix element
* @return The matrix element squared for the phase-space configuration.
*/
virtual double me2(const int ichan, const Particle & part,
const ParticleVector & decay, MEOption meopt) const;
/**
* Function to return partial Width
* @param inpart The decaying particle.
* @param outa One of the decay products.
* @param outb The other decay product.
*/
virtual Energy partialWidth(PMPair inpart, PMPair outa,
PMPair outb) const;
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
virtual IBPtr fullclone() const;
//@}
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();
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<SSVDecayer> initSSVDecayer;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
SSVDecayer & operator=(const SSVDecayer &);
private:
/**
* Abstract pointer to AbstractFFVVertex
*/
AbstractVSSVertexPtr _abstractVertex;
/**
* Pointer to the perturbative vertex
*/
VSSVertexPtr _perturbativeVertex;
/**
* Spinr density matrix
*/
mutable RhoDMatrix _rho;
/**
* Scalar wavefunction
*/
mutable Helicity::ScalarWaveFunction _swave;
/**
* Vector wavefunction
*/
mutable vector<Helicity::VectorWaveFunction> _vector;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of SSVDecayer. */
template <>
struct BaseClassTrait<Herwig::SSVDecayer,1> {
/** Typedef of the first base class of SSVDecayer. */
typedef Herwig::GeneralTwoBodyDecayer NthBase;
};
/** This template specialization informs ThePEG about the name of
* the SSVDecayer class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::SSVDecayer>
: public ClassTraitsBase<Herwig::SSVDecayer> {
/** Return a platform-independent class name */
static string className() { return "Herwig::SSVDecayer"; }
};
/** @endcond */
}
#endif /* HERWIG_SSVDecayer_H */
diff --git a/Decay/General/SVVDecayer.cc b/Decay/General/SVVDecayer.cc
--- a/Decay/General/SVVDecayer.cc
+++ b/Decay/General/SVVDecayer.cc
@@ -1,138 +1,137 @@
// -*- C++ -*-
//
// SVVDecayer.cc is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the SVVDecayer class.
//
#include "SVVDecayer.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/DecayMode.h"
#include "ThePEG/Helicity/Vertex/Scalar/VVSVertex.h"
#include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
#include "Herwig++/Utilities/Kinematics.h"
using namespace Herwig;
using namespace ThePEG::Helicity;
IBPtr SVVDecayer::clone() const {
return new_ptr(*this);
}
IBPtr SVVDecayer::fullclone() const {
return new_ptr(*this);
}
void SVVDecayer::doinit() {
GeneralTwoBodyDecayer::doinit();
_abstractVertex = dynamic_ptr_cast<AbstractVVSVertexPtr>(getVertex());
_perturbativeVertex = dynamic_ptr_cast<VVSVertexPtr >(getVertex());
- GeneralTwoBodyDecayer::doinit();
}
void SVVDecayer::doinitrun() {
getVertex()->initrun();
GeneralTwoBodyDecayer::doinitrun();
}
void SVVDecayer::persistentOutput(PersistentOStream & os) const {
os << _abstractVertex << _perturbativeVertex;
}
void SVVDecayer::persistentInput(PersistentIStream & is, int) {
is >> _abstractVertex >> _perturbativeVertex;
}
ClassDescription<SVVDecayer> SVVDecayer::initSVVDecayer;
// Definition of the static class description member.
void SVVDecayer::Init() {
static ClassDocumentation<SVVDecayer> documentation
("This implements the decay of a scalar to 2 vector bosons.");
}
double SVVDecayer::me2(const int , const Particle & inpart,
const ParticleVector& decay,
MEOption meopt) const {
bool photon[2];
for(unsigned int ix=0;ix<2;++ix)
photon[ix] = decay[ix]->mass()==ZERO;
if(meopt==Initialize) {
ScalarWaveFunction::
calculateWaveFunctions(_rho,const_ptr_cast<tPPtr>(&inpart),incoming);
_swave = ScalarWaveFunction(inpart.momentum(),inpart.dataPtr(),incoming);
ME(DecayMatrixElement(PDT::Spin0,PDT::Spin1,PDT::Spin1));
}
if(meopt==Terminate) {
ScalarWaveFunction::
constructSpinInfo(const_ptr_cast<tPPtr>(&inpart),incoming,true);
for(unsigned int ix=0;ix<2;++ix)
VectorWaveFunction::
constructSpinInfo(_vectors[ix],decay[ix],outgoing,true,photon[ix]);
}
for(unsigned int ix=0;ix<2;++ix)
VectorWaveFunction::
calculateWaveFunctions(_vectors[ix],decay[ix],outgoing,photon[ix]);
Energy2 scale(sqr(inpart.mass()));
unsigned int iv1,iv2;
for(iv2 = 0; iv2 < 3; ++iv2) {
if( photon[1] && iv2 == 1 ) ++iv2;
for(iv1=0;iv1<3;++iv1) {
if( photon[0] && iv1 == 1) ++iv1;
ME()(0, iv1, iv2) = _abstractVertex->evaluate(scale,_vectors[0][iv1],
_vectors[1][iv2],_swave);
}
}
double output = ME().contract(_rho).real()/scale*UnitRemoval::E2;
// colour and identical particle factors
output *= colourFactor(inpart.dataPtr(),decay[0]->dataPtr(),
decay[1]->dataPtr());
// return the answer
return output;
}
Energy SVVDecayer::partialWidth(PMPair inpart, PMPair outa,
PMPair outb) const {
if( inpart.second < outa.second + outb.second ) return ZERO;
if(_perturbativeVertex) {
Energy2 scale(sqr(inpart.second));
tcPDPtr in = inpart.first->CC() ? tcPDPtr(inpart.first->CC()) : inpart.first;
_perturbativeVertex->setCoupling(scale, outa.first ,
outb.first, in);
double mu1sq = sqr(outa.second/inpart.second);
double mu2sq = sqr(outb.second/inpart.second);
double m1pm2 = mu1sq + mu2sq;
double me2(0.);
if( mu1sq > 0. && mu2sq > 0.)
me2 = ( m1pm2*(m1pm2 - 2.) + 8.*mu1sq*mu2sq + 1.)/4./mu1sq/mu2sq;
else if( mu1sq == 0. || mu2sq == 0. )
me2 = 3.;
else
me2 = 4.;
Energy pcm = Kinematics::pstarTwoBodyDecay(inpart.second,outa.second,
outb.second);
Energy output = norm(_perturbativeVertex->norm())*
me2*pcm/(8*Constants::pi)/scale*UnitRemoval::E2;
// colour factor
output *= colourFactor(inpart.first,outa.first,outb.first);
// return the answer
return output;
}
else {
return GeneralTwoBodyDecayer::partialWidth(inpart,outa,outb);
}
}
diff --git a/Decay/General/SVVDecayer.h b/Decay/General/SVVDecayer.h
--- a/Decay/General/SVVDecayer.h
+++ b/Decay/General/SVVDecayer.h
@@ -1,201 +1,201 @@
// -*- C++ -*-
//
// SVVDecayer.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_SVVDecayer_H
#define HERWIG_SVVDecayer_H
//
// This is the declaration of the SVVDecayer class.
//
#include "GeneralTwoBodyDecayer.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Helicity/Vertex/AbstractVVSVertex.fh"
#include "ThePEG/Helicity/Vertex/Scalar/VVSVertex.fh"
#include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
namespace Herwig {
using namespace ThePEG;
using Helicity::VVSVertexPtr;
/** \ingroup Decay
* This SVVDecayer class implements the decay of a scalar to
* 2 vector bosons using either the tree level VVSVertex or the loop vertex.
* It inherits from
* GeneralTwoBodyDecayer and implements the virtual member functions me2()
* and partialWidth(). It also stores a pointer to the VVSVertex.
*
* @see GeneralTwoBodyDecayer
*
*/
class SVVDecayer: public GeneralTwoBodyDecayer {
public:
/**
* The default constructor.
*/
- SVVDecayer() { addToSearchList(2); }
+ SVVDecayer() {}
/** @name Virtual functions required by the Decayer class. */
//@{
/**
* Return the matrix element squared for a given mode and phase-space channel.
* @param ichan The channel we are calculating the matrix element for.
* @param part The decaying Particle.
* @param decay The particles produced in the decay.
* @param meopt Option for the calculation of the matrix element
* @return The matrix element squared for the phase-space configuration.
*/
virtual double me2(const int ichan, const Particle & part,
const ParticleVector & decay, MEOption meopt) const;
/**
* Function to return partial Width
* @param inpart The decaying particle.
* @param outa One of the decay products.
* @param outb The other decay product.
*/
virtual Energy partialWidth(PMPair inpart, PMPair outa,
PMPair outb) const;
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
virtual IBPtr fullclone() const;
//@}
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving and
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit();
/**
* Initialize this object. Called in the run phase just before
* a run begins.
*/
virtual void doinitrun();
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<SVVDecayer> initSVVDecayer;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
SVVDecayer & operator=(const SVVDecayer &);
private:
/**
* Abstract pointer to general VVS vertex
*/
AbstractVVSVertexPtr _abstractVertex;
/**
* Pointer to the perturbative form
*/
VVSVertexPtr _perturbativeVertex;
/**
* Spin density matrix
*/
mutable RhoDMatrix _rho;
/**
* Scalar wavefunction
*/
mutable Helicity::ScalarWaveFunction _swave;
/**
* Vector wavefunctions
*/
mutable vector<Helicity::VectorWaveFunction> _vectors[2];
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of SVVDecayer. */
template <>
struct BaseClassTrait<Herwig::SVVDecayer,1> {
/** Typedef of the first base class of SVVDecayer. */
typedef Herwig::GeneralTwoBodyDecayer NthBase;
};
/** This template specialization informs ThePEG about the name of
* the SVVDecayer class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::SVVDecayer>
: public ClassTraitsBase<Herwig::SVVDecayer> {
/** Return a platform-independent class name */
static string className() { return "Herwig::SVVDecayer"; }
};
/** @endcond */
}
#endif /* HERWIG_SVVDecayer_H */
diff --git a/Decay/General/StoFFVDecayer.cc b/Decay/General/StoFFVDecayer.cc
--- a/Decay/General/StoFFVDecayer.cc
+++ b/Decay/General/StoFFVDecayer.cc
@@ -1,327 +1,327 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the StoFFVDecayer class.
//
#include "StoFFVDecayer.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "Herwig++/PDT/ThreeBodyAllOnCalculator.h"
#include <numeric>
using namespace Herwig;
using namespace ThePEG;
using namespace ThePEG::Helicity;
IBPtr StoFFVDecayer::clone() const {
return new_ptr(*this);
}
IBPtr StoFFVDecayer::fullclone() const {
return new_ptr(*this);
}
void StoFFVDecayer::persistentOutput(PersistentOStream & os) const {
os << _sca << _fer << _vec;
}
void StoFFVDecayer::persistentInput(PersistentIStream & is, int) {
is >> _sca >> _fer >> _vec;
}
ClassDescription<StoFFVDecayer> StoFFVDecayer::initStoFFVDecayer;
// Definition of the static class description member.
void StoFFVDecayer::Init() {
static ClassDocumentation<StoFFVDecayer> documentation
("The StoFFVDecayer class implements the general decay of a scalar to "
"a two fermions and a vector.");
}
WidthCalculatorBasePtr StoFFVDecayer::
threeBodyMEIntegrator(const DecayMode & ) const {
vector<int> intype;
vector<Energy> inmass,inwidth;
vector<double> inpow,inweights;
constructIntegratorChannels(intype,inmass,inwidth,inpow,inweights);
return new_ptr(ThreeBodyAllOnCalculator<StoFFVDecayer>
(inweights,intype,inmass,inwidth,inpow,*this,0,
outgoing()[0]->mass(),outgoing()[1]->mass(),
- outgoing()[2]->mass()));
+ outgoing()[2]->mass(),relativeError()));
}
void StoFFVDecayer::doinit() {
GeneralThreeBodyDecayer::doinit();
unsigned int ndiags = getProcessInfo().size();
_sca.resize(ndiags);
_fer.resize(ndiags);
_vec.resize(ndiags);
for(unsigned int ix = 0;ix < ndiags; ++ix) {
TBDiagram current = getProcessInfo()[ix];
tcPDPtr offshell = current.intermediate;
if( offshell->CC() ) offshell = offshell->CC();
if(offshell->iSpin() == PDT::Spin0) {
AbstractVSSVertexPtr vert1 = dynamic_ptr_cast<AbstractVSSVertexPtr>
(current.vertices.first);
AbstractFFSVertexPtr vert2 = dynamic_ptr_cast<AbstractFFSVertexPtr>
(current.vertices.second);
if(!vert1||!vert2) throw Exception()
<< "Invalid vertices for a scalar diagram in StoFFVDecayer::doinit()"
<< Exception::runerror;
_sca[ix] = make_pair(vert1, vert2);
}
else if(offshell->iSpin() == PDT::Spin1Half) {
AbstractFFSVertexPtr vert1 = dynamic_ptr_cast<AbstractFFSVertexPtr>
(current.vertices.first);
AbstractFFVVertexPtr vert2 = dynamic_ptr_cast<AbstractFFVVertexPtr>
(current.vertices.second);
if(!vert1||!vert2) throw Exception()
<< "Invalid vertices for a fermion diagram in StoFFVDecayer::doinit()"
<< Exception::runerror;
_fer[ix] = make_pair(vert1, vert2);
}
else if(offshell->iSpin() == PDT::Spin1) {
AbstractVVSVertexPtr vert1 = dynamic_ptr_cast<AbstractVVSVertexPtr>
(current.vertices.first);
AbstractFFVVertexPtr vert2 = dynamic_ptr_cast<AbstractFFVVertexPtr>
(current.vertices.second);
if(!vert1||!vert2) throw Exception()
<< "Invalid vertices for a vector diagram in StoFFVDecayer::doinit()"
<< Exception::runerror;
_vec[ix] = make_pair(vert1, vert2);
}
}
}
double StoFFVDecayer::me2(const int ichan, const Particle & inpart,
const ParticleVector & decay, MEOption meopt) const {
// particle or CC of particle
bool cc = (*getProcessInfo().begin()).incoming != inpart.id();
// special handling or first/last call
if(meopt==Initialize) {
ScalarWaveFunction::
calculateWaveFunctions(_rho,const_ptr_cast<tPPtr>(&inpart),
Helicity::incoming);
_swave = ScalarWaveFunction(inpart.momentum(),inpart.dataPtr(),
Helicity::incoming);
}
if(meopt==Terminate) {
ScalarWaveFunction::
constructSpinInfo(const_ptr_cast<tPPtr>(&inpart),
Helicity::incoming,true);
for(unsigned int ix=0;ix<decay.size();++ix) {
if(decay[ix]->dataPtr()->iSpin()==PDT::Spin1) {
VectorWaveFunction::constructSpinInfo(_outVector,decay[ix],
Helicity::outgoing,true,false);
}
else {
SpinorWaveFunction::
constructSpinInfo(_outspin[ix].first,decay[ix],Helicity::outgoing,true);
}
}
}
unsigned int ivec(0);
bool massless(false);
for(unsigned int ix = 0; ix < decay.size();++ix) {
if(decay[ix]->dataPtr()->iSpin() == PDT::Spin1) {
ivec = ix;
massless = decay[ivec]->mass()==ZERO;
VectorWaveFunction::
calculateWaveFunctions(_outVector, decay[ix], Helicity::outgoing,massless);
}
else {
SpinorWaveFunction::
calculateWaveFunctions(_outspin[ix].first,decay[ix],Helicity::outgoing);
_outspin[ix].second.resize(2);
// Need a ubar and a v spinor
if(_outspin[ix].first[0].wave().Type() == u_spinortype) {
for(unsigned int iy = 0; iy < 2; ++iy) {
_outspin[ix].second[iy] = _outspin[ix].first[iy].bar();
_outspin[ix].first[iy].conjugate();
}
}
else {
for(unsigned int iy = 0; iy < 2; ++iy) {
_outspin[ix].second[iy] = _outspin[ix].first[iy].bar();
_outspin[ix].second[iy].conjugate();
}
}
}
}
const vector<vector<double> > cfactors(getColourFactors());
const vector<vector<double> > nfactors(getLargeNcColourFactors());
Energy2 scale(sqr(inpart.mass()));
const size_t ncf(numberOfFlows());
vector<Complex> flows(ncf, Complex(0.)), largeflows(ncf, Complex(0.));
// setup the DecayMatrixElement
vector<DecayMatrixElement>
mes(ncf,DecayMatrixElement(PDT::Spin0,
ivec == 0 ? PDT::Spin1 : PDT::Spin1Half,
ivec == 1 ? PDT::Spin1 : PDT::Spin1Half,
ivec == 2 ? PDT::Spin1 : PDT::Spin1Half));
vector<DecayMatrixElement>
mel(ncf,DecayMatrixElement(PDT::Spin0,
ivec == 0 ? PDT::Spin1 : PDT::Spin1Half,
ivec == 1 ? PDT::Spin1 : PDT::Spin1Half,
ivec == 2 ? PDT::Spin1 : PDT::Spin1Half));
//the channel possiblities
static const unsigned int out2[3] = {1,0,0}, out3[3] = {2,2,1};
for(unsigned int s1 = 0; s1 < 2; ++s1) {
for(unsigned int s2 = 0; s2 < 2; ++s2) {
for(unsigned int v1 = 0; v1 < 3; ++v1) {
if(massless&&v1==1) ++v1;
flows = vector<Complex>(ncf, Complex(0.));
largeflows = vector<Complex>(ncf, Complex(0.));
unsigned int idiag(0);
for(vector<TBDiagram>::const_iterator dit=getProcessInfo().begin();
dit!=getProcessInfo().end();++dit) {
// channels if selecting
if( ichan >= 0 && diagramMap()[ichan] != idiag ) {
++idiag;
continue;
}
tcPDPtr offshell = dit->intermediate;
if(cc&&offshell->CC()) offshell=offshell->CC();
Complex diag;
unsigned int o2(out2[dit->channelType]), o3(out3[dit->channelType]);
double sign = (o3 < o2) ? 1. : -1.;
// intermediate scalar
if(offshell->iSpin() == PDT::Spin0) {
ScalarWaveFunction inters = _sca[idiag].first->
evaluate(scale, widthOption(), offshell, _outVector[v1], _swave);
unsigned int h1(s1),h2(s2);
if(o2 > o3) swap(h1, h2);
if(decay[o2]->id() < 0 && decay[o3]->id() > 0) {
diag = -sign*_sca[idiag].second->
evaluate(scale,_outspin[o2].first[h1],
_outspin[o3].second[h2],inters);
}
else {
diag = sign*_sca[idiag].second->
evaluate(scale, _outspin[o3].first [h2],
_outspin[o2].second[h1],inters);
}
}
// intermediate fermion
else if(offshell->iSpin() == PDT::Spin1Half) {
int iferm = (decay[o2]->dataPtr()->iSpin() == PDT::Spin1Half)
? o2 : o3;
unsigned int h1(s1),h2(s2);
if(dit->channelType > iferm) swap(h1, h2);
sign = iferm < dit->channelType ? 1. : -1.;
if(decay[dit->channelType]->id() < 0 && decay[iferm]->id() > 0 ) {
SpinorWaveFunction inters = _fer[idiag].first->
evaluate(scale,widthOption(),offshell,
_outspin[dit->channelType].first[h1], _swave);
diag = -sign*_fer[idiag].second->
evaluate(scale,inters,_outspin[iferm].second[h2], _outVector[v1]);
}
else {
SpinorBarWaveFunction inters = _fer[idiag].first->
evaluate(scale,widthOption(),offshell,
_outspin[dit->channelType].second[h1],_swave);
diag = sign*_fer[idiag].second->
evaluate(scale,_outspin[iferm].first [h2],inters, _outVector[v1]);
}
}
// intermediate vector
else if(offshell->iSpin() == PDT::Spin1) {
VectorWaveFunction interv = _vec[idiag].first->
evaluate(scale, widthOption(), offshell, _outVector[v1], _swave);
unsigned int h1(s1),h2(s2);
if(o2 > o3) swap(h1,h2);
if(decay[o2]->id() < 0 && decay[o3]->id() > 0) {
diag =-sign*_vec[idiag].second->
evaluate(scale, _outspin[o2].first[h1],
_outspin[o3].second[h2], interv);
}
else {
diag = sign*_vec[idiag].second->
evaluate(scale, _outspin[o3].first[h2],
_outspin[o2].second[h1], interv);
}
}
// unknown
else throw Exception()
<< "Unknown intermediate in StoFFVDecayer::me2()"
<< Exception::runerror;
// matrix element for the different colour flows
if(ichan < 0) {
for(unsigned iy = 0; iy < dit->colourFlow.size(); ++iy) {
flows[dit->colourFlow[iy].first - 1] +=
dit->colourFlow[iy].second * diag;
}
for(unsigned iy = 0; iy < dit->largeNcColourFlow.size(); ++iy) {
largeflows[dit->largeNcColourFlow[iy].first - 1] +=
dit->largeNcColourFlow[iy].second * diag;
}
}
else {
for(unsigned iy = 0; iy < dit->colourFlow.size(); ++iy) {
if(dit->colourFlow[iy].first - 1 != colourFlow()) continue;
flows[dit->colourFlow[iy].first - 1] +=
dit->colourFlow[iy].second * diag;
}
for(unsigned iy = 0; iy < dit->largeNcColourFlow.size(); ++iy) {
if(dit->colourFlow[iy].first - 1!=colourFlow()) continue;
largeflows[dit->largeNcColourFlow[iy].first - 1] +=
dit->largeNcColourFlow[iy].second * diag;
}
}
++idiag;
} //end of diagrams
// now add the flows to the me2 with appropriate colour factors
for(unsigned int ix = 0; ix < ncf; ++ix) {
if ( ivec == 0 ) {
mes[ix](0, v1, s1, s2) = flows[ix];
mel[ix](0, v1, s1, s2) = largeflows[ix];
}
else if( ivec == 1 ) {
mes[ix](0, s1, v1, s2) = flows[ix];
mel[ix](0, s1, v1, s2) = largeflows[ix];
}
else if( ivec == 2 ) {
mes[ix](0, s1, s2, v1) = flows[ix];
mel[ix](0, s1, s2, v1) = largeflows[ix];
}
}
}
}
}
double me2(0.);
if(ichan < 0) {
vector<double> pflows(ncf,0.);
for(unsigned int ix = 0; ix < ncf; ++ix) {
for(unsigned int iy = 0; iy < ncf; ++ iy) {
double con = cfactors[ix][iy]*(mes[ix].contract(mes[iy],_rho)).real();
me2 += con;
if(ix == iy) {
con = nfactors[ix][iy]*(mel[ix].contract(mel[iy],_rho)).real();
pflows[ix] += con;
}
}
}
double ptotal(std::accumulate(pflows.begin(),pflows.end(),0.));
ptotal *= UseRandom::rnd();
for(unsigned int ix = 0;ix < pflows.size(); ++ix) {
if(ptotal <= pflows[ix]) {
colourFlow(ix);
ME(mes[ix]);
break;
}
ptotal -= pflows[ix];
}
}
else {
unsigned int iflow = colourFlow();
me2 = nfactors[iflow][iflow]*(mel[iflow].contract(mel[iflow],_rho)).real();
}
// return the matrix element squared
return me2;
}
diff --git a/Decay/General/StoSFFDecayer.cc b/Decay/General/StoSFFDecayer.cc
--- a/Decay/General/StoSFFDecayer.cc
+++ b/Decay/General/StoSFFDecayer.cc
@@ -1,355 +1,356 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the StoSFFDecayer class.
//
#include "StoSFFDecayer.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "Herwig++/PDT/ThreeBodyAllOnCalculator.h"
#include <numeric>
using namespace Herwig;
using namespace ThePEG;
using namespace ThePEG::Helicity;
IBPtr StoSFFDecayer::clone() const {
return new_ptr(*this);
}
IBPtr StoSFFDecayer::fullclone() const {
return new_ptr(*this);
}
void StoSFFDecayer::persistentOutput(PersistentOStream & os) const {
os << _sca << _fer << _vec << _ten;
}
void StoSFFDecayer::persistentInput(PersistentIStream & is, int) {
is >> _sca >> _fer >> _vec >> _ten;
}
ClassDescription<StoSFFDecayer> StoSFFDecayer::initStoSFFDecayer;
// Definition of the static class description member.
void StoSFFDecayer::Init() {
static ClassDocumentation<StoSFFDecayer> documentation
("The StoSFFDecayer class implements the general decay of a scalar to "
"a scalar and two fermions.");
}
WidthCalculatorBasePtr StoSFFDecayer::
threeBodyMEIntegrator(const DecayMode & ) const {
vector<int> intype;
vector<Energy> inmass,inwidth;
vector<double> inpow,inweights;
constructIntegratorChannels(intype,inmass,inwidth,inpow,inweights);
return new_ptr(ThreeBodyAllOnCalculator<StoSFFDecayer>
(inweights,intype,inmass,inwidth,inpow,*this,0,
- outgoing()[0]->mass(),outgoing()[1]->mass(),outgoing()[2]->mass()));
+ outgoing()[0]->mass(),outgoing()[1]->mass(),outgoing()[2]->mass(),
+ relativeError()));
}
void StoSFFDecayer::doinit() {
GeneralThreeBodyDecayer::doinit();
unsigned int ndiags = getProcessInfo().size();
_sca.resize(ndiags);
_fer.resize(ndiags);
_vec.resize(ndiags);
_ten.resize(ndiags);
for(unsigned int ix = 0;ix < ndiags; ++ix) {
TBDiagram current = getProcessInfo()[ix];
tcPDPtr offshell = current.intermediate;
if( offshell->CC() ) offshell = offshell->CC();
if(offshell->iSpin() == PDT::Spin0) {
AbstractSSSVertexPtr vert1 = dynamic_ptr_cast<AbstractSSSVertexPtr>
(current.vertices.first);
AbstractFFSVertexPtr vert2 = dynamic_ptr_cast<AbstractFFSVertexPtr>
(current.vertices.second);
if(!vert1||!vert2) throw Exception()
<< "Invalid vertices for a scalar diagram in StoSFFDecayer::doinit()"
<< Exception::runerror;
_sca[ix] = make_pair(vert1, vert2);
}
else if(offshell->iSpin() == PDT::Spin1Half) {
AbstractFFSVertexPtr vert1 = dynamic_ptr_cast<AbstractFFSVertexPtr>
(current.vertices.first);
AbstractFFSVertexPtr vert2 = dynamic_ptr_cast<AbstractFFSVertexPtr>
(current.vertices.second);
if(!vert1||!vert2) throw Exception()
<< "Invalid vertices for a fermion diagram in StoSFFDecayer::doinit()"
<< Exception::runerror;
_fer[ix] = make_pair(vert1, vert2);
}
else if(offshell->iSpin() == PDT::Spin1) {
AbstractVSSVertexPtr vert1 = dynamic_ptr_cast<AbstractVSSVertexPtr>
(current.vertices.first);
AbstractFFVVertexPtr vert2 = dynamic_ptr_cast<AbstractFFVVertexPtr>
(current.vertices.second);
if(!vert1||!vert2) throw Exception()
<< "Invalid vertices for a vector diagram in StoSFFDecayer::doinit()"
<< Exception::runerror;
_vec[ix] = make_pair(vert1, vert2);
}
else if(offshell->iSpin() == PDT::Spin2) {
AbstractSSTVertexPtr vert1 = dynamic_ptr_cast<AbstractSSTVertexPtr>
(current.vertices.first);
AbstractFFTVertexPtr vert2 = dynamic_ptr_cast<AbstractFFTVertexPtr>
(current.vertices.second);
if(!vert1||!vert2) throw Exception()
<< "Invalid vertices for a tensor diagram in StoSFFDecayer::doinit()"
<< Exception::runerror;
_ten[ix] = make_pair(vert1, vert2);
}
}
}
double StoSFFDecayer::me2(const int ichan, const Particle & inpart,
const ParticleVector & decay,
MEOption meopt) const {
// particle or CC of particle
bool cc = (*getProcessInfo().begin()).incoming != inpart.id();
// special handling or first/last call
if(meopt==Initialize) {
ScalarWaveFunction::
calculateWaveFunctions(_rho,const_ptr_cast<tPPtr>(&inpart),
Helicity::incoming);
_swave = ScalarWaveFunction(inpart.momentum(),inpart.dataPtr(),
Helicity::incoming);
}
if(meopt==Terminate) {
ScalarWaveFunction::
constructSpinInfo(const_ptr_cast<tPPtr>(&inpart),
Helicity::incoming,true);
for(unsigned int ix=0;ix<decay.size();++ix) {
if(decay[ix]->dataPtr()->iSpin()==PDT::Spin0) {
ScalarWaveFunction::constructSpinInfo(decay[ix],Helicity::outgoing,true);
}
else {
SpinorWaveFunction::
constructSpinInfo(_outspin[ix].first,decay[ix],Helicity::outgoing,true);
}
}
return 0.;
}
// get the wavefunctions for all the particles
ScalarWaveFunction outScalar;
unsigned int isca(0);
for(unsigned int ix=0;ix<decay.size();++ix) {
if(decay[ix]->dataPtr()->iSpin()==PDT::Spin0) {
isca = ix;
outScalar = ScalarWaveFunction(decay[ix]->momentum(),
decay[ix]->dataPtr(),Helicity::outgoing);
}
else {
SpinorWaveFunction::
calculateWaveFunctions(_outspin[ix].first,decay[ix],Helicity::outgoing);
_outspin[ix].second.resize(2);
if(_outspin[ix].first[0].wave().Type() == u_spinortype) {
for(unsigned int iy = 0; iy < 2; ++iy) {
_outspin[ix].second[iy] = _outspin[ix].first[iy].bar();
_outspin[ix].first[iy].conjugate();
}
}
else {
for(unsigned int iy = 0; iy < 2; ++iy) {
_outspin[ix].second[iy] = _outspin[ix].first[iy].bar();
_outspin[ix].second[iy].conjugate();
}
}
}
}
const vector<vector<double> > cfactors(getColourFactors());
const vector<vector<double> > nfactors(getLargeNcColourFactors());
Energy2 scale(sqr(inpart.mass()));
const size_t ncf(numberOfFlows());
vector<Complex> flows(ncf, Complex(0.)), largeflows(ncf, Complex(0.));
vector<DecayMatrixElement>
mes(ncf,DecayMatrixElement(PDT::Spin0,
isca==0 ? PDT::Spin0 : PDT::Spin1Half,
isca==1 ? PDT::Spin0 : PDT::Spin1Half,
isca==2 ? PDT::Spin0 : PDT::Spin1Half));
vector<DecayMatrixElement>
mel(ncf,DecayMatrixElement(PDT::Spin0,
isca == 0 ? PDT::Spin0 : PDT::Spin1Half,
isca == 1 ? PDT::Spin0 : PDT::Spin1Half,
isca == 2 ? PDT::Spin0 : PDT::Spin1Half));
static const unsigned int out2[3]={1,0,0},out3[3]={2,2,1};
for(unsigned int s1 = 0;s1 < 2; ++s1) {
for(unsigned int s2 = 0;s2 < 2; ++s2) {
flows = vector<Complex>(ncf, Complex(0.));
largeflows = vector<Complex>(ncf, Complex(0.));
unsigned int idiag(0);
for(vector<TBDiagram>::const_iterator dit = getProcessInfo().begin();
dit != getProcessInfo().end(); ++dit) {
// channels if selecting
if( ichan >= 0 && diagramMap()[ichan] != idiag ) {
++idiag;
continue;
}
tcPDPtr offshell = dit->intermediate;
if(cc&&offshell->CC()) offshell=offshell->CC();
Complex diag;
double sign = out3[dit->channelType] < out2[dit->channelType] ? 1. : -1.;
// intermediate scalar
if (offshell->iSpin() == PDT::Spin0) {
ScalarWaveFunction inters = _sca[idiag].first->
evaluate(scale, widthOption(), offshell, _swave, outScalar);
unsigned int h1(s1),h2(s2);
if(out2[dit->channelType]>out3[dit->channelType]) swap(h1,h2);
if(decay[out2[dit->channelType]]->id()<0&&
decay[out3[dit->channelType]]->id()>0) {
diag =-sign*_sca[idiag].second->
evaluate(scale,
_outspin[out2[dit->channelType]].first [h1],
_outspin[out3[dit->channelType]].second[h2],inters);
}
else {
diag = sign*_sca[idiag].second->
evaluate(scale,
_outspin[out3[dit->channelType]].first [h2],
_outspin[out2[dit->channelType]].second[h1],inters);
}
}
// intermediate fermion
else if(offshell->iSpin() == PDT::Spin1Half) {
int iferm =
decay[out2[dit->channelType]]->dataPtr()->iSpin()==PDT::Spin1Half
? out2[dit->channelType] : out3[dit->channelType];
unsigned int h1(s1),h2(s2);
if(dit->channelType>iferm) swap(h1,h2);
sign = iferm<dit->channelType ? 1. : -1.;
if(decay[dit->channelType]->id()<0&&decay[iferm]->id()>0) {
SpinorWaveFunction inters = _fer[idiag].first->
evaluate(scale,widthOption(),offshell,
_outspin[dit->channelType].first [h1],_swave);
diag = -sign*_fer[idiag].second->
evaluate(scale,inters,_outspin[iferm].second[h2],outScalar);
}
else {
SpinorBarWaveFunction inters = _fer[idiag].first->
evaluate(scale,widthOption(),offshell,
_outspin[dit->channelType].second[h1],_swave);
diag = sign*_fer[idiag].second->
evaluate(scale,_outspin[iferm].first [h2],inters,outScalar);
}
}
// intermediate vector
else if(offshell->iSpin() == PDT::Spin1) {
VectorWaveFunction interv = _vec[idiag].first->
evaluate(scale, widthOption(), offshell, _swave, outScalar);
unsigned int h1(s1),h2(s2);
if(out2[dit->channelType]>out3[dit->channelType]) swap(h1,h2);
if(decay[out2[dit->channelType]]->id()<0&&
decay[out3[dit->channelType]]->id()>0) {
diag =-sign*_vec[idiag].second->
evaluate(scale,
_outspin[out2[dit->channelType]].first [h1],
_outspin[out3[dit->channelType]].second[h2],interv);
}
else {
diag = sign*_vec[idiag].second->
evaluate(scale,
_outspin[out3[dit->channelType]].first [h2],
_outspin[out2[dit->channelType]].second[h1],interv);
}
}
// intermediate tensor
else if(offshell->iSpin() == PDT::Spin2) {
TensorWaveFunction intert = _ten[idiag].first->
evaluate(scale, widthOption(), offshell, _swave, outScalar);
unsigned int h1(s1),h2(s2);
if(out2[dit->channelType]>out3[dit->channelType]) swap(h1,h2);
if(decay[out2[dit->channelType]]->id()<0&&
decay[out3[dit->channelType]]->id()>0) {
diag =-sign*_ten[idiag].second->
evaluate(scale,
_outspin[out2[dit->channelType]].first [h1],
_outspin[out3[dit->channelType]].second[h2],intert);
}
else {
diag = sign*_ten[idiag].second->
evaluate(scale,
_outspin[out3[dit->channelType]].first [h2],
_outspin[out2[dit->channelType]].second[h1],intert);
}
}
// unknown
else throw Exception()
<< "Unknown intermediate in StoSFFDecayer::me2()"
<< Exception::runerror;
// matrix element for the different colour flows
if(ichan < 0) {
for(unsigned iy = 0; iy < dit->colourFlow.size(); ++iy) {
flows[dit->colourFlow[iy].first - 1] +=
dit->colourFlow[iy].second * diag;
}
for(unsigned iy = 0; iy < dit->largeNcColourFlow.size(); ++iy) {
largeflows[dit->largeNcColourFlow[iy].first - 1] +=
dit->largeNcColourFlow[iy].second * diag;
}
}
else {
for(unsigned iy = 0; iy < dit->colourFlow.size(); ++iy) {
if(dit->colourFlow[iy].first - 1 != colourFlow()) continue;
flows[dit->colourFlow[iy].first - 1] +=
dit->colourFlow[iy].second * diag;
}
for(unsigned iy = 0; iy < dit->largeNcColourFlow.size(); ++iy) {
if(dit->colourFlow[iy].first - 1!=colourFlow()) continue;
largeflows[dit->largeNcColourFlow[iy].first - 1] +=
dit->largeNcColourFlow[iy].second * diag;
}
}
++idiag;
}
for(unsigned int ix = 0; ix < ncf; ++ix) {
if(isca == 0) {
mes[ix](0, 0, s1, s2) = flows[ix];
mel[ix](0, 0, s1, s2) = largeflows[ix];
}
else if(isca == 1 ) {
mes[ix](0, s1, 0, s2) = flows[ix];
mel[ix](0, s1, 0, s2) = largeflows[ix];
}
else if(isca == 2) {
mes[ix](0, s1,s2, 0) = flows[ix];
mel[ix](0, s1,s2, 0) = largeflows[ix] ;
}
}
}
}
double me2(0.);
if(ichan < 0) {
vector<double> pflows(ncf,0.);
for(unsigned int ix = 0; ix < ncf; ++ix) {
for(unsigned int iy = 0; iy < ncf; ++ iy) {
double con = cfactors[ix][iy]*(mes[ix].contract(mes[iy],_rho)).real();
me2 += con;
if(ix == iy) {
con = nfactors[ix][iy]*(mel[ix].contract(mel[iy],_rho)).real();
pflows[ix] += con;
}
}
}
double ptotal(std::accumulate(pflows.begin(),pflows.end(),0.));
ptotal *= UseRandom::rnd();
for(unsigned int ix = 0;ix < pflows.size(); ++ix) {
if(ptotal <= pflows[ix]) {
colourFlow(ix);
ME(mes[ix]);
break;
}
ptotal -= pflows[ix];
}
}
else {
unsigned int iflow = colourFlow();
me2 = nfactors[iflow][iflow]*(mel[iflow].contract(mel[iflow],_rho)).real();
}
// return the matrix element squared
return me2;
}
diff --git a/Decay/General/TFFDecayer.h b/Decay/General/TFFDecayer.h
--- a/Decay/General/TFFDecayer.h
+++ b/Decay/General/TFFDecayer.h
@@ -1,197 +1,197 @@
// -*- C++ -*-
//
// TFFDecayer.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_TFFDecayer_H
#define HERWIG_TFFDecayer_H
//
// This is the declaration of the TFFDecayer class.
//
#include "GeneralTwoBodyDecayer.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Helicity/Vertex/Tensor/FFTVertex.h"
namespace Herwig {
using namespace ThePEG;
using Helicity::FFTVertexPtr;
/** \ingroup Decay
* The TFFDecayer class implements the decay of a tensor
* to 2 fermions in a general model. It holds an FFTVertex pointer
* that must be typecast from the VertexBase pointer held in
* GeneralTwoBodyDecayer. It implents the virtual functions me2() and
* partialWidth().
*
* @see GeneralTwoBodyDecayer
*/
class TFFDecayer: public GeneralTwoBodyDecayer {
public:
/**
* The default constructor.
*/
- TFFDecayer() { addToSearchList(2); }
+ TFFDecayer() {}
/** @name Virtual functions required by the Decayer class. */
//@{
/**
* Return the matrix element squared for a given mode and phase-space channel.
* @param ichan The channel we are calculating the matrix element for.
* @param part The decaying Particle.
* @param decay The particles produced in the decay.
* @param meopt Option for the matrix element
* @return The matrix element squared for the phase-space configuration.
*/
virtual double me2(const int ichan, const Particle & part,
const ParticleVector & decay, MEOption meopt) const;
/**
* Function to return partial Width
* @param inpart The decaying particle.
* @param outa One of the decay products.
* @param outb The other decay product.
*/
virtual Energy partialWidth(PMPair inpart, PMPair outa,
PMPair outb) const;
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
virtual IBPtr fullclone() const;
//@}
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving and
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit();
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<TFFDecayer> initTFFDecayer;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
TFFDecayer & operator=(const TFFDecayer &);
private:
/**
* Abstract pointer to AbstractFFTVertex
*/
AbstractFFTVertexPtr _abstractVertex;
/**
* Pointer to the perturbative vertex
*/
FFTVertexPtr _perturbativeVertex;
/**
* Spin density matrix
*/
mutable RhoDMatrix _rho;
/**
* Polarization tensors for the decaying particle
*/
mutable vector<TensorWaveFunction> _tensors;
/**
* Spinors for the decay products
*/
mutable vector<SpinorWaveFunction> _wave;
/**
* Barred spinors for the decay products
*/
mutable vector<SpinorBarWaveFunction> _wavebar;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of TFFDecayer. */
template <>
struct BaseClassTrait<Herwig::TFFDecayer,1> {
/** Typedef of the first base class of TFFDecayer. */
typedef Herwig::GeneralTwoBodyDecayer NthBase;
};
/** This template specialization informs ThePEG about the name of
* the TFFDecayer class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::TFFDecayer>
: public ClassTraitsBase<Herwig::TFFDecayer> {
/** Return a platform-independent class name */
static string className() { return "Herwig::TFFDecayer"; }
};
/** @endcond */
}
#endif /* HERWIG_TFFDecayer_H */
diff --git a/Decay/General/TSSDecayer.h b/Decay/General/TSSDecayer.h
--- a/Decay/General/TSSDecayer.h
+++ b/Decay/General/TSSDecayer.h
@@ -1,188 +1,188 @@
// -*- C++ -*-
//
// TSSDecayer.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_TSSDecayer_H
#define HERWIG_TSSDecayer_H
//
// This is the declaration of the TSSDecayer class.
//
#include "GeneralTwoBodyDecayer.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Helicity/Vertex/Tensor/SSTVertex.h"
namespace Herwig {
using namespace ThePEG;
using Helicity::SSTVertexPtr;
/** \ingroup Decay
* The TSSDecayer class implements the decay of a tensor
* to 2 scalars in a general model. It holds an SSTVertex pointer
* that must be typecast from the VertexBase pointer held in
* GeneralTwoBodyDecayer. It implents the virtual functions me2() and
* partialWidth().
*
* @see GeneralTwoBodyDecayer
*/
class TSSDecayer: public GeneralTwoBodyDecayer {
public:
/**
* The default constructor.
*/
- TSSDecayer() { addToSearchList(2); }
+ TSSDecayer() {}
public:
/** @name Virtual functions required by the Decayer class. */
//@{
/**
* Return the matrix element squared for a given mode and phase-space channel.
* @param ichan The channel we are calculating the matrix element for.
* @param part The decaying Particle.
* @param decay The particles produced in the decay.
* @param meopt Option for the matrix element
* @return The matrix element squared for the phase-space configuration.
*/
virtual double me2(const int ichan, const Particle & part,
const ParticleVector & decay, MEOption meopt) const;
/**
* Function to return partial Width
* @param inpart The decaying particle.
* @param outa One of the decay products.
* @param outb The other decay product.
*/
virtual Energy partialWidth(PMPair inpart, PMPair outa,
PMPair outb) const;
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
virtual IBPtr fullclone() const;
//@}
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving and
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit();
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<TSSDecayer> initTSSDecayer;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
TSSDecayer & operator=(const TSSDecayer &);
private:
/**
* Abstract pointer to AbstractSSTVertex
*/
AbstractSSTVertexPtr _abstractVertex;
/**
* Pointer to the perturbative vertex
*/
SSTVertexPtr _perturbativeVertex;
/**
* Spin density matrix
*/
mutable RhoDMatrix _rho;
/**
* Polarization tensors of the decaying particle
*/
mutable vector<Helicity::TensorWaveFunction> _tensors;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of TSSDecayer. */
template <>
struct BaseClassTrait<Herwig::TSSDecayer,1> {
/** Typedef of the first base class of TSSDecayer. */
typedef Herwig::GeneralTwoBodyDecayer NthBase;
};
/** This template specialization informs ThePEG about the name of
* the TSSDecayer class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::TSSDecayer>
: public ClassTraitsBase<Herwig::TSSDecayer> {
/** Return a platform-independent class name */
static string className() { return "Herwig::TSSDecayer"; }
};
/** @endcond */
}
#endif /* HERWIG_TSSDecayer_H */
diff --git a/Decay/General/TVVDecayer.h b/Decay/General/TVVDecayer.h
--- a/Decay/General/TVVDecayer.h
+++ b/Decay/General/TVVDecayer.h
@@ -1,191 +1,191 @@
// -*- C++ -*-
//
// TVVDecayer.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_TVVDecayer_H
#define HERWIG_TVVDecayer_H
//
// This is the declaration of the TVVDecayer class.
//
#include "GeneralTwoBodyDecayer.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Helicity/Vertex/Tensor/VVTVertex.h"
namespace Herwig {
using namespace ThePEG;
using Helicity::VVTVertexPtr;
/** \ingroup Decay
* The TVVDecayer class implements the decay of a tensor
* to 2 vector bosons in a general model. It holds a VVTVertex pointer
* that must be typecast from the VertexBase pointer held in
* GeneralTwoBodyDecayer. It implents the virtual functions me2() and
* partialWidth().
*
* @see GeneralTwoBodyDecayer
*/
class TVVDecayer: public GeneralTwoBodyDecayer {
public:
/**
* The default constructor.
*/
- TVVDecayer() { addToSearchList(2); }
+ TVVDecayer() {}
/** @name Virtual functions required by the Decayer class. */
//@{
/**
* Return the matrix element squared for a given mode and phase-space channel.
* @param ichan The channel we are calculating the matrix element for.
* @param part The decaying Particle.
* @param decay The particles produced in the decay.
* @param meopt Option for the matrix element
* @return The matrix element squared for the phase-space configuration.
*/
virtual double me2(const int ichan, const Particle & part,
const ParticleVector & decay, MEOption meopt) const;
/**
* Function to return partial Width
* @param inpart The decaying particle.
* @param outa One of the decay products.
* @param outb The other decay product.
*/
virtual Energy partialWidth(PMPair inpart, PMPair outa,
PMPair outb) const;
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
virtual IBPtr fullclone() const;
//@}
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving and
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit();
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<TVVDecayer> initTVVDecayer;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
TVVDecayer & operator=(const TVVDecayer &);
private:
/**
* Abstract pointer to AbstractVVTVertex
*/
AbstractVVTVertexPtr _abstractVertex;
/**
* Pointer to the perturbative vertex
*/
VVTVertexPtr _perturbativeVertex;
/**
* Spin density matrix
*/
mutable RhoDMatrix _rho;
/**
* Polarization tensors of decaying particle
*/
mutable vector<Helicity::TensorWaveFunction> _tensors;
/**
* Polarization vectors of outgoing vector bosons
*/
mutable vector<Helicity::VectorWaveFunction> _vectors[2];
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of TVVDecayer. */
template <>
struct BaseClassTrait<Herwig::TVVDecayer,1> {
/** Typedef of the first base class of TVVDecayer. */
typedef Herwig::GeneralTwoBodyDecayer NthBase;
};
/** This template specialization informs ThePEG about the name of
* the TVVDecayer class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::TVVDecayer>
: public ClassTraitsBase<Herwig::TVVDecayer> {
/** Return a platform-independent class name */
static string className() { return "Herwig::TVVDecayer"; }
};
/** @endcond */
}
#endif /* HERWIG_TVVDecayer_H */
diff --git a/Decay/General/VFFDecayer.h b/Decay/General/VFFDecayer.h
--- a/Decay/General/VFFDecayer.h
+++ b/Decay/General/VFFDecayer.h
@@ -1,200 +1,200 @@
// -*- C++ -*-
//
// VFFDecayer.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_VFFDecayer_H
#define HERWIG_VFFDecayer_H
//
// This is the declaration of the VFFDecayer class.
//
#include "GeneralTwoBodyDecayer.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Helicity/Vertex/Vector/FFVVertex.h"
namespace Herwig {
using namespace ThePEG;
using Helicity::FFVVertexPtr;
/** \ingroup Decay
* The VFFDecayer class implements the decay of a vector
* to 2 fermions in a general model. It holds an FFVVertex pointer
* that must be typecast from the VertexBase pointer held in
* GeneralTwoBodyDecayer. It implents the virtual functions me2() and
* partialWidth().
*
* @see GeneralTwoBodyDecayer
*/
class VFFDecayer: public GeneralTwoBodyDecayer {
public:
/**
* The default constructor.
*/
- VFFDecayer() { addToSearchList(2); }
+ VFFDecayer() {}
public:
/** @name Virtual functions required by the Decayer class. */
//@{
/**
* Return the matrix element squared for a given mode and phase-space channel.
* @param ichan The channel we are calculating the matrix element for.
* @param part The decaying Particle.
* @param decay The particles produced in the decay.
* @param meopt Option for the matrix element
* @return The matrix element squared for the phase-space configuration.
*/
virtual double me2(const int ichan, const Particle & part,
const ParticleVector & decay, MEOption meopt) const;
/**
* Function to return partial Width
* @param inpart The decaying particle.
* @param outa One of the decay products.
* @param outb The other decay product.
*/
virtual Energy partialWidth(PMPair inpart, PMPair outa,
PMPair outb) const;
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
virtual IBPtr fullclone() const;
//@}
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving and
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit();
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<VFFDecayer> initVFFDecayer;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
VFFDecayer & operator=(const VFFDecayer &);
private:
/**
* Abstract pointer to AbstractFFVVertex
*/
AbstractFFVVertexPtr _abstractVertex;
/**
* Pointer to the perturbative vertex
*/
FFVVertexPtr _perturbativeVertex;
/**
* Spin density matrix
*/
mutable RhoDMatrix _rho;
/**
* Polarization vectors for the decaying particle
*/
mutable vector<VectorWaveFunction> _vectors;
/**
* Spinors for the decay products
*/
mutable vector<SpinorWaveFunction> _wave;
/**
* Barred spinors for the decay products
*/
mutable vector<SpinorBarWaveFunction> _wavebar;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of VFFDecayer. */
template <>
struct BaseClassTrait<Herwig::VFFDecayer,1> {
/** Typedef of the first base class of VFFDecayer. */
typedef Herwig::GeneralTwoBodyDecayer NthBase;
};
/** This template specialization informs ThePEG about the name of
* the VFFDecayer class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::VFFDecayer>
: public ClassTraitsBase<Herwig::VFFDecayer> {
/** Return a platform-independent class name */
static string className() { return "Herwig::VFFDecayer"; }
};
/** @endcond */
}
#endif /* HERWIG_VFFDecayer_H */
diff --git a/Decay/General/VSSDecayer.h b/Decay/General/VSSDecayer.h
--- a/Decay/General/VSSDecayer.h
+++ b/Decay/General/VSSDecayer.h
@@ -1,187 +1,187 @@
// -*- C++ -*-
//
// VSSDecayer.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_VSSDecayer_H
#define HERWIG_VSSDecayer_H
//
// This is the declaration of the VSSDecayer class.
//
#include "GeneralTwoBodyDecayer.h"
#include "ThePEG/Helicity/Vertex/Scalar/VSSVertex.h"
#include "ThePEG/Repository/EventGenerator.h"
namespace Herwig {
using namespace ThePEG;
using Helicity::VSSVertexPtr;
/** \ingroup Decay
* The VSSDecayer class implements the decay of a vector
* to 2 scalars in a general model. It holds an VSSVertex pointer
* that must be typecast from the VertexBase pointer held in
* GeneralTwoBodyDecayer. It implents the virtual functions me2() and
* partialWidth().
*
* @see GeneralTwoBodyDecayer
*/
class VSSDecayer: public GeneralTwoBodyDecayer {
public:
/**
* The default constructor.
*/
- VSSDecayer() { addToSearchList(0); }
+ VSSDecayer() {}
/** @name Virtual functions required by the Decayer class. */
//@{
/**
* Return the matrix element squared for a given mode and phase-space channel
* @param ichan The channel we are calculating the matrix element for.
* @param part The decaying Particle.
* @param decay The particles produced in the decay.
* @param meopt Option for the matrix element
* @return The matrix element squared for the phase-space configuration.
*/
virtual double me2(const int ichan, const Particle & part,
const ParticleVector & decay, MEOption meopt) const;
/**
* Function to return partial Width
* @param inpart The decaying particle.
* @param outa One of the decay products.
* @param outb The other decay product.
*/
virtual Energy partialWidth(PMPair inpart, PMPair outa,
PMPair outb) const;
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
virtual IBPtr fullclone() const;
//@}
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();
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<VSSDecayer> initVSSDecayer;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
VSSDecayer & operator=(const VSSDecayer &);
private:
/**
* Abstract pointer to AbstractVSSVertex
*/
AbstractVSSVertexPtr _abstractVertex;
/**
* Pointer to the perturbative vertex
*/
VSSVertexPtr _perturbativeVertex;
/**
* Spin density matrix
*/
mutable RhoDMatrix _rho;
/**
* Polarization vectors for the decaying particle
*/
mutable vector<Helicity::VectorWaveFunction> _vectors;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of VSSDecayer. */
template <>
struct BaseClassTrait<Herwig::VSSDecayer,1> {
/** Typedef of the first base class of VSSDecayer. */
typedef Herwig::GeneralTwoBodyDecayer NthBase;
};
/** This template specialization informs ThePEG about the name of
* the VSSDecayer class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::VSSDecayer>
: public ClassTraitsBase<Herwig::VSSDecayer> {
/** Return a platform-independent class name */
static string className() { return "Herwig::VSSDecayer"; }
};
/** @endcond */
}
#endif /* HERWIG_VSSDecayer_H */
diff --git a/Decay/General/VVSDecayer.cc b/Decay/General/VVSDecayer.cc
--- a/Decay/General/VVSDecayer.cc
+++ b/Decay/General/VVSDecayer.cc
@@ -1,122 +1,117 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the VVSDecayer class.
//
#include "VVSDecayer.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace Herwig;
using namespace ThePEG::Helicity;
-VVSDecayer::VVSDecayer() {
- addToSearchList(0);
- addToSearchList(1);
-}
-
IBPtr VVSDecayer::clone() const {
return new_ptr(*this);
}
IBPtr VVSDecayer::fullclone() const {
return new_ptr(*this);
}
void VVSDecayer::doinit() {
_perturbativeVertex = dynamic_ptr_cast<VVSVertexPtr> (getVertex());
_abstractVertex = dynamic_ptr_cast<AbstractVVSVertexPtr>(getVertex());
GeneralTwoBodyDecayer::doinit();
}
void VVSDecayer::persistentOutput(PersistentOStream & os) const {
os << _abstractVertex << _perturbativeVertex;
}
void VVSDecayer::persistentInput(PersistentIStream & is, int) {
is >> _abstractVertex >> _perturbativeVertex;
}
ClassDescription<VVSDecayer> VVSDecayer::initVVSDecayer;
// Definition of the static class description member.
void VVSDecayer::Init() {
static ClassDocumentation<VVSDecayer> documentation
("The VVSDecayer class implements the decay of a vector"
" to a vector and a scalar");
}
double VVSDecayer::me2(const int , const Particle & inpart,
const ParticleVector & decay,
MEOption meopt) const {
bool massless = ( decay[0]->id()==ParticleID::gamma ||
decay[0]->id()==ParticleID::g );
if(meopt==Initialize) {
VectorWaveFunction::calculateWaveFunctions(_vectors[0],_rho,
const_ptr_cast<tPPtr>(&inpart),
incoming,false);
ME(DecayMatrixElement(PDT::Spin1,PDT::Spin1,PDT::Spin0));
}
if(meopt==Terminate) {
VectorWaveFunction::constructSpinInfo(_vectors[0],const_ptr_cast<tPPtr>(&inpart),
incoming,true,false);
VectorWaveFunction::
constructSpinInfo(_vectors[1],decay[0],outgoing,true,massless);
ScalarWaveFunction::
constructSpinInfo(decay[1],outgoing,true);
return 0.;
}
VectorWaveFunction::
calculateWaveFunctions(_vectors[1],decay[0],outgoing,massless);
ScalarWaveFunction sca(decay[1]->momentum(),decay[1]->dataPtr(),outgoing);
Energy2 scale(sqr(inpart.mass()));
for(unsigned int in=0;in<3;++in) {
for(unsigned int out=0;out<3;++out) {
if(massless&&out==1) ++out;
ME()(in,out,0) =
_abstractVertex->evaluate(scale,_vectors[0][in],_vectors[1][out],sca);
}
}
double output=(ME().contract(_rho)).real()/scale*UnitRemoval::E2;
// colour and identical particle factors
output *= colourFactor(inpart.dataPtr(),decay[0]->dataPtr(),
decay[1]->dataPtr());
// return the answer
return output;
}
Energy VVSDecayer::partialWidth(PMPair inpart, PMPair outa,
PMPair outb) const {
if( inpart.second < outa.second + outb.second ) return ZERO;
if(_perturbativeVertex) {
Energy2 scale(sqr(inpart.second));
double mu1sq = sqr(outa.second/inpart.second);
double mu2sq = sqr(outb.second/inpart.second);
tcPDPtr in = inpart.first->CC() ? tcPDPtr(inpart.first->CC()) : inpart.first;
if( outb.first->iSpin() == PDT::Spin0 )
_perturbativeVertex->setCoupling(sqr(inpart.second), in,
outa.first, outb.first);
else {
_perturbativeVertex->setCoupling(sqr(inpart.second), in,
outb.first, outa.first);
swap(mu1sq, mu2sq);
}
double me2 = 2. + 0.25*sqr(1. + mu1sq - mu2sq)/mu1sq;
Energy pcm = Kinematics::pstarTwoBodyDecay(inpart.second,outa.second,
outb.second);
Energy output = norm(_perturbativeVertex->norm())*me2*pcm/
(24.*Constants::pi)/scale*UnitRemoval::E2;
// colour factor
output *= colourFactor(inpart.first,outa.first,outb.first);
// return the answer
return output;
}
else {
return GeneralTwoBodyDecayer::partialWidth(inpart,outa,outb);
}
}
diff --git a/Decay/General/VVSDecayer.h b/Decay/General/VVSDecayer.h
--- a/Decay/General/VVSDecayer.h
+++ b/Decay/General/VVSDecayer.h
@@ -1,180 +1,180 @@
// -*- C++ -*-
#ifndef THEPEG_VVSDecayer_H
#define THEPEG_VVSDecayer_H
//
// This is the declaration of the VVSDecayer class.
//
#include "GeneralTwoBodyDecayer.h"
#include "ThePEG/Helicity/Vertex/Scalar/VVSVertex.h"
#include "ThePEG/Repository/EventGenerator.h"
namespace Herwig {
using namespace ThePEG;
using Helicity::VVSVertexPtr;
/** \ingroup Decay
* The VVSDecayer class implements the decay of a vector to a
* vector and a scalar in a general model. It holds an VVSVertex pointer
* that must be typecast from the VertexBase pointer helid in the
* GeneralTwoBodyDecayer. It implents the virtual functions me2() and
* partialWidth().
*
* @see \ref VVSDecayerInterfaces "The interfaces"
* defined for VVSDecayer.
*/
class VVSDecayer: public GeneralTwoBodyDecayer {
public:
/**
* The default constructor.
*/
- VVSDecayer();
+ VVSDecayer() {}
/** @name Virtual functions required by the Decayer class. */
//@{
/**
* Return the matrix element squared for a given mode and phase-space channel
* @param ichan The channel we are calculating the matrix element for.
* @param part The decaying Particle.
* @param decay The particles produced in the decay.
* @param meopt Option for the calculation of the matrix element
* @return The matrix element squared for the phase-space configuration.
*/
virtual double me2(const int ichan, const Particle & part,
const ParticleVector & decay, MEOption meopt) const;
/**
* Function to return partial Width
* @param inpart The decaying particle.
* @param outa One of the decay products.
* @param outb The other decay product.
*/
virtual Energy partialWidth(PMPair inpart, PMPair outa,
PMPair outb) const;
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
virtual IBPtr fullclone() const;
//@}
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();
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<VVSDecayer> initVVSDecayer;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
VVSDecayer & operator=(const VVSDecayer &);
private:
/**
* Abstract pointer to AbstractVVSVertex
*/
AbstractVVSVertexPtr _abstractVertex;
/**
* Pointer to the perturbative vertex
*/
VVSVertexPtr _perturbativeVertex;
/**
* Spin density matrix
*/
mutable RhoDMatrix _rho;
/**
* Vector wavefunctions
*/
mutable vector<Helicity::VectorWaveFunction> _vectors[2];
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of VVSDecayer. */
template <>
struct BaseClassTrait<VVSDecayer,1> {
/** Typedef of the first base class of VVSDecayer. */
typedef Herwig::GeneralTwoBodyDecayer NthBase;
};
/** This template specialization informs ThePEG about the name of
* the VVSDecayer class and the shared object where it is defined. */
template <>
struct ClassTraits<VVSDecayer>
: public ClassTraitsBase<VVSDecayer> {
/** Return a platform-independent class name */
static string className() { return "Herwig::VVSDecayer"; }
};
/** @endcond */
}
#endif /* THEPEG_VVSDecayer_H */
diff --git a/Decay/General/VVVDecayer.cc b/Decay/General/VVVDecayer.cc
--- a/Decay/General/VVVDecayer.cc
+++ b/Decay/General/VVVDecayer.cc
@@ -1,129 +1,123 @@
// -*- C++ -*-
//
// VVVDecayer.cc is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the VVVDecayer class.
//
#include "VVVDecayer.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/DecayMode.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
#include "Herwig++/Utilities/Kinematics.h"
using namespace Herwig;
using namespace ThePEG::Helicity;
-VVVDecayer::VVVDecayer() {
- addToSearchList(0);
- addToSearchList(1);
- addToSearchList(2);
-}
-
IBPtr VVVDecayer::clone() const {
return new_ptr(*this);
}
IBPtr VVVDecayer::fullclone() const {
return new_ptr(*this);
}
void VVVDecayer::doinit() {
_perturbativeVertex = dynamic_ptr_cast<VVVVertexPtr> (getVertex());
_abstractVertex = dynamic_ptr_cast<AbstractVVVVertexPtr>(getVertex());
GeneralTwoBodyDecayer::doinit();
}
void VVVDecayer::persistentOutput(PersistentOStream & os) const {
os << _abstractVertex << _perturbativeVertex;
}
void VVVDecayer::persistentInput(PersistentIStream & is, int) {
is >> _abstractVertex >> _perturbativeVertex;
}
ClassDescription<VVVDecayer> VVVDecayer::initVVVDecayer;
// Definition of the static class description member.
void VVVDecayer::Init() {
static ClassDocumentation<VVVDecayer> documentation
("The VVVDecayer class implements the decay of a vector boson "
"into 2 vector bosons");
}
double VVVDecayer::me2(const int , const Particle & inpart,
const ParticleVector & decay,
MEOption meopt) const {
bool massless[2];
for(unsigned int ix=0;ix<2;++ix)
massless[ix] = (decay[ix]->id()==ParticleID::gamma ||
decay[ix]->id()==ParticleID::g);
if(meopt==Initialize) {
VectorWaveFunction::calculateWaveFunctions(_vectors[0],_rho,
const_ptr_cast<tPPtr>(&inpart),
incoming,false);
ME(DecayMatrixElement(PDT::Spin1,PDT::Spin1,PDT::Spin1));
}
if(meopt==Terminate) {
VectorWaveFunction::constructSpinInfo(_vectors[0],const_ptr_cast<tPPtr>(&inpart),
incoming,true,false);
for(unsigned int ix=0;ix<2;++ix)
VectorWaveFunction::
constructSpinInfo(_vectors[ix+1],decay[ix],outgoing,true,massless[ix]);
return 0.;
}
for(unsigned int ix=0;ix<2;++ix)
VectorWaveFunction::
calculateWaveFunctions(_vectors[ix+1],decay[ix],outgoing,massless[ix]);
Energy2 scale(sqr(inpart.mass()));
for(unsigned int iv3=0;iv3<3;++iv3) {
for(unsigned int iv2=0;iv2<3;++iv2) {
for(unsigned int iv1=0;iv1<3;++iv1) {
ME()(iv1,iv2,iv3) = _abstractVertex->
evaluate(scale,_vectors[1][iv2],_vectors[2][iv3],_vectors[0][iv1]);
}
}
}
double output = (ME().contract(_rho)).real()/scale*UnitRemoval::E2;
// colour and identical particle factors
output *= colourFactor(inpart.dataPtr(),decay[0]->dataPtr(),
decay[1]->dataPtr());
// return the answer
return output;
}
Energy VVVDecayer::partialWidth(PMPair inpart, PMPair outa,
PMPair outb) const {
if( inpart.second < outa.second + outb.second ) return ZERO;
if(_perturbativeVertex) {
tcPDPtr in = inpart.first->CC() ? tcPDPtr(inpart.first->CC()) : inpart.first;
_perturbativeVertex->setCoupling(sqr(inpart.second), in,
outa.first, outb.first);
double mu1(outa.second/inpart.second), mu1sq(sqr(mu1)),
mu2(outb.second/inpart.second), mu2sq(sqr(mu2));
double me2 =
(mu1 - mu2 - 1.)*(mu1 - mu2 + 1.)*(mu1 + mu2 - 1.)*(mu1 + mu2 + 1.)
* (sqr(mu1sq) + sqr(mu2sq) + 10.*(mu1sq*mu2sq + mu1sq + mu2sq) + 1.)
/4./mu1sq/mu2sq;
Energy pcm = Kinematics::pstarTwoBodyDecay(inpart.second,outa.second,
outb.second);
Energy pWidth = norm(_perturbativeVertex->norm())*me2*pcm/24./Constants::pi;
// colour factor
pWidth *= colourFactor(inpart.first,outa.first,outb.first);
// return the answer
return pWidth;
}
else {
return GeneralTwoBodyDecayer::partialWidth(inpart,outa,outb);
}
}
diff --git a/Decay/General/VVVDecayer.h b/Decay/General/VVVDecayer.h
--- a/Decay/General/VVVDecayer.h
+++ b/Decay/General/VVVDecayer.h
@@ -1,186 +1,186 @@
// -*- C++ -*-
//
// VVVDecayer.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_VVVDecayer_H
#define HERWIG_VVVDecayer_H
//
// This is the declaration of the VVVDecayer class.
//
#include "GeneralTwoBodyDecayer.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Helicity/Vertex/Vector/VVVVertex.h"
namespace Herwig {
using namespace ThePEG;
using Helicity::VVVVertexPtr;
/** \ingroup Decay
* The VVVDecayer class implements the decay of a vector
* to 2 vectors in a general model. It holds an VVVVertex pointer
* that must be typecast from the VertexBase pointer held in
* GeneralTwoBodyDecayer. It implents the virtual functions me2() and
* partialWidth().
*
* @see GeneralTwoBodyDecayer
*/
class VVVDecayer: public GeneralTwoBodyDecayer {
public:
/**
* The default constructor.
*/
- VVVDecayer();
+ VVVDecayer() {}
/** @name Virtual functions required by the Decayer class. */
//@{
/**
* Return the matrix element squared for a given mode and phase-space channel.
* @param ichan The channel we are calculating the matrix element for.
* @param part The decaying Particle.
* @param decay The particles produced in the decay.
* @param meopt Option for the calculation of the matrix element
* @return The matrix element squared for the phase-space configuration.
*/
virtual double me2(const int ichan, const Particle & part,
const ParticleVector & decay, MEOption meopt) const;
/**
* Function to return partial Width
* @param inpart The decaying particle.
* @param outa One of the decay products.
* @param outb The other decay product.
*/
virtual Energy partialWidth(PMPair inpart, PMPair outa,
PMPair outb) const;
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
virtual IBPtr fullclone() const;
//@}
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving and
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit();
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<VVVDecayer> initVVVDecayer;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
VVVDecayer & operator=(const VVVDecayer &);
private:
/**
* Abstract pointer to AbstractVVVVertex
*/
AbstractVVVVertexPtr _abstractVertex;
/**
* Pointer to the perturbative vertex
*/
VVVVertexPtr _perturbativeVertex;
/**
* Spin density matrix
*/
mutable RhoDMatrix _rho;
/**
* Vector wavefunctions
*/
mutable vector<Helicity::VectorWaveFunction> _vectors[3];
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of VVVDecayer. */
template <>
struct BaseClassTrait<Herwig::VVVDecayer,1> {
/** Typedef of the first base class of VVVDecayer. */
typedef Herwig::GeneralTwoBodyDecayer NthBase;
};
/** This template specialization informs ThePEG about the name of
* the VVVDecayer class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::VVVDecayer>
: public ClassTraitsBase<Herwig::VVVDecayer> {
/** Return a platform-independent class name */
static string className() { return "Herwig::VVVDecayer"; }
};
/** @endcond */
}
#endif /* HERWIG_VVVDecayer_H */
diff --git a/Decay/General/VtoFFVDecayer.cc b/Decay/General/VtoFFVDecayer.cc
--- a/Decay/General/VtoFFVDecayer.cc
+++ b/Decay/General/VtoFFVDecayer.cc
@@ -1,361 +1,361 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the VtoFFVDecayer class.
//
#include "VtoFFVDecayer.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "Herwig++/PDT/ThreeBodyAllOnCalculator.h"
#include <numeric>
using namespace Herwig;
using namespace ThePEG;
using namespace ThePEG::Helicity;
IBPtr VtoFFVDecayer::clone() const {
return new_ptr(*this);
}
IBPtr VtoFFVDecayer::fullclone() const {
return new_ptr(*this);
}
void VtoFFVDecayer::persistentOutput(PersistentOStream & os) const {
os << _sca << _fer << _vec << _ten;
}
void VtoFFVDecayer::persistentInput(PersistentIStream & is, int) {
is >> _sca >> _fer >> _vec >> _ten;
}
ClassDescription<VtoFFVDecayer> VtoFFVDecayer::initVtoFFVDecayer;
// Definition of the static class description member.
void VtoFFVDecayer::Init() {
static ClassDocumentation<VtoFFVDecayer> documentation
("The VtoFFVDecayer class implements the general three-body "
"decay of a vector to a two fermions and a vector.");
}
WidthCalculatorBasePtr VtoFFVDecayer::
threeBodyMEIntegrator(const DecayMode & ) const {
vector<int> intype;
vector<Energy> inmass,inwidth;
vector<double> inpow,inweights;
constructIntegratorChannels(intype,inmass,inwidth,inpow,inweights);
return new_ptr(ThreeBodyAllOnCalculator<VtoFFVDecayer>
(inweights,intype,inmass,inwidth,inpow,*this,0,
outgoing()[0]->mass(),outgoing()[1]->mass(),
- outgoing()[2]->mass()));
+ outgoing()[2]->mass(),relativeError()));
}
void VtoFFVDecayer::doinit() {
GeneralThreeBodyDecayer::doinit();
unsigned int ndiags = getProcessInfo().size();
_sca.resize(ndiags);
_fer.resize(ndiags);
_vec.resize(ndiags);
_ten.resize(ndiags);
for(unsigned int ix = 0;ix < ndiags; ++ix) {
TBDiagram current = getProcessInfo()[ix];
tcPDPtr offshell = current.intermediate;
if( offshell->CC() ) offshell = offshell->CC();
if(offshell->iSpin() == PDT::Spin0) {
AbstractVVSVertexPtr vert1 = dynamic_ptr_cast<AbstractVVSVertexPtr>
(current.vertices.first);
AbstractFFSVertexPtr vert2 = dynamic_ptr_cast<AbstractFFSVertexPtr>
(current.vertices.second);
if(!vert1||!vert2) throw Exception()
<< "Invalid vertices for a scalar diagram in VtoFFVDecayer::doinit()"
<< Exception::runerror;
_sca[ix] = make_pair(vert1, vert2);
}
else if(offshell->iSpin() == PDT::Spin1Half) {
AbstractFFVVertexPtr vert1 = dynamic_ptr_cast<AbstractFFVVertexPtr>
(current.vertices.first);
AbstractFFVVertexPtr vert2 = dynamic_ptr_cast<AbstractFFVVertexPtr>
(current.vertices.second);
if(!vert1||!vert2) throw Exception()
<< "Invalid vertices for a fermion diagram in VtoFFVDecayer::doinit()"
<< Exception::runerror;
_fer[ix] = make_pair(vert1, vert2);
}
else if(offshell->iSpin() == PDT::Spin1) {
AbstractVVVVertexPtr vert1 = dynamic_ptr_cast<AbstractVVVVertexPtr>
(current.vertices.first);
AbstractFFVVertexPtr vert2 = dynamic_ptr_cast<AbstractFFVVertexPtr>
(current.vertices.second);
if(!vert1||!vert2) throw Exception()
<< "Invalid vertices for a vector diagram in VtoFFVDecayer::doinit()"
<< Exception::runerror;
_vec[ix] = make_pair(vert1, vert2);
}
else if(offshell->iSpin() == PDT::Spin2) {
AbstractVVTVertexPtr vert1 = dynamic_ptr_cast<AbstractVVTVertexPtr>
(current.vertices.first);
AbstractFFTVertexPtr vert2 = dynamic_ptr_cast<AbstractFFTVertexPtr>
(current.vertices.second);
if(!vert1||!vert2) throw Exception()
<< "Invalid vertices for a tensor diagram in VtoFFVDecayer::doinit()"
<< Exception::runerror;
_ten[ix] = make_pair(vert1, vert2);
}
}
}
double VtoFFVDecayer::me2(const int ichan, const Particle & inpart,
const ParticleVector & decay,
MEOption meopt) const {
// particle or CC of particle
bool cc = (*getProcessInfo().begin()).incoming != inpart.id();
// special handling or first/last call
if(meopt==Initialize) {
VectorWaveFunction::
calculateWaveFunctions(_inVector,_rho,const_ptr_cast<tPPtr>(&inpart),
Helicity::incoming,false);
}
if(meopt==Terminate) {
VectorWaveFunction::
constructSpinInfo(_inVector,const_ptr_cast<tPPtr>(&inpart),
Helicity::incoming,true,false);
for(unsigned int ix=0;ix<decay.size();++ix) {
if(decay[ix]->dataPtr()->iSpin()==PDT::Spin1) {
VectorWaveFunction::constructSpinInfo(_outVector,decay[ix],
Helicity::outgoing,true,false);
}
else {
SpinorWaveFunction::
constructSpinInfo(_outspin[ix].first,decay[ix],Helicity::outgoing,true);
}
}
}
unsigned int ivec(0);
for(unsigned int ix = 0; ix < decay.size();++ix) {
if(decay[ix]->dataPtr()->iSpin() == PDT::Spin1) {
ivec = ix;
VectorWaveFunction::
calculateWaveFunctions(_outVector, decay[ix], Helicity::outgoing,false);
}
else {
SpinorWaveFunction::
calculateWaveFunctions(_outspin[ix].first,decay[ix],Helicity::outgoing);
_outspin[ix].second.resize(2);
// Need a ubar and a v spinor
if(_outspin[ix].first[0].wave().Type() == u_spinortype) {
for(unsigned int iy = 0; iy < 2; ++iy) {
_outspin[ix].second[iy] = _outspin[ix].first[iy].bar();
_outspin[ix].first[iy].conjugate();
}
}
else {
for(unsigned int iy = 0; iy < 2; ++iy) {
_outspin[ix].second[iy] = _outspin[ix].first[iy].bar();
_outspin[ix].second[iy].conjugate();
}
}
}
}
const vector<vector<double> > cfactors(getColourFactors());
const vector<vector<double> > nfactors(getLargeNcColourFactors());
Energy2 scale(sqr(inpart.mass()));
const size_t ncf(numberOfFlows());
vector<Complex> flows(ncf, Complex(0.)), largeflows(ncf, Complex(0.));
// setup the DecayMatrixElement
vector<DecayMatrixElement>
mes(ncf,DecayMatrixElement(PDT::Spin1,
ivec == 0 ? PDT::Spin1 : PDT::Spin1Half,
ivec == 1 ? PDT::Spin1 : PDT::Spin1Half,
ivec == 2 ? PDT::Spin1 : PDT::Spin1Half));
vector<DecayMatrixElement>
mel(ncf,DecayMatrixElement(PDT::Spin1,
ivec == 0 ? PDT::Spin1 : PDT::Spin1Half,
ivec == 1 ? PDT::Spin1 : PDT::Spin1Half,
ivec == 2 ? PDT::Spin1 : PDT::Spin1Half));
//the channel possiblities
static const unsigned int out2[3] = {1,0,0}, out3[3] = {2,2,1};
for(unsigned int vi = 0; vi < 3; ++vi) {
for(unsigned int s1 = 0; s1 < 2; ++s1) {
for(unsigned int s2 = 0; s2 < 2; ++s2) {
for(unsigned int v1 = 0; v1 < 3; ++v1) {
flows = vector<Complex>(ncf, Complex(0.));
largeflows = vector<Complex>(ncf, Complex(0.));
unsigned int idiag(0);
for(vector<TBDiagram>::const_iterator dit=getProcessInfo().begin();
dit!=getProcessInfo().end();++dit) {
// channels if selecting
if( ichan >=0 && diagramMap()[ichan] != idiag ) {
++idiag;
continue;
}
tcPDPtr offshell = dit->intermediate;
if(cc&&offshell->CC()) offshell=offshell->CC();
Complex diag;
unsigned int o2(out2[dit->channelType]), o3(out3[dit->channelType]);
double sign = (o3 < o2) ? 1. : -1.;
// intermediate scalar
if(offshell->iSpin() == PDT::Spin0) {
ScalarWaveFunction inters = _sca[idiag].first->
evaluate(scale, widthOption(), offshell, _outVector[v1],
_inVector[vi]);
unsigned int h1(s1),h2(s2);
if(o2 > o3) swap(h1, h2);
if(decay[o2]->id() < 0 && decay[o3]->id() > 0) {
diag = -sign*_sca[idiag].second->
evaluate(scale,_outspin[o2].first[h1],
_outspin[o3].second[h2],inters);
}
else {
diag = sign*_sca[idiag].second->
evaluate(scale, _outspin[o3].first [h2],
_outspin[o2].second[h1],inters);
}
}
// intermediate fermion
else if(offshell->iSpin() == PDT::Spin1Half) {
int iferm = (decay[o2]->dataPtr()->iSpin() == PDT::Spin1Half)
? o2 : o3;
unsigned int h1(s1),h2(s2);
if(dit->channelType > iferm) swap(h1, h2);
sign = iferm < dit->channelType ? 1. : -1.;
if(decay[dit->channelType]->id() < 0 && decay[iferm]->id() > 0 ) {
SpinorWaveFunction inters = _fer[idiag].first->
evaluate(scale,widthOption(),offshell,
_outspin[dit->channelType].first[h1], _inVector[vi]);
diag = -sign*_fer[idiag].second->
evaluate(scale,inters,_outspin[iferm].second[h2], _outVector[v1]);
}
else {
SpinorBarWaveFunction inters = _fer[idiag].first->
evaluate(scale,widthOption(),offshell,
_outspin[dit->channelType].second[h1],_inVector[vi]);
diag = sign*_fer[idiag].second->
evaluate(scale,_outspin[iferm].first [h2],inters, _outVector[v1]);
}
}
// intermediate vector
else if(offshell->iSpin() == PDT::Spin1) {
VectorWaveFunction interv = _vec[idiag].first->
evaluate(scale, widthOption(), offshell, _outVector[v1],
_inVector[vi]);
unsigned int h1(s1),h2(s2);
if(o2 > o3) swap(h1,h2);
if(decay[o2]->id() < 0 && decay[o3]->id() > 0) {
diag =-sign*_vec[idiag].second->
evaluate(scale, _outspin[o2].first[h1],
_outspin[o3].second[h2], interv);
}
else {
diag = sign*_vec[idiag].second->
evaluate(scale, _outspin[o3].first[h2],
_outspin[o2].second[h1], interv);
}
}
else if(offshell->iSpin() == PDT::Spin2) {
TensorWaveFunction intert = _ten[idiag].first->
evaluate(scale, widthOption(), offshell, _inVector[vi],
_outVector[v1]);
unsigned int h1(s1),h2(s2);
if(out2[dit->channelType]>out3[dit->channelType]) swap(h1,h2);
if(decay[out2[dit->channelType]]->id()<0&&
decay[out3[dit->channelType]]->id()>0) {
diag =-sign*_ten[idiag].second->
evaluate(scale,
_outspin[out2[dit->channelType]].first [h1],
_outspin[out3[dit->channelType]].second[h2],intert);
}
else {
diag = sign*_ten[idiag].second->
evaluate(scale,
_outspin[out3[dit->channelType]].first [h2],
_outspin[out2[dit->channelType]].second[h1],intert);
}
}
// unknown
else throw Exception()
<< "Unknown intermediate in VtoFFVDecayer::me2()"
<< Exception::runerror;
// matrix element for the different colour flows
if(ichan < 0) {
for(unsigned iy = 0; iy < dit->colourFlow.size(); ++iy) {
flows[dit->colourFlow[iy].first - 1] +=
dit->colourFlow[iy].second * diag;
}
for(unsigned iy = 0; iy < dit->largeNcColourFlow.size(); ++iy) {
largeflows[dit->largeNcColourFlow[iy].first - 1] +=
dit->largeNcColourFlow[iy].second * diag;
}
}
else {
for(unsigned iy = 0; iy < dit->colourFlow.size(); ++iy) {
if(dit->colourFlow[iy].first - 1 != colourFlow()) continue;
flows[dit->colourFlow[iy].first - 1] +=
dit->colourFlow[iy].second * diag;
}
for(unsigned iy = 0; iy < dit->largeNcColourFlow.size(); ++iy) {
if(dit->colourFlow[iy].first - 1!=colourFlow()) continue;
largeflows[dit->largeNcColourFlow[iy].first - 1] +=
dit->largeNcColourFlow[iy].second * diag;
}
}
++idiag;
} //end of diagrams
// now add the flows to the me2 with appropriate colour factors
for(unsigned int ix = 0; ix < ncf; ++ix) {
if (ivec == 0) {
mes[ix](vi, v1, s1, s2) = flows[ix];
mel[ix](vi, v1, s1, s2) = largeflows[ix];
}
else if(ivec == 1) {
mes[ix](vi, s1, v1, s2) = flows[ix];
mel[ix](vi, s1, v1, s2) = largeflows[ix];
}
else if(ivec == 2) {
mes[ix](vi, s1, s2, v1) = flows[ix];
mel[ix](vi, s1, s2, v1) = largeflows[ix];
}
}
}
}
}
}
double me2(0.);
if(ichan < 0) {
vector<double> pflows(ncf,0.);
for(unsigned int ix = 0; ix < ncf; ++ix) {
for(unsigned int iy = 0; iy < ncf; ++ iy) {
double con = cfactors[ix][iy]*(mes[ix].contract(mes[iy],_rho)).real();
me2 += con;
if(ix == iy) {
con = nfactors[ix][iy]*(mel[ix].contract(mel[iy],_rho)).real();
pflows[ix] += con;
}
}
}
double ptotal(std::accumulate(pflows.begin(),pflows.end(),0.));
ptotal *= UseRandom::rnd();
for(unsigned int ix = 0;ix < pflows.size(); ++ix) {
if(ptotal <= pflows[ix]) {
colourFlow(ix);
ME(mes[ix]);
break;
}
ptotal -= pflows[ix];
}
}
else {
unsigned int iflow = colourFlow();
me2 = nfactors[iflow][iflow]*(mel[iflow].contract(mel[iflow],_rho)).real();
}
// return the matrix element squared
return me2;
}
diff --git a/Hadronization/HadronSelector.cc b/Hadronization/HadronSelector.cc
--- a/Hadronization/HadronSelector.cc
+++ b/Hadronization/HadronSelector.cc
@@ -1,822 +1,822 @@
// -*- C++ -*-
//
// HadronSelector.cc is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the HadronSelector class.
//
#include "HadronSelector.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/ParVector.h"
#include "ThePEG/Interface/RefVector.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include <ThePEG/PDT/EnumParticles.h>
#include <ThePEG/Repository/EventGenerator.h>
#include <ThePEG/Repository/CurrentGenerator.h>
#include <ThePEG/Repository/Repository.h>
#include "CheckId.h"
#include <ThePEG/Utilities/DescribeClass.h>
using namespace Herwig;
DescribeAbstractClass<HadronSelector,Interfaced>
describeHadronSelector("Herwig::HadronSelector","");
namespace {
int abs(PDT::Colour c) {
return c > 0 ? c : -c;
}
// debug helper
void dumpTable(const HadronSelector::HadronTable & tbl) {
typedef HadronSelector::HadronTable::const_iterator TableIter;
for (TableIter it = tbl.begin(); it != tbl.end(); ++it) {
cerr << it->first.first << ' '
<< it->first.second << '\n';
for (HadronSelector::KupcoData::const_iterator jt = it->second.begin();
jt != it->second.end(); ++jt) {
cerr << '\t' << *jt << '\n';
}
}
}
bool weightIsLess (pair<tcPDPtr,double> a, pair<tcPDPtr,double> b) {
return a.second < b.second;
}
}
ostream & Herwig::operator<< (ostream & os,
const HadronSelector::HadronInfo & hi ) {
os << std::scientific << std::showpoint
<< std::setprecision(4)
<< setw(2)
<< hi.id << '\t'
// << hi.ptrData << ' '
<< hi.swtef << '\t'
<< hi.wt << '\t'
<< hi.overallWeight << '\t'
<< ounit(hi.mass,GeV);
return os;
}
HadronSelector::HadronSelector(unsigned int opt)
: _pwtDquark( 1.0 ),_pwtUquark( 1.0 ),_pwtSquark( 1.0 ),_pwtCquark( 1.0 ),
_pwtBquark( 1.0 ),_pwtDIquark( 1.0 ),
_weight1S0(Nmax,1.),_weight3S1(Nmax,1.),_weight1P1(Nmax,1.),_weight3P0(Nmax,1.),
_weight3P1(Nmax,1.),_weight3P2(Nmax,1.),_weight1D2(Nmax,1.),_weight3D1(Nmax,1.),
_weight3D2(Nmax,1.),_weight3D3(Nmax,1.),
_repwt(Lmax,vector<vector<double> >(Jmax,vector<double>(Nmax))),
_sngWt( 1.0 ),_decWt( 1.0 ),
_topt(opt),_trial(0)
{
// The mixing angles
// the ideal mixing angle
const double idealAngleMix = atan( sqrt(0.5) ) * 180.0 / Constants::pi;
// \eta-\eta' mixing angle
_etamix = -23.0;
// phi-omega mixing angle
_phimix = +36.0;
// h_1'-h_1 mixing angle
_h1mix = idealAngleMix;
// f_0(1710)-f_0(1370) mixing angle
_f0mix = idealAngleMix;
// f_1(1420)-f_1(1285)\f$ mixing angle
_f1mix = idealAngleMix;
// f'_2-f_2\f$ mixing angle
_f2mix = +26.0;
// eta_2(1870)-eta_2(1645) mixing angle
_eta2mix = idealAngleMix;
// phi(???)-omega(1650) mixing angle
_omhmix = idealAngleMix;
// phi_3-omega_3 mixing angle
_ph3mix = +28.0;
// eta(1475)-eta(1295) mixing angle
_eta2Smix = idealAngleMix;
// phi(1680)-omega(1420) mixing angle
_phi2Smix = idealAngleMix;
}
void HadronSelector::persistentOutput(PersistentOStream & os) const {
os << _partons << _pwtDquark << _pwtUquark << _pwtSquark
<< _pwtCquark << _pwtBquark << _pwtDIquark
<< _etamix << _phimix << _h1mix << _f0mix << _f1mix << _f2mix
<< _eta2mix << _omhmix << _ph3mix << _eta2Smix << _phi2Smix
<< _weight1S0 << _weight3S1 << _weight1P1 << _weight3P0 << _weight3P1
<< _weight3P2 << _weight1D2 << _weight3D1 << _weight3D2 << _weight3D3
<< _forbidden << _sngWt << _decWt << _repwt << _pwt
<< _table;
}
void HadronSelector::persistentInput(PersistentIStream & is, int) {
is >> _partons >> _pwtDquark >> _pwtUquark >> _pwtSquark
>> _pwtCquark >> _pwtBquark
>> _pwtDIquark>> _etamix >> _phimix >> _h1mix >> _f0mix >> _f1mix >> _f2mix
>> _eta2mix >> _omhmix >> _ph3mix >> _eta2Smix >> _phi2Smix
>> _weight1S0 >> _weight3S1 >> _weight1P1 >> _weight3P0 >> _weight3P1
>> _weight3P2 >> _weight1D2 >> _weight3D1 >> _weight3D2 >> _weight3D3
>> _forbidden >> _sngWt >> _decWt >> _repwt >> _pwt
>> _table;
}
void HadronSelector::Init() {
static ClassDocumentation<HadronSelector> documentation
("There is no documentation for the HadronSelector class");
static Parameter<HadronSelector,double>
interfacePwtDquark("PwtDquark","Weight for choosing a quark D",
&HadronSelector::_pwtDquark, 0, 1.0, 0.0, 10.0,
false,false,false);
static Parameter<HadronSelector,double>
interfacePwtUquark("PwtUquark","Weight for choosing a quark U",
&HadronSelector::_pwtUquark, 0, 1.0, 0.0, 10.0,
false,false,false);
static Parameter<HadronSelector,double>
interfacePwtSquark("PwtSquark","Weight for choosing a quark S",
&HadronSelector::_pwtSquark, 0, 1.0, 0.0, 10.0,
false,false,false);
static Parameter<HadronSelector,double>
interfacePwtCquark("PwtCquark","Weight for choosing a quark C",
&HadronSelector::_pwtCquark, 0, 1.0, 0.0, 10.0,
false,false,false);
static Parameter<HadronSelector,double>
interfacePwtBquark("PwtBquark","Weight for choosing a quark B",
&HadronSelector::_pwtBquark, 0, 1.0, 0.0, 10.0,
false,false,false);
static Parameter<HadronSelector,double>
interfacePwtDIquark("PwtDIquark","Weight for choosing a DIquark",
&HadronSelector::_pwtDIquark, 0, 1.0, 0.0, 100.0,
false,false,false);
static Parameter<HadronSelector,double>
interfaceSngWt("SngWt","Weight for singlet baryons",
&HadronSelector::_sngWt, 0, 1.0, 0.0, 10.0,
false,false,false);
static Parameter<HadronSelector,double>
interfaceDecWt("DecWt","Weight for decuplet baryons",
&HadronSelector::_decWt, 0, 1.0, 0.0, 10.0,
false,false,false);
static RefVector<HadronSelector,ParticleData> interfacePartons
("Partons",
"The partons which are to be considered as the consistuents of the hadrons.",
&HadronSelector::_partons, -1, false, false, true, false, false);
static RefVector<HadronSelector,ParticleData> interfaceForbidden
("Forbidden",
"The PDG codes of the particles which cannot be produced in the hadronization.",
&HadronSelector::_forbidden, -1, false, false, true, false, false);
//
// mixing angles
//
// the ideal mixing angle
const double idealAngleMix = atan( sqrt(0.5) ) * 180.0 / Constants::pi;
static Parameter<HadronSelector,double> interface11S0Mixing
("11S0Mixing",
"The mixing angle for the I=0 mesons from the 1 1S0 multiplet,"
" i.e. eta and etaprime.",
&HadronSelector::_etamix, -23., -180., 180.,
false, false, Interface::limited);
static Parameter<HadronSelector,double> interface13S1Mixing
("13S1Mixing",
"The mixing angle for the I=0 mesons from the 1 3S1 multiplet,"
" i.e. phi and omega.",
&HadronSelector::_phimix, +36., -180., 180.,
false, false, Interface::limited);
static Parameter<HadronSelector,double> interface11P1Mixing
("11P1Mixing",
"The mixing angle for the I=0 mesons from the 1 1P1 multiplet,"
" i.e. h_1' and h_1.",
&HadronSelector::_h1mix, idealAngleMix, -180., 180.,
false, false, Interface::limited);
static Parameter<HadronSelector,double> interface13P0Mixing
("13P0Mixing",
"The mixing angle for the I=0 mesons from the 1 3P0 multiplet,"
" i.e. f_0(1710) and f_0(1370).",
&HadronSelector::_f0mix, idealAngleMix, -180., 180.,
false, false, Interface::limited);
static Parameter<HadronSelector,double> interface13P1Mixing
("13P1Mixing",
"The mixing angle for the I=0 mesons from the 1 3P1 multiplet,"
" i.e. f_1(1420) and f_1(1285).",
&HadronSelector::_f1mix, idealAngleMix, -180., 180.,
false, false, Interface::limited);
static Parameter<HadronSelector,double> interface13P2Mixing
("13P2Mixing",
"The mixing angle for the I=0 mesons from the 1 3P2 multiplet,"
" i.e. f'_2 and f_2.",
&HadronSelector::_f2mix, 26.0, -180., 180.,
false, false, Interface::limited);
static Parameter<HadronSelector,double> interface11D2Mixing
("11D2Mixing",
"The mixing angle for the I=0 mesons from the 1 1D2 multiplet,"
" i.e. eta_2(1870) and eta_2(1645).",
&HadronSelector::_eta2mix, idealAngleMix, -180., 180.,
false, false, Interface::limited);
static Parameter<HadronSelector,double> interface13D0Mixing
("13D0Mixing",
"The mixing angle for the I=0 mesons from the 1 3D0 multiplet,"
" i.e. eta_2(1870) phi(?) and omega(1650).",
&HadronSelector::_omhmix, idealAngleMix, -180., 180.,
false, false, Interface::limited);
static Parameter<HadronSelector,double> interface13D1Mixing
("13D1Mixing",
"The mixing angle for the I=0 mesons from the 1 3D1 multiplet,"
" i.e. phi_3 and omega_3.",
&HadronSelector::_ph3mix, 28.0, -180., 180.,
false, false, Interface::limited);
static Parameter<HadronSelector,double> interface21S0Mixing
("21S0Mixing",
"The mixing angle for the I=0 mesons from the 2 1S0 multiplet,"
" i.e. eta(1475) and eta(1295).",
&HadronSelector::_eta2Smix, idealAngleMix, -180., 180.,
false, false, Interface::limited);
static Parameter<HadronSelector,double> interface23S1Mixing
("23S1Mixing",
"The mixing angle for the I=0 mesons from the 1 3S1 multiplet,"
" i.e. phi(1680) and omega(1420).",
&HadronSelector::_phi2Smix, idealAngleMix, -180., 180.,
false, false, Interface::limited);
//
// the meson weights
//
static ParVector<HadronSelector,double> interface1S0Weights
("1S0Weights",
"The weights for the 1S0 multiplets start with n=1.",
&HadronSelector::_weight1S0, Nmax, 1.0, 0.0, 100.0,
false, false, Interface::limited);
static ParVector<HadronSelector,double> interface3S1Weights
("3S1Weights",
"The weights for the 3S1 multiplets start with n=1.",
&HadronSelector::_weight3S1, Nmax, 1.0, 0.0, 100.0,
false, false, Interface::limited);
static ParVector<HadronSelector,double> interface1P1Weights
("1P1Weights",
"The weights for the 1P1 multiplets start with n=1.",
&HadronSelector::_weight1P1, Nmax, 1.0, 0.0, 100.0,
false, false, Interface::limited);
static ParVector<HadronSelector,double> interface3P0Weights
("3P0Weights",
"The weights for the 3P0 multiplets start with n=1.",
&HadronSelector::_weight3P0, Nmax, 1.0, 0.0, 100.0,
false, false, Interface::limited);
static ParVector<HadronSelector,double> interface3P1Weights
("3P1Weights",
"The weights for the 3P1 multiplets start with n=1.",
&HadronSelector::_weight3P1, Nmax, 1.0, 0.0, 100.0,
false, false, Interface::limited);
static ParVector<HadronSelector,double> interface3P2Weights
("3P2Weights",
"The weights for the 3P2 multiplets start with n=1.",
&HadronSelector::_weight3P2, Nmax, 1.0, 0.0, 100.0,
false, false, Interface::limited);
static ParVector<HadronSelector,double> interface1D2Weights
("1D2Weights",
"The weights for the 1D2 multiplets start with n=1.",
&HadronSelector::_weight1D2, Nmax, 1.0, 0.0, 100.0,
false, false, Interface::limited);
static ParVector<HadronSelector,double> interface3D1Weights
("3D1Weights",
"The weights for the 3D1 multiplets start with n=1.",
&HadronSelector::_weight3D1, Nmax, 1.0, 0.0, 100.0,
false, false, Interface::limited);
static ParVector<HadronSelector,double> interface3D2Weights
("3D2Weights",
"The weights for the 3D2 multiplets start with n=1.",
&HadronSelector::_weight3D2, Nmax, 1.0, 0.0, 100.0,
false, false, Interface::limited);
static ParVector<HadronSelector,double> interface3D3Weights
("3D3Weights",
"The weights for the 3D3 multiplets start with n=1.",
&HadronSelector::_weight3D3, Nmax, 1.0, 0.0, 100.0,
false, false, Interface::limited);
static Switch<HadronSelector,unsigned int> interfaceTrial
("Trial",
"A Debugging option to only produce certain types of hadrons",
&HadronSelector::_trial, 0, false, false);
static SwitchOption interfaceTrialAll
(interfaceTrial,
"All",
"Produce all the hadrons",
0);
static SwitchOption interfaceTrialPions
(interfaceTrial,
"Pions",
"Only produce pions",
1);
static SwitchOption interfaceTrialSpin2
(interfaceTrial,
"Spin2",
"Only mesons with spin less than or equal to two are produced",
2);
static SwitchOption interfaceTrialSpin3
(interfaceTrial,
"Spin3",
"Only hadrons with spin less tan or equal to three are produced",
3);
}
double HadronSelector::mixingStateWeight(long id) {
switch(id) {
case ParticleID::eta: return 0.5*probabilityMixing(_etamix ,1);
case ParticleID::etaprime: return 0.5*probabilityMixing(_etamix ,2);
case ParticleID::phi: return 0.5*probabilityMixing(_phimix ,1);
case ParticleID::omega: return 0.5*probabilityMixing(_phimix ,2);
case ParticleID::hprime_1: return 0.5*probabilityMixing(_h1mix ,1);
case ParticleID::h_1: return 0.5*probabilityMixing(_h1mix ,2);
case 10331: return 0.5*probabilityMixing(_f0mix ,1);
case 10221: return 0.5*probabilityMixing(_f0mix ,2);
case ParticleID::fprime_1: return 0.5*probabilityMixing(_f1mix ,1);
case ParticleID::f_1: return 0.5*probabilityMixing(_f1mix ,2);
case ParticleID::fprime_2: return 0.5*probabilityMixing(_f2mix ,1);
case ParticleID::f_2: return 0.5*probabilityMixing(_f2mix ,2);
case 10335: return 0.5*probabilityMixing(_eta2mix ,1);
case 10225: return 0.5*probabilityMixing(_eta2mix ,2);
// missing phi member of 13D1 should be here
case 30223: return 0.5*probabilityMixing(_omhmix ,2);
case 337: return 0.5*probabilityMixing(_ph3mix ,1);
case 227: return 0.5*probabilityMixing(_ph3mix ,2);
case 100331: return 0.5*probabilityMixing(_eta2mix ,1);
case 100221: return 0.5*probabilityMixing(_eta2mix ,2);
case 100333: return 0.5*probabilityMixing(_phi2Smix,1);
case 100223: return 0.5*probabilityMixing(_phi2Smix,2);
default: return 1./3.;
}
}
void HadronSelector::doinit() {
Interfaced::doinit();
// the default partons allowed
// the quarks
for ( int ix=1; ix<=5; ++ix ) {
_partons.push_back(getParticleData(ix));
}
// the diquarks
for(unsigned int ix=1;ix<=5;++ix) {
for(unsigned int iy=1; iy<=ix;++iy) {
_partons.push_back(getParticleData(CheckId::makeDiquarkID(ix,iy)));
}
}
// set the weights for the various excited mesons
// set all to one to start with
for (int l = 0; l < Lmax; ++l ) {
for (int j = 0; j < Jmax; ++j) {
for (int n = 0; n < Nmax; ++n) {
_repwt[l][j][n] = 1.0;
}
}
}
// set the others from the relevant vectors
for( int ix=0;ix<max(int(_weight1S0.size()),int(Nmax));++ix)
_repwt[0][0][ix]=_weight1S0[ix];
for( int ix=0;ix<max(int(_weight3S1.size()),int(Nmax));++ix)
_repwt[0][1][ix]=_weight3S1[ix];
for( int ix=0;ix<max(int(_weight1P1.size()),int(Nmax));++ix)
_repwt[1][1][ix]=_weight1P1[ix];
for( int ix=0;ix<max(int(_weight3P0.size()),int(Nmax));++ix)
_repwt[1][0][ix]=_weight3P0[ix];
for( int ix=0;ix<max(int(_weight3P1.size()),int(Nmax));++ix)
_repwt[1][1][ix]=_weight3P1[ix];
for( int ix=0;ix<max(int(_weight3P2.size()),int(Nmax));++ix)
_repwt[1][2][ix]=_weight3P2[ix];
for( int ix=0;ix<max(int(_weight1D2.size()),int(Nmax));++ix)
_repwt[2][2][ix]=_weight1D2[ix];
for( int ix=0;ix<max(int(_weight3D1.size()),int(Nmax));++ix)
_repwt[2][1][ix]=_weight3D1[ix];
for( int ix=0;ix<max(int(_weight3D2.size()),int(Nmax));++ix)
_repwt[2][2][ix]=_weight3D2[ix];
for( int ix=0;ix<max(int(_weight3D3.size()),int(Nmax));++ix)
_repwt[2][3][ix]=_weight3D3[ix];
// weights for the different quarks etc
for(unsigned int ix=0; ix<_partons.size(); ++ix) {
_pwt[_partons[ix]]=1.;
}
_pwt[getParticleData(1)] = _pwtDquark;
_pwt[getParticleData(2)] = _pwtUquark;
_pwt[getParticleData(3)] = _pwtSquark;
_pwt[getParticleData(4)] = _pwtCquark;
_pwt[getParticleData(5)] = _pwtBquark;
_pwt[getParticleData(1103)] = _pwtDIquark * _pwtDquark * _pwtDquark;
_pwt[getParticleData(2101)] = 0.5 * _pwtDIquark * _pwtUquark * _pwtDquark;
_pwt[getParticleData(2203)] = _pwtDIquark * _pwtUquark * _pwtUquark;
_pwt[getParticleData(3101)] = 0.5 * _pwtDIquark * _pwtSquark * _pwtDquark;
_pwt[getParticleData(3201)] = 0.5 * _pwtDIquark * _pwtSquark * _pwtUquark;
_pwt[getParticleData(3303)] = _pwtDIquark * _pwtSquark * _pwtSquark;
// Commenting out heavy di-quark weights
_pwt[getParticleData(4101)] = 0.0;
_pwt[getParticleData(4201)] = 0.0;
_pwt[getParticleData(4301)] = 0.0;
_pwt[getParticleData(4403)] = 0.0;
_pwt[getParticleData(5101)] = 0.0;
_pwt[getParticleData(5201)] = 0.0;
_pwt[getParticleData(5301)] = 0.0;
_pwt[getParticleData(5401)] = 0.0;
_pwt[getParticleData(5503)] = 0.0;
// find the maximum
map<tcPDPtr,double>::iterator pit =
max_element(_pwt.begin(),_pwt.end(),weightIsLess);
double pmax = pit->second;
for(pit=_pwt.begin(); pit!=_pwt.end(); ++pit) {
pit->second/=pmax;
}
// construct the hadron tables
constructHadronTable();
// for debugging
// dumpTable(table());
}
void HadronSelector::constructHadronTable() {
// initialise the table
_table.clear();
for(unsigned int ix=0; ix<_partons.size(); ++ix) {
for(unsigned int iy=0; iy<_partons.size(); ++iy) {
if (!(DiquarkMatcher::Check(_partons[ix]->id())
&& DiquarkMatcher::Check(_partons[iy]->id())))
_table[make_pair(_partons[ix]->id(),_partons[iy]->id())] = KupcoData();
}
}
// get the particles from the event generator
ParticleMap particles = generator()->particles();
// loop over the particles
double maxdd(0.),maxss(0.),maxrest(0.);
for(ParticleMap::iterator it=particles.begin();
it!=particles.end(); ++it) {
long pid = it->first;
tPDPtr particle = it->second;
int pspin = particle->iSpin();
// Don't include hadrons which are explicitly forbidden
if(find(_forbidden.begin(),_forbidden.end(),particle)!=_forbidden.end())
continue;
// Don't include non-hadrons or antiparticles
if(pid < 100) continue;
// remove diffractive particles
if(pspin == 0) continue;
// K_0S and K_0L not made make K0 and Kbar0
if(pid==ParticleID::K_S0||pid==ParticleID::K_L0) continue;
// Debugging options
// Only include those with 2J+1 less than...5
if(_trial==2 && pspin >= 5) continue;
// Only include those with 2J+1 less than...7
if(_trial==3 && pspin >= 7) continue;
// Only include pions
if(_trial==1 && pid!=111 && pid!=211) continue;
// Get the flavours
const int x4 = (pid/1000)%10;
const int x3 = (pid/100 )%10;
const int x2 = (pid/10 )%10;
const int x7 = (pid/1000000)%10;
const bool wantSusy = x7 == 1 || x7 == 2;
int flav1;
int flav2;
// Skip non-hadrons (susy particles, etc...)
if(x3 == 0 || x2 == 0) continue;
else if(x4 == 0) { // meson
flav1 = x2;
flav2 = x3;
}
else { // baryon
flav1 = CheckId::makeDiquarkID(x2,x3);
flav2 = x4;
}
if (wantSusy) flav2 += 1000000 * x7;
HadronInfo a(pid,
particle,
specialWeight(pid),
particle->mass());
// set the weight to the number of spin states
a.overallWeight = pspin;
// identical light flavours
if(flav1 == flav2 && flav1<=3) {
// ddbar> uubar> admixture states
if(flav1==1) {
if(_topt != 0) a.overallWeight *= 0.5*a.swtef;
_table[make_pair(1,1)].insert(a);
_table[make_pair(2,2)].insert(a);
if(_topt == 0 && a.overallWeight > maxdd) maxdd = a.overallWeight;
}
// load up ssbar> uubar> ddbar> admixture states
else {
a.wt = mixingStateWeight(pid);
a.overallWeight *= a.wt;
if(_topt != 0) a.overallWeight *= a.swtef;
_table[make_pair(1,1)].insert(a);
_table[make_pair(2,2)].insert(a);
if(_topt == 0 && a.overallWeight > maxdd) maxdd = a.overallWeight;
a.wt = (_topt != 0) ? 1.- 2.*a.wt : 1 - a.wt;
if(a.wt > 0) {
a.overallWeight = a.wt * a.swtef * pspin;
_table[make_pair(3,3)].insert(a);
if(_topt == 0 && a.overallWeight > maxss) maxss = a.overallWeight;
}
}
}
// light baryons with all quarks identical
else if((flav1 == 1 && flav2 == 1103) || (flav1 == 1103 && flav2 == 1) ||
(flav1 == 2 && flav2 == 2203) || (flav1 == 2203 && flav2 == 2) ||
(flav1 == 3 && flav2 == 3303) || (flav1 == 3303 && flav2 == 3)) {
if(_topt != 0) a.overallWeight *= 1.5*a.swtef;
_table[make_pair(flav1,flav2)].insert(a);
_table[make_pair(flav2,flav1)].insert(a);
if(_topt == 0 && a.overallWeight > maxrest) maxrest = a.overallWeight;
}
// all other cases
else {
if(_topt != 0) a.overallWeight *=a.swtef;
_table[make_pair(flav1,flav2)].insert(a);
if(flav1 != flav2) _table[make_pair(flav2,flav1)].insert(a);
if(_topt == 0 && a.overallWeight > maxrest) maxrest = a.overallWeight;
}
}
// Account for identical combos of diquark/quarks and symmetrical elements
// e.g. U UD = D UU
HadronTable::iterator tit;
for(tit=_table.begin();tit!=_table.end();++tit) {
if(tit->first.first>ParticleID::c) continue;
if(!DiquarkMatcher::Check(tit->first.second)) continue;
long k, l, sub;
if(tit->first.second>=ParticleID::bd_0) {
k = ParticleID::b;
sub = ParticleID::bd_0/100;
}
else if(tit->first.second>=ParticleID::cd_0) {
k = ParticleID::c;
sub = ParticleID::cd_0/100;
}
else if(tit->first.second>=ParticleID::sd_0) {
k = ParticleID::s;
sub = ParticleID::sd_0/100;
}
else if(tit->first.second>=ParticleID::ud_0) {
k = ParticleID::u;
sub = ParticleID::ud_0/100;
}
else if(tit->first.second==ParticleID::dd_1) {
k = ParticleID::d;
sub = ParticleID::dd_1/100;
}
else continue;
sub=tit->first.second/100-sub+1;
if(sub > tit->first.first) {
l = 1000*sub+100*tit->first.first+1;
}
else if(sub==tit->first.first) {
l = 1000*sub+ 100*tit->first.first+3;
}
else {
l = 100*sub +1000*tit->first.first+1;
}
if(tit->second.empty()) {
pair<long,long> newpair(k,l);
tit->second=_table[newpair];
newpair=make_pair(tit->first.second,tit->first.first);
_table[newpair]=tit->second;
};
}
// normalise weights to one for first option
if(_topt == 0) {
HadronTable::const_iterator tit;
KupcoData::iterator it;
for(tit=_table.begin();tit!=_table.end();++tit) {
double weight;
if(tit->first.first==tit->first.second) {
if(tit->first.first==1||tit->first.first==2) weight=1./maxdd;
else if (tit->first.first==3) weight=1./maxss;
else weight=1./maxrest;
}
else weight=1./maxrest;
for(it = tit->second.begin(); it!=tit->second.end(); ++it) {
it->rescale(weight);
}
}
}
}
double HadronSelector::specialWeight(long id) {
int pspin = id % 10;
// Only K0L and K0S have pspin == 0
if(pspin == 0) pspin = 1;
// Baryon : J = 1/2 or 3/2
else if(pspin == 2 || pspin == 4) {
if(pspin == 2) {
// Singlet (Lambda-like) baryon
if( (id/100)%10 < (id/10 )%10 ) return sqr(_sngWt);
// octet
else return 1.;
}
// Decuplet baryon
else return sqr(_decWt);
}
// Meson
else if(pspin % 2 == 1) {
// Total angular momentum
int j = (pspin - 1) / 2;
// related to Orbital angular momentum l
int nl = (id/10000 )%10;
int l = -999;
int n = (id/100000)%10; // Radial excitation
if(j == 0) l = nl;
else if(nl == 0) l = j - 1;
else if(nl == 1 || nl == 2) l = j;
else if(nl == 3) l = j + 1;
// Angular or Radial excited meson
if((l||j||n) && l>=0 && l<Lmax && j<Jmax && n<Nmax) {
return sqr(_repwt[l][j][n]);
}
}
return 1.0;
}
int HadronSelector::signHadron(tcPDPtr idQ1, tcPDPtr idQ2,
tcPDPtr hadron) const {
// This method receives in input three PDG ids, whose the
// first two have proper signs (corresponding to particles, id > 0,
// or antiparticles, id < 0 ), whereas the third one must
// be always positive (particle not antiparticle),
// corresponding to:
// --- quark-antiquark, or antiquark-quark, or
// quark-diquark, or diquark-quark, or
// antiquark-antidiquark, or antidiquark-antiquark
// for the first two input (idQ1, idQ2);
// --- meson or baryon for the third input (idHad):
// The method returns:
// --- + 1 if the two partons (idQ1, idQ2) are exactly
// the constituents for the hadron idHad;
// --- - 1 if the two partons (idQ1, idQ2) are exactly
// the constituents for the anti-hadron -idHad;
// --- + 0 otherwise.
// The method it is therefore useful to decide the
// sign of the id of the produced hadron as appeared
// in the vector _vecHad (where only hadron idHad > 0 are present)
// given the two constituent partons.
int sign = 0;
long idHad = hadron->id();
assert(idHad > 0);
int chargeIn = idQ1->iCharge() + idQ2->iCharge();
int chargeOut = hadron->iCharge();
// same charge
if( chargeIn == chargeOut && chargeIn !=0 ) sign = +1;
else if(chargeIn == -chargeOut && chargeIn !=0 ) sign = -1;
else if(chargeIn == 0 && chargeOut == 0 ) {
// In the case of same null charge, there are four cases:
// i) K0-like mesons, B0-like mesons, Bs-like mesons
// the PDG convention is to consider them "antiparticle" (idHad < 0)
// if the "dominant" (heavier) flavour (respectively, s, b)
// is a quark (idQ > 0): for instance, B0s = (b, sbar) has id < 0
// Remember that there is an important exception for K0L (id=130) and
// K0S (id=310): they don't have antiparticles, therefore idHad > 0
// always. We use below the fact that K0L and K0S are the unique
// hadrons having 0 the first (less significant) digit of their id.
// 2) D0-like mesons: the PDG convention is to consider them "particle"
// (idHad > 0) if the charm flavour is carried by a c: (c,ubar) has id>0
// 3) the remaining mesons should not have antiparticle, therefore their
// sign is always positive.
// 4) for baryons, that is when one of idQ1 and idQ2 is a (anti-) quark and
// the other one is a (anti-) diquark the sign is negative when both
// constituents are "anti", that is both with id < 0; positive otherwise.
// meson
- if(abs(idQ1->iColour())== 3 && abs(idQ2->iColour()) == 3 &&
+ if(abs(int(idQ1->iColour()))== 3 && abs(int(idQ2->iColour())) == 3 &&
!DiquarkMatcher::Check(idQ1->id()) && !DiquarkMatcher::Check(idQ2->id()))
{
int idQa = abs(idQ1->id());
int idQb = abs(idQ2->id());
int dominant = idQ2->id();
if(idQa > idQb) {
swap(idQa,idQb);
dominant = idQ1->id();
}
if((idQa==ParticleID::d && idQb==ParticleID::s) ||
(idQa==ParticleID::d && idQb==ParticleID::b) ||
(idQa==ParticleID::s && idQb==ParticleID::b)) {
// idHad%10 is zero for K0L,K0S
if (dominant < 0 || idHad%10 == 0) sign = +1;
else if(dominant > 0) sign = -1;
}
else if((idQa==ParticleID::u && idQb==ParticleID::c) ||
(idQa==ParticleID::u && idQb==ParticleID::t) ||
(idQa==ParticleID::c && idQb==ParticleID::t)) {
if (dominant > 0) sign = +1;
else if(dominant < 0) sign = -1;
}
else if(idQa==idQb) sign = +1;
// sets sign for Susy particles
else sign = (dominant > 0) ? +1 : -1;
}
// baryon
else if(DiquarkMatcher::Check(idQ1->id()) || DiquarkMatcher::Check(idQ2->id())) {
if (idQ1->id() > 0 && idQ2->id() > 0) sign = +1;
else if(idQ1->id() < 0 && idQ2->id() < 0) sign = -1;
}
}
if (sign == 0) {
cerr << "Could not work out sign for "
<< idQ1->PDGName() << ' '
<< idQ2->PDGName() << " => "
<< hadron->PDGName() << '\n';
assert(false);
}
return sign;
}
pair<tcPDPtr,tcPDPtr> HadronSelector::lightestHadronPair(tcPDPtr ptr1, tcPDPtr ptr2,
tcPDPtr ptr3) const {
// throw exception of id3!=0 as doesn't work
if ( ptr3 ) throw Exception()
<< "ptr3!=0 not yet implemented in HadronSelector::lightestHadronPair"
<< Exception::abortnow;
// charge
int totalcharge = ptr1->iCharge() + ptr2->iCharge();
if ( ptr3 ) totalcharge += ptr3->iCharge();
tcPDPtr vIdHad1[2]={tcPDPtr(),tcPDPtr()},vIdHad2[2]={tcPDPtr(),tcPDPtr()};
bool vOk[2] = {false, false};
Energy vMassPair[2] = { ZERO, ZERO };
for (int i = 0; i < 2; i++) {
tcPDPtr idPartner = i==0 ? getParticleData(ParticleID::d) : getParticleData(ParticleID::u);
// Change sign to idPartner (transform it into a anti-quark) if it is not
// possible to form a meson or a baryon.
assert (ptr1 && idPartner);
if (!CheckId::canBeHadron(ptr1, idPartner)) idPartner = idPartner->CC();
vIdHad1[i] = lightestHadron(ptr1, idPartner);
vIdHad2[i] = lightestHadron(ptr2, idPartner->CC());
if ( vIdHad1[i] && vIdHad2[i] &&
vIdHad1[i]->iCharge() + vIdHad2[i]->iCharge() == totalcharge ) {
vOk[i] = true;
vMassPair[i] = vIdHad1[i]->mass() + vIdHad2[i]->mass();
}
}
// Take the lightest pair compatible with charge conservation.
if ( vOk[0] && ( ! vOk[1] || vMassPair[0] <= vMassPair[1] ) ) {
return make_pair(vIdHad1[0],vIdHad2[0]);
}
else if ( vOk[1] && ( ! vOk[0] || vMassPair[1] < vMassPair[0] ) ) {
return make_pair(vIdHad1[1],vIdHad2[1]);
}
else {
return make_pair(tcPDPtr(),tcPDPtr());
}
}
Energy HadronSelector::massLightestBaryonPair(tcPDPtr ptr1, tcPDPtr ptr2) const {
// Make sure that we don't have any diquarks as input, return arbitrarily
// large value if we do
Energy currentSum = Constants::MaxEnergy;
for(unsigned int ix=0; ix<_partons.size(); ++ix) {
if(!DiquarkMatcher::Check(_partons[ix]->id())) continue;
HadronTable::const_iterator
tit1=_table.find(make_pair(abs(ptr1->id()),_partons[ix]->id())),
tit2=_table.find(make_pair(_partons[ix]->id(),abs(ptr2->id())));
if( tit1==_table.end() || tit2==_table.end()) continue;
if(tit1->second.empty()||tit2->second.empty()) continue;
Energy s = tit1->second.begin()->mass + tit2->second.begin()->mass;
if(currentSum > s) currentSum = s;
}
return currentSum;
}
diff --git a/Hadronization/HwppSelector.cc b/Hadronization/HwppSelector.cc
--- a/Hadronization/HwppSelector.cc
+++ b/Hadronization/HwppSelector.cc
@@ -1,196 +1,196 @@
// -*- C++ -*-
//
// HwppSelector.cc is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the HwppSelector class.
//
#include "HwppSelector.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "Herwig++/Utilities/Kinematics.h"
#include "ThePEG/Utilities/Selector.h"
#include "ThePEG/Repository/UseRandom.h"
#include "CheckId.h"
#include <cassert>
#include <ThePEG/Utilities/DescribeClass.h>
using namespace Herwig;
DescribeClass<HwppSelector,HadronSelector>
describeHwppSelector("Herwig::HwppSelector","");
IBPtr HwppSelector::clone() const {
return new_ptr(*this);
}
IBPtr HwppSelector::fullclone() const {
return new_ptr(*this);
}
namespace {
int abs(PDT::Colour c) {
return c > 0 ? c : -c;
}
}
void HwppSelector::doinit() {
HadronSelector::doinit();
}
void HwppSelector::persistentOutput(PersistentOStream & os) const {
os << _mode;
}
void HwppSelector::persistentInput(PersistentIStream & is, int) {
is >> _mode;
}
void HwppSelector::Init() {
static ClassDocumentation<HwppSelector> documentation
("The HwppSelector class implements the Herwig++ algorithm for selecting"
" the hadrons",
"The hadronization used the selection algorithm described in \\cite{Kupco:1998fx}.",
"%\\cite{Kupco:1998fx}\n"
"\\bibitem{Kupco:1998fx}\n"
" A.~Kupco,\n"
" ``Cluster hadronization in HERWIG 5.9,''\n"
" arXiv:hep-ph/9906412.\n"
" %%CITATION = HEP-PH/9906412;%%\n"
);
// put useMe() only in correct place!
static Switch<HwppSelector,unsigned int> interfaceMode
("Mode",
"Which algorithm to use",
&HwppSelector::_mode, 1, false, false);
static SwitchOption interfaceModeKupco
(interfaceMode,
"Kupco",
"Use the Kupco approach",
0);
static SwitchOption interfaceModeHwpp
(interfaceMode,
"Hwpp",
"Use the Herwig++ approach",
1);
}
pair<tcPDPtr,tcPDPtr> HwppSelector::chooseHadronPair(const Energy cluMass,tcPDPtr par1,
tcPDPtr par2,tcPDPtr )
{
// if either of the input partons is a diquark don't allow diquarks to be
// produced
bool diquark = !(DiquarkMatcher::Check(par1->id()) || DiquarkMatcher::Check(par2->id()));
bool quark = true;
// if the Herwig++ algorithm
if(_mode ==1) {
if(cluMass > massLightestBaryonPair(par1,par2) &&
UseRandom::rnd() > 1./(1.+pwtDIquark())) {
diquark = true;
quark = false;
}
else {
useMe();
diquark = false;
quark = true;
}
}
// weights for the different possibilities
Energy weight, wgtsum(ZERO);
// loop over all hadron pairs with the allowed flavours
vector<Kupco> hadrons;
for(unsigned int ix=0;ix<partons().size();++ix) {
tcPDPtr quarktopick = partons()[ix];
- if(!quark && abs(quarktopick->iColour()) == 3
+ if(!quark && abs(int(quarktopick->iColour())) == 3
&& !DiquarkMatcher::Check(quarktopick->id())) continue;
- if(!diquark && abs(quarktopick->iColour()) == 3
+ if(!diquark && abs(int(quarktopick->iColour())) == 3
&& DiquarkMatcher::Check(quarktopick->id())) continue;
HadronTable::const_iterator
tit1 = table().find(make_pair(abs(par1->id()),quarktopick->id()));
HadronTable::const_iterator
tit2 = table().find(make_pair(quarktopick->id(),abs(par2->id())));
// If not in table skip
if(tit1 == table().end()||tit2==table().end()) continue;
// tables empty skip
if(tit1->second.empty()||tit2->second.empty()) continue;
// if too massive skip
if(cluMass <= tit1->second.begin()->mass +
tit2->second.begin()->mass) continue;
// loop over the hadrons
KupcoData::iterator H1,H2;
for(H1 = tit1->second.begin();H1 != tit1->second.end(); ++H1) {
for(H2 = tit2->second.begin();H2 != tit2->second.end(); ++H2) {
// break if cluster too light
if(cluMass < H1->mass + H2->mass) break;
// calculate the weight
weight = pwt(quarktopick) * H1->overallWeight * H2->overallWeight *
Kinematics::pstarTwoBodyDecay(cluMass, H1->mass, H2->mass );
int signQ = 0;
assert (par1 && quarktopick);
assert (par2);
assert(quarktopick->CC());
if(CheckId::canBeHadron(par1, quarktopick->CC())
&& CheckId::canBeHadron(quarktopick, par2))
signQ = +1;
else if(CheckId::canBeHadron(par1, quarktopick)
&& CheckId::canBeHadron(quarktopick->CC(), par2))
signQ = -1;
else {
cerr << "Could not make sign for" << par1->id()<< " " << quarktopick->id()
<< " " << par2->id() << "\n";
assert(false);
}
if (signQ == -1)
quarktopick = quarktopick->CC();
// construct the object with the info
Kupco a(quarktopick, H1->ptrData, H2->ptrData, weight);
hadrons.push_back(a);
wgtsum += weight;
}
}
}
if (hadrons.empty())
return make_pair(tcPDPtr(),tcPDPtr());
// select the hadron
wgtsum *= UseRandom::rnd();
unsigned int ix=0;
do {
wgtsum-= hadrons[ix].weight;
++ix;
}
while(wgtsum > ZERO && ix < hadrons.size());
if(ix == hadrons.size() && wgtsum > ZERO)
return make_pair(tcPDPtr(),tcPDPtr());
--ix;
assert(hadrons[ix].idQ);
int signHad1 = signHadron(par1, hadrons[ix].idQ->CC(), hadrons[ix].hadron1);
int signHad2 = signHadron(par2, hadrons[ix].idQ, hadrons[ix].hadron2);
assert(!( signHad1 == 0 || signHad2 == 0));
// throw Exception() << "HwppSelector::selectPair "
// << "***Inconsistent Hadron "
// << hadrons[ix].idQ->id() << " "
// << hadrons[ix].hadron1->id() << " "
// << hadrons[ix].hadron2->id() << " "
// << signHad1 << " " << signHad2
// << Exception::runerror;
return make_pair
( signHad1 > 0 ? hadrons[ix].hadron1 : tcPDPtr(hadrons[ix].hadron1->CC()),
signHad2 > 0 ? hadrons[ix].hadron2 : tcPDPtr(hadrons[ix].hadron2->CC()));
}
diff --git a/Models/ADD/ADDModel.cc b/Models/ADD/ADDModel.cc
--- a/Models/ADD/ADDModel.cc
+++ b/Models/ADD/ADDModel.cc
@@ -1,120 +1,120 @@
// -*- C++ -*-
//
// ADDModel.cc is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the ADDModel class.
//
#include "ADDModel.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace Herwig;
using namespace ThePEG;
using namespace ThePEG::Helicity;
void ADDModel::doinit() {
addVertex(FFGRVertex_);
addVertex(VVGRVertex_);
addVertex(SSGRVertex_);
addVertex(FFGGRVertex_);
addVertex(FFWGRVertex_);
addVertex(GGGGRVertex_);
addVertex(WWWGRVertex_);
- StandardModel::doinit();
+ BSMModel::doinit();
}
void ADDModel::persistentOutput(PersistentOStream & os) const {
os << ounit(mPlanckBar_,GeV) << ounit(md_,GeV) << delta_
<< ounit(lambdaT_,GeV)
<< FFGRVertex_ << VVGRVertex_ << SSGRVertex_
<< FFGGRVertex_ << FFWGRVertex_
<< GGGGRVertex_ << WWWGRVertex_;
}
void ADDModel::persistentInput(PersistentIStream & is, int) {
is >> iunit(mPlanckBar_,GeV) >> iunit(md_,GeV) >> delta_
>> iunit(lambdaT_,GeV)
>> FFGRVertex_ >> VVGRVertex_ >> SSGRVertex_
>> FFGGRVertex_ >> FFWGRVertex_
>> GGGGRVertex_ >> WWWGRVertex_;
}
ClassDescription<ADDModel> ADDModel::initADDModel;
// Definition of the static class description member.
void ADDModel::Init() {
static Reference<ADDModel,ThePEG::Helicity::AbstractFFTVertex> interfaceVertexFFGR
("Vertex/FFGR",
"Reference to the fermion-fermion-graviton vertex",
&ADDModel::FFGRVertex_, false, false, true, false, false);
static Reference<ADDModel,ThePEG::Helicity::AbstractVVTVertex> interfaceVertexVVGR
("Vertex/VVGR",
"Reference to the vector-vector-graviton vertex",
&ADDModel::VVGRVertex_, false, false, true, false, false);
static Reference<ADDModel,ThePEG::Helicity::AbstractSSTVertex> interfaceVertexSSGR
("Vertex/SSGR",
"Reference to the scalar-scalar-graviton vertex",
&ADDModel::SSGRVertex_, false, false, true, false, false);
static Reference<ADDModel,ThePEG::Helicity::AbstractFFVTVertex> interfaceVertexFFGGR
("Vertex/FFGGR",
"Reference to the fermion-antifermion-gluon graviton vertex",
&ADDModel::FFGGRVertex_, false, false, true, false, false);
static Reference<ADDModel,ThePEG::Helicity::AbstractFFVTVertex> interfaceVertexFFWGR
("Vertex/FFWGR",
"Reference to the fermion-antifermion-weak vector boson graviton vertex",
&ADDModel::FFWGRVertex_, false, false, true, false, false);
static Reference<ADDModel,ThePEG::Helicity::AbstractVVVTVertex> interfaceVertexGGGGR
("Vertex/GGGGR",
"Reference to the three gluon graviton vertex",
&ADDModel::GGGGRVertex_, false, false, true, false, false);
static Reference<ADDModel,ThePEG::Helicity::AbstractVVVTVertex> interfaceVertexWWWGR
("Vertex/WWWGR",
"Reference to the three weak vector boson graviton vertex",
&ADDModel::WWWGRVertex_, false, false, true, false, false);
static ClassDocumentation<ADDModel> documentation
("The ADDModel class replaces the Standard Model class for the"
" ADD model");
static Parameter<ADDModel,unsigned int> interfaceDelta
("Delta",
"Number of extra dimensions",
&ADDModel::delta_, 2, 2, 1000,
false, false, Interface::limited);
static Parameter<ADDModel,Energy> interfaceReducedPlanckMass
("Reduced4dPlanckMass",
"The reduced planck mass in 4 dimensions",
&ADDModel::mPlanckBar_, GeV, 2.4e18*GeV, 1e17*GeV, 1e20*GeV,
false, false, Interface::limited);
static Parameter<ADDModel,Energy> interfaceDdPlanckMass
("DdPlanckMass",
"The d dimension planck mass",
&ADDModel::md_, GeV, 1000.*GeV, 100.0*GeV, 1e6*GeV,
false, false, Interface::limited);
static Parameter<ADDModel,Energy> interfaceLambdaT
("LambdaT",
"The cut-off for virtual graviton processes",
&ADDModel::lambdaT_, GeV, 1000.*GeV, 100.*GeV, 100000.0*GeV,
false, false, Interface::limited);
}
diff --git a/Models/ADD/ADDModel.h b/Models/ADD/ADDModel.h
--- a/Models/ADD/ADDModel.h
+++ b/Models/ADD/ADDModel.h
@@ -1,267 +1,267 @@
// -*- C++ -*-
//
// ADDModel.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_ADDModel_H
#define HERWIG_ADDModel_H
// This is the declaration of the ADDModel class.
-#include "Herwig++/Models/StandardModel/StandardModel.h"
+#include "Herwig++/Models/General/BSMModel.h"
#include "ThePEG/Helicity/Vertex/AbstractFFTVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractVVTVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractSSTVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractFFVTVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractVVVTVertex.h"
#include "ADDModel.fh"
namespace Herwig {
using namespace ThePEG;
using namespace ThePEG::Helicity;
/** \ingroup Models
*
* This is the class to be used instead of the Standard Model class for
* the Randell Sundrum model.
*
* @see \ref ADDModelInterfaces "The interfaces"
* defined for ADDModel.
* @see StandardModel
* @see StandardModelBase
*
*/
-class ADDModel: public StandardModel {
+class ADDModel: public BSMModel {
public:
/**
* The default constructor
*/
ADDModel() : delta_(2), mPlanckBar_(2.4e18*GeV),
md_(1000.*GeV), lambdaT_(1000.*GeV) {
useMe();
}
/**
* Number of extrac dimensions
*/
unsigned int delta() const {return delta_;}
/**
* The reduced Planck mass in 4d
*/
Energy MPlanckBar() const {return mPlanckBar_;}
/**
* The d-dimension Planck mass
*/
Energy MD() const {return md_;}
/**
* The cut-off for virtual gravition processes
*/
Energy LambdaT() const {return lambdaT_;}
/** @name Vertices */
//@{
/**
* Pointer to the object handling the \f$G\to f\bar{f}\f$ vertex.
*/
tAbstractFFTVertexPtr vertexFFGR() const {return FFGRVertex_;}
/**
* Pointer to the object handling the \f$G\to VV\f$ vertex.
*/
tAbstractVVTVertexPtr vertexVVGR() const {return VVGRVertex_;}
/**
* Pointer to the object handling the \f$G\to SS\f$ vertex.
*/
tAbstractSSTVertexPtr vertexSSGR() const {return SSGRVertex_;}
/**
* Pointer to the object handling the \f$G\to f\bar{f}g\f$ vertex.
*/
tAbstractFFVTVertexPtr vertexFFGGR() const {return FFGGRVertex_;}
/**
* Pointer to the object handling the \f$G\to f\bar{f}W^\pm/Z^0/\gamma\f$ vertex.
*/
tAbstractFFVTVertexPtr vertexFFWGR() const {return FFWGRVertex_;}
/**
* Pointer to the object handling the \f$G\to W^+W^-Z^0/\gamma\f$ vertex.
*/
tAbstractVVVTVertexPtr vertexWWWGR() const {return WWWGRVertex_;}
/**
* Pointer to the object handling the \f$G\to ggg\f$ vertex.
*/
tAbstractVVVTVertexPtr vertexGGGGR() const {return GGGGRVertex_;}
//@}
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);
//@}
/**
* Standard Init function used to initialize the interfaces.
*/
static void Init();
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();
//@}
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
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.
*/
virtual IBPtr fullclone() const {return new_ptr(*this);}
//@}
private:
/**
* Describe a concrete class with persistent data.
*/
static ClassDescription<ADDModel> initADDModel;
/**
* Private and non-existent assignment operator.
*/
ADDModel & operator=(const ADDModel &);
private:
/**
* Number of extrac dimensions
*/
unsigned int delta_;
/**
* The reduced Planck mass in 4d
*/
Energy mPlanckBar_;
/**
* The d-dimension Planck mass
*/
Energy md_;
/**
* Cut-off parameter for virtual gravitons
*/
Energy lambdaT_;
/**
* Pointer to the object handling the \f$G\to f\bar{f}\f$ vertex.
*/
AbstractFFTVertexPtr FFGRVertex_;
/**
* Pointer to the object handling the \f$G\to VV\f$ vertex.
*/
AbstractVVTVertexPtr VVGRVertex_;
/**
* Pointer to the object handling the \f$G\to SS\f$ vertex.
*/
AbstractSSTVertexPtr SSGRVertex_;
/**
* Pointer to the object handling the \f$G\to f\bar{f}g\f$ vertex.
*/
AbstractFFVTVertexPtr FFGGRVertex_;
/**
* Pointer to the object handling the \f$G\to f\bar{f}W/Z^0\gamma\f$ vertex.
*/
AbstractFFVTVertexPtr FFWGRVertex_;
/**
* Pointer to the object handling the \f$G\to W^+W^-Z^0\gamma\f$ vertex.
*/
AbstractVVVTVertexPtr WWWGRVertex_;
/**
* Pointer to the object handling the \f$G\to ggg\f$ vertex.
*/
AbstractVVVTVertexPtr GGGGRVertex_;
};
}
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/**
* The following template specialization informs ThePEG about the
* base class of ADDModel.
*/
template <>
struct BaseClassTrait<Herwig::ADDModel,1> {
/** Typedef of the base class of ADDModel. */
- typedef Herwig::StandardModel NthBase;
+ typedef Herwig::BSMModel NthBase;
};
/**
* The following template specialization informs ThePEG about the
* name of this class and the shared object where it is defined.
*/
template <>
struct ClassTraits<Herwig::ADDModel>
: public ClassTraitsBase<Herwig::ADDModel> {
/** Return the class name.*/
static string className() { return "Herwig::ADDModel"; }
/**
* Return the name of the shared library to be loaded to get
* access to this class and every other class it uses
* (except the base class).
*/
static string library() { return "HwADDModel.so"; }
};
/** @endcond */
}
#endif /* HERWIG_ADDModel_H */
diff --git a/Models/General/BSMModel.cc b/Models/General/BSMModel.cc
new file mode 100644
--- /dev/null
+++ b/Models/General/BSMModel.cc
@@ -0,0 +1,353 @@
+// -*- C++ -*-
+//
+// This is the implementation of the non-inlined, non-templated member
+// functions of the BSMModel class.
+//
+
+#include "BSMModel.h"
+#include "ThePEG/Interface/ClassDocumentation.h"
+#include "ThePEG/Interface/Parameter.h"
+#include "ThePEG/Interface/Switch.h"
+#include "ThePEG/EventRecord/Particle.h"
+#include "ThePEG/Repository/UseRandom.h"
+#include "ThePEG/Repository/EventGenerator.h"
+#include "ThePEG/Utilities/DescribeClass.h"
+#include "ThePEG/Repository/Repository.h"
+#include "ThePEG/Utilities/StringUtils.h"
+#include "ThePEG/Persistency/PersistentOStream.h"
+#include "ThePEG/Persistency/PersistentIStream.h"
+#include "ThePEG/PDT/MassGenerator.h"
+#include "ThePEG/PDT/WidthGenerator.h"
+#include "ThePEG/PDT/DecayMode.h"
+
+using namespace Herwig;
+
+BSMModel::BSMModel() : decayFile_(), readDecays_(true),
+ topModesFromFile_(false),
+ tolerance_(1e-6)
+{}
+
+void BSMModel::persistentOutput(PersistentOStream & os) const {
+ os << decayFile_ << topModesFromFile_ << tolerance_;
+}
+
+void BSMModel::persistentInput(PersistentIStream & is, int) {
+ is >> decayFile_ >> topModesFromFile_ >> tolerance_;
+}
+
+// *** 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).
+DescribeAbstractClass<BSMModel,Herwig::StandardModel>
+ describeHerwigBSMModel("Herwig::BSMModel", "BSMModel.so");
+
+void BSMModel::Init() {
+
+ static ClassDocumentation<BSMModel> documentation
+ ("The BSMModel class provides a base class for BSM models including the"
+ " features to read decays in the SLHA format");
+
+ static Parameter<BSMModel,string> interfaceDecayFileName
+ ("DecayFileName",
+ "Name of the file from which to read decays in the SLHA format",
+ &BSMModel::decayFile_, "",
+ false, false);
+
+ static Switch<BSMModel,bool> interfaceTopModes
+ ("TopModes",
+ "Whether ro use the Herwig++ SM top decays or those from the SLHA file",
+ &BSMModel::topModesFromFile_, false, false, false);
+ static SwitchOption interfaceTopModesFile
+ (interfaceTopModes,
+ "File",
+ "Take the modes from the files",
+ true);
+ static SwitchOption interfaceTopModesHerwig
+ (interfaceTopModes,
+ "Herwig",
+ "Use the SM ones", false);
+
+ static Parameter<BSMModel,double> interfaceBRTolerance
+ ("BRTolerance",
+ "Tolerance for the sum of branching ratios to be difference from one.",
+ &BSMModel::tolerance_, 1e-6, 1e-8, 0.01,
+ false, false, Interface::limited);
+
+}
+
+void BSMModel::doinit() {
+ StandardModel::doinit();
+ // check if need to read decays
+ if(decayFile()==""||!readDecays_) return;
+ decayRead();
+}
+
+void BSMModel::decayRead() {
+ // read decays
+ CFileLineReader cfile;
+ cfile.open(decayFile_);
+ if( !cfile ) throw SetupException()
+ << "BSMModel::doinit - An error occurred in opening the "
+ << "decay file \"" << decayFile_ << "\"."
+ << Exception::runerror;
+ //Before reading the spectrum/decay files the SM higgs
+ //decay modes, mass and width generators need to be turned off.
+ PDPtr h0 = getParticleData(ParticleID::h0);
+ h0->widthGenerator(WidthGeneratorPtr());
+ h0->massGenerator(MassGenPtr());
+ h0->width(ZERO);
+ h0->stable(true);
+ DecaySet::const_iterator dit = h0->decayModes().begin();
+ DecaySet::const_iterator dend = h0->decayModes().end();
+ for( ; dit != dend; ++dit ) {
+ generator()->preinitInterface(*dit, "BranchingRatio", "set", "0.");
+ generator()->preinitInterface(*dit, "OnOff", "set", "Off");
+ }
+ // if taking the top modes from the file
+ // delete the SM stuff
+ if(topModesFromFile_) {
+ PDPtr top = getParticleData(ParticleID::t);
+ top->widthGenerator(WidthGeneratorPtr());
+ top->massGenerator(MassGenPtr());
+ DecaySet::const_iterator dit = top->decayModes().begin();
+ DecaySet::const_iterator dend = top->decayModes().end();
+ for( ; dit != dend; ++dit ) {
+ generator()->preinitInterface(*dit, "BranchingRatio", "set", "0.");
+ generator()->preinitInterface(*dit, "OnOff", "set", "Off");
+ }
+ }
+ // read first line and check if this is a Les Houches event file
+ cfile.readline();
+ bool lesHouches = cfile.find("<LesHouchesEvents");
+ bool reading = !lesHouches;
+ if(lesHouches) cfile.readline();
+ // function pointer for putting all characters to lower case.
+ int (*pf)(int) = tolower;
+ while (true) {
+ string line = cfile.getline();
+ // check for start of slha block in SLHA files
+ if(lesHouches && !reading) {
+ if(line.find("<slha")==0) reading = true;
+ if(!cfile.readline()) break;
+ continue;
+ }
+ // ignore comment lines
+ if(line[0] == '#') {
+ if(!cfile.readline()) break;
+ continue;
+ }
+ // make everything lower case
+ transform(line.begin(), line.end(), line.begin(), pf);
+ // start of a block
+ if(line.find("decay") == 0) {
+ readDecay(cfile, line);
+ continue;
+ }
+ else if( lesHouches && line.find("</slha") == 0 ) {
+ reading = false;
+ break;
+ }
+ if(!cfile.readline()) break;
+ }
+}
+
+void BSMModel::readDecay(CFileLineReader & cfile,
+ string decay) const{
+ // extract parent PDG code and width
+ long parent(0);
+ Energy width(ZERO);
+ istringstream iss(decay);
+ string dummy;
+ iss >> dummy >> parent >> iunit(width, GeV);
+ PDPtr inpart = getParticleData(parent);
+ if(!topModesFromFile_&&abs(parent)==ParticleID::t) {
+ cfile.readline();
+ return;
+ }
+ if(!inpart) throw SetupException()
+ << "BSMModel::readDecay() - "
+ << "A ParticleData object with the PDG code "
+ << parent << " does not exist. "
+ << Exception::runerror;
+ inpart->width(width);
+ if( width > ZERO ) inpart->cTau(hbarc/width);
+ inpart->widthCut(5.*width);
+ Energy inMass = inpart->mass();
+ string prefix(inpart->name() + "->");
+ double brsum(0.);
+ unsigned int nmode = 0;
+ while(cfile.readline()) {
+ string line = cfile.getline();
+ // skip comments
+ if(line[0] == '#') continue;
+ // reached the end
+ if( line[0] == 'B' || line[0] == 'b' ||
+ line[0] == 'D' || line[0] == 'd' ||
+ line[0] == '<' ) {
+ cfile.resetline();
+ break;
+ }
+ // read the mode
+ // get the branching ratio and no of decay products
+ istringstream is(line);
+ double brat(0.);
+ unsigned int nda(0),npr(0);
+ is >> brat >> nda;
+ vector<tcPDPtr> products,bosons;
+ Energy mout(ZERO),moutnoWZ(ZERO);
+ string tag = prefix;
+ while( true ) {
+ long t;
+ is >> t;
+ if( is.fail() ) break;
+ if( t == abs(parent) ) {
+ throw SetupException()
+ << "An error occurred while read a decay of the "
+ << inpart->PDGName() << ". One of its products has the same PDG code "
+ << "as the parent particle. Please check the SLHA file.\n"
+ << Exception::runerror;
+ }
+ tcPDPtr p = getParticleData(t);
+ if( !p ) {
+ throw SetupException()
+ << "BSMModel::readDecay() - An unknown PDG code has been encounterd "
+ << "while reading a decay mode. ID: " << t
+ << Exception::runerror;
+ }
+ ++npr;
+ tag += p->name() + ",";
+ Energy mass = p->mass();
+ mout += mass;
+ if(abs(p->id())==ParticleID::Wplus||p->id()==ParticleID::Z0) {
+ bosons.push_back(p);
+ }
+ else {
+ products.push_back(p);
+ moutnoWZ += mass;
+ }
+ }
+ if( npr != nda ) {
+ throw SetupException()
+ << "BSMModel::readDecay - While reading a decay of the "
+ << inpart->PDGName() << " from an SLHA file, an inconsistency "
+ << "between the number of decay products and the value in "
+ << "the 'NDA' column was found. Please check if the spectrum "
+ << "file is correct.\n"
+ << Exception::warning;
+ }
+ if( npr > 1 ) {
+ tag.replace(tag.size() - 1, 1, ";");
+ // normal option
+ if(mout<=inMass) {
+ inpart->stable(false);
+ brsum += brat;
+ createDecayMode(tag, brat);
+ }
+ // no possible off-shell gauge bosons throw it away
+ else if(bosons.empty() || bosons.size()>2 ||
+ moutnoWZ>=inMass) {
+ cerr << "BSMModel::readDecay() "
+ << "The decay " << tag << " cannot proceed for on-shell "
+ << "particles, skipping it.\n";
+ }
+ else {
+ Energy maxMass = inMass - moutnoWZ;
+ string newTag = prefix;
+ for(unsigned int ix=0;ix<products.size();++ix)
+ newTag += products[ix]->name() + ",";
+ if(bosons.size()==1) {
+ cerr << "BSMModel::readDecay() "
+ << "The decay " << tag << " cannot proceed for on-shell\n"
+ << "particles, replacing gauge boson with its decay products\n";
+ vector<pair<double,string> > modes =
+ createWZDecayModes(newTag,brat,bosons[0],maxMass);
+ for(unsigned int ix=0;ix<modes.size();++ix) {
+ modes[ix].second.replace(modes[ix].second.size() - 1, 1, ";");
+ createDecayMode(modes[ix].second,modes[ix].first);
+ brsum += modes[ix].first;
+ }
+ }
+ else if(bosons.size()==2) {
+ bool identical = bosons[0]->id()==bosons[1]->id();
+ if(maxMass>bosons[0]->mass()&&maxMass>bosons[1]->mass()) {
+ cerr << "BSMModel::readDecay() "
+ << "The decay " << tag << " cannot proceed for on-shell\n"
+ << "particles, replacing one of the gauge bosons"
+ << " with its decay products\n";
+ unsigned int imax = identical ? 1 : 2;
+ if(imax==2) brat *= 0.5;
+ for(unsigned int ix=0;ix<imax;++ix) {
+ string newTag2 = newTag+bosons[ix]->name()+',';
+ unsigned int iother = ix==0 ? 1 : 0;
+ vector<pair<double,string> > modes =
+ createWZDecayModes(newTag2,brat,bosons[iother],maxMass);
+ for(unsigned int ix=0;ix<modes.size();++ix) {
+ modes[ix].second.replace(modes[ix].second.size() - 1, 1, ";");
+ createDecayMode(modes[ix].second,modes[ix].first);
+ brsum += modes[ix].first;
+ }
+ }
+ }
+ else {
+ cerr << "BSMModel::readDecay() "
+ << "The decay " << tag << " cannot proceed for on-shell\n"
+ << "particles, and has too many off-shell gauge bosons,"
+ << " skipping it.\n";
+ }
+ }
+ else {
+ cerr << "BSMModel::readDecay() "
+ << "The decay " << tag << " cannot proceed for on-shell\n"
+ << "particles, and has too many outgoing gauge bosons skipping it.\n";
+ }
+ }
+ }
+ }
+ if( abs(brsum - 1.) > tolerance_ && nmode!=0 ) {
+ cerr << "Warning: The total branching ratio for " << inpart->PDGName()
+ << " from the spectrum file does not sum to 1. The branching fractions"
+ << " will be rescaled.\n";
+ cerr << setprecision(13) << abs(brsum - 1.) << "\n";
+ }
+}
+
+void BSMModel::createDecayMode(string tag, double brat) const {
+ tDMPtr dm = generator()->findDecayMode(tag);
+ if(!dm) {
+ dm = generator()->preinitCreateDecayMode(tag);
+ }
+ generator()->preinitInterface(dm, "OnOff", "set", "On");
+ generator()->preinitInterface(dm, "Decayer", "set","/Herwig/Decays/Mambo");
+ ostringstream brf;
+ brf << setprecision(13)<< brat;
+ generator()->preinitInterface(dm, "BranchingRatio","set", brf.str());
+}
+
+
+vector<pair<double,string> >
+BSMModel::createWZDecayModes(string tag, double brat,
+ tcPDPtr boson, Energy maxMass) const {
+ vector<pair<double,string> > modes;
+ double sum(0.);
+ for(DecaySet::const_iterator dit=boson->decayModes().begin();
+ dit!=boson->decayModes().end();++dit) {
+ tcDMPtr mode = *dit;
+ if(!mode->on()) continue;
+ string extra;
+ Energy outMass(ZERO);
+ for(ParticleMSet::const_iterator pit=mode->products().begin();
+ pit!=mode->products().end();++pit) {
+ extra += (**pit).name() + ",";
+ outMass += (**pit).mass();
+ }
+ if(outMass<maxMass) {
+ sum += mode->brat();
+ modes.push_back(make_pair(mode->brat(),tag+extra));
+ }
+ }
+ for(unsigned int ix=0;ix<modes.size();++ix)
+ modes[ix].first *= brat/sum;
+ return modes;
+}
diff --git a/Models/General/BSMModel.h b/Models/General/BSMModel.h
new file mode 100644
--- /dev/null
+++ b/Models/General/BSMModel.h
@@ -0,0 +1,162 @@
+// -*- C++ -*-
+#ifndef Herwig_BSMModel_H
+#define Herwig_BSMModel_H
+//
+// This is the declaration of the BSMModel class.
+//
+
+#include "Herwig++/Models/StandardModel/StandardModel.h"
+#include "ThePEG/Utilities/CFileLineReader.h"
+
+namespace Herwig {
+
+using namespace ThePEG;
+
+/**
+ * Here is the documentation of the BSMModel class.
+ *
+ * @see \ref BSMModelInterfaces "The interfaces"
+ * defined for BSMModel.
+ */
+class BSMModel: public Herwig::StandardModel {
+
+public:
+
+ /**
+ * The default constructor.
+ */
+ BSMModel();
+
+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:
+
+ /**
+ * Get name of SLHA decay file
+ */
+ const string & decayFile() const {return decayFile_;}
+
+ /**
+ * Set name of SLHA decay file
+ */
+ void decayFile(string in) {decayFile_ = in;}
+
+ /**
+ * Read the decays
+ */
+ void decayRead();
+
+ /**
+ * Read decaymodes from LHA file
+ * @param ifs input stream containg data
+ * @param decay string containing name of parent and value of total width
+ */
+ void readDecay(CFileLineReader & ifs, string decay) const;
+
+ /**
+ * Create a DecayMode object in the repository
+ * @param tag The tag identifying the decay mode including the prefix
+ * 'decaymode'
+ * @param brat Branching ratio of this mode
+ */
+ void createDecayMode(string tag, double brat) const;
+
+ /**
+ * Create a DecayMode object in the repository
+ * @param tag The tag identifying the decay mode including the prefix
+ * 'decaymode'
+ * @param brat Branching ratio of this mode
+ */
+ vector<pair<double,string> > createWZDecayModes(string tag, double brat,
+ tcPDPtr boson,
+ Energy maxMass) const;
+
+ /**
+ * read the decays
+ */
+ bool readDecays() const {return readDecays_;}
+
+ /**
+ * set the reading of the decays
+ */
+ void readDecays(bool in) {readDecays_=in;}
+
+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();
+ //@}
+
+ /**
+ * Overloaded function from Interfaced
+ */
+ virtual bool preInitialize() const {
+ return true;
+ }
+
+private:
+
+ /**
+ * The assignment operator is private and must never be called.
+ * In fact, it should not even be implemented.
+ */
+ BSMModel & operator=(const BSMModel &);
+
+private:
+
+ /**
+ * Name of the decay file
+ */
+ string decayFile_;
+
+ /**
+ * Read the decays from the file
+ */
+ bool readDecays_;
+
+ /**
+ * Whether or not to replace the top decay modes with those from
+ * the SLHA files
+ */
+ bool topModesFromFile_;
+
+ /**
+ * Tolerance for branching ratios
+ */
+ double tolerance_;
+
+};
+
+}
+
+#endif /* Herwig_BSMModel_H */
diff --git a/Models/General/DecayConstructor.cc b/Models/General/DecayConstructor.cc
--- a/Models/General/DecayConstructor.cc
+++ b/Models/General/DecayConstructor.cc
@@ -1,153 +1,155 @@
// -*- C++ -*-
//
// DecayConstructor.cc is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the DecayConstructor class.
//
#include "DecayConstructor.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/RefVector.h"
#include "ThePEG/Interface/ParVector.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Repository/BaseRepository.h"
#include <iterator>
using namespace Herwig;
using namespace ThePEG;
IBPtr DecayConstructor::clone() const {
return new_ptr(*this);
}
IBPtr DecayConstructor::fullclone() const {
return new_ptr(*this);
}
void DecayConstructor::persistentOutput(PersistentOStream & os) const {
os << NBodyDecayConstructors_ << QEDGenerator_;
}
void DecayConstructor::persistentInput(PersistentIStream & is, int) {
is >> NBodyDecayConstructors_ >> QEDGenerator_;
}
ClassDescription<DecayConstructor> DecayConstructor::initDecayConstructor;
// Definition of the static class description member.
void DecayConstructor::Init() {
static ClassDocumentation<DecayConstructor> documentation
("There is no documentation for the TwoBodyDecayConstructor class");
static RefVector<DecayConstructor,Herwig::NBodyDecayConstructorBase>
interfaceNBodyDecayConstructors
("NBodyDecayConstructors",
"Vector of references to NBodyDecayConstructors",
&DecayConstructor::NBodyDecayConstructors_, -1, false, false, true,
false, false);
static ParVector<DecayConstructor,string> interfaceDisableModes
("DisableModes",
"A list of decay modes to disable",
&DecayConstructor::_disableDMTags, -1, string(""), string(""), string(""),
false, false, Interface::nolimits);
static Reference<DecayConstructor,DecayRadiationGenerator> interfaceQEDGenerator
("QEDGenerator",
"Object to generate QED radiation in particle decays",
&DecayConstructor::QEDGenerator_, false, false, true, true, false);
}
/** A helper function for for_each to sort the decay mode tags into the
* standard order.
*/
namespace {
void adjustFSOrder(string & tag) {
string::size_type sep = tag.find(">");
string head = tag.substr(0, sep + 1);
string products = tag.substr(sep + 1);
OrderedParticles finalstate;
bool loopbreak(true);
while ( loopbreak ) {
sep = products.find(",");
string child;
if( sep != string::npos ) {
child = products.substr(0, sep);
products = products.substr(sep + 1);
}
else {
child = string(products.begin(), products.end() - 1);
loopbreak = false;
}
PDPtr p = BaseRepository::GetObject<PDPtr>
(string("/Herwig/Particles/" + child));
if( p ) finalstate.insert(p);
}
if( finalstate.empty() ) return;
tag = head;
OrderedParticles::const_iterator iend = finalstate.end();
OrderedParticles::size_type count(0), npr(finalstate.size());
for( OrderedParticles::const_iterator it = finalstate.begin();
it != iend; ++it ) {
tag += (**it).name();
if( ++count != npr ) tag += string(",");
}
tag += string(";");
}
}
namespace {
/// Helper function for sorting by number of outgoing lines
inline bool orderNBodyConstructors(tNBodyDecayConstructorBasePtr a,
tNBodyDecayConstructorBasePtr b) {
return a->numBodies() < b->numBodies();
}
}
void DecayConstructor::doinit() {
Interfaced::doinit();
//Need to check that the stored decay mode tags have the
//products in the standard order
for_each( _disableDMTags.begin(), _disableDMTags.end(), adjustFSOrder );
sort(NBodyDecayConstructors_.begin(), NBodyDecayConstructors_.end(),
orderNBodyConstructors);
}
-void DecayConstructor::createDecayers(const PDVector & particles) {
+void DecayConstructor::createDecayers(const PDVector & particles,
+ double minBR) {
+ _minBR = minBR;
if ( particles.empty() || NBodyDecayConstructors_.empty() ) return;
// turn the vector into a set to avoid duplicates
set<PDPtr> particleSet(particles.begin(),particles.end());
typedef vector<NBodyDecayConstructorBasePtr>::iterator NBDecayIterator;
NBDecayIterator it = NBodyDecayConstructors_.begin();
NBDecayIterator iend = NBodyDecayConstructors_.end();
for( ; it != iend; ++it ) {
(**it).init();
(**it).decayConstructor(this);
(**it).DecayList(particleSet);
}
}
bool DecayConstructor::disableDecayMode(string tag) const {
if( _disableDMTags.empty() ) return false;
vector<string>::const_iterator dit = _disableDMTags.begin();
vector<string>::const_iterator dend = _disableDMTags.end();
bool disable(false);
for( ; dit != dend; ++dit ) {
if( *dit == tag ) {
disable = true;
break;
}
}
return disable;
}
diff --git a/Models/General/DecayConstructor.h b/Models/General/DecayConstructor.h
--- a/Models/General/DecayConstructor.h
+++ b/Models/General/DecayConstructor.h
@@ -1,189 +1,200 @@
// -*- C++ -*-
//
// DecayConstructor.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_DecayConstructor_H
#define HERWIG_DecayConstructor_H
//
// This is the declaration of the DecayConstructor class.
//
#include "ThePEG/Interface/Interfaced.h"
#include "NBodyDecayConstructorBase.h"
#include "Herwig++/Decay/Radiation/DecayRadiationGenerator.h"
#include "DecayConstructor.fh"
namespace Herwig {
using namespace ThePEG;
/**
* The DecayConstructor class is an interfaced class that stores a
* vector of NBodyDecayConstructor objects and calls the appropriate
* function to create the decayers and decaymodes. There is also an interface
* to add decay mode tags of the form a->b,c,...; which will not
* be created.
*
* @see \ref DecayConstructorInterfaces "The interfaces"
* defined for DecayConstructor.
* @see Interfaced
*/
class DecayConstructor: public Interfaced {
public:
/**
* The default constructor.
*/
DecayConstructor() : NBodyDecayConstructors_(0),
- _disableDMTags(0) {}
+ _disableDMTags(0), _minBR(0.) {}
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();
/**
* Function to create decayers
* @param particles vector of ParticleData pointers to particles contained
* in model
+ * @param minBR minimum branching ratio for modes
*/
- void createDecayers(const vector<PDPtr> & particles);
+ void createDecayers(const vector<PDPtr> & particles, double minBR);
/**
* Check whether the decay mode given is one that should not be
* created
* @param tag The decay mode tag, a->b,c,d,...;
*/
bool disableDecayMode(string tag) const;
/**
* QED Generator
*/
DecayRadiationGeneratorPtr QEDGenerator() {return QEDGenerator_;}
/**
* Vector of references to the objects that will construct the N-Body
* decays.
*/
const vector<NBodyDecayConstructorBasePtr> & decayConstructors() {
return NBodyDecayConstructors_;
}
+ /**
+ * Get minimum branching ratio
+ */
+ double minimumBR() const { return _minBR;}
+
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();
//@}
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:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<DecayConstructor> initDecayConstructor;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
DecayConstructor & operator=(const DecayConstructor &);
private:
/**
* Vector of references to the objects that will construct the N-Body
* decays.
*/
vector<NBodyDecayConstructorBasePtr> NBodyDecayConstructors_;
/**
* A list of DecayMode tags that are not to be created
*/
vector<string> _disableDMTags;
/**
* The decay radiation generator to use for QED radiation
*/
DecayRadiationGeneratorPtr QEDGenerator_;
+
+ /**
+ * Minimum allowed branching ratio
+ */
+ double _minBR;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of DecayConstructor. */
template <>
struct BaseClassTrait<Herwig::DecayConstructor,1> {
/** Typedef of the first base class of DecayConstructor. */
typedef Interfaced NthBase;
};
/** This template specialization informs ThePEG about the name of
* the DecayConstructor class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::DecayConstructor>
: public ClassTraitsBase<Herwig::DecayConstructor> {
/** Return a platform-independent class name */
static string className() { return "Herwig::DecayConstructor"; }
};
/** @endcond */
}
#endif /* HERWIG_DecayConstructor_H */
diff --git a/Models/General/Makefile.am b/Models/General/Makefile.am
--- a/Models/General/Makefile.am
+++ b/Models/General/Makefile.am
@@ -1,25 +1,26 @@
noinst_LTLIBRARIES = libHwModelGenerator.la
libHwModelGenerator_la_SOURCES = \
ModelGenerator.h ModelGenerator.fh ModelGenerator.cc\
DecayConstructor.cc DecayConstructor.h DecayConstructor.fh \
NBodyDecayConstructorBase.cc NBodyDecayConstructorBase.h \
NBodyDecayConstructorBase.fh \
TwoBodyDecayConstructor.cc TwoBodyDecayConstructor.h \
TwoToTwoProcessConstructor.h TwoToTwoProcessConstructor.fh \
TwoToTwoProcessConstructor.cc \
HardProcessConstructor.h HardProcessConstructor.fh \
HardProcessConstructor.cc \
HiggsVectorBosonProcessConstructor.h \
HiggsVectorBosonProcessConstructor.cc \
HiggsVBFProcessConstructor.h \
HiggsVBFProcessConstructor.cc \
QQHiggsProcessConstructor.h \
QQHiggsProcessConstructor.cc \
HPDiagram.h \
ThreeBodyDecayConstructor.h ThreeBodyDecayConstructor.cc \
WeakCurrentDecayConstructor.h WeakCurrentDecayConstructor.cc \
ResonantProcessConstructor.cc ResonantProcessConstructor.h \
ResonantProcessConstructor.fh \
VVSLoopVertex.fh VVSLoopVertex.h VVSLoopVertex.cc \
BSMWidthGenerator.h BSMWidthGenerator.fh BSMWidthGenerator.cc \
-TBDiagram.h
+TBDiagram.h TwoBodyDecay.h\
+BSMModel.h BSMModel.cc
diff --git a/Models/General/ModelGenerator.cc b/Models/General/ModelGenerator.cc
--- a/Models/General/ModelGenerator.cc
+++ b/Models/General/ModelGenerator.cc
@@ -1,450 +1,468 @@
// -*- C++ -*-
//
// ModelGenerator.cc is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the ModelGenerator class.
//
#include "ModelGenerator.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/RefVector.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/DecayMode.h"
#include "ThePEG/Repository/CurrentGenerator.h"
#include "BSMWidthGenerator.h"
#include "Herwig++/PDT/GenericMassGenerator.h"
+#include "Herwig++/Decay/DecayIntegrator.h"
#include "ThePEG/Repository/BaseRepository.h"
using namespace Herwig;
IBPtr ModelGenerator::clone() const {
return new_ptr(*this);
}
IBPtr ModelGenerator::fullclone() const {
return new_ptr(*this);
}
void ModelGenerator::persistentOutput(PersistentOStream & os) const {
os << hardProcessConstructors_ << _theDecayConstructor << particles_
<< offshell_ << Offsel_ << BRnorm_
<< Npoints_ << Iorder_ << BWshape_ << brMin_ << decayOutput_;
}
void ModelGenerator::persistentInput(PersistentIStream & is, int) {
is >> hardProcessConstructors_ >> _theDecayConstructor >> particles_
>> offshell_ >> Offsel_ >> BRnorm_
>> Npoints_ >> Iorder_ >> BWshape_ >> brMin_ >> decayOutput_;
}
ClassDescription<ModelGenerator> ModelGenerator::initModelGenerator;
// Definition of the static class description member.
void ModelGenerator::Init() {
static ClassDocumentation<ModelGenerator> documentation
("This class controls the the use of BSM physics.",
"BSM physics was produced using the algorithm of "
"\\cite{Gigg:2007cr,Gigg:2008yc}",
"\\bibitem{Gigg:2007cr} M.~Gigg and P.~Richardson, \n"
"Eur.\\ Phys.\\ J.\\ C {\\bf 51} (2007) 989.\n"
"%%CITATION = EPHJA,C51,989;%%\n"
" %\\cite{Gigg:2008yc}\n"
"\\bibitem{Gigg:2008yc}\n"
" M.~A.~Gigg and P.~Richardson,\n"
" %``Simulation of Finite Width Effects in Physics Beyond the Standard Model,''\n"
" arXiv:0805.3037 [hep-ph].\n"
" %%CITATION = ARXIV:0805.3037;%%\n"
);
static RefVector<ModelGenerator,HardProcessConstructor>
interfaceHardProcessConstructors
("HardProcessConstructors",
"The objects to construct hard processes",
&ModelGenerator::hardProcessConstructors_, -1,
false, false, true, false, false);
static Reference<ModelGenerator,Herwig::DecayConstructor>
interfaceDecayConstructor
("DecayConstructor",
"Pointer to DecayConstructor helper class",
&ModelGenerator::_theDecayConstructor, false, false, true, false);
static RefVector<ModelGenerator,ThePEG::ParticleData> interfaceModelParticles
("DecayParticles",
"ParticleData pointers to the particles requiring spin correlation "
"decayers. If decay modes do not exist they will also be created.",
&ModelGenerator::particles_, -1, false, false, true, false);
static RefVector<ModelGenerator,ParticleData> interfaceOffshell
("Offshell",
"The particles to treat as off-shell",
&ModelGenerator::offshell_, -1, false, false, true, false);
static Switch<ModelGenerator,int> interfaceWhichOffshell
("WhichOffshell",
"A switch to determine which particles to create mass and width "
"generators for.",
&ModelGenerator::Offsel_, 0, false, false);
static SwitchOption interfaceWhichOffshellSelected
(interfaceWhichOffshell,
"Selected",
"Only create mass and width generators for the particles specified",
0);
static SwitchOption interfaceWhichOffshellAll
(interfaceWhichOffshell,
"All",
"Treat all particles specified in the DecayParticles "
"list as off-shell",
1);
static Switch<ModelGenerator,bool> interfaceBRNormalize
("BRNormalize",
"Whether to normalize the partial widths to BR*total width for an "
"on-shell particle",
&ModelGenerator::BRnorm_, true, false, false);
static SwitchOption interfaceBRNormalizeNormalize
(interfaceBRNormalize,
"Yes",
"Normalize the partial widths",
true);
static SwitchOption interfaceBRNormalizeNoNormalize
(interfaceBRNormalize,
"No",
"Do not normalize the partial widths",
false);
static Parameter<ModelGenerator,int> interfacePoints
("InterpolationPoints",
"Number of points to use for interpolation tables when needed",
&ModelGenerator::Npoints_, 50, 5, 1000,
false, false, true);
static Parameter<ModelGenerator,unsigned int>
interfaceInterpolationOrder
("InterpolationOrder", "The interpolation order for the tables",
&ModelGenerator::Iorder_, 1, 1, 5,
false, false, Interface::limited);
static Switch<ModelGenerator,int> interfaceBreitWignerShape
("BreitWignerShape",
"Controls the shape of the mass distribution generated",
&ModelGenerator::BWshape_, 0, false, false);
static SwitchOption interfaceBreitWignerShapeDefault
(interfaceBreitWignerShape,
"Default",
"Running width with q in numerator and denominator width factor",
0);
static SwitchOption interfaceBreitWignerShapeFixedWidth
(interfaceBreitWignerShape,
"FixedWidth",
"Use a fixed width",
1);
static SwitchOption interfaceBreitWignerShapeNoq
(interfaceBreitWignerShape,
"Noq",
"Use M rather than q in the numerator and denominator width factor",
2);
static SwitchOption interfaceBreitWignerShapeNoNumerator
(interfaceBreitWignerShape,
"NoNumerator",
"Neglect the numerator factors",
3);
static Parameter<ModelGenerator,double> interfaceMinimumBR
("MinimumBR",
"The minimum branching fraction to include",
&ModelGenerator::brMin_, 1e-6, 0.0, 1.0,
false, false, Interface::limited);
static Switch<ModelGenerator,unsigned int> interfaceDecayOutput
("DecayOutput",
"Option to control the output of the decay mode information",
&ModelGenerator::decayOutput_, 1, false, false);
static SwitchOption interfaceDecayOutputNone
(interfaceDecayOutput,
"None",
"No output",
0);
static SwitchOption interfaceDecayOutputPlain
(interfaceDecayOutput,
"Plain",
"Default plain text output",
1);
static SwitchOption interfaceDecayOutputSLHA
(interfaceDecayOutput,
"SLHA",
"Output in the Susy Les Houches Accord format",
2);
}
namespace {
/// Helper function for sorting by mass
inline bool massIsLess(tcPDPtr a, tcPDPtr b) {
return a->mass() < b->mass();
}
}
void ModelGenerator::doinit() {
useMe();
Interfaced::doinit();
// make sure the model is initialized
Ptr<Herwig::StandardModel>::pointer model
= dynamic_ptr_cast<Ptr<Herwig::StandardModel>::pointer>(generator()->standardModel());
model->init();
// and the vertices
for(size_t iv = 0; iv < model->numberOfVertices(); ++iv)
model->vertex(iv)->init();
// sort DecayParticles list by mass
sort(particles_.begin(),particles_.end(),
massIsLess);
//create mass and width generators for the requested particles
PDVector::iterator pit, pend;
if( Offsel_ == 0 ) {
pit = offshell_.begin();
pend = offshell_.end();
}
else {
pit = particles_.begin();
pend = particles_.end();
}
for(; pit != pend; ++pit)
createWidthGenerator(*pit);
//create decayers and decaymodes (if necessary)
if( _theDecayConstructor ) {
_theDecayConstructor->init();
- _theDecayConstructor->createDecayers(particles_);
+ _theDecayConstructor->createDecayers(particles_,brMin_);
}
// write out decays with spin correlations
ostream & os = CurrentGenerator::current().misc();
ofstream ofs;
if ( decayOutput_ >1 ) {
string filename
= CurrentGenerator::current().filename() + "-BR.spc";
ofs.open(filename.c_str());
}
if(decayOutput_!=0) {
if(decayOutput_==1) {
os << "# The decay modes listed below will have spin\n"
<< "# correlations included when they are generated.\n#\n#";
}
else {
ofs << "# Herwig++ decay tables in SUSY Les Houches accord format\n";
ofs << "Block DCINFO # Program information\n";
ofs << "1 Herwig++ # Decay Calculator\n";
ofs << "2 " << generator()->strategy()->versionstring()
<< " # Version number\n";
}
}
pit = particles_.begin();
pend = particles_.end();
for( ; pit != pend; ++pit) {
tPDPtr parent = *pit;
// Check decays for ones where quarks cannot be put on constituent
// mass-shell
checkDecays(parent);
parent->reset();
parent->update();
if( parent->CC() ) parent->CC()->synchronize();
if( parent->decaySelector().empty() ) {
parent->stable(true);
parent->width(ZERO);
parent->massGenerator(tGenericMassGeneratorPtr());
parent->widthGenerator(tGenericWidthGeneratorPtr());
}
else {
if ( decayOutput_ == 2 )
writeDecayModes(ofs, parent);
else
writeDecayModes(os, parent);
}
if( parent->massGenerator() ) {
parent->widthCut(5.*parent->width());
parent->massGenerator()->reset();
if(decayOutput_==1)
os << "# " <<parent->PDGName() << " will be considered off-shell.\n#\n";
}
if( parent->widthGenerator() ) parent->widthGenerator()->reset();
}
//Now construct hard processes given that we know which
//objects have running widths
for(unsigned int ix=0;ix<hardProcessConstructors_.size();++ix) {
hardProcessConstructors_[ix]->init();
hardProcessConstructors_[ix]->constructDiagrams();
}
}
void ModelGenerator::checkDecays(PDPtr parent) {
- if( parent->stable() ) return;
+ if( parent->stable() ) {
+ if(parent->coloured())
+ cerr << "Warning: No decays for coloured particle " << parent->PDGName() << "\n\n"
+ << "have been calcluated in BSM model.\n"
+ << "This may cause problems in the hadronization phase.\n"
+ << "You may have forgotten to switch on the decay mode calculation using\n"
+ << " set TwoBodyDC:CreateDecayModes Yes\n"
+ << " set ThreeBodyDC:CreateDecayModes Yes\n"
+ << " set WeakDecayConstructor:CreateDecayModes Yes\n"
+ << "or the decays of this particle are missing from your\n"
+ << "input spectrum and decay file in the SLHA format.\n\n";
+ return;
+ }
DecaySet::iterator dit = parent->decayModes().begin();
DecaySet::iterator dend = parent->decayModes().end();
Energy oldwidth(parent->width()), newwidth(ZERO);
bool rescalebrat(false);
double brsum(0.);
for(; dit != dend; ++dit ) {
if( !(**dit).on() ) continue;
Energy release((**dit).parent()->mass());
tPDVector::const_iterator pit = (**dit).orderedProducts().begin();
tPDVector::const_iterator pend =(**dit).orderedProducts().end();
for( ; pit != pend; ++pit ) {
release -= (**pit).constituentMass();
}
if( (**dit).brat() < brMin_ || release < ZERO ) {
if( release < ZERO )
cerr << "Warning: The shower cannot be generated using this decay "
<< (**dit).tag() << " because it is too close to threshold. It "
<< "will be switched off and the branching fractions of the "
<< "remaining modes rescaled.\n";
rescalebrat = true;
generator()->preinitInterface(*dit, "OnOff", "set", "Off");
generator()->preinitInterface(*dit, "BranchingRatio",
"set", "0.0");
+ DecayIntegratorPtr decayer = dynamic_ptr_cast<DecayIntegratorPtr>((**dit).decayer());
+ if(decayer) {
+ generator()->preinitInterface(decayer->fullName(), "Initialize", "set","0");
+ }
}
else {
brsum += (**dit).brat();
newwidth += (**dit).brat()*oldwidth;
}
}
if( rescalebrat || (abs(brsum - 1.) > 1e-12) ) {
dit = parent->decayModes().begin();
dend = parent->decayModes().end();
double factor = oldwidth/newwidth;
brsum = 0.;
for( ; dit != dend; ++dit ) {
if( !(**dit).on() ) continue;
double newbrat = ((**dit).brat())*factor;
brsum += newbrat;
ostringstream brf;
brf << setprecision(13) << newbrat;
generator()->preinitInterface(*dit, "BranchingRatio",
"set", brf.str());
}
parent->width(newwidth);
if( newwidth > ZERO ) parent->cTau(hbarc/newwidth);
}
}
namespace {
struct DecayModeOrdering {
bool operator()(tcDMPtr m1, tcDMPtr m2) {
if(m1->brat()!=m2->brat()) {
return m1->brat()>m2->brat();
}
else {
if(m1->products().size()==m2->products().size()) {
ParticleMSet::const_iterator it1=m1->products().begin();
ParticleMSet::const_iterator it2=m2->products().begin();
do {
if((**it1).id()!=(**it2).id()) {
return (**it1).id()>(**it2).id();
}
++it1;
++it2;
}
while(it1!=m1->products().end()&&
it2!=m2->products().end());
assert(false);
}
else
return m1->products().size()<m2->products().size();
}
+ return false;
}
};
}
void ModelGenerator::writeDecayModes(ostream & os, tcPDPtr parent) const {
if(decayOutput_==0) return;
set<tcDMPtr,DecayModeOrdering> modes;
for(Selector<tDMPtr>::const_iterator dit = parent->decaySelector().begin();
dit != parent->decaySelector().end(); ++dit) {
modes.insert((*dit).second);
}
if(decayOutput_==1) {
os << " Parent: " << parent->PDGName() << " Mass (GeV): "
<< parent->mass()/GeV << " Total Width (GeV): "
<< parent->width()/GeV << endl;
os << std::left << std::setw(40) << '#'
<< std::left << std::setw(20) << "Partial Width/GeV"
<< "BR\n";
for(set<tcDMPtr,DecayModeOrdering>::iterator dit=modes.begin();
dit!=modes.end();++dit)
os << std::left << std::setw(40) << (**dit).tag()
<< std::left << std::setw(20) << (**dit).brat()*parent->width()/GeV
<< (**dit).brat() << '\n';
os << "#\n#";
}
else if(decayOutput_==2) {
os << "# \t PDG \t Width\n";
os << "DECAY\t" << parent->id() << "\t" << parent->width()/GeV << "\t # " << parent->PDGName() << "\n";
for(set<tcDMPtr,DecayModeOrdering>::iterator dit=modes.begin();
dit!=modes.end();++dit) {
os << "\t" << std::left << std::setw(10)
<< (**dit).brat() << "\t" << (**dit).orderedProducts().size()
<< "\t";
for(unsigned int ix=0;ix<(**dit).orderedProducts().size();++ix)
os << std::right << std::setw(10)
<< (**dit).orderedProducts()[ix]->id() ;
for(unsigned int ix=(**dit).orderedProducts().size();ix<4;++ix)
os << "\t";
os << "# " << (**dit).tag() << "\n";
}
}
}
void ModelGenerator::createWidthGenerator(tPDPtr p) {
string wn = p->fullName() + string("-WGen");
string mn = p->fullName() + string("-MGen");
GenericMassGeneratorPtr mgen = dynamic_ptr_cast<GenericMassGeneratorPtr>
(generator()->preinitCreate("Herwig::GenericMassGenerator", mn));
BSMWidthGeneratorPtr wgen = dynamic_ptr_cast<BSMWidthGeneratorPtr>
(generator()->preinitCreate("Herwig::BSMWidthGenerator", wn));
//set the particle interface
generator()->preinitInterface(mgen, "Particle", "set", p->fullName());
generator()->preinitInterface(wgen, "Particle", "set", p->fullName());
//set the generator interfaces in the ParticleData object
generator()->preinitInterface(p, "Mass_generator","set", mn);
generator()->preinitInterface(p, "Width_generator","set", wn);
//allow the branching fraction of this particle type to vary
p->variableRatio(true);
if( p->CC() ) p->CC()->variableRatio(true);
//initialize the generators
generator()->preinitInterface(mgen, "Initialize", "set", "Yes");
generator()->preinitInterface(wgen, "Initialize", "set", "Yes");
string norm = BRnorm_ ? "Yes" : "No";
generator()->preinitInterface(wgen, "BRNormalize", "set", norm);
ostringstream os;
os << Npoints_;
generator()->preinitInterface(wgen, "InterpolationPoints", "set",
os.str());
os.str("");
os << Iorder_;
generator()->preinitInterface(wgen, "InterpolationOrder", "set",
os.str());
os.str("");
os << BWshape_;
generator()->preinitInterface(mgen, "BreitWignerShape", "set",
os.str());
}
diff --git a/Models/General/ThreeBodyDecayConstructor.cc b/Models/General/ThreeBodyDecayConstructor.cc
--- a/Models/General/ThreeBodyDecayConstructor.cc
+++ b/Models/General/ThreeBodyDecayConstructor.cc
@@ -1,809 +1,849 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the ThreeBodyDecayConstructor class.
//
#include "ThreeBodyDecayConstructor.h"
#include "ThePEG/Utilities/Debug.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/RefVector.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "Herwig++/Models/StandardModel/StandardModel.h"
#include "Herwig++/Decay/General/GeneralThreeBodyDecayer.h"
#include "Herwig++/Decay/DecayPhaseSpaceMode.h"
#include "Herwig++/PDT/ThreeBodyAllOnCalculator.h"
#include "ThePEG/PDT/StandardMatchers.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Utilities/Throw.h"
#include "DecayConstructor.h"
#include "WeakCurrentDecayConstructor.h"
using namespace Herwig;
IBPtr ThreeBodyDecayConstructor::clone() const {
return new_ptr(*this);
}
IBPtr ThreeBodyDecayConstructor::fullclone() const {
return new_ptr(*this);
}
void ThreeBodyDecayConstructor::persistentOutput(PersistentOStream & os) const {
os << _removeOnShell << _interopt << _widthopt << _minReleaseFraction
<< _includeTopOnShell << _maxBoson << _maxList
- << excludedVector_ << excludedSet_;
+ << excludedVector_ << excludedSet_ << intOpt_ << relErr_;
}
void ThreeBodyDecayConstructor::persistentInput(PersistentIStream & is, int) {
is >> _removeOnShell >> _interopt >> _widthopt >> _minReleaseFraction
>> _includeTopOnShell >> _maxBoson >> _maxList
- >> excludedVector_ >> excludedSet_;
+ >> excludedVector_ >> excludedSet_ >> intOpt_ >> relErr_;
}
ClassDescription<ThreeBodyDecayConstructor>
ThreeBodyDecayConstructor::initThreeBodyDecayConstructor;
// Definition of the static class description member.
void ThreeBodyDecayConstructor::Init() {
static ClassDocumentation<ThreeBodyDecayConstructor> documentation
("The ThreeBodyDecayConstructor class constructs the three body decay modes");
static Switch<ThreeBodyDecayConstructor,unsigned int> interfaceRemoveOnShell
("RemoveOnShell",
"Remove on-shell diagrams as should be treated as a sequence of 1->2 decays",
&ThreeBodyDecayConstructor::_removeOnShell, 1, false, false);
static SwitchOption interfaceRemoveOnShellYes
(interfaceRemoveOnShell,
"Yes",
"Remove the diagrams if neither the production of decay or the intermediate"
" can happen",
1);
static SwitchOption interfaceRemoveOnShellNo
(interfaceRemoveOnShell,
"No",
"Never remove the intermediate",
0);
static SwitchOption interfaceRemoveOnShellProduction
(interfaceRemoveOnShell,
"Production",
"Remove the diagram if the on-shell production of the intermediate is allowed",
2);
static Switch<ThreeBodyDecayConstructor,bool> interfaceIncludeOnShellTop
("IncludeOnShellTop",
"Include the on-shell diagrams involving t -> bW",
&ThreeBodyDecayConstructor::_includeTopOnShell, false, false, false);
static SwitchOption interfaceIncludeOnShellTopYes
(interfaceIncludeOnShellTop,
"Yes",
"Inlude them",
true);
static SwitchOption interfaceIncludeOnShellTopNo
(interfaceIncludeOnShellTop,
"No",
"Don't include them",
true);
static Switch<ThreeBodyDecayConstructor,unsigned int> interfaceWidthOption
("WidthOption",
"Option for the treatment of the widths of the intermediates",
&ThreeBodyDecayConstructor::_widthopt, 1, false, false);
static SwitchOption interfaceWidthOptionFixed
(interfaceWidthOption,
"Fixed",
"Use fixed widths",
1);
static SwitchOption interfaceWidthOptionRunning
(interfaceWidthOption,
"Running",
"Use running widths",
2);
static SwitchOption interfaceWidthOptionZero
(interfaceWidthOption,
"Zero",
"Set the widths to zero",
3);
static Switch<ThreeBodyDecayConstructor,unsigned int> interfaceIntermediateOption
("IntermediateOption",
"Option for the inclusion of intermediates in the event",
&ThreeBodyDecayConstructor::_interopt, 0, false, false);
static SwitchOption interfaceIntermediateOptionAlways
(interfaceIntermediateOption,
"Always",
"Always include the intermediates",
1);
static SwitchOption interfaceIntermediateOptionNever
(interfaceIntermediateOption,
"Never",
"Never include the intermediates",
2);
static SwitchOption interfaceIntermediateOptionOnlyIfOnShell
(interfaceIntermediateOption,
"OnlyIfOnShell",
"Only if there are on-shell diagrams",
0);
static Parameter<ThreeBodyDecayConstructor,double> interfaceMinReleaseFraction
("MinReleaseFraction",
"The minimum energy release for a three-body decay, as a "
"fraction of the parent mass.",
&ThreeBodyDecayConstructor::_minReleaseFraction, 1e-3, 0.0, 1.0,
false, false, Interface::limited);
static Switch<ThreeBodyDecayConstructor,unsigned int> interfaceMaximumGaugeBosons
("MaximumGaugeBosons",
"Maximum number of electroweak gauge bosons"
" to be produced as decay products",
&ThreeBodyDecayConstructor::_maxBoson, 1, false, false);
static SwitchOption interfaceMaximumGaugeBosonsNone
(interfaceMaximumGaugeBosons,
"None",
"Produce no W/Zs",
0);
static SwitchOption interfaceMaximumGaugeBosonsSingle
(interfaceMaximumGaugeBosons,
"Single",
"Produce at most one W/Zs",
1);
static SwitchOption interfaceMaximumGaugeBosonsDouble
(interfaceMaximumGaugeBosons,
"Double",
"Produce at most two W/Zs",
2);
static SwitchOption interfaceMaximumGaugeBosonsTriple
(interfaceMaximumGaugeBosons,
"Triple",
"Produce at most three W/Zs",
3);
static Switch<ThreeBodyDecayConstructor,unsigned int> interfaceMaximumNewParticles
("MaximumNewParticles",
"Maximum number of particles from the list of "
"decaying particles to be allowed as decay products",
&ThreeBodyDecayConstructor::_maxList, 1, false, false);
static SwitchOption interfaceMaximumNewParticlesNone
(interfaceMaximumNewParticles,
"None",
"No particles from the list",
0);
static SwitchOption interfaceMaximumNewParticlesSingle
(interfaceMaximumNewParticles,
"Single",
"A single particle from the list",
1);
static SwitchOption interfaceMaximumNewParticlesDouble
(interfaceMaximumNewParticles,
"Double",
"Two particles from the list",
2);
static SwitchOption interfaceMaximumNewParticlesTriple
(interfaceMaximumNewParticles,
"Triple",
"Three particles from the list",
3);
static RefVector<ThreeBodyDecayConstructor,VertexBase> interfaceExcludedVertices
("ExcludedVertices",
"Vertices which are not included in the three-body decayers",
&ThreeBodyDecayConstructor::excludedVector_, -1, false, false, true, true, false);
+
+ static Switch<ThreeBodyDecayConstructor,unsigned int> interfaceIntegrationOption
+ ("IntegrationOption",
+ "Option for the integration of the partial width",
+ &ThreeBodyDecayConstructor::intOpt_, 1, false, false);
+ static SwitchOption interfaceIntegrationOptionAllPoles
+ (interfaceIntegrationOption,
+ "AllPoles",
+ "Include all potential poles",
+ 0);
+ static SwitchOption interfaceIntegrationOptionShallowestPole
+ (interfaceIntegrationOption,
+ "ShallowestPole",
+ "Onlt include the shallowest pole",
+ 1);
+
+ static Parameter<ThreeBodyDecayConstructor,double> interfaceRelativeError
+ ("RelativeError",
+ "The relative error for the GQ integration",
+ &ThreeBodyDecayConstructor::relErr_, 1e-2, 1e-10, 1.,
+ false, false, Interface::limited);
+
}
void ThreeBodyDecayConstructor::DecayList(const set<PDPtr> & particles) {
if( particles.empty() ) return;
// special for weak decays
for(unsigned int ix=0;ix<decayConstructor()->decayConstructors().size();++ix) {
Ptr<Herwig::WeakCurrentDecayConstructor>::pointer
weak = dynamic_ptr_cast<Ptr<Herwig::WeakCurrentDecayConstructor>::pointer >
(decayConstructor()->decayConstructors()[ix]);
if(!weak) continue;
weakMassCut_ = max(weakMassCut_,weak->massCut());
}
// cast the StandardModel to the Hw++ one to get the vertices
tHwSMPtr model = dynamic_ptr_cast<tHwSMPtr>(generator()->standardModel());
unsigned int nv(model->numberOfVertices());
// loop over the particles and create the decayers
for(set<PDPtr>::const_iterator ip=particles.begin();
ip!=particles.end();++ip) {
tPDPtr parent = *ip;
// create the prototype 1->2 decays which will be turned into
// 1 -> 3 decays
vector<TwoBodyPrototype> prototypes;
for(unsigned int iv = 0; iv < nv; ++iv) {
VertexBasePtr vertex = model->vertex(iv);
if(excludedSet_.find(vertex)!=excludedSet_.end()) continue;
//skip an effective vertex
if( vertex->orderInGs() + vertex->orderInGem() == 3 )
continue;
for(unsigned int il = 0; il < 3; ++il) {
vector<TwoBodyPrototype> temp =
createPrototypes(parent, vertex, il);
if(!temp.empty()) prototypes.insert(prototypes.end(),
temp.begin(),temp.end());
}
}
// now expand the prototypes by decaying the outgoing particles
// in the prototypes
vector<TBDiagram> diagrams;
for(unsigned int ix=0;ix<prototypes.size();++ix) {
for(unsigned int iv = 0; iv < nv; ++iv) {
VertexBasePtr vertex = model->vertex(iv);
if(excludedSet_.find(vertex)!=excludedSet_.end()) continue;
//skip an effective vertex
if( vertex->orderInGs() + vertex->orderInGem() == 3 )
continue;
for(unsigned int il = 0; il < 3; ++il) {
vector<TBDiagram> temp = expandPrototype(prototypes[ix],
vertex, il);
if(!temp.empty()) diagrams.insert(diagrams.end(),temp.begin(),
temp.end());
}
}
}
// now we have the potential diagrams we need to do some sorting
// into decay modes
vector< vector<TBDiagram> > modes;
Energy min = parent->mass();
bool possibleOnShell(false);
for(vector<TBDiagram>::const_iterator dit = diagrams.begin();
dit != diagrams.end(); ++dit) {
tPDPtr outgoing[3]={getParticleData(dit->outgoing),
getParticleData(dit->outgoingPair.first),
getParticleData(dit->outgoingPair.second)};
Energy mout[3] =
{outgoing[0]->constituentMass(),outgoing[1]->constituentMass(),
outgoing[2]->constituentMass()};
// remove processes which aren't kinematically allowed within
if( min - mout[0] - mout[1] - mout[2] <= _minReleaseFraction * min )
continue;
// remove QED and QCD radiation diagrams
// radiation from intermediate
long interID = dit->intermediate->id();
if((dit->outgoingPair.first ==interID &&
(dit->outgoingPair.second==ParticleID::g ||
dit->outgoingPair.second==ParticleID::gamma ||
dit->outgoingPair.second==ParticleID::Z0 ))||
(dit->outgoingPair.second==interID &&
(dit->outgoingPair.first ==ParticleID::g ||
dit->outgoingPair.first ==ParticleID::gamma ||
dit->outgoingPair.first ==ParticleID::Z0 ))) continue;
// radiation from the parent
if((dit->outgoing ==dit->incoming&&
(interID==ParticleID::g ||
interID==ParticleID::gamma ||
interID==ParticleID::Z0 ))||
(interID==dit->incoming &&
(dit->outgoing ==ParticleID::g ||
dit->outgoing ==ParticleID::gamma ||
dit->outgoing ==ParticleID::Z0 ))) continue;
// remove weak decays of quarks other than top
if(StandardQCDPartonMatcher::Check(interID) &&
((StandardQCDPartonMatcher::Check(dit->outgoingPair.first)&&
abs(dit->outgoingPair.second)==ParticleID::Wplus)||
(StandardQCDPartonMatcher::Check(dit->outgoingPair.second)&&
abs(dit->outgoingPair.first)==ParticleID::Wplus))) continue;
// remove weak lepton decays
if((abs(interID)>=11&&abs(interID)<=16) && (
((abs(dit->outgoingPair.first)>=11&&abs(dit->outgoingPair.first)<=16)&&
abs(dit->outgoingPair.second)==ParticleID::Wplus)||
((abs(dit->outgoingPair.second)>=11&&abs(dit->outgoingPair.second)<=16)&&
abs(dit->outgoingPair.first)==ParticleID::Wplus)) ) continue;
// remove processes where one of the outgoing particles has the
//same id as the incoming particles
if(abs(parent->id()) == abs(dit->outgoing ) ||
abs(parent->id()) == abs(dit->outgoingPair.first ) ||
abs(parent->id()) == abs(dit->outgoingPair.second) ) continue;
// check the number of new particles and gauge bosons
unsigned int nbos(0),nnew(0);
for(unsigned int ix=0;ix<3;++ix) {
if(outgoing[ix]->id()==ParticleID::gamma ||
outgoing[ix]->id()==ParticleID::Z0 ||
abs(outgoing[ix]->id())==ParticleID::Wplus) ++nbos;
if(particles.find(outgoing[ix])!=particles.end()) ++nnew;
if(outgoing[ix]->CC() &&
particles.find(outgoing[ix]->CC())!=particles.end()) ++nnew;
}
if(nbos>_maxBoson || nnew>_maxList) continue;
// if needed remove intermediate diagrams where intermediate can be
// on shell
Energy mint = dit->intermediate->mass();
if( min> mout[0] + mint ) {
if(_removeOnShell==2) continue;
if(mint > mout[1] + mout[2] ) {
// special for top
if(abs(dit->incoming)==ParticleID::t&&
abs(interID)==ParticleID::Wplus) {
if(!_includeTopOnShell) continue;
}
// general
else if(_removeOnShell==1) {
continue;
}
if(dit->intermediate->width()==0.*GeV) {
Throw<InitException>()
<< "Trying to include on-shell diagram for "
<< getParticleData(dit->incoming)->PDGName() << " -> "
<< outgoing[0]->PDGName() << " "
<< outgoing[1]->PDGName() << " " << outgoing[2]->PDGName()
<< " with intermediate " << dit->intermediate->PDGName()
<< " with zero width.\n"
<< "You should make sure that the width for the intermediate is either"
<< " read from an SLHA file or the intermediate is included in the "
<< "DecayParticles list of the ModelGenerator.\n"
<< Exception::runerror;
}
possibleOnShell = true;
}
}
// check if should be added to an existing decaymode
bool added = false;
for(unsigned int iy = 0; iy < modes.size(); ++iy) {
if(modes[iy][0].sameDecay(*dit)) {
added = true;
bool already = false;
for(unsigned int iz = 0; iz < modes[iy].size(); ++iz) {
if( modes[iy][iz] == *dit) {
already = true;
break;
}
}
if(!already) modes[iy].push_back(*dit);
break;
}
}
// otherwise create a new decay mode
if(!added) modes.push_back(vector<TBDiagram>(1,*dit));
}
// print out info on the potential modes
if( Debug::level > 1 ) {
generator()->log() << "There are " << modes.size() << " modes for "
<< (**ip).PDGName() << "\n";
for(unsigned int ix=0;ix<modes.size();++ix) {
generator()->log() << "Mode: " << ix << "\n";
generator()->log()
<< "incoming = "
<< getParticleData(modes[ix][0].incoming)->PDGName() << "\n";
generator()->log()
<< "outgoing = "
<< getParticleData(modes[ix][0].outgoing)->PDGName() << " "
<< getParticleData(modes[ix][0].outgoingPair.first )->PDGName() << " "
<< getParticleData(modes[ix][0].outgoingPair.second)->PDGName() << "\n";
generator()->log()
<< "There are " << modes[ix].size() << " diagrams\n";
for(unsigned int iy=0;iy<modes[ix].size();++iy) {
generator()->log() << "Diagram: " << iy << "\n";
generator()->log()
<< "incoming = " << modes[ix][iy].incoming << "\n";
generator()->log()
<< "outgoing = " << modes[ix][iy].outgoing << " "
<< modes[ix][iy].outgoingPair.first << " "
<< modes[ix][iy].outgoingPair.second << "\n";
generator()->log()
<< "intermediate = " << modes[ix][iy].intermediate->PDGName()
<< "\t" << modes[ix][iy].intermediate->id() << "\n";
generator()->log()
<< "vertices = " << modes[ix][iy].vertices.first ->fullName() << "\n"
<< " " << modes[ix][iy].vertices.second->fullName() << "\n";
}
}
}
// now we need to create the decayers for the mode
bool inter(false);
if( _interopt == 1 || (_interopt == 0 && possibleOnShell) )
inter = true;
for( vector< vector<TBDiagram> >::iterator mit = modes.begin();
mit != modes.end(); ++mit ) {
createDecayMode(*mit, inter);
}
}// end of particle loop
}
vector<TwoBodyPrototype> ThreeBodyDecayConstructor::
createPrototypes(tPDPtr inpart, VertexBasePtr vertex, unsigned int list) {
int id = inpart->id();
if( id < 0 || !vertex->isIncoming(inpart) || vertex->getNpoint() != 3 )
return vector<TwoBodyPrototype>();
tPDVector decaylist = vertex->search(list, inpart);
vector<TwoBodyPrototype> decays;
tPDVector::size_type nd = decaylist.size();
for( tPDVector::size_type i = 0; i < nd; i += 3 ) {
tPDPtr pa(decaylist[i]), pb(decaylist[i + 1]), pc(decaylist[i + 2]);
if( pb->id() == id ) swap(pa, pb);
if( pc->id() == id ) swap(pa, pc);
// vertices are defined with all particles incoming
if( pb->CC() ) pb = pb->CC();
if( pc->CC() ) pc = pc->CC();
decays.push_back(TwoBodyPrototype(inpart,make_pair(pb,pc),vertex));
}
return decays;
}
vector<TBDiagram> ThreeBodyDecayConstructor::
expandPrototype(TwoBodyPrototype proto, VertexBasePtr vertex,unsigned int list) {
vector<TBDiagram> decays;
if( vertex->getNpoint() != 3 ) return decays;
// loop over the outgoing particles
for(unsigned int ix=0;ix<2;++ix) {
tPDPtr dec = proto.outgoing.first ;
tPDPtr other = proto.outgoing.second;
if(ix==1) swap(dec,other);
int id = dec->id();
// remove weak processes simulated using the current
if(weakMassCut_>ZERO && abs(dec->id())==ParticleID::Wplus &&
proto.incoming->mass()-other->mass()<weakMassCut_) continue;
// check allowed incoming in vertex
if( !vertex->isIncoming(dec) ) continue;
tPDVector decaylist = vertex->search(list, dec);
tPDVector::size_type nd = decaylist.size();
for( tPDVector::size_type i = 0; i < nd; i += 3 ) {
tPDPtr pa(decaylist[i]), pb(decaylist[i + 1]), pc(decaylist[i + 2]);
if( pb->id() == id ) swap(pa, pb);
if( pc->id() == id ) swap(pa, pc);
//vertices are defined with all particles incoming
if( pb->CC() ) pb = pb->CC();
if( pc->CC() ) pc = pc->CC();
// create the three body diagram
TBDiagram diag(proto.incoming->id(), other->id(),
make_pair(pb->id(),pc->id()));
diag.intermediate = pa;
diag.vertices = make_pair(proto.vertex,vertex);
diag.colourFlow = vector<CFPair>(1,make_pair(1,1.));
diag.largeNcColourFlow = vector<CFPair>(1,make_pair(1,1.));
decays.push_back(diag);
}
}
return decays;
}
GeneralThreeBodyDecayerPtr ThreeBodyDecayConstructor::
createDecayer(vector<TBDiagram> & diagrams, bool inter) const {
if(diagrams.empty()) return GeneralThreeBodyDecayerPtr();
// extract the external particles for the process
PDPtr incoming = getParticleData(diagrams[0].incoming);
// outgoing particles
OrderedParticles outgoing;
outgoing.insert(getParticleData(diagrams[0].outgoing ));
outgoing.insert(getParticleData(diagrams[0].outgoingPair.first ));
outgoing.insert(getParticleData(diagrams[0].outgoingPair.second));
// sort out ordering and labeling of diagrams
vector<PDPtr> outVector(outgoing.begin(),outgoing.end());
for(unsigned int ix=0;ix<diagrams.size();++ix) {
unsigned int iy=0;
for(;iy<3;++iy)
if(diagrams[ix].outgoing == outVector[iy]->id()) break;
if(diagrams[ix].channelType == TBDiagram::UNDEFINED) {
diagrams[ix].channelType = TBDiagram::Channel(iy);
if( ( iy == 0 && outVector[1]->id() != diagrams[ix].outgoingPair.first)||
( iy == 1 && outVector[0]->id() != diagrams[ix].outgoingPair.first)||
( iy == 2 && outVector[0]->id() != diagrams[ix].outgoingPair.first) )
swap(diagrams[ix].outgoingPair.first, diagrams[ix].outgoingPair.second);
}
}
// create the object
string objectname ("/Herwig/Decays/");
string classname = DecayerClassName(incoming, outgoing, objectname);
if(classname=="") return GeneralThreeBodyDecayerPtr();
GeneralThreeBodyDecayerPtr decayer =
dynamic_ptr_cast<GeneralThreeBodyDecayerPtr>
(generator()->preinitCreate(classname, objectname));
unsigned int ncf(0);
pair<vector<DVector>, vector<DVector> >
cfactors = getColourFactors(incoming,outgoing,diagrams,ncf);
decayer->setDecayInfo(incoming,outVector,
diagrams,cfactors.first,cfactors.second,ncf);
// set decayer options from base class
setDecayerInterfaces(objectname);
+ // options for partial width integration
+ ostringstream value;
+ value << intOpt_;
+ generator()->preinitInterface(objectname, "PartialWidthIntegration", "set",
+ value.str());
+ value.str("");
+ value << relErr_;
+ generator()->preinitInterface(objectname, "RelativeError", "set",
+ value.str());
// set the width option
- ostringstream value;
+ value.str("");
value << _widthopt;
generator()->preinitInterface(objectname, "WidthOption", "set", value.str());
// set the intermediates option
- ostringstream value2;
- value2 << inter;
+ value.str("");
+ value << inter;
generator()->preinitInterface(objectname, "GenerateIntermediates", "set",
- value2.str());
+ value.str());
// initialize the decayer
decayer->init();
// return the decayer
return decayer;
}
string ThreeBodyDecayConstructor::
DecayerClassName(tcPDPtr incoming, const OrderedParticles & outgoing,
string & objname) const {
string classname("Herwig::");
// spins of the outgoing particles
unsigned int ns(0),nf(0),nv(0);
objname += incoming->PDGName() + "2";
for(OrderedParticles::const_iterator it=outgoing.begin();
it!=outgoing.end();++it) {
if ((**it).iSpin()==PDT::Spin0 ) ++ns;
else if((**it).iSpin()==PDT::Spin1Half) ++nf;
else if((**it).iSpin()==PDT::Spin1 ) ++nv;
objname += (**it).PDGName();
}
objname += "Decayer";
if(incoming->iSpin()==PDT::Spin0) {
if(ns==1&&nf==2) classname += "StoSFFDecayer";
else if(nf==2&&nv==1) classname += "StoFFVDecayer";
else classname = "";
}
else if(incoming->iSpin()==PDT::Spin1Half) {
if(nf==3) classname += "FtoFFFDecayer";
else if(nf==1&&nv==2) classname += "FtoFVVDecayer";
else classname = "";
}
else if(incoming->iSpin()==PDT::Spin1) {
if(nf==2&&nv==1) classname += "VtoFFVDecayer";
else classname = "";
}
else {
classname="";
}
return classname;
}
void ThreeBodyDecayConstructor::
createDecayMode(vector<TBDiagram> & diagrams, bool inter) {
// incoming particle
tPDPtr inpart = getParticleData(diagrams[0].incoming);
// outgoing particles
OrderedParticles outgoing;
outgoing.insert(getParticleData(diagrams[0].outgoing));
outgoing.insert(getParticleData(diagrams[0].outgoingPair.first ));
outgoing.insert(getParticleData(diagrams[0].outgoingPair.second));
- // incoming particle is now unstable
- inpart->stable(false);
// construct the tag for the decay mode
string tag = inpart->name() + "->";
unsigned int iprod=0;
for(OrderedParticles::const_iterator it = outgoing.begin();
it != outgoing.end(); ++it) {
++iprod;
tag += (**it).name();
if(iprod != 3) tag += ",";
}
tag += ";";
tDMPtr dm = generator()->findDecayMode(tag);
if( decayConstructor()->disableDecayMode(tag) ) {
// If mode alread exists, ie has been read from file,
// disable it
if( dm ) {
generator()->preinitInterface(dm, "BranchingRatio", "set", "0.0");
generator()->preinitInterface(dm, "OnOff", "set", "Off");
}
return;
}
// create mode if needed
if( createDecayModes() && (!dm || inpart->id() == ParticleID::h0) ) {
// create the decayer
GeneralThreeBodyDecayerPtr decayer = createDecayer(diagrams,inter);
if(!decayer) {
if(Debug::level > 1 ) generator()->log() << "Can't create the decayer for "
<< tag << " so mode not created\n";
return;
}
tDMPtr ndm = generator()->preinitCreateDecayMode(tag);
if(ndm) {
generator()->preinitInterface(ndm, "Decayer", "set",
decayer->fullName());
generator()->preinitInterface(ndm, "OnOff", "set", "On");
OrderedParticles::const_iterator pit=outgoing.begin();
tPDPtr pa = *pit; ++pit;
tPDPtr pb = *pit; ++pit;
tPDPtr pc = *pit;
Energy width =
decayer->partialWidth(make_pair(inpart,inpart->mass()),
make_pair(pa,pa->mass()) ,
make_pair(pb,pb->mass()) ,
make_pair(pc,pc->mass()));
setBranchingRatio(ndm, width);
+ if(ndm->brat()<decayConstructor()->minimumBR()) {
+ generator()->preinitInterface(decayer->fullName(),
+ "Initialize", "set","0");
+ }
+ // incoming particle is now unstable
+ inpart->stable(false);
}
else
throw NBodyDecayConstructorError()
<< "ThreeBodyDecayConstructor::createDecayMode - Needed to create "
<< "new decaymode but one could not be created for the tag "
<< tag << Exception::warning;
}
else if( dm ) {
+ if(dm->brat()<decayConstructor()->minimumBR()) {
+ return;
+ }
if((dm->decayer()->fullName()).find("Mambo") != string::npos) {
// create the decayer
GeneralThreeBodyDecayerPtr decayer = createDecayer(diagrams,inter);
if(!decayer) {
if(Debug::level > 1 ) generator()->log() << "Can't create the decayer for "
<< tag << " so mode not created\n";
return;
}
generator()->preinitInterface(dm, "Decayer", "set",
decayer->fullName());
+ // incoming particle is now unstable
+ inpart->stable(false);
}
}
//update CC mode if it exists
if( inpart->CC() )
inpart->CC()->synchronize();
}
pair<vector<DVector>,vector<DVector> >
ThreeBodyDecayConstructor::
getColourFactors(tcPDPtr incoming, const OrderedParticles & outgoing,
const vector<TBDiagram> & diagrams,
unsigned int & ncf) const {
string name = incoming->PDGName() + "->";
vector<int> sng,trip,atrip,oct;
unsigned int iloc(0);
for(OrderedParticles::const_iterator it = outgoing.begin();
it != outgoing.end();++it) {
name += (**it).PDGName() + " ";
if ((**it).iColour() == PDT::Colour0 ) sng.push_back(iloc) ;
else if((**it).iColour() == PDT::Colour3 ) trip.push_back(iloc) ;
else if((**it).iColour() == PDT::Colour3bar ) atrip.push_back(iloc);
else if((**it).iColour() == PDT::Colour8 ) oct.push_back(iloc) ;
++iloc;
}
pair<vector<DVector>,vector<DVector> > output;
// colour neutral decaying particle
if ( incoming->iColour() == PDT::Colour0) {
// options are all neutral or triplet/antitriplet+ neutral
if(sng.size()==3) {
ncf = 1;
output.first = vector<DVector>(1,DVector(1,1.));
output.second = vector<DVector>(1,DVector(1,1.));
}
else if(sng.size()==1&&trip.size()==1&&atrip.size()==1) {
ncf = 1;
output.first = vector<DVector>(1,DVector(1,3.));
output.second = vector<DVector>(1,DVector(1,3.));
}
else if(trip.size()==1&&atrip.size()==1&&oct.size()==1) {
ncf = 1;
output.first = vector<DVector>(1,DVector(1,4.));
output.second = vector<DVector>(1,DVector(1,4.));
}
else throw Exception() << "Unknown colour flow structure for "
<< name << Exception::runerror;
}
// colour triplet decaying particle
else if( incoming->iColour() == PDT::Colour3) {
if(sng.size()==2&&trip.size()==1) {
ncf = 1;
output.first = vector<DVector>(1,DVector(1,1.));
output.second = vector<DVector>(1,DVector(1,1.));
}
else if(trip.size()==2&&atrip.size()==1) {
ncf = 2;
output.first.resize(2,DVector(2,0.));
output.first[0][0] = 3.; output.first[0][1] = 1.;
output.first[1][0] = 1.; output.first[1][1] = 3.;
output.second.resize(2,DVector(2,0.));
output.second[0][0] = 3.; output.second[1][1] = 3.;
// sort out the contribution of the different diagrams to the colour
// flows
for(unsigned int ix=0;ix<diagrams.size();++ix) {
// colour singlet intermediate
if(diagrams[ix].intermediate->iColour()==PDT::Colour0) {
if(diagrams[ix].channelType==trip[0]) {
diagrams[ix]. colourFlow = vector<CFPair>(1,make_pair(1,1.));
diagrams[ix].largeNcColourFlow = vector<CFPair>(1,make_pair(1,1.));
}
else {
diagrams[ix].colourFlow = vector<CFPair>(1,make_pair(2,1.));
diagrams[ix].largeNcColourFlow = vector<CFPair>(1,make_pair(2,1.));
}
}
// colour octet intermediate
else if(diagrams[ix].intermediate->iColour()==PDT::Colour8) {
if(diagrams[ix].channelType==trip[0]) {
vector<CFPair> flow(1,make_pair(2, 0.5 ));
diagrams[ix].largeNcColourFlow = flow;
flow.push_back( make_pair(1,-1./6.));
diagrams[ix].colourFlow=flow;
}
else {
vector<CFPair> flow(1,make_pair(1, 0.5 ));
diagrams[ix].largeNcColourFlow = flow;
flow.push_back( make_pair(2,-1./6.));
diagrams[ix].colourFlow=flow;
}
}
else throw Exception() << "Unknown colour for the intermediate in "
<< "triplet -> triplet triplet antitriplet in "
<< "ThreeBodyDecayConstructor::getColourFactors()"
<< Exception::runerror;
}
}
else if(trip.size()==1&&oct.size()==1&&sng.size()==1) {
ncf = 1;
output.first = vector<DVector>(1,DVector(1,4./3.));
output.second = vector<DVector>(1,DVector(1,4./3.));
}
else throw Exception() << "Unknown colour flow structure for "
<< name << Exception::runerror;
}
// colour antitriplet decaying particle
else if( incoming->iColour() == PDT::Colour3bar) {
if(sng.size()==2&&atrip.size()==1) {
ncf = 1;
output.first = vector<DVector>(1,DVector(1,1.));
output.second = vector<DVector>(1,DVector(1,1.));
}
else if(atrip.size()==2&&trip.size()==1) {
ncf = 2;
output.first.resize(2,DVector(2,0.));
output.first[0][0] = 3.; output.first[0][1] = 1.;
output.first[1][0] = 1.; output.first[1][1] = 3.;
output.second.resize(2,DVector(2,0.));
output.second[0][0] = 3.; output.second[1][1] = 3.;
// sort out the contribution of the different diagrams to the colour
// flows
for(unsigned int ix=0;ix<diagrams.size();++ix) {
// colour singlet intermediate
if(diagrams[ix].intermediate->iColour()==PDT::Colour0) {
if(diagrams[ix].channelType==atrip[0]) {
diagrams[ix]. colourFlow = vector<CFPair>(1,make_pair(1,1.));
diagrams[ix].largeNcColourFlow = vector<CFPair>(1,make_pair(1,1.));
}
else {
diagrams[ix].colourFlow = vector<CFPair>(1,make_pair(2,1.));
diagrams[ix].largeNcColourFlow = vector<CFPair>(1,make_pair(2,1.));
}
}
// colour octet intermediate
else if(diagrams[ix].intermediate->iColour()==PDT::Colour8) {
if(diagrams[ix].channelType==atrip[0]) {
vector<CFPair> flow(1,make_pair(2, 0.5 ));
diagrams[ix].largeNcColourFlow = flow;
flow.push_back( make_pair(1,-1./6.));
diagrams[ix].colourFlow=flow;
}
else {
vector<CFPair> flow(1,make_pair(1, 0.5 ));
diagrams[ix].largeNcColourFlow = flow;
flow.push_back( make_pair(2,-1./6.));
diagrams[ix].colourFlow=flow;
}
}
else throw Exception() << "Unknown colour for the intermediate in "
<< "antitriplet -> antitriplet antitriplet triplet in "
<< "ThreeBodyDecayConstructor::getColourFactors()"
<< Exception::runerror;
}
}
else if(atrip.size()==1&&oct.size()==1&&sng.size()==1) {
ncf = 1;
output.first = vector<DVector>(1,DVector(1,4./3.));
output.second = vector<DVector>(1,DVector(1,4./3.));
}
else throw Exception() << "Unknown colour flow structure for "
<< name << Exception::runerror;
}
else if( incoming->iColour() == PDT::Colour8) {
// triplet antitriplet
if(trip.size() == 1 && atrip.size() == 1 && sng.size() == 1) {
ncf = 1;
output.first = vector<DVector>(1,DVector(1,0.5));
output.second = vector<DVector>(1,DVector(1,0.5));
}
else throw Exception() << "Unknown colour flow structure for "
<< name << Exception::runerror;
}
return output;
}
void ThreeBodyDecayConstructor::doinit() {
NBodyDecayConstructorBase::doinit();
excludedSet_ = set<VertexBasePtr>(excludedVector_.begin(),
excludedVector_.end());
if(_removeOnShell==0)
generator()->log() << "Warning: Including diagrams with on-shell "
<< "intermediates in three-body BSM decays, this"
<< " can lead to double counting and is not"
<< " recommended unless you really know what you are doing\n"
<< "This can be switched off using\n set "
<< fullName() << ":RemoveOnShell Yes\n";
}
diff --git a/Models/General/ThreeBodyDecayConstructor.h b/Models/General/ThreeBodyDecayConstructor.h
--- a/Models/General/ThreeBodyDecayConstructor.h
+++ b/Models/General/ThreeBodyDecayConstructor.h
@@ -1,290 +1,301 @@
// -*- C++ -*-
#ifndef HERWIG_ThreeBodyDecayConstructor_H
#define HERWIG_ThreeBodyDecayConstructor_H
//
// This is the declaration of the ThreeBodyDecayConstructor class.
//
#include "NBodyDecayConstructorBase.h"
#include "ThePEG/Helicity/Vertex/VertexBase.h"
#include "TBDiagram.h"
#include "Herwig++/Decay/General/GeneralThreeBodyDecayer.fh"
namespace Herwig {
using namespace ThePEG;
using Helicity::VertexBasePtr;
/**
* A two body decay mode which is a prototype for the
* three body mode
*/
struct TwoBodyPrototype {
/**
* Constructor
*/
TwoBodyPrototype(tPDPtr in, tPDPair out, VertexBasePtr v) :
incoming(in), outgoing(out), vertex(v) {}
/**
* Incoming particle
*/
tPDPtr incoming;
/**
* Outgoing particles
*/
tPDPair outgoing;
/**
* The vertex for the interaction
*/
VertexBasePtr vertex;
};
/**
* The ThreeBodyDecayConstructor class inherits from the dummy base class
* NBodyDecayConstructorBase and implements the necessary functions in
* order to create the 3 body decaymodes for a given set of vertices
* stored in a Model class.
*
* @see \ref ThreeBodyDecayConstructorInterfaces "The interfaces"
* defined for ThreeBodyDecayConstructor.
* @see NBodyDecayConstructor
*/
class ThreeBodyDecayConstructor: public NBodyDecayConstructorBase {
public:
/**
* The default constructor.
*/
ThreeBodyDecayConstructor() :
_removeOnShell(1), _includeTopOnShell(false), _interopt(0), _widthopt(1),
- _minReleaseFraction(1e-3), _maxBoson(1), _maxList(1), weakMassCut_(-GeV) {}
+ _minReleaseFraction(1e-3), _maxBoson(1), _maxList(1), weakMassCut_(-GeV),
+ intOpt_(1), relErr_(1e-2) {}
/**
* Function used to determine allowed decaymodes, to be implemented
* in derived class.
*@param part vector of ParticleData pointers containing particles in model
*/
virtual void DecayList(const set<PDPtr> & part);
/**
* Number of outgoing lines. Required for correct ordering.
*/
virtual unsigned int numBodies() const { return 3; }
protected:
/**
* Create the two body prototypes for the decays
* @param inpart Incoming particle
* @param vert The vertex to create decays for
* @param ilist Which list to search
* @return A vector a decay modes
*/
vector<TwoBodyPrototype> createPrototypes(tPDPtr inpart, VertexBasePtr vert,
unsigned int ilist);
/**
* Expand the two body prototype to get the possible
* threebody diagrams
* @param proto The two body prototype
* @param vert The vertex to create decays for
* @param ilist Which list to search
*/
vector<TBDiagram> expandPrototype(TwoBodyPrototype proto, VertexBasePtr vert,
unsigned int ilist);
/**
* Create the decayer
* @param diagrams The diagrams for the decay
* @param inter Option for intermediates
*/
GeneralThreeBodyDecayerPtr createDecayer(vector<TBDiagram> & diagrams,
bool inter) const;
/**
* Contruct the classname and object name for the Decayer
* @param incoming The incoming particle
* @param outgoing The decay products
* @param objname a string containing the default path of the Decayer object
*/
string DecayerClassName(tcPDPtr incoming, const OrderedParticles & outgoing,
string & objname) const;
/**
* Create the DecayMode from the diagrams
* @param diagrams The diagrams
* @param inter Option for intermediates
*/
void createDecayMode(vector<TBDiagram> & diagrams, bool inter);
/**
* Get the correct colour factor matrix.
* @param incoming The incoming particle
* @param outgoing The outgoing particles
* @param diagrams The diagrams
* @param ncf Set the number of colourflows.
*/
pair<vector<DVector>,vector<DVector> >
getColourFactors(tcPDPtr incoming, const OrderedParticles & outgoing,
const vector<TBDiagram> & diagrams,
unsigned int & ncf) const;
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
virtual IBPtr fullclone() const;
//@}
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();
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<ThreeBodyDecayConstructor> initThreeBodyDecayConstructor;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
ThreeBodyDecayConstructor & operator=(const ThreeBodyDecayConstructor &);
private:
/**
* Whether or not to remove on-shell diagrams
*/
unsigned int _removeOnShell;
/**
* Include on-shell for \f$t\to b W\f$
*/
bool _includeTopOnShell;
/**
* Option for the inclusion of intermediates
*/
unsigned int _interopt;
/**
* How to treat the widths of the intermediate particles
*/
unsigned int _widthopt;
/**
* The minimum energy release for a three-body decay as a
* fraction of the parent mass
*/
double _minReleaseFraction;
/**
* Maximum number of EW gauge bosons
*/
unsigned int _maxBoson;
/**
* Maximum number of particles from the decaying particle list
*/
unsigned int _maxList;
/**
* Excluded Vertices
*/
vector<VertexBasePtr> excludedVector_;
/**
* Excluded Vertices
*/
set<VertexBasePtr> excludedSet_;
/**
* Cut off or decays via the weak current
*/
Energy weakMassCut_;
+
+ /**
+ * Option for the integration to get the partial width
+ */
+ unsigned int intOpt_;
+
+ /**
+ * Relative error for partial width integration
+ */
+ double relErr_;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of ThreeBodyDecayConstructor. */
template <>
struct BaseClassTrait<Herwig::ThreeBodyDecayConstructor,1> {
/** Typedef of the first base class of ThreeBodyDecayConstructor. */
typedef Herwig::NBodyDecayConstructorBase NthBase;
};
/** This template specialization informs ThePEG about the name of
* the ThreeBodyDecayConstructor class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::ThreeBodyDecayConstructor>
: public ClassTraitsBase<Herwig::ThreeBodyDecayConstructor> {
/** Return a platform-independent class name */
static string className() { return "Herwig::ThreeBodyDecayConstructor"; }
};
/** @endcond */
}
#endif /* HERWIG_ThreeBodyDecayConstructor_H */
diff --git a/Models/General/TwoBodyDecay.h b/Models/General/TwoBodyDecay.h
new file mode 100644
--- /dev/null
+++ b/Models/General/TwoBodyDecay.h
@@ -0,0 +1,66 @@
+// -*- C++ -*-
+//
+// TwoBodyDecay.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
+// Copyright (C) 2002-2011 The Herwig Collaboration
+//
+// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
+// Please respect the MCnet academic guidelines, see GUIDELINES for details.
+//
+#ifndef HERWIG_TwoBodyDecay_H
+#define HERWIG_TwoBodyDecay_H
+//
+// This is the declaration of the TwoBodyDecay struct.
+//
+
+namespace Herwig {
+using namespace ThePEG;
+using Helicity::tVertexBasePtr;
+
+/**
+ * Struct for the prototype of a two-body decay mode
+ */
+struct TwoBodyDecay {
+
+public:
+
+ /**
+ * Constructor
+ * @param pa Decaying particle
+ * @param pb First decay product
+ * @param pc Second decay product
+ */
+ TwoBodyDecay(tPDPtr pa, tPDPtr pb, tPDPtr pc,
+ tVertexBasePtr vertex) : parent_(pa), vertex_(vertex) {
+ ParticleOrdering order;
+ if( order(pb, pc) ) {
+ children_.first = pb;
+ children_.second = pc;
+ }
+ else {
+ children_.first = pc;
+ children_.second = pb;
+ }
+ }
+
+ /**
+ * The parent
+ */
+ tPDPtr parent_;
+
+ /**
+ * The children
+ */
+ tPDPair children_;
+
+ /**
+ * Vertex
+ */
+ tVertexBasePtr vertex_;
+
+private:
+
+ TwoBodyDecay();
+};
+}
+#endif /* HERWIG_TwoBodyDecay_H */
+
diff --git a/Models/General/TwoBodyDecayConstructor.cc b/Models/General/TwoBodyDecayConstructor.cc
--- a/Models/General/TwoBodyDecayConstructor.cc
+++ b/Models/General/TwoBodyDecayConstructor.cc
@@ -1,247 +1,280 @@
// -*- C++ -*-
//
// TwoBodyDecayConstructor.cc is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the TwoBodyDecayConstructor class.
//
#include "TwoBodyDecayConstructor.h"
#include "ThePEG/Interface/ClassDocumentation.h"
-#include "ThePEG/Persistency/PersistentOStream.h"
-#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "Herwig++/Decay/General/GeneralTwoBodyDecayer.h"
#include "Herwig++/Models/StandardModel/StandardModel.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "DecayConstructor.h"
+#include "ThePEG/Utilities/Throw.h"
#include "ThePEG/Helicity/Vertex/AbstractFFVVertex.fh"
#include "ThePEG/Helicity/Vertex/AbstractFFSVertex.fh"
#include "ThePEG/Helicity/Vertex/AbstractVVSVertex.fh"
#include "ThePEG/Helicity/Vertex/AbstractVSSVertex.fh"
#include "ThePEG/Helicity/Vertex/AbstractVVTVertex.fh"
#include "ThePEG/Helicity/Vertex/AbstractFFTVertex.fh"
#include "ThePEG/Helicity/Vertex/AbstractSSTVertex.fh"
#include "ThePEG/Helicity/Vertex/AbstractSSSVertex.fh"
#include "ThePEG/Helicity/Vertex/AbstractVVVVertex.fh"
#include "ThePEG/Helicity/Vertex/AbstractRFSVertex.fh"
#include "ThePEG/Helicity/Vertex/AbstractRFVVertex.fh"
using namespace Herwig;
using ThePEG::Helicity::VertexBasePtr;
IBPtr TwoBodyDecayConstructor::clone() const {
return new_ptr(*this);
}
IBPtr TwoBodyDecayConstructor::fullclone() const {
return new_ptr(*this);
}
-void TwoBodyDecayConstructor::persistentOutput(PersistentOStream & os) const {
- os << _theExistingDecayers;
-}
-
-void TwoBodyDecayConstructor::persistentInput(PersistentIStream & is, int) {
- is >>_theExistingDecayers;
-}
-
-ClassDescription<TwoBodyDecayConstructor>
+NoPIOClassDescription<TwoBodyDecayConstructor>
TwoBodyDecayConstructor::initTwoBodyDecayConstructor;
// Definition of the static class description member.
void TwoBodyDecayConstructor::Init() {
static ClassDocumentation<TwoBodyDecayConstructor> documentation
("The TwoBodyDecayConstructor implements to creation of 2 body decaymodes "
"and decayers that do not already exist for the given set of vertices.");
}
void TwoBodyDecayConstructor::DecayList(const set<PDPtr> & particles) {
if( particles.empty() ) return;
tHwSMPtr model = dynamic_ptr_cast<tHwSMPtr>(generator()->standardModel());
unsigned int nv(model->numberOfVertices());
-
- _theExistingDecayers.resize(nv,
- vector<GeneralTwoBodyDecayerPtr>(3,GeneralTwoBodyDecayerPtr()));
for(set<PDPtr>::const_iterator ip=particles.begin();
ip!=particles.end();++ip) {
tPDPtr parent = *ip;
for(unsigned int iv = 0; iv < nv; ++iv) {
for(unsigned int il = 0; il < 3; ++il) {
vector<TwoBodyDecay> decays =
- createModes(parent, model->vertex(iv), il, iv);
- if( !decays.empty() )
- createDecayMode(decays, _theExistingDecayers[iv][il]);
+ createModes(parent, model->vertex(iv), il);
+ if( !decays.empty() ) createDecayMode(decays);
}
}
}
}
vector<TwoBodyDecay> TwoBodyDecayConstructor::
createModes(tPDPtr inpart, VertexBasePtr vertex,
- unsigned int list, unsigned int iv) {
+ unsigned int list) {
int id = inpart->id();
if( id < 0 || !vertex->isIncoming(inpart) || vertex->getNpoint() != 3 )
return vector<TwoBodyDecay>();
Energy m1(inpart->mass());
tPDVector decaylist = vertex->search(list, inpart);
vector<TwoBodyDecay> decays;
tPDVector::size_type nd = decaylist.size();
for( tPDVector::size_type i = 0; i < nd; i += 3 ) {
tPDPtr pa(decaylist[i]), pb(decaylist[i + 1]), pc(decaylist[i + 2]);
if( pb->id() == id ) swap(pa, pb);
if( pc->id() == id ) swap(pa, pc);
//allowed on-shell decay?
if( m1 <= pb->mass() + pc->mass() ) continue;
//vertices are defined with all particles incoming
if( pb->CC() ) pb = pb->CC();
if( pc->CC() ) pc = pc->CC();
- decays.push_back( TwoBodyDecay(inpart,pb, pc) );
+ decays.push_back( TwoBodyDecay(inpart,pb, pc, vertex) );
}
- if( !decays.empty() )
- createDecayer(vertex,list,iv);
-
return decays;
}
-void TwoBodyDecayConstructor::createDecayer(VertexBasePtr vertex,
- unsigned int icol,
- unsigned int ivert) {
- if( _theExistingDecayers[ivert][icol] ) return;
+GeneralTwoBodyDecayerPtr TwoBodyDecayConstructor::createDecayer(TwoBodyDecay & decay) {
string name;
using namespace Helicity::VertexType;
- switch(vertex->getName()) {
+ PDT::Spin in = decay.parent_->iSpin();
+ // PDT::Spin out1 = decay.children_.first ->iSpin();
+ PDT::Spin out2 = decay.children_.second->iSpin();
+ switch(decay.vertex_->getName()) {
case FFV :
- name = ( icol == 0 || icol == 1) ? "FFVDecayer" : "VFFDecayer";
+ if(in == PDT::Spin1Half) {
+ name = "FFVDecayer";
+ if(out2==PDT::Spin1Half)
+ swap(decay.children_.first,decay.children_.second);
+ }
+ else {
+ name = "VFFDecayer";
+ }
break;
case FFS :
- name = ( icol == 0 || icol == 1) ? "FFSDecayer" : "SFFDecayer";
+ if(in == PDT::Spin1Half) {
+ name = "FFSDecayer";
+ if(out2==PDT::Spin1Half)
+ swap(decay.children_.first,decay.children_.second);
+ }
+ else {
+ name = "SFFDecayer";
+ }
break;
case VVS :
- name = ( icol == 0 || icol == 1) ? "VVSDecayer" : "SVVDecayer";
+ if(in == PDT::Spin1) {
+ name = "VVSDecayer";
+ if(out2==PDT::Spin1)
+ swap(decay.children_.first,decay.children_.second);
+ }
+ else {
+ name = "SVVDecayer";
+ }
break;
case VSS :
- name = (icol == 0) ? "VSSDecayer" : "SSVDecayer";
+ if(in == PDT::Spin1) {
+ name = "VSSDecayer";
+ }
+ else {
+ name = "SSVDecayer";
+ if(out2==PDT::Spin0)
+ swap(decay.children_.first,decay.children_.second);
+ }
break;
case VVT :
- name = (icol == 2) ? "TVVDecayer" : "Unknown";
+ name = in==PDT::Spin2 ? "TVVDecayer" : "Unknown";
break;
case FFT :
- name = (icol == 2) ? "TFFDecayer" : "Unknown";
+ name = in==PDT::Spin2 ? "TFFDecayer" : "Unknown";
break;
case SST :
- name = (icol == 2) ? "TSSDecayer" : "Unknown";
+ name = in==PDT::Spin2 ? "TSSDecayer" : "Unknown";
break;
case SSS :
name = "SSSDecayer";
break;
case VVV :
name = "VVVDecayer";
break;
case RFS :
- if(icol==1) name = "FRSDecayer";
- else if(icol==2) name = "SRFDecayer";
- else name = "Unknown";
+ if(in==PDT::Spin1Half) {
+ name = "FRSDecayer";
+ if(out2==PDT::Spin3Half)
+ swap(decay.children_.first,decay.children_.second);
+ }
+ else if(in==PDT::Spin0) {
+ name = "SRFDecayer";
+ if(out2==PDT::Spin3Half)
+ swap(decay.children_.first,decay.children_.second);
+ }
+ else {
+ name = "Unknown";
+ }
break;
case RFV :
- if(icol==1) name = "FRVDecayer";
- else name = "Unknown";
+ if(in==PDT::Spin1Half) {
+ name = "FRVDecayer";
+ if(out2==PDT::Spin3Half)
+ swap(decay.children_.first,decay.children_.second);
+ }
+ else
+ name = "Unknown";
break;
- default : throw NBodyDecayConstructorError()
- << "Error: Cannot assign " << vertex->fullName() << " to a decayer. "
- << "Looking in column " << icol;
+ default : Throw<NBodyDecayConstructorError>()
+ << "Error: Cannot assign " << decay.vertex_->fullName() << " to a decayer. "
+ << "Decay is " << decay.parent_->PDGName() << " -> "
+ << decay.children_.first ->PDGName() << " "
+ << decay.children_.second->PDGName();
}
- if(name=="Unknown") throw NBodyDecayConstructorError()
- << "Error: Cannot assign " << vertex->fullName() << " to a decayer. "
- << "Looking in column " << icol;
+ if(name=="Unknown")
+ Throw<NBodyDecayConstructorError>()
+ << "Error: Cannot assign " << decay.vertex_->fullName() << " to a decayer. "
+ << "Decay is " << decay.parent_->PDGName() << " -> "
+ << decay.children_.first ->PDGName() << " "
+ << decay.children_.second->PDGName();
ostringstream fullname;
- fullname << "/Herwig/Decays/" << name << "_"
- << ivert << "_" << icol;
+ fullname << "/Herwig/Decays/" << name << "_" << decay.parent_->PDGName()
+ << "_" << decay.children_.first ->PDGName()
+ << "_" << decay.children_.second->PDGName();
string classname = "Herwig::" + name;
GeneralTwoBodyDecayerPtr decayer;
decayer = dynamic_ptr_cast<GeneralTwoBodyDecayerPtr>
(generator()->preinitCreate(classname,fullname.str()));
- if(!decayer) throw NBodyDecayConstructorError()
- << "Error: Cannot assign " << vertex->fullName() << " to a decayer. "
- << "Looking in column " << icol;
- string msg = generator()->preinitInterface(decayer, "DecayVertex",
- "set", vertex->fullName());
- if(msg.find("Error:") != string::npos)
- throw NBodyDecayConstructorError()
- << "TwoBodyDecayConstructor::createDecayer - An error occurred while "
- << "setting the vertex for " << decayer->fullName()
- << " - " << msg
- << Exception::abortnow;
+ if(!decayer)
+ Throw<NBodyDecayConstructorError>()
+ << "Error: Cannot assign " << decay.vertex_->fullName() << " to a decayer. "
+ << "Decay is " << decay.parent_->PDGName() << " -> "
+ << decay.children_.first ->PDGName() << " "
+ << decay.children_.second->PDGName();
+ decayer->setDecayInfo(decay.parent_,decay.children_,decay.vertex_);
decayer->init();
setDecayerInterfaces(fullname.str());
- _theExistingDecayers[ivert][icol] = decayer;
+ return decayer;
}
void TwoBodyDecayConstructor::
-createDecayMode(const vector<TwoBodyDecay> & decays,
- GeneralTwoBodyDecayerPtr decayer) {
- if(!decayer)
- throw NBodyDecayConstructorError()
- << "TwoBodyDecayConstructor::createDecayMode - The decayer "
- << "pointer is null!\n"
- << Exception::runerror;
+createDecayMode(vector<TwoBodyDecay> & decays) {
tPDPtr inpart = decays[0].parent_;
- inpart->stable(false);
tEGPtr eg = generator();
- vector<TwoBodyDecay>::const_iterator dend = decays.end();
- for( vector<TwoBodyDecay>::const_iterator dit = decays.begin();
+ vector<TwoBodyDecay>::iterator dend = decays.end();
+ for( vector<TwoBodyDecay>::iterator dit = decays.begin();
dit != dend; ++dit ) {
tPDPtr pb((*dit).children_.first), pc((*dit).children_.second);
string tag = inpart->name() + "->" + pb->name() + "," +
pc->name() + ";";
// Does it exist already ?
tDMPtr dm = eg->findDecayMode(tag);
// Check if tag is one that should be disabled
if( decayConstructor()->disableDecayMode(tag) ) {
// If mode alread exists, ie has been read from file,
// disable it
if( dm ) {
eg->preinitInterface(dm, "BranchingRatio", "set", "0.0");
eg->preinitInterface(dm, "OnOff", "set", "Off");
}
continue;
}
- //now create DecayMode objects that do not already exist
+ // now create DecayMode objects that do not already exist
if( createDecayModes() && (!dm || inpart->id() == ParticleID::h0) ) {
tDMPtr ndm = eg->preinitCreateDecayMode(tag);
-
if(ndm) {
+ inpart->stable(false);
+ GeneralTwoBodyDecayerPtr decayer=createDecayer(*dit);
eg->preinitInterface(ndm, "Decayer", "set",
decayer->fullName());
eg->preinitInterface(ndm, "OnOff", "set", "On");
Energy width =
decayer->partialWidth(make_pair(inpart,inpart->mass()),
make_pair(pb,pb->mass()) ,
make_pair(pc,pc->mass()));
setBranchingRatio(ndm, width);
+ if(ndm->brat()<decayConstructor()->minimumBR()) {
+ generator()->preinitInterface(decayer->fullName(),
+ "Initialize", "set","0");
+ }
}
else
throw NBodyDecayConstructorError()
<< "TwoBodyDecayConstructor::createDecayMode - Needed to create "
<< "new decaymode but one could not be created for the tag "
<< tag << Exception::warning;
}
else if( dm ) {
- if((dm->decayer()->fullName()).find("Mambo") != string::npos)
+ if(dm->brat()<decayConstructor()->minimumBR()) {
+ continue;
+ }
+ if((dm->decayer()->fullName()).find("Mambo") != string::npos) {
+ inpart->stable(false);
+ GeneralTwoBodyDecayerPtr decayer=createDecayer(*dit);
eg->preinitInterface(dm, "Decayer", "set",
decayer->fullName());
+ }
}
}
// update CC mode if it exists
if( inpart->CC() ) inpart->CC()->synchronize();
}
diff --git a/Models/General/TwoBodyDecayConstructor.h b/Models/General/TwoBodyDecayConstructor.h
--- a/Models/General/TwoBodyDecayConstructor.h
+++ b/Models/General/TwoBodyDecayConstructor.h
@@ -1,226 +1,158 @@
// -*- C++ -*-
//
// TwoBodyDecayConstructor.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_TwoBodyDecayConstructor_H
#define HERWIG_TwoBodyDecayConstructor_H
//
// This is the declaration of the TwoBodyDecayConstructor class.
//
#include "NBodyDecayConstructorBase.h"
#include "ThePEG/Helicity/Vertex/VertexBase.h"
#include "Herwig++/Decay/General/GeneralTwoBodyDecayer.fh"
+#include "TwoBodyDecay.h"
namespace Herwig {
using namespace ThePEG;
using Helicity::VertexBasePtr;
-
-//typedef pair<tPDPtr, tPDPair> TwoBodyDecay;
-
- /**
- * A two body decay mode
- */
- struct TwoBodyDecay {
-
- public:
-
- /**
- * Constructor
- * @param pa Decaying particle
- * @param pb First decay product
- * @param pc Second decay product
- */
- TwoBodyDecay(tPDPtr pa, tPDPtr pb, tPDPtr pc) : parent_(pa) {
- ParticleOrdering order;
- if( order(pb, pc) ) {
- children_.first = pb;
- children_.second = pc;
- }
- else {
- children_.first = pc;
- children_.second = pb;
- }
- }
-
- /**
- * The parent
- */
- tPDPtr parent_;
-
- /**
- * The children
- */
- tPDPair children_;
-
- private:
-
- TwoBodyDecay();
- };
+using Helicity::tVertexBasePtr;
/**
* The TwoBodyDecayConstructor class inherits from the dummy base class
* NBodyDecayConstructorBase and implements the necessary functions in
* order to create the 2 body decay modes for a given set of vertices
* stored in a Model class.
*
* @see \ref TwoBodyDecayConstructorInterfaces "The interfaces"
* defined for TwoBodyDecayConstructor.
* @see NBodyDecayConstructor
**/
class TwoBodyDecayConstructor: public NBodyDecayConstructorBase {
public:
/**
* The default constructor.
*/
- TwoBodyDecayConstructor() : _theExistingDecayers(0) {}
+ TwoBodyDecayConstructor() {}
/**
* Function used to determine allowed decaymodes
*@param part vector of ParticleData pointers containing particles in model
*/
virtual void DecayList(const set<PDPtr> & part);
/**
* Number of outgoing lines. Required for correct ordering.
*/
virtual unsigned int numBodies() const { return 2; }
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:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
- static ClassDescription<TwoBodyDecayConstructor> initTwoBodyDecayConstructor;
+ static NoPIOClassDescription<TwoBodyDecayConstructor> initTwoBodyDecayConstructor;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
TwoBodyDecayConstructor & operator=(const TwoBodyDecayConstructor &);
private:
/** @name Functions to create decayers and decaymodes. */
//@{
/**
* Function to create decays
* @param inpart Incoming particle
* @param vert The vertex to create decays for
* @param ilist Which list to search
* @param iv Row number in _theExistingDecayers member
* @return A vector a decay modes
*/
vector<TwoBodyDecay> createModes(tPDPtr inpart, VertexBasePtr vert,
- unsigned int ilist,
- unsigned int iv);
+ unsigned int ilist);
/**
* Function to create decayer for specific vertex
- * @param vert Pointer to vertex
- * @param icol Integer referring to the colmun in _theExistingDecayers
- * @param ivert Integer referring to the row in _theExistingDecayers
+ * @param decay decay mode for this decay
* member variable
*/
- void createDecayer(VertexBasePtr vert, unsigned int icol,
- unsigned int ivert);
+ GeneralTwoBodyDecayerPtr createDecayer(TwoBodyDecay & decay);
/**
* Create decay mode(s) from given part and decay modes
* @param decays The vector of decay modes
* @param decayer The decayer responsible for this decay
*/
- void createDecayMode(const vector<TwoBodyDecay> & decays,
- GeneralTwoBodyDecayerPtr decayer);
+ void createDecayMode(vector<TwoBodyDecay> & decays);
//@}
-
-private:
-
- /**
- * Existing decayers
- */
- vector<vector<GeneralTwoBodyDecayerPtr> > _theExistingDecayers;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of TwoBodyDecayConstructor. */
template <>
struct BaseClassTrait<Herwig::TwoBodyDecayConstructor,1> {
/** Typedef of the first base class of TwoBodyDecayConstructor. */
typedef Herwig::NBodyDecayConstructorBase NthBase;
};
/** This template specialization informs ThePEG about the name of
* the TwoBodyDecayConstructor class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::TwoBodyDecayConstructor>
: public ClassTraitsBase<Herwig::TwoBodyDecayConstructor> {
/** Return a platform-independent class name */
static string className() { return "Herwig::TwoBodyDecayConstructor"; }
};
/** @endcond */
}
#endif /* HERWIG_TwoBodyDecayConstructor_H */
diff --git a/Models/General/WeakCurrentDecayConstructor.cc b/Models/General/WeakCurrentDecayConstructor.cc
--- a/Models/General/WeakCurrentDecayConstructor.cc
+++ b/Models/General/WeakCurrentDecayConstructor.cc
@@ -1,369 +1,291 @@
// -*- C++ -*-
//
// WeakCurrentDecayConstructor.cc is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the WeakCurrentDecayConstructor class.
//
#include "WeakCurrentDecayConstructor.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/ParVector.h"
#include "ThePEG/Interface/RefVector.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/PDT/DecayMode.h"
#include "ThePEG/Helicity/Vertex/AbstractFFVVertex.fh"
+#include "DecayConstructor.h"
using namespace Herwig;
using ThePEG::Helicity::VertexBasePtr;
IBPtr WeakCurrentDecayConstructor::clone() const {
return new_ptr(*this);
}
IBPtr WeakCurrentDecayConstructor::fullclone() const {
return new_ptr(*this);
}
void WeakCurrentDecayConstructor::doinit() {
NBodyDecayConstructorBase::doinit();
_theModel = dynamic_ptr_cast<Ptr<Herwig::StandardModel>::pointer>
(generator()->standardModel());
unsigned int isize=decayTags_.size();
if(isize!=_norm .size()||isize!=_current.size())
throw InitException() << "Invalid sizes for the decay mode vectors in "
<< " WeakCurrentDecayConstructor "
<< decayTags_.size() << " " << _norm.size() << " "
<< _current.size() << Exception::runerror;
// get the particles from the tags
for(unsigned int ix=0;ix<decayTags_.size();++ix) {
_current[ix]->init();
particles_.push_back(vector<tPDPtr>());
string tag=decayTags_[ix];
do {
string::size_type next = min(tag.find(','), tag.find(';'));
particles_.back().push_back(generator()->findParticle(tag.substr(0,next)));
if(!particles_.back().back())
throw Exception() << "Failed to find particle " << tag.substr(0,next)
<< " in DecayMode " << decayTags_[ix]
<< " in WeakCurrentDecayConstructor::doinit()"
<< Exception::runerror;
if(tag[next]==';') break;
tag = tag.substr(next+1);
}
while(true);
}
}
void WeakCurrentDecayConstructor::persistentOutput(PersistentOStream & os) const {
- os << _theExistingDecayers << _init << _iteration << _points << ounit(_masscut,GeV)
- << decayTags_ << particles_ << _norm << _current;
+ os << ounit(_masscut,GeV) << decayTags_ << particles_ << _norm << _current;
}
void WeakCurrentDecayConstructor::persistentInput(PersistentIStream & is, int) {
- is >>_theExistingDecayers >> _init >> _iteration >> _points >> iunit(_masscut,GeV)
- >> decayTags_ >> particles_ >> _norm >> _current;
+ is >> iunit(_masscut,GeV) >> decayTags_ >> particles_ >> _norm >> _current;
}
ClassDescription<WeakCurrentDecayConstructor> WeakCurrentDecayConstructor::initWeakCurrentDecayConstructor;
// Definition of the static class description member.
void WeakCurrentDecayConstructor::Init() {
static ClassDocumentation<WeakCurrentDecayConstructor> documentation
("The WeakCurrentDecayConstructor class implemets the decay of BSM particles "
"to low mass hadronic states using the Weak current");
-
- static Switch<WeakCurrentDecayConstructor,bool> interfaceInitializeDecayers
- ("InitializeDecayers",
- "Initialize new decayers",
- &WeakCurrentDecayConstructor::_init, true, false, false);
- static SwitchOption interfaceInitializeDecayersInitializeDecayersOn
- (interfaceInitializeDecayers,
- "Yes",
- "Initialize new decayers to find max weights",
- true);
- static SwitchOption interfaceInitializeDecayersoff
- (interfaceInitializeDecayers,
- "No",
- "Use supplied weights for integration",
- false);
-
- static Parameter<WeakCurrentDecayConstructor,int> interfaceInitIteration
- ("InitIteration",
- "Number of iterations to optimise integration weights",
- &WeakCurrentDecayConstructor::_iteration, 5, 0, 5,
- false, false, true);
-
- static Parameter<WeakCurrentDecayConstructor,int> interfaceInitPoints
- ("InitPoints",
- "Number of points to generate when optimising integration",
- &WeakCurrentDecayConstructor::_points, 10000, 100, 100000000,
- false, false, true);
static ParVector<WeakCurrentDecayConstructor,string> interfaceDecayModes
("DecayModes",
"The decays of the weak current",
&WeakCurrentDecayConstructor::decayTags_, -1, "", "", "",
false, false, Interface::nolimits);
static ParVector<WeakCurrentDecayConstructor,double> interfaceNormalisation
("Normalisation",
"The normalisation of the different modes",
&WeakCurrentDecayConstructor::_norm, -1, 1.0, 0.0, 10.0,
false, false, Interface::limited);
static RefVector<WeakCurrentDecayConstructor,WeakDecayCurrent> interfaceCurrent
("Current",
"The current for the decay mode",
&WeakCurrentDecayConstructor::_current, -1, false, false, true, false, false);
static Parameter<WeakCurrentDecayConstructor,Energy> interfaceMassCut
("MassCut",
"The maximum mass difference for the decay",
&WeakCurrentDecayConstructor::_masscut, GeV, 5.0*GeV, 1.0*GeV, 10.0*GeV,
false, false, Interface::limited);
}
void WeakCurrentDecayConstructor::DecayList(const set<PDPtr> & part) {
if( part.empty() ) return;
unsigned int nv(_theModel->numberOfVertices());
- // resize the vectors
- _theExistingDecayers.
- resize(nv,vector<map<WeakDecayCurrentPtr,GeneralCurrentDecayerPtr> >
- (3,map<WeakDecayCurrentPtr,GeneralCurrentDecayerPtr>()));
- tPDVector decays;
for(set<PDPtr>::const_iterator ip=part.begin();ip!=part.end();++ip) {
for(unsigned int iv = 0; iv < nv; ++iv) {
for(unsigned int ilist = 0; ilist < 3; ++ilist) {
- decays = createModes(*ip, _theModel->vertex(iv),
- ilist, iv);
- if(decays.size() > 0){
- tPDPtr incpart = (**ip).CC() ? (**ip).CC() : tPDPtr(*ip);
- createDecayMode(incpart, decays, _theExistingDecayers[iv][ilist]);
- }
+ vector<TwoBodyDecay> decays =
+ createModes(*ip, _theModel->vertex(iv),ilist);
+ if(!decays.empty()) createDecayMode(decays);
}
}
}
}
-vector<tPDPtr> WeakCurrentDecayConstructor::createModes(const PDPtr inpart,
- const VertexBasePtr vert,
- unsigned int ilist,
- unsigned int iv) {
+vector<TwoBodyDecay> WeakCurrentDecayConstructor::createModes(const PDPtr inpart,
+ const VertexBasePtr vert,
+ unsigned int ilist) {
int id = inpart->id();
if( id < 0 || !vert->isIncoming(inpart) || vert->getNpoint() != 3 )
- return tPDVector();
+ return vector<TwoBodyDecay>();
Energy m1(inpart->mass());
vector<tPDPtr> decaylist;
decaylist = vert->search(ilist,inpart);
tPDVector::size_type nd = decaylist.size();
- tPDVector decays;
+ vector<TwoBodyDecay> decays;
for( tPDVector::size_type i = 0; i < nd; i += 3 ) {
tPDPtr pa(decaylist[i]), pb(decaylist.at(i + 1)),
pc(decaylist.at(i + 2));
if( pb->id() == id ) swap(pa, pb);
if( pc->id() == id ) swap(pa, pc);
//One of the products must be a W
Energy mp(ZERO);
if( abs(pb->id()) == ParticleID::Wplus )
mp = pc->mass();
else if( abs(pc->id()) == ParticleID::Wplus )
mp = pb->mass();
else
continue;
//allowed on-shell decay and passes mass cut
if( m1 >= pb->mass() + pc->mass() ) continue;
if( m1 < mp ) continue;
if( m1 - mp >= _masscut ) continue;
//vertices are defined with all particles incoming
if( pb->CC() ) pb = pb->CC();
if( pc->CC() ) pc = pc->CC();
- decays.push_back(inpart);
- decays.push_back(pb);
- decays.push_back(pc);
- }
-
- if( !decays.empty() ) {
- bool output = createDecayer(vert,ilist,iv);
- if(!output) decays.clear();
+ decays.push_back( TwoBodyDecay(inpart,pb, pc, vert) );
+ if(abs(decays.back().children_.second->id())!=ParticleID::Wplus)
+ swap(decays.back().children_.first,decays.back().children_.second);
+ assert(abs(decays.back().children_.second->id())==ParticleID::Wplus);
}
return decays;
}
-bool WeakCurrentDecayConstructor::createDecayer(const VertexBasePtr vert,
- unsigned int icol,
- unsigned int ivert) {
- if(_theExistingDecayers[ivert][icol].empty()) {
- string name;
- using namespace ThePEG::Helicity::VertexType;
- switch(vert->getName()) {
- case FFV :
- name = "FFVCurrentDecayer";
- break;
- default :
- ostringstream message;
- message << "Invalid vertex for decays via weak current "
- << vert->fullName() << "\n";;
- generator()->logWarning(NBodyDecayConstructorError(message.str(),
- Exception::warning));
- return false;
- }
- ostringstream fullname;
- fullname << "/Herwig/Decays/" << name << "_"
- << ivert << "_" << icol;
- string classname = "Herwig::" + name;
- ostringstream cut;
- cut << _masscut/GeV;
- for(unsigned int ix=0;ix<particles_.size();++ix) {
- ostringstream fullname2;
- fullname2 << fullname.str() << "_" << ix;
- if(_theExistingDecayers[ivert][icol].find(_current[ix])==
- _theExistingDecayers[ivert][icol].end()) {
- GeneralCurrentDecayerPtr decayer = dynamic_ptr_cast<GeneralCurrentDecayerPtr>
- (generator()->preinitCreate(classname,fullname2.str()));
- string msg = generator()->preinitInterface(decayer, "DecayVertex",
- "set", vert->fullName());
- if(msg.find("Error:") != string::npos)
- throw NBodyDecayConstructorError()
- << "WeakCurrentDecayConstructor::createDecayer - An error occurred while "
- << "setting the vertex for " << decayer->fullName()
- << " - " << msg
- << Exception::abortnow;
- msg = generator()->preinitInterface(decayer, "Current","set",
- _current[ix]->fullName());
- if(msg.find("Error:") != string::npos)
- throw NBodyDecayConstructorError()
- << "WeakCurrentDecayConstructor::createDecayer - An error occurred while "
- << "setting the current for " << decayer->fullName()
- << " - " << msg
- << Exception::abortnow;
- msg = generator()->preinitInterface(decayer, "MaximumMass","set",cut.str());
- if(msg.find("Error:") != string::npos)
- throw NBodyDecayConstructorError()
- << "WeakCurrentDecayConstructor::createDecayer - An error occurred while "
- << "setting the cut-off for " << decayer->fullName()
- << " - " << msg
- << Exception::abortnow;
- if(_init) initializeDecayers(fullname2.str());
- decayer->init();
- _theExistingDecayers[ivert][icol][_current[ix]]=decayer;
- }
- }
+GeneralCurrentDecayerPtr WeakCurrentDecayConstructor::createDecayer(PDPtr in, PDPtr out1,
+ vector<tPDPtr> outCurrent,
+ VertexBasePtr vertex,
+ WeakDecayCurrentPtr current) {
+ string name;
+ using namespace ThePEG::Helicity::VertexType;
+ switch(vertex->getName()) {
+ case FFV :
+ name = "FFVCurrentDecayer";
+ break;
+ default :
+ ostringstream message;
+ message << "Invalid vertex for decays of " << in->PDGName() << " -> " << out1->PDGName()
+ << " via weak current " << vertex->fullName() << "\n";
+ generator()->logWarning(NBodyDecayConstructorError(message.str(),
+ Exception::warning));
+ return GeneralCurrentDecayerPtr();
}
- return true;
+ ostringstream fullname;
+ fullname << "/Herwig/Decays/" << name << "_" << in->PDGName() << "_"
+ << out1->PDGName();
+ for(unsigned int ix=0;ix<outCurrent.size();++ix)
+ fullname << "_" << outCurrent[ix]->PDGName();
+ string classname = "Herwig::" + name;
+ GeneralCurrentDecayerPtr decayer = dynamic_ptr_cast<GeneralCurrentDecayerPtr>
+ (generator()->preinitCreate(classname,fullname.str()));
+ decayer->setDecayInfo(in,out1,outCurrent,vertex,current,_masscut);
+ // set decayer options from base class
+ setDecayerInterfaces(fullname.str());
+ // initialize the decayer
+ decayer->init();
+ // return the decayer
+ return decayer;
}
void WeakCurrentDecayConstructor::
-createDecayMode(PDPtr inpart, const tPDVector & decays,
- map<WeakDecayCurrentPtr,GeneralCurrentDecayerPtr> decayers) {
- if(decays.empty()) {
- throw NBodyDecayConstructorError()
- << "WeakCurrentDecayConstructor::createDecayMode - No decayers\n"
- << Exception::runerror;
- }
- // the partial widths
- PDVector particles(3);
- if(inpart->CC()) inpart = inpart->CC();
- inpart->stable(false);
- particles[0] = inpart;
- bool Wplus;
- for(unsigned int ix = 0; ix < decays.size(); ix += 3) {
- if(decays[ix]->id() == inpart->id()) {
- particles[1] = decays[ix+1];
- particles[2] = decays[ix+2];
- }
- else if(decays[ix+1]->id() == inpart->id()) {
- particles[1] = decays[ix];
- particles[2] = decays[ix+2];
- }
- else {
- particles[1] = decays[ix];
- particles[2] = decays[ix+1];
- }
- if(abs(particles[1]->id())==ParticleID::Wplus) swap(particles[1],particles[2]);
- Wplus=particles[2]->id()==ParticleID::Wplus;
- particles.resize(2);
+createDecayMode(vector<TwoBodyDecay> & decays) {
+ assert(!decays.empty());
+ for(unsigned int ix = 0; ix < decays.size(); ++ix) {
+ PDVector particles(3);
+ particles[0] = decays[ix].parent_;
+ particles[1] = decays[ix].children_.first ;
+ bool Wplus=decays[ix].children_.second->id()==ParticleID::Wplus;
for(unsigned int iy=0;iy<_current.size();++iy) {
particles.resize(2);
vector<tPDPtr> wprod=particles_[iy];
int icharge=0;
- Energy msum = inpart->mass()-particles[1]->mass();
+ Energy msum = particles[0]->mass()-particles[1]->mass();
for(unsigned int iz=0;iz<wprod.size();++iz) {
icharge += wprod[iz]->iCharge();
msum -=wprod[iz]->mass();
}
if(msum<=ZERO) continue;
bool cc = (Wplus&&icharge==-3)||(!Wplus&&icharge==3);
OrderedParticles outgoing;
outgoing.insert(particles[1]);
for(unsigned int iz=0;iz<wprod.size();++iz) {
if(cc&&wprod[iz]->CC()) wprod[iz]=wprod[iz]->CC();
outgoing.insert(wprod[iz]);
}
+ // check outgoing particles initialised
+ for(unsigned int iz=0;iz<wprod.size();++iz) wprod[iz]->init();
+ // create the tag for the decay mode
string tag = particles[0]->PDGName() + "->";
OrderedParticles::const_iterator it = outgoing.begin();
do {
tag += (**it).name();
++it;
if(it!=outgoing.end()) tag +=",";
else tag +=";";
}
while(it!=outgoing.end());
- // create the decayer
- GeneralCurrentDecayerPtr decayer = decayers.find(_current[iy])->second;
- // check outgoing particles initialised
- for(unsigned int iz=0;iz<wprod.size();++iz) wprod[iz]->init();
- // calculate the width
- Energy pWidth = _norm[iy]*decayer->partialWidth(inpart,particles[1],wprod);
- if(pWidth<=ZERO) continue;
// find the decay mode
tDMPtr dm= generator()->findDecayMode(tag);
if( !dm && createDecayModes() ) {
+ // create the decayer
+ GeneralCurrentDecayerPtr decayer = createDecayer(particles[0],particles[1],
+ wprod,decays[ix].vertex_,
+ _current[iy]);
+ // calculate the width
+ Energy pWidth = _norm[iy]*decayer->partialWidth(particles[0],particles[1],wprod);
+ if(pWidth<=ZERO) {
+ generator()->preinitInterface(decayer->fullName(),
+ "Initialize", "set","0");
+ continue;
+ }
tDMPtr ndm = generator()->preinitCreateDecayMode(tag);
if(!ndm) throw NBodyDecayConstructorError()
<< "WeakCurrentDecayConstructor::createDecayMode - Needed to create "
<< "new decaymode but one could not be created for the tag "
<< tag
<< Exception::warning;
generator()->preinitInterface(ndm, "Decayer", "set",
decayer->fullName());
generator()->preinitInterface(ndm, "OnOff", "set", "On");
setBranchingRatio(ndm, pWidth);
+ particles[0]->stable(false);
+ if(ndm->brat()<decayConstructor()->minimumBR()) {
+ generator()->preinitInterface(decayer->fullName(),
+ "Initialize", "set","0");
+ }
}
- else {
+ else if (dm) {
+ // create the decayer
+ GeneralCurrentDecayerPtr decayer = createDecayer(particles[0],particles[1],
+ wprod,decays[ix].vertex_,
+ _current[iy]);
generator()->preinitInterface(dm, "Decayer", "set", decayer->fullName());
+ particles[0]->stable(false);
if(createDecayModes()) {
+ // calculate the width
+ Energy pWidth = _norm[iy]*decayer->partialWidth(particles[0],particles[1],wprod);
+ if(pWidth<=ZERO) {
+ generator()->preinitInterface(decayer->fullName(),
+ "Initialize", "set","0");
+ continue;
+ }
generator()->preinitInterface(dm, "OnOff", "set", "On");
particles[0]->width(particles[0]->width()*(1.-dm->brat()));
setBranchingRatio(dm, pWidth);
}
+ if(dm->brat()<decayConstructor()->minimumBR()) {
+ generator()->preinitInterface(decayer->fullName(),
+ "Initialize", "set","0");
+ }
}
}
}
}
-
-void WeakCurrentDecayConstructor::initializeDecayers(string fullname) const {
- ostringstream value;
- value << _init;
- string msg = generator()->preinitInterface(fullname, "Initialize", "set",
- value.str());
- value.str("");
- value << _iteration;
- msg=generator()->preinitInterface(fullname, "Iteration", "set",
- value.str());
- value.str("");
- value << _points;
- msg=generator()->preinitInterface(fullname, "Points", "set",
- value.str());
-}
diff --git a/Models/General/WeakCurrentDecayConstructor.h b/Models/General/WeakCurrentDecayConstructor.h
--- a/Models/General/WeakCurrentDecayConstructor.h
+++ b/Models/General/WeakCurrentDecayConstructor.h
@@ -1,259 +1,229 @@
// -*- C++ -*-
//
// WeakCurrentDecayConstructor.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_WeakCurrentDecayConstructor_H
#define HERWIG_WeakCurrentDecayConstructor_H
//
// This is the declaration of the WeakCurrentDecayConstructor class.
//
#include "NBodyDecayConstructorBase.h"
#include "ThePEG/Helicity/Vertex/VertexBase.h"
#include "Herwig++/Decay/DecayIntegrator.h"
#include "Herwig++/Decay/DecayPhaseSpaceMode.h"
#include "Herwig++/Decay/General/GeneralCurrentDecayer.fh"
#include "Herwig++/Models/StandardModel/StandardModel.h"
#include "Herwig++/Decay/WeakCurrents/WeakDecayCurrent.h"
#include "Herwig++/Decay/General/GeneralCurrentDecayer.h"
+#include "TwoBodyDecay.h"
namespace Herwig {
using namespace ThePEG;
/**
* Here is the documentation of the WeakCurrentDecayConstructor class.
*
* @see \ref WeakCurrentDecayConstructorInterfaces "The interfaces"
* defined for WeakCurrentDecayConstructor.
*/
class WeakCurrentDecayConstructor: public NBodyDecayConstructorBase {
public:
/**
* The default constructor.
*/
- WeakCurrentDecayConstructor() :
- _theExistingDecayers(0),_init(true),_iteration(5),_points(10000),
- _masscut(5.*GeV) {}
+ WeakCurrentDecayConstructor() : _masscut(5.*GeV) {}
/**
* Function used to determine allowed decaymodes, to be implemented
* in derived class.
*@param part vector of ParticleData pointers containing particles in model
*/
virtual void DecayList(const set<PDPtr> & part);
/**
* Number of outgoing lines. Required for correct ordering (do this one last)
*/
virtual unsigned int numBodies() const { return 1000; }
/**
* Cut off
*/
Energy massCut() const { return _masscut;}
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;
//@}
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();
//@}
private:
/** @name Functions to create decayers and decaymodes. */
//@{
/**
* Function to create decays
* @param inpart Incoming particle
* @param vert The vertex to create decays for
* @param ilist Which list to search
* @param iv Row number in _theExistingDecayers member
* @return vector of ParticleData ptrs
*/
- vector<tPDPtr> createModes(const PDPtr inpart,
- const VertexBasePtr vert,
- unsigned int ilist,
- unsigned int iv);
+ vector<TwoBodyDecay>
+ createModes(const PDPtr inpart,const VertexBasePtr vert,
+ unsigned int ilist);
/**
* Function to create decayer for specific vertex
* @param vert Pointer to vertex
* @param icol Integer referring to the colmun in _theExistingDecayers
* @param ivert Integer referring to the row in _theExistingDecayers
* member variable
*/
- bool createDecayer(const VertexBasePtr vert, unsigned int icol,
- unsigned int ivert);
+ GeneralCurrentDecayerPtr createDecayer(PDPtr in, PDPtr out1,
+ vector<tPDPtr> outCurrent,
+ VertexBasePtr vertex,
+ WeakDecayCurrentPtr current);
/**
* Create decay mode(s) from given part and decay modes
* @param inpart pointer to incoming particle
* @param decays list of allowed interactions
* @param decayer The decayer responsible for this decay
*/
- void createDecayMode(PDPtr inpart,
- const tPDVector & decays,
- map<WeakDecayCurrentPtr,GeneralCurrentDecayerPtr> decayer);
-
- /**
- * Set the interfaces on the decayers to initialise them
- * @param name Fullname of the decayer in the EventGenerator
- * including the path
- */
- void initializeDecayers(string name) const;
+ void createDecayMode(vector<TwoBodyDecay> & decays);
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<WeakCurrentDecayConstructor> initWeakCurrentDecayConstructor;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
WeakCurrentDecayConstructor & operator=(const WeakCurrentDecayConstructor &);
private:
/**
- * Existing decayers
- */
- vector<vector<map<WeakDecayCurrentPtr,GeneralCurrentDecayerPtr> > >
- _theExistingDecayers;
-
- /**
* Model Pointer
*/
Ptr<Herwig::StandardModel>::pointer _theModel;
/**
- * Whether to initialize the decayers or not
- */
- bool _init;
-
- /**
- * Number of iterations if initializing (default 1)
- */
- int _iteration;
-
- /**
- * Number of points to do in initialization
- */
- int _points;
-
- /**
* Cut-off on the mass difference
*/
Energy _masscut;
/**
* Tags for the modes
*/
vector<string> decayTags_;
/**
* Particles for the mode
*/
vector<vector<tPDPtr> > particles_;
/**
* Normalisation
*/
vector<double> _norm;
/**
* The current for the mode
*/
vector<WeakDecayCurrentPtr> _current;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of WeakCurrentDecayConstructor. */
template <>
struct BaseClassTrait<Herwig::WeakCurrentDecayConstructor,1> {
/** Typedef of the first base class of WeakCurrentDecayConstructor. */
typedef Herwig::NBodyDecayConstructorBase NthBase;
};
/** This template specialization informs ThePEG about the name of
* the WeakCurrentDecayConstructor class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::WeakCurrentDecayConstructor>
: public ClassTraitsBase<Herwig::WeakCurrentDecayConstructor> {
/** Return a platform-independent class name */
static string className() { return "Herwig::WeakCurrentDecayConstructor"; }
};
/** @endcond */
}
#endif /* HERWIG_WeakCurrentDecayConstructor_H */
diff --git a/Models/Leptoquarks/LeptoquarkModel.cc b/Models/Leptoquarks/LeptoquarkModel.cc
--- a/Models/Leptoquarks/LeptoquarkModel.cc
+++ b/Models/Leptoquarks/LeptoquarkModel.cc
@@ -1,213 +1,213 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the LeptoquarkModel class.
//
#include "LeptoquarkModel.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace Herwig;
using namespace ThePEG;
using namespace ThePEG::Helicity;
void LeptoquarkModel::doinit() {
addVertex(_theSLQSLQGVertex);
addVertex(_theSLQSLQGGVertex);
addVertex(_theSLQFFVertex);
- StandardModel::doinit();
+ BSMModel::doinit();
}
LeptoquarkModel::LeptoquarkModel() : _CouplFF(0.312), _leftcoup(1.0), _rightcoup(1.0), _rightcouptilde(1.0), _leftcoup1(1.0) , _leftcoup12(1.0), _rightcoup12(1.0), _leftcoup12t(1.0), _dleftcoup(1.0), _drightcoup(1.0), _drightcouptilde(1.0), _dleftcoup1(1.0) , _dleftcoup12(1.0), _drightcoup12(1.0), _dleftcoup12t(1.0), _derivscalef(500.0) {}
IBPtr LeptoquarkModel::clone() const {
return new_ptr(*this);
}
IBPtr LeptoquarkModel::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 LeptoquarkModel::persistentOutput(PersistentOStream & os) const {
os << _theSLQSLQGGVertex
<< _theSLQSLQGVertex
<< _theSLQFFVertex
<< _CouplFF
<< _leftcoup
<< _rightcoup
<< _leftcoup1
<< _rightcouptilde
<< _leftcoup12
<< _rightcoup12
<< _leftcoup12t
<< _dleftcoup
<< _drightcoup
<< _dleftcoup1
<< _drightcouptilde
<< _dleftcoup12
<< _drightcoup12
<< _dleftcoup12t
<< _derivscalef;
}
void LeptoquarkModel::persistentInput(PersistentIStream & is, int) {
is >> _theSLQSLQGGVertex
>> _theSLQSLQGVertex
>> _theSLQFFVertex
>> _CouplFF
>> _leftcoup
>> _rightcoup
>> _leftcoup1
>> _rightcouptilde
>> _leftcoup12
>> _rightcoup12
>> _leftcoup12t
>> _dleftcoup
>> _drightcoup
>> _dleftcoup1
>> _drightcouptilde
>> _dleftcoup12
>> _drightcoup12
>> _dleftcoup12t
>> _derivscalef;
}
ClassDescription<LeptoquarkModel> LeptoquarkModel::initLeptoquarkModel;
// Definition of the static class description member.
void LeptoquarkModel::Init() {
static Reference<LeptoquarkModel,ThePEG::Helicity::AbstractVSSVertex> interfaceVertexSLQSLQG
("Vertex/SLQSLQG",
"Reference to the scalar leptoquark-scalar leptoquark-gluon vertex",
&LeptoquarkModel::_theSLQSLQGVertex, false, false, true, false, false);
static Reference<LeptoquarkModel,ThePEG::Helicity::AbstractVVSSVertex> interfaceVertexSLQSLQGG
("Vertex/SLQSLQGG",
"Reference to the scalar leptoquark-scalar leptoquark-gluon-gluon vertex",
&LeptoquarkModel::_theSLQSLQGGVertex, false, false, true, false, false);
static Reference<LeptoquarkModel,ThePEG::Helicity::AbstractFFSVertex> interfaceVertexSLQFF
("Vertex/SLQFF",
"Reference to the scalar leptoquark-scalar-quark-lepton",
&LeptoquarkModel::_theSLQFFVertex, false, false, true, false, false);
static Parameter<LeptoquarkModel, double> interfaceLQCoupling
("LQCoupling",
"The overall Leptoquark Coupling",
&LeptoquarkModel::_CouplFF, 0.312, 0., 10.0,
false, false, Interface::limited);
static Parameter<LeptoquarkModel, double> interfacegLQ_L
("g_S0_L",
"The leptoquark S0 coupling LQ-lepton_left-quark_right",
&LeptoquarkModel::_leftcoup, 1.0, 0., 1.0,
false, false, Interface::limited);
static Parameter<LeptoquarkModel, double> interfacegLQ_R
("g_S0_R",
"The leptoquark S0 coupling LQ-lepton_right-quark_left",
&LeptoquarkModel::_rightcoup, 1.0, 0., 1.0,
false, false, Interface::limited);
static Parameter<LeptoquarkModel, double> interfacegLQ_Rt
("g_S0t_R",
"The leptoquark ~S0 coupling LQ-lepton_right-quark_left",
&LeptoquarkModel::_rightcouptilde, 1.0, 0., 1.0,
false, false, Interface::limited);
static Parameter<LeptoquarkModel, double> interfacegLQ_L1
("g_S1_L",
"The leptoquark S1 coupling LQ-lepton_left-quark_right",
&LeptoquarkModel::_leftcoup1, 1.0, 0., 1.0,
false, false, Interface::limited);
static Parameter<LeptoquarkModel, double> interfacegLQ12_L
("g_S12_L",
"The leptoquark S1/2 coupling LQ-lepton_left-quark_right",
&LeptoquarkModel::_leftcoup12, 1.0, 0., 1.0,
false, false, Interface::limited);
static Parameter<LeptoquarkModel, double> interfacegLQ12_R
("g_S12_R",
"The leptoquark S1/2 coupling LQ-lepton_right-quark_left",
&LeptoquarkModel::_rightcoup12, 1.0, 0., 1.0,
false, false, Interface::limited);
static Parameter<LeptoquarkModel, double> interfacegLQ12t_L
("g_S12t_L",
"The leptoquark ~S1/2 coupling LQ-lepton_left-quark_right",
&LeptoquarkModel::_leftcoup12t, 1.0, 0., 1.0,
false, false, Interface::limited);
static Parameter<LeptoquarkModel, double> interfacegdLQ_L
("g_dS0_L",
"The leptoquark dS0 coupling LQ-lepton_left-quark_right",
&LeptoquarkModel::_dleftcoup, 1.0, 0., 1.0,
false, false, Interface::limited);
static Parameter<LeptoquarkModel, double> interfacegdLQ_R
("g_dS0_R",
"The leptoquark dS0 coupling LQ-lepton_right-quark_left",
&LeptoquarkModel::_drightcoup, 1.0, 0., 1.0,
false, false, Interface::limited);
static Parameter<LeptoquarkModel, double> interfacegdLQ_Rt
("g_dS0t_R",
"The leptoquark ~dS0 coupling LQ-lepton_right-quark_left",
&LeptoquarkModel::_drightcouptilde, 1.0, 0., 1.0,
false, false, Interface::limited);
static Parameter<LeptoquarkModel, double> interfacegdLQ_L1
("g_dS1_L",
"The leptoquark dS1 coupling LQ-lepton_left-quark_right",
&LeptoquarkModel::_dleftcoup1, 1.0, 0., 1.0,
false, false, Interface::limited);
static Parameter<LeptoquarkModel, double> interfacegdLQ12_L
("g_dS12_L",
"The leptoquark dS1/2 coupling LQ-lepton_left-quark_right",
&LeptoquarkModel::_dleftcoup12, 1.0, 0., 1.0,
false, false, Interface::limited);
static Parameter<LeptoquarkModel, double> interfacegdLQ12_R
("g_dS12_R",
"The leptoquark dS1/2 coupling LQ-lepton_right-quark_left",
&LeptoquarkModel::_drightcoup12, 1.0, 0., 1.0,
false, false, Interface::limited);
static Parameter<LeptoquarkModel, double> interfacegdLQ12t_L
("g_dS12t_L",
"The leptoquark ~dS1/2 coupling LQ-lepton_left-quark_right",
&LeptoquarkModel::_dleftcoup12t, 1.0, 0., 1.0,
false, false, Interface::limited);
static Parameter<LeptoquarkModel, double> interfaceDerivativeScale
("derivscale",
"The suppression scale for the derivatively coupled leptoquarks",
&LeptoquarkModel::_derivscalef, 500.0, 0., 10000.0,
false, false, Interface::limited);
static ClassDocumentation<LeptoquarkModel> documentation
("There is no documentation for the LeptoquarkModel class");
}
diff --git a/Models/Leptoquarks/LeptoquarkModel.h b/Models/Leptoquarks/LeptoquarkModel.h
--- a/Models/Leptoquarks/LeptoquarkModel.h
+++ b/Models/Leptoquarks/LeptoquarkModel.h
@@ -1,356 +1,356 @@
// -*- C++ -*-
#ifndef HERWIG_LeptoquarkModel_H
#define HERWIG_LeptoquarkModel_H
//
// This is the declaration of the LeptoquarkModel class.
//
-#include "Herwig++/Models/StandardModel/StandardModel.h"
+#include "Herwig++/Models/General/BSMModel.h"
#include "ThePEG/Helicity/Vertex/AbstractVSSVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractVVSSVertex.h"
#include "LeptoquarkModel.fh"
namespace Herwig {
using namespace ThePEG;
using namespace ThePEG::Helicity;
/**
* Here is the documentation of the LeptoquarkModel class.
*
* @see \ref LeptoquarkModelInterfaces "The interfaces"
* defined for LeptoquarkModel.
*/
-class LeptoquarkModel: public StandardModel {
+class LeptoquarkModel: public BSMModel {
public:
/**
* The default constructor.
*/
LeptoquarkModel();
/** @name Vertices */
//@{
/**
* Pointer to the object handling S0S0barg vertex.
*/
tAbstractVSSVertexPtr vertexSLQSLQG() const {return _theSLQSLQGVertex;}
/**
* Pointer to the object handling the S0S0bargg vertex.
*/
tAbstractVVSSVertexPtr vertexSLQSLQGG() const {return _theSLQSLQGGVertex;}
/**
* Pointer to the object handling the S0ql vertex.
*/
tAbstractFFSVertexPtr vertexSLQFF() const {return _theSLQFFVertex;}
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();
/**
* Return the overall fermion coupling
*/
double cfermion() const {return _CouplFF;}
/**
* Return the coupling of the leptoquark to left-handed leptons + right-handed quarks (S0)
*/
double cleft() const {return _leftcoup;}
/**
* Return the coupling of the leptoquark to right-handed leptons + left-handed quarks (S0)
*/
double cright() const {return _rightcoup;}
/**
* Return the coupling of the leptoquark to left-handed leptons + right-handed quarks (S1 triplet)
*/
double cleft1() const {return _leftcoup1;}
/**
* Return the coupling of the leptoquark to right-handed leptons
* + left-handed quarks (~S0)
*/
double crighttilde() const {return _rightcouptilde;}
/**
* Return the coupling of the leptoquark to left-handed leptons + right-handed quarks (S1/2)
*/
double cleft12() const {return _leftcoup12;}
/**
* Return the coupling of the leptoquark to right-handed leptons + left-handed quarks (S1/2)
*/
double cright12() const {return _rightcoup12;}
/**
* Return the coupling of the leptoquark to left-handed leptons + right-handed quarks (S1/2)
*/
double cleft12tilde() const {return _leftcoup12t;}
/**
* Return the coupling of the leptoquark to left-handed leptons + right-handed quarks (S0)
*/
double dcleft() const {return _dleftcoup;}
/**
* Return the coupling of the leptoquark to right-handed leptons + left-handed quarks (dS0)
*/
double dcright() const {return _drightcoup;}
/**
* Return the coupling of the leptoquark to left-handed leptons + right-handed quarks (dS1 triplet)
*/
double dcleft1() const {return _dleftcoup1;}
/**
* Return the coupling of the leptoquark to right-handed leptons
* + left-handed quarks (~dS0)
*/
double dcrighttilde() const {return _drightcouptilde;}
/**
* Return the coupling of the leptoquark to left-handed leptons + right-handed quarks (dS1/2)
*/
double dcleft12() const {return _dleftcoup12;}
/**
* Return the coupling of the leptoquark to right-handed leptons + left-handed quarks (dS1/2)
*/
double dcright12() const {return _drightcoup12;}
/**
* Return the coupling of the leptoquark to left-handed leptons + right-handed quarks (dS1/2)
*/
double dcleft12tilde() const {return _dleftcoup12t;}
/**
* Suppression scale for derivatively coupled scalar leptoquarks
*/
double fscale() const {return _derivscalef;}
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();
//@}
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 static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<LeptoquarkModel> initLeptoquarkModel;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
LeptoquarkModel & operator=(const LeptoquarkModel &);
/**
* Pointer to the object handling the G to SLQ SLQ vertex.
*/
AbstractVSSVertexPtr _theSLQSLQGVertex;
/**
* Pointer to the object handling the GG to SLQ SLQ vertex.
*/
AbstractVVSSVertexPtr _theSLQSLQGGVertex;
/**
* Pointer to the object handling the SLQ to FF vertex.
*/
AbstractFFSVertexPtr _theSLQFFVertex;
/**
* Overall coupling to fermions
*/
double _CouplFF;
/**
* Overall coupling to left-handed leptons (S0)
*/
double _leftcoup;
/**
* Overall coupling to right-handed leptons (S0)
*/
double _rightcoup;
/**
* Overall coupling to left-handed leptons (~S0)
*/
double _rightcouptilde;
/**
* Overall coupling to left-handed leptons (S1 triplet)
*/
double _leftcoup1;
/**
* Overall coupling to left-handed leptons (S1/2)
*/
double _leftcoup12;
/**
* Overall coupling to right-handed leptons (S1/2)
*/
double _rightcoup12;
/**
* Overall coupling to left-handed leptons (~S1/2)
*/
double _leftcoup12t;
/**
* Overall coupling to left-handed leptons (dS0)
*/
double _dleftcoup;
/**
* Overall coupling to right-handed leptons (dS0)
*/
double _drightcoup;
/**
* Overall coupling to left-handed leptons (~dS0)
*/
double _drightcouptilde;
/**
* Overall coupling to left-handed leptons (dS1 triplet)
*/
double _dleftcoup1;
/**
* Overall coupling to left-handed leptons (dS1/2)
*/
double _dleftcoup12;
/**
* Overall coupling to right-handed leptons (dS1/2)
*/
double _drightcoup12;
/**
* Overall coupling to left-handed leptons (~dS1/2)
*/
double _dleftcoup12t;
/**
* Suppression scale for derivatively coupled scalar leptoquarks, f
*/
double _derivscalef;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of LeptoquarkModel. */
template <>
struct BaseClassTrait<Herwig::LeptoquarkModel,1> {
/** Typedef of the first base class of LeptoquarkModel. */
- typedef Herwig::StandardModel NthBase;
+ typedef Herwig::BSMModel NthBase;
};
/** This template specialization informs ThePEG about the name of
* the LeptoquarkModel class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::LeptoquarkModel>
: public ClassTraitsBase<Herwig::LeptoquarkModel> {
/** Return a platform-independent class name */
static string className() { return "Herwig::LeptoquarkModel"; }
/**
* The name of a file containing the dynamic library where the class
* LeptoquarkModel is implemented. It may also include several, space-separated,
* libraries if the class LeptoquarkModel 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 "HwLeptoquarkModel.so"; }
};
/** @endcond */
}
#endif /* HERWIG_LeptoquarkModel_H */
diff --git a/Models/RSModel/RSModel.cc b/Models/RSModel/RSModel.cc
--- a/Models/RSModel/RSModel.cc
+++ b/Models/RSModel/RSModel.cc
@@ -1,110 +1,110 @@
// -*- C++ -*-
//
// RSModel.cc is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the RSModel class.
//
#include "RSModel.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace Herwig;
using namespace ThePEG;
using namespace ThePEG::Helicity;
void RSModel::doinit() {
addVertex(FFGRVertex_);
addVertex(VVGRVertex_);
addVertex(SSGRVertex_);
addVertex(FFGGRVertex_);
addVertex(FFWGRVertex_);
addVertex(GGGGRVertex_);
addVertex(WWWGRVertex_);
- StandardModel::doinit();
+ BSMModel::doinit();
}
void RSModel::persistentOutput(PersistentOStream & os) const {
os << ounit(Lambda_pi_,GeV)
<< FFGRVertex_ << VVGRVertex_ << SSGRVertex_
<< FFGGRVertex_ << FFWGRVertex_
<< GGGGRVertex_ << WWWGRVertex_;
}
void RSModel::persistentInput(PersistentIStream & is, int) {
is >> iunit(Lambda_pi_,GeV)
>> FFGRVertex_ >> VVGRVertex_ >> SSGRVertex_
>> FFGGRVertex_ >> FFWGRVertex_
>> GGGGRVertex_ >> WWWGRVertex_;
}
ClassDescription<RSModel> RSModel::initRSModel;
// Definition of the static class description member.
void RSModel::Init() {
static Reference<RSModel,ThePEG::Helicity::AbstractFFTVertex> interfaceVertexFFGR
("Vertex/FFGR",
"Reference to the fermion-fermion-graviton vertex",
&RSModel::FFGRVertex_, false, false, true, false, false);
static Reference<RSModel,ThePEG::Helicity::AbstractVVTVertex> interfaceVertexVVGR
("Vertex/VVGR",
"Reference to the vector-vector-graviton vertex",
&RSModel::VVGRVertex_, false, false, true, false, false);
static Reference<RSModel,ThePEG::Helicity::AbstractSSTVertex> interfaceVertexSSGR
("Vertex/SSGR",
"Reference to the scalar-scalar-graviton vertex",
&RSModel::SSGRVertex_, false, false, true, false, false);
static Reference<RSModel,ThePEG::Helicity::AbstractFFVTVertex> interfaceVertexFFGGR
("Vertex/FFGGR",
"Reference to the fermion-antifermion-gluon graviton vertex",
&RSModel::FFGGRVertex_, false, false, true, false, false);
static Reference<RSModel,ThePEG::Helicity::AbstractFFVTVertex> interfaceVertexFFWGR
("Vertex/FFWGR",
"Reference to the fermion-antifermion-weak vector boson graviton vertex",
&RSModel::FFWGRVertex_, false, false, true, false, false);
static Reference<RSModel,ThePEG::Helicity::AbstractVVVTVertex> interfaceVertexGGGGR
("Vertex/GGGGR",
"Reference to the three gluon graviton vertex",
&RSModel::GGGGRVertex_, false, false, true, false, false);
static Reference<RSModel,ThePEG::Helicity::AbstractVVVTVertex> interfaceVertexWWWGR
("Vertex/WWWGR",
"Reference to the three weak vector boson graviton vertex",
&RSModel::WWWGRVertex_, false, false, true, false, false);
static Parameter<RSModel,Energy> interfaceLambda_pi
("Lambda_pi",
"The coupling of the graviton to matter",
&RSModel::Lambda_pi_, GeV, 10000*GeV, ZERO, 1.0e12*GeV,
false, false, false);
static ClassDocumentation<RSModel> documentation
("The RSModel class replaces the Standard Model class for the"
" RS model",
"The Randall-Sundrum model was constructed from \\cite{Randall:1999ee}.",
"%\\cite{Randall:1999ee}\n"
"\\bibitem{Randall:1999ee}\n"
" L.~Randall and R.~Sundrum,\n"
" ``A large mass hierarchy from a small extra dimension,''\n"
" Phys.\\ Rev.\\ Lett.\\ {\\bf 83}, 3370 (1999)\n"
" [arXiv:hep-ph/9905221].\n"
" %%CITATION = PRLTA,83,3370;%%\n"
);
}
diff --git a/Models/RSModel/RSModel.h b/Models/RSModel/RSModel.h
--- a/Models/RSModel/RSModel.h
+++ b/Models/RSModel/RSModel.h
@@ -1,237 +1,237 @@
// -*- C++ -*-
//
// RSModel.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_RSModel_H
#define HERWIG_RSModel_H
// This is the declaration of the RSModel class.
-#include "Herwig++/Models/StandardModel/StandardModel.h"
+#include "Herwig++/Models/General/BSMModel.h"
#include "ThePEG/Helicity/Vertex/AbstractFFTVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractVVTVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractSSTVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractFFVTVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractVVVTVertex.h"
#include "RSModel.fh"
namespace Herwig {
using namespace ThePEG;
using namespace ThePEG::Helicity;
/** \ingroup Models
*
* This is the class to be used instead of the Standard Model class for
* the Randell Sundrum model.
*
* @see \ref RSModelInterfaces "The interfaces"
* defined for RSModel.
* @see StandardModel
* @see StandardModelBase
*
*/
-class RSModel: public StandardModel {
+class RSModel: public BSMModel {
public:
/**
* The default constructor
*/
RSModel(): Lambda_pi_(10000*GeV) {
useMe();
}
/**
* Return the gravition coupling
*/
Energy lambda_pi() const {return Lambda_pi_;}
/** @name Vertices */
//@{
/**
* Pointer to the object handling the \f$G\to f\bar{f}\f$ vertex.
*/
tAbstractFFTVertexPtr vertexFFGR() const {return FFGRVertex_;}
/**
* Pointer to the object handling the \f$G\to VV\f$ vertex.
*/
tAbstractVVTVertexPtr vertexVVGR() const {return VVGRVertex_;}
/**
* Pointer to the object handling the \f$G\to SS\f$ vertex.
*/
tAbstractSSTVertexPtr vertexSSGR() const {return SSGRVertex_;}
/**
* Pointer to the object handling the \f$G\to f\bar{f}g\f$ vertex.
*/
tAbstractFFVTVertexPtr vertexFFGGR() const {return FFGGRVertex_;}
/**
* Pointer to the object handling the \f$G\to f\bar{f}W^\pm/Z^0/\gamma\f$ vertex.
*/
tAbstractFFVTVertexPtr vertexFFWGR() const {return FFWGRVertex_;}
/**
* Pointer to the object handling the \f$G\to W^+W^-Z^0/\gamma\f$ vertex.
*/
tAbstractVVVTVertexPtr vertexWWWGR() const {return WWWGRVertex_;}
/**
* Pointer to the object handling the \f$G\to ggg\f$ vertex.
*/
tAbstractVVVTVertexPtr vertexGGGGR() const {return GGGGRVertex_;}
//@}
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);
//@}
/**
* Standard Init function used to initialize the interfaces.
*/
static void Init();
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();
//@}
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
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.
*/
virtual IBPtr fullclone() const {return new_ptr(*this);}
//@}
private:
/**
* Describe a concrete class with persistent data.
*/
static ClassDescription<RSModel> initRSModel;
/**
* Private and non-existent assignment operator.
*/
RSModel & operator=(const RSModel &);
private:
/**
* Coupling of the graviton
*/
Energy Lambda_pi_;
/**
* Pointer to the object handling the \f$G\to f\bar{f}\f$ vertex.
*/
AbstractFFTVertexPtr FFGRVertex_;
/**
* Pointer to the object handling the \f$G\to VV\f$ vertex.
*/
AbstractVVTVertexPtr VVGRVertex_;
/**
* Pointer to the object handling the \f$G\to SS\f$ vertex.
*/
AbstractSSTVertexPtr SSGRVertex_;
/**
* Pointer to the object handling the \f$G\to f\bar{f}g\f$ vertex.
*/
AbstractFFVTVertexPtr FFGGRVertex_;
/**
* Pointer to the object handling the \f$G\to f\bar{f}W/Z^0\gamma\f$ vertex.
*/
AbstractFFVTVertexPtr FFWGRVertex_;
/**
* Pointer to the object handling the \f$G\to W^+W^-Z^0\gamma\f$ vertex.
*/
AbstractVVVTVertexPtr WWWGRVertex_;
/**
* Pointer to the object handling the \f$G\to ggg\f$ vertex.
*/
AbstractVVVTVertexPtr GGGGRVertex_;
};
}
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/**
* The following template specialization informs ThePEG about the
* base class of RSModel.
*/
template <>
struct BaseClassTrait<Herwig::RSModel,1> {
/** Typedef of the base class of RSModel. */
- typedef Herwig::StandardModel NthBase;
+ typedef Herwig::BSMModel NthBase;
};
/**
* The following template specialization informs ThePEG about the
* name of this class and the shared object where it is defined.
*/
template <>
struct ClassTraits<Herwig::RSModel>
: public ClassTraitsBase<Herwig::RSModel> {
/** Return the class name.*/
static string className() { return "Herwig::RSModel"; }
/**
* Return the name of the shared library to be loaded to get
* access to this class and every other class it uses
* (except the base class).
*/
static string library() { return "HwRSModel.so"; }
};
/** @endcond */
}
#endif /* HERWIG_RSModel_H */
diff --git a/Models/Susy/NMSSM/NMSSMGOGOHVertex.h b/Models/Susy/NMSSM/NMSSMGOGOHVertex.h
--- a/Models/Susy/NMSSM/NMSSMGOGOHVertex.h
+++ b/Models/Susy/NMSSM/NMSSMGOGOHVertex.h
@@ -1,219 +1,219 @@
// -*- C++ -*-
#ifndef HERWIG_NMSSMGOGOHVertex_H
#define HERWIG_NMSSMGOGOHVertex_H
//
// This is the declaration of the NMSSMGOGOHVertex class.
//
#include "ThePEG/Helicity/Vertex/Scalar/FFSVertex.h"
-#include "Herwig++/Models/StandardModel/StandardModel.h"
#include "Herwig++/Models/Susy/MixingMatrix.h"
namespace Herwig {
using namespace ThePEG;
+using namespace ThePEG::Helicity;
/**
* Here is the documentation of the NMSSMGOGOHVertex class.
*
* @see \ref NMSSMGOGOHVertexInterfaces "The interfaces"
* defined for NMSSMGOGOHVertex.
*/
class NMSSMGOGOHVertex: public FFSVertex {
public:
/**
* The default constructor.
*/
inline NMSSMGOGOHVertex();
/** @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();
/**
* Calculate the couplings. This method is virtual and must be implemented in
* classes inheriting from this.
* @param q2 The scale \f$q^2\f$ for the coupling at the vertex.
* @param part1 The ParticleData pointer for the first particle.
* @param part2 The ParticleData pointer for the second particle.
* @param part3 The ParticleData pointer for the third particle.
*/
virtual void setCoupling(Energy2 q2,tcPDPtr part1,tcPDPtr part2,
tcPDPtr part3);
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
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.
*/
virtual IBPtr fullclone() const {return new_ptr(*this);}
//@}
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
*/
virtual void doinit();
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<NMSSMGOGOHVertex> initNMSSMGOGOHVertex;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
NMSSMGOGOHVertex & operator=(const NMSSMGOGOHVertex &);
private:
/**
* The various mixing matrices and couplings
*/
//@{
/**
* The V chargino mixing matrix
*/
MixingMatrixPtr _mixV;
/**
* The U chargino mixing matrix
*/
MixingMatrixPtr _mixU;
/**
* The neutralino mixing matrix
*/
MixingMatrixPtr _mixN;
/**
* The CP-even neutral Higgs mixing matrix
*/
MixingMatrixPtr _mixS;
/**
* The CP-odd neutral Higgs mixing matrix
*/
MixingMatrixPtr _mixP;
/**
* The tri-linear \f$\lambda\f$ coupling
*/
double _lambda;
/**
* The tri-linear \f$\kappa\f$ coupling
*/
double _kappa;
/**
* \f$\sin\beta\f$
*/
double _sinb;
/**
* \f$\cos\beta\f$
*/
double _cosb;
/**
* \f$\sin\theta_W\f$
*/
double _sw;
/**
* \f$\cos\theta_W\f$
*/
double _cw;
/**
* The last \f$q^2\f$ the coupling was evaluated at.
*/
Energy2 _q2last;
/**
* The last value of the coupling
*/
double _couplast;
//@}
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of NMSSMGOGOHVertex. */
template <>
struct BaseClassTrait<Herwig::NMSSMGOGOHVertex,1> {
/** Typedef of the first base class of NMSSMGOGOHVertex. */
typedef ThePEG::Helicity::FFSVertex NthBase;
};
/** This template specialization informs ThePEG about the name of
* the NMSSMGOGOHVertex class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::NMSSMGOGOHVertex>
: public ClassTraitsBase<Herwig::NMSSMGOGOHVertex> {
/** Return a platform-independent class name */
static string className() { return "Herwig::NMSSMGOGOHVertex"; }
/**
* The name of a file containing the dynamic library where the class
* NMSSMGOGOHVertex is implemented. It may also include several, space-separated,
* libraries if the class NMSSMGOGOHVertex 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 "HwSusy.so HwNMSSM.so"; }
};
/** @endcond */
}
#endif /* HERWIG_NMSSMGOGOHVertex_H */
diff --git a/Models/Susy/NMSSM/NMSSMHHHVertex.h b/Models/Susy/NMSSM/NMSSMHHHVertex.h
--- a/Models/Susy/NMSSM/NMSSMHHHVertex.h
+++ b/Models/Susy/NMSSM/NMSSMHHHVertex.h
@@ -1,318 +1,317 @@
// -*- C++ -*-
#ifndef HERWIG_NMSSMHHHVertex_H
#define HERWIG_NMSSMHHHVertex_H
//
// This is the declaration of the NMSSMHHHVertex class.
//
#include "ThePEG/Helicity/Vertex/Scalar/SSSVertex.h"
-#include "ThePEG/StandardModel/StandardModelBase.h"
#include "Herwig++/Models/StandardModel/StandardModel.h"
#include "Herwig++/Models/Susy/MixingMatrix.h"
namespace Herwig {
using namespace ThePEG;
using namespace ThePEG::Helicity;
/** \ingroup Helicity
* The NMSSMHHHVertex defines the triple
* Higgs coupling in the NMSSM.
*
* @see \ref NMSSMHHHVertexInterfaces "The interfaces"
* defined for NMSSMHHHVertex.
*/
class NMSSMHHHVertex: public SSSVertex {
public:
/**
* The default constructor.
*/
NMSSMHHHVertex();
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();
/**
* Calculate the couplings. This method is virtual and must be implemented in
* classes inheriting from this.
* @param q2 The scale \f$q^2\f$ for the coupling at the vertex.
* @param part1 The ParticleData pointer for the first particle.
* @param part2 The ParticleData pointer for the second particle.
* @param part3 The ParticleData pointer for the third particle.
*/
virtual void setCoupling(Energy2 q2,tcPDPtr part1,tcPDPtr part2,
tcPDPtr part3);
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
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.
*/
virtual IBPtr fullclone() const {return new_ptr(*this);}
//@}
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
*/
virtual void doinit();
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<NMSSMHHHVertex> initNMSSMHHHVertex;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
NMSSMHHHVertex & operator=(const NMSSMHHHVertex &);
private:
/**
* The mixing matrix combination \f$U^S_{ai}U^S_{bj}U^S_{ck}\f$
* @param a The row element of the first CP-even mixing matrix
* @param b The column element of the first CP-even mixing matrix
* @param c The row element of the second CP-even mixing matrix
* @param i The column element of the second CP-even mixing matrix
* @param j The row element of the third CP-even mixing matrix
* @param k The column element of the third CP-even mixing matrix
*/
Complex usMix(unsigned int a, unsigned int b, unsigned int c,
unsigned int i, unsigned int j, unsigned int k) const {
return (*_mixS)(a,i)*(*_mixS)(b,j)*(*_mixS)(c,k) +
(*_mixS)(a,i)*(*_mixS)(c,j)*(*_mixS)(b,k) +
(*_mixS)(b,i)*(*_mixS)(a,j)*(*_mixS)(c,k) +
(*_mixS)(b,i)*(*_mixS)(c,j)*(*_mixS)(a,k) +
(*_mixS)(c,i)*(*_mixS)(a,j)*(*_mixS)(b,k) +
(*_mixS)(c,i)*(*_mixS)(b,j)*(*_mixS)(a,k);
}
/**
* The mixing matrix combination \f$U^S_{ai}U^P_{bj}U^P_{ck}\f$
* @param a The row element of the first CP-even mixing matrix
* @param b The column element of the first CP-even mixing matrix
* @param c The row element of the second CP-even mixing matrix
* @param i The column element of the second CP-even mixing matrix
* @param j The row element of the third CP-even mixing matrix
* @param k The column element of the third CP-even mixing matrix
*/
Complex upMix(unsigned int a, unsigned int b, unsigned int c,
unsigned int i, unsigned int j, unsigned int k) const {
return (*_mixS)(a,i)*((*_mixP)(b,j)*(*_mixP)(c,k) +
(*_mixP)(c,j)*(*_mixP)(b,k));
}
private:
/**
* A pointer to the object containing the SM parameters
*/
tcHwSMPtr _theSM;
/**
* The \f$W\f$ mass
*/
Energy _mw;
/**
* The \f$Z\f$ mass
*/
Energy _mz;
/**
* The \f$b\f$ mass
*/
Energy _mb;
/**
* The \f$t\f$ mass
*/
Energy _mt;
/**
* \f$\sin^2\theta_W\f$
*/
double _sw2;
/**
* \f$\cos\theta_W\f$
*/
double _cw;
/**
* The CP-even Higgs mixing matrix
*/
MixingMatrixPtr _mixS;
/**
* The CP-odd Higgs mixing matrix
*/
MixingMatrixPtr _mixP;
/**
* The coefficient of the trilinear \f$SH_2 H_1\f$ term in the superpotential
*/
double _lambda;
/**
* The coefficient of the cubic singlet term in the superpotential
*/
double _kappa;
/**
* The product \f$\lambda \langle S\rangle \f$.
*/
Energy _lambdaVEV;
/**
* The soft trilinear \f$SH_2 H_1\f$ coupling
*/
Energy _theAl;
/**
* The soft cubic \f$S\f$ coupling
*/
Energy _theAk;
/**
* \f$\sin\beta\f$
*/
double _sb;
/**
* \f$\cos\beta\f$
*/
double _cb;
/**
* \f$\sin2\beta\f$
*/
double _s2b;
/**
* \f$\cos2\beta\f$
*/
double _c2b;
/**
* The value of the VEV of the higgs that couples to the down-type sector
* \f$ g*sqrt(2)M_W\cos\beta \f$
*/
Energy _vu;
/**
* The value of the VEV of the higgs that couples to the up-type sector
* i.e. \f$ g*sqrt(2)M_W\sin\beta \f$
*/
Energy _vd;
/**
* The value of the VEV of the singlet higgs
*/
Energy _s;
/**
* The scale at which this vertex was last evaluated
*/
Energy2 _q2last;
/**
* The value of the EW coupling when it was last evaluated
*/
double _glast;
/**
* left 3rd generation scalar quark mass
*/
Energy _MQ3;
/**
* right scalar top mass
*/
Energy _MU2;
/**
* Whether or onto to include the radiative terms
*/
bool _includeRadiative;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of NMSSMHHHVertex. */
template <>
struct BaseClassTrait<Herwig::NMSSMHHHVertex,1> {
/** Typedef of the first base class of NMSSMHHHVertex. */
typedef Helicity::SSSVertex NthBase;
};
/** This template specialization informs ThePEG about the name of
* the NMSSMHHHVertex class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::NMSSMHHHVertex>
: public ClassTraitsBase<Herwig::NMSSMHHHVertex> {
/** Return a platform-independent class name */
static string className() { return "Herwig::NMSSMHHHVertex"; }
/**
* The name of a file containing the dynamic library where the class
* NMSSMHHHVertex is implemented. It may also include several, space-separated,
* libraries if the class NMSSMHHHVertex 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 "HwSusy.so HwNMSSM.so"; }
};
/** @endcond */
}
#endif /* HERWIG_NMSSMHHHVertex_H */
diff --git a/Models/Susy/NMSSM/NMSSMWHHVertex.h b/Models/Susy/NMSSM/NMSSMWHHVertex.h
--- a/Models/Susy/NMSSM/NMSSMWHHVertex.h
+++ b/Models/Susy/NMSSM/NMSSMWHHVertex.h
@@ -1,189 +1,189 @@
// -*- C++ -*-
#ifndef HERWIG_NMSSMWHHVertex_H
#define HERWIG_NMSSMWHHVertex_H
//
// This is the declaration of the NMSSMWHHVertex class.
//
#include "ThePEG/Helicity/Vertex/Scalar/VSSVertex.h"
-#include "Herwig++/Models/StandardModel/StandardModel.h"
#include "Herwig++/Models/Susy/MixingMatrix.h"
namespace Herwig {
using namespace ThePEG;
+using namespace ThePEG::Helicity;
/**
* The NMSSMWHHVertex class implements the coupling of an electroweak"
* gauge boson with two Higgs bosons in the NMSSM.
*
* @see \ref NMSSMWHHVertexInterfaces "The interfaces"
* defined for NMSSMWHHVertex.
*/
class NMSSMWHHVertex: public VSSVertex {
public:
/**
* The default constructor.
*/
NMSSMWHHVertex();
/** @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();
/**
* Calculate the couplings. This method is virtual and must be implemented in
* classes inheriting from this.
* @param q2 The scale \f$q^2\f$ for the coupling at the vertex.
* @param part1 The ParticleData pointer for the first particle.
* @param part2 The ParticleData pointer for the second particle.
* @param part3 The ParticleData pointer for the third particle.
*/
virtual void setCoupling(Energy2 q2,tcPDPtr part1,tcPDPtr part2,tcPDPtr part3);
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
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.
*/
virtual IBPtr fullclone() const {return new_ptr(*this);}
//@}
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
*/
virtual void doinit();
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<NMSSMWHHVertex> initNMSSMWHHVertex;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
NMSSMWHHVertex & operator=(const NMSSMWHHVertex &);
private:
/**
* \f$\sin\beta\f$
*/
double _sinb;
/**
* \f$\cos\beta\f$
*/
double _cosb;
/**
* \f$\sin\theta_W\f$
*/
double _sw;
/**
* \f$\cos\theta_W\f$
*/
double _cw;
/**
* The last \f$q^2\f$ the coupling was evaluated at.
*/
Energy2 _q2last;
/**
* The last value of the coupling
*/
double _couplast;
/**
* Mixing matrix for the CP-even Higgs bosons
*/
MixingMatrixPtr _mixS;
/**
* Mixing matrix for the CP-odd Higgs bosons
*/
MixingMatrixPtr _mixP;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of NMSSMWHHVertex. */
template <>
struct BaseClassTrait<Herwig::NMSSMWHHVertex,1> {
/** Typedef of the first base class of NMSSMWHHVertex. */
typedef ThePEG::Helicity::VSSVertex NthBase;
};
/** This template specialization informs ThePEG about the name of
* the NMSSMWHHVertex class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::NMSSMWHHVertex>
: public ClassTraitsBase<Herwig::NMSSMWHHVertex> {
/** Return a platform-independent class name */
static string className() { return "Herwig::NMSSMWHHVertex"; }
/**
* The name of a file containing the dynamic library where the class
* NMSSMWHHVertex is implemented. It may also include several, space-separated,
* libraries if the class NMSSMWHHVertex 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 "HwSusy.so HwNMSSM.so"; }
};
/** @endcond */
}
#endif /* HERWIG_NMSSMWHHVertex_H */
diff --git a/Models/Susy/NMSSM/NMSSMWWHVertex.h b/Models/Susy/NMSSM/NMSSMWWHVertex.h
--- a/Models/Susy/NMSSM/NMSSMWWHVertex.h
+++ b/Models/Susy/NMSSM/NMSSMWWHVertex.h
@@ -1,193 +1,193 @@
// -*- C++ -*-
#ifndef HERWIG_NMSSMWWHVertex_H
#define HERWIG_NMSSMWWHVertex_H
//
// This is the declaration of the NMSSMWWHVertex class.
//
#include "ThePEG/Helicity/Vertex/Scalar/VVSVertex.h"
#include "Herwig++/Models/Susy/MixingMatrix.h"
-#include "Herwig++/Models/StandardModel/StandardModel.h"
namespace Herwig {
using namespace ThePEG;
+using namespace ThePEG::Helicity;
/** \ingroup Helicity
*
* The NMSSMWWHVertex class is the implementation of the coupling of two electroweak
* gauge bosons to the Higgs bosons of the NMSSM. It inherits from VVSVertex and
* implements the setCoupling member.
*
* @see \ref NMSSMWWHVertexInterfaces "The interfaces"
* @see VVSVertex
* @see SMWWHVertex
* defined for NMSSMWWHVertex.
*/
class NMSSMWWHVertex: public VVSVertex {
public:
/**
* The default constructor.
*/
NMSSMWWHVertex();
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();
/**
* Calculate the couplings.
* @param q2 The scale \f$q^2\f$ for the coupling at the vertex.
* @param part1 The ParticleData pointer for the first particle.
* @param part2 The ParticleData pointer for the second particle.
* @param part3 The ParticleData pointer for the third particle.
*/
virtual void setCoupling(Energy2 q2,tcPDPtr part1,tcPDPtr part2,tcPDPtr part3);
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
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.
*/
virtual IBPtr fullclone() const {return new_ptr(*this);}
//@}
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
*/
virtual void doinit();
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<NMSSMWWHVertex> initNMSSMWWHVertex;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
NMSSMWWHVertex & operator=(const NMSSMWWHVertex &);
private:
/**
* Storage of the couplings.
*/
//@{
/**
* The last value of the electroweak coupling calculated.
*/
Complex _couplast;
/**
* The scale \f$q^2\f$ at which the coupling was last evaluated.
*/
Energy2 _q2last;
/**
* The mass of the \f$W\f$ boson.
*/
Energy _mw;
/**
* The factor for the \f$Z\f$ vertex.
*/
double _zfact;
/**
* \f$\sin\beta\f$
*/
double _sinb;
/**
* \f$\cos\beta\f$
*/
double _cosb;
/**
* Mixing matrix for the CP-even Higgs bosons
*/
MixingMatrixPtr _mixS;
//@}
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of NMSSMWWHVertex. */
template <>
struct BaseClassTrait<Herwig::NMSSMWWHVertex,1> {
/** Typedef of the first base class of NMSSMWWHVertex. */
typedef ThePEG::Helicity::VVSVertex NthBase;
};
/** This template specialization informs ThePEG about the name of
* the NMSSMWWHVertex class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::NMSSMWWHVertex>
: public ClassTraitsBase<Herwig::NMSSMWWHVertex> {
/** Return a platform-independent class name */
static string className() { return "Herwig::NMSSMWWHVertex"; }
/**
* The name of a file containing the dynamic library where the class
* NMSSMWWHVertex is implemented. It may also include several, space-separated,
* libraries if the class NMSSMWWHVertex 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 "HwSusy.so HwNMSSM.so"; }
};
/** @endcond */
}
#endif /* HERWIG_NMSSMWWHVertex_H */
diff --git a/Models/Susy/SusyBase.cc b/Models/Susy/SusyBase.cc
--- a/Models/Susy/SusyBase.cc
+++ b/Models/Susy/SusyBase.cc
@@ -1,905 +1,644 @@
// -*- C++ -*-
//
// SusyBase.cc is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the SusyBase class.
//
#include "SusyBase.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Repository/Repository.h"
#include "ThePEG/Utilities/StringUtils.h"
#include "ThePEG/Repository/CurrentGenerator.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/PDT/MassGenerator.h"
#include "ThePEG/PDT/WidthGenerator.h"
#include "ThePEG/PDT/DecayMode.h"
using namespace Herwig;
-SusyBase::SusyBase() : readFile_(false), topModesFromFile_(false),
- tolerance_(1e-6), MPlanck_(2.4e18*GeV),
+SusyBase::SusyBase() : readFile_(false), MPlanck_(2.4e18*GeV),
gravitino_(false),
tanBeta_(0), mu_(ZERO),
M1_(ZERO), M2_(ZERO), M3_(ZERO),
mH12_(ZERO),mH22_(ZERO),
meL_(ZERO),mmuL_(ZERO),mtauL_(ZERO),
meR_(ZERO),mmuR_(ZERO),mtauR_(ZERO),
mq1L_(ZERO),mq2L_(ZERO),mq3L_(ZERO),
mdR_(ZERO),muR_(ZERO),msR_(ZERO),
mcR_(ZERO),mbR_(ZERO),mtR_(ZERO),
gluinoPhase_(1.)
{}
IBPtr SusyBase::clone() const {
return new_ptr(*this);
}
IBPtr SusyBase::fullclone() const {
return new_ptr(*this);
}
void SusyBase::doinit() {
addVertex(WSFSFVertex_);
addVertex(NFSFVertex_);
addVertex(GFSFVertex_);
addVertex(HSFSFVertex_);
addVertex(CFSFVertex_);
addVertex(GSFSFVertex_);
addVertex(GGSQSQVertex_);
addVertex(GSGSGVertex_);
addVertex(NNZVertex_);
if(NNPVertex_) addVertex(NNPVertex_);
if(GNGVertex_) addVertex(GNGVertex_);
addVertex(CCZVertex_);
addVertex(CNWVertex_);
addVertex(GOGOHVertex_);
addVertex(WHHVertex_);
addVertex(NCTVertex_);
if(gravitino_) {
if(GVNHVertex_) addVertex(GVNHVertex_);
if(GVNVVertex_) addVertex(GVNVVertex_);
if(GVFSVertex_) addVertex(GVFSVertex_);
}
- StandardModel::doinit();
+ BSMModel::doinit();
}
void SusyBase::persistentOutput(PersistentOStream & os) const {
- os << readFile_ << topModesFromFile_ << gravitino_
+ os << readFile_ << gravitino_
<< NMix_ << UMix_ << VMix_ << WSFSFVertex_
<< NFSFVertex_ << GFSFVertex_ << HSFSFVertex_ << CFSFVertex_
<< GSFSFVertex_ << GGSQSQVertex_ << GSGSGVertex_
<< NNZVertex_ << NNPVertex_ << CCZVertex_ << CNWVertex_
<< GOGOHVertex_ << WHHVertex_ << GNGVertex_ << NCTVertex_
<< GVNHVertex_ << GVNVVertex_ << GVFSVertex_
<< tanBeta_ << ounit(mu_,GeV)
<< ounit(M1_,GeV) << ounit(M2_,GeV) << ounit(M3_,GeV)
<< ounit(mH12_,GeV2) << ounit(mH22_,GeV2)
<< ounit(meL_,GeV) << ounit(mmuL_,GeV) << ounit(mtauL_,GeV)
<< ounit(meR_,GeV) << ounit(mmuR_,GeV) << ounit(mtauR_,GeV)
<< ounit(mq1L_,GeV) << ounit(mq2L_,GeV) << ounit(mq3L_,GeV)
<< ounit(mdR_,GeV) << ounit(muR_,GeV) << ounit(msR_,GeV)
<< ounit(mcR_,GeV) << ounit(mbR_,GeV) << ounit(mtR_,GeV)
- << gluinoPhase_ << tolerance_ << ounit(MPlanck_,GeV);
+ << gluinoPhase_ << ounit(MPlanck_,GeV);
}
void SusyBase::persistentInput(PersistentIStream & is, int) {
- is >> readFile_ >> topModesFromFile_ >> gravitino_
+ is >> readFile_ >> gravitino_
>> NMix_ >> UMix_ >> VMix_ >> WSFSFVertex_
>> NFSFVertex_ >> GFSFVertex_ >> HSFSFVertex_ >> CFSFVertex_
>> GSFSFVertex_ >> GGSQSQVertex_ >> GSGSGVertex_
>> NNZVertex_ >> NNPVertex_ >> CCZVertex_ >> CNWVertex_
>> GOGOHVertex_ >> WHHVertex_ >> GNGVertex_ >> NCTVertex_
>> GVNHVertex_ >> GVNVVertex_ >> GVFSVertex_
>> tanBeta_ >> iunit(mu_,GeV)
>> iunit(M1_,GeV) >> iunit(M2_,GeV) >> iunit(M3_,GeV)
>> iunit(mH12_,GeV2) >> iunit(mH22_,GeV2)
>> iunit(meL_,GeV) >> iunit(mmuL_,GeV) >> iunit(mtauL_,GeV)
>> iunit(meR_,GeV) >> iunit(mmuR_,GeV) >> iunit(mtauR_,GeV)
>> iunit(mq1L_,GeV) >> iunit(mq2L_,GeV) >> iunit(mq3L_,GeV)
>> iunit(mdR_,GeV) >> iunit(muR_,GeV) >> iunit(msR_,GeV)
>> iunit(mcR_,GeV) >> iunit(mbR_,GeV) >> iunit(mtR_,GeV)
- >> gluinoPhase_ >> tolerance_ >> iunit(MPlanck_,GeV);
+ >> gluinoPhase_ >> iunit(MPlanck_,GeV);
}
ClassDescription<SusyBase> SusyBase::initSusyBase;
// Definition of the static class description member.
void SusyBase::Init() {
static ClassDocumentation<SusyBase> documentation
("This is the base class for any SUSY model.",
"SUSY spectrum files follow the Les Houches accord"
" \\cite{Skands:2003cj,Allanach:2008qq}.",
" %\\cite{Skands:2003cj}\n"
"\\bibitem{Skands:2003cj}\n"
" P.~Skands {\\it et al.},\n"
" ``SUSY Les Houches accord: Interfacing SUSY spectrum calculators, decay\n"
" %packages, and event generators,''\n"
" JHEP {\\bf 0407}, 036 (2004)\n"
" [arXiv:hep-ph/0311123].\n"
" %%CITATION = JHEPA,0407,036;%%\n"
"%\\cite{Allanach:2008qq}\n"
"\\bibitem{Allanach:2008qq}\n"
" B.~Allanach {\\it et al.},\n"
" %``SUSY Les Houches Accord 2,''\n"
" Comput.\\ Phys.\\ Commun.\\ {\\bf 180}, 8 (2009)\n"
" [arXiv:0801.0045 [hep-ph]].\n"
" %%CITATION = CPHCB,180,8;%%\n"
);
- static Switch<SusyBase,bool> interfaceTopModes
- ("TopModes",
- "Whether ro use the Herwig++ SM top decays or those from the SLHA file",
- &SusyBase::topModesFromFile_, false, false, false);
- static SwitchOption interfaceTopModesFile
- (interfaceTopModes,
- "File",
- "Take the modes from the files",
- true);
- static SwitchOption interfaceTopModesHerwig
- (interfaceTopModes,
- "Herwig",
- "Use the SM ones",
- false);
static Reference<SusyBase,Helicity::AbstractVSSVertex> interfaceVertexWSS
("Vertex/WSFSF",
"Reference to Susy W SF SF vertex",
&SusyBase::WSFSFVertex_, false, false, true, false);
static Reference<SusyBase,Helicity::AbstractFFSVertex> interfaceVertexNFSF
("Vertex/NFSF",
"Reference to the neutralino-fermion-sfermion vertex",
&SusyBase::NFSFVertex_, false, false, true, false);
static Reference<SusyBase,Helicity::AbstractFFSVertex> interfaceVertexGFSF
("Vertex/GFSF",
"Reference to the gluino-fermion-sfermion vertex",
&SusyBase::GFSFVertex_, false, false, true, false);
static Reference<SusyBase,Helicity::AbstractSSSVertex> interfaceVertexHSFSF
("Vertex/HSFSF",
"Reference to the Higgs-fermion-sfermion vertex",
&SusyBase::HSFSFVertex_, false, false, true, false);
static Reference<SusyBase,Helicity::AbstractFFSVertex> interfaceVertexCFSF
("Vertex/CFSF",
"Reference to the chargino-fermion-sfermion vertex",
&SusyBase::CFSFVertex_, false, false, true, false);
static Reference<SusyBase,Helicity::AbstractVSSVertex> interfaceVertexGSFSF
("Vertex/GSFSF",
"Reference to the gluon-sfermion-sfermion vertex",
&SusyBase::GSFSFVertex_, false, false, true, false);
static Reference<SusyBase,Helicity::AbstractVVSSVertex> interfaceVertexGGSS
("Vertex/GGSQSQ",
"Reference to the gluon-gluon-squark-squark vertex",
&SusyBase::GGSQSQVertex_, false, false, true, false);
static Reference<SusyBase,Helicity::AbstractFFVVertex> interfaceVertexGSGSG
("Vertex/GSGSG",
"Reference to the gluon-gluino-gluino vertex",
&SusyBase::GSGSGVertex_, false, false, true, false);
static Reference<SusyBase,Helicity::AbstractFFVVertex> interfaceVertexNNZ
("Vertex/NNZ",
"Reference to Z-~chi_i0-~chi_i0 vertex",
&SusyBase::NNZVertex_, false, false, true, false);
static Reference<SusyBase,Helicity::AbstractFFVVertex> interfaceVertexNNP
("Vertex/NNP",
"Reference to photon-~chi_i0-~chi_i0 vertex",
&SusyBase::NNPVertex_, false, false, true, true, false);
static Reference<SusyBase,Helicity::AbstractFFVVertex> interfaceVertexGNG
("Vertex/GNG",
"Reference to gluon-~chi_i0-gluino vertex",
&SusyBase::GNGVertex_, false, false, true, true, false);
static Reference<SusyBase,Helicity::AbstractFFVVertex> interfaceVertexCCZ
("Vertex/CCZ",
"Reference to ~chi_i+-~chi_i-Z vertex",
&SusyBase::CCZVertex_, false, false, true, false);
static Reference<SusyBase,Helicity::AbstractFFVVertex> interfaceVertexCNW
("Vertex/CNW",
"Reference to ~chi_i+-chi_i0-W vertex",
&SusyBase::CNWVertex_, false, false, true, false);
static Reference<SusyBase,Helicity::AbstractFFSVertex> interfaceVertexGOGOH
("Vertex/GOGOH",
"Reference to the gaugino-gaugino-higgs vertex",
&SusyBase::GOGOHVertex_, false, false, true, false);
static Reference<SusyBase,Helicity::AbstractVSSVertex> interfaceVertexWHH
("Vertex/SSWHH",
"Reference to Susy WHHVertex",
&SusyBase::WHHVertex_, false, false, true, false);
static Reference<SusyBase,AbstractFFSVertex> interfaceVertexNCT
("Vertex/NCT",
"Vertex for the flavour violating coupling of the top squark "
"to the neutralino and charm quark.",
&SusyBase::NCTVertex_, false, false, true, false, false);
static Reference<SusyBase,AbstractRFSVertex> interfaceVertexGVNH
("Vertex/GVNH",
"Vertex for the interfaction of the gravitino-neutralino"
" and Higgs bosons",
&SusyBase::GVNHVertex_, false, false, true, true, false);
static Reference<SusyBase,AbstractRFVVertex> interfaceVertexGVNV
("Vertex/GVNV",
"Vertex for the interfaction of the gravitino-neutralino"
" and vector bosons",
&SusyBase::GVNVVertex_, false, false, true, true, false);
static Reference<SusyBase,AbstractRFSVertex> interfaceVertexGVFS
("Vertex/GVFS",
"Vertex for the interfaction of the gravitino-fermion"
" and sfermion",
&SusyBase::GVFSVertex_, false, false, true, true, false);
- static Parameter<SusyBase,double> interfaceBRTolerance
- ("BRTolerance",
- "Tolerance for the sum of branching ratios to be difference from one.",
- &SusyBase::tolerance_, 1e-6, 1e-8, 0.01,
- false, false, Interface::limited);
-
static Parameter<SusyBase,Energy> interfaceMPlanck
("MPlanck",
"The Planck mass for GMSB models",
&SusyBase::MPlanck_, GeV, 2.4e18*GeV, 1.e16*GeV, 1.e20*GeV,
false, false, Interface::limited);
}
void SusyBase::readSetup(istream & is) {
string filename = dynamic_ptr_cast<istringstream*>(&is)->str();
if(readFile_)
throw SetupException()
<< "A second SLHA file " << filename << " has been opened."
<< "This is probably unintended and as it can cause crashes"
<< " and other unpredictable behaviour it is not allowed."
<< Exception::runerror;
CFileLineReader cfile;
cfile.open(filename);
if( !cfile ) throw SetupException()
<< "SusyBase::readSetup - An error occurred in opening the "
<< "spectrum file \"" << filename << "\". A SUSY model cannot be "
<< "run without this."
<< Exception::runerror;
useMe();
- //Before reading the spectrum/decay files the SM higgs
- //decay modes, mass and width generators need to be turned off.
- PDPtr h0 = getParticleData(ParticleID::h0);
- h0->widthGenerator(WidthGeneratorPtr());
- h0->massGenerator(MassGenPtr());
- h0->width(ZERO);
- DecaySet::const_iterator dit = h0->decayModes().begin();
- DecaySet::const_iterator dend = h0->decayModes().end();
- for( ; dit != dend; ++dit ) {
- const InterfaceBase * ifb =
- BaseRepository::FindInterface(*dit, "BranchingRatio");
- ifb->exec(**dit, "set", "0.0");
- ifb = BaseRepository::FindInterface(*dit, "OnOff");
- ifb->exec(**dit, "set", "Off");
- }
- // if taking the top modes from the file
- // delete the SM stuff
- if(topModesFromFile_) {
- PDPtr top = getParticleData(ParticleID::t);
- top->widthGenerator(WidthGeneratorPtr());
- top->massGenerator(MassGenPtr());
- DecaySet::const_iterator dit = top->decayModes().begin();
- DecaySet::const_iterator dend = top->decayModes().end();
- for( ; dit != dend; ++dit ) {
- const InterfaceBase * ifb =
- BaseRepository::FindInterface(*dit, "BranchingRatio");
- ifb->exec(**dit, "set", "0.0");
- ifb = BaseRepository::FindInterface(*dit, "OnOff");
- ifb->exec(**dit, "set", "Off");
- }
- }
// read first line and check if this is a Les Houches event file
cfile.readline();
bool lesHouches = cfile.find("<LesHouchesEvents");
bool reading = !lesHouches;
if(lesHouches) cfile.readline();
//function pointer for putting all characters to lower case.
int (*pf)(int) = tolower;
do {
string line = cfile.getline();
// check for start of slha block in SLHA files
if(lesHouches && !reading) {
if(line.find("<slha")==0) reading = true;
if(!cfile.readline()) break;
continue;
}
// ignore comment lines
if(line[0] == '#') {
if(!cfile.readline()) break;
continue;
}
// make everything lower case
transform(line.begin(), line.end(), line.begin(), pf);
// start of a block
if(line.find("block") == 0) {
string name = StringUtils::car(StringUtils::cdr(line), " #");
name = StringUtils::stripws(name);
// mixing matrix
if((name.find("mix") != string::npos &&
name.find("hmix") != 0)) {
unsigned int row(0),col(0);
MixingVector vals = readMatrix(cfile,row,col);
mixings_[name] = make_pair(make_pair(row,col),vals);
}
else if(name.find("au") == 0 || name.find("ad") == 0 ||
name.find("ae") == 0 ) {
string test = StringUtils::car(line, "#");
while (test.find("=")!= string::npos) {
test = StringUtils::cdr(test, "=");
}
istringstream is(test);
double scale;
is >> scale;
unsigned int row(0),col(0);
MixingVector vals = readMatrix(cfile,row,col);
if(scale>1e10) continue;
mixings_[name] = make_pair(make_pair(row,col),vals);
}
else if( name.find("info") == string::npos) {
readBlock(cfile,name,line);
}
else {
if(!cfile.readline()) break;
}
continue;
}
- // decays
- else if( line.find("decay") == 0 ) {
- readDecay(cfile, line);
- continue;
- }
else if( lesHouches && line.find("</slha") == 0 ) {
reading = false;
break;
}
if(!cfile.readline()) break;
}
while(true);
// extract the relevant parameters
extractParameters();
// create the mixing matrices we need
createMixingMatrices();
// set the masses, this has to be done after the
// mixing matrices have been created
resetRepositoryMasses();
// have now read the file
+ if(decayFile()=="") decayFile(filename);
readFile_=true;
}
void SusyBase::readBlock(CFileLineReader & cfile,string name,string linein) {
if(!cfile)
throw SetupException()
<< "SusyBase::readBlock() - The input stream is in a bad state"
<< Exception::runerror;
// storage or the parameters
string test = StringUtils::car(linein, "#");
ParamMap store;
bool set = true;
// special for the alpha block
if(name.find("alpha") == 0 ) {
double alpha;
cfile.readline();
string line = cfile.getline();
istringstream iss(line);
iss >> alpha;
store.insert(make_pair(1,alpha));
}
else {
// extract the scale from the block if present
if(test.find("=")!= string::npos) {
while(test.find("=")!=string::npos)
test= StringUtils::cdr(test,"=");
istringstream is(test);
double scale;
is >> scale;
// only store the lowest scale block
if(parameters_.find(name)!=parameters_.end()) {
set = scale < parameters_[name][-1];
}
else {
store.insert(make_pair(-1,scale));
}
}
while(cfile.readline()) {
string line = cfile.getline();
// skip comments
if(line[0] == '#') continue;
// reached the end
if( line[0] == 'B' || line[0] == 'b' ||
line[0] == 'D' || line[0] == 'd' ||
line[0] == '<' ) {
cfile.resetline();
break;
}
istringstream is(line);
long index;
double value;
is >> index >> value;
store.insert(make_pair(index, value));
}
}
if(set) parameters_[name]=store;
}
-void SusyBase::readDecay(CFileLineReader & cfile,
- string decay) const{
- map<string,ParamMap>::const_iterator fit=parameters_.find("mass");
- if(fit==parameters_.end())
- throw Exception() << "SusyBase::readDecay() "
- << "BLOCK MASS not found in input file"
- << "it must be before the decays so the kinematics can be checked"
- << Exception::runerror;
- ParamMap theMasses = fit->second;
- if(!cfile)
- throw SetupException()
- <<"SusyBase::readDecay - The input stream is in a bad state";
- // extract parent PDG code and width
- long parent(0);
- Energy width(ZERO);
- istringstream iss(decay);
- string dummy;
- iss >> dummy >> parent >> iunit(width, GeV);
- PDPtr inpart = getParticleData(parent);
- if(!topModesFromFile_&&abs(parent)==ParticleID::t) {
- cfile.readline();
- return;
- }
- if(!inpart) throw SetupException()
- << "SusyBase::readDecay() - "
- << "A ParticleData object with the PDG code "
- << parent << " does not exist. "
- << Exception::runerror;
- inpart->width(width);
- if( width > ZERO ) inpart->cTau(hbarc/width);
- inpart->widthCut(5.*width);
- ParamMap::iterator it = theMasses.find(abs(inpart->id()));
- Energy inMass = it!=theMasses.end() ? abs(it->second*GeV) : inpart->mass();
- string prefix("decaymode " + inpart->name() + "->");
- double brsum(0.);
- unsigned int nmode = 0;
- while(cfile.readline()) {
- string line = cfile.getline();
- // skip comments
- if(line[0] == '#') continue;
- // reached the end
- if( line[0] == 'B' || line[0] == 'b' ||
- line[0] == 'D' || line[0] == 'd' ||
- line[0] == '<' ) {
- cfile.resetline();
- break;
- }
- // read the mode
- // get the branching ratio and no of decay products
- istringstream is(line);
- double brat(0.);
- unsigned int nda(0),npr(0);
- is >> brat >> nda;
- vector<tcPDPtr> products,bosons;
- Energy mout(ZERO),moutnoWZ(ZERO);
- string tag = prefix;
- while( true ) {
- long t;
- is >> t;
- if( is.fail() ) break;
- if( t == abs(parent) ) {
- throw SetupException()
- << "An error occurred while read a decay of the "
- << inpart->PDGName() << ". One of its products has the same PDG code "
- << "as the parent particle. Please check the SLHA file.\n"
- << Exception::runerror;
- }
- tcPDPtr p = getParticleData(t);
- if( !p ) {
- throw SetupException()
- << "SusyBase::readDecay() - An unknown PDG code has been encounterd "
- << "while reading a decay mode. ID: " << t
- << Exception::runerror;
- }
- ++npr;
- tag += p->name() + ",";
- ParamMap::iterator it = theMasses.find(abs(p->id()));
- Energy mass = it!=theMasses.end() ? abs(it->second*GeV) : p->mass();
- mout += mass;
- if(abs(p->id())==ParticleID::Wplus||p->id()==ParticleID::Z0) {
- bosons.push_back(p);
- }
- else {
- products.push_back(p);
- moutnoWZ += mass;
- }
- }
- if( npr != nda ) {
- throw SetupException()
- << "SusyBase::readDecay - While reading a decay of the "
- << inpart->PDGName() << " from an SLHA file, an inconsistency "
- << "between the number of decay products and the value in "
- << "the 'NDA' column was found. Please check if the spectrum "
- << "file is correct.\n"
- << Exception::warning;
- }
- if( npr > 1 ) {
- tag.replace(tag.size() - 1, 1, ";");
- // normal option
- if(mout<=inMass) {
- inpart->stable(false);
- brsum += brat;
- createDecayMode(tag, brat);
- }
- // no possible off-shell gauge bosons throw it away
- else if(bosons.empty() || bosons.size()>2 ||
- moutnoWZ>=inMass) {
- cerr << "SusyBase::readDecay() "
- << "The decay " << tag << " cannot proceed for on-shell "
- << "particles, skipping it.\n";
- }
- else {
- Energy maxMass = inMass - moutnoWZ;
- string newTag = prefix;
- for(unsigned int ix=0;ix<products.size();++ix)
- newTag += products[ix]->name() + ",";
- if(bosons.size()==1) {
- cerr << "SusyBase::readDecay() "
- << "The decay " << tag << " cannot proceed for on-shell\n"
- << "particles, replacing gauge boson with its decay products\n";
- vector<pair<double,string> > modes =
- createWZDecayModes(newTag,brat,bosons[0],maxMass);
- for(unsigned int ix=0;ix<modes.size();++ix) {
- modes[ix].second.replace(modes[ix].second.size() - 1, 1, ";");
- createDecayMode(modes[ix].second,modes[ix].first);
- brsum += modes[ix].first;
- }
- }
- else if(bosons.size()==2) {
- bool identical = bosons[0]->id()==bosons[1]->id();
- if(maxMass>bosons[0]->mass()&&maxMass>bosons[1]->mass()) {
- cerr << "SusyBase::readDecay() "
- << "The decay " << tag << " cannot proceed for on-shell\n"
- << "particles, replacing one of the gauge bosons"
- << " with its decay products\n";
- unsigned int imax = identical ? 1 : 2;
- if(imax==2) brat *= 0.5;
- for(unsigned int ix=0;ix<imax;++ix) {
- string newTag2 = newTag+bosons[ix]->name()+',';
- unsigned int iother = ix==0 ? 1 : 0;
- vector<pair<double,string> > modes =
- createWZDecayModes(newTag2,brat,bosons[iother],maxMass);
- for(unsigned int ix=0;ix<modes.size();++ix) {
- modes[ix].second.replace(modes[ix].second.size() - 1, 1, ";");
- createDecayMode(modes[ix].second,modes[ix].first);
- brsum += modes[ix].first;
- }
- }
- }
- else {
- cerr << "SusyBase::readDecay() "
- << "The decay " << tag << " cannot proceed for on-shell\n"
- << "particles, and has too many off-shell gauge bosons,"
- << " skipping it.\n";
- }
- }
- else {
- cerr << "SusyBase::readDecay() "
- << "The decay " << tag << " cannot proceed for on-shell\n"
- << "particles, and has too many outgoing gauge bosons skipping it.\n";
- }
- }
- }
- }
- if( abs(brsum - 1.) > tolerance_ && nmode!=0 ) {
- cerr << "Warning: The total branching ratio for " << inpart->PDGName()
- << " from the spectrum file does not sum to 1. The branching fractions"
- << " will be rescaled.\n";
- cerr << setprecision(13) << abs(brsum - 1.) << "\n";
- }
-}
-
const MixingVector
SusyBase::readMatrix(CFileLineReader & cfile,
unsigned int & row, unsigned int & col) {
if(!cfile)
throw SetupException()
<< "SusyBase::readMatrix() - The input stream is in a bad state."
<< Exception::runerror;
unsigned int rowmax(0), colmax(0);
MixingVector values;
while(cfile.readline()) {
string line = cfile.getline();
// skip comments
if(line[0] == '#') continue;
// reached the end
if( line[0] == 'B' || line[0] == 'b' ||
line[0] == 'D' || line[0] == 'd' ||
line[0] == '<' ) {
cfile.resetline();
break;
}
istringstream is(line);
unsigned int index1, index2;
double real(0.), imag(0.);
is >> index1 >> index2 >> real >> imag;
values.push_back(MixingElement(index1,index2,Complex(real, imag)));
if(index1 > rowmax) rowmax = index1;
if(index2 > colmax) colmax = index2;
}
col=colmax;
row=rowmax;
return values;
}
-void SusyBase::createDecayMode(string tag, double brat) const {
- ostringstream cmd;
- cmd << tag << string(" ")
- << setprecision(13) << brat << string(" 1 /Herwig/Decays/Mambo");
- Repository::exec(cmd.str(), cerr);
-}
-
void SusyBase::createMixingMatrix(MixingMatrixPtr & matrix,
string name, const MixingVector & values,
MatrixSize size) {
matrix = new_ptr(MixingMatrix(size.first,size.second));
for(unsigned int ix=0; ix < values.size(); ++ix)
(*matrix)(values[ix].row-1,values[ix].col-1) = values[ix].value;
if(name == "nmix") {
vector<long> ids(4);
ids[0] = 1000022; ids[1] = 1000023;
ids[2] = 1000025; ids[3] = 1000035;
matrix->setIds(ids);
}
else if(name == "nmnmix") {
vector<long> ids(5);
ids[0] = 1000022; ids[1] = 1000023;
ids[2] = 1000025; ids[3] = 1000035;
ids[4] = 1000045;
matrix->setIds(ids);
}
else if(name == "umix") {
vector<long> ids(2);
ids[0] = 1000024; ids[1] = 1000037;
matrix->setIds(ids);
}
else if(name == "vmix") {
vector<long> ids(2);
ids[0] = 1000024; ids[1] = 1000037;
matrix->setIds(ids);
}
else if(name == "stopmix") {
vector<long> ids(2);
ids[0] = 1000006; ids[1] = 2000006;
matrix->setIds(ids);
}
else if(name == "sbotmix") {
vector<long> ids(2);
ids[0] = 1000005; ids[1] = 2000005;
matrix->setIds(ids);
}
else if(name == "staumix") {
vector<long> ids(2);
ids[0] = 1000015; ids[1] = 2000015;
matrix->setIds(ids);
}
else if(name == "nmhmix") {
vector<long> ids(3);
ids[0] = 25; ids[1] = 35; ids[2] = 45;
matrix->setIds(ids);
}
else if(name == "nmamix") {
vector<long> ids(2);
ids[0] = 36; ids[1] = 46;
matrix->setIds(ids);
}
else
throw SetupException() << "Cannot find correct title for mixing matrix "
<< name << Exception::runerror;
}
void SusyBase::resetRepositoryMasses() {
map<string,ParamMap>::const_iterator fit=parameters_.find("mass");
if(fit==parameters_.end())
throw Exception() << "BLOCK MASS not found in input file"
<< " can't set masses of SUSY particles"
<< Exception::runerror;
ParamMap theMasses = fit->second;
for(ParamMap::iterator it = theMasses.begin(); it != theMasses.end();
++it) {
long id = it->first;
double mass = it->second;
//a negative mass requires an adjustment to the
//associated mixing matrix by a factor of i
if(mass < 0.0) adjustMixingMatrix(id);
PDPtr part = getParticleData(id);
if(!part) throw SetupException()
<< "SusyBase::resetRepositoryMasses() - Particle with PDG code " << id
<< " not found." << Exception::warning;
//Find interface nominal mass interface
const InterfaceBase * ifb = BaseRepository::FindInterface(part, "NominalMass");
ostringstream os;
os << abs(it->second);
ifb->exec(*part, "set", os.str());
// switch on gravitino interactions?
gravitino_ |= id== ParticleID::SUSY_Gravitino;
}
theMasses.clear();
}
void SusyBase::adjustMixingMatrix(long id) {
//get correct mixing matrix
switch(id) {
case 1000021 :
gluinoPhase_ = Complex(0.,1.);
break;
case 1000022 :
case 1000023 :
case 1000025 :
case 1000035 :
case 1000045 :
if(NMix_)
NMix_->adjustPhase(id);
else
throw SetupException() << "SusyBase::adjustMixingMatrix - "
<< "The neutralino mixing matrix pointer "
<< "is null!" << Exception::runerror;
break;
case 1000024 :
case 1000037 :
if(UMix_)
UMix_->adjustPhase(id);
else
throw SetupException() << "SusyBase::adjustMixingMatrix - "
<< "The U-Type chargino mixing matrix pointer "
<< "is null!" << Exception::runerror;
if(VMix_)
VMix_->adjustPhase(id);
else
throw SetupException() << "SusyBase::adjustMixingMatrix - "
<< "The V-Type chargino mixing matrix pointer "
<< "is null!" << Exception::runerror;
break;
default :
throw SetupException()
<< "SusyBase::adjustMixingMatrix - Trying to adjust mixing matrix "
<< "phase for a particle that does not have a mixing matrix "
<< "associated with it. " << id << " must have a negative mass in "
<< "the spectrum file, this should only occur for particles that mix."
<< Exception::runerror;
}
}
void SusyBase::createMixingMatrices() {
map<string,pair<MatrixSize, MixingVector > >::const_iterator it;
for(it=mixings_.begin();it!=mixings_.end();++it) {
string name=it->first;
// create the gaugino mixing matrices
if(name == "nmix" || name == "nmnmix" ){
createMixingMatrix(NMix_,name,it->second.second,it->second.first);
}
else if (name == "umix" ) {
createMixingMatrix(UMix_,name,it->second.second,it->second.first);
}
else if (name == "vmix") {
createMixingMatrix(VMix_,name,it->second.second,it->second.first);
}
}
}
void SusyBase::extractParameters(bool checkmodel) {
map<string,ParamMap>::const_iterator pit;
ParamMap::const_iterator it;
// try and get tan beta from extpar first
pit=parameters_.find("extpar");
// extract tan beta
tanBeta_ = -1.;
if(pit!=parameters_.end()) {
it = pit->second.find(25);
if(it!=pit->second.end()) tanBeta_ = it->second;
}
// otherwise from minpar
if(tanBeta_<0.) {
pit=parameters_.find("minpar");
if(pit!=parameters_.end()) {
it = pit->second.find(3);
if(it!=pit->second.end()) tanBeta_ = it->second;
}
}
if(tanBeta_<0.)
throw Exception() << "Can't find tan beta in BLOCK MINPAR"
<< " or BLOCK EXTPAR " << Exception::runerror;
// extract parameters from hmix
pit=parameters_.find("hmix");
if(pit==parameters_.end()) {
cerr << "BLOCK HMIX not found setting mu to zero\n";
mu_=ZERO;
}
else {
it = pit->second.find(1);
if(it==pit->second.end()) {
cerr << "mu not found in BLOCK HMIX setting to zero\n";
}
else {
mu_=it->second*GeV;
}
}
pit = parameters_.find("msoft");
if( pit == parameters_.end() )
throw Exception() << "BLOCK MSOFT not found in "
<< "SusyBase::extractParameters()"
<< Exception::runerror;
M1_ = pit->second.find(1 )->second*GeV;
M2_ = pit->second.find(2 )->second*GeV;
M3_ = pit->second.find(3 )->second*GeV;
mH12_ = pit->second.find(21)->second*GeV2;
mH22_ = pit->second.find(22)->second*GeV2;
meL_ = pit->second.find(31)->second*GeV;
mmuL_ = pit->second.find(32)->second*GeV;
mtauL_ = pit->second.find(33)->second*GeV;
meR_ = pit->second.find(34)->second*GeV;
mmuR_ = pit->second.find(35)->second*GeV;
mtauR_ = pit->second.find(36)->second*GeV;
mq1L_ = pit->second.find(41)->second*GeV;
mq2L_ = pit->second.find(42)->second*GeV;
mq3L_ = pit->second.find(43)->second*GeV;
muR_ = pit->second.find(44)->second*GeV;
mcR_ = pit->second.find(45)->second*GeV;
mtR_ = pit->second.find(46)->second*GeV;
mdR_ = pit->second.find(47)->second*GeV;
msR_ = pit->second.find(48)->second*GeV;
mbR_ = pit->second.find(49)->second*GeV;
if(checkmodel) {
throw Exception() << "The SusyBase class should not be used as a "
<< "Model class, use one of the models which inherit"
<< " from it" << Exception::runerror;
}
}
-
-vector<pair<double,string> >
-SusyBase::createWZDecayModes(string tag, double brat,
- tcPDPtr boson, Energy maxMass) const {
- vector<pair<double,string> > modes;
- double sum(0.);
- for(DecaySet::const_iterator dit=boson->decayModes().begin();
- dit!=boson->decayModes().end();++dit) {
- tcDMPtr mode = *dit;
- if(!mode->on()) continue;
- string extra;
- Energy outMass(ZERO);
- for(ParticleMSet::const_iterator pit=mode->products().begin();
- pit!=mode->products().end();++pit) {
- extra += (**pit).name() + ",";
- outMass += (**pit).mass();
- }
- if(outMass<maxMass) {
- sum += mode->brat();
- modes.push_back(make_pair(mode->brat(),tag+extra));
- }
- }
- for(unsigned int ix=0;ix<modes.size();++ix)
- modes[ix].first *= brat/sum;
- return modes;
-}
diff --git a/Models/Susy/SusyBase.h b/Models/Susy/SusyBase.h
--- a/Models/Susy/SusyBase.h
+++ b/Models/Susy/SusyBase.h
@@ -1,724 +1,688 @@
// -*- C++ -*-
//
// SusyBase.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_SusyBase_H
#define HERWIG_SusyBase_H
//
// This is the declaration of the SusyBase class.
//
-#include "Herwig++/Models/StandardModel/StandardModel.h"
+#include "Herwig++/Models/General/BSMModel.h"
#include "MixingMatrix.h"
#include "ThePEG/Utilities/CFileLineReader.h"
#include "ThePEG/Helicity/Vertex/AbstractVSSVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractSSSVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractVVSSVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractRFSVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractRFVVertex.h"
#include "SusyBase.fh"
namespace Herwig {
using namespace ThePEG;
/*@name Some convenient typedefs. */
//@{
/**
* Map to hold key, parameter pairs.
*/
typedef map<long, double> ParamMap;
//@}
/** \ingroup Models
* This class is designed to be a base class for SUSY models. There is
* an interface to set the name of the spectrum file to read in
* the necessary parameters for a SUSY model.
*
* @see \ref SusyBaseInterfaces "The interfaces"
* defined for SusyBase.
* @see StandardModel
*/
-class SusyBase: public StandardModel {
+class SusyBase: public BSMModel {
public:
/**
* The default constructor.
*/
SusyBase();
public:
/** @name Access functions. */
//@{
/**
* Value of \f$\tan\beta\f$.
*/
double tanBeta() const { return tanBeta_; }
/**
* Value of \f$\mu\f$ parameter.
*/
Energy muParameter() const { return mu_; }
/**
* The neutralino mixing matrix
*/
const MixingMatrixPtr & neutralinoMix() const {
return NMix_;
}
/**
* The U-type chargino mixing matrix
*/
const MixingMatrixPtr & charginoUMix() const {
return UMix_;
}
/**
* The V-type chargino mixing matrix
*/
const MixingMatrixPtr & charginoVMix() const {
return VMix_;
}
/**
* The phase for gluino vertices
*/
const Complex & gluinoPhase() const {return gluinoPhase_;}
//@}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
public:
/**
* Soft breaking parameters
*/
//@{
/**
* The bilinear breaking mass term for the bino
*/
const Energy & M1() const {return M1_;}
/**
* The bilinear breaking mass term for the wino
*/
const Energy & M2() const {return M2_;}
/**
* The bilinear breaking mass term for the gluinos
*/
const Energy & M3() const {return M3_;}
/**
* The soft breaking mass squared for \f$H_1\f$
*/
const Energy2 & Mh12() const {return mH12_;}
/**
* The soft breaking mass squared for \f$H_2\f$
*/
const Energy2 & Mh22() const {return mH22_;}
/**
* Soft breaking mass for the first generation lepton doublet
*/
const Energy & MeL() const {return meL_;}
/**
* Soft breaking mass for the second generation lepton doublet
*/
const Energy & MmuL() const {return mmuL_;}
/**
* Soft breaking mass for the third generation lepton doublet
*/
const Energy & MtauL() const {return mtauL_;}
/**
* Soft breaking mass for the first generation lepton singlet
*/
const Energy & MeR() const {return meR_;}
/**
* Soft breaking mass for the second generation lepton singlet
*/
const Energy & MmuR() const {return mmuR_;}
/**
* Soft breaking mass for the third generation lepton singlet
*/
const Energy & MtauR() const {return mtauR_;}
/**
* Soft breaking mass for the first generation quark doublet
*/
const Energy & Mq1L() const {return mq1L_;}
/**
* Soft breaking mass for the second generation quark doublet
*/
const Energy & Mq2L() const {return mq2L_;}
/**
* Soft breaking mass for the third generation quark doublet
*/
const Energy & Mq3L() const {return mq3L_;}
/**
* Soft breaking mass for the down singlet
*/
const Energy & MdR() const {return mdR_;}
/**
* Soft breaking mass for the up singlet
*/
const Energy & MuR() const {return muR_;}
/**
* Soft breaking mass for the strange singlet
*/
const Energy & MsR() const {return msR_;}
/**
* Soft breaking mass for the charm singlet
*/
const Energy & McR() const {return mcR_;}
/**
* Soft breaking mass for the bottom singlet
*/
const Energy & MbR() const {return mbR_;}
/**
* Soft breaking mass for the top singlet
*/
const Energy & MtR() const {return mtR_;}
//@}
/**
* Planck mass
*/
const Energy & MPlanck() const {return MPlanck_;}
protected:
/**
* Function to read information from a setup file.
* @param is istream object to read file.
*/
virtual void readSetup(istream & is);
private:
/**@name Functions to help file read-in. */
//@{
/**
* Read block from LHA file
* @param ifs input stream containg data
* @param name The name of the block
* @param line The line defining the block
*/
void readBlock(CFileLineReader & ifs,string name,string line);
/**
* Function to read mixing matrix from LHA file
* @param ifs input stream containg data
* @param row Number of rows
* @param col Number of columns
*/
const MixingVector readMatrix(CFileLineReader & ifs, unsigned int & row,
unsigned int & col);
- /**
- * Read decaymodes from LHA file
- * @param ifs input stream containg data
- * @param decay string containing name of parent and value of total width
- */
- void readDecay(CFileLineReader & ifs, string decay) const;
-
- /**
- * Create a DecayMode object in the repository
- * @param tag The tag identifying the decay mode including the prefix
- * 'decaymode'
- * @param brat Branching ratio of this mode
- */
- void createDecayMode(string tag, double brat) const;
-
- /**
- * Create a DecayMode object in the repository
- * @param tag The tag identifying the decay mode including the prefix
- * 'decaymode'
- * @param brat Branching ratio of this mode
- */
- vector<pair<double,string> > createWZDecayModes(string tag, double brat,
- tcPDPtr boson,
- Energy maxMass) const;
-
protected:
/**
* Create the mixing matrices for the model
*/
virtual void createMixingMatrices();
/**
* Extract the parameters from the input blocks
*/
virtual void extractParameters(bool checkmodel=true);
/**
* Create a object MixingMatrix in the repository
* @param matrix Pointer to the mixing matrix
* @param name Name of the mixing matrix, i.e. nmix, umix...
* @param values Value of each entry in the matrix
* @param size The size of the matrix
*/
void createMixingMatrix(MixingMatrixPtr & matrix, string name,
const MixingVector & values,
MatrixSize size);
/**
* Reset masses in the repository to values read from LHA file.
*/
void resetRepositoryMasses();
/**
* Adjust row of Mixing Matrix if a negative mass occurs in LHA file
* @param id The PDG code of the particle with a negative mass
*/
virtual void adjustMixingMatrix(long id);
//@}
/**
* Access to the mixings and parameters for the inheriting classes
*/
//@{
/**
* Parameter blocks
*/
const map<string,ParamMap> & parameters() const {
return parameters_;
}
/**
* Mixing blocks
*/
const map<string,pair<MatrixSize,MixingVector> > & mixings() const {
return mixings_;
}
//@}
/**
* Reset neutralino mixing matrix
*/
void neutralinoMix(MixingMatrixPtr nm) { NMix_ = nm; }
/**
* Reset the U-type chargino mixing matrix
*/
void charginoUMix(MixingMatrixPtr um) { UMix_ = um; }
/**
* Reset the V-type chargino mixing matrix
*/
void charginoVMix(MixingMatrixPtr vm) { VMix_ = vm; }
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;
//@}
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();
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<SusyBase> initSusyBase;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
SusyBase & operator=(const SusyBase &);
private:
/**
* Whether or not the SLHA fiel has been read
*/
bool readFile_;
/**
- * Whether or not to replace the top decay modes with those from
- * the SLHA files
- */
- bool topModesFromFile_;
-
- /**
- * Tolerance for branching ratios
- */
- double tolerance_;
-
- /**
* Planck mass needed in GMSB models
*/
Energy MPlanck_;
/**
* Whether or not to include gravitino interactions
*/
bool gravitino_;
/*
* Storage of the parameters.
*/
//@{
/**
* Parameter blocks
*/
map<string,ParamMap> parameters_;
/**
* Mixing blocks
*/
map<string,pair<MatrixSize, MixingVector> > mixings_;
/**
* \f$\tan\beta\f$
*/
double tanBeta_;
/**
* \f$\mu\f$
*/
Energy mu_;
//@}
/**
* Soft breaking parameters
*/
//@{
/**
* The bilinear breaking mass term for the bino
*/
Energy M1_;
/**
* The bilinear breaking mass term for the wino
*/
Energy M2_;
/**
* The bilinear breaking mass term for the gluinos
*/
Energy M3_;
/**
* The soft breaking mass squared for \f$H_1\f$
*/
Energy2 mH12_;
/**
* The soft breaking mass squared for \f$H_2\f$
*/
Energy2 mH22_;
/**
* Soft breaking mass for the first generation lepton doublet
*/
Energy meL_;
/**
* Soft breaking mass for the second generation lepton doublet
*/
Energy mmuL_;
/**
* Soft breaking mass for the third generation lepton doublet
*/
Energy mtauL_;
/**
* Soft breaking mass for the first generation lepton singlet
*/
Energy meR_;
/**
* Soft breaking mass for the second generation lepton singlet
*/
Energy mmuR_;
/**
* Soft breaking mass for the third generation lepton singlet
*/
Energy mtauR_;
/**
* Soft breaking mass for the first generation quark doublet
*/
Energy mq1L_;
/**
* Soft breaking mass for the second generation quark doublet
*/
Energy mq2L_;
/**
* Soft breaking mass for the third generation quark doublet
*/
Energy mq3L_;
/**
* Soft breaking mass for the down singlet
*/
Energy mdR_;
/**
* Soft breaking mass for the up singlet
*/
Energy muR_;
/**
* Soft breaking mass for the strange singlet
*/
Energy msR_;
/**
* Soft breaking mass for the charm singlet
*/
Energy mcR_;
/**
* Soft breaking mass for the bottom singlet
*/
Energy mbR_;
/**
* Soft breaking mass for the top singlet
*/
Energy mtR_;
//@}
/**
* Phase for the gluino
*/
Complex gluinoPhase_;
/**
* Neutralino and Chargino mixing matrices
*/
//@{
/**
* Store pointers to the gaugino mixing matrices
*/
//@{
/**
* The neutralino mixing matrix
*/
MixingMatrixPtr NMix_;
/**
* The \f$U\f$ mixing matrix for the charginos
*/
MixingMatrixPtr UMix_;
/**
* The \f$V\f$ mixing matrix for the charginos
*/
MixingMatrixPtr VMix_;
//@}
/**@name Vertex pointers. */
//@{
/**
* Pointer to the gauge boson sfermion-sfermion vertex
*/
AbstractVSSVertexPtr WSFSFVertex_;
/**
* Pointer to the neutralino-fermion-sfermion vertex
*/
AbstractFFSVertexPtr NFSFVertex_;
/**
* Pointer to the gluino-fermion-sfermion coupling
*/
AbstractFFSVertexPtr GFSFVertex_;
/**
* Pointer to the Higgs-sfermion-sfermion vertex
*/
AbstractSSSVertexPtr HSFSFVertex_;
/**
* Pointer to the \f$\tilde{\chi}^+\f$-fermion-sfermion vertex
*/
AbstractFFSVertexPtr CFSFVertex_;
/**
* Pointer to the gluon-sfermion-sfermion vertex
*/
AbstractVSSVertexPtr GSFSFVertex_;
/**
* Pointer to the gluon-gluon-squark-squark vertex;
*/
AbstractVVSSVertexPtr GGSQSQVertex_;
/**
* Pointer to the gluon-gluino-gluino vertex
*/
AbstractFFVVertexPtr GSGSGVertex_;
/**
* Pointer to the gluino-neutralino-gluon vertex
*/
AbstractFFVVertexPtr GNGVertex_;
/**
* Pointer to the neutralino-neutralino-Z vertex
*/
AbstractFFVVertexPtr NNZVertex_;
/**
* Pointer to the neutralino-neutralino-photon vertex
*/
AbstractFFVVertexPtr NNPVertex_;
/**
* Pointer to the vertex chargino-chargino-Z vertex
*/
AbstractFFVVertexPtr CCZVertex_;
/**
* Pointer to the vertex chargino-neutralino-Z vertex
*/
AbstractFFVVertexPtr CNWVertex_;
/**
* Pointer to the vertex gaugino-gaugino-higgs vertex
*/
AbstractFFSVertexPtr GOGOHVertex_;
/**
* Pointer to the vertex for a gauge boson and higgs
*/
AbstractVSSVertexPtr WHHVertex_;
/**
* Pointer to the vertex for flavour changing stop decay
*/
AbstractFFSVertexPtr NCTVertex_;
/**
* Pointer to the vertex for gravitino-neutralino vector boson
*/
AbstractRFVVertexPtr GVNVVertex_;
/**
* Pointer to the vertex for gravitino-neutralino Higgs boson
*/
AbstractRFSVertexPtr GVNHVertex_;
/**
* Pointer to the vertex for gravitino-fermion sfermion
*/
AbstractRFSVertexPtr GVFSVertex_;
//@}
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of SusyBase. */
template <>
struct BaseClassTrait<Herwig::SusyBase,1> {
/** Typedef of the first base class of SusyBase. */
- typedef Herwig::StandardModel NthBase;
+ typedef Herwig::BSMModel NthBase;
};
/** This template specialization informs ThePEG about the name of
* the SusyBase class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::SusyBase>
: public ClassTraitsBase<Herwig::SusyBase> {
/** Return a platform-independent class name */
static string className() { return "Herwig::SusyBase"; }
/**
* The name of a file containing the dynamic library where the class
* SusyBase is implemented. It may also include several, space-separated,
* libraries if the class SusyBase 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 "HwSusy.so"; }
};
/** @endcond */
}
#endif /* HERWIG_SusyBase_H */
diff --git a/Models/Transplanckian/METRP2to2.cc b/Models/Transplanckian/METRP2to2.cc
--- a/Models/Transplanckian/METRP2to2.cc
+++ b/Models/Transplanckian/METRP2to2.cc
@@ -1,351 +1,355 @@
// -*- C++ -*-
//
// METRP2to2.cc is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2009-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the METRP2to2 class.
//
#include "METRP2to2.h"
#include "ThePEG/Utilities/SimplePhaseSpace.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/MatrixElement/Tree2toNDiagram.h"
#include "Herwig++/Models/StandardModel/StandardModel.h"
#include "ThePEG/Handlers/StandardXComb.h"
#include "ThePEG/Cuts/Cuts.h"
#include "Herwig++/Utilities/Interpolator.h"
#include <fstream>
+namespace Herwig {
+
+// Need to init the interpolator instance here
+HERWIG_INTERPOLATOR_CLASSDESC(double,double)
+
+}
+
using namespace Herwig;
METRP2to2::METRP2to2()
: _maxflavour(2), _ndim(6), _planckmass(1500.0*GeV), _process(0) {
massOption(vector<unsigned int>(2,0));
}
void METRP2to2::doinit() {
HwMEBase::doinit();
setup_interpolator();
}
void METRP2to2::rebind(const TranslationMap & trans) {
_interpol = trans.translate(_interpol);
HwMEBase::rebind(trans);
}
IVector METRP2to2::getReferences() {
IVector ret = HwMEBase::getReferences();
ret.push_back(_interpol);
return ret;
}
void METRP2to2::setup_interpolator() {
static const double xmatrix1[103] = {0.0, 0.02, 0.10, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3., 3.2, 3.4, 3.6, 3.8, 4., 4.2, 4.4, 4.6, 4.8, 5.0, 5.2, 5.4, 5.6, 5.8, 6., 6.2, 6.4, 6.6, 6.8, 7., 7.2, 7.4, 7.6, 7.8, 8., 8.2, 8.4, 8.6, 8.8, 9., 9.2, 9.4, 9.6, 9.8, 10., 10.2, 10.4, 10.6, 10.8, 11., 11.2, 11.4, 11.6, 11.8, 12., 12.2, 12.4, 12.6, 12.8, 13., 13.2, 13.4, 13.6, 13.8, 14., 14.2, 14.4, 14.6, 14.8, 15., 15.2, 15.4, 15.6, 15.8, 16., 16.2, 16.4, 16.6, 16.8, 17., 17.2, 17.4, 17.6, 17.8, 18., 18.2, 18.4, 18.6, 18.8, 19., 19.2, 19.4, 19.6, 19.8, 20.0 };
static const double xmatrix2[102] = {0.02, 0.10, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3., 3.2, 3.4, 3.6, 3.8, 4., 4.2, 4.4, 4.6, 4.8, 5., 5.2, 5.4, 5.6, 5.8, 6., 6.2, 6.4, 6.6, 6.8, 7., 7.2, 7.4, 7.6, 7.8, 8., 8.2, 8.4, 8.6, 8.8, 9., 9.2, 9.4, 9.6, 9.8, 10., 10.2, 10.4, 10.6, 10.8, 11., 11.2, 11.4, 11.6, 11.8, 12., 12.2, 12.4, 12.6, 12.8, 13., 13.2, 13.4, 13.6, 13.8, 14., 14.2, 14.4, 14.6, 14.8, 15., 15.2, 15.4, 15.6, 15.8, 16., 16.2, 16.4, 16.6, 16.8, 17., 17.2, 17.4, 17.6, 17.8, 18., 18.2, 18.4, 18.6, 18.8, 19., 19.2, 19.4, 19.6, 19.8, 20.0 };
static const double datamatrix2[102] = {4.32048, 2.74662, 2.090560, 1.457590, 1.113050, 0.885216, 0.720795, 0.597404, 0.501483, 0.425543, 0.364668, 0.315299, 0.274983, 0.241792, 0.214466, 0.191698, 0.172689, 0.156841, 0.143329, 0.131919, 0.122174, 0.113656, 0.106339, 0.099869, 0.094101, 0.089013, 0.084378, 0.080185, 0.076376, 0.072856, 0.069622, 0.066624, 0.063844, 0.061242, 0.058820, 0.056561, 0.054417, 0.052433, 0.05055, 0.048772, 0.047129, 0.045546, 0.044056, 0.042673, 0.041328, 0.040078, 0.038895, 0.037749, 0.036688, 0.035666, 0.034687, 0.033771, 0.032883, 0.032041, 0.031239, 0.030467, 0.029731, 0.029025, 0.028350, 0.027698, 0.027075, 0.026479, 0.025896, 0.025347, 0.024812, 0.024291, 0.023804, 0.023318, 0.022854, 0.022416, 0.021974, 0.021561, 0.021160, 0.020761, 0.020390, 0.020021, 0.019662, 0.019325, 0.01898, 0.018662, 0.018351, 0.018041, 0.017747, 0.017459, 0.017177, 0.016906, 0.016641, 0.016384, 0.016132, 0.015889, 0.015651, 0.015418, 0.015196, 0.014973, 0.014759, 0.014553, 0.014345, 0.014149, 0.013956, 0.013762, 0.013582, 0.013399};
static const double datamatrix3[103] = {1.33947, 1.32238, 1.25505, 1.17491, 1.02696, 0.89463, 0.77688, 0.67270, 0.58105, 0.50095, 0.43143, 0.37156, 0.32046, 0.27726, 0.24113, 0.21126, 0.18684, 0.16707, 0.15118, 0.13843, 0.12815, 0.11974, 0.11271, 0.10670, 0.10141, 0.09663, 0.09224, 0.08814, 0.08427, 0.08061, 0.07715, 0.07387, 0.07077, 0.06785, 0.06511, 0.06254, 0.06014, 0.05790, 0.05582, 0.05388, 0.05207, 0.05038, 0.04879, 0.04731, 0.04591, 0.04459, 0.04334, 0.04216, 0.04103, 0.03996, 0.03894, 0.03796, 0.03702, 0.03612, 0.03526, 0.03443, 0.03363, 0.03287, 0.03214, 0.03143, 0.03075, 0.03010, 0.02947, 0.02887, 0.02829, 0.02773, 0.02719, 0.02666, 0.02616, 0.02567, 0.0250, 0.02475, 0.02431, 0.02388, 0.02347, 0.02306, 0.02267, 0.02230, 0.02193, 0.02157, 0.02123, 0.02089, 0.02056, 0.02025, 0.01994, 0.01964, 0.01934, 0.01906, 0.018, 0.01851, 0.01825, 0.01799, 0.01774, 0.01750, 0.01726, 0.01703, 0.01680, 0.01658, 0.01637, 0.01616, 0.01595, 0.01575, 0.01555};
static const double datamatrix4[103] = {0.88623, 0.885845, 0.879328, 0.86361, 0.81617, 0.75594, 0.68928, 0.62036, 0.55206, 0.48641, 0.42484, 0.36832, 0.31749, 0.27273, 0.23419, 0.20185, 0.17547, 0.15464, 0.13871, 0.12685, 0.11813, 0.11162, 0.10654, 0.10229, 0.09844, 0.09475, 0.09107, 0.08738, 0.08368, 0.08000, 0.07641, 0.07295, 0.06967, 0.06660, 0.06377, 0.06118, 0.05883, 0.05670, 0.05476, 0.05300, 0.05138, 0.04989, 0.04849, 0.04716, 0.04590, 0.04469, 0.04353, 0.04240, 0.04131, 0.04026, 0.03924, 0.03826, 0.037, 0.03642, 0.03556, 0.03473, 0.03394, 0.03319, 0.03247, 0.03178, 0.03112, 0.03049, 0.02988, 0.02930, 0.02873, 0.02819, 0.02767, 0.02716, 0.02667, 0.02619, 0.02573, 0.02529, 0.02486, 0.02444, 0.02403, 0.02364, 0.02326, 0.02289, 0.02253, 0.02218, 0.02184, 0.02152, 0.02120, 0.02089, 0.02058, 0.02029, 0.02000, 0.01972, 0.01944, 0.01918, 0.01892, 0.01866, 0.01841, 0.01816, 0.01792, 0.01769, 0.01746, 0.01724, 0.01702, 0.01681, 0.01660, 0.01639, 0.01619 };
static const double datamatrix5[103] = {0.744596, 0.744489, 0.742327, 0.73584, 0.71183, 0.67590, 0.63118, 0.58053, 0.52645, 0.47109, 0.41628, 0.36351, 0.31401, 0.26878, 0.22857, 0.19396, 0.16533, 0.14280, 0.12611, 0.11459, 0.10713, 0.10244, 0.09934, 0.09690, 0.09453, 0.09189, 0.08887, 0.08548, 0.08180, 0.07796, 0.07410, 0.07035, 0.06681, 0.06358, 0.06068, 0.05815, 0.05595, 0.05405, 0.05240, 0.05094, 0.04962, 0.04838, 0.04720, 0.04604, 0.04489, 0.04375, 0.04262, 0.04150, 0.04040, 0.03934, 0.03831, 0.03733, 0.03639, 0.03551, 0.03469, 0.03391, 0.03317, 0.03247, 0.03181, 0.03118, 0.03057, 0.02998, 0.02941, 0.02886, 0.02832, 0.02779, 0.02728, 0.02678, 0.02630, 0.02583, 0.02538, 0.02494, 0.02452, 0.02412, 0.02373, 0.02335, 0.02299, 0.02264, 0.02230, 0.02197, 0.02165, 0.02134, 0.02104, 0.02074, 0.02045, 0.02016, 0.01989, 0.01961, 0.01935, 0.01909, 0.01883, 0.01858, 0.01834, 0.01810, 0.01787, 0.01764, 0.01742, 0.01721, 0.01699, 0.01679, 0.01659, 0.01639, 0.01620};
static const double datamatrix6[103] = {0.67759, 0.677074, 0.675686, 0.67139, 0.65466, 0.62818, 0.59351, 0.55242, 0.50671, 0.45815, 0.40837, 0.35888, 0.31104, 0.26603, 0.22490, 0.18855, 0.15777, 0.13319, 0.11510, 0.10322, 0.09650, 0.09333, 0.09206, 0.09137, 0.09045, 0.08888, 0.08652, 0.08343, 0.07977, 0.07574, 0.07157, 0.06747, 0.06364, 0.06020, 0.05725, 0.05479, 0.05281, 0.05121, 0.04991, 0.04880, 0.04779, 0.04680, 0.04580, 0.04475, 0.04364, 0.04249, 0.04130, 0.04012, 0.03895, 0.03783, 0.03677, 0.03579, 0.03488, 0.03405, 0.03330, 0.03261, 0.03197, 0.03137, 0.03080, 0.03025, 0.02970, 0.02917, 0.02863, 0.02811, 0.02758, 0.02707, 0.02657, 0.02608, 0.02560, 0.02515, 0.02471, 0.02430, 0.02390, 0.02351, 0.02314, 0.02279, 0.02244, 0.02211, 0.02178, 0.02146, 0.02115, 0.02084, 0.02054, 0.02025, 0.01996, 0.01968, 0.01941, 0.01915, 0.01890, 0.01865, 0.01841, 0.01818, 0.01795, 0.01773, 0.01751, 0.01730, 0.01710, 0.01690, 0.01670, 0.01650, 0.01631, 0.01612, 0.01593 };
const double * datamatrix = 0;
const double * xmatrix = 0;
int xsize = 0;
//assign the appropriate tabulated points for the number of extra dimensions
switch ( _ndim ) {
case 2 : datamatrix = datamatrix2; xmatrix = xmatrix2; xsize = 102; break;
case 3 : datamatrix = datamatrix3; xmatrix = xmatrix1; xsize = 103; break;
case 4 : datamatrix = datamatrix4; xmatrix = xmatrix1; xsize = 103; break;
case 5 : datamatrix = datamatrix5; xmatrix = xmatrix1; xsize = 103; break;
case 6 : datamatrix = datamatrix6; xmatrix = xmatrix1; xsize = 103; break;
default : assert(false);
}
_interpol = make_InterpolatorPtr(xsize, datamatrix, 1.0, xmatrix, 1.0, 1);
}
IBPtr METRP2to2::clone() const {
return new_ptr(*this);
}
IBPtr METRP2to2::fullclone() const {
return new_ptr(*this);
}
void METRP2to2::persistentOutput(PersistentOStream & os) const {
os << _interpol << _maxflavour << _process << _ndim << ounit(_planckmass,GeV);
}
void METRP2to2::persistentInput(PersistentIStream & is, int) {
is >> _interpol >> _maxflavour >> _process >> _ndim >> iunit(_planckmass,GeV);
}
Energy2 METRP2to2::scale() const {
Energy2 invbcsq = 1 / sqr(bccalc(sHat()));
return ( -tHat() > invbcsq ) ? invbcsq : -tHat();
}
// Definition of the static class description member.
ClassDescription<METRP2to2> METRP2to2::initMETRP2to2;
-// Need to init the interpolator instance here
-HERWIG_INTERPOLATOR_CLASSDESC(double,double)
-
void METRP2to2::Init() {
static ClassDocumentation<METRP2to2> documentation
("The METRP2to2 class implements the transplanckian 2->2 processes in hadron-hadron"
" collisions");
static Parameter<METRP2to2,unsigned int> interfaceMaximumFlavour
("MaximumFlavour",
"The maximum flavour of the quarks in the process",
&METRP2to2::_maxflavour, 2, 1, 5,
false, false, Interface::limited);
static Parameter<METRP2to2, Energy> interfacePlanckMass
("PlanckMass",
"The Planck Mass",
&METRP2to2::_planckmass, GeV, 2000.0*GeV, 200.0*GeV, 200000.0*GeV,
false, false, Interface::limited);
static Parameter<METRP2to2, unsigned int> interfaceNumberExtraDimensions
("NumberExtraDimensions",
"The number of extra dimensions to consider",
&METRP2to2::_ndim, 6, 2, 6,
false, false, Interface::limited);
static Switch<METRP2to2,unsigned int> interfaceProcess
("Process",
"Which subprocesses to include",
&METRP2to2::_process, 0, false, false);
static SwitchOption interfaceProcessAll
(interfaceProcess,
"All",
"Include all subprocesses",
0);
static SwitchOption interfaceProcess1
(interfaceProcess,
"gg2gg",
"Include only gg->gg subprocesses",
1);
static SwitchOption interfaceProcessqgqg
(interfaceProcess,
"qg2qg",
"Include only q g -> q g processes",
4);
static SwitchOption interfaceProcessqbargqbarg
(interfaceProcess,
"qbarg2qbarg",
"Include only qbar g -> qbar g processes",
5);
static SwitchOption interfaceProcessqqqq
(interfaceProcess,
"qq2qq",
"Include only q q -> q q processes",
6);
static SwitchOption interfaceProcessqbarqbarqbarqbar
(interfaceProcess,
"qbarqbar2qbarqbar",
"Include only qbar qbar -> qbar qbar processes",
7);
static SwitchOption interfaceProcessqqbarqqbar
(interfaceProcess,
"qqbar2qqbar",
"Include only q qbar -> q qbar processes",
8);
}
Selector<MEBase::DiagramIndex>
METRP2to2::diagrams(const DiagramVector & diags) const {
// select the diagram, this is easy for us as we have already done it
Selector<DiagramIndex> sel;
for ( DiagramIndex i = 0; i < diags.size(); ++i ) {
sel.insert(1.0, i);
}
return sel;
}
void METRP2to2::getDiagrams() const {
// get the particle data objects
PDPtr gluon = getParticleData(ParticleID::g);
PDPtr trpon = getParticleData(39);
vector<PDPtr> quark,antiquark;
for(int ix=1;ix<=int(_maxflavour);++ix) {
quark.push_back( getParticleData( ix));
antiquark.push_back(getParticleData(-ix));
}
// gg-> gg subprocess
if(_process==0||_process==1) {
add(new_ptr((Tree2toNDiagram(3),gluon,trpon,gluon,
1,gluon, 2,gluon,-2)));
}
// processes involving one quark line
for(unsigned int ix=0;ix<_maxflavour;++ix) {
// q g -> q g subprocesses
if(_process==0||_process==4) {
add(new_ptr((Tree2toNDiagram(3),quark[ix],trpon,gluon,
1,quark[ix],2,gluon,-12)));
}
// qbar g -> qbar g subprocesses
if(_process==0||_process==5) {
add(new_ptr((Tree2toNDiagram(3),antiquark[ix],trpon,gluon,
1,antiquark[ix],2,gluon,-15)));
}
// processes involving two quark lines
for(unsigned int iy=0;iy<_maxflavour;++iy) {
// q q -> q q subprocesses
if(_process==0||_process==6) {
// t-channel
add(new_ptr((Tree2toNDiagram(3),quark[ix],trpon,quark[iy],
1,quark[ix],2,quark[iy],-16)));
//exchange for identical quarks
if(ix==iy)
add(new_ptr((Tree2toNDiagram(3),quark[ix],trpon,quark[iy],
2,quark[ix],1,quark[iy],-17)));
}
// qbar qbar -> qbar qbar subprocesses
if(_process==0||_process==7) {
// t-channel
add(new_ptr((Tree2toNDiagram(3),antiquark[ix],trpon,antiquark[iy],
1,antiquark[ix],2,antiquark[iy],-18)));
//exchange for identical quarks
if(ix==iy)
add(new_ptr((Tree2toNDiagram(3),antiquark[ix],trpon,antiquark[iy],
2,antiquark[ix],1,antiquark[iy],-19)));
}
// q qbar -> q qbar
if(_process==0||_process==8) {
add(new_ptr((Tree2toNDiagram(3),quark[ix],trpon,antiquark[iy],
1,quark[ix],2,antiquark[iy],-21)));
}
}
}
}
Selector<const ColourLines *>
METRP2to2::colourGeometries(tcDiagPtr diag) const {
// colour lines for gg to gg
static const ColourLines cgggg("1 4, -1 -4, 3 5, -3 -5");
// colour lines for q g to q g
static const ColourLines cqgqg("1 4, 3 5, -3 -5");
// colour lines for qbar g -> qbar g
static const ColourLines cqbgqbg("-1 -4, -3 -5, 3 5");
// colour lines for q q -> q q
static const ColourLines cqqqq("1 4,3 5");
// colour lines for qbar qbar -> qbar qbar
static const ColourLines cqbqbqbqb("-1 -4,-3 -5");
// colour lines for q qbar -> q qbar
static const ColourLines cqqbqqb("1 4,-3 -5");
// select the colour flow (as already picked just insert answer)
Selector<const ColourLines *> sel;
switch(abs(diag->id())) {
//gg -> gg
case 2:
sel.insert(1.0, &cgggg);
break;
// q g -> q g subprocess
case 12:
sel.insert(1.0, &cqgqg);
break;
// qbar g -> qbar g subprocess
case 15:
sel.insert(1.0, &cqbgqbg);
break;
// q q -> q q subprocess
case 16: case 17:
sel.insert(1.0, &cqqqq);
break;
// qbar qbar -> qbar qbar subprocess
case 18: case 19:
sel.insert(1.0, &cqbqbqbqb);
break;
// q qbar -> q qbar subprocess
case 21:
sel.insert(1.0, &cqqbqqb);
break;
}
return sel;
}
double METRP2to2::me2() const {
double me(0.), me_exch(0.);
double fac1(1.), fac2(0.);
if ( mePartonData()[0]->id() == mePartonData()[1]->id() ) {
if ( mePartonData()[0]->id()>0 ) {
me_exch = - A_ny(sHat(),uHat());
fac1 = 2./3.;
fac2 = 1./6.;
}
else if ( mePartonData()[0]->id() == ParticleID::g ) {
me_exch = A_ny(sHat(),uHat());
fac1 = 7./8.;
fac2 = 1./16.;
}
}
me = A_ny(sHat(),tHat());
return fac1 * sqr(me) + fac2 * sqr(me+me_exch);
}
// Calculate the constant b_c which depends on s_hat and the number of
// extra dimensions
InvEnergy METRP2to2::bccalc(Energy2 s) const {
static const double fourpi = 4.0*Constants::pi;
return 1/_planckmass * sqrt(fourpi) *
pow( (0.5 * s / (sqr(_planckmass) * fourpi)) * Math::gamma(_ndim/2.0),
1.0/_ndim);
}
//Calculation of the matrix element squared using the function F_n(y)
double METRP2to2::A_ny(Energy2 s, Energy2 t) const {
InvEnergy bc = bccalc(s);
double fny = 0;
double y = bc * sqrt(-t);
if ( y >= 20.0 )
fny = fnyasympt(y);
else
fny = fpoint(y);
return 4. * Constants::pi * fny * s * sqr(bc);
}
//The asymptotic form of the F_n functions; used for x > 20
double METRP2to2::fnyasympt(double y) const {
return pow( _ndim, 1.0/(_ndim+1.0) ) * pow( y, -(_ndim+2.0)/(_ndim+1.0) ) / sqrt(_ndim+1.0);
}
//fpoint uses the interpolator to calculate the value of F_n for intermediate values of the argument
double METRP2to2::fpoint(double x) const {
assert( x < 20.0 );
if ( _ndim == 2 && x < 0.02 ) {
return sqrt( sqr(-log(x/1.4)) + sqr(Constants::pi)/16 );
}
else {
return (*_interpol)(x);
}
}
diff --git a/Models/UED/UEDBase.cc b/Models/UED/UEDBase.cc
--- a/Models/UED/UEDBase.cc
+++ b/Models/UED/UEDBase.cc
@@ -1,425 +1,429 @@
// -*- C++ -*-
//
// UEDBase.cc is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the UEDBase class.
//
#include "UEDBase.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Repository/Repository.h"
#include "ThePEG/Repository/CurrentGenerator.h"
using namespace Herwig;
UEDBase::UEDBase() : theRadCorr(true), theInvRadius(500.*GeV),
theLambdaR(20.), theMbarH(), theSinThetaOne(0.),
theVeV(246.*GeV) {}
void UEDBase::doinit() {
- StandardModel::doinit();
+ readDecays(false);
+ BSMModel::doinit();
//level-1 masses and mixing angle
calculateKKMasses(1);
writeSpectrum();
//add the level-1 vertices.
addVertex(theF1F1Z0Vertex);
addVertex(theF1F1G0Vertex);
addVertex(theF1F0G1Vertex);
addVertex(theG1G1G0Vertex);
addVertex(theG0G0G1G1Vertex);
addVertex(theF1F1P0Vertex);
addVertex(theF1F1W0Vertex);
addVertex(theF1F0W1Vertex);
addVertex(theF1F0H1Vertex);
addVertex(theP0H1H1Vertex);
addVertex(theZ0H1H1Vertex);
addVertex(theW0A1H1Vertex);
addVertex(theZ0A1h1Vertex);
addVertex(theW0W1W1Vertex);
+ readDecays(true);
+ if(decayFile()=="") return;
+ decayRead();
}
void UEDBase::persistentOutput(PersistentOStream & os) const {
os << theRadCorr << ounit(theInvRadius, GeV) << theLambdaR
<< theF1F1Z0Vertex << theF1F1G0Vertex << theF1F0G1Vertex
<< theG1G1G0Vertex << theG0G0G1G1Vertex << theF1F1P0Vertex
<< theF1F1W0Vertex << theF1F0W1Vertex << theF1F0H1Vertex
<< theP0H1H1Vertex << theZ0H1H1Vertex << theW0A1H1Vertex
<< theZ0A1h1Vertex << theW0W1W1Vertex << ounit(theVeV,GeV)
<< ounit(theMbarH, GeV) << theSinThetaOne;
}
void UEDBase::persistentInput(PersistentIStream & is, int) {
is >> theRadCorr >> iunit(theInvRadius, GeV) >> theLambdaR
>> theF1F1Z0Vertex >> theF1F1G0Vertex >> theF1F0G1Vertex
>> theG1G1G0Vertex >> theG0G0G1G1Vertex >> theF1F1P0Vertex
>> theF1F1W0Vertex >> theF1F0W1Vertex >> theF1F0H1Vertex
>> theP0H1H1Vertex >> theZ0H1H1Vertex >> theW0A1H1Vertex
>> theZ0A1h1Vertex >> theW0W1W1Vertex >> iunit(theVeV,GeV)
>> iunit(theMbarH, GeV) >> theSinThetaOne;
}
ClassDescription<UEDBase> UEDBase::initUEDBase;
// Definition of the static class description member.
void UEDBase::Init() {
static ClassDocumentation<UEDBase> documentation
("This class implements/stores the necessary information for the simulation"
" of a Universal Extra Dimensions model.",
"Universal extra dimensions model based on \\cite{Cheng:2002iz,Appelquist:2000nn}.",
"%\\cite{Cheng:2002iz}\n"
"\\bibitem{Cheng:2002iz}\n"
" H.~C.~Cheng, K.~T.~Matchev and M.~Schmaltz,\n"
" ``Radiative corrections to Kaluza-Klein masses,''\n"
" Phys.\\ Rev.\\ D {\\bf 66}, 036005 (2002)\n"
" [arXiv:hep-ph/0204342].\n"
" %%CITATION = PHRVA,D66,036005;%%\n"
"%\\cite{Appelquist:2000nn}\n"
"\\bibitem{Appelquist:2000nn}\n"
" T.~Appelquist, H.~C.~Cheng and B.~A.~Dobrescu,\n"
" ``Bounds on universal extra dimensions,''\n"
" Phys.\\ Rev.\\ D {\\bf 64}, 035002 (2001)\n"
" [arXiv:hep-ph/0012100].\n"
" %%CITATION = PHRVA,D64,035002;%%\n"
);
static Switch<UEDBase,bool> interfaceRadiativeCorrections
("RadiativeCorrections",
"Calculate the radiative corrections to the masses",
&UEDBase::theRadCorr, true, false, false);
static SwitchOption interfaceRadiativeCorrectionsYes
(interfaceRadiativeCorrections,
"Yes",
"Calculate the radiative corrections to the masses",
true);
static SwitchOption interfaceRadiativeCorrectionsNo
(interfaceRadiativeCorrections,
"No",
"Leave the masses of the KK particles as n/R",
false);
static Parameter<UEDBase,Energy> interfaceInverseRadius
("InverseRadius",
"The inverse radius of the compactified dimension ",
&UEDBase::theInvRadius, GeV, 500.*GeV, ZERO, ZERO,
true, false, Interface::nolimits);
static Parameter<UEDBase,double> interfaceLambdaR
("LambdaR",
"The product of the cut-off scale and the radius of compactification",
&UEDBase::theLambdaR, 20.0, 0.0, 0,
false, false, Interface::lowerlim);
static Parameter<UEDBase,Energy> interfaceBoundaryMass
("HiggsBoundaryMass",
"The boundary mass for the Higgs",
&UEDBase::theMbarH, GeV, ZERO, ZERO, ZERO,
false, false, Interface::lowerlim);
static Parameter<UEDBase,Energy> interfaceVeV
("HiggsVEV",
"The vacuum expectation value of the Higgs field",
&UEDBase::theVeV, GeV, 246.*GeV, ZERO, ZERO,
true, false, Interface::nolimits);
static Reference<UEDBase,Helicity::AbstractFFVVertex> interfaceF1F1Z
("Vertex/F1F1Z",
"The F1F1Z UED Vertex",
&UEDBase::theF1F1Z0Vertex, false, false, true, false, false);
static Reference<UEDBase,Helicity::AbstractFFVVertex> interfaceF1F1G0
("Vertex/F1F1G0",
"The F1F1G UED Vertex",
&UEDBase::theF1F1G0Vertex, false, false, true, false, false);
static Reference<UEDBase,Helicity::AbstractFFVVertex> interfaceF1F0G1
("Vertex/F1F0G1",
"The F1F0G0 UED Vertex",
&UEDBase::theF1F0G1Vertex, false, false, true, false, false);
static Reference<UEDBase,Helicity::AbstractVVVVertex> interfaceG1G1G0
("Vertex/G1G1G0",
"The G1G1G0 UED Vertex",
&UEDBase::theG1G1G0Vertex, false, false, true, false, false);
static Reference<UEDBase,Helicity::AbstractVVVVVertex> interfaceG0G0G1G1
("Vertex/G0G0G1G1",
"The G0G0G1G1 UED Vertex",
&UEDBase::theG0G0G1G1Vertex, false, false, true, false, false);
static Reference<UEDBase,Helicity::AbstractFFVVertex> interfaceF1F1P
("Vertex/F1F1P",
"The F1F1P UED Vertex",
&UEDBase::theF1F1P0Vertex, false, false, true, false, false);
static Reference<UEDBase,Helicity::AbstractFFVVertex> interfaceF1F1W
("Vertex/F1F1W",
"The F1F1W UED Vertex",
&UEDBase::theF1F1W0Vertex, false, false, true, false, false);
static Reference<UEDBase,Helicity::AbstractFFVVertex> interfaceF1F0W1
("Vertex/F1F0W1",
"The F1F0W1 UED Vertex",
&UEDBase::theF1F0W1Vertex, false, false, true, false, false);
static Reference<UEDBase,Helicity::AbstractFFSVertex> interfaceF1F0H1
("Vertex/F1F0H1",
"The F1F0H1 UED Vertex",
&UEDBase::theF1F0H1Vertex, false, false, true, false, false);
static Reference<UEDBase,Helicity::AbstractVSSVertex> interfaceP0H1H1
("Vertex/P0H1H1",
"The P0H1H1 UED Vertex",
&UEDBase::theP0H1H1Vertex, false, false, true, false, false);
static Reference<UEDBase,Helicity::AbstractVSSVertex> interfaceZ0H1H1
("Vertex/Z0H1H1",
"The Z0H1H1 UED Vertex",
&UEDBase::theZ0H1H1Vertex, false, false, true, false, false);
static Reference<UEDBase,Helicity::AbstractVSSVertex> interfaceW0A1H1
("Vertex/W0A1H1",
"The W0A1H1 UED Vertex",
&UEDBase::theW0A1H1Vertex, false, false, true, false, false);
static Reference<UEDBase,Helicity::AbstractVSSVertex> interfaceZ0A1h1
("Vertex/Z0A1h1",
"The W0A1H1 UED Vertex",
&UEDBase::theZ0A1h1Vertex, false, false, true, false, false);
static Reference<UEDBase,Helicity::AbstractVVVVertex> interfaceW0W1W1
("Vertex/W0W1W1",
"The W0W1W1 UED Vertex",
&UEDBase::theW0W1W1Vertex, false, false, true, false, false);
}
void UEDBase::calculateKKMasses(const unsigned int n) {
useMe();
if(n == 0)
throw InitException() << "UEDBase::resetKKMasses - "
<< "Trying to reset masses with KK number == 0!"
<< Exception::warning;
if(theRadCorr) {
fermionMasses(n);
bosonMasses(n);
}
else {
cerr <<
"Warning: Radiative corrections to particle masses have been "
"turned off.\n The masses will be set to (n/R + m_sm)^1/2 and "
"the spectrum will be\n highly degenerate so that no decays "
"will occur.\n This is only meant to be used for debugging "
"purposes.\n";
//set masses to tree level for each kk mode
long level1 = 5000000 + n*100000;
long level2 = 6000000 + n*100000;
Energy2 ndmass2 = sqr(n*theInvRadius);
for ( int i = 1; i < 38; ++i ) {
if(i == 7 || i == 17) i += 4;
if(i == 26) i += 10;
Energy kkmass = sqrt( ndmass2 + sqr(getParticleData(i)->mass()) );
resetMass(level1 + i, kkmass);
if( i < 7 || i == 11 || i == 13 || i == 15 )
resetMass(level2 + i, kkmass);
}
}
}
void UEDBase::bosonMasses(const unsigned int n) {
// Common constants
const Energy2 invRad2 = theInvRadius*theInvRadius;
const double g_em2 = 4.*Constants::pi*alphaEM(invRad2);
const double g_s2 = 4.*Constants::pi*alphaS(invRad2);
const double g_W2 = g_em2/sin2ThetaW();
//Should probably use a function to calculate zeta.
const double zeta3 = 1.20206;
const Energy2 nmass2 = sqr(n*theInvRadius);
const double pi2 = sqr(Constants::pi);
const double norm = 1./16./pi2;
const double nnlogLR = n*n*log(theLambdaR);
long level = 5000000 + n*100000;
//gluon
Energy2 deltaGB = g_s2*invRad2*norm*(23.*nnlogLR - 3.*zeta3/2./pi2 );
resetMass(level + 21, sqrt(nmass2 + deltaGB));
//W+/-
Energy2 deltaGW = g_W2*invRad2*norm*( 15.*nnlogLR - 5.*zeta3/2./pi2 );
Energy2 mw2 = sqr(getParticleData(24)->mass());
resetMass(level + 24, sqrt(mw2 + nmass2 + deltaGW));
//Z and gamma are a mixture of Bn and W3n
deltaGB = -g_em2*invRad2*norm*( 39.*zeta3/2./pi2 + nnlogLR/3. );
Energy2 mz2 = sqr(getParticleData(23)->mass());
Energy2 fp = 0.5*(mz2 + deltaGB + deltaGW + 2.*nmass2);
Energy2 sp = 0.5*sqrt( sqr(deltaGB - deltaGW - 2.*mw2 + mz2)
- 4.*mw2*(mw2 - mz2) );
resetMass(level + 22, sqrt(fp - sp));
resetMass(level + 23, sqrt(fp + sp));
//mixing angle will now depend on both Z* and gamma* mass
//Derived expression:
//
// cos^2_theta_N = ( (n/R)^2 + delta_GW + mw^2 - m_gam*^2)/(m_z*^2 - m_gam*^2)
//
double cn2 = (nmass2 + deltaGW + mw2 - fp + sp)/2./sp;
double sn = sqrt(1. - cn2);
theMixingAngles.insert(make_pair(n, sn));
if( n == 1 ) theSinThetaOne = sn;
//scalars
Energy2 mh2 = sqr(getParticleData(25)->mass());
double lambda_H = mh2/theVeV/theVeV;
deltaGB = nnlogLR*norm*invRad2*(3.*g_W2 + (3.*g_em2/2.) - 2.*lambda_H)
+ sqr(theMbarH);
//H0
Energy2 new_m2 = nmass2 + deltaGB;
resetMass(level + 25, sqrt( mh2 + new_m2 ));
//A0
resetMass(level + 36, sqrt( mz2 + new_m2 ));
//H+
resetMass(level + 37, sqrt( mw2 + new_m2 ));
}
void UEDBase::fermionMasses(const unsigned int n) {
const Energy2 invRad2 = theInvRadius*theInvRadius;
const double g_em2 = 4.*Constants::pi*alphaEM(invRad2);
const double g_s2 = 4.*Constants::pi*alphaS(invRad2);
const double g_W2 = g_em2/sin2ThetaW();
const Energy nmass = n*theInvRadius;
const Energy norm =
nmass*log(theLambdaR)/16./Constants::pi/Constants::pi;
const Energy topMass = getParticleData(6)->mass();
const double ht = sqrt(2)*topMass/theVeV;
//doublets
Energy deltaL = norm*(6.*g_s2 + (27.*g_W2/8.) + (g_em2/8.));
Energy deltaQ = deltaL;
Energy2 shift = sqr(nmass + deltaL);
long level = 5000000 + n*100000;
for(long i = 1; i < 17; ++i) {
if(i == 6) {
i += 5;
deltaL = norm*( (27.*g_W2/8.) + (9.*g_em2/8.) );
shift = sqr(nmass + deltaL);
}
Energy2 new_m2 = sqr(getParticleData(i)->mass()) + shift;
resetMass(level + i, sqrt(new_m2));
}
//singlet shifts
const Energy deltaU = norm*(6.*g_s2 + 2.*g_em2);
const Energy deltaD = norm*(6.*g_s2 + 0.5*g_em2);
const Energy2 shiftU = sqr(nmass + deltaU);
const Energy2 shiftD = sqr(nmass + deltaD);
//Top quarks seperately as they have different corrections
const Energy2 mt2 = sqr(topMass);
const Energy delta_Q3 = -3.*ht*ht*norm/2.;
const Energy deltaTD = deltaQ + delta_Q3;
const Energy deltaTS = deltaU + 2.*delta_Q3;
Energy second_term =
0.5*sqrt( sqr(2.*nmass + deltaTS + deltaTD) + 4.*mt2 );
//doublet
resetMass(level + 6, abs(0.5*(deltaTD - deltaTS) - second_term) );
//singlet
level += 1000000;
resetMass(level + 6, 0.5*(deltaTD - deltaTS) + second_term);
// others
//lepton
Energy delta = 9.*norm*g_em2/2.;
shift = sqr(nmass + delta);
for(long i = 1; i < 17; ) {
if(i == 6) i += 5;
Energy2 smMass2(sqr(getParticleData(i)->mass()));
if(i < 6) {
Energy2 new_m2;
if( i % 2 == 0)
new_m2 = smMass2 + shiftU;
else
new_m2 = smMass2 + shiftD;
resetMass(level + i, sqrt(new_m2));
++i;
}
else {
resetMass(level + i, sqrt(smMass2 + shift));
i += 2;
}
}
}
void UEDBase::resetMass(long id, Energy mass) {
theMasses.push_back(make_pair(id, mass));
tPDPtr particle = getParticleData(id);
if(!particle) {
throw InitException() << "UEDBase::resetMass - Trying to reset a mass for "
<< "a ParticleData object that does not exist. ID: "
<< id << Exception::warning;
return;
}
//find the correct interface
const InterfaceBase * ifc =
Repository::FindInterface(particle, "NominalMass");
if(!ifc)
throw InitException() << "UEDBase::resetMass - There was an error while "
<< "retrieving the NominalMass interface for "
<< particle->fullName()
<< Exception::abortnow;
//put value into a stream
ostringstream oss;
oss << ounit(mass, GeV);
if(!oss)
throw InitException() << "UEDBase::resetMass - There was an error while "
<< "reading the new mass into a stream for "
<< particle->fullName()
<< Exception::abortnow;
ifc->exec(*particle, "set", oss.str());
}
void UEDBase::writeSpectrum() {
sort(theMasses.begin(), theMasses.end(), lowerMass);
ostream & ofs = CurrentGenerator::current().misc();
ofs << "# MUED Model Particle Spectrum\n"
<< "# R^-1: " << theInvRadius/GeV << " GeV\n"
<< "# Lambda * R: " << theLambdaR << "\n"
<< "# Higgs Mass: " << getParticleData(25)->mass()/GeV << " GeV\n";
ofs << "#\n# ID\t\t\tMass(GeV)\n";
while (!theMasses.empty()) {
IDMassPair tmp = theMasses.back();
tcPDPtr data = getParticleData(tmp.first);
ofs << tmp.first << "\t\t\t" << tmp.second/GeV << "\t\t" << (data? data->PDGName() : "")
<< endl;
theMasses.pop_back();
}
ofs << "#\n";
}
double UEDBase::sinThetaN(const unsigned int n) const {
WAMap::const_iterator pos = theMixingAngles.find(n);
if(pos != theMixingAngles.end())
return pos->second;
else {
throw Exception() << "UEDBase::sinThetaN() - A mixing angle has "
<< "been requested for a level that does not "
<< "exist. Check that the radiative corrections "
<< "for the " << n << "th level have been "
<< "calculated." << Exception::warning;
return 0.0;
}
}
diff --git a/Models/UED/UEDBase.h b/Models/UED/UEDBase.h
--- a/Models/UED/UEDBase.h
+++ b/Models/UED/UEDBase.h
@@ -1,367 +1,367 @@
// -*- C++ -*-
//
// UEDBase.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_UEDBase_H
#define HERWIG_UEDBase_H
//
// This is the declaration of the UEDBase class.
//
-#include "Herwig++/Models/StandardModel/StandardModel.h"
+#include "Herwig++/Models/General/BSMModel.h"
#include "ThePEG/Helicity/Vertex/AbstractFFVVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractFFSVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractVVVVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractVSSVertex.h"
#include "UEDBase.fh"
namespace Herwig {
using namespace ThePEG;
/**
* This class serves as a base class for all UED models. It stores the
* values of the inverse radius and the product \f$\Lambda R \f$ and has functions
* to calculate the radiative corrections to the nth level KK excitations.
*
* To use this class for n > 1 simply inherit off it, calculate the necessary masses
* using the provided functions for the new excitations and add the
* appropriate vertices.
*
* @see \ref UEDBaseInterfaces "The interfaces"
* defined for UEDBase.
*/
-class UEDBase: public StandardModel {
+class UEDBase: public BSMModel {
public:
/** Typedef for ID-Mass pair. */
typedef pair<long, Energy> IDMassPair;
/** Typedef for unsigned int/double map to store Weinburg angles.*/
typedef map<unsigned int, double> WAMap;
public:
/**
* The default constructor.
*/
UEDBase();
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
public:
/** @name Public Access Functions.*/
//@{
/**
* Return the compactification radius
*/
InvEnergy compactRadius() const {
return 1./theInvRadius;
}
/**
* Return the Weinburg mixing angle for any level.
*/
double sinThetaN(const unsigned int n) const;
/**
* Return the Weinburg mixing angle for \f$n = 1\f$
*/
double sinThetaOne() const {
return theSinThetaOne;
}
//@}
protected:
/**
* Add a new ID,mass pair to the mass storage
* @param elem The element to add in to storage
*/
void addMassElement(IDMassPair elem) {
theMasses.push_back(elem);
}
/**
* Add a new mixing angle to the storage
* @param n The level
* @param val The value
*/
void addMixingAngle(const unsigned int n,
const double val) {
theMixingAngles.insert(make_pair(n, val));
}
private:
/** @name Utility Functions for calculating masses. */
//@{
/**
* Calculate the radiative corrections to the masses of the KK excitations
* @param n The KK-level for which to calculate the masses.
*/
void calculateKKMasses(const unsigned int n);
/**
* Calculate the radiative corrections to the spin-0 and spin-1
* masses of the KK excitations
* @param n The KK-level for which to calculate the masses.
*/
void bosonMasses(const unsigned int n);
/**
* Calculate the radiative corrections to the spin-1/2
* masses of the KK excitations.
* @param n The KK-level for which to calculate the masses.
*/
void fermionMasses(const unsigned int n);
/**
* Reset the mass of the ParticleData object
*@param id The id of the particles mass to reset
*@param value The new mass
*/
void resetMass(long id, Energy value);
/**
* Calculate the Weinburg Mixing angle for the appropriate level.
* @param n The KK-level for which to calculate the mixing angle.
*/
double calculateMixingAngle(const unsigned int n);
//@}
/**
* Write out a spectrum file ordered in mass (name can be set by an interface).
*/
void writeSpectrum();
/**
* A predicate for sorting the list of masses.
*/
static bool lowerMass(const pair<long, Energy> & p1,
const pair<long, Energy> & p2) {
return p1.second < p2.second;
}
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
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.
*/
virtual IBPtr fullclone() const {return new_ptr(*this);}
//@}
protected:
/** @name Standard Interfaced functions. */
//@{
virtual void doinit();
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<UEDBase> initUEDBase;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
UEDBase & operator=(const UEDBase &);
private:
/**
* Whether to calculate the radiative corrections to the KK masses
*/
bool theRadCorr;
/**
* Store the radius of the compactified dimension.
*/
Energy theInvRadius;
/**
* The value of \f$\Lambda R \f$.
*/
double theLambdaR;
/**
* The boundary mass term for the Higgs.
*/
Energy theMbarH;
/**
* The values of \f$\sin\theta_N\f$
*/
WAMap theMixingAngles;
/**
* Store \f$\sin\theta_1\f$ for faster access
*/
double theSinThetaOne;
/**
* Store the masses of the new particles
*/
vector<IDMassPair> theMasses;
/**
* The value of the vacuum expectation value of the higgs field.
*/
Energy theVeV;
/** @name The level 1 UED vertices. */
//@{
/**
* The \f$\bar{f}^{(1)}f^{(1)}Z^{(0)}\f$
*/
AbstractFFVVertexPtr theF1F1Z0Vertex;
/**
* The \f$\bar{f}^{(1)}f^{(1)}g^{(0)}\f$
*/
AbstractFFVVertexPtr theF1F1G0Vertex;
/**
* The \f$\bar{f}^{(1)}f^{(0)}g^{(1)}\f$
*/
AbstractFFVVertexPtr theF1F0G1Vertex;
/**
* The \f$g^{(1)}g^{(1)}g\f$ vertex
*/
AbstractVVVVertexPtr theG1G1G0Vertex;
/**
* The \f$g\,g\,g^{(1)},g^{(1)}\f$ vertex
*/
AbstractVVVVVertexPtr theG0G0G1G1Vertex;
/**
* The \f$\bar{f}^{(1)}f^{(1)}\gamma\f$
*/
AbstractFFVVertexPtr theF1F1P0Vertex;
/**
* The \f$\bar{f}^{(1)}f^{(1)}W\f$
*/
AbstractFFVVertexPtr theF1F1W0Vertex;
/**
* The \f$\bar{f}^{(1)}f^{(0)}W^{(1)}\f$
*/
AbstractFFVVertexPtr theF1F0W1Vertex;
/**
* The \f$\bar{f}^{(1)}f^{(0)}H^{(1)}\f$
*/
AbstractFFSVertexPtr theF1F0H1Vertex;
/**
* The \f$ A^\mu_{(0)}H^+_{(1)}H-_{(1)}\f$
*/
AbstractVSSVertexPtr theP0H1H1Vertex;
/**
* The \f$ Z^\mu_{(0)}H^+_{(1)}H-_{(1)}\f$
*/
AbstractVSSVertexPtr theZ0H1H1Vertex;
/**
* The \f$ W^\pm_{\mu(0)}A_{(1)}H^\mp_{(1)}\f$
*/
AbstractVSSVertexPtr theW0A1H1Vertex;
/**
* The \f$ Z^\mu_{\mu(0)}A_{(1)}h_{(1)}\f$
*/
AbstractVSSVertexPtr theZ0A1h1Vertex;
/**
* The \f$W^{(1)}Z^{(1)}W_{(0)}\f$ vertex
*/
AbstractVVVVertexPtr theW0W1W1Vertex;
//@}
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of UEDBase. */
template <>
struct BaseClassTrait<Herwig::UEDBase,1> {
/** Typedef of the first base class of UEDBase. */
- typedef Herwig::StandardModel NthBase;
+ typedef Herwig::BSMModel NthBase;
};
/** This template specialization informs ThePEG about the name of
* the UEDBase class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::UEDBase>
: public ClassTraitsBase<Herwig::UEDBase> {
/** Return a platform-independent class name */
static string className() { return "Herwig::UEDBase"; }
/**
* The name of a file containing the dynamic library where the class
* UEDBase is implemented. It may also include several, space-separated,
* libraries if the class UEDBase 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 "HwUED.so"; }
};
/** @endcond */
}
#endif /* HERWIG_UEDBase_H */
diff --git a/PDT/GenericMassGenerator.cc b/PDT/GenericMassGenerator.cc
--- a/PDT/GenericMassGenerator.cc
+++ b/PDT/GenericMassGenerator.cc
@@ -1,219 +1,219 @@
// -*- C++ -*-
//
// GenericMassGenerator.cc is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the GenericMassGenerator class.
//
#include "GenericMassGenerator.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Utilities/Throw.h"
#include "ThePEG/Utilities/Rebinder.h"
using namespace Herwig;
using namespace ThePEG;
void GenericMassGenerator::persistentOutput(PersistentOStream & os) const {
os << particle_
<< ounit(lowerMass_,GeV) << ounit(upperMass_,GeV) << maxWgt_
<< BWShape_ << nGenerate_
<< ounit(mass_,GeV) << ounit(width_,GeV)
<< ounit(mass2_,GeV2) << ounit(mWidth_,GeV2)
<< nInitial_ << initialize_ << widthGen_ << widthOpt_;
}
void GenericMassGenerator::persistentInput(PersistentIStream & is, int) {
is >> particle_
>> iunit(lowerMass_,GeV) >> iunit(upperMass_,GeV) >> maxWgt_
>> BWShape_ >> nGenerate_
>> iunit(mass_,GeV) >> iunit(width_ ,GeV)
>> iunit(mass2_,GeV2) >> iunit(mWidth_ ,GeV2)
>> nInitial_ >> initialize_ >> widthGen_ >> widthOpt_;
}
ClassDescription<GenericMassGenerator> GenericMassGenerator::initGenericMassGenerator;
// Definition of the static class description member.
void GenericMassGenerator::Init() {
static ClassDocumentation<GenericMassGenerator> documentation
("The GenericMassGenerator class is the main class for"
" mass generation in Herwig++.");
static Parameter<GenericMassGenerator,string> interfaceParticle
("Particle",
"The particle data object for this class",
0, "", true, false,
&GenericMassGenerator::setParticle,
&GenericMassGenerator::getParticle);
static Switch<GenericMassGenerator,bool> interfaceInitialize
("Initialize",
"Initialize the calculation of the maximum weight etc",
&GenericMassGenerator::initialize_, false, false, false);
static SwitchOption interfaceInitializeInitialization
(interfaceInitialize,
"Yes",
"Do the initialization",
true);
static SwitchOption interfaceInitializeNoInitialization
(interfaceInitialize,
"No",
"Don't do the initalization",
false);
static Switch<GenericMassGenerator,int> interfaceBreitWignerShape
("BreitWignerShape",
"Controls the shape of the mass distribution generated",
&GenericMassGenerator::BWShape_, 0, false, false);
static SwitchOption interfaceBreitWignerShapeDefault
(interfaceBreitWignerShape,
"Default",
"Running width with q in numerator and denominator width factor",
0);
static SwitchOption interfaceBreitWignerShapeFixedWidth
(interfaceBreitWignerShape,
"FixedWidth",
"Use a fixed width",
1);
static SwitchOption interfaceBreitWignerShapeNoq
(interfaceBreitWignerShape,
"Noq",
"Use M rather than q in the numerator and denominator width factor",
2);
static SwitchOption interfaceBreitWignerShapeNoNumerator
(interfaceBreitWignerShape,
"NoNumerator",
"Neglect the numerator factors",
3);
static Parameter<GenericMassGenerator,double> interfaceMaximumWeight
("MaximumWeight",
"The maximum weight for the unweighting",
&GenericMassGenerator::maxWgt_, 1.0, 0.0, 1000.0,
false, false, true);
static Parameter<GenericMassGenerator,int> interfaceNGenerate
("NGenerate",
"The number of tries to generate the mass",
&GenericMassGenerator::nGenerate_, 100, 0, 10000,
false, false, true);
static Parameter<GenericMassGenerator,int> interfaceNInitial
("NInitial",
"Number of tries for the initialisation",
&GenericMassGenerator::nInitial_, 1000, 0, 100000,
false, false, true);
static Switch<GenericMassGenerator,bool> interfaceWidthOption
("WidthOption",
"Which width to use",
&GenericMassGenerator::widthOpt_, false, false, false);
static SwitchOption interfaceWidthOptionNominalWidth
(interfaceWidthOption,
"NominalWidth",
"Use the normal width from the particle data object",
false);
static SwitchOption interfaceWidthOptionPhysicalWidth
(interfaceWidthOption,
"PhysicalWidth",
"Use the width calculated at the on-shell mass",
true);
}
bool GenericMassGenerator::accept(const ParticleData & in) const {
if(!particle_) return false;
return in.id() == particle_->id() ||
( particle_->CC() && particle_->CC()->id() == in.id() );
}
void GenericMassGenerator::doinit() {
MassGenerator::doinit();
// the width generator
particle_->init();
widthGen_=particle_->widthGenerator();
if(widthGen_){widthGen_->init();}
// local storage of particle properties for speed
mass_=particle_->mass();
width_= widthOpt_ ? particle_->generateWidth(mass_) : particle_->width();
mass2_=mass_*mass_;
mWidth_=mass_*width_;
lowerMass_ = mass_-particle_->widthLoCut();
upperMass_ = mass_+particle_->widthUpCut();
// print out messagw if doing the initialisation
if(initialize_) {
// zero the maximum weight
maxWgt_=0.;
// storage of variables for the loop
double wgt=0.,swgt=0.,sqwgt=0.;
// perform the initialisation
for(int ix=0;ix<nInitial_;++ix) {
mass(wgt,*particle_,3);
swgt += wgt;
sqwgt += sqr(wgt);
if(wgt>maxWgt_) maxWgt_=wgt;
}
swgt=swgt/nInitial_;
sqwgt=sqrt(max(0.,sqwgt/nInitial_-swgt*swgt)/nInitial_);
}
}
void GenericMassGenerator::dataBaseOutput(ofstream & output, bool header) {
if(header) output << "update Mass_Generators set parameters=\"";
output << "newdef " << fullName() << ":BreitWignerShape " << BWShape_ << "\n";
output << "newdef " << fullName() << ":MaximumWeight " << maxWgt_ << "\n";
output << "newdef " << fullName() << ":NGenerate " << nGenerate_ << "\n";
output << "newdef " << fullName() << ":WidthOption " << widthOpt_ << "\n";
if(header) output << "\n\" where BINARY ThePEGFullName=\""
<< fullName() << "\";" << endl;
}
void GenericMassGenerator::dofinish() {
if(initialize_) {
string fname = CurrentGenerator::current().filename() +
string("-") + name() + string(".output");
ofstream output(fname.c_str());
dataBaseOutput(output,true);
}
MassGenerator::dofinish();
}
void GenericMassGenerator::setParticle(string p) {
- if ( particle_ = Repository::GetPtr<tPDPtr>(p) ) return;
+ if ( (particle_ = Repository::GetPtr<tPDPtr>(p)) ) return;
particle_ = Repository::findParticle(StringUtils::basename(p));
if ( ! particle_ )
Throw<InterfaceException>()
<< "Could not set Particle interface "
<< "for the object \"" << name()
<< "\". Particle \"" << StringUtils::basename(p) << "\" not found."
<< Exception::runerror;
}
string GenericMassGenerator::getParticle() const {
return particle_ ? particle_->fullName() : "";
}
void GenericMassGenerator::rebind(const TranslationMap & trans)
{
particle_ = trans.translate(particle_);
MassGenerator::rebind(trans);
}
IVector GenericMassGenerator::getReferences() {
IVector ret = MassGenerator::getReferences();
ret.push_back(particle_);
return ret;
}
diff --git a/PDT/GenericWidthGenerator.cc b/PDT/GenericWidthGenerator.cc
--- a/PDT/GenericWidthGenerator.cc
+++ b/PDT/GenericWidthGenerator.cc
@@ -1,809 +1,809 @@
// -*- C++ -*-
//
// GenericWidthGenerator.cc is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the GenericWidthGenerator class.
//
#include "GenericWidthGenerator.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/ParVector.h"
#include "TwoBodyAllOnCalculator.h"
#include "OneOffShellCalculator.h"
#include "TwoOffShellCalculator.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Repository/Repository.h"
#include "ThePEG/Utilities/Throw.h"
#include "ThePEG/Utilities/StringUtils.h"
using namespace Herwig;
void GenericWidthGenerator::persistentOutput(PersistentOStream & os) const {
os << particle_ << ounit(mass_,GeV) << prefactor_ << MEtype_ << MEcode_
<< ounit(MEmass1_,GeV) << ounit(MEmass2_,GeV) << MEcoupling_ << modeOn_
<< ounit(interMasses_,GeV) << ounit(interWidths_,GeV)
<< noOfEntries_ << initialize_ << BRnorm_
<< npoints_ << decayModes_ << decayTags_ << ounit(minMass_,GeV)
<< BRminimum_ << intOrder_ << interpolators_;
}
void GenericWidthGenerator::persistentInput(PersistentIStream & is, int) {
is >> particle_ >> iunit(mass_,GeV) >> prefactor_ >> MEtype_ >> MEcode_
>> iunit(MEmass1_,GeV) >> iunit(MEmass2_,GeV) >> MEcoupling_ >>modeOn_
>> iunit(interMasses_,GeV) >> iunit(interWidths_,GeV)
>> noOfEntries_ >> initialize_ >> BRnorm_
>> npoints_ >> decayModes_ >> decayTags_ >> iunit(minMass_,GeV)
>> BRminimum_ >> intOrder_ >> interpolators_;
}
ClassDescription<Interpolator<Energy, Energy> > initInterpolatorEE;
ClassDescription<GenericWidthGenerator> GenericWidthGenerator::initGenericWidthGenerator;
// Definition of the static class description member.
void GenericWidthGenerator::setParticle(string p) {
- if ( particle_ = Repository::GetPtr<tPDPtr>(p) ) return;
+ if ( (particle_ = Repository::GetPtr<tPDPtr>(p)) ) return;
particle_ = Repository::findParticle(StringUtils::basename(p));
if ( ! particle_ )
Throw<InterfaceException>()
<< "Could not set Particle interface "
<< "for the object \"" << name()
<< "\". Particle \"" << StringUtils::basename(p) << "\" not found."
<< Exception::runerror;
}
string GenericWidthGenerator::getParticle() const {
return particle_ ? particle_->fullName() : "";
}
void GenericWidthGenerator::Init() {
static ClassDocumentation<GenericWidthGenerator> documentation
("The GenericWidthGenerator class is the base class for running widths");
static Parameter<GenericWidthGenerator,string> interfaceParticle
("Particle",
"The particle for which this is the width generator",
0, "", true, false,
&GenericWidthGenerator::setParticle,
&GenericWidthGenerator::getParticle);
static Switch<GenericWidthGenerator,bool> interfaceInitialize
("Initialize",
"Initialize the width using the particle data object",
&GenericWidthGenerator::initialize_, false, false, false);
static SwitchOption interfaceInitializeInitialization
(interfaceInitialize,
"Yes",
"Do the initialization",
true);
static SwitchOption interfaceInitializeNoInitialization
(interfaceInitialize,
"No",
"Don't do the initalization",
false);
static ParVector<GenericWidthGenerator,int> interfacemetype
("MEtype",
"The type of matrix element either 2-body from this class or higher from"
" class inheriting from this",
&GenericWidthGenerator::MEtype_,
0, 0, 0, 0, 3, false, false, true);
static ParVector<GenericWidthGenerator,int> interfacemecode
("MEcode",
"The code of matrix element either 2-body from this class or higher from"
" class inheriting from this",
&GenericWidthGenerator::MEcode_,
0, 0, 0, -1, 200, false, false, true);
static ParVector<GenericWidthGenerator,Energy> interfaceMinimumMasses
("MinimumMasses",
"The minimum mass of the decay products",
&GenericWidthGenerator::minMass_,
GeV, 0, ZERO, ZERO, 1.E12*GeV, false, false, true);
static ParVector<GenericWidthGenerator,double> interfaceMEcoupling
("MEcoupling",
"The coupling for a given ME",
&GenericWidthGenerator::MEcoupling_,
0, 0, 0, 0, 1.E12, false, false, true);
static ParVector<GenericWidthGenerator,bool> interfaceModeOn
("ModeOn",
"Is this mode included in the total width calculation",
&GenericWidthGenerator::modeOn_,
0, 0, 0, 0, 1, false, false, true);
static ParVector<GenericWidthGenerator,Energy> interfaceMEmass1
("MEmass1",
"The mass for first particle in a two body mode",
&GenericWidthGenerator::MEmass1_,
GeV, 0, ZERO, ZERO, 1.E12*GeV, false, false, true);
static ParVector<GenericWidthGenerator,Energy> interfaceMEmass2
("MEmass2",
"The mass for second particle in a two body mode",
&GenericWidthGenerator::MEmass2_,
GeV, 0, ZERO, ZERO, 1.E12*GeV, false, false, true);
static ParVector<GenericWidthGenerator,Energy> interfaceInterpolationMasses
("InterpolationMasses",
"The masses for interpolation table",
&GenericWidthGenerator::interMasses_,
GeV, 0, ZERO, ZERO, 1E12*GeV, false, false, true);
static ParVector<GenericWidthGenerator,Energy> interfaceInterpolationWidths
("InterpolationWidths",
"The widths for interpolation table",
&GenericWidthGenerator::interWidths_,
GeV, 0, ZERO, ZERO, 1E12*GeV, false, false, true);
static ParVector<GenericWidthGenerator,int> interfacenoofenteries
("NumberofEntries",
"The number of entries in the table after this mode",
&GenericWidthGenerator::noOfEntries_,
0, 0, 0, 0, 100000000, false, false, true);
static Switch<GenericWidthGenerator,bool> interfaceBRNormalize
("BRNormalize",
"Normalize the partial widths so that they have the value BR*Total Width"
" for an on-shell particle",
&GenericWidthGenerator::BRnorm_, false, false, false);
static SwitchOption interfaceBRNormalizeNormalize
(interfaceBRNormalize,
"Yes",
"Perform the normalization",
true);
static SwitchOption interfaceBRNormalizeNoNormalisation
(interfaceBRNormalize,
"No",
"Do not perform the normalization",
false);
static Parameter<GenericWidthGenerator,double> interfaceBRMinimum
("BRMinimum",
"Minimum branching ratio for inclusion in the running width calculation.",
&GenericWidthGenerator::BRminimum_, 0.01, 0.0, 1.0,
false, false, true);
static Parameter<GenericWidthGenerator,double> interfacePrefactor
("Prefactor",
"The prefactor to get the correct on-shell width",
&GenericWidthGenerator::prefactor_, 1.0, 0., 1000.,
false, false, false);
static Parameter<GenericWidthGenerator,int> interfacePoints
("Points",
"Number of points to use for interpolation tables when needed",
&GenericWidthGenerator::npoints_, 50, 5, 1000,
false, false, true);
static ParVector<GenericWidthGenerator,string> interfaceDecayModes
("DecayModes",
"The tags for the decay modes used in the width generator",
&GenericWidthGenerator::decayTags_, -1, "", "", "",
false, false, Interface::nolimits);
static Parameter<GenericWidthGenerator,unsigned int> interfaceInterpolationOrder
("InterpolationOrder",
"The interpolation order for the tables",
&GenericWidthGenerator::intOrder_, 1, 1, 5,
false, false, Interface::limited);
}
Energy GenericWidthGenerator::width(const ParticleData &, Energy m) const {
Energy gamma= ZERO;
for(unsigned int ix =0;ix<MEcoupling_.size();++ix) {
if(modeOn_[ix]) gamma +=partialWidth(ix,m);
}
return gamma*prefactor_;
}
void GenericWidthGenerator::doinit() {
WidthGenerator::doinit();
// make sure the particle data object was initialized
particle_->init();
tDecayIntegratorPtr decayer;
// mass of the decaying particle
mass_ = particle_->mass();
if(initialize_) {
// the initial prefactor
prefactor_=1.;
// resize all the storage vectors
MEtype_.clear();
MEcode_.clear();
MEmass1_.clear();
MEmass2_.clear();
MEcoupling_.clear();
modeOn_.clear();
minMass_.clear();
interMasses_.clear();
interWidths_.clear();
noOfEntries_.clear();
decayTags_.clear();
// integrators that we may need
WidthCalculatorBasePtr widthptr;
// get the list of decay modes as a decay selector
DecayMap modes=particle_->decaySelector();
DecayMap::const_iterator start=modes.begin();
DecayMap::const_iterator end=modes.end();
tPDPtr part1,part2;
tGenericMassGeneratorPtr massgen1,massgen2;
// loop over the decay modes to get the partial widths
for(;start!=end;++start) {
// the decay mode
tcDMPtr mode=(*start).second;
decayModes_.push_back(const_ptr_cast<DMPtr>(mode));
decayTags_.push_back(decayModes_.back()->tag());
ParticleMSet::const_iterator pit(mode->products().begin());
// minimum mass for the decaymode
Energy minmass = ZERO;
for(;pit!=mode->products().end();++pit) {
(**pit).init();
minmass+=(**pit).massMin();
}
minMass_.push_back(minmass);
pit=mode->products().begin();
// its decayer
decayer=dynamic_ptr_cast<tDecayIntegratorPtr>(mode->decayer());
if(decayer) decayer->init();
// if there's no decayer then set the partial width to the br times the
// on-shell value
if(!decayer) {
MEtype_.push_back(0);
MEcode_.push_back(0);
MEcoupling_.push_back(mode->brat());
MEmass1_.push_back(ZERO);
MEmass2_.push_back(ZERO);
noOfEntries_.push_back(interMasses_.size());
modeOn_.push_back(mode->brat()>BRminimum_);
setupMode(mode,decayer,MEtype_.size()-1);
}
else if(mode->products().size()==2) {
// the outgoing particles
ParticleMSet::const_iterator pit = mode->products().begin();
part1=*pit;++pit;
part2=*pit;
// mass generators
if( part1->stable() || part1->massGenerator())
massgen1=dynamic_ptr_cast<tGenericMassGeneratorPtr>(part1->massGenerator());
else
massgen1=tGenericMassGeneratorPtr();
if(part2->stable() || part2->massGenerator())
massgen2=dynamic_ptr_cast<tGenericMassGeneratorPtr>(part2->massGenerator());
else
massgen2=tGenericMassGeneratorPtr();
if(massgen1) massgen1->init();
if(massgen2) massgen2->init();
double coupling(0.);
int mecode(-1);
bool order(decayer->twoBodyMEcode(*mode,mecode,coupling));
MEcode_.push_back(mecode);
MEcoupling_.push_back(coupling);
modeOn_.push_back(mode->brat()>BRminimum_);
if(order) {
MEmass1_.push_back(part1->mass());
MEmass2_.push_back(part2->mass());
}
else {
MEmass1_.push_back(part2->mass());
MEmass2_.push_back(part1->mass());
}
// perform setup in the inheriting class
setupMode(mode,decayer,MEcode_.size()-1);
// both particles on shell
if(!massgen1&&!massgen2) {
MEtype_.push_back(1);
noOfEntries_.push_back(interMasses_.size());
if(BRnorm_) {
if(mass_>MEmass1_[MEtype_.size()-1]+MEmass2_[MEtype_.size()-1]) {
Energy gamma(partial2BodyWidth(MEtype_.size()-1,mass_));
double ratio(mode->brat()*mode->parent()->width()/gamma);
ratio=sqrt(ratio);
MEcoupling_.back() *=ratio;
}
}
}
else {
// one off-shell particle
if(!massgen1||!massgen2) {
// create the width calculator
tGenericWidthGeneratorPtr
ttthis(const_ptr_cast<tGenericWidthGeneratorPtr>(this));
WidthCalculatorBasePtr twobody
(new_ptr(TwoBodyAllOnCalculator(ttthis,MEcode_.size()-1,
MEmass1_[MEcode_.size()-1],
MEmass2_[MEcode_.size()-1])));
int ioff = ((part1->massGenerator()&&!order)||
(part2->massGenerator()&&order)) ? 2 : 1;
if(massgen1)
widthptr=new_ptr(OneOffShellCalculator(ioff,twobody,massgen1,ZERO));
else
widthptr=new_ptr(OneOffShellCalculator(ioff,twobody,massgen2,ZERO));
}
else {
int ioff = order ? 1 : 2;
int iother = order ? 2 : 1;
// create the width calculator
tGenericWidthGeneratorPtr
ttthis(const_ptr_cast<tGenericWidthGeneratorPtr>(this));
// this is the both on-shell case
WidthCalculatorBasePtr twobody
(new_ptr(TwoBodyAllOnCalculator(ttthis,MEcode_.size()-1,
MEmass1_[MEcode_.size()-1],
MEmass2_[MEcode_.size()-1])));
// this is the first off-shell
WidthCalculatorBasePtr widthptr2=
new_ptr(OneOffShellCalculator(ioff,twobody,massgen1,ZERO));
widthptr=new_ptr(TwoOffShellCalculator(iother,widthptr2,massgen2,
ZERO,massgen1->lowerLimit()));
}
// set up the interpolation table
Energy test(part1->massMin()+part2->massMin());
Energy min(max(particle_->massMin(),test)),upp(particle_->massMax());
Energy step((upp-min)/(npoints_-1));
Energy moff(min);
Energy2 moff2;
// additional points to improve the interpolation
if(min==test) {
interMasses_.push_back(moff-2.*step);interWidths_.push_back(ZERO);
interMasses_.push_back(moff- step);interWidths_.push_back(ZERO);
interMasses_.push_back(moff );interWidths_.push_back(ZERO);
double fact(exp(0.1*log(1.+step/moff)));
for(unsigned int ix=0;ix<10;++ix) {
moff*=fact;
moff2=sqr(moff);
interMasses_.push_back(moff);
interWidths_.push_back(widthptr->partialWidth(moff2));
}
moff+=step;
}
else if(test>min-2.*step) {
interMasses_.push_back(moff-2.*step);interWidths_.push_back(ZERO);
interMasses_.push_back(test );interWidths_.push_back(ZERO);
}
else {
interMasses_.push_back(moff-2.*step);
interWidths_.push_back(widthptr->partialWidth((moff-2.*step)*
(moff-2.*step)));
interMasses_.push_back(moff- step);
interWidths_.push_back(widthptr->partialWidth((moff- step)*
(moff- step)));
}
for(; moff<upp+2.5*step;moff+=step) {
moff2=moff*moff;
interMasses_.push_back(moff);
interWidths_.push_back(widthptr->partialWidth(moff2));
}
coupling=1.;
if(BRnorm_) {
double ratio(1.);
if((massgen1&&massgen2&&
mass_>massgen1->lowerLimit()+massgen2->lowerLimit())||
(massgen1&&!massgen2&&
mass_>massgen1->lowerLimit()+part2->mass())||
(massgen2&&!massgen1&&
mass_>massgen2->lowerLimit()+part1->mass())||
(!massgen1&&!massgen2&&
mass_>part1->mass()+part2->mass())) {
Energy gamma(widthptr->partialWidth(mass_*mass_));
ratio=mode->brat()*mode->parent()->width()/gamma;
}
MEcoupling_.back()=ratio;
}
else MEcoupling_.back()=1.;
MEtype_.push_back(2);
MEcode_.back()=0;
noOfEntries_.push_back(interMasses_.size());
interpolators_.resize(MEtype_.size());
// get the vectors we will need
vector<Energy>::iterator istart= interMasses_.begin();
if(MEtype_.size()>1){istart+=noOfEntries_[MEtype_.size()-2];}
vector<Energy>::iterator iend=interMasses_.end();
vector<Energy> masses(istart,iend);
istart= interWidths_.begin();
if(MEtype_.size()>1){istart+=noOfEntries_[MEtype_.size()-2];}
iend=interWidths_.end();
vector<Energy> widths(istart,iend);
interpolators_.back() = make_InterpolatorPtr(widths,masses,intOrder_);
}
}
// higher multiplicities
else {
setupMode(mode,decayer,MEcode_.size());
widthptr=decayer->threeBodyMEIntegrator(*mode);
if(!widthptr) {
MEtype_.push_back(0);
MEcode_.push_back(0);
MEcoupling_.push_back(mode->brat());
MEmass1_.push_back(ZERO);
MEmass2_.push_back(ZERO);
noOfEntries_.push_back(interMasses_.size());
modeOn_.push_back(mode->brat()>BRminimum_);
}
else {
Energy step((particle_->widthUpCut()+particle_->widthLoCut())/
(npoints_-1));
Energy moff(particle_->massMin()),upp(particle_->massMax());
for( ; moff<upp+0.5*step;moff+=step) {
Energy2 moff2=sqr(moff);
Energy wtemp=widthptr->partialWidth(moff2);
interMasses_.push_back(moff);
interWidths_.push_back(wtemp);
}
double coupling(1.);
if(BRnorm_) {
Energy gamma = ZERO;
gamma=widthptr->partialWidth(mass_*mass_);
double ratio(mode->brat()*mode->parent()->width()/gamma);
coupling *=ratio;
}
MEtype_.push_back(2);
MEcode_.push_back(0);
MEcoupling_.push_back(coupling);
MEmass1_.push_back(ZERO);
MEmass2_.push_back(ZERO);
modeOn_.push_back(mode->brat()>BRminimum_);
noOfEntries_.push_back(interMasses_.size());
interpolators_.resize(MEtype_.size());
// get the vectors we will need
vector<Energy>::iterator istart( interMasses_.begin()),
iend(interMasses_.end());
if(MEtype_.size()>1){istart+=noOfEntries_[MEtype_.size()-2];}
vector<Energy> masses(istart,iend);
istart= interWidths_.begin();
if(MEtype_.size()>1){istart+=noOfEntries_[MEtype_.size()-2];}
iend=interWidths_.end();
vector<Energy> widths(istart,iend);
interpolators_.back() = make_InterpolatorPtr(widths,masses,intOrder_);
}
}
}
// now check the overall normalisation of the running width
Energy gamma = width(*particle_,mass_);
if(gamma>ZERO) prefactor_ = particle_->width()/gamma;
// output the info so it can be read back in
}
else {
// get the decay modes from the tags
if(decayTags_.size()!=0) {
decayModes_.clear();
for(unsigned int ix=0;ix<decayTags_.size();++ix) {
decayModes_.push_back(CurrentGenerator::current().findDecayMode(decayTags_[ix]));
if(!decayModes_.back())
generator()->log() << "Error in GenericWidthGenerator::doinit() "
<< "Failed to find DecayMode for tag"
<< decayTags_[ix] << "\n";
}
}
// otherwise just use the modes from the selector
else {
DecaySet modes(particle_->decayModes());
DecaySet::const_iterator start(modes.begin()),end(modes.end());
tcDMPtr mode;
for(;start!=end;++start) {
decayModes_.push_back(const_ptr_cast<DMPtr>(*start));
}
}
// set up the interpolators
interpolators_.resize(MEtype_.size());
vector<Energy>::iterator estart(interMasses_.begin()),eend;
vector<Energy>::iterator wstart(interWidths_.begin()),wend;
vector<Energy> masses,widths;
for(unsigned int ix=0;ix<MEtype_.size();++ix) {
eend=interMasses_.begin()+noOfEntries_[ix];
wend=interWidths_.begin()+noOfEntries_[ix];
if(MEtype_[ix]==2) {
masses.assign(estart,eend);
widths.assign(wstart,wend);
interpolators_[ix]= make_InterpolatorPtr(widths,masses,intOrder_);
}
estart=eend;
wstart=wend;
}
}
// setup the partial widths in the decayers for normalization
tDecayIntegratorPtr temp;
for(unsigned int ix=0;ix<decayModes_.size();++ix) {
if(!decayModes_[ix]) continue;
decayModes_[ix]->init();
decayer=dynamic_ptr_cast<tDecayIntegratorPtr>(decayModes_[ix]->decayer());
if(!decayer) continue;
decayer->init();
decayer->setPartialWidth(*decayModes_[ix],ix);
}
// code to output plots
// string fname = CurrentGenerator::current().filename() +
// string("-") + name() + string(".top");
// ofstream output(fname.c_str());
// Energy step = (particle_->massMax()-particle_->massMin())/100.;
// output << "SET FONT DUPLEX\n";
// output << "TITLE TOP \"Width for " << particle_->name() << "\"\n";
// output << "TITLE BOTTOM \"m/GeV\"\n";
// output << "TITLE LEFT \"G/GeV\"\n";
// output << "CASE \"F \"\n";
// output << "SET LIMITS X "
// << (particle_->massMin()-10.*step)/GeV << " "
// << particle_->massMax()/GeV << "\n";
// Energy upper(ZERO);
// for(Energy etest=particle_->massMin();etest<particle_->massMax();etest+=step) {
// Energy gamma=width(*particle_,etest);
// upper = max(gamma,upper);
// output << etest/GeV << "\t" << gamma/GeV << "\n";
// }
// output << "SET LIMITS Y 0. " << upper/GeV << "\n";
// output << "JOIN\n";
// output << (particle_->massMin()-9.*step)/GeV << "\t"
// << upper*(MEcode_.size()+1)/(MEcode_.size()+2)/GeV << "\n";
// output << (particle_->massMin()-7.*step)/GeV << "\t"
// << upper*(MEcode_.size()+1)/(MEcode_.size()+2)/GeV << "\n";
// output << "JOIN\n";
// output << "TITLE DATA "
// << (particle_->massMin()-6.*step)/GeV << "\t"
// << upper*(MEcode_.size()+1)/(MEcode_.size()+2)/GeV
// << " \"total\"\n";
// for(unsigned int ix=0;ix<MEcode_.size();++ix) {
// for(Energy etest=particle_->massMin();etest<particle_->massMax();etest+=step) {
// output << etest/GeV << "\t" << partialWidth(ix,etest)*prefactor_/GeV << "\n";
// }
// switch(ix) {
// case 0: output << "join red\n" ; break;
// case 1: output << "join blue\n" ; break;
// case 2: output << "join green\n" ; break;
// case 3: output << "join yellow\n" ; break;
// case 4: output << "join magenta\n"; break;
// case 5: output << "join cyan\n" ; break;
// case 6: output << "join dashes\n" ; break;
// case 7: output << "join dotted\n" ; break;
// case 8: output << "join dotdash\n"; break;
// default: output << "join daashes space\n"; break;
// }
// output << (particle_->massMin()-9.*step)/GeV << "\t"
// << upper*(MEcode_.size()-ix)/(MEcode_.size()+2)/GeV << "\n";
// output << (particle_->massMin()-7.*step)/GeV << "\t"
// << upper*(MEcode_.size()-ix)/(MEcode_.size()+2)/GeV << "\n";
// switch(ix) {
// case 0: output << "join red\n" ; break;
// case 1: output << "join blue\n" ; break;
// case 2: output << "join green\n" ; break;
// case 3: output << "join yellow\n" ; break;
// case 4: output << "join magenta\n"; break;
// case 5: output << "join cyan\n" ; break;
// case 6: output << "join dashes\n" ; break;
// case 7: output << "join dotted\n" ; break;
// case 8: output << "join dotdash\n"; break;
// default: output << "join daashes space\n"; break;
// }
// output << "TITLE DATA "
// << (particle_->massMin()-6.*step)/GeV << "\t"
// << upper*(MEcode_.size()-ix)/(MEcode_.size()+2)/GeV
// << " \"" << decayTags_[ix] << "\"\n";
// }
}
void GenericWidthGenerator::dataBaseOutput(ofstream & output, bool header) {
if(header) output << "update Width_Generators set parameters=\"";
// prefactor and general switiches
output << "newdef " << name() << ":Prefactor " << prefactor_ << "\n";
output << "newdef " << name() << ":BRNormalize " << BRnorm_ << "\n";
output << "newdef " << name() << ":BRMinimum " << BRminimum_ << "\n";
output << "newdef " << name() << ":Points " << npoints_ << "\n";
output << "newdef " << name() << ":InterpolationOrder " << intOrder_ << "\n";
// the type of the matrix element
for(unsigned int ix=0;ix<MEtype_.size();++ix) {
output << "insert " << name() << ":MEtype " << ix << " "
<< MEtype_[ix] << "\n";
}
// the code for thew two body matrix elements
for(unsigned int ix=0;ix<MEcode_.size();++ix) {
output << "insert " << name() << ":MEcode "
<< ix << " " << MEcode_[ix] << "\n";
}
// the coupling for trhe two body matrix elements
for(unsigned int ix=0;ix<MEcoupling_.size();++ix) {
output << "insert " << name() << ":MEcoupling "
<< ix << " " << MEcoupling_[ix] << "\n";
}
// use this mode for the running width
for(unsigned int ix=0;ix<modeOn_.size();++ix) {
output << "insert " << name() << ":ModeOn "
<< ix << " " << modeOn_[ix] << "\n";
}
// first outgoing mass
for(unsigned int ix=0;ix<minMass_.size();++ix) {
output << "insert " << name() << ":MinimumMasses "
<< ix << " " << minMass_[ix]/GeV << "\n";
}
// first outgoing mass
for(unsigned int ix=0;ix<MEmass1_.size();++ix) {
output << "insert " << name() << ":MEmass1 "
<< ix << " " << MEmass1_[ix]/GeV << "\n";
}
// second outgoing mass
for(unsigned int ix=0;ix<MEmass2_.size();++ix) {
output << "insert " << name() << ":MEmass2 "
<< ix << " " << MEmass2_[ix]/GeV << "\n";
}
for(unsigned int ix=0;ix<decayModes_.size();++ix) {
output << "insert " << name() << ":DecayModes "
<< ix << " " << decayTags_[ix] << " \n";
}
// data for the interpolation tables
std::streamsize curpre=output.precision();
output.precision(curpre+2);
for(unsigned int ix=0;ix<interMasses_.size();++ix) {
output << "insert " << name()
<< ":InterpolationMasses "
<< ix << " " << interMasses_[ix]/GeV << "\n";
}
for(unsigned int ix=0;ix<interWidths_.size();++ix) {
output << "insert " << name()
<< ":InterpolationWidths "
<< ix << " " << interWidths_[ix]/GeV << "\n";
}
output.precision(curpre);
for(unsigned int ix=0;ix<noOfEntries_.size();++ix) {
output << "insert " << name()
<< ":NumberofEntries "
<< ix << " " << noOfEntries_[ix] << "\n";
}
if(header) output << "\n\" where BINARY ThePEGName=\"" << name()
<< "\";" << endl;
}
DecayMap GenericWidthGenerator::rate(const Particle & p) {
// return default if not using running widths
if(!particle_->variableRatio()) return p.data().decaySelector();
// use the running widths to generate the branching ratios
Energy scale(p.mass());
DecayMap dm;
Energy width = particle_->width();
for(unsigned int ix=0;ix<decayModes_.size();++ix) {
dm.insert(partialWidth(ix,scale)/width,
p.id()==particle_->id() ?
decayModes_[ix] : decayModes_[ix]->CC());
}
return dm;
}
void GenericWidthGenerator::setupMode(tcDMPtr, tDecayIntegratorPtr,
unsigned int)
{}
Energy GenericWidthGenerator::partialWidth(int imode,Energy q) const {
if(q<minMass_[imode]) return ZERO;
Energy gamma;
if(MEtype_[imode]==0) {
gamma=MEcoupling_[imode]*particle_->width();
}
else if(MEtype_[imode]==1) {
gamma=partial2BodyWidth(imode,q);
}
else if(MEtype_[imode]==2) {
gamma=MEcoupling_[imode]*(*interpolators_[imode])(q);
}
else {
throw Exception() << "Unknown type of mode " << MEtype_[imode]
<< "in GenericWidthGenerator::partialWidth()"
<< Exception::runerror;
}
return max(gamma,ZERO);
}
void GenericWidthGenerator::dofinish() {
if(initialize_) {
string fname = CurrentGenerator::current().filename() +
string("-") + name() + string(".output");
ofstream output(fname.c_str());
dataBaseOutput(output,true);
}
WidthGenerator::dofinish();
}
void GenericWidthGenerator::rebind(const TranslationMap & trans) {
particle_ = trans.translate(particle_);
WidthGenerator::rebind(trans);
}
IVector GenericWidthGenerator::getReferences() {
IVector ret = WidthGenerator::getReferences();
ret.push_back(particle_);
return ret;
}
Length GenericWidthGenerator::lifeTime(const ParticleData &, Energy m, Energy w) const {
if(m<particle_->massMin()) w = width(*particle_,particle_->massMin());
else if(m>particle_->massMax()) w = width(*particle_,particle_->massMax());
return UseRandom::rndExp(hbarc/w);
}
Energy GenericWidthGenerator::partial2BodyWidth(int imode, Energy q,Energy m1,
Energy m2) const {
using Constants::pi;
if(q<m1+m2) return ZERO;
// calcluate the decay momentum
Energy2 q2(q*q),m02(mass_*mass_),m12(m1*m1),m22(m2*m2),
pcm2(0.25*(q2*(q2-2.*m12-2.*m22)+(m12-m22)*(m12-m22))/q2);
if(MEcode_[imode]==-1) return q/mass_*particle_->width();
Energy pcm(sqrt(pcm2));
double gam(0.);
switch(MEcode_[imode]) {
// V -> P P
case 0: gam = pcm2/6./q2;
break;
// V -> P V
case 1: gam = pcm2/12./m02;
break;
// V -> f fbar
case 2: gam = 1./12.*(q2*(2.*q2-m12-m22+6.*m1*m2)
-(m12-m22)*(m12-m22))/q2/q2;
break;
// P -> VV
case 3: gam = 0.25*pcm2/m02;
break;
// A -> VP
case 4: gam = (2.*pcm2+3.*m12)/24./m02;
break;
// V -> VV
case 5: gam = pcm2/3./q2*(1.+m12/q2+m22/q2);
break;
// S -> SS
case 6: gam = 0.125/q2*m02;
break;
// T -> PP
case 7: gam = pcm2*pcm2/60./q2/m02;
break;
// T -> VP
case 8: gam = pcm2*pcm2/40./m02/m02;
break;
// T -> VV
case 9: gam = 1./30./q2/q2/m02*
(3.*q2*(8.*pcm2*pcm2+5.*(m12*m22+pcm2*(m12+m22)))
-5.*(m12-m22)*(m12-m22)*pcm2);
break;
// P -> PV
case 10: gam = 0.5*pcm2/m22;
break;
// P -> PT
case 11: gam = sqr(pcm2)/12.*q2/m12/m12/m02;
break;
// S -> VV
case 12: gam = 0.125*(2.*pcm2+3.*m12*m22/q2)/m02;
break;
// unknown
default:
throw Exception() << "Unknown type of mode " << MEcode_[imode]
<< " in GenericWidthGenerator::partial2BodyWidth() "
<< Exception::abortnow;
}
return gam*pcm*sqr(MEcoupling_[imode])/pi;
}
pair<Energy,Energy>
GenericWidthGenerator::width(Energy m, const ParticleData & ) const {
pair<Energy,Energy> gamma(make_pair(ZERO,ZERO));
for(unsigned int ix=0;ix<decayModes_.size();++ix) {
if(modeOn_[ix]) {
Energy partial = partialWidth(ix,m);
gamma.second += partial;
if(decayModes_[ix]->on())
gamma.first += partial;
}
}
gamma.first *= prefactor_;
gamma.second *= prefactor_;
return gamma;
}
diff --git a/PDT/OneOffShellCalculator.h b/PDT/OneOffShellCalculator.h
--- a/PDT/OneOffShellCalculator.h
+++ b/PDT/OneOffShellCalculator.h
@@ -1,205 +1,205 @@
// -*- C++ -*-
//
// OneOffShellCalculator.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_OneOffShellCalculator_H
#define HERWIG_OneOffShellCalculator_H
//
// This is the declaration of the OneOffShellCalculator class.
//
#include "GenericMassGenerator.h"
#include "WidthCalculatorBase.h"
#include "OneOffShellCalculator.fh"
#include "Herwig++/Utilities/GSLIntegrator.h"
namespace Herwig {
using namespace ThePEG;
struct OneOffShellIntegrand;
/** \ingroup PDT
*
* Use another <code>WidthCalculatorBase</code> object to integrate over the
* mass of on of the external particles which can be off-shell for running
* width calculations.
*
* @see WidthCalculatorBase
* @see OneOffShellIntegrand
*
*/
class OneOffShellCalculator: public WidthCalculatorBase {
public:
/**
* The OneOffShellIntegrand is a friend to allow access to the members needed
* for the integration without making the members public.
*/
- friend class OneOffShellIntegrand;
+ friend struct OneOffShellIntegrand;
public:
/**
* Constructor which should be used setting all the required members.
* @param inloc The mass which is off-shell and to be integrated over.
* @param inwidth Pointer to the WidthGeneratorBase object which calculates
* the partial width for a given mass of the off-shell particle.
* @param inmass Pointer to the GenericMassGenerator for the off-shell particle.
* @param inmin The minimum mass for the off-shell particle.
*/
OneOffShellCalculator(int inloc,WidthCalculatorBasePtr inwidth,
GenericMassGeneratorPtr inmass,
Energy inmin)
: _themass(inloc), _minmass(inmin),_onshellwidth(inwidth),_massptr(inmass)
{}
/**
* member to calculate the partial width.
* @param scale The mass squared for the decaying particle.
* @return The partial width.
*/
Energy partialWidth(Energy2 scale) const;
/**
* Get the mass of one of the decay products. This must be
* implemented in classes inheriting from this one.
* @param imass The mass required.
* @param mass The new value.
* @return The mass required.
*/
void resetMass(int imass,Energy mass) {
_onshellwidth->resetMass(imass,mass);
}
/**
* Get the mass of one of the decay products. This must be
* implemented in classes inheriting from this one.
* @param imass The mass required.
* @return The mass required.
*/
Energy getMass(const int imass) const {
return _onshellwidth->getMass(imass);
}
/**
* Get the masses of all bar the one specified. Used to get the limits
* for integration.
* @param imass The particle not needed
* @return The sum of the other masses.
*/
Energy otherMass(const int imass) const {
return _onshellwidth->otherMass(imass);
}
protected:
/**
* The integrand.
* @param min The mass of the off-shell particle,
* @return The differential rate.
*/
Energy dGamma(Energy min) const {
_onshellwidth->resetMass(_themass,min);
Energy wgt = (_onshellwidth->partialWidth(_scale));
wgt*=(_massptr->weight(min));
return wgt;
}
private:
/**
* Private and non-existent assignment operator.
*/
OneOffShellCalculator & operator=(const OneOffShellCalculator &);
private:
/**
* which mass is offshell.
*/
int _themass;
/**
* the minimum allowed mass.
*/
Energy _minmass;
/**
* pointer to object calculating the on-shell width.
*/
WidthCalculatorBasePtr _onshellwidth;
/**
* pointer to object calculating the mass of the particle.
*/
GenericMassGeneratorPtr _massptr;
/**
* integrator
*/
GSLIntegrator _integrator;
/**
* the mass squared of the decaying particle
*/
mutable Energy2 _scale;
};
/** \ingroup PDT
* Class for the integrand of a matrix element where one of the outgoing
* particles is off-shell.This class is used by the OneOffShellCalculator class
* to perform the integral.
*
* @see OneOffShellCalculator
*/
struct OneOffShellIntegrand {
/**
* Constructor.
* @param in Pointer to the OneOffShellCalculator class this is doing the
* integration for.
* @param m2 The mass squared of the off-shell particle for the Jacobian
* transform.
* @param mw The mass times width of the off-shell particle for the Jacobian
* transform.
*/
OneOffShellIntegrand(tcOneOffShellCalculatorPtr in,Energy2 m2,Energy2 mw)
: _integrand(in),_mass2(m2),_mwidth(mw)
{}
/**
* return the value
*/
Energy operator ()(double x) const {
return _integrand->dGamma(sqrt(_mass2+_mwidth*tan(x)));
}
/** Argument type for the GSLIntegrator */
typedef double ArgType;
/** Return type for the GSLIntegrator */
typedef Energy ValType;
/**
* pointer to the decay integrator
*/
tcOneOffShellCalculatorPtr _integrand;
/**
* The mass squared for the off-shell particle for the Jacobian transform.
*/
Energy2 _mass2;
/**
* The mass times width for the off-shell particle for the Jacobian transform.
*/
Energy2 _mwidth;
};
}
#endif /* HERWIG_OneOffShellCalculator_H */
diff --git a/PDT/SMHiggsMassGenerator.cc b/PDT/SMHiggsMassGenerator.cc
--- a/PDT/SMHiggsMassGenerator.cc
+++ b/PDT/SMHiggsMassGenerator.cc
@@ -1,84 +1,86 @@
// -*- C++ -*-
//
// SMHiggsMassGenerator.cc is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the SMHiggsMassGenerator class.
//
#include "SMHiggsMassGenerator.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace Herwig;
void SMHiggsMassGenerator::persistentOutput(PersistentOStream & os) const {
os << _shape << _hwidth;
}
void SMHiggsMassGenerator::persistentInput(PersistentIStream & is, int) {
is >> _shape >> _hwidth;
}
ClassDescription<SMHiggsMassGenerator> SMHiggsMassGenerator::initSMHiggsMassGenerator;
// Definition of the static class description member.
void SMHiggsMassGenerator::Init() {
static ClassDocumentation<SMHiggsMassGenerator> documentation
("The SMHiggsMassGenerator class implements the mass distribution for the"
" Higgs boson as in hep-ph/9505211.",
"The Higgs mass was distributed as in \\cite{Seymour:1995qg}.",
"%\\cite{Seymour:1995qg}\n"
"\\bibitem{Seymour:1995qg}\n"
" M.~H.~Seymour,\n"
" %``The Higgs boson line shape and perturbative unitarity,''\n"
" Phys.\\ Lett.\\ B {\\bf 354}, 409 (1995)\n"
" [arXiv:hep-ph/9505211].\n"
" %%CITATION = PHLTA,B354,409;%%\n"
);
static Switch<SMHiggsMassGenerator,unsigned int> interfaceHiggsShape
("HiggsShape",
"The distribution for the Higgs mass",
&SMHiggsMassGenerator::_shape, 1, false, false);
static SwitchOption interfaceHiggsShapeNormal
(interfaceHiggsShape,
"Normal",
"The standard running width distribution",
0);
static SwitchOption interfaceHiggsShapeImproved
(interfaceHiggsShape,
"Improved",
"The improved shape of hep-ph/9505211",
1);
}
bool SMHiggsMassGenerator::accept(const ParticleData & part) const {
if(part.id()!=ParticleID::h0) return false;
return GenericMassGenerator::accept(part);
}
void SMHiggsMassGenerator::doinit() {
- if(particle()->widthGenerator()) {
- _hwidth=dynamic_ptr_cast<GenericWidthGeneratorPtr>(particle()->widthGenerator());
+ if(particle()->massGenerator()==this) {
+ if(particle()->widthGenerator()) {
+ _hwidth=dynamic_ptr_cast<GenericWidthGeneratorPtr>(particle()->widthGenerator());
+ }
+ if(!_hwidth) throw InitException()
+ << "Must be using the Herwig::GenericWidthGenerator in "
+ << "SMHiggsMassGenerator::doinit()" << Exception::runerror;
}
- if(!_hwidth) throw InitException()
- << "Must be using the Herwig::GenericWidthGenerator in "
- << "SMHiggsMassGenerator::doinit()" << Exception::runerror;
GenericMassGenerator::doinit();
}
void SMHiggsMassGenerator::dataBaseOutput(ofstream & output,bool header) {
if(header) output << "update Mass_Generators set parameters=\"";
output << "newdef " << fullName() << ":BreitWignerShape " << _shape << "\n";
if(header) output << "\n\" where BINARY ThePEGName=\"" << fullName() << "\";" << endl;
}
diff --git a/PDT/SMHiggsWidthGenerator.cc b/PDT/SMHiggsWidthGenerator.cc
--- a/PDT/SMHiggsWidthGenerator.cc
+++ b/PDT/SMHiggsWidthGenerator.cc
@@ -1,398 +1,396 @@
// -*- C++ -*-
//
// SMHiggsWidthGenerator.cc is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the SMHiggsWidthGenerator class.
//
#include "SMHiggsWidthGenerator.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/StandardModel/StandardModelBase.h"
using namespace Herwig;
IBPtr SMHiggsWidthGenerator::clone() const {
return new_ptr(*this);
}
IBPtr SMHiggsWidthGenerator::fullclone() const {
return new_ptr(*this);
}
void SMHiggsWidthGenerator::persistentOutput(PersistentOStream & os) const {
os << widthopt_ << offshell_ << ounit(mw_,GeV) << ounit(mz_,GeV)
<< ounit(gamw_,GeV) << ounit(gamz_,GeV) << ounit(qmass_,GeV)
<< ounit(lmass_,GeV) << sw2_ << ca_ << cf_ << locMap_;
}
void SMHiggsWidthGenerator::persistentInput(PersistentIStream & is, int) {
is >> widthopt_ >> offshell_ >> iunit(mw_,GeV) >> iunit(mz_,GeV)
>> iunit(gamw_,GeV) >> iunit(gamz_,GeV) >> iunit(qmass_,GeV)
>> iunit(lmass_,GeV) >> sw2_ >> ca_ >> cf_ >> locMap_;
}
ClassDescription<SMHiggsWidthGenerator> SMHiggsWidthGenerator::initSMHiggsWidthGenerator;
// Definition of the static class description member.
void SMHiggsWidthGenerator::Init() {
static ClassDocumentation<SMHiggsWidthGenerator> documentation
("The SMHiggsWidthGenerator class calculates the running Higgs width as in "
"hep-ph/9505211.",
"The Higgs width was calculated as in \\cite{Seymour:1995qg}.",
"%\\cite{Seymour:1995qg}\n"
"\\bibitem{Seymour:1995qg}\n"
" M.~H.~Seymour,\n"
" %``The Higgs boson line shape and perturbative unitarity,''\n"
" Phys.\\ Lett.\\ B {\\bf 354}, 409 (1995)\n"
" [arXiv:hep-ph/9505211].\n"
" %%CITATION = PHLTA,B354,409;%%\n"
);
static Switch<SMHiggsWidthGenerator,unsigned int> interfaceWidthOption
("WidthScheme",
"Option for the treatment of the Higss Width calculation",
&SMHiggsWidthGenerator::widthopt_, 2, false, false);
static SwitchOption interfaceFixedWidth
(interfaceWidthOption,
"Fixed",
"Fixed Higgs width, taken from ThePEGParticles.in",
1);
static SwitchOption interfaceNLLWidth
(interfaceWidthOption,
"NLLcorrected",
"NLL corrected Higgs width (a-la FORTRAN HERWIG)",
2);
static SwitchOption interfaceLOWidthOption
(interfaceWidthOption,
"LO",
"LO Higgs width (formula taken from The \"Higgs Hunter's Guide\")",
3);
static Parameter<SMHiggsWidthGenerator,double> interfaceOffShell
("OffShell",
"Number of times the width the Higgs is allowed to be off-shell",
&SMHiggsWidthGenerator::offshell_, 10., 0.01, 100.0,
false, false, Interface::limited);
}
Energy SMHiggsWidthGenerator::width(const ParticleData & in, Energy m) const {
if(widthopt_==1) {
return in.width();
}
else if(widthopt_ <=3 ) {
Energy higgswidth = ZERO;
for (unsigned int i = 0; i < decayModes().size(); ++i)
higgswidth += partialWidth(i,m);
return higgswidth;
}
else
throw Exception() << "Unknown width option in SMHiggsWidthGenerator::width()"
<< Exception::runerror;
}
DecayMap SMHiggsWidthGenerator::rate(const ParticleData & p) const {
if(mw_==ZERO) return p.decaySelector();
else return branching(p.mass(),p);
}
DecayMap SMHiggsWidthGenerator::rate(const Particle & p) {
return branching(p.mass(),p.data());
}
DecayMap SMHiggsWidthGenerator::branching(Energy scale,
const ParticleData & p) const {
// if not using running width return original
if(widthopt_==1) return p.decaySelector();
// calculate the partial widths
vector<Energy> partial;
Energy total(ZERO);
for(unsigned int ix=0;ix<decayModes().size();++ix) {
partial.push_back(partialWidth(ix,scale));
total+=partial.back();
}
// produce the new decay selector
DecayMap newdm;
for(unsigned int ix=0;ix<decayModes().size();++ix) {
tDMPtr mode = decayModes()[ix];
if(mode->orderedProducts().size()!=2||!mode->on()) continue;
double br = partial[ix]/total;
// insert the mode into the new selector
newdm.insert(br,mode);
}
return newdm;
}
// Taken from HERWIG 6510.
Complex SMHiggsWidthGenerator::HwW2(double tau) const {
using Constants::pi;
if (tau > 1.0) {
return sqr(asin(1.0/sqrt(tau)));
}
else if (tau < 1.0) {
double FNsqr = sqrt(1-tau);
double FNlog = log((1+FNsqr)/(1-FNsqr));
return Complex(-0.25 * (sqr(FNlog)-pi*pi),0.5*pi*FNlog);
}
else {
return sqr(0.5*pi);
}
}
Energy SMHiggsWidthGenerator::partialWidth(int iloc,Energy Mh) const {
useMe();
using Constants::pi;
if(Mh!=qlast_) {
qlast_ = Mh;
Energy2 q2 = sqr(qlast_);
// couplings
lambdaQCD_ = generator()->standardModel()->LambdaQCD(q2);
alphaEM_ = generator()->standardModel()->alphaEM();
alphaS_ = generator()->standardModel()->alphaS(q2);
// QCD correction factors for H -> f fbar
double nflavour=0.;
for (unsigned int i =1; i <= 6; ++i)
if (2.0*qmass_[i] < Mh) nflavour+=1.;
// All calculation are being done for Monte-Carlo QCD Lambda, except Higgs width...
// not needed in C++ as should be normal lambda
// MC only in shower
//double bcoeff4=(11.*ca_-10.)/(12.*pi);
//double kfac=ca_*(67./18.-sqr(pi)/6.)-25./9.;
//lambdaQCD_ /= exp(kfac/(4.*pi*bcoeff4))/sqrt(2.);
double k1 = 5./sqr(pi);
double k0 = 3./(4.*sqr(pi));
beta0_ = (11.*ca_-2.0*nflavour)/3.;
double beta1 = (34.*sqr(ca_)-(10.*ca_+6.*cf_)*nflavour)/3.;
gam0_ = -8.;
double gam1 = -404./3.+40.*nflavour/9.;
double SClog = log(sqr(Mh/lambdaQCD_));
if(SClog<=0.)
cd_ = 1.;
else
cd_ = 1.+(k1/k0-2.*gam0_+gam0_*beta1/sqr(beta0_)*log(SClog)+
(gam0_*beta1-gam1*beta0_)/sqr(beta0_))/(beta0_*SClog);
gfermiinv_ = 8.*sw2_*sqr(mw_)/alphaEM_;
}
// output value
Energy3 output(ZERO);
// work out which mode
map<int,int>::const_iterator it = locMap_.find(iloc);
if(it==locMap_.end()) return ZERO;
int imode = it->second;
// quark modes
if(imode<=6) {
Energy mf = qmass_[imode];
double xf = sqr(mf/Mh);
if( xf >= 0.25 ) return ZERO;
if(widthopt_==2) {
if (mf > lambdaQCD_) mf *= pow(log(Mh/lambdaQCD_)/log(mf/lambdaQCD_),
gam0_/(2.0*beta0_));
output = ca_*Mh*sqr(mf)*pow(1.0-4.0*xf,1.5)*cd_;
}
else {
output = ca_*Mh*sqr(mf)*pow(1.0-4.0*xf,1.5);
}
}
// lepton modes
else if(imode<=9) {
Energy mf = lmass_[imode-7];
double xf = sqr(mf/Mh);
if (xf < 0.25) output = Mh*sqr(mf)*pow(1.0-4.0*xf,1.5);
}
// H->W*W*
else if(imode==10) {
if(widthopt_==2) {
double xw = sqr(mw_/Mh);
double yw = mw_*gamw_/sqr(Mh);
output = pow<3,1>(Mh)*HwDoubleBW(xw,yw)/2.;
}
else {
double xfw = sqr(mw_/Mh);
if(2.0*mw_ < Mh) output = pow<3,1>(Mh)*sqrt(1-4.0*xfw)*(1-xfw+0.75*sqr(xfw))/2.;
}
}
// H->Z*Z*
else if(imode==11) {
if(widthopt_==2) {
double xz = sqr(mz_/Mh);
double yz = mz_*gamz_/sqr(Mh);
output = pow<3,1>(Mh)*HwDoubleBW(xz,yz)/4.;
}
else {
double xfz = sqr(mz_/Mh);
if (2.0*mz_ < Mh) output = pow<3,1>(Mh)*sqrt(1-4.0*xfz)*(1-xfz+0.75*sqr(xfz))/4.;
}
}
// H->gamma gamma
else if(imode==12) {
double taut = sqr(2.0*qmass_[ParticleID::t]/Mh);
double tauw = sqr(2.0*mw_/Mh);
Complex ftaut = HwW2 (taut);
Complex ftauw = HwW2 (tauw);
double re = 4.0/3.0*(-2.0*taut*(1.0+(1.0-taut)*ftaut.real())) +
(2.0+3.0*tauw*(1+(2.0-tauw)*ftauw.real()));
double im = 4.0/3.0*(-2.0*taut*( (1.0-taut)*ftaut.imag())) +
( 3.0*tauw*( (2.0-tauw)*ftauw.imag()));
output = sqr(alphaEM_/pi)*pow<3,1>(Mh)*(sqr(re)+ sqr(im))/32.;
}
// H -> gg
else if(imode==13) {
double tau = sqr(2.0*qmass_[ParticleID::t]/Mh);
Complex ftau = HwW2(tau);
double re = 1+(1.0-tau)*ftau.real();
double im = (1.0-tau)*ftau.imag();
output = sqr(alphaS_/pi)*pow<3,1>(Mh)*sqr(tau)*(sqr(re)+ sqr(im))/4.;
}
return output/gfermiinv_;
}
// Taken from HERWIG 6510.
double SMHiggsWidthGenerator::HwDoubleBW(double x, double y) const {
// Calculate the Double Breit-Wigner Integral
// x=(mw/mh)**2, y=mw*gw/mh**2
double limit = 0.425;
double nbin = 25;
double itgerl = 0.0;
if (y < 0.0) return itgerl;
if (x > limit) {
// Direct Integration
double fac1 = 0.25/nbin;
for (unsigned int i = 0; i < nbin; ++i) {
double x1 = (i+0.5)*fac1;
double fac2 = (sqr(1-sqrt(x1))-x1)/nbin;
double sq = 1.0;
int j = 0;
while (j < nbin && 0.0 < sq) {
double x2 = (j+0.5)*fac2+x1;
sq = 1.0+x1*x1+x2*x2-2*(x1+x2+x1*x2);
itgerl += 2.0*(sqr(1-x1-x2)+8.0*x1*x2)*sqrt(sq)
/(sqr(x1-x)+y*y)*y/(sqr(x2-x)+y*y)*y*fac1*fac2;
++j;
}
}
}
else {
// Integration using tan theta substitution
double th1low = atan2 ((0.0-x),y);
double th1high = atan2 ((1.0-x),y);
double fac1 = (th1high-th1low)/nbin;
for (unsigned int i = 0; i < nbin; ++i) {
double th1 = (i+0.5)*fac1+th1low;
double x1 = y*tan(th1)+x;
double x2max = min(x1,sqr(1-sqrt(x1)));
double th2low = atan2 ((0-x),y);
double th2high = atan2 ((x2max-x),y);
double fac2 = (th2high-th2low)/nbin;
double sq = 1.0;
int j = 0;
while (j < nbin && 0.0 < sq) {
double th2 = (j+0.5)*fac2+th2low;
double x2 = y*tan(th2)+x;
double sq = 1.0+x1*x1+x2*x2-2*(x1+x2+x1*x2);
itgerl += 2.0*(sqr(1-x1-x2)+8*x1*x2)*sqrt(sq)*fac1*fac2;
++j;
}
}
}
itgerl *= 1/sqr(Constants::pi);
return itgerl;
}
void SMHiggsWidthGenerator::doinit() {
GenericWidthGenerator::doinit();
// extract W and Z mass and width
tPDPtr w = getParticleData(ParticleID::Wplus);
tPDPtr z = getParticleData(ParticleID::Z0);
mw_ = w->mass();
mz_ = z->mass();
gamw_ = w->width();
gamz_ = z->width();
// quark masses
for(int ix=1;ix<7;++ix) {
tcPDPtr q = getParticleData(ix);
qmass_[ix] = q->mass();
}
// lepton masses
for ( int ix=0; ix<3; ++ix ) {
tcPDPtr lepton = getParticleData(11+2*ix);
lmass_[ix] = lepton->mass();
}
// sin2 theta_w
sw2_ = generator()->standardModel()->sin2ThetaW();
// casmirs
double ncolour = generator()->standardModel()->Nc();
ca_ = ncolour;
cf_ = (sqr(ncolour)-1.0)/(2.0*ca_);
// construct the map
for(unsigned int ix=0;ix<decayModes().size();++ix) {
tDMPtr mode = decayModes()[ix];
if(mode->orderedProducts().size()!=2) continue;
// particle antiparticle
long id=abs(mode->orderedProducts()[0]->id());
if(mode->orderedProducts()[0]->id()==-mode->orderedProducts()[1]->id()) {
- // quarks
- if(id<=6)
- id=id;
+ // do nothing for quarks.
// leptons
- else if(id>=11&&id<=15&&(id-9)%2==0)
+ if(id>=11&&id<=15&&(id-9)%2==0)
id = (id+3)/2;
// WW
else if(id==ParticleID::Wplus)
id = 10;
// unknown mode
else continue;
}
else if(mode->orderedProducts()[0]->id()==mode->orderedProducts()[1]->id()) {
// gamma gamma
if(id==ParticleID::Z0) id = 11;
else if(id==ParticleID::gamma) id = 12;
else if(id==ParticleID::g) id = 13;
// unknown mode
else continue;
}
// unknown mode
else continue;
// set pu the map
locMap_[ix] = id;
}
// reset the width and set the limits
if(particle()->id() != ParticleID::h0)
throw Exception() << "Must be the Standard Model Higgs boson "
<< "in SMHiggsWidthGenerator::doinit()"
<< Exception::runerror;
Energy wid = width(*particle(),particle()->mass());
particle()->width (wid);
particle()->widthCut(offshell_*wid);
}
pair<Energy,Energy> SMHiggsWidthGenerator::width(Energy scale,
const ParticleData & p) const {
if(widthopt_==1) return make_pair(p.width(),p.width());
// calculate the partial widths
vector<Energy> partial;
Energy total(ZERO);
for(unsigned int ix=0;ix<decayModes().size();++ix) {
partial.push_back(partialWidth(ix,scale));
total += partial.back();
}
// sum for the on modes
Energy partialon(ZERO);
for(unsigned int ix=0;ix<decayModes().size();++ix) {
tDMPtr mode= decayModes()[ix];
if(!mode->on()||mode->orderedProducts().size()!=2) continue;
partialon += partial[ix];
}
return make_pair(partialon,total);
}
diff --git a/PDT/ThreeBodyAllOnCalculator.h b/PDT/ThreeBodyAllOnCalculator.h
--- a/PDT/ThreeBodyAllOnCalculator.h
+++ b/PDT/ThreeBodyAllOnCalculator.h
@@ -1,272 +1,279 @@
// -*- C++ -*-
//
// ThreeBodyAllOnCalculator.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_ThreeBodyAllOnCalculator_H
#define HERWIG_ThreeBodyAllOnCalculator_H
// This is the declaration of the ThreeBodyAllOnCalculator class.
#include "WidthCalculatorBase.h"
#include "Herwig++/Utilities/GSLIntegrator.h"
#include "Herwig++/Decay/DecayIntegrator.h"
#include "Herwig++/Decay/DecayPhaseSpaceMode.h"
namespace Herwig {
using namespace ThePEG;
template <class T>
class ThreeBodyAllOnCalculator;
/** \ingroup PDT
*
* The ThreeBodyAllOnCalculator class is designed to integrate
* a three-body matrix element in which all the outgoing particles are
* on-shell to give the partial width. A multi-channel type approach is
* used together with a GSL integration subroutine.
*
* @see GSLIntegrator
* @see ThreeBodyAllOnOuter
* @see ThreeBodyAllOnIner
*
*/
template <class T>
class ThreeBodyAllOnCalculator: public WidthCalculatorBase {
/** \ingroup PDT
* The class for the outer integrand of the integral of a three body decay matrix
* element. This class is used by the ThreeBodyAllOnCalculator
* to perform the outer integral.
*
* @see ThreeBodyAllOnCalculator
* @see ThreeBodyAllOnInner
- */
-struct Outer {
+ */ struct Outer {
/**
* Constructor with a pointer to the ThreeBodyAllOnCalculator
*/
- Outer(typename Ptr<Herwig::ThreeBodyAllOnCalculator<T> >::const_pointer in)
- : _integrand(in)
+ Outer(typename Ptr<Herwig::ThreeBodyAllOnCalculator<T> >::const_pointer in,
+ double relerr)
+ : _integrand(in), _integrator(1e-35,relerr,1000)
{}
/**
* Retreive function value
*/
Energy4 operator ()(double x) const {
Energy2 low, upp;
_integrand->outerVariables(x,low,upp);
return _integrator.value(*_integrand,low,upp);
}
/** Argument type for the GSLIntegrator */
typedef double ArgType;
/** Return type for the GSLIntegrator */
typedef Energy4 ValType;
/**
* pointer to the decay integrator
*/
typename Ptr<Herwig::ThreeBodyAllOnCalculator<T> >::const_pointer _integrand;
/**
* GSL integration class
*/
GSLIntegrator _integrator;
};
public:
/**
* The ThreeBodyAllOnOuter class is a friend so it can access the private
* members and perform the integral.
*/
friend struct ThreeBodyAllOnOuter;
public:
/**
* Constructor with all the parameters
* @param inweights The weights for the different integration channels
* @param intype The types of the different integration channels.
* @param inmass The mass for the Jacobian for the different channels.
* @param inwidth The width for the Jacobian for the different channels.
* @param inpow the power for power-law smoothing for a given channel
* @param inme The pointer to the function which gives the matrix element.
* @param mode The mode to be integrated
* @param m1 The mass of the first particle.
* @param m2 The mass of the second particle.
* @param m3 The mass of the third particle.
*/
ThreeBodyAllOnCalculator(vector<double> inweights,
vector<int> intype,
vector<Energy> inmass,
vector<Energy> inwidth,
vector<double> inpow,
T inme, int mode,
- Energy m1,Energy m2,Energy m3)
+ Energy m1,Energy m2,Energy m3,
+ double relerr=1e-3)
: _channelweights(inweights),_channeltype(intype),_channelmass(inmass),
_channelwidth(inwidth),_channelpower(inpow),_theME(inme),_mode(mode),
- _thechannel(0),_souter(ZERO) {
+ _thechannel(0),_souter(ZERO), _integrator(1e-35,relerr,1000),
+ _relerr(relerr) {
_m.resize(4);
_m[1]=m1;_m[2]=m2;_m[3]=m3;
_m2.resize(4);
for(int ix=1;ix<4;++ix) {
_m2[ix]=sqr(_m[ix]);
}
}
/**
* calculate the width for a given mass
* @param q2 The mass squared of the decaying particle.
* @return The partial width.
*/
Energy partialWidth(Energy2 q2) const;
/**
* Get the mass of one of the decay products. This must be
* implemented in classes inheriting from this one.
* @param imass The mass required.
* @param mass The new value.
* @return The mass required.
*/
void resetMass(int imass,Energy mass) {
assert(imass<4);
_m[imass]=mass;
_m2[imass]=mass*mass;
}
/**
* Get the mass of one of the decay products. This must be
* implemented in classes inheriting from this one.
* @param imass The mass required.
* @return The mass required.
*/
Energy getMass(const int imass) const {
assert(imass>=0&&imass<4);
return _m[imass];
}
/**
* Get the masses of all bar the one specified. Used to get the limits
* for integration.
* @param imass The particle not needed
* @return The sum of the other masses.
*/
Energy otherMass(const int imass) const {
assert(imass>0&&imass<4);
if(imass==1) return _m[2]+_m[3];
else if(imass==2) return _m[1]+_m[3];
else return _m[1]+_m[2];
}
/**
* The integrand for the inner integrand.
* @param argument The mass squared for the inner integral
* @return The value of the inner integrand.
*/
Energy2 operator ()(Energy2 argument) const;
/** Argument type for the GSLIntegrator */
typedef Energy2 ArgType;
/** Return type for the GSLIntegrator */
typedef Energy2 ValType;
protected:
/**
* shift the variables for the outer integrand and give limits for the inner one.
* This member sets the value of the _souter member for the mass squared of the
* outer integral and calculates the limits on the mass squared of the inner
* integral.
* @param x The integration variable
* @param low The lower limit for the inner integral.
* @param upp The upper limit for the inner integral.
*/
void outerVariables(const double & x, Energy2 & low, Energy2 & upp) const;
private:
/**
* Private and non-existent assignment operator.
*/
ThreeBodyAllOnCalculator & operator=(const ThreeBodyAllOnCalculator &);
private:
/**
* weights for the different channels
*/
vector<double> _channelweights;
/**
* the types for the different channels
*/
vector<int> _channeltype;
/**
* the mass of the resonance for a given channel
*/
vector<Energy> _channelmass;
/**
* the width of the resonance for a given channel
*/
vector<Energy> _channelwidth;
/**
* the power for power-law smoothing for a given channel
*/
vector<double> _channelpower;
/**
* Function giving the matrix element as a function of s12,s13,s23
*/
T _theME;
/**
* The mode
*/
int _mode;
/**
* the channel currently being integrated
*/
mutable int _thechannel;
/**
* The mapping currently in used
*/
mutable int _mapping;
/**
* the value of s for the outer integral
*/
mutable Energy2 _souter;
/**
* masses of the external particles
*/
mutable vector<Energy> _m;
/**
* mass squareds of the external particles
*/
mutable vector<Energy2> _m2;
/**
* member to do the integration
*/
GSLIntegrator _integrator;
+
+ /**
+ * Relative error for the integration
+ */
+ double _relerr;
};
}
#ifndef ThePEG_TEMPLATES_IN_CC_FILE
#include "ThreeBodyAllOnCalculator.tcc"
#endif
#endif /* HERWIG_ThreeBodyAllOnCalculator_H */
diff --git a/PDT/ThreeBodyAllOnCalculator.tcc b/PDT/ThreeBodyAllOnCalculator.tcc
--- a/PDT/ThreeBodyAllOnCalculator.tcc
+++ b/PDT/ThreeBodyAllOnCalculator.tcc
@@ -1,189 +1,191 @@
// -*- C++ -*-
//
// ThreeBodyAllOnCalculator.tcc is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined templated member
// functions of the ThreeBodyAllOnCalculator class.
//
using namespace Herwig;
// shift the variables for the outer integrand and give limits for the inner one
template <class T>
void ThreeBodyAllOnCalculator<T>::outerVariables(const double & x, Energy2 & low,
Energy2 & upp) const {
// first convert the value of x into the value of souter
if(_mapping==0) {
_souter = _channelmass[_thechannel]*(_channelmass[_thechannel]+
_channelwidth[_thechannel]*tan(x));
}
else if(_mapping==1) {
_souter = sqr(_channelmass[_thechannel])*(1.+1./x);
}
else {
_souter = UnitRemoval::E2 * pow(x,1./(_channelpower[_thechannel]+1.));
}
// now the limits of the inner integral
Energy ea(ZERO),eb(ZERO);
Energy rs=sqrt(_souter);
- Energy2 eam2,ebm2;
+ Energy2 eam2(ZERO),ebm2(ZERO);
switch(_channeltype[_thechannel]) {
case 1:
ea = 0.5*(_souter-_m2[1]+_m2[2])/rs;
eam2 = sqr(ea)-_m2[2];
eb = 0.5*(_m2[0]-_souter-_m2[3])/rs;
ebm2 = sqr(eb)-_m2[3];
break;
case 2:
ea = 0.5*(_souter-_m2[1]+_m2[3])/rs;
eam2 = sqr(ea)-_m2[3];
eb = 0.5*(_m2[0]-_souter-_m2[2])/rs;
ebm2 = sqr(eb)-_m2[2];
break;
case 3:
ea = 0.5*(_souter-_m2[2]+_m2[3])/rs;
eam2 = sqr(ea)-_m2[3];
eb = 0.5*(_m2[0]-_souter-_m2[1])/rs;
ebm2 = sqr(eb)-_m2[1];
break;
+ default:
+ assert(false);
}
Energy eam = sqrt(max(ZERO,eam2));
Energy ebm = sqrt(max(ZERO,ebm2));
Energy2 sum = sqr(ea+eb);
// calculate the limits
low = sum - sqr(eam+ebm);
upp = sum - sqr(eam-ebm);
}
template <class T>
Energy2 ThreeBodyAllOnCalculator<T>::operator ()(Energy2 y) const {
assert(!isnan(y/MeV2));
// set up the values of the s variables
Energy2 s12(ZERO),s23(ZERO),s13(ZERO),
m2sum(_m2[0]+_m2[1]+_m2[2]+_m2[3]);
switch(_channeltype[_thechannel]) {
case 1:
s12 = _souter;
s23 = y;
s13 = m2sum-s12-s23;
break;
case 2:
s23 = y;
s13 = _souter;
s12 = m2sum-s23-s13;
break;
case 3:
s23 = _souter;
s13 = y;
s12 = m2sum-s23-s13;
break;
}
// compute the jacobian
// computer the denominator for the jacobian
InvEnergy2 jacdem = ZERO;
Energy2 sjac(ZERO);
Energy2 rm2,rw2;
for(unsigned int ix=0,N=_channeltype.size(); ix<N; ++ix) {
switch(_channeltype[ix]) {
case 1:
sjac = s12;
break;
case 2:
sjac = s13;
break;
case 3:
sjac = s23;
break;
}
assert(!isnan(sjac/MeV2));
InvEnergy2 term;
if(_mapping==0) {
rm2 = sqr(_channelmass[ix]);
rw2 = sqr(_channelwidth[ix]);
Energy4 tmp = sqr(sjac-rm2) + rw2*rm2;
term = _channelweights[ix]*_channelmass[ix]*_channelwidth[ix]/tmp;
}
else if(_mapping==1) {
term = _channelweights[ix]*sqr(_channelmass[ix]/(sjac-sqr(_channelmass[ix])));
}
else {
term = UnitRemoval::InvE2 * _channelweights[ix]*(_channelpower[ix]+1.)*
pow(sjac*UnitRemoval::InvE2, _channelpower[ix]);
}
jacdem += term;
}
// now computer the matrix element
return _theME.threeBodyMatrixElement(_mode,_m2[0],s12,s13,
s23,_m[1],_m[2],_m[3])/jacdem;
}
// calculate the width for a given mass
template <class T>
Energy ThreeBodyAllOnCalculator<T>::partialWidth(Energy2 q2) const {
- Outer outer(this);
+ Outer outer(this,_relerr);
_m[0] = sqrt(q2);
_m2[0]=q2;
// check the decay is kinematically allowed
if(_m[0]<_m[1]+_m[2]+_m[3]){return ZERO;}
// perform the integrals for all the different channels
Energy4 sum(ZERO);
for(unsigned int ix=0,N=_channeltype.size(); ix<N; ++ix) {
Energy2 upp(ZERO),low(ZERO);
// work out the kinematic limits
switch(_channeltype[ix]) {
case 1:
upp = sqr(_m[0]-_m[3]);
low = sqr(_m[1]+_m[2]);
break;
case 2:
upp = sqr(_m[0]-_m[2]);
low = sqr(_m[1]+_m[3]);
break;
case 3:
upp = sqr(_m[0]-_m[1]);
low = sqr(_m[2]+_m[3]);
break;
default:
assert(false);
}
double rupp, rlow;
// transform them
if(_channelmass[ix] > ZERO) {
if(_channelwidth[ix] > 1e-8*MeV) {
rupp = atan2((upp-_channelmass[ix]*_channelmass[ix]),
_channelmass[ix]*_channelwidth[ix]);
rlow = atan2((low-_channelmass[ix]*_channelmass[ix]),
_channelmass[ix]*_channelwidth[ix]);
_mapping = 0;
if(rupp/rlow>0.&&_channelwidth[ix]/_channelmass[ix]<1e-6) {
_mapping = 1;
Energy2 m2=sqr(_channelmass[ix]);
rupp = m2/(low-m2);
rlow = m2/(upp-m2);
}
}
else {
_mapping = 1;
Energy2 m2=sqr(_channelmass[ix]);
rupp = m2/(low-m2);
rlow = m2/(upp-m2);
}
}
else {
_mapping = 2;
rupp = pow(upp*UnitRemoval::InvE2, _channelpower[ix]+1.);
rlow = pow(low*UnitRemoval::InvE2, _channelpower[ix]+1.);
}
// perform the integral using GSLIntegrator class
_thechannel=ix;
- GSLIntegrator intb;
+ GSLIntegrator intb(1e-35,_relerr,1000);
sum += _channelweights[ix] * intb.value(outer,rlow,rupp);
}
// final factors
Energy3 fact = pow<3,1>(Constants::twopi * _m[0]);
return sum/fact/32.;
}
diff --git a/PDT/TwoOffShellCalculator.h b/PDT/TwoOffShellCalculator.h
--- a/PDT/TwoOffShellCalculator.h
+++ b/PDT/TwoOffShellCalculator.h
@@ -1,208 +1,208 @@
// -*- C++ -*-
//
// TwoOffShellCalculator.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_TwoOffShellCalculator_H
#define HERWIG_TwoOffShellCalculator_H
//
// This is the declaration of the TwoOffShellCalculator class.
//
#include "WidthCalculatorBase.h"
#include "GenericMassGenerator.h"
#include "TwoOffShellCalculator.fh"
#include "OneOffShellCalculator.fh"
#include "Herwig++/Utilities/GSLIntegrator.h"
namespace Herwig {
using namespace ThePEG;
-class TwoOffShellIntegrand;
+struct TwoOffShellIntegrand;
/** \ingroup PDT
*
* Use <code>WidthCalculatorBase</code> objects to integrate over the mass of two
* external particles which can be off-shell for running width calculations.
*
* @see WidthCalculatorBase
* @see TwoOffShellIntegrand
*/
class TwoOffShellCalculator: public WidthCalculatorBase {
/**
* The TwoOffShellIntegrand class is a friend to allow access to the private
* members for the integration.
*/
-friend class TwoOffShellIntegrand;
+friend struct TwoOffShellIntegrand;
public:
/**
* Constructor which should be used setting all the required members.
* @param inloc The mass which is off-shell and to be integrated over.
* @param inwidth Pointer to the WidthGeneratorBase object which calculates
* the partial width for a given mass of the off-shell particle. This
* should be a OneOffShellCalculator instance.
* @param inmass Pointer to the GenericMassGenerator for the off-shell particle.
* @param inmin1 The minimum mass for the first off-shell particle.
* @param inmin2 The minimum mass for the second off-shell particle.
*/
TwoOffShellCalculator(int inloc, WidthCalculatorBasePtr inwidth,
GenericMassGeneratorPtr inmass,
Energy inmin2,Energy inmin1)
: _themass(inloc),_minmass(inmin2),_mother(inmin1),_oneoffwidth(inwidth),
_massptr(inmass)
{}
/**
* member to calculate the partial width.
* @param scale The mass squared for the decaying particle.
* @return The partial width.
*/
Energy partialWidth(Energy2 scale) const;
/**
* Get the mass of one of the decay products. This must be
* implemented in classes inheriting from this one.
* @param imass The mass required.
* @param mass The new value.
* @return The mass required.
*/
void resetMass(int imass,Energy mass) {
_oneoffwidth->resetMass(imass,mass);
}
/**
* Get the mass of one of the decay products. This must be
* implemented in classes inheriting from this one.
* @param imass The mass required.
* @return The mass required.
*/
Energy getMass(const int imass) const {
return _oneoffwidth->getMass(imass);
}
/**
* Get the masses of all bar the one specified. Used to get the limits
* for integration.
* @param imass The particle not needed
* @return The sum of the other masses.
*/
Energy otherMass(const int imass) const {
return _oneoffwidth->otherMass(imass);
}
protected:
/**
* The integrand.
* @param mass The mass of the second off-shell particle,
* @return The differential rate.
*/
Energy dGamma(Energy mass) const {
_oneoffwidth->resetMass(_themass,mass);
Energy wgt = (_oneoffwidth->partialWidth(_scale));
wgt*=(_massptr->weight(mass));
return wgt;
}
private:
/**
* Private and non-existent assignment operator.
*/
TwoOffShellCalculator & operator=(const TwoOffShellCalculator &);
private:
/**
* The second mass which is offshell
*/
int _themass;
/**
* the minimum allowed mass
*/
Energy _minmass;
/**
* sum of the masses of the other decay products
*/
Energy _mother;
/**
* pointer to object calculating the width for one-off shell particle.
*/
WidthCalculatorBasePtr _oneoffwidth;
/**
* pointer to object calculating the mass of the particle
*/
GenericMassGeneratorPtr _massptr;
/**
* integrator
*/
GSLIntegrator _integrator;
/**
* the mass squared of the decaying particle
*/
mutable Energy2 _scale;
};
/** \ingroup PDT
* Class for the integrand of a matrix element where two of the outgoing
* particles is off-shell. This class is used by the TwoOffShellCalculator class
* to perform the integral.
*/
struct TwoOffShellIntegrand {
/**
* Constructor.
* @param in Pointer to the OneOffShellCalculator class this is doing the
* integration for.
* @param m2 The mass squared of the off-shell particle for the Jacobian
* transform.
* @param mw The mass times width of the off-shell particle for the Jacobian
* transform.
*/
TwoOffShellIntegrand(tcTwoOffShellCalculatorPtr in,Energy2 m2,Energy2 mw)
: _integrand(in),_mass2(m2),_mwidth(mw)
{}
/**
* Retreive function value
*/
Energy operator ()(double x) const {
return _integrand->dGamma(sqrt(_mass2+_mwidth*tan(x)));
}
/** Argument type for the GSLIntegrator */
typedef double ArgType;
/** Return type for the GSLIntegrator */
typedef Energy ValType;
private:
/**
* pointer to the decay integrator
*/
cTwoOffShellCalculatorPtr _integrand;
/**
* The mass squared for the off-shell particle for the Jacobian transform.
*/
Energy2 _mass2;
/**
* The mass times width for the off-shell particle for the Jacobian transform.
*/
Energy2 _mwidth;
};
}
#endif /* HERWIG_TwoOffShellCalculator_H */
diff --git a/Tests/Makefile.am b/Tests/Makefile.am
--- a/Tests/Makefile.am
+++ b/Tests/Makefile.am
@@ -1,230 +1,239 @@
AUTOMAKE_OPTIONS = -Wno-portability
AM_LDFLAGS += -module -avoid-version -rpath /dummy/path/not/used
EXTRA_DIST = Inputs python Rivet
dist-hook:
rm -rf $(distdir)/Inputs/.svn
rm -rf $(distdir)/python/.svn
rm -rf $(distdir)/Rivet/.svn
EXTRA_LTLIBRARIES = LeptonTest.la GammaTest.la HadronTest.la DISTest.la
if WANT_LIBFASTJET
EXTRA_LTLIBRARIES += HadronJetTest.la LeptonJetTest.la
HadronJetTest_la_SOURCES = \
Hadron/VHTest.h Hadron/VHTest.cc\
Hadron/VTest.h Hadron/VTest.cc\
Hadron/HTest.h Hadron/HTest.cc
HadronJetTest_la_CPPFLAGS = $(AM_CPPFLAGS) $(FASTJETINCLUDE) \
-I$(FASTJETPATH)
HadronJetTest_la_LIBADD = $(FASTJETLIBS)
LeptonJetTest_la_SOURCES = \
Lepton/TopDecay.h Lepton/TopDecay.cc
LeptonJetTest_la_CPPFLAGS = $(AM_CPPFLAGS) $(FASTJETINCLUDE) \
-I$(FASTJETPATH)
LeptonJetTest_la_LIBADD = $(FASTJETLIBS)
endif
LeptonTest_la_SOURCES = \
Lepton/VVTest.h Lepton/VVTest.cc \
Lepton/VBFTest.h Lepton/VBFTest.cc \
Lepton/VHTest.h Lepton/VHTest.cc \
Lepton/FermionTest.h Lepton/FermionTest.cc
GammaTest_la_SOURCES = \
Gamma/GammaMETest.h Gamma/GammaMETest.cc \
Gamma/GammaPMETest.h Gamma/GammaPMETest.cc
DISTest_la_SOURCES = \
DIS/DISTest.h DIS/DISTest.cc
HadronTest_la_SOURCES = \
Hadron/HadronVVTest.h Hadron/HadronVVTest.cc\
Hadron/HadronVBFTest.h Hadron/HadronVBFTest.cc\
Hadron/WHTest.h Hadron/WHTest.cc\
Hadron/ZHTest.h Hadron/ZHTest.cc\
Hadron/VGammaTest.h Hadron/VGammaTest.cc\
Hadron/ZJetTest.h Hadron/ZJetTest.cc\
Hadron/WJetTest.h Hadron/WJetTest.cc\
Hadron/QQHTest.h Hadron/QQHTest.cc
REPO = $(top_builddir)/src/HerwigDefaults.rpo
HERWIG = $(top_builddir)/src/Herwig++
HWREAD = $(HERWIG) read -r $(REPO) -L $(builddir)/.libs
HWRUN = $(HERWIG) run
tests : tests-LEP tests-DIS tests-LHC tests-Gamma
if WANT_LIBFASTJET
tests-LEP : test-LEP-VV test-LEP-VH test-LEP-VBF test-LEP-BB test-LEP-Quarks test-LEP-Leptons \
test-LEP-default test-LEP-Powheg test-LEP-TopDecay
else
tests-LEP : test-LEP-VV test-LEP-VH test-LEP-VBF test-LEP-BB test-LEP-Quarks test-LEP-Leptons
endif
tests-DIS : test-DIS-Charged test-DIS-Neutral
if WANT_LIBFASTJET
tests-LHC : test-LHC-WW test-LHC-WZ test-LHC-ZZ test-LHC-ZGamma test-LHC-WGamma \
test-LHC-ZH test-LHC-WH test-LHC-ZJet test-LHC-WJet test-LHC-Z test-LHC-W test-LHC-ZZVBF test-LHC-VBF \
test-LHC-WWVBF test-LHC-bbH test-LHC-ttH test-LHC-GammaGamma test-LHC-GammaJet test-LHC-Higgs \
test-LHC-HiggsJet test-LHC-QCDFast test-LHC-QCD test-LHC-Top test-LHC-Bottom \
test-LHC-WHJet test-LHC-ZHJet test-LHC-HJet test-LHC-ZShower test-LHC-WShower\
test-LHC-WHJet-Powheg test-LHC-ZHJet-Powheg test-LHC-HJet-Powheg \
test-LHC-ZShower-Powheg test-LHC-WShower-Powheg
else
tests-LHC : test-LHC-WW test-LHC-WZ test-LHC-ZZ test-LHC-ZGamma test-LHC-WGamma \
test-LHC-ZH test-LHC-WH test-LHC-ZJet test-LHC-WJet test-LHC-Z test-LHC-W test-LHC-ZZVBF test-LHC-VBF \
test-LHC-WWVBF test-LHC-bbH test-LHC-ttH test-LHC-GammaGamma test-LHC-GammaJet test-LHC-Higgs \
test-LHC-HiggsJet test-LHC-QCDFast test-LHC-QCD test-LHC-Top
endif
tests-Gamma : test-Gamma-FF test-Gamma-WW test-Gamma-P
if WANT_LIBFASTJET
test-LEP-% : Inputs/LEP-%.in LeptonTest.la LeptonJetTest.la
$(HWREAD) $<
$(HWRUN) $(notdir $(subst .in,.run,$<)) -N $${NUMEVENTS:-10000}
else
test-LEP-% : Inputs/LEP-%.in LeptonTest.la
$(HWREAD) $<
$(HWRUN) $(notdir $(subst .in,.run,$<)) -N $${NUMEVENTS:-10000}
endif
Rivet-LEP-% : Rivet/LEP-%.in
$(HWREAD) $<
$(HWRUN) $(notdir $(subst .in,.run,$<)) -N $${NUMEVENTS:-10000}
Rivet-TVT-% : Rivet/TVT-%.in
$(HWREAD) $<
$(HWRUN) $(notdir $(subst .in,.run,$<)) -N $${NUMEVENTS:-10000}
-Rivet-TVT-% : Rivet/TVT-%.in
+
+Rivet-DIS-% : Rivet/DIS-%.in
$(HWREAD) $<
$(HWRUN) $(notdir $(subst .in,.run,$<)) -N $${NUMEVENTS:-10000}
Rivet-LHC-% : Rivet/LHC-%.in
$(HWREAD) $<
$(HWRUN) $(notdir $(subst .in,.run,$<)) -N $${NUMEVENTS:-10000}
Rivet-Star-% : Rivet/Star-%.in
$(HWREAD) $<
$(HWRUN) $(notdir $(subst .in,.run,$<)) -N $${NUMEVENTS:-10000}
Rivet-LEP: Rivet-LEP-22 Rivet-LEP-35 Rivet-LEP-44 Rivet-LEP-91 \
Rivet-LEP-133 Rivet-LEP-161 Rivet-LEP-172 Rivet-LEP-177 \
Rivet-LEP-183 Rivet-LEP-189 Rivet-LEP-196 Rivet-LEP-197 \
Rivet-LEP-200 Rivet-LEP-206 Rivet-LEP-14 \
Rivet-LEP-Powheg-14 Rivet-LEP-Powheg-22 \
Rivet-LEP-Powheg-35 Rivet-LEP-Powheg-44 \
Rivet-LEP-Powheg-91 Rivet-LEP-Powheg-133 \
Rivet-LEP-Powheg-161 Rivet-LEP-Powheg-172 \
Rivet-LEP-Powheg-177 Rivet-LEP-Powheg-183 \
Rivet-LEP-Powheg-189 Rivet-LEP-Powheg-196 \
Rivet-LEP-Powheg-197 Rivet-LEP-Powheg-200 \
Rivet-LEP-Powheg-206
for i in LEP-*.aida; do rivet-rmgaps $$i; done;
rivet-rmgaps LEP-91.aida;
rivet-rmgaps LEP-Powheg-91.aida
rm -rf Rivet-LEP
python/merge-LEP LEP
python/merge-LEP LEP-Powheg
rivet-mkhtml -o Rivet-LEP LEP.aida:Hw++ LEP-Powheg.aida:Hw++-Powheg
+Rivet-DIS: Rivet-DIS-e--LowQ2 \
+ Rivet-DIS-e+-LowQ2 Rivet-DIS-e+-HighQ2
+ rivet-rmgaps DIS-e+-LowQ2.aida
+ rivet-rmgaps DIS-e--LowQ2.aida
+ rivet-rmgaps DIS-e--HighQ2.aida
+ python/merge-DIS DIS
+ rivet-mkhtml -o Rivet-DIS DIS.aida
+
Rivet-TVT-WZ: Rivet-TVT-Run-I-Z Rivet-TVT-Powheg-Run-I-Z \
Rivet-TVT-Run-I-W Rivet-TVT-Powheg-Run-I-W \
Rivet-TVT-Run-I-WZ Rivet-TVT-Powheg-Run-I-WZ\
Rivet-TVT-Run-II-Z-e Rivet-TVT-Powheg-Run-II-Z-e \
Rivet-TVT-Run-II-Z-mu Rivet-TVT-Powheg-Run-II-Z-mu \
Rivet-TVT-Run-II-W Rivet-TVT-Powheg-Run-II-W
rivet-rmgaps TVT-Run-II-Z-e.aida;
rivet-rmgaps TVT-Powheg-Run-II-Z-e.aida;
rm -rf Rivet-TVT-WZ
python/merge-TVT-EW TVT-Run-II-W.aida TVT-Run-II-Z-{e,mu}.aida\
TVT-Run-I-{W,Z,WZ}.aida -o TVT-WZ.aida
python/merge-TVT-EW TVT-Powheg-Run-II-W.aida TVT-Powheg-Run-II-Z-{e,mu}.aida\
TVT-Powheg-Run-I-{W,Z,WZ}.aida -o TVT-Powheg-WZ.aida
rivet-mkhtml -o Rivet-TVT-WZ TVT-WZ.aida:Hw++ TVT-Powheg-WZ.aida:Hw++-Powheg
Rivet-TVT-Photon: Rivet-TVT-Run-II-DiPhoton Rivet-TVT-Run-II-PromptPhoton
# Rivet-TVT-Run-I-PromptPhoton
rm -rf Rivet-TVT-Photon
python/merge-aida TVT-Run-II-DiPhoton.aida TVT-Run-II-PromptPhoton.aida\
-o TVT-Photon.aida
rivet-mkhtml -o Rivet-TVT-Photon TVT-Photon.aida:Hw++
Rivet-TVT-Jets: Rivet-TVT-Run-II-Jets-1 Rivet-TVT-Run-II-Jets-2 \
Rivet-TVT-Run-II-Jets-3 Rivet-TVT-Run-II-Jets-4 \
Rivet-TVT-Run-II-Jets-5 Rivet-TVT-Run-II-Jets-6 \
Rivet-TVT-Run-II-Jets-7 Rivet-TVT-Run-II-Jets-8 \
Rivet-TVT-Run-II-Jets-9 Rivet-TVT-Run-II-Jets-10\
Rivet-TVT-Run-II-Jets-11 Rivet-TVT-Run-II-UE \
Rivet-TVT-Run-I-Jets-1 Rivet-TVT-Run-I-Jets-2 \
Rivet-TVT-Run-I-Jets-3 Rivet-TVT-Run-I-Jets-4 \
Rivet-TVT-Run-I-Jets-5 Rivet-TVT-Run-I-Jets-6 \
Rivet-TVT-Run-I-Jets-7 Rivet-TVT-Run-I-Jets-8\
Rivet-TVT-Run-I-UE\
Rivet-TVT-630-UE Rivet-TVT-630-Jets-1 \
Rivet-TVT-630-Jets-2 Rivet-TVT-630-Jets-3
rivet-rmgaps TVT-Run-I-Jets-4.aida
rm -rf Rivet-TVT-Jets
python/merge-TVT-Jets TVT
rivet-mkhtml -o Rivet-TVT-Jets TVT-Jets.aida:Hw++
Rivet-LHC-Jets: Rivet-LHC-7-Jets-1 Rivet-LHC-7-Jets-2 \
Rivet-LHC-7-Jets-3 Rivet-LHC-7-Jets-4 \
Rivet-LHC-7-Jets-5 Rivet-LHC-7-Jets-6 \
Rivet-LHC-7-Jets-7 Rivet-LHC-7-Jets-8 \
Rivet-LHC-7-Jets-9 Rivet-LHC-7-Jets-10 \
Rivet-LHC-7-Jets-11 Rivet-LHC-7-Jets-12 \
Rivet-LHC-7-Jets-13 Rivet-LHC-7-UE \
Rivet-LHC-2360-UE Rivet-LHC-900-UE
rm -rf Rivet-LHC-Jets
python/merge-LHC-Jets
rivet-mkhtml -o Rivet-LHC-Jets LHC-Jets.aida:Hw++
Rivet-Star: Rivet-Star-UE Rivet-Star-Jets-1 \
Rivet-Star-Jets-2 Rivet-Star-Jets-3 \
Rivet-Star-Jets-4
rm -rf Rivet-Star
rivet-rmgaps Star-UE.aida
python/merge-Star Star
rivet-mkhtml -o Rivet-Star Star.aida
Rivet-LHC-EW: Rivet-LHC-W-e Rivet-LHC-Powheg-W-e \
Rivet-LHC-W-mu Rivet-LHC-Powheg-W-mu \
Rivet-LHC-Z Rivet-LHC-Powheg-Z \
Rivet-LHC-WW Rivet-LHC-Powheg-WW\
Rivet-LHC-ZZ Rivet-LHC-Powheg-ZZ
rm -rf Rivet-LHC-EW;
python/merge-LHC-EW LHC-{W-e,W-mu,Z,WW,ZZ}.aida -o LHC-EW.aida;
python/merge-LHC-EW LHC-Powheg-{W-e,W-mu,Z,WW,ZZ}.aida -o LHC-Powheg-EW.aida;
rivet-mkhtml -o Rivet-LHC-EW LHC-EW.aida:Hw++ LHC-Powheg-EW.aida:Hw++-Powheg;
Rivet-LHC-Photon: Rivet-LHC-7-PromptPhoton Rivet-LHC-7-DiPhoton
rm -rf Rivet-LHC-Photon
python/merge-aida LHC-7-PromptPhoton.aida LHC-7-DiPhoton.aida -o LHC-Photon.aida
rivet-mkhtml -o Rivet-LHC-Photon LHC-Photon.aida:Hw++
test-Gamma-% : Inputs/Gamma-%.in GammaTest.la
$(HWREAD) $<
$(HWRUN) $(notdir $(subst .in,.run,$<)) -N $${NUMEVENTS:-10000}
test-DIS-% : Inputs/DIS-%.in DISTest.la
$(HWREAD) $<
$(HWRUN) $(notdir $(subst .in,.run,$<)) -N $${NUMEVENTS:-10000}
if WANT_LIBFASTJET
test-LHC-% : Inputs/LHC-%.in HadronTest.la GammaTest.la HadronJetTest.la
$(HWREAD) $<
$(HWRUN) $(notdir $(subst .in,.run,$<)) -N $${NUMEVENTS:-10000}
else
test-LHC-% : Inputs/LHC-%.in HadronTest.la GammaTest.la
$(HWREAD) $<
$(HWRUN) $(notdir $(subst .in,.run,$<)) -N $${NUMEVENTS:-10000}
endif
clean-local:
rm -f *.out *.log *.tex *.top *.run *.dump *.mult *.Bmult *.aida
diff --git a/Tests/Rivet/DIS-e+-HighQ2.in b/Tests/Rivet/DIS-e+-HighQ2.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/DIS-e+-HighQ2.in
@@ -0,0 +1,24 @@
+##################################################
+# Rivet analyses at HERA
+##################################################
+read DISBase.in
+
+##################################################
+# DIS parameters
+##################################################
+cd /Herwig/Generators
+set /Herwig/EventHandlers/DISHandler:BeamB /Herwig/Particles/p+
+set /Herwig/EventHandlers/DISLuminosity:BeamEMaxB 820.*GeV
+set /Herwig/EventHandlers/DISHandler:BeamA /Herwig/Particles/e+
+set /Herwig/EventHandlers/DISLuminosity:BeamEMaxA 27.5*GeV
+set /Herwig/Cuts/NeutralCurrentCut:MinW2 1000.
+set /Herwig/Cuts/NeutralCurrentCut:MaxW2 1000000.
+set /Herwig/Cuts/NeutralCurrentCut:MaxQ2 1000000.
+set /Herwig/Cuts/NeutralCurrentCut:MinQ2 40.
+set /Herwig/Cuts/DISCuts:MHatMin 0.
+
+# H1 energy flow analysis
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 H1_2000_S4129130
+
+cd /Herwig/Generators
+saverun DIS-e+-HighQ2 DISGenerator
diff --git a/Tests/Rivet/DIS-e+-LowQ2.in b/Tests/Rivet/DIS-e+-LowQ2.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/DIS-e+-LowQ2.in
@@ -0,0 +1,24 @@
+##################################################
+# Rivet analyses at HERA
+##################################################
+read DISBase.in
+
+##################################################
+# DIS parameters
+##################################################
+cd /Herwig/Generators
+set /Herwig/EventHandlers/DISHandler:BeamB /Herwig/Particles/p+
+set /Herwig/EventHandlers/DISLuminosity:BeamEMaxB 820.*GeV
+set /Herwig/EventHandlers/DISHandler:BeamA /Herwig/Particles/e+
+set /Herwig/EventHandlers/DISLuminosity:BeamEMaxA 27.5*GeV
+set /Herwig/Cuts/NeutralCurrentCut:MinW2 1000.
+set /Herwig/Cuts/NeutralCurrentCut:MaxW2 1000000.
+set /Herwig/Cuts/NeutralCurrentCut:MaxQ2 60.
+set /Herwig/Cuts/NeutralCurrentCut:MinQ2 2.5
+set /Herwig/Cuts/DISCuts:MHatMin 0.
+
+# H1 energy flow analysis
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 H1_2000_S4129130
+
+cd /Herwig/Generators
+saverun DIS-e+-LowQ2 DISGenerator
diff --git a/Tests/Rivet/DIS-e--LowQ2.in b/Tests/Rivet/DIS-e--LowQ2.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/DIS-e--LowQ2.in
@@ -0,0 +1,26 @@
+##################################################
+# Rivet analyses at HERA
+##################################################
+read DISBase.in
+
+##################################################
+# DIS parameters
+##################################################
+cd /Herwig/Generators
+set /Herwig/EventHandlers/DISHandler:BeamB /Herwig/Particles/p+
+set /Herwig/EventHandlers/DISLuminosity:BeamEMaxB 820.*GeV
+set /Herwig/EventHandlers/DISHandler:BeamA /Herwig/Particles/e-
+set /Herwig/EventHandlers/DISLuminosity:BeamEMaxA 26.7*GeV
+set /Herwig/Cuts/NeutralCurrentCut:MinW2 1000.
+set /Herwig/Cuts/NeutralCurrentCut:MaxW2 1000000.
+set /Herwig/Cuts/NeutralCurrentCut:MaxQ2 60.
+set /Herwig/Cuts/NeutralCurrentCut:MinQ2 2.5
+set /Herwig/Cuts/DISCuts:MHatMin 0.
+
+# H1 energy flow analysis
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 H1_1994_S2919893
+#insert /Herwig/Analysis/RivetAnalysis:Analyses 0 H1_1995_S3167097
+
+
+cd /Herwig/Generators
+saverun DIS-e--LowQ2 DISGenerator
diff --git a/Tests/Rivet/DISBase.in b/Tests/Rivet/DISBase.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/DISBase.in
@@ -0,0 +1,23 @@
+##################################################
+# Example generator based on DIS parameters
+# usage: Herwig++ read DIS.in
+##################################################
+
+set /Herwig/Particles/e-:PDF /Herwig/Partons/NoPDF
+set /Herwig/Particles/e+:PDF /Herwig/Partons/NoPDF
+
+cd /Herwig/MatrixElements/
+# Neutral current DIS
+insert SimpleDIS:MatrixElements[0] MEDISNC
+
+cd /Herwig/Generators
+set DISGenerator:NumberOfEvents 10000000
+set DISGenerator:RandomNumberGenerator:Seed 31122001
+set DISGenerator:DebugLevel 0
+set DISGenerator:PrintEvent 10
+set DISGenerator:MaxErrors 1000000
+set /Herwig/Shower/ShowerHandler:MPIHandler NULL
+cd /Herwig/Generators
+
+create ThePEG::RivetAnalysis /Herwig/Analysis/RivetAnalysis RivetAnalysis.so
+insert DISGenerator:AnalysisHandlers 0 /Herwig/Analysis/RivetAnalysis
diff --git a/Tests/Rivet/LEPBase-Powheg.in b/Tests/Rivet/LEPBase-Powheg.in
--- a/Tests/Rivet/LEPBase-Powheg.in
+++ b/Tests/Rivet/LEPBase-Powheg.in
@@ -1,36 +1,36 @@
##################################################
# base parameters for LEP analyses
##################################################
##################################################
# Technical parameters for this run
##################################################
cd /Herwig/Generators
set LEPGenerator:NumberOfEvents 100000000
set LEPGenerator:RandomNumberGenerator:Seed 31122001
-set LEPGenerator:DebugLevel 1
+set LEPGenerator:DebugLevel 0
set LEPGenerator:PrintEvent 10
set LEPGenerator:MaxErrors 10000
# no MPI
set LEPGenerator:EventHandler:CascadeHandler:MPIHandler NULL
##################################################
# Switch off ISR
##################################################
set /Herwig/Particles/e-:PDF /Herwig/Partons/NoPDF
set /Herwig/Particles/e+:PDF /Herwig/Partons/NoPDF
##################################################
# Create the Herwig analysis
##################################################
create ThePEG::RivetAnalysis /Herwig/Analysis/RivetAnalysis RivetAnalysis.so
insert LEPGenerator:AnalysisHandlers 0 /Herwig/Analysis/RivetAnalysis
##################################################
# Use the NLO q qbar matrix element
##################################################
create Herwig::O2AlphaS /Herwig/O2AlphaS
set /Herwig/Generators/LHCGenerator:StandardModelParameters:QCD/RunningAlphaS /Herwig/O2AlphaS
set /Herwig/Shower/Evolver:HardEmissionMode POWHEG
set /Herwig/Shower/AlphaQCD:AlphaMZ 0.118
insert /Herwig/MatrixElements/SimpleEE:MatrixElements 0 /Herwig/MatrixElements/PowhegMEee2gZ2qq
diff --git a/Tests/python/merge-DIS b/Tests/python/merge-DIS
new file mode 100755
--- /dev/null
+++ b/Tests/python/merge-DIS
@@ -0,0 +1,183 @@
+#! /usr/bin/env python
+import lighthisto
+import logging
+import sys
+
+if sys.version_info[:3] < (2,4,0):
+ print "rivet scripts require Python version >= 2.4.0... exiting"
+ sys.exit(1)
+
+import os, copy, re
+from math import sqrt
+
+## Try to load faster but non-standard cElementTree module
+try:
+ import xml.etree.cElementTree as ET
+except ImportError:
+ try:
+ import cElementTree as ET
+ except ImportError:
+ try:
+ import xml.etree.ElementTree as ET
+ except:
+ sys.stderr.write("Can't load the ElementTree XML parser: please install it!\n")
+ sys.exit(1)
+
+
+
+# #############################################
+
+def fillAbove(desthisto, sourcehistosbyptmin):
+ for i,b in enumerate(desthisto.getBins()):
+ ## Fill bins with pT-ordered histos (so that 'highest always wins')
+ for ptmin, h in sorted(sourcehistosbyptmin.iteritems()):
+ newb = h.getBin(i)
+ if b.xlow >= float(ptmin) :
+ b.val = newb.val
+ b.errplus = newb.errplus
+ b.errminus = newb.errminus
+ b._focus= newb._focus
+
+def merge(hpath):
+ global inhistos
+ global outhistos
+ try:
+ fillAbove(outhistos[hpath], inhistos[hpath])
+ except:
+ pass
+
+def useOne(hpath, sqrts):
+ global inhistos
+ global outhistos
+ try:
+ outhistos[hpath] = inhistos[hpath][float(sqrts)]
+ except:
+ pass
+if __name__ == "__main__":
+ import logging
+ from optparse import OptionParser, OptionGroup
+ parser = OptionParser(usage="%prog name")
+ verbgroup = OptionGroup(parser, "Verbosity control")
+ verbgroup.add_option("-v", "--verbose", action="store_const", const=logging.DEBUG, dest="LOGLEVEL",
+ default=logging.INFO, help="print debug (very verbose) messages")
+ verbgroup.add_option("-q", "--quiet", action="store_const", const=logging.WARNING, dest="LOGLEVEL",
+ default=logging.INFO, help="be very quiet")
+ parser.add_option_group(verbgroup)
+ (opts, args) = parser.parse_args()
+ logging.basicConfig(level=opts.LOGLEVEL, format="%(message)s")
+
+
+ ## Prefix used in dat file headers
+ headerprefix = "# "
+
+
+ ## Check args
+ if len(args) < 1:
+ logging.error("Must specify at least the name of the files")
+ sys.exit(1)
+
+# #######################################
+
+aidafiles=["-e--LowQ2.aida","-e+-LowQ2.aida","-e+-HighQ2.aida"]
+
+## Get histos
+inhistos = {}
+outhistos={}
+weights = {}
+
+for f in aidafiles:
+ file = args[0]+f
+ if(file.find("Low")> 0) :
+ q2=0
+ elif(file.find("High")>0) :
+ q2=50
+
+ if not os.access(file, os.R_OK):
+ logging.error("%s can not be read" % file)
+ break
+ try:
+ tree = ET.parse(file)
+ except:
+ logging.error("%s can not be parsed as XML" % file)
+ break
+ tree = ET.parse(file)
+ ## Get histos from this AIDA file
+ for dps in tree.findall("dataPointSet"):
+ h = lighthisto.Histo.fromDPS(dps)
+ # di-jet decorrelations
+ # jet shapes
+ if(h.fullPath().find("4129130")>0 ) :
+ if not inhistos.has_key(h.fullPath()):
+ inhistos[h.fullPath()] = {}
+ tmpE = inhistos[h.fullPath()]
+ if not tmpE.has_key(q2):
+ tmpE[q2] = h
+ else:
+ raise Exception("A set with q2 = %s already exists" % ( q2 ))
+ elif(h.fullPath().find("2919893")>0 ) :
+ outhistos[h.fullPath()] = h
+ else :
+ print '!!!!! DIDNT FIND',h.fullPath()
+
+## Make empty output histos if needed
+for hpath,hsets in inhistos.iteritems():
+ if( hpath.find("4129130")>0) :
+ outhistos[hpath] = copy.deepcopy(hsets.values()[0])
+ ## Empty the bin set for histos which we're going to merge
+ for i,b in enumerate(outhistos[hpath].getBins()):
+ b.val = 0
+ b.errplus = 0
+ b.errminus = 0
+ b._focus= None
+
+# H1 transverse energy
+useOne("/H1_2000_S4129130/d01-x01-y01","0")
+useOne("/H1_2000_S4129130/d02-x01-y01","0")
+useOne("/H1_2000_S4129130/d03-x01-y01","0")
+useOne("/H1_2000_S4129130/d04-x01-y01","0")
+useOne("/H1_2000_S4129130/d05-x01-y01","0")
+useOne("/H1_2000_S4129130/d06-x01-y01","0")
+useOne("/H1_2000_S4129130/d07-x01-y01","0")
+useOne("/H1_2000_S4129130/d08-x01-y01","0")
+useOne("/H1_2000_S4129130/d09-x01-y01","0")
+useOne("/H1_2000_S4129130/d10-x01-y01","0")
+useOne("/H1_2000_S4129130/d11-x01-y01","0")
+useOne("/H1_2000_S4129130/d12-x01-y01","0")
+useOne("/H1_2000_S4129130/d13-x01-y01","0")
+useOne("/H1_2000_S4129130/d14-x01-y01","0")
+useOne("/H1_2000_S4129130/d15-x01-y01","0")
+useOne("/H1_2000_S4129130/d16-x01-y01","50")
+useOne("/H1_2000_S4129130/d17-x01-y01","50")
+useOne("/H1_2000_S4129130/d18-x01-y01","50")
+useOne("/H1_2000_S4129130/d19-x01-y01","50")
+useOne("/H1_2000_S4129130/d20-x01-y01","50")
+useOne("/H1_2000_S4129130/d21-x01-y01","50")
+useOne("/H1_2000_S4129130/d22-x01-y01","50")
+useOne("/H1_2000_S4129130/d23-x01-y01","50")
+useOne("/H1_2000_S4129130/d24-x01-y01","50")
+useOne("/H1_2000_S4129130/d25-x01-y01","0")
+useOne("/H1_2000_S4129130/d26-x01-y01","0")
+useOne("/H1_2000_S4129130/d27-x01-y01","0")
+useOne("/H1_2000_S4129130/d28-x01-y01","0")
+useOne("/H1_2000_S4129130/d29-x01-y01","50")
+useOne("/H1_2000_S4129130/d30-x01-y01","50")
+useOne("/H1_2000_S4129130/d31-x01-y01","50")
+useOne("/H1_2000_S4129130/d32-x01-y01","50")
+
+merge("/H1_2000_S4129130/d33-x01-y01")
+merge("/H1_2000_S4129130/d34-x01-y01")
+
+# Choose output file
+name = args[0]+".aida"
+out = open(name, "w")
+## Write out merged histos
+out.write('<?xml version="1.0" encoding="ISO-8859-1" ?>\n')
+out.write('<!DOCTYPE aida SYSTEM "http://aida.freehep.org/schemas/3.3/aida.dtd">\n')
+out.write('<aida version="3.3">\n')
+out.write(' <implementation version="1.1" package="FreeHEP"/>\n')
+for hpath, h in sorted(outhistos.iteritems()):
+ logging.debug("hpath = %s" % hpath)
+ out.write(h.asAIDA() + "\n\n")
+out.write('</aida>\n')
+
+sys.exit(0)
diff --git a/Tests/python/merge-LEP b/Tests/python/merge-LEP
--- a/Tests/python/merge-LEP
+++ b/Tests/python/merge-LEP
@@ -1,655 +1,656 @@
#! /usr/bin/env python
import lighthisto
import logging
import sys
if sys.version_info[:3] < (2,4,0):
print "rivet scripts require Python version >= 2.4.0... exiting"
sys.exit(1)
import os, copy, re
from math import sqrt
## Try to load faster but non-standard cElementTree module
try:
import xml.etree.cElementTree as ET
except ImportError:
try:
import cElementTree as ET
except ImportError:
try:
import xml.etree.ElementTree as ET
except:
sys.stderr.write("Can't load the ElementTree XML parser: please install it!\n")
sys.exit(1)
# #############################################
def fillAbove(desthisto, sourcehistosbyptmin):
for i,b in enumerate(desthisto.getBins()):
## Fill bins with pT-ordered histos (so that 'highest always wins')
for ptmin, h in sorted(sourcehistosbyptmin.iteritems()):
newb = h.getBin(i)
if newb.xlow <= float(ptmin) and newb.xhigh >=float(ptmin):
b.val = newb.val
b.errplus = newb.errplus
b.errminus = newb.errminus
- b.focus= newb.focus
+ b._focus= newb._focus
def merge(hpath):
global inhistos
global outhistos
try:
fillAbove(outhistos[hpath], inhistos[hpath])
except:
pass
def useOne(hpath, sqrts):
global inhistos
global outhistos
try:
outhistos[hpath] = inhistos[hpath][float(sqrts)]
except:
pass
if __name__ == "__main__":
import logging
from optparse import OptionParser, OptionGroup
parser = OptionParser(usage="%prog name")
verbgroup = OptionGroup(parser, "Verbosity control")
verbgroup.add_option("-v", "--verbose", action="store_const", const=logging.DEBUG, dest="LOGLEVEL",
default=logging.INFO, help="print debug (very verbose) messages")
verbgroup.add_option("-q", "--quiet", action="store_const", const=logging.WARNING, dest="LOGLEVEL",
default=logging.INFO, help="be very quiet")
parser.add_option_group(verbgroup)
(opts, args) = parser.parse_args()
logging.basicConfig(level=opts.LOGLEVEL, format="%(message)s")
## Prefix used in dat file headers
headerprefix = "# "
## Check args
if len(args) < 1:
logging.error("Must specify at least the name of the files")
sys.exit(1)
# #######################################
aidafiles=["-133.aida","-177.aida","-196.aida","-206.aida","-91.aida" ,\
"-161.aida","-183.aida","-197.aida","-35.aida" ,"-172.aida",\
"-189.aida","-200.aida","-44.aida","-14.aida","-22.aida" ]
## Get histos
inhistos = {}
outhistos={}
weights = {}
for f in aidafiles:
file = args[0]+f
if(file.find("14")>0) :
sqrts=14
elif(file.find("22")>0) :
sqrts=22
elif(file.find("35")>0) :
sqrts=35
elif(file.find("44")>0) :
sqrts=44
elif(file.find("91")>0) :
sqrts=91
elif(file.find("133")>0) :
sqrts=133
elif(file.find("161")>0) :
sqrts=161
elif(file.find("172")>0) :
sqrts=172
elif(file.find("177")>0) :
sqrts=177
elif(file.find("183")>0) :
sqrts=183
elif(file.find("189")>0) :
sqrts=189
elif(file.find("196")>0) :
sqrts=196
elif(file.find("197")>0) :
sqrts=197
elif(file.find("200")>0) :
sqrts=200
elif(file.find("206")>0) :
sqrts=206
if not os.access(file, os.R_OK):
logging.error("%s can not be read" % file)
break
try:
tree = ET.parse(file)
except:
logging.error("%s can not be parsed as XML" % file)
break
tree = ET.parse(file)
## Get histos from this AIDA file
for dps in tree.findall("dataPointSet"):
h = lighthisto.Histo.fromDPS(dps)
# di-jet decorrelations
# jet shapes
if(h.fullPath().find("4300807")>0 or h.fullPath().find("6132243")>0 or
h.fullPath().find("5765862")>0 or h.fullPath().find("3612880")>0 or
h.fullPath().find("2148048")>0 ) :
if not inhistos.has_key(h.fullPath()):
inhistos[h.fullPath()] = {}
tmpE = inhistos[h.fullPath()]
if not tmpE.has_key(sqrts):
tmpE[sqrts] = h
else:
raise Exception("A set with sqrts = %s already exists" % ( sqrts))
elif(h.fullPath().find("4553896")>0 or h.fullPath().find("MULTIPLICITIES")>0 or
h.fullPath().find("2435284")>0 or h.fullPath().find("3486095")>0 or
h.fullPath().find("3430090")>0 or h.fullPath().find("3137023")>0 or
h.fullPath().find("3780481")>0 or h.fullPath().find("WUD_03_11")>0 or
- h.fullPath().find("CONF_603")>0 ) :
+ h.fullPath().find("CONF_603")>0 or h.fullPath().find("3196992")>0 or
+ h.fullPath().find("2692198")>0) :
outhistos[h.fullPath()] = h
else :
print '!!!!! DIDNT FIND',h.fullPath()
## Make empty output histos if needed
for hpath,hsets in inhistos.iteritems():
- if( h.fullPath().find("4300807")>0 or h.fullPath().find("6132243")>0 or h.fullPath().find("5765862")>0) :
+ if( hpath.find("4300807")>0 or hpath.find("6132243")>0 or hpath.find("5765862")>0) :
workhisto = copy.deepcopy(hsets.values()[0])
outhistos[hpath] = workhisto
## Empty the bin set for histos which we're going to merge
for b in outhistos[hpath]:
b.val = 0
b.errplus = 0
b.errminus = 0
b._focus= None
# tasso
useOne("/TASSO_1990_S2148048/d06-x01-y01","14")
useOne("/TASSO_1990_S2148048/d07-x01-y01","14")
useOne("/TASSO_1990_S2148048/d08-x01-y01","14")
useOne("/TASSO_1990_S2148048/d06-x01-y02","22")
useOne("/TASSO_1990_S2148048/d07-x01-y02","22")
useOne("/TASSO_1990_S2148048/d08-x01-y02","22")
useOne("/TASSO_1990_S2148048/d06-x01-y03","35")
useOne("/TASSO_1990_S2148048/d07-x01-y03","35")
useOne("/TASSO_1990_S2148048/d08-x01-y03","35")
useOne("/TASSO_1990_S2148048/d06-x01-y04","44")
useOne("/TASSO_1990_S2148048/d07-x01-y04","44")
useOne("/TASSO_1990_S2148048/d08-x01-y04","44")
# jade
useOne("/JADE_1998_S3612880/d02-x01-y01","44")
useOne("/JADE_1998_S3612880/d03-x01-y01","44")
useOne("/JADE_1998_S3612880/d04-x01-y01","44")
useOne("/JADE_1998_S3612880/d05-x01-y01","44")
useOne("/JADE_1998_S3612880/d06-x01-y01","35")
useOne("/JADE_1998_S3612880/d07-x01-y01","35")
useOne("/JADE_1998_S3612880/d08-x01-y01","35")
useOne("/JADE_1998_S3612880/d09-x01-y01","35")
useOne("/JADE_1998_S3612880/d10-x01-y01","44")
useOne("/JADE_1998_S3612880/d11-x01-y01","22")
# opal/jade
useOne("/JADE_OPAL_2000_S4300807/d07-x01-y01","35")
useOne("/JADE_OPAL_2000_S4300807/d07-x01-y02","35")
useOne("/JADE_OPAL_2000_S4300807/d07-x01-y03","35")
useOne("/JADE_OPAL_2000_S4300807/d07-x01-y04","35")
useOne("/JADE_OPAL_2000_S4300807/d07-x01-y05","35")
useOne("/JADE_OPAL_2000_S4300807/d08-x01-y01","44")
useOne("/JADE_OPAL_2000_S4300807/d08-x01-y02","44")
useOne("/JADE_OPAL_2000_S4300807/d08-x01-y03","44")
useOne("/JADE_OPAL_2000_S4300807/d08-x01-y04","44")
useOne("/JADE_OPAL_2000_S4300807/d08-x01-y05","44")
useOne("/JADE_OPAL_2000_S4300807/d09-x01-y01","91")
useOne("/JADE_OPAL_2000_S4300807/d09-x01-y02","91")
useOne("/JADE_OPAL_2000_S4300807/d09-x01-y03","91")
useOne("/JADE_OPAL_2000_S4300807/d09-x01-y04","91")
useOne("/JADE_OPAL_2000_S4300807/d09-x01-y05","91")
useOne("/JADE_OPAL_2000_S4300807/d10-x01-y01","133")
useOne("/JADE_OPAL_2000_S4300807/d10-x01-y02","133")
useOne("/JADE_OPAL_2000_S4300807/d10-x01-y03","133")
useOne("/JADE_OPAL_2000_S4300807/d10-x01-y04","133")
useOne("/JADE_OPAL_2000_S4300807/d10-x01-y05","133")
useOne("/JADE_OPAL_2000_S4300807/d11-x01-y01","161")
useOne("/JADE_OPAL_2000_S4300807/d11-x01-y02","161")
useOne("/JADE_OPAL_2000_S4300807/d11-x01-y03","161")
useOne("/JADE_OPAL_2000_S4300807/d11-x01-y04","161")
useOne("/JADE_OPAL_2000_S4300807/d11-x01-y05","161")
useOne("/JADE_OPAL_2000_S4300807/d12-x01-y01","172")
useOne("/JADE_OPAL_2000_S4300807/d12-x01-y02","172")
useOne("/JADE_OPAL_2000_S4300807/d12-x01-y03","172")
useOne("/JADE_OPAL_2000_S4300807/d12-x01-y04","172")
useOne("/JADE_OPAL_2000_S4300807/d12-x01-y05","172")
useOne("/JADE_OPAL_2000_S4300807/d13-x01-y01","183")
useOne("/JADE_OPAL_2000_S4300807/d13-x01-y02","183")
useOne("/JADE_OPAL_2000_S4300807/d13-x01-y03","183")
useOne("/JADE_OPAL_2000_S4300807/d13-x01-y04","183")
useOne("/JADE_OPAL_2000_S4300807/d13-x01-y05","183")
useOne("/JADE_OPAL_2000_S4300807/d14-x01-y01","189")
useOne("/JADE_OPAL_2000_S4300807/d14-x01-y02","189")
useOne("/JADE_OPAL_2000_S4300807/d14-x01-y03","189")
useOne("/JADE_OPAL_2000_S4300807/d14-x01-y04","189")
useOne("/JADE_OPAL_2000_S4300807/d14-x01-y05","189")
useOne("/JADE_OPAL_2000_S4300807/d16-x01-y01","35")
useOne("/JADE_OPAL_2000_S4300807/d16-x01-y02","35")
useOne("/JADE_OPAL_2000_S4300807/d16-x01-y03","35")
useOne("/JADE_OPAL_2000_S4300807/d16-x01-y04","35")
useOne("/JADE_OPAL_2000_S4300807/d16-x01-y05","35")
useOne("/JADE_OPAL_2000_S4300807/d17-x01-y01","44")
useOne("/JADE_OPAL_2000_S4300807/d17-x01-y02","44")
useOne("/JADE_OPAL_2000_S4300807/d17-x01-y03","44")
useOne("/JADE_OPAL_2000_S4300807/d17-x01-y04","44")
useOne("/JADE_OPAL_2000_S4300807/d17-x01-y05","44")
useOne("/JADE_OPAL_2000_S4300807/d18-x01-y01","91")
useOne("/JADE_OPAL_2000_S4300807/d18-x01-y02","91")
useOne("/JADE_OPAL_2000_S4300807/d18-x01-y03","91")
useOne("/JADE_OPAL_2000_S4300807/d18-x01-y04","91")
useOne("/JADE_OPAL_2000_S4300807/d18-x01-y05","91")
useOne("/JADE_OPAL_2000_S4300807/d19-x01-y01","133")
useOne("/JADE_OPAL_2000_S4300807/d19-x01-y02","133")
useOne("/JADE_OPAL_2000_S4300807/d19-x01-y03","133")
useOne("/JADE_OPAL_2000_S4300807/d19-x01-y04","133")
useOne("/JADE_OPAL_2000_S4300807/d19-x01-y05","133")
useOne("/JADE_OPAL_2000_S4300807/d20-x01-y01","161")
useOne("/JADE_OPAL_2000_S4300807/d20-x01-y02","161")
useOne("/JADE_OPAL_2000_S4300807/d20-x01-y03","161")
useOne("/JADE_OPAL_2000_S4300807/d20-x01-y04","161")
useOne("/JADE_OPAL_2000_S4300807/d20-x01-y05","161")
useOne("/JADE_OPAL_2000_S4300807/d21-x01-y01","172")
useOne("/JADE_OPAL_2000_S4300807/d21-x01-y02","172")
useOne("/JADE_OPAL_2000_S4300807/d21-x01-y03","172")
useOne("/JADE_OPAL_2000_S4300807/d21-x01-y04","172")
useOne("/JADE_OPAL_2000_S4300807/d21-x01-y05","172")
useOne("/JADE_OPAL_2000_S4300807/d22-x01-y01","183")
useOne("/JADE_OPAL_2000_S4300807/d22-x01-y02","183")
useOne("/JADE_OPAL_2000_S4300807/d22-x01-y03","183")
useOne("/JADE_OPAL_2000_S4300807/d22-x01-y04","183")
useOne("/JADE_OPAL_2000_S4300807/d22-x01-y05","183")
useOne("/JADE_OPAL_2000_S4300807/d23-x01-y01","189")
useOne("/JADE_OPAL_2000_S4300807/d23-x01-y02","189")
useOne("/JADE_OPAL_2000_S4300807/d23-x01-y03","189")
useOne("/JADE_OPAL_2000_S4300807/d23-x01-y04","189")
useOne("/JADE_OPAL_2000_S4300807/d23-x01-y05","189")
useOne("/JADE_OPAL_2000_S4300807/d24-x01-y01","35")
useOne("/JADE_OPAL_2000_S4300807/d24-x01-y02","35")
useOne("/JADE_OPAL_2000_S4300807/d24-x01-y03","35")
useOne("/JADE_OPAL_2000_S4300807/d24-x01-y04","35")
useOne("/JADE_OPAL_2000_S4300807/d25-x01-y01","44")
useOne("/JADE_OPAL_2000_S4300807/d25-x01-y02","44")
useOne("/JADE_OPAL_2000_S4300807/d25-x01-y03","44")
useOne("/JADE_OPAL_2000_S4300807/d25-x01-y04","44")
useOne("/JADE_OPAL_2000_S4300807/d26-x01-y01","91")
useOne("/JADE_OPAL_2000_S4300807/d26-x01-y02","91")
useOne("/JADE_OPAL_2000_S4300807/d26-x01-y03","91")
useOne("/JADE_OPAL_2000_S4300807/d26-x01-y04","91")
useOne("/JADE_OPAL_2000_S4300807/d27-x01-y01","133")
useOne("/JADE_OPAL_2000_S4300807/d27-x01-y02","133")
useOne("/JADE_OPAL_2000_S4300807/d27-x01-y03","133")
useOne("/JADE_OPAL_2000_S4300807/d27-x01-y04","133")
useOne("/JADE_OPAL_2000_S4300807/d28-x01-y01","161")
useOne("/JADE_OPAL_2000_S4300807/d28-x01-y02","161")
useOne("/JADE_OPAL_2000_S4300807/d28-x01-y03","161")
useOne("/JADE_OPAL_2000_S4300807/d28-x01-y04","161")
useOne("/JADE_OPAL_2000_S4300807/d29-x01-y01","172")
useOne("/JADE_OPAL_2000_S4300807/d29-x01-y02","172")
useOne("/JADE_OPAL_2000_S4300807/d29-x01-y03","172")
useOne("/JADE_OPAL_2000_S4300807/d29-x01-y04","172")
useOne("/JADE_OPAL_2000_S4300807/d30-x01-y01","183")
useOne("/JADE_OPAL_2000_S4300807/d30-x01-y02","183")
useOne("/JADE_OPAL_2000_S4300807/d30-x01-y03","183")
useOne("/JADE_OPAL_2000_S4300807/d30-x01-y04","183")
useOne("/JADE_OPAL_2000_S4300807/d31-x01-y01","189")
useOne("/JADE_OPAL_2000_S4300807/d31-x01-y02","189")
useOne("/JADE_OPAL_2000_S4300807/d31-x01-y03","189")
useOne("/JADE_OPAL_2000_S4300807/d31-x01-y04","189")
useOne("/OPAL_2004_S6132243/d01-x01-y01","91")
useOne("/OPAL_2004_S6132243/d01-x01-y02","133")
useOne("/OPAL_2004_S6132243/d01-x01-y03","177")
useOne("/OPAL_2004_S6132243/d01-x01-y04","197")
useOne("/OPAL_2004_S6132243/d02-x01-y01","91")
useOne("/OPAL_2004_S6132243/d02-x01-y02","133")
useOne("/OPAL_2004_S6132243/d02-x01-y03","177")
useOne("/OPAL_2004_S6132243/d02-x01-y04","197")
useOne("/OPAL_2004_S6132243/d03-x01-y01","91")
useOne("/OPAL_2004_S6132243/d03-x01-y02","133")
useOne("/OPAL_2004_S6132243/d03-x01-y03","177")
useOne("/OPAL_2004_S6132243/d03-x01-y04","197")
useOne("/OPAL_2004_S6132243/d04-x01-y01","91")
useOne("/OPAL_2004_S6132243/d04-x01-y02","133")
useOne("/OPAL_2004_S6132243/d04-x01-y03","177")
useOne("/OPAL_2004_S6132243/d04-x01-y04","197")
useOne("/OPAL_2004_S6132243/d05-x01-y01","91")
useOne("/OPAL_2004_S6132243/d05-x01-y02","133")
useOne("/OPAL_2004_S6132243/d05-x01-y03","177")
useOne("/OPAL_2004_S6132243/d05-x01-y04","197")
useOne("/OPAL_2004_S6132243/d06-x01-y01","91")
useOne("/OPAL_2004_S6132243/d06-x01-y02","133")
useOne("/OPAL_2004_S6132243/d06-x01-y03","177")
useOne("/OPAL_2004_S6132243/d06-x01-y04","197")
useOne("/OPAL_2004_S6132243/d07-x01-y01","91")
useOne("/OPAL_2004_S6132243/d07-x01-y02","133")
useOne("/OPAL_2004_S6132243/d07-x01-y03","177")
useOne("/OPAL_2004_S6132243/d07-x01-y04","197")
useOne("/OPAL_2004_S6132243/d08-x01-y01","91")
useOne("/OPAL_2004_S6132243/d08-x01-y02","133")
useOne("/OPAL_2004_S6132243/d08-x01-y03","177")
useOne("/OPAL_2004_S6132243/d08-x01-y04","197")
useOne("/OPAL_2004_S6132243/d09-x01-y01","91")
useOne("/OPAL_2004_S6132243/d09-x01-y02","133")
useOne("/OPAL_2004_S6132243/d09-x01-y03","177")
useOne("/OPAL_2004_S6132243/d09-x01-y04","197")
useOne("/OPAL_2004_S6132243/d10-x01-y01","91")
useOne("/OPAL_2004_S6132243/d10-x01-y02","133")
useOne("/OPAL_2004_S6132243/d10-x01-y03","177")
useOne("/OPAL_2004_S6132243/d10-x01-y04","197")
useOne("/OPAL_2004_S6132243/d11-x01-y01","91")
useOne("/OPAL_2004_S6132243/d11-x01-y02","133")
useOne("/OPAL_2004_S6132243/d11-x01-y03","177")
useOne("/OPAL_2004_S6132243/d11-x01-y04","197")
useOne("/OPAL_2004_S6132243/d12-x01-y01","91")
useOne("/OPAL_2004_S6132243/d12-x01-y02","133")
useOne("/OPAL_2004_S6132243/d12-x01-y03","177")
useOne("/OPAL_2004_S6132243/d12-x01-y04","197")
useOne("/OPAL_2004_S6132243/d13-x01-y01","91")
useOne("/OPAL_2004_S6132243/d13-x01-y02","133")
useOne("/OPAL_2004_S6132243/d13-x01-y03","177")
useOne("/OPAL_2004_S6132243/d13-x01-y04","197")
useOne("/OPAL_2004_S6132243/d14-x01-y01","91")
useOne("/OPAL_2004_S6132243/d14-x01-y02","133")
useOne("/OPAL_2004_S6132243/d14-x01-y03","177")
useOne("/OPAL_2004_S6132243/d14-x01-y04","197")
useOne("/OPAL_2004_S6132243/d15-x01-y01","91")
useOne("/OPAL_2004_S6132243/d15-x01-y02","133")
useOne("/OPAL_2004_S6132243/d15-x01-y03","177")
useOne("/OPAL_2004_S6132243/d15-x01-y04","197")
useOne("/OPAL_2004_S6132243/d16-x01-y01","91")
useOne("/OPAL_2004_S6132243/d16-x01-y02","133")
useOne("/OPAL_2004_S6132243/d16-x01-y03","177")
useOne("/OPAL_2004_S6132243/d16-x01-y04","197")
useOne("/OPAL_2004_S6132243/d17-x01-y01","91")
useOne("/OPAL_2004_S6132243/d17-x01-y02","133")
useOne("/OPAL_2004_S6132243/d17-x01-y03","177")
useOne("/OPAL_2004_S6132243/d17-x01-y04","197")
useOne("/OPAL_2004_S6132243/d18-x01-y01","91")
useOne("/OPAL_2004_S6132243/d18-x01-y02","133")
useOne("/OPAL_2004_S6132243/d18-x01-y03","177")
useOne("/OPAL_2004_S6132243/d18-x01-y04","197")
useOne("/OPAL_2004_S6132243/d19-x01-y01","91")
useOne("/OPAL_2004_S6132243/d19-x01-y02","133")
useOne("/OPAL_2004_S6132243/d19-x01-y03","177")
useOne("/OPAL_2004_S6132243/d19-x01-y04","197")
useOne("/OPAL_2004_S6132243/d20-x01-y01","91")
useOne("/OPAL_2004_S6132243/d20-x01-y02","133")
useOne("/OPAL_2004_S6132243/d20-x01-y03","177")
useOne("/OPAL_2004_S6132243/d20-x01-y04","197")
useOne("/OPAL_2004_S6132243/d21-x01-y01","91")
useOne("/OPAL_2004_S6132243/d21-x01-y02","133")
useOne("/OPAL_2004_S6132243/d21-x01-y03","177")
useOne("/OPAL_2004_S6132243/d21-x01-y04","197")
useOne("/OPAL_2004_S6132243/d22-x01-y01","91")
useOne("/OPAL_2004_S6132243/d22-x01-y02","133")
useOne("/OPAL_2004_S6132243/d22-x01-y03","177")
useOne("/OPAL_2004_S6132243/d22-x01-y04","197")
useOne("/OPAL_2004_S6132243/d23-x01-y01","91")
useOne("/OPAL_2004_S6132243/d23-x01-y02","133")
useOne("/OPAL_2004_S6132243/d23-x01-y03","177")
useOne("/OPAL_2004_S6132243/d23-x01-y04","197")
useOne("/OPAL_2004_S6132243/d24-x01-y01","91")
useOne("/OPAL_2004_S6132243/d24-x01-y02","133")
useOne("/OPAL_2004_S6132243/d24-x01-y03","177")
useOne("/OPAL_2004_S6132243/d24-x01-y04","197")
useOne("/OPAL_2004_S6132243/d25-x01-y01","91")
useOne("/OPAL_2004_S6132243/d25-x01-y02","133")
useOne("/OPAL_2004_S6132243/d25-x01-y03","177")
useOne("/OPAL_2004_S6132243/d25-x01-y04","197")
useOne("/OPAL_2004_S6132243/d26-x01-y01","91")
useOne("/OPAL_2004_S6132243/d26-x01-y02","133")
useOne("/OPAL_2004_S6132243/d26-x01-y03","177")
useOne("/OPAL_2004_S6132243/d26-x01-y04","197")
merge("/ALEPH_2004_S5765862/d01-x01-y01")
useOne("/ALEPH_2004_S5765862/d02-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d03-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d04-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d05-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d06-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d07-x01-y01","196")
useOne("/ALEPH_2004_S5765862/d08-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d09-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d11-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d12-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d13-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d14-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d15-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d16-x01-y01","196")
useOne("/ALEPH_2004_S5765862/d17-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d18-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d19-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d20-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d21-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d22-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d23-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d24-x01-y01","196")
useOne("/ALEPH_2004_S5765862/d25-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d26-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d27-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d28-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d29-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d30-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d31-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d32-x01-y01","196")
useOne("/ALEPH_2004_S5765862/d33-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d34-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d35-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d36-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d37-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d38-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d39-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d40-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d41-x01-y01","196")
useOne("/ALEPH_2004_S5765862/d42-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d43-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d44-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d45-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d46-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d47-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d48-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d49-x01-y01","196")
useOne("/ALEPH_2004_S5765862/d50-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d51-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d54-x01-y01","91")
useOne("/ALEPH_2004_S5765862/d55-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d56-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d57-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d58-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d59-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d60-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d61-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d62-x01-y01","91")
useOne("/ALEPH_2004_S5765862/d63-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d64-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d65-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d66-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d67-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d68-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d69-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d70-x01-y01","91")
useOne("/ALEPH_2004_S5765862/d71-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d72-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d73-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d74-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d75-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d76-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d77-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d78-x01-y01","91")
useOne("/ALEPH_2004_S5765862/d79-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d80-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d81-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d82-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d83-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d84-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d85-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d86-x01-y01","91")
useOne("/ALEPH_2004_S5765862/d87-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d88-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d89-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d90-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d91-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d92-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d93-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d94-x01-y01","91")
useOne("/ALEPH_2004_S5765862/d95-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d96-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d97-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d98-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d99-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d100-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d101-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d102-x01-y01","91")
useOne("/ALEPH_2004_S5765862/d103-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d104-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d105-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d106-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d107-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d108-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d109-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d110-x01-y01","91")
useOne("/ALEPH_2004_S5765862/d111-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d112-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d113-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d114-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d115-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d116-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d117-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d118-x01-y01","91")
useOne("/ALEPH_2004_S5765862/d119-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d120-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d121-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d122-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d123-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d124-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d125-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d126-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d127-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d128-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d129-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d130-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d131-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d132-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d133-x01-y01","91")
useOne("/ALEPH_2004_S5765862/d134-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d135-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d136-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d137-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d138-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d139-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d140-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d141-x01-y01","91")
useOne("/ALEPH_2004_S5765862/d142-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d143-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d144-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d145-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d146-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d147-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d148-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d149-x01-y01","91")
useOne("/ALEPH_2004_S5765862/d150-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d151-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d152-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d153-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d154-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d155-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d156-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d157-x01-y01","91")
useOne("/ALEPH_2004_S5765862/d158-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d159-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d160-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d161-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d162-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d163-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d164-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d165-x01-y01","91")
useOne("/ALEPH_2004_S5765862/d166-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d167-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d168-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d169-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d170-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d172-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d173-x01-y01","91")
useOne("/ALEPH_2004_S5765862/d174-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d175-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d176-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d177-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d178-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d179-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d180-x01-y01","91")
useOne("/ALEPH_2004_S5765862/d181-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d182-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d183-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d184-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d185-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d186-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d187-x01-y01","91")
useOne("/ALEPH_2004_S5765862/d188-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d189-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d190-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d191-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d192-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d193-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d194-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d195-x01-y01","91")
useOne("/ALEPH_2004_S5765862/d196-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d197-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d198-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d199-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d200-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d201-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d202-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d203-x01-y01","91")
useOne("/ALEPH_2004_S5765862/d204-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d205-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d206-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d207-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d208-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d209-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d210-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d211-x01-y01","91")
useOne("/ALEPH_2004_S5765862/d212-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d213-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d214-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d215-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d216-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d217-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d218-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d219-x01-y01","91")
useOne("/ALEPH_2004_S5765862/d220-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d221-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d222-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d223-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d224-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d225-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d226-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d227-x01-y01","91")
useOne("/ALEPH_2004_S5765862/d228-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d229-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d230-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d231-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d232-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d233-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d234-x01-y01","206")
# Choose output file
name = args[0]+".aida"
out = open(name, "w")
## Write out merged histos
out.write('<?xml version="1.0" encoding="ISO-8859-1" ?>\n')
out.write('<!DOCTYPE aida SYSTEM "http://aida.freehep.org/schemas/3.3/aida.dtd">\n')
out.write('<aida version="3.3">\n')
out.write(' <implementation version="1.1" package="FreeHEP"/>\n')
for hpath, h in sorted(outhistos.iteritems()):
logging.debug("hpath = %s" % hpath)
out.write(h.asAIDA() + "\n\n")
out.write('</aida>\n')
sys.exit(0)
diff --git a/UnderlyingEvent/MPIHandler.h b/UnderlyingEvent/MPIHandler.h
--- a/UnderlyingEvent/MPIHandler.h
+++ b/UnderlyingEvent/MPIHandler.h
@@ -1,863 +1,863 @@
// -*- C++ -*-
//
// MPIHandler.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_MPIHandler_H
#define HERWIG_MPIHandler_H
//
// This is the declaration of the MPIHandler class.
//
#include "ThePEG/Interface/Interfaced.h"
#include "ThePEG/Handlers/StandardEventHandler.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "Herwig++/PDT/StandardMatchers.h"
#include "Herwig++/Utilities/GSLBisection.h"
//#include "Herwig++/Utilities/GSLMultiRoot.h"
#include "Herwig++/Utilities/GSLIntegrator.h"
#include "Herwig++/Shower/UEBase.h"
#include <cassert>
#include "ProcessHandler.h"
#include "MPIHandler.fh"
namespace Herwig {
using namespace ThePEG;
/** \ingroup UnderlyingEvent
* \class MPIHandler
* This class is responsible for generating additional
* semi hard partonic interactions.
*
* \author Manuel B\"ahr
*
* @see \ref MPIHandlerInterfaces "The interfaces"
* defined for MPIHandler.
* @see ProcessHandler
* @see ShowerHandler
* @see HwRemDecayer
*/
class MPIHandler: public UEBase {
/**
* Maximum number of scatters
*/
static const unsigned int maxScatters_ = 99;
/**
* Class for the integration is a friend to access private members
*/
- friend class Eikonalization;
- friend class TotalXSecBisection;
- friend class slopeAndTotalXSec;
- friend class slopeInt;
- friend class slopeBisection;
+ friend struct Eikonalization;
+ friend struct TotalXSecBisection;
+ friend struct slopeAndTotalXSec;
+ friend struct slopeInt;
+ friend struct slopeBisection;
public:
/** A vector of <code>SubProcessHandler</code>s. */
typedef vector<SubHdlPtr> SubHandlerList;
/** A vector of <code>Cut</code>s. */
typedef vector<CutsPtr> CutsList;
/** A vector of <code>ProcessHandler</code>s. */
typedef vector<ProHdlPtr> ProcessHandlerList;
/** A vector of cross sections. */
typedef vector<CrossSection> XSVector;
/** A pair of multiplicities: hard, soft. */
typedef pair<unsigned int, unsigned int> MPair;
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
MPIHandler(): softMult_(0), identicalToUE_(-1),
PtOfQCDProc_(-1.0*GeV), Ptmin_(-1.0*GeV),
hardXSec_(0*millibarn), softXSec_(0*millibarn),
totalXSecExp_(0*millibarn),
softMu2_(ZERO), beta_(100.0/GeV2),
algorithm_(2), numSubProcs_(0),
colourDisrupt_(0.0), softInt_(true), twoComp_(true),
DLmode_(2), avgNhard_(0.0), avgNsoft_(0.0) {}
/**
* The destructor.
*/
virtual ~MPIHandler(){}
//@}
public:
/** @name Methods for the MPI generation. */
//@{
/*
* @return true if for this beam setup MPI can be generated
*/
virtual bool beamOK() const;
/**
* Return true or false depending on whether soft interactions are enabled.
*/
virtual bool softInt() const {return softInt_;}
/**
* Get the soft multiplicity from the pretabulated multiplicity
* distribution. Generated in multiplicity in the first place.
* @return the number of extra soft events in this collision
*/
virtual unsigned int softMultiplicity() const {return softMult_;}
/**
* Sample from the pretabulated multiplicity distribution.
* @return the number of extra events in this collision
*/
virtual unsigned int multiplicity(unsigned int sel=0);
/**
* Select a StandardXComb according to it's weight
* @return that StandardXComb Object
* @param sel is the subprocess that should be returned,
* if more than one is specified.
*/
virtual tStdXCombPtr generate(unsigned int sel=0);
//@}
/** @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();
/**
* Initialize this Multiple Interaction handler and all related objects needed to
* generate additional events.
*/
virtual void initialize();
/**
* Finalize this Multiple Interaction handler and all related objects needed to
* generate additional events.
*/
virtual void finalize();
/**
* Write out accumulated statistics about integrated cross sections.
*/
void statistics() const;
/**
* The level of statistics. Controlls the amount of statistics
* written out after each run to the <code>EventGenerator</code>s
* <code>.out</code> file. Simply the EventHandler method is called here.
*/
int statLevel() const {return eventHandler()->statLevel();}
/** @name Simple access functions. */
//@{
/**
* Return the ThePEG::EventHandler assigned to this handler.
* This methods shadows ThePEG::StepHandler::eventHandler(), because
* it is not virtual in ThePEG::StepHandler. This is ok, because this
* method would give a null-pointer at some stages, whereas this method
* gives access to the explicitely copied pointer (in initialize())
* to the ThePEG::EventHandler.
*/
tEHPtr eventHandler() const {return theHandler;}
/**
* Return theAlgorithm.
*/
virtual int Algorithm() const {return algorithm_;}
/**
* Return the ptmin parameter of the model
*/
virtual Energy Ptmin() const {
if(Ptmin_ > ZERO)
return Ptmin_;
else
throw Exception() << "MPIHandler::Ptmin called without initialize before"
<< Exception::runerror;
}
/**
* Return the slope of the soft pt spectrum as calculated.
*/
virtual InvEnergy2 beta() const {
if(beta_ != 100.0/GeV2)
return beta_;
else
throw Exception() << "MPIHandler::beta called without initialization"
<< Exception::runerror;
}
/**
* Return the pt Cutoff of the Interaction that is identical to the UE
* one.
*/
virtual Energy PtForVeto() const {return PtOfQCDProc_;}
/**
* Return the number of additional "hard" processes ( = multiple
* parton scattering)
*/
virtual unsigned int additionalHardProcs() const {return numSubProcs_-1;}
/**
* Return the fraction of colour disrupted connections to the
* suprocesses.
*/
virtual double colourDisrupt() const {return colourDisrupt_;}
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:
/**
* Access the list of sub-process handlers.
*/
const SubHandlerList & subProcesses()
const {return theSubProcesses;}
/**
* Access the list of sub-process handlers.
*/
SubHandlerList & subProcesses() {return theSubProcesses;}
/**
* Access the list of cuts.
*/
const CutsList & cuts() const {return theCuts;}
/**
* Access the list of cuts.
*/
CutsList & cuts() {return theCuts;}
/**
* Access the list of sub-process handlers.
*/
const ProcessHandlerList & processHandlers()
const {return theProcessHandlers;}
/**
* Access the list of sub-process handlers.
*/
ProcessHandlerList & processHandlers() {return theProcessHandlers;}
/**
* Method to calculate the individual probabilities for N scatters in the event.
* @param UEXSecs is(are) the inclusiv cross section(s) for the UE process(es).
*/
void Probs(XSVector UEXSecs);
/**
* Debug method to check the individual probabilities.
* @param filename is the file the output gets written to
*/
void MultDistribution(string filename) const;
/**
* Return the value of the Overlap function A(b) for a given impact
* parameter \a b.
* @param b impact parameter
* @param mu2 = inv hadron radius squared. 0 will use the value of
* invRadius_
* @return inverse area.
*/
InvArea OverlapFunction(Length b, Energy2 mu2=ZERO) const;
/**
* Method to calculate the poisson probability for expectation value
* \f$<n> = A(b)\sigma\f$, and multiplicity N.
*/
double poisson(Length b, CrossSection sigma,
unsigned int N, Energy2 mu2=ZERO) const;
/**
* Return n!
*/
double factorial (unsigned int n) const;
/**
* Returns the total cross section for the current CMenergy. The
* decision which parametrization will be used is steered by a
* external parameter of this class.
*/
CrossSection totalXSecExp() const;
/**
* Difference of the calculated total cross section and the
* experimental one from totalXSecExp.
* @param softXSec = the soft cross section that is used
* @param softMu2 = the soft radius, if 0 the hard radius will be used
*/
CrossSection totalXSecDiff(CrossSection softXSec,
Energy2 softMu2=ZERO) const;
/**
* Difference of the calculated elastic slope and the
* experimental one from slopeExp.
* @param softXSec = the soft cross section that is used
* @param softMu2 = the soft radius, if 0 the hard radius will be used
*/
InvEnergy2 slopeDiff(CrossSection softXSec,
Energy2 softMu2=ZERO) const;
/**
* Returns the value of the elastic slope for the current CMenergy.
* The decision which parametrization will be used is steered by a
* external parameter of this class.
*/
InvEnergy2 slopeExp() const;
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<MPIHandler> initMPIHandler;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MPIHandler & operator=(const MPIHandler &);
/**
* A pointer to the EventHandler that calls us. Has to be saved, because the
* method eventHandler() inherited from ThePEG::StepHandler returns a null-pointer
* sometimes. Leif changed that in r1053 so that a valid pointer is present, when
* calling doinitrun().
*/
tEHPtr theHandler;
/**
* The list of <code>SubProcessHandler</code>s.
*/
SubHandlerList theSubProcesses;
/**
* The kinematical cuts used for this collision handler.
*/
CutsList theCuts;
/**
* List of ProcessHandler used to sample different processes independently
*/
ProcessHandlerList theProcessHandlers;
/**
* A ThePEG::Selector where the individual Probabilities P_N are stored
* and the actual Multiplicities can be selected.
*/
Selector<MPair> theMultiplicities;
/**
* Variable to store the soft multiplicity generated for a event. This
* has to be stored as it is generated at the time of the hard
* additional interactions but used later on.
*/
unsigned int softMult_;
/**
* Variable to store the multiplicity of the second hard process
*/
vector<int> additionalMultiplicities_;
/**
* Variable to store the information, which process is identical to
* the UE one (QCD dijets).
* 0 means "real" hard one
* n>0 means the nth additional hard scatter
* -1 means no one!
*/
int identicalToUE_;
/**
* Variable to store the minimal pt of the process that is identical
* to the UE one. This only has to be set, if it can't be determined
* automatically (i.e. when reading QCD LesHouches files in).
*/
Energy PtOfQCDProc_;
/**
* Variable to store the parameter ptmin
*/
Energy Ptmin_;
/**
* Variable to store the hard cross section above ptmin
*/
CrossSection hardXSec_;
/**
* Variable to store the final soft cross section below ptmin
*/
CrossSection softXSec_;
/**
* Variable to store the inelastic cross section
*/
CrossSection inelXSec_;
/**
* Variable to store the total pp cross section (assuming rho=0!) as
* measured at LHC. If this variable is set, this value is used in the
* subsequent run instead of any of the Donnachie-Landshoff
* parametrizations.
*/
CrossSection totalXSecExp_;
/**
* Variable to store the soft radius, that is calculated during
* initialization for the two-component model.
*/
Energy2 softMu2_;
/**
* slope to the non-perturbative pt spectrum: \f$d\sigma/dp_T^2 = A \exp
* (- beta p_T^2)\f$. Its value is determined durint initialization.
*/
InvEnergy2 beta_;
/**
* Switch to be set from outside to determine the algorithm used for
* UE activity.
*/
int algorithm_;
/**
* Inverse hadron Radius squared \f$ (\mu^2) \f$. Used inside the overlap function.
*/
Energy2 invRadius_;
/**
* Member variable to store the actual number of separate SubProcesses
*/
unsigned int numSubProcs_;
/**
* Variable to store the relative number of colour disrupted
* connections to additional subprocesses. This variable is used in
* Herwig::HwRemDecayer but store here, to have access to all
* parameters through one Object.
*/
double colourDisrupt_;
/**
* Flag to store whether soft interactions, i.e. pt < ptmin should be
* simulated.
*/
bool softInt_;
/**
* Flag to steer wheather the soft part has a different radius, that
* will be dynamically fixed.
*/
bool twoComp_;
/**
* Switch to determine which Donnachie & Landshoff parametrization
* should be used.
*/
unsigned int DLmode_;
/**
* Variable to store the average hard multiplicity.
*/
double avgNhard_;
/**
* Variable to store the average soft multiplicity.
*/
double avgNsoft_;
protected:
/** @cond EXCEPTIONCLASSES */
/**
* Exception class used by the MultipleInteractionHandler, when something
* during initialization went wrong.
* \todo understand!!!
*/
class InitError: public Exception {};
/** @endcond */
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of MPIHandler. */
template <>
struct BaseClassTrait<Herwig::MPIHandler,1> {
/** Typedef of the first base class of MPIHandler. */
typedef Interfaced NthBase;
};
/** This template specialization informs ThePEG about the name of
* the MPIHandler class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::MPIHandler>
: public ClassTraitsBase<Herwig::MPIHandler> {
/** Return a platform-independent class name */
static string className() { return "Herwig::MPIHandler"; }
/** Return the name(s) of the shared library (or libraries) be loaded to get
* access to the MPIHandler class and any other class on which it depends
* (except the base class). */
static string library() { return "SimpleKTCut.so HwMPI.so"; }
};
/** @endcond */
}
namespace Herwig {
/**
* A struct for the 2D root finding that is necessary to determine the
* soft cross section and the soft radius that is needed to describe
* the total cross section correctly.
* NOT IN USE CURRENTLY
*/
struct slopeAndTotalXSec : public GSLHelper<CrossSection, CrossSection> {
public:
/**
* Constructor
*/
slopeAndTotalXSec(tcMPIHPtr handler): handler_(handler) {}
/** second argument type */
typedef Energy2 ArgType2;
/** second value type */
typedef InvEnergy2 ValType2;
/** first element of the vector like function to find root for
* @param softXSec soft cross-section
* @param softMu2 \f$\mu^2\f$
*/
CrossSection f1(ArgType softXSec, ArgType2 softMu2) const {
return handler_->totalXSecDiff(softXSec, softMu2);
}
/** second element of the vector like function to find root for
* @param softXSec soft cross-section
* @param softMu2 \f$\mu^2\f$
*/
InvEnergy2 f2(ArgType softXSec, ArgType2 softMu2) const {
return handler_->slopeDiff(softXSec, softMu2);
}
/** provide the actual units of use */
virtual ValType vUnit() const {return 1.0*millibarn;}
/** otherwise rounding errors may get significant */
virtual ArgType aUnit() const {return 1.0*millibarn;}
/** provide the actual units of use */
ValType2 vUnit2() const {return 1.0/GeV2;}
/** otherwise rounding errors may get significant */
ArgType2 aUnit2() const {return GeV2;}
private:
/**
* Pointer to the handler
*/
tcMPIHPtr handler_;
};
/**
* A struct for the root finding that is necessary to determine the
* slope of the soft pt spectrum to match the soft cross section
*/
struct betaBisection : public GSLHelper<Energy2, InvEnergy2>{
public:
/**
* Constructor.
* @param soft = soft cross section, i.e. the integral of the soft
* pt spectrum f(u=p_T^2) = dsig exp(-beta*u/u_min)
* @param dsig = dsigma_hard/dp_T^2 at the p_T cutoff
* @param ptmin = p_T cutoff
*/
betaBisection(CrossSection soft, DiffXSec dsig, Energy ptmin)
: softXSec_(soft), dsig_(dsig), ptmin_(ptmin) {}
/**
* Operator that is used inside the GSLBisection class
*/
virtual Energy2 operator ()(InvEnergy2 beta) const
{
if( fabs(beta*GeV2) < 1.E-4 )
beta = (beta > ZERO) ? 1.E-4/GeV2 : -1.E-4/GeV2;
return (exp(beta*sqr(ptmin_)) - 1.0)/beta - softXSec_/dsig_;
}
/** provide the actual units of use */
virtual ValType vUnit() const {return 1.0*GeV2;}
/** provide the actual units of use */
virtual ArgType aUnit() const {return 1.0/GeV2;}
private:
/** soft cross section */
CrossSection softXSec_;
/** dsigma/dp_T^2 at ptmin */
DiffXSec dsig_;
/** pt cutoff */
Energy ptmin_;
};
/**
* A struct for the root finding that is necessary to determine the
* soft cross section and soft mu2 that are needed to describe the
* total cross section AND elastic slope correctly.
*/
struct slopeBisection : public GSLHelper<InvEnergy2, Energy2> {
public:
/** Constructor */
slopeBisection(tcMPIHPtr handler) : handler_(handler) {}
/**
* Return the difference of the calculated elastic slope to the
* experimental one for a given value of the soft mu2. During that,
* the soft cross section get fixed.
*/
InvEnergy2 operator ()(Energy2 arg) const;
/** Return the soft cross section that has been calculated */
CrossSection softXSec() const {return softXSec_;}
private:
/** const pointer to the MPIHandler to give access to member functions.*/
tcMPIHPtr handler_;
/** soft cross section that is determined on the fly.*/
mutable CrossSection softXSec_;
};
/**
* A struct for the root finding that is necessary to determine the
* soft cross section that is needed to describe the total cross
* section correctly.
*/
struct TotalXSecBisection : public GSLHelper<CrossSection, CrossSection> {
public:
/**
* Constructor
* @param handler The handler
* @param softMu2 \f$\mu^2\f$
*/
TotalXSecBisection(tcMPIHPtr handler, Energy2 softMu2=ZERO):
handler_(handler), softMu2_(softMu2) {}
/**
* operator to return the cross section
* @param argument input cross section
*/
CrossSection operator ()(CrossSection argument) const {
return handler_->totalXSecDiff(argument, softMu2_);
}
/** provide the actual units of use */
virtual ValType vUnit() const {return 1.0*millibarn;}
/** otherwise rounding errors may get significant */
virtual ArgType aUnit() const {return 1.0*millibarn;}
private:
/**
* The handler
*/
tcMPIHPtr handler_;
/**
* \f$\mu^2\f$
*/
Energy2 softMu2_;
};
/**
* Typedef for derivative of the length
*/
typedef QTY<1,-2,0>::Type LengthDiff;
/**
* A struct for the integrand for the slope
*/
struct slopeInt : public GSLHelper<LengthDiff, Length>{
public:
/** Constructor
* @param handler The handler
* @param hard The hard cross section
* @param soft The soft cross section
* @param softMu2 \f$\mu^2\f$
*/
slopeInt(tcMPIHPtr handler, CrossSection hard,
CrossSection soft=0*millibarn, Energy2 softMu2=ZERO)
: handler_(handler), hardXSec_(hard),
softXSec_(soft), softMu2_(softMu2) {}
/**
* Operator to return the answer
* @param arg The argument
*/
ValType operator ()(ArgType arg) const;
private:
/**
* Pointer to the Handler that calls this integrand
*/
tcMPIHPtr handler_;
/**
* The hard cross section to be eikonalized
*/
CrossSection hardXSec_;
/**
* The soft cross section to be eikonalized. Default is zero
*/
CrossSection softXSec_;
/**
* The inv radius^2 of the soft interactions.
*/
Energy2 softMu2_;
};
/**
* A struct for the eikonalization of the inclusive cross section.
*/
struct Eikonalization : public GSLHelper<Length, Length>{
/**
* The constructor
* @param handler is the pointer to the MPIHandler to get access to
* MPIHandler::OverlapFunction and member variables of the MPIHandler.
* @param option is a flag, whether the inelastic or the total
* @param handler The handler
* @param hard The hard cross section
* @param soft The soft cross section
* @param softMu2 \f$\mu^2\f$
* cross section should be returned (-2 or -1). For option = N > 0 the integrand
* is N*(A(b)*sigma)^N/N! exp(-A(b)*sigma) this is the P_N*sigma where
* P_N is the Probability of having exactly N interaction (including the hard one)
* This is equation 14 from "Jimmy4: Multiparton Interactions in HERWIG for the LHC"
*/
Eikonalization(tcMPIHPtr handler, int option, CrossSection hard,
CrossSection soft=0*millibarn, Energy2 softMu2=ZERO)
: theHandler(handler), theoption(option), hardXSec_(hard),
softXSec_(soft), softMu2_(softMu2) {}
/**
* Get the function value
*/
Length operator ()(Length argument) const;
private:
/**
* Pointer to the Handler that calls this integrand
*/
tcMPIHPtr theHandler;
/**
* A flag to switch between the calculation of total and inelastic cross section
* or calculations for the individual probabilities. See the constructor
*/
int theoption;
/**
* The hard cross section to be eikonalized
*/
CrossSection hardXSec_;
/**
* The soft cross section to be eikonalized. Default is zero
*/
CrossSection softXSec_;
/**
* The inv radius^2 of the soft interactions.
*/
Energy2 softMu2_;
};
}
#ifndef ThePEG_TEMPLATES_IN_CC_FILE
// #include "MPIHandler.tcc"
#endif
#endif /* HERWIG_MPIHandler_H */
diff --git a/Utilities/GSLIntegrator.h b/Utilities/GSLIntegrator.h
--- a/Utilities/GSLIntegrator.h
+++ b/Utilities/GSLIntegrator.h
@@ -1,104 +1,120 @@
// -*- C++ -*-
//
// GSLIntegrator.h is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_GSLIntegrator_H
#define HERWIG_GSLIntegrator_H
//
// This is the declaration of the GSLIntegrator class.
//
#include "ThePEG/Pointer/ReferenceCounted.h"
#include "ThePEG/Repository/CurrentGenerator.h"
#include "gsl/gsl_integration.h"
#include "gsl/gsl_errno.h"
namespace Herwig {
using namespace ThePEG;
/** \ingroup Utilities
* This class is designed to integrate a given function between
* 2 limits using the gsl QAGS integration subroutine.
*
* The function is supplied using a templated class that must define
* operator(argument). The units of the argument ArgType and return
* type ValType must be supplied in the integrand class using a typedef
* i.e. <br>
* <code> struct integrand { </code><br>
* <code> ... </code> <BR>
* <code>Energy operator(double arg) const;</code><BR>
* <code>typedef double ArgType</code><BR>
* <code>typedef Energy ValType</code><BR>
* <code> ... </code> <BR>
* <code>}</code> <BR>
*/
class GSLIntegrator : public Pointer::ReferenceCounted {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* Default Constructor uses values in GSL manual as parameters
**/
GSLIntegrator() : _abserr(1.0E-35), _relerr(1.0E-3), _nbins(1000) {}
/**
* Specify all the parameters.
* @param abserr Absolute error.
* @param relerr Relative error.
* @param nbins Number of bins
*/
GSLIntegrator(double abserr, double relerr, int nbins) :
_abserr(abserr), _relerr(relerr), _nbins(nbins) {}
//@}
/**
* The value of the integral
* @param function The integrand class that defines operator()
* @param lower The lower limit of integration.
* @param upper The upper limit of integration.
*/
template <class T>
inline typename BinaryOpTraits<typename T::ValType,
typename T::ArgType>::MulT
value(const T & function,
const typename T::ArgType lower,
const typename T::ArgType upper) const;
+ /**
+ * The value of the integral
+ * @param function The integrand class that defines operator()
+ * @param lower The lower limit of integration.
+ * @param upper The upper limit of integration.
+ * @param error Returns the estimated error of the integral
+ */
+ template <class T>
+ inline typename BinaryOpTraits<typename T::ValType,
+ typename T::ArgType>::MulT
+ value(const T & function,
+ const typename T::ArgType lower,
+ const typename T::ArgType upper,
+ typename BinaryOpTraits<typename T::ValType,
+ typename T::ArgType>::MulT & error) const;
+
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
GSLIntegrator & operator=(const GSLIntegrator &);
private:
/**
* The parameters controlling the absolute error.
*/
double _abserr;
/**
* The parameters controlling the relative error.
*/
double _relerr;
/**
* The maximum number of intervals to use.
*/
int _nbins;
};
}
#include "GSLIntegrator.tcc"
#endif /* HERWIG_GSLIntegrator_H */
diff --git a/Utilities/GSLIntegrator.tcc b/Utilities/GSLIntegrator.tcc
--- a/Utilities/GSLIntegrator.tcc
+++ b/Utilities/GSLIntegrator.tcc
@@ -1,100 +1,116 @@
// -*- C++ -*-
//
// GSLIntegrator.tcc is a part of Herwig++ - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 The Herwig Collaboration
//
// Herwig++ is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
// This is the implementation of the non-inlined templated member
// functions of the GSLIntegrator class.
//
using namespace Herwig;
using namespace ThePEG;
namespace {
template <class T> struct param {
//The integrand function
const T & function;
};
template<class T> double integrand(double x , void * p) {
//Units of the argument and return type
const typename T::ValType ValUnit =
TypeTraits<typename T::ValType>::baseunit;
const typename T::ArgType ArgUnit =
TypeTraits<typename T::ArgType>::baseunit;
const T & f = ((struct param<T> *)p)->function;
return f(x * ArgUnit ) / ValUnit;
}
}
namespace Herwig {
using namespace ThePEG;
+
template <class T>
inline typename BinaryOpTraits<typename T::ValType,
typename T::ArgType>::MulT
GSLIntegrator::value(const T & fn,
const typename T::ArgType lower,
const typename T::ArgType upper) const {
+ typename BinaryOpTraits<typename T::ValType,
+ typename T::ArgType>::MulT error;
+ return value(fn,lower,upper,error);
+}
+
+
+template <class T>
+inline typename BinaryOpTraits<typename T::ValType,
+ typename T::ArgType>::MulT
+GSLIntegrator::value(const T & fn,
+ const typename T::ArgType lower,
+ const typename T::ArgType upper,
+ typename BinaryOpTraits<typename T::ValType,
+ typename T::ArgType>::MulT & error) const {
typedef typename T::ValType ValType;
typedef typename T::ArgType ArgType;
const ValType ValUnit = TypeTraits<ValType>::baseunit;
const ArgType ArgUnit = TypeTraits<ArgType>::baseunit;
- double result(0.), error(0.);
+ double result(0.), error2(0.);
param<T> parameters = { fn };
gsl_function integrationFunction;
integrationFunction.function = &integrand<T>;
integrationFunction.params = &parameters;
gsl_integration_workspace * workspace =
gsl_integration_workspace_alloc(_nbins);
//do integration
//Want to check error messages ourselves
gsl_error_handler_t * oldhandler = gsl_set_error_handler_off();
int status = gsl_integration_qags(&integrationFunction, lower/ArgUnit,
upper/ArgUnit, _abserr, _relerr, _nbins,
- workspace, &result, &error);
+ workspace, &result, &error2);
if( status > 0 ) {
CurrentGenerator::log() << "An error occurred in the GSL "
"integration subroutine:\n";
switch( status ) {
case GSL_EMAXITER:
CurrentGenerator::log() << "The maximum number of subdivisions "
"was exceeded.\n";
break;
case GSL_EROUND:
CurrentGenerator::log() << "Cannot reach tolerance because of "
"roundoff error, or roundoff error was detected in the "
"extrapolation table.\n";
break;
case GSL_ESING:
CurrentGenerator::log() << "A non-integrable singularity or "
"other bad integrand behavior was found in the integration "
"interval.\n";
break;
case GSL_EDIVERGE:
break;
default:
CurrentGenerator::log() << "A general error occurred with code "
<< status << '\n';
}
result = 0.;
}
gsl_set_error_handler(oldhandler);
gsl_integration_workspace_free(workspace);
//fix units and return
+ error = error2* ValUnit * ArgUnit;
return result * ValUnit * ArgUnit;
}
}
diff --git a/src/LHC-MUED-no3body.in b/src/LHC-MUED-no3body.in
deleted file mode 100644
--- a/src/LHC-MUED-no3body.in
+++ /dev/null
@@ -1,73 +0,0 @@
-##################################################
-# Example generator for the MUED
-# The best way to use this is to make your own
-# copy of this file and edit that as you require.
-#
-# The first section loads the model file which
-# does not contain anything that users need to touch.
-#
-# The second section contains the user settings.
-###################################################
-
-read MUED.model
-cd /Herwig/NewPhysics
-
-##################################################
-#
-# This section contains the user defined settings
-#
-##################################################
-
-# The UED parameters (these are the default)
-set MUED/Model:InverseRadius 500.*GeV
-set MUED/Model:LambdaR 20
-
-# --- Hard Process ----
-# The particle name can be found in the relevant model file
-# by searching for its PDG code and noting the text
-# '/Herwig/Particles/###' where the hashes denote the name
-
-# Switch to decide whether to include EW diagrams in the
-# hard process (On by default)
-set HPConstructor:IncludeEW No
-
-# Example hard process: Incoming proton, outgoing kk quarks
-insert HPConstructor:Incoming 0 /Herwig/Particles/g
-insert HPConstructor:Incoming 1 /Herwig/Particles/u
-insert HPConstructor:Incoming 2 /Herwig/Particles/ubar
-insert HPConstructor:Incoming 3 /Herwig/Particles/d
-insert HPConstructor:Incoming 4 /Herwig/Particles/dbar
-
-insert HPConstructor:Outgoing 0 /Herwig/Particles/KK1_u_L
-insert HPConstructor:Outgoing 1 /Herwig/Particles/KK1_u_Lbar
-insert HPConstructor:Outgoing 2 /Herwig/Particles/KK1_d_L
-insert HPConstructor:Outgoing 3 /Herwig/Particles/KK1_d_Lbar
-
-
-# --- Perturbative Decays ---
-# All of the two- and three-body decay modes are calculated automatically.
-# Set the next line to 'Yes' to enable the creation of the three-body modes.
-# Initialisation of all three-body decayers will take several minutes.
-# For production runs, they should be enabled!
-set ThreeBodyDC:CreateDecayModes No
-
-# To disable a particular decay mode, add it's tag to the DisableModes
-# interface of the DecayConstructor object, i.e.
-#insert DecayConstructor:DisableModes 0 KK1_u_L->KK1_Z0,u;
-#insert DecayConstructor:DisableModes 1 KK1_Z0->KK1_e_R-,e+;
-# etc ...
-
-# To set a minimum allowed branching fraction (the default is shown)
-#set NewModel:MinimumBR 1e-6
-
-# Intrinsic pT tune extrapolated to LHC energy
-set /Herwig/Shower/Evolver:IntrinsicPtGaussian 2.2*GeV
-
-# Other parameters for run
-cd /Herwig/Generators
-set LHCGenerator:NumberOfEvents 10000000
-set LHCGenerator:RandomNumberGenerator:Seed 31122001
-set LHCGenerator:PrintEvent 10
-set LHCGenerator:MaxErrors 10000
-
-saverun LHC-MUED-no3body LHCGenerator
diff --git a/src/Makefile.am b/src/Makefile.am
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,133 +1,131 @@
SUBDIRS = defaults
AUTOMAKE_OPTIONS = -Wno-portability
defaultsdir = ${pkgdatadir}/defaults
bin_PROGRAMS = Herwig++
Herwig___SOURCES = Herwig++.cc herwigopts.c herwigopts.h
BUILT_SOURCES = herwigopts.c herwigopts.h
Herwig___LDFLAGS = $(AM_LDFLAGS) -export-dynamic $(THEPEGLDFLAGS)
Herwig___LDADD = $(THEPEGLIB) -ldl
Herwig___CPPFLAGS = $(AM_CPPFLAGS) \
-DHERWIG_PKGDATADIR="\"$(pkgdatadir)\"" \
-DHERWIG_PKGLIBDIR="\"$(pkglibdir)\"" \
-DTHEPEG_PKGLIBDIR="\"$(THEPEGPATH)/lib/ThePEG\""
bin_SCRIPTS = herwig-config
HELPERFILES = SPhenoSPS1a.spc NMSSM.spc MUED.model MSSM.model NMSSM.model\
RS.model ADD.model Leptoquark.model
INPUTFILES = ILC.in LEP.in LHC.in TVT.in LHC-MSSM.in \
LHC-MUED.in LHC-NMSSM.in LHC-RS.in LHC-ADD.in\
ILC-MSSM.in ILC-MUED.in ILC-RS.in DIS.in LHC-Powheg.in \
TVT-Powheg.in GammaGamma.in LHC-TRP.in LHC-diffractive.in \
LHC-GammaGamma.in LHC-LQ.in LHC-MU900-2.in LHC-UE7-2.in \
LHC-UE-EE-2.in LHC-UE-EE-3-CTEQ6L1.in LHC-UE-EE-3.in
-## provide -no3body for faster 'make check'
-dist_noinst_DATA = LHC-MUED-no3body.in
dist_pkgdata_DATA = $(INPUTFILES) $(HELPERFILES)
pkgdata_DATA = Makefile-UserModules
CLEANFILES = HerwigDefaults.rpo \
*.run *.log *.out *.tex \
multi.test *.output probs.test chisq.value \
- LHC-RS-BR.spc LHC-MUED-no3body-BR.spc LHC-MSSM-BR.spc
+ LHC-RS-BR.spc LHC-MSSM-BR.spc
## checking targets ##
HerwigDefaults.rpo: Herwig++ $(srcdir)/defaults/*.in defaults/PDF.in defaults/Analysis.in $(top_builddir)/lib/*.so
./Herwig++ init -L$(top_builddir)/lib -i defaults/HerwigDefaults.in -D
check_BSM_Full=
check_BSM=
if WANT_MSSM
check_BSM += check-LHC-MSSM
check_BSM_Full += check-LHC-MSSM
endif
if WANT_NMSSM
check_BSM_Full += check-LHC-NMSSM
endif
if WANT_UED
-check_BSM += check-LHC-MUED-no3body
+check_BSM += check-LHC-MUED
check_BSM_Full += check-LHC-MUED
endif
if WANT_RS
check_BSM += check-LHC-RS
check_BSM_Full += check-LHC-RS
endif
if WANT_TRP
check_BSM_Full += check-LHC-TRP
endif
if WANT_ADD
check_BSM_Full += check-LHC-ADD
endif
check-local: check-LHC check-LEP check-DIS check-ILC check-GammaGamma $(check_BSM) check-LHC-Powheg
check-Powheg: check-LHC-Powheg check-TVT-Powheg
check-BSM: $(check_BSM_Full)
link-helper-files:
@for i in $(HELPERFILES); do \
if test -f $(srcdir)/$$i -a ! -e $$i; then \
$(LN_S) -f $(srcdir)/$$i; fi; done
check-%: $(srcdir)/%.in HerwigDefaults.rpo link-helper-files
./Herwig++ read $< -D
./Herwig++ run $(notdir $(subst .in,.run,$<)) -N500 -d1 -D
## valgrind targets ##
VALGRIND=valgrind --leak-check=full --num-callers=25 --freelist-vol=100000000 --leak-resolution=med --trace-children=yes
valgrind: valgrind-init valgrind-read valgrind-run
valgrind-init:
$(VALGRIND) ./Herwig++ init -d1 -D -L$(top_builddir)/lib -i defaults/HerwigDefaults.in \
&> /tmp/valgrind-init.log
valgrind-read:
$(VALGRIND) ./Herwig++ read -d1 -D LHC.in &> /tmp/valgrind-read.log
valgrind-run:
$(VALGRIND) ./Herwig++ run -d1 -D -N5 LHC.run &> /tmp/valgrind-run.log
SETUPTHEPEG=$(THEPEGPATH)/bin/setupThePEG
THEPEGREPO=$(THEPEGPATH)/lib/ThePEG/ThePEGDefaults.rpo
install-data-hook:
@echo Creating repository
@./Herwig++ init -L$(DESTDIR)$(pkglibdir) -i $(DESTDIR)$(defaultsdir)/HerwigDefaults.in -r $(DESTDIR)$(pkgdatadir)/HerwigDefaults.rpo
uninstall-hook:
rm -f $(DESTDIR)$(pkgdatadir)/HerwigDefaults.rpo
register: register-with-thepeg-repo
register-with-thepeg-repo:
@if test -x "$(SETUPTHEPEG)" -a -w "$(THEPEGREPO)"; \
then echo Registering with ThePEG; \
"$(SETUPTHEPEG)" --init \
$(DESTDIR)$(defaultsdir)/HerwigDefaults.in \
-r "$(THEPEGREPO)" -o "$(THEPEGREPO)" \
-l$(DESTDIR)$(pkglibdir) ; \
fi
unregister : unregister-from-thepeg-repo
unregister-from-thepeg-repo:
@if test -x "$(SETUPTHEPEG)" -a -w "$(THEPEGREPO)"; \
then echo Unregistering with ThePEG; \
"$(SETUPTHEPEG)" --init defaults/HerwigCleanup.in \
-r "$(THEPEGREPO)" -o "$(THEPEGREPO)" \
-l$(DESTDIR)$(pkglibdir) ; \
fi
EXTRA_DIST = herwigopts.ggo
GENGETOPT = gengetopt
%opts.h %opts.c : %opts.ggo
$(GENGETOPT) < $<
diff --git a/src/defaults/BSM.in b/src/defaults/BSM.in
--- a/src/defaults/BSM.in
+++ b/src/defaults/BSM.in
@@ -1,128 +1,129 @@
#################################################
# Create the BSM machinery
# This only gets switched on in read if it is
# requested by the user
################################################
mkdir /Herwig/NewPhysics
cd /Herwig/NewPhysics
create Herwig::ModelGenerator NewModel
create Herwig::ResonantProcessConstructor ResConstructor
create Herwig::TwoToTwoProcessConstructor HPConstructor
create Herwig::HiggsVectorBosonProcessConstructor HVConstructor
create Herwig::HiggsVBFProcessConstructor HiggsVBFConstructor
create Herwig::QQHiggsProcessConstructor QQHiggsConstructor
create Herwig::DecayConstructor DecayConstructor
newdef DecayConstructor:QEDGenerator /Herwig/QEDRadiation/SOPHTY
create Herwig::TwoBodyDecayConstructor TwoBodyDC
create Herwig::ThreeBodyDecayConstructor ThreeBodyDC
create Herwig::WeakCurrentDecayConstructor WeakDecayConstructor
+set WeakDecayConstructor:InitPoints 10000
set WeakDecayConstructor:MassCut 2.
# pi-
insert WeakDecayConstructor:Current 0 /Herwig/Decays/Tau1MesonCurrent
insert WeakDecayConstructor:DecayModes 0 pi-;
insert WeakDecayConstructor:Normalisation 0 1.01386262897
# pi-,pi0
insert WeakDecayConstructor:Current 0 /Herwig/Decays/Tau2MesonCurrent
insert WeakDecayConstructor:DecayModes 0 pi-,pi0;
insert WeakDecayConstructor:Normalisation 0 1.17616809738
# e-,nu_ebar
insert WeakDecayConstructor:Current 0 /Herwig/Decays/Tau2LeptonCurrent
insert WeakDecayConstructor:DecayModes 0 e-,nu_ebar;
insert WeakDecayConstructor:Normalisation 0 1.
# mu-,nu_mubar
insert WeakDecayConstructor:Current 0 /Herwig/Decays/Tau2LeptonCurrent
insert WeakDecayConstructor:DecayModes 0 mu-,nu_mubar;
insert WeakDecayConstructor:Normalisation 0 1.
# tau-,nu_taubar
insert WeakDecayConstructor:Current 0 /Herwig/Decays/Tau2LeptonCurrent
insert WeakDecayConstructor:DecayModes 0 tau-,nu_taubar;
insert WeakDecayConstructor:Normalisation 0 1.
# pi-,pi0,pi0
insert WeakDecayConstructor:Current 0 /Herwig/Decays/Tau3PionCurrent
insert WeakDecayConstructor:DecayModes 0 pi-,pi0,pi0;
insert WeakDecayConstructor:Normalisation 0 1.65956712121
# pi-,pi+,pi-
insert WeakDecayConstructor:Current 0 /Herwig/Decays/Tau3PionCurrent
insert WeakDecayConstructor:DecayModes 0 pi-,pi+,pi-;
insert WeakDecayConstructor:Normalisation 0 1.62175791702
# pi-,pi+,pi-,pi0
insert WeakDecayConstructor:Current 0 /Herwig/Decays/Tau4PionCurrent
insert WeakDecayConstructor:DecayModes 0 pi-,pi+,pi-,pi0;
insert WeakDecayConstructor:Normalisation 0 1.09170097618
# pi-,pi0,pi0,pi0
insert WeakDecayConstructor:Current 0 /Herwig/Decays/Tau4PionCurrent
insert WeakDecayConstructor:DecayModes 0 pi-,pi0,pi0,pi0;
insert WeakDecayConstructor:Normalisation 0 1.
# Kbar0,pi-
insert WeakDecayConstructor:Current 0 /Herwig/Decays/TauKPiCurrent
insert WeakDecayConstructor:DecayModes 0 Kbar0,pi-;
insert WeakDecayConstructor:Normalisation 0 1.17156865176
# K-
insert WeakDecayConstructor:Current 0 /Herwig/Decays/Tau1MesonCurrent
insert WeakDecayConstructor:DecayModes 0 K-;
insert WeakDecayConstructor:Normalisation 0 0.938794564668
# K-,pi0
insert WeakDecayConstructor:Current 0 /Herwig/Decays/TauKPiCurrent
insert WeakDecayConstructor:DecayModes 0 K-,pi0;
insert WeakDecayConstructor:Normalisation 0 1.12526014943
# pi-,pi-,pi+,pi0,pi0
insert WeakDecayConstructor:Current 0 /Herwig/Decays/Tau5PionCurrent
insert WeakDecayConstructor:DecayModes 0 pi-,pi-,pi+,pi0,pi0;
insert WeakDecayConstructor:Normalisation 0 0.954286993254
# pi-,pi-,pi-,pi+,pi+
insert WeakDecayConstructor:Current 0 /Herwig/Decays/Tau5PionCurrent
insert WeakDecayConstructor:DecayModes 0 pi+,pi+,pi+,pi-,pi-;
insert WeakDecayConstructor:Normalisation 0 0.435953860245
# pi-,pi0,pi0,pi0,pi0
insert WeakDecayConstructor:Current 0 /Herwig/Decays/Tau5PionCurrent
insert WeakDecayConstructor:DecayModes 0 pi+,pi0,pi0,pi0,pi0;
insert WeakDecayConstructor:Normalisation 0 0.603378959531
# K0,pi+,pi0
insert WeakDecayConstructor:Current 0 /Herwig/Decays/Tau3KaonCurrent
insert WeakDecayConstructor:DecayModes 0 K0,pi+,pi0;
insert WeakDecayConstructor:Normalisation 0 0.380268556539
# K+,pi+,pi-
insert WeakDecayConstructor:Current 0 /Herwig/Decays/Tau3KaonCurrent
insert WeakDecayConstructor:DecayModes 0 K+,pi+,pi-;
insert WeakDecayConstructor:Normalisation 0 0.407904176498
# K+,K-,pi+
insert WeakDecayConstructor:Current 0 /Herwig/Decays/Tau3KaonCurrent
insert WeakDecayConstructor:DecayModes 0 K+,K-,pi+;
insert WeakDecayConstructor:Normalisation 0 0.727416124384
# K+,Kbar0,pi0
insert WeakDecayConstructor:Current 0 /Herwig/Decays/Tau3KaonCurrent
insert WeakDecayConstructor:DecayModes 0 K+,Kbar0,pi0;
insert WeakDecayConstructor:Normalisation 0 0.945076580717
# K_L0,K_S0,pi+
insert WeakDecayConstructor:Current 0 /Herwig/Decays/Tau3KaonCurrent
insert WeakDecayConstructor:DecayModes 0 K_L0,K_S0,pi+;
insert WeakDecayConstructor:Normalisation 0 1.10729951668
# pi+,pi0,gamma
insert WeakDecayConstructor:Current 0 /Herwig/Decays/Tau2MesonPhotonCurrent
insert WeakDecayConstructor:DecayModes 0 pi+,pi0,gamma;
insert WeakDecayConstructor:Normalisation 0 3.13799210805
# eta,pi+,pi0
insert WeakDecayConstructor:Current 0 /Herwig/Decays/Tau3MesonCurrent
insert WeakDecayConstructor:DecayModes 0 eta,pi+,pi0;
insert WeakDecayConstructor:Normalisation 0 0.880539616307
# K+,Kbar0
insert WeakDecayConstructor:Current 0 /Herwig/Decays/Tau2MesonCurrent
insert WeakDecayConstructor:DecayModes 0 K+,Kbar0;
insert WeakDecayConstructor:Normalisation 0 1.62501804004
insert NewModel:HardProcessConstructors[0] HPConstructor
insert NewModel:HardProcessConstructors[1] ResConstructor
insert NewModel:HardProcessConstructors[2] HVConstructor
insert NewModel:HardProcessConstructors[3] HiggsVBFConstructor
insert NewModel:HardProcessConstructors[4] QQHiggsConstructor
newdef NewModel:DecayConstructor DecayConstructor
insert DecayConstructor:NBodyDecayConstructors[0] TwoBodyDC
insert DecayConstructor:NBodyDecayConstructors[1] ThreeBodyDC
# Required to decay the particles before showering so as to keep
# the spin correlations in the decay
create Herwig::HwDecayHandler DecayHandler
newdef DecayHandler:NewStep No
insert DecayHandler:Excluded 0 /Herwig/Particles/tau-
insert DecayHandler:Excluded 1 /Herwig/Particles/tau+

File Metadata

Mime Type
text/x-diff
Expires
Tue, Nov 19, 4:08 PM (1 d, 13 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3805085
Default Alt Text
(797 KB)

Event Timeline