Page Menu
Home
HEPForge
Search
Configure Global Search
Log In
Files
F8309518
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
252 KB
Subscribers
None
View Options
diff --git a/Decay/General/VectorCurrentDecayer.cc b/Decay/General/VectorCurrentDecayer.cc
--- a/Decay/General/VectorCurrentDecayer.cc
+++ b/Decay/General/VectorCurrentDecayer.cc
@@ -1,273 +1,273 @@
// -*- C++ -*-
//
// VectorCurrentDecayer.cc is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2019 The Herwig Collaboration
//
// Herwig is licenced under version 3 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 VectorCurrentDecayer class.
//
#include "VectorCurrentDecayer.h"
#include "ThePEG/Utilities/DescribeClass.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"
#include "Herwig/Decay/GeneralDecayMatrixElement.h"
#include "Herwig/Models/General/BSMModel.h"
using namespace Herwig;
IBPtr VectorCurrentDecayer::clone() const {
return new_ptr(*this);
}
IBPtr VectorCurrentDecayer::fullclone() const {
return new_ptr(*this);
}
void VectorCurrentDecayer::persistentOutput(PersistentOStream & os) const {
os << inpart_ << currentOut_ << current_ << mode_ << wgtloc_ << wgtmax_ << weights_ << cSMmed_;
}
void VectorCurrentDecayer::persistentInput(PersistentIStream & is, int) {
is >> inpart_ >> currentOut_ >> current_ >> mode_ >> wgtloc_ >> wgtmax_ >> weights_ >> cSMmed_;
}
// The following static variable is needed for the type
// description system in ThePEG.
DescribeClass<VectorCurrentDecayer,DecayIntegrator>
describeHerwigVectorCurrentDecayer("Herwig::VectorCurrentDecayer", "Herwig.so");
void VectorCurrentDecayer::Init() {
static ClassDocumentation<VectorCurrentDecayer> documentation
("The VectorCurrentDecayer class is designed for the decays of low mass vector bosons");
}
void VectorCurrentDecayer::setDecayInfo(PDPtr in, const vector<tPDPtr> & outCurrent, WeakCurrentPtr current) {
inpart_ = in;
currentOut_ = outCurrent;
current_ = current;
// cast the model
Ptr<BSMModel>::ptr model = dynamic_ptr_cast<Ptr<BSMModel>::ptr>(generator()->standardModel());
bool foundU(false),foundD(false),foundS(false);
// find the vertices we need and extract the couplings
for(unsigned int ix = 0; ix < model->numberOfVertices(); ++ix ) {
VertexBasePtr vertex = model->vertex(ix);
if(vertex->getNpoint()!=3) continue;
for(unsigned int iloc = 0;iloc < 3; ++iloc) {
vector<long> ext = vertex->search(iloc, in->id());
if(ext.empty()) continue;
for(unsigned int ioff=0;ioff<ext.size();ioff+=3) {
if(iloc!=2) assert(false);
if(abs(ext[ioff])==1 && abs(ext[ioff+1])==1 && ext[ioff]==-ext[ioff+1]) {
foundD = true;
vertex->setCoupling(sqr(in->mass()),getParticleData(1),getParticleData(-1),in);
cSMmed_[0] = vertex->norm();
}
else if(abs(ext[ioff])==2 && abs(ext[ioff+1])==2 && ext[ioff]==-ext[ioff+1]) {
foundU = true;
vertex->setCoupling(sqr(in->mass()),getParticleData(2),getParticleData(-2),in);
cSMmed_[1] = vertex->norm();
}
else if(abs(ext[ioff])==3 && abs(ext[ioff+1])==3 && ext[ioff]==-ext[ioff+1]) {
foundS = true;
vertex->setCoupling(sqr(in->mass()),getParticleData(3),getParticleData(-3),in);
cSMmed_[2] = vertex->norm();
}
}
}
}
if(!foundD) {
throw InitException() << "Cannot find down quark coupling in VectorCurrentDecayer::doinit()";
}
if(!foundU) {
throw InitException() << "Cannot find up quark coupling in VectorCurrentDecayer::doinit()";
}
if(!foundS) {
throw InitException() << "Cannot find strange quark coupling in VectorCurrentDecayer::doinit()";
}
}
int VectorCurrentDecayer::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 VectorCurrentDecayer::doinitrun() {
current_->initrun();
DecayIntegrator::doinitrun();
}
void VectorCurrentDecayer::doinit() {
DecayIntegrator::doinit();
// make sure the current got initialised
current_->init();
// find the mode
for(unsigned int ix=0;ix<current_->numberOfModes();++ix) {
// get the external particles for this mode
int iq(0),ia(0);
tPDVector ptemp = current_->particles(inpart_->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;
}
}
if(!found) {
match = false;
break;
}
}
if(!match) continue;
tPDVector out = {};
out.insert(std::end(out), std::begin(ptemp), std::end(ptemp));
// create the mode
PhaseSpaceModePtr mode = new_ptr(PhaseSpaceMode(inpart_,out,1.));
PhaseSpaceChannel channel(mode,true);
bool done=current_->createMode(inpart_->iCharge(),tcPDPtr(),FlavourInfo(),
ix,mode,0,-1,channel,inpart_->mass());
if(done) {
// the maximum weight and the channel weights
// the weights for the channel
if(weights_.empty()) {
weights_.resize(mode->channels().size(),1./(mode->channels().size()));
}
mode_ = ix;
// special for the two body modes
if(out.size()==2) {
weights_.clear();
mode=new_ptr(PhaseSpaceMode(inpart_,out,1.));
}
mode->maxWeight(wgtmax_);
mode->setWeights(weights_);
addMode(mode);
}
break;
}
}
int VectorCurrentDecayer::modeNumber(bool & cc, vector<long> id) const {
// incoming particle
long idtemp;
tPDPtr p0=getParticleData(id[0]);
idtemp = p0->CC() ? -id[0] : id[0];
if( id[0] ==inpart_->id()) cc=false;
else if(idtemp==inpart_->id()) cc=true ;
else return -1;
vector<int> idout;
for(vector<long>::iterator it=++id.begin();it!=id.end();++it) {
idout.push_back(*it);
}
unsigned int icurr=current_->decayMode(idout);
if(mode_==icurr) return 0;
else return -1;
}
void VectorCurrentDecayer::
constructSpinInfo(const Particle & part, ParticleVector decay) const {
VectorWaveFunction::constructSpinInfo(vectors_,const_ptr_cast<tPPtr>(&part),
Helicity::incoming,true,false);
weakCurrent()->constructSpinInfo(ParticleVector(decay.begin(),decay.end()));
}
double VectorCurrentDecayer::me2(const int ichan, const Particle & part,
const tPDVector & outgoing,
const vector<Lorentz5Momentum> & momenta,
MEOption meopt) const {
using namespace ThePEG::Helicity;
// polarization vectors for the incoming particle
if(meopt==Initialize) {
VectorWaveFunction::calculateWaveFunctions(vectors_,rho_,
const_ptr_cast<tPPtr>(&part),
incoming,false);
// fix rho if no correlations
fixRho(rho_);
}
// work out the mapping for the hadron vector
int nOut = momenta.size();
vector<unsigned int> constants(nOut+1);
vector<PDT::Spin > iSpin(nOut);
vector<int> hadrons(nOut);
int itemp(1);
int ix(nOut);
do {
--ix;
iSpin[ix] = outgoing[ix]->iSpin();
itemp *= iSpin[ix];
constants[ix] = itemp;
hadrons[ix] = outgoing[ix]->id();
}
while(ix>0);
constants[nOut] = 1;
Energy2 scale(sqr(part.mass()));
// calculate the hadron current
Energy q = part.mass();
// currents for the different flavour components
vector<LorentzPolarizationVectorE>
hadronI0(current_->current(tcPDPtr(), FlavourInfo(IsoSpin::IZero, IsoSpin::I3Zero,Strangeness::Zero),
mode(),ichan,q,outgoing,momenta,DecayIntegrator::Calculate));
vector<LorentzPolarizationVectorE>
hadronI1(current_->current(tcPDPtr(), FlavourInfo(IsoSpin::IOne, IsoSpin::I3Zero,Strangeness::Zero),
mode(),ichan,q,outgoing,momenta,DecayIntegrator::Calculate));
vector<LorentzPolarizationVectorE>
hadronssbar(current_->current(tcPDPtr(), FlavourInfo(IsoSpin::IZero, IsoSpin::I3Zero,Strangeness::ssbar),
mode(),ichan,q,outgoing,momenta,DecayIntegrator::Calculate));
// compute the matrix element
GeneralDecayMEPtr newME(new_ptr(GeneralDecayMatrixElement(PDT::Spin1,iSpin)));
vector<unsigned int> ihel(momenta.size()+1);
unsigned int hI0_size = hadronI0.size();
unsigned int hI1_size = hadronI1.size();
unsigned int hss_size = hadronssbar.size();
unsigned int maxsize = max(max(hadronI0.size(),hadronI1.size()),hss_size);
for(unsigned int hhel=0;hhel<maxsize;++hhel) {
// map the index for the hadrons to a helicity state
for(int ix=nOut;ix>0;--ix) {
ihel[ix]=(hhel%constants[ix-1])/constants[ix];
}
for(ihel[0]=0;ihel[0]<3;++ihel[0]) {
Complex amp = 0.;
// work on coefficients for the I1 and I0 bits
if(hI0_size != 0 )
- amp += (cSMmed_[0]+cSMmed_[1])/sqrt(2.)/q*(vectors_[ihel[0]].wave().dot(hadronI0[hhel]));
+ amp += Complex((cSMmed_[0]+cSMmed_[1])/sqrt(2.)/q*(vectors_[ihel[0]].wave().dot(hadronI0[hhel])));
if(hI1_size !=0)
- amp += (cSMmed_[0]-cSMmed_[1])/sqrt(2.)/q*(vectors_[ihel[0]].wave().dot(hadronI1[hhel]));
+ amp += Complex((cSMmed_[0]-cSMmed_[1])/sqrt(2.)/q*(vectors_[ihel[0]].wave().dot(hadronI1[hhel])));
if(hss_size !=0)
- amp += cSMmed_[2] /q*(vectors_[ihel[0]].wave().dot(hadronssbar[hhel]));
+ amp += Complex(cSMmed_[2] /q*(vectors_[ihel[0]].wave().dot(hadronssbar[hhel])));
(*newME)(ihel) = amp;
}
}
// store the matrix element
ME(newME);
// return the answer
double output = (ME()->contract(rho_)).real();
return output;
}
Energy VectorCurrentDecayer::partialWidth(tPDPtr part, vector<tPDPtr> out) {
vector<long> id;
id.push_back(part->id());
for(unsigned int ix=0;ix<out.size();++ix) id.push_back(out[ix]->id());
bool cc;
int mode=modeNumber(cc,id);
imode(mode);
return initializePhaseSpaceMode(mode,true,true);
}
diff --git a/Decay/ScalarMeson/PScalar4FermionsDecayer.cc b/Decay/ScalarMeson/PScalar4FermionsDecayer.cc
--- a/Decay/ScalarMeson/PScalar4FermionsDecayer.cc
+++ b/Decay/ScalarMeson/PScalar4FermionsDecayer.cc
@@ -1,398 +1,398 @@
// -*- C++ -*-
//
// PScalar4FermionsDecayer.cc is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2019 The Herwig Collaboration
//
// Herwig is licenced under version 3 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 PScalar4FermionsDecayer class.
//
#include "PScalar4FermionsDecayer.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/StandardModel/StandardModelBase.h"
#include "ThePEG/PDT/DecayMode.h"
#include "ThePEG/Interface/ParVector.h"
#include "ThePEG/Helicity/ScalarSpinInfo.h"
#include "ThePEG/Helicity/FermionSpinInfo.h"
#include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h"
#include "ThePEG/Helicity/epsilon.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "Herwig/Decay/GeneralDecayMatrixElement.h"
using namespace Herwig;
using namespace ThePEG::Helicity;
void PScalar4FermionsDecayer::doinitrun() {
DecayIntegrator::doinitrun();
if(initialize()) {
for(unsigned int ix=0;ix<_incoming.size();++ix)
_maxweight[ix] = mode(ix)->maxWeight();
}
}
PScalar4FermionsDecayer::PScalar4FermionsDecayer()
: _coupling(1,0.025159062/GeV), _incoming(1,111), _outgoing1(1,11),
_outgoing2(1,11), _maxweight(1,0.000234211),
_includeVMD(1,2),_VMDid(1,113), _VMDmass(1,0.7758*GeV),
_VMDwidth(1,0.1503*GeV), _initsize(1) {
// intermediates
generateIntermediates(false);
}
void PScalar4FermionsDecayer::doinit() {
DecayIntegrator::doinit();
// check the parameters are consistent
unsigned int isize=_coupling.size();
if(isize!=_incoming.size() || isize!=_outgoing1.size() || isize!=_outgoing2.size()||
isize!=_maxweight.size() || isize!=_includeVMD.size()|| isize!=_VMDid.size() ||
isize!=_VMDmass.size() || isize!=_VMDwidth.size())
throw InitException() << "Inconsistent parameters in PScalar4FermionsDecayer"
<< Exception::abortnow;
// create the integration channels for each mode
tPDPtr gamma=getParticleData(ParticleID::gamma);
for(unsigned int ix=0;ix<_incoming.size();++ix) {
tPDPtr in = getParticleData(_incoming[ix]);
tPDVector out={getParticleData( _outgoing1[ix]),
getParticleData(-_outgoing1[ix]),
getParticleData( _outgoing2[ix]),
getParticleData(-_outgoing2[ix])};
PhaseSpaceModePtr mode = new_ptr(PhaseSpaceMode(in,out,_maxweight[ix]));
PhaseSpaceChannel newChannel((PhaseSpaceChannel(mode),0,gamma,0,gamma,1,1,1,2,2,3,2,4));
newChannel.setJacobian(1,PhaseSpaceChannel::PhaseSpaceResonance::Power,-1.1);
newChannel.setJacobian(2,PhaseSpaceChannel::PhaseSpaceResonance::Power,-1.1);
mode->addChannel(newChannel);
PhaseSpaceChannel newChannel2((PhaseSpaceChannel(mode),0,gamma,0,gamma,1,3,1,2,2,1,2,4));
newChannel2.setJacobian(1,PhaseSpaceChannel::PhaseSpaceResonance::Power,-1.1);
newChannel2.setJacobian(2,PhaseSpaceChannel::PhaseSpaceResonance::Power,-1.1);
mode->addChannel(newChannel2);
addMode(mode);
}
// set up the values for the VMD factor if needed (copy the default mass and width
// into the array)
for(unsigned ix=0;ix<isize;++ix) {
if(_includeVMD[ix]==1) {
_VMDmass[ix]=getParticleData(_VMDid[ix])->mass();
_VMDwidth[ix]=getParticleData(_VMDid[ix])->width();
}
}
}
int PScalar4FermionsDecayer::modeNumber(bool & cc,tcPDPtr parent,
const tPDVector & children) const {
// must be four outgoing particles
if(children.size()!=4) return -1;
// get the id's of the outgoing particles
int id[4]={0,0,0,0};
bool done[4]={false,false,false,false};
unsigned int ix(0),iy(0);
// ids of the particles
int id0(parent->id()),idtemp(-1),idl1(-1),idl2(-1),idt[2];
tPDVector::const_iterator pit = children.begin();
for ( ;pit!=children.end();++pit) {
id[ix]=(**pit).id();
done[ix]=false;
++ix;
}
// find the two lepton pairs
// find the first fermion
ix=0;
do {
if( id[ix]>0 && !done[ix] ) {
done[ix]=true;
idtemp=id[ix];
}
++ix;
}
while(ix<4&&idtemp<0);
if(idtemp<0) return -1;
// find its antiparticle
ix=0;
do {
if( id[ix]==-idtemp && !done[ix] ) {
done[ix]=true;
idl1=idtemp;
}
++ix;
} while( ix<4 && idl1<0 );
if(idl1<0) return -1;
// find the second particle antiparticle pair
for(ix=0;ix<4;++ix) {
if(!done[ix]) {
idt[iy]=id[ix];
++iy;
}
}
if(idt[0]==-idt[1]) idl2=abs(idt[0]);
if(idl2<0) return -1;
// loop over the modes and see if this is one of them
ix=0;
int imode(-1);
do {
if(_incoming[ix]==id0) {
if((idl1==_outgoing1[ix]&&idl2==_outgoing2[ix])||
(idl2==_outgoing1[ix]&&idl1==_outgoing2[ix])) imode=ix;
}
++ix;
}
while(imode<0&&ix<_incoming.size());
cc=false;
return imode;
}
void PScalar4FermionsDecayer::persistentOutput(PersistentOStream & os) const {
os << ounit(_coupling,1/MeV)
<< _incoming << _outgoing1 << _outgoing2 << _maxweight
<< _includeVMD << _VMDid
<< ounit(_VMDmass,MeV) << ounit(_VMDwidth,MeV);
}
void PScalar4FermionsDecayer::persistentInput(PersistentIStream & is, int) {
is >> iunit(_coupling,1/MeV)
>> _incoming >> _outgoing1 >> _outgoing2 >> _maxweight
>> _includeVMD >> _VMDid
>> iunit(_VMDmass,MeV) >> iunit(_VMDwidth,MeV);
}
// The following static variable is needed for the type
// description system in ThePEG.
DescribeClass<PScalar4FermionsDecayer,DecayIntegrator>
describeHerwigPScalar4FermionsDecayer("Herwig::PScalar4FermionsDecayer", "HwSMDecay.so");
void PScalar4FermionsDecayer::Init() {
static ClassDocumentation<PScalar4FermionsDecayer> documentation
("The PScalar4FermionsDecayer class is designed for the decay"
" of a pseudosclar meson to four fermions. It is intended for the decay of"
"the pion to two electron-positron pairs.");
static ParVector<PScalar4FermionsDecayer,int> interfaceIncoming
("Incoming",
"The PDG code for the incoming particle",
&PScalar4FermionsDecayer::_incoming,
0, 0, 0, -10000, 10000, false, false, true);
static ParVector<PScalar4FermionsDecayer,int> interfaceOutcoming1
("Outgoing1",
"The PDG code for the first outgoing fermion",
&PScalar4FermionsDecayer::_outgoing1,
0, 0, 0, -10000, 10000, false, false, true);
static ParVector<PScalar4FermionsDecayer,int> interfaceOutcoming2
("Outgoing2",
"The PDG code for the second outgoing fermion",
&PScalar4FermionsDecayer::_outgoing2,
0, 0, 0, -10000, 10000, false, false, true);
static ParVector<PScalar4FermionsDecayer,InvEnergy> interfaceCoupling
("Coupling",
"The coupling for the decay mode",
&PScalar4FermionsDecayer::_coupling,
1/MeV, 0, ZERO, -10000/MeV, 10000/MeV, false, false, true);
static ParVector<PScalar4FermionsDecayer,double> interfaceMaxWeight
("MaxWeight",
"The maximum weight for the decay mode",
&PScalar4FermionsDecayer::_maxweight,
0, 0, 0, -10000, 10000, false, false, true);
static ParVector<PScalar4FermionsDecayer,int> interfaceIncludeVMD
("IncludeVMD",
"There are three options for 0 the VMD factor is not included, for 1 the factor "
"is included using the default mass and width of the particle specified by"
" VMDID, and for 2 the factor is included using the mass and width specified"
" by VMDwidth and VMDmass.",
&PScalar4FermionsDecayer::_includeVMD,
0, 0, 0, 0, 2, false, false, true);
static ParVector<PScalar4FermionsDecayer,int> interfaceVMDID
("VMDID",
"The PDG code for the particle to be used for the VMD factor.",
&PScalar4FermionsDecayer::_VMDid,
0, 0, 0, -10000, 10000, false, false, true);
static ParVector<PScalar4FermionsDecayer,Energy> interfaceVMDmass
("VMDmass",
"The mass to use for the particle in the VMD factor",
&PScalar4FermionsDecayer::_VMDmass,
1.*MeV, -1, ZERO, -10000*MeV, 10000*MeV, false, false, true);
static ParVector<PScalar4FermionsDecayer,Energy> interfaceVMDwidth
("VMDwidth",
"The width to use for the particle in the VMD factor",
&PScalar4FermionsDecayer::_VMDwidth,
1.*MeV, -1, ZERO, -10000*MeV, 10000*MeV, false, false, true);
}
void PScalar4FermionsDecayer::
constructSpinInfo(const Particle & part, ParticleVector decay) const {
// set up the spin information for the decay products
ScalarWaveFunction::constructSpinInfo(const_ptr_cast<tPPtr>(&part),
incoming,true);
// set up the spin information for the decay products
for(unsigned int ix=0;ix<2;++ix) {
SpinorBarWaveFunction::
constructSpinInfo(_wavebar[ix],decay[2*ix ],outgoing,true);
SpinorWaveFunction::
constructSpinInfo(_wave[ix] ,decay[2*ix+1],outgoing,true);
}
}
double PScalar4FermionsDecayer::me2(const int,const Particle & part,
const tPDVector &,
const vector<Lorentz5Momentum> & momenta,
MEOption meopt) const {
if(!ME())
ME(new_ptr(GeneralDecayMatrixElement(PDT::Spin0,PDT::Spin1Half,PDT::Spin1Half,
PDT::Spin1Half,PDT::Spin1Half)));
bool identical((_outgoing1[imode()]==_outgoing2[imode()]));
if(meopt==Initialize) {
ScalarWaveFunction::
calculateWaveFunctions(_rho,const_ptr_cast<tPPtr>(&part),incoming);
}
// calculate the spinors
for(unsigned int ix=0;ix<2;++ix) {
_wavebar[ix].resize(2);
_wave [ix].resize(2);
for(unsigned int ihel=0;ihel<2;++ihel) {
_wavebar[ix][ihel] = HelicityFunctions::dimensionedSpinorBar(-momenta[2*ix ],ihel,Helicity::outgoing);
_wave [ix][ihel] = HelicityFunctions::dimensionedSpinor (-momenta[2*ix+1],ihel,Helicity::outgoing);
}
}
// // momenta of the outgoing photons
Lorentz5Momentum poff[4];
poff[0]=momenta[0]+momenta[1];
poff[0].rescaleMass();
poff[1]=momenta[2]+momenta[3];
poff[1].rescaleMass();
if(identical) {
poff[2]=momenta[2]+momenta[1];
poff[2].rescaleMass();
poff[3]=momenta[0]+momenta[3];
poff[3].rescaleMass();
}
// compute the currents for the two leptonic decays
LorentzPolarizationVectorE current[4][2][2];
unsigned int it,ix,iy,iz;
for(iz=0;iz<2;++iz) {
it = iz==0 ? 1 : 0;
for(ix=0;ix<2;++ix) {
for(iy=0;iy<2;++iy) {
current[iz][iy][ix] = _wave[iz][ix].vectorCurrent(_wavebar[iz][iy]);
// the second two currents
if(identical)
current[iz+2][iy][ix] = _wave[it][ix].vectorCurrent(_wavebar[iz][iy]);
}
}
}
// invariants
Energy2 m12(sqr(poff[0].mass()));
Energy2 m34(sqr(poff[1].mass()));
Energy2 m14(ZERO), m23(ZERO);
complex<InvEnergy4> prop1(1./m12/m34),prop2(0./sqr(MeV2));
Complex ii(0.,1.);
if(identical) {
m14=poff[2].mass()*poff[2].mass();
m23=poff[3].mass()*poff[3].mass();
prop2=1./m14/m23;
}
// the VMD factor if needed
if(_includeVMD[imode()]>0) {
Energy2 mrho2(_VMDmass[imode()]*_VMDmass[imode()]);
Energy2 mwrho(_VMDmass[imode()]*_VMDwidth[imode()]);
prop1 = prop1*(-mrho2+ii*mwrho)/(m12-mrho2+ii*mwrho)*
(-mrho2+ii*mwrho)/(m34-mrho2+ii*mwrho);
if(identical) {
prop2 = prop2*(-mrho2+ii*mwrho)/(m14-mrho2+ii*mwrho)*
(-mrho2+ii*mwrho)/(m23-mrho2+ii*mwrho);
}
}
// prefactor
Complex pre(_coupling[imode()]*4.*Constants::pi
*SM().alphaEM()*part.mass());
Complex diag;
// now compute the matrix element
LorentzVector<complex<Energy3> > eps;
vector<unsigned int> ispin(5,0);
for(ispin[1]=0; ispin[1]<2;++ispin[1]) {
for(ispin[2]=0;ispin[2]<2;++ispin[2]) {
for(ispin[3]=0;ispin[3]<2;++ispin[3]) {
for(ispin[4]=0;ispin[4]<2;++ispin[4]) {
// the first diagram
eps = epsilon(current[0][ispin[1]][ispin[2]],poff[1],
current[1][ispin[3]][ispin[4]]);
- diag = prop1*(eps*poff[0]);
+ diag = Complex(prop1*(eps*poff[0]));
// exchanged diagram if identical particles
// (sign due normal ordering)
if(identical) {
eps = epsilon(current[2][ispin[1]][ispin[4]],poff[3],
current[3][ispin[3]][ispin[2]]);
- diag-= prop2*(eps*poff[2]);
+ diag-= Complex(prop2*(eps*poff[2]));
}
(*ME())(ispin)=pre*diag;
}
}
}
}
double me=ME()->contract(_rho).real();
if(identical) me *= 0.25;
return me;
}
// output the setup info for the particle database
void PScalar4FermionsDecayer::dataBaseOutput(ofstream & output,
bool header) const {
if(header) output << "update decayers set parameters=\"";
// parameters for the DecayIntegrator base class
DecayIntegrator::dataBaseOutput(output,false);
for(unsigned int ix=0;ix<_incoming.size();++ix) {
if(ix<_initsize) {
output << "newdef " << name() << ":Incoming " << ix << " "
<< _incoming[ix] << "\n";
output << "newdef " << name() << ":Outgoing1 " << ix << " "
<< _outgoing1[ix] << "\n";
output << "newdef " << name() << ":Outgoing2 " << ix << " "
<< _outgoing2[ix] << "\n";
output << "newdef " << name() << ":Coupling " << ix << " "
<< _coupling[ix]*MeV << "\n";
output << "newdef " << name() << ":MaxWeight " << ix << " "
<< _maxweight[ix] << "\n";
output << "newdef " << name() << ":IncludeVMD " << ix << " "
<< _includeVMD[ix] << "\n";
output << "newdef " << name() << ":VMDID " << ix << " "
<< _VMDid[ix] << "\n";
output << "newdef " << name() << ":VMDmass " << ix << " "
<< _VMDmass[ix]/MeV << "\n";
output << "newdef " << name() << ":VMDwidth " << ix << " "
<< _VMDwidth[ix]/MeV << "\n";
}
else {
output << "insert " << name() << ":Incoming " << ix << " "
<< _incoming[ix] << "\n";
output << "insert " << name() << ":Outgoing1 " << ix << " "
<< _outgoing1[ix] << "\n";
output << "insert " << name() << ":Outgoing2 " << ix << " "
<< _outgoing2[ix] << "\n";
output << "insert " << name() << ":Coupling " << ix << " "
<< _coupling[ix]*MeV << "\n";
output << "insert " << name() << ":MaxWeight " << ix << " "
<< _maxweight[ix] << "\n";
output << "insert " << name() << ":IncludeVMD " << ix << " "
<< _includeVMD[ix] << "\n";
output << "insert " << name() << ":VMDID " << ix << " "
<< _VMDid[ix] << "\n";
output << "insert " << name() << ":VMDmass " << ix << " "
<< _VMDmass[ix]/MeV << "\n";
output << "insert " << name() << ":VMDwidth " << ix << " "
<< _VMDwidth[ix]/MeV << "\n";
}
}
if(header) output << "\n\" where BINARY ThePEGName=\"" << fullName() << "\";" << endl;
}
diff --git a/Decay/ScalarMeson/PScalarPScalarVectorDecayer.cc b/Decay/ScalarMeson/PScalarPScalarVectorDecayer.cc
--- a/Decay/ScalarMeson/PScalarPScalarVectorDecayer.cc
+++ b/Decay/ScalarMeson/PScalarPScalarVectorDecayer.cc
@@ -1,283 +1,283 @@
// -*- C++ -*-
//
// PScalarPScalarVectorDecayer.cc is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2019 The Herwig Collaboration
//
// Herwig is licenced under version 3 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 PScalarPScalarVectorDecayer class.
//
#include "PScalarPScalarVectorDecayer.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/ParVector.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/VectorWaveFunction.h"
#include "Herwig/Decay/TwoBodyDecayMatrixElement.h"
#include "ThePEG/Helicity/HelicityFunctions.h"
using namespace Herwig;
using namespace ThePEG::Helicity;
void PScalarPScalarVectorDecayer::doinitrun() {
DecayIntegrator::doinitrun();
if(initialize()) {
for(unsigned int ix=0;ix<_incoming.size();++ix)
if(mode(ix)) _maxweight[ix] = mode(ix)->maxWeight();
}
}
PScalarPScalarVectorDecayer::PScalarPScalarVectorDecayer() {
_incoming = { 100111, 100211, 100211, 100311, 100321, 100311, 100321,
100311, 100321, 100311, 100321, 100331, 100331,9020221,9020221,
10221, 10221,9030221,9030221};
_outgoingP = { -211, 111, 211, 311, 321, 321, 311,
111, 111, -211, 211, -321, -311, -321, -311,
-211, 111, -211, 111};
_outgoingV = { 213, 213, 113, 113, 113, -213, 213,
313, 323, 323, 313, 323, 313, 323, 313,
20213, 20113, 20213, 20113};
_coupling = { 3.57, 3.57, 3.57, 1., 1., 1.41, 1.41,
1.55, 1.55, 2.19, 2.19, 2.92, 2.92, 0.956, 0.956,
2.68, 2.68, 1.147, 1.147};
_maxweight = { 4.5, 4.5, 4.5, 4., 4., 4., 4.,
2., 2., 2., 2., 3.5, 3.5, 4., 4.,
4.5, 4.5, 3.2, 3.2};
// initial size of the arrays
_initsize=_incoming.size();
// intermediates
generateIntermediates(false);
}
void PScalarPScalarVectorDecayer::doinit() {
DecayIntegrator::doinit();
// check the parameters arew consistent
unsigned int isize=_coupling.size();
if(isize!=_incoming.size() || isize!=_outgoingP.size()||
isize!=_outgoingV.size() || isize!=_maxweight.size())
throw InitException() << "Inconsistent parameters in PScalarPScalarVectorDecayer"
<< Exception::abortnow;
// set up the integration channels
PhaseSpaceModePtr mode;
for(unsigned int ix=0;ix<_incoming.size();++ix) {
tPDPtr in = getParticleData( _incoming[ix]);
tPDVector out = {getParticleData(_outgoingP[ix]),
getParticleData(_outgoingV[ix])};
if(in&&out[0]&&out[1])
mode = new_ptr(PhaseSpaceMode(in,out,_maxweight[ix]));
else
mode=PhaseSpaceModePtr();
addMode(mode);
}
}
int PScalarPScalarVectorDecayer::modeNumber(bool & cc,tcPDPtr parent,
const tPDVector & children) const {
if(children.size()!=2) return -1;
int id(parent->id());
int idbar = parent->CC() ? parent->CC()->id() : id;
int id1(children[0]->id());
int id1bar = children[0]->CC() ? children[0]->CC()->id() : id1;
int id2(children[1]->id());
int id2bar = children[1]->CC() ? children[1]->CC()->id() : id2;
int imode(-1);
unsigned int ix(0);
cc=false;
do {
if(id ==_incoming[ix]) {
if((id1 ==_outgoingP[ix]&&id2 ==_outgoingV[ix])||
(id2 ==_outgoingP[ix]&&id1 ==_outgoingV[ix])) imode=ix;
}
if(idbar==_incoming[ix]) {
if((id1bar==_outgoingP[ix]&&id2bar==_outgoingV[ix])||
(id2bar==_outgoingP[ix]&&id1bar==_outgoingV[ix])) {
imode=ix;
cc=true;
}
}
++ix;
}
while(ix<_incoming.size()&&imode<0);
return imode;
}
void PScalarPScalarVectorDecayer::persistentOutput(PersistentOStream & os) const {
os << _coupling << _incoming << _outgoingP << _outgoingV << _maxweight;
}
void PScalarPScalarVectorDecayer::persistentInput(PersistentIStream & is, int) {
is >> _coupling >> _incoming >> _outgoingP >> _outgoingV >> _maxweight;
}
// The following static variable is needed for the type
// description system in ThePEG.
DescribeClass<PScalarPScalarVectorDecayer,DecayIntegrator>
describeHerwigPScalarPScalarVectorDecayer("Herwig::PScalarPScalarVectorDecayer", "HwSMDecay.so");
void PScalarPScalarVectorDecayer::Init() {
static ClassDocumentation<PScalarPScalarVectorDecayer> documentation
("The PScalarPScalarVectorDecayer class is designed for"
" the decay of a pseduoscalar meson to two spin-1 particles.");
static ParVector<PScalarPScalarVectorDecayer,int> interfaceIncoming
("Incoming",
"The PDG code for the incoming particle",
&PScalarPScalarVectorDecayer::_incoming,
0, 0, 0, -10000000, 10000000, false, false, true);
static ParVector<PScalarPScalarVectorDecayer,int> interfaceOutgoingScalar
("OutgoingPScalar",
"The PDG code for the outgoing pseudoscalar meson",
&PScalarPScalarVectorDecayer::_outgoingP,
0, 0, 0, -10000000, 10000000, false, false, true);
static ParVector<PScalarPScalarVectorDecayer,int> interfaceOutgoingVector
("OutgoingVector",
"The PDG code for the outgoing vector meson",
&PScalarPScalarVectorDecayer::_outgoingV,
0, 0, 0, -10000000, 10000000, false, false, true);
static ParVector<PScalarPScalarVectorDecayer,double> interfaceCoupling
("Coupling",
"The coupling for the decay mode",
&PScalarPScalarVectorDecayer::_coupling,
0, 0, 0, 0., 100., false, false, true);
static ParVector<PScalarPScalarVectorDecayer,double> interfaceMaxWeight
("MaxWeight",
"The maximum weight for the decay mode",
&PScalarPScalarVectorDecayer::_maxweight,
0, 0, 0, 0., 100., false, false, true);
}
void PScalarPScalarVectorDecayer::
constructSpinInfo(const Particle & part, ParticleVector decay) const {
// set up the spin information for the decay products
ScalarWaveFunction::constructSpinInfo(const_ptr_cast<tPPtr>(&part),
incoming,true);
ScalarWaveFunction::constructSpinInfo(decay[0],outgoing,true);
VectorWaveFunction::constructSpinInfo(_vectors,decay[1],
outgoing,true,false);
}
double PScalarPScalarVectorDecayer::me2(const int,const Particle & part,
const tPDVector & outgoing,
const vector<Lorentz5Momentum> & momenta,
MEOption meopt) const {
if(!ME())
ME(new_ptr(TwoBodyDecayMatrixElement(PDT::Spin0,PDT::Spin0,PDT::Spin1)));
if(meopt==Initialize) {
ScalarWaveFunction::
calculateWaveFunctions(_rho,const_ptr_cast<tPPtr>(&part),incoming);
}
_vectors.resize(3);
bool massless = outgoing[1]->id()==ParticleID::gamma;
for(unsigned int ix=0;ix<3;++ix) {
if(massless && ix==1) continue;
_vectors[ix] = HelicityFunctions::polarizationVector(-momenta[1],ix,Helicity::outgoing);
}
// calculate the matrix element
Lorentz5Momentum psum(part.momentum()+momenta[0]);
for(unsigned int ix=0;ix<3;++ix) {
- (*ME())(0,0,ix)=_coupling[imode()]/part.mass()*(_vectors[ix]*psum);
+ (*ME())(0,0,ix) = Complex(_coupling[imode()]/part.mass()*(_vectors[ix]*psum));
}
double me=ME()->contract(_rho).real();
// test of the matrix element
// Energy pcm = Kinematics::pstarTwoBodyDecay(part.mass(),momenta[0].mass(),
// momenta[1].mass());
// double test = 4.*sqr(_coupling[imode()]*pcm/momenta[1].mass());
// cerr << "testing matrix element for " << part.PDGName() << " -> "
// << outgoing[0]->PDGName() << " " << outgoing[1]->PDGName() << " "
// << me << " " << (me-test)/(me+test) << "\n";
// output the answer
return me;
}
// specify the 1-2 matrix element to be used in the running width calculation
bool PScalarPScalarVectorDecayer::twoBodyMEcode(const DecayMode & dm, int & mecode,
double & coupling) const {
int imode(-1);
int id(dm.parent()->id());
int idbar = dm.parent()->CC() ? dm.parent()->CC()->id() : id;
ParticleMSet::const_iterator pit(dm.products().begin());
int id1((**pit).id());
int id1bar = (**pit).CC() ? (**pit).CC()->id() : id1;
++pit;
int id2((**pit).id());
int id2bar = (**pit).CC() ? (**pit).CC()->id() : id2;
unsigned int ix(0); bool order(true);
do {
if(id ==_incoming[ix]) {
if(id1==_outgoingP[ix]&&id2==_outgoingV[ix]) {
imode=ix;
order=true;
}
if(id2==_outgoingP[ix]&&id1==_outgoingV[ix]) {
imode=ix;
order=false;
}
}
if(idbar==_incoming[ix]&&imode<0) {
if(id1bar==_outgoingP[ix]&&id2bar==_outgoingV[ix]) {
imode=ix;
order=true;
}
if(id2bar==_outgoingP[ix]&&id1bar==_outgoingV[ix]) {
imode=ix;
order=false;
}
}
++ix;
}
while(ix<_incoming.size()&&imode<0);
coupling=_coupling[imode];
mecode=10;
return order;
}
// output the setup information for the particle database
void PScalarPScalarVectorDecayer::dataBaseOutput(ofstream & output,
bool header) const {
if(header) output << "update decayers set parameters=\"";
// parameters for the DecayIntegrator base class
DecayIntegrator::dataBaseOutput(output,false);
// the rest of the parameters
for(unsigned int ix=0;ix<_incoming.size();++ix) {
if(ix<_initsize) {
output << "newdef " << name() << ":Incoming " << ix << " "
<< _incoming[ix] << "\n";
output << "newdef " << name() << ":OutgoingPScalar " << ix << " "
<< _outgoingP[ix] << "\n";
output << "newdef " << name() << ":OutgoingVector " << ix << " "
<< _outgoingV[ix] << "\n";
output << "newdef " << name() << ":Coupling " << ix << " "
<< _coupling[ix] << "\n";
output << "newdef " << name() << ":MaxWeight " << ix << " "
<< _maxweight[ix] << "\n";
}
else {
output << "insert " << name() << ":Incoming " << ix << " "
<< _incoming[ix] << "\n";
output << "insert " << name() << ":OutgoingPScalar " << ix << " "
<< _outgoingP[ix] << "\n";
output << "insert " << name() << ":OutgoingVector " << ix << " "
<< _outgoingV[ix] << "\n";
output << "insert " << name() << ":Coupling " << ix << " "
<< _coupling[ix] << "\n";
output << "insert " << name() << ":MaxWeight " << ix << " "
<< _maxweight[ix] << "\n";
}
}
if(header) output << "\n\" where BINARY ThePEGName=\""
<< fullName() << "\";" << endl;
}
diff --git a/Decay/ScalarMeson/PScalarVectorVectorDecayer.cc b/Decay/ScalarMeson/PScalarVectorVectorDecayer.cc
--- a/Decay/ScalarMeson/PScalarVectorVectorDecayer.cc
+++ b/Decay/ScalarMeson/PScalarVectorVectorDecayer.cc
@@ -1,275 +1,275 @@
// -*- C++ -*-
//
// PScalarVectorVectorDecayer.cc is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2019 The Herwig Collaboration
//
// Herwig is licenced under version 3 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 PScalarVectorVectorDecayer class.
//
#include "PScalarVectorVectorDecayer.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/ParVector.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "Herwig/Utilities/Kinematics.h"
#include "ThePEG/PDT/DecayMode.h"
#include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
#include "ThePEG/Helicity/epsilon.h"
#include "Herwig/Decay/TwoBodyDecayMatrixElement.h"
using namespace Herwig;
using namespace ThePEG::Helicity;
void PScalarVectorVectorDecayer::doinitrun() {
DecayIntegrator::doinitrun();
if(initialize()) {
for(unsigned int ix=0;ix<_incoming.size();++ix)
_maxweight[ix] = mode(ix)->maxWeight();
}
}
PScalarVectorVectorDecayer::PScalarVectorVectorDecayer()
: _incoming(10), _outgoing1(10), _outgoing2(10), _coupling(10), _maxweight(10) {
// decay eta -> omega gamma
_incoming[0] = 331; _outgoing1[0] = 223; _outgoing2[0] = 22;
_coupling[0] = 0.1412/GeV; _maxweight[0] = 1.2;
// decay pi -> gamma gamma
_incoming[1] = 111; _outgoing1[1] = 22; _outgoing2[1] = 22;
_coupling[1] = 0.0178/GeV; _maxweight[1] = 1.1;
// decay eta -> gamma gamma
_incoming[2] = 221; _outgoing1[2] = 22; _outgoing2[2] = 22;
_coupling[2] = 0.0176/GeV; _maxweight[2] = 1.1;
// decay eta' -> gamma gamma
_incoming[3] = 331; _outgoing1[3] = 22; _outgoing2[3] = 22;
_coupling[3] = 0.0221/GeV; _maxweight[3] = 1.1;
// decay eta_c -> rho rho
_incoming[4] = 441; _outgoing1[4] = 213; _outgoing2[4] = -213;
_coupling[4] = 0.0525/GeV; _maxweight[4] = 2.7;
_incoming[5] = 441; _outgoing1[5] = 113; _outgoing2[5] = 113;
_coupling[5] = 0.0371/GeV; _maxweight[5] = 2.7;
// decay eta-c -> phi phi
_incoming[6] = 441; _outgoing1[6] = 333; _outgoing2[6] = 333;
_coupling[6] = 0.0267/GeV; _maxweight[6] = 9.;
// decay eta-c -> gamma gamma
_incoming[7] = 441; _outgoing1[7] = 22; _outgoing2[7] = 22;
_coupling[7] = 0.00521/GeV; _maxweight[7] = 1.2;
// decay eta_c -> K* K*
_incoming[8] = 441; _outgoing1[8] = 323; _outgoing2[8] = -323;
_coupling[8] = 0.0308/GeV; _maxweight[8] = 5.3;
_incoming[9] = 441; _outgoing1[9] = 313; _outgoing2[9] = -313;
_coupling[9] = 0.0308/GeV; _maxweight[9] = 5.3;
// initial size of the vectors
_initsize = _incoming.size();
// intermediates
generateIntermediates(false);
}
void PScalarVectorVectorDecayer::doinit() {
DecayIntegrator::doinit();
// check the parameters arew consistent
unsigned int isize(_coupling.size());
if(isize!=_incoming.size() || isize!=_outgoing1.size()||
isize!=_outgoing2.size() || isize!=_maxweight.size())
throw InitException() << "Inconsistent parameters in PScalarVectorVectorDecayer"
<< Exception::abortnow;
// set up the integration channels
vector<double> wgt;
PhaseSpaceModePtr mode;
for(unsigned int ix=0;ix<_incoming.size();++ix) {
tPDPtr in = getParticleData( _incoming[ix]);
tPDVector out = {getParticleData(_outgoing1[ix]),
getParticleData(_outgoing2[ix])};
if(in&&out[0]&&out[1])
mode = new_ptr(PhaseSpaceMode(in,out,_maxweight[ix]));
else
mode=PhaseSpaceModePtr();
addMode(mode);
}
}
int PScalarVectorVectorDecayer::modeNumber(bool & cc,tcPDPtr parent,
const tPDVector & children) const {
cc = false;
if(children.size()!=2) return -1;
int id(parent->id());
int id1(children[0]->id());
int id2(children[1]->id());
unsigned int ix(0);
int imode(-1);
do {
if(_incoming[ix]==id) {
if((id1==_outgoing1[ix]&&id2==_outgoing2[ix])||
(id2==_outgoing1[ix]&&id1==_outgoing2[ix])) imode=ix;
}
++ix;
}
while(imode<0&&ix<_incoming.size());
return imode;
}
void PScalarVectorVectorDecayer::persistentOutput(PersistentOStream & os) const {
os << ounit(_coupling,1/GeV) << _incoming << _outgoing1 << _outgoing2 << _maxweight;
}
void PScalarVectorVectorDecayer::persistentInput(PersistentIStream & is, int) {
is >> iunit(_coupling,1/GeV) >> _incoming >> _outgoing1 >> _outgoing2 >> _maxweight;
}
// The following static variable is needed for the type
// description system in ThePEG.
DescribeClass<PScalarVectorVectorDecayer,DecayIntegrator>
describeHerwigPScalarVectorVectorDecayer("Herwig::PScalarVectorVectorDecayer", "HwSMDecay.so");
void PScalarVectorVectorDecayer::Init() {
static ClassDocumentation<PScalarVectorVectorDecayer> documentation
("The PScalarVectorVectorDecayer class is designed for"
" the decay of a pseduoscalar meson to two spin-1 particles.");
static ParVector<PScalarVectorVectorDecayer,int> interfaceIncoming
("Incoming",
"The PDG code for the incoming particle",
&PScalarVectorVectorDecayer::_incoming,
0, 0, 0, -10000000, 10000000, false, false, true);
static ParVector<PScalarVectorVectorDecayer,int> interfaceOutcoming1
("FirstOutgoing",
"The PDG code for the first outgoing particle",
&PScalarVectorVectorDecayer::_outgoing1,
0, 0, 0, -10000000, 10000000, false, false, true);
static ParVector<PScalarVectorVectorDecayer,int> interfaceOutcoming2
("SecondOutgoing",
"The PDG code for the second outgoing particle",
&PScalarVectorVectorDecayer::_outgoing2,
0, 0, 0, -10000000, 10000000, false, false, true);
static ParVector<PScalarVectorVectorDecayer,InvEnergy> interfaceCoupling
("Coupling",
"The coupling for the decay mode",
&PScalarVectorVectorDecayer::_coupling,
1/GeV, 0, ZERO, ZERO, 10000/GeV, false, false, true);
static ParVector<PScalarVectorVectorDecayer,double> interfaceMaxWeight
("MaxWeight",
"The maximum weight for the decay mode",
&PScalarVectorVectorDecayer::_maxweight,
0, 0, 0, 0., 200., false, false, true);
}
void PScalarVectorVectorDecayer::
constructSpinInfo(const Particle & part, ParticleVector decay) const {
// set up the spin information for the decay products
ScalarWaveFunction::constructSpinInfo(const_ptr_cast<tPPtr>(&part),
incoming,true);
bool photon[2]={false,false};
for(unsigned int ix=0;ix<2;++ix)
photon[ix] = decay[ix]->id()==ParticleID::gamma;
for(unsigned int ix=0;ix<2;++ix)
VectorWaveFunction::constructSpinInfo(_vectors[ix],decay[ix],
outgoing,true,photon[ix]);
}
double PScalarVectorVectorDecayer::me2(const int,const Particle & part,
const tPDVector & outgoing,
const vector<Lorentz5Momentum> & momenta,
MEOption meopt) const {
if(!ME())
ME(new_ptr(TwoBodyDecayMatrixElement(PDT::Spin0,PDT::Spin1,PDT::Spin1)));
bool photon[2]={false,false};
for(unsigned int ix=0;ix<2;++ix)
photon[ix] = outgoing[ix]->id()==ParticleID::gamma;
if(meopt==Initialize) {
ScalarWaveFunction::
calculateWaveFunctions(_rho,const_ptr_cast<tPPtr>(&part),incoming);
}
for(unsigned int ix=0;ix<2;++ix) {
_vectors[ix].resize(3);
for(unsigned int ihel=0;ihel<3;++ihel) {
if(photon[ix] && ihel==1) continue;
_vectors[ix][ihel] = HelicityFunctions::polarizationVector(-momenta[ix],ihel,Helicity::outgoing);
}
}
// now compute the matrix element
InvEnergy2 fact(_coupling[imode()]/part.mass());
for(unsigned int ix=0;ix<3;++ix) {
if(photon[0] && ix==1) continue;
for(unsigned int iy=0;iy<3;++iy) {
if(photon[1] && iy==1) continue;
- (*ME())(0,ix,iy)=fact*epsilon(_vectors[0][ix],momenta[1],
- _vectors[1][iy])*momenta[0];
+ (*ME())(0,ix,iy)=Complex(fact*epsilon(_vectors[0][ix],momenta[1],
+ _vectors[1][iy])*momenta[0]);
}
}
double output = ME()->contract(_rho).real();
// test of the matrix element
// double test = 2.*sqr(fact*part.mass())*
// sqr(Kinematics::pstarTwoBodyDecay(part.mass(),momenta[0].mass(),momenta[1].mass()));
// cerr << "testing the matrix element for " << part.PDGName() << " -> "
// << outgoing[0]->PDGName() << " " << outgoing[1]->PDGName() << " "
// << output << " " << (output-test)/(output+test) << "\n";
return output;
}
// specify the 1-2 matrix element to be used in the running width calculation
bool PScalarVectorVectorDecayer::twoBodyMEcode(const DecayMode & dm, int & itype,
double & coupling) const {
int imode(-1);
int id(dm.parent()->id());
ParticleMSet::const_iterator pit(dm.products().begin());
int id1((**pit).id());++pit;
int id2((**pit).id());
unsigned int ix(0);
do {
if(_incoming[ix]==id) {
if((id1==_outgoing1[ix]&&id2==_outgoing2[ix])||
(id2==_outgoing1[ix]&&id1==_outgoing2[ix])) imode=ix;
}
++ix;
}
while(imode<0&&ix<_incoming.size());
coupling=_coupling[imode]*dm.parent()->mass();
itype = 3;
return id1==_outgoing1[imode]&&id2==_outgoing2[imode];
}
// output the setup info for the particle database
void PScalarVectorVectorDecayer::dataBaseOutput(ofstream & output,
bool header) const {
if(header) output << "update decayers set parameters=\"";
// parameters for the DecayIntegrator base class
DecayIntegrator::dataBaseOutput(output,false);
for(unsigned int ix=0;ix<_incoming.size();++ix) {
if(ix<_initsize) {
output << "newdef " << name() << ":Incoming " << ix << " "
<< _incoming[ix] << "\n";
output << "newdef " << name() << ":FirstOutgoing " << ix << " "
<< _outgoing1[ix] << "\n";
output << "newdef " << name() << ":SecondOutgoing " << ix << " "
<< _outgoing2[ix] << "\n";
output << "newdef " << name() << ":Coupling " << ix << " "
<< _coupling[ix]*GeV << "\n";
output << "newdef " << name() << ":MaxWeight " << ix << " "
<< _maxweight[ix] << "\n";
}
else {
output << "insert " << name() << ":Incoming " << ix << " "
<< _incoming[ix] << "\n";
output << "insert " << name() << ":FirstOutgoing " << ix << " "
<< _outgoing1[ix] << "\n";
output << "insert " << name() << ":SecondOutgoing " << ix << " "
<< _outgoing2[ix] << "\n";
output << "insert " << name() << ":Coupling " << ix << " "
<< _coupling[ix]*GeV << "\n";
output << "insert " << name() << ":MaxWeight " << ix << " "
<< _maxweight[ix] << "\n";
}
}
if(header) output << "\n\" where BINARY ThePEGName=\""
<< fullName() << "\";" << endl;
}
diff --git a/Decay/ScalarMeson/ScalarMesonTensorScalarDecayer.cc b/Decay/ScalarMeson/ScalarMesonTensorScalarDecayer.cc
--- a/Decay/ScalarMeson/ScalarMesonTensorScalarDecayer.cc
+++ b/Decay/ScalarMeson/ScalarMesonTensorScalarDecayer.cc
@@ -1,281 +1,281 @@
// -*- C++ -*-
//
// ScalarMesonTensorScalarDecayer.cc is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2019 The Herwig Collaboration
//
// Herwig is licenced under version 3 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 ScalarMesonTensorScalarDecayer class.
//
#include "ScalarMesonTensorScalarDecayer.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/ParVector.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/DecayMode.h"
#include "ThePEG/Helicity/WaveFunction/TensorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h"
#include "Herwig/Decay/TwoBodyDecayMatrixElement.h"
using namespace Herwig;
using namespace ThePEG::Helicity;
void ScalarMesonTensorScalarDecayer::doinitrun() {
DecayIntegrator::doinitrun();
if(initialize()) {
for(unsigned int ix=0;ix<_incoming.size();++ix)
if(mode(ix)) _maxweight[ix] = mode(ix)->maxWeight();
}
}
ScalarMesonTensorScalarDecayer::ScalarMesonTensorScalarDecayer()
: _incoming(3), _outgoingT(3), _outgoingS(3), _coupling(3), _maxweight(3) {
// D+ -> f_2 pi
_incoming[0] = 411; _outgoingT[0] = 225; _outgoingS[0] = 211;
_coupling[0] = 8.23E-7/GeV; _maxweight[0] = 5;
// chi_c0 -> K*_0 K*_2
_incoming[1] = 10441; _outgoingT[1] = 325; _outgoingS[1] = -10321;
_coupling[1] = 0.0217/GeV; _maxweight[1] = 5;
_incoming[2] = 10441; _outgoingT[2] = 315; _outgoingS[2] = -10311;
_coupling[2] = 0.0217/GeV; _maxweight[2] = 5;
// initial size of the arrays
_initsize=_incoming.size();
// intermediates
generateIntermediates(false);
}
void ScalarMesonTensorScalarDecayer::doinit() {
DecayIntegrator::doinit();
// check the parameters arew consistent
unsigned int isize=_coupling.size();
if(isize!=_incoming.size() || isize!=_outgoingT.size()||
isize!=_outgoingS.size() || isize!=_maxweight.size())
throw InitException() << "Inconsistent parameters in "
<< "ScalarMesonTensorScalarDecayer"
<< Exception::abortnow;
// set up the integration channels
for(unsigned int ix=0;ix<_incoming.size();++ix) {
tPDPtr in = getParticleData(_incoming[ix]);
tPDVector out = {getParticleData(_outgoingT[ix]),
getParticleData(_outgoingS[ix])};
PhaseSpaceModePtr mode;
if(in&&out[0]&&out[1])
mode = new_ptr(PhaseSpaceMode(in,out,_maxweight[ix]));
else
mode=PhaseSpaceModePtr();
addMode(mode);
}
}
int ScalarMesonTensorScalarDecayer::modeNumber(bool & cc,tcPDPtr parent,
const tPDVector & children) const {
if(children.size()!=2) return -1;
int id0(parent->id());
int id0bar = parent->CC() ? parent->CC()->id() : id0;
int id1(children[0]->id());
int id1bar = children[0]->CC() ? children[0]->CC()->id() : id1;
int id2(children[1]->id());
int id2bar = children[1]->CC() ? children[1]->CC()->id() : id2;
unsigned int ix(0);
int imode(-1);
do {
if(id0 ==_incoming[ix]) {
if((id1 ==_outgoingT[ix]&&id2 ==_outgoingS[ix])||
(id2 ==_outgoingT[ix]&&id1 ==_outgoingS[ix])) {
imode=ix;
cc=false;
}
}
if(id0bar==_incoming[ix]&&imode<0) {
if((id1bar==_outgoingT[ix]&&id2bar==_outgoingS[ix])||
(id2bar==_outgoingT[ix]&&id1bar==_outgoingS[ix])) {
imode=ix;
cc=true;
}
}
++ix;
}
while(ix<_incoming.size()&&imode<0);
return imode;
}
void ScalarMesonTensorScalarDecayer::persistentOutput(PersistentOStream & os) const {
os << ounit(_coupling,1/GeV) << _incoming << _outgoingT << _outgoingS << _maxweight;
}
void ScalarMesonTensorScalarDecayer::persistentInput(PersistentIStream & is, int) {
is >> iunit(_coupling,1/GeV) >> _incoming >> _outgoingT >> _outgoingS >> _maxweight;
}
// The following static variable is needed for the type
// description system in ThePEG.
DescribeClass<ScalarMesonTensorScalarDecayer,DecayIntegrator>
describeHerwigScalarMesonTensorScalarDecayer("Herwig::ScalarMesonTensorScalarDecayer", "HwSMDecay.so");
void ScalarMesonTensorScalarDecayer::Init() {
static ClassDocumentation<ScalarMesonTensorScalarDecayer> documentation
("The ScalarMesonTensorScalarDecayer class is designed for"
" the decay of a pseduoscalar meson to two spin-1 particles.");
static ParVector<ScalarMesonTensorScalarDecayer,int> interfaceIncoming
("Incoming",
"The PDG code for the incoming particle",
&ScalarMesonTensorScalarDecayer::_incoming,
0, 0, 0, -10000000, 10000000, false, false, true);
static ParVector<ScalarMesonTensorScalarDecayer,int> interfaceOutcomingT
("OutgoingTensor",
"The PDG code for the outgoing tensor",
&ScalarMesonTensorScalarDecayer::_outgoingT,
0, 0, 0, -10000000, 10000000, false, false, true);
static ParVector<ScalarMesonTensorScalarDecayer,int> interfaceOutcomingS
("OutgoingScalar",
"The PDG code for the outgoing scalar",
&ScalarMesonTensorScalarDecayer::_outgoingS,
0, 0, 0, -10000000, 10000000, false, false, true);
static ParVector<ScalarMesonTensorScalarDecayer,InvEnergy> interfaceCoupling
("Coupling",
"The coupling for the decay mode",
&ScalarMesonTensorScalarDecayer::_coupling,
1/GeV, 0, ZERO, ZERO, 100./GeV, false, false, true);
static ParVector<ScalarMesonTensorScalarDecayer,double> interfaceMaxWeight
("MaxWeight",
"The maximum weight for the decay mode",
&ScalarMesonTensorScalarDecayer::_maxweight,
0, 0, 0, 0., 100., false, false, true);
}
void ScalarMesonTensorScalarDecayer::
constructSpinInfo(const Particle & part, ParticleVector decay) const {
// set up the spin information for the decay products
ScalarWaveFunction::constructSpinInfo(const_ptr_cast<tPPtr>(&part),
incoming,true);
TensorWaveFunction::constructSpinInfo(_tensors,decay[0],
outgoing,true,false);
ScalarWaveFunction::constructSpinInfo(decay[1],outgoing,true);
}
double ScalarMesonTensorScalarDecayer::me2(const int,const Particle & part,
const tPDVector & outgoing,
const vector<Lorentz5Momentum> & momenta,
MEOption meopt) const {
if(!ME())
ME(new_ptr(TwoBodyDecayMatrixElement(PDT::Spin0,PDT::Spin2,PDT::Spin0)));
if(meopt==Initialize) {
ScalarWaveFunction::
calculateWaveFunctions(_rho,const_ptr_cast<tPPtr>(&part),incoming);
}
TensorWaveFunction twave(momenta[0],outgoing[0],Helicity::outgoing);
_tensors.resize(5);
for(unsigned int ihel=0;ihel<5;++ihel) {
twave.reset(ihel);
_tensors[ihel] = twave.wave();
}
// calculate the matrix element
InvEnergy2 fact(_coupling[imode()]/part.mass());
LorentzPolarizationVectorE vtemp;
for(unsigned int ix=0;ix<5;++ix) {
vtemp = _tensors[ix]*part.momentum();
- (*ME())(0,ix,0) = fact * momenta[1].dot(vtemp);
+ (*ME())(0,ix,0) = Complex(fact * momenta[1].dot(vtemp));
}
double me = ME()->contract(_rho).real();
// // test of the matrix element
// Energy pcm = Kinematics::pstarTwoBodyDecay(part.mass(),momenta[0].mass(),
// momenta[1].mass());
// double test = 2.*pow<4,1>(pcm)*sqr(_coupling[imode()]*part.mass())/
// 3./pow<4,1>(momenta[0].mass());
// cerr << "testing matrix element for " << part.PDGName() << " -> "
// << outgoing[0]->PDGName() << " " << outgoing[1]->PDGName() << " "
// << me << " " << (me-test)/(me+test) << "\n";
// output the answer
return me;
}
// specify the 1-2 matrix element to be used in the running width calculation
bool ScalarMesonTensorScalarDecayer::twoBodyMEcode(const DecayMode & dm, int & itype,
double & coupling) const {
int id(dm.parent()->id());
int idbar = dm.parent()->CC() ? dm.parent()->CC()->id() : id;
ParticleMSet::const_iterator pit(dm.products().begin());
int id1((**pit).id());
int id1bar = (**pit).CC() ? (**pit).CC()->id() : id1;
++pit;
int id2((**pit).id());
int id2bar = (**pit).CC() ? (**pit).CC()->id() : id2;
unsigned int ix(0);
bool order(false);
int imode(-1);
do {
if(id ==_incoming[ix]) {
if(id1==_outgoingT[ix]&&id2==_outgoingS[ix]) {
imode=ix;
order=true;
}
if(id2==_outgoingT[ix]&&id1==_outgoingS[ix]) {
imode=ix;
order=false;
}
}
if(idbar==_incoming[ix]&&imode<0) {
if(id1bar==_outgoingT[ix]&&id2bar==_outgoingS[ix]) {
imode=ix;
order=true;
}
if(id2bar==_outgoingT[ix]&&id1bar==_outgoingS[ix]) {
imode=ix;
order=false;
}
}
++ix;
}
while(ix<_incoming.size()&&imode<0);
coupling=_coupling[imode]*dm.parent()->mass();
itype = 11;
return order;
}
// output the setup information for the particle database
void ScalarMesonTensorScalarDecayer::dataBaseOutput(ofstream & output,
bool header) const {
if(header) output << "update decayers set parameters=\"";
// parameters for the DecayIntegrator base class
DecayIntegrator::dataBaseOutput(output,false);
// the rest of the parameters
for(unsigned int ix=0;ix<_incoming.size();++ix) {
if(ix<_initsize) {
output << "newdef " << name() << ":Incoming " << ix << " "
<< _incoming[ix] << "\n";
output << "newdef " << name() << ":OutgoingTensor " << ix << " "
<< _outgoingT[ix] << "\n";
output << "newdef " << name() << ":OutgoingScalar " << ix << " "
<< _outgoingS[ix] << "\n";
output << "newdef " << name() << ":Coupling " << ix << " "
<< _coupling[ix]*GeV << "\n";
output << "newdef " << name() << ":MaxWeight " << ix << " "
<< _maxweight[ix] << "\n";
}
else {
output << "insert " << name() << ":Incoming " << ix << " "
<< _incoming[ix] << "\n";
output << "insert " << name() << ":OutgoingTensor " << ix << " "
<< _outgoingT[ix] << "\n";
output << "insert " << name() << ":OutgoingScalar " << ix << " "
<< _outgoingS[ix] << "\n";
output << "insert " << name() << ":Coupling " << ix << " "
<< _coupling[ix]*GeV << "\n";
output << "insert " << name() << ":MaxWeight " << ix << " "
<< _maxweight[ix] << "\n";
}
}
if(header) output << "\n\" where BINARY ThePEGName=\""
<< fullName() << "\";" << endl;
}
diff --git a/Decay/Tau/TauDecayer.cc b/Decay/Tau/TauDecayer.cc
--- a/Decay/Tau/TauDecayer.cc
+++ b/Decay/Tau/TauDecayer.cc
@@ -1,360 +1,360 @@
// -*- C++ -*-
//
// TauDecayer.cc is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2019 The Herwig Collaboration
//
// Herwig is licenced under version 3 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 TauDecayer class.
//
// Author: Peter Richardson
//
#include "TauDecayer.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/PDT/DecayMode.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/ParVector.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Helicity/VectorSpinInfo.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h"
#include "Herwig/Decay/DecayVertex.h"
#include "Herwig/Decay/GeneralDecayMatrixElement.h"
#include "ThePEG/Helicity/FermionSpinInfo.h"
#include "ThePEG/StandardModel/StandardModelBase.h"
#include "ThePEG/Helicity/HelicityFunctions.h"
using namespace Herwig;
using namespace ThePEG::Helicity;
void TauDecayer::doinit() {
DecayIntegrator::doinit();
// make sure the current got initialised
current_->init();
// set up the phase-space channels
tPDPtr tau = getParticleData(ParticleID::tauminus);
tPDPtr nu = getParticleData(ParticleID::nu_tau);
Energy mtau(tau->mass());
vector<double> channelwgts;
modeMap_.clear();
for(unsigned int ix=0;ix<current_->numberOfModes();++ix) {
// get the external particles for this mode
tPDVector out = {nu};
int iq(0),ia(0);
tPDVector ptemp = current_->particles(-3,ix,iq,ia);
out.insert(std::end(out), std::begin(ptemp), std::end(ptemp));
// the maximum weight
double maxweight = wgtMax_.size()>numberModes() ? wgtMax_[numberModes()] : 1.;
// create the mode
PhaseSpaceModePtr mode = new_ptr(PhaseSpaceMode(tau,out,maxweight));
// create the first piece of the channel
PhaseSpaceChannel channel((PhaseSpaceChannel(mode),0,1));
if(!current_->createMode(-3,tcPDPtr(),FlavourInfo(),ix,mode,1,0,channel,mtau)) continue;
// the channel weights
// the weights for the channel
if(wgtLoc_.size()>numberModes()&&
wgtLoc_[numberModes()]+mode->channels().size()<=weights_.size()) {
channelwgts=vector<double>(weights_.begin()+wgtLoc_[numberModes()],
weights_.begin()+wgtLoc_[numberModes()]+mode->channels().size());
}
else {
channelwgts.resize(mode->channels().size(),1./(mode->channels().size()));
}
modeMap_.push_back(ix);
// special for the two body modes
if(out.size()==2) {
channelwgts.clear();
mode=new_ptr(PhaseSpaceMode(tau,out,maxweight));
}
mode->setWeights(channelwgts);
// need to do the weights
addMode(mode);
}
current_->reset();
current_->touch();
current_->update();
}
void TauDecayer::doinitrun() {
current_->initrun();
DecayIntegrator::doinitrun();
if(initialize()) {
weights_.clear();
wgtLoc_.clear();
wgtMax_.clear();
for(unsigned int ix=0;ix<numberModes();++ix) {
wgtMax_.push_back(mode(ix)->maxWeight());
wgtLoc_.push_back(weights_.size());
for(unsigned int iy=0;iy<mode(ix)->channels().size();++iy) {
weights_.push_back(mode(ix)->channels()[iy].weight());
}
}
}
}
bool TauDecayer::accept(tcPDPtr parent, const tPDVector & children) const {
bool allowed(false);
// find the neutrino
int idnu(0),idtemp,idin(parent->id());
vector<int> idother;
tPDVector::const_iterator pit = children.begin();
tPDVector::const_iterator pend = children.end();
for( ; pit!=pend;++pit) {
idtemp=(**pit).id();
if(abs(idtemp)==16) idnu=idtemp;
else idother.push_back(idtemp);
}
if((idnu==ParticleID::nu_tau && idin==ParticleID::tauminus)||
(idnu==ParticleID::nu_taubar && idin==ParticleID::tauplus )) {
allowed=current_->accept(idother);
}
return allowed;
}
int TauDecayer::modeNumber(bool & cc,tcPDPtr parent, const tPDVector & children) const {
int imode(-1);
tPDVector::const_iterator pit = children.begin();
tPDVector::const_iterator pend = children.end();
int idtemp;vector<int> idother;
for( ; pit!=pend;++pit) {
idtemp=(**pit).id();
if(abs(idtemp)!=16) idother.push_back(idtemp);
}
unsigned int itemp=current_->decayMode(idother);
for(unsigned int ix=0;ix<modeMap_.size();++ix) {
if(modeMap_[ix]==itemp) imode=ix;
}
// perform the decay
cc=parent->id()==ParticleID::tauplus;
return imode;
}
void TauDecayer::persistentOutput(PersistentOStream & os) const {
os << modeMap_ << current_ << wgtLoc_
<< wgtMax_ << weights_ << polOpt_ << tauMpol_ << tauPpol_;
}
void TauDecayer::persistentInput(PersistentIStream & is, int) {
is >> modeMap_ >> current_ >> wgtLoc_
>> wgtMax_ >> weights_ >> polOpt_ >> tauMpol_ >> tauPpol_;
}
// The following static variable is needed for the type
// description system in ThePEG.
DescribeClass<TauDecayer,DecayIntegrator>
describeHerwigTauDecayer("Herwig::TauDecayer", "HwTauDecay.so");
void TauDecayer::Init() {
static ClassDocumentation<TauDecayer> documentation
("The TauDecayer class is designed to use a weak current"
" to perform the decay of the tau.");
static Reference<TauDecayer,WeakCurrent> interfaceWeakCurrent
("WeakCurrent",
"The reference for the decay current to be used.",
&TauDecayer::current_, false, false, true, false, false);
static ParVector<TauDecayer,int> interfaceWeightLocation
("WeightLocation",
"The locations of the weights for a given channel in the vector",
&TauDecayer::wgtLoc_,
0, 0, 0, 0, 10000, false, false, true);
static ParVector<TauDecayer,double> interfaceWeightMax
("MaximumWeight",
"The maximum weight for a given channel.",
&TauDecayer::wgtMax_,
0, 0, 0, 0., 100., false, false, true);
static ParVector<TauDecayer,double> interfaceWeights
("Weights",
"The weights for the integration.",
&TauDecayer::weights_,
0, 0, 0, 0., 1., false, false, true);
static Switch<TauDecayer,bool> interfacePolarizationOption
("PolarizationOption",
"Option of forcing the polarization of the tau leptons, N.B. you"
" should only use this option for making distributions for"
" comparision if you really know what you are doing.",
&TauDecayer::polOpt_, false, false, false);
static SwitchOption interfacePolarizationOptionDefault
(interfacePolarizationOption,
"Default",
"Don't force the polarization use the full spin density matrices"
" to get the right answer",
false);
static SwitchOption interfacePolarizationOptionForce
(interfacePolarizationOption,
"Force",
"Force the polarizations",
true);
static Parameter<TauDecayer,double> interfaceTauMinusPolarization
("TauMinusPolarization",
"The polarization of the tau-, left=-1, right=+1 if this is forced.",
&TauDecayer::tauMpol_, 0.0, -1.0, 1.0,
false, false, Interface::limited);
static Parameter<TauDecayer,double> interfaceTauPlusPolarization
("TauPlusPolarization",
"The polarization of the tau+, left=-1, right=+1 if this is forced.",
&TauDecayer::tauPpol_, 0.0, -1.0, 1.0,
false, false, Interface::limited);
}
void TauDecayer::
constructSpinInfo(const Particle & part, ParticleVector decay) const {
if(part.id()==ParticleID::tauminus) {
SpinorWaveFunction ::
constructSpinInfo(inSpin_,const_ptr_cast<tPPtr>(&part),incoming,true);
SpinorBarWaveFunction::
constructSpinInfo(inBar_,decay[0],outgoing,true);
}
else {
SpinorBarWaveFunction::
constructSpinInfo(inBar_ ,const_ptr_cast<tPPtr>(&part),incoming,true);
SpinorWaveFunction::
constructSpinInfo(inSpin_,decay[0],outgoing,true);
}
current_->constructSpinInfo(ParticleVector(decay.begin()+1,decay.end()));
}
// combine the currents to give the matrix element
double TauDecayer::me2(const int ichan, const Particle & part,
const tPDVector & outgoing,
const vector<Lorentz5Momentum> & momenta,
MEOption meopt) const {
// map the mode to those in the current
int mode(modeMap_[imode()]);
// extract info on the decaying particle
if(meopt==Initialize) {
// spin density matrix for the decaying particle
rho_ = RhoDMatrix(PDT::Spin1Half);
if(part.id()==ParticleID::tauminus)
SpinorWaveFunction ::calculateWaveFunctions(inSpin_,rho_,
const_ptr_cast<tPPtr>(&part),
incoming);
else
SpinorBarWaveFunction::calculateWaveFunctions(inBar_ ,rho_,
const_ptr_cast<tPPtr>(&part),
incoming);
// fix rho if no correlations
fixRho(rho_);
if(polOpt_) {
rho_(0,1) = rho_(1,0) = 0.;
if(part.id()==ParticleID::tauminus) {
rho_(0,0) = 0.5*(1.-tauMpol_);
rho_(1,1) = 0.5*(1.+tauMpol_);
}
else {
rho_(0,0) = 0.5*(1.+tauPpol_);
rho_(1,1) = 0.5*(1.-tauPpol_);
}
}
// work out the mapping for the hadron vector
constants_ = vector<unsigned int>(outgoing.size()+1);
iSpin_ = vector<PDT::Spin >(outgoing.size());
int itemp(1);
unsigned int ix(outgoing.size());
do {
--ix;
iSpin_[ix] = outgoing[ix]->iSpin();
itemp *= iSpin_[ix];
constants_[ix] = itemp;
}
while(ix>0);
constants_[outgoing.size()] = 1;
constants_[0 ] = constants_[1];
}
if(!ME())
ME(new_ptr(GeneralDecayMatrixElement(PDT::Spin1Half,iSpin_)));
// calculate the spinors for the decay products
if(part.id()==ParticleID::tauminus) {
inBar_.resize(2);
for(unsigned int ihel=0;ihel<2;++ihel)
inBar_[ihel] = HelicityFunctions::dimensionedSpinorBar(-momenta[0],ihel,Helicity::outgoing);
}
else {
inSpin_.resize(2);
for(unsigned int ihel=0;ihel<2;++ihel)
inSpin_[ihel] = HelicityFunctions::dimensionedSpinor (-momenta[0],ihel,Helicity::outgoing);
}
// calculate the hadron current
Energy q;
vector<LorentzPolarizationVectorE>
hadron(current_->current(tcPDPtr(),FlavourInfo(),mode,ichan,q,tPDVector(outgoing.begin()+1,outgoing.end()),
vector<Lorentz5Momentum>(momenta.begin()+1,momenta.end()),meopt));
// prefactor
double pre = sqr(pow(part.mass()/q,int(outgoing.size()-3)));
// calculate the lepton current
LorentzPolarizationVectorE lepton[2][2];
for(unsigned ix=0;ix<2;++ix) {
for(unsigned iy=0;iy<2;++iy) {
if(part.id()==15)
lepton[ix][iy]=2.*inSpin_[ix].leftCurrent(inBar_[iy]);
else
lepton[iy][ix]=2.*inSpin_[ix].leftCurrent(inBar_[iy]);
}
}
// compute the matrix element
vector<unsigned int> ihel(outgoing.size()+1);
for(unsigned int hhel=0;hhel<hadron.size();++hhel) {
// map the index for the hadrons to a helicity state
for(unsigned int ix=outgoing.size();ix>1;--ix) {
ihel[ix]=(hhel%constants_[ix-1])/constants_[ix];
}
// loop over the helicities of the tau and neutrino and set up the matrix
// element
for(ihel[1]=0;ihel[1]<2;++ihel[1]){
for(ihel[0]=0;ihel[0]<2;++ihel[0]) {
- (*ME())(ihel)= lepton[ihel[0]][ihel[1]].dot(hadron[hhel])*
- SM().fermiConstant();
+ (*ME())(ihel)= Complex(lepton[ihel[0]][ihel[1]].dot(hadron[hhel])*
+ SM().fermiConstant());
}
}
}
// multiply by the CKM element
int iq,ia;
current_->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);
}
return 0.5*pre*ckm*(ME()->contract(rho_)).real();
}
// output the setup information for the particle database
void TauDecayer::dataBaseOutput(ofstream & output,bool header) const {
unsigned int ix;
if(header) output << "update decayers set parameters=\"";
DecayIntegrator::dataBaseOutput(output,false);
for(ix=0;ix<wgtLoc_.size();++ix) {
output << "insert " << name() << ":WeightLocation " << ix << " "
<< wgtLoc_[ix] << "\n";
}
for(ix=0;ix<wgtMax_.size();++ix) {
output << "insert " << name() << ":MaximumWeight " << ix << " "
<< wgtMax_[ix] << "\n";
}
for(ix=0;ix<weights_.size();++ix) {
output << "insert " << name() << ":Weights " << ix << " "
<< weights_[ix] << "\n";
}
current_->dataBaseOutput(output,false,true);
output << "newdef " << name() << ":WeakCurrent " << current_->name() << " \n";
output << "\n\" where BINARY ThePEGName=\"" << fullName() << "\";\n";
}
diff --git a/Decay/TensorMeson/TensorMesonVectorPScalarDecayer.cc b/Decay/TensorMeson/TensorMesonVectorPScalarDecayer.cc
--- a/Decay/TensorMeson/TensorMesonVectorPScalarDecayer.cc
+++ b/Decay/TensorMeson/TensorMesonVectorPScalarDecayer.cc
@@ -1,356 +1,356 @@
// -*- C++ -*-
//
// TensorMesonVectorPScalarDecayer.cc is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2019 The Herwig Collaboration
//
// Herwig is licenced under version 3 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 TensorMesonVectorPScalarDecayer class.
//
#include "TensorMesonVectorPScalarDecayer.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/ParVector.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/DecayMode.h"
#include "ThePEG/Helicity/WaveFunction/TensorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h"
#include "ThePEG/Helicity/epsilon.h"
#include "Herwig/Decay/TwoBodyDecayMatrixElement.h"
#include "ThePEG/Helicity/HelicityFunctions.h"
using namespace Herwig;
using namespace ThePEG::Helicity;
void TensorMesonVectorPScalarDecayer::doinitrun() {
DecayIntegrator::doinitrun();
if(initialize()){
for(unsigned int ix=0;ix<_incoming.size();++ix)
if(mode(ix)) _maxweight[ix] = mode(ix)->maxWeight();
}
}
TensorMesonVectorPScalarDecayer::TensorMesonVectorPScalarDecayer()
: _incoming(31), _outgoingV(31), _outgoingP(31),
_coupling(31), _maxweight(31) {
// a_2 -> rho pi
_incoming[0] = 115; _outgoingV[0] = 213; _outgoingP[0] = -211;
_coupling[0] = 21.1/GeV2; _maxweight[0] = 10.;
_incoming[1] = 215; _outgoingV[1] = 113; _outgoingP[1] = 211;
_coupling[1] = 21.1/GeV2; _maxweight[1] = 9.;
_incoming[2] = 215; _outgoingV[2] = 213; _outgoingP[2] = 111;
_coupling[2] = 21.1/GeV2; _maxweight[2] = 9.;
// a_2+/- -> gamma pi+/-
_incoming[3] = 215; _outgoingV[3] = 22; _outgoingP[3] = 211;
_coupling[3] = 0.551/GeV2; _maxweight[3] = 2.;
// k_2 -> K_2 omega
_incoming[4] = 315; _outgoingV[4] = 223; _outgoingP[4] = 311;
_coupling[4] = 11.66/GeV2; _maxweight[4] = 17.;
_incoming[5] = 325; _outgoingV[5] = 223; _outgoingP[5] = 321;
_coupling[5] = 11.66/GeV2; _maxweight[5] = 20.5;
// k_2+/- -> K+/- gamma
_incoming[6] = 325; _outgoingV[6] = 22; _outgoingP[6] = 321;
_coupling[6] = 0.553/GeV2; _maxweight[6] = 2.2;
// B_c2 -> B_c gamma
_incoming[7] = 545; _outgoingV[7] = 22; _outgoingP[7] = 541;
_coupling[7] = 0.651/GeV2; _maxweight[7] = 2.;
// K_2 -> K rho
_incoming[8] = 325; _outgoingV[8] = 113; _outgoingP[8] = 321;
_coupling[8] = 10.14/GeV2; _maxweight[8] = 9.;
_incoming[9] = 325; _outgoingV[9] = 213; _outgoingP[9] = 311;
_coupling[9] = 14.33/GeV2; _maxweight[9] = 9.;
_incoming[10] = 315; _outgoingV[10] = 113; _outgoingP[10] = 311;
_coupling[10] = 10.14/GeV2; _maxweight[10] = 9.;
_incoming[11] = 315; _outgoingV[11] = -213; _outgoingP[11] = 321;
_coupling[11] = 14.33/GeV2; _maxweight[11] = 9.;
// K_2 -> K* pi
_incoming[12] = 325; _outgoingV[12] = 323; _outgoingP[12] = 111;
_coupling[12] = 9.733/GeV2; _maxweight[12] = 13;
_incoming[13] = 325; _outgoingV[13] = 313; _outgoingP[13] = 211;
_coupling[13] = 13.77/GeV2; _maxweight[13] = 11;
_incoming[14] = 315; _outgoingV[14] = 313; _outgoingP[14] = 111;
_coupling[14] = 9.733/GeV2; _maxweight[14] = 8.;
_incoming[15] = 315; _outgoingV[15] = 323; _outgoingP[15] = -211;
_coupling[15] = 13.77/GeV2; _maxweight[15] = 8.;
// D_2 -> D* pi
_incoming[16] = 425; _outgoingV[16] = 423; _outgoingP[16] = 111;
_coupling[16] = 8.035/GeV2; _maxweight[16] = 2.2;
_incoming[17] = 425; _outgoingV[17] = 413; _outgoingP[17] = -211;
_coupling[17] = 11.670/GeV2; _maxweight[17] = 2.4;
_incoming[18] = 415; _outgoingV[18] = 413; _outgoingP[18] = 111;
_coupling[18] = 6.801/GeV2; _maxweight[18] = 2.4;
_incoming[19] = 415; _outgoingV[19] = 423; _outgoingP[19] = 211;
_coupling[19] = 9.527/GeV2; _maxweight[19] = 2.;
// D_s2 -> D* K
_incoming[20] = 435; _outgoingV[20] = 423; _outgoingP[20] = 321;
_coupling[20] = 13.10/GeV2; _maxweight[20] = 2.2;
_incoming[21] = 435; _outgoingV[21] = 413; _outgoingP[21] = 311;
_coupling[21] = 13.10/GeV2; _maxweight[21] = 2.5;
// B_2 -> B* pi
_incoming[22] = 525; _outgoingV[22] = 523; _outgoingP[22] = 111;
_coupling[22] = 4.99/GeV2; _maxweight[22] = 2.1;
_incoming[23] = 525; _outgoingV[23] = 513; _outgoingP[23] = 211;
_coupling[23] = 7.059/GeV2; _maxweight[23] = 2.1;
_incoming[24] = 515; _outgoingV[24] = 513; _outgoingP[24] = 111;
_coupling[24] = 4.99/GeV2; _maxweight[24] = 2.1;
_incoming[25] = 515; _outgoingV[25] = 523; _outgoingP[25] = -211;
_coupling[25] = 7.059/GeV2; _maxweight[25] = 2.1;
// D_s2
_incoming[26] = 435; _outgoingV[26] = 423; _outgoingP[26] = 321;
_coupling[26] = 13.09/GeV2; _maxweight[26] = 2.2;
_incoming[27] = 435; _outgoingV[27] = 413; _outgoingP[27] = 311;
_coupling[27] = 13.09/GeV2; _maxweight[27] = 2.5;
// B_s2
_incoming[28] = 535; _outgoingV[28] = 523; _outgoingP[28] = -321;
_coupling[28] = 7.29/GeV2; _maxweight[28] = 2.4;
_incoming[29] = 535; _outgoingV[29] = 513; _outgoingP[29] = -311;
_coupling[29] = 9.43/GeV2; _maxweight[29] = 2.1;
// upsilon_2(1d) to chi_b gamma
_incoming[30] = 20555; _outgoingV[30] = 22; _outgoingP[30] = 10551;
_coupling[30] = 1.11/GeV2; _maxweight[30] = 2.4;
// initial size of the arrays
_initsize=_incoming.size();
// intermediates
generateIntermediates(false);
}
void TensorMesonVectorPScalarDecayer::doinit() {
DecayIntegrator::doinit();
// check consistence of the parameters
unsigned int isize=_incoming.size();
if(isize!=_outgoingV.size()||isize!=_outgoingP.size()||
isize!=_maxweight.size()||isize!=_coupling.size())
throw InitException() << "Inconsistent parameters TensorMesonVectorPScalarDecayer"
<< Exception::abortnow;
// set up the integration channels
PhaseSpaceModePtr mode;
for(unsigned int ix=0;ix<_incoming.size();++ix) {
tPDPtr in = getParticleData(_incoming[ix]);
tPDVector out = {getParticleData(_outgoingV[ix]),
getParticleData(_outgoingP[ix])};
if(in&&out[0]&&out[1])
mode=new_ptr(PhaseSpaceMode(in,out,_maxweight[ix]));
else
mode=PhaseSpaceModePtr();
addMode(mode);
}
}
int TensorMesonVectorPScalarDecayer::modeNumber(bool & cc, tcPDPtr parent,
const tPDVector & children) const {
if(children.size()!=2) return -1;
int id(parent->id());
int idbar = parent->CC() ? parent->CC()->id() : id;
int id1(children[0]->id());
int id1bar = children[0]->CC() ? children[0]->CC()->id() : id1;
int id2(children[1]->id());
int id2bar = children[1]->CC() ? children[1]->CC()->id() : id2;
int imode(-1);
unsigned int ix(0);
cc=false;
do {
if(id ==_incoming[ix]) {
if((id1 ==_outgoingP[ix]&&id2 ==_outgoingV[ix])||
(id2 ==_outgoingP[ix]&&id1 ==_outgoingV[ix])) imode=ix;
}
if(idbar==_incoming[ix]) {
if((id1bar==_outgoingP[ix]&&id2bar==_outgoingV[ix])||
(id2bar==_outgoingP[ix]&&id1bar==_outgoingV[ix])) {
imode=ix;
cc=true;
}
}
++ix;
}
while(ix<_incoming.size()&&imode<0);
return imode;
}
void TensorMesonVectorPScalarDecayer::persistentOutput(PersistentOStream & os) const {
os << _incoming << _outgoingV << _outgoingP << _maxweight << ounit(_coupling,1/GeV2);
}
void TensorMesonVectorPScalarDecayer::persistentInput(PersistentIStream & is, int) {
is >> _incoming >> _outgoingV >> _outgoingP >> _maxweight >> iunit(_coupling,1/GeV2);
}
// The following static variable is needed for the type
// description system in ThePEG.
DescribeClass<TensorMesonVectorPScalarDecayer,DecayIntegrator>
describeHerwigTensorMesonVectorPScalarDecayer("Herwig::TensorMesonVectorPScalarDecayer", "HwTMDecay.so");
void TensorMesonVectorPScalarDecayer::Init() {
static ClassDocumentation<TensorMesonVectorPScalarDecayer> documentation
("The TensorMesonVectorPScalarDecayer class implements the"
" decay of a tensor meson to a spin-1 particle and a pseduoscalar meson");
static ParVector<TensorMesonVectorPScalarDecayer,int> interfaceIncoming
("Incoming",
"The PDG code for the incoming particle",
&TensorMesonVectorPScalarDecayer::_incoming,
0, 0, 0, -10000000, 10000000, false, false, true);
static ParVector<TensorMesonVectorPScalarDecayer,int> interfaceOutcomingV
("OutgoingVector",
"The PDG code for the outgoing spin-1particle",
&TensorMesonVectorPScalarDecayer::_outgoingV,
0, 0, 0, -10000000, 10000000, false, false, true);
static ParVector<TensorMesonVectorPScalarDecayer,int> interfaceOutcomingP
("OutgoingScalar",
"The PDG code for the outgoing pseudoscalar meson",
&TensorMesonVectorPScalarDecayer::_outgoingP,
0, 0, 0, -10000000, 10000000, false, false, true);
static ParVector<TensorMesonVectorPScalarDecayer,InvEnergy2> interfaceCoupling
("Coupling",
"The coupling for the decay mode",
&TensorMesonVectorPScalarDecayer::_coupling,
1/GeV2, 0, ZERO, ZERO, 100./GeV2, false, false, true);
static ParVector<TensorMesonVectorPScalarDecayer,double> interfaceMaxWeight
("MaxWeight",
"The maximum weight for the decay mode",
&TensorMesonVectorPScalarDecayer::_maxweight,
0, 0, 0, 0., 1000., false, false, true);
}
void TensorMesonVectorPScalarDecayer::
constructSpinInfo(const Particle & part, ParticleVector decay) const {
TensorWaveFunction::constructSpinInfo(_tensors,const_ptr_cast<tPPtr>(&part),
incoming,true,false);
// set up the spin information for the decay products
VectorWaveFunction::constructSpinInfo(_vectors,decay[0],outgoing,true,
decay[0]->id()==ParticleID::gamma);
ScalarWaveFunction::constructSpinInfo(decay[1],outgoing,true);
}
// matrix elememt for the process
double TensorMesonVectorPScalarDecayer::me2(const int,const Particle & part,
const tPDVector &,
const vector<Lorentz5Momentum> & momenta,
MEOption meopt) const {
if(!ME())
ME(new_ptr(TwoBodyDecayMatrixElement(PDT::Spin2,PDT::Spin1,PDT::Spin0)));
// check for photons
bool photon(_outgoingV[imode()]==ParticleID::gamma);
// stuff for incoming particle
if(meopt==Initialize) {
_rho = RhoDMatrix(PDT::Spin2);
TensorWaveFunction::
calculateWaveFunctions(_tensors,_rho,const_ptr_cast<tPPtr>(&part),
incoming,false);
}
_vectors.resize(3);
for(unsigned int ix=0;ix<3;++ix) {
if(photon && ix==1) continue;
_vectors[ix] = HelicityFunctions::polarizationVector(-momenta[0],ix,Helicity::outgoing);
}
InvEnergy3 fact(_coupling[imode()]/part.mass());
// calculate the matrix element
for(unsigned int inhel=0;inhel<5;++inhel) {
for(unsigned int vhel=0;vhel<3;++vhel){
if(vhel==1&&photon) (*ME())(inhel,vhel,0)=0.;
else {
LorentzVector<complex<InvEnergy> > vtemp=
fact*epsilon(momenta[0],_vectors[vhel],momenta[1]);
- (*ME())(inhel,vhel,0)= (momenta[1]*_tensors[inhel]).dot(vtemp);
+ (*ME())(inhel,vhel,0) = Complex((momenta[1]*_tensors[inhel]).dot(vtemp));
}
}
}
double me = ME()->contract(_rho).real();
// test of the answer
// Energy pcm = Kinematics::pstarTwoBodyDecay(part.mass(),momenta[0].mass(),
// momenta[1].mass());
// double test = Energy4(pow<4,1>(2*pcm))*sqr( _coupling[imode()])/80.;
// cout << "testing matrix element for " << part.PDGName() << " -> "
// << outgoing[0]->PDGName() << " " << outgoing[1]->PDGName() << " "
// << me << " " << test << " " << (me-test)/(me+test) << endl;
// return the answer
return me;
}
bool TensorMesonVectorPScalarDecayer::twoBodyMEcode(const DecayMode & dm,int & mecode,
double & coupling) const {
int imode(-1);
int id(dm.parent()->id());
int idbar = dm.parent()->CC() ? dm.parent()->CC()->id() : id;
ParticleMSet::const_iterator pit(dm.products().begin());
int id1((**pit).id());
int id1bar = (**pit).CC() ? (**pit).CC()->id() : id1;
++pit;
int id2((**pit).id());
int id2bar = (**pit).CC() ? (**pit).CC()->id() : id2;
unsigned int ix(0);
bool order(false);
do {
if(id ==_incoming[ix]) {
if(id1==_outgoingP[ix]&&id2==_outgoingV[ix]) {
imode=ix;
order=true;
}
if(id2==_outgoingP[ix]&&id1==_outgoingV[ix]) {
imode=ix;
order=false;
}
}
if(idbar==_incoming[ix]&&imode<0) {
if(id1bar==_outgoingP[ix]&&id2bar==_outgoingV[ix]) {
imode=ix;
order=true;
}
if(id2bar==_outgoingP[ix]&&id1bar==_outgoingV[ix]) {
imode=ix;
order=false;
}
}
++ix;
}
while(ix<_incoming.size()&&imode<0);
coupling=_coupling[imode]*sqr(dm.parent()->mass());
mecode=8;
return order;
}
void TensorMesonVectorPScalarDecayer::dataBaseOutput(ofstream & output,
bool header) const {
if(header) output << "update decayers set parameters=\"";
// parameters for the DecayIntegrator base class
DecayIntegrator::dataBaseOutput(output,false);
// the rest of the parameters
for(unsigned int ix=0;ix<_incoming.size();++ix) {
if(ix<_initsize) {
output << "newdef " << name() << ":Incoming " << ix << " "
<< _incoming[ix] << "\n";
output << "newdef " << name() << ":OutgoingVector " << ix << " "
<< _outgoingV[ix] << "\n";
output << "newdef " << name() << ":OutgoingScalar " << ix << " "
<< _outgoingP[ix] << "\n";
output << "newdef " << name() << ":Coupling " << ix << " "
<< _coupling[ix]*GeV2 << "\n";
output << "newdef " << name() << ":MaxWeight " << ix << " "
<< _maxweight[ix] << "\n";
}
else {
output << "insert " << name() << ":Incoming " << ix << " "
<< _incoming[ix] << "\n";
output << "insert " << name() << ":OutgoingVector " << ix << " "
<< _outgoingV[ix] << "\n";
output << "insert " << name() << ":OutgoingScalar " << ix << " "
<< _outgoingP[ix] << "\n";
output << "insert " << name() << ":Coupling " << ix << " "
<< _coupling[ix]*GeV2 << "\n";
output << "insert " << name() << ":MaxWeight " << ix << " "
<< _maxweight[ix] << "\n";
}
}
if(header) output << "\n\" where BINARY ThePEGName=\""
<< fullName() << "\";" << endl;
}
diff --git a/Decay/VectorMeson/VectorMeson2BaryonsDecayer.h b/Decay/VectorMeson/VectorMeson2BaryonsDecayer.h
--- a/Decay/VectorMeson/VectorMeson2BaryonsDecayer.h
+++ b/Decay/VectorMeson/VectorMeson2BaryonsDecayer.h
@@ -1,230 +1,230 @@
// -*- C++ -*-
#ifndef Herwig_VectorMeson2BaryonsDecayer_H
#define Herwig_VectorMeson2BaryonsDecayer_H
//
// This is the declaration of the VectorMeson2BaryonsDecayer class.
//
#include "Herwig/Decay/DecayIntegrator.h"
#include "Herwig/Decay/PhaseSpaceMode.h"
#include "ThePEG/Helicity/LorentzPolarizationVector.h"
#include "ThePEG/Helicity/LorentzSpinorBar.h"
#include "ThePEG/Helicity/LorentzRSSpinorBar.h"
namespace Herwig {
using namespace ThePEG;
/** \ingroup Decay
*
* The <code>VectorMeson2BaryonsDecayer</code> class is designed for the decay
* of a vector meson to a baryon-antibaryon pair.
*
* In this case the matrix element is taken to have the form
* \f[\mathcal{M} = e_g \epsilon_\mu \bar{u}(p_f) \left[\gamma^\mu \right]u(p_{\bar{f}}).\f]
*
* The incoming vector mesons together with their decay products and the coupling
* \f$e_g\f$, \f$G_E\f$ and the phase \f$\phi_E\f$ can be specified using the interfaces for the class.
* The maximum weights
* for the decays can be calculated using the Initialize interface of the
* DecayIntegrator class or specified using the interface.
*
* The incoming and outgoing particles, couplings and maximum weights for
* many of the common \f$V\to f\bar{f}\f$ decays are specified in the default
* constructor.
*
* @see DecayIntegrator
* @see \ref VectorMeson2BaryonsDecayerInterfaces "The interfaces"
* defined for VectorMeson2BaryonsDecayer.
*
*/
class VectorMeson2BaryonsDecayer: public DecayIntegrator {
public:
/**
* The default constructor.
*/
VectorMeson2BaryonsDecayer();
/**
* 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 outgoing The particles produced in the decay
* @param momenta The momenta of 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.
*/
double me2(const int ichan,const Particle & part,
const tPDVector & outgoing,
const vector<Lorentz5Momentum> & momenta,
MEOption meopt) const;
/**
* Construct the SpinInfos for the particles produced in the decay
*/
virtual void constructSpinInfo(const Particle & part,
ParticleVector outgoing) const;
/**
* 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
*/
virtual void dataBaseOutput(ofstream & os,bool header) 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 to the begining of the run phase.
*/
virtual void doinitrun();
//@}
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
- VectorMeson2BaryonsDecayer & operator=(const VectorMeson2BaryonsDecayer &);
+ VectorMeson2BaryonsDecayer & operator=(const VectorMeson2BaryonsDecayer &) = delete;
private:
/**
* \f$G_M\f$ coupling
*/
vector<double> gm_;
/**
* \f$G_E\f$ coupling
*/
vector<double> ge_;
/**
* Relative phase of \f$G_E\f$/\f$G_M\f$
*/
vector<double> phi_;
/**
* the PDG codes for the incoming particles
*/
vector<int> incoming_;
/**
* the PDG codes for the outgoing fermion
*/
vector<int> outgoingf_;
/**
* the PDG codes for the outgoing antifermion.
*/
vector<int> outgoinga_;
/**
* maximum weight for a decay
*/
vector<double> maxweight_;
/**
* Initial size of the vectors
*/
unsigned int initsize_;
/**
* Spin density matrix
*/
mutable RhoDMatrix rho_;
/**
* Polarization vectors for the decaying particle
*/
mutable vector<Helicity::LorentzPolarizationVector> vectors_;
/**
* Spinors for the decay products
*/
mutable vector<Helicity::LorentzSpinor <SqrtEnergy> > wave_;
/**
* barred spinors for the decay products
*/
mutable vector<Helicity::LorentzSpinorBar<SqrtEnergy> > wavebar_;
/**
* Spinors for the decay products
*/
mutable vector<Helicity::LorentzRSSpinor <SqrtEnergy> > wave2_;
/**
* barred spinors for the decay products
*/
mutable vector<Helicity::LorentzRSSpinorBar<SqrtEnergy> > wave2bar_;
};
}
#endif /* Herwig_VectorMeson2BaryonsDecayer_H */
diff --git a/Decay/VectorMeson/f1FourPiDecayer.cc b/Decay/VectorMeson/f1FourPiDecayer.cc
--- a/Decay/VectorMeson/f1FourPiDecayer.cc
+++ b/Decay/VectorMeson/f1FourPiDecayer.cc
@@ -1,313 +1,313 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the f1FourPiDecayer class.
//
#include "f1FourPiDecayer.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/ParVector.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Helicity/epsilon.h"
using namespace Herwig;
f1FourPiDecayer::f1FourPiDecayer() :
gRhoPiPi_(6.), ga1RhoPi_(4.8*GeV), gf1a1Pi_(9.77/GeV), maxWeight_({1.,1.}) {
generateIntermediates(true);
}
// normally not implemented but do it here to get rid of the a_1 which
// can't be on-shell
ParticleVector f1FourPiDecayer::decay(const Particle & parent,
const tPDVector & children) const {
ParticleVector output = DecayIntegrator::decay(parent,children);
ParticleVector::iterator it =output.begin();
for(;it!=output.end();++it) {
long id = (**it).id();
if(id==20113 || id==20213 || id==-20213)
break;
}
if(it!=output.end()) {
PPtr a1 = *it;
output.erase(it);
for(PPtr child : a1->children()) {
output.push_back(child);
a1->abandonChild(child);
}
}
return output;
}
IBPtr f1FourPiDecayer::clone() const {
return new_ptr(*this);
}
IBPtr f1FourPiDecayer::fullclone() const {
return new_ptr(*this);
}
void f1FourPiDecayer::persistentOutput(PersistentOStream & os) const {
os << gRhoPiPi_ << ounit(ga1RhoPi_,GeV) << ounit(gf1a1Pi_,1./GeV)
<< ounit(ma1_,GeV) << ounit(ga1_,GeV)
<< ounit(mrho_,GeV) << ounit(grho_,GeV) << maxWeight_;
}
void f1FourPiDecayer::persistentInput(PersistentIStream & is, int) {
is >> gRhoPiPi_ >> iunit(ga1RhoPi_,GeV) >> iunit(gf1a1Pi_,1./GeV)
>> iunit(ma1_,GeV) >> iunit(ga1_,GeV)
>> iunit(mrho_,GeV) >> iunit(grho_,GeV) >> maxWeight_;
}
// The following static variable is needed for the type
// description system in ThePEG.
DescribeClass<f1FourPiDecayer,DecayIntegrator>
describeHerwigf1FourPiDecayer("Herwig::f1FourPiDecayer", "HwVMDecay.so");
void f1FourPiDecayer::Init() {
static ClassDocumentation<f1FourPiDecayer> documentation
("The f1FourPiDecayer class implements a simple model for "
"f1 -> pipirho via an intermediate a_1");
static ParVector<f1FourPiDecayer,double> interfaceMaxWeight
("MaxWeight",
"Maximum weights for the decays",
&f1FourPiDecayer::maxWeight_, 2, 1.0, 0.0, 100.0,
false, false, Interface::limited);
static Parameter<f1FourPiDecayer,double> interfacegRhoPiPi
("gRhoPiPi",
"The coupling of the rho to two pions",
&f1FourPiDecayer::gRhoPiPi_, 6., 0.0, 10.0,
false, false, Interface::limited);
static Parameter<f1FourPiDecayer,Energy> interfacega1RhoPi
("ga1RhoPi",
"Coupling of the a_1 to rho pi",
&f1FourPiDecayer::ga1RhoPi_, GeV, 4.8*GeV, 0.*GeV, 20.*GeV,
false, false, Interface::limited);
static Parameter<f1FourPiDecayer,InvEnergy> interfacegf1a1Pi
("gf1a1Pi",
"Coupling of f_1 to a_1 pi",
&f1FourPiDecayer::gf1a1Pi_, 1./GeV, 1.0/GeV, 0.0/GeV, 10.0/GeV,
false, false, Interface::limited);
}
void f1FourPiDecayer::doinit() {
DecayIntegrator::doinit();
// pointers to the particles we need as external particles
tPDPtr f1 = getParticleData(ParticleID::f_1);
tPDPtr a1p = getParticleData(ParticleID::a_1plus);
tPDPtr a1m = getParticleData(ParticleID::a_1minus);
tPDPtr a10 = getParticleData(ParticleID::a_10);
tPDPtr pip = getParticleData(ParticleID::piplus);
tPDPtr pim = getParticleData(ParticleID::piminus);
tPDPtr pi0 = getParticleData(ParticleID::pi0);
tPDPtr rhop = getParticleData(ParticleID::rhoplus);
tPDPtr rhom = getParticleData(ParticleID::rhominus);
tPDPtr rho0 = getParticleData(ParticleID::rho0);
// decay mode f_1 -> pi+ pi- pi+ pi-
PhaseSpaceModePtr mode = new_ptr(PhaseSpaceMode(f1,{pip,pim,pip,pim},maxWeight_[0]));
mode->addChannel((PhaseSpaceChannel(mode),0,a1m,0,1,1,2,1,rho0,2,3,2,4));
mode->addChannel((PhaseSpaceChannel(mode),0,a1p,0,2,1,1,1,rho0,2,3,2,4));
mode->addChannel((PhaseSpaceChannel(mode),0,a1m,0,3,1,2,1,rho0,2,1,2,4));
mode->addChannel((PhaseSpaceChannel(mode),0,a1p,0,2,1,3,1,rho0,2,1,2,4));
mode->addChannel((PhaseSpaceChannel(mode),0,a1m,0,1,1,4,1,rho0,2,3,2,2));
mode->addChannel((PhaseSpaceChannel(mode),0,a1p,0,4,1,1,1,rho0,2,3,2,2));
mode->addChannel((PhaseSpaceChannel(mode),0,a1m,0,3,1,4,1,rho0,2,1,2,2));
mode->addChannel((PhaseSpaceChannel(mode),0,a1p,0,4,1,3,1,rho0,2,1,2,2));
addMode(mode);
// decay mode f_1 -> pi+ pi0 pi- pi0
mode = new_ptr(PhaseSpaceMode(f1,{pip,pi0,pim,pi0},maxWeight_[0]));
mode->addChannel((PhaseSpaceChannel(mode),0,a1m,0,1,1,2,1,rhop,2,3,2,4));
mode->addChannel((PhaseSpaceChannel(mode),0,a10,0,2,1,1,1,rhop,2,3,2,4));
mode->addChannel((PhaseSpaceChannel(mode),0,a1m,0,1,1,4,1,rhop,2,3,2,2));
mode->addChannel((PhaseSpaceChannel(mode),0,a10,0,4,1,1,1,rhop,2,3,2,2));
mode->addChannel((PhaseSpaceChannel(mode),0,a1p,0,3,1,4,1,rhom,2,1,2,2));
mode->addChannel((PhaseSpaceChannel(mode),0,a10,0,4,1,3,1,rhom,2,1,2,2));
mode->addChannel((PhaseSpaceChannel(mode),0,a1p,0,3,1,2,1,rhom,2,1,2,4));
mode->addChannel((PhaseSpaceChannel(mode),0,a10,0,2,1,3,1,rhom,2,1,2,4));
addMode(mode);
// masses of intermediates
ma1_ = a1p->mass();
ga1_ = a1p->width();
mrho_ = rhop->mass();
grho_ = rhop->width();
}
void f1FourPiDecayer::doinitrun() {
DecayIntegrator::doinitrun();
if(initialize()) {
for(unsigned int ix=0;ix<maxWeight_.size();++ix)
maxWeight_[ix] = mode(ix)->maxWeight();
}
}
int f1FourPiDecayer::modeNumber(bool & cc,tcPDPtr parent,
const tPDVector & children) const {
if(children.size()!=4 || parent->id()!=ParticleID::f_1) return -1;
// check the pions
int npi0(0),npiplus(0),npiminus(0);
for(auto child : children) {
int idtemp= child->id();
if(idtemp==ParticleID::piplus) ++npiplus;
else if(idtemp==ParticleID::piminus) ++npiminus;
else if(idtemp==ParticleID::pi0) ++npi0;
}
cc = false;
// f_1 -> 2pi+ 2pi-mode
if(npiplus==2 && npiminus==2) return 0;
// f_1 -> pi+ pi- pi0 pi0 mode
else if (npiplus ==1 && npiminus==1 && npi0==2) return 1;
// not found
return -1;
}
void f1FourPiDecayer::
constructSpinInfo(const Particle & part, ParticleVector decay) const {
VectorWaveFunction::constructSpinInfo(vector_,const_ptr_cast<tPPtr>(&part),
incoming,true,false);
// set up the spin information for the pions
for(unsigned int ix=0;ix<4;++ix)
ScalarWaveFunction::constructSpinInfo(decay[ix],outgoing,true);
}
double f1FourPiDecayer::me2(const int ichan, const Particle & part,
const tPDVector & ,
const vector<Lorentz5Momentum> & momenta,
MEOption meopt) const {
if(!ME())
ME(new_ptr(GeneralDecayMatrixElement(PDT::Spin1,PDT::Spin0,PDT::Spin0,PDT::Spin0,PDT::Spin0)));
useMe();
// polarization vectors for incoming
if(meopt==Initialize) {
VectorWaveFunction::calculateWaveFunctions(vector_,rho_,
const_ptr_cast<tPPtr>(&part),
incoming,false);
}
// breit wigners
Lorentz5Momentum pa1[4] = {part.momentum()-momenta[0],part.momentum()-momenta[1],
part.momentum()-momenta[2],part.momentum()-momenta[3]};
complex<InvEnergy2> bwa1[4];
for(unsigned int ix=0;ix<4;++ix) {
pa1[ix].rescaleMass();
bwa1[ix] = Resonance::BreitWignera1(pa1[ix].mass2(),ma1_,ga1_)/sqr(ma1_);
}
// compute the matrix element (as a current and then contract)
LorentzVector<complex<InvEnergy> > current;
// decay mode f_1 -> pi+ pi- pi+pi-
double sym(0.5);
if(imode()==0) {
sym=0.25;
complex<InvEnergy2> bwrho[4] =
{Resonance::BreitWignerPWave((momenta[0]+momenta[1]).m2(),mrho_,grho_,momenta[0].mass(),momenta[1].mass())/sqr(mrho_),
Resonance::BreitWignerPWave((momenta[0]+momenta[3]).m2(),mrho_,grho_,momenta[0].mass(),momenta[3].mass())/sqr(mrho_),
Resonance::BreitWignerPWave((momenta[2]+momenta[1]).m2(),mrho_,grho_,momenta[2].mass(),momenta[1].mass())/sqr(mrho_),
Resonance::BreitWignerPWave((momenta[2]+momenta[3]).m2(),mrho_,grho_,momenta[2].mass(),momenta[3].mass())/sqr(mrho_)};
if(ichan<=0) {
// mode->addChannel((PhaseSpaceChannel(mode),0,a1m,0,1,1,2,1,rho0,2,3,2,4));
current += bwa1[0]*bwrho[3]*epsilon(part.momentum(),pa1[0],momenta[2]-momenta[3]);
}
if(ichan<0||ichan==1) {
// mode->addChannel((PhaseSpaceChannel(mode),0,a1p,0,2,1,1,1,rho0,2,3,2,4));
current -= bwa1[1]*bwrho[3]*epsilon(part.momentum(),pa1[1],momenta[2]-momenta[3]);
}
if(ichan<0||ichan==2) {
// mode->addChannel((PhaseSpaceChannel(mode),0,a1m,0,3,1,2,1,rho0,2,1,2,4));
current += bwa1[2]*bwrho[1]*epsilon(part.momentum(),pa1[2],momenta[0]-momenta[3]);
}
if(ichan<0||ichan==3) {
// mode->addChannel((PhaseSpaceChannel(mode),0,a1p,0,2,1,3,1,rho0,2,1,2,4));
current -= bwa1[1]*bwrho[1]*epsilon(part.momentum(),pa1[1],momenta[0]-momenta[3]);
}
if(ichan<0||ichan==4) {
// mode->addChannel((PhaseSpaceChannel(mode),0,a1m,0,1,1,4,1,rho0,2,3,2,2));
current += bwa1[0]*bwrho[2]*epsilon(part.momentum(),pa1[0],momenta[2]-momenta[1]);
}
if(ichan<0||ichan==5) {
// mode->addChannel((PhaseSpaceChannel(mode),0,a1p,0,4,1,1,1,rho0,2,3,2,2));
current -= bwa1[3]*bwrho[2]*epsilon(part.momentum(),pa1[3],momenta[2]-momenta[1]);
}
if(ichan<0||ichan==6) {
// mode->addChannel((PhaseSpaceChannel(mode),0,a1m,0,3,1,4,1,rho0,2,1,2,2));
current += bwa1[2]*bwrho[0]*epsilon(part.momentum(),pa1[2],momenta[0]-momenta[1]);
}
if(ichan<0||ichan==7) {
// mode->addChannel((PhaseSpaceChannel(mode),0,a1p,0,4,1,3,1,rho0,2,1,2,2));
current -= bwa1[3]*bwrho[0]*epsilon(part.momentum(),pa1[3],momenta[0]-momenta[1]);
}
}
// decay mode f_1 -> pi+ pi0 pi- pi0
else {
complex<InvEnergy2> bwrho[4] =
{Resonance::BreitWignerPWave((momenta[0]+momenta[1]).m2(),mrho_,grho_,momenta[0].mass(),momenta[1].mass())/sqr(mrho_),
Resonance::BreitWignerPWave((momenta[0]+momenta[3]).m2(),mrho_,grho_,momenta[0].mass(),momenta[3].mass())/sqr(mrho_),
Resonance::BreitWignerPWave((momenta[2]+momenta[1]).m2(),mrho_,grho_,momenta[2].mass(),momenta[1].mass())/sqr(mrho_),
Resonance::BreitWignerPWave((momenta[2]+momenta[3]).m2(),mrho_,grho_,momenta[2].mass(),momenta[3].mass())/sqr(mrho_)};
double f1 = (momenta[2].mass2()-momenta[3].mass2())/sqr(mrho_);
double f2 = 1+f1;
f1 = 1.-f1;
if(ichan<=0) {
// mode->addChannel((PhaseSpaceChannel(mode),0,a1m,0,1,1,2,1,rhop,2,3,2,4));
current += bwa1[0]*bwrho[3]*epsilon(part.momentum(),pa1[0],f1*momenta[2]-f2*momenta[3]);
}
if(ichan<0||ichan==1) {
// mode->addChannel((PhaseSpaceChannel(mode),0,a10,0,2,1,1,1,rhop,2,3,2,4));
current -= bwa1[1]*bwrho[3]*epsilon(part.momentum(),pa1[1],f1*momenta[2]-f2*momenta[3]);
}
if(ichan<0||ichan==2) {
// mode->addChannel((PhaseSpaceChannel(mode),0,a1m,0,1,1,4,1,rhop,2,3,2,2));
current += bwa1[0]*bwrho[2]*epsilon(part.momentum(),pa1[0],f1*momenta[2]-f2*momenta[1]);
}
if(ichan<0||ichan==3) {
// mode->addChannel((PhaseSpaceChannel(mode),0,a10,0,4,1,1,1,rhop,2,3,2,2));
current -= bwa1[3]*bwrho[2]*epsilon(part.momentum(),pa1[3],f1*momenta[2]-f2*momenta[1]);
}
if(ichan<0||ichan==4) {
// mode->addChannel((PhaseSpaceChannel(mode),0,a1p,0,3,1,4,1,rhom,2,1,2,2));
current += bwa1[2]*bwrho[0]*epsilon(part.momentum(),pa1[2],f1*momenta[0]-f2*momenta[1]);
}
if(ichan<0||ichan==5) {
// mode->addChannel((PhaseSpaceChannel(mode),0,a10,0,4,1,3,1,rhom,2,1,2,2));
current -= bwa1[3]*bwrho[0]*epsilon(part.momentum(),pa1[3],f1*momenta[0]-f2*momenta[1]);
}
if(ichan<0||ichan==6) {
// mode->addChannel((PhaseSpaceChannel(mode),0,a1p,0,3,1,2,1,rhom,2,1,2,4));
current += bwa1[2]*bwrho[1]*epsilon(part.momentum(),pa1[2],f1*momenta[0]-f2*momenta[3]);
}
if(ichan<0||ichan==7) {
// mode->addChannel((PhaseSpaceChannel(mode),0,a10,0,2,1,3,1,rhom,2,1,2,4));
current -= bwa1[1]*bwrho[1]*epsilon(part.momentum(),pa1[1],f1*momenta[0]-f2*momenta[3]);
}
}
// contract the current
double pre = gRhoPiPi_*gf1a1Pi_*ga1RhoPi_;
for(unsigned int ihel=0;ihel<3;++ihel)
- (*ME())(ihel,0,0,0,0) = pre*current.dot(vector_[ihel])*part.mass();
+ (*ME())(ihel,0,0,0,0) = Complex(pre*current.dot(vector_[ihel])*part.mass());
// matrix element
return sym*ME()->contract(rho_).real();
}
void f1FourPiDecayer::dataBaseOutput(ofstream & output,
bool header) const {
if(header) output << "update decayers set parameters=\"";
// parameters for the DecayIntegrator base class
DecayIntegrator::dataBaseOutput(output,false);
output << "newdef " << name() << ":gRhoPiPi " << gRhoPiPi_ << "\n";
output << "newdef " << name() << ":ga1RhoPi " << ga1RhoPi_/GeV << "\n";
output << "newdef " << name() << ":gf1a1Pi " << gf1a1Pi_*GeV << "\n";
for(unsigned int ix=0;ix<maxWeight_.size();++ix) {
output << "newdef " << name() << ":maxWeight " << ix << " "
<< maxWeight_[ix] << "\n";
}
if(header) output << "\n\" where BINARY ThePEGName=\""
<< fullName() << "\";" << endl;
}
diff --git a/Decay/VectorMeson/f1RhoPiPiDecayer.cc b/Decay/VectorMeson/f1RhoPiPiDecayer.cc
--- a/Decay/VectorMeson/f1RhoPiPiDecayer.cc
+++ b/Decay/VectorMeson/f1RhoPiPiDecayer.cc
@@ -1,219 +1,219 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the f1RhoPiPiDecayer class.
//
#include "f1RhoPiPiDecayer.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/ParVector.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Helicity/epsilon.h"
using namespace Herwig;
f1RhoPiPiDecayer::f1RhoPiPiDecayer() :
ga1RhoPi_(4.8*GeV), gf1a1Pi_(9.77/GeV), maxWeight_({1.,1.}) {
generateIntermediates(true);
}
// normally not implemented but do it here to get rid of the a_1 which
// can't be on-shell
ParticleVector f1RhoPiPiDecayer::decay(const Particle & parent,
const tPDVector & children) const {
ParticleVector output = DecayIntegrator::decay(parent,children);
ParticleVector::iterator it =output.begin();
for(;it!=output.end();++it) {
long id = (**it).id();
if(id==20113 || id==20213 || id==-20213)
break;
}
if(it!=output.end()) {
PPtr a1 = *it;
output.erase(it);
for(PPtr child : a1->children()) {
output.push_back(child);
a1->abandonChild(child);
}
}
return output;
}
IBPtr f1RhoPiPiDecayer::clone() const {
return new_ptr(*this);
}
IBPtr f1RhoPiPiDecayer::fullclone() const {
return new_ptr(*this);
}
void f1RhoPiPiDecayer::persistentOutput(PersistentOStream & os) const {
os << ounit(ga1RhoPi_,GeV) << ounit(gf1a1Pi_,1./GeV)
<< ounit(ma1_,GeV) << ounit(ga1_,GeV) << maxWeight_;
}
void f1RhoPiPiDecayer::persistentInput(PersistentIStream & is, int) {
is >> iunit(ga1RhoPi_,GeV) >> iunit(gf1a1Pi_,1./GeV)
>> iunit(ma1_,GeV) >> iunit(ga1_,GeV) >> maxWeight_;
}
// The following static variable is needed for the type
// description system in ThePEG.
DescribeClass<f1RhoPiPiDecayer,DecayIntegrator>
describeHerwigf1RhoPiPiDecayer("Herwig::f1RhoPiPiDecayer", "HwVMDecay.so");
void f1RhoPiPiDecayer::Init() {
static ClassDocumentation<f1RhoPiPiDecayer> documentation
("The f1RhoPiPiDecayer class implements a simple model for "
"f1 -> pipirho via an intermediate a_1");
static ParVector<f1RhoPiPiDecayer,double> interfaceMaxWeight
("MaxWeight",
"Maximum weights for the decays",
&f1RhoPiPiDecayer::maxWeight_, 2, 1.0, 0.0, 100.0,
false, false, Interface::limited);
static Parameter<f1RhoPiPiDecayer,Energy> interfacega1RhoPi
("ga1RhoPi",
"Coupling of the a_1 to rho pi",
&f1RhoPiPiDecayer::ga1RhoPi_, GeV, 4.8*GeV, 0.*GeV, 20.*GeV,
false, false, Interface::limited);
static Parameter<f1RhoPiPiDecayer,InvEnergy> interfacegf1a1Pi
("gf1a1Pi",
"Coupling of f_1 to a_1 pi",
&f1RhoPiPiDecayer::gf1a1Pi_, 1./GeV, 1.0/GeV, 0.0/GeV, 10.0/GeV,
false, false, Interface::limited);
}
void f1RhoPiPiDecayer::doinit() {
DecayIntegrator::doinit();
// pointers to the particles we need as external particles
tPDPtr f1 = getParticleData(ParticleID::f_1);
tPDPtr a1p = getParticleData(ParticleID::a_1plus);
tPDPtr a1m = getParticleData(ParticleID::a_1minus);
tPDPtr a10 = getParticleData(ParticleID::a_10);
tPDPtr pip = getParticleData(ParticleID::piplus);
tPDPtr pim = getParticleData(ParticleID::piminus);
tPDPtr pi0 = getParticleData(ParticleID::pi0);
tPDPtr rhop = getParticleData(ParticleID::rhoplus);
tPDPtr rhom = getParticleData(ParticleID::rhominus);
tPDPtr rho0 = getParticleData(ParticleID::rho0);
// decay mode f_1 -> pi+ pi- rho0
PhaseSpaceModePtr mode = new_ptr(PhaseSpaceMode(f1,{pip,pim,rho0},maxWeight_[0]));
mode->addChannel((PhaseSpaceChannel(mode),0,a1m,0,1,1,2,1,3));
mode->addChannel((PhaseSpaceChannel(mode),0,a1p,0,2,1,1,1,3));
addMode(mode);
// decay mode f_1 -> pi- pi0 rho+
mode = new_ptr(PhaseSpaceMode(f1,{pim,pi0,rhop},maxWeight_[1]));
mode->addChannel((PhaseSpaceChannel(mode),0,a1p,0,1,1,2,1,3));
mode->addChannel((PhaseSpaceChannel(mode),0,a10,0,2,1,1,1,3));
addMode(mode);
ma1_ = a1p->mass();
ga1_ = a1p->width();
}
void f1RhoPiPiDecayer::doinitrun() {
DecayIntegrator::doinitrun();
if(initialize()) {
for(unsigned int ix=0;ix<maxWeight_.size();++ix)
maxWeight_[ix] = mode(ix)->maxWeight();
}
}
int f1RhoPiPiDecayer::modeNumber(bool & cc,tcPDPtr parent,
const tPDVector & children) const {
if(children.size()!=3 || parent->id()!=ParticleID::f_1) return -1;
// check the pions
int npi0(0),npiplus(0),npiminus(0),idrho(0);
for(auto child : children) {
int idtemp= child->id();
if(idtemp==ParticleID::piplus) ++npiplus;
else if(idtemp==ParticleID::piminus) ++npiminus;
else if(idtemp==ParticleID::pi0) ++npi0;
else idrho=idtemp;
}
cc = false;
// f_1 -> pi+pi-rho0 mode
if(idrho==113 && npiplus==1 && npiminus==1) return 0;
// f_1 -> pi-pi0rho+ mode
else if (idrho== 213 && npiminus==1 && npi0==1) return 1;
else if (idrho==-213 && npiplus ==1 && npi0==1) {
cc=true;
return 1;
}
// not found
return -1;
}
void f1RhoPiPiDecayer::
constructSpinInfo(const Particle & part, ParticleVector decay) const {
VectorWaveFunction::constructSpinInfo(vectors_[0],const_ptr_cast<tPPtr>(&part),
incoming,true,false);
// set up the spin information for the decay products
// pions
for(unsigned int ix=0;ix<2;++ix)
ScalarWaveFunction::constructSpinInfo(decay[ix],outgoing,true);
// rho
VectorWaveFunction::constructSpinInfo(vectors_[1],decay[2],outgoing,true,false);
}
double f1RhoPiPiDecayer::me2(const int ichan, const Particle & part,
const tPDVector & ,
const vector<Lorentz5Momentum> & momenta,
MEOption meopt) const {
if(!ME())
ME(new_ptr(GeneralDecayMatrixElement(PDT::Spin1,PDT::Spin0,PDT::Spin0,PDT::Spin1)));
useMe();
// polarization vectors for incoming
if(meopt==Initialize) {
VectorWaveFunction::calculateWaveFunctions(vectors_[0],rho_,
const_ptr_cast<tPPtr>(&part),
incoming,false);
}
// polarization vectors for rho
vectors_[1].resize(3);
for(unsigned int ix=0;ix<3;++ix)
vectors_[1][ix] = HelicityFunctions::polarizationVector(-momenta[2],ix,Helicity::outgoing);
// breit wigners
Lorentz5Momentum pa1[2] = {part.momentum()-momenta[0],
part.momentum()-momenta[1]};
for(unsigned int ix=0;ix<2;++ix) pa1[ix].rescaleMass();
complex<InvEnergy2> bwa1[2] = {Resonance::BreitWignera1(pa1[0].mass2(),ma1_,ga1_)/sqr(ma1_),
Resonance::BreitWignera1(pa1[1].mass2(),ma1_,ga1_)/sqr(ma1_)};
if(ichan>0) bwa1[ ichan == 0 ? 1 : 0 ] = ZERO;
// compute the matrix element
for(unsigned int ihel=0;ihel<3;++ihel) {
LorentzVector<complex<Energy2> > pol[2] = {epsilon(vectors_[0][ihel],part.momentum(),pa1[0]),
epsilon(vectors_[0][ihel],part.momentum(),pa1[1])};
for(unsigned int ohel=0;ohel<3;++ohel) {
- (*ME())(ihel,0,0,ohel) = gf1a1Pi_*ga1RhoPi_*(LorentzPolarizationVector(pol[0]*bwa1[0])-
- LorentzPolarizationVector(pol[1]*bwa1[1])).dot(vectors_[1][ohel]);
+ (*ME())(ihel,0,0,ohel) = Complex(gf1a1Pi_*ga1RhoPi_*(LorentzPolarizationVector(pol[0]*bwa1[0])-
+ LorentzPolarizationVector(pol[1]*bwa1[1])).dot(vectors_[1][ohel]));
}
}
// matrix element
return ME()->contract(rho_).real();
}
void f1RhoPiPiDecayer::dataBaseOutput(ofstream & output,
bool header) const {
if(header) output << "update decayers set parameters=\"";
// parameters for the DecayIntegrator base class
DecayIntegrator::dataBaseOutput(output,false);
output << "newdef " << name() << ":ga1RhoPi " << ga1RhoPi_/GeV << "\n";
output << "newdef " << name() << ":gf1a1Pi " << gf1a1Pi_*GeV << "\n";
for(unsigned int ix=0;ix<maxWeight_.size();++ix) {
output << "newdef " << name() << ":maxWeight " << ix << " "
<< maxWeight_[ix] << "\n";
}
if(header) output << "\n\" where BINARY ThePEGName=\""
<< fullName() << "\";" << endl;
}
diff --git a/Decay/WeakCurrents/ThreePionCLEOCurrent.cc b/Decay/WeakCurrents/ThreePionCLEOCurrent.cc
--- a/Decay/WeakCurrents/ThreePionCLEOCurrent.cc
+++ b/Decay/WeakCurrents/ThreePionCLEOCurrent.cc
@@ -1,1283 +1,1284 @@
// -*- C++ -*-
//
// ThreePionCLEOCurrent.cc is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2019 The Herwig Collaboration
//
// Herwig is licenced under version 3 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 ThreePionCLEOCurrent class.
//
#include "ThreePionCLEOCurrent.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/ParVector.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "Herwig/PDT/ThreeBodyAllOnCalculator.h"
#include "Herwig/Decay/ResonanceHelpers.h"
#include "ThePEG/Utilities/DescribeClass.h"
using namespace Herwig;
DescribeClass<ThreePionCLEOCurrent,WeakCurrent>
describeHerwigThreePionCLEOCurrent("Herwig::ThreePionCLEOCurrent",
"HwWeakCurrents.so");
HERWIG_INTERPOLATOR_CLASSDESC(ThreePionCLEOCurrent,Energy,Energy2)
ThreePionCLEOCurrent::ThreePionCLEOCurrent() {
addDecayMode(1,-1);
addDecayMode(2,-2);
addDecayMode(2,-1);
addDecayMode(1,-1);
addDecayMode(2,-2);
addDecayMode(2,-1);
setInitialModes(6);
// rho masses and widths
_rhomass = {0.7743*GeV,1.370*GeV};
_rhowidth = {0.1491*GeV,0.386*GeV};
// f_2 mass and width
_f2mass = 1.275*GeV;
_f2width = 0.185*GeV;
// f_0(1370) mass and width
_f0mass = 1.186*GeV;
_f0width = 0.350*GeV;
// sigma mass and width
_sigmamass = 0.860*GeV;
_sigmawidth = 0.880*GeV;
// a1 mass and width
_a1mass = 1.331*GeV;
_a1width = 0.814*GeV;
// parameters for the K K* contribution to the a_1 running width
_mKstar = 894*MeV;
_mK = 496*MeV;
_gammk = 3.32;
// pion decay constant
_fpi = 130.7*MeV/sqrt(2.);
// couplings and phases for the different channels
// p-wave rho and rho prime
using Constants::pi;
_rhomagP = {1.,0.12};
_rhophaseP = {0.,0.99*pi};
// d-wave rho and rho prime
_rhomagD = {0.37/GeV2,0.87/GeV2};
_rhophaseD = {-0.15*pi, 0.53*pi};
// f_2
_f2mag = 0.71/GeV2;
_f2phase = 0.56*pi;
_f2coup = ZERO;
// sigma
_sigmamag = 2.10;
_sigmaphase = 0.23*pi;
_sigmacoup = 0.;
// f_0
_f0mag = 0.77;
_f0phase = -0.54*pi;
_f0coup = 0.;
// initialize the a_1 width
_initializea1=false;
_a1opt=true;
double a1q2in[200]={0 ,15788.6,31577.3,47365.9,63154.6,78943.2,
94731.9,110521 ,126309 ,142098 ,157886 ,173675 ,
189464 ,205252 ,221041 ,236830 ,252618 ,268407 ,
284196 ,299984 ,315773 ,331562 ,347350 ,363139 ,
378927 ,394716 ,410505 ,426293 ,442082 ,457871 ,
473659 ,489448 ,505237 ,521025 ,536814 ,552603 ,
568391 ,584180 ,599969 ,615757 ,631546 ,647334 ,
663123 ,678912 ,694700 ,710489 ,726278 ,742066 ,
757855 ,773644 ,789432 ,805221 ,821010 ,836798 ,
852587 ,868375 ,884164 ,899953 ,915741 ,931530 ,
947319 ,963107 ,978896 ,994685 ,
1.01047e+06,1.02626e+06,1.04205e+06,1.05784e+06,
1.07363e+06,1.08942e+06,1.10521e+06,1.12099e+06,
1.13678e+06,1.15257e+06,1.16836e+06,1.18415e+06,
1.19994e+06,1.21573e+06,1.23151e+06,1.24730e+06,
1.26309e+06,1.27888e+06,1.29467e+06,1.31046e+06,
1.32625e+06,1.34203e+06,1.35782e+06,1.37361e+06,
1.38940e+06,1.40519e+06,1.42098e+06,1.43677e+06,
1.45256e+06,1.46834e+06,1.48413e+06,1.49992e+06,
1.51571e+06,1.53150e+06,1.54729e+06,1.56308e+06,
1.57886e+06,1.59465e+06,1.61044e+06,1.62623e+06,
1.64202e+06,1.65781e+06,1.67360e+06,1.68939e+06,
1.70517e+06,1.72096e+06,1.73675e+06,1.75254e+06,
1.76833e+06,1.78412e+06,1.79991e+06,1.81569e+06,
1.83148e+06,1.84727e+06,1.86306e+06,1.87885e+06,
1.89464e+06,1.91043e+06,1.92621e+06,1.94200e+06,
1.95779e+06,1.97358e+06,1.98937e+06,2.00516e+06,
2.02095e+06,2.03674e+06,2.05252e+06,2.06831e+06,
2.08410e+06,2.09989e+06,2.11568e+06,2.13147e+06,
2.14726e+06,2.16304e+06,2.17883e+06,2.19462e+06,
2.21041e+06,2.22620e+06,2.24199e+06,2.25778e+06,
2.27356e+06,2.28935e+06,2.30514e+06,2.32093e+06,
2.33672e+06,2.35251e+06,2.36830e+06,2.38409e+06,
2.39987e+06,2.41566e+06,2.43145e+06,2.44724e+06,
2.46303e+06,2.47882e+06,2.49461e+06,2.51039e+06,
2.52618e+06,2.54197e+06,2.55776e+06,2.57355e+06,
2.58934e+06,2.60513e+06,2.62092e+06,2.63670e+06,
2.65249e+06,2.66828e+06,2.68407e+06,2.69986e+06,
2.71565e+06,2.73144e+06,2.74722e+06,2.76301e+06,
2.77880e+06,2.79459e+06,2.81038e+06,2.82617e+06,
2.84196e+06,2.85774e+06,2.87353e+06,2.88932e+06,
2.90511e+06,2.92090e+06,2.93669e+06,2.95248e+06,
2.96827e+06,2.98405e+06,2.99984e+06,3.01563e+06,
3.03142e+06,3.04721e+06,3.06300e+06,3.07879e+06,
3.09457e+06,3.11036e+06,3.12615e+06,3.14194e+06};
double a1widthin[200]={0,0,0,0,0,0,0,0,
0,0,0,0.00021256,0.0107225,0.0554708,0.150142,0.303848,
0.522655,0.81121,1.1736,1.61381,2.13606,2.74499,3.44583,4.24454,
5.14795,6.16391,7.3014,8.57079,9.98398,11.5547,13.2987,15.2344,
17.3827,19.7683,22.4195,25.3695,28.6568,32.3264,36.4311,41.0322,
46.201,52.0203,58.5847,66.0011,74.3871,83.8666,94.5615,106.578,
119.989,134.807,150.968,168.315,186.615,205.576,224.893,244.28,
263.499,282.364,300.748,318.569,335.781,352.367,368.327,383.677,
398.438,412.638,426.306,439.472,452.167,464.421,476.263,487.719,
498.815,509.576,520.024,530.179,540.063,549.693,559.621,568.26,
577.229,586.005,594.604,603.035,611.314,619.447,627.446,635.321,
643.082,650.736,658.288,665.75,673.127,680.427,687.659,694.82,
701.926,708.977,715.983,722.944,729.862,736.752,743.619,750.452,
757.271,764.076,770.874,777.658,784.444,791.233,798.027,804.838,
811.649,818.485,825.342,832.224,839.139,846.082,853.059,860.079,
867.143,874.248,881.409,919.527,945.28,965.514,983.228,999.471,
1014.69,1029.15,1043.05,1056.49,1069.57,1082.36,1094.88,1107.2,
1120.89,1131.4,1143.33,1155.15,1166.92,1178.61,1190.27,1201.92,
1213.55,1225.18,1236.81,1250.06,1260.16,1271.86,1283.64,1295.46,
1307.36,1319.3,1331.34,1343.45,1355.64,1367.93,1380.31,1392.77,
1405.35,1418.03,1430.83,1443.75,1457.17,1469.94,1483.22,1496.64,
1510.18,1523.86,1537.67,1551.64,1565.72,1579.99,1594.38,1608.92,
1623.63,1642.08,1653.51,1668.69,1684.03,1699.53,1715.21,1731.04,
1747.05,1763.23,1779.59,1796.12,1812.83,1829.72,1846.79,1864.04,
1881.49,1899.11,1916.93,1934.93,1953.13,1971.52,1990.12,2008.89};
if(_a1runwidth.empty()) {
vector<double> tmp1(a1widthin,a1widthin+200);
std::transform(tmp1.begin(), tmp1.end(),
back_inserter(_a1runwidth),
[](double x){return x*GeV;});
vector<double> tmp2(a1q2in,a1q2in+200);
_a1runq2.clear();
std::transform(tmp2.begin(), tmp2.end(),
back_inserter(_a1runq2),
[](double x){return x*GeV2;});
}
// zero parameters which will be calculated later to avoid problems
_mpi0=ZERO;
_mpic=ZERO;
_fact=ZERO;
_maxmass=ZERO;
_maxcalc=ZERO;
}
void ThreePionCLEOCurrent::doinit() {
WeakCurrent::doinit();
// parameters for the breit-wigners
_mpic = getParticleData(ParticleID::piplus)->mass();
_mpi0 = getParticleData(ParticleID::pi0) ->mass();
// couplings for the different modes
Complex ii(0.,1.);
_rhocoupP.resize(_rhomagP.size());
for(unsigned int ix=0;ix<_rhomagP.size();++ix)
_rhocoupP[ix]=_rhomagP[ix]*(cos(_rhophaseP[ix])+ii*sin(_rhophaseP[ix]));
_rhocoupD.resize(_rhomagD.size());
for(unsigned int ix=0;ix<_rhomagD.size();++ix)
_rhocoupD[ix]=_rhomagD[ix]*(cos(_rhophaseD[ix])+ii*sin(_rhophaseD[ix]));
_f0coup=_f0mag*(cos(_f0phase)+ii*sin(_f0phase));
_f2coup=_f2mag*(cos(_f2phase)+ii*sin(_f2phase));
_sigmacoup=_sigmamag*(cos(_sigmaphase)+ii*sin(_sigmaphase));
// overall coupling
_fact = 2.*sqrt(2.)/_fpi/3.;
// initialise the a_1 running width calculation
inita1Width(-1);
}
void ThreePionCLEOCurrent::persistentOutput(PersistentOStream & os) const {
os << ounit(_rhomass,GeV) << ounit(_rhowidth,GeV)
<< ounit(_f2mass,GeV) << ounit(_f2width,GeV)
<< ounit(_f0mass,GeV) << ounit(_f0width,GeV)
<< ounit(_sigmamass,GeV) << ounit(_sigmawidth,GeV)
<< ounit(_mpi0,GeV) << ounit(_mpic,GeV)
<< ounit(_fpi,GeV) << ounit(_fact,1/GeV)
<< _rhomagP << _rhophaseP
<< _rhocoupP << ounit(_rhomagD,1/GeV2) << _rhophaseD
<< ounit(_rhocoupD,1/GeV2) <<ounit(_f2mag,1/GeV2) << _f2phase << ounit(_f2coup ,1/GeV2)
<< _f0mag << _f0phase << _f0coup << _sigmamag << _sigmaphase << _sigmacoup
<< ounit(_a1mass,GeV) << ounit(_a1width,GeV) << ounit(_a1runwidth,GeV)
<< ounit(_a1runq2,GeV2) << _initializea1
<< ounit(_mKstar,GeV) << ounit(_mK,GeV) << _gammk << _a1opt
<< ounit(_maxmass,GeV) << ounit(_maxcalc,GeV) << _a1runinter;
}
void ThreePionCLEOCurrent::persistentInput(PersistentIStream & is, int) {
is >> iunit(_rhomass,GeV) >> iunit(_rhowidth,GeV)
>> iunit(_f2mass,GeV) >> iunit(_f2width,GeV)
>> iunit(_f0mass,GeV) >> iunit(_f0width,GeV)
>> iunit(_sigmamass,GeV) >> iunit(_sigmawidth,GeV)
>> iunit(_mpi0,GeV) >> iunit(_mpic,GeV)
>> iunit(_fpi,GeV) >> iunit(_fact,1/GeV)
>> _rhomagP >> _rhophaseP
>> _rhocoupP >> iunit(_rhomagD,1/GeV2) >> _rhophaseD >> iunit(_rhocoupD,1/GeV2)
>> iunit(_f2mag,1/GeV2) >> _f2phase >> iunit(_f2coup,1/GeV2)
>> _f0mag >> _f0phase >> _f0coup >> _sigmamag >> _sigmaphase >> _sigmacoup
>> iunit(_a1mass,GeV) >> iunit(_a1width,GeV) >> iunit(_a1runwidth,GeV)
>> iunit(_a1runq2,GeV2) >> _initializea1
>> iunit(_mKstar,GeV) >> iunit(_mK,GeV) >> _gammk >> _a1opt
>> iunit(_maxmass,GeV) >> iunit(_maxcalc,GeV) >> _a1runinter;
}
void ThreePionCLEOCurrent::Init() {
static ClassDocumentation<ThreePionCLEOCurrent> documentation
("The ThreePionCLEOCurrent class performs the decay of the"
" tau to three pions using the currents from CLEO",
"The decay of tau to three pions is modelled using the currents from "
"\\cite{Asner:1999kj}.",
" %\\cite{Asner:1999kj}\n"
"\\bibitem{Asner:1999kj}\n"
" D.~M.~Asner {\\it et al.} [CLEO Collaboration],\n"
" ``Hadronic structure in the decay tau- --> nu/tau pi- pi0 pi0 and the sign\n"
" %of the tau neutrino helicity,''\n"
" Phys.\\ Rev.\\ D {\\bf 61}, 012002 (2000)\n"
" [arXiv:hep-ex/9902022].\n"
" %%CITATION = PHRVA,D61,012002;%%\n"
);
static ParVector<ThreePionCLEOCurrent,Energy> interfacerhomass
("RhoMasses",
"The masses of the different rho resonnaces",
&ThreePionCLEOCurrent::_rhomass,
MeV, 0, ZERO, -10000*MeV, 10000*MeV, false, false, true);
static ParVector<ThreePionCLEOCurrent,Energy> interfacerhowidth
("RhoWidths",
"The widths of the different rho resonnaces",
&ThreePionCLEOCurrent::_rhowidth,
MeV, 0, ZERO, -10000*MeV, 10000*MeV, false, false, true);
static Parameter<ThreePionCLEOCurrent,Energy> interfacef_2Mass
("f_2Mass",
"The mass of the f_2 meson",
&ThreePionCLEOCurrent::_f2mass, GeV, 1.275*GeV, ZERO, 10.0*GeV,
false, false, true);
static Parameter<ThreePionCLEOCurrent,Energy> interfacef_2Width
("f_2Width",
"The width of the f_2 meson",
&ThreePionCLEOCurrent::_f2width, GeV, 0.185*GeV, ZERO, 1.0*GeV,
false, false, true);
static Parameter<ThreePionCLEOCurrent,Energy> interfacef_0Mass
("f_0Mass",
"The mass of the f_0 meson",
&ThreePionCLEOCurrent::_f0mass, GeV, 1.186*GeV, ZERO, 10.0*GeV,
false, false, true);
static Parameter<ThreePionCLEOCurrent,Energy> interfacef_0Width
("f_0Width",
"The width of the f_0 meson",
&ThreePionCLEOCurrent::_f0width, GeV, 0.350*GeV, ZERO, 1.0*GeV,
false, false, true);
static Parameter<ThreePionCLEOCurrent,Energy> interfacesigmaMass
("sigmaMass",
"The mass of the sigma meson",
&ThreePionCLEOCurrent::_sigmamass, GeV, 0.860*GeV, ZERO, 10.0*GeV,
false, false, true);
static Parameter<ThreePionCLEOCurrent,Energy> interfacesigmaWidth
("sigmaWidth",
"The width of the sigma meson",
&ThreePionCLEOCurrent::_sigmawidth, GeV, 0.880*GeV, ZERO, 2.0*GeV,
false, false, true);
static Parameter<ThreePionCLEOCurrent,Energy> interfacea1Mass
("a1Mass",
"The mass of the a_1 meson",
&ThreePionCLEOCurrent::_a1mass, GeV, 1.331*GeV, ZERO, 10.0*GeV,
false, false, true);
static Parameter<ThreePionCLEOCurrent,Energy> interfacea1Width
("a1Width",
"The width of the a_1 meson",
&ThreePionCLEOCurrent::_a1width, GeV, 0.814*GeV, ZERO, 10.0*GeV,
false, false, true);
static Parameter<ThreePionCLEOCurrent,Energy> interfaceKaonMass
("KaonMass",
"The mass of the kaon",
&ThreePionCLEOCurrent::_mK, GeV, 0.496*GeV, ZERO, 10.0*GeV,
false, false, true);
static Parameter<ThreePionCLEOCurrent,Energy> interfaceKStarMass
("KStarMass",
"The mass of the k* meson",
&ThreePionCLEOCurrent::_mKstar, GeV, 0.894*GeV, ZERO, 10.0*GeV,
false, false, true);
static Parameter<ThreePionCLEOCurrent,double> interfaceKaonCoupling
("KaonCoupling",
"The relative coupling for the kaon in the a_1 running width",
&ThreePionCLEOCurrent::_gammk, 3.32, 0.0, 10.0,
false, false, true);
static Parameter<ThreePionCLEOCurrent,Energy> interfaceFpi
("Fpi",
"The pion decay constant",
&ThreePionCLEOCurrent::_fpi, MeV, 130.7*MeV/sqrt(2.), ZERO, 500.0*MeV,
false, false, true);
static ParVector<ThreePionCLEOCurrent,double> interfacerhomagP
("RhoPWaveMagnitude",
"The magnitude of the couplings for the p-wave rho currents",
&ThreePionCLEOCurrent::_rhomagP,
0, 0, 0, 0, 10000, false, false, true);
static ParVector<ThreePionCLEOCurrent,double> interfacerhophaseP
("RhoPWavePhase",
"The phase of the couplings for the p-wave rho currents",
&ThreePionCLEOCurrent::_rhophaseP,
0, 0, 0, -Constants::twopi, Constants::twopi, false, false, true);
static ParVector<ThreePionCLEOCurrent,InvEnergy2> interfacerhomagD
("RhoDWaveMagnitude",
"The magnitude of the couplings for the d-wave rho currents",
&ThreePionCLEOCurrent::_rhomagD,
1/MeV2, 0, ZERO, ZERO, 10000/MeV2, false, false, true);
static ParVector<ThreePionCLEOCurrent,double> interfacerhophaseD
("RhoDWavePhase",
"The phase of the couplings for the d-wave rho currents",
&ThreePionCLEOCurrent::_rhophaseD,
0, 0, 0, -Constants::twopi, Constants::twopi, false, false, true);
static Parameter<ThreePionCLEOCurrent,double> interfacef0Phase
("f0Phase",
"The phase of the f_0 scalar current",
&ThreePionCLEOCurrent::_f0phase, 0.54*Constants::pi, -Constants::twopi, Constants::twopi,
false, false, true);
static Parameter<ThreePionCLEOCurrent,double> interfacef2Phase
("f2Phase",
"The phase of the f_2 tensor current",
&ThreePionCLEOCurrent::_f2phase, 0.56*Constants::pi,-Constants::twopi, Constants::twopi,
false, false, true);
static Parameter<ThreePionCLEOCurrent,double> interfacesigmaPhase
("sigmaPhase",
"The phase of the sigma scalar current",
&ThreePionCLEOCurrent::_sigmaphase, 0.23*Constants::pi, -Constants::twopi, Constants::twopi,
false, false, true);
static Parameter<ThreePionCLEOCurrent,double> interfacef0Magnitude
("f0Magnitude",
"The magnitude of the f_0 scalar current",
&ThreePionCLEOCurrent::_f0mag, 0.77, 0.0, 10,
false, false, true);
static Parameter<ThreePionCLEOCurrent,InvEnergy2> interfacef2Magnitude
("f2Magnitude",
"The magnitude of the f_2 tensor current",
&ThreePionCLEOCurrent::_f2mag, 1./GeV2, 0.71/GeV2, ZERO, 10./GeV2,
false, false, true);
static Parameter<ThreePionCLEOCurrent,double> interfacesigmaMagnitude
("sigmaMagnitude",
"The magnitude of the sigma scalar current",
&ThreePionCLEOCurrent::_sigmamag, 2.1, 0.0, 10,
false, false, true);
static ParVector<ThreePionCLEOCurrent,Energy> interfacea1RunningWidth
("a1RunningWidth",
"The values of the a_1 width for interpolation to giving the running width.",
&ThreePionCLEOCurrent::_a1runwidth,
MeV, 0, ZERO, ZERO, 10000000*MeV, false, false, true);
static ParVector<ThreePionCLEOCurrent,Energy2> interfacea1RunningQ2
("a1RunningQ2",
"The values of the q^2 for interpolation to giving the running width.",
&ThreePionCLEOCurrent::_a1runq2,
MeV2, 0, ZERO, ZERO, 10000000*MeV2, false, false, true);
static Switch<ThreePionCLEOCurrent,bool> interfaceInitializea1
("Initializea1",
"Initialise the calculation of the a_1 running width",
&ThreePionCLEOCurrent::_initializea1, false, false, false);
static SwitchOption interfaceInitializea1Initialization
(interfaceInitializea1,
"Yes",
"Initialize the calculation",
true);
static SwitchOption interfaceInitializea1NoInitialization
(interfaceInitializea1,
"No",
"Use the default values",
false);
static Switch<ThreePionCLEOCurrent,bool> interfacea1WidthOption
("a1WidthOption",
"Option for the treatment of the a1 width",
&ThreePionCLEOCurrent::_a1opt, true, false, false);
static SwitchOption interfacea1WidthOptionLocal
(interfacea1WidthOption,
"Local",
"Use a calculation of the running width based on the parameters as"
" interpolation table.",
true);
static SwitchOption interfacea1WidthOptionParam
(interfacea1WidthOption,
"Kuhn",
"Use the parameterization of Kuhn and Santamaria for default parameters."
" This should only be used for testing vs TAUOLA",
false);
}
// initialisation of the a_1 width
// (iopt=-1 initialises, iopt=0 starts the interpolation)
void ThreePionCLEOCurrent::inita1Width(int iopt) {
if(iopt==-1) {
_maxcalc=_maxmass;
if(!_initializea1||_maxmass==ZERO) return;
// parameters for the table of values
Energy2 step=sqr(_maxmass)/200.;
// function to be integrated to give the matrix element
// integrator to perform the integral
vector<double> inweights;inweights.push_back(0.5);inweights.push_back(0.5);
vector<int> intype;intype.push_back(2);intype.push_back(3);
Energy mrho=getParticleData(ParticleID::rhoplus)->mass();
Energy wrho=getParticleData(ParticleID::rhoplus)->width();
vector<Energy> inmass;inmass.push_back(mrho);inmass.push_back(mrho);
vector<Energy> inwidth;inwidth.push_back(wrho);inwidth.push_back(wrho);
vector<double> inpow(2,0.0);
ThreeBodyAllOnCalculator<ThreePionCLEOCurrent>
widthgenN(inweights,intype,inmass,inwidth,inpow,*this,0,_mpi0,_mpi0,_mpic);
ThreeBodyAllOnCalculator<ThreePionCLEOCurrent>
widthgenC(inweights,intype,inmass,inwidth,inpow,*this,1,_mpic,_mpic,_mpic);
// normalisation constant to give physical width if on shell
double a1const = _a1width/(widthgenN.partialWidth(sqr(_a1mass))+
widthgenC.partialWidth(sqr(_a1mass)));
// loop to give the values
_a1runq2.clear();_a1runwidth.clear();
for(Energy2 moff2=ZERO; moff2<=sqr(_maxmass); moff2+=step) {
Energy moff=sqrt(moff2);
_a1runq2.push_back(moff2);
Energy charged=a1const*widthgenC.partialWidth(moff2);
Energy neutral=a1const*widthgenN.partialWidth(moff2);
Energy kaon = moff<=_mK+_mKstar ? ZERO : 2.870*_gammk*_gammk/8./Constants::pi*
Kinematics::pstarTwoBodyDecay(moff,_mK,_mKstar)/moff2*GeV2;
Energy total = charged + neutral + kaon;
_a1runwidth.push_back(total);
}
}
// set up the interpolator
else if(iopt==0) {
_a1runinter = make_InterpolatorPtr(_a1runwidth,_a1runq2,3);
}
}
void ThreePionCLEOCurrent::CLEOFormFactor(int imode,int ichan,
Energy2 q2,Energy2 s1, Energy2 s2, Energy2 s3,
Complex & F1, Complex & F2,
Complex & F3) const {
useMe();
double fact=1.;
if(imode<=1) {
// identical particle factors
fact = 1./sqrt(6.);
// compute the breit wigners we need
Complex sigbws1 = Resonance::BreitWignerSWave(s1,_sigmamass,_sigmawidth,_mpi0,_mpi0);
Complex sigbws2 = Resonance::BreitWignerSWave(s2,_sigmamass,_sigmawidth,_mpi0,_mpi0);
Complex sigbws3 = Resonance::BreitWignerSWave(s3,_sigmamass,_sigmawidth,_mpi0,_mpi0);
Complex f0bws1 = Resonance::BreitWignerSWave(s1, _f0mass, _f0width,_mpi0,_mpi0);
Complex f0bws2 = Resonance::BreitWignerSWave(s2, _f0mass, _f0width,_mpi0,_mpi0);
Complex f0bws3 = Resonance::BreitWignerSWave(s3, _f0mass, _f0width,_mpi0,_mpi0);
Complex f2bws1 = Resonance::BreitWignerDWave(s1, _f2mass, _f2width,_mpi0,_mpi0);
Complex f2bws2 = Resonance::BreitWignerDWave(s2, _f2mass, _f2width,_mpi0,_mpi0);
Complex f2bws3 = Resonance::BreitWignerDWave(s3, _f2mass, _f2width,_mpi0,_mpi0);
if(ichan<0) {
// the scalar terms
F1=2./3.*(_sigmacoup*sigbws3+_f0coup*f0bws3)
-2./3.*(_sigmacoup*sigbws2+_f0coup*f0bws2);
F2=2./3.*(_sigmacoup*sigbws3+_f0coup*f0bws3)
-2./3.*(_sigmacoup*sigbws1+_f0coup*f0bws1);
F3=-2./3.*(_sigmacoup*sigbws1+_f0coup*f0bws1)
+2./3.*(_sigmacoup*sigbws2+_f0coup*f0bws2);
// the tensor terms
complex<Energy2> Dfact1 = 1./18.*(4.*_mpi0*_mpi0-s1)*(q2+s1-_mpi0*_mpi0)/s1*f2bws1;
complex<Energy2> Dfact2 = 1./18.*(4.*_mpi0*_mpi0-s2)*(q2+s2-_mpi0*_mpi0)/s2*f2bws2;
complex<Energy2> Dfact3 = 1./18.*(4.*_mpi0*_mpi0-s3)*(q2-_mpi0*_mpi0+s3)/s3*f2bws3;
- F1+=_f2coup*( 0.5*(s3-s2)*f2bws1-Dfact2+Dfact3);
- F2+=_f2coup*( 0.5*(s3-s1)*f2bws2-Dfact1+Dfact3);
- F3+=_f2coup*(-0.5*(s1-s2)*f2bws3-Dfact1+Dfact2);
+ F1+=Complex(_f2coup*( 0.5*(s3-s2)*f2bws1-Dfact2+Dfact3));
+ F2+=Complex(_f2coup*( 0.5*(s3-s1)*f2bws2-Dfact1+Dfact3));
+ F3+=Complex(_f2coup*(-0.5*(s1-s2)*f2bws3-Dfact1+Dfact2));
}
else if(ichan==0) {
F2=-2./3.*_sigmacoup*sigbws1;
F3=-2./3.*_sigmacoup*sigbws1;
}
else if(ichan==1) {
F1=-2./3.*_sigmacoup*sigbws2;
F3=+2./3.*_sigmacoup*sigbws2;
}
else if(ichan==2) {
F1= 2./3.*_sigmacoup*sigbws3;
F2= 2./3.*_sigmacoup*sigbws3;
}
else if(ichan==3) {
complex<Energy2> Dfact1 = 1./18.*(4.*_mpi0*_mpi0-s1)*(q2+s1-_mpi0*_mpi0)/s1*f2bws1;
- F1+=_f2coup*0.5*(s3-s2)*f2bws1;
- F2-=_f2coup*Dfact1;
- F3-=_f2coup*Dfact1;
+ F1+=Complex(_f2coup*0.5*(s3-s2)*f2bws1);
+ F2-=Complex(_f2coup*Dfact1);
+ F3-=Complex(_f2coup*Dfact1);
}
else if(ichan==4) {
complex<Energy2> Dfact2 = 1./18.*(4.*_mpi0*_mpi0-s2)*(q2+s2-_mpi0*_mpi0)/s2*f2bws2;
- F2+=_f2coup*0.5*(s3-s1)*f2bws2;
- F1-=_f2coup*Dfact2;
- F3+=_f2coup*Dfact2;
+ F2+=Complex(_f2coup*0.5*(s3-s1)*f2bws2);
+ F1-=Complex(_f2coup*Dfact2);
+ F3+=Complex(_f2coup*Dfact2);
}
else if(ichan==5) {
complex<Energy2> Dfact3 = 1./18.*(4.*_mpi0*_mpi0-s3)*(q2-_mpi0*_mpi0+s3)/s3*f2bws3;
- F3+=-_f2coup*0.5*(s1-s2)*f2bws3;
- F1+=_f2coup*Dfact3;
- F2+=_f2coup*Dfact3;
+ F3+=Complex(-_f2coup*0.5*(s1-s2)*f2bws3);
+ F1+=Complex(_f2coup*Dfact3);
+ F2+=Complex(_f2coup*Dfact3);
}
else if(ichan==6) {
F2=-2./3.*_f0coup*f0bws1;
F3=-2./3.*_f0coup*f0bws1;
}
else if(ichan==7) {
F1=-2./3.*_f0coup*f0bws2;
F3=+2./3.*_f0coup*f0bws2;
}
else if(ichan==8) {
F1= 2./3.*_f0coup*f0bws3;
F2= 2./3.*_f0coup*f0bws3;
}
}
// calculate the pi0 pi0 pi+ factor
else if(imode==2) {
// identical particle factors
fact = 1./sqrt(2.);
// compute the breit wigners we need
Complex rhos1bw[3],rhos2bw[3];
for(unsigned int ix=0,N=max(_rhocoupP.size(),_rhocoupD.size());ix<N;++ix) {
rhos1bw[ix] = Resonance::BreitWignerPWave(s1,_rhomass[ix], _rhowidth[ix],_mpic,_mpi0);
rhos2bw[ix] = Resonance::BreitWignerPWave(s2,_rhomass[ix], _rhowidth[ix],_mpic,_mpi0);
}
Complex f0bw = Resonance::BreitWignerSWave(s3, _f0mass, _f0width,_mpi0,_mpi0);
Complex sigbw = Resonance::BreitWignerSWave(s3,_sigmamass,_sigmawidth,_mpi0,_mpi0);
Complex f2bw = Resonance::BreitWignerDWave(s3, _f2mass, _f2width,_mpi0,_mpi0);
if(ichan<0) {
// the p-wave rho terms
for(unsigned int ix=0;ix<_rhocoupP.size();++ix) {
F1+=_rhocoupP[ix]*rhos1bw[ix];
F2+=_rhocoupP[ix]*rhos2bw[ix];
}
// the D-wave rho terms
Energy2 Dfact1=-1./3.*((s3-_mpic*_mpic)-(s1-_mpi0*_mpi0));
Energy2 Dfact2=-1./3.*((s3-_mpic*_mpic)-(s2-_mpi0*_mpi0));
for(unsigned int ix=0;ix<_rhocoupD.size();++ix) {
- F1+=Dfact1*_rhocoupD[ix]*rhos2bw[ix];
- F2+=Dfact2*_rhocoupD[ix]*rhos1bw[ix];
- F3+=_rhocoupD[ix]*(Dfact2*rhos1bw[ix]-Dfact1*rhos2bw[ix]);
+ F1+=Complex(Dfact1*_rhocoupD[ix]*rhos2bw[ix]);
+ F2+=Complex(Dfact2*_rhocoupD[ix]*rhos1bw[ix]);
+ F3+=Complex(_rhocoupD[ix]*(Dfact2*rhos1bw[ix]-Dfact1*rhos2bw[ix]));
}
// the scalar terms
Complex scalar=2./3.*(_sigmacoup*sigbw+_f0coup*f0bw);
F1+=scalar;F2+=scalar;
// the tensor terms
Complex Dfact3=1./18./s3*_f2coup*(q2-_mpic*_mpic+s3)*(4.*_mpi0*_mpi0-s3)*f2bw;
F1+=Dfact3;F2+=Dfact3;
- F3-=0.5*_f2coup*(s1-s2)*f2bw;
+ F3-=Complex(0.5*_f2coup*(s1-s2)*f2bw);
}
else if(ichan%2==0&&ichan<=4) {
unsigned int ires=ichan/2;
if(ires<_rhocoupP.size()){F1+=_rhocoupP[ires]*rhos1bw[ires];}
Energy2 Dfact2=-1./3.*((s3-_mpic*_mpic)-(s2-_mpi0*_mpi0));
if(ires<_rhocoupD.size()) {
- F2+=Dfact2*_rhocoupD[ires]*rhos1bw[ires];
- F3+=_rhocoupD[ires]*Dfact2*rhos1bw[ires];
+ F2+=Complex(Dfact2*_rhocoupD[ires]*rhos1bw[ires]);
+ F3+=Complex(_rhocoupD[ires]*Dfact2*rhos1bw[ires]);
}
}
else if(ichan%2==1&&ichan<=5) {
unsigned int ires=(ichan-1)/2;
if(ires<_rhocoupP.size()){F2+=_rhocoupP[ires]*rhos2bw[ires];}
Energy2 Dfact1=-1./3.*((s3-_mpic*_mpic)-(s1-_mpi0*_mpi0));
if(ires<_rhocoupD.size()) {
- F1+=Dfact1*_rhocoupD[ires]*rhos2bw[ires];
- F3-=_rhocoupD[ires]*Dfact1*rhos2bw[ires];
+ F1+=Complex(Dfact1*_rhocoupD[ires]*rhos2bw[ires]);
+ F3-=Complex(_rhocoupD[ires]*Dfact1*rhos2bw[ires]);
}
}
else if(ichan==6) {
F1+=2./3.*_sigmacoup*sigbw;
F2+=2./3.*_sigmacoup*sigbw;
}
else if(ichan==7) {
Complex Dfact3=1./18./s3*_f2coup*(q2-_mpic*_mpic+s3)*(4.*_mpi0*_mpi0-s3)*f2bw;
- F1+=Dfact3;F2+=Dfact3;
- F3-=0.5*_f2coup*(s1-s2)*f2bw;
+ F1+=Dfact3;
+ F2+=Dfact3;
+ F3-=Complex(0.5*_f2coup*(s1-s2)*f2bw);
}
else if(ichan==8) {
F1+=2./3.*_f0coup*f0bw;
F2+=2./3.*_f0coup*f0bw;
}
}
// a_1^0 ->pi+pi-pi0
else if(imode==3||imode==4) {
// compute the breit wigners we need
Complex rhos1bw[3],rhos2bw[3];
for(unsigned int ix=0,N=max(_rhocoupP.size(),_rhocoupD.size());ix<N;++ix) {
rhos1bw[ix] = Resonance::BreitWignerPWave(s1,_rhomass[ix], _rhowidth[ix],_mpic,_mpi0);
rhos2bw[ix] = Resonance::BreitWignerPWave(s2,_rhomass[ix], _rhowidth[ix],_mpic,_mpi0);
}
Complex f0bw = Resonance::BreitWignerSWave(s3, _f0mass, _f0width,_mpic,_mpic);
Complex sigbw = Resonance::BreitWignerSWave(s3,_sigmamass,_sigmawidth,_mpic,_mpic);
Complex f2bw = Resonance::BreitWignerDWave(s3, _f2mass, _f2width,_mpic,_mpic);
if(ichan<0) {
// the p-wave rho terms
for(unsigned int ix=0;ix<_rhocoupP.size();++ix) {
F1+=_rhocoupP[ix]*rhos1bw[ix];
F2+=_rhocoupP[ix]*rhos2bw[ix];
}
// the D-wave rho terms
Energy2 Dfact1=-1./3.*(s3-_mpi0*_mpi0-s1+_mpic*_mpic);
Energy2 Dfact2=-1./3.*(s3-_mpi0*_mpi0-s2+_mpic*_mpic);
for(unsigned int ix=0;ix<_rhocoupD.size();++ix) {
- F1+=Dfact1*_rhocoupD[ix]*rhos2bw[ix];
- F2+=Dfact2*_rhocoupD[ix]*rhos1bw[ix];
- F3+=_rhocoupD[ix]*(Dfact2*rhos1bw[ix]-Dfact1*rhos2bw[ix]);
+ F1+=Complex(Dfact1*_rhocoupD[ix]*rhos2bw[ix]);
+ F2+=Complex(Dfact2*_rhocoupD[ix]*rhos1bw[ix]);
+ F3+=Complex(_rhocoupD[ix]*(Dfact2*rhos1bw[ix]-Dfact1*rhos2bw[ix]));
}
// the scalar terms
Complex scalar=2./3.*(_sigmacoup*sigbw+_f0coup*f0bw);
F1+=scalar;
F2+=scalar;
// the tensor terms
Complex Dfact3=1./18./s3*_f2coup*(q2-_mpi0*_mpi0+s3)*(4.*_mpic*_mpic-s3)*f2bw;
F1+=Dfact3;
F2+=Dfact3;
- F3-=0.5*_f2coup*(s1-s2)*f2bw;
+ F3-=Complex(0.5*_f2coup*(s1-s2)*f2bw);
}
else if(ichan%2==0&&ichan<=4) {
unsigned int ires=ichan/2;
if(ires<_rhocoupP.size()) F1+=_rhocoupP[ires]*rhos1bw[ires];
Energy2 Dfact2=-1./3.*(s3-_mpi0*_mpi0-s2+_mpic*_mpic);
if(ires<_rhocoupD.size()) {
- F2+=Dfact2*_rhocoupD[ires]*rhos1bw[ires];
- F3+=_rhocoupD[ires]*Dfact2*rhos1bw[ires];
+ F2+=Complex(Dfact2*_rhocoupD[ires]*rhos1bw[ires]);
+ F3+=Complex(_rhocoupD[ires]*Dfact2*rhos1bw[ires]);
}
}
else if(ichan%2==1&&ichan<=5) {
unsigned int ires=(ichan-1)/2;
if(ires<_rhocoupP.size()) F2+=_rhocoupP[ires]*rhos2bw[ires];
Energy2 Dfact1=-1./3.*(s3-_mpi0*_mpi0-s1+_mpic*_mpic);
if(ires<_rhocoupD.size()) {
- F1+=Dfact1*_rhocoupD[ires]*rhos2bw[ires];
- F3-=_rhocoupD[ires]*-Dfact1*rhos2bw[ires];
+ F1+=Complex(Dfact1*_rhocoupD[ires]*rhos2bw[ires]);
+ F3-=Complex(_rhocoupD[ires]*-Dfact1*rhos2bw[ires]);
}
}
else if(ichan==6) {
F1+=2./3.*_sigmacoup*sigbw;
F2+=2./3.*_sigmacoup*sigbw;
}
else if(ichan==7) {
Complex Dfact3=1./18./s3*_f2coup*(q2-_mpi0*_mpi0+s3)*(4.*_mpic*_mpic-s3)*f2bw;
F1+=Dfact3;
F2+=Dfact3;
- F3-=0.5*_f2coup*(s1-s2)*f2bw;
+ F3-=Complex(0.5*_f2coup*(s1-s2)*f2bw);
}
else if(ichan==8) {
F1+=2./3.*_f0coup*f0bw;
F2+=2./3.*_f0coup*f0bw;
}
}
else if(imode==5) {
// identical particle factors
fact = 1./sqrt(2.);
// compute the breit wigners we need
Complex rhos1bw[3],rhos2bw[3];
for(unsigned int ix=0,N=max(_rhocoupP.size(),_rhocoupD.size());ix<N;++ix) {
rhos1bw[ix] = Resonance::BreitWignerPWave(s1,_rhomass[ix], _rhowidth[ix],_mpic,_mpic);
rhos2bw[ix] = Resonance::BreitWignerPWave(s2,_rhomass[ix], _rhowidth[ix],_mpic,_mpic);
}
Complex f0bws1 = Resonance::BreitWignerSWave(s1, _f0mass, _f0width,_mpic,_mpic);
Complex sigbws1 = Resonance::BreitWignerSWave(s1,_sigmamass,_sigmawidth,_mpic,_mpic);
Complex f2bws1 = Resonance::BreitWignerDWave(s1, _f2mass, _f2width,_mpic,_mpic);
Complex f0bws2 = Resonance::BreitWignerSWave(s2, _f0mass, _f0width,_mpic,_mpic);
Complex sigbws2 = Resonance::BreitWignerSWave(s2,_sigmamass,_sigmawidth,_mpic,_mpic);
Complex f2bws2 = Resonance::BreitWignerDWave(s2, _f2mass, _f2width,_mpic,_mpic);
if(ichan<0) {
// the p-wave rho terms
for(unsigned int ix=0;ix<_rhocoupP.size();++ix) {
F1-=_rhocoupP[ix]*rhos1bw[ix];
F2-=_rhocoupP[ix]*rhos2bw[ix];
}
// the D-wave rho terms
Energy2 Dfact1=1./3.*(s1-s3);
Energy2 Dfact2=1./3.*(s2-s3);
for(unsigned int ix=0;ix<_rhocoupD.size();++ix) {
F1-=Complex(Dfact1*_rhocoupD[ix]*rhos2bw[ix]);
F2-=Complex(Dfact2*_rhocoupD[ix]*rhos1bw[ix]);
F3-=Complex(_rhocoupD[ix]*(Dfact2*rhos1bw[ix]-Dfact1*rhos2bw[ix]));
}
// the scalar terms
F1-=2./3.*(_sigmacoup*sigbws2+_f0coup*f0bws2);
F2-=2./3.*(_sigmacoup*sigbws1+_f0coup*f0bws1);
F3+=-2./3.*(_sigmacoup*sigbws1+_f0coup*f0bws1)
+2./3.*(_sigmacoup*sigbws2+_f0coup*f0bws2);
// the tensor terms
complex<Energy2> sfact1 = 1./18.*(4.*_mpic*_mpic-s1)*(q2+s1-_mpic*_mpic)/s1*f2bws1;
complex<Energy2> sfact2 = 1./18.*(4.*_mpic*_mpic-s2)*(q2+s2-_mpic*_mpic)/s2*f2bws2;
F1+=Complex(_f2coup*(0.5*(s3-s2)*f2bws1-sfact2));
F2+=Complex(_f2coup*(0.5*(s3-s1)*f2bws2-sfact1));
F3+=Complex(_f2coup*(-sfact1+sfact2));
}
else if(ichan%2==0&&ichan<=4) {
unsigned int ires=ichan/2;
Energy2 Dfact2=1./3.*(s2-s3);
if(ires<_rhocoupP.size()) F1-=_rhocoupP[ires]*rhos1bw[ires];
if(ires<_rhocoupD.size()) {
F2-=Complex(Dfact2*_rhocoupD[ires]*rhos1bw[ires]);
F3-=Complex(_rhocoupD[ires]*Dfact2*rhos1bw[ires]);
}
}
else if(ichan%2==1&&ichan<=5) {
unsigned int ires=(ichan-1)/2;
Energy2 Dfact1=1./3.*(s1-s3);
if(ires<_rhocoupP.size()) {
F2-=_rhocoupP[ires]*rhos2bw[ires];
}
if(ires<_rhocoupD.size()) {
F1-=Complex(Dfact1*_rhocoupD[ires]*rhos2bw[ires]);
F3+=Complex(_rhocoupD[ires]*Dfact1*rhos2bw[ires]);
}
}
else if(ichan==6) {
F2-=2./3.*_sigmacoup*sigbws1;
F3-=2./3.*_sigmacoup*sigbws1;
}
else if(ichan==7) {
F1-=2./3.*_sigmacoup*sigbws2;
F3+=2./3.*_sigmacoup*sigbws2;
}
else if(ichan==8) {
complex<Energy2> sfact1 = 1./18.*(4.*_mpic*_mpic-s1)*(q2+s1-_mpic*_mpic)/s1*f2bws1;
F1+=Complex(_f2coup*0.5*(s3-s2)*f2bws1);
F2-=Complex(_f2coup*sfact1);
F3-=Complex(_f2coup*sfact1);
}
else if(ichan==9) {
complex<Energy2> sfact2 = 1./18.*(4.*_mpic*_mpic-s2)*(q2+s2-_mpic*_mpic)/s2*f2bws2;
F1-=Complex(_f2coup*sfact2);
F2+=Complex(_f2coup*0.5*(s3-s1)*f2bws2);
F3+=Complex(_f2coup*sfact2);
}
else if(ichan==10) {
F2-=2./3.*_f0coup*f0bws1;
F3-=2./3.*_f0coup*f0bws1;
}
else if(ichan==11) {
F1-=2./3.*_f0coup*f0bws2;
F3+=2./3.*_f0coup*f0bws2;
}
}
else {
throw Exception() << "ThreePionCLEOCurrent Unknown Decay" << imode
<< Exception::abortnow;
}
F1 *= fact;
F2 *= fact;
F3 *= fact;
}
// complete the construction of the decay mode for integration
bool ThreePionCLEOCurrent::createMode(int icharge, tcPDPtr resonance,
FlavourInfo flavour,
unsigned int imode,PhaseSpaceModePtr mode,
unsigned int iloc,int ires,
PhaseSpaceChannel phase, Energy upp ) {
// check the charge and resonance
if(imode<=1||imode==3||imode==4) {
if(icharge!=0) return false;
if(resonance && resonance->id()!=ParticleID::a_10) return false;
}
else if(imode==2||imode==5) {
if(abs(icharge)!=3) return false;
if(resonance && abs(resonance->id())!=ParticleID::a_1plus) return false;
}
// check the total isospin
if(flavour.I!=IsoSpin::IUnknown) {
if(flavour.I!=IsoSpin::IOne) return false;
}
// check I_3
if(flavour.I3!=IsoSpin::I3Unknown) {
switch(flavour.I3) {
case IsoSpin::I3Zero:
if(imode==2||imode==5) return false;
break;
case IsoSpin::I3One:
if((imode!=2&&imode!=5) || icharge ==-3) return false;
break;
case IsoSpin::I3MinusOne:
if((imode!=2&&imode!=5) || icharge == 3) return false;
break;
default:
return false;
}
}
if(flavour.strange != Strangeness::Unknown and flavour.strange != Strangeness::Zero) return false;
if(flavour.charm != Charm::Unknown and flavour.charm != Charm::Zero ) return false;
if(flavour.bottom != Beauty::Unknown and flavour.bottom !=Beauty::Zero ) return false;
// get the particles and check the masses
int iq(0),ia(0);
tPDVector extpart=particles(1,imode,iq,ia);
Energy min(ZERO);
for(unsigned int ix=0;ix<extpart.size();++ix) min+=extpart[ix]->massMin();
if(min>upp) return false;
_maxmass=max(_maxmass,upp);
// pointers to the particles we need
tPDPtr a1m = getParticleData(ParticleID::a_1minus);
tPDPtr a10 = getParticleData(ParticleID::a_10);
// the different rho resonances
tPDPtr rhom[3] = {getParticleData(-213),getParticleData(-100213),getParticleData(-30213)};
if(icharge==3) {
for(unsigned int ix=0;ix<3;++ix) rhom[ix]=rhom[ix]->CC();
a1m = a1m->CC();
}
tPDPtr rho0[3] = {getParticleData(113),getParticleData(100113),getParticleData(30113)};
// the sigma
tPDPtr sigma = getParticleData(9000221);
// the f_2
tPDPtr f2=getParticleData(225);
// the f_0
tPDPtr f0=getParticleData(10221);
assert(f2 && f0 && sigma);
// a0 -> pi0 pi0 pi0
if(imode<=1) {
for(unsigned int ix=0;ix<3;++ix) {
tPDPtr temp;
if(ix==0) temp = sigma;
else if(ix==1) temp = f2;
else if(ix==2) temp = f0;
mode->addChannel((PhaseSpaceChannel(phase),ires,a10,ires+1,temp,ires+1,iloc+1,
ires+2,iloc+2,ires+2,iloc+3));
mode->addChannel((PhaseSpaceChannel(phase),ires,a10,ires+1,temp,ires+1,iloc+2,
ires+2,iloc+1,ires+2,iloc+3));
mode->addChannel((PhaseSpaceChannel(phase),ires,a10,ires+1,temp,ires+1,iloc+3,
ires+2,iloc+1,ires+2,iloc+2));
}
}
// decay mode a_1- -> pi0 pi0 pi-
else if(imode==2) {
for(unsigned int ix=0;ix<3;++ix) {
// first rho+ channel
mode->addChannel((PhaseSpaceChannel(phase),ires,a1m,ires+1,rhom[ix],ires+1,iloc+1,
ires+2,iloc+2,ires+2,iloc+3));
// second rho+ channel
mode->addChannel((PhaseSpaceChannel(phase),ires,a1m,ires+1,rhom[ix],ires+1,iloc+2,
ires+2,iloc+1,ires+2,iloc+3));
}
// I=0 channels
for(unsigned int iy=0;iy<3;++iy) {
tPDPtr temp;
if(iy==0) temp = sigma;
else if(iy==1) temp = f2;
else if(iy==2) temp = f0;
mode->addChannel((PhaseSpaceChannel(phase),ires,a1m,ires+1,temp,ires+1,iloc+3,
ires+2,iloc+1,ires+2,iloc+2));
}
}
// decay mode a_10 -> pi+ pi- pi0
else if(imode==3||imode==4) {
// rho modes
for(unsigned int ix=0;ix<3;++ix) {
// first rho channel
mode->addChannel((PhaseSpaceChannel(phase),ires,a10,ires+1,rhom[ix],ires+1,iloc+1,
ires+2,iloc+2,ires+2,iloc+3));
// second channel
mode->addChannel((PhaseSpaceChannel(phase),ires,a10,ires+1,rhom[ix],ires+1,iloc+2,
ires+2,iloc+1,ires+2,iloc+3));
}
// I=0 channels
for(unsigned int iy=0;iy<3;++iy) {
tPDPtr temp;
if(iy==0) temp = sigma;
else if(iy==1) temp = f2;
else if(iy==2) temp = f0;
mode->addChannel((PhaseSpaceChannel(phase),ires,a10,ires+1,temp,ires+1,iloc+3,
ires+2,iloc+1,ires+2,iloc+2));
}
}
else if(imode==5) {
for(unsigned int ix=0;ix<3;++ix) {
// the neutral rho channels
// first channel
mode->addChannel((PhaseSpaceChannel(phase),ires,a1m,ires+1,rho0[ix],ires+1,iloc+1,
ires+2,iloc+2,ires+2,iloc+3));
// interchanged channel
mode->addChannel((PhaseSpaceChannel(phase),ires,a1m,ires+1,rho0[ix],ires+1,iloc+2,
ires+2,iloc+1,ires+2,iloc+3));
}
for(unsigned int iy=0;iy<3;++iy) {
tPDPtr temp;
if(iy==0) temp = sigma;
else if(iy==1) temp = f2;
else if(iy==2) temp = f0;
// first channel
mode->addChannel((PhaseSpaceChannel(phase),ires,a1m,ires+1,temp,ires+1,iloc+1,
ires+2,iloc+2,ires+2,iloc+3));
// interchanged channel
mode->addChannel((PhaseSpaceChannel(phase),ires,a1m,ires+1,temp,ires+1,iloc+2,
ires+2,iloc+1,ires+2,iloc+3));
}
}
// reset the integration parameters
for(unsigned int iy=0;iy<_rhomass.size();++iy) {
mode->resetIntermediate(rho0[iy],_rhomass[iy],_rhowidth[iy]);
mode->resetIntermediate(rhom[iy],_rhomass[iy],_rhowidth[iy]);
}
mode->resetIntermediate(sigma,_sigmamass,_sigmawidth);
mode->resetIntermediate(f2,_f2mass,_f2width);
mode->resetIntermediate(f0,_f0mass,_f0width);
mode->resetIntermediate(a10,_a1mass,_a1width);
mode->resetIntermediate(a10,_a1mass,_a1width);
return true;
}
void ThreePionCLEOCurrent::dataBaseOutput(ofstream & output,bool header,
bool create) const {
if(header){output << "update decayers set parameters=\"";}
if(create) {
output << "create Herwig::ThreePionCLEOCurrent " << name()
<< " HwWeakCurrents.so\n";
}
for(unsigned int ix=0;ix<_rhomass.size();++ix) {
if(ix<2) {
output << "newdef " << name() << ":RhoMasses " << ix
<< " " << _rhomass[ix]/MeV << "\n";
}
else {
output << "insert " << name() << ":RhoMasses " << ix
<< " " << _rhomass[ix]/MeV << "\n";
}
}
for(unsigned int ix=0;ix<_rhowidth.size();++ix) {
if(ix<2) {
output << "newdef " << name() << ":RhoWidths " << ix
<< " " << _rhowidth[ix]/MeV << "\n";
}
else {
output << "insert " << name() << ":RhoWidths " << ix
<< " " << _rhowidth[ix]/MeV << "\n";
}
}
output << "newdef " << name() << ":f_2Mass " << _f2mass/GeV << "\n";
output << "newdef " << name() << ":f_2Width " << _f2width/GeV << "\n";
output << "newdef " << name() << ":f_0Mass " << _f0mass/GeV << "\n";
output << "newdef " << name() << ":f_0Width " << _f0width/GeV << "\n";
output << "newdef " << name() << ":sigmaMass " << _sigmamass/GeV << "\n";
output << "newdef " << name() << ":sigmaWidth " << _sigmawidth/GeV << "\n";
output << "newdef " << name() << ":a1Mass " << _a1mass/GeV << "\n";
output << "newdef " << name() << ":a1Width " <<_a1width /GeV << "\n";
output << "newdef " << name() << ":KaonMass " << _mK/GeV << "\n";
output << "newdef " << name() << ":KStarMass " << _mKstar/GeV << "\n";
output << "newdef " << name() << ":KaonCoupling " << _gammk << "\n";
output << "newdef " << name() << ":Fpi " << _fpi/MeV << "\n";
output << "newdef " << name() << ":a1WidthOption " << _a1opt << "\n";
for(unsigned int ix=0;ix<_rhomagP.size();++ix) {
if(ix<2) {
output << "newdef " << name() << ":RhoPWaveMagnitude " << ix
<< " " << _rhomagP[ix] << "\n";
}
else {
output << "insert " << name() << ":RhoPWaveMagnitude " << ix
<< " " << _rhomagP[ix] << "\n";
}
}
for(unsigned int ix=0;ix<_rhophaseP.size();++ix) {
if(ix<2) {
output << "newdef " << name() << ":RhoPWavePhase " << ix
<< " " << _rhophaseP[ix] << "\n";
}
else {
output << "insert " << name() << ":RhoPWavePhase " << ix
<< " " << _rhophaseP[ix] << "\n";
}
}
for(unsigned int ix=0;ix<_rhomagD.size();++ix) {
if(ix<2) {
output << "newdef " << name() << ":RhoDWaveMagnitude " << ix
<< " " << _rhomagD[ix]*MeV2 << "\n";
}
else {
output << "insert " << name() << ":RhoDWaveMagnitude " << ix
<< " " << _rhomagD[ix]*MeV2 << "\n";
}
}
for(unsigned int ix=0;ix<_rhophaseD.size();++ix) {
if(ix<2) {
output << "newdef " << name() << ":RhoDWavePhase " << ix
<< " " << _rhophaseD[ix] << "\n";
}
else {
output << "insert " << name() << ":RhoDWavePhase " << ix
<< " " << _rhophaseD[ix] << "\n";
}
}
output << "newdef " << name() << ":f0Phase " << _f0phase << "\n";
output << "newdef " << name() << ":f2Phase " <<_f2phase << "\n";
output << "newdef " << name() << ":sigmaPhase " <<_sigmaphase << "\n";
output << "newdef " << name() << ":f0Magnitude " << _f0mag << "\n";
output << "newdef " << name() << ":f2Magnitude " << _f2mag*GeV2 << "\n";
output << "newdef " << name() << ":sigmaMagnitude " <<_sigmamag << "\n";
output << "newdef " << name() << ":Initializea1 " <<_initializea1 << "\n";
for(unsigned int ix=0;ix<_a1runwidth.size();++ix) {
if(ix<200) {
output << "newdef " << name() << ":a1RunningWidth " << ix
<< " " << _a1runwidth[ix]/MeV << "\n";
}
else {
output << "insert " << name() << ":a1RunningWidth " << ix
<< " " << _a1runwidth[ix]/MeV << "\n";
}
}
for(unsigned int ix=0;ix<_a1runq2.size();++ix) {
if(ix<200) {
output << "newdef " << name() << ":a1RunningQ2 " << ix
<< " " << _a1runq2[ix]/MeV2 << "\n";
}
else {
output << "insert " << name() << ":a1RunningQ2 " << ix
<< " " << _a1runq2[ix]/MeV2 << "\n";
}
}
WeakCurrent::dataBaseOutput(output,false,false);
if(header) output << "\n\" where BINARY ThePEGName=\""
<< fullName() << "\";" << endl;
}
void ThreePionCLEOCurrent::doinitrun() {
// set up the running a_1 width
inita1Width(0);
WeakCurrent::doinitrun();
}
void ThreePionCLEOCurrent::doupdate() {
WeakCurrent::doupdate();
// update running width if needed
if ( !touched() ) return;
if(_maxmass!=_maxcalc) inita1Width(-1);
}
Energy ThreePionCLEOCurrent::a1width(Energy2 q2) const {
Energy output;
if(_a1opt) output=(*_a1runinter)(q2);
else {
double gam(0.);
if(q2<0.1753*GeV2) {
gam =0.;
}
else if(q2<0.823*GeV2) {
double p=q2/GeV2-0.1753;
gam = 5.80900*p*sqr(p)*(1.-3.00980*p+4.57920*sqr(p));
}
else {
double p=q2/GeV2;
gam = -13.91400+27.67900*p-13.39300*sqr(p)
+3.19240*sqr(p)*p-0.10487*sqr(sqr(p));
}
if(q2<0.1676*GeV2) {
gam+=0.;
}
else if(q2<0.823*GeV2) {
double p=q2/GeV2-0.1676;
gam+= 6.28450*p*sqr(p)*(1.-2.95950*p+4.33550*sqr(p));
}
else {
double p=q2/GeV2;
gam+= -15.41100+32.08800*p-17.66600*sqr(p)
+4.93550*sqr(p)*p-0.37498*sqr(sqr(p));
}
Energy mkst=0.894*GeV,mk=0.496*GeV;
Energy2 mk1sq=sqr(mkst+mk), mk2sq=sqr(mkst-mk);
double c3pi=sqr(0.2384),ckst=sqr(4.7621)*c3pi;
gam*=c3pi;
if(q2>mk1sq) gam+=0.5*ckst*sqrt((q2-mk1sq)*(q2-mk2sq))/q2;
gam = gam*_a1width*_a1mass/GeV2/1.331/0.814/1.0252088;
output = gam*GeV2/sqrt(q2);
}
return output;
}
double
ThreePionCLEOCurrent::threeBodyMatrixElement(const int iopt, const Energy2 q2,
const Energy2 s3, const Energy2 s2,
const Energy2 s1, const Energy,
const Energy, const Energy) const {
Energy p1[5],p2[5],p3[5];
Energy2 p1sq, p2sq, p3sq;
Energy q=sqrt(q2);
Energy2 mpi2c=_mpic*_mpic;
Energy2 mpi20=_mpi0*_mpi0;
// construct the momenta for the 2 neutral 1 charged mode
Complex F1,F2,F3;
if(iopt==0) {
// construct the momenta of the decay products
p1[0] = 0.5*(q2+mpi20-s1)/q; p1sq=p1[0]*p1[0]; p1[4]=sqrt(p1sq-mpi20);
p2[0] = 0.5*(q2+mpi20-s2)/q; p2sq=p2[0]*p2[0]; p2[4]=sqrt(p2sq-mpi20);
p3[0] = 0.5*(q2+mpi2c-s3)/q; p3sq=p3[0]*p3[0]; p3[4]=sqrt(p3sq-mpi2c);
// take momentum of 1 parallel to z axis
p1[1]=ZERO;p1[2]=ZERO;p1[3]=p1[4];
// construct 2
double cos2 = 0.5*(p1sq+p2sq-p3sq-2.*mpi20+mpi2c)/p1[4]/p2[4];
p2[1] = p2[4]*sqrt(1.-cos2*cos2); p2[2]=ZERO; p2[3]=-p2[4]*cos2;
// construct 3
double cos3 = 0.5*(p1sq-p2sq+p3sq-mpi2c)/p1[4]/p3[4];
p3[1] =-p3[4]*sqrt(1.-cos3*cos3); p3[2]=ZERO; p3[3]=-p3[4]*cos3;
// calculate the form factors
CLEOFormFactor(1,-1,q2,s1,s2,s3,F1,F2,F3);
}
// construct the momenta for the 3 charged mode
else {
// construct the momenta of the decay products
p1[0] = 0.5*(q2+mpi2c-s1)/q; p1sq=p1[0]*p1[0]; p1[4]=sqrt(p1sq-mpi2c);
p2[0] = 0.5*(q2+mpi2c-s2)/q; p2sq=p2[0]*p2[0]; p2[4]=sqrt(p2sq-mpi2c);
p3[0] = 0.5*(q2+mpi2c-s3)/q; p3sq=p3[0]*p3[0]; p3[4]=sqrt(p3sq-mpi2c);
// take momentum of 1 parallel to z axis
p1[1]=ZERO;p1[2]=ZERO;p1[3]=p1[4];
// construct 2
double cos2 = 0.5*(p1sq+p2sq-p3sq-mpi2c)/p1[4]/p2[4];
p2[1] = p2[4]*sqrt(1.-cos2*cos2); p2[2]=ZERO; p2[3]=-p2[4]*cos2;
// construct 3
double cos3 = 0.5*(p1sq-p2sq+p3sq-mpi2c)/p1[4]/p3[4];
p3[1] =-p3[4]*sqrt(1.-cos3*cos3); p3[2]=ZERO; p3[3]=-p3[4]*cos3;
// calculate the form factors
CLEOFormFactor(0,-1,q2,s1,s2,s3,F1,F2,F3);
}
// construct a vector with the current
complex<Energy> current[4];
for(unsigned int ix=0;ix<4;++ix)
current[ix] = F1*(p2[ix]-p3[ix])-F2*(p3[ix]-p1[ix])+F3*(p1[ix]-p2[ix]);
complex<Energy2> dot1=current[0]*conj(current[0]);
for(unsigned int ix=1;ix<4;++ix) dot1-=current[ix]*conj(current[ix]);
complex<Energy2> dot2=current[0]*q;
return(-dot1+dot2*conj(dot2)/q2).real() / sqr(_rhomass[0]);
}
// the hadronic currents
vector<LorentzPolarizationVectorE>
ThreePionCLEOCurrent::current(tcPDPtr resonance,
FlavourInfo flavour,
const int imode, const int ichan, Energy & scale,
const tPDVector & ,
const vector<Lorentz5Momentum> & momenta,
DecayIntegrator::MEOption) const {
useMe();
// check the isospin
if(flavour.I!=IsoSpin::IUnknown && flavour.I!=IsoSpin::IOne)
return vector<LorentzPolarizationVectorE>();
// check I_3
if(flavour.I3!=IsoSpin::I3Unknown) {
switch(flavour.I3) {
case IsoSpin::I3Zero:
if(imode==2||imode==5) return vector<LorentzPolarizationVectorE>();
break;
case IsoSpin::I3One:
if(imode!=2&&imode!=5) return vector<LorentzPolarizationVectorE>();
break;
case IsoSpin::I3MinusOne:
if(imode!=2&&imode!=5) return vector<LorentzPolarizationVectorE>();
break;
default:
return vector<LorentzPolarizationVectorE>();
}
}
if(flavour.strange != Strangeness::Unknown and flavour.strange != Strangeness::Zero) return vector<LorentzPolarizationVectorE>();
if(flavour.charm != Charm::Unknown and flavour.charm != Charm::Zero ) return vector<LorentzPolarizationVectorE>();
if(flavour.bottom != Beauty::Unknown and flavour.bottom !=Beauty::Zero ) return vector<LorentzPolarizationVectorE>();
// calculate q2,s1,s2,s3
Lorentz5Momentum q;
for(unsigned int ix=0;ix<momenta.size();++ix)
q+=momenta[ix];
q.rescaleMass();
scale=q.mass();
Energy2 q2=q.mass2();
Energy2 s1 = (momenta[1]+momenta[2]).m2();
Energy2 s2 = (momenta[0]+momenta[2]).m2();
Energy2 s3 = (momenta[0]+momenta[1]).m2();
// form factors
Complex F1(0.), F2(0.), F3(0.);
CLEOFormFactor(imode,ichan,q2,s1,s2,s3,F1,F2,F3);
// change sign of the F2 term
F2 =- F2;
// prefactor
complex<InvEnergy> a1fact = _fact;
if(!resonance) a1fact *= a1BreitWigner(q2);
// current
LorentzPolarizationVectorE vect = q.mass()*a1fact*
((F2-F1)*momenta[2] + (F1-F3)*momenta[1] + (F3-F2)*momenta[0]);
// scalar piece
Complex dot=(vect*q)/q2;
vect -= dot*q;
// return the answer
return vector<LorentzPolarizationVectorE>(1,vect);
}
bool ThreePionCLEOCurrent::accept(vector<int> id) {
if(id.size()!=3) return false;
for(unsigned int ix=0;ix<id.size();++ix) {
if(id[ix]==ParticleID::piplus) continue;
else if(id[ix]==ParticleID::piminus) continue;
else if(id[ix]==ParticleID::pi0) continue;
return false;
}
return true;
}
unsigned int ThreePionCLEOCurrent::decayMode(vector<int> id) {
if(id.size()!=3) return -1;
int npip(0),npim(0),npi0(0);
for(unsigned int ix=0;ix<id.size();++ix) {
if(id[ix]==ParticleID::piplus) ++npip;
else if(id[ix]==ParticleID::piminus) ++npim;
else if(id[ix]==ParticleID::pi0) ++npi0;
}
if (npi0==3) return 0;
else if( (npip==1&&npi0==2) || (npim==1&&npi0==2) ) return 2;
else if( npi0==1 && npip==1 && npim==1 ) return 3;
else if( (npip==2&&npim==1) || (npim==2&&npip==1) ) return 5;
else return -1;
}
tPDVector ThreePionCLEOCurrent::particles(int icharge, unsigned int imode,int,int) {
tPDVector extpart(3);
if(imode==0||imode==1) {
extpart[0]=getParticleData(ParticleID::pi0);
extpart[1]=getParticleData(ParticleID::pi0);
extpart[2]=getParticleData(ParticleID::pi0);
}
else if(imode==2) {
extpart[0]=getParticleData(ParticleID::pi0);
extpart[1]=getParticleData(ParticleID::pi0);
extpart[2]=getParticleData(ParticleID::piminus);
}
else if(imode==3||imode==4) {
extpart[0]=getParticleData(ParticleID::piplus);
extpart[1]=getParticleData(ParticleID::piminus);
extpart[2]=getParticleData(ParticleID::pi0);
}
else if(imode==5) {
extpart[0]=getParticleData(ParticleID::piminus);
extpart[1]=getParticleData(ParticleID::piminus);
extpart[2]=getParticleData(ParticleID::piplus);
}
else
assert(false);
// conjugate the particles if needed
if(icharge==3) {
for(unsigned int ix=0;ix<3;++ix) {
if(extpart[ix]->CC()) extpart[ix]=extpart[ix]->CC();
}
}
// return the answer
return extpart;
}
diff --git a/Hadronization/SpinHadronizer.h b/Hadronization/SpinHadronizer.h
--- a/Hadronization/SpinHadronizer.h
+++ b/Hadronization/SpinHadronizer.h
@@ -1,191 +1,191 @@
// -*- C++ -*-
#ifndef Herwig_SpinHadronizer_H
#define Herwig_SpinHadronizer_H
//
// This is the declaration of the SpinHadronizer class.
//
#include "ThePEG/Handlers/StepHandler.h"
namespace Herwig {
using namespace ThePEG;
/**
* The SpinHadronizer class is designed to be used as a post-hadronization handler to
* give a simple model of spin transfer between the perturbative and non-perturbative
* stages.
*
* @see \ref SpinHadronizerInterfaces "The interfaces"
* defined for SpinHadronizer.
*/
class SpinHadronizer: public StepHandler {
public:
/**
* The default constructor.
*/
SpinHadronizer() : omegaHalf_(2./3.), omegaThreeHalf_(0.2),
minFlav_(3), maxFlav_(5), debug_(false), qPol_(6,make_pair(0.,0.))
{}
public:
/** @name Virtual functions required by the StepHandler class. */
//@{
/**
* The main function called by the EventHandler class to
* perform a step. Given the current state of an Event, this function
* performs the event generation step and includes the result in a new
* Step object int the Event record.
* @param eh the EventHandler in charge of the Event generation.
* @param tagged if not empty these are the only particles which should
* be considered by the StepHandler.
* @param hint a Hint object with possible information from previously
* performed steps.
* @throws Veto if the StepHandler requires the current step to be discarded.
* @throws Stop if the generation of the current Event should be stopped
* after this call.
* @throws Exception if something goes wrong.
*/
virtual void handle(EventHandler & eh, const tPVector & tagged,
const Hint & hint);
//@}
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:
/**
* Functions to calculate the spins
*/
//@{
/**
* Calculate the spin of a baryon
*/
void baryonSpin(tPPtr baryon);
/**
* Calculate the spin of a meson
*/
void mesonSpin(tPPtr meson);
//@}
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();
/**
* Finalize this object. Called in the run phase just after a
* run has ended. Used eg. to write out statistics.
*/
virtual void dofinish();
//@}
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 assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
- SpinHadronizer & operator=(const SpinHadronizer &);
+ SpinHadronizer & operator=(const SpinHadronizer &) = delete;
private:
/**
* Parameters
*/
//@{
/**
* Falk-Peskin \f$\omega_\frac12\f$ parameter
*/
double omegaHalf_;
/**
* Falk-Peskin \f$\omega_\frac32\f$ parameter
*/
double omegaThreeHalf_;
/**
* Minimum quark flavour
*/
unsigned int minFlav_;
/**
* Maximum quark flavour
*/
unsigned int maxFlav_;
/**
* Print out debugging info
*/
bool debug_;
/**
* Polarization of the quarks
*/
vector<pair<double,double> > qPol_;
//@}
};
}
#endif /* Herwig_SpinHadronizer_H */
diff --git a/MatrixElement/Matchbox/Utility/DensityOperator.h b/MatrixElement/Matchbox/Utility/DensityOperator.h
--- a/MatrixElement/Matchbox/Utility/DensityOperator.h
+++ b/MatrixElement/Matchbox/Utility/DensityOperator.h
@@ -1,248 +1,248 @@
// -*- C++ -*-
//
// DensityOperator.h is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2019 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_DensityOperator_H
#define Herwig_DensityOperator_H
//
// This is the declaration of the DensityOperator class.
//
#include "ThePEG/Handlers/HandlerBase.h"
#include "Herwig/MatrixElement/Matchbox/Utility/ColourBasis.h"
#include <tuple>
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/vector.hpp>
namespace Herwig {
using namespace ThePEG;
typedef boost::numeric::ublas::vector<Complex> CVector;
/**
* Here is the documentation of the DensityOperator class.
*
* @see \ref DensityOperatorInterfaces "The interfaces"
* defined for DensityOperator.
*/
class DensityOperator: public HandlerBase {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
DensityOperator();
/**
* The destructor.
*/
virtual ~DensityOperator();
//@}
public:
/**
* Clears theDensityOperatorMap.
*/
void clear();
/**
* Prepare for the given sub process.
*/
void prepare(const cPDVector&);
/**
* Fill the density operator for the given hard subprocess, summing over all
* helicity configurations.
*/
void fill(const Ptr<MatchboxXComb>::ptr,
const cPDVector&, const vector<Lorentz5Momentum>& momenta);
/**
* Evolve the density operator, by
* M_{n+1} = -\sum_{i,k}{-4*pi*alpha_s/Ti2*V_{ij,k} T_{i,n}M_nT_{k,n}^\dag},
* see arXiv:1206.0180 eq. (5), note that the pi*pj factor is assumed to be
* included in V_{ij,k}.
*/
void evolve(const map<pair<size_t,size_t>,Complex>& Vijk,
const cPDVector& before,
const cPDVector& after,
const map<std::tuple<size_t,size_t,size_t>,map<size_t,size_t> >& emissionsMap,
const bool splitAGluon,
const bool initialGluonSplitting);
/**
* Calculate the colour matrix element correction.
* -(1+delta(i,gluon))/Ti^2 Tr(Sn+1 Ti Mn Tk^dagger)/Tr(Sn Mn)
* where the bracket in front compensates for the gluon symmetry factor,
* Ti^2 is C_f or C_a, Sn+1 is the matrix of scalar products, and
* Ti is the radiation matrix.
* The first arg contains (emitter index, spectator index, emission pid)
*
*/
double colourMatrixElementCorrection(const std::tuple<size_t,size_t,long>& ikemission,
const cPDVector& particles);
/**
* Checking colour conservation for the colour matrix element corrections.
*/
void colourConservation(const cPDVector& particles);
/**
* Get the colour basis.
*/
Ptr<ColourBasis>::tptr colourBasis() { return theColourBasis; }
/**
* Get the colour basis.
*/
const Ptr<ColourBasis>::tptr colourBasis() const { return theColourBasis; }
/**
* Set the colour basis.
*/
void colourBasis(Ptr<ColourBasis>::ptr ptr) { theColourBasis = ptr; }
/**
* Get the correlator map.
*/
const map<pair<vector<PDT::Colour>,pair<size_t,size_t> >,double>& correlatorMap() const {
return theCorrelatorMap;
}
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
virtual IBPtr fullclone() const;
//@}
// If needed, insert declarations of virtual function defined in the
// InterfacedBase class here (using ThePEG-interfaced-decl in Emacs).
private:
/**
* Number of colours used in colourNorm.
*/
double Nc;
/**
* QCD vertex normalization.
*/
double TR;
/**
* Normalization of colour charges \mathbf{T}_{ij}^2.
*/
double colourNorm(const cPDPtr particle);
/**
* Fast evaluation of Tij*Mn, where a Tij is the matrix from ColourBasis::charge,
* which is a sparse matrix, and Mn is the density operator, a dense matrix.
*
*/
matrix<Complex> prodSparseDense(const compressed_matrix<double>&,
const matrix<Complex>&);
/**
* Fast evaluation of TijMn*Tkdagger, where a TijMn is the result from the method
* prodSparseDense, a dense matrix, and Tkdagger is the transponse conjugate of
* the matrix from ColourBasis::charge, a sparse matrix.
*
*/
matrix<Complex> prodDenseSparse(const matrix<Complex>&,
const compressed_matrix<double>&);
/**
* Boosts a vector of momenta to the rest frame of the initial pair
* of particles (the first 2 elements of the argument vector). Returns
* the boosted vectors
*/
vector<Lorentz5Momentum> boostToRestFrame(const vector<Lorentz5Momentum>& momenta);
/**
* Boosts a vector of momenta to the rest frame of the initial pair
*/
bool compareMomentum(const Lorentz5Momentum& p, const Lorentz5Momentum& q);
/**
* Mapping of colour structures to density operator matrices.
*
*/
map<vector<PDT::Colour>,matrix<Complex> > theDensityOperatorMap;
/**
* Mapping of colour structures and legs to colour correlators.
*/
map<pair<vector<PDT::Colour>,pair<size_t,size_t> >,double> theCorrelatorMap;
/**
* A map from the hard subprocess particles to a map of amplitude colour
* basis order to the normal ordered colour basis.
*/
map<cPDVector, map<size_t,size_t> > theColourBasisToColourBasisMap;
/**
* Colour basis used.
*/
Ptr<ColourBasis>::ptr theColourBasis;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
- DensityOperator & operator=(const DensityOperator &);
+ DensityOperator & operator=(const DensityOperator &) = delete;
};
}
#endif /* Herwig_DensityOperator_H */
diff --git a/Models/DarkMatter/DMDMMediatorVertex.h b/Models/DarkMatter/DMDMMediatorVertex.h
--- a/Models/DarkMatter/DMDMMediatorVertex.h
+++ b/Models/DarkMatter/DMDMMediatorVertex.h
@@ -1,113 +1,113 @@
// -*- C++ -*-
#ifndef Herwig_DMDMMediatorVertex_H
#define Herwig_DMDMMediatorVertex_H
//
// This is the declaration of the DMDMMediatorVertex class.
//
#include "ThePEG/Helicity/Vertex/Vector/FFVVertex.h"
namespace Herwig {
using namespace ThePEG;
/**
* The DMDMMediatorVertex class implements the coupling of the dark matter to the mediator
*
* @see \ref DMDMMediatorVertexInterfaces "The interfaces"
* defined for DMDMMediatorVertex.
*/
class DMDMMediatorVertex: public FFVVertex {
public:
/**
* The default constructor.
*/
DMDMMediatorVertex();
/**
* 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);
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 assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
- DMDMMediatorVertex & operator=(const DMDMMediatorVertex &);
+ DMDMMediatorVertex & operator=(const DMDMMediatorVertex &) = delete;
private:
/**
* DM coupling to the dark mediator
*/
double cDMmed_;
};
}
#endif /* Herwig_DMDMMediatorVertex_H */
diff --git a/Models/DarkMatter/MEDM2Mesons.cc b/Models/DarkMatter/MEDM2Mesons.cc
--- a/Models/DarkMatter/MEDM2Mesons.cc
+++ b/Models/DarkMatter/MEDM2Mesons.cc
@@ -1,266 +1,266 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the MEDM2Mesons class.
//
#include "MEDM2Mesons.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Helicity/Vertex/Vector/FFVVertex.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h"
#include "Herwig/Models/General/BSMModel.h"
using namespace Herwig;
typedef LorentzVector<complex<InvEnergy> > LorentzPolarizationVectorInvE;
MEDM2Mesons::MEDM2Mesons() : cDMmed_(0.), cSMmed_({0.0,0.0,0.0})
{}
Energy2 MEDM2Mesons::scale() const {
return sHat();
}
unsigned int MEDM2Mesons::orderInAlphaS() const {
return 0;
}
unsigned int MEDM2Mesons::orderInAlphaEW() const {
return 0;
}
IBPtr MEDM2Mesons::clone() const {
return new_ptr(*this);
}
IBPtr MEDM2Mesons::fullclone() const {
return new_ptr(*this);
}
void MEDM2Mesons::doinit() {
// make sure the current got initialised
current_->init();
// max energy
Energy Emax = generator()->maximumCMEnergy();
// loop over the modes
int nmode=0;
for(unsigned int imode=0;imode<current_->numberOfModes();++imode) {
// get the external particles for this mode
int iq(0),ia(0);
tPDVector out = current_->particles(0,imode,iq,ia);
current_->decayModeInfo(imode,iq,ia);
if(iq==2&&ia==-2) continue;
PhaseSpaceModePtr mode = new_ptr(PhaseSpaceMode(incomingA_,out,1.,
incomingB_,Emax));
PhaseSpaceChannel channel(mode);
if(!current_->createMode(0,tcPDPtr(), FlavourInfo(), imode,mode,0,-1,channel,Emax)) continue;
modeMap_[imode] = nmode;
addMode(mode);
++nmode;
}
// cast the model
Ptr<BSMModel>::ptr model = dynamic_ptr_cast<Ptr<BSMModel>::ptr>(generator()->standardModel());
bool foundDM(false),foundU(false),foundD(false),foundS(false);
// find the vertices we need and extract the couplings
for(unsigned int ix = 0; ix < model->numberOfVertices(); ++ix ) {
VertexBasePtr vertex = model->vertex(ix);
if(vertex->getNpoint()!=3) continue;
for(unsigned int iloc = 0;iloc < 3; ++iloc) {
vector<long> ext = vertex->search(iloc, Mediator_->id());
if(ext.empty()) continue;
for(unsigned int ioff=0;ioff<ext.size();ioff+=3) {
if(iloc!=2) assert(false);
if((ext[ioff]==incomingA_->id() && ext[ioff+1]==incomingB_->id()) ||
(ext[ioff]==incomingB_->id() && ext[ioff+1]==incomingA_->id())) {
foundDM = true;
vertex->setCoupling(sqr(Emax),incomingA_,incomingB_,Mediator_);
cDMmed_ = vertex->norm();
}
else if(abs(ext[ioff])==1 && abs(ext[ioff+1])==1 && ext[ioff]==-ext[ioff+1]) {
foundD = true;
vertex->setCoupling(sqr(Emax),getParticleData(1),getParticleData(-1),Mediator_);
cSMmed_[0] = vertex->norm();
}
else if(abs(ext[ioff])==2 && abs(ext[ioff+1])==2 && ext[ioff]==-ext[ioff+1]) {
foundU = true;
vertex->setCoupling(sqr(Emax),getParticleData(2),getParticleData(-2),Mediator_);
cSMmed_[1] = vertex->norm();
}
else if(abs(ext[ioff])==3 && abs(ext[ioff+1])==3 && ext[ioff]==-ext[ioff+1]) {
foundS = true;
vertex->setCoupling(sqr(Emax),getParticleData(3),getParticleData(-3),Mediator_);
cSMmed_[2] = vertex->norm();
}
}
}
}
if(!foundDM) {
throw InitException() << "Cannot find DM coupling in MEDM2Mesons::doinit()";
}
if(!foundD) {
throw InitException() << "Cannot find down quark coupling in MEDM2Mesons::doinit()";
}
if(!foundU) {
throw InitException() << "Cannot find up quark coupling in MEDM2Mesons::doinit()";
}
if(!foundS) {
throw InitException() << "Cannot find strange quark coupling in MEDM2Mesons::doinit()";
}
MEMultiChannel::doinit();
}
void MEDM2Mesons::persistentOutput(PersistentOStream & os) const {
os << current_ << modeMap_ << incomingA_ << incomingB_ << Mediator_ << cDMmed_ << cSMmed_;
}
void MEDM2Mesons::persistentInput(PersistentIStream & is, int) {
is >> current_ >> modeMap_ >> incomingA_ >> incomingB_ >> Mediator_ >> cDMmed_ >> cSMmed_;
}
//The following static variable is needed for the type
// description system in ThePEG.
DescribeClass<MEDM2Mesons,MEMultiChannel>
describeHerwigMEDM2Mesons("Herwig::MEDM2Mesons", "Herwig.so");
void MEDM2Mesons::Init() {
static ClassDocumentation<MEDM2Mesons> documentation
("The MEDM2Mesons class simulates the annhilation of"
" DM particles to mesons at low energy");
static Reference<MEDM2Mesons,WeakCurrent> interfaceWeakCurrent
("WeakCurrent",
"The reference for the decay current to be used.",
&MEDM2Mesons::current_, false, false, true, false, false);
static Reference<MEDM2Mesons,ParticleData> interfaceIncomingA
("IncomingA",
"First incoming particle",
&MEDM2Mesons::incomingA_, false, false, true, false, false);
static Reference<MEDM2Mesons,ParticleData> interfaceIncomingB
("IncomingB",
"Second incoming particle",
&MEDM2Mesons::incomingB_, false, false, true, false, false);
static Reference<MEDM2Mesons,ParticleData> interfaceMediator_
("Mediator",
"DM mediator",
&MEDM2Mesons::Mediator_, false, false, true, false, false);
}
double MEDM2Mesons::me2(const int ichan) const {
// compute the incoming current
LorentzPolarizationVectorInvE lepton[2][2];
if(incomingA_->iSpin()==PDT::Spin1Half && incomingB_->iSpin()==PDT::Spin1Half) {
SpinorWaveFunction em_in( meMomenta()[0],mePartonData()[0],incoming);
SpinorBarWaveFunction ep_in( meMomenta()[1],mePartonData()[1],incoming);
vector<SpinorWaveFunction> f1;
vector<SpinorBarWaveFunction> a1;
for(unsigned int ix=0;ix<2;++ix) {
em_in.reset(ix);
f1.push_back(em_in);
ep_in.reset(ix);
a1.push_back(ep_in);
}
// this should be coupling of DM to mediator/ mediator propagator
complex<Energy> mmed = Mediator_->mass();
complex<Energy2> mmed2 = sqr(mmed);
complex<Energy> mwid = Mediator_->width();
complex<Energy2> prop = sHat()-mmed2+Complex(0.,1.)*mmed*mwid;
complex<InvEnergy2> pre = cDMmed_/prop;
for(unsigned ix=0;ix<2;++ix) {
for(unsigned iy=0;iy<2;++iy) {
lepton[ix][iy]= pre*f1[ix].dimensionedWave().vectorCurrent(a1[iy].dimensionedWave());
}
}
}
// TODO think about other spins for the DM
else
assert(false);
// work out the mapping for the hadron vector
int nOut = int(meMomenta().size())-2;
vector<unsigned int> constants(nOut+1);
vector<PDT::Spin > iSpin(nOut);
vector<int> hadrons(nOut);
int itemp(1);
int ix(nOut);
do {
--ix;
iSpin[ix] = mePartonData()[ix+2]->iSpin();
itemp *= iSpin[ix];
constants[ix] = itemp;
hadrons[ix] = mePartonData()[ix+2]->id();
}
while(ix>0);
constants[nOut] = 1;
// calculate the matrix element
me_.reset(ProductionMatrixElement(PDT::Spin1Half,PDT::Spin1Half,iSpin));
// calculate the hadron current
unsigned int imode = current_->decayMode(hadrons);
Energy q = sqrt(sHat());
vector<Lorentz5Momentum> momenta(meMomenta() .begin()+2, meMomenta().end());
tPDVector out = mode(modeMap_.at(imode))->outgoing();
if(ichan<0) iMode(modeMap_.at(imode));
// get the hadronic currents for the I=1 and I=0 components
vector<LorentzPolarizationVectorE>
hadronI0(current_->current(tcPDPtr(), FlavourInfo(IsoSpin::IZero, IsoSpin::I3Zero,Strangeness::Zero),
imode,ichan,q,out,momenta,DecayIntegrator::Calculate));
vector<LorentzPolarizationVectorE>
hadronI1(current_->current(tcPDPtr(), FlavourInfo(IsoSpin::IOne, IsoSpin::I3Zero,Strangeness::Zero),
imode,ichan,q,out,momenta,DecayIntegrator::Calculate));
vector<LorentzPolarizationVectorE>
hadronssbar(current_->current(tcPDPtr(), FlavourInfo(IsoSpin::IZero, IsoSpin::I3Zero,Strangeness::ssbar),
imode,ichan,q,out,momenta,DecayIntegrator::Calculate));
// compute the matrix element
vector<unsigned int> ihel(meMomenta().size());
double output(0.);
unsigned int hI0_size = hadronI0.size();
unsigned int hI1_size = hadronI1.size();
unsigned int hss_size = hadronssbar.size();
unsigned int maxsize = max(max(hadronI0.size(),hadronI1.size()),hss_size);
for(unsigned int hhel=0;hhel<maxsize;++hhel) {
// map the index for the hadrons to a helicity state
for(int ix=nOut;ix>0;--ix) {
ihel[ix+1]=(hhel%constants[ix-1])/constants[ix];
}
// loop over the helicities of the incoming particles
for(ihel[1]=0;ihel[1]<2;++ihel[1]){
for(ihel[0]=0;ihel[0]<2;++ihel[0]) {
Complex amp = 0.;
// work on coefficients for the I1 and I0 bits
if(hI0_size != 0 )
- amp += (cSMmed_[0]+cSMmed_[1])/sqrt(2.)*(lepton[ihel[0]][ihel[1]].dot(hadronI0[hhel]));
+ amp += Complex((cSMmed_[0]+cSMmed_[1])/sqrt(2.)*(lepton[ihel[0]][ihel[1]].dot(hadronI0[hhel])));
if(hI1_size !=0)
- amp += (cSMmed_[0]-cSMmed_[1])/sqrt(2.)*(lepton[ihel[0]][ihel[1]].dot(hadronI1[hhel]));
+ amp += Complex((cSMmed_[0]-cSMmed_[1])/sqrt(2.)*(lepton[ihel[0]][ihel[1]].dot(hadronI1[hhel])));
if(hss_size !=0)
- amp += cSMmed_[2]* (lepton[ihel[0]][ihel[1]].dot(hadronssbar[hhel]));
+ amp += Complex(cSMmed_[2]* (lepton[ihel[0]][ihel[1]].dot(hadronssbar[hhel])));
me_(ihel)= amp;
output += std::norm(amp);
}
}
}
// symmetry factors
map<long,int> ncount;
double symmetry(1.);
for(tPDPtr o : out) ncount[o->id()]+=1;
for(map<long,int>::const_iterator it=ncount.begin();it!=ncount.end();++it) {
symmetry *= it->second;
}
// prefactors
output *= 0.25*sqr(pow(sqrt(sHat())/q,int(momenta.size()-2)));
return output/symmetry;
}
void MEDM2Mesons::constructVertex(tSubProPtr) {
}
diff --git a/Models/DarkMatter/MEDM2Mesons.h b/Models/DarkMatter/MEDM2Mesons.h
--- a/Models/DarkMatter/MEDM2Mesons.h
+++ b/Models/DarkMatter/MEDM2Mesons.h
@@ -1,177 +1,177 @@
// -*- C++ -*-
#ifndef Herwig_MEDM2Mesons_H
#define Herwig_MEDM2Mesons_H
//
// This is the declaration of the MEDM2Mesons class.
//
#include "Herwig/MatrixElement/MEMultiChannel.h"
#include "Herwig/Decay/WeakCurrents/WeakCurrent.h"
#include "Herwig/MatrixElement/ProductionMatrixElement.h"
namespace Herwig {
using namespace ThePEG;
/**
* The MEDM2Mesons class implements dark matter annhilation via a vector current to
* mesons at low energies
*
* @see \ref MEDM2MesonsInterfaces "The interfaces"
* defined for MEDM2Mesons.
*/
class MEDM2Mesons: public MEMultiChannel {
public:
/**
* The default constructor.
*/
MEDM2Mesons();
public:
/** @name Virtual functions required by the MEBase class. */
//@{
/**
* Return the order in \f$\alpha_S\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaS() const;
/**
* Return the order in \f$\alpha_{EW}\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaEW() const;
/**
* Return the scale associated with the last set phase space point.
*/
virtual Energy2 scale() const;
//@}
/**
* Construct the vertex of spin correlations.
*/
virtual void constructVertex(tSubProPtr);
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:
/**
* Return the matrix element squared for a given mode and phase-space channel.
* @param ichan The channel we are calculating the matrix element for.
*/
virtual double me2(const int ichan) const;
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:
/**
* 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 assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
- MEDM2Mesons & operator=(const MEDM2Mesons &);
+ MEDM2Mesons & operator=(const MEDM2Mesons &) = delete;
private :
/**
* Hadronic current etc
*/
//@{
/**
* the hadronic current
*/
WeakCurrentPtr current_;
/**
* The matrix element
*/
mutable ProductionMatrixElement me_;
/**
* Map for the modes
*/
map<int,int> modeMap_;
//@}
/**
* DM
*/
//@{
/**
* Incoming Particles
*/
PDPtr incomingA_, incomingB_;
//@}
/**
* DM coupling to the dark mediator
*/
Complex cDMmed_;
/**
* SM couplings to the dark mediator
*/
vector<Complex> cSMmed_;
/**
* DM vector mediator
*/
PDPtr Mediator_;
};
}
#endif /* Herwig_MEDM2Mesons_H */
diff --git a/PDF/HwRemDecayer.h b/PDF/HwRemDecayer.h
--- a/PDF/HwRemDecayer.h
+++ b/PDF/HwRemDecayer.h
@@ -1,747 +1,747 @@
// -*- C++ -*-
//
// HwRemDecayer.h is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2019 The Herwig Collaboration
//
// Herwig is licenced under version 3 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_HwRemDecayer_H
#define HERWIG_HwRemDecayer_H
//
// This is the declaration of the HwRemDecayer class.
//
#include "ThePEG/PDT/RemnantDecayer.h"
#include "ThePEG/Handlers/EventHandler.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/EventRecord/SubProcess.h"
#include "ThePEG/PDF/BeamParticleData.h"
#include "Herwig/Shower/ShowerAlpha.h"
#include "Herwig/PDT/StandardMatchers.h"
#include "ThePEG/PDT/StandardMatchers.h"
#include "HwRemDecayer.fh"
namespace Herwig {
using namespace ThePEG;
/**
* The HwRemDecayer class is responsible for the decay of the remnants. Additional
* secondary scatters have to be evolved backwards to a gluon, the
* first/hard interaction has to be evolved back to a valence quark.
* This is all generated inside this class,
* which main methods are then called by the ShowerHandler.
*
* A simple forced splitting algorithm is used.
* This takes the Remnant object produced from the PDF and backward
* evolution (hadron - parton) and produce partons with the remaining
* flavours and with the correct colour connections.
*
* The algorithim operates by starting with the parton which enters the hard process.
* If this is from the sea there is a forced branching to produce the antiparticle
* from a gluon branching. If the parton entering the hard process was a gluon, or
* a gluon was produced from the first step of the algorithm, there is then a further
* branching back to a valence parton. After these partons have been produced a quark or
* diquark is produced to give the remaining valence content of the incoming hadron.
*
* The forced branching are generated using a scale between QSpac and EmissionRange times
* the minimum scale. The energy fractions are then distributed using
* \f[\frac{\alpha_S}{2\pi}\frac{P(z)}{z}f(x/z,\tilde{q})\f]
* with the massless splitting functions.
*
* \author Manuel B\"ahr
*
* @see \ref HwRemDecayerInterfaces "The interfaces"
* defined for HwRemDecayer.
*/
class HwRemDecayer: public RemnantDecayer {
public:
/** Typedef to store information about colour partners */
typedef vector<pair<tPPtr, tPPtr> > PartnerMap;
public:
/**
* The default constructor.
*/
HwRemDecayer() : allowTop_(false), multiPeriph_(true), quarkPair_(false),
ptmin_(-1.*GeV), beta_(ZERO),
maxtrySoft_(10),
colourDisrupt_(1.0),
ladderbFactor_(0.0),
ladderPower_(-0.08),
ladderNorm_(1.0),
ladderMult_(1.0),
gaussWidth_(0.1),
valOfN_(0),
initTotRap_(0),
_kinCutoff(0.75*GeV),
_forcedSplitScale(2.5*GeV),
_range(1.1), _zbin(0.05),_ybin(0.),
_nbinmax(100), DISRemnantOpt_(0),
PtDistribution_(0),
pomeronStructure_(0), mg_(ZERO) {}
/** @name Virtual functions required by the Decayer class. */
//@{
/**
* Check if this decayer can perfom the decay specified by the
* given decay mode.
* @return true if this decayer can handle the given mode, otherwise false.
*/
virtual bool accept(const DecayMode &) const {
return true;
}
/**
* Return true if this decayer can handle the extraction of the \a
* extracted parton from the given \a particle.
*/
virtual bool canHandle(tcPDPtr particle, tcPDPtr parton) const;
/**
* Return true if this decayed can extract more than one parton from
* a particle.
*/
virtual bool multiCapable() const {
return true;
}
/**
* Perform a decay for a given DecayMode and a given Particle instance.
* @param dm the DecayMode describing the decay.
* @param p the Particle instance to be decayed.
* @param step the step we are working on.
* @return a ParticleVector containing the decay products.
*/
virtual ParticleVector decay(const DecayMode & dm, const Particle & p, Step & step) const;
//@}
public:
/**
* struct that is used to catch exceptions which are thrown
* due to energy conservation issues of additional soft scatters
*/
struct ExtraSoftScatterVeto {};
/** @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();
/**
* Do several checks and initialization, for remnantdecay inside ShowerHandler.
*/
void initialize(pair<tRemPPtr, tRemPPtr> rems, tPPair beam, Step & step,
Energy forcedSplitScale);
/**
* Initialize the soft scattering machinery.
* @param ptmin = the pt cutoff used in the UE model
* @param beta = slope of the soft pt-spectrum
*/
void initSoftInteractions(Energy ptmin, InvEnergy2 beta);
/**
* Perform the acual forced splitting.
* @param partons is a pair of ThePEG::Particle pointers which store the final
* partons on which the shower ends.
* @param pdfs are pointers to the pdf objects for both beams
* @param first is a flage wether or not this is the first or a secondary interation
*/
void doSplit(pair<tPPtr, tPPtr> partons, pair<tcPDFPtr, tcPDFPtr> pdfs, bool first);
/**
* Perform the final creation of the diquarks. Set the remnant masses and do
* all colour connections.
* @param colourDisrupt = variable to control how many "hard" scatters
* are colour isolated
* @param softInt = parameter for the number of soft scatters
*/
void finalize(double colourDisrupt=0.0, unsigned int softInt=0);
/**
* Find the children
*/
void findChildren(tPPtr,vector<PPtr> &) const;
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() {
Interfaced::doinit();
_ybin=0.25/_zbin;
mg_ = getParticleData(ParticleID::g)->constituentMass();
}
//@}
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
- HwRemDecayer & operator=(const HwRemDecayer &);
+ HwRemDecayer & operator=(const HwRemDecayer &) = delete;
public:
/**
* Simple struct to store info about baryon quark and di-quark
* constituents.
*/
struct HadronContent {
/**
* manually extract the valence flavour \a id.
*/
inline void extract(int id) {
for(unsigned int i=0; i<flav.size(); i++) {
if(id == sign*flav[i]){
if(hadron->id() == ParticleID::gamma ||
(hadron->id() == ParticleID::pomeron && pomeronStructure==1) ||
hadron->id() == ParticleID::reggeon) {
flav[0] = id;
flav[1] = -id;
extracted = 0;
flav.resize(2);
}
else if (hadron->id() == ParticleID::pomeron && pomeronStructure==0) {
extracted = 0;
}
else {
extracted = i;
}
break;
}
}
}
/**
* Return a proper particle ID assuming that \a id has been removed
* from the hadron.
*/
long RemID() const;
/**
* Method to determine whether \a parton is a quark from the sea.
* @return TRUE if \a parton is neither a valence quark nor a gluon.
*/
bool isSeaQuark(tcPPtr parton) const {
return ((parton->id() != ParticleID::g) && ( !isValenceQuark(parton) ) );
}
/**
* Method to determine whether \a parton is a valence quark.
*/
bool isValenceQuark(tcPPtr parton) const {
return isValenceQuark(parton->id());
}
/**
* Method to determine whether \a parton is a quark from the sea.
* @return TRUE if \a parton is neither a valence quark nor a gluon.
*/
bool isSeaQuarkData(tcPDPtr partonData) const {
return ((partonData->id() != ParticleID::g) && ( !isValenceQuarkData(partonData) ) );
}
/**
* Method to determine whether \a parton is a valence quark.
*/
bool isValenceQuarkData(tcPDPtr partonData) const {
int id(sign*partonData->id());
return find(flav.begin(),flav.end(),id) != flav.end();
}
/**
* Method to determine whether \a parton is a valence quark.
*/
bool isValenceQuark(int id) const {
return find(flav.begin(),flav.end(),sign*id) != flav.end();
}
/** The valence flavours of the corresponding baryon. */
vector<int> flav;
/** The array index of the extracted particle. */
int extracted;
/** -1 if the particle is an anti-particle. +1 otherwise. */
int sign;
/** The ParticleData objects of the hadron */
tcPDPtr hadron;
/** Pomeron treatment */
unsigned int pomeronStructure;
};
/**
* Return the hadron content objects for the incoming particles.
*/
const pair<HadronContent, HadronContent>& content() const {
return theContent;
}
/**
* Return a HadronContent struct from a PPtr to a hadron.
*/
HadronContent getHadronContent(tcPPtr hadron) const;
/**
* Set the hadron contents.
*/
void setHadronContent(tPPair beam) {
theContent.first = getHadronContent(beam.first);
theContent.second = getHadronContent(beam.second);
}
private:
/**
* Do the forced Splitting of the Remnant with respect to the
* extracted parton \a parton.
* @param parton = PPtr to the parton going into the subprocess.
* @param content = HadronContent struct to keep track of flavours.
* @param rem = Pointer to the ThePEG::RemnantParticle.
* @param used = Momentum vector to keep track of remaining momenta.
* @param partners = Vector of pairs filled with tPPtr to the particles
* which should be colour connected.
* @param pdf pointer to the PDF Object which is used for this particle
* @param first = Flag for the first interaction.
*/
void split(tPPtr parton, HadronContent & content, tRemPPtr rem,
Lorentz5Momentum & used, PartnerMap & partners, tcPDFPtr pdf, bool first);
/**
* Merge the colour lines of two particles
* @param p1 = Pointer to particle 1
* @param p2 = Pointer to particle 2
* @param anti = flag to indicate, if (anti)colour was extracted as first parton.
*/
void mergeColour(tPPtr p1, tPPtr p2, bool anti) const;
/**
* Set the colour connections.
* @param partners = Object that holds the information which particles to connect.
* @param anti = flag to indicate, if (anti)colour was extracted as first parton.
* @param disrupt parameter for disruption of the colour structure
*/
void fixColours(PartnerMap partners, bool anti, double disrupt) const;
/**
* Set the momenta of the Remnants properly and boost the decay particles.
*/
void setRemMasses() const;
/**
* This creates a parton from the remaining flavours of the hadron. The
* last parton used was a valance parton, so only 2 (or 1, if meson) flavours
* remain to be used.
*/
PPtr finalSplit(const tRemPPtr rem, long remID,
Lorentz5Momentum usedMomentum) const {
// Create the remnant and set its momentum, also reset all of the decay
// products from the hadron
PPtr remnant = new_ptr(Particle(getParticleData(remID)));
Lorentz5Momentum prem(rem->momentum()-usedMomentum);
prem.setMass(getParticleData(remID)->constituentMass());
prem.rescaleEnergy();
remnant->set5Momentum(prem);
// Add the remnant to the step, but don't do colour connections
thestep->addDecayProduct(rem,remnant,false);
return remnant;
}
/**
* This takes the particle and find a splitting for np -> p + child and
* creates the correct kinematics and connects for such a split. This
* Splitting has an upper bound on qtilde given by the energy argument
* @param rem The Remnant
* @param child The PDG code for the outgoing particle
* @param oldQ The maximum scale for the evolution
* @param oldx The fraction of the hadron's momentum carried by the last parton
* @param pf The momentum of the last parton at input and after branching at output
* @param p The total emitted momentum
* @param content The content of the hadron
*/
PPtr forceSplit(const tRemPPtr rem, long child, Energy &oldQ, double &oldx,
Lorentz5Momentum &pf, Lorentz5Momentum &p,
HadronContent & content) const;
/**
* Check if a particle is a parton from a hadron or not
* @param parton The parton to be tested
*/
bool isPartonic(tPPtr parton) const;
/** @name Soft interaction methods. */
//@{
/**
* Produce pt values according to dN/dp_T = N p_T exp(-beta_*p_T^2)
*/
Energy softPt() const;
/**
* Get the 2 pairs of 5Momenta for the scattering. Needs calling of
* initSoftInteractions.
*/
void softKinematics(Lorentz5Momentum &r1, Lorentz5Momentum &r2,
Lorentz5Momentum &g1, Lorentz5Momentum &g2) const;
/**
* Create N soft gluon interactions
*/
void doSoftInteractions(unsigned int N){
if(!multiPeriph_){
doSoftInteractions_old(N);} //outdated model for soft interactions
else{
doSoftInteractions_multiPeriph(N); // Multiperipheral model
}
}
/**
* Create N soft gluon interactions (old version)
*/
void doSoftInteractions_old(unsigned int N);
/**
* Create N soft gluon interactions with multiperhpheral kinematics
*/
void doSoftInteractions_multiPeriph(unsigned int N);
/**
* Phase space generation for the ladder partons
*/
bool doPhaseSpaceGenerationGluons(vector<Lorentz5Momentum> &softGluons, Energy energy, unsigned int &its)
const;
/**
* This returns the rotation matrix needed to rotate p into the z axis
*/
LorentzRotation rotate(const LorentzMomentum &p) const;
/**
* Methods to generate random distributions also all stolen form UA5Handler
**/
template <typename T>
inline T gaussDistribution(T mean, T stdev) const{
double x = rnd();
x = sqrt(-2.*log(x));
double y;
randAzm(x,x,y);
return mean + stdev*x;
}
/**
* This returns a random number with a flat distribution
* [-A,A] plus gaussian tail with stdev B
* TODO: Should move this to Utilities
* @param A The width of the flat part
* @param B The standard deviation of the gaussian tail
* @return the randomly generated value
*/
inline double randUng(double A, double B) const{
double prun;
if(A == 0.) prun = 0.;
else prun = 1./(1.+B*1.2533/A);
if(rnd() < prun) return 2.*(rnd()-0.5)*A;
else {
double temp = gaussDistribution(0.,B);
if(temp < 0) return temp - abs(A);
else return temp + abs(A);
}
}
template <typename T>
inline void randAzm(T pt, T &px, T &py) const{
double c,s,cs;
while(true) {
c = 2.*rnd()-1.;
s = 2.*rnd()-1.;
cs = c*c+s*s;
if(cs <= 1.&&cs!=0.) break;
}
T qt = pt/cs;
px = (c*c-s*s)*qt;
py = 2.*c*s*qt;
}
inline Energy randExt(Energy AM0,InvEnergy B) const{
double r = rnd();
// Starting value
Energy am = AM0-log(r)/B;
for(int i = 1; i<20; ++i) {
double a = exp(-B*(am-AM0))/(1.+B*AM0);
double f = (1.+B*am)*a-r;
InvEnergy df = -B*B*am*a;
Energy dam = -f/df;
am += dam;
if(am<AM0) am = AM0 + .001*MeV;
if(abs(dam) < .001*MeV) break;
}
return am;
}
/**
* Method to add a particle to the step
* @param parent = pointer to the parent particle
* @param id = Particle ID of the newly created particle
* @param p = Lorentz5Momentum of the new particle
*/
tPPtr addParticle(tcPPtr parent, long id, Lorentz5Momentum p) const;
//@}
/**
* A flag which indicates, whether the extracted valence quark was a
* anti particle.
*/
pair<bool, bool> theanti;
/**
* variable to sum up the x values of the extracted particles
*/
pair<double, double> theX;
/**Pair of HadronContent structs to know about the quark content of the beams*/
pair<HadronContent, HadronContent> theContent;
/**Pair of Lorentz5Momentum to keep track of the forced splitting product momenta*/
pair<Lorentz5Momentum, Lorentz5Momentum> theUsed;
/**
* Pair of PartnerMap's to store the particles, which will be colour
* connected in the end.
*/
pair<PartnerMap, PartnerMap> theMaps;
/**
* Variable to hold a pointer to the current step. The variable is used to
* determine, wether decay(const DecayMode & dm, const Particle & p, Step & step)
* has been called in this event or not.
*/
StepPtr thestep;
/**
* Pair of Remnant pointers. This is needed to boost
* in the Remnant-Remnant CMF after all have been decayed.
*/
pair<RemPPtr, RemPPtr> theRems;
/**
* The beam particle data for the current incoming hadron
*/
mutable tcPPtr theBeam;
/**
* the beam data
*/
mutable Ptr<BeamParticleData>::const_pointer theBeamData;
/**
* The PDF for the current initial-state shower
*/
mutable tcPDFPtr _pdf;
private:
/**
* Switch to control handling of top quarks in proton
*/
bool allowTop_;
/**
* Switch to control using multiperipheral kinemaics
*/
bool multiPeriph_;
/**
* True if kinematics is to be calculated for quarks
*/
bool quarkPair_;
/** @name Soft interaction variables. */
//@{
/**
* Pair of soft Remnant pointers, i.e. Diquarks.
*/
tPPair softRems_;
/**
* ptcut of the UE model
*/
Energy ptmin_;
/**
* slope of the soft pt-spectrum: dN/dp_T = N p_T exp(-beta*p_T^2)
*/
InvEnergy2 beta_;
/**
* Maximum number of attempts for the regeneration of an additional
* soft scattering, before the number of scatters is reduced.
*/
unsigned int maxtrySoft_;
/**
* Variable to store the relative number of colour disrupted
* connections to additional soft subprocesses.
*/
double colourDisrupt_;
/**
* Variable to store the additive factor of the
multiperipheral ladder multiplicity.
*/
double ladderbFactor_;
/**
* Variable of the parameterization of the ladder multiplicity.
*/
double ladderPower_;
/**
* Variable of the parameterization of the ladder multiplicity.
*/
double ladderNorm_;
double ladderMult_;
/**
* Variable to store the gaussian width of the
* fluctuation of the longitudinal momentum
* fraction.
*/
double gaussWidth_;
/**
* Variable to store the current total multiplicity
of a ladder.
*/
double valOfN_;
/**
* Variable to store the initial total rapidity between
of the remnants.
*/
double initTotRap_;
//@}
/** @name Forced splitting variables. */
//@{
/**
* The kinematic cut-off
*/
Energy _kinCutoff;
/**
* The PDF freezing scale as set in ShowerHandler
*/
Energy _forcedSplitScale;
/**
* Range for emission
*/
double _range;
/**
* Size of the bins in z for the interpolation
*/
double _zbin;
/**
* Size of the bins in y for the interpolation
*/
double _ybin;
/**
* Maximum number of bins for the z interpolation
*/
int _nbinmax;
/**
* Pointer to the object calculating the QCD coupling
*/
ShowerAlphaPtr _alphaS;
/**
* Pointer to the object calculating the QED coupling
*/
ShowerAlphaPtr _alphaEM;
/**
* Option for the DIS remnant
*/
unsigned int DISRemnantOpt_;
/**
* Option for the pT generation
*/
unsigned int PtDistribution_;
/**
* Option for the treatment of the pomeron structure
*/
unsigned int pomeronStructure_;
//@}
/**
* The gluon constituent mass.
*/
Energy mg_;
};
}
#endif /* HERWIG_HwRemDecayer_H */
diff --git a/PDF/MultiPartonExtractor.h b/PDF/MultiPartonExtractor.h
--- a/PDF/MultiPartonExtractor.h
+++ b/PDF/MultiPartonExtractor.h
@@ -1,114 +1,114 @@
// -*- C++ -*-
#ifndef Herwig_MultiPartonExtractor_H
#define Herwig_MultiPartonExtractor_H
//
// This is the declaration of the MultiPartonExtractor class.
//
#include "ThePEG/PDF/PartonExtractor.h"
#include <deque>
namespace Herwig {
using namespace ThePEG;
/**
* The MultiPartonExtractor class inherits from the PartonExtractor of ThePEG
* but allows more control over the PDFs used in the case that there are multiple
* stages of parton extraction
*
* @see \ref MultiPartonExtractorInterfaces "The interfaces"
* defined for MultiPartonExtractor.
*/
class MultiPartonExtractor: public PartonExtractor {
public:
/**
* The default constructor.
*/
MultiPartonExtractor() {};
/**
* Return a vector of possible pairs of parton bins which can be
* produced within a given maximum total particle-particle
* invariant mass squared, \a maxEnergy sBin.
*/
virtual PartonPairVec getPartons(Energy maxEnergy, const cPDPair &,
const Cuts &) 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:
/**
* Add parton bins to pbins for the given incoming particle and the
* specified cuts.
*/
virtual void addPartons(tPBPtr incoming ,const PDFCuts & cuts,
std::deque<tcPDFPtr> pdf ,PartonVector & pbins) const;
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 assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
- MultiPartonExtractor & operator=(const MultiPartonExtractor &);
+ MultiPartonExtractor & operator=(const MultiPartonExtractor &) = delete;
/**
* PDFBase object to override first PDF
*/
vector<PDFPtr> firstPDF_;
/**
* PDFBase object to override second PDF
*/
vector<PDFPtr> secondPDF_;
};
}
#endif /* Herwig_MultiPartonExtractor_H */
diff --git a/Shower/Dipole/Kernels/ColourMatrixElementCorrection.h b/Shower/Dipole/Kernels/ColourMatrixElementCorrection.h
--- a/Shower/Dipole/Kernels/ColourMatrixElementCorrection.h
+++ b/Shower/Dipole/Kernels/ColourMatrixElementCorrection.h
@@ -1,171 +1,171 @@
// -*- C++ -*-
//
// ColourMatrixElementCorrection.h is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2019 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_ColourMatrixElementCorrection_H
#define Herwig_ColourMatrixElementCorrection_H
//
// This is the declaration of the ColourMatrixElementCorrection class.
//
#include "Herwig/Shower/Dipole/Base/DipoleSplittingReweight.h"
#include <tuple>
namespace Herwig {
using namespace ThePEG;
/**
* \ingroup DipoleShower
* \author Johan Thoren, Simon Platzer
*
* \brief ColourMatrixElementCorrection is implementing colour matrix element
* corrections through the weighted Sudakov algorithm
*
* @see \ref ColourMatrixElementCorrectionInterfaces "The interfaces"
* defined for ColourMatrixElementCorrection.
*/
class ColourMatrixElementCorrection: public DipoleSplittingReweight {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
ColourMatrixElementCorrection();
/**
* The destructor.
*/
virtual ~ColourMatrixElementCorrection();
//@}
public:
/**
* Calculate and cache the colour matrix element correction factor
* for the given splitting type.
*/
double cmec(const DipoleSplittingInfo&) const;
/**
* Return the reweighting factor for the given splitting type.
*/
virtual double evaluate(const DipoleSplittingInfo& s) const {
return cmec(s);
}
/**
* Return the absolute value of the colour matrix element correction
* as an enhancement hint for the sampling of the un-reweighted
* splitting kernel.
*/
virtual double hint(const DipoleSplittingInfo& s) const {
if ( hintOnly(s) )
return cmec(s);
return abs(cmec(s))*lambda;
}
/**
* Return true, if the reweight can be entirely absorbed into the hint. A
* possible detuning will be switched off.
*/
virtual bool hintOnly(const DipoleSplittingInfo& s) const {
return cmec(s) > 0.;
}
/**
* Set the factor in front of enhance used by the veto algorithm.
*/
virtual void reweightFactor(const double c) {
assert(c > 0.0);
lambda = c;
}
/**
* Set the factor in front of enhance used by the veto algorithm.
*/
virtual void negativeScaling(const double c) {
assert(c >= 0.0);
negCMECScaling = c;
}
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
virtual IBPtr fullclone() const;
//@}
// If needed, insert declarations of virtual function defined in the
// InterfacedBase class here (using ThePEG-interfaced-decl in Emacs).
private:
/**
* Factor to shuffle the magnitude of the CMEC between the splitting kernel
* and the weight in the reweighted veto algorithm.
*/
double lambda;
/**
* Scaling factor multiplying all of the negative colour matrix element
* corrections. The physically sensible value is 1.0, but this factor can
* be used to examine the effects of the negative contributions.
*/
double negCMECScaling;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
- ColourMatrixElementCorrection & operator=(const ColourMatrixElementCorrection &);
+ ColourMatrixElementCorrection & operator=(const ColourMatrixElementCorrection &) = delete;
};
}
#endif /* Herwig_ColourMatrixElementCorrection_H */
diff --git a/Shower/Dipole/Kinematics/IFMassiveKinematics.h b/Shower/Dipole/Kinematics/IFMassiveKinematics.h
--- a/Shower/Dipole/Kinematics/IFMassiveKinematics.h
+++ b/Shower/Dipole/Kinematics/IFMassiveKinematics.h
@@ -1,279 +1,279 @@
// -*- C++ -*-
//
// IFLightKinematics.h is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2019 The Herwig Collaboration
//
// Herwig is licenced under version 3 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
#ifndef HERWIG_IFLightKinematics_H
#define HERWIG_IFLightKinematics_H
//
// This is the declaration of the IFLightKinematics class.
//
#include "DipoleSplittingKinematics.h"
namespace Herwig {
using namespace ThePEG;
/**
* \ingroup DipoleShower
* \author Simon Platzer, Martin Stoll
*
* \brief IFMassiveKinematics implements massless splittings
* off an initial-final dipole.
*
* @see \ref IFMassiveKinematicsInterfaces "The interfaces"
* defined for IFMassiveKinematics.
*/
class IFMassiveKinematics: public DipoleSplittingKinematics {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
IFMassiveKinematics();
/**
* The destructor.
*/
virtual ~IFMassiveKinematics();
//@}
public:
/**
* Return the boundaries in between the evolution
* variable random number is to be sampled; the lower
* cuoff is assumed to correspond to the infrared cutoff.
*/
virtual pair<double,double> kappaSupport(const DipoleSplittingInfo& dIndex) const;
/**
* Return the boundaries in between the momentum
* fraction random number is to be sampled.
*/
virtual pair<double,double> xiSupport(const DipoleSplittingInfo& dIndex) const;
/**
* Return the boundaries on the momentum fraction
*/
virtual pair<double,double> zBoundaries(Energy,
const DipoleSplittingInfo&,
const DipoleSplittingKernel&) const {
return {0.0,1.0};
}
/**
* Return the dipole scale associated to the
* given pair of emitter and spectator. This
* should be the invariant mass or absolute value
* final/final or initial/initial and the absolute
* value of the momentum transfer for intial/final or
* final/initial dipoles.
*/
virtual Energy dipoleScale(const Lorentz5Momentum& pEmitter,
const Lorentz5Momentum& pSpectator) const;
/**
* Return the maximum pt for the given dipole scale.
*/
virtual Energy ptMax(Energy dScale,
double emX, double specX,
const DipoleSplittingInfo& dInfo,
const DipoleSplittingKernel& split) const;
/**
* Return the maximum pt for the given dipole scale.
*/
virtual Energy ptMax(Energy dScale,
double, double,
const DipoleIndex& dIndex,
const DipoleSplittingKernel& split,
tPPtr emitter, tPPtr) const;
/**
* Return the maximum pt for the given dipole scale.
*/
virtual Energy ptMax(Energy,
double, double,
const DipoleIndex&,
const DipoleSplittingKernel&) const {
// Only the DipoleSplittingInfo version should be used for massive
// dipoles, for now anyway.
assert(false);
return ZERO;
}
/**
* Return the maximum virtuality for the given dipole scale.
*/
virtual Energy QMax(Energy dScale,
double emX, double specX,
const DipoleSplittingInfo& dInfo,
const DipoleSplittingKernel& split) const;
/**
* Return the maximum virtuality for the given dipole scale.
*/
virtual Energy QMax(Energy,
double, double,
const DipoleIndex&,
const DipoleSplittingKernel&) const {
// Only the DipoleSplittingInfo version should be used for massive
// dipoles, for now anyway.
assert(false);
return ZERO;
}
/**
* Return the pt given a virtuality.
*/
virtual Energy PtFromQ(Energy scale, const DipoleSplittingInfo&) const;
/**
* Return the virtuality given a pt.
*/
virtual Energy QFromPt(Energy scale, const DipoleSplittingInfo&) const;
/**
* Return the random number associated to
* the given pt.
*/
virtual double ptToRandom(Energy pt, Energy dScale,
double emX, double specX,
const DipoleIndex& dIndex,
const DipoleSplittingKernel&) const;
/**
* Generate splitting variables given three random numbers
* and the momentum fractions of the emitter and spectator.
* Return true on success.
*/
virtual bool generateSplitting(double kappa, double xi, double phi,
DipoleSplittingInfo& dIndex,
const DipoleSplittingKernel&);
/**
* Generate the full kinematics given emitter and
* spectator momentum and a previously completeted
* DipoleSplittingInfo object.
*/
virtual void generateKinematics(const Lorentz5Momentum& pEmitter,
const Lorentz5Momentum& pSpectator,
const DipoleSplittingInfo& dInfo);
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @param os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @param is the persistent input stream read from.
* @param version the version number of the object when written.
*/
void persistentInput(PersistentIStream & is, int version);
//@}
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
virtual IBPtr clone() const;
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
virtual IBPtr fullclone() const;
//@}
// If needed, insert declarations of virtual function defined in the
// InterfacedBase class here (using ThePEG-interfaced-decl in Emacs).
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<IFMassiveKinematics> initIFMassiveKinematics;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
- IFMassiveKinematics & operator=(const IFMassiveKinematics &);
+ IFMassiveKinematics & operator=(const IFMassiveKinematics &) = delete;
private:
/**
* Wether or not to choose the `collinear' scheme
*/
bool theCollinearScheme;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of IFMassiveKinematics. */
template <>
struct BaseClassTrait<Herwig::IFMassiveKinematics,1> {
/** Typedef of the first base class of IFMassiveKinematics. */
typedef Herwig::DipoleSplittingKinematics NthBase;
};
/** This template specialization informs ThePEG about the name of
* the IFMassiveKinematics class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::IFMassiveKinematics>
: public ClassTraitsBase<Herwig::IFMassiveKinematics> {
/** Return a platform-independent class name */
static string className() { return "Herwig::IFMassiveKinematics"; }
/**
* The name of a file containing the dynamic library where the class
* IFMassiveKinematics is implemented. It may also include several, space-separated,
* libraries if the class IFMassiveKinematics 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 "HwDipoleShower.so"; }
};
/** @endcond */
}
#endif /* HERWIG_IFMassiveKinematics_H */
diff --git a/Shower/Dipole/SpinCorrelations/DipoleShowerParticle.h b/Shower/Dipole/SpinCorrelations/DipoleShowerParticle.h
--- a/Shower/Dipole/SpinCorrelations/DipoleShowerParticle.h
+++ b/Shower/Dipole/SpinCorrelations/DipoleShowerParticle.h
@@ -1,182 +1,182 @@
// -*- C++ -*-
//
// DipoleShowerParticle.h is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2019 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_DipoleShowerParticle_H
#define HERWIG_DipoleShowerParticle_H
//
// This is the declaration of the DipoleShowerParticle class.
//
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/Helicity/WaveFunction/WaveFunctionBase.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
#include "DipoleShowerVertex.h"
namespace Herwig {
using namespace ThePEG;
/** \ingroup DipoleShower
*
* \author Stephen Webster
*
*/
class DipoleShowerParticle : public Base {
public:
/**
* Default constructor
*/
DipoleShowerParticle() {}
/**
* Default destructor
**/
~DipoleShowerParticle() {}
public:
/**
* Reset the member variables of the object.
*/
void clear();
/**
* Set up the decay vertex for the emitter.
*/
void prepare( PPtr& part,
const Helicity::Direction emmDir,
const Helicity::Direction specDir,
const Lorentz5Momentum& pVector,
const Lorentz5Momentum& nVector );
/**
* Return the associated decay vertex,
* a DipoleShowerVertex.
**/
DSVertexPtr decayVertex() { return theDecayVertex; }
/**
* Create fermion decay basis states.
* It returns the decay basis states in the
* decay frame as required for the mapping.
*/
vector<LorentzSpinor<SqrtEnergy> > createFermionDecayStates();
/**
* Create vector decay basis states.
*/
void createVectorDecayStates();
/**
* Create fermion production basis states
* for the given particle produced in the splitting.
*/
void createNewFermionSpinInfo( PPtr& outgoing, Helicity::Direction dir);
/**
* Create vector production basis states
* for the given particle produced in the splitting.
*/
void createNewVectorSpinInfo( PPtr& outgoing, Helicity::Direction dir);
/**
* Create the mappings between the production
* and decay states for the fermion and
* store them in the associated decay vertex.
* (No longer applicable) reason for passing the
* decay states as an argument:
* Previously used a check on zero values for computing
* the mapping, rather than a </> 1e-5, this would only
* work when using the original decay state as calculated
* in the decay frame (i.e. without transforming to the
* lab frame and back). Now it simply avoids doing an
* unnecessary rotation of the decay basis
*/
void setFermionMapping( const vector<LorentzSpinor<SqrtEnergy>>& decayBasis );
/**
* Create the mappings between the production
* and decay states the boson and
* store them in the associated decay vertex.
*/
void setVectorMapping();
public:
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
private:
/**
* The pptr to this particle.
*/
PPtr theParticle;
/**
* The dipole shower vertex associated
* with this particle.
*/
DSVertexPtr theDecayVertex;
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
- DipoleShowerParticle & operator=(const DipoleShowerParticle &);
+ DipoleShowerParticle & operator=(const DipoleShowerParticle &) = delete;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of DipoleShowerParticle. */
template <>
struct BaseClassTrait<Herwig::DipoleShowerParticle,1> {
/** Typedef of the first base class of DipoleShowerParticle. */
typedef Base NthBase;
};
/** This template specialization informs ThePEG about the name of
* the DipoleShowerParticle class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::DipoleShowerParticle>
: public ClassTraitsBase<Herwig::DipoleShowerParticle> {
/** Return a platform-independent class name */
static string className() { return "Herwig::DipoleShowerParticle"; }
/**
* The name of a file containing the dynamic library where the class
* DipoleShowerParticle is implemented. It may also include several, space-separated,
* libraries if the class DipoleShowerParticle 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 "HwDipoleShower.so"; }
};
/** @endcond */
}
#endif /* HERWIG_DipoleShowerParticle_H */
diff --git a/Shower/Dipole/SpinCorrelations/DipoleShowerVertex.h b/Shower/Dipole/SpinCorrelations/DipoleShowerVertex.h
--- a/Shower/Dipole/SpinCorrelations/DipoleShowerVertex.h
+++ b/Shower/Dipole/SpinCorrelations/DipoleShowerVertex.h
@@ -1,285 +1,285 @@
// -*- C++ -*-
//
// DipoleShowerVertex.h is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2019 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_DipoleShowerVertex_H
#define HERWIG_DipoleShowerVertex_H
//
// This is the declaration of the DipoleShowerVertex class.
//
#include "ThePEG/EventRecord/HelicityVertex.h"
#include "Herwig/Decay/DecayMatrixElement.h"
#include "DipoleShowerVertex.fh"
namespace Herwig {
using namespace ThePEG;
/** \ingroup DipoleShower
*
* This class represents the vertex for a given splitting
* in the dipole shower.
*
* \author Stephen Webster
*
*/
class DipoleShowerVertex: public HelicityVertex {
public:
/**
* Default constructor
*/
DipoleShowerVertex();
/**
* Default destructor
**/
~DipoleShowerVertex() {}
public:
/**
* Return the matrix element for this vertex.
*/
inline const DecayMEPtr ME() const {
return theMatrixElement;
}
/**
* Set the matrix element
*/
inline void ME(DecayMEPtr in) {
theMatrixElement = in;
}
public:
/**
* Method to calculate the \f$\rho\f$ matrix for one of the decay products
* in the frame of this splitting vertex.
*
* @param iprod The splitting product to compute the \f$\rho\f$ matrix for.
*/
RhoDMatrix getRhoMatrix(int iprod, bool ) const;
/**
* Method to calculate the \f$D\f$ matrix for the decaying
* particle / the incoming to the vertex, in the frame of
* the vertex. The argument is a dummy argument.
*/
RhoDMatrix getDMatrix(int) const;
/**
* Get the lorentz rotation from the working frame
* to the frame of the splitting.
*/
LorentzRotation boostToSplitting();
/**
* Set the p vector for this splitting
*/
void pVector( const Lorentz5Momentum& emitterMom ) { thePVector = emitterMom; }
/**
* Set the n vector for this splitting
*/
void nVector( const Lorentz5Momentum& nMom ) { theNVector = nMom; }
/**
* Set the emitter,Spectator Config (II,IF,FF,FI - F=true, I=false)
*/
void dipoleConfig(const pair<bool,bool>& newConfig) { theDipoleConfig = newConfig; }
/**
* Return the p vector for this splitting
*/
Lorentz5Momentum pVector() const { return thePVector; }
/**
* Return the n/spectator vector for this splitting
*/
Lorentz5Momentum nVector() const { return theNVector; }
/**
* Return the emitter,Spectator Config (II,IF,FF,FI - F=true, I=false)
*/
const pair<bool,bool>& dipoleConfig() const { return theDipoleConfig; }
/**
* Set the decay state to production state
* mapping for this vertex.
*/
void mappingD2P( RhoDMatrix& mapping ) { theMappingDecay2Prod = mapping; }
/**
* Return the mapping from the decay
* states to the production states.
*/
RhoDMatrix mappingD2P() { return theMappingDecay2Prod; }
/**
* Set the production state to decay state
* mapping for this vertex.
*/
void mappingP2D( RhoDMatrix& mapping ) { theMappingProd2Decay = mapping; }
/**
* Return the mapping from the production
* states to the decay states.
*/
RhoDMatrix mappingP2D() { return theMappingProd2Decay; }
/**
* Set the new to old spectator mapping
* for this vertex.
*/
void mappingSpecNewToOld( RhoDMatrix& mapping ) { theMappingSpectatorNewToOld = mapping; }
/**
* Return the new to old spectator mapping
* for this vertex.
*/
RhoDMatrix mappingSpecNewToOld() { return theMappingSpectatorNewToOld; }
/**
* Set the new to old spectator mapping
* for this vertex.
*/
void mappingSpecOldToNew( RhoDMatrix& mapping ) { theMappingSpectatorOldToNew = mapping; }
/**
* Return the new to old spectator mapping
* for this vertex.
*/
RhoDMatrix mappingSpecOldToNew() { return theMappingSpectatorOldToNew; }
public:
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
private:
/**
* Storage of the decay matrix element.
*/
DecayMEPtr theMatrixElement;
/**
* The p vector of the 'splitting basis'
* associated with this vertex.
**/
Lorentz5Momentum thePVector;
/**
* The n vector of the 'splitting basis'
* associated with this vertex.
**/
Lorentz5Momentum theNVector;
/**
* Initial/final config {emitter, spectator}
*/
pair<bool,bool> theDipoleConfig;
/**
* An indicator flag to record if the
* boost to shower for this vertex has been done
*/
bool theBoostCalculated;
/**
* The lorentz transformation from the
* working frame to this splitting.
*/
LorentzRotation theBoostToSplitting;
/**
* The mapping from the decay basis states
* to the production basis states.
*/
RhoDMatrix theMappingDecay2Prod;
/**
* The mapping from the production basis states
* to the decay basis states.
*/
RhoDMatrix theMappingProd2Decay;
/**
* The mapping from the new spectator basis
* states to the old spectator basis states.
*/
RhoDMatrix theMappingSpectatorNewToOld;
/**
* The mapping from the old spectator basis
* states to the new spectator basis states.
*/
RhoDMatrix theMappingSpectatorOldToNew;
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
- DipoleShowerVertex & operator=(const DipoleShowerVertex &);
+ DipoleShowerVertex & operator=(const DipoleShowerVertex &) = delete;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of DipoleShowerVertex. */
template <>
struct BaseClassTrait<Herwig::DipoleShowerVertex,1> {
/** Typedef of the first base class of DipoleShowerVertex. */
typedef HelicityVertex NthBase;
};
/** This template specialization informs ThePEG about the name of
* the DipoleShowerVertex class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::DipoleShowerVertex>
: public ClassTraitsBase<Herwig::DipoleShowerVertex> {
/** Return a platform-independent class name */
static string className() { return "Herwig::DipoleShowerVertex"; }
/**
* The name of a file containing the dynamic library where the class
* DipoleShowerVertex is implemented. It may also include several, space-separated,
* libraries if the class DipoleShowerVertex 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 "HwDipoleShower.so"; }
};
/** @endcond */
}
#endif /* HERWIG_DipoleShowerVertex_H */
diff --git a/Shower/Dipole/SpinCorrelations/DipoleVertexRecord.h b/Shower/Dipole/SpinCorrelations/DipoleVertexRecord.h
--- a/Shower/Dipole/SpinCorrelations/DipoleVertexRecord.h
+++ b/Shower/Dipole/SpinCorrelations/DipoleVertexRecord.h
@@ -1,207 +1,207 @@
// -*- C++ -*-
#ifndef Herwig_DipoleVertexRecord_H
#define Herwig_DipoleVertexRecord_H
//
// This is the declaration of the DipoleVertexRecord class.
//
#include "ThePEG/Config/ThePEG.h"
#include "Herwig/Shower/Dipole/Base/DipoleSplittingInfo.h"
#include "Herwig/Shower/Dipole/Base/Dipole.h"
#include "ThePEG/EventRecord/RhoDMatrix.h"
#include "DipoleShowerParticle.h"
namespace Herwig {
using namespace ThePEG;
/**
* Here is the documentation of the DipoleVertexRecord class.
*/
class DipoleVertexRecord: public Base {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
DipoleVertexRecord() {}
/**
* The destructor.
*/
virtual ~DipoleVertexRecord() { clear(); }
//@}
public:
/**
* Prepare the emitter and spectator
* for the spin correlations computations.
**/
void prepareSplitting( const DipoleSplittingInfo& dInfo, const Dipole& dip);
/**
* Correctly initialise the decay matrix
* to a delta matrix for an external particle.
*/
void initDecayMatrix(PPtr& particle, Helicity::Direction dir);
/**
* Compute the spin density matrix for the given emitter.
* This tracks the path between the given emitter and
* the previous emitter, calculating a rho/decay matrix
* at each vertex as appropriate.
*/
RhoDMatrix emitterDensityMatrix(PPtr emitter);
/**
* Generate the spin-correlated azimuthal angle for a splitting.
*/
void generatePhi(DipoleSplittingInfo& dInfo, Dipole& dip);
/**
* Identify the type of particle and use the appropriate function
* to set up the spin info.
* Required for e.g. MPI
*/
void createSpinInfo(PPtr& part,
const Helicity::Direction& dir);
/**
* Create and set up fermion spin info.
* Required for e.g. MPI
*/
void createFermionSpinInfo(PPtr& part,
const Helicity::Direction& dir);
/**
* Create and set up vector spin info.
* Required for e.g. MPI
*/
void createVectorSpinInfo(PPtr& part,
const Helicity::Direction& dir);
/**
* Update the vertex record following a splitting.
*/
void update(const DipoleSplittingInfo& dInfo);
/**
* For spectators. Set new particle spin info the that of the
* old particle. Update the spin info to include any momentum changes.
*/
void updateSpinInfo( PPtr& oldPart,
PPtr& newPart );
/**
* Set the stopUpdate flag in the spin info of a particle
* incoming to the current decay.
*/
void prepareParticleDecay( const PPtr& parent );
/**
* Update the spin info of the incoming to the decay
* following showering of the decay.
*/
void updateParticleDecay();
/**
* SW 06/02/2019: Required for NearestNeighbourDipoleAnalysis tests.
* Access the emitter info record.
*/
//map<PPtr,DipoleSplittingInfo> emitterInfoRecord() const {
//return theEmitterInfoRecord;
//}
/**
* SW 06/02/2019: Required for NearestNeighbourDipoleAnalysis tests.
* Add a splitting to the emitter info record.
*/
// void addToRecord(const DipoleSplittingInfo& dInfo) {
// assert(dInfo.emitter());
// theEmitterInfoRecord[dInfo.emitter()] = dInfo;
// }
/**
* Clear the vertex record: Give up ownership
* on any object involved in the evolution.
*/
virtual void clear();
/**
* The standard Init function used to initialize the interfaces.
* Called exactly once for each class by the class description system
* before the main function starts or
* when this class is dynamically loaded.
*/
static void Init();
private:
/**
* The current emitter.
*/
DipoleShowerParticle theCurrentEmitter;
/**
* SW 06/02/2019: Required for NearestNeighbourDipoleAnalysis tests.
* Record of the splittings as
* required for the testing analysis.
*/
//map<PPtr, DipoleSplittingInfo> theEmitterInfoRecord;
/**
* The spin info of a particle incoming to the decay
* under consideration.
*/
tcSpinPtr theDecayParentSpinInfo;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
- DipoleVertexRecord & operator=(const DipoleVertexRecord &);
+ DipoleVertexRecord & operator=(const DipoleVertexRecord &) = delete;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of DipoleVertexRecord. */
template <>
struct BaseClassTrait<Herwig::DipoleVertexRecord,1> {
/** Typedef of the first base class of DipoleVertexRecord. */
typedef Base NthBase;
};
/** This template specialization informs ThePEG about the name of
* the DipoleVertexRecord class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::DipoleVertexRecord>
: public ClassTraitsBase<Herwig::DipoleVertexRecord> {
/** Return a platform-independent class name */
static string className() { return "Herwig::DipoleVertexRecord"; }
/**
* The name of a file containing the dynamic library where the class
* DipoleVertexRecord is implemented. It may also include several, space-separated,
* libraries if the class DipoleVertexRecord 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 "HwDipoleShower.so"; }
};
/** @endcond */
}
#endif /* Herwig_DipoleVertexRecord_H */
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Dec 21, 3:36 PM (1 d, 14 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4021202
Default Alt Text
(252 KB)
Attached To
rHERWIGHG herwighg
Event Timeline
Log In to Comment